diff options
Diffstat (limited to 'drivers/net/wireless')
311 files changed, 23976 insertions, 7437 deletions
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index f9a24e599dee..cfce83e1f273 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c | |||
| @@ -1924,7 +1924,6 @@ static int adm8211_probe(struct pci_dev *pdev, | |||
| 1924 | pci_iounmap(pdev, priv->map); | 1924 | pci_iounmap(pdev, priv->map); |
| 1925 | 1925 | ||
| 1926 | err_free_dev: | 1926 | err_free_dev: |
| 1927 | pci_set_drvdata(pdev, NULL); | ||
| 1928 | ieee80211_free_hw(dev); | 1927 | ieee80211_free_hw(dev); |
| 1929 | 1928 | ||
| 1930 | err_free_reg: | 1929 | err_free_reg: |
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 7fe19648f10e..edf4b57c4aaa 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c | |||
| @@ -5570,7 +5570,6 @@ static void airo_pci_remove(struct pci_dev *pdev) | |||
| 5570 | airo_print_info(dev->name, "Unregistering..."); | 5570 | airo_print_info(dev->name, "Unregistering..."); |
| 5571 | stop_airo_card(dev, 1); | 5571 | stop_airo_card(dev, 1); |
| 5572 | pci_disable_device(pdev); | 5572 | pci_disable_device(pdev); |
| 5573 | pci_set_drvdata(pdev, NULL); | ||
| 5574 | } | 5573 | } |
| 5575 | 5574 | ||
| 5576 | static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state) | 5575 | static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state) |
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index 1abf1d421173..c63d1159db5c 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig | |||
| @@ -25,6 +25,23 @@ config ATH_DEBUG | |||
| 25 | Say Y, if you want to debug atheros wireless drivers. | 25 | Say Y, if you want to debug atheros wireless drivers. |
| 26 | Right now only ath9k makes use of this. | 26 | Right now only ath9k makes use of this. |
| 27 | 27 | ||
| 28 | config ATH_REG_DYNAMIC_USER_REG_HINTS | ||
| 29 | bool "Atheros dynamic user regulatory hints" | ||
| 30 | depends on CFG80211_CERTIFICATION_ONUS | ||
| 31 | default n | ||
| 32 | ---help--- | ||
| 33 | Say N. This should only be enabled in countries where | ||
| 34 | this feature is explicitly allowed and only on cards that | ||
| 35 | specifically have been tested for this. | ||
| 36 | |||
| 37 | config ATH_REG_DYNAMIC_USER_CERT_TESTING | ||
| 38 | bool "Atheros dynamic user regulatory testing" | ||
| 39 | depends on ATH_REG_DYNAMIC_USER_REG_HINTS && CFG80211_CERTIFICATION_ONUS | ||
| 40 | default n | ||
| 41 | ---help--- | ||
| 42 | Say N. This should only be enabled on systems | ||
| 43 | undergoing certification testing. | ||
| 44 | |||
| 28 | source "drivers/net/wireless/ath/ath5k/Kconfig" | 45 | source "drivers/net/wireless/ath/ath5k/Kconfig" |
| 29 | source "drivers/net/wireless/ath/ath9k/Kconfig" | 46 | source "drivers/net/wireless/ath/ath9k/Kconfig" |
| 30 | source "drivers/net/wireless/ath/carl9170/Kconfig" | 47 | source "drivers/net/wireless/ath/carl9170/Kconfig" |
| @@ -32,5 +49,6 @@ source "drivers/net/wireless/ath/ath6kl/Kconfig" | |||
| 32 | source "drivers/net/wireless/ath/ar5523/Kconfig" | 49 | source "drivers/net/wireless/ath/ar5523/Kconfig" |
| 33 | source "drivers/net/wireless/ath/wil6210/Kconfig" | 50 | source "drivers/net/wireless/ath/wil6210/Kconfig" |
| 34 | source "drivers/net/wireless/ath/ath10k/Kconfig" | 51 | source "drivers/net/wireless/ath/ath10k/Kconfig" |
| 52 | source "drivers/net/wireless/ath/wcn36xx/Kconfig" | ||
| 35 | 53 | ||
| 36 | endif | 54 | endif |
diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile index fb05cfd19361..7d023b0f13b4 100644 --- a/drivers/net/wireless/ath/Makefile +++ b/drivers/net/wireless/ath/Makefile | |||
| @@ -5,13 +5,16 @@ obj-$(CONFIG_ATH6KL) += ath6kl/ | |||
| 5 | obj-$(CONFIG_AR5523) += ar5523/ | 5 | obj-$(CONFIG_AR5523) += ar5523/ |
| 6 | obj-$(CONFIG_WIL6210) += wil6210/ | 6 | obj-$(CONFIG_WIL6210) += wil6210/ |
| 7 | obj-$(CONFIG_ATH10K) += ath10k/ | 7 | obj-$(CONFIG_ATH10K) += ath10k/ |
| 8 | obj-$(CONFIG_WCN36XX) += wcn36xx/ | ||
| 8 | 9 | ||
| 9 | obj-$(CONFIG_ATH_COMMON) += ath.o | 10 | obj-$(CONFIG_ATH_COMMON) += ath.o |
| 10 | 11 | ||
| 11 | ath-objs := main.o \ | 12 | ath-objs := main.o \ |
| 12 | regd.o \ | 13 | regd.o \ |
| 13 | hw.o \ | 14 | hw.o \ |
| 14 | key.o | 15 | key.o \ |
| 16 | dfs_pattern_detector.o \ | ||
| 17 | dfs_pri_detector.o | ||
| 15 | 18 | ||
| 16 | ath-$(CONFIG_ATH_DEBUG) += debug.o | 19 | ath-$(CONFIG_ATH_DEBUG) += debug.o |
| 17 | ccflags-y += -D__CHECK_ENDIAN__ | 20 | ccflags-y += -D__CHECK_ENDIAN__ |
diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c index 17d7fece35d2..280fc3d53a36 100644 --- a/drivers/net/wireless/ath/ar5523/ar5523.c +++ b/drivers/net/wireless/ath/ar5523/ar5523.c | |||
| @@ -1762,6 +1762,7 @@ static struct usb_device_id ar5523_id_table[] = { | |||
| 1762 | AR5523_DEVICE_UX(0x2001, 0x3a00), /* Dlink / DWLAG132 */ | 1762 | AR5523_DEVICE_UX(0x2001, 0x3a00), /* Dlink / DWLAG132 */ |
| 1763 | AR5523_DEVICE_UG(0x2001, 0x3a02), /* Dlink / DWLG132 */ | 1763 | AR5523_DEVICE_UG(0x2001, 0x3a02), /* Dlink / DWLG132 */ |
| 1764 | AR5523_DEVICE_UX(0x2001, 0x3a04), /* Dlink / DWLAG122 */ | 1764 | AR5523_DEVICE_UX(0x2001, 0x3a04), /* Dlink / DWLAG122 */ |
| 1765 | AR5523_DEVICE_UG(0x07d1, 0x3a07), /* D-Link / WUA-2340 rev A1 */ | ||
| 1765 | AR5523_DEVICE_UG(0x1690, 0x0712), /* Gigaset / AR5523 */ | 1766 | AR5523_DEVICE_UG(0x1690, 0x0712), /* Gigaset / AR5523 */ |
| 1766 | AR5523_DEVICE_UG(0x1690, 0x0710), /* Gigaset / SMCWUSBTG */ | 1767 | AR5523_DEVICE_UG(0x1690, 0x0710), /* Gigaset / SMCWUSBTG */ |
| 1767 | AR5523_DEVICE_UG(0x129b, 0x160c), /* Gigaset / USB stick 108 | 1768 | AR5523_DEVICE_UG(0x129b, 0x160c), /* Gigaset / USB stick 108 |
diff --git a/drivers/net/wireless/ath/ath10k/bmi.c b/drivers/net/wireless/ath/ath10k/bmi.c index 744da6d1c405..a1f099628850 100644 --- a/drivers/net/wireless/ath/ath10k/bmi.c +++ b/drivers/net/wireless/ath/ath10k/bmi.c | |||
| @@ -22,7 +22,8 @@ | |||
| 22 | 22 | ||
| 23 | void ath10k_bmi_start(struct ath10k *ar) | 23 | void ath10k_bmi_start(struct ath10k *ar) |
| 24 | { | 24 | { |
| 25 | ath10k_dbg(ATH10K_DBG_CORE, "BMI started\n"); | 25 | ath10k_dbg(ATH10K_DBG_BMI, "bmi start\n"); |
| 26 | |||
| 26 | ar->bmi.done_sent = false; | 27 | ar->bmi.done_sent = false; |
| 27 | } | 28 | } |
| 28 | 29 | ||
| @@ -32,8 +33,10 @@ int ath10k_bmi_done(struct ath10k *ar) | |||
| 32 | u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.done); | 33 | u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.done); |
| 33 | int ret; | 34 | int ret; |
| 34 | 35 | ||
| 36 | ath10k_dbg(ATH10K_DBG_BMI, "bmi done\n"); | ||
| 37 | |||
| 35 | if (ar->bmi.done_sent) { | 38 | if (ar->bmi.done_sent) { |
| 36 | ath10k_dbg(ATH10K_DBG_CORE, "%s skipped\n", __func__); | 39 | ath10k_dbg(ATH10K_DBG_BMI, "bmi skipped\n"); |
| 37 | return 0; | 40 | return 0; |
| 38 | } | 41 | } |
| 39 | 42 | ||
| @@ -46,7 +49,6 @@ int ath10k_bmi_done(struct ath10k *ar) | |||
| 46 | return ret; | 49 | return ret; |
| 47 | } | 50 | } |
| 48 | 51 | ||
| 49 | ath10k_dbg(ATH10K_DBG_CORE, "BMI done\n"); | ||
| 50 | return 0; | 52 | return 0; |
| 51 | } | 53 | } |
| 52 | 54 | ||
| @@ -59,6 +61,8 @@ int ath10k_bmi_get_target_info(struct ath10k *ar, | |||
| 59 | u32 resplen = sizeof(resp.get_target_info); | 61 | u32 resplen = sizeof(resp.get_target_info); |
| 60 | int ret; | 62 | int ret; |
| 61 | 63 | ||
| 64 | ath10k_dbg(ATH10K_DBG_BMI, "bmi get target info\n"); | ||
| 65 | |||
| 62 | if (ar->bmi.done_sent) { | 66 | if (ar->bmi.done_sent) { |
| 63 | ath10k_warn("BMI Get Target Info Command disallowed\n"); | 67 | ath10k_warn("BMI Get Target Info Command disallowed\n"); |
| 64 | return -EBUSY; | 68 | return -EBUSY; |
| @@ -80,6 +84,7 @@ int ath10k_bmi_get_target_info(struct ath10k *ar, | |||
| 80 | 84 | ||
| 81 | target_info->version = __le32_to_cpu(resp.get_target_info.version); | 85 | target_info->version = __le32_to_cpu(resp.get_target_info.version); |
| 82 | target_info->type = __le32_to_cpu(resp.get_target_info.type); | 86 | target_info->type = __le32_to_cpu(resp.get_target_info.type); |
| 87 | |||
| 83 | return 0; | 88 | return 0; |
| 84 | } | 89 | } |
| 85 | 90 | ||
| @@ -92,15 +97,14 @@ int ath10k_bmi_read_memory(struct ath10k *ar, | |||
| 92 | u32 rxlen; | 97 | u32 rxlen; |
| 93 | int ret; | 98 | int ret; |
| 94 | 99 | ||
| 100 | ath10k_dbg(ATH10K_DBG_BMI, "bmi read address 0x%x length %d\n", | ||
| 101 | address, length); | ||
| 102 | |||
| 95 | if (ar->bmi.done_sent) { | 103 | if (ar->bmi.done_sent) { |
| 96 | ath10k_warn("command disallowed\n"); | 104 | ath10k_warn("command disallowed\n"); |
| 97 | return -EBUSY; | 105 | return -EBUSY; |
| 98 | } | 106 | } |
| 99 | 107 | ||
| 100 | ath10k_dbg(ATH10K_DBG_CORE, | ||
| 101 | "%s: (device: 0x%p, address: 0x%x, length: %d)\n", | ||
| 102 | __func__, ar, address, length); | ||
| 103 | |||
| 104 | while (length) { | 108 | while (length) { |
| 105 | rxlen = min_t(u32, length, BMI_MAX_DATA_SIZE); | 109 | rxlen = min_t(u32, length, BMI_MAX_DATA_SIZE); |
| 106 | 110 | ||
| @@ -133,15 +137,14 @@ int ath10k_bmi_write_memory(struct ath10k *ar, | |||
| 133 | u32 txlen; | 137 | u32 txlen; |
| 134 | int ret; | 138 | int ret; |
| 135 | 139 | ||
| 140 | ath10k_dbg(ATH10K_DBG_BMI, "bmi write address 0x%x length %d\n", | ||
| 141 | address, length); | ||
| 142 | |||
| 136 | if (ar->bmi.done_sent) { | 143 | if (ar->bmi.done_sent) { |
| 137 | ath10k_warn("command disallowed\n"); | 144 | ath10k_warn("command disallowed\n"); |
| 138 | return -EBUSY; | 145 | return -EBUSY; |
| 139 | } | 146 | } |
| 140 | 147 | ||
| 141 | ath10k_dbg(ATH10K_DBG_CORE, | ||
| 142 | "%s: (device: 0x%p, address: 0x%x, length: %d)\n", | ||
| 143 | __func__, ar, address, length); | ||
| 144 | |||
| 145 | while (length) { | 148 | while (length) { |
| 146 | txlen = min(length, BMI_MAX_DATA_SIZE - hdrlen); | 149 | txlen = min(length, BMI_MAX_DATA_SIZE - hdrlen); |
| 147 | 150 | ||
| @@ -180,15 +183,14 @@ int ath10k_bmi_execute(struct ath10k *ar, u32 address, u32 *param) | |||
| 180 | u32 resplen = sizeof(resp.execute); | 183 | u32 resplen = sizeof(resp.execute); |
| 181 | int ret; | 184 | int ret; |
| 182 | 185 | ||
| 186 | ath10k_dbg(ATH10K_DBG_BMI, "bmi execute address 0x%x param 0x%x\n", | ||
| 187 | address, *param); | ||
| 188 | |||
| 183 | if (ar->bmi.done_sent) { | 189 | if (ar->bmi.done_sent) { |
| 184 | ath10k_warn("command disallowed\n"); | 190 | ath10k_warn("command disallowed\n"); |
| 185 | return -EBUSY; | 191 | return -EBUSY; |
| 186 | } | 192 | } |
| 187 | 193 | ||
| 188 | ath10k_dbg(ATH10K_DBG_CORE, | ||
| 189 | "%s: (device: 0x%p, address: 0x%x, param: %d)\n", | ||
| 190 | __func__, ar, address, *param); | ||
| 191 | |||
| 192 | cmd.id = __cpu_to_le32(BMI_EXECUTE); | 194 | cmd.id = __cpu_to_le32(BMI_EXECUTE); |
| 193 | cmd.execute.addr = __cpu_to_le32(address); | 195 | cmd.execute.addr = __cpu_to_le32(address); |
| 194 | cmd.execute.param = __cpu_to_le32(*param); | 196 | cmd.execute.param = __cpu_to_le32(*param); |
| @@ -216,6 +218,9 @@ int ath10k_bmi_lz_data(struct ath10k *ar, const void *buffer, u32 length) | |||
| 216 | u32 txlen; | 218 | u32 txlen; |
| 217 | int ret; | 219 | int ret; |
| 218 | 220 | ||
| 221 | ath10k_dbg(ATH10K_DBG_BMI, "bmi lz data buffer 0x%p length %d\n", | ||
| 222 | buffer, length); | ||
| 223 | |||
| 219 | if (ar->bmi.done_sent) { | 224 | if (ar->bmi.done_sent) { |
| 220 | ath10k_warn("command disallowed\n"); | 225 | ath10k_warn("command disallowed\n"); |
| 221 | return -EBUSY; | 226 | return -EBUSY; |
| @@ -250,6 +255,9 @@ int ath10k_bmi_lz_stream_start(struct ath10k *ar, u32 address) | |||
| 250 | u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.lz_start); | 255 | u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.lz_start); |
| 251 | int ret; | 256 | int ret; |
| 252 | 257 | ||
| 258 | ath10k_dbg(ATH10K_DBG_BMI, "bmi lz stream start address 0x%x\n", | ||
| 259 | address); | ||
| 260 | |||
| 253 | if (ar->bmi.done_sent) { | 261 | if (ar->bmi.done_sent) { |
| 254 | ath10k_warn("command disallowed\n"); | 262 | ath10k_warn("command disallowed\n"); |
| 255 | return -EBUSY; | 263 | return -EBUSY; |
| @@ -275,6 +283,10 @@ int ath10k_bmi_fast_download(struct ath10k *ar, | |||
| 275 | u32 trailer_len = length - head_len; | 283 | u32 trailer_len = length - head_len; |
| 276 | int ret; | 284 | int ret; |
| 277 | 285 | ||
| 286 | ath10k_dbg(ATH10K_DBG_BMI, | ||
| 287 | "bmi fast download address 0x%x buffer 0x%p length %d\n", | ||
| 288 | address, buffer, length); | ||
| 289 | |||
| 278 | ret = ath10k_bmi_lz_stream_start(ar, address); | 290 | ret = ath10k_bmi_lz_stream_start(ar, address); |
| 279 | if (ret) | 291 | if (ret) |
| 280 | return ret; | 292 | return ret; |
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index f8b969f518f8..e46951b8fb92 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c | |||
| @@ -76,36 +76,7 @@ static inline void ath10k_ce_src_ring_write_index_set(struct ath10k *ar, | |||
| 76 | u32 ce_ctrl_addr, | 76 | u32 ce_ctrl_addr, |
| 77 | unsigned int n) | 77 | unsigned int n) |
| 78 | { | 78 | { |
| 79 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 79 | ath10k_pci_write32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS, n); |
| 80 | void __iomem *indicator_addr; | ||
| 81 | |||
| 82 | if (!test_bit(ATH10K_PCI_FEATURE_HW_1_0_WORKAROUND, ar_pci->features)) { | ||
| 83 | ath10k_pci_write32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS, n); | ||
| 84 | return; | ||
| 85 | } | ||
| 86 | |||
| 87 | /* workaround for QCA988x_1.0 HW CE */ | ||
| 88 | indicator_addr = ar_pci->mem + ce_ctrl_addr + DST_WATERMARK_ADDRESS; | ||
| 89 | |||
| 90 | if (ce_ctrl_addr == ath10k_ce_base_address(CDC_WAR_DATA_CE)) { | ||
| 91 | iowrite32((CDC_WAR_MAGIC_STR | n), indicator_addr); | ||
| 92 | } else { | ||
| 93 | unsigned long irq_flags; | ||
| 94 | local_irq_save(irq_flags); | ||
| 95 | iowrite32(1, indicator_addr); | ||
| 96 | |||
| 97 | /* | ||
| 98 | * PCIE write waits for ACK in IPQ8K, there is no | ||
| 99 | * need to read back value. | ||
| 100 | */ | ||
| 101 | (void)ioread32(indicator_addr); | ||
| 102 | (void)ioread32(indicator_addr); /* conservative */ | ||
| 103 | |||
| 104 | ath10k_pci_write32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS, n); | ||
| 105 | |||
| 106 | iowrite32(0, indicator_addr); | ||
| 107 | local_irq_restore(irq_flags); | ||
| 108 | } | ||
| 109 | } | 80 | } |
| 110 | 81 | ||
| 111 | static inline u32 ath10k_ce_src_ring_write_index_get(struct ath10k *ar, | 82 | static inline u32 ath10k_ce_src_ring_write_index_get(struct ath10k *ar, |
| @@ -285,7 +256,7 @@ static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar, | |||
| 285 | * ath10k_ce_sendlist_send. | 256 | * ath10k_ce_sendlist_send. |
| 286 | * The caller takes responsibility for any needed locking. | 257 | * The caller takes responsibility for any needed locking. |
| 287 | */ | 258 | */ |
| 288 | static int ath10k_ce_send_nolock(struct ce_state *ce_state, | 259 | static int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, |
| 289 | void *per_transfer_context, | 260 | void *per_transfer_context, |
| 290 | u32 buffer, | 261 | u32 buffer, |
| 291 | unsigned int nbytes, | 262 | unsigned int nbytes, |
| @@ -293,7 +264,7 @@ static int ath10k_ce_send_nolock(struct ce_state *ce_state, | |||
| 293 | unsigned int flags) | 264 | unsigned int flags) |
| 294 | { | 265 | { |
| 295 | struct ath10k *ar = ce_state->ar; | 266 | struct ath10k *ar = ce_state->ar; |
| 296 | struct ce_ring_state *src_ring = ce_state->src_ring; | 267 | struct ath10k_ce_ring *src_ring = ce_state->src_ring; |
| 297 | struct ce_desc *desc, *sdesc; | 268 | struct ce_desc *desc, *sdesc; |
| 298 | unsigned int nentries_mask = src_ring->nentries_mask; | 269 | unsigned int nentries_mask = src_ring->nentries_mask; |
| 299 | unsigned int sw_index = src_ring->sw_index; | 270 | unsigned int sw_index = src_ring->sw_index; |
| @@ -306,11 +277,13 @@ static int ath10k_ce_send_nolock(struct ce_state *ce_state, | |||
| 306 | ath10k_warn("%s: send more we can (nbytes: %d, max: %d)\n", | 277 | ath10k_warn("%s: send more we can (nbytes: %d, max: %d)\n", |
| 307 | __func__, nbytes, ce_state->src_sz_max); | 278 | __func__, nbytes, ce_state->src_sz_max); |
| 308 | 279 | ||
| 309 | ath10k_pci_wake(ar); | 280 | ret = ath10k_pci_wake(ar); |
| 281 | if (ret) | ||
| 282 | return ret; | ||
| 310 | 283 | ||
| 311 | if (unlikely(CE_RING_DELTA(nentries_mask, | 284 | if (unlikely(CE_RING_DELTA(nentries_mask, |
| 312 | write_index, sw_index - 1) <= 0)) { | 285 | write_index, sw_index - 1) <= 0)) { |
| 313 | ret = -EIO; | 286 | ret = -ENOSR; |
| 314 | goto exit; | 287 | goto exit; |
| 315 | } | 288 | } |
| 316 | 289 | ||
| @@ -346,7 +319,7 @@ exit: | |||
| 346 | return ret; | 319 | return ret; |
| 347 | } | 320 | } |
| 348 | 321 | ||
| 349 | int ath10k_ce_send(struct ce_state *ce_state, | 322 | int ath10k_ce_send(struct ath10k_ce_pipe *ce_state, |
| 350 | void *per_transfer_context, | 323 | void *per_transfer_context, |
| 351 | u32 buffer, | 324 | u32 buffer, |
| 352 | unsigned int nbytes, | 325 | unsigned int nbytes, |
| @@ -365,77 +338,26 @@ int ath10k_ce_send(struct ce_state *ce_state, | |||
| 365 | return ret; | 338 | return ret; |
| 366 | } | 339 | } |
| 367 | 340 | ||
| 368 | void ath10k_ce_sendlist_buf_add(struct ce_sendlist *sendlist, u32 buffer, | 341 | int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe) |
| 369 | unsigned int nbytes, u32 flags) | ||
| 370 | { | 342 | { |
| 371 | unsigned int num_items = sendlist->num_items; | 343 | struct ath10k *ar = pipe->ar; |
| 372 | struct ce_sendlist_item *item; | ||
| 373 | |||
| 374 | item = &sendlist->item[num_items]; | ||
| 375 | item->data = buffer; | ||
| 376 | item->u.nbytes = nbytes; | ||
| 377 | item->flags = flags; | ||
| 378 | sendlist->num_items++; | ||
| 379 | } | ||
| 380 | |||
| 381 | int ath10k_ce_sendlist_send(struct ce_state *ce_state, | ||
| 382 | void *per_transfer_context, | ||
| 383 | struct ce_sendlist *sendlist, | ||
| 384 | unsigned int transfer_id) | ||
| 385 | { | ||
| 386 | struct ce_ring_state *src_ring = ce_state->src_ring; | ||
| 387 | struct ce_sendlist_item *item; | ||
| 388 | struct ath10k *ar = ce_state->ar; | ||
| 389 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 344 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 390 | unsigned int nentries_mask = src_ring->nentries_mask; | 345 | int delta; |
| 391 | unsigned int num_items = sendlist->num_items; | ||
| 392 | unsigned int sw_index; | ||
| 393 | unsigned int write_index; | ||
| 394 | int i, delta, ret = -ENOMEM; | ||
| 395 | 346 | ||
| 396 | spin_lock_bh(&ar_pci->ce_lock); | 347 | spin_lock_bh(&ar_pci->ce_lock); |
| 397 | 348 | delta = CE_RING_DELTA(pipe->src_ring->nentries_mask, | |
| 398 | sw_index = src_ring->sw_index; | 349 | pipe->src_ring->write_index, |
| 399 | write_index = src_ring->write_index; | 350 | pipe->src_ring->sw_index - 1); |
| 400 | |||
| 401 | delta = CE_RING_DELTA(nentries_mask, write_index, sw_index - 1); | ||
| 402 | |||
| 403 | if (delta >= num_items) { | ||
| 404 | /* | ||
| 405 | * Handle all but the last item uniformly. | ||
| 406 | */ | ||
| 407 | for (i = 0; i < num_items - 1; i++) { | ||
| 408 | item = &sendlist->item[i]; | ||
| 409 | ret = ath10k_ce_send_nolock(ce_state, | ||
| 410 | CE_SENDLIST_ITEM_CTXT, | ||
| 411 | (u32) item->data, | ||
| 412 | item->u.nbytes, transfer_id, | ||
| 413 | item->flags | | ||
| 414 | CE_SEND_FLAG_GATHER); | ||
| 415 | if (ret) | ||
| 416 | ath10k_warn("CE send failed for item: %d\n", i); | ||
| 417 | } | ||
| 418 | /* | ||
| 419 | * Provide valid context pointer for final item. | ||
| 420 | */ | ||
| 421 | item = &sendlist->item[i]; | ||
| 422 | ret = ath10k_ce_send_nolock(ce_state, per_transfer_context, | ||
| 423 | (u32) item->data, item->u.nbytes, | ||
| 424 | transfer_id, item->flags); | ||
| 425 | if (ret) | ||
| 426 | ath10k_warn("CE send failed for last item: %d\n", i); | ||
| 427 | } | ||
| 428 | |||
| 429 | spin_unlock_bh(&ar_pci->ce_lock); | 351 | spin_unlock_bh(&ar_pci->ce_lock); |
| 430 | 352 | ||
| 431 | return ret; | 353 | return delta; |
| 432 | } | 354 | } |
| 433 | 355 | ||
| 434 | int ath10k_ce_recv_buf_enqueue(struct ce_state *ce_state, | 356 | int ath10k_ce_recv_buf_enqueue(struct ath10k_ce_pipe *ce_state, |
| 435 | void *per_recv_context, | 357 | void *per_recv_context, |
| 436 | u32 buffer) | 358 | u32 buffer) |
| 437 | { | 359 | { |
| 438 | struct ce_ring_state *dest_ring = ce_state->dest_ring; | 360 | struct ath10k_ce_ring *dest_ring = ce_state->dest_ring; |
| 439 | u32 ctrl_addr = ce_state->ctrl_addr; | 361 | u32 ctrl_addr = ce_state->ctrl_addr; |
| 440 | struct ath10k *ar = ce_state->ar; | 362 | struct ath10k *ar = ce_state->ar; |
| 441 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 363 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| @@ -448,7 +370,9 @@ int ath10k_ce_recv_buf_enqueue(struct ce_state *ce_state, | |||
| 448 | write_index = dest_ring->write_index; | 370 | write_index = dest_ring->write_index; |
| 449 | sw_index = dest_ring->sw_index; | 371 | sw_index = dest_ring->sw_index; |
| 450 | 372 | ||
| 451 | ath10k_pci_wake(ar); | 373 | ret = ath10k_pci_wake(ar); |
| 374 | if (ret) | ||
| 375 | goto out; | ||
| 452 | 376 | ||
| 453 | if (CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) > 0) { | 377 | if (CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) > 0) { |
| 454 | struct ce_desc *base = dest_ring->base_addr_owner_space; | 378 | struct ce_desc *base = dest_ring->base_addr_owner_space; |
| @@ -470,6 +394,8 @@ int ath10k_ce_recv_buf_enqueue(struct ce_state *ce_state, | |||
| 470 | ret = -EIO; | 394 | ret = -EIO; |
| 471 | } | 395 | } |
| 472 | ath10k_pci_sleep(ar); | 396 | ath10k_pci_sleep(ar); |
| 397 | |||
| 398 | out: | ||
| 473 | spin_unlock_bh(&ar_pci->ce_lock); | 399 | spin_unlock_bh(&ar_pci->ce_lock); |
| 474 | 400 | ||
| 475 | return ret; | 401 | return ret; |
| @@ -479,14 +405,14 @@ int ath10k_ce_recv_buf_enqueue(struct ce_state *ce_state, | |||
| 479 | * Guts of ath10k_ce_completed_recv_next. | 405 | * Guts of ath10k_ce_completed_recv_next. |
| 480 | * The caller takes responsibility for any necessary locking. | 406 | * The caller takes responsibility for any necessary locking. |
| 481 | */ | 407 | */ |
| 482 | static int ath10k_ce_completed_recv_next_nolock(struct ce_state *ce_state, | 408 | static int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state, |
| 483 | void **per_transfer_contextp, | 409 | void **per_transfer_contextp, |
| 484 | u32 *bufferp, | 410 | u32 *bufferp, |
| 485 | unsigned int *nbytesp, | 411 | unsigned int *nbytesp, |
| 486 | unsigned int *transfer_idp, | 412 | unsigned int *transfer_idp, |
| 487 | unsigned int *flagsp) | 413 | unsigned int *flagsp) |
| 488 | { | 414 | { |
| 489 | struct ce_ring_state *dest_ring = ce_state->dest_ring; | 415 | struct ath10k_ce_ring *dest_ring = ce_state->dest_ring; |
| 490 | unsigned int nentries_mask = dest_ring->nentries_mask; | 416 | unsigned int nentries_mask = dest_ring->nentries_mask; |
| 491 | unsigned int sw_index = dest_ring->sw_index; | 417 | unsigned int sw_index = dest_ring->sw_index; |
| 492 | 418 | ||
| @@ -535,7 +461,7 @@ static int ath10k_ce_completed_recv_next_nolock(struct ce_state *ce_state, | |||
| 535 | return 0; | 461 | return 0; |
| 536 | } | 462 | } |
| 537 | 463 | ||
| 538 | int ath10k_ce_completed_recv_next(struct ce_state *ce_state, | 464 | int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state, |
| 539 | void **per_transfer_contextp, | 465 | void **per_transfer_contextp, |
| 540 | u32 *bufferp, | 466 | u32 *bufferp, |
| 541 | unsigned int *nbytesp, | 467 | unsigned int *nbytesp, |
| @@ -556,11 +482,11 @@ int ath10k_ce_completed_recv_next(struct ce_state *ce_state, | |||
| 556 | return ret; | 482 | return ret; |
| 557 | } | 483 | } |
| 558 | 484 | ||
| 559 | int ath10k_ce_revoke_recv_next(struct ce_state *ce_state, | 485 | int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, |
| 560 | void **per_transfer_contextp, | 486 | void **per_transfer_contextp, |
| 561 | u32 *bufferp) | 487 | u32 *bufferp) |
| 562 | { | 488 | { |
| 563 | struct ce_ring_state *dest_ring; | 489 | struct ath10k_ce_ring *dest_ring; |
| 564 | unsigned int nentries_mask; | 490 | unsigned int nentries_mask; |
| 565 | unsigned int sw_index; | 491 | unsigned int sw_index; |
| 566 | unsigned int write_index; | 492 | unsigned int write_index; |
| @@ -612,19 +538,20 @@ int ath10k_ce_revoke_recv_next(struct ce_state *ce_state, | |||
| 612 | * Guts of ath10k_ce_completed_send_next. | 538 | * Guts of ath10k_ce_completed_send_next. |
| 613 | * The caller takes responsibility for any necessary locking. | 539 | * The caller takes responsibility for any necessary locking. |
| 614 | */ | 540 | */ |
| 615 | static int ath10k_ce_completed_send_next_nolock(struct ce_state *ce_state, | 541 | static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, |
| 616 | void **per_transfer_contextp, | 542 | void **per_transfer_contextp, |
| 617 | u32 *bufferp, | 543 | u32 *bufferp, |
| 618 | unsigned int *nbytesp, | 544 | unsigned int *nbytesp, |
| 619 | unsigned int *transfer_idp) | 545 | unsigned int *transfer_idp) |
| 620 | { | 546 | { |
| 621 | struct ce_ring_state *src_ring = ce_state->src_ring; | 547 | struct ath10k_ce_ring *src_ring = ce_state->src_ring; |
| 622 | u32 ctrl_addr = ce_state->ctrl_addr; | 548 | u32 ctrl_addr = ce_state->ctrl_addr; |
| 623 | struct ath10k *ar = ce_state->ar; | 549 | struct ath10k *ar = ce_state->ar; |
| 624 | unsigned int nentries_mask = src_ring->nentries_mask; | 550 | unsigned int nentries_mask = src_ring->nentries_mask; |
| 625 | unsigned int sw_index = src_ring->sw_index; | 551 | unsigned int sw_index = src_ring->sw_index; |
| 552 | struct ce_desc *sdesc, *sbase; | ||
| 626 | unsigned int read_index; | 553 | unsigned int read_index; |
| 627 | int ret = -EIO; | 554 | int ret; |
| 628 | 555 | ||
| 629 | if (src_ring->hw_index == sw_index) { | 556 | if (src_ring->hw_index == sw_index) { |
| 630 | /* | 557 | /* |
| @@ -634,48 +561,54 @@ static int ath10k_ce_completed_send_next_nolock(struct ce_state *ce_state, | |||
| 634 | * the SW has really caught up to the HW, or if the cached | 561 | * the SW has really caught up to the HW, or if the cached |
| 635 | * value of the HW index has become stale. | 562 | * value of the HW index has become stale. |
| 636 | */ | 563 | */ |
| 637 | ath10k_pci_wake(ar); | 564 | |
| 565 | ret = ath10k_pci_wake(ar); | ||
| 566 | if (ret) | ||
| 567 | return ret; | ||
| 568 | |||
| 638 | src_ring->hw_index = | 569 | src_ring->hw_index = |
| 639 | ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); | 570 | ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); |
| 640 | src_ring->hw_index &= nentries_mask; | 571 | src_ring->hw_index &= nentries_mask; |
| 572 | |||
| 641 | ath10k_pci_sleep(ar); | 573 | ath10k_pci_sleep(ar); |
| 642 | } | 574 | } |
| 575 | |||
| 643 | read_index = src_ring->hw_index; | 576 | read_index = src_ring->hw_index; |
| 644 | 577 | ||
| 645 | if ((read_index != sw_index) && (read_index != 0xffffffff)) { | 578 | if ((read_index == sw_index) || (read_index == 0xffffffff)) |
| 646 | struct ce_desc *sbase = src_ring->shadow_base; | 579 | return -EIO; |
| 647 | struct ce_desc *sdesc = CE_SRC_RING_TO_DESC(sbase, sw_index); | ||
| 648 | 580 | ||
| 649 | /* Return data from completed source descriptor */ | 581 | sbase = src_ring->shadow_base; |
| 650 | *bufferp = __le32_to_cpu(sdesc->addr); | 582 | sdesc = CE_SRC_RING_TO_DESC(sbase, sw_index); |
| 651 | *nbytesp = __le16_to_cpu(sdesc->nbytes); | ||
| 652 | *transfer_idp = MS(__le16_to_cpu(sdesc->flags), | ||
| 653 | CE_DESC_FLAGS_META_DATA); | ||
| 654 | 583 | ||
| 655 | if (per_transfer_contextp) | 584 | /* Return data from completed source descriptor */ |
| 656 | *per_transfer_contextp = | 585 | *bufferp = __le32_to_cpu(sdesc->addr); |
| 657 | src_ring->per_transfer_context[sw_index]; | 586 | *nbytesp = __le16_to_cpu(sdesc->nbytes); |
| 587 | *transfer_idp = MS(__le16_to_cpu(sdesc->flags), | ||
| 588 | CE_DESC_FLAGS_META_DATA); | ||
| 658 | 589 | ||
| 659 | /* sanity */ | 590 | if (per_transfer_contextp) |
| 660 | src_ring->per_transfer_context[sw_index] = NULL; | 591 | *per_transfer_contextp = |
| 592 | src_ring->per_transfer_context[sw_index]; | ||
| 661 | 593 | ||
| 662 | /* Update sw_index */ | 594 | /* sanity */ |
| 663 | sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); | 595 | src_ring->per_transfer_context[sw_index] = NULL; |
| 664 | src_ring->sw_index = sw_index; | ||
| 665 | ret = 0; | ||
| 666 | } | ||
| 667 | 596 | ||
| 668 | return ret; | 597 | /* Update sw_index */ |
| 598 | sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); | ||
| 599 | src_ring->sw_index = sw_index; | ||
| 600 | |||
| 601 | return 0; | ||
| 669 | } | 602 | } |
| 670 | 603 | ||
| 671 | /* NB: Modeled after ath10k_ce_completed_send_next */ | 604 | /* NB: Modeled after ath10k_ce_completed_send_next */ |
| 672 | int ath10k_ce_cancel_send_next(struct ce_state *ce_state, | 605 | int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state, |
| 673 | void **per_transfer_contextp, | 606 | void **per_transfer_contextp, |
| 674 | u32 *bufferp, | 607 | u32 *bufferp, |
| 675 | unsigned int *nbytesp, | 608 | unsigned int *nbytesp, |
| 676 | unsigned int *transfer_idp) | 609 | unsigned int *transfer_idp) |
| 677 | { | 610 | { |
| 678 | struct ce_ring_state *src_ring; | 611 | struct ath10k_ce_ring *src_ring; |
| 679 | unsigned int nentries_mask; | 612 | unsigned int nentries_mask; |
| 680 | unsigned int sw_index; | 613 | unsigned int sw_index; |
| 681 | unsigned int write_index; | 614 | unsigned int write_index; |
| @@ -727,7 +660,7 @@ int ath10k_ce_cancel_send_next(struct ce_state *ce_state, | |||
| 727 | return ret; | 660 | return ret; |
| 728 | } | 661 | } |
| 729 | 662 | ||
| 730 | int ath10k_ce_completed_send_next(struct ce_state *ce_state, | 663 | int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state, |
| 731 | void **per_transfer_contextp, | 664 | void **per_transfer_contextp, |
| 732 | u32 *bufferp, | 665 | u32 *bufferp, |
| 733 | unsigned int *nbytesp, | 666 | unsigned int *nbytesp, |
| @@ -756,53 +689,29 @@ int ath10k_ce_completed_send_next(struct ce_state *ce_state, | |||
| 756 | void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id) | 689 | void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id) |
| 757 | { | 690 | { |
| 758 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 691 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 759 | struct ce_state *ce_state = ar_pci->ce_id_to_state[ce_id]; | 692 | struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; |
| 760 | u32 ctrl_addr = ce_state->ctrl_addr; | 693 | u32 ctrl_addr = ce_state->ctrl_addr; |
| 761 | void *transfer_context; | 694 | int ret; |
| 762 | u32 buf; | 695 | |
| 763 | unsigned int nbytes; | 696 | ret = ath10k_pci_wake(ar); |
| 764 | unsigned int id; | 697 | if (ret) |
| 765 | unsigned int flags; | 698 | return; |
| 766 | 699 | ||
| 767 | ath10k_pci_wake(ar); | ||
| 768 | spin_lock_bh(&ar_pci->ce_lock); | 700 | spin_lock_bh(&ar_pci->ce_lock); |
| 769 | 701 | ||
| 770 | /* Clear the copy-complete interrupts that will be handled here. */ | 702 | /* Clear the copy-complete interrupts that will be handled here. */ |
| 771 | ath10k_ce_engine_int_status_clear(ar, ctrl_addr, | 703 | ath10k_ce_engine_int_status_clear(ar, ctrl_addr, |
| 772 | HOST_IS_COPY_COMPLETE_MASK); | 704 | HOST_IS_COPY_COMPLETE_MASK); |
| 773 | 705 | ||
| 774 | if (ce_state->recv_cb) { | 706 | spin_unlock_bh(&ar_pci->ce_lock); |
| 775 | /* | ||
| 776 | * Pop completed recv buffers and call the registered | ||
| 777 | * recv callback for each | ||
| 778 | */ | ||
| 779 | while (ath10k_ce_completed_recv_next_nolock(ce_state, | ||
| 780 | &transfer_context, | ||
| 781 | &buf, &nbytes, | ||
| 782 | &id, &flags) == 0) { | ||
| 783 | spin_unlock_bh(&ar_pci->ce_lock); | ||
| 784 | ce_state->recv_cb(ce_state, transfer_context, buf, | ||
| 785 | nbytes, id, flags); | ||
| 786 | spin_lock_bh(&ar_pci->ce_lock); | ||
| 787 | } | ||
| 788 | } | ||
| 789 | 707 | ||
| 790 | if (ce_state->send_cb) { | 708 | if (ce_state->recv_cb) |
| 791 | /* | 709 | ce_state->recv_cb(ce_state); |
| 792 | * Pop completed send buffers and call the registered | 710 | |
| 793 | * send callback for each | 711 | if (ce_state->send_cb) |
| 794 | */ | 712 | ce_state->send_cb(ce_state); |
| 795 | while (ath10k_ce_completed_send_next_nolock(ce_state, | 713 | |
| 796 | &transfer_context, | 714 | spin_lock_bh(&ar_pci->ce_lock); |
| 797 | &buf, | ||
| 798 | &nbytes, | ||
| 799 | &id) == 0) { | ||
| 800 | spin_unlock_bh(&ar_pci->ce_lock); | ||
| 801 | ce_state->send_cb(ce_state, transfer_context, | ||
| 802 | buf, nbytes, id); | ||
| 803 | spin_lock_bh(&ar_pci->ce_lock); | ||
| 804 | } | ||
| 805 | } | ||
| 806 | 715 | ||
| 807 | /* | 716 | /* |
| 808 | * Misc CE interrupts are not being handled, but still need | 717 | * Misc CE interrupts are not being handled, but still need |
| @@ -823,10 +732,13 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id) | |||
| 823 | void ath10k_ce_per_engine_service_any(struct ath10k *ar) | 732 | void ath10k_ce_per_engine_service_any(struct ath10k *ar) |
| 824 | { | 733 | { |
| 825 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 734 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 826 | int ce_id; | 735 | int ce_id, ret; |
| 827 | u32 intr_summary; | 736 | u32 intr_summary; |
| 828 | 737 | ||
| 829 | ath10k_pci_wake(ar); | 738 | ret = ath10k_pci_wake(ar); |
| 739 | if (ret) | ||
| 740 | return; | ||
| 741 | |||
| 830 | intr_summary = CE_INTERRUPT_SUMMARY(ar); | 742 | intr_summary = CE_INTERRUPT_SUMMARY(ar); |
| 831 | 743 | ||
| 832 | for (ce_id = 0; intr_summary && (ce_id < ar_pci->ce_count); ce_id++) { | 744 | for (ce_id = 0; intr_summary && (ce_id < ar_pci->ce_count); ce_id++) { |
| @@ -849,13 +761,16 @@ void ath10k_ce_per_engine_service_any(struct ath10k *ar) | |||
| 849 | * | 761 | * |
| 850 | * Called with ce_lock held. | 762 | * Called with ce_lock held. |
| 851 | */ | 763 | */ |
| 852 | static void ath10k_ce_per_engine_handler_adjust(struct ce_state *ce_state, | 764 | static void ath10k_ce_per_engine_handler_adjust(struct ath10k_ce_pipe *ce_state, |
| 853 | int disable_copy_compl_intr) | 765 | int disable_copy_compl_intr) |
| 854 | { | 766 | { |
| 855 | u32 ctrl_addr = ce_state->ctrl_addr; | 767 | u32 ctrl_addr = ce_state->ctrl_addr; |
| 856 | struct ath10k *ar = ce_state->ar; | 768 | struct ath10k *ar = ce_state->ar; |
| 769 | int ret; | ||
| 857 | 770 | ||
| 858 | ath10k_pci_wake(ar); | 771 | ret = ath10k_pci_wake(ar); |
| 772 | if (ret) | ||
| 773 | return; | ||
| 859 | 774 | ||
| 860 | if ((!disable_copy_compl_intr) && | 775 | if ((!disable_copy_compl_intr) && |
| 861 | (ce_state->send_cb || ce_state->recv_cb)) | 776 | (ce_state->send_cb || ce_state->recv_cb)) |
| @@ -871,11 +786,14 @@ static void ath10k_ce_per_engine_handler_adjust(struct ce_state *ce_state, | |||
| 871 | void ath10k_ce_disable_interrupts(struct ath10k *ar) | 786 | void ath10k_ce_disable_interrupts(struct ath10k *ar) |
| 872 | { | 787 | { |
| 873 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 788 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 874 | int ce_id; | 789 | int ce_id, ret; |
| 790 | |||
| 791 | ret = ath10k_pci_wake(ar); | ||
| 792 | if (ret) | ||
| 793 | return; | ||
| 875 | 794 | ||
| 876 | ath10k_pci_wake(ar); | ||
| 877 | for (ce_id = 0; ce_id < ar_pci->ce_count; ce_id++) { | 795 | for (ce_id = 0; ce_id < ar_pci->ce_count; ce_id++) { |
| 878 | struct ce_state *ce_state = ar_pci->ce_id_to_state[ce_id]; | 796 | struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; |
| 879 | u32 ctrl_addr = ce_state->ctrl_addr; | 797 | u32 ctrl_addr = ce_state->ctrl_addr; |
| 880 | 798 | ||
| 881 | ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr); | 799 | ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr); |
| @@ -883,12 +801,8 @@ void ath10k_ce_disable_interrupts(struct ath10k *ar) | |||
| 883 | ath10k_pci_sleep(ar); | 801 | ath10k_pci_sleep(ar); |
| 884 | } | 802 | } |
| 885 | 803 | ||
| 886 | void ath10k_ce_send_cb_register(struct ce_state *ce_state, | 804 | void ath10k_ce_send_cb_register(struct ath10k_ce_pipe *ce_state, |
| 887 | void (*send_cb) (struct ce_state *ce_state, | 805 | void (*send_cb)(struct ath10k_ce_pipe *), |
| 888 | void *transfer_context, | ||
| 889 | u32 buffer, | ||
| 890 | unsigned int nbytes, | ||
| 891 | unsigned int transfer_id), | ||
| 892 | int disable_interrupts) | 806 | int disable_interrupts) |
| 893 | { | 807 | { |
| 894 | struct ath10k *ar = ce_state->ar; | 808 | struct ath10k *ar = ce_state->ar; |
| @@ -900,13 +814,8 @@ void ath10k_ce_send_cb_register(struct ce_state *ce_state, | |||
| 900 | spin_unlock_bh(&ar_pci->ce_lock); | 814 | spin_unlock_bh(&ar_pci->ce_lock); |
| 901 | } | 815 | } |
| 902 | 816 | ||
| 903 | void ath10k_ce_recv_cb_register(struct ce_state *ce_state, | 817 | void ath10k_ce_recv_cb_register(struct ath10k_ce_pipe *ce_state, |
| 904 | void (*recv_cb) (struct ce_state *ce_state, | 818 | void (*recv_cb)(struct ath10k_ce_pipe *)) |
| 905 | void *transfer_context, | ||
| 906 | u32 buffer, | ||
| 907 | unsigned int nbytes, | ||
| 908 | unsigned int transfer_id, | ||
| 909 | unsigned int flags)) | ||
| 910 | { | 819 | { |
| 911 | struct ath10k *ar = ce_state->ar; | 820 | struct ath10k *ar = ce_state->ar; |
| 912 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 821 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| @@ -919,11 +828,11 @@ void ath10k_ce_recv_cb_register(struct ce_state *ce_state, | |||
| 919 | 828 | ||
| 920 | static int ath10k_ce_init_src_ring(struct ath10k *ar, | 829 | static int ath10k_ce_init_src_ring(struct ath10k *ar, |
| 921 | unsigned int ce_id, | 830 | unsigned int ce_id, |
| 922 | struct ce_state *ce_state, | 831 | struct ath10k_ce_pipe *ce_state, |
| 923 | const struct ce_attr *attr) | 832 | const struct ce_attr *attr) |
| 924 | { | 833 | { |
| 925 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 834 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 926 | struct ce_ring_state *src_ring; | 835 | struct ath10k_ce_ring *src_ring; |
| 927 | unsigned int nentries = attr->src_nentries; | 836 | unsigned int nentries = attr->src_nentries; |
| 928 | unsigned int ce_nbytes; | 837 | unsigned int ce_nbytes; |
| 929 | u32 ctrl_addr = ath10k_ce_base_address(ce_id); | 838 | u32 ctrl_addr = ath10k_ce_base_address(ce_id); |
| @@ -937,19 +846,18 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar, | |||
| 937 | return 0; | 846 | return 0; |
| 938 | } | 847 | } |
| 939 | 848 | ||
| 940 | ce_nbytes = sizeof(struct ce_ring_state) + (nentries * sizeof(void *)); | 849 | ce_nbytes = sizeof(struct ath10k_ce_ring) + (nentries * sizeof(void *)); |
| 941 | ptr = kzalloc(ce_nbytes, GFP_KERNEL); | 850 | ptr = kzalloc(ce_nbytes, GFP_KERNEL); |
| 942 | if (ptr == NULL) | 851 | if (ptr == NULL) |
| 943 | return -ENOMEM; | 852 | return -ENOMEM; |
| 944 | 853 | ||
| 945 | ce_state->src_ring = (struct ce_ring_state *)ptr; | 854 | ce_state->src_ring = (struct ath10k_ce_ring *)ptr; |
| 946 | src_ring = ce_state->src_ring; | 855 | src_ring = ce_state->src_ring; |
| 947 | 856 | ||
| 948 | ptr += sizeof(struct ce_ring_state); | 857 | ptr += sizeof(struct ath10k_ce_ring); |
| 949 | src_ring->nentries = nentries; | 858 | src_ring->nentries = nentries; |
| 950 | src_ring->nentries_mask = nentries - 1; | 859 | src_ring->nentries_mask = nentries - 1; |
| 951 | 860 | ||
| 952 | ath10k_pci_wake(ar); | ||
| 953 | src_ring->sw_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); | 861 | src_ring->sw_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); |
| 954 | src_ring->sw_index &= src_ring->nentries_mask; | 862 | src_ring->sw_index &= src_ring->nentries_mask; |
| 955 | src_ring->hw_index = src_ring->sw_index; | 863 | src_ring->hw_index = src_ring->sw_index; |
| @@ -957,7 +865,6 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar, | |||
| 957 | src_ring->write_index = | 865 | src_ring->write_index = |
| 958 | ath10k_ce_src_ring_write_index_get(ar, ctrl_addr); | 866 | ath10k_ce_src_ring_write_index_get(ar, ctrl_addr); |
| 959 | src_ring->write_index &= src_ring->nentries_mask; | 867 | src_ring->write_index &= src_ring->nentries_mask; |
| 960 | ath10k_pci_sleep(ar); | ||
| 961 | 868 | ||
| 962 | src_ring->per_transfer_context = (void **)ptr; | 869 | src_ring->per_transfer_context = (void **)ptr; |
| 963 | 870 | ||
| @@ -970,6 +877,12 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar, | |||
| 970 | (nentries * sizeof(struct ce_desc) + | 877 | (nentries * sizeof(struct ce_desc) + |
| 971 | CE_DESC_RING_ALIGN), | 878 | CE_DESC_RING_ALIGN), |
| 972 | &base_addr); | 879 | &base_addr); |
| 880 | if (!src_ring->base_addr_owner_space_unaligned) { | ||
| 881 | kfree(ce_state->src_ring); | ||
| 882 | ce_state->src_ring = NULL; | ||
| 883 | return -ENOMEM; | ||
| 884 | } | ||
| 885 | |||
| 973 | src_ring->base_addr_ce_space_unaligned = base_addr; | 886 | src_ring->base_addr_ce_space_unaligned = base_addr; |
| 974 | 887 | ||
| 975 | src_ring->base_addr_owner_space = PTR_ALIGN( | 888 | src_ring->base_addr_owner_space = PTR_ALIGN( |
| @@ -986,12 +899,21 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar, | |||
| 986 | src_ring->shadow_base_unaligned = | 899 | src_ring->shadow_base_unaligned = |
| 987 | kmalloc((nentries * sizeof(struct ce_desc) + | 900 | kmalloc((nentries * sizeof(struct ce_desc) + |
| 988 | CE_DESC_RING_ALIGN), GFP_KERNEL); | 901 | CE_DESC_RING_ALIGN), GFP_KERNEL); |
| 902 | if (!src_ring->shadow_base_unaligned) { | ||
| 903 | pci_free_consistent(ar_pci->pdev, | ||
| 904 | (nentries * sizeof(struct ce_desc) + | ||
| 905 | CE_DESC_RING_ALIGN), | ||
| 906 | src_ring->base_addr_owner_space, | ||
| 907 | src_ring->base_addr_ce_space); | ||
| 908 | kfree(ce_state->src_ring); | ||
| 909 | ce_state->src_ring = NULL; | ||
| 910 | return -ENOMEM; | ||
| 911 | } | ||
| 989 | 912 | ||
| 990 | src_ring->shadow_base = PTR_ALIGN( | 913 | src_ring->shadow_base = PTR_ALIGN( |
| 991 | src_ring->shadow_base_unaligned, | 914 | src_ring->shadow_base_unaligned, |
| 992 | CE_DESC_RING_ALIGN); | 915 | CE_DESC_RING_ALIGN); |
| 993 | 916 | ||
| 994 | ath10k_pci_wake(ar); | ||
| 995 | ath10k_ce_src_ring_base_addr_set(ar, ctrl_addr, | 917 | ath10k_ce_src_ring_base_addr_set(ar, ctrl_addr, |
| 996 | src_ring->base_addr_ce_space); | 918 | src_ring->base_addr_ce_space); |
| 997 | ath10k_ce_src_ring_size_set(ar, ctrl_addr, nentries); | 919 | ath10k_ce_src_ring_size_set(ar, ctrl_addr, nentries); |
| @@ -999,18 +921,21 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar, | |||
| 999 | ath10k_ce_src_ring_byte_swap_set(ar, ctrl_addr, 0); | 921 | ath10k_ce_src_ring_byte_swap_set(ar, ctrl_addr, 0); |
| 1000 | ath10k_ce_src_ring_lowmark_set(ar, ctrl_addr, 0); | 922 | ath10k_ce_src_ring_lowmark_set(ar, ctrl_addr, 0); |
| 1001 | ath10k_ce_src_ring_highmark_set(ar, ctrl_addr, nentries); | 923 | ath10k_ce_src_ring_highmark_set(ar, ctrl_addr, nentries); |
| 1002 | ath10k_pci_sleep(ar); | 924 | |
| 925 | ath10k_dbg(ATH10K_DBG_BOOT, | ||
| 926 | "boot ce src ring id %d entries %d base_addr %p\n", | ||
| 927 | ce_id, nentries, src_ring->base_addr_owner_space); | ||
| 1003 | 928 | ||
| 1004 | return 0; | 929 | return 0; |
| 1005 | } | 930 | } |
| 1006 | 931 | ||
| 1007 | static int ath10k_ce_init_dest_ring(struct ath10k *ar, | 932 | static int ath10k_ce_init_dest_ring(struct ath10k *ar, |
| 1008 | unsigned int ce_id, | 933 | unsigned int ce_id, |
| 1009 | struct ce_state *ce_state, | 934 | struct ath10k_ce_pipe *ce_state, |
| 1010 | const struct ce_attr *attr) | 935 | const struct ce_attr *attr) |
| 1011 | { | 936 | { |
| 1012 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 937 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 1013 | struct ce_ring_state *dest_ring; | 938 | struct ath10k_ce_ring *dest_ring; |
| 1014 | unsigned int nentries = attr->dest_nentries; | 939 | unsigned int nentries = attr->dest_nentries; |
| 1015 | unsigned int ce_nbytes; | 940 | unsigned int ce_nbytes; |
| 1016 | u32 ctrl_addr = ath10k_ce_base_address(ce_id); | 941 | u32 ctrl_addr = ath10k_ce_base_address(ce_id); |
| @@ -1024,25 +949,23 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar, | |||
| 1024 | return 0; | 949 | return 0; |
| 1025 | } | 950 | } |
| 1026 | 951 | ||
| 1027 | ce_nbytes = sizeof(struct ce_ring_state) + (nentries * sizeof(void *)); | 952 | ce_nbytes = sizeof(struct ath10k_ce_ring) + (nentries * sizeof(void *)); |
| 1028 | ptr = kzalloc(ce_nbytes, GFP_KERNEL); | 953 | ptr = kzalloc(ce_nbytes, GFP_KERNEL); |
| 1029 | if (ptr == NULL) | 954 | if (ptr == NULL) |
| 1030 | return -ENOMEM; | 955 | return -ENOMEM; |
| 1031 | 956 | ||
| 1032 | ce_state->dest_ring = (struct ce_ring_state *)ptr; | 957 | ce_state->dest_ring = (struct ath10k_ce_ring *)ptr; |
| 1033 | dest_ring = ce_state->dest_ring; | 958 | dest_ring = ce_state->dest_ring; |
| 1034 | 959 | ||
| 1035 | ptr += sizeof(struct ce_ring_state); | 960 | ptr += sizeof(struct ath10k_ce_ring); |
| 1036 | dest_ring->nentries = nentries; | 961 | dest_ring->nentries = nentries; |
| 1037 | dest_ring->nentries_mask = nentries - 1; | 962 | dest_ring->nentries_mask = nentries - 1; |
| 1038 | 963 | ||
| 1039 | ath10k_pci_wake(ar); | ||
| 1040 | dest_ring->sw_index = ath10k_ce_dest_ring_read_index_get(ar, ctrl_addr); | 964 | dest_ring->sw_index = ath10k_ce_dest_ring_read_index_get(ar, ctrl_addr); |
| 1041 | dest_ring->sw_index &= dest_ring->nentries_mask; | 965 | dest_ring->sw_index &= dest_ring->nentries_mask; |
| 1042 | dest_ring->write_index = | 966 | dest_ring->write_index = |
| 1043 | ath10k_ce_dest_ring_write_index_get(ar, ctrl_addr); | 967 | ath10k_ce_dest_ring_write_index_get(ar, ctrl_addr); |
| 1044 | dest_ring->write_index &= dest_ring->nentries_mask; | 968 | dest_ring->write_index &= dest_ring->nentries_mask; |
| 1045 | ath10k_pci_sleep(ar); | ||
| 1046 | 969 | ||
| 1047 | dest_ring->per_transfer_context = (void **)ptr; | 970 | dest_ring->per_transfer_context = (void **)ptr; |
| 1048 | 971 | ||
| @@ -1055,6 +978,12 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar, | |||
| 1055 | (nentries * sizeof(struct ce_desc) + | 978 | (nentries * sizeof(struct ce_desc) + |
| 1056 | CE_DESC_RING_ALIGN), | 979 | CE_DESC_RING_ALIGN), |
| 1057 | &base_addr); | 980 | &base_addr); |
| 981 | if (!dest_ring->base_addr_owner_space_unaligned) { | ||
| 982 | kfree(ce_state->dest_ring); | ||
| 983 | ce_state->dest_ring = NULL; | ||
| 984 | return -ENOMEM; | ||
| 985 | } | ||
| 986 | |||
| 1058 | dest_ring->base_addr_ce_space_unaligned = base_addr; | 987 | dest_ring->base_addr_ce_space_unaligned = base_addr; |
| 1059 | 988 | ||
| 1060 | /* | 989 | /* |
| @@ -1071,44 +1000,35 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar, | |||
| 1071 | dest_ring->base_addr_ce_space_unaligned, | 1000 | dest_ring->base_addr_ce_space_unaligned, |
| 1072 | CE_DESC_RING_ALIGN); | 1001 | CE_DESC_RING_ALIGN); |
| 1073 | 1002 | ||
| 1074 | ath10k_pci_wake(ar); | ||
| 1075 | ath10k_ce_dest_ring_base_addr_set(ar, ctrl_addr, | 1003 | ath10k_ce_dest_ring_base_addr_set(ar, ctrl_addr, |
| 1076 | dest_ring->base_addr_ce_space); | 1004 | dest_ring->base_addr_ce_space); |
| 1077 | ath10k_ce_dest_ring_size_set(ar, ctrl_addr, nentries); | 1005 | ath10k_ce_dest_ring_size_set(ar, ctrl_addr, nentries); |
| 1078 | ath10k_ce_dest_ring_byte_swap_set(ar, ctrl_addr, 0); | 1006 | ath10k_ce_dest_ring_byte_swap_set(ar, ctrl_addr, 0); |
| 1079 | ath10k_ce_dest_ring_lowmark_set(ar, ctrl_addr, 0); | 1007 | ath10k_ce_dest_ring_lowmark_set(ar, ctrl_addr, 0); |
| 1080 | ath10k_ce_dest_ring_highmark_set(ar, ctrl_addr, nentries); | 1008 | ath10k_ce_dest_ring_highmark_set(ar, ctrl_addr, nentries); |
| 1081 | ath10k_pci_sleep(ar); | 1009 | |
| 1010 | ath10k_dbg(ATH10K_DBG_BOOT, | ||
| 1011 | "boot ce dest ring id %d entries %d base_addr %p\n", | ||
| 1012 | ce_id, nentries, dest_ring->base_addr_owner_space); | ||
| 1082 | 1013 | ||
| 1083 | return 0; | 1014 | return 0; |
| 1084 | } | 1015 | } |
| 1085 | 1016 | ||
| 1086 | static struct ce_state *ath10k_ce_init_state(struct ath10k *ar, | 1017 | static struct ath10k_ce_pipe *ath10k_ce_init_state(struct ath10k *ar, |
| 1087 | unsigned int ce_id, | 1018 | unsigned int ce_id, |
| 1088 | const struct ce_attr *attr) | 1019 | const struct ce_attr *attr) |
| 1089 | { | 1020 | { |
| 1090 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 1021 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 1091 | struct ce_state *ce_state = NULL; | 1022 | struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; |
| 1092 | u32 ctrl_addr = ath10k_ce_base_address(ce_id); | 1023 | u32 ctrl_addr = ath10k_ce_base_address(ce_id); |
| 1093 | 1024 | ||
| 1094 | spin_lock_bh(&ar_pci->ce_lock); | 1025 | spin_lock_bh(&ar_pci->ce_lock); |
| 1095 | 1026 | ||
| 1096 | if (!ar_pci->ce_id_to_state[ce_id]) { | 1027 | ce_state->ar = ar; |
| 1097 | ce_state = kzalloc(sizeof(*ce_state), GFP_ATOMIC); | 1028 | ce_state->id = ce_id; |
| 1098 | if (ce_state == NULL) { | 1029 | ce_state->ctrl_addr = ctrl_addr; |
| 1099 | spin_unlock_bh(&ar_pci->ce_lock); | 1030 | ce_state->attr_flags = attr->flags; |
| 1100 | return NULL; | 1031 | ce_state->src_sz_max = attr->src_sz_max; |
| 1101 | } | ||
| 1102 | |||
| 1103 | ar_pci->ce_id_to_state[ce_id] = ce_state; | ||
| 1104 | ce_state->ar = ar; | ||
| 1105 | ce_state->id = ce_id; | ||
| 1106 | ce_state->ctrl_addr = ctrl_addr; | ||
| 1107 | ce_state->state = CE_RUNNING; | ||
| 1108 | /* Save attribute flags */ | ||
| 1109 | ce_state->attr_flags = attr->flags; | ||
| 1110 | ce_state->src_sz_max = attr->src_sz_max; | ||
| 1111 | } | ||
| 1112 | 1032 | ||
| 1113 | spin_unlock_bh(&ar_pci->ce_lock); | 1033 | spin_unlock_bh(&ar_pci->ce_lock); |
| 1114 | 1034 | ||
| @@ -1122,12 +1042,17 @@ static struct ce_state *ath10k_ce_init_state(struct ath10k *ar, | |||
| 1122 | * initialization. It may be that only one side or the other is | 1042 | * initialization. It may be that only one side or the other is |
| 1123 | * initialized by software/firmware. | 1043 | * initialized by software/firmware. |
| 1124 | */ | 1044 | */ |
| 1125 | struct ce_state *ath10k_ce_init(struct ath10k *ar, | 1045 | struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar, |
| 1126 | unsigned int ce_id, | 1046 | unsigned int ce_id, |
| 1127 | const struct ce_attr *attr) | 1047 | const struct ce_attr *attr) |
| 1128 | { | 1048 | { |
| 1129 | struct ce_state *ce_state; | 1049 | struct ath10k_ce_pipe *ce_state; |
| 1130 | u32 ctrl_addr = ath10k_ce_base_address(ce_id); | 1050 | u32 ctrl_addr = ath10k_ce_base_address(ce_id); |
| 1051 | int ret; | ||
| 1052 | |||
| 1053 | ret = ath10k_pci_wake(ar); | ||
| 1054 | if (ret) | ||
| 1055 | return NULL; | ||
| 1131 | 1056 | ||
| 1132 | ce_state = ath10k_ce_init_state(ar, ce_id, attr); | 1057 | ce_state = ath10k_ce_init_state(ar, ce_id, attr); |
| 1133 | if (!ce_state) { | 1058 | if (!ce_state) { |
| @@ -1136,40 +1061,38 @@ struct ce_state *ath10k_ce_init(struct ath10k *ar, | |||
| 1136 | } | 1061 | } |
| 1137 | 1062 | ||
| 1138 | if (attr->src_nentries) { | 1063 | if (attr->src_nentries) { |
| 1139 | if (ath10k_ce_init_src_ring(ar, ce_id, ce_state, attr)) { | 1064 | ret = ath10k_ce_init_src_ring(ar, ce_id, ce_state, attr); |
| 1140 | ath10k_err("Failed to initialize CE src ring for ID: %d\n", | 1065 | if (ret) { |
| 1141 | ce_id); | 1066 | ath10k_err("Failed to initialize CE src ring for ID: %d (%d)\n", |
| 1067 | ce_id, ret); | ||
| 1142 | ath10k_ce_deinit(ce_state); | 1068 | ath10k_ce_deinit(ce_state); |
| 1143 | return NULL; | 1069 | return NULL; |
| 1144 | } | 1070 | } |
| 1145 | } | 1071 | } |
| 1146 | 1072 | ||
| 1147 | if (attr->dest_nentries) { | 1073 | if (attr->dest_nentries) { |
| 1148 | if (ath10k_ce_init_dest_ring(ar, ce_id, ce_state, attr)) { | 1074 | ret = ath10k_ce_init_dest_ring(ar, ce_id, ce_state, attr); |
| 1149 | ath10k_err("Failed to initialize CE dest ring for ID: %d\n", | 1075 | if (ret) { |
| 1150 | ce_id); | 1076 | ath10k_err("Failed to initialize CE dest ring for ID: %d (%d)\n", |
| 1077 | ce_id, ret); | ||
| 1151 | ath10k_ce_deinit(ce_state); | 1078 | ath10k_ce_deinit(ce_state); |
| 1152 | return NULL; | 1079 | return NULL; |
| 1153 | } | 1080 | } |
| 1154 | } | 1081 | } |
| 1155 | 1082 | ||
| 1156 | /* Enable CE error interrupts */ | 1083 | /* Enable CE error interrupts */ |
| 1157 | ath10k_pci_wake(ar); | ||
| 1158 | ath10k_ce_error_intr_enable(ar, ctrl_addr); | 1084 | ath10k_ce_error_intr_enable(ar, ctrl_addr); |
| 1085 | |||
| 1159 | ath10k_pci_sleep(ar); | 1086 | ath10k_pci_sleep(ar); |
| 1160 | 1087 | ||
| 1161 | return ce_state; | 1088 | return ce_state; |
| 1162 | } | 1089 | } |
| 1163 | 1090 | ||
| 1164 | void ath10k_ce_deinit(struct ce_state *ce_state) | 1091 | void ath10k_ce_deinit(struct ath10k_ce_pipe *ce_state) |
| 1165 | { | 1092 | { |
| 1166 | unsigned int ce_id = ce_state->id; | ||
| 1167 | struct ath10k *ar = ce_state->ar; | 1093 | struct ath10k *ar = ce_state->ar; |
| 1168 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 1094 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 1169 | 1095 | ||
| 1170 | ce_state->state = CE_UNUSED; | ||
| 1171 | ar_pci->ce_id_to_state[ce_id] = NULL; | ||
| 1172 | |||
| 1173 | if (ce_state->src_ring) { | 1096 | if (ce_state->src_ring) { |
| 1174 | kfree(ce_state->src_ring->shadow_base_unaligned); | 1097 | kfree(ce_state->src_ring->shadow_base_unaligned); |
| 1175 | pci_free_consistent(ar_pci->pdev, | 1098 | pci_free_consistent(ar_pci->pdev, |
| @@ -1190,5 +1113,7 @@ void ath10k_ce_deinit(struct ce_state *ce_state) | |||
| 1190 | ce_state->dest_ring->base_addr_ce_space); | 1113 | ce_state->dest_ring->base_addr_ce_space); |
| 1191 | kfree(ce_state->dest_ring); | 1114 | kfree(ce_state->dest_ring); |
| 1192 | } | 1115 | } |
| 1193 | kfree(ce_state); | 1116 | |
| 1117 | ce_state->src_ring = NULL; | ||
| 1118 | ce_state->dest_ring = NULL; | ||
| 1194 | } | 1119 | } |
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index c17f07c026f4..15d45b5b7615 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h | |||
| @@ -27,7 +27,6 @@ | |||
| 27 | 27 | ||
| 28 | /* Descriptor rings must be aligned to this boundary */ | 28 | /* Descriptor rings must be aligned to this boundary */ |
| 29 | #define CE_DESC_RING_ALIGN 8 | 29 | #define CE_DESC_RING_ALIGN 8 |
| 30 | #define CE_SENDLIST_ITEMS_MAX 12 | ||
| 31 | #define CE_SEND_FLAG_GATHER 0x00010000 | 30 | #define CE_SEND_FLAG_GATHER 0x00010000 |
| 32 | 31 | ||
| 33 | /* | 32 | /* |
| @@ -36,16 +35,9 @@ | |||
| 36 | * how to use copy engines. | 35 | * how to use copy engines. |
| 37 | */ | 36 | */ |
| 38 | 37 | ||
| 39 | struct ce_state; | 38 | struct ath10k_ce_pipe; |
| 40 | 39 | ||
| 41 | 40 | ||
| 42 | /* Copy Engine operational state */ | ||
| 43 | enum ce_op_state { | ||
| 44 | CE_UNUSED, | ||
| 45 | CE_PAUSED, | ||
| 46 | CE_RUNNING, | ||
| 47 | }; | ||
| 48 | |||
| 49 | #define CE_DESC_FLAGS_GATHER (1 << 0) | 41 | #define CE_DESC_FLAGS_GATHER (1 << 0) |
| 50 | #define CE_DESC_FLAGS_BYTE_SWAP (1 << 1) | 42 | #define CE_DESC_FLAGS_BYTE_SWAP (1 << 1) |
| 51 | #define CE_DESC_FLAGS_META_DATA_MASK 0xFFFC | 43 | #define CE_DESC_FLAGS_META_DATA_MASK 0xFFFC |
| @@ -57,8 +49,7 @@ struct ce_desc { | |||
| 57 | __le16 flags; /* %CE_DESC_FLAGS_ */ | 49 | __le16 flags; /* %CE_DESC_FLAGS_ */ |
| 58 | }; | 50 | }; |
| 59 | 51 | ||
| 60 | /* Copy Engine Ring internal state */ | 52 | struct ath10k_ce_ring { |
| 61 | struct ce_ring_state { | ||
| 62 | /* Number of entries in this ring; must be power of 2 */ | 53 | /* Number of entries in this ring; must be power of 2 */ |
| 63 | unsigned int nentries; | 54 | unsigned int nentries; |
| 64 | unsigned int nentries_mask; | 55 | unsigned int nentries_mask; |
| @@ -116,49 +107,20 @@ struct ce_ring_state { | |||
| 116 | void **per_transfer_context; | 107 | void **per_transfer_context; |
| 117 | }; | 108 | }; |
| 118 | 109 | ||
| 119 | /* Copy Engine internal state */ | 110 | struct ath10k_ce_pipe { |
| 120 | struct ce_state { | ||
| 121 | struct ath10k *ar; | 111 | struct ath10k *ar; |
| 122 | unsigned int id; | 112 | unsigned int id; |
| 123 | 113 | ||
| 124 | unsigned int attr_flags; | 114 | unsigned int attr_flags; |
| 125 | 115 | ||
| 126 | u32 ctrl_addr; | 116 | u32 ctrl_addr; |
| 127 | enum ce_op_state state; | ||
| 128 | |||
| 129 | void (*send_cb) (struct ce_state *ce_state, | ||
| 130 | void *per_transfer_send_context, | ||
| 131 | u32 buffer, | ||
| 132 | unsigned int nbytes, | ||
| 133 | unsigned int transfer_id); | ||
| 134 | void (*recv_cb) (struct ce_state *ce_state, | ||
| 135 | void *per_transfer_recv_context, | ||
| 136 | u32 buffer, | ||
| 137 | unsigned int nbytes, | ||
| 138 | unsigned int transfer_id, | ||
| 139 | unsigned int flags); | ||
| 140 | |||
| 141 | unsigned int src_sz_max; | ||
| 142 | struct ce_ring_state *src_ring; | ||
| 143 | struct ce_ring_state *dest_ring; | ||
| 144 | }; | ||
| 145 | 117 | ||
| 146 | struct ce_sendlist_item { | 118 | void (*send_cb)(struct ath10k_ce_pipe *); |
| 147 | /* e.g. buffer or desc list */ | 119 | void (*recv_cb)(struct ath10k_ce_pipe *); |
| 148 | dma_addr_t data; | ||
| 149 | union { | ||
| 150 | /* simple buffer */ | ||
| 151 | unsigned int nbytes; | ||
| 152 | /* Rx descriptor list */ | ||
| 153 | unsigned int ndesc; | ||
| 154 | } u; | ||
| 155 | /* externally-specified flags; OR-ed with internal flags */ | ||
| 156 | u32 flags; | ||
| 157 | }; | ||
| 158 | 120 | ||
| 159 | struct ce_sendlist { | 121 | unsigned int src_sz_max; |
| 160 | unsigned int num_items; | 122 | struct ath10k_ce_ring *src_ring; |
| 161 | struct ce_sendlist_item item[CE_SENDLIST_ITEMS_MAX]; | 123 | struct ath10k_ce_ring *dest_ring; |
| 162 | }; | 124 | }; |
| 163 | 125 | ||
| 164 | /* Copy Engine settable attributes */ | 126 | /* Copy Engine settable attributes */ |
| @@ -182,7 +144,7 @@ struct ce_attr; | |||
| 182 | * | 144 | * |
| 183 | * Implementation note: pushes 1 buffer to Source ring | 145 | * Implementation note: pushes 1 buffer to Source ring |
| 184 | */ | 146 | */ |
| 185 | int ath10k_ce_send(struct ce_state *ce_state, | 147 | int ath10k_ce_send(struct ath10k_ce_pipe *ce_state, |
| 186 | void *per_transfer_send_context, | 148 | void *per_transfer_send_context, |
| 187 | u32 buffer, | 149 | u32 buffer, |
| 188 | unsigned int nbytes, | 150 | unsigned int nbytes, |
| @@ -190,36 +152,11 @@ int ath10k_ce_send(struct ce_state *ce_state, | |||
| 190 | unsigned int transfer_id, | 152 | unsigned int transfer_id, |
| 191 | unsigned int flags); | 153 | unsigned int flags); |
| 192 | 154 | ||
| 193 | void ath10k_ce_send_cb_register(struct ce_state *ce_state, | 155 | void ath10k_ce_send_cb_register(struct ath10k_ce_pipe *ce_state, |
| 194 | void (*send_cb) (struct ce_state *ce_state, | 156 | void (*send_cb)(struct ath10k_ce_pipe *), |
| 195 | void *transfer_context, | ||
| 196 | u32 buffer, | ||
| 197 | unsigned int nbytes, | ||
| 198 | unsigned int transfer_id), | ||
| 199 | int disable_interrupts); | 157 | int disable_interrupts); |
| 200 | 158 | ||
| 201 | /* Append a simple buffer (address/length) to a sendlist. */ | 159 | int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe); |
| 202 | void ath10k_ce_sendlist_buf_add(struct ce_sendlist *sendlist, | ||
| 203 | u32 buffer, | ||
| 204 | unsigned int nbytes, | ||
| 205 | /* OR-ed with internal flags */ | ||
| 206 | u32 flags); | ||
| 207 | |||
| 208 | /* | ||
| 209 | * Queue a "sendlist" of buffers to be sent using gather to a single | ||
| 210 | * anonymous destination buffer | ||
| 211 | * ce - which copy engine to use | ||
| 212 | * sendlist - list of simple buffers to send using gather | ||
| 213 | * transfer_id - arbitrary ID; reflected to destination | ||
| 214 | * Returns 0 on success; otherwise an error status. | ||
| 215 | * | ||
| 216 | * Implemenation note: Pushes multiple buffers with Gather to Source ring. | ||
| 217 | */ | ||
| 218 | int ath10k_ce_sendlist_send(struct ce_state *ce_state, | ||
| 219 | void *per_transfer_send_context, | ||
| 220 | struct ce_sendlist *sendlist, | ||
| 221 | /* 14 bits */ | ||
| 222 | unsigned int transfer_id); | ||
| 223 | 160 | ||
| 224 | /*==================Recv=======================*/ | 161 | /*==================Recv=======================*/ |
| 225 | 162 | ||
| @@ -233,17 +170,12 @@ int ath10k_ce_sendlist_send(struct ce_state *ce_state, | |||
| 233 | * | 170 | * |
| 234 | * Implemenation note: Pushes a buffer to Dest ring. | 171 | * Implemenation note: Pushes a buffer to Dest ring. |
| 235 | */ | 172 | */ |
| 236 | int ath10k_ce_recv_buf_enqueue(struct ce_state *ce_state, | 173 | int ath10k_ce_recv_buf_enqueue(struct ath10k_ce_pipe *ce_state, |
| 237 | void *per_transfer_recv_context, | 174 | void *per_transfer_recv_context, |
| 238 | u32 buffer); | 175 | u32 buffer); |
| 239 | 176 | ||
| 240 | void ath10k_ce_recv_cb_register(struct ce_state *ce_state, | 177 | void ath10k_ce_recv_cb_register(struct ath10k_ce_pipe *ce_state, |
| 241 | void (*recv_cb) (struct ce_state *ce_state, | 178 | void (*recv_cb)(struct ath10k_ce_pipe *)); |
| 242 | void *transfer_context, | ||
| 243 | u32 buffer, | ||
| 244 | unsigned int nbytes, | ||
| 245 | unsigned int transfer_id, | ||
| 246 | unsigned int flags)); | ||
| 247 | 179 | ||
| 248 | /* recv flags */ | 180 | /* recv flags */ |
| 249 | /* Data is byte-swapped */ | 181 | /* Data is byte-swapped */ |
| @@ -253,7 +185,7 @@ void ath10k_ce_recv_cb_register(struct ce_state *ce_state, | |||
| 253 | * Supply data for the next completed unprocessed receive descriptor. | 185 | * Supply data for the next completed unprocessed receive descriptor. |
| 254 | * Pops buffer from Dest ring. | 186 | * Pops buffer from Dest ring. |
| 255 | */ | 187 | */ |
| 256 | int ath10k_ce_completed_recv_next(struct ce_state *ce_state, | 188 | int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state, |
| 257 | void **per_transfer_contextp, | 189 | void **per_transfer_contextp, |
| 258 | u32 *bufferp, | 190 | u32 *bufferp, |
| 259 | unsigned int *nbytesp, | 191 | unsigned int *nbytesp, |
| @@ -263,7 +195,7 @@ int ath10k_ce_completed_recv_next(struct ce_state *ce_state, | |||
| 263 | * Supply data for the next completed unprocessed send descriptor. | 195 | * Supply data for the next completed unprocessed send descriptor. |
| 264 | * Pops 1 completed send buffer from Source ring. | 196 | * Pops 1 completed send buffer from Source ring. |
| 265 | */ | 197 | */ |
| 266 | int ath10k_ce_completed_send_next(struct ce_state *ce_state, | 198 | int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state, |
| 267 | void **per_transfer_contextp, | 199 | void **per_transfer_contextp, |
| 268 | u32 *bufferp, | 200 | u32 *bufferp, |
| 269 | unsigned int *nbytesp, | 201 | unsigned int *nbytesp, |
| @@ -272,7 +204,7 @@ int ath10k_ce_completed_send_next(struct ce_state *ce_state, | |||
| 272 | /*==================CE Engine Initialization=======================*/ | 204 | /*==================CE Engine Initialization=======================*/ |
| 273 | 205 | ||
| 274 | /* Initialize an instance of a CE */ | 206 | /* Initialize an instance of a CE */ |
| 275 | struct ce_state *ath10k_ce_init(struct ath10k *ar, | 207 | struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar, |
| 276 | unsigned int ce_id, | 208 | unsigned int ce_id, |
| 277 | const struct ce_attr *attr); | 209 | const struct ce_attr *attr); |
| 278 | 210 | ||
| @@ -282,7 +214,7 @@ struct ce_state *ath10k_ce_init(struct ath10k *ar, | |||
| 282 | * receive buffers. Target DMA must be stopped before using | 214 | * receive buffers. Target DMA must be stopped before using |
| 283 | * this API. | 215 | * this API. |
| 284 | */ | 216 | */ |
| 285 | int ath10k_ce_revoke_recv_next(struct ce_state *ce_state, | 217 | int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, |
| 286 | void **per_transfer_contextp, | 218 | void **per_transfer_contextp, |
| 287 | u32 *bufferp); | 219 | u32 *bufferp); |
| 288 | 220 | ||
| @@ -291,13 +223,13 @@ int ath10k_ce_revoke_recv_next(struct ce_state *ce_state, | |||
| 291 | * pending sends. Target DMA must be stopped before using | 223 | * pending sends. Target DMA must be stopped before using |
| 292 | * this API. | 224 | * this API. |
| 293 | */ | 225 | */ |
| 294 | int ath10k_ce_cancel_send_next(struct ce_state *ce_state, | 226 | int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state, |
| 295 | void **per_transfer_contextp, | 227 | void **per_transfer_contextp, |
| 296 | u32 *bufferp, | 228 | u32 *bufferp, |
| 297 | unsigned int *nbytesp, | 229 | unsigned int *nbytesp, |
| 298 | unsigned int *transfer_idp); | 230 | unsigned int *transfer_idp); |
| 299 | 231 | ||
| 300 | void ath10k_ce_deinit(struct ce_state *ce_state); | 232 | void ath10k_ce_deinit(struct ath10k_ce_pipe *ce_state); |
| 301 | 233 | ||
| 302 | /*==================CE Interrupt Handlers====================*/ | 234 | /*==================CE Interrupt Handlers====================*/ |
| 303 | void ath10k_ce_per_engine_service_any(struct ath10k *ar); | 235 | void ath10k_ce_per_engine_service_any(struct ath10k *ar); |
| @@ -322,9 +254,6 @@ struct ce_attr { | |||
| 322 | /* CE_ATTR_* values */ | 254 | /* CE_ATTR_* values */ |
| 323 | unsigned int flags; | 255 | unsigned int flags; |
| 324 | 256 | ||
| 325 | /* currently not in use */ | ||
| 326 | unsigned int priority; | ||
| 327 | |||
| 328 | /* #entries in source ring - Must be a power of 2 */ | 257 | /* #entries in source ring - Must be a power of 2 */ |
| 329 | unsigned int src_nentries; | 258 | unsigned int src_nentries; |
| 330 | 259 | ||
| @@ -336,21 +265,8 @@ struct ce_attr { | |||
| 336 | 265 | ||
| 337 | /* #entries in destination ring - Must be a power of 2 */ | 266 | /* #entries in destination ring - Must be a power of 2 */ |
| 338 | unsigned int dest_nentries; | 267 | unsigned int dest_nentries; |
| 339 | |||
| 340 | /* Future use */ | ||
| 341 | void *reserved; | ||
| 342 | }; | 268 | }; |
| 343 | 269 | ||
| 344 | /* | ||
| 345 | * When using sendlist_send to transfer multiple buffer fragments, the | ||
| 346 | * transfer context of each fragment, except last one, will be filled | ||
| 347 | * with CE_SENDLIST_ITEM_CTXT. ce_completed_send will return success for | ||
| 348 | * each fragment done with send and the transfer context would be | ||
| 349 | * CE_SENDLIST_ITEM_CTXT. Upper layer could use this to identify the | ||
| 350 | * status of a send completion. | ||
| 351 | */ | ||
| 352 | #define CE_SENDLIST_ITEM_CTXT ((void *)0xcecebeef) | ||
| 353 | |||
| 354 | #define SR_BA_ADDRESS 0x0000 | 270 | #define SR_BA_ADDRESS 0x0000 |
| 355 | #define SR_SIZE_ADDRESS 0x0004 | 271 | #define SR_SIZE_ADDRESS 0x0004 |
| 356 | #define DR_BA_ADDRESS 0x0008 | 272 | #define DR_BA_ADDRESS 0x0008 |
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 7226c23b9569..1129994fb105 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c | |||
| @@ -39,17 +39,6 @@ MODULE_PARM_DESC(p2p, "Enable ath10k P2P support"); | |||
| 39 | 39 | ||
| 40 | static const struct ath10k_hw_params ath10k_hw_params_list[] = { | 40 | static const struct ath10k_hw_params ath10k_hw_params_list[] = { |
| 41 | { | 41 | { |
| 42 | .id = QCA988X_HW_1_0_VERSION, | ||
| 43 | .name = "qca988x hw1.0", | ||
| 44 | .patch_load_addr = QCA988X_HW_1_0_PATCH_LOAD_ADDR, | ||
| 45 | .fw = { | ||
| 46 | .dir = QCA988X_HW_1_0_FW_DIR, | ||
| 47 | .fw = QCA988X_HW_1_0_FW_FILE, | ||
| 48 | .otp = QCA988X_HW_1_0_OTP_FILE, | ||
| 49 | .board = QCA988X_HW_1_0_BOARD_DATA_FILE, | ||
| 50 | }, | ||
| 51 | }, | ||
| 52 | { | ||
| 53 | .id = QCA988X_HW_2_0_VERSION, | 42 | .id = QCA988X_HW_2_0_VERSION, |
| 54 | .name = "qca988x hw2.0", | 43 | .name = "qca988x hw2.0", |
| 55 | .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR, | 44 | .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR, |
| @@ -64,33 +53,12 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { | |||
| 64 | 53 | ||
| 65 | static void ath10k_send_suspend_complete(struct ath10k *ar) | 54 | static void ath10k_send_suspend_complete(struct ath10k *ar) |
| 66 | { | 55 | { |
| 67 | ath10k_dbg(ATH10K_DBG_CORE, "%s\n", __func__); | 56 | ath10k_dbg(ATH10K_DBG_BOOT, "boot suspend complete\n"); |
| 68 | 57 | ||
| 69 | ar->is_target_paused = true; | 58 | ar->is_target_paused = true; |
| 70 | wake_up(&ar->event_queue); | 59 | wake_up(&ar->event_queue); |
| 71 | } | 60 | } |
| 72 | 61 | ||
| 73 | static int ath10k_check_fw_version(struct ath10k *ar) | ||
| 74 | { | ||
| 75 | char version[32]; | ||
| 76 | |||
| 77 | if (ar->fw_version_major >= SUPPORTED_FW_MAJOR && | ||
| 78 | ar->fw_version_minor >= SUPPORTED_FW_MINOR && | ||
| 79 | ar->fw_version_release >= SUPPORTED_FW_RELEASE && | ||
| 80 | ar->fw_version_build >= SUPPORTED_FW_BUILD) | ||
| 81 | return 0; | ||
| 82 | |||
| 83 | snprintf(version, sizeof(version), "%u.%u.%u.%u", | ||
| 84 | SUPPORTED_FW_MAJOR, SUPPORTED_FW_MINOR, | ||
| 85 | SUPPORTED_FW_RELEASE, SUPPORTED_FW_BUILD); | ||
| 86 | |||
| 87 | ath10k_warn("WARNING: Firmware version %s is not officially supported.\n", | ||
| 88 | ar->hw->wiphy->fw_version); | ||
| 89 | ath10k_warn("Please upgrade to version %s (or newer)\n", version); | ||
| 90 | |||
| 91 | return 0; | ||
| 92 | } | ||
| 93 | |||
| 94 | static int ath10k_init_connect_htc(struct ath10k *ar) | 62 | static int ath10k_init_connect_htc(struct ath10k *ar) |
| 95 | { | 63 | { |
| 96 | int status; | 64 | int status; |
| @@ -112,7 +80,7 @@ static int ath10k_init_connect_htc(struct ath10k *ar) | |||
| 112 | goto timeout; | 80 | goto timeout; |
| 113 | } | 81 | } |
| 114 | 82 | ||
| 115 | ath10k_dbg(ATH10K_DBG_CORE, "core wmi ready\n"); | 83 | ath10k_dbg(ATH10K_DBG_BOOT, "boot wmi ready\n"); |
| 116 | return 0; | 84 | return 0; |
| 117 | 85 | ||
| 118 | timeout: | 86 | timeout: |
| @@ -200,8 +168,7 @@ static const struct firmware *ath10k_fetch_fw_file(struct ath10k *ar, | |||
| 200 | return fw; | 168 | return fw; |
| 201 | } | 169 | } |
| 202 | 170 | ||
| 203 | static int ath10k_push_board_ext_data(struct ath10k *ar, | 171 | static int ath10k_push_board_ext_data(struct ath10k *ar) |
| 204 | const struct firmware *fw) | ||
| 205 | { | 172 | { |
| 206 | u32 board_data_size = QCA988X_BOARD_DATA_SZ; | 173 | u32 board_data_size = QCA988X_BOARD_DATA_SZ; |
| 207 | u32 board_ext_data_size = QCA988X_BOARD_EXT_DATA_SZ; | 174 | u32 board_ext_data_size = QCA988X_BOARD_EXT_DATA_SZ; |
| @@ -214,21 +181,21 @@ static int ath10k_push_board_ext_data(struct ath10k *ar, | |||
| 214 | return ret; | 181 | return ret; |
| 215 | } | 182 | } |
| 216 | 183 | ||
| 217 | ath10k_dbg(ATH10K_DBG_CORE, | 184 | ath10k_dbg(ATH10K_DBG_BOOT, |
| 218 | "ath10k: Board extended Data download addr: 0x%x\n", | 185 | "boot push board extended data addr 0x%x\n", |
| 219 | board_ext_data_addr); | 186 | board_ext_data_addr); |
| 220 | 187 | ||
| 221 | if (board_ext_data_addr == 0) | 188 | if (board_ext_data_addr == 0) |
| 222 | return 0; | 189 | return 0; |
| 223 | 190 | ||
| 224 | if (fw->size != (board_data_size + board_ext_data_size)) { | 191 | if (ar->board_len != (board_data_size + board_ext_data_size)) { |
| 225 | ath10k_err("invalid board (ext) data sizes %zu != %d+%d\n", | 192 | ath10k_err("invalid board (ext) data sizes %zu != %d+%d\n", |
| 226 | fw->size, board_data_size, board_ext_data_size); | 193 | ar->board_len, board_data_size, board_ext_data_size); |
| 227 | return -EINVAL; | 194 | return -EINVAL; |
| 228 | } | 195 | } |
| 229 | 196 | ||
| 230 | ret = ath10k_bmi_write_memory(ar, board_ext_data_addr, | 197 | ret = ath10k_bmi_write_memory(ar, board_ext_data_addr, |
| 231 | fw->data + board_data_size, | 198 | ar->board_data + board_data_size, |
| 232 | board_ext_data_size); | 199 | board_ext_data_size); |
| 233 | if (ret) { | 200 | if (ret) { |
| 234 | ath10k_err("could not write board ext data (%d)\n", ret); | 201 | ath10k_err("could not write board ext data (%d)\n", ret); |
| @@ -247,12 +214,11 @@ static int ath10k_push_board_ext_data(struct ath10k *ar, | |||
| 247 | 214 | ||
| 248 | static int ath10k_download_board_data(struct ath10k *ar) | 215 | static int ath10k_download_board_data(struct ath10k *ar) |
| 249 | { | 216 | { |
| 250 | const struct firmware *fw = ar->board_data; | ||
| 251 | u32 board_data_size = QCA988X_BOARD_DATA_SZ; | 217 | u32 board_data_size = QCA988X_BOARD_DATA_SZ; |
| 252 | u32 address; | 218 | u32 address; |
| 253 | int ret; | 219 | int ret; |
| 254 | 220 | ||
| 255 | ret = ath10k_push_board_ext_data(ar, fw); | 221 | ret = ath10k_push_board_ext_data(ar); |
| 256 | if (ret) { | 222 | if (ret) { |
| 257 | ath10k_err("could not push board ext data (%d)\n", ret); | 223 | ath10k_err("could not push board ext data (%d)\n", ret); |
| 258 | goto exit; | 224 | goto exit; |
| @@ -264,8 +230,9 @@ static int ath10k_download_board_data(struct ath10k *ar) | |||
| 264 | goto exit; | 230 | goto exit; |
| 265 | } | 231 | } |
| 266 | 232 | ||
| 267 | ret = ath10k_bmi_write_memory(ar, address, fw->data, | 233 | ret = ath10k_bmi_write_memory(ar, address, ar->board_data, |
| 268 | min_t(u32, board_data_size, fw->size)); | 234 | min_t(u32, board_data_size, |
| 235 | ar->board_len)); | ||
| 269 | if (ret) { | 236 | if (ret) { |
| 270 | ath10k_err("could not write board data (%d)\n", ret); | 237 | ath10k_err("could not write board data (%d)\n", ret); |
| 271 | goto exit; | 238 | goto exit; |
| @@ -283,17 +250,16 @@ exit: | |||
| 283 | 250 | ||
| 284 | static int ath10k_download_and_run_otp(struct ath10k *ar) | 251 | static int ath10k_download_and_run_otp(struct ath10k *ar) |
| 285 | { | 252 | { |
| 286 | const struct firmware *fw = ar->otp; | ||
| 287 | u32 address = ar->hw_params.patch_load_addr; | 253 | u32 address = ar->hw_params.patch_load_addr; |
| 288 | u32 exec_param; | 254 | u32 exec_param; |
| 289 | int ret; | 255 | int ret; |
| 290 | 256 | ||
| 291 | /* OTP is optional */ | 257 | /* OTP is optional */ |
| 292 | 258 | ||
| 293 | if (!ar->otp) | 259 | if (!ar->otp_data || !ar->otp_len) |
| 294 | return 0; | 260 | return 0; |
| 295 | 261 | ||
| 296 | ret = ath10k_bmi_fast_download(ar, address, fw->data, fw->size); | 262 | ret = ath10k_bmi_fast_download(ar, address, ar->otp_data, ar->otp_len); |
| 297 | if (ret) { | 263 | if (ret) { |
| 298 | ath10k_err("could not write otp (%d)\n", ret); | 264 | ath10k_err("could not write otp (%d)\n", ret); |
| 299 | goto exit; | 265 | goto exit; |
| @@ -312,13 +278,13 @@ exit: | |||
| 312 | 278 | ||
| 313 | static int ath10k_download_fw(struct ath10k *ar) | 279 | static int ath10k_download_fw(struct ath10k *ar) |
| 314 | { | 280 | { |
| 315 | const struct firmware *fw = ar->firmware; | ||
| 316 | u32 address; | 281 | u32 address; |
| 317 | int ret; | 282 | int ret; |
| 318 | 283 | ||
| 319 | address = ar->hw_params.patch_load_addr; | 284 | address = ar->hw_params.patch_load_addr; |
| 320 | 285 | ||
| 321 | ret = ath10k_bmi_fast_download(ar, address, fw->data, fw->size); | 286 | ret = ath10k_bmi_fast_download(ar, address, ar->firmware_data, |
| 287 | ar->firmware_len); | ||
| 322 | if (ret) { | 288 | if (ret) { |
| 323 | ath10k_err("could not write fw (%d)\n", ret); | 289 | ath10k_err("could not write fw (%d)\n", ret); |
| 324 | goto exit; | 290 | goto exit; |
| @@ -330,8 +296,8 @@ exit: | |||
| 330 | 296 | ||
| 331 | static void ath10k_core_free_firmware_files(struct ath10k *ar) | 297 | static void ath10k_core_free_firmware_files(struct ath10k *ar) |
| 332 | { | 298 | { |
| 333 | if (ar->board_data && !IS_ERR(ar->board_data)) | 299 | if (ar->board && !IS_ERR(ar->board)) |
| 334 | release_firmware(ar->board_data); | 300 | release_firmware(ar->board); |
| 335 | 301 | ||
| 336 | if (ar->otp && !IS_ERR(ar->otp)) | 302 | if (ar->otp && !IS_ERR(ar->otp)) |
| 337 | release_firmware(ar->otp); | 303 | release_firmware(ar->otp); |
| @@ -339,12 +305,20 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar) | |||
| 339 | if (ar->firmware && !IS_ERR(ar->firmware)) | 305 | if (ar->firmware && !IS_ERR(ar->firmware)) |
| 340 | release_firmware(ar->firmware); | 306 | release_firmware(ar->firmware); |
| 341 | 307 | ||
| 308 | ar->board = NULL; | ||
| 342 | ar->board_data = NULL; | 309 | ar->board_data = NULL; |
| 310 | ar->board_len = 0; | ||
| 311 | |||
| 343 | ar->otp = NULL; | 312 | ar->otp = NULL; |
| 313 | ar->otp_data = NULL; | ||
| 314 | ar->otp_len = 0; | ||
| 315 | |||
| 344 | ar->firmware = NULL; | 316 | ar->firmware = NULL; |
| 317 | ar->firmware_data = NULL; | ||
| 318 | ar->firmware_len = 0; | ||
| 345 | } | 319 | } |
| 346 | 320 | ||
| 347 | static int ath10k_core_fetch_firmware_files(struct ath10k *ar) | 321 | static int ath10k_core_fetch_firmware_api_1(struct ath10k *ar) |
| 348 | { | 322 | { |
| 349 | int ret = 0; | 323 | int ret = 0; |
| 350 | 324 | ||
| @@ -358,15 +332,18 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar) | |||
| 358 | return -EINVAL; | 332 | return -EINVAL; |
| 359 | } | 333 | } |
| 360 | 334 | ||
| 361 | ar->board_data = ath10k_fetch_fw_file(ar, | 335 | ar->board = ath10k_fetch_fw_file(ar, |
| 362 | ar->hw_params.fw.dir, | 336 | ar->hw_params.fw.dir, |
| 363 | ar->hw_params.fw.board); | 337 | ar->hw_params.fw.board); |
| 364 | if (IS_ERR(ar->board_data)) { | 338 | if (IS_ERR(ar->board)) { |
| 365 | ret = PTR_ERR(ar->board_data); | 339 | ret = PTR_ERR(ar->board); |
| 366 | ath10k_err("could not fetch board data (%d)\n", ret); | 340 | ath10k_err("could not fetch board data (%d)\n", ret); |
| 367 | goto err; | 341 | goto err; |
| 368 | } | 342 | } |
| 369 | 343 | ||
| 344 | ar->board_data = ar->board->data; | ||
| 345 | ar->board_len = ar->board->size; | ||
| 346 | |||
| 370 | ar->firmware = ath10k_fetch_fw_file(ar, | 347 | ar->firmware = ath10k_fetch_fw_file(ar, |
| 371 | ar->hw_params.fw.dir, | 348 | ar->hw_params.fw.dir, |
| 372 | ar->hw_params.fw.fw); | 349 | ar->hw_params.fw.fw); |
| @@ -376,6 +353,9 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar) | |||
| 376 | goto err; | 353 | goto err; |
| 377 | } | 354 | } |
| 378 | 355 | ||
| 356 | ar->firmware_data = ar->firmware->data; | ||
| 357 | ar->firmware_len = ar->firmware->size; | ||
| 358 | |||
| 379 | /* OTP may be undefined. If so, don't fetch it at all */ | 359 | /* OTP may be undefined. If so, don't fetch it at all */ |
| 380 | if (ar->hw_params.fw.otp == NULL) | 360 | if (ar->hw_params.fw.otp == NULL) |
| 381 | return 0; | 361 | return 0; |
| @@ -389,6 +369,172 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar) | |||
| 389 | goto err; | 369 | goto err; |
| 390 | } | 370 | } |
| 391 | 371 | ||
| 372 | ar->otp_data = ar->otp->data; | ||
| 373 | ar->otp_len = ar->otp->size; | ||
| 374 | |||
| 375 | return 0; | ||
| 376 | |||
| 377 | err: | ||
| 378 | ath10k_core_free_firmware_files(ar); | ||
| 379 | return ret; | ||
| 380 | } | ||
| 381 | |||
| 382 | static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name) | ||
| 383 | { | ||
| 384 | size_t magic_len, len, ie_len; | ||
| 385 | int ie_id, i, index, bit, ret; | ||
| 386 | struct ath10k_fw_ie *hdr; | ||
| 387 | const u8 *data; | ||
| 388 | __le32 *timestamp; | ||
| 389 | |||
| 390 | /* first fetch the firmware file (firmware-*.bin) */ | ||
| 391 | ar->firmware = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, name); | ||
| 392 | if (IS_ERR(ar->firmware)) { | ||
| 393 | ath10k_err("Could not fetch firmware file '%s': %ld\n", | ||
| 394 | name, PTR_ERR(ar->firmware)); | ||
| 395 | return PTR_ERR(ar->firmware); | ||
| 396 | } | ||
| 397 | |||
| 398 | data = ar->firmware->data; | ||
| 399 | len = ar->firmware->size; | ||
| 400 | |||
| 401 | /* magic also includes the null byte, check that as well */ | ||
| 402 | magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1; | ||
| 403 | |||
| 404 | if (len < magic_len) { | ||
| 405 | ath10k_err("firmware image too small to contain magic: %zu\n", | ||
| 406 | len); | ||
| 407 | ret = -EINVAL; | ||
| 408 | goto err; | ||
| 409 | } | ||
| 410 | |||
| 411 | if (memcmp(data, ATH10K_FIRMWARE_MAGIC, magic_len) != 0) { | ||
| 412 | ath10k_err("Invalid firmware magic\n"); | ||
| 413 | ret = -EINVAL; | ||
| 414 | goto err; | ||
| 415 | } | ||
| 416 | |||
| 417 | /* jump over the padding */ | ||
| 418 | magic_len = ALIGN(magic_len, 4); | ||
| 419 | |||
| 420 | len -= magic_len; | ||
| 421 | data += magic_len; | ||
| 422 | |||
| 423 | /* loop elements */ | ||
| 424 | while (len > sizeof(struct ath10k_fw_ie)) { | ||
| 425 | hdr = (struct ath10k_fw_ie *)data; | ||
| 426 | |||
| 427 | ie_id = le32_to_cpu(hdr->id); | ||
| 428 | ie_len = le32_to_cpu(hdr->len); | ||
| 429 | |||
| 430 | len -= sizeof(*hdr); | ||
| 431 | data += sizeof(*hdr); | ||
| 432 | |||
| 433 | if (len < ie_len) { | ||
| 434 | ath10k_err("Invalid length for FW IE %d (%zu < %zu)\n", | ||
| 435 | ie_id, len, ie_len); | ||
| 436 | ret = -EINVAL; | ||
| 437 | goto err; | ||
| 438 | } | ||
| 439 | |||
| 440 | switch (ie_id) { | ||
| 441 | case ATH10K_FW_IE_FW_VERSION: | ||
| 442 | if (ie_len > sizeof(ar->hw->wiphy->fw_version) - 1) | ||
| 443 | break; | ||
| 444 | |||
| 445 | memcpy(ar->hw->wiphy->fw_version, data, ie_len); | ||
| 446 | ar->hw->wiphy->fw_version[ie_len] = '\0'; | ||
| 447 | |||
| 448 | ath10k_dbg(ATH10K_DBG_BOOT, | ||
| 449 | "found fw version %s\n", | ||
| 450 | ar->hw->wiphy->fw_version); | ||
| 451 | break; | ||
| 452 | case ATH10K_FW_IE_TIMESTAMP: | ||
| 453 | if (ie_len != sizeof(u32)) | ||
| 454 | break; | ||
| 455 | |||
| 456 | timestamp = (__le32 *)data; | ||
| 457 | |||
| 458 | ath10k_dbg(ATH10K_DBG_BOOT, "found fw timestamp %d\n", | ||
| 459 | le32_to_cpup(timestamp)); | ||
| 460 | break; | ||
| 461 | case ATH10K_FW_IE_FEATURES: | ||
| 462 | ath10k_dbg(ATH10K_DBG_BOOT, | ||
| 463 | "found firmware features ie (%zd B)\n", | ||
| 464 | ie_len); | ||
| 465 | |||
| 466 | for (i = 0; i < ATH10K_FW_FEATURE_COUNT; i++) { | ||
| 467 | index = i / 8; | ||
| 468 | bit = i % 8; | ||
| 469 | |||
| 470 | if (index == ie_len) | ||
| 471 | break; | ||
| 472 | |||
| 473 | if (data[index] & (1 << bit)) | ||
| 474 | __set_bit(i, ar->fw_features); | ||
| 475 | } | ||
| 476 | |||
| 477 | ath10k_dbg_dump(ATH10K_DBG_BOOT, "features", "", | ||
| 478 | ar->fw_features, | ||
| 479 | sizeof(ar->fw_features)); | ||
| 480 | break; | ||
| 481 | case ATH10K_FW_IE_FW_IMAGE: | ||
| 482 | ath10k_dbg(ATH10K_DBG_BOOT, | ||
| 483 | "found fw image ie (%zd B)\n", | ||
| 484 | ie_len); | ||
| 485 | |||
| 486 | ar->firmware_data = data; | ||
| 487 | ar->firmware_len = ie_len; | ||
| 488 | |||
| 489 | break; | ||
| 490 | case ATH10K_FW_IE_OTP_IMAGE: | ||
| 491 | ath10k_dbg(ATH10K_DBG_BOOT, | ||
| 492 | "found otp image ie (%zd B)\n", | ||
| 493 | ie_len); | ||
| 494 | |||
| 495 | ar->otp_data = data; | ||
| 496 | ar->otp_len = ie_len; | ||
| 497 | |||
| 498 | break; | ||
| 499 | default: | ||
| 500 | ath10k_warn("Unknown FW IE: %u\n", | ||
| 501 | le32_to_cpu(hdr->id)); | ||
| 502 | break; | ||
| 503 | } | ||
| 504 | |||
| 505 | /* jump over the padding */ | ||
| 506 | ie_len = ALIGN(ie_len, 4); | ||
| 507 | |||
| 508 | len -= ie_len; | ||
| 509 | data += ie_len; | ||
| 510 | } | ||
| 511 | |||
| 512 | if (!ar->firmware_data || !ar->firmware_len) { | ||
| 513 | ath10k_warn("No ATH10K_FW_IE_FW_IMAGE found from %s, skipping\n", | ||
| 514 | name); | ||
| 515 | ret = -ENOMEDIUM; | ||
| 516 | goto err; | ||
| 517 | } | ||
| 518 | |||
| 519 | /* now fetch the board file */ | ||
| 520 | if (ar->hw_params.fw.board == NULL) { | ||
| 521 | ath10k_err("board data file not defined"); | ||
| 522 | ret = -EINVAL; | ||
| 523 | goto err; | ||
| 524 | } | ||
| 525 | |||
| 526 | ar->board = ath10k_fetch_fw_file(ar, | ||
| 527 | ar->hw_params.fw.dir, | ||
| 528 | ar->hw_params.fw.board); | ||
| 529 | if (IS_ERR(ar->board)) { | ||
| 530 | ret = PTR_ERR(ar->board); | ||
| 531 | ath10k_err("could not fetch board data (%d)\n", ret); | ||
| 532 | goto err; | ||
| 533 | } | ||
| 534 | |||
| 535 | ar->board_data = ar->board->data; | ||
| 536 | ar->board_len = ar->board->size; | ||
| 537 | |||
| 392 | return 0; | 538 | return 0; |
| 393 | 539 | ||
| 394 | err: | 540 | err: |
| @@ -396,6 +542,28 @@ err: | |||
| 396 | return ret; | 542 | return ret; |
| 397 | } | 543 | } |
| 398 | 544 | ||
| 545 | static int ath10k_core_fetch_firmware_files(struct ath10k *ar) | ||
| 546 | { | ||
| 547 | int ret; | ||
| 548 | |||
| 549 | ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API2_FILE); | ||
| 550 | if (ret == 0) { | ||
| 551 | ar->fw_api = 2; | ||
| 552 | goto out; | ||
| 553 | } | ||
| 554 | |||
| 555 | ret = ath10k_core_fetch_firmware_api_1(ar); | ||
| 556 | if (ret) | ||
| 557 | return ret; | ||
| 558 | |||
| 559 | ar->fw_api = 1; | ||
| 560 | |||
| 561 | out: | ||
| 562 | ath10k_dbg(ATH10K_DBG_BOOT, "using fw api %d\n", ar->fw_api); | ||
| 563 | |||
| 564 | return 0; | ||
| 565 | } | ||
| 566 | |||
| 399 | static int ath10k_init_download_firmware(struct ath10k *ar) | 567 | static int ath10k_init_download_firmware(struct ath10k *ar) |
| 400 | { | 568 | { |
| 401 | int ret; | 569 | int ret; |
| @@ -446,6 +614,13 @@ static int ath10k_init_uart(struct ath10k *ar) | |||
| 446 | return ret; | 614 | return ret; |
| 447 | } | 615 | } |
| 448 | 616 | ||
| 617 | /* Set the UART baud rate to 19200. */ | ||
| 618 | ret = ath10k_bmi_write32(ar, hi_desired_baud_rate, 19200); | ||
| 619 | if (ret) { | ||
| 620 | ath10k_warn("could not set the baud rate (%d)\n", ret); | ||
| 621 | return ret; | ||
| 622 | } | ||
| 623 | |||
| 449 | ath10k_info("UART prints enabled\n"); | 624 | ath10k_info("UART prints enabled\n"); |
| 450 | return 0; | 625 | return 0; |
| 451 | } | 626 | } |
| @@ -545,6 +720,9 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev, | |||
| 545 | INIT_WORK(&ar->offchan_tx_work, ath10k_offchan_tx_work); | 720 | INIT_WORK(&ar->offchan_tx_work, ath10k_offchan_tx_work); |
| 546 | skb_queue_head_init(&ar->offchan_tx_queue); | 721 | skb_queue_head_init(&ar->offchan_tx_queue); |
| 547 | 722 | ||
| 723 | INIT_WORK(&ar->wmi_mgmt_tx_work, ath10k_mgmt_over_wmi_tx_work); | ||
| 724 | skb_queue_head_init(&ar->wmi_mgmt_tx_queue); | ||
| 725 | |||
| 548 | init_waitqueue_head(&ar->event_queue); | 726 | init_waitqueue_head(&ar->event_queue); |
| 549 | 727 | ||
| 550 | INIT_WORK(&ar->restart_work, ath10k_core_restart); | 728 | INIT_WORK(&ar->restart_work, ath10k_core_restart); |
| @@ -559,6 +737,8 @@ EXPORT_SYMBOL(ath10k_core_create); | |||
| 559 | 737 | ||
| 560 | void ath10k_core_destroy(struct ath10k *ar) | 738 | void ath10k_core_destroy(struct ath10k *ar) |
| 561 | { | 739 | { |
| 740 | ath10k_debug_destroy(ar); | ||
| 741 | |||
| 562 | flush_workqueue(ar->workqueue); | 742 | flush_workqueue(ar->workqueue); |
| 563 | destroy_workqueue(ar->workqueue); | 743 | destroy_workqueue(ar->workqueue); |
| 564 | 744 | ||
| @@ -570,6 +750,8 @@ int ath10k_core_start(struct ath10k *ar) | |||
| 570 | { | 750 | { |
| 571 | int status; | 751 | int status; |
| 572 | 752 | ||
| 753 | lockdep_assert_held(&ar->conf_mutex); | ||
| 754 | |||
| 573 | ath10k_bmi_start(ar); | 755 | ath10k_bmi_start(ar); |
| 574 | 756 | ||
| 575 | if (ath10k_init_configure_target(ar)) { | 757 | if (ath10k_init_configure_target(ar)) { |
| @@ -620,10 +802,6 @@ int ath10k_core_start(struct ath10k *ar) | |||
| 620 | 802 | ||
| 621 | ath10k_info("firmware %s booted\n", ar->hw->wiphy->fw_version); | 803 | ath10k_info("firmware %s booted\n", ar->hw->wiphy->fw_version); |
| 622 | 804 | ||
| 623 | status = ath10k_check_fw_version(ar); | ||
| 624 | if (status) | ||
| 625 | goto err_disconnect_htc; | ||
| 626 | |||
| 627 | status = ath10k_wmi_cmd_init(ar); | 805 | status = ath10k_wmi_cmd_init(ar); |
| 628 | if (status) { | 806 | if (status) { |
| 629 | ath10k_err("could not send WMI init command (%d)\n", status); | 807 | ath10k_err("could not send WMI init command (%d)\n", status); |
| @@ -641,7 +819,12 @@ int ath10k_core_start(struct ath10k *ar) | |||
| 641 | if (status) | 819 | if (status) |
| 642 | goto err_disconnect_htc; | 820 | goto err_disconnect_htc; |
| 643 | 821 | ||
| 822 | status = ath10k_debug_start(ar); | ||
| 823 | if (status) | ||
| 824 | goto err_disconnect_htc; | ||
| 825 | |||
| 644 | ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1; | 826 | ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1; |
| 827 | INIT_LIST_HEAD(&ar->arvifs); | ||
| 645 | 828 | ||
| 646 | return 0; | 829 | return 0; |
| 647 | 830 | ||
| @@ -658,6 +841,9 @@ EXPORT_SYMBOL(ath10k_core_start); | |||
| 658 | 841 | ||
| 659 | void ath10k_core_stop(struct ath10k *ar) | 842 | void ath10k_core_stop(struct ath10k *ar) |
| 660 | { | 843 | { |
| 844 | lockdep_assert_held(&ar->conf_mutex); | ||
| 845 | |||
| 846 | ath10k_debug_stop(ar); | ||
| 661 | ath10k_htc_stop(&ar->htc); | 847 | ath10k_htc_stop(&ar->htc); |
| 662 | ath10k_htt_detach(&ar->htt); | 848 | ath10k_htt_detach(&ar->htt); |
| 663 | ath10k_wmi_detach(ar); | 849 | ath10k_wmi_detach(ar); |
| @@ -704,23 +890,65 @@ static int ath10k_core_probe_fw(struct ath10k *ar) | |||
| 704 | return ret; | 890 | return ret; |
| 705 | } | 891 | } |
| 706 | 892 | ||
| 893 | mutex_lock(&ar->conf_mutex); | ||
| 894 | |||
| 707 | ret = ath10k_core_start(ar); | 895 | ret = ath10k_core_start(ar); |
| 708 | if (ret) { | 896 | if (ret) { |
| 709 | ath10k_err("could not init core (%d)\n", ret); | 897 | ath10k_err("could not init core (%d)\n", ret); |
| 710 | ath10k_core_free_firmware_files(ar); | 898 | ath10k_core_free_firmware_files(ar); |
| 711 | ath10k_hif_power_down(ar); | 899 | ath10k_hif_power_down(ar); |
| 900 | mutex_unlock(&ar->conf_mutex); | ||
| 712 | return ret; | 901 | return ret; |
| 713 | } | 902 | } |
| 714 | 903 | ||
| 715 | ath10k_core_stop(ar); | 904 | ath10k_core_stop(ar); |
| 905 | |||
| 906 | mutex_unlock(&ar->conf_mutex); | ||
| 907 | |||
| 716 | ath10k_hif_power_down(ar); | 908 | ath10k_hif_power_down(ar); |
| 717 | return 0; | 909 | return 0; |
| 718 | } | 910 | } |
| 719 | 911 | ||
| 720 | int ath10k_core_register(struct ath10k *ar) | 912 | static int ath10k_core_check_chip_id(struct ath10k *ar) |
| 913 | { | ||
| 914 | u32 hw_revision = MS(ar->chip_id, SOC_CHIP_ID_REV); | ||
| 915 | |||
| 916 | ath10k_dbg(ATH10K_DBG_BOOT, "boot chip_id 0x%08x hw_revision 0x%x\n", | ||
| 917 | ar->chip_id, hw_revision); | ||
| 918 | |||
| 919 | /* Check that we are not using hw1.0 (some of them have same pci id | ||
| 920 | * as hw2.0) before doing anything else as ath10k crashes horribly | ||
| 921 | * due to missing hw1.0 workarounds. */ | ||
| 922 | switch (hw_revision) { | ||
| 923 | case QCA988X_HW_1_0_CHIP_ID_REV: | ||
| 924 | ath10k_err("ERROR: qca988x hw1.0 is not supported\n"); | ||
| 925 | return -EOPNOTSUPP; | ||
| 926 | |||
| 927 | case QCA988X_HW_2_0_CHIP_ID_REV: | ||
| 928 | /* known hardware revision, continue normally */ | ||
| 929 | return 0; | ||
| 930 | |||
| 931 | default: | ||
| 932 | ath10k_warn("Warning: hardware revision unknown (0x%x), expect problems\n", | ||
| 933 | ar->chip_id); | ||
| 934 | return 0; | ||
| 935 | } | ||
| 936 | |||
| 937 | return 0; | ||
| 938 | } | ||
| 939 | |||
| 940 | int ath10k_core_register(struct ath10k *ar, u32 chip_id) | ||
| 721 | { | 941 | { |
| 722 | int status; | 942 | int status; |
| 723 | 943 | ||
| 944 | ar->chip_id = chip_id; | ||
| 945 | |||
| 946 | status = ath10k_core_check_chip_id(ar); | ||
| 947 | if (status) { | ||
| 948 | ath10k_err("Unsupported chip id 0x%08x\n", ar->chip_id); | ||
| 949 | return status; | ||
| 950 | } | ||
| 951 | |||
| 724 | status = ath10k_core_probe_fw(ar); | 952 | status = ath10k_core_probe_fw(ar); |
| 725 | if (status) { | 953 | if (status) { |
| 726 | ath10k_err("could not probe fw (%d)\n", status); | 954 | ath10k_err("could not probe fw (%d)\n", status); |
| @@ -755,6 +983,7 @@ void ath10k_core_unregister(struct ath10k *ar) | |||
| 755 | * Otherwise we will fail to submit commands to FW and mac80211 will be | 983 | * Otherwise we will fail to submit commands to FW and mac80211 will be |
| 756 | * unhappy about callback failures. */ | 984 | * unhappy about callback failures. */ |
| 757 | ath10k_mac_unregister(ar); | 985 | ath10k_mac_unregister(ar); |
| 986 | |||
| 758 | ath10k_core_free_firmware_files(ar); | 987 | ath10k_core_free_firmware_files(ar); |
| 759 | } | 988 | } |
| 760 | EXPORT_SYMBOL(ath10k_core_unregister); | 989 | EXPORT_SYMBOL(ath10k_core_unregister); |
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index e4bba563ed42..0934f7633de3 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h | |||
| @@ -43,27 +43,23 @@ | |||
| 43 | /* Antenna noise floor */ | 43 | /* Antenna noise floor */ |
| 44 | #define ATH10K_DEFAULT_NOISE_FLOOR -95 | 44 | #define ATH10K_DEFAULT_NOISE_FLOOR -95 |
| 45 | 45 | ||
| 46 | #define ATH10K_MAX_NUM_MGMT_PENDING 16 | ||
| 47 | |||
| 46 | struct ath10k; | 48 | struct ath10k; |
| 47 | 49 | ||
| 48 | struct ath10k_skb_cb { | 50 | struct ath10k_skb_cb { |
| 49 | dma_addr_t paddr; | 51 | dma_addr_t paddr; |
| 50 | bool is_mapped; | 52 | bool is_mapped; |
| 51 | bool is_aborted; | 53 | bool is_aborted; |
| 54 | u8 vdev_id; | ||
| 52 | 55 | ||
| 53 | struct { | 56 | struct { |
| 54 | u8 vdev_id; | ||
| 55 | u16 msdu_id; | ||
| 56 | u8 tid; | 57 | u8 tid; |
| 57 | bool is_offchan; | 58 | bool is_offchan; |
| 58 | bool is_conf; | ||
| 59 | bool discard; | ||
| 60 | bool no_ack; | ||
| 61 | u8 refcount; | ||
| 62 | struct sk_buff *txfrag; | ||
| 63 | struct sk_buff *msdu; | ||
| 64 | } __packed htt; | ||
| 65 | 59 | ||
| 66 | /* 4 bytes left on 64bit arch */ | 60 | u8 frag_len; |
| 61 | u8 pad_len; | ||
| 62 | } __packed htt; | ||
| 67 | } __packed; | 63 | } __packed; |
| 68 | 64 | ||
| 69 | static inline struct ath10k_skb_cb *ATH10K_SKB_CB(struct sk_buff *skb) | 65 | static inline struct ath10k_skb_cb *ATH10K_SKB_CB(struct sk_buff *skb) |
| @@ -108,15 +104,26 @@ struct ath10k_bmi { | |||
| 108 | bool done_sent; | 104 | bool done_sent; |
| 109 | }; | 105 | }; |
| 110 | 106 | ||
| 107 | #define ATH10K_MAX_MEM_REQS 16 | ||
| 108 | |||
| 109 | struct ath10k_mem_chunk { | ||
| 110 | void *vaddr; | ||
| 111 | dma_addr_t paddr; | ||
| 112 | u32 len; | ||
| 113 | u32 req_id; | ||
| 114 | }; | ||
| 115 | |||
| 111 | struct ath10k_wmi { | 116 | struct ath10k_wmi { |
| 112 | enum ath10k_htc_ep_id eid; | 117 | enum ath10k_htc_ep_id eid; |
| 113 | struct completion service_ready; | 118 | struct completion service_ready; |
| 114 | struct completion unified_ready; | 119 | struct completion unified_ready; |
| 115 | atomic_t pending_tx_count; | 120 | wait_queue_head_t tx_credits_wq; |
| 116 | wait_queue_head_t wq; | 121 | struct wmi_cmd_map *cmd; |
| 122 | struct wmi_vdev_param_map *vdev_param; | ||
| 123 | struct wmi_pdev_param_map *pdev_param; | ||
| 117 | 124 | ||
| 118 | struct sk_buff_head wmi_event_list; | 125 | u32 num_mem_chunks; |
| 119 | struct work_struct wmi_event_work; | 126 | struct ath10k_mem_chunk mem_chunks[ATH10K_MAX_MEM_REQS]; |
| 120 | }; | 127 | }; |
| 121 | 128 | ||
| 122 | struct ath10k_peer_stat { | 129 | struct ath10k_peer_stat { |
| @@ -198,17 +205,22 @@ struct ath10k_peer { | |||
| 198 | #define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ) | 205 | #define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ) |
| 199 | 206 | ||
| 200 | struct ath10k_vif { | 207 | struct ath10k_vif { |
| 208 | struct list_head list; | ||
| 209 | |||
| 201 | u32 vdev_id; | 210 | u32 vdev_id; |
| 202 | enum wmi_vdev_type vdev_type; | 211 | enum wmi_vdev_type vdev_type; |
| 203 | enum wmi_vdev_subtype vdev_subtype; | 212 | enum wmi_vdev_subtype vdev_subtype; |
| 204 | u32 beacon_interval; | 213 | u32 beacon_interval; |
| 205 | u32 dtim_period; | 214 | u32 dtim_period; |
| 215 | struct sk_buff *beacon; | ||
| 206 | 216 | ||
| 207 | struct ath10k *ar; | 217 | struct ath10k *ar; |
| 208 | struct ieee80211_vif *vif; | 218 | struct ieee80211_vif *vif; |
| 209 | 219 | ||
| 220 | struct work_struct wep_key_work; | ||
| 210 | struct ieee80211_key_conf *wep_keys[WMI_MAX_KEY_INDEX + 1]; | 221 | struct ieee80211_key_conf *wep_keys[WMI_MAX_KEY_INDEX + 1]; |
| 211 | u8 def_wep_key_index; | 222 | u8 def_wep_key_idx; |
| 223 | u8 def_wep_key_newidx; | ||
| 212 | 224 | ||
| 213 | u16 tx_seq_no; | 225 | u16 tx_seq_no; |
| 214 | 226 | ||
| @@ -246,6 +258,9 @@ struct ath10k_debug { | |||
| 246 | u32 wmi_service_bitmap[WMI_SERVICE_BM_SIZE]; | 258 | u32 wmi_service_bitmap[WMI_SERVICE_BM_SIZE]; |
| 247 | 259 | ||
| 248 | struct completion event_stats_compl; | 260 | struct completion event_stats_compl; |
| 261 | |||
| 262 | unsigned long htt_stats_mask; | ||
| 263 | struct delayed_work htt_stats_dwork; | ||
| 249 | }; | 264 | }; |
| 250 | 265 | ||
| 251 | enum ath10k_state { | 266 | enum ath10k_state { |
| @@ -270,12 +285,27 @@ enum ath10k_state { | |||
| 270 | ATH10K_STATE_WEDGED, | 285 | ATH10K_STATE_WEDGED, |
| 271 | }; | 286 | }; |
| 272 | 287 | ||
| 288 | enum ath10k_fw_features { | ||
| 289 | /* wmi_mgmt_rx_hdr contains extra RSSI information */ | ||
| 290 | ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX = 0, | ||
| 291 | |||
| 292 | /* firmware from 10X branch */ | ||
| 293 | ATH10K_FW_FEATURE_WMI_10X = 1, | ||
| 294 | |||
| 295 | /* firmware support tx frame management over WMI, otherwise it's HTT */ | ||
| 296 | ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX = 2, | ||
| 297 | |||
| 298 | /* keep last */ | ||
| 299 | ATH10K_FW_FEATURE_COUNT, | ||
| 300 | }; | ||
| 301 | |||
| 273 | struct ath10k { | 302 | struct ath10k { |
| 274 | struct ath_common ath_common; | 303 | struct ath_common ath_common; |
| 275 | struct ieee80211_hw *hw; | 304 | struct ieee80211_hw *hw; |
| 276 | struct device *dev; | 305 | struct device *dev; |
| 277 | u8 mac_addr[ETH_ALEN]; | 306 | u8 mac_addr[ETH_ALEN]; |
| 278 | 307 | ||
| 308 | u32 chip_id; | ||
| 279 | u32 target_version; | 309 | u32 target_version; |
| 280 | u8 fw_version_major; | 310 | u8 fw_version_major; |
| 281 | u32 fw_version_minor; | 311 | u32 fw_version_minor; |
| @@ -288,6 +318,8 @@ struct ath10k { | |||
| 288 | u32 vht_cap_info; | 318 | u32 vht_cap_info; |
| 289 | u32 num_rf_chains; | 319 | u32 num_rf_chains; |
| 290 | 320 | ||
| 321 | DECLARE_BITMAP(fw_features, ATH10K_FW_FEATURE_COUNT); | ||
| 322 | |||
| 291 | struct targetdef *targetdef; | 323 | struct targetdef *targetdef; |
| 292 | struct hostdef *hostdef; | 324 | struct hostdef *hostdef; |
| 293 | 325 | ||
| @@ -319,9 +351,19 @@ struct ath10k { | |||
| 319 | } fw; | 351 | } fw; |
| 320 | } hw_params; | 352 | } hw_params; |
| 321 | 353 | ||
| 322 | const struct firmware *board_data; | 354 | const struct firmware *board; |
| 355 | const void *board_data; | ||
| 356 | size_t board_len; | ||
| 357 | |||
| 323 | const struct firmware *otp; | 358 | const struct firmware *otp; |
| 359 | const void *otp_data; | ||
| 360 | size_t otp_len; | ||
| 361 | |||
| 324 | const struct firmware *firmware; | 362 | const struct firmware *firmware; |
| 363 | const void *firmware_data; | ||
| 364 | size_t firmware_len; | ||
| 365 | |||
| 366 | int fw_api; | ||
| 325 | 367 | ||
| 326 | struct { | 368 | struct { |
| 327 | struct completion started; | 369 | struct completion started; |
| @@ -364,6 +406,7 @@ struct ath10k { | |||
| 364 | /* protects shared structure data */ | 406 | /* protects shared structure data */ |
| 365 | spinlock_t data_lock; | 407 | spinlock_t data_lock; |
| 366 | 408 | ||
| 409 | struct list_head arvifs; | ||
| 367 | struct list_head peers; | 410 | struct list_head peers; |
| 368 | wait_queue_head_t peer_mapping_wq; | 411 | wait_queue_head_t peer_mapping_wq; |
| 369 | 412 | ||
| @@ -372,6 +415,9 @@ struct ath10k { | |||
| 372 | struct completion offchan_tx_completed; | 415 | struct completion offchan_tx_completed; |
| 373 | struct sk_buff *offchan_tx_skb; | 416 | struct sk_buff *offchan_tx_skb; |
| 374 | 417 | ||
| 418 | struct work_struct wmi_mgmt_tx_work; | ||
| 419 | struct sk_buff_head wmi_mgmt_tx_queue; | ||
| 420 | |||
| 375 | enum ath10k_state state; | 421 | enum ath10k_state state; |
| 376 | 422 | ||
| 377 | struct work_struct restart_work; | 423 | struct work_struct restart_work; |
| @@ -393,7 +439,7 @@ void ath10k_core_destroy(struct ath10k *ar); | |||
| 393 | 439 | ||
| 394 | int ath10k_core_start(struct ath10k *ar); | 440 | int ath10k_core_start(struct ath10k *ar); |
| 395 | void ath10k_core_stop(struct ath10k *ar); | 441 | void ath10k_core_stop(struct ath10k *ar); |
| 396 | int ath10k_core_register(struct ath10k *ar); | 442 | int ath10k_core_register(struct ath10k *ar, u32 chip_id); |
| 397 | void ath10k_core_unregister(struct ath10k *ar); | 443 | void ath10k_core_unregister(struct ath10k *ar); |
| 398 | 444 | ||
| 399 | #endif /* _CORE_H_ */ | 445 | #endif /* _CORE_H_ */ |
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 3d65594fa098..760ff2289e3c 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c | |||
| @@ -21,6 +21,9 @@ | |||
| 21 | #include "core.h" | 21 | #include "core.h" |
| 22 | #include "debug.h" | 22 | #include "debug.h" |
| 23 | 23 | ||
| 24 | /* ms */ | ||
| 25 | #define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000 | ||
| 26 | |||
| 24 | static int ath10k_printk(const char *level, const char *fmt, ...) | 27 | static int ath10k_printk(const char *level, const char *fmt, ...) |
| 25 | { | 28 | { |
| 26 | struct va_format vaf; | 29 | struct va_format vaf; |
| @@ -260,7 +263,6 @@ void ath10k_debug_read_target_stats(struct ath10k *ar, | |||
| 260 | } | 263 | } |
| 261 | 264 | ||
| 262 | spin_unlock_bh(&ar->data_lock); | 265 | spin_unlock_bh(&ar->data_lock); |
| 263 | mutex_unlock(&ar->conf_mutex); | ||
| 264 | complete(&ar->debug.event_stats_compl); | 266 | complete(&ar->debug.event_stats_compl); |
| 265 | } | 267 | } |
| 266 | 268 | ||
| @@ -499,6 +501,144 @@ static const struct file_operations fops_simulate_fw_crash = { | |||
| 499 | .llseek = default_llseek, | 501 | .llseek = default_llseek, |
| 500 | }; | 502 | }; |
| 501 | 503 | ||
| 504 | static ssize_t ath10k_read_chip_id(struct file *file, char __user *user_buf, | ||
| 505 | size_t count, loff_t *ppos) | ||
| 506 | { | ||
| 507 | struct ath10k *ar = file->private_data; | ||
| 508 | unsigned int len; | ||
| 509 | char buf[50]; | ||
| 510 | |||
| 511 | len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->chip_id); | ||
| 512 | |||
| 513 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
| 514 | } | ||
| 515 | |||
| 516 | static const struct file_operations fops_chip_id = { | ||
| 517 | .read = ath10k_read_chip_id, | ||
| 518 | .open = simple_open, | ||
| 519 | .owner = THIS_MODULE, | ||
| 520 | .llseek = default_llseek, | ||
| 521 | }; | ||
| 522 | |||
| 523 | static int ath10k_debug_htt_stats_req(struct ath10k *ar) | ||
| 524 | { | ||
| 525 | u64 cookie; | ||
| 526 | int ret; | ||
| 527 | |||
| 528 | lockdep_assert_held(&ar->conf_mutex); | ||
| 529 | |||
| 530 | if (ar->debug.htt_stats_mask == 0) | ||
| 531 | /* htt stats are disabled */ | ||
| 532 | return 0; | ||
| 533 | |||
| 534 | if (ar->state != ATH10K_STATE_ON) | ||
| 535 | return 0; | ||
| 536 | |||
| 537 | cookie = get_jiffies_64(); | ||
| 538 | |||
| 539 | ret = ath10k_htt_h2t_stats_req(&ar->htt, ar->debug.htt_stats_mask, | ||
| 540 | cookie); | ||
| 541 | if (ret) { | ||
| 542 | ath10k_warn("failed to send htt stats request: %d\n", ret); | ||
| 543 | return ret; | ||
| 544 | } | ||
| 545 | |||
| 546 | queue_delayed_work(ar->workqueue, &ar->debug.htt_stats_dwork, | ||
| 547 | msecs_to_jiffies(ATH10K_DEBUG_HTT_STATS_INTERVAL)); | ||
| 548 | |||
| 549 | return 0; | ||
| 550 | } | ||
| 551 | |||
| 552 | static void ath10k_debug_htt_stats_dwork(struct work_struct *work) | ||
| 553 | { | ||
| 554 | struct ath10k *ar = container_of(work, struct ath10k, | ||
| 555 | debug.htt_stats_dwork.work); | ||
| 556 | |||
| 557 | mutex_lock(&ar->conf_mutex); | ||
| 558 | |||
| 559 | ath10k_debug_htt_stats_req(ar); | ||
| 560 | |||
| 561 | mutex_unlock(&ar->conf_mutex); | ||
| 562 | } | ||
| 563 | |||
| 564 | static ssize_t ath10k_read_htt_stats_mask(struct file *file, | ||
| 565 | char __user *user_buf, | ||
| 566 | size_t count, loff_t *ppos) | ||
| 567 | { | ||
| 568 | struct ath10k *ar = file->private_data; | ||
| 569 | char buf[32]; | ||
| 570 | unsigned int len; | ||
| 571 | |||
| 572 | len = scnprintf(buf, sizeof(buf), "%lu\n", ar->debug.htt_stats_mask); | ||
| 573 | |||
| 574 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
| 575 | } | ||
| 576 | |||
| 577 | static ssize_t ath10k_write_htt_stats_mask(struct file *file, | ||
| 578 | const char __user *user_buf, | ||
| 579 | size_t count, loff_t *ppos) | ||
| 580 | { | ||
| 581 | struct ath10k *ar = file->private_data; | ||
| 582 | unsigned long mask; | ||
| 583 | int ret; | ||
| 584 | |||
| 585 | ret = kstrtoul_from_user(user_buf, count, 0, &mask); | ||
| 586 | if (ret) | ||
| 587 | return ret; | ||
| 588 | |||
| 589 | /* max 8 bit masks (for now) */ | ||
| 590 | if (mask > 0xff) | ||
| 591 | return -E2BIG; | ||
| 592 | |||
| 593 | mutex_lock(&ar->conf_mutex); | ||
| 594 | |||
| 595 | ar->debug.htt_stats_mask = mask; | ||
| 596 | |||
| 597 | ret = ath10k_debug_htt_stats_req(ar); | ||
| 598 | if (ret) | ||
| 599 | goto out; | ||
| 600 | |||
| 601 | ret = count; | ||
| 602 | |||
| 603 | out: | ||
| 604 | mutex_unlock(&ar->conf_mutex); | ||
| 605 | |||
| 606 | return ret; | ||
| 607 | } | ||
| 608 | |||
| 609 | static const struct file_operations fops_htt_stats_mask = { | ||
| 610 | .read = ath10k_read_htt_stats_mask, | ||
| 611 | .write = ath10k_write_htt_stats_mask, | ||
| 612 | .open = simple_open, | ||
| 613 | .owner = THIS_MODULE, | ||
| 614 | .llseek = default_llseek, | ||
| 615 | }; | ||
| 616 | |||
| 617 | int ath10k_debug_start(struct ath10k *ar) | ||
| 618 | { | ||
| 619 | int ret; | ||
| 620 | |||
| 621 | lockdep_assert_held(&ar->conf_mutex); | ||
| 622 | |||
| 623 | ret = ath10k_debug_htt_stats_req(ar); | ||
| 624 | if (ret) | ||
| 625 | /* continue normally anyway, this isn't serious */ | ||
| 626 | ath10k_warn("failed to start htt stats workqueue: %d\n", ret); | ||
| 627 | |||
| 628 | return 0; | ||
| 629 | } | ||
| 630 | |||
| 631 | void ath10k_debug_stop(struct ath10k *ar) | ||
| 632 | { | ||
| 633 | lockdep_assert_held(&ar->conf_mutex); | ||
| 634 | |||
| 635 | /* Must not use _sync to avoid deadlock, we do that in | ||
| 636 | * ath10k_debug_destroy(). The check for htt_stats_mask is to avoid | ||
| 637 | * warning from del_timer(). */ | ||
| 638 | if (ar->debug.htt_stats_mask != 0) | ||
| 639 | cancel_delayed_work(&ar->debug.htt_stats_dwork); | ||
| 640 | } | ||
| 641 | |||
| 502 | int ath10k_debug_create(struct ath10k *ar) | 642 | int ath10k_debug_create(struct ath10k *ar) |
| 503 | { | 643 | { |
| 504 | ar->debug.debugfs_phy = debugfs_create_dir("ath10k", | 644 | ar->debug.debugfs_phy = debugfs_create_dir("ath10k", |
| @@ -507,6 +647,9 @@ int ath10k_debug_create(struct ath10k *ar) | |||
| 507 | if (!ar->debug.debugfs_phy) | 647 | if (!ar->debug.debugfs_phy) |
| 508 | return -ENOMEM; | 648 | return -ENOMEM; |
| 509 | 649 | ||
| 650 | INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork, | ||
| 651 | ath10k_debug_htt_stats_dwork); | ||
| 652 | |||
| 510 | init_completion(&ar->debug.event_stats_compl); | 653 | init_completion(&ar->debug.event_stats_compl); |
| 511 | 654 | ||
| 512 | debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar, | 655 | debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar, |
| @@ -518,8 +661,20 @@ int ath10k_debug_create(struct ath10k *ar) | |||
| 518 | debugfs_create_file("simulate_fw_crash", S_IRUSR, ar->debug.debugfs_phy, | 661 | debugfs_create_file("simulate_fw_crash", S_IRUSR, ar->debug.debugfs_phy, |
| 519 | ar, &fops_simulate_fw_crash); | 662 | ar, &fops_simulate_fw_crash); |
| 520 | 663 | ||
| 664 | debugfs_create_file("chip_id", S_IRUSR, ar->debug.debugfs_phy, | ||
| 665 | ar, &fops_chip_id); | ||
| 666 | |||
| 667 | debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy, | ||
| 668 | ar, &fops_htt_stats_mask); | ||
| 669 | |||
| 521 | return 0; | 670 | return 0; |
| 522 | } | 671 | } |
| 672 | |||
| 673 | void ath10k_debug_destroy(struct ath10k *ar) | ||
| 674 | { | ||
| 675 | cancel_delayed_work_sync(&ar->debug.htt_stats_dwork); | ||
| 676 | } | ||
| 677 | |||
| 523 | #endif /* CONFIG_ATH10K_DEBUGFS */ | 678 | #endif /* CONFIG_ATH10K_DEBUGFS */ |
| 524 | 679 | ||
| 525 | #ifdef CONFIG_ATH10K_DEBUG | 680 | #ifdef CONFIG_ATH10K_DEBUG |
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index 168140c54028..3cfe3ee90dbe 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h | |||
| @@ -27,22 +27,26 @@ enum ath10k_debug_mask { | |||
| 27 | ATH10K_DBG_HTC = 0x00000004, | 27 | ATH10K_DBG_HTC = 0x00000004, |
| 28 | ATH10K_DBG_HTT = 0x00000008, | 28 | ATH10K_DBG_HTT = 0x00000008, |
| 29 | ATH10K_DBG_MAC = 0x00000010, | 29 | ATH10K_DBG_MAC = 0x00000010, |
| 30 | ATH10K_DBG_CORE = 0x00000020, | 30 | ATH10K_DBG_BOOT = 0x00000020, |
| 31 | ATH10K_DBG_PCI_DUMP = 0x00000040, | 31 | ATH10K_DBG_PCI_DUMP = 0x00000040, |
| 32 | ATH10K_DBG_HTT_DUMP = 0x00000080, | 32 | ATH10K_DBG_HTT_DUMP = 0x00000080, |
| 33 | ATH10K_DBG_MGMT = 0x00000100, | 33 | ATH10K_DBG_MGMT = 0x00000100, |
| 34 | ATH10K_DBG_DATA = 0x00000200, | 34 | ATH10K_DBG_DATA = 0x00000200, |
| 35 | ATH10K_DBG_BMI = 0x00000400, | ||
| 35 | ATH10K_DBG_ANY = 0xffffffff, | 36 | ATH10K_DBG_ANY = 0xffffffff, |
| 36 | }; | 37 | }; |
| 37 | 38 | ||
| 38 | extern unsigned int ath10k_debug_mask; | 39 | extern unsigned int ath10k_debug_mask; |
| 39 | 40 | ||
| 40 | extern __printf(1, 2) int ath10k_info(const char *fmt, ...); | 41 | __printf(1, 2) int ath10k_info(const char *fmt, ...); |
| 41 | extern __printf(1, 2) int ath10k_err(const char *fmt, ...); | 42 | __printf(1, 2) int ath10k_err(const char *fmt, ...); |
| 42 | extern __printf(1, 2) int ath10k_warn(const char *fmt, ...); | 43 | __printf(1, 2) int ath10k_warn(const char *fmt, ...); |
| 43 | 44 | ||
| 44 | #ifdef CONFIG_ATH10K_DEBUGFS | 45 | #ifdef CONFIG_ATH10K_DEBUGFS |
| 46 | int ath10k_debug_start(struct ath10k *ar); | ||
| 47 | void ath10k_debug_stop(struct ath10k *ar); | ||
| 45 | int ath10k_debug_create(struct ath10k *ar); | 48 | int ath10k_debug_create(struct ath10k *ar); |
| 49 | void ath10k_debug_destroy(struct ath10k *ar); | ||
| 46 | void ath10k_debug_read_service_map(struct ath10k *ar, | 50 | void ath10k_debug_read_service_map(struct ath10k *ar, |
| 47 | void *service_map, | 51 | void *service_map, |
| 48 | size_t map_size); | 52 | size_t map_size); |
| @@ -50,11 +54,24 @@ void ath10k_debug_read_target_stats(struct ath10k *ar, | |||
| 50 | struct wmi_stats_event *ev); | 54 | struct wmi_stats_event *ev); |
| 51 | 55 | ||
| 52 | #else | 56 | #else |
| 57 | static inline int ath10k_debug_start(struct ath10k *ar) | ||
| 58 | { | ||
| 59 | return 0; | ||
| 60 | } | ||
| 61 | |||
| 62 | static inline void ath10k_debug_stop(struct ath10k *ar) | ||
| 63 | { | ||
| 64 | } | ||
| 65 | |||
| 53 | static inline int ath10k_debug_create(struct ath10k *ar) | 66 | static inline int ath10k_debug_create(struct ath10k *ar) |
| 54 | { | 67 | { |
| 55 | return 0; | 68 | return 0; |
| 56 | } | 69 | } |
| 57 | 70 | ||
| 71 | static inline void ath10k_debug_destroy(struct ath10k *ar) | ||
| 72 | { | ||
| 73 | } | ||
| 74 | |||
| 58 | static inline void ath10k_debug_read_service_map(struct ath10k *ar, | 75 | static inline void ath10k_debug_read_service_map(struct ath10k *ar, |
| 59 | void *service_map, | 76 | void *service_map, |
| 60 | size_t map_size) | 77 | size_t map_size) |
| @@ -68,7 +85,7 @@ static inline void ath10k_debug_read_target_stats(struct ath10k *ar, | |||
| 68 | #endif /* CONFIG_ATH10K_DEBUGFS */ | 85 | #endif /* CONFIG_ATH10K_DEBUGFS */ |
| 69 | 86 | ||
| 70 | #ifdef CONFIG_ATH10K_DEBUG | 87 | #ifdef CONFIG_ATH10K_DEBUG |
| 71 | extern __printf(2, 3) void ath10k_dbg(enum ath10k_debug_mask mask, | 88 | __printf(2, 3) void ath10k_dbg(enum ath10k_debug_mask mask, |
| 72 | const char *fmt, ...); | 89 | const char *fmt, ...); |
| 73 | void ath10k_dbg_dump(enum ath10k_debug_mask mask, | 90 | void ath10k_dbg_dump(enum ath10k_debug_mask mask, |
| 74 | const char *msg, const char *prefix, | 91 | const char *msg, const char *prefix, |
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c index ef3329ef52f3..3118d7506734 100644 --- a/drivers/net/wireless/ath/ath10k/htc.c +++ b/drivers/net/wireless/ath/ath10k/htc.c | |||
| @@ -103,10 +103,10 @@ static void ath10k_htc_prepare_tx_skb(struct ath10k_htc_ep *ep, | |||
| 103 | struct ath10k_htc_hdr *hdr; | 103 | struct ath10k_htc_hdr *hdr; |
| 104 | 104 | ||
| 105 | hdr = (struct ath10k_htc_hdr *)skb->data; | 105 | hdr = (struct ath10k_htc_hdr *)skb->data; |
| 106 | memset(hdr, 0, sizeof(*hdr)); | ||
| 107 | 106 | ||
| 108 | hdr->eid = ep->eid; | 107 | hdr->eid = ep->eid; |
| 109 | hdr->len = __cpu_to_le16(skb->len - sizeof(*hdr)); | 108 | hdr->len = __cpu_to_le16(skb->len - sizeof(*hdr)); |
| 109 | hdr->flags = 0; | ||
| 110 | 110 | ||
| 111 | spin_lock_bh(&ep->htc->tx_lock); | 111 | spin_lock_bh(&ep->htc->tx_lock); |
| 112 | hdr->seq_no = ep->seq_no++; | 112 | hdr->seq_no = ep->seq_no++; |
| @@ -117,134 +117,13 @@ static void ath10k_htc_prepare_tx_skb(struct ath10k_htc_ep *ep, | |||
| 117 | spin_unlock_bh(&ep->htc->tx_lock); | 117 | spin_unlock_bh(&ep->htc->tx_lock); |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | static int ath10k_htc_issue_skb(struct ath10k_htc *htc, | ||
| 121 | struct ath10k_htc_ep *ep, | ||
| 122 | struct sk_buff *skb, | ||
| 123 | u8 credits) | ||
| 124 | { | ||
| 125 | struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); | ||
| 126 | int ret; | ||
| 127 | |||
| 128 | ath10k_dbg(ATH10K_DBG_HTC, "%s: ep %d skb %p\n", __func__, | ||
| 129 | ep->eid, skb); | ||
| 130 | |||
| 131 | ath10k_htc_prepare_tx_skb(ep, skb); | ||
| 132 | |||
| 133 | ret = ath10k_skb_map(htc->ar->dev, skb); | ||
| 134 | if (ret) | ||
| 135 | goto err; | ||
| 136 | |||
| 137 | ret = ath10k_hif_send_head(htc->ar, | ||
| 138 | ep->ul_pipe_id, | ||
| 139 | ep->eid, | ||
| 140 | skb->len, | ||
| 141 | skb); | ||
| 142 | if (unlikely(ret)) | ||
| 143 | goto err; | ||
| 144 | |||
| 145 | return 0; | ||
| 146 | err: | ||
| 147 | ath10k_warn("HTC issue failed: %d\n", ret); | ||
| 148 | |||
| 149 | spin_lock_bh(&htc->tx_lock); | ||
| 150 | ep->tx_credits += credits; | ||
| 151 | spin_unlock_bh(&htc->tx_lock); | ||
| 152 | |||
| 153 | /* this is the simplest way to handle out-of-resources for non-credit | ||
| 154 | * based endpoints. credit based endpoints can still get -ENOSR, but | ||
| 155 | * this is highly unlikely as credit reservation should prevent that */ | ||
| 156 | if (ret == -ENOSR) { | ||
| 157 | spin_lock_bh(&htc->tx_lock); | ||
| 158 | __skb_queue_head(&ep->tx_queue, skb); | ||
| 159 | spin_unlock_bh(&htc->tx_lock); | ||
| 160 | |||
| 161 | return ret; | ||
| 162 | } | ||
| 163 | |||
| 164 | skb_cb->is_aborted = true; | ||
| 165 | ath10k_htc_notify_tx_completion(ep, skb); | ||
| 166 | |||
| 167 | return ret; | ||
| 168 | } | ||
| 169 | |||
| 170 | static struct sk_buff *ath10k_htc_get_skb_credit_based(struct ath10k_htc *htc, | ||
| 171 | struct ath10k_htc_ep *ep, | ||
| 172 | u8 *credits) | ||
| 173 | { | ||
| 174 | struct sk_buff *skb; | ||
| 175 | struct ath10k_skb_cb *skb_cb; | ||
| 176 | int credits_required; | ||
| 177 | int remainder; | ||
| 178 | unsigned int transfer_len; | ||
| 179 | |||
| 180 | lockdep_assert_held(&htc->tx_lock); | ||
| 181 | |||
| 182 | skb = __skb_dequeue(&ep->tx_queue); | ||
| 183 | if (!skb) | ||
| 184 | return NULL; | ||
| 185 | |||
| 186 | skb_cb = ATH10K_SKB_CB(skb); | ||
| 187 | transfer_len = skb->len; | ||
| 188 | |||
| 189 | if (likely(transfer_len <= htc->target_credit_size)) { | ||
| 190 | credits_required = 1; | ||
| 191 | } else { | ||
| 192 | /* figure out how many credits this message requires */ | ||
| 193 | credits_required = transfer_len / htc->target_credit_size; | ||
| 194 | remainder = transfer_len % htc->target_credit_size; | ||
| 195 | |||
| 196 | if (remainder) | ||
| 197 | credits_required++; | ||
| 198 | } | ||
| 199 | |||
| 200 | ath10k_dbg(ATH10K_DBG_HTC, "Credits required %d got %d\n", | ||
| 201 | credits_required, ep->tx_credits); | ||
| 202 | |||
| 203 | if (ep->tx_credits < credits_required) { | ||
| 204 | __skb_queue_head(&ep->tx_queue, skb); | ||
| 205 | return NULL; | ||
| 206 | } | ||
| 207 | |||
| 208 | ep->tx_credits -= credits_required; | ||
| 209 | *credits = credits_required; | ||
| 210 | return skb; | ||
| 211 | } | ||
| 212 | |||
| 213 | static void ath10k_htc_send_work(struct work_struct *work) | ||
| 214 | { | ||
| 215 | struct ath10k_htc_ep *ep = container_of(work, | ||
| 216 | struct ath10k_htc_ep, send_work); | ||
| 217 | struct ath10k_htc *htc = ep->htc; | ||
| 218 | struct sk_buff *skb; | ||
| 219 | u8 credits = 0; | ||
| 220 | int ret; | ||
| 221 | |||
| 222 | while (true) { | ||
| 223 | if (ep->ul_is_polled) | ||
| 224 | ath10k_htc_send_complete_check(ep, 0); | ||
| 225 | |||
| 226 | spin_lock_bh(&htc->tx_lock); | ||
| 227 | if (ep->tx_credit_flow_enabled) | ||
| 228 | skb = ath10k_htc_get_skb_credit_based(htc, ep, | ||
| 229 | &credits); | ||
| 230 | else | ||
| 231 | skb = __skb_dequeue(&ep->tx_queue); | ||
| 232 | spin_unlock_bh(&htc->tx_lock); | ||
| 233 | |||
| 234 | if (!skb) | ||
| 235 | break; | ||
| 236 | |||
| 237 | ret = ath10k_htc_issue_skb(htc, ep, skb, credits); | ||
| 238 | if (ret == -ENOSR) | ||
| 239 | break; | ||
| 240 | } | ||
| 241 | } | ||
| 242 | |||
| 243 | int ath10k_htc_send(struct ath10k_htc *htc, | 120 | int ath10k_htc_send(struct ath10k_htc *htc, |
| 244 | enum ath10k_htc_ep_id eid, | 121 | enum ath10k_htc_ep_id eid, |
| 245 | struct sk_buff *skb) | 122 | struct sk_buff *skb) |
| 246 | { | 123 | { |
| 247 | struct ath10k_htc_ep *ep = &htc->endpoint[eid]; | 124 | struct ath10k_htc_ep *ep = &htc->endpoint[eid]; |
| 125 | int credits = 0; | ||
| 126 | int ret; | ||
| 248 | 127 | ||
| 249 | if (htc->ar->state == ATH10K_STATE_WEDGED) | 128 | if (htc->ar->state == ATH10K_STATE_WEDGED) |
| 250 | return -ECOMM; | 129 | return -ECOMM; |
| @@ -254,18 +133,55 @@ int ath10k_htc_send(struct ath10k_htc *htc, | |||
| 254 | return -ENOENT; | 133 | return -ENOENT; |
| 255 | } | 134 | } |
| 256 | 135 | ||
| 136 | /* FIXME: This looks ugly, can we fix it? */ | ||
| 257 | spin_lock_bh(&htc->tx_lock); | 137 | spin_lock_bh(&htc->tx_lock); |
| 258 | if (htc->stopped) { | 138 | if (htc->stopped) { |
| 259 | spin_unlock_bh(&htc->tx_lock); | 139 | spin_unlock_bh(&htc->tx_lock); |
| 260 | return -ESHUTDOWN; | 140 | return -ESHUTDOWN; |
| 261 | } | 141 | } |
| 142 | spin_unlock_bh(&htc->tx_lock); | ||
| 262 | 143 | ||
| 263 | __skb_queue_tail(&ep->tx_queue, skb); | ||
| 264 | skb_push(skb, sizeof(struct ath10k_htc_hdr)); | 144 | skb_push(skb, sizeof(struct ath10k_htc_hdr)); |
| 265 | spin_unlock_bh(&htc->tx_lock); | ||
| 266 | 145 | ||
| 267 | queue_work(htc->ar->workqueue, &ep->send_work); | 146 | if (ep->tx_credit_flow_enabled) { |
| 147 | credits = DIV_ROUND_UP(skb->len, htc->target_credit_size); | ||
| 148 | spin_lock_bh(&htc->tx_lock); | ||
| 149 | if (ep->tx_credits < credits) { | ||
| 150 | spin_unlock_bh(&htc->tx_lock); | ||
| 151 | ret = -EAGAIN; | ||
| 152 | goto err_pull; | ||
| 153 | } | ||
| 154 | ep->tx_credits -= credits; | ||
| 155 | spin_unlock_bh(&htc->tx_lock); | ||
| 156 | } | ||
| 157 | |||
| 158 | ath10k_htc_prepare_tx_skb(ep, skb); | ||
| 159 | |||
| 160 | ret = ath10k_skb_map(htc->ar->dev, skb); | ||
| 161 | if (ret) | ||
| 162 | goto err_credits; | ||
| 163 | |||
| 164 | ret = ath10k_hif_send_head(htc->ar, ep->ul_pipe_id, ep->eid, | ||
| 165 | skb->len, skb); | ||
| 166 | if (ret) | ||
| 167 | goto err_unmap; | ||
| 168 | |||
| 268 | return 0; | 169 | return 0; |
| 170 | |||
| 171 | err_unmap: | ||
| 172 | ath10k_skb_unmap(htc->ar->dev, skb); | ||
| 173 | err_credits: | ||
| 174 | if (ep->tx_credit_flow_enabled) { | ||
| 175 | spin_lock_bh(&htc->tx_lock); | ||
| 176 | ep->tx_credits += credits; | ||
| 177 | spin_unlock_bh(&htc->tx_lock); | ||
| 178 | |||
| 179 | if (ep->ep_ops.ep_tx_credits) | ||
| 180 | ep->ep_ops.ep_tx_credits(htc->ar); | ||
| 181 | } | ||
| 182 | err_pull: | ||
| 183 | skb_pull(skb, sizeof(struct ath10k_htc_hdr)); | ||
| 184 | return ret; | ||
| 269 | } | 185 | } |
| 270 | 186 | ||
| 271 | static int ath10k_htc_tx_completion_handler(struct ath10k *ar, | 187 | static int ath10k_htc_tx_completion_handler(struct ath10k *ar, |
| @@ -278,39 +194,9 @@ static int ath10k_htc_tx_completion_handler(struct ath10k *ar, | |||
| 278 | ath10k_htc_notify_tx_completion(ep, skb); | 194 | ath10k_htc_notify_tx_completion(ep, skb); |
| 279 | /* the skb now belongs to the completion handler */ | 195 | /* the skb now belongs to the completion handler */ |
| 280 | 196 | ||
| 281 | /* note: when using TX credit flow, the re-checking of queues happens | ||
| 282 | * when credits flow back from the target. in the non-TX credit case, | ||
| 283 | * we recheck after the packet completes */ | ||
| 284 | spin_lock_bh(&htc->tx_lock); | ||
| 285 | if (!ep->tx_credit_flow_enabled && !htc->stopped) | ||
| 286 | queue_work(ar->workqueue, &ep->send_work); | ||
| 287 | spin_unlock_bh(&htc->tx_lock); | ||
| 288 | |||
| 289 | return 0; | 197 | return 0; |
| 290 | } | 198 | } |
| 291 | 199 | ||
| 292 | /* flush endpoint TX queue */ | ||
| 293 | static void ath10k_htc_flush_endpoint_tx(struct ath10k_htc *htc, | ||
| 294 | struct ath10k_htc_ep *ep) | ||
| 295 | { | ||
| 296 | struct sk_buff *skb; | ||
| 297 | struct ath10k_skb_cb *skb_cb; | ||
| 298 | |||
| 299 | spin_lock_bh(&htc->tx_lock); | ||
| 300 | for (;;) { | ||
| 301 | skb = __skb_dequeue(&ep->tx_queue); | ||
| 302 | if (!skb) | ||
| 303 | break; | ||
| 304 | |||
| 305 | skb_cb = ATH10K_SKB_CB(skb); | ||
| 306 | skb_cb->is_aborted = true; | ||
| 307 | ath10k_htc_notify_tx_completion(ep, skb); | ||
| 308 | } | ||
| 309 | spin_unlock_bh(&htc->tx_lock); | ||
| 310 | |||
| 311 | cancel_work_sync(&ep->send_work); | ||
| 312 | } | ||
| 313 | |||
| 314 | /***********/ | 200 | /***********/ |
| 315 | /* Receive */ | 201 | /* Receive */ |
| 316 | /***********/ | 202 | /***********/ |
| @@ -340,8 +226,11 @@ ath10k_htc_process_credit_report(struct ath10k_htc *htc, | |||
| 340 | ep = &htc->endpoint[report->eid]; | 226 | ep = &htc->endpoint[report->eid]; |
| 341 | ep->tx_credits += report->credits; | 227 | ep->tx_credits += report->credits; |
| 342 | 228 | ||
| 343 | if (ep->tx_credits && !skb_queue_empty(&ep->tx_queue)) | 229 | if (ep->ep_ops.ep_tx_credits) { |
| 344 | queue_work(htc->ar->workqueue, &ep->send_work); | 230 | spin_unlock_bh(&htc->tx_lock); |
| 231 | ep->ep_ops.ep_tx_credits(htc->ar); | ||
| 232 | spin_lock_bh(&htc->tx_lock); | ||
| 233 | } | ||
| 345 | } | 234 | } |
| 346 | spin_unlock_bh(&htc->tx_lock); | 235 | spin_unlock_bh(&htc->tx_lock); |
| 347 | } | 236 | } |
| @@ -599,10 +488,8 @@ static void ath10k_htc_reset_endpoint_states(struct ath10k_htc *htc) | |||
| 599 | ep->max_ep_message_len = 0; | 488 | ep->max_ep_message_len = 0; |
| 600 | ep->max_tx_queue_depth = 0; | 489 | ep->max_tx_queue_depth = 0; |
| 601 | ep->eid = i; | 490 | ep->eid = i; |
| 602 | skb_queue_head_init(&ep->tx_queue); | ||
| 603 | ep->htc = htc; | 491 | ep->htc = htc; |
| 604 | ep->tx_credit_flow_enabled = true; | 492 | ep->tx_credit_flow_enabled = true; |
| 605 | INIT_WORK(&ep->send_work, ath10k_htc_send_work); | ||
| 606 | } | 493 | } |
| 607 | } | 494 | } |
| 608 | 495 | ||
| @@ -752,8 +639,8 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc, | |||
| 752 | tx_alloc = ath10k_htc_get_credit_allocation(htc, | 639 | tx_alloc = ath10k_htc_get_credit_allocation(htc, |
| 753 | conn_req->service_id); | 640 | conn_req->service_id); |
| 754 | if (!tx_alloc) | 641 | if (!tx_alloc) |
| 755 | ath10k_dbg(ATH10K_DBG_HTC, | 642 | ath10k_dbg(ATH10K_DBG_BOOT, |
| 756 | "HTC Service %s does not allocate target credits\n", | 643 | "boot htc service %s does not allocate target credits\n", |
| 757 | htc_service_name(conn_req->service_id)); | 644 | htc_service_name(conn_req->service_id)); |
| 758 | 645 | ||
| 759 | skb = ath10k_htc_build_tx_ctrl_skb(htc->ar); | 646 | skb = ath10k_htc_build_tx_ctrl_skb(htc->ar); |
| @@ -772,16 +659,16 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc, | |||
| 772 | 659 | ||
| 773 | flags |= SM(tx_alloc, ATH10K_HTC_CONN_FLAGS_RECV_ALLOC); | 660 | flags |= SM(tx_alloc, ATH10K_HTC_CONN_FLAGS_RECV_ALLOC); |
| 774 | 661 | ||
| 775 | req_msg = &msg->connect_service; | ||
| 776 | req_msg->flags = __cpu_to_le16(flags); | ||
| 777 | req_msg->service_id = __cpu_to_le16(conn_req->service_id); | ||
| 778 | |||
| 779 | /* Only enable credit flow control for WMI ctrl service */ | 662 | /* Only enable credit flow control for WMI ctrl service */ |
| 780 | if (conn_req->service_id != ATH10K_HTC_SVC_ID_WMI_CONTROL) { | 663 | if (conn_req->service_id != ATH10K_HTC_SVC_ID_WMI_CONTROL) { |
| 781 | flags |= ATH10K_HTC_CONN_FLAGS_DISABLE_CREDIT_FLOW_CTRL; | 664 | flags |= ATH10K_HTC_CONN_FLAGS_DISABLE_CREDIT_FLOW_CTRL; |
| 782 | disable_credit_flow_ctrl = true; | 665 | disable_credit_flow_ctrl = true; |
| 783 | } | 666 | } |
| 784 | 667 | ||
| 668 | req_msg = &msg->connect_service; | ||
| 669 | req_msg->flags = __cpu_to_le16(flags); | ||
| 670 | req_msg->service_id = __cpu_to_le16(conn_req->service_id); | ||
| 671 | |||
| 785 | INIT_COMPLETION(htc->ctl_resp); | 672 | INIT_COMPLETION(htc->ctl_resp); |
| 786 | 673 | ||
| 787 | status = ath10k_htc_send(htc, ATH10K_HTC_EP_0, skb); | 674 | status = ath10k_htc_send(htc, ATH10K_HTC_EP_0, skb); |
| @@ -873,19 +760,19 @@ setup: | |||
| 873 | if (status) | 760 | if (status) |
| 874 | return status; | 761 | return status; |
| 875 | 762 | ||
| 876 | ath10k_dbg(ATH10K_DBG_HTC, | 763 | ath10k_dbg(ATH10K_DBG_BOOT, |
| 877 | "HTC service: %s UL pipe: %d DL pipe: %d eid: %d ready\n", | 764 | "boot htc service '%s' ul pipe %d dl pipe %d eid %d ready\n", |
| 878 | htc_service_name(ep->service_id), ep->ul_pipe_id, | 765 | htc_service_name(ep->service_id), ep->ul_pipe_id, |
| 879 | ep->dl_pipe_id, ep->eid); | 766 | ep->dl_pipe_id, ep->eid); |
| 880 | 767 | ||
| 881 | ath10k_dbg(ATH10K_DBG_HTC, | 768 | ath10k_dbg(ATH10K_DBG_BOOT, |
| 882 | "EP %d UL polled: %d, DL polled: %d\n", | 769 | "boot htc ep %d ul polled %d dl polled %d\n", |
| 883 | ep->eid, ep->ul_is_polled, ep->dl_is_polled); | 770 | ep->eid, ep->ul_is_polled, ep->dl_is_polled); |
| 884 | 771 | ||
| 885 | if (disable_credit_flow_ctrl && ep->tx_credit_flow_enabled) { | 772 | if (disable_credit_flow_ctrl && ep->tx_credit_flow_enabled) { |
| 886 | ep->tx_credit_flow_enabled = false; | 773 | ep->tx_credit_flow_enabled = false; |
| 887 | ath10k_dbg(ATH10K_DBG_HTC, | 774 | ath10k_dbg(ATH10K_DBG_BOOT, |
| 888 | "HTC service: %s eid: %d TX flow control disabled\n", | 775 | "boot htc service '%s' eid %d TX flow control disabled\n", |
| 889 | htc_service_name(ep->service_id), assigned_eid); | 776 | htc_service_name(ep->service_id), assigned_eid); |
| 890 | } | 777 | } |
| 891 | 778 | ||
| @@ -945,18 +832,10 @@ int ath10k_htc_start(struct ath10k_htc *htc) | |||
| 945 | */ | 832 | */ |
| 946 | void ath10k_htc_stop(struct ath10k_htc *htc) | 833 | void ath10k_htc_stop(struct ath10k_htc *htc) |
| 947 | { | 834 | { |
| 948 | int i; | ||
| 949 | struct ath10k_htc_ep *ep; | ||
| 950 | |||
| 951 | spin_lock_bh(&htc->tx_lock); | 835 | spin_lock_bh(&htc->tx_lock); |
| 952 | htc->stopped = true; | 836 | htc->stopped = true; |
| 953 | spin_unlock_bh(&htc->tx_lock); | 837 | spin_unlock_bh(&htc->tx_lock); |
| 954 | 838 | ||
| 955 | for (i = ATH10K_HTC_EP_0; i < ATH10K_HTC_EP_COUNT; i++) { | ||
| 956 | ep = &htc->endpoint[i]; | ||
| 957 | ath10k_htc_flush_endpoint_tx(htc, ep); | ||
| 958 | } | ||
| 959 | |||
| 960 | ath10k_hif_stop(htc->ar); | 839 | ath10k_hif_stop(htc->ar); |
| 961 | } | 840 | } |
| 962 | 841 | ||
diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h index e1dd8c761853..4716d331e6b6 100644 --- a/drivers/net/wireless/ath/ath10k/htc.h +++ b/drivers/net/wireless/ath/ath10k/htc.h | |||
| @@ -276,6 +276,7 @@ struct ath10k_htc_ops { | |||
| 276 | struct ath10k_htc_ep_ops { | 276 | struct ath10k_htc_ep_ops { |
| 277 | void (*ep_tx_complete)(struct ath10k *, struct sk_buff *); | 277 | void (*ep_tx_complete)(struct ath10k *, struct sk_buff *); |
| 278 | void (*ep_rx_complete)(struct ath10k *, struct sk_buff *); | 278 | void (*ep_rx_complete)(struct ath10k *, struct sk_buff *); |
| 279 | void (*ep_tx_credits)(struct ath10k *); | ||
| 279 | }; | 280 | }; |
| 280 | 281 | ||
| 281 | /* service connection information */ | 282 | /* service connection information */ |
| @@ -315,15 +316,11 @@ struct ath10k_htc_ep { | |||
| 315 | int ul_is_polled; /* call HIF to get tx completions */ | 316 | int ul_is_polled; /* call HIF to get tx completions */ |
| 316 | int dl_is_polled; /* call HIF to fetch rx (not implemented) */ | 317 | int dl_is_polled; /* call HIF to fetch rx (not implemented) */ |
| 317 | 318 | ||
| 318 | struct sk_buff_head tx_queue; | ||
| 319 | |||
| 320 | u8 seq_no; /* for debugging */ | 319 | u8 seq_no; /* for debugging */ |
| 321 | int tx_credits; | 320 | int tx_credits; |
| 322 | int tx_credit_size; | 321 | int tx_credit_size; |
| 323 | int tx_credits_per_max_message; | 322 | int tx_credits_per_max_message; |
| 324 | bool tx_credit_flow_enabled; | 323 | bool tx_credit_flow_enabled; |
| 325 | |||
| 326 | struct work_struct send_work; | ||
| 327 | }; | 324 | }; |
| 328 | 325 | ||
| 329 | struct ath10k_htc_svc_tx_credits { | 326 | struct ath10k_htc_svc_tx_credits { |
diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c index 39342c5cfcb2..5f7eeebc5432 100644 --- a/drivers/net/wireless/ath/ath10k/htt.c +++ b/drivers/net/wireless/ath/ath10k/htt.c | |||
| @@ -104,21 +104,16 @@ err_htc_attach: | |||
| 104 | 104 | ||
| 105 | static int ath10k_htt_verify_version(struct ath10k_htt *htt) | 105 | static int ath10k_htt_verify_version(struct ath10k_htt *htt) |
| 106 | { | 106 | { |
| 107 | ath10k_dbg(ATH10K_DBG_HTT, | 107 | ath10k_info("htt target version %d.%d\n", |
| 108 | "htt target version %d.%d; host version %d.%d\n", | 108 | htt->target_version_major, htt->target_version_minor); |
| 109 | htt->target_version_major, | 109 | |
| 110 | htt->target_version_minor, | 110 | if (htt->target_version_major != 2 && |
| 111 | HTT_CURRENT_VERSION_MAJOR, | 111 | htt->target_version_major != 3) { |
| 112 | HTT_CURRENT_VERSION_MINOR); | 112 | ath10k_err("unsupported htt major version %d. supported versions are 2 and 3\n", |
| 113 | 113 | htt->target_version_major); | |
| 114 | if (htt->target_version_major != HTT_CURRENT_VERSION_MAJOR) { | ||
| 115 | ath10k_err("htt major versions are incompatible!\n"); | ||
| 116 | return -ENOTSUPP; | 114 | return -ENOTSUPP; |
| 117 | } | 115 | } |
| 118 | 116 | ||
| 119 | if (htt->target_version_minor != HTT_CURRENT_VERSION_MINOR) | ||
| 120 | ath10k_warn("htt minor version differ but still compatible\n"); | ||
| 121 | |||
| 122 | return 0; | 117 | return 0; |
| 123 | } | 118 | } |
| 124 | 119 | ||
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 318be4629cde..1a337e93b7e9 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h | |||
| @@ -19,13 +19,11 @@ | |||
| 19 | #define _HTT_H_ | 19 | #define _HTT_H_ |
| 20 | 20 | ||
| 21 | #include <linux/bug.h> | 21 | #include <linux/bug.h> |
| 22 | #include <linux/interrupt.h> | ||
| 22 | 23 | ||
| 23 | #include "htc.h" | 24 | #include "htc.h" |
| 24 | #include "rx_desc.h" | 25 | #include "rx_desc.h" |
| 25 | 26 | ||
| 26 | #define HTT_CURRENT_VERSION_MAJOR 2 | ||
| 27 | #define HTT_CURRENT_VERSION_MINOR 1 | ||
| 28 | |||
| 29 | enum htt_dbg_stats_type { | 27 | enum htt_dbg_stats_type { |
| 30 | HTT_DBG_STATS_WAL_PDEV_TXRX = 1 << 0, | 28 | HTT_DBG_STATS_WAL_PDEV_TXRX = 1 << 0, |
| 31 | HTT_DBG_STATS_RX_REORDER = 1 << 1, | 29 | HTT_DBG_STATS_RX_REORDER = 1 << 1, |
| @@ -45,6 +43,9 @@ enum htt_h2t_msg_type { /* host-to-target */ | |||
| 45 | HTT_H2T_MSG_TYPE_SYNC = 4, | 43 | HTT_H2T_MSG_TYPE_SYNC = 4, |
| 46 | HTT_H2T_MSG_TYPE_AGGR_CFG = 5, | 44 | HTT_H2T_MSG_TYPE_AGGR_CFG = 5, |
| 47 | HTT_H2T_MSG_TYPE_FRAG_DESC_BANK_CFG = 6, | 45 | HTT_H2T_MSG_TYPE_FRAG_DESC_BANK_CFG = 6, |
| 46 | |||
| 47 | /* This command is used for sending management frames in HTT < 3.0. | ||
| 48 | * HTT >= 3.0 uses TX_FRM for everything. */ | ||
| 48 | HTT_H2T_MSG_TYPE_MGMT_TX = 7, | 49 | HTT_H2T_MSG_TYPE_MGMT_TX = 7, |
| 49 | 50 | ||
| 50 | HTT_H2T_NUM_MSGS /* keep this last */ | 51 | HTT_H2T_NUM_MSGS /* keep this last */ |
| @@ -1268,6 +1269,7 @@ struct ath10k_htt { | |||
| 1268 | /* set if host-fw communication goes haywire | 1269 | /* set if host-fw communication goes haywire |
| 1269 | * used to avoid further failures */ | 1270 | * used to avoid further failures */ |
| 1270 | bool rx_confused; | 1271 | bool rx_confused; |
| 1272 | struct tasklet_struct rx_replenish_task; | ||
| 1271 | }; | 1273 | }; |
| 1272 | 1274 | ||
| 1273 | #define RX_HTT_HDR_STATUS_LEN 64 | 1275 | #define RX_HTT_HDR_STATUS_LEN 64 |
| @@ -1308,6 +1310,10 @@ struct htt_rx_desc { | |||
| 1308 | #define HTT_RX_BUF_SIZE 1920 | 1310 | #define HTT_RX_BUF_SIZE 1920 |
| 1309 | #define HTT_RX_MSDU_SIZE (HTT_RX_BUF_SIZE - (int)sizeof(struct htt_rx_desc)) | 1311 | #define HTT_RX_MSDU_SIZE (HTT_RX_BUF_SIZE - (int)sizeof(struct htt_rx_desc)) |
| 1310 | 1312 | ||
| 1313 | /* Refill a bunch of RX buffers for each refill round so that FW/HW can handle | ||
| 1314 | * aggregated traffic more nicely. */ | ||
| 1315 | #define ATH10K_HTT_MAX_NUM_REFILL 16 | ||
| 1316 | |||
| 1311 | /* | 1317 | /* |
| 1312 | * DMA_MAP expects the buffer to be an integral number of cache lines. | 1318 | * DMA_MAP expects the buffer to be an integral number of cache lines. |
| 1313 | * Rather than checking the actual cache line size, this code makes a | 1319 | * Rather than checking the actual cache line size, this code makes a |
| @@ -1327,6 +1333,7 @@ void ath10k_htt_rx_detach(struct ath10k_htt *htt); | |||
| 1327 | void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb); | 1333 | void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb); |
| 1328 | void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb); | 1334 | void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb); |
| 1329 | int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt); | 1335 | int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt); |
| 1336 | int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie); | ||
| 1330 | int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt); | 1337 | int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt); |
| 1331 | 1338 | ||
| 1332 | void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt); | 1339 | void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt); |
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index e784c40b904b..90d4f74c28d7 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include "htt.h" | 20 | #include "htt.h" |
| 21 | #include "txrx.h" | 21 | #include "txrx.h" |
| 22 | #include "debug.h" | 22 | #include "debug.h" |
| 23 | #include "trace.h" | ||
| 23 | 24 | ||
| 24 | #include <linux/log2.h> | 25 | #include <linux/log2.h> |
| 25 | 26 | ||
| @@ -40,6 +41,10 @@ | |||
| 40 | /* when under memory pressure rx ring refill may fail and needs a retry */ | 41 | /* when under memory pressure rx ring refill may fail and needs a retry */ |
| 41 | #define HTT_RX_RING_REFILL_RETRY_MS 50 | 42 | #define HTT_RX_RING_REFILL_RETRY_MS 50 |
| 42 | 43 | ||
| 44 | |||
| 45 | static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb); | ||
| 46 | |||
| 47 | |||
| 43 | static int ath10k_htt_rx_ring_size(struct ath10k_htt *htt) | 48 | static int ath10k_htt_rx_ring_size(struct ath10k_htt *htt) |
| 44 | { | 49 | { |
| 45 | int size; | 50 | int size; |
| @@ -177,10 +182,27 @@ static int ath10k_htt_rx_ring_fill_n(struct ath10k_htt *htt, int num) | |||
| 177 | 182 | ||
| 178 | static void ath10k_htt_rx_msdu_buff_replenish(struct ath10k_htt *htt) | 183 | static void ath10k_htt_rx_msdu_buff_replenish(struct ath10k_htt *htt) |
| 179 | { | 184 | { |
| 180 | int ret, num_to_fill; | 185 | int ret, num_deficit, num_to_fill; |
| 181 | 186 | ||
| 187 | /* Refilling the whole RX ring buffer proves to be a bad idea. The | ||
| 188 | * reason is RX may take up significant amount of CPU cycles and starve | ||
| 189 | * other tasks, e.g. TX on an ethernet device while acting as a bridge | ||
| 190 | * with ath10k wlan interface. This ended up with very poor performance | ||
| 191 | * once CPU the host system was overwhelmed with RX on ath10k. | ||
| 192 | * | ||
| 193 | * By limiting the number of refills the replenishing occurs | ||
| 194 | * progressively. This in turns makes use of the fact tasklets are | ||
| 195 | * processed in FIFO order. This means actual RX processing can starve | ||
| 196 | * out refilling. If there's not enough buffers on RX ring FW will not | ||
| 197 | * report RX until it is refilled with enough buffers. This | ||
| 198 | * automatically balances load wrt to CPU power. | ||
| 199 | * | ||
| 200 | * This probably comes at a cost of lower maximum throughput but | ||
| 201 | * improves the avarage and stability. */ | ||
| 182 | spin_lock_bh(&htt->rx_ring.lock); | 202 | spin_lock_bh(&htt->rx_ring.lock); |
| 183 | num_to_fill = htt->rx_ring.fill_level - htt->rx_ring.fill_cnt; | 203 | num_deficit = htt->rx_ring.fill_level - htt->rx_ring.fill_cnt; |
| 204 | num_to_fill = min(ATH10K_HTT_MAX_NUM_REFILL, num_deficit); | ||
| 205 | num_deficit -= num_to_fill; | ||
| 184 | ret = ath10k_htt_rx_ring_fill_n(htt, num_to_fill); | 206 | ret = ath10k_htt_rx_ring_fill_n(htt, num_to_fill); |
| 185 | if (ret == -ENOMEM) { | 207 | if (ret == -ENOMEM) { |
| 186 | /* | 208 | /* |
| @@ -191,6 +213,8 @@ static void ath10k_htt_rx_msdu_buff_replenish(struct ath10k_htt *htt) | |||
| 191 | */ | 213 | */ |
| 192 | mod_timer(&htt->rx_ring.refill_retry_timer, jiffies + | 214 | mod_timer(&htt->rx_ring.refill_retry_timer, jiffies + |
| 193 | msecs_to_jiffies(HTT_RX_RING_REFILL_RETRY_MS)); | 215 | msecs_to_jiffies(HTT_RX_RING_REFILL_RETRY_MS)); |
| 216 | } else if (num_deficit > 0) { | ||
| 217 | tasklet_schedule(&htt->rx_replenish_task); | ||
| 194 | } | 218 | } |
| 195 | spin_unlock_bh(&htt->rx_ring.lock); | 219 | spin_unlock_bh(&htt->rx_ring.lock); |
| 196 | } | 220 | } |
| @@ -212,6 +236,7 @@ void ath10k_htt_rx_detach(struct ath10k_htt *htt) | |||
| 212 | int sw_rd_idx = htt->rx_ring.sw_rd_idx.msdu_payld; | 236 | int sw_rd_idx = htt->rx_ring.sw_rd_idx.msdu_payld; |
| 213 | 237 | ||
| 214 | del_timer_sync(&htt->rx_ring.refill_retry_timer); | 238 | del_timer_sync(&htt->rx_ring.refill_retry_timer); |
| 239 | tasklet_kill(&htt->rx_replenish_task); | ||
| 215 | 240 | ||
| 216 | while (sw_rd_idx != __le32_to_cpu(*(htt->rx_ring.alloc_idx.vaddr))) { | 241 | while (sw_rd_idx != __le32_to_cpu(*(htt->rx_ring.alloc_idx.vaddr))) { |
| 217 | struct sk_buff *skb = | 242 | struct sk_buff *skb = |
| @@ -441,6 +466,12 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, | |||
| 441 | return msdu_chaining; | 466 | return msdu_chaining; |
| 442 | } | 467 | } |
| 443 | 468 | ||
| 469 | static void ath10k_htt_rx_replenish_task(unsigned long ptr) | ||
| 470 | { | ||
| 471 | struct ath10k_htt *htt = (struct ath10k_htt *)ptr; | ||
| 472 | ath10k_htt_rx_msdu_buff_replenish(htt); | ||
| 473 | } | ||
| 474 | |||
| 444 | int ath10k_htt_rx_attach(struct ath10k_htt *htt) | 475 | int ath10k_htt_rx_attach(struct ath10k_htt *htt) |
| 445 | { | 476 | { |
| 446 | dma_addr_t paddr; | 477 | dma_addr_t paddr; |
| @@ -501,7 +532,10 @@ int ath10k_htt_rx_attach(struct ath10k_htt *htt) | |||
| 501 | if (__ath10k_htt_rx_ring_fill_n(htt, htt->rx_ring.fill_level)) | 532 | if (__ath10k_htt_rx_ring_fill_n(htt, htt->rx_ring.fill_level)) |
| 502 | goto err_fill_ring; | 533 | goto err_fill_ring; |
| 503 | 534 | ||
| 504 | ath10k_dbg(ATH10K_DBG_HTT, "HTT RX ring size: %d, fill_level: %d\n", | 535 | tasklet_init(&htt->rx_replenish_task, ath10k_htt_rx_replenish_task, |
| 536 | (unsigned long)htt); | ||
| 537 | |||
| 538 | ath10k_dbg(ATH10K_DBG_BOOT, "htt rx ring size %d fill_level %d\n", | ||
| 505 | htt->rx_ring.size, htt->rx_ring.fill_level); | 539 | htt->rx_ring.size, htt->rx_ring.fill_level); |
| 506 | return 0; | 540 | return 0; |
| 507 | 541 | ||
| @@ -590,134 +624,144 @@ static bool ath10k_htt_rx_hdr_is_amsdu(struct ieee80211_hdr *hdr) | |||
| 590 | return false; | 624 | return false; |
| 591 | } | 625 | } |
| 592 | 626 | ||
| 593 | static int ath10k_htt_rx_amsdu(struct ath10k_htt *htt, | 627 | struct rfc1042_hdr { |
| 594 | struct htt_rx_info *info) | 628 | u8 llc_dsap; |
| 629 | u8 llc_ssap; | ||
| 630 | u8 llc_ctrl; | ||
| 631 | u8 snap_oui[3]; | ||
| 632 | __be16 snap_type; | ||
| 633 | } __packed; | ||
| 634 | |||
| 635 | struct amsdu_subframe_hdr { | ||
| 636 | u8 dst[ETH_ALEN]; | ||
| 637 | u8 src[ETH_ALEN]; | ||
| 638 | __be16 len; | ||
| 639 | } __packed; | ||
| 640 | |||
| 641 | static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt, | ||
| 642 | struct htt_rx_info *info) | ||
| 595 | { | 643 | { |
| 596 | struct htt_rx_desc *rxd; | 644 | struct htt_rx_desc *rxd; |
| 597 | struct sk_buff *amsdu; | ||
| 598 | struct sk_buff *first; | 645 | struct sk_buff *first; |
| 599 | struct ieee80211_hdr *hdr; | ||
| 600 | struct sk_buff *skb = info->skb; | 646 | struct sk_buff *skb = info->skb; |
| 601 | enum rx_msdu_decap_format fmt; | 647 | enum rx_msdu_decap_format fmt; |
| 602 | enum htt_rx_mpdu_encrypt_type enctype; | 648 | enum htt_rx_mpdu_encrypt_type enctype; |
| 649 | struct ieee80211_hdr *hdr; | ||
| 650 | u8 hdr_buf[64], addr[ETH_ALEN], *qos; | ||
| 603 | unsigned int hdr_len; | 651 | unsigned int hdr_len; |
| 604 | int crypto_len; | ||
| 605 | 652 | ||
| 606 | rxd = (void *)skb->data - sizeof(*rxd); | 653 | rxd = (void *)skb->data - sizeof(*rxd); |
| 607 | fmt = MS(__le32_to_cpu(rxd->msdu_start.info1), | ||
| 608 | RX_MSDU_START_INFO1_DECAP_FORMAT); | ||
| 609 | enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0), | 654 | enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0), |
| 610 | RX_MPDU_START_INFO0_ENCRYPT_TYPE); | 655 | RX_MPDU_START_INFO0_ENCRYPT_TYPE); |
| 611 | 656 | ||
| 612 | /* FIXME: No idea what assumptions are safe here. Need logs */ | 657 | hdr = (struct ieee80211_hdr *)rxd->rx_hdr_status; |
| 613 | if ((fmt == RX_MSDU_DECAP_RAW && skb->next) || | 658 | hdr_len = ieee80211_hdrlen(hdr->frame_control); |
| 614 | (fmt == RX_MSDU_DECAP_8023_SNAP_LLC)) { | 659 | memcpy(hdr_buf, hdr, hdr_len); |
| 615 | ath10k_htt_rx_free_msdu_chain(skb->next); | 660 | hdr = (struct ieee80211_hdr *)hdr_buf; |
| 616 | skb->next = NULL; | ||
| 617 | return -ENOTSUPP; | ||
| 618 | } | ||
| 619 | 661 | ||
| 620 | /* A-MSDU max is a little less than 8K */ | 662 | /* FIXME: Hopefully this is a temporary measure. |
| 621 | amsdu = dev_alloc_skb(8*1024); | 663 | * |
| 622 | if (!amsdu) { | 664 | * Reporting individual A-MSDU subframes means each reported frame |
| 623 | ath10k_warn("A-MSDU allocation failed\n"); | 665 | * shares the same sequence number. |
| 624 | ath10k_htt_rx_free_msdu_chain(skb->next); | 666 | * |
| 625 | skb->next = NULL; | 667 | * mac80211 drops frames it recognizes as duplicates, i.e. |
| 626 | return -ENOMEM; | 668 | * retransmission flag is set and sequence number matches sequence |
| 627 | } | 669 | * number from a previous frame (as per IEEE 802.11-2012: 9.3.2.10 |
| 628 | 670 | * "Duplicate detection and recovery") | |
| 629 | if (fmt >= RX_MSDU_DECAP_NATIVE_WIFI) { | 671 | * |
| 630 | int hdrlen; | 672 | * To avoid frames being dropped clear retransmission flag for all |
| 631 | 673 | * received A-MSDUs. | |
| 632 | hdr = (void *)rxd->rx_hdr_status; | 674 | * |
| 633 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 675 | * Worst case: actual duplicate frames will be reported but this should |
| 634 | memcpy(skb_put(amsdu, hdrlen), hdr, hdrlen); | 676 | * still be handled gracefully by other OSI/ISO layers. */ |
| 635 | } | 677 | hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_RETRY); |
| 636 | 678 | ||
| 637 | first = skb; | 679 | first = skb; |
| 638 | while (skb) { | 680 | while (skb) { |
| 639 | void *decap_hdr; | 681 | void *decap_hdr; |
| 640 | int decap_len = 0; | 682 | int len; |
| 641 | 683 | ||
| 642 | rxd = (void *)skb->data - sizeof(*rxd); | 684 | rxd = (void *)skb->data - sizeof(*rxd); |
| 643 | fmt = MS(__le32_to_cpu(rxd->msdu_start.info1), | 685 | fmt = MS(__le32_to_cpu(rxd->msdu_start.info1), |
| 644 | RX_MSDU_START_INFO1_DECAP_FORMAT); | 686 | RX_MSDU_START_INFO1_DECAP_FORMAT); |
| 645 | decap_hdr = (void *)rxd->rx_hdr_status; | 687 | decap_hdr = (void *)rxd->rx_hdr_status; |
| 646 | 688 | ||
| 647 | if (skb == first) { | 689 | skb->ip_summed = ath10k_htt_rx_get_csum_state(skb); |
| 648 | /* We receive linked A-MSDU subframe skbuffs. The | ||
| 649 | * first one contains the original 802.11 header (and | ||
| 650 | * possible crypto param) in the RX descriptor. The | ||
| 651 | * A-MSDU subframe header follows that. Each part is | ||
| 652 | * aligned to 4 byte boundary. */ | ||
| 653 | |||
| 654 | hdr = (void *)amsdu->data; | ||
| 655 | hdr_len = ieee80211_hdrlen(hdr->frame_control); | ||
| 656 | crypto_len = ath10k_htt_rx_crypto_param_len(enctype); | ||
| 657 | |||
| 658 | decap_hdr += roundup(hdr_len, 4); | ||
| 659 | decap_hdr += roundup(crypto_len, 4); | ||
| 660 | } | ||
| 661 | 690 | ||
| 662 | if (fmt == RX_MSDU_DECAP_ETHERNET2_DIX) { | 691 | /* First frame in an A-MSDU chain has more decapped data. */ |
| 663 | /* Ethernet2 decap inserts ethernet header in place of | 692 | if (skb == first) { |
| 664 | * A-MSDU subframe header. */ | 693 | len = round_up(ieee80211_hdrlen(hdr->frame_control), 4); |
| 665 | skb_pull(skb, 6 + 6 + 2); | 694 | len += round_up(ath10k_htt_rx_crypto_param_len(enctype), |
| 666 | 695 | 4); | |
| 667 | /* A-MSDU subframe header length */ | 696 | decap_hdr += len; |
| 668 | decap_len += 6 + 6 + 2; | ||
| 669 | |||
| 670 | /* Ethernet2 decap also strips the LLC/SNAP so we need | ||
| 671 | * to re-insert it. The LLC/SNAP follows A-MSDU | ||
| 672 | * subframe header. */ | ||
| 673 | /* FIXME: Not all LLCs are 8 bytes long */ | ||
| 674 | decap_len += 8; | ||
| 675 | |||
| 676 | memcpy(skb_put(amsdu, decap_len), decap_hdr, decap_len); | ||
| 677 | } | 697 | } |
| 678 | 698 | ||
| 679 | if (fmt == RX_MSDU_DECAP_NATIVE_WIFI) { | 699 | switch (fmt) { |
| 680 | /* Native Wifi decap inserts regular 802.11 header | 700 | case RX_MSDU_DECAP_RAW: |
| 681 | * in place of A-MSDU subframe header. */ | 701 | /* remove trailing FCS */ |
| 702 | skb_trim(skb, skb->len - FCS_LEN); | ||
| 703 | break; | ||
| 704 | case RX_MSDU_DECAP_NATIVE_WIFI: | ||
| 705 | /* pull decapped header and copy DA */ | ||
| 682 | hdr = (struct ieee80211_hdr *)skb->data; | 706 | hdr = (struct ieee80211_hdr *)skb->data; |
| 683 | skb_pull(skb, ieee80211_hdrlen(hdr->frame_control)); | 707 | hdr_len = ieee80211_hdrlen(hdr->frame_control); |
| 708 | memcpy(addr, ieee80211_get_DA(hdr), ETH_ALEN); | ||
| 709 | skb_pull(skb, hdr_len); | ||
| 684 | 710 | ||
| 685 | /* A-MSDU subframe header length */ | 711 | /* push original 802.11 header */ |
| 686 | decap_len += 6 + 6 + 2; | 712 | hdr = (struct ieee80211_hdr *)hdr_buf; |
| 713 | hdr_len = ieee80211_hdrlen(hdr->frame_control); | ||
| 714 | memcpy(skb_push(skb, hdr_len), hdr, hdr_len); | ||
| 687 | 715 | ||
| 688 | memcpy(skb_put(amsdu, decap_len), decap_hdr, decap_len); | 716 | /* original A-MSDU header has the bit set but we're |
| 689 | } | 717 | * not including A-MSDU subframe header */ |
| 718 | hdr = (struct ieee80211_hdr *)skb->data; | ||
| 719 | qos = ieee80211_get_qos_ctl(hdr); | ||
| 720 | qos[0] &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT; | ||
| 690 | 721 | ||
| 691 | if (fmt == RX_MSDU_DECAP_RAW) | 722 | /* original 802.11 header has a different DA */ |
| 692 | skb_trim(skb, skb->len - 4); /* remove FCS */ | 723 | memcpy(ieee80211_get_DA(hdr), addr, ETH_ALEN); |
| 724 | break; | ||
| 725 | case RX_MSDU_DECAP_ETHERNET2_DIX: | ||
| 726 | /* strip ethernet header and insert decapped 802.11 | ||
| 727 | * header, amsdu subframe header and rfc1042 header */ | ||
| 693 | 728 | ||
| 694 | memcpy(skb_put(amsdu, skb->len), skb->data, skb->len); | 729 | len = 0; |
| 730 | len += sizeof(struct rfc1042_hdr); | ||
| 731 | len += sizeof(struct amsdu_subframe_hdr); | ||
| 695 | 732 | ||
| 696 | /* A-MSDU subframes are padded to 4bytes | 733 | skb_pull(skb, sizeof(struct ethhdr)); |
| 697 | * but relative to first subframe, not the whole MPDU */ | 734 | memcpy(skb_push(skb, len), decap_hdr, len); |
| 698 | if (skb->next && ((decap_len + skb->len) & 3)) { | 735 | memcpy(skb_push(skb, hdr_len), hdr, hdr_len); |
| 699 | int padlen = 4 - ((decap_len + skb->len) & 3); | 736 | break; |
| 700 | memset(skb_put(amsdu, padlen), 0, padlen); | 737 | case RX_MSDU_DECAP_8023_SNAP_LLC: |
| 738 | /* insert decapped 802.11 header making a singly | ||
| 739 | * A-MSDU */ | ||
| 740 | memcpy(skb_push(skb, hdr_len), hdr, hdr_len); | ||
| 741 | break; | ||
| 701 | } | 742 | } |
| 702 | 743 | ||
| 744 | info->skb = skb; | ||
| 745 | info->encrypt_type = enctype; | ||
| 703 | skb = skb->next; | 746 | skb = skb->next; |
| 704 | } | 747 | info->skb->next = NULL; |
| 705 | 748 | ||
| 706 | info->skb = amsdu; | 749 | ath10k_process_rx(htt->ar, info); |
| 707 | info->encrypt_type = enctype; | 750 | } |
| 708 | |||
| 709 | ath10k_htt_rx_free_msdu_chain(first); | ||
| 710 | 751 | ||
| 711 | return 0; | 752 | /* FIXME: It might be nice to re-assemble the A-MSDU when there's a |
| 753 | * monitor interface active for sniffing purposes. */ | ||
| 712 | } | 754 | } |
| 713 | 755 | ||
| 714 | static int ath10k_htt_rx_msdu(struct ath10k_htt *htt, struct htt_rx_info *info) | 756 | static void ath10k_htt_rx_msdu(struct ath10k_htt *htt, struct htt_rx_info *info) |
| 715 | { | 757 | { |
| 716 | struct sk_buff *skb = info->skb; | 758 | struct sk_buff *skb = info->skb; |
| 717 | struct htt_rx_desc *rxd; | 759 | struct htt_rx_desc *rxd; |
| 718 | struct ieee80211_hdr *hdr; | 760 | struct ieee80211_hdr *hdr; |
| 719 | enum rx_msdu_decap_format fmt; | 761 | enum rx_msdu_decap_format fmt; |
| 720 | enum htt_rx_mpdu_encrypt_type enctype; | 762 | enum htt_rx_mpdu_encrypt_type enctype; |
| 763 | int hdr_len; | ||
| 764 | void *rfc1042; | ||
| 721 | 765 | ||
| 722 | /* This shouldn't happen. If it does than it may be a FW bug. */ | 766 | /* This shouldn't happen. If it does than it may be a FW bug. */ |
| 723 | if (skb->next) { | 767 | if (skb->next) { |
| @@ -731,49 +775,53 @@ static int ath10k_htt_rx_msdu(struct ath10k_htt *htt, struct htt_rx_info *info) | |||
| 731 | RX_MSDU_START_INFO1_DECAP_FORMAT); | 775 | RX_MSDU_START_INFO1_DECAP_FORMAT); |
| 732 | enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0), | 776 | enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0), |
| 733 | RX_MPDU_START_INFO0_ENCRYPT_TYPE); | 777 | RX_MPDU_START_INFO0_ENCRYPT_TYPE); |
| 734 | hdr = (void *)skb->data - RX_HTT_HDR_STATUS_LEN; | 778 | hdr = (struct ieee80211_hdr *)rxd->rx_hdr_status; |
| 779 | hdr_len = ieee80211_hdrlen(hdr->frame_control); | ||
| 780 | |||
| 781 | skb->ip_summed = ath10k_htt_rx_get_csum_state(skb); | ||
| 735 | 782 | ||
| 736 | switch (fmt) { | 783 | switch (fmt) { |
| 737 | case RX_MSDU_DECAP_RAW: | 784 | case RX_MSDU_DECAP_RAW: |
| 738 | /* remove trailing FCS */ | 785 | /* remove trailing FCS */ |
| 739 | skb_trim(skb, skb->len - 4); | 786 | skb_trim(skb, skb->len - FCS_LEN); |
| 740 | break; | 787 | break; |
| 741 | case RX_MSDU_DECAP_NATIVE_WIFI: | 788 | case RX_MSDU_DECAP_NATIVE_WIFI: |
| 742 | /* nothing to do here */ | 789 | /* Pull decapped header */ |
| 790 | hdr = (struct ieee80211_hdr *)skb->data; | ||
| 791 | hdr_len = ieee80211_hdrlen(hdr->frame_control); | ||
| 792 | skb_pull(skb, hdr_len); | ||
| 793 | |||
| 794 | /* Push original header */ | ||
| 795 | hdr = (struct ieee80211_hdr *)rxd->rx_hdr_status; | ||
| 796 | hdr_len = ieee80211_hdrlen(hdr->frame_control); | ||
| 797 | memcpy(skb_push(skb, hdr_len), hdr, hdr_len); | ||
| 743 | break; | 798 | break; |
| 744 | case RX_MSDU_DECAP_ETHERNET2_DIX: | 799 | case RX_MSDU_DECAP_ETHERNET2_DIX: |
| 745 | /* macaddr[6] + macaddr[6] + ethertype[2] */ | 800 | /* strip ethernet header and insert decapped 802.11 header and |
| 746 | skb_pull(skb, 6 + 6 + 2); | 801 | * rfc1042 header */ |
| 747 | break; | ||
| 748 | case RX_MSDU_DECAP_8023_SNAP_LLC: | ||
| 749 | /* macaddr[6] + macaddr[6] + len[2] */ | ||
| 750 | /* we don't need this for non-A-MSDU */ | ||
| 751 | skb_pull(skb, 6 + 6 + 2); | ||
| 752 | break; | ||
| 753 | } | ||
| 754 | 802 | ||
| 755 | if (fmt == RX_MSDU_DECAP_ETHERNET2_DIX) { | 803 | rfc1042 = hdr; |
| 756 | void *llc; | 804 | rfc1042 += roundup(hdr_len, 4); |
| 757 | int llclen; | 805 | rfc1042 += roundup(ath10k_htt_rx_crypto_param_len(enctype), 4); |
| 758 | 806 | ||
| 759 | llclen = 8; | 807 | skb_pull(skb, sizeof(struct ethhdr)); |
| 760 | llc = hdr; | 808 | memcpy(skb_push(skb, sizeof(struct rfc1042_hdr)), |
| 761 | llc += roundup(ieee80211_hdrlen(hdr->frame_control), 4); | 809 | rfc1042, sizeof(struct rfc1042_hdr)); |
| 762 | llc += roundup(ath10k_htt_rx_crypto_param_len(enctype), 4); | 810 | memcpy(skb_push(skb, hdr_len), hdr, hdr_len); |
| 763 | 811 | break; | |
| 764 | skb_push(skb, llclen); | 812 | case RX_MSDU_DECAP_8023_SNAP_LLC: |
| 765 | memcpy(skb->data, llc, llclen); | 813 | /* remove A-MSDU subframe header and insert |
| 766 | } | 814 | * decapped 802.11 header. rfc1042 header is already there */ |
| 767 | 815 | ||
| 768 | if (fmt >= RX_MSDU_DECAP_ETHERNET2_DIX) { | 816 | skb_pull(skb, sizeof(struct amsdu_subframe_hdr)); |
| 769 | int len = ieee80211_hdrlen(hdr->frame_control); | 817 | memcpy(skb_push(skb, hdr_len), hdr, hdr_len); |
| 770 | skb_push(skb, len); | 818 | break; |
| 771 | memcpy(skb->data, hdr, len); | ||
| 772 | } | 819 | } |
| 773 | 820 | ||
| 774 | info->skb = skb; | 821 | info->skb = skb; |
| 775 | info->encrypt_type = enctype; | 822 | info->encrypt_type = enctype; |
| 776 | return 0; | 823 | |
| 824 | ath10k_process_rx(htt->ar, info); | ||
| 777 | } | 825 | } |
| 778 | 826 | ||
| 779 | static bool ath10k_htt_rx_has_decrypt_err(struct sk_buff *skb) | 827 | static bool ath10k_htt_rx_has_decrypt_err(struct sk_buff *skb) |
| @@ -845,8 +893,6 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, | |||
| 845 | int fw_desc_len; | 893 | int fw_desc_len; |
| 846 | u8 *fw_desc; | 894 | u8 *fw_desc; |
| 847 | int i, j; | 895 | int i, j; |
| 848 | int ret; | ||
| 849 | int ip_summed; | ||
| 850 | 896 | ||
| 851 | memset(&info, 0, sizeof(info)); | 897 | memset(&info, 0, sizeof(info)); |
| 852 | 898 | ||
| @@ -921,11 +967,6 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, | |||
| 921 | continue; | 967 | continue; |
| 922 | } | 968 | } |
| 923 | 969 | ||
| 924 | /* The skb is not yet processed and it may be | ||
| 925 | * reallocated. Since the offload is in the original | ||
| 926 | * skb extract the checksum now and assign it later */ | ||
| 927 | ip_summed = ath10k_htt_rx_get_csum_state(msdu_head); | ||
| 928 | |||
| 929 | info.skb = msdu_head; | 970 | info.skb = msdu_head; |
| 930 | info.fcs_err = ath10k_htt_rx_has_fcs_err(msdu_head); | 971 | info.fcs_err = ath10k_htt_rx_has_fcs_err(msdu_head); |
| 931 | info.signal = ATH10K_DEFAULT_NOISE_FLOOR; | 972 | info.signal = ATH10K_DEFAULT_NOISE_FLOOR; |
| @@ -938,28 +979,13 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, | |||
| 938 | hdr = ath10k_htt_rx_skb_get_hdr(msdu_head); | 979 | hdr = ath10k_htt_rx_skb_get_hdr(msdu_head); |
| 939 | 980 | ||
| 940 | if (ath10k_htt_rx_hdr_is_amsdu(hdr)) | 981 | if (ath10k_htt_rx_hdr_is_amsdu(hdr)) |
| 941 | ret = ath10k_htt_rx_amsdu(htt, &info); | 982 | ath10k_htt_rx_amsdu(htt, &info); |
| 942 | else | 983 | else |
| 943 | ret = ath10k_htt_rx_msdu(htt, &info); | 984 | ath10k_htt_rx_msdu(htt, &info); |
| 944 | |||
| 945 | if (ret && !info.fcs_err) { | ||
| 946 | ath10k_warn("error processing msdus %d\n", ret); | ||
| 947 | dev_kfree_skb_any(info.skb); | ||
| 948 | continue; | ||
| 949 | } | ||
| 950 | |||
| 951 | if (ath10k_htt_rx_hdr_is_amsdu((void *)info.skb->data)) | ||
| 952 | ath10k_dbg(ATH10K_DBG_HTT, "htt mpdu is amsdu\n"); | ||
| 953 | |||
| 954 | info.skb->ip_summed = ip_summed; | ||
| 955 | |||
| 956 | ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt mpdu: ", | ||
| 957 | info.skb->data, info.skb->len); | ||
| 958 | ath10k_process_rx(htt->ar, &info); | ||
| 959 | } | 985 | } |
| 960 | } | 986 | } |
| 961 | 987 | ||
| 962 | ath10k_htt_rx_msdu_buff_replenish(htt); | 988 | tasklet_schedule(&htt->rx_replenish_task); |
| 963 | } | 989 | } |
| 964 | 990 | ||
| 965 | static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, | 991 | static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, |
| @@ -1131,7 +1157,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) | |||
| 1131 | break; | 1157 | break; |
| 1132 | } | 1158 | } |
| 1133 | 1159 | ||
| 1134 | ath10k_txrx_tx_completed(htt, &tx_done); | 1160 | ath10k_txrx_tx_unref(htt, &tx_done); |
| 1135 | break; | 1161 | break; |
| 1136 | } | 1162 | } |
| 1137 | case HTT_T2H_MSG_TYPE_TX_COMPL_IND: { | 1163 | case HTT_T2H_MSG_TYPE_TX_COMPL_IND: { |
| @@ -1165,7 +1191,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) | |||
| 1165 | for (i = 0; i < resp->data_tx_completion.num_msdus; i++) { | 1191 | for (i = 0; i < resp->data_tx_completion.num_msdus; i++) { |
| 1166 | msdu_id = resp->data_tx_completion.msdus[i]; | 1192 | msdu_id = resp->data_tx_completion.msdus[i]; |
| 1167 | tx_done.msdu_id = __le16_to_cpu(msdu_id); | 1193 | tx_done.msdu_id = __le16_to_cpu(msdu_id); |
| 1168 | ath10k_txrx_tx_completed(htt, &tx_done); | 1194 | ath10k_txrx_tx_unref(htt, &tx_done); |
| 1169 | } | 1195 | } |
| 1170 | break; | 1196 | break; |
| 1171 | } | 1197 | } |
| @@ -1190,8 +1216,10 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) | |||
| 1190 | case HTT_T2H_MSG_TYPE_TEST: | 1216 | case HTT_T2H_MSG_TYPE_TEST: |
| 1191 | /* FIX THIS */ | 1217 | /* FIX THIS */ |
| 1192 | break; | 1218 | break; |
| 1193 | case HTT_T2H_MSG_TYPE_TX_INSPECT_IND: | ||
| 1194 | case HTT_T2H_MSG_TYPE_STATS_CONF: | 1219 | case HTT_T2H_MSG_TYPE_STATS_CONF: |
| 1220 | trace_ath10k_htt_stats(skb->data, skb->len); | ||
| 1221 | break; | ||
| 1222 | case HTT_T2H_MSG_TYPE_TX_INSPECT_IND: | ||
| 1195 | case HTT_T2H_MSG_TYPE_RX_ADDBA: | 1223 | case HTT_T2H_MSG_TYPE_RX_ADDBA: |
| 1196 | case HTT_T2H_MSG_TYPE_RX_DELBA: | 1224 | case HTT_T2H_MSG_TYPE_RX_DELBA: |
| 1197 | case HTT_T2H_MSG_TYPE_RX_FLUSH: | 1225 | case HTT_T2H_MSG_TYPE_RX_FLUSH: |
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 656c2546b294..d9335e9d0d04 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c | |||
| @@ -96,7 +96,7 @@ int ath10k_htt_tx_attach(struct ath10k_htt *htt) | |||
| 96 | htt->max_num_pending_tx = ath10k_hif_get_free_queue_number(htt->ar, | 96 | htt->max_num_pending_tx = ath10k_hif_get_free_queue_number(htt->ar, |
| 97 | pipe); | 97 | pipe); |
| 98 | 98 | ||
| 99 | ath10k_dbg(ATH10K_DBG_HTT, "htt tx max num pending tx %d\n", | 99 | ath10k_dbg(ATH10K_DBG_BOOT, "htt tx max num pending tx %d\n", |
| 100 | htt->max_num_pending_tx); | 100 | htt->max_num_pending_tx); |
| 101 | 101 | ||
| 102 | htt->pending_tx = kzalloc(sizeof(*htt->pending_tx) * | 102 | htt->pending_tx = kzalloc(sizeof(*htt->pending_tx) * |
| @@ -117,7 +117,7 @@ int ath10k_htt_tx_attach(struct ath10k_htt *htt) | |||
| 117 | 117 | ||
| 118 | static void ath10k_htt_tx_cleanup_pending(struct ath10k_htt *htt) | 118 | static void ath10k_htt_tx_cleanup_pending(struct ath10k_htt *htt) |
| 119 | { | 119 | { |
| 120 | struct sk_buff *txdesc; | 120 | struct htt_tx_done tx_done = {0}; |
| 121 | int msdu_id; | 121 | int msdu_id; |
| 122 | 122 | ||
| 123 | /* No locks needed. Called after communication with the device has | 123 | /* No locks needed. Called after communication with the device has |
| @@ -127,18 +127,13 @@ static void ath10k_htt_tx_cleanup_pending(struct ath10k_htt *htt) | |||
| 127 | if (!test_bit(msdu_id, htt->used_msdu_ids)) | 127 | if (!test_bit(msdu_id, htt->used_msdu_ids)) |
| 128 | continue; | 128 | continue; |
| 129 | 129 | ||
| 130 | txdesc = htt->pending_tx[msdu_id]; | ||
| 131 | if (!txdesc) | ||
| 132 | continue; | ||
| 133 | |||
| 134 | ath10k_dbg(ATH10K_DBG_HTT, "force cleanup msdu_id %hu\n", | 130 | ath10k_dbg(ATH10K_DBG_HTT, "force cleanup msdu_id %hu\n", |
| 135 | msdu_id); | 131 | msdu_id); |
| 136 | 132 | ||
| 137 | if (ATH10K_SKB_CB(txdesc)->htt.refcount > 0) | 133 | tx_done.discard = 1; |
| 138 | ATH10K_SKB_CB(txdesc)->htt.refcount = 1; | 134 | tx_done.msdu_id = msdu_id; |
| 139 | 135 | ||
| 140 | ATH10K_SKB_CB(txdesc)->htt.discard = true; | 136 | ath10k_txrx_tx_unref(htt, &tx_done); |
| 141 | ath10k_txrx_tx_unref(htt, txdesc); | ||
| 142 | } | 137 | } |
| 143 | } | 138 | } |
| 144 | 139 | ||
| @@ -152,26 +147,7 @@ void ath10k_htt_tx_detach(struct ath10k_htt *htt) | |||
| 152 | 147 | ||
| 153 | void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) | 148 | void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) |
| 154 | { | 149 | { |
| 155 | struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); | 150 | dev_kfree_skb_any(skb); |
| 156 | struct ath10k_htt *htt = &ar->htt; | ||
| 157 | |||
| 158 | if (skb_cb->htt.is_conf) { | ||
| 159 | dev_kfree_skb_any(skb); | ||
| 160 | return; | ||
| 161 | } | ||
| 162 | |||
| 163 | if (skb_cb->is_aborted) { | ||
| 164 | skb_cb->htt.discard = true; | ||
| 165 | |||
| 166 | /* if the skbuff is aborted we need to make sure we'll free up | ||
| 167 | * the tx resources, we can't simply run tx_unref() 2 times | ||
| 168 | * because if htt tx completion came in earlier we'd access | ||
| 169 | * unallocated memory */ | ||
| 170 | if (skb_cb->htt.refcount > 1) | ||
| 171 | skb_cb->htt.refcount = 1; | ||
| 172 | } | ||
| 173 | |||
| 174 | ath10k_txrx_tx_unref(htt, skb); | ||
| 175 | } | 151 | } |
| 176 | 152 | ||
| 177 | int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt) | 153 | int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt) |
| @@ -192,10 +168,48 @@ int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt) | |||
| 192 | cmd = (struct htt_cmd *)skb->data; | 168 | cmd = (struct htt_cmd *)skb->data; |
| 193 | cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_VERSION_REQ; | 169 | cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_VERSION_REQ; |
| 194 | 170 | ||
| 195 | ATH10K_SKB_CB(skb)->htt.is_conf = true; | 171 | ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb); |
| 172 | if (ret) { | ||
| 173 | dev_kfree_skb_any(skb); | ||
| 174 | return ret; | ||
| 175 | } | ||
| 176 | |||
| 177 | return 0; | ||
| 178 | } | ||
| 179 | |||
| 180 | int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie) | ||
| 181 | { | ||
| 182 | struct htt_stats_req *req; | ||
| 183 | struct sk_buff *skb; | ||
| 184 | struct htt_cmd *cmd; | ||
| 185 | int len = 0, ret; | ||
| 186 | |||
| 187 | len += sizeof(cmd->hdr); | ||
| 188 | len += sizeof(cmd->stats_req); | ||
| 189 | |||
| 190 | skb = ath10k_htc_alloc_skb(len); | ||
| 191 | if (!skb) | ||
| 192 | return -ENOMEM; | ||
| 193 | |||
| 194 | skb_put(skb, len); | ||
| 195 | cmd = (struct htt_cmd *)skb->data; | ||
| 196 | cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_STATS_REQ; | ||
| 197 | |||
| 198 | req = &cmd->stats_req; | ||
| 199 | |||
| 200 | memset(req, 0, sizeof(*req)); | ||
| 201 | |||
| 202 | /* currently we support only max 8 bit masks so no need to worry | ||
| 203 | * about endian support */ | ||
| 204 | req->upload_types[0] = mask; | ||
| 205 | req->reset_types[0] = mask; | ||
| 206 | req->stat_type = HTT_STATS_REQ_CFG_STAT_TYPE_INVALID; | ||
| 207 | req->cookie_lsb = cpu_to_le32(cookie & 0xffffffff); | ||
| 208 | req->cookie_msb = cpu_to_le32((cookie & 0xffffffff00000000ULL) >> 32); | ||
| 196 | 209 | ||
| 197 | ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb); | 210 | ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb); |
| 198 | if (ret) { | 211 | if (ret) { |
| 212 | ath10k_warn("failed to send htt type stats request: %d", ret); | ||
| 199 | dev_kfree_skb_any(skb); | 213 | dev_kfree_skb_any(skb); |
| 200 | return ret; | 214 | return ret; |
| 201 | } | 215 | } |
| @@ -279,8 +293,6 @@ int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt) | |||
| 279 | 293 | ||
| 280 | #undef desc_offset | 294 | #undef desc_offset |
| 281 | 295 | ||
| 282 | ATH10K_SKB_CB(skb)->htt.is_conf = true; | ||
| 283 | |||
| 284 | ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb); | 296 | ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb); |
| 285 | if (ret) { | 297 | if (ret) { |
| 286 | dev_kfree_skb_any(skb); | 298 | dev_kfree_skb_any(skb); |
| @@ -293,10 +305,10 @@ int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt) | |||
| 293 | int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) | 305 | int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) |
| 294 | { | 306 | { |
| 295 | struct device *dev = htt->ar->dev; | 307 | struct device *dev = htt->ar->dev; |
| 296 | struct ath10k_skb_cb *skb_cb; | ||
| 297 | struct sk_buff *txdesc = NULL; | 308 | struct sk_buff *txdesc = NULL; |
| 298 | struct htt_cmd *cmd; | 309 | struct htt_cmd *cmd; |
| 299 | u8 vdev_id = ATH10K_SKB_CB(msdu)->htt.vdev_id; | 310 | struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu); |
| 311 | u8 vdev_id = skb_cb->vdev_id; | ||
| 300 | int len = 0; | 312 | int len = 0; |
| 301 | int msdu_id = -1; | 313 | int msdu_id = -1; |
| 302 | int res; | 314 | int res; |
| @@ -304,30 +316,30 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) | |||
| 304 | 316 | ||
| 305 | res = ath10k_htt_tx_inc_pending(htt); | 317 | res = ath10k_htt_tx_inc_pending(htt); |
| 306 | if (res) | 318 | if (res) |
| 307 | return res; | 319 | goto err; |
| 308 | 320 | ||
| 309 | len += sizeof(cmd->hdr); | 321 | len += sizeof(cmd->hdr); |
| 310 | len += sizeof(cmd->mgmt_tx); | 322 | len += sizeof(cmd->mgmt_tx); |
| 311 | 323 | ||
| 312 | txdesc = ath10k_htc_alloc_skb(len); | ||
| 313 | if (!txdesc) { | ||
| 314 | res = -ENOMEM; | ||
| 315 | goto err; | ||
| 316 | } | ||
| 317 | |||
| 318 | spin_lock_bh(&htt->tx_lock); | 324 | spin_lock_bh(&htt->tx_lock); |
| 319 | msdu_id = ath10k_htt_tx_alloc_msdu_id(htt); | 325 | res = ath10k_htt_tx_alloc_msdu_id(htt); |
| 320 | if (msdu_id < 0) { | 326 | if (res < 0) { |
| 321 | spin_unlock_bh(&htt->tx_lock); | 327 | spin_unlock_bh(&htt->tx_lock); |
| 322 | res = msdu_id; | 328 | goto err_tx_dec; |
| 323 | goto err; | ||
| 324 | } | 329 | } |
| 325 | htt->pending_tx[msdu_id] = txdesc; | 330 | msdu_id = res; |
| 331 | htt->pending_tx[msdu_id] = msdu; | ||
| 326 | spin_unlock_bh(&htt->tx_lock); | 332 | spin_unlock_bh(&htt->tx_lock); |
| 327 | 333 | ||
| 334 | txdesc = ath10k_htc_alloc_skb(len); | ||
| 335 | if (!txdesc) { | ||
| 336 | res = -ENOMEM; | ||
| 337 | goto err_free_msdu_id; | ||
| 338 | } | ||
| 339 | |||
| 328 | res = ath10k_skb_map(dev, msdu); | 340 | res = ath10k_skb_map(dev, msdu); |
| 329 | if (res) | 341 | if (res) |
| 330 | goto err; | 342 | goto err_free_txdesc; |
| 331 | 343 | ||
| 332 | skb_put(txdesc, len); | 344 | skb_put(txdesc, len); |
| 333 | cmd = (struct htt_cmd *)txdesc->data; | 345 | cmd = (struct htt_cmd *)txdesc->data; |
| @@ -339,31 +351,27 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) | |||
| 339 | memcpy(cmd->mgmt_tx.hdr, msdu->data, | 351 | memcpy(cmd->mgmt_tx.hdr, msdu->data, |
| 340 | min_t(int, msdu->len, HTT_MGMT_FRM_HDR_DOWNLOAD_LEN)); | 352 | min_t(int, msdu->len, HTT_MGMT_FRM_HDR_DOWNLOAD_LEN)); |
| 341 | 353 | ||
| 342 | /* refcount is decremented by HTC and HTT completions until it reaches | 354 | skb_cb->htt.frag_len = 0; |
| 343 | * zero and is freed */ | 355 | skb_cb->htt.pad_len = 0; |
| 344 | skb_cb = ATH10K_SKB_CB(txdesc); | ||
| 345 | skb_cb->htt.msdu_id = msdu_id; | ||
| 346 | skb_cb->htt.refcount = 2; | ||
| 347 | skb_cb->htt.msdu = msdu; | ||
| 348 | 356 | ||
| 349 | res = ath10k_htc_send(&htt->ar->htc, htt->eid, txdesc); | 357 | res = ath10k_htc_send(&htt->ar->htc, htt->eid, txdesc); |
| 350 | if (res) | 358 | if (res) |
| 351 | goto err; | 359 | goto err_unmap_msdu; |
| 352 | 360 | ||
| 353 | return 0; | 361 | return 0; |
| 354 | 362 | ||
| 355 | err: | 363 | err_unmap_msdu: |
| 356 | ath10k_skb_unmap(dev, msdu); | 364 | ath10k_skb_unmap(dev, msdu); |
| 357 | 365 | err_free_txdesc: | |
| 358 | if (txdesc) | 366 | dev_kfree_skb_any(txdesc); |
| 359 | dev_kfree_skb_any(txdesc); | 367 | err_free_msdu_id: |
| 360 | if (msdu_id >= 0) { | 368 | spin_lock_bh(&htt->tx_lock); |
| 361 | spin_lock_bh(&htt->tx_lock); | 369 | htt->pending_tx[msdu_id] = NULL; |
| 362 | htt->pending_tx[msdu_id] = NULL; | 370 | ath10k_htt_tx_free_msdu_id(htt, msdu_id); |
| 363 | ath10k_htt_tx_free_msdu_id(htt, msdu_id); | 371 | spin_unlock_bh(&htt->tx_lock); |
| 364 | spin_unlock_bh(&htt->tx_lock); | 372 | err_tx_dec: |
| 365 | } | ||
| 366 | ath10k_htt_tx_dec_pending(htt); | 373 | ath10k_htt_tx_dec_pending(htt); |
| 374 | err: | ||
| 367 | return res; | 375 | return res; |
| 368 | } | 376 | } |
| 369 | 377 | ||
| @@ -373,13 +381,12 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) | |||
| 373 | struct htt_cmd *cmd; | 381 | struct htt_cmd *cmd; |
| 374 | struct htt_data_tx_desc_frag *tx_frags; | 382 | struct htt_data_tx_desc_frag *tx_frags; |
| 375 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; | 383 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; |
| 376 | struct ath10k_skb_cb *skb_cb; | 384 | struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu); |
| 377 | struct sk_buff *txdesc = NULL; | 385 | struct sk_buff *txdesc = NULL; |
| 378 | struct sk_buff *txfrag = NULL; | 386 | bool use_frags; |
| 379 | u8 vdev_id = ATH10K_SKB_CB(msdu)->htt.vdev_id; | 387 | u8 vdev_id = ATH10K_SKB_CB(msdu)->vdev_id; |
| 380 | u8 tid; | 388 | u8 tid; |
| 381 | int prefetch_len, desc_len, frag_len; | 389 | int prefetch_len, desc_len; |
| 382 | dma_addr_t frags_paddr; | ||
| 383 | int msdu_id = -1; | 390 | int msdu_id = -1; |
| 384 | int res; | 391 | int res; |
| 385 | u8 flags0; | 392 | u8 flags0; |
| @@ -387,69 +394,82 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) | |||
| 387 | 394 | ||
| 388 | res = ath10k_htt_tx_inc_pending(htt); | 395 | res = ath10k_htt_tx_inc_pending(htt); |
| 389 | if (res) | 396 | if (res) |
| 390 | return res; | 397 | goto err; |
| 398 | |||
| 399 | spin_lock_bh(&htt->tx_lock); | ||
| 400 | res = ath10k_htt_tx_alloc_msdu_id(htt); | ||
| 401 | if (res < 0) { | ||
| 402 | spin_unlock_bh(&htt->tx_lock); | ||
| 403 | goto err_tx_dec; | ||
| 404 | } | ||
| 405 | msdu_id = res; | ||
| 406 | htt->pending_tx[msdu_id] = msdu; | ||
| 407 | spin_unlock_bh(&htt->tx_lock); | ||
| 391 | 408 | ||
| 392 | prefetch_len = min(htt->prefetch_len, msdu->len); | 409 | prefetch_len = min(htt->prefetch_len, msdu->len); |
| 393 | prefetch_len = roundup(prefetch_len, 4); | 410 | prefetch_len = roundup(prefetch_len, 4); |
| 394 | 411 | ||
| 395 | desc_len = sizeof(cmd->hdr) + sizeof(cmd->data_tx) + prefetch_len; | 412 | desc_len = sizeof(cmd->hdr) + sizeof(cmd->data_tx) + prefetch_len; |
| 396 | frag_len = sizeof(*tx_frags) * 2; | ||
| 397 | 413 | ||
| 398 | txdesc = ath10k_htc_alloc_skb(desc_len); | 414 | txdesc = ath10k_htc_alloc_skb(desc_len); |
| 399 | if (!txdesc) { | 415 | if (!txdesc) { |
| 400 | res = -ENOMEM; | 416 | res = -ENOMEM; |
| 401 | goto err; | 417 | goto err_free_msdu_id; |
| 402 | } | 418 | } |
| 403 | 419 | ||
| 404 | txfrag = dev_alloc_skb(frag_len); | 420 | /* Since HTT 3.0 there is no separate mgmt tx command. However in case |
| 405 | if (!txfrag) { | 421 | * of mgmt tx using TX_FRM there is not tx fragment list. Instead of tx |
| 406 | res = -ENOMEM; | 422 | * fragment list host driver specifies directly frame pointer. */ |
| 407 | goto err; | 423 | use_frags = htt->target_version_major < 3 || |
| 408 | } | 424 | !ieee80211_is_mgmt(hdr->frame_control); |
| 409 | 425 | ||
| 410 | if (!IS_ALIGNED((unsigned long)txdesc->data, 4)) { | 426 | if (!IS_ALIGNED((unsigned long)txdesc->data, 4)) { |
| 411 | ath10k_warn("htt alignment check failed. dropping packet.\n"); | 427 | ath10k_warn("htt alignment check failed. dropping packet.\n"); |
| 412 | res = -EIO; | 428 | res = -EIO; |
| 413 | goto err; | 429 | goto err_free_txdesc; |
| 414 | } | 430 | } |
| 415 | 431 | ||
| 416 | spin_lock_bh(&htt->tx_lock); | 432 | if (use_frags) { |
| 417 | msdu_id = ath10k_htt_tx_alloc_msdu_id(htt); | 433 | skb_cb->htt.frag_len = sizeof(*tx_frags) * 2; |
| 418 | if (msdu_id < 0) { | 434 | skb_cb->htt.pad_len = (unsigned long)msdu->data - |
| 419 | spin_unlock_bh(&htt->tx_lock); | 435 | round_down((unsigned long)msdu->data, 4); |
| 420 | res = msdu_id; | 436 | |
| 421 | goto err; | 437 | skb_push(msdu, skb_cb->htt.frag_len + skb_cb->htt.pad_len); |
| 438 | } else { | ||
| 439 | skb_cb->htt.frag_len = 0; | ||
| 440 | skb_cb->htt.pad_len = 0; | ||
| 422 | } | 441 | } |
| 423 | htt->pending_tx[msdu_id] = txdesc; | ||
| 424 | spin_unlock_bh(&htt->tx_lock); | ||
| 425 | 442 | ||
| 426 | res = ath10k_skb_map(dev, msdu); | 443 | res = ath10k_skb_map(dev, msdu); |
| 427 | if (res) | 444 | if (res) |
| 428 | goto err; | 445 | goto err_pull_txfrag; |
| 429 | 446 | ||
| 430 | /* tx fragment list must be terminated with zero-entry */ | 447 | if (use_frags) { |
| 431 | skb_put(txfrag, frag_len); | 448 | dma_sync_single_for_cpu(dev, skb_cb->paddr, msdu->len, |
| 432 | tx_frags = (struct htt_data_tx_desc_frag *)txfrag->data; | 449 | DMA_TO_DEVICE); |
| 433 | tx_frags[0].paddr = __cpu_to_le32(ATH10K_SKB_CB(msdu)->paddr); | 450 | |
| 434 | tx_frags[0].len = __cpu_to_le32(msdu->len); | 451 | /* tx fragment list must be terminated with zero-entry */ |
| 435 | tx_frags[1].paddr = __cpu_to_le32(0); | 452 | tx_frags = (struct htt_data_tx_desc_frag *)msdu->data; |
| 436 | tx_frags[1].len = __cpu_to_le32(0); | 453 | tx_frags[0].paddr = __cpu_to_le32(skb_cb->paddr + |
| 437 | 454 | skb_cb->htt.frag_len + | |
| 438 | res = ath10k_skb_map(dev, txfrag); | 455 | skb_cb->htt.pad_len); |
| 439 | if (res) | 456 | tx_frags[0].len = __cpu_to_le32(msdu->len - |
| 440 | goto err; | 457 | skb_cb->htt.frag_len - |
| 458 | skb_cb->htt.pad_len); | ||
| 459 | tx_frags[1].paddr = __cpu_to_le32(0); | ||
| 460 | tx_frags[1].len = __cpu_to_le32(0); | ||
| 461 | |||
| 462 | dma_sync_single_for_device(dev, skb_cb->paddr, msdu->len, | ||
| 463 | DMA_TO_DEVICE); | ||
| 464 | } | ||
| 441 | 465 | ||
| 442 | ath10k_dbg(ATH10K_DBG_HTT, "txfrag 0x%llx msdu 0x%llx\n", | 466 | ath10k_dbg(ATH10K_DBG_HTT, "msdu 0x%llx\n", |
| 443 | (unsigned long long) ATH10K_SKB_CB(txfrag)->paddr, | ||
| 444 | (unsigned long long) ATH10K_SKB_CB(msdu)->paddr); | 467 | (unsigned long long) ATH10K_SKB_CB(msdu)->paddr); |
| 445 | ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "txfrag: ", | ||
| 446 | txfrag->data, frag_len); | ||
| 447 | ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "msdu: ", | 468 | ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "msdu: ", |
| 448 | msdu->data, msdu->len); | 469 | msdu->data, msdu->len); |
| 449 | 470 | ||
| 450 | skb_put(txdesc, desc_len); | 471 | skb_put(txdesc, desc_len); |
| 451 | cmd = (struct htt_cmd *)txdesc->data; | 472 | cmd = (struct htt_cmd *)txdesc->data; |
| 452 | memset(cmd, 0, desc_len); | ||
| 453 | 473 | ||
| 454 | tid = ATH10K_SKB_CB(msdu)->htt.tid; | 474 | tid = ATH10K_SKB_CB(msdu)->htt.tid; |
| 455 | 475 | ||
| @@ -459,8 +479,13 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) | |||
| 459 | if (!ieee80211_has_protected(hdr->frame_control)) | 479 | if (!ieee80211_has_protected(hdr->frame_control)) |
| 460 | flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT; | 480 | flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT; |
| 461 | flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT; | 481 | flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT; |
| 462 | flags0 |= SM(ATH10K_HW_TXRX_NATIVE_WIFI, | 482 | |
| 463 | HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE); | 483 | if (use_frags) |
| 484 | flags0 |= SM(ATH10K_HW_TXRX_NATIVE_WIFI, | ||
| 485 | HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE); | ||
| 486 | else | ||
| 487 | flags0 |= SM(ATH10K_HW_TXRX_MGMT, | ||
| 488 | HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE); | ||
| 464 | 489 | ||
| 465 | flags1 = 0; | 490 | flags1 = 0; |
| 466 | flags1 |= SM((u16)vdev_id, HTT_DATA_TX_DESC_FLAGS1_VDEV_ID); | 491 | flags1 |= SM((u16)vdev_id, HTT_DATA_TX_DESC_FLAGS1_VDEV_ID); |
| @@ -468,45 +493,37 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) | |||
| 468 | flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L3_OFFLOAD; | 493 | flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L3_OFFLOAD; |
| 469 | flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L4_OFFLOAD; | 494 | flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L4_OFFLOAD; |
| 470 | 495 | ||
| 471 | frags_paddr = ATH10K_SKB_CB(txfrag)->paddr; | ||
| 472 | |||
| 473 | cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FRM; | 496 | cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FRM; |
| 474 | cmd->data_tx.flags0 = flags0; | 497 | cmd->data_tx.flags0 = flags0; |
| 475 | cmd->data_tx.flags1 = __cpu_to_le16(flags1); | 498 | cmd->data_tx.flags1 = __cpu_to_le16(flags1); |
| 476 | cmd->data_tx.len = __cpu_to_le16(msdu->len); | 499 | cmd->data_tx.len = __cpu_to_le16(msdu->len - |
| 500 | skb_cb->htt.frag_len - | ||
| 501 | skb_cb->htt.pad_len); | ||
| 477 | cmd->data_tx.id = __cpu_to_le16(msdu_id); | 502 | cmd->data_tx.id = __cpu_to_le16(msdu_id); |
| 478 | cmd->data_tx.frags_paddr = __cpu_to_le32(frags_paddr); | 503 | cmd->data_tx.frags_paddr = __cpu_to_le32(skb_cb->paddr); |
| 479 | cmd->data_tx.peerid = __cpu_to_le32(HTT_INVALID_PEERID); | 504 | cmd->data_tx.peerid = __cpu_to_le32(HTT_INVALID_PEERID); |
| 480 | 505 | ||
| 481 | memcpy(cmd->data_tx.prefetch, msdu->data, prefetch_len); | 506 | memcpy(cmd->data_tx.prefetch, hdr, prefetch_len); |
| 482 | |||
| 483 | /* refcount is decremented by HTC and HTT completions until it reaches | ||
| 484 | * zero and is freed */ | ||
| 485 | skb_cb = ATH10K_SKB_CB(txdesc); | ||
| 486 | skb_cb->htt.msdu_id = msdu_id; | ||
| 487 | skb_cb->htt.refcount = 2; | ||
| 488 | skb_cb->htt.txfrag = txfrag; | ||
| 489 | skb_cb->htt.msdu = msdu; | ||
| 490 | 507 | ||
| 491 | res = ath10k_htc_send(&htt->ar->htc, htt->eid, txdesc); | 508 | res = ath10k_htc_send(&htt->ar->htc, htt->eid, txdesc); |
| 492 | if (res) | 509 | if (res) |
| 493 | goto err; | 510 | goto err_unmap_msdu; |
| 494 | 511 | ||
| 495 | return 0; | 512 | return 0; |
| 496 | err: | 513 | |
| 497 | if (txfrag) | 514 | err_unmap_msdu: |
| 498 | ath10k_skb_unmap(dev, txfrag); | ||
| 499 | if (txdesc) | ||
| 500 | dev_kfree_skb_any(txdesc); | ||
| 501 | if (txfrag) | ||
| 502 | dev_kfree_skb_any(txfrag); | ||
| 503 | if (msdu_id >= 0) { | ||
| 504 | spin_lock_bh(&htt->tx_lock); | ||
| 505 | htt->pending_tx[msdu_id] = NULL; | ||
| 506 | ath10k_htt_tx_free_msdu_id(htt, msdu_id); | ||
| 507 | spin_unlock_bh(&htt->tx_lock); | ||
| 508 | } | ||
| 509 | ath10k_htt_tx_dec_pending(htt); | ||
| 510 | ath10k_skb_unmap(dev, msdu); | 515 | ath10k_skb_unmap(dev, msdu); |
| 516 | err_pull_txfrag: | ||
| 517 | skb_pull(msdu, skb_cb->htt.frag_len + skb_cb->htt.pad_len); | ||
| 518 | err_free_txdesc: | ||
| 519 | dev_kfree_skb_any(txdesc); | ||
| 520 | err_free_msdu_id: | ||
| 521 | spin_lock_bh(&htt->tx_lock); | ||
| 522 | htt->pending_tx[msdu_id] = NULL; | ||
| 523 | ath10k_htt_tx_free_msdu_id(htt, msdu_id); | ||
| 524 | spin_unlock_bh(&htt->tx_lock); | ||
| 525 | err_tx_dec: | ||
| 526 | ath10k_htt_tx_dec_pending(htt); | ||
| 527 | err: | ||
| 511 | return res; | 528 | return res; |
| 512 | } | 529 | } |
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 44ed5af0a204..8aeb46d9b534 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h | |||
| @@ -20,28 +20,37 @@ | |||
| 20 | 20 | ||
| 21 | #include "targaddrs.h" | 21 | #include "targaddrs.h" |
| 22 | 22 | ||
| 23 | /* Supported FW version */ | 23 | /* QCA988X 1.0 definitions (unsupported) */ |
| 24 | #define SUPPORTED_FW_MAJOR 1 | 24 | #define QCA988X_HW_1_0_CHIP_ID_REV 0x0 |
| 25 | #define SUPPORTED_FW_MINOR 0 | ||
| 26 | #define SUPPORTED_FW_RELEASE 0 | ||
| 27 | #define SUPPORTED_FW_BUILD 629 | ||
| 28 | |||
| 29 | /* QCA988X 1.0 definitions */ | ||
| 30 | #define QCA988X_HW_1_0_VERSION 0x4000002c | ||
| 31 | #define QCA988X_HW_1_0_FW_DIR "ath10k/QCA988X/hw1.0" | ||
| 32 | #define QCA988X_HW_1_0_FW_FILE "firmware.bin" | ||
| 33 | #define QCA988X_HW_1_0_OTP_FILE "otp.bin" | ||
| 34 | #define QCA988X_HW_1_0_BOARD_DATA_FILE "board.bin" | ||
| 35 | #define QCA988X_HW_1_0_PATCH_LOAD_ADDR 0x1234 | ||
| 36 | 25 | ||
| 37 | /* QCA988X 2.0 definitions */ | 26 | /* QCA988X 2.0 definitions */ |
| 38 | #define QCA988X_HW_2_0_VERSION 0x4100016c | 27 | #define QCA988X_HW_2_0_VERSION 0x4100016c |
| 28 | #define QCA988X_HW_2_0_CHIP_ID_REV 0x2 | ||
| 39 | #define QCA988X_HW_2_0_FW_DIR "ath10k/QCA988X/hw2.0" | 29 | #define QCA988X_HW_2_0_FW_DIR "ath10k/QCA988X/hw2.0" |
| 40 | #define QCA988X_HW_2_0_FW_FILE "firmware.bin" | 30 | #define QCA988X_HW_2_0_FW_FILE "firmware.bin" |
| 41 | #define QCA988X_HW_2_0_OTP_FILE "otp.bin" | 31 | #define QCA988X_HW_2_0_OTP_FILE "otp.bin" |
| 42 | #define QCA988X_HW_2_0_BOARD_DATA_FILE "board.bin" | 32 | #define QCA988X_HW_2_0_BOARD_DATA_FILE "board.bin" |
| 43 | #define QCA988X_HW_2_0_PATCH_LOAD_ADDR 0x1234 | 33 | #define QCA988X_HW_2_0_PATCH_LOAD_ADDR 0x1234 |
| 44 | 34 | ||
| 35 | #define ATH10K_FW_API2_FILE "firmware-2.bin" | ||
| 36 | |||
| 37 | /* includes also the null byte */ | ||
| 38 | #define ATH10K_FIRMWARE_MAGIC "QCA-ATH10K" | ||
| 39 | |||
| 40 | struct ath10k_fw_ie { | ||
| 41 | __le32 id; | ||
| 42 | __le32 len; | ||
| 43 | u8 data[0]; | ||
| 44 | }; | ||
| 45 | |||
| 46 | enum ath10k_fw_ie_type { | ||
| 47 | ATH10K_FW_IE_FW_VERSION = 0, | ||
| 48 | ATH10K_FW_IE_TIMESTAMP = 1, | ||
| 49 | ATH10K_FW_IE_FEATURES = 2, | ||
| 50 | ATH10K_FW_IE_FW_IMAGE = 3, | ||
| 51 | ATH10K_FW_IE_OTP_IMAGE = 4, | ||
| 52 | }; | ||
| 53 | |||
| 45 | /* Known pecularities: | 54 | /* Known pecularities: |
| 46 | * - current FW doesn't support raw rx mode (last tested v599) | 55 | * - current FW doesn't support raw rx mode (last tested v599) |
| 47 | * - current FW dumps upon raw tx mode (last tested v599) | 56 | * - current FW dumps upon raw tx mode (last tested v599) |
| @@ -53,6 +62,9 @@ enum ath10k_hw_txrx_mode { | |||
| 53 | ATH10K_HW_TXRX_RAW = 0, | 62 | ATH10K_HW_TXRX_RAW = 0, |
| 54 | ATH10K_HW_TXRX_NATIVE_WIFI = 1, | 63 | ATH10K_HW_TXRX_NATIVE_WIFI = 1, |
| 55 | ATH10K_HW_TXRX_ETHERNET = 2, | 64 | ATH10K_HW_TXRX_ETHERNET = 2, |
| 65 | |||
| 66 | /* Valid for HTT >= 3.0. Used for management frames in TX_FRM. */ | ||
| 67 | ATH10K_HW_TXRX_MGMT = 3, | ||
| 56 | }; | 68 | }; |
| 57 | 69 | ||
| 58 | enum ath10k_mcast2ucast_mode { | 70 | enum ath10k_mcast2ucast_mode { |
| @@ -60,6 +72,7 @@ enum ath10k_mcast2ucast_mode { | |||
| 60 | ATH10K_MCAST2UCAST_ENABLED = 1, | 72 | ATH10K_MCAST2UCAST_ENABLED = 1, |
| 61 | }; | 73 | }; |
| 62 | 74 | ||
| 75 | /* Target specific defines for MAIN firmware */ | ||
| 63 | #define TARGET_NUM_VDEVS 8 | 76 | #define TARGET_NUM_VDEVS 8 |
| 64 | #define TARGET_NUM_PEER_AST 2 | 77 | #define TARGET_NUM_PEER_AST 2 |
| 65 | #define TARGET_NUM_WDS_ENTRIES 32 | 78 | #define TARGET_NUM_WDS_ENTRIES 32 |
| @@ -75,7 +88,11 @@ enum ath10k_mcast2ucast_mode { | |||
| 75 | #define TARGET_RX_CHAIN_MASK (BIT(0) | BIT(1) | BIT(2)) | 88 | #define TARGET_RX_CHAIN_MASK (BIT(0) | BIT(1) | BIT(2)) |
| 76 | #define TARGET_RX_TIMEOUT_LO_PRI 100 | 89 | #define TARGET_RX_TIMEOUT_LO_PRI 100 |
| 77 | #define TARGET_RX_TIMEOUT_HI_PRI 40 | 90 | #define TARGET_RX_TIMEOUT_HI_PRI 40 |
| 78 | #define TARGET_RX_DECAP_MODE ATH10K_HW_TXRX_ETHERNET | 91 | |
| 92 | /* Native Wifi decap mode is used to align IP frames to 4-byte boundaries and | ||
| 93 | * avoid a very expensive re-alignment in mac80211. */ | ||
| 94 | #define TARGET_RX_DECAP_MODE ATH10K_HW_TXRX_NATIVE_WIFI | ||
| 95 | |||
| 79 | #define TARGET_SCAN_MAX_PENDING_REQS 4 | 96 | #define TARGET_SCAN_MAX_PENDING_REQS 4 |
| 80 | #define TARGET_BMISS_OFFLOAD_MAX_VDEV 3 | 97 | #define TARGET_BMISS_OFFLOAD_MAX_VDEV 3 |
| 81 | #define TARGET_ROAM_OFFLOAD_MAX_VDEV 3 | 98 | #define TARGET_ROAM_OFFLOAD_MAX_VDEV 3 |
| @@ -90,6 +107,36 @@ enum ath10k_mcast2ucast_mode { | |||
| 90 | #define TARGET_NUM_MSDU_DESC (1024 + 400) | 107 | #define TARGET_NUM_MSDU_DESC (1024 + 400) |
| 91 | #define TARGET_MAX_FRAG_ENTRIES 0 | 108 | #define TARGET_MAX_FRAG_ENTRIES 0 |
| 92 | 109 | ||
| 110 | /* Target specific defines for 10.X firmware */ | ||
| 111 | #define TARGET_10X_NUM_VDEVS 16 | ||
| 112 | #define TARGET_10X_NUM_PEER_AST 2 | ||
| 113 | #define TARGET_10X_NUM_WDS_ENTRIES 32 | ||
| 114 | #define TARGET_10X_DMA_BURST_SIZE 0 | ||
| 115 | #define TARGET_10X_MAC_AGGR_DELIM 0 | ||
| 116 | #define TARGET_10X_AST_SKID_LIMIT 16 | ||
| 117 | #define TARGET_10X_NUM_PEERS (128 + (TARGET_10X_NUM_VDEVS)) | ||
| 118 | #define TARGET_10X_NUM_OFFLOAD_PEERS 0 | ||
| 119 | #define TARGET_10X_NUM_OFFLOAD_REORDER_BUFS 0 | ||
| 120 | #define TARGET_10X_NUM_PEER_KEYS 2 | ||
| 121 | #define TARGET_10X_NUM_TIDS 256 | ||
| 122 | #define TARGET_10X_TX_CHAIN_MASK (BIT(0) | BIT(1) | BIT(2)) | ||
| 123 | #define TARGET_10X_RX_CHAIN_MASK (BIT(0) | BIT(1) | BIT(2)) | ||
| 124 | #define TARGET_10X_RX_TIMEOUT_LO_PRI 100 | ||
| 125 | #define TARGET_10X_RX_TIMEOUT_HI_PRI 40 | ||
| 126 | #define TARGET_10X_RX_DECAP_MODE ATH10K_HW_TXRX_NATIVE_WIFI | ||
| 127 | #define TARGET_10X_SCAN_MAX_PENDING_REQS 4 | ||
| 128 | #define TARGET_10X_BMISS_OFFLOAD_MAX_VDEV 2 | ||
| 129 | #define TARGET_10X_ROAM_OFFLOAD_MAX_VDEV 2 | ||
| 130 | #define TARGET_10X_ROAM_OFFLOAD_MAX_AP_PROFILES 8 | ||
| 131 | #define TARGET_10X_GTK_OFFLOAD_MAX_VDEV 3 | ||
| 132 | #define TARGET_10X_NUM_MCAST_GROUPS 0 | ||
| 133 | #define TARGET_10X_NUM_MCAST_TABLE_ELEMS 0 | ||
| 134 | #define TARGET_10X_MCAST2UCAST_MODE ATH10K_MCAST2UCAST_DISABLED | ||
| 135 | #define TARGET_10X_TX_DBG_LOG_SIZE 1024 | ||
| 136 | #define TARGET_10X_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK 1 | ||
| 137 | #define TARGET_10X_VOW_CONFIG 0 | ||
| 138 | #define TARGET_10X_NUM_MSDU_DESC (1024 + 400) | ||
| 139 | #define TARGET_10X_MAX_FRAG_ENTRIES 0 | ||
| 93 | 140 | ||
| 94 | /* Number of Copy Engines supported */ | 141 | /* Number of Copy Engines supported */ |
| 95 | #define CE_COUNT 8 | 142 | #define CE_COUNT 8 |
| @@ -169,6 +216,10 @@ enum ath10k_mcast2ucast_mode { | |||
| 169 | #define SOC_LPO_CAL_ENABLE_LSB 20 | 216 | #define SOC_LPO_CAL_ENABLE_LSB 20 |
| 170 | #define SOC_LPO_CAL_ENABLE_MASK 0x00100000 | 217 | #define SOC_LPO_CAL_ENABLE_MASK 0x00100000 |
| 171 | 218 | ||
| 219 | #define SOC_CHIP_ID_ADDRESS 0x000000ec | ||
| 220 | #define SOC_CHIP_ID_REV_LSB 8 | ||
| 221 | #define SOC_CHIP_ID_REV_MASK 0x00000f00 | ||
| 222 | |||
| 172 | #define WLAN_RESET_CONTROL_COLD_RST_MASK 0x00000008 | 223 | #define WLAN_RESET_CONTROL_COLD_RST_MASK 0x00000008 |
| 173 | #define WLAN_RESET_CONTROL_WARM_RST_MASK 0x00000004 | 224 | #define WLAN_RESET_CONTROL_WARM_RST_MASK 0x00000004 |
| 174 | #define WLAN_SYSTEM_SLEEP_DISABLE_LSB 0 | 225 | #define WLAN_SYSTEM_SLEEP_DISABLE_LSB 0 |
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index cf2ba4d850c9..0b1cc516e778 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c | |||
| @@ -334,25 +334,29 @@ static int ath10k_peer_create(struct ath10k *ar, u32 vdev_id, const u8 *addr) | |||
| 334 | 334 | ||
| 335 | static int ath10k_mac_set_rts(struct ath10k_vif *arvif, u32 value) | 335 | static int ath10k_mac_set_rts(struct ath10k_vif *arvif, u32 value) |
| 336 | { | 336 | { |
| 337 | struct ath10k *ar = arvif->ar; | ||
| 338 | u32 vdev_param; | ||
| 339 | |||
| 337 | if (value != 0xFFFFFFFF) | 340 | if (value != 0xFFFFFFFF) |
| 338 | value = min_t(u32, arvif->ar->hw->wiphy->rts_threshold, | 341 | value = min_t(u32, arvif->ar->hw->wiphy->rts_threshold, |
| 339 | ATH10K_RTS_MAX); | 342 | ATH10K_RTS_MAX); |
| 340 | 343 | ||
| 341 | return ath10k_wmi_vdev_set_param(arvif->ar, arvif->vdev_id, | 344 | vdev_param = ar->wmi.vdev_param->rts_threshold; |
| 342 | WMI_VDEV_PARAM_RTS_THRESHOLD, | 345 | return ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, value); |
| 343 | value); | ||
| 344 | } | 346 | } |
| 345 | 347 | ||
| 346 | static int ath10k_mac_set_frag(struct ath10k_vif *arvif, u32 value) | 348 | static int ath10k_mac_set_frag(struct ath10k_vif *arvif, u32 value) |
| 347 | { | 349 | { |
| 350 | struct ath10k *ar = arvif->ar; | ||
| 351 | u32 vdev_param; | ||
| 352 | |||
| 348 | if (value != 0xFFFFFFFF) | 353 | if (value != 0xFFFFFFFF) |
| 349 | value = clamp_t(u32, arvif->ar->hw->wiphy->frag_threshold, | 354 | value = clamp_t(u32, arvif->ar->hw->wiphy->frag_threshold, |
| 350 | ATH10K_FRAGMT_THRESHOLD_MIN, | 355 | ATH10K_FRAGMT_THRESHOLD_MIN, |
| 351 | ATH10K_FRAGMT_THRESHOLD_MAX); | 356 | ATH10K_FRAGMT_THRESHOLD_MAX); |
| 352 | 357 | ||
| 353 | return ath10k_wmi_vdev_set_param(arvif->ar, arvif->vdev_id, | 358 | vdev_param = ar->wmi.vdev_param->fragmentation_threshold; |
| 354 | WMI_VDEV_PARAM_FRAGMENTATION_THRESHOLD, | 359 | return ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, value); |
| 355 | value); | ||
| 356 | } | 360 | } |
| 357 | 361 | ||
| 358 | static int ath10k_peer_delete(struct ath10k *ar, u32 vdev_id, const u8 *addr) | 362 | static int ath10k_peer_delete(struct ath10k *ar, u32 vdev_id, const u8 *addr) |
| @@ -460,6 +464,11 @@ static int ath10k_vdev_start(struct ath10k_vif *arvif) | |||
| 460 | arg.ssid_len = arvif->vif->bss_conf.ssid_len; | 464 | arg.ssid_len = arvif->vif->bss_conf.ssid_len; |
| 461 | } | 465 | } |
| 462 | 466 | ||
| 467 | ath10k_dbg(ATH10K_DBG_MAC, | ||
| 468 | "mac vdev %d start center_freq %d phymode %s\n", | ||
| 469 | arg.vdev_id, arg.channel.freq, | ||
| 470 | ath10k_wmi_phymode_str(arg.channel.mode)); | ||
| 471 | |||
| 463 | ret = ath10k_wmi_vdev_start(ar, &arg); | 472 | ret = ath10k_wmi_vdev_start(ar, &arg); |
| 464 | if (ret) { | 473 | if (ret) { |
| 465 | ath10k_warn("WMI vdev start failed: ret %d\n", ret); | 474 | ath10k_warn("WMI vdev start failed: ret %d\n", ret); |
| @@ -503,13 +512,10 @@ static int ath10k_monitor_start(struct ath10k *ar, int vdev_id) | |||
| 503 | { | 512 | { |
| 504 | struct ieee80211_channel *channel = ar->hw->conf.chandef.chan; | 513 | struct ieee80211_channel *channel = ar->hw->conf.chandef.chan; |
| 505 | struct wmi_vdev_start_request_arg arg = {}; | 514 | struct wmi_vdev_start_request_arg arg = {}; |
| 506 | enum nl80211_channel_type type; | ||
| 507 | int ret = 0; | 515 | int ret = 0; |
| 508 | 516 | ||
| 509 | lockdep_assert_held(&ar->conf_mutex); | 517 | lockdep_assert_held(&ar->conf_mutex); |
| 510 | 518 | ||
| 511 | type = cfg80211_get_chandef_type(&ar->hw->conf.chandef); | ||
| 512 | |||
| 513 | arg.vdev_id = vdev_id; | 519 | arg.vdev_id = vdev_id; |
| 514 | arg.channel.freq = channel->center_freq; | 520 | arg.channel.freq = channel->center_freq; |
| 515 | arg.channel.band_center_freq1 = ar->hw->conf.chandef.center_freq1; | 521 | arg.channel.band_center_freq1 = ar->hw->conf.chandef.center_freq1; |
| @@ -560,12 +566,9 @@ static int ath10k_monitor_stop(struct ath10k *ar) | |||
| 560 | 566 | ||
| 561 | lockdep_assert_held(&ar->conf_mutex); | 567 | lockdep_assert_held(&ar->conf_mutex); |
| 562 | 568 | ||
| 563 | /* For some reasons, ath10k_wmi_vdev_down() here couse | 569 | ret = ath10k_wmi_vdev_down(ar, ar->monitor_vdev_id); |
| 564 | * often ath10k_wmi_vdev_stop() to fail. Next we could | 570 | if (ret) |
| 565 | * not run monitor vdev and driver reload | 571 | ath10k_warn("Monitor vdev down failed: %d\n", ret); |
| 566 | * required. Don't see such problems we skip | ||
| 567 | * ath10k_wmi_vdev_down() here. | ||
| 568 | */ | ||
| 569 | 572 | ||
| 570 | ret = ath10k_wmi_vdev_stop(ar, ar->monitor_vdev_id); | 573 | ret = ath10k_wmi_vdev_stop(ar, ar->monitor_vdev_id); |
| 571 | if (ret) | 574 | if (ret) |
| @@ -607,7 +610,7 @@ static int ath10k_monitor_create(struct ath10k *ar) | |||
| 607 | goto vdev_fail; | 610 | goto vdev_fail; |
| 608 | } | 611 | } |
| 609 | 612 | ||
| 610 | ath10k_dbg(ATH10K_DBG_MAC, "Monitor interface created, vdev id: %d\n", | 613 | ath10k_dbg(ATH10K_DBG_MAC, "mac monitor vdev %d created\n", |
| 611 | ar->monitor_vdev_id); | 614 | ar->monitor_vdev_id); |
| 612 | 615 | ||
| 613 | ar->monitor_present = true; | 616 | ar->monitor_present = true; |
| @@ -639,7 +642,7 @@ static int ath10k_monitor_destroy(struct ath10k *ar) | |||
| 639 | ar->free_vdev_map |= 1 << (ar->monitor_vdev_id); | 642 | ar->free_vdev_map |= 1 << (ar->monitor_vdev_id); |
| 640 | ar->monitor_present = false; | 643 | ar->monitor_present = false; |
| 641 | 644 | ||
| 642 | ath10k_dbg(ATH10K_DBG_MAC, "Monitor interface destroyed, vdev id: %d\n", | 645 | ath10k_dbg(ATH10K_DBG_MAC, "mac monitor vdev %d deleted\n", |
| 643 | ar->monitor_vdev_id); | 646 | ar->monitor_vdev_id); |
| 644 | return ret; | 647 | return ret; |
| 645 | } | 648 | } |
| @@ -668,13 +671,14 @@ static void ath10k_control_beaconing(struct ath10k_vif *arvif, | |||
| 668 | arvif->vdev_id); | 671 | arvif->vdev_id); |
| 669 | return; | 672 | return; |
| 670 | } | 673 | } |
| 671 | ath10k_dbg(ATH10K_DBG_MAC, "VDEV: %d up\n", arvif->vdev_id); | 674 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d up\n", arvif->vdev_id); |
| 672 | } | 675 | } |
| 673 | 676 | ||
| 674 | static void ath10k_control_ibss(struct ath10k_vif *arvif, | 677 | static void ath10k_control_ibss(struct ath10k_vif *arvif, |
| 675 | struct ieee80211_bss_conf *info, | 678 | struct ieee80211_bss_conf *info, |
| 676 | const u8 self_peer[ETH_ALEN]) | 679 | const u8 self_peer[ETH_ALEN]) |
| 677 | { | 680 | { |
| 681 | u32 vdev_param; | ||
| 678 | int ret = 0; | 682 | int ret = 0; |
| 679 | 683 | ||
| 680 | lockdep_assert_held(&arvif->ar->conf_mutex); | 684 | lockdep_assert_held(&arvif->ar->conf_mutex); |
| @@ -708,8 +712,8 @@ static void ath10k_control_ibss(struct ath10k_vif *arvif, | |||
| 708 | return; | 712 | return; |
| 709 | } | 713 | } |
| 710 | 714 | ||
| 711 | ret = ath10k_wmi_vdev_set_param(arvif->ar, arvif->vdev_id, | 715 | vdev_param = arvif->ar->wmi.vdev_param->atim_window; |
| 712 | WMI_VDEV_PARAM_ATIM_WINDOW, | 716 | ret = ath10k_wmi_vdev_set_param(arvif->ar, arvif->vdev_id, vdev_param, |
| 713 | ATH10K_DEFAULT_ATIM); | 717 | ATH10K_DEFAULT_ATIM); |
| 714 | if (ret) | 718 | if (ret) |
| 715 | ath10k_warn("Failed to set IBSS ATIM for VDEV:%d ret:%d\n", | 719 | ath10k_warn("Failed to set IBSS ATIM for VDEV:%d ret:%d\n", |
| @@ -719,47 +723,45 @@ static void ath10k_control_ibss(struct ath10k_vif *arvif, | |||
| 719 | /* | 723 | /* |
| 720 | * Review this when mac80211 gains per-interface powersave support. | 724 | * Review this when mac80211 gains per-interface powersave support. |
| 721 | */ | 725 | */ |
| 722 | static void ath10k_ps_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | 726 | static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif) |
| 723 | { | 727 | { |
| 724 | struct ath10k_generic_iter *ar_iter = data; | 728 | struct ath10k *ar = arvif->ar; |
| 725 | struct ieee80211_conf *conf = &ar_iter->ar->hw->conf; | 729 | struct ieee80211_conf *conf = &ar->hw->conf; |
| 726 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | ||
| 727 | enum wmi_sta_powersave_param param; | 730 | enum wmi_sta_powersave_param param; |
| 728 | enum wmi_sta_ps_mode psmode; | 731 | enum wmi_sta_ps_mode psmode; |
| 729 | int ret; | 732 | int ret; |
| 730 | 733 | ||
| 731 | lockdep_assert_held(&arvif->ar->conf_mutex); | 734 | lockdep_assert_held(&arvif->ar->conf_mutex); |
| 732 | 735 | ||
| 733 | if (vif->type != NL80211_IFTYPE_STATION) | 736 | if (arvif->vif->type != NL80211_IFTYPE_STATION) |
| 734 | return; | 737 | return 0; |
| 735 | 738 | ||
| 736 | if (conf->flags & IEEE80211_CONF_PS) { | 739 | if (conf->flags & IEEE80211_CONF_PS) { |
| 737 | psmode = WMI_STA_PS_MODE_ENABLED; | 740 | psmode = WMI_STA_PS_MODE_ENABLED; |
| 738 | param = WMI_STA_PS_PARAM_INACTIVITY_TIME; | 741 | param = WMI_STA_PS_PARAM_INACTIVITY_TIME; |
| 739 | 742 | ||
| 740 | ret = ath10k_wmi_set_sta_ps_param(ar_iter->ar, | 743 | ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param, |
| 741 | arvif->vdev_id, | ||
| 742 | param, | ||
| 743 | conf->dynamic_ps_timeout); | 744 | conf->dynamic_ps_timeout); |
| 744 | if (ret) { | 745 | if (ret) { |
| 745 | ath10k_warn("Failed to set inactivity time for VDEV: %d\n", | 746 | ath10k_warn("Failed to set inactivity time for VDEV: %d\n", |
| 746 | arvif->vdev_id); | 747 | arvif->vdev_id); |
| 747 | return; | 748 | return ret; |
| 748 | } | 749 | } |
| 749 | |||
| 750 | ar_iter->ret = ret; | ||
| 751 | } else { | 750 | } else { |
| 752 | psmode = WMI_STA_PS_MODE_DISABLED; | 751 | psmode = WMI_STA_PS_MODE_DISABLED; |
| 753 | } | 752 | } |
| 754 | 753 | ||
| 755 | ar_iter->ret = ath10k_wmi_set_psmode(ar_iter->ar, arvif->vdev_id, | 754 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d psmode %s\n", |
| 756 | psmode); | 755 | arvif->vdev_id, psmode ? "enable" : "disable"); |
| 757 | if (ar_iter->ret) | 756 | |
| 757 | ret = ath10k_wmi_set_psmode(ar, arvif->vdev_id, psmode); | ||
| 758 | if (ret) { | ||
| 758 | ath10k_warn("Failed to set PS Mode: %d for VDEV: %d\n", | 759 | ath10k_warn("Failed to set PS Mode: %d for VDEV: %d\n", |
| 759 | psmode, arvif->vdev_id); | 760 | psmode, arvif->vdev_id); |
| 760 | else | 761 | return ret; |
| 761 | ath10k_dbg(ATH10K_DBG_MAC, "Set PS Mode: %d for VDEV: %d\n", | 762 | } |
| 762 | psmode, arvif->vdev_id); | 763 | |
| 764 | return 0; | ||
| 763 | } | 765 | } |
| 764 | 766 | ||
| 765 | /**********************/ | 767 | /**********************/ |
| @@ -949,7 +951,8 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar, | |||
| 949 | arg->peer_ht_rates.num_rates = n; | 951 | arg->peer_ht_rates.num_rates = n; |
| 950 | arg->peer_num_spatial_streams = max((n+7) / 8, 1); | 952 | arg->peer_num_spatial_streams = max((n+7) / 8, 1); |
| 951 | 953 | ||
| 952 | ath10k_dbg(ATH10K_DBG_MAC, "mcs cnt %d nss %d\n", | 954 | ath10k_dbg(ATH10K_DBG_MAC, "mac ht peer %pM mcs cnt %d nss %d\n", |
| 955 | arg->addr, | ||
| 953 | arg->peer_ht_rates.num_rates, | 956 | arg->peer_ht_rates.num_rates, |
| 954 | arg->peer_num_spatial_streams); | 957 | arg->peer_num_spatial_streams); |
| 955 | } | 958 | } |
| @@ -969,11 +972,11 @@ static void ath10k_peer_assoc_h_qos_ap(struct ath10k *ar, | |||
| 969 | arg->peer_flags |= WMI_PEER_QOS; | 972 | arg->peer_flags |= WMI_PEER_QOS; |
| 970 | 973 | ||
| 971 | if (sta->wme && sta->uapsd_queues) { | 974 | if (sta->wme && sta->uapsd_queues) { |
| 972 | ath10k_dbg(ATH10K_DBG_MAC, "uapsd_queues: 0x%X, max_sp: %d\n", | 975 | ath10k_dbg(ATH10K_DBG_MAC, "mac uapsd_queues 0x%x max_sp %d\n", |
| 973 | sta->uapsd_queues, sta->max_sp); | 976 | sta->uapsd_queues, sta->max_sp); |
| 974 | 977 | ||
| 975 | arg->peer_flags |= WMI_PEER_APSD; | 978 | arg->peer_flags |= WMI_PEER_APSD; |
| 976 | arg->peer_flags |= WMI_RC_UAPSD_FLAG; | 979 | arg->peer_rate_caps |= WMI_RC_UAPSD_FLAG; |
| 977 | 980 | ||
| 978 | if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) | 981 | if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) |
| 979 | uapsd |= WMI_AP_PS_UAPSD_AC3_DELIVERY_EN | | 982 | uapsd |= WMI_AP_PS_UAPSD_AC3_DELIVERY_EN | |
| @@ -1028,14 +1031,27 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar, | |||
| 1028 | struct wmi_peer_assoc_complete_arg *arg) | 1031 | struct wmi_peer_assoc_complete_arg *arg) |
| 1029 | { | 1032 | { |
| 1030 | const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; | 1033 | const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; |
| 1034 | u8 ampdu_factor; | ||
| 1031 | 1035 | ||
| 1032 | if (!vht_cap->vht_supported) | 1036 | if (!vht_cap->vht_supported) |
| 1033 | return; | 1037 | return; |
| 1034 | 1038 | ||
| 1035 | arg->peer_flags |= WMI_PEER_VHT; | 1039 | arg->peer_flags |= WMI_PEER_VHT; |
| 1036 | |||
| 1037 | arg->peer_vht_caps = vht_cap->cap; | 1040 | arg->peer_vht_caps = vht_cap->cap; |
| 1038 | 1041 | ||
| 1042 | |||
| 1043 | ampdu_factor = (vht_cap->cap & | ||
| 1044 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK) >> | ||
| 1045 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; | ||
| 1046 | |||
| 1047 | /* Workaround: Some Netgear/Linksys 11ac APs set Rx A-MPDU factor to | ||
| 1048 | * zero in VHT IE. Using it would result in degraded throughput. | ||
| 1049 | * arg->peer_max_mpdu at this point contains HT max_mpdu so keep | ||
| 1050 | * it if VHT max_mpdu is smaller. */ | ||
| 1051 | arg->peer_max_mpdu = max(arg->peer_max_mpdu, | ||
| 1052 | (1U << (IEEE80211_HT_MAX_AMPDU_FACTOR + | ||
| 1053 | ampdu_factor)) - 1); | ||
| 1054 | |||
| 1039 | if (sta->bandwidth == IEEE80211_STA_RX_BW_80) | 1055 | if (sta->bandwidth == IEEE80211_STA_RX_BW_80) |
| 1040 | arg->peer_flags |= WMI_PEER_80MHZ; | 1056 | arg->peer_flags |= WMI_PEER_80MHZ; |
| 1041 | 1057 | ||
| @@ -1048,7 +1064,8 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar, | |||
| 1048 | arg->peer_vht_rates.tx_mcs_set = | 1064 | arg->peer_vht_rates.tx_mcs_set = |
| 1049 | __le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map); | 1065 | __le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map); |
| 1050 | 1066 | ||
| 1051 | ath10k_dbg(ATH10K_DBG_MAC, "mac vht peer\n"); | 1067 | ath10k_dbg(ATH10K_DBG_MAC, "mac vht peer %pM max_mpdu %d flags 0x%x\n", |
| 1068 | sta->addr, arg->peer_max_mpdu, arg->peer_flags); | ||
| 1052 | } | 1069 | } |
| 1053 | 1070 | ||
| 1054 | static void ath10k_peer_assoc_h_qos(struct ath10k *ar, | 1071 | static void ath10k_peer_assoc_h_qos(struct ath10k *ar, |
| @@ -1076,8 +1093,6 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar, | |||
| 1076 | { | 1093 | { |
| 1077 | enum wmi_phy_mode phymode = MODE_UNKNOWN; | 1094 | enum wmi_phy_mode phymode = MODE_UNKNOWN; |
| 1078 | 1095 | ||
| 1079 | /* FIXME: add VHT */ | ||
| 1080 | |||
| 1081 | switch (ar->hw->conf.chandef.chan->band) { | 1096 | switch (ar->hw->conf.chandef.chan->band) { |
| 1082 | case IEEE80211_BAND_2GHZ: | 1097 | case IEEE80211_BAND_2GHZ: |
| 1083 | if (sta->ht_cap.ht_supported) { | 1098 | if (sta->ht_cap.ht_supported) { |
| @@ -1091,7 +1106,17 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar, | |||
| 1091 | 1106 | ||
| 1092 | break; | 1107 | break; |
| 1093 | case IEEE80211_BAND_5GHZ: | 1108 | case IEEE80211_BAND_5GHZ: |
| 1094 | if (sta->ht_cap.ht_supported) { | 1109 | /* |
| 1110 | * Check VHT first. | ||
| 1111 | */ | ||
| 1112 | if (sta->vht_cap.vht_supported) { | ||
| 1113 | if (sta->bandwidth == IEEE80211_STA_RX_BW_80) | ||
| 1114 | phymode = MODE_11AC_VHT80; | ||
| 1115 | else if (sta->bandwidth == IEEE80211_STA_RX_BW_40) | ||
| 1116 | phymode = MODE_11AC_VHT40; | ||
| 1117 | else if (sta->bandwidth == IEEE80211_STA_RX_BW_20) | ||
| 1118 | phymode = MODE_11AC_VHT20; | ||
| 1119 | } else if (sta->ht_cap.ht_supported) { | ||
| 1095 | if (sta->bandwidth == IEEE80211_STA_RX_BW_40) | 1120 | if (sta->bandwidth == IEEE80211_STA_RX_BW_40) |
| 1096 | phymode = MODE_11NA_HT40; | 1121 | phymode = MODE_11NA_HT40; |
| 1097 | else | 1122 | else |
| @@ -1105,30 +1130,32 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar, | |||
| 1105 | break; | 1130 | break; |
| 1106 | } | 1131 | } |
| 1107 | 1132 | ||
| 1133 | ath10k_dbg(ATH10K_DBG_MAC, "mac peer %pM phymode %s\n", | ||
| 1134 | sta->addr, ath10k_wmi_phymode_str(phymode)); | ||
| 1135 | |||
| 1108 | arg->peer_phymode = phymode; | 1136 | arg->peer_phymode = phymode; |
| 1109 | WARN_ON(phymode == MODE_UNKNOWN); | 1137 | WARN_ON(phymode == MODE_UNKNOWN); |
| 1110 | } | 1138 | } |
| 1111 | 1139 | ||
| 1112 | static int ath10k_peer_assoc(struct ath10k *ar, | 1140 | static int ath10k_peer_assoc_prepare(struct ath10k *ar, |
| 1113 | struct ath10k_vif *arvif, | 1141 | struct ath10k_vif *arvif, |
| 1114 | struct ieee80211_sta *sta, | 1142 | struct ieee80211_sta *sta, |
| 1115 | struct ieee80211_bss_conf *bss_conf) | 1143 | struct ieee80211_bss_conf *bss_conf, |
| 1144 | struct wmi_peer_assoc_complete_arg *arg) | ||
| 1116 | { | 1145 | { |
| 1117 | struct wmi_peer_assoc_complete_arg arg; | ||
| 1118 | |||
| 1119 | lockdep_assert_held(&ar->conf_mutex); | 1146 | lockdep_assert_held(&ar->conf_mutex); |
| 1120 | 1147 | ||
| 1121 | memset(&arg, 0, sizeof(struct wmi_peer_assoc_complete_arg)); | 1148 | memset(arg, 0, sizeof(*arg)); |
| 1122 | 1149 | ||
| 1123 | ath10k_peer_assoc_h_basic(ar, arvif, sta, bss_conf, &arg); | 1150 | ath10k_peer_assoc_h_basic(ar, arvif, sta, bss_conf, arg); |
| 1124 | ath10k_peer_assoc_h_crypto(ar, arvif, &arg); | 1151 | ath10k_peer_assoc_h_crypto(ar, arvif, arg); |
| 1125 | ath10k_peer_assoc_h_rates(ar, sta, &arg); | 1152 | ath10k_peer_assoc_h_rates(ar, sta, arg); |
| 1126 | ath10k_peer_assoc_h_ht(ar, sta, &arg); | 1153 | ath10k_peer_assoc_h_ht(ar, sta, arg); |
| 1127 | ath10k_peer_assoc_h_vht(ar, sta, &arg); | 1154 | ath10k_peer_assoc_h_vht(ar, sta, arg); |
| 1128 | ath10k_peer_assoc_h_qos(ar, arvif, sta, bss_conf, &arg); | 1155 | ath10k_peer_assoc_h_qos(ar, arvif, sta, bss_conf, arg); |
| 1129 | ath10k_peer_assoc_h_phymode(ar, arvif, sta, &arg); | 1156 | ath10k_peer_assoc_h_phymode(ar, arvif, sta, arg); |
| 1130 | 1157 | ||
| 1131 | return ath10k_wmi_peer_assoc(ar, &arg); | 1158 | return 0; |
| 1132 | } | 1159 | } |
| 1133 | 1160 | ||
| 1134 | /* can be called only in mac80211 callbacks due to `key_count` usage */ | 1161 | /* can be called only in mac80211 callbacks due to `key_count` usage */ |
| @@ -1138,6 +1165,7 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, | |||
| 1138 | { | 1165 | { |
| 1139 | struct ath10k *ar = hw->priv; | 1166 | struct ath10k *ar = hw->priv; |
| 1140 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | 1167 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); |
| 1168 | struct wmi_peer_assoc_complete_arg peer_arg; | ||
| 1141 | struct ieee80211_sta *ap_sta; | 1169 | struct ieee80211_sta *ap_sta; |
| 1142 | int ret; | 1170 | int ret; |
| 1143 | 1171 | ||
| @@ -1153,24 +1181,33 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, | |||
| 1153 | return; | 1181 | return; |
| 1154 | } | 1182 | } |
| 1155 | 1183 | ||
| 1156 | ret = ath10k_peer_assoc(ar, arvif, ap_sta, bss_conf); | 1184 | ret = ath10k_peer_assoc_prepare(ar, arvif, ap_sta, |
| 1185 | bss_conf, &peer_arg); | ||
| 1157 | if (ret) { | 1186 | if (ret) { |
| 1158 | ath10k_warn("Peer assoc failed for %pM\n", bss_conf->bssid); | 1187 | ath10k_warn("Peer assoc prepare failed for %pM\n: %d", |
| 1188 | bss_conf->bssid, ret); | ||
| 1159 | rcu_read_unlock(); | 1189 | rcu_read_unlock(); |
| 1160 | return; | 1190 | return; |
| 1161 | } | 1191 | } |
| 1162 | 1192 | ||
| 1163 | rcu_read_unlock(); | 1193 | rcu_read_unlock(); |
| 1164 | 1194 | ||
| 1195 | ret = ath10k_wmi_peer_assoc(ar, &peer_arg); | ||
| 1196 | if (ret) { | ||
| 1197 | ath10k_warn("Peer assoc failed for %pM\n: %d", | ||
| 1198 | bss_conf->bssid, ret); | ||
| 1199 | return; | ||
| 1200 | } | ||
| 1201 | |||
| 1202 | ath10k_dbg(ATH10K_DBG_MAC, | ||
| 1203 | "mac vdev %d up (associated) bssid %pM aid %d\n", | ||
| 1204 | arvif->vdev_id, bss_conf->bssid, bss_conf->aid); | ||
| 1205 | |||
| 1165 | ret = ath10k_wmi_vdev_up(ar, arvif->vdev_id, bss_conf->aid, | 1206 | ret = ath10k_wmi_vdev_up(ar, arvif->vdev_id, bss_conf->aid, |
| 1166 | bss_conf->bssid); | 1207 | bss_conf->bssid); |
| 1167 | if (ret) | 1208 | if (ret) |
| 1168 | ath10k_warn("VDEV: %d up failed: ret %d\n", | 1209 | ath10k_warn("VDEV: %d up failed: ret %d\n", |
| 1169 | arvif->vdev_id, ret); | 1210 | arvif->vdev_id, ret); |
| 1170 | else | ||
| 1171 | ath10k_dbg(ATH10K_DBG_MAC, | ||
| 1172 | "VDEV: %d associated, BSSID: %pM, AID: %d\n", | ||
| 1173 | arvif->vdev_id, bss_conf->bssid, bss_conf->aid); | ||
| 1174 | } | 1211 | } |
| 1175 | 1212 | ||
| 1176 | /* | 1213 | /* |
| @@ -1191,10 +1228,11 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw, | |||
| 1191 | * No idea why this happens, even though VDEV-DOWN is supposed | 1228 | * No idea why this happens, even though VDEV-DOWN is supposed |
| 1192 | * to be analogous to link down, so just stop the VDEV. | 1229 | * to be analogous to link down, so just stop the VDEV. |
| 1193 | */ | 1230 | */ |
| 1231 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d stop (disassociated\n", | ||
| 1232 | arvif->vdev_id); | ||
| 1233 | |||
| 1234 | /* FIXME: check return value */ | ||
| 1194 | ret = ath10k_vdev_stop(arvif); | 1235 | ret = ath10k_vdev_stop(arvif); |
| 1195 | if (!ret) | ||
| 1196 | ath10k_dbg(ATH10K_DBG_MAC, "VDEV: %d stopped\n", | ||
| 1197 | arvif->vdev_id); | ||
| 1198 | 1236 | ||
| 1199 | /* | 1237 | /* |
| 1200 | * If we don't call VDEV-DOWN after VDEV-STOP FW will remain active and | 1238 | * If we don't call VDEV-DOWN after VDEV-STOP FW will remain active and |
| @@ -1203,26 +1241,33 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw, | |||
| 1203 | * interfaces as it expects there is no rx when no interface is | 1241 | * interfaces as it expects there is no rx when no interface is |
| 1204 | * running. | 1242 | * running. |
| 1205 | */ | 1243 | */ |
| 1206 | ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id); | 1244 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d down\n", arvif->vdev_id); |
| 1207 | if (ret) | ||
| 1208 | ath10k_dbg(ATH10K_DBG_MAC, "VDEV: %d ath10k_wmi_vdev_down failed (%d)\n", | ||
| 1209 | arvif->vdev_id, ret); | ||
| 1210 | 1245 | ||
| 1211 | ath10k_wmi_flush_tx(ar); | 1246 | /* FIXME: why don't we print error if wmi call fails? */ |
| 1247 | ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id); | ||
| 1212 | 1248 | ||
| 1213 | arvif->def_wep_key_index = 0; | 1249 | arvif->def_wep_key_idx = 0; |
| 1214 | } | 1250 | } |
| 1215 | 1251 | ||
| 1216 | static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif, | 1252 | static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif, |
| 1217 | struct ieee80211_sta *sta) | 1253 | struct ieee80211_sta *sta) |
| 1218 | { | 1254 | { |
| 1255 | struct wmi_peer_assoc_complete_arg peer_arg; | ||
| 1219 | int ret = 0; | 1256 | int ret = 0; |
| 1220 | 1257 | ||
| 1221 | lockdep_assert_held(&ar->conf_mutex); | 1258 | lockdep_assert_held(&ar->conf_mutex); |
| 1222 | 1259 | ||
| 1223 | ret = ath10k_peer_assoc(ar, arvif, sta, NULL); | 1260 | ret = ath10k_peer_assoc_prepare(ar, arvif, sta, NULL, &peer_arg); |
| 1261 | if (ret) { | ||
| 1262 | ath10k_warn("WMI peer assoc prepare failed for %pM\n", | ||
| 1263 | sta->addr); | ||
| 1264 | return ret; | ||
| 1265 | } | ||
| 1266 | |||
| 1267 | ret = ath10k_wmi_peer_assoc(ar, &peer_arg); | ||
| 1224 | if (ret) { | 1268 | if (ret) { |
| 1225 | ath10k_warn("WMI peer assoc failed for %pM\n", sta->addr); | 1269 | ath10k_warn("Peer assoc failed for STA %pM\n: %d", |
| 1270 | sta->addr, ret); | ||
| 1226 | return ret; | 1271 | return ret; |
| 1227 | } | 1272 | } |
| 1228 | 1273 | ||
| @@ -1333,8 +1378,8 @@ static int ath10k_update_channel_list(struct ath10k *ar) | |||
| 1333 | continue; | 1378 | continue; |
| 1334 | 1379 | ||
| 1335 | ath10k_dbg(ATH10K_DBG_WMI, | 1380 | ath10k_dbg(ATH10K_DBG_WMI, |
| 1336 | "%s: [%zd/%d] freq %d maxpower %d regpower %d antenna %d mode %d\n", | 1381 | "mac channel [%zd/%d] freq %d maxpower %d regpower %d antenna %d mode %d\n", |
| 1337 | __func__, ch - arg.channels, arg.n_channels, | 1382 | ch - arg.channels, arg.n_channels, |
| 1338 | ch->freq, ch->max_power, ch->max_reg_power, | 1383 | ch->freq, ch->max_power, ch->max_reg_power, |
| 1339 | ch->max_antenna_gain, ch->mode); | 1384 | ch->max_antenna_gain, ch->mode); |
| 1340 | 1385 | ||
| @@ -1391,6 +1436,33 @@ static void ath10k_reg_notifier(struct wiphy *wiphy, | |||
| 1391 | /* TX handlers */ | 1436 | /* TX handlers */ |
| 1392 | /***************/ | 1437 | /***************/ |
| 1393 | 1438 | ||
| 1439 | static u8 ath10k_tx_h_get_tid(struct ieee80211_hdr *hdr) | ||
| 1440 | { | ||
| 1441 | if (ieee80211_is_mgmt(hdr->frame_control)) | ||
| 1442 | return HTT_DATA_TX_EXT_TID_MGMT; | ||
| 1443 | |||
| 1444 | if (!ieee80211_is_data_qos(hdr->frame_control)) | ||
| 1445 | return HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST; | ||
| 1446 | |||
| 1447 | if (!is_unicast_ether_addr(ieee80211_get_DA(hdr))) | ||
| 1448 | return HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST; | ||
| 1449 | |||
| 1450 | return ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
| 1451 | } | ||
| 1452 | |||
| 1453 | static u8 ath10k_tx_h_get_vdev_id(struct ath10k *ar, | ||
| 1454 | struct ieee80211_tx_info *info) | ||
| 1455 | { | ||
| 1456 | if (info->control.vif) | ||
| 1457 | return ath10k_vif_to_arvif(info->control.vif)->vdev_id; | ||
| 1458 | |||
| 1459 | if (ar->monitor_enabled) | ||
| 1460 | return ar->monitor_vdev_id; | ||
| 1461 | |||
| 1462 | ath10k_warn("could not resolve vdev id\n"); | ||
| 1463 | return 0; | ||
| 1464 | } | ||
| 1465 | |||
| 1394 | /* | 1466 | /* |
| 1395 | * Frames sent to the FW have to be in "Native Wifi" format. | 1467 | * Frames sent to the FW have to be in "Native Wifi" format. |
| 1396 | * Strip the QoS field from the 802.11 header. | 1468 | * Strip the QoS field from the 802.11 header. |
| @@ -1411,6 +1483,30 @@ static void ath10k_tx_h_qos_workaround(struct ieee80211_hw *hw, | |||
| 1411 | skb_pull(skb, IEEE80211_QOS_CTL_LEN); | 1483 | skb_pull(skb, IEEE80211_QOS_CTL_LEN); |
| 1412 | } | 1484 | } |
| 1413 | 1485 | ||
| 1486 | static void ath10k_tx_wep_key_work(struct work_struct *work) | ||
| 1487 | { | ||
| 1488 | struct ath10k_vif *arvif = container_of(work, struct ath10k_vif, | ||
| 1489 | wep_key_work); | ||
| 1490 | int ret, keyidx = arvif->def_wep_key_newidx; | ||
| 1491 | |||
| 1492 | if (arvif->def_wep_key_idx == keyidx) | ||
| 1493 | return; | ||
| 1494 | |||
| 1495 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d set keyidx %d\n", | ||
| 1496 | arvif->vdev_id, keyidx); | ||
| 1497 | |||
| 1498 | ret = ath10k_wmi_vdev_set_param(arvif->ar, | ||
| 1499 | arvif->vdev_id, | ||
| 1500 | arvif->ar->wmi.vdev_param->def_keyid, | ||
| 1501 | keyidx); | ||
| 1502 | if (ret) { | ||
| 1503 | ath10k_warn("could not update wep keyidx (%d)\n", ret); | ||
| 1504 | return; | ||
| 1505 | } | ||
| 1506 | |||
| 1507 | arvif->def_wep_key_idx = keyidx; | ||
| 1508 | } | ||
| 1509 | |||
| 1414 | static void ath10k_tx_h_update_wep_key(struct sk_buff *skb) | 1510 | static void ath10k_tx_h_update_wep_key(struct sk_buff *skb) |
| 1415 | { | 1511 | { |
| 1416 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1512 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
| @@ -1419,11 +1515,6 @@ static void ath10k_tx_h_update_wep_key(struct sk_buff *skb) | |||
| 1419 | struct ath10k *ar = arvif->ar; | 1515 | struct ath10k *ar = arvif->ar; |
| 1420 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 1516 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
| 1421 | struct ieee80211_key_conf *key = info->control.hw_key; | 1517 | struct ieee80211_key_conf *key = info->control.hw_key; |
| 1422 | int ret; | ||
| 1423 | |||
| 1424 | /* TODO AP mode should be implemented */ | ||
| 1425 | if (vif->type != NL80211_IFTYPE_STATION) | ||
| 1426 | return; | ||
| 1427 | 1518 | ||
| 1428 | if (!ieee80211_has_protected(hdr->frame_control)) | 1519 | if (!ieee80211_has_protected(hdr->frame_control)) |
| 1429 | return; | 1520 | return; |
| @@ -1435,20 +1526,14 @@ static void ath10k_tx_h_update_wep_key(struct sk_buff *skb) | |||
| 1435 | key->cipher != WLAN_CIPHER_SUITE_WEP104) | 1526 | key->cipher != WLAN_CIPHER_SUITE_WEP104) |
| 1436 | return; | 1527 | return; |
| 1437 | 1528 | ||
| 1438 | if (key->keyidx == arvif->def_wep_key_index) | 1529 | if (key->keyidx == arvif->def_wep_key_idx) |
| 1439 | return; | 1530 | return; |
| 1440 | 1531 | ||
| 1441 | ath10k_dbg(ATH10K_DBG_MAC, "new wep keyidx will be %d\n", key->keyidx); | 1532 | /* FIXME: Most likely a few frames will be TXed with an old key. Simply |
| 1442 | 1533 | * queueing frames until key index is updated is not an option because | |
| 1443 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, | 1534 | * sk_buff may need more processing to be done, e.g. offchannel */ |
| 1444 | WMI_VDEV_PARAM_DEF_KEYID, | 1535 | arvif->def_wep_key_newidx = key->keyidx; |
| 1445 | key->keyidx); | 1536 | ieee80211_queue_work(ar->hw, &arvif->wep_key_work); |
| 1446 | if (ret) { | ||
| 1447 | ath10k_warn("could not update wep keyidx (%d)\n", ret); | ||
| 1448 | return; | ||
| 1449 | } | ||
| 1450 | |||
| 1451 | arvif->def_wep_key_index = key->keyidx; | ||
| 1452 | } | 1537 | } |
| 1453 | 1538 | ||
| 1454 | static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, struct sk_buff *skb) | 1539 | static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, struct sk_buff *skb) |
| @@ -1478,19 +1563,42 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, struct sk_buff *skb) | |||
| 1478 | static void ath10k_tx_htt(struct ath10k *ar, struct sk_buff *skb) | 1563 | static void ath10k_tx_htt(struct ath10k *ar, struct sk_buff *skb) |
| 1479 | { | 1564 | { |
| 1480 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 1565 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
| 1481 | int ret; | 1566 | int ret = 0; |
| 1482 | 1567 | ||
| 1483 | if (ieee80211_is_mgmt(hdr->frame_control)) | 1568 | if (ar->htt.target_version_major >= 3) { |
| 1484 | ret = ath10k_htt_mgmt_tx(&ar->htt, skb); | 1569 | /* Since HTT 3.0 there is no separate mgmt tx command */ |
| 1485 | else if (ieee80211_is_nullfunc(hdr->frame_control)) | 1570 | ret = ath10k_htt_tx(&ar->htt, skb); |
| 1571 | goto exit; | ||
| 1572 | } | ||
| 1573 | |||
| 1574 | if (ieee80211_is_mgmt(hdr->frame_control)) { | ||
| 1575 | if (test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX, | ||
| 1576 | ar->fw_features)) { | ||
| 1577 | if (skb_queue_len(&ar->wmi_mgmt_tx_queue) >= | ||
| 1578 | ATH10K_MAX_NUM_MGMT_PENDING) { | ||
| 1579 | ath10k_warn("wmi mgmt_tx queue limit reached\n"); | ||
| 1580 | ret = -EBUSY; | ||
| 1581 | goto exit; | ||
| 1582 | } | ||
| 1583 | |||
| 1584 | skb_queue_tail(&ar->wmi_mgmt_tx_queue, skb); | ||
| 1585 | ieee80211_queue_work(ar->hw, &ar->wmi_mgmt_tx_work); | ||
| 1586 | } else { | ||
| 1587 | ret = ath10k_htt_mgmt_tx(&ar->htt, skb); | ||
| 1588 | } | ||
| 1589 | } else if (!test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX, | ||
| 1590 | ar->fw_features) && | ||
| 1591 | ieee80211_is_nullfunc(hdr->frame_control)) { | ||
| 1486 | /* FW does not report tx status properly for NullFunc frames | 1592 | /* FW does not report tx status properly for NullFunc frames |
| 1487 | * unless they are sent through mgmt tx path. mac80211 sends | 1593 | * unless they are sent through mgmt tx path. mac80211 sends |
| 1488 | * those frames when it detects link/beacon loss and depends on | 1594 | * those frames when it detects link/beacon loss and depends |
| 1489 | * the tx status to be correct. */ | 1595 | * on the tx status to be correct. */ |
| 1490 | ret = ath10k_htt_mgmt_tx(&ar->htt, skb); | 1596 | ret = ath10k_htt_mgmt_tx(&ar->htt, skb); |
| 1491 | else | 1597 | } else { |
| 1492 | ret = ath10k_htt_tx(&ar->htt, skb); | 1598 | ret = ath10k_htt_tx(&ar->htt, skb); |
| 1599 | } | ||
| 1493 | 1600 | ||
| 1601 | exit: | ||
| 1494 | if (ret) { | 1602 | if (ret) { |
| 1495 | ath10k_warn("tx failed (%d). dropping packet.\n", ret); | 1603 | ath10k_warn("tx failed (%d). dropping packet.\n", ret); |
| 1496 | ieee80211_free_txskb(ar->hw, skb); | 1604 | ieee80211_free_txskb(ar->hw, skb); |
| @@ -1534,18 +1642,19 @@ void ath10k_offchan_tx_work(struct work_struct *work) | |||
| 1534 | 1642 | ||
| 1535 | mutex_lock(&ar->conf_mutex); | 1643 | mutex_lock(&ar->conf_mutex); |
| 1536 | 1644 | ||
| 1537 | ath10k_dbg(ATH10K_DBG_MAC, "processing offchannel skb %p\n", | 1645 | ath10k_dbg(ATH10K_DBG_MAC, "mac offchannel skb %p\n", |
| 1538 | skb); | 1646 | skb); |
| 1539 | 1647 | ||
| 1540 | hdr = (struct ieee80211_hdr *)skb->data; | 1648 | hdr = (struct ieee80211_hdr *)skb->data; |
| 1541 | peer_addr = ieee80211_get_DA(hdr); | 1649 | peer_addr = ieee80211_get_DA(hdr); |
| 1542 | vdev_id = ATH10K_SKB_CB(skb)->htt.vdev_id; | 1650 | vdev_id = ATH10K_SKB_CB(skb)->vdev_id; |
| 1543 | 1651 | ||
| 1544 | spin_lock_bh(&ar->data_lock); | 1652 | spin_lock_bh(&ar->data_lock); |
| 1545 | peer = ath10k_peer_find(ar, vdev_id, peer_addr); | 1653 | peer = ath10k_peer_find(ar, vdev_id, peer_addr); |
| 1546 | spin_unlock_bh(&ar->data_lock); | 1654 | spin_unlock_bh(&ar->data_lock); |
| 1547 | 1655 | ||
| 1548 | if (peer) | 1656 | if (peer) |
| 1657 | /* FIXME: should this use ath10k_warn()? */ | ||
| 1549 | ath10k_dbg(ATH10K_DBG_MAC, "peer %pM on vdev %d already present\n", | 1658 | ath10k_dbg(ATH10K_DBG_MAC, "peer %pM on vdev %d already present\n", |
| 1550 | peer_addr, vdev_id); | 1659 | peer_addr, vdev_id); |
| 1551 | 1660 | ||
| @@ -1580,6 +1689,36 @@ void ath10k_offchan_tx_work(struct work_struct *work) | |||
| 1580 | } | 1689 | } |
| 1581 | } | 1690 | } |
| 1582 | 1691 | ||
| 1692 | void ath10k_mgmt_over_wmi_tx_purge(struct ath10k *ar) | ||
| 1693 | { | ||
| 1694 | struct sk_buff *skb; | ||
| 1695 | |||
| 1696 | for (;;) { | ||
| 1697 | skb = skb_dequeue(&ar->wmi_mgmt_tx_queue); | ||
| 1698 | if (!skb) | ||
| 1699 | break; | ||
| 1700 | |||
| 1701 | ieee80211_free_txskb(ar->hw, skb); | ||
| 1702 | } | ||
| 1703 | } | ||
| 1704 | |||
| 1705 | void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work) | ||
| 1706 | { | ||
| 1707 | struct ath10k *ar = container_of(work, struct ath10k, wmi_mgmt_tx_work); | ||
| 1708 | struct sk_buff *skb; | ||
| 1709 | int ret; | ||
| 1710 | |||
| 1711 | for (;;) { | ||
| 1712 | skb = skb_dequeue(&ar->wmi_mgmt_tx_queue); | ||
| 1713 | if (!skb) | ||
| 1714 | break; | ||
| 1715 | |||
| 1716 | ret = ath10k_wmi_mgmt_tx(ar, skb); | ||
| 1717 | if (ret) | ||
| 1718 | ath10k_warn("wmi mgmt_tx failed (%d)\n", ret); | ||
| 1719 | } | ||
| 1720 | } | ||
| 1721 | |||
| 1583 | /************/ | 1722 | /************/ |
| 1584 | /* Scanning */ | 1723 | /* Scanning */ |
| 1585 | /************/ | 1724 | /************/ |
| @@ -1643,8 +1782,6 @@ static int ath10k_abort_scan(struct ath10k *ar) | |||
| 1643 | return -EIO; | 1782 | return -EIO; |
| 1644 | } | 1783 | } |
| 1645 | 1784 | ||
| 1646 | ath10k_wmi_flush_tx(ar); | ||
| 1647 | |||
| 1648 | ret = wait_for_completion_timeout(&ar->scan.completed, 3*HZ); | 1785 | ret = wait_for_completion_timeout(&ar->scan.completed, 3*HZ); |
| 1649 | if (ret == 0) | 1786 | if (ret == 0) |
| 1650 | ath10k_warn("timed out while waiting for scan to stop\n"); | 1787 | ath10k_warn("timed out while waiting for scan to stop\n"); |
| @@ -1678,10 +1815,6 @@ static int ath10k_start_scan(struct ath10k *ar, | |||
| 1678 | if (ret) | 1815 | if (ret) |
| 1679 | return ret; | 1816 | return ret; |
| 1680 | 1817 | ||
| 1681 | /* make sure we submit the command so the completion | ||
| 1682 | * timeout makes sense */ | ||
| 1683 | ath10k_wmi_flush_tx(ar); | ||
| 1684 | |||
| 1685 | ret = wait_for_completion_timeout(&ar->scan.started, 1*HZ); | 1818 | ret = wait_for_completion_timeout(&ar->scan.started, 1*HZ); |
| 1686 | if (ret == 0) { | 1819 | if (ret == 0) { |
| 1687 | ath10k_abort_scan(ar); | 1820 | ath10k_abort_scan(ar); |
| @@ -1709,16 +1842,7 @@ static void ath10k_tx(struct ieee80211_hw *hw, | |||
| 1709 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1842 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
| 1710 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 1843 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
| 1711 | struct ath10k *ar = hw->priv; | 1844 | struct ath10k *ar = hw->priv; |
| 1712 | struct ath10k_vif *arvif = NULL; | 1845 | u8 tid, vdev_id; |
| 1713 | u32 vdev_id = 0; | ||
| 1714 | u8 tid; | ||
| 1715 | |||
| 1716 | if (info->control.vif) { | ||
| 1717 | arvif = ath10k_vif_to_arvif(info->control.vif); | ||
| 1718 | vdev_id = arvif->vdev_id; | ||
| 1719 | } else if (ar->monitor_enabled) { | ||
| 1720 | vdev_id = ar->monitor_vdev_id; | ||
| 1721 | } | ||
| 1722 | 1846 | ||
| 1723 | /* We should disable CCK RATE due to P2P */ | 1847 | /* We should disable CCK RATE due to P2P */ |
| 1724 | if (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE) | 1848 | if (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE) |
| @@ -1726,12 +1850,8 @@ static void ath10k_tx(struct ieee80211_hw *hw, | |||
| 1726 | 1850 | ||
| 1727 | /* we must calculate tid before we apply qos workaround | 1851 | /* we must calculate tid before we apply qos workaround |
| 1728 | * as we'd lose the qos control field */ | 1852 | * as we'd lose the qos control field */ |
| 1729 | tid = HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST; | 1853 | tid = ath10k_tx_h_get_tid(hdr); |
| 1730 | if (ieee80211_is_data_qos(hdr->frame_control) && | 1854 | vdev_id = ath10k_tx_h_get_vdev_id(ar, info); |
| 1731 | is_unicast_ether_addr(ieee80211_get_DA(hdr))) { | ||
| 1732 | u8 *qc = ieee80211_get_qos_ctl(hdr); | ||
| 1733 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
| 1734 | } | ||
| 1735 | 1855 | ||
| 1736 | /* it makes no sense to process injected frames like that */ | 1856 | /* it makes no sense to process injected frames like that */ |
| 1737 | if (info->control.vif && | 1857 | if (info->control.vif && |
| @@ -1742,14 +1862,14 @@ static void ath10k_tx(struct ieee80211_hw *hw, | |||
| 1742 | ath10k_tx_h_seq_no(skb); | 1862 | ath10k_tx_h_seq_no(skb); |
| 1743 | } | 1863 | } |
| 1744 | 1864 | ||
| 1745 | memset(ATH10K_SKB_CB(skb), 0, sizeof(*ATH10K_SKB_CB(skb))); | 1865 | ATH10K_SKB_CB(skb)->vdev_id = vdev_id; |
| 1746 | ATH10K_SKB_CB(skb)->htt.vdev_id = vdev_id; | 1866 | ATH10K_SKB_CB(skb)->htt.is_offchan = false; |
| 1747 | ATH10K_SKB_CB(skb)->htt.tid = tid; | 1867 | ATH10K_SKB_CB(skb)->htt.tid = tid; |
| 1748 | 1868 | ||
| 1749 | if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) { | 1869 | if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) { |
| 1750 | spin_lock_bh(&ar->data_lock); | 1870 | spin_lock_bh(&ar->data_lock); |
| 1751 | ATH10K_SKB_CB(skb)->htt.is_offchan = true; | 1871 | ATH10K_SKB_CB(skb)->htt.is_offchan = true; |
| 1752 | ATH10K_SKB_CB(skb)->htt.vdev_id = ar->scan.vdev_id; | 1872 | ATH10K_SKB_CB(skb)->vdev_id = ar->scan.vdev_id; |
| 1753 | spin_unlock_bh(&ar->data_lock); | 1873 | spin_unlock_bh(&ar->data_lock); |
| 1754 | 1874 | ||
| 1755 | ath10k_dbg(ATH10K_DBG_MAC, "queued offchannel skb %p\n", skb); | 1875 | ath10k_dbg(ATH10K_DBG_MAC, "queued offchannel skb %p\n", skb); |
| @@ -1771,6 +1891,7 @@ void ath10k_halt(struct ath10k *ar) | |||
| 1771 | 1891 | ||
| 1772 | del_timer_sync(&ar->scan.timeout); | 1892 | del_timer_sync(&ar->scan.timeout); |
| 1773 | ath10k_offchan_tx_purge(ar); | 1893 | ath10k_offchan_tx_purge(ar); |
| 1894 | ath10k_mgmt_over_wmi_tx_purge(ar); | ||
| 1774 | ath10k_peer_cleanup_all(ar); | 1895 | ath10k_peer_cleanup_all(ar); |
| 1775 | ath10k_core_stop(ar); | 1896 | ath10k_core_stop(ar); |
| 1776 | ath10k_hif_power_down(ar); | 1897 | ath10k_hif_power_down(ar); |
| @@ -1817,12 +1938,12 @@ static int ath10k_start(struct ieee80211_hw *hw) | |||
| 1817 | else if (ar->state == ATH10K_STATE_RESTARTING) | 1938 | else if (ar->state == ATH10K_STATE_RESTARTING) |
| 1818 | ar->state = ATH10K_STATE_RESTARTED; | 1939 | ar->state = ATH10K_STATE_RESTARTED; |
| 1819 | 1940 | ||
| 1820 | ret = ath10k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PMF_QOS, 1); | 1941 | ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->pmf_qos, 1); |
| 1821 | if (ret) | 1942 | if (ret) |
| 1822 | ath10k_warn("could not enable WMI_PDEV_PARAM_PMF_QOS (%d)\n", | 1943 | ath10k_warn("could not enable WMI_PDEV_PARAM_PMF_QOS (%d)\n", |
| 1823 | ret); | 1944 | ret); |
| 1824 | 1945 | ||
| 1825 | ret = ath10k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_DYNAMIC_BW, 0); | 1946 | ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->dynamic_bw, 0); |
| 1826 | if (ret) | 1947 | if (ret) |
| 1827 | ath10k_warn("could not init WMI_PDEV_PARAM_DYNAMIC_BW (%d)\n", | 1948 | ath10k_warn("could not init WMI_PDEV_PARAM_DYNAMIC_BW (%d)\n", |
| 1828 | ret); | 1949 | ret); |
| @@ -1847,32 +1968,29 @@ static void ath10k_stop(struct ieee80211_hw *hw) | |||
| 1847 | ar->state = ATH10K_STATE_OFF; | 1968 | ar->state = ATH10K_STATE_OFF; |
| 1848 | mutex_unlock(&ar->conf_mutex); | 1969 | mutex_unlock(&ar->conf_mutex); |
| 1849 | 1970 | ||
| 1971 | ath10k_mgmt_over_wmi_tx_purge(ar); | ||
| 1972 | |||
| 1850 | cancel_work_sync(&ar->offchan_tx_work); | 1973 | cancel_work_sync(&ar->offchan_tx_work); |
| 1974 | cancel_work_sync(&ar->wmi_mgmt_tx_work); | ||
| 1851 | cancel_work_sync(&ar->restart_work); | 1975 | cancel_work_sync(&ar->restart_work); |
| 1852 | } | 1976 | } |
| 1853 | 1977 | ||
| 1854 | static void ath10k_config_ps(struct ath10k *ar) | 1978 | static int ath10k_config_ps(struct ath10k *ar) |
| 1855 | { | 1979 | { |
| 1856 | struct ath10k_generic_iter ar_iter; | 1980 | struct ath10k_vif *arvif; |
| 1981 | int ret = 0; | ||
| 1857 | 1982 | ||
| 1858 | lockdep_assert_held(&ar->conf_mutex); | 1983 | lockdep_assert_held(&ar->conf_mutex); |
| 1859 | 1984 | ||
| 1860 | /* During HW reconfiguration mac80211 reports all interfaces that were | 1985 | list_for_each_entry(arvif, &ar->arvifs, list) { |
| 1861 | * running until reconfiguration was started. Since FW doesn't have any | 1986 | ret = ath10k_mac_vif_setup_ps(arvif); |
| 1862 | * vdevs at this point we must not iterate over this interface list. | 1987 | if (ret) { |
| 1863 | * This setting will be updated upon add_interface(). */ | 1988 | ath10k_warn("could not setup powersave (%d)\n", ret); |
| 1864 | if (ar->state == ATH10K_STATE_RESTARTED) | 1989 | break; |
| 1865 | return; | 1990 | } |
| 1866 | 1991 | } | |
| 1867 | memset(&ar_iter, 0, sizeof(struct ath10k_generic_iter)); | ||
| 1868 | ar_iter.ar = ar; | ||
| 1869 | |||
| 1870 | ieee80211_iterate_active_interfaces_atomic( | ||
| 1871 | ar->hw, IEEE80211_IFACE_ITER_NORMAL, | ||
| 1872 | ath10k_ps_iter, &ar_iter); | ||
| 1873 | 1992 | ||
| 1874 | if (ar_iter.ret) | 1993 | return ret; |
| 1875 | ath10k_warn("failed to set ps config (%d)\n", ar_iter.ret); | ||
| 1876 | } | 1994 | } |
| 1877 | 1995 | ||
| 1878 | static int ath10k_config(struct ieee80211_hw *hw, u32 changed) | 1996 | static int ath10k_config(struct ieee80211_hw *hw, u32 changed) |
| @@ -1884,7 +2002,7 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed) | |||
| 1884 | mutex_lock(&ar->conf_mutex); | 2002 | mutex_lock(&ar->conf_mutex); |
| 1885 | 2003 | ||
| 1886 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | 2004 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { |
| 1887 | ath10k_dbg(ATH10K_DBG_MAC, "Config channel %d mhz\n", | 2005 | ath10k_dbg(ATH10K_DBG_MAC, "mac config channel %d mhz\n", |
| 1888 | conf->chandef.chan->center_freq); | 2006 | conf->chandef.chan->center_freq); |
| 1889 | spin_lock_bh(&ar->data_lock); | 2007 | spin_lock_bh(&ar->data_lock); |
| 1890 | ar->rx_channel = conf->chandef.chan; | 2008 | ar->rx_channel = conf->chandef.chan; |
| @@ -1901,7 +2019,6 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed) | |||
| 1901 | ret = ath10k_monitor_destroy(ar); | 2019 | ret = ath10k_monitor_destroy(ar); |
| 1902 | } | 2020 | } |
| 1903 | 2021 | ||
| 1904 | ath10k_wmi_flush_tx(ar); | ||
| 1905 | mutex_unlock(&ar->conf_mutex); | 2022 | mutex_unlock(&ar->conf_mutex); |
| 1906 | return ret; | 2023 | return ret; |
| 1907 | } | 2024 | } |
| @@ -1922,6 +2039,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
| 1922 | int ret = 0; | 2039 | int ret = 0; |
| 1923 | u32 value; | 2040 | u32 value; |
| 1924 | int bit; | 2041 | int bit; |
| 2042 | u32 vdev_param; | ||
| 1925 | 2043 | ||
| 1926 | mutex_lock(&ar->conf_mutex); | 2044 | mutex_lock(&ar->conf_mutex); |
| 1927 | 2045 | ||
| @@ -1930,21 +2048,22 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
| 1930 | arvif->ar = ar; | 2048 | arvif->ar = ar; |
| 1931 | arvif->vif = vif; | 2049 | arvif->vif = vif; |
| 1932 | 2050 | ||
| 2051 | INIT_WORK(&arvif->wep_key_work, ath10k_tx_wep_key_work); | ||
| 2052 | |||
| 1933 | if ((vif->type == NL80211_IFTYPE_MONITOR) && ar->monitor_present) { | 2053 | if ((vif->type == NL80211_IFTYPE_MONITOR) && ar->monitor_present) { |
| 1934 | ath10k_warn("Only one monitor interface allowed\n"); | 2054 | ath10k_warn("Only one monitor interface allowed\n"); |
| 1935 | ret = -EBUSY; | 2055 | ret = -EBUSY; |
| 1936 | goto exit; | 2056 | goto err; |
| 1937 | } | 2057 | } |
| 1938 | 2058 | ||
| 1939 | bit = ffs(ar->free_vdev_map); | 2059 | bit = ffs(ar->free_vdev_map); |
| 1940 | if (bit == 0) { | 2060 | if (bit == 0) { |
| 1941 | ret = -EBUSY; | 2061 | ret = -EBUSY; |
| 1942 | goto exit; | 2062 | goto err; |
| 1943 | } | 2063 | } |
| 1944 | 2064 | ||
| 1945 | arvif->vdev_id = bit - 1; | 2065 | arvif->vdev_id = bit - 1; |
| 1946 | arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE; | 2066 | arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE; |
| 1947 | ar->free_vdev_map &= ~(1 << arvif->vdev_id); | ||
| 1948 | 2067 | ||
| 1949 | if (ar->p2p) | 2068 | if (ar->p2p) |
| 1950 | arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE; | 2069 | arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE; |
| @@ -1973,32 +2092,41 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
| 1973 | break; | 2092 | break; |
| 1974 | } | 2093 | } |
| 1975 | 2094 | ||
| 1976 | ath10k_dbg(ATH10K_DBG_MAC, "Add interface: id %d type %d subtype %d\n", | 2095 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev create %d (add interface) type %d subtype %d\n", |
| 1977 | arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype); | 2096 | arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype); |
| 1978 | 2097 | ||
| 1979 | ret = ath10k_wmi_vdev_create(ar, arvif->vdev_id, arvif->vdev_type, | 2098 | ret = ath10k_wmi_vdev_create(ar, arvif->vdev_id, arvif->vdev_type, |
| 1980 | arvif->vdev_subtype, vif->addr); | 2099 | arvif->vdev_subtype, vif->addr); |
| 1981 | if (ret) { | 2100 | if (ret) { |
| 1982 | ath10k_warn("WMI vdev create failed: ret %d\n", ret); | 2101 | ath10k_warn("WMI vdev create failed: ret %d\n", ret); |
| 1983 | goto exit; | 2102 | goto err; |
| 1984 | } | 2103 | } |
| 1985 | 2104 | ||
| 1986 | ret = ath10k_wmi_vdev_set_param(ar, 0, WMI_VDEV_PARAM_DEF_KEYID, | 2105 | ar->free_vdev_map &= ~BIT(arvif->vdev_id); |
| 1987 | arvif->def_wep_key_index); | 2106 | list_add(&arvif->list, &ar->arvifs); |
| 1988 | if (ret) | 2107 | |
| 2108 | vdev_param = ar->wmi.vdev_param->def_keyid; | ||
| 2109 | ret = ath10k_wmi_vdev_set_param(ar, 0, vdev_param, | ||
| 2110 | arvif->def_wep_key_idx); | ||
| 2111 | if (ret) { | ||
| 1989 | ath10k_warn("Failed to set default keyid: %d\n", ret); | 2112 | ath10k_warn("Failed to set default keyid: %d\n", ret); |
| 2113 | goto err_vdev_delete; | ||
| 2114 | } | ||
| 1990 | 2115 | ||
| 1991 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, | 2116 | vdev_param = ar->wmi.vdev_param->tx_encap_type; |
| 1992 | WMI_VDEV_PARAM_TX_ENCAP_TYPE, | 2117 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, |
| 1993 | ATH10K_HW_TXRX_NATIVE_WIFI); | 2118 | ATH10K_HW_TXRX_NATIVE_WIFI); |
| 1994 | if (ret) | 2119 | /* 10.X firmware does not support this VDEV parameter. Do not warn */ |
| 2120 | if (ret && ret != -EOPNOTSUPP) { | ||
| 1995 | ath10k_warn("Failed to set TX encap: %d\n", ret); | 2121 | ath10k_warn("Failed to set TX encap: %d\n", ret); |
| 2122 | goto err_vdev_delete; | ||
| 2123 | } | ||
| 1996 | 2124 | ||
| 1997 | if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { | 2125 | if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { |
| 1998 | ret = ath10k_peer_create(ar, arvif->vdev_id, vif->addr); | 2126 | ret = ath10k_peer_create(ar, arvif->vdev_id, vif->addr); |
| 1999 | if (ret) { | 2127 | if (ret) { |
| 2000 | ath10k_warn("Failed to create peer for AP: %d\n", ret); | 2128 | ath10k_warn("Failed to create peer for AP: %d\n", ret); |
| 2001 | goto exit; | 2129 | goto err_vdev_delete; |
| 2002 | } | 2130 | } |
| 2003 | } | 2131 | } |
| 2004 | 2132 | ||
| @@ -2007,39 +2135,62 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
| 2007 | value = WMI_STA_PS_RX_WAKE_POLICY_WAKE; | 2135 | value = WMI_STA_PS_RX_WAKE_POLICY_WAKE; |
| 2008 | ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, | 2136 | ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, |
| 2009 | param, value); | 2137 | param, value); |
| 2010 | if (ret) | 2138 | if (ret) { |
| 2011 | ath10k_warn("Failed to set RX wake policy: %d\n", ret); | 2139 | ath10k_warn("Failed to set RX wake policy: %d\n", ret); |
| 2140 | goto err_peer_delete; | ||
| 2141 | } | ||
| 2012 | 2142 | ||
| 2013 | param = WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD; | 2143 | param = WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD; |
| 2014 | value = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS; | 2144 | value = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS; |
| 2015 | ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, | 2145 | ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, |
| 2016 | param, value); | 2146 | param, value); |
| 2017 | if (ret) | 2147 | if (ret) { |
| 2018 | ath10k_warn("Failed to set TX wake thresh: %d\n", ret); | 2148 | ath10k_warn("Failed to set TX wake thresh: %d\n", ret); |
| 2149 | goto err_peer_delete; | ||
| 2150 | } | ||
| 2019 | 2151 | ||
| 2020 | param = WMI_STA_PS_PARAM_PSPOLL_COUNT; | 2152 | param = WMI_STA_PS_PARAM_PSPOLL_COUNT; |
| 2021 | value = WMI_STA_PS_PSPOLL_COUNT_NO_MAX; | 2153 | value = WMI_STA_PS_PSPOLL_COUNT_NO_MAX; |
| 2022 | ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, | 2154 | ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, |
| 2023 | param, value); | 2155 | param, value); |
| 2024 | if (ret) | 2156 | if (ret) { |
| 2025 | ath10k_warn("Failed to set PSPOLL count: %d\n", ret); | 2157 | ath10k_warn("Failed to set PSPOLL count: %d\n", ret); |
| 2158 | goto err_peer_delete; | ||
| 2159 | } | ||
| 2026 | } | 2160 | } |
| 2027 | 2161 | ||
| 2028 | ret = ath10k_mac_set_rts(arvif, ar->hw->wiphy->rts_threshold); | 2162 | ret = ath10k_mac_set_rts(arvif, ar->hw->wiphy->rts_threshold); |
| 2029 | if (ret) | 2163 | if (ret) { |
| 2030 | ath10k_warn("failed to set rts threshold for vdev %d (%d)\n", | 2164 | ath10k_warn("failed to set rts threshold for vdev %d (%d)\n", |
| 2031 | arvif->vdev_id, ret); | 2165 | arvif->vdev_id, ret); |
| 2166 | goto err_peer_delete; | ||
| 2167 | } | ||
| 2032 | 2168 | ||
| 2033 | ret = ath10k_mac_set_frag(arvif, ar->hw->wiphy->frag_threshold); | 2169 | ret = ath10k_mac_set_frag(arvif, ar->hw->wiphy->frag_threshold); |
| 2034 | if (ret) | 2170 | if (ret) { |
| 2035 | ath10k_warn("failed to set frag threshold for vdev %d (%d)\n", | 2171 | ath10k_warn("failed to set frag threshold for vdev %d (%d)\n", |
| 2036 | arvif->vdev_id, ret); | 2172 | arvif->vdev_id, ret); |
| 2173 | goto err_peer_delete; | ||
| 2174 | } | ||
| 2037 | 2175 | ||
| 2038 | if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) | 2176 | if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) |
| 2039 | ar->monitor_present = true; | 2177 | ar->monitor_present = true; |
| 2040 | 2178 | ||
| 2041 | exit: | ||
| 2042 | mutex_unlock(&ar->conf_mutex); | 2179 | mutex_unlock(&ar->conf_mutex); |
| 2180 | return 0; | ||
| 2181 | |||
| 2182 | err_peer_delete: | ||
| 2183 | if (arvif->vdev_type == WMI_VDEV_TYPE_AP) | ||
| 2184 | ath10k_wmi_peer_delete(ar, arvif->vdev_id, vif->addr); | ||
| 2185 | |||
| 2186 | err_vdev_delete: | ||
| 2187 | ath10k_wmi_vdev_delete(ar, arvif->vdev_id); | ||
| 2188 | ar->free_vdev_map &= ~BIT(arvif->vdev_id); | ||
| 2189 | list_del(&arvif->list); | ||
| 2190 | |||
| 2191 | err: | ||
| 2192 | mutex_unlock(&ar->conf_mutex); | ||
| 2193 | |||
| 2043 | return ret; | 2194 | return ret; |
| 2044 | } | 2195 | } |
| 2045 | 2196 | ||
| @@ -2052,9 +2203,17 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, | |||
| 2052 | 2203 | ||
| 2053 | mutex_lock(&ar->conf_mutex); | 2204 | mutex_lock(&ar->conf_mutex); |
| 2054 | 2205 | ||
| 2055 | ath10k_dbg(ATH10K_DBG_MAC, "Remove interface: id %d\n", arvif->vdev_id); | 2206 | cancel_work_sync(&arvif->wep_key_work); |
| 2207 | |||
| 2208 | spin_lock_bh(&ar->data_lock); | ||
| 2209 | if (arvif->beacon) { | ||
| 2210 | dev_kfree_skb_any(arvif->beacon); | ||
| 2211 | arvif->beacon = NULL; | ||
| 2212 | } | ||
| 2213 | spin_unlock_bh(&ar->data_lock); | ||
| 2056 | 2214 | ||
| 2057 | ar->free_vdev_map |= 1 << (arvif->vdev_id); | 2215 | ar->free_vdev_map |= 1 << (arvif->vdev_id); |
| 2216 | list_del(&arvif->list); | ||
| 2058 | 2217 | ||
| 2059 | if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { | 2218 | if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { |
| 2060 | ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id, vif->addr); | 2219 | ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id, vif->addr); |
| @@ -2064,6 +2223,9 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, | |||
| 2064 | kfree(arvif->u.ap.noa_data); | 2223 | kfree(arvif->u.ap.noa_data); |
| 2065 | } | 2224 | } |
| 2066 | 2225 | ||
| 2226 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev delete %d (remove interface)\n", | ||
| 2227 | arvif->vdev_id); | ||
| 2228 | |||
| 2067 | ret = ath10k_wmi_vdev_delete(ar, arvif->vdev_id); | 2229 | ret = ath10k_wmi_vdev_delete(ar, arvif->vdev_id); |
| 2068 | if (ret) | 2230 | if (ret) |
| 2069 | ath10k_warn("WMI vdev delete failed: %d\n", ret); | 2231 | ath10k_warn("WMI vdev delete failed: %d\n", ret); |
| @@ -2105,18 +2267,20 @@ static void ath10k_configure_filter(struct ieee80211_hw *hw, | |||
| 2105 | 2267 | ||
| 2106 | if ((ar->filter_flags & FIF_PROMISC_IN_BSS) && | 2268 | if ((ar->filter_flags & FIF_PROMISC_IN_BSS) && |
| 2107 | !ar->monitor_enabled) { | 2269 | !ar->monitor_enabled) { |
| 2270 | ath10k_dbg(ATH10K_DBG_MAC, "mac monitor %d start\n", | ||
| 2271 | ar->monitor_vdev_id); | ||
| 2272 | |||
| 2108 | ret = ath10k_monitor_start(ar, ar->monitor_vdev_id); | 2273 | ret = ath10k_monitor_start(ar, ar->monitor_vdev_id); |
| 2109 | if (ret) | 2274 | if (ret) |
| 2110 | ath10k_warn("Unable to start monitor mode\n"); | 2275 | ath10k_warn("Unable to start monitor mode\n"); |
| 2111 | else | ||
| 2112 | ath10k_dbg(ATH10K_DBG_MAC, "Monitor mode started\n"); | ||
| 2113 | } else if (!(ar->filter_flags & FIF_PROMISC_IN_BSS) && | 2276 | } else if (!(ar->filter_flags & FIF_PROMISC_IN_BSS) && |
| 2114 | ar->monitor_enabled) { | 2277 | ar->monitor_enabled) { |
| 2278 | ath10k_dbg(ATH10K_DBG_MAC, "mac monitor %d stop\n", | ||
| 2279 | ar->monitor_vdev_id); | ||
| 2280 | |||
| 2115 | ret = ath10k_monitor_stop(ar); | 2281 | ret = ath10k_monitor_stop(ar); |
| 2116 | if (ret) | 2282 | if (ret) |
| 2117 | ath10k_warn("Unable to stop monitor mode\n"); | 2283 | ath10k_warn("Unable to stop monitor mode\n"); |
| 2118 | else | ||
| 2119 | ath10k_dbg(ATH10K_DBG_MAC, "Monitor mode stopped\n"); | ||
| 2120 | } | 2284 | } |
| 2121 | 2285 | ||
| 2122 | mutex_unlock(&ar->conf_mutex); | 2286 | mutex_unlock(&ar->conf_mutex); |
| @@ -2130,6 +2294,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
| 2130 | struct ath10k *ar = hw->priv; | 2294 | struct ath10k *ar = hw->priv; |
| 2131 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | 2295 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); |
| 2132 | int ret = 0; | 2296 | int ret = 0; |
| 2297 | u32 vdev_param, pdev_param; | ||
| 2133 | 2298 | ||
| 2134 | mutex_lock(&ar->conf_mutex); | 2299 | mutex_lock(&ar->conf_mutex); |
| 2135 | 2300 | ||
| @@ -2138,44 +2303,44 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
| 2138 | 2303 | ||
| 2139 | if (changed & BSS_CHANGED_BEACON_INT) { | 2304 | if (changed & BSS_CHANGED_BEACON_INT) { |
| 2140 | arvif->beacon_interval = info->beacon_int; | 2305 | arvif->beacon_interval = info->beacon_int; |
| 2141 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, | 2306 | vdev_param = ar->wmi.vdev_param->beacon_interval; |
| 2142 | WMI_VDEV_PARAM_BEACON_INTERVAL, | 2307 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, |
| 2143 | arvif->beacon_interval); | 2308 | arvif->beacon_interval); |
| 2309 | ath10k_dbg(ATH10K_DBG_MAC, | ||
| 2310 | "mac vdev %d beacon_interval %d\n", | ||
| 2311 | arvif->vdev_id, arvif->beacon_interval); | ||
| 2312 | |||
| 2144 | if (ret) | 2313 | if (ret) |
| 2145 | ath10k_warn("Failed to set beacon interval for VDEV: %d\n", | 2314 | ath10k_warn("Failed to set beacon interval for VDEV: %d\n", |
| 2146 | arvif->vdev_id); | 2315 | arvif->vdev_id); |
| 2147 | else | ||
| 2148 | ath10k_dbg(ATH10K_DBG_MAC, | ||
| 2149 | "Beacon interval: %d set for VDEV: %d\n", | ||
| 2150 | arvif->beacon_interval, arvif->vdev_id); | ||
| 2151 | } | 2316 | } |
| 2152 | 2317 | ||
| 2153 | if (changed & BSS_CHANGED_BEACON) { | 2318 | if (changed & BSS_CHANGED_BEACON) { |
| 2154 | ret = ath10k_wmi_pdev_set_param(ar, | 2319 | ath10k_dbg(ATH10K_DBG_MAC, |
| 2155 | WMI_PDEV_PARAM_BEACON_TX_MODE, | 2320 | "vdev %d set beacon tx mode to staggered\n", |
| 2321 | arvif->vdev_id); | ||
| 2322 | |||
| 2323 | pdev_param = ar->wmi.pdev_param->beacon_tx_mode; | ||
| 2324 | ret = ath10k_wmi_pdev_set_param(ar, pdev_param, | ||
| 2156 | WMI_BEACON_STAGGERED_MODE); | 2325 | WMI_BEACON_STAGGERED_MODE); |
| 2157 | if (ret) | 2326 | if (ret) |
| 2158 | ath10k_warn("Failed to set beacon mode for VDEV: %d\n", | 2327 | ath10k_warn("Failed to set beacon mode for VDEV: %d\n", |
| 2159 | arvif->vdev_id); | 2328 | arvif->vdev_id); |
| 2160 | else | ||
| 2161 | ath10k_dbg(ATH10K_DBG_MAC, | ||
| 2162 | "Set staggered beacon mode for VDEV: %d\n", | ||
| 2163 | arvif->vdev_id); | ||
| 2164 | } | 2329 | } |
| 2165 | 2330 | ||
| 2166 | if (changed & BSS_CHANGED_BEACON_INFO) { | 2331 | if (changed & BSS_CHANGED_BEACON_INFO) { |
| 2167 | arvif->dtim_period = info->dtim_period; | 2332 | arvif->dtim_period = info->dtim_period; |
| 2168 | 2333 | ||
| 2169 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, | 2334 | ath10k_dbg(ATH10K_DBG_MAC, |
| 2170 | WMI_VDEV_PARAM_DTIM_PERIOD, | 2335 | "mac vdev %d dtim_period %d\n", |
| 2336 | arvif->vdev_id, arvif->dtim_period); | ||
| 2337 | |||
| 2338 | vdev_param = ar->wmi.vdev_param->dtim_period; | ||
| 2339 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, | ||
| 2171 | arvif->dtim_period); | 2340 | arvif->dtim_period); |
| 2172 | if (ret) | 2341 | if (ret) |
| 2173 | ath10k_warn("Failed to set dtim period for VDEV: %d\n", | 2342 | ath10k_warn("Failed to set dtim period for VDEV: %d\n", |
| 2174 | arvif->vdev_id); | 2343 | arvif->vdev_id); |
| 2175 | else | ||
| 2176 | ath10k_dbg(ATH10K_DBG_MAC, | ||
| 2177 | "Set dtim period: %d for VDEV: %d\n", | ||
| 2178 | arvif->dtim_period, arvif->vdev_id); | ||
| 2179 | } | 2344 | } |
| 2180 | 2345 | ||
| 2181 | if (changed & BSS_CHANGED_SSID && | 2346 | if (changed & BSS_CHANGED_SSID && |
| @@ -2188,16 +2353,15 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
| 2188 | 2353 | ||
| 2189 | if (changed & BSS_CHANGED_BSSID) { | 2354 | if (changed & BSS_CHANGED_BSSID) { |
| 2190 | if (!is_zero_ether_addr(info->bssid)) { | 2355 | if (!is_zero_ether_addr(info->bssid)) { |
| 2356 | ath10k_dbg(ATH10K_DBG_MAC, | ||
| 2357 | "mac vdev %d create peer %pM\n", | ||
| 2358 | arvif->vdev_id, info->bssid); | ||
| 2359 | |||
| 2191 | ret = ath10k_peer_create(ar, arvif->vdev_id, | 2360 | ret = ath10k_peer_create(ar, arvif->vdev_id, |
| 2192 | info->bssid); | 2361 | info->bssid); |
| 2193 | if (ret) | 2362 | if (ret) |
| 2194 | ath10k_warn("Failed to add peer: %pM for VDEV: %d\n", | 2363 | ath10k_warn("Failed to add peer: %pM for VDEV: %d\n", |
| 2195 | info->bssid, arvif->vdev_id); | 2364 | info->bssid, arvif->vdev_id); |
| 2196 | else | ||
| 2197 | ath10k_dbg(ATH10K_DBG_MAC, | ||
| 2198 | "Added peer: %pM for VDEV: %d\n", | ||
| 2199 | info->bssid, arvif->vdev_id); | ||
| 2200 | |||
| 2201 | 2365 | ||
| 2202 | if (vif->type == NL80211_IFTYPE_STATION) { | 2366 | if (vif->type == NL80211_IFTYPE_STATION) { |
| 2203 | /* | 2367 | /* |
| @@ -2207,11 +2371,12 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
| 2207 | memcpy(arvif->u.sta.bssid, info->bssid, | 2371 | memcpy(arvif->u.sta.bssid, info->bssid, |
| 2208 | ETH_ALEN); | 2372 | ETH_ALEN); |
| 2209 | 2373 | ||
| 2374 | ath10k_dbg(ATH10K_DBG_MAC, | ||
| 2375 | "mac vdev %d start %pM\n", | ||
| 2376 | arvif->vdev_id, info->bssid); | ||
| 2377 | |||
| 2378 | /* FIXME: check return value */ | ||
| 2210 | ret = ath10k_vdev_start(arvif); | 2379 | ret = ath10k_vdev_start(arvif); |
| 2211 | if (!ret) | ||
| 2212 | ath10k_dbg(ATH10K_DBG_MAC, | ||
| 2213 | "VDEV: %d started with BSSID: %pM\n", | ||
| 2214 | arvif->vdev_id, info->bssid); | ||
| 2215 | } | 2380 | } |
| 2216 | 2381 | ||
| 2217 | /* | 2382 | /* |
| @@ -2235,16 +2400,15 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
| 2235 | else | 2400 | else |
| 2236 | cts_prot = 0; | 2401 | cts_prot = 0; |
| 2237 | 2402 | ||
| 2238 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, | 2403 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d cts_prot %d\n", |
| 2239 | WMI_VDEV_PARAM_ENABLE_RTSCTS, | 2404 | arvif->vdev_id, cts_prot); |
| 2405 | |||
| 2406 | vdev_param = ar->wmi.vdev_param->enable_rtscts; | ||
| 2407 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, | ||
| 2240 | cts_prot); | 2408 | cts_prot); |
| 2241 | if (ret) | 2409 | if (ret) |
| 2242 | ath10k_warn("Failed to set CTS prot for VDEV: %d\n", | 2410 | ath10k_warn("Failed to set CTS prot for VDEV: %d\n", |
| 2243 | arvif->vdev_id); | 2411 | arvif->vdev_id); |
| 2244 | else | ||
| 2245 | ath10k_dbg(ATH10K_DBG_MAC, | ||
| 2246 | "Set CTS prot: %d for VDEV: %d\n", | ||
| 2247 | cts_prot, arvif->vdev_id); | ||
| 2248 | } | 2412 | } |
| 2249 | 2413 | ||
| 2250 | if (changed & BSS_CHANGED_ERP_SLOT) { | 2414 | if (changed & BSS_CHANGED_ERP_SLOT) { |
| @@ -2255,16 +2419,15 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
| 2255 | else | 2419 | else |
| 2256 | slottime = WMI_VDEV_SLOT_TIME_LONG; /* 20us */ | 2420 | slottime = WMI_VDEV_SLOT_TIME_LONG; /* 20us */ |
| 2257 | 2421 | ||
| 2258 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, | 2422 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d slot_time %d\n", |
| 2259 | WMI_VDEV_PARAM_SLOT_TIME, | 2423 | arvif->vdev_id, slottime); |
| 2424 | |||
| 2425 | vdev_param = ar->wmi.vdev_param->slot_time; | ||
| 2426 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, | ||
| 2260 | slottime); | 2427 | slottime); |
| 2261 | if (ret) | 2428 | if (ret) |
| 2262 | ath10k_warn("Failed to set erp slot for VDEV: %d\n", | 2429 | ath10k_warn("Failed to set erp slot for VDEV: %d\n", |
| 2263 | arvif->vdev_id); | 2430 | arvif->vdev_id); |
| 2264 | else | ||
| 2265 | ath10k_dbg(ATH10K_DBG_MAC, | ||
| 2266 | "Set slottime: %d for VDEV: %d\n", | ||
| 2267 | slottime, arvif->vdev_id); | ||
| 2268 | } | 2431 | } |
| 2269 | 2432 | ||
| 2270 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { | 2433 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { |
| @@ -2274,16 +2437,16 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
| 2274 | else | 2437 | else |
| 2275 | preamble = WMI_VDEV_PREAMBLE_LONG; | 2438 | preamble = WMI_VDEV_PREAMBLE_LONG; |
| 2276 | 2439 | ||
| 2277 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, | 2440 | ath10k_dbg(ATH10K_DBG_MAC, |
| 2278 | WMI_VDEV_PARAM_PREAMBLE, | 2441 | "mac vdev %d preamble %dn", |
| 2442 | arvif->vdev_id, preamble); | ||
| 2443 | |||
| 2444 | vdev_param = ar->wmi.vdev_param->preamble; | ||
| 2445 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, | ||
| 2279 | preamble); | 2446 | preamble); |
| 2280 | if (ret) | 2447 | if (ret) |
| 2281 | ath10k_warn("Failed to set preamble for VDEV: %d\n", | 2448 | ath10k_warn("Failed to set preamble for VDEV: %d\n", |
| 2282 | arvif->vdev_id); | 2449 | arvif->vdev_id); |
| 2283 | else | ||
| 2284 | ath10k_dbg(ATH10K_DBG_MAC, | ||
| 2285 | "Set preamble: %d for VDEV: %d\n", | ||
| 2286 | preamble, arvif->vdev_id); | ||
| 2287 | } | 2450 | } |
| 2288 | 2451 | ||
| 2289 | if (changed & BSS_CHANGED_ASSOC) { | 2452 | if (changed & BSS_CHANGED_ASSOC) { |
| @@ -2474,27 +2637,26 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, | |||
| 2474 | /* | 2637 | /* |
| 2475 | * New station addition. | 2638 | * New station addition. |
| 2476 | */ | 2639 | */ |
| 2640 | ath10k_dbg(ATH10K_DBG_MAC, | ||
| 2641 | "mac vdev %d peer create %pM (new sta)\n", | ||
| 2642 | arvif->vdev_id, sta->addr); | ||
| 2643 | |||
| 2477 | ret = ath10k_peer_create(ar, arvif->vdev_id, sta->addr); | 2644 | ret = ath10k_peer_create(ar, arvif->vdev_id, sta->addr); |
| 2478 | if (ret) | 2645 | if (ret) |
| 2479 | ath10k_warn("Failed to add peer: %pM for VDEV: %d\n", | 2646 | ath10k_warn("Failed to add peer: %pM for VDEV: %d\n", |
| 2480 | sta->addr, arvif->vdev_id); | 2647 | sta->addr, arvif->vdev_id); |
| 2481 | else | ||
| 2482 | ath10k_dbg(ATH10K_DBG_MAC, | ||
| 2483 | "Added peer: %pM for VDEV: %d\n", | ||
| 2484 | sta->addr, arvif->vdev_id); | ||
| 2485 | } else if ((old_state == IEEE80211_STA_NONE && | 2648 | } else if ((old_state == IEEE80211_STA_NONE && |
| 2486 | new_state == IEEE80211_STA_NOTEXIST)) { | 2649 | new_state == IEEE80211_STA_NOTEXIST)) { |
| 2487 | /* | 2650 | /* |
| 2488 | * Existing station deletion. | 2651 | * Existing station deletion. |
| 2489 | */ | 2652 | */ |
| 2653 | ath10k_dbg(ATH10K_DBG_MAC, | ||
| 2654 | "mac vdev %d peer delete %pM (sta gone)\n", | ||
| 2655 | arvif->vdev_id, sta->addr); | ||
| 2490 | ret = ath10k_peer_delete(ar, arvif->vdev_id, sta->addr); | 2656 | ret = ath10k_peer_delete(ar, arvif->vdev_id, sta->addr); |
| 2491 | if (ret) | 2657 | if (ret) |
| 2492 | ath10k_warn("Failed to delete peer: %pM for VDEV: %d\n", | 2658 | ath10k_warn("Failed to delete peer: %pM for VDEV: %d\n", |
| 2493 | sta->addr, arvif->vdev_id); | 2659 | sta->addr, arvif->vdev_id); |
| 2494 | else | ||
| 2495 | ath10k_dbg(ATH10K_DBG_MAC, | ||
| 2496 | "Removed peer: %pM for VDEV: %d\n", | ||
| 2497 | sta->addr, arvif->vdev_id); | ||
| 2498 | 2660 | ||
| 2499 | if (vif->type == NL80211_IFTYPE_STATION) | 2661 | if (vif->type == NL80211_IFTYPE_STATION) |
| 2500 | ath10k_bss_disassoc(hw, vif); | 2662 | ath10k_bss_disassoc(hw, vif); |
| @@ -2505,14 +2667,13 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, | |||
| 2505 | /* | 2667 | /* |
| 2506 | * New association. | 2668 | * New association. |
| 2507 | */ | 2669 | */ |
| 2670 | ath10k_dbg(ATH10K_DBG_MAC, "mac sta %pM associated\n", | ||
| 2671 | sta->addr); | ||
| 2672 | |||
| 2508 | ret = ath10k_station_assoc(ar, arvif, sta); | 2673 | ret = ath10k_station_assoc(ar, arvif, sta); |
| 2509 | if (ret) | 2674 | if (ret) |
| 2510 | ath10k_warn("Failed to associate station: %pM\n", | 2675 | ath10k_warn("Failed to associate station: %pM\n", |
| 2511 | sta->addr); | 2676 | sta->addr); |
| 2512 | else | ||
| 2513 | ath10k_dbg(ATH10K_DBG_MAC, | ||
| 2514 | "Station %pM moved to assoc state\n", | ||
| 2515 | sta->addr); | ||
| 2516 | } else if (old_state == IEEE80211_STA_ASSOC && | 2677 | } else if (old_state == IEEE80211_STA_ASSOC && |
| 2517 | new_state == IEEE80211_STA_AUTH && | 2678 | new_state == IEEE80211_STA_AUTH && |
| 2518 | (vif->type == NL80211_IFTYPE_AP || | 2679 | (vif->type == NL80211_IFTYPE_AP || |
| @@ -2520,14 +2681,13 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, | |||
| 2520 | /* | 2681 | /* |
| 2521 | * Disassociation. | 2682 | * Disassociation. |
| 2522 | */ | 2683 | */ |
| 2684 | ath10k_dbg(ATH10K_DBG_MAC, "mac sta %pM disassociated\n", | ||
| 2685 | sta->addr); | ||
| 2686 | |||
| 2523 | ret = ath10k_station_disassoc(ar, arvif, sta); | 2687 | ret = ath10k_station_disassoc(ar, arvif, sta); |
| 2524 | if (ret) | 2688 | if (ret) |
| 2525 | ath10k_warn("Failed to disassociate station: %pM\n", | 2689 | ath10k_warn("Failed to disassociate station: %pM\n", |
| 2526 | sta->addr); | 2690 | sta->addr); |
| 2527 | else | ||
| 2528 | ath10k_dbg(ATH10K_DBG_MAC, | ||
| 2529 | "Station %pM moved to disassociated state\n", | ||
| 2530 | sta->addr); | ||
| 2531 | } | 2691 | } |
| 2532 | 2692 | ||
| 2533 | mutex_unlock(&ar->conf_mutex); | 2693 | mutex_unlock(&ar->conf_mutex); |
| @@ -2732,88 +2892,51 @@ static int ath10k_cancel_remain_on_channel(struct ieee80211_hw *hw) | |||
| 2732 | * Both RTS and Fragmentation threshold are interface-specific | 2892 | * Both RTS and Fragmentation threshold are interface-specific |
| 2733 | * in ath10k, but device-specific in mac80211. | 2893 | * in ath10k, but device-specific in mac80211. |
| 2734 | */ | 2894 | */ |
| 2735 | static void ath10k_set_rts_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | ||
| 2736 | { | ||
| 2737 | struct ath10k_generic_iter *ar_iter = data; | ||
| 2738 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | ||
| 2739 | u32 rts = ar_iter->ar->hw->wiphy->rts_threshold; | ||
| 2740 | |||
| 2741 | lockdep_assert_held(&arvif->ar->conf_mutex); | ||
| 2742 | |||
| 2743 | /* During HW reconfiguration mac80211 reports all interfaces that were | ||
| 2744 | * running until reconfiguration was started. Since FW doesn't have any | ||
| 2745 | * vdevs at this point we must not iterate over this interface list. | ||
| 2746 | * This setting will be updated upon add_interface(). */ | ||
| 2747 | if (ar_iter->ar->state == ATH10K_STATE_RESTARTED) | ||
| 2748 | return; | ||
| 2749 | |||
| 2750 | ar_iter->ret = ath10k_mac_set_rts(arvif, rts); | ||
| 2751 | if (ar_iter->ret) | ||
| 2752 | ath10k_warn("Failed to set RTS threshold for VDEV: %d\n", | ||
| 2753 | arvif->vdev_id); | ||
| 2754 | else | ||
| 2755 | ath10k_dbg(ATH10K_DBG_MAC, | ||
| 2756 | "Set RTS threshold: %d for VDEV: %d\n", | ||
| 2757 | rts, arvif->vdev_id); | ||
| 2758 | } | ||
| 2759 | 2895 | ||
| 2760 | static int ath10k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | 2896 | static int ath10k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) |
| 2761 | { | 2897 | { |
| 2762 | struct ath10k_generic_iter ar_iter; | ||
| 2763 | struct ath10k *ar = hw->priv; | 2898 | struct ath10k *ar = hw->priv; |
| 2764 | 2899 | struct ath10k_vif *arvif; | |
| 2765 | memset(&ar_iter, 0, sizeof(struct ath10k_generic_iter)); | 2900 | int ret = 0; |
| 2766 | ar_iter.ar = ar; | ||
| 2767 | 2901 | ||
| 2768 | mutex_lock(&ar->conf_mutex); | 2902 | mutex_lock(&ar->conf_mutex); |
| 2769 | ieee80211_iterate_active_interfaces_atomic( | 2903 | list_for_each_entry(arvif, &ar->arvifs, list) { |
| 2770 | hw, IEEE80211_IFACE_ITER_NORMAL, | 2904 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d rts threshold %d\n", |
| 2771 | ath10k_set_rts_iter, &ar_iter); | 2905 | arvif->vdev_id, value); |
| 2772 | mutex_unlock(&ar->conf_mutex); | ||
| 2773 | |||
| 2774 | return ar_iter.ret; | ||
| 2775 | } | ||
| 2776 | 2906 | ||
| 2777 | static void ath10k_set_frag_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | 2907 | ret = ath10k_mac_set_rts(arvif, value); |
| 2778 | { | 2908 | if (ret) { |
| 2779 | struct ath10k_generic_iter *ar_iter = data; | 2909 | ath10k_warn("could not set rts threshold for vdev %d (%d)\n", |
| 2780 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | 2910 | arvif->vdev_id, ret); |
| 2781 | u32 frag = ar_iter->ar->hw->wiphy->frag_threshold; | 2911 | break; |
| 2782 | 2912 | } | |
| 2783 | lockdep_assert_held(&arvif->ar->conf_mutex); | 2913 | } |
| 2784 | 2914 | mutex_unlock(&ar->conf_mutex); | |
| 2785 | /* During HW reconfiguration mac80211 reports all interfaces that were | ||
| 2786 | * running until reconfiguration was started. Since FW doesn't have any | ||
| 2787 | * vdevs at this point we must not iterate over this interface list. | ||
| 2788 | * This setting will be updated upon add_interface(). */ | ||
| 2789 | if (ar_iter->ar->state == ATH10K_STATE_RESTARTED) | ||
| 2790 | return; | ||
| 2791 | 2915 | ||
| 2792 | ar_iter->ret = ath10k_mac_set_frag(arvif, frag); | 2916 | return ret; |
| 2793 | if (ar_iter->ret) | ||
| 2794 | ath10k_warn("Failed to set frag threshold for VDEV: %d\n", | ||
| 2795 | arvif->vdev_id); | ||
| 2796 | else | ||
| 2797 | ath10k_dbg(ATH10K_DBG_MAC, | ||
| 2798 | "Set frag threshold: %d for VDEV: %d\n", | ||
| 2799 | frag, arvif->vdev_id); | ||
| 2800 | } | 2917 | } |
| 2801 | 2918 | ||
| 2802 | static int ath10k_set_frag_threshold(struct ieee80211_hw *hw, u32 value) | 2919 | static int ath10k_set_frag_threshold(struct ieee80211_hw *hw, u32 value) |
| 2803 | { | 2920 | { |
| 2804 | struct ath10k_generic_iter ar_iter; | ||
| 2805 | struct ath10k *ar = hw->priv; | 2921 | struct ath10k *ar = hw->priv; |
| 2806 | 2922 | struct ath10k_vif *arvif; | |
| 2807 | memset(&ar_iter, 0, sizeof(struct ath10k_generic_iter)); | 2923 | int ret = 0; |
| 2808 | ar_iter.ar = ar; | ||
| 2809 | 2924 | ||
| 2810 | mutex_lock(&ar->conf_mutex); | 2925 | mutex_lock(&ar->conf_mutex); |
| 2811 | ieee80211_iterate_active_interfaces_atomic( | 2926 | list_for_each_entry(arvif, &ar->arvifs, list) { |
| 2812 | hw, IEEE80211_IFACE_ITER_NORMAL, | 2927 | ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d fragmentation threshold %d\n", |
| 2813 | ath10k_set_frag_iter, &ar_iter); | 2928 | arvif->vdev_id, value); |
| 2929 | |||
| 2930 | ret = ath10k_mac_set_rts(arvif, value); | ||
| 2931 | if (ret) { | ||
| 2932 | ath10k_warn("could not set fragmentation threshold for vdev %d (%d)\n", | ||
| 2933 | arvif->vdev_id, ret); | ||
| 2934 | break; | ||
| 2935 | } | ||
| 2936 | } | ||
| 2814 | mutex_unlock(&ar->conf_mutex); | 2937 | mutex_unlock(&ar->conf_mutex); |
| 2815 | 2938 | ||
| 2816 | return ar_iter.ret; | 2939 | return ret; |
| 2817 | } | 2940 | } |
| 2818 | 2941 | ||
| 2819 | static void ath10k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) | 2942 | static void ath10k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) |
| @@ -2836,8 +2959,7 @@ static void ath10k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) | |||
| 2836 | bool empty; | 2959 | bool empty; |
| 2837 | 2960 | ||
| 2838 | spin_lock_bh(&ar->htt.tx_lock); | 2961 | spin_lock_bh(&ar->htt.tx_lock); |
| 2839 | empty = bitmap_empty(ar->htt.used_msdu_ids, | 2962 | empty = (ar->htt.num_pending_tx == 0); |
| 2840 | ar->htt.max_num_pending_tx); | ||
| 2841 | spin_unlock_bh(&ar->htt.tx_lock); | 2963 | spin_unlock_bh(&ar->htt.tx_lock); |
| 2842 | 2964 | ||
| 2843 | skip = (ar->state == ATH10K_STATE_WEDGED); | 2965 | skip = (ar->state == ATH10K_STATE_WEDGED); |
| @@ -3326,6 +3448,10 @@ int ath10k_mac_register(struct ath10k *ar) | |||
| 3326 | IEEE80211_HW_WANT_MONITOR_VIF | | 3448 | IEEE80211_HW_WANT_MONITOR_VIF | |
| 3327 | IEEE80211_HW_AP_LINK_PS; | 3449 | IEEE80211_HW_AP_LINK_PS; |
| 3328 | 3450 | ||
| 3451 | /* MSDU can have HTT TX fragment pushed in front. The additional 4 | ||
| 3452 | * bytes is used for padding/alignment if necessary. */ | ||
| 3453 | ar->hw->extra_tx_headroom += sizeof(struct htt_data_tx_desc_frag)*2 + 4; | ||
| 3454 | |||
| 3329 | if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS) | 3455 | if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS) |
| 3330 | ar->hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS; | 3456 | ar->hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS; |
| 3331 | 3457 | ||
diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h index 6fce9bfb19a5..ba1021997b8f 100644 --- a/drivers/net/wireless/ath/ath10k/mac.h +++ b/drivers/net/wireless/ath/ath10k/mac.h | |||
| @@ -34,6 +34,8 @@ struct ath10k_vif *ath10k_get_arvif(struct ath10k *ar, u32 vdev_id); | |||
| 34 | void ath10k_reset_scan(unsigned long ptr); | 34 | void ath10k_reset_scan(unsigned long ptr); |
| 35 | void ath10k_offchan_tx_purge(struct ath10k *ar); | 35 | void ath10k_offchan_tx_purge(struct ath10k *ar); |
| 36 | void ath10k_offchan_tx_work(struct work_struct *work); | 36 | void ath10k_offchan_tx_work(struct work_struct *work); |
| 37 | void ath10k_mgmt_over_wmi_tx_purge(struct ath10k *ar); | ||
| 38 | void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work); | ||
| 37 | void ath10k_halt(struct ath10k *ar); | 39 | void ath10k_halt(struct ath10k *ar); |
| 38 | 40 | ||
| 39 | static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif) | 41 | static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif) |
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index e2f9ef50b1bd..f8d59c7b9082 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c | |||
| @@ -36,11 +36,9 @@ static unsigned int ath10k_target_ps; | |||
| 36 | module_param(ath10k_target_ps, uint, 0644); | 36 | module_param(ath10k_target_ps, uint, 0644); |
| 37 | MODULE_PARM_DESC(ath10k_target_ps, "Enable ath10k Target (SoC) PS option"); | 37 | MODULE_PARM_DESC(ath10k_target_ps, "Enable ath10k Target (SoC) PS option"); |
| 38 | 38 | ||
| 39 | #define QCA988X_1_0_DEVICE_ID (0xabcd) | ||
| 40 | #define QCA988X_2_0_DEVICE_ID (0x003c) | 39 | #define QCA988X_2_0_DEVICE_ID (0x003c) |
| 41 | 40 | ||
| 42 | static DEFINE_PCI_DEVICE_TABLE(ath10k_pci_id_table) = { | 41 | static DEFINE_PCI_DEVICE_TABLE(ath10k_pci_id_table) = { |
| 43 | { PCI_VDEVICE(ATHEROS, QCA988X_1_0_DEVICE_ID) }, /* PCI-E QCA988X V1 */ | ||
| 44 | { PCI_VDEVICE(ATHEROS, QCA988X_2_0_DEVICE_ID) }, /* PCI-E QCA988X V2 */ | 42 | { PCI_VDEVICE(ATHEROS, QCA988X_2_0_DEVICE_ID) }, /* PCI-E QCA988X V2 */ |
| 45 | {0} | 43 | {0} |
| 46 | }; | 44 | }; |
| @@ -50,9 +48,9 @@ static int ath10k_pci_diag_read_access(struct ath10k *ar, u32 address, | |||
| 50 | 48 | ||
| 51 | static void ath10k_pci_process_ce(struct ath10k *ar); | 49 | static void ath10k_pci_process_ce(struct ath10k *ar); |
| 52 | static int ath10k_pci_post_rx(struct ath10k *ar); | 50 | static int ath10k_pci_post_rx(struct ath10k *ar); |
| 53 | static int ath10k_pci_post_rx_pipe(struct hif_ce_pipe_info *pipe_info, | 51 | static int ath10k_pci_post_rx_pipe(struct ath10k_pci_pipe *pipe_info, |
| 54 | int num); | 52 | int num); |
| 55 | static void ath10k_pci_rx_pipe_cleanup(struct hif_ce_pipe_info *pipe_info); | 53 | static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info); |
| 56 | static void ath10k_pci_stop_ce(struct ath10k *ar); | 54 | static void ath10k_pci_stop_ce(struct ath10k *ar); |
| 57 | static void ath10k_pci_device_reset(struct ath10k *ar); | 55 | static void ath10k_pci_device_reset(struct ath10k *ar); |
| 58 | static int ath10k_pci_reset_target(struct ath10k *ar); | 56 | static int ath10k_pci_reset_target(struct ath10k *ar); |
| @@ -60,43 +58,145 @@ static int ath10k_pci_start_intr(struct ath10k *ar); | |||
| 60 | static void ath10k_pci_stop_intr(struct ath10k *ar); | 58 | static void ath10k_pci_stop_intr(struct ath10k *ar); |
| 61 | 59 | ||
| 62 | static const struct ce_attr host_ce_config_wlan[] = { | 60 | static const struct ce_attr host_ce_config_wlan[] = { |
| 63 | /* host->target HTC control and raw streams */ | 61 | /* CE0: host->target HTC control and raw streams */ |
| 64 | { /* CE0 */ CE_ATTR_FLAGS, 0, 16, 256, 0, NULL,}, | 62 | { |
| 65 | /* could be moved to share CE3 */ | 63 | .flags = CE_ATTR_FLAGS, |
| 66 | /* target->host HTT + HTC control */ | 64 | .src_nentries = 16, |
| 67 | { /* CE1 */ CE_ATTR_FLAGS, 0, 0, 512, 512, NULL,}, | 65 | .src_sz_max = 256, |
| 68 | /* target->host WMI */ | 66 | .dest_nentries = 0, |
| 69 | { /* CE2 */ CE_ATTR_FLAGS, 0, 0, 2048, 32, NULL,}, | 67 | }, |
| 70 | /* host->target WMI */ | 68 | |
| 71 | { /* CE3 */ CE_ATTR_FLAGS, 0, 32, 2048, 0, NULL,}, | 69 | /* CE1: target->host HTT + HTC control */ |
| 72 | /* host->target HTT */ | 70 | { |
| 73 | { /* CE4 */ CE_ATTR_FLAGS | CE_ATTR_DIS_INTR, 0, | 71 | .flags = CE_ATTR_FLAGS, |
| 74 | CE_HTT_H2T_MSG_SRC_NENTRIES, 256, 0, NULL,}, | 72 | .src_nentries = 0, |
| 75 | /* unused */ | 73 | .src_sz_max = 512, |
| 76 | { /* CE5 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,}, | 74 | .dest_nentries = 512, |
| 77 | /* Target autonomous hif_memcpy */ | 75 | }, |
| 78 | { /* CE6 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,}, | 76 | |
| 79 | /* ce_diag, the Diagnostic Window */ | 77 | /* CE2: target->host WMI */ |
| 80 | { /* CE7 */ CE_ATTR_FLAGS, 0, 2, DIAG_TRANSFER_LIMIT, 2, NULL,}, | 78 | { |
| 79 | .flags = CE_ATTR_FLAGS, | ||
| 80 | .src_nentries = 0, | ||
| 81 | .src_sz_max = 2048, | ||
| 82 | .dest_nentries = 32, | ||
| 83 | }, | ||
| 84 | |||
| 85 | /* CE3: host->target WMI */ | ||
| 86 | { | ||
| 87 | .flags = CE_ATTR_FLAGS, | ||
| 88 | .src_nentries = 32, | ||
| 89 | .src_sz_max = 2048, | ||
| 90 | .dest_nentries = 0, | ||
| 91 | }, | ||
| 92 | |||
| 93 | /* CE4: host->target HTT */ | ||
| 94 | { | ||
| 95 | .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR, | ||
| 96 | .src_nentries = CE_HTT_H2T_MSG_SRC_NENTRIES, | ||
| 97 | .src_sz_max = 256, | ||
| 98 | .dest_nentries = 0, | ||
| 99 | }, | ||
| 100 | |||
| 101 | /* CE5: unused */ | ||
| 102 | { | ||
| 103 | .flags = CE_ATTR_FLAGS, | ||
| 104 | .src_nentries = 0, | ||
| 105 | .src_sz_max = 0, | ||
| 106 | .dest_nentries = 0, | ||
| 107 | }, | ||
| 108 | |||
| 109 | /* CE6: target autonomous hif_memcpy */ | ||
| 110 | { | ||
| 111 | .flags = CE_ATTR_FLAGS, | ||
| 112 | .src_nentries = 0, | ||
| 113 | .src_sz_max = 0, | ||
| 114 | .dest_nentries = 0, | ||
| 115 | }, | ||
| 116 | |||
| 117 | /* CE7: ce_diag, the Diagnostic Window */ | ||
| 118 | { | ||
| 119 | .flags = CE_ATTR_FLAGS, | ||
| 120 | .src_nentries = 2, | ||
| 121 | .src_sz_max = DIAG_TRANSFER_LIMIT, | ||
| 122 | .dest_nentries = 2, | ||
| 123 | }, | ||
| 81 | }; | 124 | }; |
| 82 | 125 | ||
| 83 | /* Target firmware's Copy Engine configuration. */ | 126 | /* Target firmware's Copy Engine configuration. */ |
| 84 | static const struct ce_pipe_config target_ce_config_wlan[] = { | 127 | static const struct ce_pipe_config target_ce_config_wlan[] = { |
| 85 | /* host->target HTC control and raw streams */ | 128 | /* CE0: host->target HTC control and raw streams */ |
| 86 | { /* CE0 */ 0, PIPEDIR_OUT, 32, 256, CE_ATTR_FLAGS, 0,}, | 129 | { |
| 87 | /* target->host HTT + HTC control */ | 130 | .pipenum = 0, |
| 88 | { /* CE1 */ 1, PIPEDIR_IN, 32, 512, CE_ATTR_FLAGS, 0,}, | 131 | .pipedir = PIPEDIR_OUT, |
| 89 | /* target->host WMI */ | 132 | .nentries = 32, |
| 90 | { /* CE2 */ 2, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,}, | 133 | .nbytes_max = 256, |
| 91 | /* host->target WMI */ | 134 | .flags = CE_ATTR_FLAGS, |
| 92 | { /* CE3 */ 3, PIPEDIR_OUT, 32, 2048, CE_ATTR_FLAGS, 0,}, | 135 | .reserved = 0, |
| 93 | /* host->target HTT */ | 136 | }, |
| 94 | { /* CE4 */ 4, PIPEDIR_OUT, 256, 256, CE_ATTR_FLAGS, 0,}, | 137 | |
| 138 | /* CE1: target->host HTT + HTC control */ | ||
| 139 | { | ||
| 140 | .pipenum = 1, | ||
| 141 | .pipedir = PIPEDIR_IN, | ||
| 142 | .nentries = 32, | ||
| 143 | .nbytes_max = 512, | ||
| 144 | .flags = CE_ATTR_FLAGS, | ||
| 145 | .reserved = 0, | ||
| 146 | }, | ||
| 147 | |||
| 148 | /* CE2: target->host WMI */ | ||
| 149 | { | ||
| 150 | .pipenum = 2, | ||
| 151 | .pipedir = PIPEDIR_IN, | ||
| 152 | .nentries = 32, | ||
| 153 | .nbytes_max = 2048, | ||
| 154 | .flags = CE_ATTR_FLAGS, | ||
| 155 | .reserved = 0, | ||
| 156 | }, | ||
| 157 | |||
| 158 | /* CE3: host->target WMI */ | ||
| 159 | { | ||
| 160 | .pipenum = 3, | ||
| 161 | .pipedir = PIPEDIR_OUT, | ||
| 162 | .nentries = 32, | ||
| 163 | .nbytes_max = 2048, | ||
| 164 | .flags = CE_ATTR_FLAGS, | ||
| 165 | .reserved = 0, | ||
| 166 | }, | ||
| 167 | |||
| 168 | /* CE4: host->target HTT */ | ||
| 169 | { | ||
| 170 | .pipenum = 4, | ||
| 171 | .pipedir = PIPEDIR_OUT, | ||
| 172 | .nentries = 256, | ||
| 173 | .nbytes_max = 256, | ||
| 174 | .flags = CE_ATTR_FLAGS, | ||
| 175 | .reserved = 0, | ||
| 176 | }, | ||
| 177 | |||
| 95 | /* NB: 50% of src nentries, since tx has 2 frags */ | 178 | /* NB: 50% of src nentries, since tx has 2 frags */ |
| 96 | /* unused */ | 179 | |
| 97 | { /* CE5 */ 5, PIPEDIR_OUT, 32, 2048, CE_ATTR_FLAGS, 0,}, | 180 | /* CE5: unused */ |
| 98 | /* Reserved for target autonomous hif_memcpy */ | 181 | { |
| 99 | { /* CE6 */ 6, PIPEDIR_INOUT, 32, 4096, CE_ATTR_FLAGS, 0,}, | 182 | .pipenum = 5, |
| 183 | .pipedir = PIPEDIR_OUT, | ||
| 184 | .nentries = 32, | ||
| 185 | .nbytes_max = 2048, | ||
| 186 | .flags = CE_ATTR_FLAGS, | ||
| 187 | .reserved = 0, | ||
| 188 | }, | ||
| 189 | |||
| 190 | /* CE6: Reserved for target autonomous hif_memcpy */ | ||
| 191 | { | ||
| 192 | .pipenum = 6, | ||
| 193 | .pipedir = PIPEDIR_INOUT, | ||
| 194 | .nentries = 32, | ||
| 195 | .nbytes_max = 4096, | ||
| 196 | .flags = CE_ATTR_FLAGS, | ||
| 197 | .reserved = 0, | ||
| 198 | }, | ||
| 199 | |||
| 100 | /* CE7 used only by Host */ | 200 | /* CE7 used only by Host */ |
| 101 | }; | 201 | }; |
| 102 | 202 | ||
| @@ -114,7 +214,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, | |||
| 114 | unsigned int completed_nbytes, orig_nbytes, remaining_bytes; | 214 | unsigned int completed_nbytes, orig_nbytes, remaining_bytes; |
| 115 | unsigned int id; | 215 | unsigned int id; |
| 116 | unsigned int flags; | 216 | unsigned int flags; |
| 117 | struct ce_state *ce_diag; | 217 | struct ath10k_ce_pipe *ce_diag; |
| 118 | /* Host buffer address in CE space */ | 218 | /* Host buffer address in CE space */ |
| 119 | u32 ce_data; | 219 | u32 ce_data; |
| 120 | dma_addr_t ce_data_base = 0; | 220 | dma_addr_t ce_data_base = 0; |
| @@ -278,7 +378,7 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, | |||
| 278 | unsigned int completed_nbytes, orig_nbytes, remaining_bytes; | 378 | unsigned int completed_nbytes, orig_nbytes, remaining_bytes; |
| 279 | unsigned int id; | 379 | unsigned int id; |
| 280 | unsigned int flags; | 380 | unsigned int flags; |
| 281 | struct ce_state *ce_diag; | 381 | struct ath10k_ce_pipe *ce_diag; |
| 282 | void *data_buf = NULL; | 382 | void *data_buf = NULL; |
| 283 | u32 ce_data; /* Host buffer address in CE space */ | 383 | u32 ce_data; /* Host buffer address in CE space */ |
| 284 | dma_addr_t ce_data_base = 0; | 384 | dma_addr_t ce_data_base = 0; |
| @@ -437,7 +537,7 @@ static void ath10k_pci_wait(struct ath10k *ar) | |||
| 437 | ath10k_warn("Unable to wakeup target\n"); | 537 | ath10k_warn("Unable to wakeup target\n"); |
| 438 | } | 538 | } |
| 439 | 539 | ||
| 440 | void ath10k_do_pci_wake(struct ath10k *ar) | 540 | int ath10k_do_pci_wake(struct ath10k *ar) |
| 441 | { | 541 | { |
| 442 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 542 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 443 | void __iomem *pci_addr = ar_pci->mem; | 543 | void __iomem *pci_addr = ar_pci->mem; |
| @@ -453,18 +553,19 @@ void ath10k_do_pci_wake(struct ath10k *ar) | |||
| 453 | atomic_inc(&ar_pci->keep_awake_count); | 553 | atomic_inc(&ar_pci->keep_awake_count); |
| 454 | 554 | ||
| 455 | if (ar_pci->verified_awake) | 555 | if (ar_pci->verified_awake) |
| 456 | return; | 556 | return 0; |
| 457 | 557 | ||
| 458 | for (;;) { | 558 | for (;;) { |
| 459 | if (ath10k_pci_target_is_awake(ar)) { | 559 | if (ath10k_pci_target_is_awake(ar)) { |
| 460 | ar_pci->verified_awake = true; | 560 | ar_pci->verified_awake = true; |
| 461 | break; | 561 | return 0; |
| 462 | } | 562 | } |
| 463 | 563 | ||
| 464 | if (tot_delay > PCIE_WAKE_TIMEOUT) { | 564 | if (tot_delay > PCIE_WAKE_TIMEOUT) { |
| 465 | ath10k_warn("target takes too long to wake up (awake count %d)\n", | 565 | ath10k_warn("target took longer %d us to wake up (awake count %d)\n", |
| 566 | PCIE_WAKE_TIMEOUT, | ||
| 466 | atomic_read(&ar_pci->keep_awake_count)); | 567 | atomic_read(&ar_pci->keep_awake_count)); |
| 467 | break; | 568 | return -ETIMEDOUT; |
| 468 | } | 569 | } |
| 469 | 570 | ||
| 470 | udelay(curr_delay); | 571 | udelay(curr_delay); |
| @@ -493,7 +594,7 @@ void ath10k_do_pci_sleep(struct ath10k *ar) | |||
| 493 | * FIXME: Handle OOM properly. | 594 | * FIXME: Handle OOM properly. |
| 494 | */ | 595 | */ |
| 495 | static inline | 596 | static inline |
| 496 | struct ath10k_pci_compl *get_free_compl(struct hif_ce_pipe_info *pipe_info) | 597 | struct ath10k_pci_compl *get_free_compl(struct ath10k_pci_pipe *pipe_info) |
| 497 | { | 598 | { |
| 498 | struct ath10k_pci_compl *compl = NULL; | 599 | struct ath10k_pci_compl *compl = NULL; |
| 499 | 600 | ||
| @@ -511,39 +612,28 @@ exit: | |||
| 511 | } | 612 | } |
| 512 | 613 | ||
| 513 | /* Called by lower (CE) layer when a send to Target completes. */ | 614 | /* Called by lower (CE) layer when a send to Target completes. */ |
| 514 | static void ath10k_pci_ce_send_done(struct ce_state *ce_state, | 615 | static void ath10k_pci_ce_send_done(struct ath10k_ce_pipe *ce_state) |
| 515 | void *transfer_context, | ||
| 516 | u32 ce_data, | ||
| 517 | unsigned int nbytes, | ||
| 518 | unsigned int transfer_id) | ||
| 519 | { | 616 | { |
| 520 | struct ath10k *ar = ce_state->ar; | 617 | struct ath10k *ar = ce_state->ar; |
| 521 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 618 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 522 | struct hif_ce_pipe_info *pipe_info = &ar_pci->pipe_info[ce_state->id]; | 619 | struct ath10k_pci_pipe *pipe_info = &ar_pci->pipe_info[ce_state->id]; |
| 523 | struct ath10k_pci_compl *compl; | 620 | struct ath10k_pci_compl *compl; |
| 524 | bool process = false; | 621 | void *transfer_context; |
| 525 | 622 | u32 ce_data; | |
| 526 | do { | 623 | unsigned int nbytes; |
| 527 | /* | 624 | unsigned int transfer_id; |
| 528 | * For the send completion of an item in sendlist, just | ||
| 529 | * increment num_sends_allowed. The upper layer callback will | ||
| 530 | * be triggered when last fragment is done with send. | ||
| 531 | */ | ||
| 532 | if (transfer_context == CE_SENDLIST_ITEM_CTXT) { | ||
| 533 | spin_lock_bh(&pipe_info->pipe_lock); | ||
| 534 | pipe_info->num_sends_allowed++; | ||
| 535 | spin_unlock_bh(&pipe_info->pipe_lock); | ||
| 536 | continue; | ||
| 537 | } | ||
| 538 | 625 | ||
| 626 | while (ath10k_ce_completed_send_next(ce_state, &transfer_context, | ||
| 627 | &ce_data, &nbytes, | ||
| 628 | &transfer_id) == 0) { | ||
| 539 | compl = get_free_compl(pipe_info); | 629 | compl = get_free_compl(pipe_info); |
| 540 | if (!compl) | 630 | if (!compl) |
| 541 | break; | 631 | break; |
| 542 | 632 | ||
| 543 | compl->send_or_recv = HIF_CE_COMPLETE_SEND; | 633 | compl->state = ATH10K_PCI_COMPL_SEND; |
| 544 | compl->ce_state = ce_state; | 634 | compl->ce_state = ce_state; |
| 545 | compl->pipe_info = pipe_info; | 635 | compl->pipe_info = pipe_info; |
| 546 | compl->transfer_context = transfer_context; | 636 | compl->skb = transfer_context; |
| 547 | compl->nbytes = nbytes; | 637 | compl->nbytes = nbytes; |
| 548 | compl->transfer_id = transfer_id; | 638 | compl->transfer_id = transfer_id; |
| 549 | compl->flags = 0; | 639 | compl->flags = 0; |
| @@ -554,46 +644,36 @@ static void ath10k_pci_ce_send_done(struct ce_state *ce_state, | |||
| 554 | spin_lock_bh(&ar_pci->compl_lock); | 644 | spin_lock_bh(&ar_pci->compl_lock); |
| 555 | list_add_tail(&compl->list, &ar_pci->compl_process); | 645 | list_add_tail(&compl->list, &ar_pci->compl_process); |
| 556 | spin_unlock_bh(&ar_pci->compl_lock); | 646 | spin_unlock_bh(&ar_pci->compl_lock); |
| 557 | 647 | } | |
| 558 | process = true; | ||
| 559 | } while (ath10k_ce_completed_send_next(ce_state, | ||
| 560 | &transfer_context, | ||
| 561 | &ce_data, &nbytes, | ||
| 562 | &transfer_id) == 0); | ||
| 563 | |||
| 564 | /* | ||
| 565 | * If only some of the items within a sendlist have completed, | ||
| 566 | * don't invoke completion processing until the entire sendlist | ||
| 567 | * has been sent. | ||
| 568 | */ | ||
| 569 | if (!process) | ||
| 570 | return; | ||
| 571 | 648 | ||
| 572 | ath10k_pci_process_ce(ar); | 649 | ath10k_pci_process_ce(ar); |
| 573 | } | 650 | } |
| 574 | 651 | ||
| 575 | /* Called by lower (CE) layer when data is received from the Target. */ | 652 | /* Called by lower (CE) layer when data is received from the Target. */ |
| 576 | static void ath10k_pci_ce_recv_data(struct ce_state *ce_state, | 653 | static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state) |
| 577 | void *transfer_context, u32 ce_data, | ||
| 578 | unsigned int nbytes, | ||
| 579 | unsigned int transfer_id, | ||
| 580 | unsigned int flags) | ||
| 581 | { | 654 | { |
| 582 | struct ath10k *ar = ce_state->ar; | 655 | struct ath10k *ar = ce_state->ar; |
| 583 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 656 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 584 | struct hif_ce_pipe_info *pipe_info = &ar_pci->pipe_info[ce_state->id]; | 657 | struct ath10k_pci_pipe *pipe_info = &ar_pci->pipe_info[ce_state->id]; |
| 585 | struct ath10k_pci_compl *compl; | 658 | struct ath10k_pci_compl *compl; |
| 586 | struct sk_buff *skb; | 659 | struct sk_buff *skb; |
| 660 | void *transfer_context; | ||
| 661 | u32 ce_data; | ||
| 662 | unsigned int nbytes; | ||
| 663 | unsigned int transfer_id; | ||
| 664 | unsigned int flags; | ||
| 587 | 665 | ||
| 588 | do { | 666 | while (ath10k_ce_completed_recv_next(ce_state, &transfer_context, |
| 667 | &ce_data, &nbytes, &transfer_id, | ||
| 668 | &flags) == 0) { | ||
| 589 | compl = get_free_compl(pipe_info); | 669 | compl = get_free_compl(pipe_info); |
| 590 | if (!compl) | 670 | if (!compl) |
| 591 | break; | 671 | break; |
| 592 | 672 | ||
| 593 | compl->send_or_recv = HIF_CE_COMPLETE_RECV; | 673 | compl->state = ATH10K_PCI_COMPL_RECV; |
| 594 | compl->ce_state = ce_state; | 674 | compl->ce_state = ce_state; |
| 595 | compl->pipe_info = pipe_info; | 675 | compl->pipe_info = pipe_info; |
| 596 | compl->transfer_context = transfer_context; | 676 | compl->skb = transfer_context; |
| 597 | compl->nbytes = nbytes; | 677 | compl->nbytes = nbytes; |
| 598 | compl->transfer_id = transfer_id; | 678 | compl->transfer_id = transfer_id; |
| 599 | compl->flags = flags; | 679 | compl->flags = flags; |
| @@ -608,12 +688,7 @@ static void ath10k_pci_ce_recv_data(struct ce_state *ce_state, | |||
| 608 | spin_lock_bh(&ar_pci->compl_lock); | 688 | spin_lock_bh(&ar_pci->compl_lock); |
| 609 | list_add_tail(&compl->list, &ar_pci->compl_process); | 689 | list_add_tail(&compl->list, &ar_pci->compl_process); |
| 610 | spin_unlock_bh(&ar_pci->compl_lock); | 690 | spin_unlock_bh(&ar_pci->compl_lock); |
| 611 | 691 | } | |
| 612 | } while (ath10k_ce_completed_recv_next(ce_state, | ||
| 613 | &transfer_context, | ||
| 614 | &ce_data, &nbytes, | ||
| 615 | &transfer_id, | ||
| 616 | &flags) == 0); | ||
| 617 | 692 | ||
| 618 | ath10k_pci_process_ce(ar); | 693 | ath10k_pci_process_ce(ar); |
| 619 | } | 694 | } |
| @@ -625,15 +700,12 @@ static int ath10k_pci_hif_send_head(struct ath10k *ar, u8 pipe_id, | |||
| 625 | { | 700 | { |
| 626 | struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(nbuf); | 701 | struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(nbuf); |
| 627 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 702 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 628 | struct hif_ce_pipe_info *pipe_info = &(ar_pci->pipe_info[pipe_id]); | 703 | struct ath10k_pci_pipe *pipe_info = &(ar_pci->pipe_info[pipe_id]); |
| 629 | struct ce_state *ce_hdl = pipe_info->ce_hdl; | 704 | struct ath10k_ce_pipe *ce_hdl = pipe_info->ce_hdl; |
| 630 | struct ce_sendlist sendlist; | ||
| 631 | unsigned int len; | 705 | unsigned int len; |
| 632 | u32 flags = 0; | 706 | u32 flags = 0; |
| 633 | int ret; | 707 | int ret; |
| 634 | 708 | ||
| 635 | memset(&sendlist, 0, sizeof(struct ce_sendlist)); | ||
| 636 | |||
| 637 | len = min(bytes, nbuf->len); | 709 | len = min(bytes, nbuf->len); |
| 638 | bytes -= len; | 710 | bytes -= len; |
| 639 | 711 | ||
| @@ -648,19 +720,8 @@ static int ath10k_pci_hif_send_head(struct ath10k *ar, u8 pipe_id, | |||
| 648 | "ath10k tx: data: ", | 720 | "ath10k tx: data: ", |
| 649 | nbuf->data, nbuf->len); | 721 | nbuf->data, nbuf->len); |
| 650 | 722 | ||
| 651 | ath10k_ce_sendlist_buf_add(&sendlist, skb_cb->paddr, len, flags); | 723 | ret = ath10k_ce_send(ce_hdl, nbuf, skb_cb->paddr, len, transfer_id, |
| 652 | 724 | flags); | |
| 653 | /* Make sure we have resources to handle this request */ | ||
| 654 | spin_lock_bh(&pipe_info->pipe_lock); | ||
| 655 | if (!pipe_info->num_sends_allowed) { | ||
| 656 | ath10k_warn("Pipe: %d is full\n", pipe_id); | ||
| 657 | spin_unlock_bh(&pipe_info->pipe_lock); | ||
| 658 | return -ENOSR; | ||
| 659 | } | ||
| 660 | pipe_info->num_sends_allowed--; | ||
| 661 | spin_unlock_bh(&pipe_info->pipe_lock); | ||
| 662 | |||
| 663 | ret = ath10k_ce_sendlist_send(ce_hdl, nbuf, &sendlist, transfer_id); | ||
| 664 | if (ret) | 725 | if (ret) |
| 665 | ath10k_warn("CE send failed: %p\n", nbuf); | 726 | ath10k_warn("CE send failed: %p\n", nbuf); |
| 666 | 727 | ||
| @@ -670,14 +731,7 @@ static int ath10k_pci_hif_send_head(struct ath10k *ar, u8 pipe_id, | |||
| 670 | static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe) | 731 | static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe) |
| 671 | { | 732 | { |
| 672 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 733 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 673 | struct hif_ce_pipe_info *pipe_info = &(ar_pci->pipe_info[pipe]); | 734 | return ath10k_ce_num_free_src_entries(ar_pci->pipe_info[pipe].ce_hdl); |
| 674 | int ret; | ||
| 675 | |||
| 676 | spin_lock_bh(&pipe_info->pipe_lock); | ||
| 677 | ret = pipe_info->num_sends_allowed; | ||
| 678 | spin_unlock_bh(&pipe_info->pipe_lock); | ||
| 679 | |||
| 680 | return ret; | ||
| 681 | } | 735 | } |
| 682 | 736 | ||
| 683 | static void ath10k_pci_hif_dump_area(struct ath10k *ar) | 737 | static void ath10k_pci_hif_dump_area(struct ath10k *ar) |
| @@ -764,9 +818,9 @@ static void ath10k_pci_hif_set_callbacks(struct ath10k *ar, | |||
| 764 | static int ath10k_pci_start_ce(struct ath10k *ar) | 818 | static int ath10k_pci_start_ce(struct ath10k *ar) |
| 765 | { | 819 | { |
| 766 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 820 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 767 | struct ce_state *ce_diag = ar_pci->ce_diag; | 821 | struct ath10k_ce_pipe *ce_diag = ar_pci->ce_diag; |
| 768 | const struct ce_attr *attr; | 822 | const struct ce_attr *attr; |
| 769 | struct hif_ce_pipe_info *pipe_info; | 823 | struct ath10k_pci_pipe *pipe_info; |
| 770 | struct ath10k_pci_compl *compl; | 824 | struct ath10k_pci_compl *compl; |
| 771 | int i, pipe_num, completions, disable_interrupts; | 825 | int i, pipe_num, completions, disable_interrupts; |
| 772 | 826 | ||
| @@ -792,7 +846,6 @@ static int ath10k_pci_start_ce(struct ath10k *ar) | |||
| 792 | ath10k_pci_ce_send_done, | 846 | ath10k_pci_ce_send_done, |
| 793 | disable_interrupts); | 847 | disable_interrupts); |
| 794 | completions += attr->src_nentries; | 848 | completions += attr->src_nentries; |
| 795 | pipe_info->num_sends_allowed = attr->src_nentries - 1; | ||
| 796 | } | 849 | } |
| 797 | 850 | ||
| 798 | if (attr->dest_nentries) { | 851 | if (attr->dest_nentries) { |
| @@ -805,15 +858,14 @@ static int ath10k_pci_start_ce(struct ath10k *ar) | |||
| 805 | continue; | 858 | continue; |
| 806 | 859 | ||
| 807 | for (i = 0; i < completions; i++) { | 860 | for (i = 0; i < completions; i++) { |
| 808 | compl = kmalloc(sizeof(struct ath10k_pci_compl), | 861 | compl = kmalloc(sizeof(*compl), GFP_KERNEL); |
| 809 | GFP_KERNEL); | ||
| 810 | if (!compl) { | 862 | if (!compl) { |
| 811 | ath10k_warn("No memory for completion state\n"); | 863 | ath10k_warn("No memory for completion state\n"); |
| 812 | ath10k_pci_stop_ce(ar); | 864 | ath10k_pci_stop_ce(ar); |
| 813 | return -ENOMEM; | 865 | return -ENOMEM; |
| 814 | } | 866 | } |
| 815 | 867 | ||
| 816 | compl->send_or_recv = HIF_CE_COMPLETE_FREE; | 868 | compl->state = ATH10K_PCI_COMPL_FREE; |
| 817 | list_add_tail(&compl->list, &pipe_info->compl_free); | 869 | list_add_tail(&compl->list, &pipe_info->compl_free); |
| 818 | } | 870 | } |
| 819 | } | 871 | } |
| @@ -840,7 +892,7 @@ static void ath10k_pci_stop_ce(struct ath10k *ar) | |||
| 840 | * their associated resources */ | 892 | * their associated resources */ |
| 841 | spin_lock_bh(&ar_pci->compl_lock); | 893 | spin_lock_bh(&ar_pci->compl_lock); |
| 842 | list_for_each_entry(compl, &ar_pci->compl_process, list) { | 894 | list_for_each_entry(compl, &ar_pci->compl_process, list) { |
| 843 | skb = (struct sk_buff *)compl->transfer_context; | 895 | skb = compl->skb; |
| 844 | ATH10K_SKB_CB(skb)->is_aborted = true; | 896 | ATH10K_SKB_CB(skb)->is_aborted = true; |
| 845 | } | 897 | } |
| 846 | spin_unlock_bh(&ar_pci->compl_lock); | 898 | spin_unlock_bh(&ar_pci->compl_lock); |
| @@ -850,7 +902,7 @@ static void ath10k_pci_cleanup_ce(struct ath10k *ar) | |||
| 850 | { | 902 | { |
| 851 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 903 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 852 | struct ath10k_pci_compl *compl, *tmp; | 904 | struct ath10k_pci_compl *compl, *tmp; |
| 853 | struct hif_ce_pipe_info *pipe_info; | 905 | struct ath10k_pci_pipe *pipe_info; |
| 854 | struct sk_buff *netbuf; | 906 | struct sk_buff *netbuf; |
| 855 | int pipe_num; | 907 | int pipe_num; |
| 856 | 908 | ||
| @@ -861,7 +913,7 @@ static void ath10k_pci_cleanup_ce(struct ath10k *ar) | |||
| 861 | 913 | ||
| 862 | list_for_each_entry_safe(compl, tmp, &ar_pci->compl_process, list) { | 914 | list_for_each_entry_safe(compl, tmp, &ar_pci->compl_process, list) { |
| 863 | list_del(&compl->list); | 915 | list_del(&compl->list); |
| 864 | netbuf = (struct sk_buff *)compl->transfer_context; | 916 | netbuf = compl->skb; |
| 865 | dev_kfree_skb_any(netbuf); | 917 | dev_kfree_skb_any(netbuf); |
| 866 | kfree(compl); | 918 | kfree(compl); |
| 867 | } | 919 | } |
| @@ -912,12 +964,14 @@ static void ath10k_pci_process_ce(struct ath10k *ar) | |||
| 912 | list_del(&compl->list); | 964 | list_del(&compl->list); |
| 913 | spin_unlock_bh(&ar_pci->compl_lock); | 965 | spin_unlock_bh(&ar_pci->compl_lock); |
| 914 | 966 | ||
| 915 | if (compl->send_or_recv == HIF_CE_COMPLETE_SEND) { | 967 | switch (compl->state) { |
| 968 | case ATH10K_PCI_COMPL_SEND: | ||
| 916 | cb->tx_completion(ar, | 969 | cb->tx_completion(ar, |
| 917 | compl->transfer_context, | 970 | compl->skb, |
| 918 | compl->transfer_id); | 971 | compl->transfer_id); |
| 919 | send_done = 1; | 972 | send_done = 1; |
| 920 | } else { | 973 | break; |
| 974 | case ATH10K_PCI_COMPL_RECV: | ||
| 921 | ret = ath10k_pci_post_rx_pipe(compl->pipe_info, 1); | 975 | ret = ath10k_pci_post_rx_pipe(compl->pipe_info, 1); |
| 922 | if (ret) { | 976 | if (ret) { |
| 923 | ath10k_warn("Unable to post recv buffer for pipe: %d\n", | 977 | ath10k_warn("Unable to post recv buffer for pipe: %d\n", |
| @@ -925,7 +979,7 @@ static void ath10k_pci_process_ce(struct ath10k *ar) | |||
| 925 | break; | 979 | break; |
| 926 | } | 980 | } |
| 927 | 981 | ||
| 928 | skb = (struct sk_buff *)compl->transfer_context; | 982 | skb = compl->skb; |
| 929 | nbytes = compl->nbytes; | 983 | nbytes = compl->nbytes; |
| 930 | 984 | ||
| 931 | ath10k_dbg(ATH10K_DBG_PCI, | 985 | ath10k_dbg(ATH10K_DBG_PCI, |
| @@ -944,16 +998,23 @@ static void ath10k_pci_process_ce(struct ath10k *ar) | |||
| 944 | nbytes, | 998 | nbytes, |
| 945 | skb->len + skb_tailroom(skb)); | 999 | skb->len + skb_tailroom(skb)); |
| 946 | } | 1000 | } |
| 1001 | break; | ||
| 1002 | case ATH10K_PCI_COMPL_FREE: | ||
| 1003 | ath10k_warn("free completion cannot be processed\n"); | ||
| 1004 | break; | ||
| 1005 | default: | ||
| 1006 | ath10k_warn("invalid completion state (%d)\n", | ||
| 1007 | compl->state); | ||
| 1008 | break; | ||
| 947 | } | 1009 | } |
| 948 | 1010 | ||
| 949 | compl->send_or_recv = HIF_CE_COMPLETE_FREE; | 1011 | compl->state = ATH10K_PCI_COMPL_FREE; |
| 950 | 1012 | ||
| 951 | /* | 1013 | /* |
| 952 | * Add completion back to the pipe's free list. | 1014 | * Add completion back to the pipe's free list. |
| 953 | */ | 1015 | */ |
| 954 | spin_lock_bh(&compl->pipe_info->pipe_lock); | 1016 | spin_lock_bh(&compl->pipe_info->pipe_lock); |
| 955 | list_add_tail(&compl->list, &compl->pipe_info->compl_free); | 1017 | list_add_tail(&compl->list, &compl->pipe_info->compl_free); |
| 956 | compl->pipe_info->num_sends_allowed += send_done; | ||
| 957 | spin_unlock_bh(&compl->pipe_info->pipe_lock); | 1018 | spin_unlock_bh(&compl->pipe_info->pipe_lock); |
| 958 | } | 1019 | } |
| 959 | 1020 | ||
| @@ -1037,12 +1098,12 @@ static void ath10k_pci_hif_get_default_pipe(struct ath10k *ar, | |||
| 1037 | &dl_is_polled); | 1098 | &dl_is_polled); |
| 1038 | } | 1099 | } |
| 1039 | 1100 | ||
| 1040 | static int ath10k_pci_post_rx_pipe(struct hif_ce_pipe_info *pipe_info, | 1101 | static int ath10k_pci_post_rx_pipe(struct ath10k_pci_pipe *pipe_info, |
| 1041 | int num) | 1102 | int num) |
| 1042 | { | 1103 | { |
| 1043 | struct ath10k *ar = pipe_info->hif_ce_state; | 1104 | struct ath10k *ar = pipe_info->hif_ce_state; |
| 1044 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 1105 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 1045 | struct ce_state *ce_state = pipe_info->ce_hdl; | 1106 | struct ath10k_ce_pipe *ce_state = pipe_info->ce_hdl; |
| 1046 | struct sk_buff *skb; | 1107 | struct sk_buff *skb; |
| 1047 | dma_addr_t ce_data; | 1108 | dma_addr_t ce_data; |
| 1048 | int i, ret = 0; | 1109 | int i, ret = 0; |
| @@ -1097,7 +1158,7 @@ err: | |||
| 1097 | static int ath10k_pci_post_rx(struct ath10k *ar) | 1158 | static int ath10k_pci_post_rx(struct ath10k *ar) |
| 1098 | { | 1159 | { |
| 1099 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 1160 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 1100 | struct hif_ce_pipe_info *pipe_info; | 1161 | struct ath10k_pci_pipe *pipe_info; |
| 1101 | const struct ce_attr *attr; | 1162 | const struct ce_attr *attr; |
| 1102 | int pipe_num, ret = 0; | 1163 | int pipe_num, ret = 0; |
| 1103 | 1164 | ||
| @@ -1147,11 +1208,11 @@ static int ath10k_pci_hif_start(struct ath10k *ar) | |||
| 1147 | return 0; | 1208 | return 0; |
| 1148 | } | 1209 | } |
| 1149 | 1210 | ||
| 1150 | static void ath10k_pci_rx_pipe_cleanup(struct hif_ce_pipe_info *pipe_info) | 1211 | static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info) |
| 1151 | { | 1212 | { |
| 1152 | struct ath10k *ar; | 1213 | struct ath10k *ar; |
| 1153 | struct ath10k_pci *ar_pci; | 1214 | struct ath10k_pci *ar_pci; |
| 1154 | struct ce_state *ce_hdl; | 1215 | struct ath10k_ce_pipe *ce_hdl; |
| 1155 | u32 buf_sz; | 1216 | u32 buf_sz; |
| 1156 | struct sk_buff *netbuf; | 1217 | struct sk_buff *netbuf; |
| 1157 | u32 ce_data; | 1218 | u32 ce_data; |
| @@ -1179,11 +1240,11 @@ static void ath10k_pci_rx_pipe_cleanup(struct hif_ce_pipe_info *pipe_info) | |||
| 1179 | } | 1240 | } |
| 1180 | } | 1241 | } |
| 1181 | 1242 | ||
| 1182 | static void ath10k_pci_tx_pipe_cleanup(struct hif_ce_pipe_info *pipe_info) | 1243 | static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info) |
| 1183 | { | 1244 | { |
| 1184 | struct ath10k *ar; | 1245 | struct ath10k *ar; |
| 1185 | struct ath10k_pci *ar_pci; | 1246 | struct ath10k_pci *ar_pci; |
| 1186 | struct ce_state *ce_hdl; | 1247 | struct ath10k_ce_pipe *ce_hdl; |
| 1187 | struct sk_buff *netbuf; | 1248 | struct sk_buff *netbuf; |
| 1188 | u32 ce_data; | 1249 | u32 ce_data; |
| 1189 | unsigned int nbytes; | 1250 | unsigned int nbytes; |
| @@ -1206,15 +1267,14 @@ static void ath10k_pci_tx_pipe_cleanup(struct hif_ce_pipe_info *pipe_info) | |||
| 1206 | 1267 | ||
| 1207 | while (ath10k_ce_cancel_send_next(ce_hdl, (void **)&netbuf, | 1268 | while (ath10k_ce_cancel_send_next(ce_hdl, (void **)&netbuf, |
| 1208 | &ce_data, &nbytes, &id) == 0) { | 1269 | &ce_data, &nbytes, &id) == 0) { |
| 1209 | if (netbuf != CE_SENDLIST_ITEM_CTXT) | 1270 | /* |
| 1210 | /* | 1271 | * Indicate the completion to higer layer to free |
| 1211 | * Indicate the completion to higer layer to free | 1272 | * the buffer |
| 1212 | * the buffer | 1273 | */ |
| 1213 | */ | 1274 | ATH10K_SKB_CB(netbuf)->is_aborted = true; |
| 1214 | ATH10K_SKB_CB(netbuf)->is_aborted = true; | 1275 | ar_pci->msg_callbacks_current.tx_completion(ar, |
| 1215 | ar_pci->msg_callbacks_current.tx_completion(ar, | 1276 | netbuf, |
| 1216 | netbuf, | 1277 | id); |
| 1217 | id); | ||
| 1218 | } | 1278 | } |
| 1219 | } | 1279 | } |
| 1220 | 1280 | ||
| @@ -1232,7 +1292,7 @@ static void ath10k_pci_buffer_cleanup(struct ath10k *ar) | |||
| 1232 | int pipe_num; | 1292 | int pipe_num; |
| 1233 | 1293 | ||
| 1234 | for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) { | 1294 | for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) { |
| 1235 | struct hif_ce_pipe_info *pipe_info; | 1295 | struct ath10k_pci_pipe *pipe_info; |
| 1236 | 1296 | ||
| 1237 | pipe_info = &ar_pci->pipe_info[pipe_num]; | 1297 | pipe_info = &ar_pci->pipe_info[pipe_num]; |
| 1238 | ath10k_pci_rx_pipe_cleanup(pipe_info); | 1298 | ath10k_pci_rx_pipe_cleanup(pipe_info); |
| @@ -1243,7 +1303,7 @@ static void ath10k_pci_buffer_cleanup(struct ath10k *ar) | |||
| 1243 | static void ath10k_pci_ce_deinit(struct ath10k *ar) | 1303 | static void ath10k_pci_ce_deinit(struct ath10k *ar) |
| 1244 | { | 1304 | { |
| 1245 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 1305 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 1246 | struct hif_ce_pipe_info *pipe_info; | 1306 | struct ath10k_pci_pipe *pipe_info; |
| 1247 | int pipe_num; | 1307 | int pipe_num; |
| 1248 | 1308 | ||
| 1249 | for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) { | 1309 | for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) { |
| @@ -1293,8 +1353,10 @@ static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar, | |||
| 1293 | void *resp, u32 *resp_len) | 1353 | void *resp, u32 *resp_len) |
| 1294 | { | 1354 | { |
| 1295 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 1355 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 1296 | struct ce_state *ce_tx = ar_pci->pipe_info[BMI_CE_NUM_TO_TARG].ce_hdl; | 1356 | struct ath10k_pci_pipe *pci_tx = &ar_pci->pipe_info[BMI_CE_NUM_TO_TARG]; |
| 1297 | struct ce_state *ce_rx = ar_pci->pipe_info[BMI_CE_NUM_TO_HOST].ce_hdl; | 1357 | struct ath10k_pci_pipe *pci_rx = &ar_pci->pipe_info[BMI_CE_NUM_TO_HOST]; |
| 1358 | struct ath10k_ce_pipe *ce_tx = pci_tx->ce_hdl; | ||
| 1359 | struct ath10k_ce_pipe *ce_rx = pci_rx->ce_hdl; | ||
| 1298 | dma_addr_t req_paddr = 0; | 1360 | dma_addr_t req_paddr = 0; |
| 1299 | dma_addr_t resp_paddr = 0; | 1361 | dma_addr_t resp_paddr = 0; |
| 1300 | struct bmi_xfer xfer = {}; | 1362 | struct bmi_xfer xfer = {}; |
| @@ -1378,13 +1440,16 @@ err_dma: | |||
| 1378 | return ret; | 1440 | return ret; |
| 1379 | } | 1441 | } |
| 1380 | 1442 | ||
| 1381 | static void ath10k_pci_bmi_send_done(struct ce_state *ce_state, | 1443 | static void ath10k_pci_bmi_send_done(struct ath10k_ce_pipe *ce_state) |
| 1382 | void *transfer_context, | ||
| 1383 | u32 data, | ||
| 1384 | unsigned int nbytes, | ||
| 1385 | unsigned int transfer_id) | ||
| 1386 | { | 1444 | { |
| 1387 | struct bmi_xfer *xfer = transfer_context; | 1445 | struct bmi_xfer *xfer; |
| 1446 | u32 ce_data; | ||
| 1447 | unsigned int nbytes; | ||
| 1448 | unsigned int transfer_id; | ||
| 1449 | |||
| 1450 | if (ath10k_ce_completed_send_next(ce_state, (void **)&xfer, &ce_data, | ||
| 1451 | &nbytes, &transfer_id)) | ||
| 1452 | return; | ||
| 1388 | 1453 | ||
| 1389 | if (xfer->wait_for_resp) | 1454 | if (xfer->wait_for_resp) |
| 1390 | return; | 1455 | return; |
| @@ -1392,14 +1457,17 @@ static void ath10k_pci_bmi_send_done(struct ce_state *ce_state, | |||
| 1392 | complete(&xfer->done); | 1457 | complete(&xfer->done); |
| 1393 | } | 1458 | } |
| 1394 | 1459 | ||
| 1395 | static void ath10k_pci_bmi_recv_data(struct ce_state *ce_state, | 1460 | static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state) |
| 1396 | void *transfer_context, | ||
| 1397 | u32 data, | ||
| 1398 | unsigned int nbytes, | ||
| 1399 | unsigned int transfer_id, | ||
| 1400 | unsigned int flags) | ||
| 1401 | { | 1461 | { |
| 1402 | struct bmi_xfer *xfer = transfer_context; | 1462 | struct bmi_xfer *xfer; |
| 1463 | u32 ce_data; | ||
| 1464 | unsigned int nbytes; | ||
| 1465 | unsigned int transfer_id; | ||
| 1466 | unsigned int flags; | ||
| 1467 | |||
| 1468 | if (ath10k_ce_completed_recv_next(ce_state, (void **)&xfer, &ce_data, | ||
| 1469 | &nbytes, &transfer_id, &flags)) | ||
| 1470 | return; | ||
| 1403 | 1471 | ||
| 1404 | if (!xfer->wait_for_resp) { | 1472 | if (!xfer->wait_for_resp) { |
| 1405 | ath10k_warn("unexpected: BMI data received; ignoring\n"); | 1473 | ath10k_warn("unexpected: BMI data received; ignoring\n"); |
| @@ -1679,7 +1747,7 @@ static int ath10k_pci_init_config(struct ath10k *ar) | |||
| 1679 | static int ath10k_pci_ce_init(struct ath10k *ar) | 1747 | static int ath10k_pci_ce_init(struct ath10k *ar) |
| 1680 | { | 1748 | { |
| 1681 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 1749 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 1682 | struct hif_ce_pipe_info *pipe_info; | 1750 | struct ath10k_pci_pipe *pipe_info; |
| 1683 | const struct ce_attr *attr; | 1751 | const struct ce_attr *attr; |
| 1684 | int pipe_num; | 1752 | int pipe_num; |
| 1685 | 1753 | ||
| @@ -1895,7 +1963,7 @@ static const struct ath10k_hif_ops ath10k_pci_hif_ops = { | |||
| 1895 | 1963 | ||
| 1896 | static void ath10k_pci_ce_tasklet(unsigned long ptr) | 1964 | static void ath10k_pci_ce_tasklet(unsigned long ptr) |
| 1897 | { | 1965 | { |
| 1898 | struct hif_ce_pipe_info *pipe = (struct hif_ce_pipe_info *)ptr; | 1966 | struct ath10k_pci_pipe *pipe = (struct ath10k_pci_pipe *)ptr; |
| 1899 | struct ath10k_pci *ar_pci = pipe->ar_pci; | 1967 | struct ath10k_pci *ar_pci = pipe->ar_pci; |
| 1900 | 1968 | ||
| 1901 | ath10k_ce_per_engine_service(ar_pci->ar, pipe->pipe_num); | 1969 | ath10k_ce_per_engine_service(ar_pci->ar, pipe->pipe_num); |
| @@ -2212,18 +2280,13 @@ static int ath10k_pci_reset_target(struct ath10k *ar) | |||
| 2212 | 2280 | ||
| 2213 | static void ath10k_pci_device_reset(struct ath10k *ar) | 2281 | static void ath10k_pci_device_reset(struct ath10k *ar) |
| 2214 | { | 2282 | { |
| 2215 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | ||
| 2216 | void __iomem *mem = ar_pci->mem; | ||
| 2217 | int i; | 2283 | int i; |
| 2218 | u32 val; | 2284 | u32 val; |
| 2219 | 2285 | ||
| 2220 | if (!SOC_GLOBAL_RESET_ADDRESS) | 2286 | if (!SOC_GLOBAL_RESET_ADDRESS) |
| 2221 | return; | 2287 | return; |
| 2222 | 2288 | ||
| 2223 | if (!mem) | 2289 | ath10k_pci_reg_write32(ar, PCIE_SOC_WAKE_ADDRESS, |
| 2224 | return; | ||
| 2225 | |||
| 2226 | ath10k_pci_reg_write32(mem, PCIE_SOC_WAKE_ADDRESS, | ||
| 2227 | PCIE_SOC_WAKE_V_MASK); | 2290 | PCIE_SOC_WAKE_V_MASK); |
| 2228 | for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) { | 2291 | for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) { |
| 2229 | if (ath10k_pci_target_is_awake(ar)) | 2292 | if (ath10k_pci_target_is_awake(ar)) |
| @@ -2232,12 +2295,12 @@ static void ath10k_pci_device_reset(struct ath10k *ar) | |||
| 2232 | } | 2295 | } |
| 2233 | 2296 | ||
| 2234 | /* Put Target, including PCIe, into RESET. */ | 2297 | /* Put Target, including PCIe, into RESET. */ |
| 2235 | val = ath10k_pci_reg_read32(mem, SOC_GLOBAL_RESET_ADDRESS); | 2298 | val = ath10k_pci_reg_read32(ar, SOC_GLOBAL_RESET_ADDRESS); |
| 2236 | val |= 1; | 2299 | val |= 1; |
| 2237 | ath10k_pci_reg_write32(mem, SOC_GLOBAL_RESET_ADDRESS, val); | 2300 | ath10k_pci_reg_write32(ar, SOC_GLOBAL_RESET_ADDRESS, val); |
| 2238 | 2301 | ||
| 2239 | for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) { | 2302 | for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) { |
| 2240 | if (ath10k_pci_reg_read32(mem, RTC_STATE_ADDRESS) & | 2303 | if (ath10k_pci_reg_read32(ar, RTC_STATE_ADDRESS) & |
| 2241 | RTC_STATE_COLD_RESET_MASK) | 2304 | RTC_STATE_COLD_RESET_MASK) |
| 2242 | break; | 2305 | break; |
| 2243 | msleep(1); | 2306 | msleep(1); |
| @@ -2245,16 +2308,16 @@ static void ath10k_pci_device_reset(struct ath10k *ar) | |||
| 2245 | 2308 | ||
| 2246 | /* Pull Target, including PCIe, out of RESET. */ | 2309 | /* Pull Target, including PCIe, out of RESET. */ |
| 2247 | val &= ~1; | 2310 | val &= ~1; |
| 2248 | ath10k_pci_reg_write32(mem, SOC_GLOBAL_RESET_ADDRESS, val); | 2311 | ath10k_pci_reg_write32(ar, SOC_GLOBAL_RESET_ADDRESS, val); |
| 2249 | 2312 | ||
| 2250 | for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) { | 2313 | for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) { |
| 2251 | if (!(ath10k_pci_reg_read32(mem, RTC_STATE_ADDRESS) & | 2314 | if (!(ath10k_pci_reg_read32(ar, RTC_STATE_ADDRESS) & |
| 2252 | RTC_STATE_COLD_RESET_MASK)) | 2315 | RTC_STATE_COLD_RESET_MASK)) |
| 2253 | break; | 2316 | break; |
| 2254 | msleep(1); | 2317 | msleep(1); |
| 2255 | } | 2318 | } |
| 2256 | 2319 | ||
| 2257 | ath10k_pci_reg_write32(mem, PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_RESET); | 2320 | ath10k_pci_reg_write32(ar, PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_RESET); |
| 2258 | } | 2321 | } |
| 2259 | 2322 | ||
| 2260 | static void ath10k_pci_dump_features(struct ath10k_pci *ar_pci) | 2323 | static void ath10k_pci_dump_features(struct ath10k_pci *ar_pci) |
| @@ -2267,13 +2330,10 @@ static void ath10k_pci_dump_features(struct ath10k_pci *ar_pci) | |||
| 2267 | 2330 | ||
| 2268 | switch (i) { | 2331 | switch (i) { |
| 2269 | case ATH10K_PCI_FEATURE_MSI_X: | 2332 | case ATH10K_PCI_FEATURE_MSI_X: |
| 2270 | ath10k_dbg(ATH10K_DBG_PCI, "device supports MSI-X\n"); | 2333 | ath10k_dbg(ATH10K_DBG_BOOT, "device supports MSI-X\n"); |
| 2271 | break; | ||
| 2272 | case ATH10K_PCI_FEATURE_HW_1_0_WORKAROUND: | ||
| 2273 | ath10k_dbg(ATH10K_DBG_PCI, "QCA988X_1.0 workaround enabled\n"); | ||
| 2274 | break; | 2334 | break; |
| 2275 | case ATH10K_PCI_FEATURE_SOC_POWER_SAVE: | 2335 | case ATH10K_PCI_FEATURE_SOC_POWER_SAVE: |
| 2276 | ath10k_dbg(ATH10K_DBG_PCI, "QCA98XX SoC power save enabled\n"); | 2336 | ath10k_dbg(ATH10K_DBG_BOOT, "QCA98XX SoC power save enabled\n"); |
| 2277 | break; | 2337 | break; |
| 2278 | } | 2338 | } |
| 2279 | } | 2339 | } |
| @@ -2286,7 +2346,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, | |||
| 2286 | int ret = 0; | 2346 | int ret = 0; |
| 2287 | struct ath10k *ar; | 2347 | struct ath10k *ar; |
| 2288 | struct ath10k_pci *ar_pci; | 2348 | struct ath10k_pci *ar_pci; |
| 2289 | u32 lcr_val; | 2349 | u32 lcr_val, chip_id; |
| 2290 | 2350 | ||
| 2291 | ath10k_dbg(ATH10K_DBG_PCI, "%s\n", __func__); | 2351 | ath10k_dbg(ATH10K_DBG_PCI, "%s\n", __func__); |
| 2292 | 2352 | ||
| @@ -2298,9 +2358,6 @@ static int ath10k_pci_probe(struct pci_dev *pdev, | |||
| 2298 | ar_pci->dev = &pdev->dev; | 2358 | ar_pci->dev = &pdev->dev; |
| 2299 | 2359 | ||
| 2300 | switch (pci_dev->device) { | 2360 | switch (pci_dev->device) { |
| 2301 | case QCA988X_1_0_DEVICE_ID: | ||
| 2302 | set_bit(ATH10K_PCI_FEATURE_HW_1_0_WORKAROUND, ar_pci->features); | ||
| 2303 | break; | ||
| 2304 | case QCA988X_2_0_DEVICE_ID: | 2361 | case QCA988X_2_0_DEVICE_ID: |
| 2305 | set_bit(ATH10K_PCI_FEATURE_MSI_X, ar_pci->features); | 2362 | set_bit(ATH10K_PCI_FEATURE_MSI_X, ar_pci->features); |
| 2306 | break; | 2363 | break; |
| @@ -2322,10 +2379,6 @@ static int ath10k_pci_probe(struct pci_dev *pdev, | |||
| 2322 | goto err_ar_pci; | 2379 | goto err_ar_pci; |
| 2323 | } | 2380 | } |
| 2324 | 2381 | ||
| 2325 | /* Enable QCA988X_1.0 HW workarounds */ | ||
| 2326 | if (test_bit(ATH10K_PCI_FEATURE_HW_1_0_WORKAROUND, ar_pci->features)) | ||
| 2327 | spin_lock_init(&ar_pci->hw_v1_workaround_lock); | ||
| 2328 | |||
| 2329 | ar_pci->ar = ar; | 2382 | ar_pci->ar = ar; |
| 2330 | ar_pci->fw_indicator_address = FW_INDICATOR_ADDRESS; | 2383 | ar_pci->fw_indicator_address = FW_INDICATOR_ADDRESS; |
| 2331 | atomic_set(&ar_pci->keep_awake_count, 0); | 2384 | atomic_set(&ar_pci->keep_awake_count, 0); |
| @@ -2395,9 +2448,20 @@ static int ath10k_pci_probe(struct pci_dev *pdev, | |||
| 2395 | 2448 | ||
| 2396 | spin_lock_init(&ar_pci->ce_lock); | 2449 | spin_lock_init(&ar_pci->ce_lock); |
| 2397 | 2450 | ||
| 2398 | ar_pci->cacheline_sz = dma_get_cache_alignment(); | 2451 | ret = ath10k_do_pci_wake(ar); |
| 2452 | if (ret) { | ||
| 2453 | ath10k_err("Failed to get chip id: %d\n", ret); | ||
| 2454 | return ret; | ||
| 2455 | } | ||
| 2456 | |||
| 2457 | chip_id = ath10k_pci_read32(ar, | ||
| 2458 | RTC_SOC_BASE_ADDRESS + SOC_CHIP_ID_ADDRESS); | ||
| 2459 | |||
| 2460 | ath10k_do_pci_sleep(ar); | ||
| 2461 | |||
| 2462 | ath10k_dbg(ATH10K_DBG_BOOT, "boot pci_mem 0x%p\n", ar_pci->mem); | ||
| 2399 | 2463 | ||
| 2400 | ret = ath10k_core_register(ar); | 2464 | ret = ath10k_core_register(ar, chip_id); |
| 2401 | if (ret) { | 2465 | if (ret) { |
| 2402 | ath10k_err("could not register driver core (%d)\n", ret); | 2466 | ath10k_err("could not register driver core (%d)\n", ret); |
| 2403 | goto err_iomap; | 2467 | goto err_iomap; |
| @@ -2414,7 +2478,6 @@ err_region: | |||
| 2414 | err_device: | 2478 | err_device: |
| 2415 | pci_disable_device(pdev); | 2479 | pci_disable_device(pdev); |
| 2416 | err_ar: | 2480 | err_ar: |
| 2417 | pci_set_drvdata(pdev, NULL); | ||
| 2418 | ath10k_core_destroy(ar); | 2481 | ath10k_core_destroy(ar); |
| 2419 | err_ar_pci: | 2482 | err_ar_pci: |
| 2420 | /* call HIF PCI free here */ | 2483 | /* call HIF PCI free here */ |
| @@ -2442,7 +2505,6 @@ static void ath10k_pci_remove(struct pci_dev *pdev) | |||
| 2442 | 2505 | ||
| 2443 | ath10k_core_unregister(ar); | 2506 | ath10k_core_unregister(ar); |
| 2444 | 2507 | ||
| 2445 | pci_set_drvdata(pdev, NULL); | ||
| 2446 | pci_iounmap(pdev, ar_pci->mem); | 2508 | pci_iounmap(pdev, ar_pci->mem); |
| 2447 | pci_release_region(pdev, BAR_NUM); | 2509 | pci_release_region(pdev, BAR_NUM); |
| 2448 | pci_clear_master(pdev); | 2510 | pci_clear_master(pdev); |
| @@ -2483,9 +2545,6 @@ module_exit(ath10k_pci_exit); | |||
| 2483 | MODULE_AUTHOR("Qualcomm Atheros"); | 2545 | MODULE_AUTHOR("Qualcomm Atheros"); |
| 2484 | MODULE_DESCRIPTION("Driver support for Atheros QCA988X PCIe devices"); | 2546 | MODULE_DESCRIPTION("Driver support for Atheros QCA988X PCIe devices"); |
| 2485 | MODULE_LICENSE("Dual BSD/GPL"); | 2547 | MODULE_LICENSE("Dual BSD/GPL"); |
| 2486 | MODULE_FIRMWARE(QCA988X_HW_1_0_FW_DIR "/" QCA988X_HW_1_0_FW_FILE); | ||
| 2487 | MODULE_FIRMWARE(QCA988X_HW_1_0_FW_DIR "/" QCA988X_HW_1_0_OTP_FILE); | ||
| 2488 | MODULE_FIRMWARE(QCA988X_HW_1_0_FW_DIR "/" QCA988X_HW_1_0_BOARD_DATA_FILE); | ||
| 2489 | MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_FILE); | 2548 | MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_FILE); |
| 2490 | MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_OTP_FILE); | 2549 | MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_OTP_FILE); |
| 2491 | MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_BOARD_DATA_FILE); | 2550 | MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_BOARD_DATA_FILE); |
diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index 871bb339d56d..52fb7b973571 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h | |||
| @@ -43,22 +43,23 @@ struct bmi_xfer { | |||
| 43 | u32 resp_len; | 43 | u32 resp_len; |
| 44 | }; | 44 | }; |
| 45 | 45 | ||
| 46 | enum ath10k_pci_compl_state { | ||
| 47 | ATH10K_PCI_COMPL_FREE = 0, | ||
| 48 | ATH10K_PCI_COMPL_SEND, | ||
| 49 | ATH10K_PCI_COMPL_RECV, | ||
| 50 | }; | ||
| 51 | |||
| 46 | struct ath10k_pci_compl { | 52 | struct ath10k_pci_compl { |
| 47 | struct list_head list; | 53 | struct list_head list; |
| 48 | int send_or_recv; | 54 | enum ath10k_pci_compl_state state; |
| 49 | struct ce_state *ce_state; | 55 | struct ath10k_ce_pipe *ce_state; |
| 50 | struct hif_ce_pipe_info *pipe_info; | 56 | struct ath10k_pci_pipe *pipe_info; |
| 51 | void *transfer_context; | 57 | struct sk_buff *skb; |
| 52 | unsigned int nbytes; | 58 | unsigned int nbytes; |
| 53 | unsigned int transfer_id; | 59 | unsigned int transfer_id; |
| 54 | unsigned int flags; | 60 | unsigned int flags; |
| 55 | }; | 61 | }; |
| 56 | 62 | ||
| 57 | /* compl_state.send_or_recv */ | ||
| 58 | #define HIF_CE_COMPLETE_FREE 0 | ||
| 59 | #define HIF_CE_COMPLETE_SEND 1 | ||
| 60 | #define HIF_CE_COMPLETE_RECV 2 | ||
| 61 | |||
| 62 | /* | 63 | /* |
| 63 | * PCI-specific Target state | 64 | * PCI-specific Target state |
| 64 | * | 65 | * |
| @@ -152,17 +153,16 @@ struct service_to_pipe { | |||
| 152 | 153 | ||
| 153 | enum ath10k_pci_features { | 154 | enum ath10k_pci_features { |
| 154 | ATH10K_PCI_FEATURE_MSI_X = 0, | 155 | ATH10K_PCI_FEATURE_MSI_X = 0, |
| 155 | ATH10K_PCI_FEATURE_HW_1_0_WORKAROUND = 1, | 156 | ATH10K_PCI_FEATURE_SOC_POWER_SAVE = 1, |
| 156 | ATH10K_PCI_FEATURE_SOC_POWER_SAVE = 2, | ||
| 157 | 157 | ||
| 158 | /* keep last */ | 158 | /* keep last */ |
| 159 | ATH10K_PCI_FEATURE_COUNT | 159 | ATH10K_PCI_FEATURE_COUNT |
| 160 | }; | 160 | }; |
| 161 | 161 | ||
| 162 | /* Per-pipe state. */ | 162 | /* Per-pipe state. */ |
| 163 | struct hif_ce_pipe_info { | 163 | struct ath10k_pci_pipe { |
| 164 | /* Handle of underlying Copy Engine */ | 164 | /* Handle of underlying Copy Engine */ |
| 165 | struct ce_state *ce_hdl; | 165 | struct ath10k_ce_pipe *ce_hdl; |
| 166 | 166 | ||
| 167 | /* Our pipe number; facilitiates use of pipe_info ptrs. */ | 167 | /* Our pipe number; facilitiates use of pipe_info ptrs. */ |
| 168 | u8 pipe_num; | 168 | u8 pipe_num; |
| @@ -178,9 +178,6 @@ struct hif_ce_pipe_info { | |||
| 178 | /* List of free CE completion slots */ | 178 | /* List of free CE completion slots */ |
| 179 | struct list_head compl_free; | 179 | struct list_head compl_free; |
| 180 | 180 | ||
| 181 | /* Limit the number of outstanding send requests. */ | ||
| 182 | int num_sends_allowed; | ||
| 183 | |||
| 184 | struct ath10k_pci *ar_pci; | 181 | struct ath10k_pci *ar_pci; |
| 185 | struct tasklet_struct intr; | 182 | struct tasklet_struct intr; |
| 186 | }; | 183 | }; |
| @@ -190,7 +187,6 @@ struct ath10k_pci { | |||
| 190 | struct device *dev; | 187 | struct device *dev; |
| 191 | struct ath10k *ar; | 188 | struct ath10k *ar; |
| 192 | void __iomem *mem; | 189 | void __iomem *mem; |
| 193 | int cacheline_sz; | ||
| 194 | 190 | ||
| 195 | DECLARE_BITMAP(features, ATH10K_PCI_FEATURE_COUNT); | 191 | DECLARE_BITMAP(features, ATH10K_PCI_FEATURE_COUNT); |
| 196 | 192 | ||
| @@ -219,7 +215,7 @@ struct ath10k_pci { | |||
| 219 | 215 | ||
| 220 | bool compl_processing; | 216 | bool compl_processing; |
| 221 | 217 | ||
| 222 | struct hif_ce_pipe_info pipe_info[CE_COUNT_MAX]; | 218 | struct ath10k_pci_pipe pipe_info[CE_COUNT_MAX]; |
| 223 | 219 | ||
| 224 | struct ath10k_hif_cb msg_callbacks_current; | 220 | struct ath10k_hif_cb msg_callbacks_current; |
| 225 | 221 | ||
| @@ -227,16 +223,13 @@ struct ath10k_pci { | |||
| 227 | u32 fw_indicator_address; | 223 | u32 fw_indicator_address; |
| 228 | 224 | ||
| 229 | /* Copy Engine used for Diagnostic Accesses */ | 225 | /* Copy Engine used for Diagnostic Accesses */ |
| 230 | struct ce_state *ce_diag; | 226 | struct ath10k_ce_pipe *ce_diag; |
| 231 | 227 | ||
| 232 | /* FIXME: document what this really protects */ | 228 | /* FIXME: document what this really protects */ |
| 233 | spinlock_t ce_lock; | 229 | spinlock_t ce_lock; |
| 234 | 230 | ||
| 235 | /* Map CE id to ce_state */ | 231 | /* Map CE id to ce_state */ |
| 236 | struct ce_state *ce_id_to_state[CE_COUNT_MAX]; | 232 | struct ath10k_ce_pipe ce_states[CE_COUNT_MAX]; |
| 237 | |||
| 238 | /* makes sure that dummy reads are atomic */ | ||
| 239 | spinlock_t hw_v1_workaround_lock; | ||
| 240 | }; | 233 | }; |
| 241 | 234 | ||
| 242 | static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar) | 235 | static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar) |
| @@ -244,14 +237,18 @@ static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar) | |||
| 244 | return ar->hif.priv; | 237 | return ar->hif.priv; |
| 245 | } | 238 | } |
| 246 | 239 | ||
| 247 | static inline u32 ath10k_pci_reg_read32(void __iomem *mem, u32 addr) | 240 | static inline u32 ath10k_pci_reg_read32(struct ath10k *ar, u32 addr) |
| 248 | { | 241 | { |
| 249 | return ioread32(mem + PCIE_LOCAL_BASE_ADDRESS + addr); | 242 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 243 | |||
| 244 | return ioread32(ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + addr); | ||
| 250 | } | 245 | } |
| 251 | 246 | ||
| 252 | static inline void ath10k_pci_reg_write32(void __iomem *mem, u32 addr, u32 val) | 247 | static inline void ath10k_pci_reg_write32(struct ath10k *ar, u32 addr, u32 val) |
| 253 | { | 248 | { |
| 254 | iowrite32(val, mem + PCIE_LOCAL_BASE_ADDRESS + addr); | 249 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 250 | |||
| 251 | iowrite32(val, ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + addr); | ||
| 255 | } | 252 | } |
| 256 | 253 | ||
| 257 | #define ATH_PCI_RESET_WAIT_MAX 10 /* ms */ | 254 | #define ATH_PCI_RESET_WAIT_MAX 10 /* ms */ |
| @@ -310,23 +307,8 @@ static inline void ath10k_pci_write32(struct ath10k *ar, u32 offset, | |||
| 310 | u32 value) | 307 | u32 value) |
| 311 | { | 308 | { |
| 312 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 309 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 313 | void __iomem *addr = ar_pci->mem; | ||
| 314 | |||
| 315 | if (test_bit(ATH10K_PCI_FEATURE_HW_1_0_WORKAROUND, ar_pci->features)) { | ||
| 316 | unsigned long irq_flags; | ||
| 317 | 310 | ||
| 318 | spin_lock_irqsave(&ar_pci->hw_v1_workaround_lock, irq_flags); | 311 | iowrite32(value, ar_pci->mem + offset); |
| 319 | |||
| 320 | ioread32(addr+offset+4); /* 3rd read prior to write */ | ||
| 321 | ioread32(addr+offset+4); /* 2nd read prior to write */ | ||
| 322 | ioread32(addr+offset+4); /* 1st read prior to write */ | ||
| 323 | iowrite32(value, addr+offset); | ||
| 324 | |||
| 325 | spin_unlock_irqrestore(&ar_pci->hw_v1_workaround_lock, | ||
| 326 | irq_flags); | ||
| 327 | } else { | ||
| 328 | iowrite32(value, addr+offset); | ||
| 329 | } | ||
| 330 | } | 312 | } |
| 331 | 313 | ||
| 332 | static inline u32 ath10k_pci_read32(struct ath10k *ar, u32 offset) | 314 | static inline u32 ath10k_pci_read32(struct ath10k *ar, u32 offset) |
| @@ -336,15 +318,17 @@ static inline u32 ath10k_pci_read32(struct ath10k *ar, u32 offset) | |||
| 336 | return ioread32(ar_pci->mem + offset); | 318 | return ioread32(ar_pci->mem + offset); |
| 337 | } | 319 | } |
| 338 | 320 | ||
| 339 | void ath10k_do_pci_wake(struct ath10k *ar); | 321 | int ath10k_do_pci_wake(struct ath10k *ar); |
| 340 | void ath10k_do_pci_sleep(struct ath10k *ar); | 322 | void ath10k_do_pci_sleep(struct ath10k *ar); |
| 341 | 323 | ||
| 342 | static inline void ath10k_pci_wake(struct ath10k *ar) | 324 | static inline int ath10k_pci_wake(struct ath10k *ar) |
| 343 | { | 325 | { |
| 344 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 326 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
| 345 | 327 | ||
| 346 | if (test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features)) | 328 | if (test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features)) |
| 347 | ath10k_do_pci_wake(ar); | 329 | return ath10k_do_pci_wake(ar); |
| 330 | |||
| 331 | return 0; | ||
| 348 | } | 332 | } |
| 349 | 333 | ||
| 350 | static inline void ath10k_pci_sleep(struct ath10k *ar) | 334 | static inline void ath10k_pci_sleep(struct ath10k *ar) |
diff --git a/drivers/net/wireless/ath/ath10k/rx_desc.h b/drivers/net/wireless/ath/ath10k/rx_desc.h index bfec6c8f2ecb..1c584c4b019c 100644 --- a/drivers/net/wireless/ath/ath10k/rx_desc.h +++ b/drivers/net/wireless/ath/ath10k/rx_desc.h | |||
| @@ -422,10 +422,30 @@ struct rx_mpdu_end { | |||
| 422 | #define RX_MSDU_START_INFO1_IP_FRAG (1 << 14) | 422 | #define RX_MSDU_START_INFO1_IP_FRAG (1 << 14) |
| 423 | #define RX_MSDU_START_INFO1_TCP_ONLY_ACK (1 << 15) | 423 | #define RX_MSDU_START_INFO1_TCP_ONLY_ACK (1 << 15) |
| 424 | 424 | ||
| 425 | /* The decapped header (rx_hdr_status) contains the following: | ||
| 426 | * a) 802.11 header | ||
| 427 | * [padding to 4 bytes] | ||
| 428 | * b) HW crypto parameter | ||
| 429 | * - 0 bytes for no security | ||
| 430 | * - 4 bytes for WEP | ||
| 431 | * - 8 bytes for TKIP, AES | ||
| 432 | * [padding to 4 bytes] | ||
| 433 | * c) A-MSDU subframe header (14 bytes) if appliable | ||
| 434 | * d) LLC/SNAP (RFC1042, 8 bytes) | ||
| 435 | * | ||
| 436 | * In case of A-MSDU only first frame in sequence contains (a) and (b). */ | ||
| 425 | enum rx_msdu_decap_format { | 437 | enum rx_msdu_decap_format { |
| 426 | RX_MSDU_DECAP_RAW = 0, | 438 | RX_MSDU_DECAP_RAW = 0, |
| 427 | RX_MSDU_DECAP_NATIVE_WIFI = 1, | 439 | |
| 440 | /* Note: QoS frames are reported as non-QoS. The rx_hdr_status in | ||
| 441 | * htt_rx_desc contains the original decapped 802.11 header. */ | ||
| 442 | RX_MSDU_DECAP_NATIVE_WIFI = 1, | ||
| 443 | |||
| 444 | /* Payload contains an ethernet header (struct ethhdr). */ | ||
| 428 | RX_MSDU_DECAP_ETHERNET2_DIX = 2, | 445 | RX_MSDU_DECAP_ETHERNET2_DIX = 2, |
| 446 | |||
| 447 | /* Payload contains two 48-bit addresses and 2-byte length (14 bytes | ||
| 448 | * total), followed by an RFC1042 header (8 bytes). */ | ||
| 429 | RX_MSDU_DECAP_8023_SNAP_LLC = 3 | 449 | RX_MSDU_DECAP_8023_SNAP_LLC = 3 |
| 430 | }; | 450 | }; |
| 431 | 451 | ||
diff --git a/drivers/net/wireless/ath/ath10k/trace.h b/drivers/net/wireless/ath/ath10k/trace.h index 85e806bf7257..90817ddc92ba 100644 --- a/drivers/net/wireless/ath/ath10k/trace.h +++ b/drivers/net/wireless/ath/ath10k/trace.h | |||
| @@ -111,26 +111,29 @@ TRACE_EVENT(ath10k_log_dbg_dump, | |||
| 111 | ); | 111 | ); |
| 112 | 112 | ||
| 113 | TRACE_EVENT(ath10k_wmi_cmd, | 113 | TRACE_EVENT(ath10k_wmi_cmd, |
| 114 | TP_PROTO(int id, void *buf, size_t buf_len), | 114 | TP_PROTO(int id, void *buf, size_t buf_len, int ret), |
| 115 | 115 | ||
| 116 | TP_ARGS(id, buf, buf_len), | 116 | TP_ARGS(id, buf, buf_len, ret), |
| 117 | 117 | ||
| 118 | TP_STRUCT__entry( | 118 | TP_STRUCT__entry( |
| 119 | __field(unsigned int, id) | 119 | __field(unsigned int, id) |
| 120 | __field(size_t, buf_len) | 120 | __field(size_t, buf_len) |
| 121 | __dynamic_array(u8, buf, buf_len) | 121 | __dynamic_array(u8, buf, buf_len) |
| 122 | __field(int, ret) | ||
| 122 | ), | 123 | ), |
| 123 | 124 | ||
| 124 | TP_fast_assign( | 125 | TP_fast_assign( |
| 125 | __entry->id = id; | 126 | __entry->id = id; |
| 126 | __entry->buf_len = buf_len; | 127 | __entry->buf_len = buf_len; |
| 128 | __entry->ret = ret; | ||
| 127 | memcpy(__get_dynamic_array(buf), buf, buf_len); | 129 | memcpy(__get_dynamic_array(buf), buf, buf_len); |
| 128 | ), | 130 | ), |
| 129 | 131 | ||
| 130 | TP_printk( | 132 | TP_printk( |
| 131 | "id %d len %zu", | 133 | "id %d len %zu ret %d", |
| 132 | __entry->id, | 134 | __entry->id, |
| 133 | __entry->buf_len | 135 | __entry->buf_len, |
| 136 | __entry->ret | ||
| 134 | ) | 137 | ) |
| 135 | ); | 138 | ); |
| 136 | 139 | ||
| @@ -158,6 +161,27 @@ TRACE_EVENT(ath10k_wmi_event, | |||
| 158 | ) | 161 | ) |
| 159 | ); | 162 | ); |
| 160 | 163 | ||
| 164 | TRACE_EVENT(ath10k_htt_stats, | ||
| 165 | TP_PROTO(void *buf, size_t buf_len), | ||
| 166 | |||
| 167 | TP_ARGS(buf, buf_len), | ||
| 168 | |||
| 169 | TP_STRUCT__entry( | ||
| 170 | __field(size_t, buf_len) | ||
| 171 | __dynamic_array(u8, buf, buf_len) | ||
| 172 | ), | ||
| 173 | |||
| 174 | TP_fast_assign( | ||
| 175 | __entry->buf_len = buf_len; | ||
| 176 | memcpy(__get_dynamic_array(buf), buf, buf_len); | ||
| 177 | ), | ||
| 178 | |||
| 179 | TP_printk( | ||
| 180 | "len %zu", | ||
| 181 | __entry->buf_len | ||
| 182 | ) | ||
| 183 | ); | ||
| 184 | |||
| 161 | #endif /* _TRACE_H_ || TRACE_HEADER_MULTI_READ*/ | 185 | #endif /* _TRACE_H_ || TRACE_HEADER_MULTI_READ*/ |
| 162 | 186 | ||
| 163 | /* we don't want to use include/trace/events */ | 187 | /* we don't want to use include/trace/events */ |
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index 68b6faefd1d8..5ae373a1e294 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c | |||
| @@ -44,40 +44,39 @@ out: | |||
| 44 | spin_unlock_bh(&ar->data_lock); | 44 | spin_unlock_bh(&ar->data_lock); |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | void ath10k_txrx_tx_unref(struct ath10k_htt *htt, struct sk_buff *txdesc) | 47 | void ath10k_txrx_tx_unref(struct ath10k_htt *htt, |
| 48 | const struct htt_tx_done *tx_done) | ||
| 48 | { | 49 | { |
| 49 | struct device *dev = htt->ar->dev; | 50 | struct device *dev = htt->ar->dev; |
| 50 | struct ieee80211_tx_info *info; | 51 | struct ieee80211_tx_info *info; |
| 51 | struct sk_buff *txfrag = ATH10K_SKB_CB(txdesc)->htt.txfrag; | 52 | struct ath10k_skb_cb *skb_cb; |
| 52 | struct sk_buff *msdu = ATH10K_SKB_CB(txdesc)->htt.msdu; | 53 | struct sk_buff *msdu; |
| 53 | int ret; | 54 | int ret; |
| 54 | 55 | ||
| 55 | if (ATH10K_SKB_CB(txdesc)->htt.refcount == 0) | 56 | ath10k_dbg(ATH10K_DBG_HTT, "htt tx completion msdu_id %u discard %d no_ack %d\n", |
| 56 | return; | 57 | tx_done->msdu_id, !!tx_done->discard, !!tx_done->no_ack); |
| 57 | |||
| 58 | ATH10K_SKB_CB(txdesc)->htt.refcount--; | ||
| 59 | 58 | ||
| 60 | if (ATH10K_SKB_CB(txdesc)->htt.refcount > 0) | 59 | if (tx_done->msdu_id >= htt->max_num_pending_tx) { |
| 60 | ath10k_warn("warning: msdu_id %d too big, ignoring\n", | ||
| 61 | tx_done->msdu_id); | ||
| 61 | return; | 62 | return; |
| 62 | |||
| 63 | if (txfrag) { | ||
| 64 | ret = ath10k_skb_unmap(dev, txfrag); | ||
| 65 | if (ret) | ||
| 66 | ath10k_warn("txfrag unmap failed (%d)\n", ret); | ||
| 67 | |||
| 68 | dev_kfree_skb_any(txfrag); | ||
| 69 | } | 63 | } |
| 70 | 64 | ||
| 65 | msdu = htt->pending_tx[tx_done->msdu_id]; | ||
| 66 | skb_cb = ATH10K_SKB_CB(msdu); | ||
| 67 | |||
| 71 | ret = ath10k_skb_unmap(dev, msdu); | 68 | ret = ath10k_skb_unmap(dev, msdu); |
| 72 | if (ret) | 69 | if (ret) |
| 73 | ath10k_warn("data skb unmap failed (%d)\n", ret); | 70 | ath10k_warn("data skb unmap failed (%d)\n", ret); |
| 74 | 71 | ||
| 72 | if (skb_cb->htt.frag_len) | ||
| 73 | skb_pull(msdu, skb_cb->htt.frag_len + skb_cb->htt.pad_len); | ||
| 74 | |||
| 75 | ath10k_report_offchan_tx(htt->ar, msdu); | 75 | ath10k_report_offchan_tx(htt->ar, msdu); |
| 76 | 76 | ||
| 77 | info = IEEE80211_SKB_CB(msdu); | 77 | info = IEEE80211_SKB_CB(msdu); |
| 78 | memset(&info->status, 0, sizeof(info->status)); | ||
| 79 | 78 | ||
| 80 | if (ATH10K_SKB_CB(txdesc)->htt.discard) { | 79 | if (tx_done->discard) { |
| 81 | ieee80211_free_txskb(htt->ar->hw, msdu); | 80 | ieee80211_free_txskb(htt->ar->hw, msdu); |
| 82 | goto exit; | 81 | goto exit; |
| 83 | } | 82 | } |
| @@ -85,7 +84,7 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, struct sk_buff *txdesc) | |||
| 85 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) | 84 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) |
| 86 | info->flags |= IEEE80211_TX_STAT_ACK; | 85 | info->flags |= IEEE80211_TX_STAT_ACK; |
| 87 | 86 | ||
| 88 | if (ATH10K_SKB_CB(txdesc)->htt.no_ack) | 87 | if (tx_done->no_ack) |
| 89 | info->flags &= ~IEEE80211_TX_STAT_ACK; | 88 | info->flags &= ~IEEE80211_TX_STAT_ACK; |
| 90 | 89 | ||
| 91 | ieee80211_tx_status(htt->ar->hw, msdu); | 90 | ieee80211_tx_status(htt->ar->hw, msdu); |
| @@ -93,36 +92,12 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, struct sk_buff *txdesc) | |||
| 93 | 92 | ||
| 94 | exit: | 93 | exit: |
| 95 | spin_lock_bh(&htt->tx_lock); | 94 | spin_lock_bh(&htt->tx_lock); |
| 96 | htt->pending_tx[ATH10K_SKB_CB(txdesc)->htt.msdu_id] = NULL; | 95 | htt->pending_tx[tx_done->msdu_id] = NULL; |
| 97 | ath10k_htt_tx_free_msdu_id(htt, ATH10K_SKB_CB(txdesc)->htt.msdu_id); | 96 | ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id); |
| 98 | __ath10k_htt_tx_dec_pending(htt); | 97 | __ath10k_htt_tx_dec_pending(htt); |
| 99 | if (bitmap_empty(htt->used_msdu_ids, htt->max_num_pending_tx)) | 98 | if (htt->num_pending_tx == 0) |
| 100 | wake_up(&htt->empty_tx_wq); | 99 | wake_up(&htt->empty_tx_wq); |
| 101 | spin_unlock_bh(&htt->tx_lock); | 100 | spin_unlock_bh(&htt->tx_lock); |
| 102 | |||
| 103 | dev_kfree_skb_any(txdesc); | ||
| 104 | } | ||
| 105 | |||
| 106 | void ath10k_txrx_tx_completed(struct ath10k_htt *htt, | ||
| 107 | const struct htt_tx_done *tx_done) | ||
| 108 | { | ||
| 109 | struct sk_buff *txdesc; | ||
| 110 | |||
| 111 | ath10k_dbg(ATH10K_DBG_HTT, "htt tx completion msdu_id %u discard %d no_ack %d\n", | ||
| 112 | tx_done->msdu_id, !!tx_done->discard, !!tx_done->no_ack); | ||
| 113 | |||
| 114 | if (tx_done->msdu_id >= htt->max_num_pending_tx) { | ||
| 115 | ath10k_warn("warning: msdu_id %d too big, ignoring\n", | ||
| 116 | tx_done->msdu_id); | ||
| 117 | return; | ||
| 118 | } | ||
| 119 | |||
| 120 | txdesc = htt->pending_tx[tx_done->msdu_id]; | ||
| 121 | |||
| 122 | ATH10K_SKB_CB(txdesc)->htt.discard = tx_done->discard; | ||
| 123 | ATH10K_SKB_CB(txdesc)->htt.no_ack = tx_done->no_ack; | ||
| 124 | |||
| 125 | ath10k_txrx_tx_unref(htt, txdesc); | ||
| 126 | } | 101 | } |
| 127 | 102 | ||
| 128 | static const u8 rx_legacy_rate_idx[] = { | 103 | static const u8 rx_legacy_rate_idx[] = { |
| @@ -293,6 +268,8 @@ void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info) | |||
| 293 | status->vht_nss, | 268 | status->vht_nss, |
| 294 | status->freq, | 269 | status->freq, |
| 295 | status->band); | 270 | status->band); |
| 271 | ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "rx skb: ", | ||
| 272 | info->skb->data, info->skb->len); | ||
| 296 | 273 | ||
| 297 | ieee80211_rx(ar->hw, info->skb); | 274 | ieee80211_rx(ar->hw, info->skb); |
| 298 | } | 275 | } |
diff --git a/drivers/net/wireless/ath/ath10k/txrx.h b/drivers/net/wireless/ath/ath10k/txrx.h index e78632a76df7..356dc9c04c9e 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.h +++ b/drivers/net/wireless/ath/ath10k/txrx.h | |||
| @@ -19,9 +19,8 @@ | |||
| 19 | 19 | ||
| 20 | #include "htt.h" | 20 | #include "htt.h" |
| 21 | 21 | ||
| 22 | void ath10k_txrx_tx_unref(struct ath10k_htt *htt, struct sk_buff *txdesc); | 22 | void ath10k_txrx_tx_unref(struct ath10k_htt *htt, |
| 23 | void ath10k_txrx_tx_completed(struct ath10k_htt *htt, | 23 | const struct htt_tx_done *tx_done); |
| 24 | const struct htt_tx_done *tx_done); | ||
| 25 | void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info); | 24 | void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info); |
| 26 | 25 | ||
| 27 | struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id, | 26 | struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id, |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 55f90c761868..ccf3597fd9e2 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c | |||
| @@ -23,29 +23,470 @@ | |||
| 23 | #include "wmi.h" | 23 | #include "wmi.h" |
| 24 | #include "mac.h" | 24 | #include "mac.h" |
| 25 | 25 | ||
| 26 | void ath10k_wmi_flush_tx(struct ath10k *ar) | 26 | /* MAIN WMI cmd track */ |
| 27 | { | 27 | static struct wmi_cmd_map wmi_cmd_map = { |
| 28 | int ret; | 28 | .init_cmdid = WMI_INIT_CMDID, |
| 29 | 29 | .start_scan_cmdid = WMI_START_SCAN_CMDID, | |
| 30 | lockdep_assert_held(&ar->conf_mutex); | 30 | .stop_scan_cmdid = WMI_STOP_SCAN_CMDID, |
| 31 | 31 | .scan_chan_list_cmdid = WMI_SCAN_CHAN_LIST_CMDID, | |
| 32 | if (ar->state == ATH10K_STATE_WEDGED) { | 32 | .scan_sch_prio_tbl_cmdid = WMI_SCAN_SCH_PRIO_TBL_CMDID, |
| 33 | ath10k_warn("wmi flush skipped - device is wedged anyway\n"); | 33 | .pdev_set_regdomain_cmdid = WMI_PDEV_SET_REGDOMAIN_CMDID, |
| 34 | return; | 34 | .pdev_set_channel_cmdid = WMI_PDEV_SET_CHANNEL_CMDID, |
| 35 | } | 35 | .pdev_set_param_cmdid = WMI_PDEV_SET_PARAM_CMDID, |
| 36 | 36 | .pdev_pktlog_enable_cmdid = WMI_PDEV_PKTLOG_ENABLE_CMDID, | |
| 37 | ret = wait_event_timeout(ar->wmi.wq, | 37 | .pdev_pktlog_disable_cmdid = WMI_PDEV_PKTLOG_DISABLE_CMDID, |
| 38 | atomic_read(&ar->wmi.pending_tx_count) == 0, | 38 | .pdev_set_wmm_params_cmdid = WMI_PDEV_SET_WMM_PARAMS_CMDID, |
| 39 | 5*HZ); | 39 | .pdev_set_ht_cap_ie_cmdid = WMI_PDEV_SET_HT_CAP_IE_CMDID, |
| 40 | if (atomic_read(&ar->wmi.pending_tx_count) == 0) | 40 | .pdev_set_vht_cap_ie_cmdid = WMI_PDEV_SET_VHT_CAP_IE_CMDID, |
| 41 | return; | 41 | .pdev_set_dscp_tid_map_cmdid = WMI_PDEV_SET_DSCP_TID_MAP_CMDID, |
| 42 | 42 | .pdev_set_quiet_mode_cmdid = WMI_PDEV_SET_QUIET_MODE_CMDID, | |
| 43 | if (ret == 0) | 43 | .pdev_green_ap_ps_enable_cmdid = WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID, |
| 44 | ret = -ETIMEDOUT; | 44 | .pdev_get_tpc_config_cmdid = WMI_PDEV_GET_TPC_CONFIG_CMDID, |
| 45 | 45 | .pdev_set_base_macaddr_cmdid = WMI_PDEV_SET_BASE_MACADDR_CMDID, | |
| 46 | if (ret < 0) | 46 | .vdev_create_cmdid = WMI_VDEV_CREATE_CMDID, |
| 47 | ath10k_warn("wmi flush failed (%d)\n", ret); | 47 | .vdev_delete_cmdid = WMI_VDEV_DELETE_CMDID, |
| 48 | } | 48 | .vdev_start_request_cmdid = WMI_VDEV_START_REQUEST_CMDID, |
| 49 | .vdev_restart_request_cmdid = WMI_VDEV_RESTART_REQUEST_CMDID, | ||
| 50 | .vdev_up_cmdid = WMI_VDEV_UP_CMDID, | ||
| 51 | .vdev_stop_cmdid = WMI_VDEV_STOP_CMDID, | ||
| 52 | .vdev_down_cmdid = WMI_VDEV_DOWN_CMDID, | ||
| 53 | .vdev_set_param_cmdid = WMI_VDEV_SET_PARAM_CMDID, | ||
| 54 | .vdev_install_key_cmdid = WMI_VDEV_INSTALL_KEY_CMDID, | ||
| 55 | .peer_create_cmdid = WMI_PEER_CREATE_CMDID, | ||
| 56 | .peer_delete_cmdid = WMI_PEER_DELETE_CMDID, | ||
| 57 | .peer_flush_tids_cmdid = WMI_PEER_FLUSH_TIDS_CMDID, | ||
| 58 | .peer_set_param_cmdid = WMI_PEER_SET_PARAM_CMDID, | ||
| 59 | .peer_assoc_cmdid = WMI_PEER_ASSOC_CMDID, | ||
| 60 | .peer_add_wds_entry_cmdid = WMI_PEER_ADD_WDS_ENTRY_CMDID, | ||
| 61 | .peer_remove_wds_entry_cmdid = WMI_PEER_REMOVE_WDS_ENTRY_CMDID, | ||
| 62 | .peer_mcast_group_cmdid = WMI_PEER_MCAST_GROUP_CMDID, | ||
| 63 | .bcn_tx_cmdid = WMI_BCN_TX_CMDID, | ||
| 64 | .pdev_send_bcn_cmdid = WMI_PDEV_SEND_BCN_CMDID, | ||
| 65 | .bcn_tmpl_cmdid = WMI_BCN_TMPL_CMDID, | ||
| 66 | .bcn_filter_rx_cmdid = WMI_BCN_FILTER_RX_CMDID, | ||
| 67 | .prb_req_filter_rx_cmdid = WMI_PRB_REQ_FILTER_RX_CMDID, | ||
| 68 | .mgmt_tx_cmdid = WMI_MGMT_TX_CMDID, | ||
| 69 | .prb_tmpl_cmdid = WMI_PRB_TMPL_CMDID, | ||
| 70 | .addba_clear_resp_cmdid = WMI_ADDBA_CLEAR_RESP_CMDID, | ||
| 71 | .addba_send_cmdid = WMI_ADDBA_SEND_CMDID, | ||
| 72 | .addba_status_cmdid = WMI_ADDBA_STATUS_CMDID, | ||
| 73 | .delba_send_cmdid = WMI_DELBA_SEND_CMDID, | ||
| 74 | .addba_set_resp_cmdid = WMI_ADDBA_SET_RESP_CMDID, | ||
| 75 | .send_singleamsdu_cmdid = WMI_SEND_SINGLEAMSDU_CMDID, | ||
| 76 | .sta_powersave_mode_cmdid = WMI_STA_POWERSAVE_MODE_CMDID, | ||
| 77 | .sta_powersave_param_cmdid = WMI_STA_POWERSAVE_PARAM_CMDID, | ||
| 78 | .sta_mimo_ps_mode_cmdid = WMI_STA_MIMO_PS_MODE_CMDID, | ||
| 79 | .pdev_dfs_enable_cmdid = WMI_PDEV_DFS_ENABLE_CMDID, | ||
| 80 | .pdev_dfs_disable_cmdid = WMI_PDEV_DFS_DISABLE_CMDID, | ||
| 81 | .roam_scan_mode = WMI_ROAM_SCAN_MODE, | ||
| 82 | .roam_scan_rssi_threshold = WMI_ROAM_SCAN_RSSI_THRESHOLD, | ||
| 83 | .roam_scan_period = WMI_ROAM_SCAN_PERIOD, | ||
| 84 | .roam_scan_rssi_change_threshold = WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD, | ||
| 85 | .roam_ap_profile = WMI_ROAM_AP_PROFILE, | ||
| 86 | .ofl_scan_add_ap_profile = WMI_ROAM_AP_PROFILE, | ||
| 87 | .ofl_scan_remove_ap_profile = WMI_OFL_SCAN_REMOVE_AP_PROFILE, | ||
| 88 | .ofl_scan_period = WMI_OFL_SCAN_PERIOD, | ||
| 89 | .p2p_dev_set_device_info = WMI_P2P_DEV_SET_DEVICE_INFO, | ||
| 90 | .p2p_dev_set_discoverability = WMI_P2P_DEV_SET_DISCOVERABILITY, | ||
| 91 | .p2p_go_set_beacon_ie = WMI_P2P_GO_SET_BEACON_IE, | ||
| 92 | .p2p_go_set_probe_resp_ie = WMI_P2P_GO_SET_PROBE_RESP_IE, | ||
| 93 | .p2p_set_vendor_ie_data_cmdid = WMI_P2P_SET_VENDOR_IE_DATA_CMDID, | ||
| 94 | .ap_ps_peer_param_cmdid = WMI_AP_PS_PEER_PARAM_CMDID, | ||
| 95 | .ap_ps_peer_uapsd_coex_cmdid = WMI_AP_PS_PEER_UAPSD_COEX_CMDID, | ||
| 96 | .peer_rate_retry_sched_cmdid = WMI_PEER_RATE_RETRY_SCHED_CMDID, | ||
| 97 | .wlan_profile_trigger_cmdid = WMI_WLAN_PROFILE_TRIGGER_CMDID, | ||
| 98 | .wlan_profile_set_hist_intvl_cmdid = | ||
| 99 | WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID, | ||
| 100 | .wlan_profile_get_profile_data_cmdid = | ||
| 101 | WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID, | ||
| 102 | .wlan_profile_enable_profile_id_cmdid = | ||
| 103 | WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID, | ||
| 104 | .wlan_profile_list_profile_id_cmdid = | ||
| 105 | WMI_WLAN_PROFILE_LIST_PROFILE_ID_CMDID, | ||
| 106 | .pdev_suspend_cmdid = WMI_PDEV_SUSPEND_CMDID, | ||
| 107 | .pdev_resume_cmdid = WMI_PDEV_RESUME_CMDID, | ||
| 108 | .add_bcn_filter_cmdid = WMI_ADD_BCN_FILTER_CMDID, | ||
| 109 | .rmv_bcn_filter_cmdid = WMI_RMV_BCN_FILTER_CMDID, | ||
| 110 | .wow_add_wake_pattern_cmdid = WMI_WOW_ADD_WAKE_PATTERN_CMDID, | ||
| 111 | .wow_del_wake_pattern_cmdid = WMI_WOW_DEL_WAKE_PATTERN_CMDID, | ||
| 112 | .wow_enable_disable_wake_event_cmdid = | ||
| 113 | WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID, | ||
| 114 | .wow_enable_cmdid = WMI_WOW_ENABLE_CMDID, | ||
| 115 | .wow_hostwakeup_from_sleep_cmdid = WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID, | ||
| 116 | .rtt_measreq_cmdid = WMI_RTT_MEASREQ_CMDID, | ||
| 117 | .rtt_tsf_cmdid = WMI_RTT_TSF_CMDID, | ||
| 118 | .vdev_spectral_scan_configure_cmdid = | ||
| 119 | WMI_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID, | ||
| 120 | .vdev_spectral_scan_enable_cmdid = WMI_VDEV_SPECTRAL_SCAN_ENABLE_CMDID, | ||
| 121 | .request_stats_cmdid = WMI_REQUEST_STATS_CMDID, | ||
| 122 | .set_arp_ns_offload_cmdid = WMI_SET_ARP_NS_OFFLOAD_CMDID, | ||
| 123 | .network_list_offload_config_cmdid = | ||
| 124 | WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID, | ||
| 125 | .gtk_offload_cmdid = WMI_GTK_OFFLOAD_CMDID, | ||
| 126 | .csa_offload_enable_cmdid = WMI_CSA_OFFLOAD_ENABLE_CMDID, | ||
| 127 | .csa_offload_chanswitch_cmdid = WMI_CSA_OFFLOAD_CHANSWITCH_CMDID, | ||
| 128 | .chatter_set_mode_cmdid = WMI_CHATTER_SET_MODE_CMDID, | ||
| 129 | .peer_tid_addba_cmdid = WMI_PEER_TID_ADDBA_CMDID, | ||
| 130 | .peer_tid_delba_cmdid = WMI_PEER_TID_DELBA_CMDID, | ||
| 131 | .sta_dtim_ps_method_cmdid = WMI_STA_DTIM_PS_METHOD_CMDID, | ||
| 132 | .sta_uapsd_auto_trig_cmdid = WMI_STA_UAPSD_AUTO_TRIG_CMDID, | ||
| 133 | .sta_keepalive_cmd = WMI_STA_KEEPALIVE_CMD, | ||
| 134 | .echo_cmdid = WMI_ECHO_CMDID, | ||
| 135 | .pdev_utf_cmdid = WMI_PDEV_UTF_CMDID, | ||
| 136 | .dbglog_cfg_cmdid = WMI_DBGLOG_CFG_CMDID, | ||
| 137 | .pdev_qvit_cmdid = WMI_PDEV_QVIT_CMDID, | ||
| 138 | .pdev_ftm_intg_cmdid = WMI_PDEV_FTM_INTG_CMDID, | ||
| 139 | .vdev_set_keepalive_cmdid = WMI_VDEV_SET_KEEPALIVE_CMDID, | ||
| 140 | .vdev_get_keepalive_cmdid = WMI_VDEV_GET_KEEPALIVE_CMDID, | ||
| 141 | .force_fw_hang_cmdid = WMI_FORCE_FW_HANG_CMDID, | ||
| 142 | .gpio_config_cmdid = WMI_GPIO_CONFIG_CMDID, | ||
| 143 | .gpio_output_cmdid = WMI_GPIO_OUTPUT_CMDID, | ||
| 144 | }; | ||
| 145 | |||
| 146 | /* 10.X WMI cmd track */ | ||
| 147 | static struct wmi_cmd_map wmi_10x_cmd_map = { | ||
| 148 | .init_cmdid = WMI_10X_INIT_CMDID, | ||
| 149 | .start_scan_cmdid = WMI_10X_START_SCAN_CMDID, | ||
| 150 | .stop_scan_cmdid = WMI_10X_STOP_SCAN_CMDID, | ||
| 151 | .scan_chan_list_cmdid = WMI_10X_SCAN_CHAN_LIST_CMDID, | ||
| 152 | .scan_sch_prio_tbl_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 153 | .pdev_set_regdomain_cmdid = WMI_10X_PDEV_SET_REGDOMAIN_CMDID, | ||
| 154 | .pdev_set_channel_cmdid = WMI_10X_PDEV_SET_CHANNEL_CMDID, | ||
| 155 | .pdev_set_param_cmdid = WMI_10X_PDEV_SET_PARAM_CMDID, | ||
| 156 | .pdev_pktlog_enable_cmdid = WMI_10X_PDEV_PKTLOG_ENABLE_CMDID, | ||
| 157 | .pdev_pktlog_disable_cmdid = WMI_10X_PDEV_PKTLOG_DISABLE_CMDID, | ||
| 158 | .pdev_set_wmm_params_cmdid = WMI_10X_PDEV_SET_WMM_PARAMS_CMDID, | ||
| 159 | .pdev_set_ht_cap_ie_cmdid = WMI_10X_PDEV_SET_HT_CAP_IE_CMDID, | ||
| 160 | .pdev_set_vht_cap_ie_cmdid = WMI_10X_PDEV_SET_VHT_CAP_IE_CMDID, | ||
| 161 | .pdev_set_dscp_tid_map_cmdid = WMI_10X_PDEV_SET_DSCP_TID_MAP_CMDID, | ||
| 162 | .pdev_set_quiet_mode_cmdid = WMI_10X_PDEV_SET_QUIET_MODE_CMDID, | ||
| 163 | .pdev_green_ap_ps_enable_cmdid = WMI_10X_PDEV_GREEN_AP_PS_ENABLE_CMDID, | ||
| 164 | .pdev_get_tpc_config_cmdid = WMI_10X_PDEV_GET_TPC_CONFIG_CMDID, | ||
| 165 | .pdev_set_base_macaddr_cmdid = WMI_10X_PDEV_SET_BASE_MACADDR_CMDID, | ||
| 166 | .vdev_create_cmdid = WMI_10X_VDEV_CREATE_CMDID, | ||
| 167 | .vdev_delete_cmdid = WMI_10X_VDEV_DELETE_CMDID, | ||
| 168 | .vdev_start_request_cmdid = WMI_10X_VDEV_START_REQUEST_CMDID, | ||
| 169 | .vdev_restart_request_cmdid = WMI_10X_VDEV_RESTART_REQUEST_CMDID, | ||
| 170 | .vdev_up_cmdid = WMI_10X_VDEV_UP_CMDID, | ||
| 171 | .vdev_stop_cmdid = WMI_10X_VDEV_STOP_CMDID, | ||
| 172 | .vdev_down_cmdid = WMI_10X_VDEV_DOWN_CMDID, | ||
| 173 | .vdev_set_param_cmdid = WMI_10X_VDEV_SET_PARAM_CMDID, | ||
| 174 | .vdev_install_key_cmdid = WMI_10X_VDEV_INSTALL_KEY_CMDID, | ||
| 175 | .peer_create_cmdid = WMI_10X_PEER_CREATE_CMDID, | ||
| 176 | .peer_delete_cmdid = WMI_10X_PEER_DELETE_CMDID, | ||
| 177 | .peer_flush_tids_cmdid = WMI_10X_PEER_FLUSH_TIDS_CMDID, | ||
| 178 | .peer_set_param_cmdid = WMI_10X_PEER_SET_PARAM_CMDID, | ||
| 179 | .peer_assoc_cmdid = WMI_10X_PEER_ASSOC_CMDID, | ||
| 180 | .peer_add_wds_entry_cmdid = WMI_10X_PEER_ADD_WDS_ENTRY_CMDID, | ||
| 181 | .peer_remove_wds_entry_cmdid = WMI_10X_PEER_REMOVE_WDS_ENTRY_CMDID, | ||
| 182 | .peer_mcast_group_cmdid = WMI_10X_PEER_MCAST_GROUP_CMDID, | ||
| 183 | .bcn_tx_cmdid = WMI_10X_BCN_TX_CMDID, | ||
| 184 | .pdev_send_bcn_cmdid = WMI_10X_PDEV_SEND_BCN_CMDID, | ||
| 185 | .bcn_tmpl_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 186 | .bcn_filter_rx_cmdid = WMI_10X_BCN_FILTER_RX_CMDID, | ||
| 187 | .prb_req_filter_rx_cmdid = WMI_10X_PRB_REQ_FILTER_RX_CMDID, | ||
| 188 | .mgmt_tx_cmdid = WMI_10X_MGMT_TX_CMDID, | ||
| 189 | .prb_tmpl_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 190 | .addba_clear_resp_cmdid = WMI_10X_ADDBA_CLEAR_RESP_CMDID, | ||
| 191 | .addba_send_cmdid = WMI_10X_ADDBA_SEND_CMDID, | ||
| 192 | .addba_status_cmdid = WMI_10X_ADDBA_STATUS_CMDID, | ||
| 193 | .delba_send_cmdid = WMI_10X_DELBA_SEND_CMDID, | ||
| 194 | .addba_set_resp_cmdid = WMI_10X_ADDBA_SET_RESP_CMDID, | ||
| 195 | .send_singleamsdu_cmdid = WMI_10X_SEND_SINGLEAMSDU_CMDID, | ||
| 196 | .sta_powersave_mode_cmdid = WMI_10X_STA_POWERSAVE_MODE_CMDID, | ||
| 197 | .sta_powersave_param_cmdid = WMI_10X_STA_POWERSAVE_PARAM_CMDID, | ||
| 198 | .sta_mimo_ps_mode_cmdid = WMI_10X_STA_MIMO_PS_MODE_CMDID, | ||
| 199 | .pdev_dfs_enable_cmdid = WMI_10X_PDEV_DFS_ENABLE_CMDID, | ||
| 200 | .pdev_dfs_disable_cmdid = WMI_10X_PDEV_DFS_DISABLE_CMDID, | ||
| 201 | .roam_scan_mode = WMI_10X_ROAM_SCAN_MODE, | ||
| 202 | .roam_scan_rssi_threshold = WMI_10X_ROAM_SCAN_RSSI_THRESHOLD, | ||
| 203 | .roam_scan_period = WMI_10X_ROAM_SCAN_PERIOD, | ||
| 204 | .roam_scan_rssi_change_threshold = | ||
| 205 | WMI_10X_ROAM_SCAN_RSSI_CHANGE_THRESHOLD, | ||
| 206 | .roam_ap_profile = WMI_10X_ROAM_AP_PROFILE, | ||
| 207 | .ofl_scan_add_ap_profile = WMI_10X_OFL_SCAN_ADD_AP_PROFILE, | ||
| 208 | .ofl_scan_remove_ap_profile = WMI_10X_OFL_SCAN_REMOVE_AP_PROFILE, | ||
| 209 | .ofl_scan_period = WMI_10X_OFL_SCAN_PERIOD, | ||
| 210 | .p2p_dev_set_device_info = WMI_10X_P2P_DEV_SET_DEVICE_INFO, | ||
| 211 | .p2p_dev_set_discoverability = WMI_10X_P2P_DEV_SET_DISCOVERABILITY, | ||
| 212 | .p2p_go_set_beacon_ie = WMI_10X_P2P_GO_SET_BEACON_IE, | ||
| 213 | .p2p_go_set_probe_resp_ie = WMI_10X_P2P_GO_SET_PROBE_RESP_IE, | ||
| 214 | .p2p_set_vendor_ie_data_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 215 | .ap_ps_peer_param_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 216 | .ap_ps_peer_uapsd_coex_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 217 | .peer_rate_retry_sched_cmdid = WMI_10X_PEER_RATE_RETRY_SCHED_CMDID, | ||
| 218 | .wlan_profile_trigger_cmdid = WMI_10X_WLAN_PROFILE_TRIGGER_CMDID, | ||
| 219 | .wlan_profile_set_hist_intvl_cmdid = | ||
| 220 | WMI_10X_WLAN_PROFILE_SET_HIST_INTVL_CMDID, | ||
| 221 | .wlan_profile_get_profile_data_cmdid = | ||
| 222 | WMI_10X_WLAN_PROFILE_GET_PROFILE_DATA_CMDID, | ||
| 223 | .wlan_profile_enable_profile_id_cmdid = | ||
| 224 | WMI_10X_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID, | ||
| 225 | .wlan_profile_list_profile_id_cmdid = | ||
| 226 | WMI_10X_WLAN_PROFILE_LIST_PROFILE_ID_CMDID, | ||
| 227 | .pdev_suspend_cmdid = WMI_10X_PDEV_SUSPEND_CMDID, | ||
| 228 | .pdev_resume_cmdid = WMI_10X_PDEV_RESUME_CMDID, | ||
| 229 | .add_bcn_filter_cmdid = WMI_10X_ADD_BCN_FILTER_CMDID, | ||
| 230 | .rmv_bcn_filter_cmdid = WMI_10X_RMV_BCN_FILTER_CMDID, | ||
| 231 | .wow_add_wake_pattern_cmdid = WMI_10X_WOW_ADD_WAKE_PATTERN_CMDID, | ||
| 232 | .wow_del_wake_pattern_cmdid = WMI_10X_WOW_DEL_WAKE_PATTERN_CMDID, | ||
| 233 | .wow_enable_disable_wake_event_cmdid = | ||
| 234 | WMI_10X_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID, | ||
| 235 | .wow_enable_cmdid = WMI_10X_WOW_ENABLE_CMDID, | ||
| 236 | .wow_hostwakeup_from_sleep_cmdid = | ||
| 237 | WMI_10X_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID, | ||
| 238 | .rtt_measreq_cmdid = WMI_10X_RTT_MEASREQ_CMDID, | ||
| 239 | .rtt_tsf_cmdid = WMI_10X_RTT_TSF_CMDID, | ||
| 240 | .vdev_spectral_scan_configure_cmdid = | ||
| 241 | WMI_10X_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID, | ||
| 242 | .vdev_spectral_scan_enable_cmdid = | ||
| 243 | WMI_10X_VDEV_SPECTRAL_SCAN_ENABLE_CMDID, | ||
| 244 | .request_stats_cmdid = WMI_10X_REQUEST_STATS_CMDID, | ||
| 245 | .set_arp_ns_offload_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 246 | .network_list_offload_config_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 247 | .gtk_offload_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 248 | .csa_offload_enable_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 249 | .csa_offload_chanswitch_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 250 | .chatter_set_mode_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 251 | .peer_tid_addba_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 252 | .peer_tid_delba_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 253 | .sta_dtim_ps_method_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 254 | .sta_uapsd_auto_trig_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 255 | .sta_keepalive_cmd = WMI_CMD_UNSUPPORTED, | ||
| 256 | .echo_cmdid = WMI_10X_ECHO_CMDID, | ||
| 257 | .pdev_utf_cmdid = WMI_10X_PDEV_UTF_CMDID, | ||
| 258 | .dbglog_cfg_cmdid = WMI_10X_DBGLOG_CFG_CMDID, | ||
| 259 | .pdev_qvit_cmdid = WMI_10X_PDEV_QVIT_CMDID, | ||
| 260 | .pdev_ftm_intg_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 261 | .vdev_set_keepalive_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 262 | .vdev_get_keepalive_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 263 | .force_fw_hang_cmdid = WMI_CMD_UNSUPPORTED, | ||
| 264 | .gpio_config_cmdid = WMI_10X_GPIO_CONFIG_CMDID, | ||
| 265 | .gpio_output_cmdid = WMI_10X_GPIO_OUTPUT_CMDID, | ||
| 266 | }; | ||
| 267 | |||
| 268 | /* MAIN WMI VDEV param map */ | ||
| 269 | static struct wmi_vdev_param_map wmi_vdev_param_map = { | ||
| 270 | .rts_threshold = WMI_VDEV_PARAM_RTS_THRESHOLD, | ||
| 271 | .fragmentation_threshold = WMI_VDEV_PARAM_FRAGMENTATION_THRESHOLD, | ||
| 272 | .beacon_interval = WMI_VDEV_PARAM_BEACON_INTERVAL, | ||
| 273 | .listen_interval = WMI_VDEV_PARAM_LISTEN_INTERVAL, | ||
| 274 | .multicast_rate = WMI_VDEV_PARAM_MULTICAST_RATE, | ||
| 275 | .mgmt_tx_rate = WMI_VDEV_PARAM_MGMT_TX_RATE, | ||
| 276 | .slot_time = WMI_VDEV_PARAM_SLOT_TIME, | ||
| 277 | .preamble = WMI_VDEV_PARAM_PREAMBLE, | ||
| 278 | .swba_time = WMI_VDEV_PARAM_SWBA_TIME, | ||
| 279 | .wmi_vdev_stats_update_period = WMI_VDEV_STATS_UPDATE_PERIOD, | ||
| 280 | .wmi_vdev_pwrsave_ageout_time = WMI_VDEV_PWRSAVE_AGEOUT_TIME, | ||
| 281 | .wmi_vdev_host_swba_interval = WMI_VDEV_HOST_SWBA_INTERVAL, | ||
| 282 | .dtim_period = WMI_VDEV_PARAM_DTIM_PERIOD, | ||
| 283 | .wmi_vdev_oc_scheduler_air_time_limit = | ||
| 284 | WMI_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT, | ||
| 285 | .wds = WMI_VDEV_PARAM_WDS, | ||
| 286 | .atim_window = WMI_VDEV_PARAM_ATIM_WINDOW, | ||
| 287 | .bmiss_count_max = WMI_VDEV_PARAM_BMISS_COUNT_MAX, | ||
| 288 | .bmiss_first_bcnt = WMI_VDEV_PARAM_BMISS_FIRST_BCNT, | ||
| 289 | .bmiss_final_bcnt = WMI_VDEV_PARAM_BMISS_FINAL_BCNT, | ||
| 290 | .feature_wmm = WMI_VDEV_PARAM_FEATURE_WMM, | ||
| 291 | .chwidth = WMI_VDEV_PARAM_CHWIDTH, | ||
| 292 | .chextoffset = WMI_VDEV_PARAM_CHEXTOFFSET, | ||
| 293 | .disable_htprotection = WMI_VDEV_PARAM_DISABLE_HTPROTECTION, | ||
| 294 | .sta_quickkickout = WMI_VDEV_PARAM_STA_QUICKKICKOUT, | ||
| 295 | .mgmt_rate = WMI_VDEV_PARAM_MGMT_RATE, | ||
| 296 | .protection_mode = WMI_VDEV_PARAM_PROTECTION_MODE, | ||
| 297 | .fixed_rate = WMI_VDEV_PARAM_FIXED_RATE, | ||
| 298 | .sgi = WMI_VDEV_PARAM_SGI, | ||
| 299 | .ldpc = WMI_VDEV_PARAM_LDPC, | ||
| 300 | .tx_stbc = WMI_VDEV_PARAM_TX_STBC, | ||
| 301 | .rx_stbc = WMI_VDEV_PARAM_RX_STBC, | ||
| 302 | .intra_bss_fwd = WMI_VDEV_PARAM_INTRA_BSS_FWD, | ||
| 303 | .def_keyid = WMI_VDEV_PARAM_DEF_KEYID, | ||
| 304 | .nss = WMI_VDEV_PARAM_NSS, | ||
| 305 | .bcast_data_rate = WMI_VDEV_PARAM_BCAST_DATA_RATE, | ||
| 306 | .mcast_data_rate = WMI_VDEV_PARAM_MCAST_DATA_RATE, | ||
| 307 | .mcast_indicate = WMI_VDEV_PARAM_MCAST_INDICATE, | ||
| 308 | .dhcp_indicate = WMI_VDEV_PARAM_DHCP_INDICATE, | ||
| 309 | .unknown_dest_indicate = WMI_VDEV_PARAM_UNKNOWN_DEST_INDICATE, | ||
| 310 | .ap_keepalive_min_idle_inactive_time_secs = | ||
| 311 | WMI_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS, | ||
| 312 | .ap_keepalive_max_idle_inactive_time_secs = | ||
| 313 | WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS, | ||
| 314 | .ap_keepalive_max_unresponsive_time_secs = | ||
| 315 | WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS, | ||
| 316 | .ap_enable_nawds = WMI_VDEV_PARAM_AP_ENABLE_NAWDS, | ||
| 317 | .mcast2ucast_set = WMI_VDEV_PARAM_UNSUPPORTED, | ||
| 318 | .enable_rtscts = WMI_VDEV_PARAM_ENABLE_RTSCTS, | ||
| 319 | .txbf = WMI_VDEV_PARAM_TXBF, | ||
| 320 | .packet_powersave = WMI_VDEV_PARAM_PACKET_POWERSAVE, | ||
| 321 | .drop_unencry = WMI_VDEV_PARAM_DROP_UNENCRY, | ||
| 322 | .tx_encap_type = WMI_VDEV_PARAM_TX_ENCAP_TYPE, | ||
| 323 | .ap_detect_out_of_sync_sleeping_sta_time_secs = | ||
| 324 | WMI_VDEV_PARAM_UNSUPPORTED, | ||
| 325 | }; | ||
| 326 | |||
| 327 | /* 10.X WMI VDEV param map */ | ||
| 328 | static struct wmi_vdev_param_map wmi_10x_vdev_param_map = { | ||
| 329 | .rts_threshold = WMI_10X_VDEV_PARAM_RTS_THRESHOLD, | ||
| 330 | .fragmentation_threshold = WMI_10X_VDEV_PARAM_FRAGMENTATION_THRESHOLD, | ||
| 331 | .beacon_interval = WMI_10X_VDEV_PARAM_BEACON_INTERVAL, | ||
| 332 | .listen_interval = WMI_10X_VDEV_PARAM_LISTEN_INTERVAL, | ||
| 333 | .multicast_rate = WMI_10X_VDEV_PARAM_MULTICAST_RATE, | ||
| 334 | .mgmt_tx_rate = WMI_10X_VDEV_PARAM_MGMT_TX_RATE, | ||
| 335 | .slot_time = WMI_10X_VDEV_PARAM_SLOT_TIME, | ||
| 336 | .preamble = WMI_10X_VDEV_PARAM_PREAMBLE, | ||
| 337 | .swba_time = WMI_10X_VDEV_PARAM_SWBA_TIME, | ||
| 338 | .wmi_vdev_stats_update_period = WMI_10X_VDEV_STATS_UPDATE_PERIOD, | ||
| 339 | .wmi_vdev_pwrsave_ageout_time = WMI_10X_VDEV_PWRSAVE_AGEOUT_TIME, | ||
| 340 | .wmi_vdev_host_swba_interval = WMI_10X_VDEV_HOST_SWBA_INTERVAL, | ||
| 341 | .dtim_period = WMI_10X_VDEV_PARAM_DTIM_PERIOD, | ||
| 342 | .wmi_vdev_oc_scheduler_air_time_limit = | ||
| 343 | WMI_10X_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT, | ||
| 344 | .wds = WMI_10X_VDEV_PARAM_WDS, | ||
| 345 | .atim_window = WMI_10X_VDEV_PARAM_ATIM_WINDOW, | ||
| 346 | .bmiss_count_max = WMI_10X_VDEV_PARAM_BMISS_COUNT_MAX, | ||
| 347 | .bmiss_first_bcnt = WMI_VDEV_PARAM_UNSUPPORTED, | ||
| 348 | .bmiss_final_bcnt = WMI_VDEV_PARAM_UNSUPPORTED, | ||
| 349 | .feature_wmm = WMI_10X_VDEV_PARAM_FEATURE_WMM, | ||
| 350 | .chwidth = WMI_10X_VDEV_PARAM_CHWIDTH, | ||
| 351 | .chextoffset = WMI_10X_VDEV_PARAM_CHEXTOFFSET, | ||
| 352 | .disable_htprotection = WMI_10X_VDEV_PARAM_DISABLE_HTPROTECTION, | ||
| 353 | .sta_quickkickout = WMI_10X_VDEV_PARAM_STA_QUICKKICKOUT, | ||
| 354 | .mgmt_rate = WMI_10X_VDEV_PARAM_MGMT_RATE, | ||
| 355 | .protection_mode = WMI_10X_VDEV_PARAM_PROTECTION_MODE, | ||
| 356 | .fixed_rate = WMI_10X_VDEV_PARAM_FIXED_RATE, | ||
| 357 | .sgi = WMI_10X_VDEV_PARAM_SGI, | ||
| 358 | .ldpc = WMI_10X_VDEV_PARAM_LDPC, | ||
| 359 | .tx_stbc = WMI_10X_VDEV_PARAM_TX_STBC, | ||
| 360 | .rx_stbc = WMI_10X_VDEV_PARAM_RX_STBC, | ||
| 361 | .intra_bss_fwd = WMI_10X_VDEV_PARAM_INTRA_BSS_FWD, | ||
| 362 | .def_keyid = WMI_10X_VDEV_PARAM_DEF_KEYID, | ||
| 363 | .nss = WMI_10X_VDEV_PARAM_NSS, | ||
| 364 | .bcast_data_rate = WMI_10X_VDEV_PARAM_BCAST_DATA_RATE, | ||
| 365 | .mcast_data_rate = WMI_10X_VDEV_PARAM_MCAST_DATA_RATE, | ||
| 366 | .mcast_indicate = WMI_10X_VDEV_PARAM_MCAST_INDICATE, | ||
| 367 | .dhcp_indicate = WMI_10X_VDEV_PARAM_DHCP_INDICATE, | ||
| 368 | .unknown_dest_indicate = WMI_10X_VDEV_PARAM_UNKNOWN_DEST_INDICATE, | ||
| 369 | .ap_keepalive_min_idle_inactive_time_secs = | ||
| 370 | WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS, | ||
| 371 | .ap_keepalive_max_idle_inactive_time_secs = | ||
| 372 | WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS, | ||
| 373 | .ap_keepalive_max_unresponsive_time_secs = | ||
| 374 | WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS, | ||
| 375 | .ap_enable_nawds = WMI_10X_VDEV_PARAM_AP_ENABLE_NAWDS, | ||
| 376 | .mcast2ucast_set = WMI_10X_VDEV_PARAM_MCAST2UCAST_SET, | ||
| 377 | .enable_rtscts = WMI_10X_VDEV_PARAM_ENABLE_RTSCTS, | ||
| 378 | .txbf = WMI_VDEV_PARAM_UNSUPPORTED, | ||
| 379 | .packet_powersave = WMI_VDEV_PARAM_UNSUPPORTED, | ||
| 380 | .drop_unencry = WMI_VDEV_PARAM_UNSUPPORTED, | ||
| 381 | .tx_encap_type = WMI_VDEV_PARAM_UNSUPPORTED, | ||
| 382 | .ap_detect_out_of_sync_sleeping_sta_time_secs = | ||
| 383 | WMI_10X_VDEV_PARAM_AP_DETECT_OUT_OF_SYNC_SLEEPING_STA_TIME_SECS, | ||
| 384 | }; | ||
| 385 | |||
| 386 | static struct wmi_pdev_param_map wmi_pdev_param_map = { | ||
| 387 | .tx_chain_mask = WMI_PDEV_PARAM_TX_CHAIN_MASK, | ||
| 388 | .rx_chain_mask = WMI_PDEV_PARAM_RX_CHAIN_MASK, | ||
| 389 | .txpower_limit2g = WMI_PDEV_PARAM_TXPOWER_LIMIT2G, | ||
| 390 | .txpower_limit5g = WMI_PDEV_PARAM_TXPOWER_LIMIT5G, | ||
| 391 | .txpower_scale = WMI_PDEV_PARAM_TXPOWER_SCALE, | ||
| 392 | .beacon_gen_mode = WMI_PDEV_PARAM_BEACON_GEN_MODE, | ||
| 393 | .beacon_tx_mode = WMI_PDEV_PARAM_BEACON_TX_MODE, | ||
| 394 | .resmgr_offchan_mode = WMI_PDEV_PARAM_RESMGR_OFFCHAN_MODE, | ||
| 395 | .protection_mode = WMI_PDEV_PARAM_PROTECTION_MODE, | ||
| 396 | .dynamic_bw = WMI_PDEV_PARAM_DYNAMIC_BW, | ||
| 397 | .non_agg_sw_retry_th = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH, | ||
| 398 | .agg_sw_retry_th = WMI_PDEV_PARAM_AGG_SW_RETRY_TH, | ||
| 399 | .sta_kickout_th = WMI_PDEV_PARAM_STA_KICKOUT_TH, | ||
| 400 | .ac_aggrsize_scaling = WMI_PDEV_PARAM_AC_AGGRSIZE_SCALING, | ||
| 401 | .ltr_enable = WMI_PDEV_PARAM_LTR_ENABLE, | ||
| 402 | .ltr_ac_latency_be = WMI_PDEV_PARAM_LTR_AC_LATENCY_BE, | ||
| 403 | .ltr_ac_latency_bk = WMI_PDEV_PARAM_LTR_AC_LATENCY_BK, | ||
| 404 | .ltr_ac_latency_vi = WMI_PDEV_PARAM_LTR_AC_LATENCY_VI, | ||
| 405 | .ltr_ac_latency_vo = WMI_PDEV_PARAM_LTR_AC_LATENCY_VO, | ||
| 406 | .ltr_ac_latency_timeout = WMI_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT, | ||
| 407 | .ltr_sleep_override = WMI_PDEV_PARAM_LTR_SLEEP_OVERRIDE, | ||
| 408 | .ltr_rx_override = WMI_PDEV_PARAM_LTR_RX_OVERRIDE, | ||
| 409 | .ltr_tx_activity_timeout = WMI_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT, | ||
| 410 | .l1ss_enable = WMI_PDEV_PARAM_L1SS_ENABLE, | ||
| 411 | .dsleep_enable = WMI_PDEV_PARAM_DSLEEP_ENABLE, | ||
| 412 | .pcielp_txbuf_flush = WMI_PDEV_PARAM_PCIELP_TXBUF_FLUSH, | ||
| 413 | .pcielp_txbuf_watermark = WMI_PDEV_PARAM_PCIELP_TXBUF_TMO_EN, | ||
| 414 | .pcielp_txbuf_tmo_en = WMI_PDEV_PARAM_PCIELP_TXBUF_TMO_EN, | ||
| 415 | .pcielp_txbuf_tmo_value = WMI_PDEV_PARAM_PCIELP_TXBUF_TMO_VALUE, | ||
| 416 | .pdev_stats_update_period = WMI_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD, | ||
| 417 | .vdev_stats_update_period = WMI_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD, | ||
| 418 | .peer_stats_update_period = WMI_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD, | ||
| 419 | .bcnflt_stats_update_period = WMI_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD, | ||
| 420 | .pmf_qos = WMI_PDEV_PARAM_PMF_QOS, | ||
| 421 | .arp_ac_override = WMI_PDEV_PARAM_ARP_AC_OVERRIDE, | ||
| 422 | .arpdhcp_ac_override = WMI_PDEV_PARAM_UNSUPPORTED, | ||
| 423 | .dcs = WMI_PDEV_PARAM_DCS, | ||
| 424 | .ani_enable = WMI_PDEV_PARAM_ANI_ENABLE, | ||
| 425 | .ani_poll_period = WMI_PDEV_PARAM_ANI_POLL_PERIOD, | ||
| 426 | .ani_listen_period = WMI_PDEV_PARAM_ANI_LISTEN_PERIOD, | ||
| 427 | .ani_ofdm_level = WMI_PDEV_PARAM_ANI_OFDM_LEVEL, | ||
| 428 | .ani_cck_level = WMI_PDEV_PARAM_ANI_CCK_LEVEL, | ||
| 429 | .dyntxchain = WMI_PDEV_PARAM_DYNTXCHAIN, | ||
| 430 | .proxy_sta = WMI_PDEV_PARAM_PROXY_STA, | ||
| 431 | .idle_ps_config = WMI_PDEV_PARAM_IDLE_PS_CONFIG, | ||
| 432 | .power_gating_sleep = WMI_PDEV_PARAM_POWER_GATING_SLEEP, | ||
| 433 | .fast_channel_reset = WMI_PDEV_PARAM_UNSUPPORTED, | ||
| 434 | .burst_dur = WMI_PDEV_PARAM_UNSUPPORTED, | ||
| 435 | .burst_enable = WMI_PDEV_PARAM_UNSUPPORTED, | ||
| 436 | }; | ||
| 437 | |||
| 438 | static struct wmi_pdev_param_map wmi_10x_pdev_param_map = { | ||
| 439 | .tx_chain_mask = WMI_10X_PDEV_PARAM_TX_CHAIN_MASK, | ||
| 440 | .rx_chain_mask = WMI_10X_PDEV_PARAM_RX_CHAIN_MASK, | ||
| 441 | .txpower_limit2g = WMI_10X_PDEV_PARAM_TXPOWER_LIMIT2G, | ||
| 442 | .txpower_limit5g = WMI_10X_PDEV_PARAM_TXPOWER_LIMIT5G, | ||
| 443 | .txpower_scale = WMI_10X_PDEV_PARAM_TXPOWER_SCALE, | ||
| 444 | .beacon_gen_mode = WMI_10X_PDEV_PARAM_BEACON_GEN_MODE, | ||
| 445 | .beacon_tx_mode = WMI_10X_PDEV_PARAM_BEACON_TX_MODE, | ||
| 446 | .resmgr_offchan_mode = WMI_10X_PDEV_PARAM_RESMGR_OFFCHAN_MODE, | ||
| 447 | .protection_mode = WMI_10X_PDEV_PARAM_PROTECTION_MODE, | ||
| 448 | .dynamic_bw = WMI_10X_PDEV_PARAM_DYNAMIC_BW, | ||
| 449 | .non_agg_sw_retry_th = WMI_10X_PDEV_PARAM_NON_AGG_SW_RETRY_TH, | ||
| 450 | .agg_sw_retry_th = WMI_10X_PDEV_PARAM_AGG_SW_RETRY_TH, | ||
| 451 | .sta_kickout_th = WMI_10X_PDEV_PARAM_STA_KICKOUT_TH, | ||
| 452 | .ac_aggrsize_scaling = WMI_10X_PDEV_PARAM_AC_AGGRSIZE_SCALING, | ||
| 453 | .ltr_enable = WMI_10X_PDEV_PARAM_LTR_ENABLE, | ||
| 454 | .ltr_ac_latency_be = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_BE, | ||
| 455 | .ltr_ac_latency_bk = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_BK, | ||
| 456 | .ltr_ac_latency_vi = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_VI, | ||
| 457 | .ltr_ac_latency_vo = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_VO, | ||
| 458 | .ltr_ac_latency_timeout = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT, | ||
| 459 | .ltr_sleep_override = WMI_10X_PDEV_PARAM_LTR_SLEEP_OVERRIDE, | ||
| 460 | .ltr_rx_override = WMI_10X_PDEV_PARAM_LTR_RX_OVERRIDE, | ||
| 461 | .ltr_tx_activity_timeout = WMI_10X_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT, | ||
| 462 | .l1ss_enable = WMI_10X_PDEV_PARAM_L1SS_ENABLE, | ||
| 463 | .dsleep_enable = WMI_10X_PDEV_PARAM_DSLEEP_ENABLE, | ||
| 464 | .pcielp_txbuf_flush = WMI_PDEV_PARAM_UNSUPPORTED, | ||
| 465 | .pcielp_txbuf_watermark = WMI_PDEV_PARAM_UNSUPPORTED, | ||
| 466 | .pcielp_txbuf_tmo_en = WMI_PDEV_PARAM_UNSUPPORTED, | ||
| 467 | .pcielp_txbuf_tmo_value = WMI_PDEV_PARAM_UNSUPPORTED, | ||
| 468 | .pdev_stats_update_period = WMI_10X_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD, | ||
| 469 | .vdev_stats_update_period = WMI_10X_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD, | ||
| 470 | .peer_stats_update_period = WMI_10X_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD, | ||
| 471 | .bcnflt_stats_update_period = | ||
| 472 | WMI_10X_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD, | ||
| 473 | .pmf_qos = WMI_10X_PDEV_PARAM_PMF_QOS, | ||
| 474 | .arp_ac_override = WMI_PDEV_PARAM_UNSUPPORTED, | ||
| 475 | .arpdhcp_ac_override = WMI_10X_PDEV_PARAM_ARPDHCP_AC_OVERRIDE, | ||
| 476 | .dcs = WMI_10X_PDEV_PARAM_DCS, | ||
| 477 | .ani_enable = WMI_10X_PDEV_PARAM_ANI_ENABLE, | ||
| 478 | .ani_poll_period = WMI_10X_PDEV_PARAM_ANI_POLL_PERIOD, | ||
| 479 | .ani_listen_period = WMI_10X_PDEV_PARAM_ANI_LISTEN_PERIOD, | ||
| 480 | .ani_ofdm_level = WMI_10X_PDEV_PARAM_ANI_OFDM_LEVEL, | ||
| 481 | .ani_cck_level = WMI_10X_PDEV_PARAM_ANI_CCK_LEVEL, | ||
| 482 | .dyntxchain = WMI_10X_PDEV_PARAM_DYNTXCHAIN, | ||
| 483 | .proxy_sta = WMI_PDEV_PARAM_UNSUPPORTED, | ||
| 484 | .idle_ps_config = WMI_PDEV_PARAM_UNSUPPORTED, | ||
| 485 | .power_gating_sleep = WMI_PDEV_PARAM_UNSUPPORTED, | ||
| 486 | .fast_channel_reset = WMI_10X_PDEV_PARAM_FAST_CHANNEL_RESET, | ||
| 487 | .burst_dur = WMI_10X_PDEV_PARAM_BURST_DUR, | ||
| 488 | .burst_enable = WMI_10X_PDEV_PARAM_BURST_ENABLE, | ||
| 489 | }; | ||
| 49 | 490 | ||
| 50 | int ath10k_wmi_wait_for_service_ready(struct ath10k *ar) | 491 | int ath10k_wmi_wait_for_service_ready(struct ath10k *ar) |
| 51 | { | 492 | { |
| @@ -85,18 +526,14 @@ static struct sk_buff *ath10k_wmi_alloc_skb(u32 len) | |||
| 85 | static void ath10k_wmi_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) | 526 | static void ath10k_wmi_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) |
| 86 | { | 527 | { |
| 87 | dev_kfree_skb(skb); | 528 | dev_kfree_skb(skb); |
| 88 | |||
| 89 | if (atomic_sub_return(1, &ar->wmi.pending_tx_count) == 0) | ||
| 90 | wake_up(&ar->wmi.wq); | ||
| 91 | } | 529 | } |
| 92 | 530 | ||
| 93 | /* WMI command API */ | 531 | static int ath10k_wmi_cmd_send_nowait(struct ath10k *ar, struct sk_buff *skb, |
| 94 | static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, | 532 | u32 cmd_id) |
| 95 | enum wmi_cmd_id cmd_id) | ||
| 96 | { | 533 | { |
| 97 | struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); | 534 | struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); |
| 98 | struct wmi_cmd_hdr *cmd_hdr; | 535 | struct wmi_cmd_hdr *cmd_hdr; |
| 99 | int status; | 536 | int ret; |
| 100 | u32 cmd = 0; | 537 | u32 cmd = 0; |
| 101 | 538 | ||
| 102 | if (skb_push(skb, sizeof(struct wmi_cmd_hdr)) == NULL) | 539 | if (skb_push(skb, sizeof(struct wmi_cmd_hdr)) == NULL) |
| @@ -107,25 +544,146 @@ static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, | |||
| 107 | cmd_hdr = (struct wmi_cmd_hdr *)skb->data; | 544 | cmd_hdr = (struct wmi_cmd_hdr *)skb->data; |
| 108 | cmd_hdr->cmd_id = __cpu_to_le32(cmd); | 545 | cmd_hdr->cmd_id = __cpu_to_le32(cmd); |
| 109 | 546 | ||
| 110 | if (atomic_add_return(1, &ar->wmi.pending_tx_count) > | 547 | memset(skb_cb, 0, sizeof(*skb_cb)); |
| 111 | WMI_MAX_PENDING_TX_COUNT) { | 548 | ret = ath10k_htc_send(&ar->htc, ar->wmi.eid, skb); |
| 112 | /* avoid using up memory when FW hangs */ | 549 | trace_ath10k_wmi_cmd(cmd_id, skb->data, skb->len, ret); |
| 113 | atomic_dec(&ar->wmi.pending_tx_count); | 550 | |
| 114 | return -EBUSY; | 551 | if (ret) |
| 552 | goto err_pull; | ||
| 553 | |||
| 554 | return 0; | ||
| 555 | |||
| 556 | err_pull: | ||
| 557 | skb_pull(skb, sizeof(struct wmi_cmd_hdr)); | ||
| 558 | return ret; | ||
| 559 | } | ||
| 560 | |||
| 561 | static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif) | ||
| 562 | { | ||
| 563 | struct wmi_bcn_tx_arg arg = {0}; | ||
| 564 | int ret; | ||
| 565 | |||
| 566 | lockdep_assert_held(&arvif->ar->data_lock); | ||
| 567 | |||
| 568 | if (arvif->beacon == NULL) | ||
| 569 | return; | ||
| 570 | |||
| 571 | arg.vdev_id = arvif->vdev_id; | ||
| 572 | arg.tx_rate = 0; | ||
| 573 | arg.tx_power = 0; | ||
| 574 | arg.bcn = arvif->beacon->data; | ||
| 575 | arg.bcn_len = arvif->beacon->len; | ||
| 576 | |||
| 577 | ret = ath10k_wmi_beacon_send_nowait(arvif->ar, &arg); | ||
| 578 | if (ret) | ||
| 579 | return; | ||
| 580 | |||
| 581 | dev_kfree_skb_any(arvif->beacon); | ||
| 582 | arvif->beacon = NULL; | ||
| 583 | } | ||
| 584 | |||
| 585 | static void ath10k_wmi_tx_beacons_iter(void *data, u8 *mac, | ||
| 586 | struct ieee80211_vif *vif) | ||
| 587 | { | ||
| 588 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | ||
| 589 | |||
| 590 | ath10k_wmi_tx_beacon_nowait(arvif); | ||
| 591 | } | ||
| 592 | |||
| 593 | static void ath10k_wmi_tx_beacons_nowait(struct ath10k *ar) | ||
| 594 | { | ||
| 595 | spin_lock_bh(&ar->data_lock); | ||
| 596 | ieee80211_iterate_active_interfaces_atomic(ar->hw, | ||
| 597 | IEEE80211_IFACE_ITER_NORMAL, | ||
| 598 | ath10k_wmi_tx_beacons_iter, | ||
| 599 | NULL); | ||
| 600 | spin_unlock_bh(&ar->data_lock); | ||
| 601 | } | ||
| 602 | |||
| 603 | static void ath10k_wmi_op_ep_tx_credits(struct ath10k *ar) | ||
| 604 | { | ||
| 605 | /* try to send pending beacons first. they take priority */ | ||
| 606 | ath10k_wmi_tx_beacons_nowait(ar); | ||
| 607 | |||
| 608 | wake_up(&ar->wmi.tx_credits_wq); | ||
| 609 | } | ||
| 610 | |||
| 611 | static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, | ||
| 612 | u32 cmd_id) | ||
| 613 | { | ||
| 614 | int ret = -EOPNOTSUPP; | ||
| 615 | |||
| 616 | might_sleep(); | ||
| 617 | |||
| 618 | if (cmd_id == WMI_CMD_UNSUPPORTED) { | ||
| 619 | ath10k_warn("wmi command %d is not supported by firmware\n", | ||
| 620 | cmd_id); | ||
| 621 | return ret; | ||
| 115 | } | 622 | } |
| 116 | 623 | ||
| 117 | memset(skb_cb, 0, sizeof(*skb_cb)); | 624 | wait_event_timeout(ar->wmi.tx_credits_wq, ({ |
| 625 | /* try to send pending beacons first. they take priority */ | ||
| 626 | ath10k_wmi_tx_beacons_nowait(ar); | ||
| 118 | 627 | ||
| 119 | trace_ath10k_wmi_cmd(cmd_id, skb->data, skb->len); | 628 | ret = ath10k_wmi_cmd_send_nowait(ar, skb, cmd_id); |
| 629 | (ret != -EAGAIN); | ||
| 630 | }), 3*HZ); | ||
| 120 | 631 | ||
| 121 | status = ath10k_htc_send(&ar->htc, ar->wmi.eid, skb); | 632 | if (ret) |
| 122 | if (status) { | ||
| 123 | dev_kfree_skb_any(skb); | 633 | dev_kfree_skb_any(skb); |
| 124 | atomic_dec(&ar->wmi.pending_tx_count); | 634 | |
| 125 | return status; | 635 | return ret; |
| 636 | } | ||
| 637 | |||
| 638 | int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb) | ||
| 639 | { | ||
| 640 | int ret = 0; | ||
| 641 | struct wmi_mgmt_tx_cmd *cmd; | ||
| 642 | struct ieee80211_hdr *hdr; | ||
| 643 | struct sk_buff *wmi_skb; | ||
| 644 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
| 645 | int len; | ||
| 646 | u16 fc; | ||
| 647 | |||
| 648 | hdr = (struct ieee80211_hdr *)skb->data; | ||
| 649 | fc = le16_to_cpu(hdr->frame_control); | ||
| 650 | |||
| 651 | if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control))) | ||
| 652 | return -EINVAL; | ||
| 653 | |||
| 654 | len = sizeof(cmd->hdr) + skb->len; | ||
| 655 | len = round_up(len, 4); | ||
| 656 | |||
| 657 | wmi_skb = ath10k_wmi_alloc_skb(len); | ||
| 658 | if (!wmi_skb) | ||
| 659 | return -ENOMEM; | ||
| 660 | |||
| 661 | cmd = (struct wmi_mgmt_tx_cmd *)wmi_skb->data; | ||
| 662 | |||
| 663 | cmd->hdr.vdev_id = __cpu_to_le32(ATH10K_SKB_CB(skb)->vdev_id); | ||
| 664 | cmd->hdr.tx_rate = 0; | ||
| 665 | cmd->hdr.tx_power = 0; | ||
| 666 | cmd->hdr.buf_len = __cpu_to_le32((u32)(skb->len)); | ||
| 667 | |||
| 668 | memcpy(cmd->hdr.peer_macaddr.addr, ieee80211_get_DA(hdr), ETH_ALEN); | ||
| 669 | memcpy(cmd->buf, skb->data, skb->len); | ||
| 670 | |||
| 671 | ath10k_dbg(ATH10K_DBG_WMI, "wmi mgmt tx skb %p len %d ftype %02x stype %02x\n", | ||
| 672 | wmi_skb, wmi_skb->len, fc & IEEE80211_FCTL_FTYPE, | ||
| 673 | fc & IEEE80211_FCTL_STYPE); | ||
| 674 | |||
| 675 | /* Send the management frame buffer to the target */ | ||
| 676 | ret = ath10k_wmi_cmd_send(ar, wmi_skb, ar->wmi.cmd->mgmt_tx_cmdid); | ||
| 677 | if (ret) { | ||
| 678 | dev_kfree_skb_any(skb); | ||
| 679 | return ret; | ||
| 126 | } | 680 | } |
| 127 | 681 | ||
| 128 | return 0; | 682 | /* TODO: report tx status to mac80211 - temporary just ACK */ |
| 683 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
| 684 | ieee80211_tx_status_irqsafe(ar->hw, skb); | ||
| 685 | |||
| 686 | return ret; | ||
| 129 | } | 687 | } |
| 130 | 688 | ||
| 131 | static int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb) | 689 | static int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb) |
| @@ -315,7 +873,9 @@ static inline u8 get_rate_idx(u32 rate, enum ieee80211_band band) | |||
| 315 | 873 | ||
| 316 | static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) | 874 | static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) |
| 317 | { | 875 | { |
| 318 | struct wmi_mgmt_rx_event *event = (struct wmi_mgmt_rx_event *)skb->data; | 876 | struct wmi_mgmt_rx_event_v1 *ev_v1; |
| 877 | struct wmi_mgmt_rx_event_v2 *ev_v2; | ||
| 878 | struct wmi_mgmt_rx_hdr_v1 *ev_hdr; | ||
| 319 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 879 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
| 320 | struct ieee80211_hdr *hdr; | 880 | struct ieee80211_hdr *hdr; |
| 321 | u32 rx_status; | 881 | u32 rx_status; |
| @@ -325,13 +885,24 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) | |||
| 325 | u32 rate; | 885 | u32 rate; |
| 326 | u32 buf_len; | 886 | u32 buf_len; |
| 327 | u16 fc; | 887 | u16 fc; |
| 888 | int pull_len; | ||
| 889 | |||
| 890 | if (test_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features)) { | ||
| 891 | ev_v2 = (struct wmi_mgmt_rx_event_v2 *)skb->data; | ||
| 892 | ev_hdr = &ev_v2->hdr.v1; | ||
| 893 | pull_len = sizeof(*ev_v2); | ||
| 894 | } else { | ||
| 895 | ev_v1 = (struct wmi_mgmt_rx_event_v1 *)skb->data; | ||
| 896 | ev_hdr = &ev_v1->hdr; | ||
| 897 | pull_len = sizeof(*ev_v1); | ||
| 898 | } | ||
| 328 | 899 | ||
| 329 | channel = __le32_to_cpu(event->hdr.channel); | 900 | channel = __le32_to_cpu(ev_hdr->channel); |
| 330 | buf_len = __le32_to_cpu(event->hdr.buf_len); | 901 | buf_len = __le32_to_cpu(ev_hdr->buf_len); |
| 331 | rx_status = __le32_to_cpu(event->hdr.status); | 902 | rx_status = __le32_to_cpu(ev_hdr->status); |
| 332 | snr = __le32_to_cpu(event->hdr.snr); | 903 | snr = __le32_to_cpu(ev_hdr->snr); |
| 333 | phy_mode = __le32_to_cpu(event->hdr.phy_mode); | 904 | phy_mode = __le32_to_cpu(ev_hdr->phy_mode); |
| 334 | rate = __le32_to_cpu(event->hdr.rate); | 905 | rate = __le32_to_cpu(ev_hdr->rate); |
| 335 | 906 | ||
| 336 | memset(status, 0, sizeof(*status)); | 907 | memset(status, 0, sizeof(*status)); |
| 337 | 908 | ||
| @@ -358,7 +929,7 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) | |||
| 358 | status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR; | 929 | status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR; |
| 359 | status->rate_idx = get_rate_idx(rate, status->band); | 930 | status->rate_idx = get_rate_idx(rate, status->band); |
| 360 | 931 | ||
| 361 | skb_pull(skb, sizeof(event->hdr)); | 932 | skb_pull(skb, pull_len); |
| 362 | 933 | ||
| 363 | hdr = (struct ieee80211_hdr *)skb->data; | 934 | hdr = (struct ieee80211_hdr *)skb->data; |
| 364 | fc = le16_to_cpu(hdr->frame_control); | 935 | fc = le16_to_cpu(hdr->frame_control); |
| @@ -734,10 +1305,8 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) | |||
| 734 | int i = -1; | 1305 | int i = -1; |
| 735 | struct wmi_bcn_info *bcn_info; | 1306 | struct wmi_bcn_info *bcn_info; |
| 736 | struct ath10k_vif *arvif; | 1307 | struct ath10k_vif *arvif; |
| 737 | struct wmi_bcn_tx_arg arg; | ||
| 738 | struct sk_buff *bcn; | 1308 | struct sk_buff *bcn; |
| 739 | int vdev_id = 0; | 1309 | int vdev_id = 0; |
| 740 | int ret; | ||
| 741 | 1310 | ||
| 742 | ath10k_dbg(ATH10K_DBG_MGMT, "WMI_HOST_SWBA_EVENTID\n"); | 1311 | ath10k_dbg(ATH10K_DBG_MGMT, "WMI_HOST_SWBA_EVENTID\n"); |
| 743 | 1312 | ||
| @@ -794,17 +1363,17 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) | |||
| 794 | ath10k_wmi_update_tim(ar, arvif, bcn, bcn_info); | 1363 | ath10k_wmi_update_tim(ar, arvif, bcn, bcn_info); |
| 795 | ath10k_wmi_update_noa(ar, arvif, bcn, bcn_info); | 1364 | ath10k_wmi_update_noa(ar, arvif, bcn, bcn_info); |
| 796 | 1365 | ||
| 797 | arg.vdev_id = arvif->vdev_id; | 1366 | spin_lock_bh(&ar->data_lock); |
| 798 | arg.tx_rate = 0; | 1367 | if (arvif->beacon) { |
| 799 | arg.tx_power = 0; | 1368 | ath10k_warn("SWBA overrun on vdev %d\n", |
| 800 | arg.bcn = bcn->data; | 1369 | arvif->vdev_id); |
| 801 | arg.bcn_len = bcn->len; | 1370 | dev_kfree_skb_any(arvif->beacon); |
| 1371 | } | ||
| 802 | 1372 | ||
| 803 | ret = ath10k_wmi_beacon_send(ar, &arg); | 1373 | arvif->beacon = bcn; |
| 804 | if (ret) | ||
| 805 | ath10k_warn("could not send beacon (%d)\n", ret); | ||
| 806 | 1374 | ||
| 807 | dev_kfree_skb_any(bcn); | 1375 | ath10k_wmi_tx_beacon_nowait(arvif); |
| 1376 | spin_unlock_bh(&ar->data_lock); | ||
| 808 | } | 1377 | } |
| 809 | } | 1378 | } |
| 810 | 1379 | ||
| @@ -919,6 +1488,55 @@ static void ath10k_wmi_event_vdev_install_key_complete(struct ath10k *ar, | |||
| 919 | ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID\n"); | 1488 | ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID\n"); |
| 920 | } | 1489 | } |
| 921 | 1490 | ||
| 1491 | static void ath10k_wmi_event_inst_rssi_stats(struct ath10k *ar, | ||
| 1492 | struct sk_buff *skb) | ||
| 1493 | { | ||
| 1494 | ath10k_dbg(ATH10K_DBG_WMI, "WMI_INST_RSSI_STATS_EVENTID\n"); | ||
| 1495 | } | ||
| 1496 | |||
| 1497 | static void ath10k_wmi_event_vdev_standby_req(struct ath10k *ar, | ||
| 1498 | struct sk_buff *skb) | ||
| 1499 | { | ||
| 1500 | ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_STANDBY_REQ_EVENTID\n"); | ||
| 1501 | } | ||
| 1502 | |||
| 1503 | static void ath10k_wmi_event_vdev_resume_req(struct ath10k *ar, | ||
| 1504 | struct sk_buff *skb) | ||
| 1505 | { | ||
| 1506 | ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_RESUME_REQ_EVENTID\n"); | ||
| 1507 | } | ||
| 1508 | |||
| 1509 | static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id, | ||
| 1510 | u32 num_units, u32 unit_len) | ||
| 1511 | { | ||
| 1512 | dma_addr_t paddr; | ||
| 1513 | u32 pool_size; | ||
| 1514 | int idx = ar->wmi.num_mem_chunks; | ||
| 1515 | |||
| 1516 | pool_size = num_units * round_up(unit_len, 4); | ||
| 1517 | |||
| 1518 | if (!pool_size) | ||
| 1519 | return -EINVAL; | ||
| 1520 | |||
| 1521 | ar->wmi.mem_chunks[idx].vaddr = dma_alloc_coherent(ar->dev, | ||
| 1522 | pool_size, | ||
| 1523 | &paddr, | ||
| 1524 | GFP_ATOMIC); | ||
| 1525 | if (!ar->wmi.mem_chunks[idx].vaddr) { | ||
| 1526 | ath10k_warn("failed to allocate memory chunk\n"); | ||
| 1527 | return -ENOMEM; | ||
| 1528 | } | ||
| 1529 | |||
| 1530 | memset(ar->wmi.mem_chunks[idx].vaddr, 0, pool_size); | ||
| 1531 | |||
| 1532 | ar->wmi.mem_chunks[idx].paddr = paddr; | ||
| 1533 | ar->wmi.mem_chunks[idx].len = pool_size; | ||
| 1534 | ar->wmi.mem_chunks[idx].req_id = req_id; | ||
| 1535 | ar->wmi.num_mem_chunks++; | ||
| 1536 | |||
| 1537 | return 0; | ||
| 1538 | } | ||
| 1539 | |||
| 922 | static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar, | 1540 | static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar, |
| 923 | struct sk_buff *skb) | 1541 | struct sk_buff *skb) |
| 924 | { | 1542 | { |
| @@ -943,6 +1561,10 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar, | |||
| 943 | ar->phy_capability = __le32_to_cpu(ev->phy_capability); | 1561 | ar->phy_capability = __le32_to_cpu(ev->phy_capability); |
| 944 | ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains); | 1562 | ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains); |
| 945 | 1563 | ||
| 1564 | /* only manually set fw features when not using FW IE format */ | ||
| 1565 | if (ar->fw_api == 1 && ar->fw_version_build > 636) | ||
| 1566 | set_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features); | ||
| 1567 | |||
| 946 | if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) { | 1568 | if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) { |
| 947 | ath10k_warn("hardware advertises support for more spatial streams than it should (%d > %d)\n", | 1569 | ath10k_warn("hardware advertises support for more spatial streams than it should (%d > %d)\n", |
| 948 | ar->num_rf_chains, WMI_MAX_SPATIAL_STREAM); | 1570 | ar->num_rf_chains, WMI_MAX_SPATIAL_STREAM); |
| @@ -987,6 +1609,108 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar, | |||
| 987 | complete(&ar->wmi.service_ready); | 1609 | complete(&ar->wmi.service_ready); |
| 988 | } | 1610 | } |
| 989 | 1611 | ||
| 1612 | static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar, | ||
| 1613 | struct sk_buff *skb) | ||
| 1614 | { | ||
| 1615 | u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i; | ||
| 1616 | int ret; | ||
| 1617 | struct wmi_service_ready_event_10x *ev = (void *)skb->data; | ||
| 1618 | |||
| 1619 | if (skb->len < sizeof(*ev)) { | ||
| 1620 | ath10k_warn("Service ready event was %d B but expected %zu B. Wrong firmware version?\n", | ||
| 1621 | skb->len, sizeof(*ev)); | ||
| 1622 | return; | ||
| 1623 | } | ||
| 1624 | |||
| 1625 | ar->hw_min_tx_power = __le32_to_cpu(ev->hw_min_tx_power); | ||
| 1626 | ar->hw_max_tx_power = __le32_to_cpu(ev->hw_max_tx_power); | ||
| 1627 | ar->ht_cap_info = __le32_to_cpu(ev->ht_cap_info); | ||
| 1628 | ar->vht_cap_info = __le32_to_cpu(ev->vht_cap_info); | ||
| 1629 | ar->fw_version_major = | ||
| 1630 | (__le32_to_cpu(ev->sw_version) & 0xff000000) >> 24; | ||
| 1631 | ar->fw_version_minor = (__le32_to_cpu(ev->sw_version) & 0x00ffffff); | ||
| 1632 | ar->phy_capability = __le32_to_cpu(ev->phy_capability); | ||
| 1633 | ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains); | ||
| 1634 | |||
| 1635 | if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) { | ||
| 1636 | ath10k_warn("hardware advertises support for more spatial streams than it should (%d > %d)\n", | ||
| 1637 | ar->num_rf_chains, WMI_MAX_SPATIAL_STREAM); | ||
| 1638 | ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM; | ||
| 1639 | } | ||
| 1640 | |||
| 1641 | ar->ath_common.regulatory.current_rd = | ||
| 1642 | __le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd); | ||
| 1643 | |||
| 1644 | ath10k_debug_read_service_map(ar, ev->wmi_service_bitmap, | ||
| 1645 | sizeof(ev->wmi_service_bitmap)); | ||
| 1646 | |||
| 1647 | if (strlen(ar->hw->wiphy->fw_version) == 0) { | ||
| 1648 | snprintf(ar->hw->wiphy->fw_version, | ||
| 1649 | sizeof(ar->hw->wiphy->fw_version), | ||
| 1650 | "%u.%u", | ||
| 1651 | ar->fw_version_major, | ||
| 1652 | ar->fw_version_minor); | ||
| 1653 | } | ||
| 1654 | |||
| 1655 | num_mem_reqs = __le32_to_cpu(ev->num_mem_reqs); | ||
| 1656 | |||
| 1657 | if (num_mem_reqs > ATH10K_MAX_MEM_REQS) { | ||
| 1658 | ath10k_warn("requested memory chunks number (%d) exceeds the limit\n", | ||
| 1659 | num_mem_reqs); | ||
| 1660 | return; | ||
| 1661 | } | ||
| 1662 | |||
| 1663 | if (!num_mem_reqs) | ||
| 1664 | goto exit; | ||
| 1665 | |||
| 1666 | ath10k_dbg(ATH10K_DBG_WMI, "firmware has requested %d memory chunks\n", | ||
| 1667 | num_mem_reqs); | ||
| 1668 | |||
| 1669 | for (i = 0; i < num_mem_reqs; ++i) { | ||
| 1670 | req_id = __le32_to_cpu(ev->mem_reqs[i].req_id); | ||
| 1671 | num_units = __le32_to_cpu(ev->mem_reqs[i].num_units); | ||
| 1672 | unit_size = __le32_to_cpu(ev->mem_reqs[i].unit_size); | ||
| 1673 | num_unit_info = __le32_to_cpu(ev->mem_reqs[i].num_unit_info); | ||
| 1674 | |||
| 1675 | if (num_unit_info & NUM_UNITS_IS_NUM_PEERS) | ||
| 1676 | /* number of units to allocate is number of | ||
| 1677 | * peers, 1 extra for self peer on target */ | ||
| 1678 | /* this needs to be tied, host and target | ||
| 1679 | * can get out of sync */ | ||
| 1680 | num_units = TARGET_10X_NUM_PEERS + 1; | ||
| 1681 | else if (num_unit_info & NUM_UNITS_IS_NUM_VDEVS) | ||
| 1682 | num_units = TARGET_10X_NUM_VDEVS + 1; | ||
| 1683 | |||
| 1684 | ath10k_dbg(ATH10K_DBG_WMI, | ||
| 1685 | "wmi mem_req_id %d num_units %d num_unit_info %d unit size %d actual units %d\n", | ||
| 1686 | req_id, | ||
| 1687 | __le32_to_cpu(ev->mem_reqs[i].num_units), | ||
| 1688 | num_unit_info, | ||
| 1689 | unit_size, | ||
| 1690 | num_units); | ||
| 1691 | |||
| 1692 | ret = ath10k_wmi_alloc_host_mem(ar, req_id, num_units, | ||
| 1693 | unit_size); | ||
| 1694 | if (ret) | ||
| 1695 | return; | ||
| 1696 | } | ||
| 1697 | |||
| 1698 | exit: | ||
| 1699 | ath10k_dbg(ATH10K_DBG_WMI, | ||
| 1700 | "wmi event service ready sw_ver 0x%08x abi_ver %u phy_cap 0x%08x ht_cap 0x%08x vht_cap 0x%08x vht_supp_msc 0x%08x sys_cap_info 0x%08x mem_reqs %u num_rf_chains %u\n", | ||
| 1701 | __le32_to_cpu(ev->sw_version), | ||
| 1702 | __le32_to_cpu(ev->abi_version), | ||
| 1703 | __le32_to_cpu(ev->phy_capability), | ||
| 1704 | __le32_to_cpu(ev->ht_cap_info), | ||
| 1705 | __le32_to_cpu(ev->vht_cap_info), | ||
| 1706 | __le32_to_cpu(ev->vht_supp_mcs), | ||
| 1707 | __le32_to_cpu(ev->sys_cap_info), | ||
| 1708 | __le32_to_cpu(ev->num_mem_reqs), | ||
| 1709 | __le32_to_cpu(ev->num_rf_chains)); | ||
| 1710 | |||
| 1711 | complete(&ar->wmi.service_ready); | ||
| 1712 | } | ||
| 1713 | |||
| 990 | static int ath10k_wmi_ready_event_rx(struct ath10k *ar, struct sk_buff *skb) | 1714 | static int ath10k_wmi_ready_event_rx(struct ath10k *ar, struct sk_buff *skb) |
| 991 | { | 1715 | { |
| 992 | struct wmi_ready_event *ev = (struct wmi_ready_event *)skb->data; | 1716 | struct wmi_ready_event *ev = (struct wmi_ready_event *)skb->data; |
| @@ -1007,7 +1731,7 @@ static int ath10k_wmi_ready_event_rx(struct ath10k *ar, struct sk_buff *skb) | |||
| 1007 | return 0; | 1731 | return 0; |
| 1008 | } | 1732 | } |
| 1009 | 1733 | ||
| 1010 | static void ath10k_wmi_event_process(struct ath10k *ar, struct sk_buff *skb) | 1734 | static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb) |
| 1011 | { | 1735 | { |
| 1012 | struct wmi_cmd_hdr *cmd_hdr; | 1736 | struct wmi_cmd_hdr *cmd_hdr; |
| 1013 | enum wmi_event_id id; | 1737 | enum wmi_event_id id; |
| @@ -1126,64 +1850,158 @@ static void ath10k_wmi_event_process(struct ath10k *ar, struct sk_buff *skb) | |||
| 1126 | dev_kfree_skb(skb); | 1850 | dev_kfree_skb(skb); |
| 1127 | } | 1851 | } |
| 1128 | 1852 | ||
| 1129 | static void ath10k_wmi_event_work(struct work_struct *work) | 1853 | static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb) |
| 1130 | { | 1854 | { |
| 1131 | struct ath10k *ar = container_of(work, struct ath10k, | 1855 | struct wmi_cmd_hdr *cmd_hdr; |
| 1132 | wmi.wmi_event_work); | 1856 | enum wmi_10x_event_id id; |
| 1133 | struct sk_buff *skb; | 1857 | u16 len; |
| 1134 | 1858 | ||
| 1135 | for (;;) { | 1859 | cmd_hdr = (struct wmi_cmd_hdr *)skb->data; |
| 1136 | skb = skb_dequeue(&ar->wmi.wmi_event_list); | 1860 | id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); |
| 1137 | if (!skb) | ||
| 1138 | break; | ||
| 1139 | 1861 | ||
| 1140 | ath10k_wmi_event_process(ar, skb); | 1862 | if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) |
| 1141 | } | 1863 | return; |
| 1142 | } | ||
| 1143 | 1864 | ||
| 1144 | static void ath10k_wmi_process_rx(struct ath10k *ar, struct sk_buff *skb) | 1865 | len = skb->len; |
| 1145 | { | ||
| 1146 | struct wmi_cmd_hdr *cmd_hdr = (struct wmi_cmd_hdr *)skb->data; | ||
| 1147 | enum wmi_event_id event_id; | ||
| 1148 | 1866 | ||
| 1149 | event_id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); | 1867 | trace_ath10k_wmi_event(id, skb->data, skb->len); |
| 1150 | 1868 | ||
| 1151 | /* some events require to be handled ASAP | 1869 | switch (id) { |
| 1152 | * thus can't be defered to a worker thread */ | 1870 | case WMI_10X_MGMT_RX_EVENTID: |
| 1153 | switch (event_id) { | 1871 | ath10k_wmi_event_mgmt_rx(ar, skb); |
| 1154 | case WMI_HOST_SWBA_EVENTID: | 1872 | /* mgmt_rx() owns the skb now! */ |
| 1155 | case WMI_MGMT_RX_EVENTID: | ||
| 1156 | ath10k_wmi_event_process(ar, skb); | ||
| 1157 | return; | 1873 | return; |
| 1874 | case WMI_10X_SCAN_EVENTID: | ||
| 1875 | ath10k_wmi_event_scan(ar, skb); | ||
| 1876 | break; | ||
| 1877 | case WMI_10X_CHAN_INFO_EVENTID: | ||
| 1878 | ath10k_wmi_event_chan_info(ar, skb); | ||
| 1879 | break; | ||
| 1880 | case WMI_10X_ECHO_EVENTID: | ||
| 1881 | ath10k_wmi_event_echo(ar, skb); | ||
| 1882 | break; | ||
| 1883 | case WMI_10X_DEBUG_MESG_EVENTID: | ||
| 1884 | ath10k_wmi_event_debug_mesg(ar, skb); | ||
| 1885 | break; | ||
| 1886 | case WMI_10X_UPDATE_STATS_EVENTID: | ||
| 1887 | ath10k_wmi_event_update_stats(ar, skb); | ||
| 1888 | break; | ||
| 1889 | case WMI_10X_VDEV_START_RESP_EVENTID: | ||
| 1890 | ath10k_wmi_event_vdev_start_resp(ar, skb); | ||
| 1891 | break; | ||
| 1892 | case WMI_10X_VDEV_STOPPED_EVENTID: | ||
| 1893 | ath10k_wmi_event_vdev_stopped(ar, skb); | ||
| 1894 | break; | ||
| 1895 | case WMI_10X_PEER_STA_KICKOUT_EVENTID: | ||
| 1896 | ath10k_wmi_event_peer_sta_kickout(ar, skb); | ||
| 1897 | break; | ||
| 1898 | case WMI_10X_HOST_SWBA_EVENTID: | ||
| 1899 | ath10k_wmi_event_host_swba(ar, skb); | ||
| 1900 | break; | ||
| 1901 | case WMI_10X_TBTTOFFSET_UPDATE_EVENTID: | ||
| 1902 | ath10k_wmi_event_tbttoffset_update(ar, skb); | ||
| 1903 | break; | ||
| 1904 | case WMI_10X_PHYERR_EVENTID: | ||
| 1905 | ath10k_wmi_event_phyerr(ar, skb); | ||
| 1906 | break; | ||
| 1907 | case WMI_10X_ROAM_EVENTID: | ||
| 1908 | ath10k_wmi_event_roam(ar, skb); | ||
| 1909 | break; | ||
| 1910 | case WMI_10X_PROFILE_MATCH: | ||
| 1911 | ath10k_wmi_event_profile_match(ar, skb); | ||
| 1912 | break; | ||
| 1913 | case WMI_10X_DEBUG_PRINT_EVENTID: | ||
| 1914 | ath10k_wmi_event_debug_print(ar, skb); | ||
| 1915 | break; | ||
| 1916 | case WMI_10X_PDEV_QVIT_EVENTID: | ||
| 1917 | ath10k_wmi_event_pdev_qvit(ar, skb); | ||
| 1918 | break; | ||
| 1919 | case WMI_10X_WLAN_PROFILE_DATA_EVENTID: | ||
| 1920 | ath10k_wmi_event_wlan_profile_data(ar, skb); | ||
| 1921 | break; | ||
| 1922 | case WMI_10X_RTT_MEASUREMENT_REPORT_EVENTID: | ||
| 1923 | ath10k_wmi_event_rtt_measurement_report(ar, skb); | ||
| 1924 | break; | ||
| 1925 | case WMI_10X_TSF_MEASUREMENT_REPORT_EVENTID: | ||
| 1926 | ath10k_wmi_event_tsf_measurement_report(ar, skb); | ||
| 1927 | break; | ||
| 1928 | case WMI_10X_RTT_ERROR_REPORT_EVENTID: | ||
| 1929 | ath10k_wmi_event_rtt_error_report(ar, skb); | ||
| 1930 | break; | ||
| 1931 | case WMI_10X_WOW_WAKEUP_HOST_EVENTID: | ||
| 1932 | ath10k_wmi_event_wow_wakeup_host(ar, skb); | ||
| 1933 | break; | ||
| 1934 | case WMI_10X_DCS_INTERFERENCE_EVENTID: | ||
| 1935 | ath10k_wmi_event_dcs_interference(ar, skb); | ||
| 1936 | break; | ||
| 1937 | case WMI_10X_PDEV_TPC_CONFIG_EVENTID: | ||
| 1938 | ath10k_wmi_event_pdev_tpc_config(ar, skb); | ||
| 1939 | break; | ||
| 1940 | case WMI_10X_INST_RSSI_STATS_EVENTID: | ||
| 1941 | ath10k_wmi_event_inst_rssi_stats(ar, skb); | ||
| 1942 | break; | ||
| 1943 | case WMI_10X_VDEV_STANDBY_REQ_EVENTID: | ||
| 1944 | ath10k_wmi_event_vdev_standby_req(ar, skb); | ||
| 1945 | break; | ||
| 1946 | case WMI_10X_VDEV_RESUME_REQ_EVENTID: | ||
| 1947 | ath10k_wmi_event_vdev_resume_req(ar, skb); | ||
| 1948 | break; | ||
| 1949 | case WMI_10X_SERVICE_READY_EVENTID: | ||
| 1950 | ath10k_wmi_10x_service_ready_event_rx(ar, skb); | ||
| 1951 | break; | ||
| 1952 | case WMI_10X_READY_EVENTID: | ||
| 1953 | ath10k_wmi_ready_event_rx(ar, skb); | ||
| 1954 | break; | ||
| 1158 | default: | 1955 | default: |
| 1956 | ath10k_warn("Unknown eventid: %d\n", id); | ||
| 1159 | break; | 1957 | break; |
| 1160 | } | 1958 | } |
| 1161 | 1959 | ||
| 1162 | skb_queue_tail(&ar->wmi.wmi_event_list, skb); | 1960 | dev_kfree_skb(skb); |
| 1163 | queue_work(ar->workqueue, &ar->wmi.wmi_event_work); | 1961 | } |
| 1962 | |||
| 1963 | |||
| 1964 | static void ath10k_wmi_process_rx(struct ath10k *ar, struct sk_buff *skb) | ||
| 1965 | { | ||
| 1966 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) | ||
| 1967 | ath10k_wmi_10x_process_rx(ar, skb); | ||
| 1968 | else | ||
| 1969 | ath10k_wmi_main_process_rx(ar, skb); | ||
| 1164 | } | 1970 | } |
| 1165 | 1971 | ||
| 1166 | /* WMI Initialization functions */ | 1972 | /* WMI Initialization functions */ |
| 1167 | int ath10k_wmi_attach(struct ath10k *ar) | 1973 | int ath10k_wmi_attach(struct ath10k *ar) |
| 1168 | { | 1974 | { |
| 1975 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { | ||
| 1976 | ar->wmi.cmd = &wmi_10x_cmd_map; | ||
| 1977 | ar->wmi.vdev_param = &wmi_10x_vdev_param_map; | ||
| 1978 | ar->wmi.pdev_param = &wmi_10x_pdev_param_map; | ||
| 1979 | } else { | ||
| 1980 | ar->wmi.cmd = &wmi_cmd_map; | ||
| 1981 | ar->wmi.vdev_param = &wmi_vdev_param_map; | ||
| 1982 | ar->wmi.pdev_param = &wmi_pdev_param_map; | ||
| 1983 | } | ||
| 1984 | |||
| 1169 | init_completion(&ar->wmi.service_ready); | 1985 | init_completion(&ar->wmi.service_ready); |
| 1170 | init_completion(&ar->wmi.unified_ready); | 1986 | init_completion(&ar->wmi.unified_ready); |
| 1171 | init_waitqueue_head(&ar->wmi.wq); | 1987 | init_waitqueue_head(&ar->wmi.tx_credits_wq); |
| 1172 | |||
| 1173 | skb_queue_head_init(&ar->wmi.wmi_event_list); | ||
| 1174 | INIT_WORK(&ar->wmi.wmi_event_work, ath10k_wmi_event_work); | ||
| 1175 | 1988 | ||
| 1176 | return 0; | 1989 | return 0; |
| 1177 | } | 1990 | } |
| 1178 | 1991 | ||
| 1179 | void ath10k_wmi_detach(struct ath10k *ar) | 1992 | void ath10k_wmi_detach(struct ath10k *ar) |
| 1180 | { | 1993 | { |
| 1181 | /* HTC should've drained the packets already */ | 1994 | int i; |
| 1182 | if (WARN_ON(atomic_read(&ar->wmi.pending_tx_count) > 0)) | 1995 | |
| 1183 | ath10k_warn("there are still pending packets\n"); | 1996 | /* free the host memory chunks requested by firmware */ |
| 1997 | for (i = 0; i < ar->wmi.num_mem_chunks; i++) { | ||
| 1998 | dma_free_coherent(ar->dev, | ||
| 1999 | ar->wmi.mem_chunks[i].len, | ||
| 2000 | ar->wmi.mem_chunks[i].vaddr, | ||
| 2001 | ar->wmi.mem_chunks[i].paddr); | ||
| 2002 | } | ||
| 1184 | 2003 | ||
| 1185 | cancel_work_sync(&ar->wmi.wmi_event_work); | 2004 | ar->wmi.num_mem_chunks = 0; |
| 1186 | skb_queue_purge(&ar->wmi.wmi_event_list); | ||
| 1187 | } | 2005 | } |
| 1188 | 2006 | ||
| 1189 | int ath10k_wmi_connect_htc_service(struct ath10k *ar) | 2007 | int ath10k_wmi_connect_htc_service(struct ath10k *ar) |
| @@ -1198,6 +2016,7 @@ int ath10k_wmi_connect_htc_service(struct ath10k *ar) | |||
| 1198 | /* these fields are the same for all service endpoints */ | 2016 | /* these fields are the same for all service endpoints */ |
| 1199 | conn_req.ep_ops.ep_tx_complete = ath10k_wmi_htc_tx_complete; | 2017 | conn_req.ep_ops.ep_tx_complete = ath10k_wmi_htc_tx_complete; |
| 1200 | conn_req.ep_ops.ep_rx_complete = ath10k_wmi_process_rx; | 2018 | conn_req.ep_ops.ep_rx_complete = ath10k_wmi_process_rx; |
| 2019 | conn_req.ep_ops.ep_tx_credits = ath10k_wmi_op_ep_tx_credits; | ||
| 1201 | 2020 | ||
| 1202 | /* connect to control service */ | 2021 | /* connect to control service */ |
| 1203 | conn_req.service_id = ATH10K_HTC_SVC_ID_WMI_CONTROL; | 2022 | conn_req.service_id = ATH10K_HTC_SVC_ID_WMI_CONTROL; |
| @@ -1234,7 +2053,8 @@ int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g, | |||
| 1234 | "wmi pdev regdomain rd %x rd2g %x rd5g %x ctl2g %x ctl5g %x\n", | 2053 | "wmi pdev regdomain rd %x rd2g %x rd5g %x ctl2g %x ctl5g %x\n", |
| 1235 | rd, rd2g, rd5g, ctl2g, ctl5g); | 2054 | rd, rd2g, rd5g, ctl2g, ctl5g); |
| 1236 | 2055 | ||
| 1237 | return ath10k_wmi_cmd_send(ar, skb, WMI_PDEV_SET_REGDOMAIN_CMDID); | 2056 | return ath10k_wmi_cmd_send(ar, skb, |
| 2057 | ar->wmi.cmd->pdev_set_regdomain_cmdid); | ||
| 1238 | } | 2058 | } |
| 1239 | 2059 | ||
| 1240 | int ath10k_wmi_pdev_set_channel(struct ath10k *ar, | 2060 | int ath10k_wmi_pdev_set_channel(struct ath10k *ar, |
| @@ -1264,7 +2084,8 @@ int ath10k_wmi_pdev_set_channel(struct ath10k *ar, | |||
| 1264 | "wmi set channel mode %d freq %d\n", | 2084 | "wmi set channel mode %d freq %d\n", |
| 1265 | arg->mode, arg->freq); | 2085 | arg->mode, arg->freq); |
| 1266 | 2086 | ||
| 1267 | return ath10k_wmi_cmd_send(ar, skb, WMI_PDEV_SET_CHANNEL_CMDID); | 2087 | return ath10k_wmi_cmd_send(ar, skb, |
| 2088 | ar->wmi.cmd->pdev_set_channel_cmdid); | ||
| 1268 | } | 2089 | } |
| 1269 | 2090 | ||
| 1270 | int ath10k_wmi_pdev_suspend_target(struct ath10k *ar) | 2091 | int ath10k_wmi_pdev_suspend_target(struct ath10k *ar) |
| @@ -1279,7 +2100,7 @@ int ath10k_wmi_pdev_suspend_target(struct ath10k *ar) | |||
| 1279 | cmd = (struct wmi_pdev_suspend_cmd *)skb->data; | 2100 | cmd = (struct wmi_pdev_suspend_cmd *)skb->data; |
| 1280 | cmd->suspend_opt = WMI_PDEV_SUSPEND; | 2101 | cmd->suspend_opt = WMI_PDEV_SUSPEND; |
| 1281 | 2102 | ||
| 1282 | return ath10k_wmi_cmd_send(ar, skb, WMI_PDEV_SUSPEND_CMDID); | 2103 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_suspend_cmdid); |
| 1283 | } | 2104 | } |
| 1284 | 2105 | ||
| 1285 | int ath10k_wmi_pdev_resume_target(struct ath10k *ar) | 2106 | int ath10k_wmi_pdev_resume_target(struct ath10k *ar) |
| @@ -1290,15 +2111,19 @@ int ath10k_wmi_pdev_resume_target(struct ath10k *ar) | |||
| 1290 | if (skb == NULL) | 2111 | if (skb == NULL) |
| 1291 | return -ENOMEM; | 2112 | return -ENOMEM; |
| 1292 | 2113 | ||
| 1293 | return ath10k_wmi_cmd_send(ar, skb, WMI_PDEV_RESUME_CMDID); | 2114 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_resume_cmdid); |
| 1294 | } | 2115 | } |
| 1295 | 2116 | ||
| 1296 | int ath10k_wmi_pdev_set_param(struct ath10k *ar, enum wmi_pdev_param id, | 2117 | int ath10k_wmi_pdev_set_param(struct ath10k *ar, u32 id, u32 value) |
| 1297 | u32 value) | ||
| 1298 | { | 2118 | { |
| 1299 | struct wmi_pdev_set_param_cmd *cmd; | 2119 | struct wmi_pdev_set_param_cmd *cmd; |
| 1300 | struct sk_buff *skb; | 2120 | struct sk_buff *skb; |
| 1301 | 2121 | ||
| 2122 | if (id == WMI_PDEV_PARAM_UNSUPPORTED) { | ||
| 2123 | ath10k_warn("pdev param %d not supported by firmware\n", id); | ||
| 2124 | return -EOPNOTSUPP; | ||
| 2125 | } | ||
| 2126 | |||
| 1302 | skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); | 2127 | skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); |
| 1303 | if (!skb) | 2128 | if (!skb) |
| 1304 | return -ENOMEM; | 2129 | return -ENOMEM; |
| @@ -1309,15 +2134,16 @@ int ath10k_wmi_pdev_set_param(struct ath10k *ar, enum wmi_pdev_param id, | |||
| 1309 | 2134 | ||
| 1310 | ath10k_dbg(ATH10K_DBG_WMI, "wmi pdev set param %d value %d\n", | 2135 | ath10k_dbg(ATH10K_DBG_WMI, "wmi pdev set param %d value %d\n", |
| 1311 | id, value); | 2136 | id, value); |
| 1312 | return ath10k_wmi_cmd_send(ar, skb, WMI_PDEV_SET_PARAM_CMDID); | 2137 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_set_param_cmdid); |
| 1313 | } | 2138 | } |
| 1314 | 2139 | ||
| 1315 | int ath10k_wmi_cmd_init(struct ath10k *ar) | 2140 | static int ath10k_wmi_main_cmd_init(struct ath10k *ar) |
| 1316 | { | 2141 | { |
| 1317 | struct wmi_init_cmd *cmd; | 2142 | struct wmi_init_cmd *cmd; |
| 1318 | struct sk_buff *buf; | 2143 | struct sk_buff *buf; |
| 1319 | struct wmi_resource_config config = {}; | 2144 | struct wmi_resource_config config = {}; |
| 1320 | u32 val; | 2145 | u32 len, val; |
| 2146 | int i; | ||
| 1321 | 2147 | ||
| 1322 | config.num_vdevs = __cpu_to_le32(TARGET_NUM_VDEVS); | 2148 | config.num_vdevs = __cpu_to_le32(TARGET_NUM_VDEVS); |
| 1323 | config.num_peers = __cpu_to_le32(TARGET_NUM_PEERS + TARGET_NUM_VDEVS); | 2149 | config.num_peers = __cpu_to_le32(TARGET_NUM_PEERS + TARGET_NUM_VDEVS); |
| @@ -1370,23 +2196,158 @@ int ath10k_wmi_cmd_init(struct ath10k *ar) | |||
| 1370 | config.num_msdu_desc = __cpu_to_le32(TARGET_NUM_MSDU_DESC); | 2196 | config.num_msdu_desc = __cpu_to_le32(TARGET_NUM_MSDU_DESC); |
| 1371 | config.max_frag_entries = __cpu_to_le32(TARGET_MAX_FRAG_ENTRIES); | 2197 | config.max_frag_entries = __cpu_to_le32(TARGET_MAX_FRAG_ENTRIES); |
| 1372 | 2198 | ||
| 1373 | buf = ath10k_wmi_alloc_skb(sizeof(*cmd)); | 2199 | len = sizeof(*cmd) + |
| 2200 | (sizeof(struct host_memory_chunk) * ar->wmi.num_mem_chunks); | ||
| 2201 | |||
| 2202 | buf = ath10k_wmi_alloc_skb(len); | ||
| 1374 | if (!buf) | 2203 | if (!buf) |
| 1375 | return -ENOMEM; | 2204 | return -ENOMEM; |
| 1376 | 2205 | ||
| 1377 | cmd = (struct wmi_init_cmd *)buf->data; | 2206 | cmd = (struct wmi_init_cmd *)buf->data; |
| 1378 | cmd->num_host_mem_chunks = 0; | 2207 | |
| 2208 | if (ar->wmi.num_mem_chunks == 0) { | ||
| 2209 | cmd->num_host_mem_chunks = 0; | ||
| 2210 | goto out; | ||
| 2211 | } | ||
| 2212 | |||
| 2213 | ath10k_dbg(ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n", | ||
| 2214 | __cpu_to_le32(ar->wmi.num_mem_chunks)); | ||
| 2215 | |||
| 2216 | cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks); | ||
| 2217 | |||
| 2218 | for (i = 0; i < ar->wmi.num_mem_chunks; i++) { | ||
| 2219 | cmd->host_mem_chunks[i].ptr = | ||
| 2220 | __cpu_to_le32(ar->wmi.mem_chunks[i].paddr); | ||
| 2221 | cmd->host_mem_chunks[i].size = | ||
| 2222 | __cpu_to_le32(ar->wmi.mem_chunks[i].len); | ||
| 2223 | cmd->host_mem_chunks[i].req_id = | ||
| 2224 | __cpu_to_le32(ar->wmi.mem_chunks[i].req_id); | ||
| 2225 | |||
| 2226 | ath10k_dbg(ATH10K_DBG_WMI, | ||
| 2227 | "wmi chunk %d len %d requested, addr 0x%x\n", | ||
| 2228 | i, | ||
| 2229 | cmd->host_mem_chunks[i].size, | ||
| 2230 | cmd->host_mem_chunks[i].ptr); | ||
| 2231 | } | ||
| 2232 | out: | ||
| 1379 | memcpy(&cmd->resource_config, &config, sizeof(config)); | 2233 | memcpy(&cmd->resource_config, &config, sizeof(config)); |
| 1380 | 2234 | ||
| 1381 | ath10k_dbg(ATH10K_DBG_WMI, "wmi init\n"); | 2235 | ath10k_dbg(ATH10K_DBG_WMI, "wmi init\n"); |
| 1382 | return ath10k_wmi_cmd_send(ar, buf, WMI_INIT_CMDID); | 2236 | return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid); |
| 1383 | } | 2237 | } |
| 1384 | 2238 | ||
| 1385 | static int ath10k_wmi_start_scan_calc_len(const struct wmi_start_scan_arg *arg) | 2239 | static int ath10k_wmi_10x_cmd_init(struct ath10k *ar) |
| 2240 | { | ||
| 2241 | struct wmi_init_cmd_10x *cmd; | ||
| 2242 | struct sk_buff *buf; | ||
| 2243 | struct wmi_resource_config_10x config = {}; | ||
| 2244 | u32 len, val; | ||
| 2245 | int i; | ||
| 2246 | |||
| 2247 | config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS); | ||
| 2248 | config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS); | ||
| 2249 | config.num_peer_keys = __cpu_to_le32(TARGET_10X_NUM_PEER_KEYS); | ||
| 2250 | config.num_tids = __cpu_to_le32(TARGET_10X_NUM_TIDS); | ||
| 2251 | config.ast_skid_limit = __cpu_to_le32(TARGET_10X_AST_SKID_LIMIT); | ||
| 2252 | config.tx_chain_mask = __cpu_to_le32(TARGET_10X_TX_CHAIN_MASK); | ||
| 2253 | config.rx_chain_mask = __cpu_to_le32(TARGET_10X_RX_CHAIN_MASK); | ||
| 2254 | config.rx_timeout_pri_vo = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI); | ||
| 2255 | config.rx_timeout_pri_vi = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI); | ||
| 2256 | config.rx_timeout_pri_be = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI); | ||
| 2257 | config.rx_timeout_pri_bk = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_HI_PRI); | ||
| 2258 | config.rx_decap_mode = __cpu_to_le32(TARGET_10X_RX_DECAP_MODE); | ||
| 2259 | |||
| 2260 | config.scan_max_pending_reqs = | ||
| 2261 | __cpu_to_le32(TARGET_10X_SCAN_MAX_PENDING_REQS); | ||
| 2262 | |||
| 2263 | config.bmiss_offload_max_vdev = | ||
| 2264 | __cpu_to_le32(TARGET_10X_BMISS_OFFLOAD_MAX_VDEV); | ||
| 2265 | |||
| 2266 | config.roam_offload_max_vdev = | ||
| 2267 | __cpu_to_le32(TARGET_10X_ROAM_OFFLOAD_MAX_VDEV); | ||
| 2268 | |||
| 2269 | config.roam_offload_max_ap_profiles = | ||
| 2270 | __cpu_to_le32(TARGET_10X_ROAM_OFFLOAD_MAX_AP_PROFILES); | ||
| 2271 | |||
| 2272 | config.num_mcast_groups = __cpu_to_le32(TARGET_10X_NUM_MCAST_GROUPS); | ||
| 2273 | config.num_mcast_table_elems = | ||
| 2274 | __cpu_to_le32(TARGET_10X_NUM_MCAST_TABLE_ELEMS); | ||
| 2275 | |||
| 2276 | config.mcast2ucast_mode = __cpu_to_le32(TARGET_10X_MCAST2UCAST_MODE); | ||
| 2277 | config.tx_dbg_log_size = __cpu_to_le32(TARGET_10X_TX_DBG_LOG_SIZE); | ||
| 2278 | config.num_wds_entries = __cpu_to_le32(TARGET_10X_NUM_WDS_ENTRIES); | ||
| 2279 | config.dma_burst_size = __cpu_to_le32(TARGET_10X_DMA_BURST_SIZE); | ||
| 2280 | config.mac_aggr_delim = __cpu_to_le32(TARGET_10X_MAC_AGGR_DELIM); | ||
| 2281 | |||
| 2282 | val = TARGET_10X_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK; | ||
| 2283 | config.rx_skip_defrag_timeout_dup_detection_check = __cpu_to_le32(val); | ||
| 2284 | |||
| 2285 | config.vow_config = __cpu_to_le32(TARGET_10X_VOW_CONFIG); | ||
| 2286 | |||
| 2287 | config.num_msdu_desc = __cpu_to_le32(TARGET_10X_NUM_MSDU_DESC); | ||
| 2288 | config.max_frag_entries = __cpu_to_le32(TARGET_10X_MAX_FRAG_ENTRIES); | ||
| 2289 | |||
| 2290 | len = sizeof(*cmd) + | ||
| 2291 | (sizeof(struct host_memory_chunk) * ar->wmi.num_mem_chunks); | ||
| 2292 | |||
| 2293 | buf = ath10k_wmi_alloc_skb(len); | ||
| 2294 | if (!buf) | ||
| 2295 | return -ENOMEM; | ||
| 2296 | |||
| 2297 | cmd = (struct wmi_init_cmd_10x *)buf->data; | ||
| 2298 | |||
| 2299 | if (ar->wmi.num_mem_chunks == 0) { | ||
| 2300 | cmd->num_host_mem_chunks = 0; | ||
| 2301 | goto out; | ||
| 2302 | } | ||
| 2303 | |||
| 2304 | ath10k_dbg(ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n", | ||
| 2305 | __cpu_to_le32(ar->wmi.num_mem_chunks)); | ||
| 2306 | |||
| 2307 | cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks); | ||
| 2308 | |||
| 2309 | for (i = 0; i < ar->wmi.num_mem_chunks; i++) { | ||
| 2310 | cmd->host_mem_chunks[i].ptr = | ||
| 2311 | __cpu_to_le32(ar->wmi.mem_chunks[i].paddr); | ||
| 2312 | cmd->host_mem_chunks[i].size = | ||
| 2313 | __cpu_to_le32(ar->wmi.mem_chunks[i].len); | ||
| 2314 | cmd->host_mem_chunks[i].req_id = | ||
| 2315 | __cpu_to_le32(ar->wmi.mem_chunks[i].req_id); | ||
| 2316 | |||
| 2317 | ath10k_dbg(ATH10K_DBG_WMI, | ||
| 2318 | "wmi chunk %d len %d requested, addr 0x%x\n", | ||
| 2319 | i, | ||
| 2320 | cmd->host_mem_chunks[i].size, | ||
| 2321 | cmd->host_mem_chunks[i].ptr); | ||
| 2322 | } | ||
| 2323 | out: | ||
| 2324 | memcpy(&cmd->resource_config, &config, sizeof(config)); | ||
| 2325 | |||
| 2326 | ath10k_dbg(ATH10K_DBG_WMI, "wmi init 10x\n"); | ||
| 2327 | return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid); | ||
| 2328 | } | ||
| 2329 | |||
| 2330 | int ath10k_wmi_cmd_init(struct ath10k *ar) | ||
| 2331 | { | ||
| 2332 | int ret; | ||
| 2333 | |||
| 2334 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) | ||
| 2335 | ret = ath10k_wmi_10x_cmd_init(ar); | ||
| 2336 | else | ||
| 2337 | ret = ath10k_wmi_main_cmd_init(ar); | ||
| 2338 | |||
| 2339 | return ret; | ||
| 2340 | } | ||
| 2341 | |||
| 2342 | static int ath10k_wmi_start_scan_calc_len(struct ath10k *ar, | ||
| 2343 | const struct wmi_start_scan_arg *arg) | ||
| 1386 | { | 2344 | { |
| 1387 | int len; | 2345 | int len; |
| 1388 | 2346 | ||
| 1389 | len = sizeof(struct wmi_start_scan_cmd); | 2347 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) |
| 2348 | len = sizeof(struct wmi_start_scan_cmd_10x); | ||
| 2349 | else | ||
| 2350 | len = sizeof(struct wmi_start_scan_cmd); | ||
| 1390 | 2351 | ||
| 1391 | if (arg->ie_len) { | 2352 | if (arg->ie_len) { |
| 1392 | if (!arg->ie) | 2353 | if (!arg->ie) |
| @@ -1446,7 +2407,7 @@ int ath10k_wmi_start_scan(struct ath10k *ar, | |||
| 1446 | int len = 0; | 2407 | int len = 0; |
| 1447 | int i; | 2408 | int i; |
| 1448 | 2409 | ||
| 1449 | len = ath10k_wmi_start_scan_calc_len(arg); | 2410 | len = ath10k_wmi_start_scan_calc_len(ar, arg); |
| 1450 | if (len < 0) | 2411 | if (len < 0) |
| 1451 | return len; /* len contains error code here */ | 2412 | return len; /* len contains error code here */ |
| 1452 | 2413 | ||
| @@ -1478,7 +2439,14 @@ int ath10k_wmi_start_scan(struct ath10k *ar, | |||
| 1478 | cmd->scan_ctrl_flags = __cpu_to_le32(arg->scan_ctrl_flags); | 2439 | cmd->scan_ctrl_flags = __cpu_to_le32(arg->scan_ctrl_flags); |
| 1479 | 2440 | ||
| 1480 | /* TLV list starts after fields included in the struct */ | 2441 | /* TLV list starts after fields included in the struct */ |
| 1481 | off = sizeof(*cmd); | 2442 | /* There's just one filed that differes the two start_scan |
| 2443 | * structures - burst_duration, which we are not using btw, | ||
| 2444 | no point to make the split here, just shift the buffer to fit with | ||
| 2445 | given FW */ | ||
| 2446 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) | ||
| 2447 | off = sizeof(struct wmi_start_scan_cmd_10x); | ||
| 2448 | else | ||
| 2449 | off = sizeof(struct wmi_start_scan_cmd); | ||
| 1482 | 2450 | ||
| 1483 | if (arg->n_channels) { | 2451 | if (arg->n_channels) { |
| 1484 | channels = (void *)skb->data + off; | 2452 | channels = (void *)skb->data + off; |
| @@ -1540,7 +2508,7 @@ int ath10k_wmi_start_scan(struct ath10k *ar, | |||
| 1540 | } | 2508 | } |
| 1541 | 2509 | ||
| 1542 | ath10k_dbg(ATH10K_DBG_WMI, "wmi start scan\n"); | 2510 | ath10k_dbg(ATH10K_DBG_WMI, "wmi start scan\n"); |
| 1543 | return ath10k_wmi_cmd_send(ar, skb, WMI_START_SCAN_CMDID); | 2511 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->start_scan_cmdid); |
| 1544 | } | 2512 | } |
| 1545 | 2513 | ||
| 1546 | void ath10k_wmi_start_scan_init(struct ath10k *ar, | 2514 | void ath10k_wmi_start_scan_init(struct ath10k *ar, |
| @@ -1556,7 +2524,7 @@ void ath10k_wmi_start_scan_init(struct ath10k *ar, | |||
| 1556 | arg->repeat_probe_time = 0; | 2524 | arg->repeat_probe_time = 0; |
| 1557 | arg->probe_spacing_time = 0; | 2525 | arg->probe_spacing_time = 0; |
| 1558 | arg->idle_time = 0; | 2526 | arg->idle_time = 0; |
| 1559 | arg->max_scan_time = 5000; | 2527 | arg->max_scan_time = 20000; |
| 1560 | arg->probe_delay = 5; | 2528 | arg->probe_delay = 5; |
| 1561 | arg->notify_scan_events = WMI_SCAN_EVENT_STARTED | 2529 | arg->notify_scan_events = WMI_SCAN_EVENT_STARTED |
| 1562 | | WMI_SCAN_EVENT_COMPLETED | 2530 | | WMI_SCAN_EVENT_COMPLETED |
| @@ -1600,7 +2568,7 @@ int ath10k_wmi_stop_scan(struct ath10k *ar, const struct wmi_stop_scan_arg *arg) | |||
| 1600 | ath10k_dbg(ATH10K_DBG_WMI, | 2568 | ath10k_dbg(ATH10K_DBG_WMI, |
| 1601 | "wmi stop scan reqid %d req_type %d vdev/scan_id %d\n", | 2569 | "wmi stop scan reqid %d req_type %d vdev/scan_id %d\n", |
| 1602 | arg->req_id, arg->req_type, arg->u.scan_id); | 2570 | arg->req_id, arg->req_type, arg->u.scan_id); |
| 1603 | return ath10k_wmi_cmd_send(ar, skb, WMI_STOP_SCAN_CMDID); | 2571 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->stop_scan_cmdid); |
| 1604 | } | 2572 | } |
| 1605 | 2573 | ||
| 1606 | int ath10k_wmi_vdev_create(struct ath10k *ar, u32 vdev_id, | 2574 | int ath10k_wmi_vdev_create(struct ath10k *ar, u32 vdev_id, |
| @@ -1625,7 +2593,7 @@ int ath10k_wmi_vdev_create(struct ath10k *ar, u32 vdev_id, | |||
| 1625 | "WMI vdev create: id %d type %d subtype %d macaddr %pM\n", | 2593 | "WMI vdev create: id %d type %d subtype %d macaddr %pM\n", |
| 1626 | vdev_id, type, subtype, macaddr); | 2594 | vdev_id, type, subtype, macaddr); |
| 1627 | 2595 | ||
| 1628 | return ath10k_wmi_cmd_send(ar, skb, WMI_VDEV_CREATE_CMDID); | 2596 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_create_cmdid); |
| 1629 | } | 2597 | } |
| 1630 | 2598 | ||
| 1631 | int ath10k_wmi_vdev_delete(struct ath10k *ar, u32 vdev_id) | 2599 | int ath10k_wmi_vdev_delete(struct ath10k *ar, u32 vdev_id) |
| @@ -1643,20 +2611,20 @@ int ath10k_wmi_vdev_delete(struct ath10k *ar, u32 vdev_id) | |||
| 1643 | ath10k_dbg(ATH10K_DBG_WMI, | 2611 | ath10k_dbg(ATH10K_DBG_WMI, |
| 1644 | "WMI vdev delete id %d\n", vdev_id); | 2612 | "WMI vdev delete id %d\n", vdev_id); |
| 1645 | 2613 | ||
| 1646 | return ath10k_wmi_cmd_send(ar, skb, WMI_VDEV_DELETE_CMDID); | 2614 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_delete_cmdid); |
| 1647 | } | 2615 | } |
| 1648 | 2616 | ||
| 1649 | static int ath10k_wmi_vdev_start_restart(struct ath10k *ar, | 2617 | static int ath10k_wmi_vdev_start_restart(struct ath10k *ar, |
| 1650 | const struct wmi_vdev_start_request_arg *arg, | 2618 | const struct wmi_vdev_start_request_arg *arg, |
| 1651 | enum wmi_cmd_id cmd_id) | 2619 | u32 cmd_id) |
| 1652 | { | 2620 | { |
| 1653 | struct wmi_vdev_start_request_cmd *cmd; | 2621 | struct wmi_vdev_start_request_cmd *cmd; |
| 1654 | struct sk_buff *skb; | 2622 | struct sk_buff *skb; |
| 1655 | const char *cmdname; | 2623 | const char *cmdname; |
| 1656 | u32 flags = 0; | 2624 | u32 flags = 0; |
| 1657 | 2625 | ||
| 1658 | if (cmd_id != WMI_VDEV_START_REQUEST_CMDID && | 2626 | if (cmd_id != ar->wmi.cmd->vdev_start_request_cmdid && |
| 1659 | cmd_id != WMI_VDEV_RESTART_REQUEST_CMDID) | 2627 | cmd_id != ar->wmi.cmd->vdev_restart_request_cmdid) |
| 1660 | return -EINVAL; | 2628 | return -EINVAL; |
| 1661 | if (WARN_ON(arg->ssid && arg->ssid_len == 0)) | 2629 | if (WARN_ON(arg->ssid && arg->ssid_len == 0)) |
| 1662 | return -EINVAL; | 2630 | return -EINVAL; |
| @@ -1665,9 +2633,9 @@ static int ath10k_wmi_vdev_start_restart(struct ath10k *ar, | |||
| 1665 | if (WARN_ON(arg->ssid_len > sizeof(cmd->ssid.ssid))) | 2633 | if (WARN_ON(arg->ssid_len > sizeof(cmd->ssid.ssid))) |
| 1666 | return -EINVAL; | 2634 | return -EINVAL; |
| 1667 | 2635 | ||
| 1668 | if (cmd_id == WMI_VDEV_START_REQUEST_CMDID) | 2636 | if (cmd_id == ar->wmi.cmd->vdev_start_request_cmdid) |
| 1669 | cmdname = "start"; | 2637 | cmdname = "start"; |
| 1670 | else if (cmd_id == WMI_VDEV_RESTART_REQUEST_CMDID) | 2638 | else if (cmd_id == ar->wmi.cmd->vdev_restart_request_cmdid) |
| 1671 | cmdname = "restart"; | 2639 | cmdname = "restart"; |
| 1672 | else | 2640 | else |
| 1673 | return -EINVAL; /* should not happen, we already check cmd_id */ | 2641 | return -EINVAL; /* should not happen, we already check cmd_id */ |
| @@ -1718,15 +2686,17 @@ static int ath10k_wmi_vdev_start_restart(struct ath10k *ar, | |||
| 1718 | int ath10k_wmi_vdev_start(struct ath10k *ar, | 2686 | int ath10k_wmi_vdev_start(struct ath10k *ar, |
| 1719 | const struct wmi_vdev_start_request_arg *arg) | 2687 | const struct wmi_vdev_start_request_arg *arg) |
| 1720 | { | 2688 | { |
| 1721 | return ath10k_wmi_vdev_start_restart(ar, arg, | 2689 | u32 cmd_id = ar->wmi.cmd->vdev_start_request_cmdid; |
| 1722 | WMI_VDEV_START_REQUEST_CMDID); | 2690 | |
| 2691 | return ath10k_wmi_vdev_start_restart(ar, arg, cmd_id); | ||
| 1723 | } | 2692 | } |
| 1724 | 2693 | ||
| 1725 | int ath10k_wmi_vdev_restart(struct ath10k *ar, | 2694 | int ath10k_wmi_vdev_restart(struct ath10k *ar, |
| 1726 | const struct wmi_vdev_start_request_arg *arg) | 2695 | const struct wmi_vdev_start_request_arg *arg) |
| 1727 | { | 2696 | { |
| 1728 | return ath10k_wmi_vdev_start_restart(ar, arg, | 2697 | u32 cmd_id = ar->wmi.cmd->vdev_restart_request_cmdid; |
| 1729 | WMI_VDEV_RESTART_REQUEST_CMDID); | 2698 | |
| 2699 | return ath10k_wmi_vdev_start_restart(ar, arg, cmd_id); | ||
| 1730 | } | 2700 | } |
| 1731 | 2701 | ||
| 1732 | int ath10k_wmi_vdev_stop(struct ath10k *ar, u32 vdev_id) | 2702 | int ath10k_wmi_vdev_stop(struct ath10k *ar, u32 vdev_id) |
| @@ -1743,7 +2713,7 @@ int ath10k_wmi_vdev_stop(struct ath10k *ar, u32 vdev_id) | |||
| 1743 | 2713 | ||
| 1744 | ath10k_dbg(ATH10K_DBG_WMI, "wmi vdev stop id 0x%x\n", vdev_id); | 2714 | ath10k_dbg(ATH10K_DBG_WMI, "wmi vdev stop id 0x%x\n", vdev_id); |
| 1745 | 2715 | ||
| 1746 | return ath10k_wmi_cmd_send(ar, skb, WMI_VDEV_STOP_CMDID); | 2716 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_stop_cmdid); |
| 1747 | } | 2717 | } |
| 1748 | 2718 | ||
| 1749 | int ath10k_wmi_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid, const u8 *bssid) | 2719 | int ath10k_wmi_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid, const u8 *bssid) |
| @@ -1758,13 +2728,13 @@ int ath10k_wmi_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid, const u8 *bssid) | |||
| 1758 | cmd = (struct wmi_vdev_up_cmd *)skb->data; | 2728 | cmd = (struct wmi_vdev_up_cmd *)skb->data; |
| 1759 | cmd->vdev_id = __cpu_to_le32(vdev_id); | 2729 | cmd->vdev_id = __cpu_to_le32(vdev_id); |
| 1760 | cmd->vdev_assoc_id = __cpu_to_le32(aid); | 2730 | cmd->vdev_assoc_id = __cpu_to_le32(aid); |
| 1761 | memcpy(&cmd->vdev_bssid.addr, bssid, 6); | 2731 | memcpy(&cmd->vdev_bssid.addr, bssid, ETH_ALEN); |
| 1762 | 2732 | ||
| 1763 | ath10k_dbg(ATH10K_DBG_WMI, | 2733 | ath10k_dbg(ATH10K_DBG_WMI, |
| 1764 | "wmi mgmt vdev up id 0x%x assoc id %d bssid %pM\n", | 2734 | "wmi mgmt vdev up id 0x%x assoc id %d bssid %pM\n", |
| 1765 | vdev_id, aid, bssid); | 2735 | vdev_id, aid, bssid); |
| 1766 | 2736 | ||
| 1767 | return ath10k_wmi_cmd_send(ar, skb, WMI_VDEV_UP_CMDID); | 2737 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_up_cmdid); |
| 1768 | } | 2738 | } |
| 1769 | 2739 | ||
| 1770 | int ath10k_wmi_vdev_down(struct ath10k *ar, u32 vdev_id) | 2740 | int ath10k_wmi_vdev_down(struct ath10k *ar, u32 vdev_id) |
| @@ -1782,15 +2752,22 @@ int ath10k_wmi_vdev_down(struct ath10k *ar, u32 vdev_id) | |||
| 1782 | ath10k_dbg(ATH10K_DBG_WMI, | 2752 | ath10k_dbg(ATH10K_DBG_WMI, |
| 1783 | "wmi mgmt vdev down id 0x%x\n", vdev_id); | 2753 | "wmi mgmt vdev down id 0x%x\n", vdev_id); |
| 1784 | 2754 | ||
| 1785 | return ath10k_wmi_cmd_send(ar, skb, WMI_VDEV_DOWN_CMDID); | 2755 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_down_cmdid); |
| 1786 | } | 2756 | } |
| 1787 | 2757 | ||
| 1788 | int ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id, | 2758 | int ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id, |
| 1789 | enum wmi_vdev_param param_id, u32 param_value) | 2759 | u32 param_id, u32 param_value) |
| 1790 | { | 2760 | { |
| 1791 | struct wmi_vdev_set_param_cmd *cmd; | 2761 | struct wmi_vdev_set_param_cmd *cmd; |
| 1792 | struct sk_buff *skb; | 2762 | struct sk_buff *skb; |
| 1793 | 2763 | ||
| 2764 | if (param_id == WMI_VDEV_PARAM_UNSUPPORTED) { | ||
| 2765 | ath10k_dbg(ATH10K_DBG_WMI, | ||
| 2766 | "vdev param %d not supported by firmware\n", | ||
| 2767 | param_id); | ||
| 2768 | return -EOPNOTSUPP; | ||
| 2769 | } | ||
| 2770 | |||
| 1794 | skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); | 2771 | skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); |
| 1795 | if (!skb) | 2772 | if (!skb) |
| 1796 | return -ENOMEM; | 2773 | return -ENOMEM; |
| @@ -1804,7 +2781,7 @@ int ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id, | |||
| 1804 | "wmi vdev id 0x%x set param %d value %d\n", | 2781 | "wmi vdev id 0x%x set param %d value %d\n", |
| 1805 | vdev_id, param_id, param_value); | 2782 | vdev_id, param_id, param_value); |
| 1806 | 2783 | ||
| 1807 | return ath10k_wmi_cmd_send(ar, skb, WMI_VDEV_SET_PARAM_CMDID); | 2784 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_set_param_cmdid); |
| 1808 | } | 2785 | } |
| 1809 | 2786 | ||
| 1810 | int ath10k_wmi_vdev_install_key(struct ath10k *ar, | 2787 | int ath10k_wmi_vdev_install_key(struct ath10k *ar, |
| @@ -1839,7 +2816,8 @@ int ath10k_wmi_vdev_install_key(struct ath10k *ar, | |||
| 1839 | ath10k_dbg(ATH10K_DBG_WMI, | 2816 | ath10k_dbg(ATH10K_DBG_WMI, |
| 1840 | "wmi vdev install key idx %d cipher %d len %d\n", | 2817 | "wmi vdev install key idx %d cipher %d len %d\n", |
| 1841 | arg->key_idx, arg->key_cipher, arg->key_len); | 2818 | arg->key_idx, arg->key_cipher, arg->key_len); |
| 1842 | return ath10k_wmi_cmd_send(ar, skb, WMI_VDEV_INSTALL_KEY_CMDID); | 2819 | return ath10k_wmi_cmd_send(ar, skb, |
| 2820 | ar->wmi.cmd->vdev_install_key_cmdid); | ||
| 1843 | } | 2821 | } |
| 1844 | 2822 | ||
| 1845 | int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id, | 2823 | int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id, |
| @@ -1859,7 +2837,7 @@ int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id, | |||
| 1859 | ath10k_dbg(ATH10K_DBG_WMI, | 2837 | ath10k_dbg(ATH10K_DBG_WMI, |
| 1860 | "wmi peer create vdev_id %d peer_addr %pM\n", | 2838 | "wmi peer create vdev_id %d peer_addr %pM\n", |
| 1861 | vdev_id, peer_addr); | 2839 | vdev_id, peer_addr); |
| 1862 | return ath10k_wmi_cmd_send(ar, skb, WMI_PEER_CREATE_CMDID); | 2840 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_create_cmdid); |
| 1863 | } | 2841 | } |
| 1864 | 2842 | ||
| 1865 | int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id, | 2843 | int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id, |
| @@ -1879,7 +2857,7 @@ int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id, | |||
| 1879 | ath10k_dbg(ATH10K_DBG_WMI, | 2857 | ath10k_dbg(ATH10K_DBG_WMI, |
| 1880 | "wmi peer delete vdev_id %d peer_addr %pM\n", | 2858 | "wmi peer delete vdev_id %d peer_addr %pM\n", |
| 1881 | vdev_id, peer_addr); | 2859 | vdev_id, peer_addr); |
| 1882 | return ath10k_wmi_cmd_send(ar, skb, WMI_PEER_DELETE_CMDID); | 2860 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_delete_cmdid); |
| 1883 | } | 2861 | } |
| 1884 | 2862 | ||
| 1885 | int ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id, | 2863 | int ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id, |
| @@ -1900,7 +2878,7 @@ int ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id, | |||
| 1900 | ath10k_dbg(ATH10K_DBG_WMI, | 2878 | ath10k_dbg(ATH10K_DBG_WMI, |
| 1901 | "wmi peer flush vdev_id %d peer_addr %pM tids %08x\n", | 2879 | "wmi peer flush vdev_id %d peer_addr %pM tids %08x\n", |
| 1902 | vdev_id, peer_addr, tid_bitmap); | 2880 | vdev_id, peer_addr, tid_bitmap); |
| 1903 | return ath10k_wmi_cmd_send(ar, skb, WMI_PEER_FLUSH_TIDS_CMDID); | 2881 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_flush_tids_cmdid); |
| 1904 | } | 2882 | } |
| 1905 | 2883 | ||
| 1906 | int ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id, | 2884 | int ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id, |
| @@ -1918,13 +2896,13 @@ int ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id, | |||
| 1918 | cmd->vdev_id = __cpu_to_le32(vdev_id); | 2896 | cmd->vdev_id = __cpu_to_le32(vdev_id); |
| 1919 | cmd->param_id = __cpu_to_le32(param_id); | 2897 | cmd->param_id = __cpu_to_le32(param_id); |
| 1920 | cmd->param_value = __cpu_to_le32(param_value); | 2898 | cmd->param_value = __cpu_to_le32(param_value); |
| 1921 | memcpy(&cmd->peer_macaddr.addr, peer_addr, 6); | 2899 | memcpy(&cmd->peer_macaddr.addr, peer_addr, ETH_ALEN); |
| 1922 | 2900 | ||
| 1923 | ath10k_dbg(ATH10K_DBG_WMI, | 2901 | ath10k_dbg(ATH10K_DBG_WMI, |
| 1924 | "wmi vdev %d peer 0x%pM set param %d value %d\n", | 2902 | "wmi vdev %d peer 0x%pM set param %d value %d\n", |
| 1925 | vdev_id, peer_addr, param_id, param_value); | 2903 | vdev_id, peer_addr, param_id, param_value); |
| 1926 | 2904 | ||
| 1927 | return ath10k_wmi_cmd_send(ar, skb, WMI_PEER_SET_PARAM_CMDID); | 2905 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_set_param_cmdid); |
| 1928 | } | 2906 | } |
| 1929 | 2907 | ||
| 1930 | int ath10k_wmi_set_psmode(struct ath10k *ar, u32 vdev_id, | 2908 | int ath10k_wmi_set_psmode(struct ath10k *ar, u32 vdev_id, |
| @@ -1945,7 +2923,8 @@ int ath10k_wmi_set_psmode(struct ath10k *ar, u32 vdev_id, | |||
| 1945 | "wmi set powersave id 0x%x mode %d\n", | 2923 | "wmi set powersave id 0x%x mode %d\n", |
| 1946 | vdev_id, psmode); | 2924 | vdev_id, psmode); |
| 1947 | 2925 | ||
| 1948 | return ath10k_wmi_cmd_send(ar, skb, WMI_STA_POWERSAVE_MODE_CMDID); | 2926 | return ath10k_wmi_cmd_send(ar, skb, |
| 2927 | ar->wmi.cmd->sta_powersave_mode_cmdid); | ||
| 1949 | } | 2928 | } |
| 1950 | 2929 | ||
| 1951 | int ath10k_wmi_set_sta_ps_param(struct ath10k *ar, u32 vdev_id, | 2930 | int ath10k_wmi_set_sta_ps_param(struct ath10k *ar, u32 vdev_id, |
| @@ -1967,7 +2946,8 @@ int ath10k_wmi_set_sta_ps_param(struct ath10k *ar, u32 vdev_id, | |||
| 1967 | ath10k_dbg(ATH10K_DBG_WMI, | 2946 | ath10k_dbg(ATH10K_DBG_WMI, |
| 1968 | "wmi sta ps param vdev_id 0x%x param %d value %d\n", | 2947 | "wmi sta ps param vdev_id 0x%x param %d value %d\n", |
| 1969 | vdev_id, param_id, value); | 2948 | vdev_id, param_id, value); |
| 1970 | return ath10k_wmi_cmd_send(ar, skb, WMI_STA_POWERSAVE_PARAM_CMDID); | 2949 | return ath10k_wmi_cmd_send(ar, skb, |
| 2950 | ar->wmi.cmd->sta_powersave_param_cmdid); | ||
| 1971 | } | 2951 | } |
| 1972 | 2952 | ||
| 1973 | int ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac, | 2953 | int ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac, |
| @@ -1993,7 +2973,8 @@ int ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac, | |||
| 1993 | "wmi ap ps param vdev_id 0x%X param %d value %d mac_addr %pM\n", | 2973 | "wmi ap ps param vdev_id 0x%X param %d value %d mac_addr %pM\n", |
| 1994 | vdev_id, param_id, value, mac); | 2974 | vdev_id, param_id, value, mac); |
| 1995 | 2975 | ||
| 1996 | return ath10k_wmi_cmd_send(ar, skb, WMI_AP_PS_PEER_PARAM_CMDID); | 2976 | return ath10k_wmi_cmd_send(ar, skb, |
| 2977 | ar->wmi.cmd->ap_ps_peer_param_cmdid); | ||
| 1997 | } | 2978 | } |
| 1998 | 2979 | ||
| 1999 | int ath10k_wmi_scan_chan_list(struct ath10k *ar, | 2980 | int ath10k_wmi_scan_chan_list(struct ath10k *ar, |
| @@ -2046,7 +3027,7 @@ int ath10k_wmi_scan_chan_list(struct ath10k *ar, | |||
| 2046 | ci->flags |= __cpu_to_le32(flags); | 3027 | ci->flags |= __cpu_to_le32(flags); |
| 2047 | } | 3028 | } |
| 2048 | 3029 | ||
| 2049 | return ath10k_wmi_cmd_send(ar, skb, WMI_SCAN_CHAN_LIST_CMDID); | 3030 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->scan_chan_list_cmdid); |
| 2050 | } | 3031 | } |
| 2051 | 3032 | ||
| 2052 | int ath10k_wmi_peer_assoc(struct ath10k *ar, | 3033 | int ath10k_wmi_peer_assoc(struct ath10k *ar, |
| @@ -2105,10 +3086,11 @@ int ath10k_wmi_peer_assoc(struct ath10k *ar, | |||
| 2105 | ath10k_dbg(ATH10K_DBG_WMI, | 3086 | ath10k_dbg(ATH10K_DBG_WMI, |
| 2106 | "wmi peer assoc vdev %d addr %pM\n", | 3087 | "wmi peer assoc vdev %d addr %pM\n", |
| 2107 | arg->vdev_id, arg->addr); | 3088 | arg->vdev_id, arg->addr); |
| 2108 | return ath10k_wmi_cmd_send(ar, skb, WMI_PEER_ASSOC_CMDID); | 3089 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_assoc_cmdid); |
| 2109 | } | 3090 | } |
| 2110 | 3091 | ||
| 2111 | int ath10k_wmi_beacon_send(struct ath10k *ar, const struct wmi_bcn_tx_arg *arg) | 3092 | int ath10k_wmi_beacon_send_nowait(struct ath10k *ar, |
| 3093 | const struct wmi_bcn_tx_arg *arg) | ||
| 2112 | { | 3094 | { |
| 2113 | struct wmi_bcn_tx_cmd *cmd; | 3095 | struct wmi_bcn_tx_cmd *cmd; |
| 2114 | struct sk_buff *skb; | 3096 | struct sk_buff *skb; |
| @@ -2124,7 +3106,7 @@ int ath10k_wmi_beacon_send(struct ath10k *ar, const struct wmi_bcn_tx_arg *arg) | |||
| 2124 | cmd->hdr.bcn_len = __cpu_to_le32(arg->bcn_len); | 3106 | cmd->hdr.bcn_len = __cpu_to_le32(arg->bcn_len); |
| 2125 | memcpy(cmd->bcn, arg->bcn, arg->bcn_len); | 3107 | memcpy(cmd->bcn, arg->bcn, arg->bcn_len); |
| 2126 | 3108 | ||
| 2127 | return ath10k_wmi_cmd_send(ar, skb, WMI_BCN_TX_CMDID); | 3109 | return ath10k_wmi_cmd_send_nowait(ar, skb, ar->wmi.cmd->bcn_tx_cmdid); |
| 2128 | } | 3110 | } |
| 2129 | 3111 | ||
| 2130 | static void ath10k_wmi_pdev_set_wmm_param(struct wmi_wmm_params *params, | 3112 | static void ath10k_wmi_pdev_set_wmm_param(struct wmi_wmm_params *params, |
| @@ -2155,7 +3137,8 @@ int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar, | |||
| 2155 | ath10k_wmi_pdev_set_wmm_param(&cmd->ac_vo, &arg->ac_vo); | 3137 | ath10k_wmi_pdev_set_wmm_param(&cmd->ac_vo, &arg->ac_vo); |
| 2156 | 3138 | ||
| 2157 | ath10k_dbg(ATH10K_DBG_WMI, "wmi pdev set wmm params\n"); | 3139 | ath10k_dbg(ATH10K_DBG_WMI, "wmi pdev set wmm params\n"); |
| 2158 | return ath10k_wmi_cmd_send(ar, skb, WMI_PDEV_SET_WMM_PARAMS_CMDID); | 3140 | return ath10k_wmi_cmd_send(ar, skb, |
| 3141 | ar->wmi.cmd->pdev_set_wmm_params_cmdid); | ||
| 2159 | } | 3142 | } |
| 2160 | 3143 | ||
| 2161 | int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id) | 3144 | int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id) |
| @@ -2171,7 +3154,7 @@ int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id) | |||
| 2171 | cmd->stats_id = __cpu_to_le32(stats_id); | 3154 | cmd->stats_id = __cpu_to_le32(stats_id); |
| 2172 | 3155 | ||
| 2173 | ath10k_dbg(ATH10K_DBG_WMI, "wmi request stats %d\n", (int)stats_id); | 3156 | ath10k_dbg(ATH10K_DBG_WMI, "wmi request stats %d\n", (int)stats_id); |
| 2174 | return ath10k_wmi_cmd_send(ar, skb, WMI_REQUEST_STATS_CMDID); | 3157 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->request_stats_cmdid); |
| 2175 | } | 3158 | } |
| 2176 | 3159 | ||
| 2177 | int ath10k_wmi_force_fw_hang(struct ath10k *ar, | 3160 | int ath10k_wmi_force_fw_hang(struct ath10k *ar, |
| @@ -2190,5 +3173,5 @@ int ath10k_wmi_force_fw_hang(struct ath10k *ar, | |||
| 2190 | 3173 | ||
| 2191 | ath10k_dbg(ATH10K_DBG_WMI, "wmi force fw hang %d delay %d\n", | 3174 | ath10k_dbg(ATH10K_DBG_WMI, "wmi force fw hang %d delay %d\n", |
| 2192 | type, delay_ms); | 3175 | type, delay_ms); |
| 2193 | return ath10k_wmi_cmd_send(ar, skb, WMI_FORCE_FW_HANG_CMDID); | 3176 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->force_fw_hang_cmdid); |
| 2194 | } | 3177 | } |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 2c5a4f8daf2e..78c991aec7f9 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h | |||
| @@ -208,6 +208,118 @@ struct wmi_mac_addr { | |||
| 208 | (c_macaddr)[5] = (((pwmi_mac_addr)->word1) >> 8) & 0xff; \ | 208 | (c_macaddr)[5] = (((pwmi_mac_addr)->word1) >> 8) & 0xff; \ |
| 209 | } while (0) | 209 | } while (0) |
| 210 | 210 | ||
| 211 | struct wmi_cmd_map { | ||
| 212 | u32 init_cmdid; | ||
| 213 | u32 start_scan_cmdid; | ||
| 214 | u32 stop_scan_cmdid; | ||
| 215 | u32 scan_chan_list_cmdid; | ||
| 216 | u32 scan_sch_prio_tbl_cmdid; | ||
| 217 | u32 pdev_set_regdomain_cmdid; | ||
| 218 | u32 pdev_set_channel_cmdid; | ||
| 219 | u32 pdev_set_param_cmdid; | ||
| 220 | u32 pdev_pktlog_enable_cmdid; | ||
| 221 | u32 pdev_pktlog_disable_cmdid; | ||
| 222 | u32 pdev_set_wmm_params_cmdid; | ||
| 223 | u32 pdev_set_ht_cap_ie_cmdid; | ||
| 224 | u32 pdev_set_vht_cap_ie_cmdid; | ||
| 225 | u32 pdev_set_dscp_tid_map_cmdid; | ||
| 226 | u32 pdev_set_quiet_mode_cmdid; | ||
| 227 | u32 pdev_green_ap_ps_enable_cmdid; | ||
| 228 | u32 pdev_get_tpc_config_cmdid; | ||
| 229 | u32 pdev_set_base_macaddr_cmdid; | ||
| 230 | u32 vdev_create_cmdid; | ||
| 231 | u32 vdev_delete_cmdid; | ||
| 232 | u32 vdev_start_request_cmdid; | ||
| 233 | u32 vdev_restart_request_cmdid; | ||
| 234 | u32 vdev_up_cmdid; | ||
| 235 | u32 vdev_stop_cmdid; | ||
| 236 | u32 vdev_down_cmdid; | ||
| 237 | u32 vdev_set_param_cmdid; | ||
| 238 | u32 vdev_install_key_cmdid; | ||
| 239 | u32 peer_create_cmdid; | ||
| 240 | u32 peer_delete_cmdid; | ||
| 241 | u32 peer_flush_tids_cmdid; | ||
| 242 | u32 peer_set_param_cmdid; | ||
| 243 | u32 peer_assoc_cmdid; | ||
| 244 | u32 peer_add_wds_entry_cmdid; | ||
| 245 | u32 peer_remove_wds_entry_cmdid; | ||
| 246 | u32 peer_mcast_group_cmdid; | ||
| 247 | u32 bcn_tx_cmdid; | ||
| 248 | u32 pdev_send_bcn_cmdid; | ||
| 249 | u32 bcn_tmpl_cmdid; | ||
| 250 | u32 bcn_filter_rx_cmdid; | ||
| 251 | u32 prb_req_filter_rx_cmdid; | ||
| 252 | u32 mgmt_tx_cmdid; | ||
| 253 | u32 prb_tmpl_cmdid; | ||
| 254 | u32 addba_clear_resp_cmdid; | ||
| 255 | u32 addba_send_cmdid; | ||
| 256 | u32 addba_status_cmdid; | ||
| 257 | u32 delba_send_cmdid; | ||
| 258 | u32 addba_set_resp_cmdid; | ||
| 259 | u32 send_singleamsdu_cmdid; | ||
| 260 | u32 sta_powersave_mode_cmdid; | ||
| 261 | u32 sta_powersave_param_cmdid; | ||
| 262 | u32 sta_mimo_ps_mode_cmdid; | ||
| 263 | u32 pdev_dfs_enable_cmdid; | ||
| 264 | u32 pdev_dfs_disable_cmdid; | ||
| 265 | u32 roam_scan_mode; | ||
| 266 | u32 roam_scan_rssi_threshold; | ||
| 267 | u32 roam_scan_period; | ||
| 268 | u32 roam_scan_rssi_change_threshold; | ||
| 269 | u32 roam_ap_profile; | ||
| 270 | u32 ofl_scan_add_ap_profile; | ||
| 271 | u32 ofl_scan_remove_ap_profile; | ||
| 272 | u32 ofl_scan_period; | ||
| 273 | u32 p2p_dev_set_device_info; | ||
| 274 | u32 p2p_dev_set_discoverability; | ||
| 275 | u32 p2p_go_set_beacon_ie; | ||
| 276 | u32 p2p_go_set_probe_resp_ie; | ||
| 277 | u32 p2p_set_vendor_ie_data_cmdid; | ||
| 278 | u32 ap_ps_peer_param_cmdid; | ||
| 279 | u32 ap_ps_peer_uapsd_coex_cmdid; | ||
| 280 | u32 peer_rate_retry_sched_cmdid; | ||
| 281 | u32 wlan_profile_trigger_cmdid; | ||
| 282 | u32 wlan_profile_set_hist_intvl_cmdid; | ||
| 283 | u32 wlan_profile_get_profile_data_cmdid; | ||
| 284 | u32 wlan_profile_enable_profile_id_cmdid; | ||
| 285 | u32 wlan_profile_list_profile_id_cmdid; | ||
| 286 | u32 pdev_suspend_cmdid; | ||
| 287 | u32 pdev_resume_cmdid; | ||
| 288 | u32 add_bcn_filter_cmdid; | ||
| 289 | u32 rmv_bcn_filter_cmdid; | ||
| 290 | u32 wow_add_wake_pattern_cmdid; | ||
| 291 | u32 wow_del_wake_pattern_cmdid; | ||
| 292 | u32 wow_enable_disable_wake_event_cmdid; | ||
| 293 | u32 wow_enable_cmdid; | ||
| 294 | u32 wow_hostwakeup_from_sleep_cmdid; | ||
| 295 | u32 rtt_measreq_cmdid; | ||
| 296 | u32 rtt_tsf_cmdid; | ||
| 297 | u32 vdev_spectral_scan_configure_cmdid; | ||
| 298 | u32 vdev_spectral_scan_enable_cmdid; | ||
| 299 | u32 request_stats_cmdid; | ||
| 300 | u32 set_arp_ns_offload_cmdid; | ||
| 301 | u32 network_list_offload_config_cmdid; | ||
| 302 | u32 gtk_offload_cmdid; | ||
| 303 | u32 csa_offload_enable_cmdid; | ||
| 304 | u32 csa_offload_chanswitch_cmdid; | ||
| 305 | u32 chatter_set_mode_cmdid; | ||
| 306 | u32 peer_tid_addba_cmdid; | ||
| 307 | u32 peer_tid_delba_cmdid; | ||
| 308 | u32 sta_dtim_ps_method_cmdid; | ||
| 309 | u32 sta_uapsd_auto_trig_cmdid; | ||
| 310 | u32 sta_keepalive_cmd; | ||
| 311 | u32 echo_cmdid; | ||
| 312 | u32 pdev_utf_cmdid; | ||
| 313 | u32 dbglog_cfg_cmdid; | ||
| 314 | u32 pdev_qvit_cmdid; | ||
| 315 | u32 pdev_ftm_intg_cmdid; | ||
| 316 | u32 vdev_set_keepalive_cmdid; | ||
| 317 | u32 vdev_get_keepalive_cmdid; | ||
| 318 | u32 force_fw_hang_cmdid; | ||
| 319 | u32 gpio_config_cmdid; | ||
| 320 | u32 gpio_output_cmdid; | ||
| 321 | }; | ||
| 322 | |||
| 211 | /* | 323 | /* |
| 212 | * wmi command groups. | 324 | * wmi command groups. |
| 213 | */ | 325 | */ |
| @@ -247,7 +359,9 @@ enum wmi_cmd_group { | |||
| 247 | #define WMI_CMD_GRP(grp_id) (((grp_id) << 12) | 0x1) | 359 | #define WMI_CMD_GRP(grp_id) (((grp_id) << 12) | 0x1) |
| 248 | #define WMI_EVT_GRP_START_ID(grp_id) (((grp_id) << 12) | 0x1) | 360 | #define WMI_EVT_GRP_START_ID(grp_id) (((grp_id) << 12) | 0x1) |
| 249 | 361 | ||
| 250 | /* Command IDs and commande events. */ | 362 | #define WMI_CMD_UNSUPPORTED 0 |
| 363 | |||
| 364 | /* Command IDs and command events for MAIN FW. */ | ||
| 251 | enum wmi_cmd_id { | 365 | enum wmi_cmd_id { |
| 252 | WMI_INIT_CMDID = 0x1, | 366 | WMI_INIT_CMDID = 0x1, |
| 253 | 367 | ||
| @@ -488,6 +602,217 @@ enum wmi_event_id { | |||
| 488 | WMI_GPIO_INPUT_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_GPIO), | 602 | WMI_GPIO_INPUT_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_GPIO), |
| 489 | }; | 603 | }; |
| 490 | 604 | ||
| 605 | /* Command IDs and command events for 10.X firmware */ | ||
| 606 | enum wmi_10x_cmd_id { | ||
| 607 | WMI_10X_START_CMDID = 0x9000, | ||
| 608 | WMI_10X_END_CMDID = 0x9FFF, | ||
| 609 | |||
| 610 | /* initialize the wlan sub system */ | ||
| 611 | WMI_10X_INIT_CMDID, | ||
| 612 | |||
| 613 | /* Scan specific commands */ | ||
| 614 | |||
| 615 | WMI_10X_START_SCAN_CMDID = WMI_10X_START_CMDID, | ||
| 616 | WMI_10X_STOP_SCAN_CMDID, | ||
| 617 | WMI_10X_SCAN_CHAN_LIST_CMDID, | ||
| 618 | WMI_10X_ECHO_CMDID, | ||
| 619 | |||
| 620 | /* PDEV(physical device) specific commands */ | ||
| 621 | WMI_10X_PDEV_SET_REGDOMAIN_CMDID, | ||
| 622 | WMI_10X_PDEV_SET_CHANNEL_CMDID, | ||
| 623 | WMI_10X_PDEV_SET_PARAM_CMDID, | ||
| 624 | WMI_10X_PDEV_PKTLOG_ENABLE_CMDID, | ||
| 625 | WMI_10X_PDEV_PKTLOG_DISABLE_CMDID, | ||
| 626 | WMI_10X_PDEV_SET_WMM_PARAMS_CMDID, | ||
| 627 | WMI_10X_PDEV_SET_HT_CAP_IE_CMDID, | ||
| 628 | WMI_10X_PDEV_SET_VHT_CAP_IE_CMDID, | ||
| 629 | WMI_10X_PDEV_SET_BASE_MACADDR_CMDID, | ||
| 630 | WMI_10X_PDEV_SET_DSCP_TID_MAP_CMDID, | ||
| 631 | WMI_10X_PDEV_SET_QUIET_MODE_CMDID, | ||
| 632 | WMI_10X_PDEV_GREEN_AP_PS_ENABLE_CMDID, | ||
| 633 | WMI_10X_PDEV_GET_TPC_CONFIG_CMDID, | ||
| 634 | |||
| 635 | /* VDEV(virtual device) specific commands */ | ||
| 636 | WMI_10X_VDEV_CREATE_CMDID, | ||
| 637 | WMI_10X_VDEV_DELETE_CMDID, | ||
| 638 | WMI_10X_VDEV_START_REQUEST_CMDID, | ||
| 639 | WMI_10X_VDEV_RESTART_REQUEST_CMDID, | ||
| 640 | WMI_10X_VDEV_UP_CMDID, | ||
| 641 | WMI_10X_VDEV_STOP_CMDID, | ||
| 642 | WMI_10X_VDEV_DOWN_CMDID, | ||
| 643 | WMI_10X_VDEV_STANDBY_RESPONSE_CMDID, | ||
| 644 | WMI_10X_VDEV_RESUME_RESPONSE_CMDID, | ||
| 645 | WMI_10X_VDEV_SET_PARAM_CMDID, | ||
| 646 | WMI_10X_VDEV_INSTALL_KEY_CMDID, | ||
| 647 | |||
| 648 | /* peer specific commands */ | ||
| 649 | WMI_10X_PEER_CREATE_CMDID, | ||
| 650 | WMI_10X_PEER_DELETE_CMDID, | ||
| 651 | WMI_10X_PEER_FLUSH_TIDS_CMDID, | ||
| 652 | WMI_10X_PEER_SET_PARAM_CMDID, | ||
| 653 | WMI_10X_PEER_ASSOC_CMDID, | ||
| 654 | WMI_10X_PEER_ADD_WDS_ENTRY_CMDID, | ||
| 655 | WMI_10X_PEER_REMOVE_WDS_ENTRY_CMDID, | ||
| 656 | WMI_10X_PEER_MCAST_GROUP_CMDID, | ||
| 657 | |||
| 658 | /* beacon/management specific commands */ | ||
| 659 | |||
| 660 | WMI_10X_BCN_TX_CMDID, | ||
| 661 | WMI_10X_BCN_PRB_TMPL_CMDID, | ||
| 662 | WMI_10X_BCN_FILTER_RX_CMDID, | ||
| 663 | WMI_10X_PRB_REQ_FILTER_RX_CMDID, | ||
| 664 | WMI_10X_MGMT_TX_CMDID, | ||
| 665 | |||
| 666 | /* commands to directly control ba negotiation directly from host. */ | ||
| 667 | WMI_10X_ADDBA_CLEAR_RESP_CMDID, | ||
| 668 | WMI_10X_ADDBA_SEND_CMDID, | ||
| 669 | WMI_10X_ADDBA_STATUS_CMDID, | ||
| 670 | WMI_10X_DELBA_SEND_CMDID, | ||
| 671 | WMI_10X_ADDBA_SET_RESP_CMDID, | ||
| 672 | WMI_10X_SEND_SINGLEAMSDU_CMDID, | ||
| 673 | |||
| 674 | /* Station power save specific config */ | ||
| 675 | WMI_10X_STA_POWERSAVE_MODE_CMDID, | ||
| 676 | WMI_10X_STA_POWERSAVE_PARAM_CMDID, | ||
| 677 | WMI_10X_STA_MIMO_PS_MODE_CMDID, | ||
| 678 | |||
| 679 | /* set debug log config */ | ||
| 680 | WMI_10X_DBGLOG_CFG_CMDID, | ||
| 681 | |||
| 682 | /* DFS-specific commands */ | ||
| 683 | WMI_10X_PDEV_DFS_ENABLE_CMDID, | ||
| 684 | WMI_10X_PDEV_DFS_DISABLE_CMDID, | ||
| 685 | |||
| 686 | /* QVIT specific command id */ | ||
| 687 | WMI_10X_PDEV_QVIT_CMDID, | ||
| 688 | |||
| 689 | /* Offload Scan and Roaming related commands */ | ||
| 690 | WMI_10X_ROAM_SCAN_MODE, | ||
| 691 | WMI_10X_ROAM_SCAN_RSSI_THRESHOLD, | ||
| 692 | WMI_10X_ROAM_SCAN_PERIOD, | ||
| 693 | WMI_10X_ROAM_SCAN_RSSI_CHANGE_THRESHOLD, | ||
| 694 | WMI_10X_ROAM_AP_PROFILE, | ||
| 695 | WMI_10X_OFL_SCAN_ADD_AP_PROFILE, | ||
| 696 | WMI_10X_OFL_SCAN_REMOVE_AP_PROFILE, | ||
| 697 | WMI_10X_OFL_SCAN_PERIOD, | ||
| 698 | |||
| 699 | /* P2P specific commands */ | ||
| 700 | WMI_10X_P2P_DEV_SET_DEVICE_INFO, | ||
| 701 | WMI_10X_P2P_DEV_SET_DISCOVERABILITY, | ||
| 702 | WMI_10X_P2P_GO_SET_BEACON_IE, | ||
| 703 | WMI_10X_P2P_GO_SET_PROBE_RESP_IE, | ||
| 704 | |||
| 705 | /* AP power save specific config */ | ||
| 706 | WMI_10X_AP_PS_PEER_PARAM_CMDID, | ||
| 707 | WMI_10X_AP_PS_PEER_UAPSD_COEX_CMDID, | ||
| 708 | |||
| 709 | /* Rate-control specific commands */ | ||
| 710 | WMI_10X_PEER_RATE_RETRY_SCHED_CMDID, | ||
| 711 | |||
| 712 | /* WLAN Profiling commands. */ | ||
| 713 | WMI_10X_WLAN_PROFILE_TRIGGER_CMDID, | ||
| 714 | WMI_10X_WLAN_PROFILE_SET_HIST_INTVL_CMDID, | ||
| 715 | WMI_10X_WLAN_PROFILE_GET_PROFILE_DATA_CMDID, | ||
| 716 | WMI_10X_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID, | ||
| 717 | WMI_10X_WLAN_PROFILE_LIST_PROFILE_ID_CMDID, | ||
| 718 | |||
| 719 | /* Suspend resume command Ids */ | ||
| 720 | WMI_10X_PDEV_SUSPEND_CMDID, | ||
| 721 | WMI_10X_PDEV_RESUME_CMDID, | ||
| 722 | |||
| 723 | /* Beacon filter commands */ | ||
| 724 | WMI_10X_ADD_BCN_FILTER_CMDID, | ||
| 725 | WMI_10X_RMV_BCN_FILTER_CMDID, | ||
| 726 | |||
| 727 | /* WOW Specific WMI commands*/ | ||
| 728 | WMI_10X_WOW_ADD_WAKE_PATTERN_CMDID, | ||
| 729 | WMI_10X_WOW_DEL_WAKE_PATTERN_CMDID, | ||
| 730 | WMI_10X_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID, | ||
| 731 | WMI_10X_WOW_ENABLE_CMDID, | ||
| 732 | WMI_10X_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID, | ||
| 733 | |||
| 734 | /* RTT measurement related cmd */ | ||
| 735 | WMI_10X_RTT_MEASREQ_CMDID, | ||
| 736 | WMI_10X_RTT_TSF_CMDID, | ||
| 737 | |||
| 738 | /* transmit beacon by value */ | ||
| 739 | WMI_10X_PDEV_SEND_BCN_CMDID, | ||
| 740 | |||
| 741 | /* F/W stats */ | ||
| 742 | WMI_10X_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID, | ||
| 743 | WMI_10X_VDEV_SPECTRAL_SCAN_ENABLE_CMDID, | ||
| 744 | WMI_10X_REQUEST_STATS_CMDID, | ||
| 745 | |||
| 746 | /* GPIO Configuration */ | ||
| 747 | WMI_10X_GPIO_CONFIG_CMDID, | ||
| 748 | WMI_10X_GPIO_OUTPUT_CMDID, | ||
| 749 | |||
| 750 | WMI_10X_PDEV_UTF_CMDID = WMI_10X_END_CMDID - 1, | ||
| 751 | }; | ||
| 752 | |||
| 753 | enum wmi_10x_event_id { | ||
| 754 | WMI_10X_SERVICE_READY_EVENTID = 0x8000, | ||
| 755 | WMI_10X_READY_EVENTID, | ||
| 756 | WMI_10X_START_EVENTID = 0x9000, | ||
| 757 | WMI_10X_END_EVENTID = 0x9FFF, | ||
| 758 | |||
| 759 | /* Scan specific events */ | ||
| 760 | WMI_10X_SCAN_EVENTID = WMI_10X_START_EVENTID, | ||
| 761 | WMI_10X_ECHO_EVENTID, | ||
| 762 | WMI_10X_DEBUG_MESG_EVENTID, | ||
| 763 | WMI_10X_UPDATE_STATS_EVENTID, | ||
| 764 | |||
| 765 | /* Instantaneous RSSI event */ | ||
| 766 | WMI_10X_INST_RSSI_STATS_EVENTID, | ||
| 767 | |||
| 768 | /* VDEV specific events */ | ||
| 769 | WMI_10X_VDEV_START_RESP_EVENTID, | ||
| 770 | WMI_10X_VDEV_STANDBY_REQ_EVENTID, | ||
| 771 | WMI_10X_VDEV_RESUME_REQ_EVENTID, | ||
| 772 | WMI_10X_VDEV_STOPPED_EVENTID, | ||
| 773 | |||
| 774 | /* peer specific events */ | ||
| 775 | WMI_10X_PEER_STA_KICKOUT_EVENTID, | ||
| 776 | |||
| 777 | /* beacon/mgmt specific events */ | ||
| 778 | WMI_10X_HOST_SWBA_EVENTID, | ||
| 779 | WMI_10X_TBTTOFFSET_UPDATE_EVENTID, | ||
| 780 | WMI_10X_MGMT_RX_EVENTID, | ||
| 781 | |||
| 782 | /* Channel stats event */ | ||
| 783 | WMI_10X_CHAN_INFO_EVENTID, | ||
| 784 | |||
| 785 | /* PHY Error specific WMI event */ | ||
| 786 | WMI_10X_PHYERR_EVENTID, | ||
| 787 | |||
| 788 | /* Roam event to trigger roaming on host */ | ||
| 789 | WMI_10X_ROAM_EVENTID, | ||
| 790 | |||
| 791 | /* matching AP found from list of profiles */ | ||
| 792 | WMI_10X_PROFILE_MATCH, | ||
| 793 | |||
| 794 | /* debug print message used for tracing FW code while debugging */ | ||
| 795 | WMI_10X_DEBUG_PRINT_EVENTID, | ||
| 796 | /* VI spoecific event */ | ||
| 797 | WMI_10X_PDEV_QVIT_EVENTID, | ||
| 798 | /* FW code profile data in response to profile request */ | ||
| 799 | WMI_10X_WLAN_PROFILE_DATA_EVENTID, | ||
| 800 | |||
| 801 | /*RTT related event ID*/ | ||
| 802 | WMI_10X_RTT_MEASUREMENT_REPORT_EVENTID, | ||
| 803 | WMI_10X_TSF_MEASUREMENT_REPORT_EVENTID, | ||
| 804 | WMI_10X_RTT_ERROR_REPORT_EVENTID, | ||
| 805 | |||
| 806 | WMI_10X_WOW_WAKEUP_HOST_EVENTID, | ||
| 807 | WMI_10X_DCS_INTERFERENCE_EVENTID, | ||
| 808 | |||
| 809 | /* TPC config for the current operating channel */ | ||
| 810 | WMI_10X_PDEV_TPC_CONFIG_EVENTID, | ||
| 811 | |||
| 812 | WMI_10X_GPIO_INPUT_EVENTID, | ||
| 813 | WMI_10X_PDEV_UTF_EVENTID = WMI_10X_END_EVENTID-1, | ||
| 814 | }; | ||
| 815 | |||
| 491 | enum wmi_phy_mode { | 816 | enum wmi_phy_mode { |
| 492 | MODE_11A = 0, /* 11a Mode */ | 817 | MODE_11A = 0, /* 11a Mode */ |
| 493 | MODE_11G = 1, /* 11b/g Mode */ | 818 | MODE_11G = 1, /* 11b/g Mode */ |
| @@ -508,6 +833,48 @@ enum wmi_phy_mode { | |||
| 508 | MODE_MAX = 14 | 833 | MODE_MAX = 14 |
| 509 | }; | 834 | }; |
| 510 | 835 | ||
| 836 | static inline const char *ath10k_wmi_phymode_str(enum wmi_phy_mode mode) | ||
| 837 | { | ||
| 838 | switch (mode) { | ||
| 839 | case MODE_11A: | ||
| 840 | return "11a"; | ||
| 841 | case MODE_11G: | ||
| 842 | return "11g"; | ||
| 843 | case MODE_11B: | ||
| 844 | return "11b"; | ||
| 845 | case MODE_11GONLY: | ||
| 846 | return "11gonly"; | ||
| 847 | case MODE_11NA_HT20: | ||
| 848 | return "11na-ht20"; | ||
| 849 | case MODE_11NG_HT20: | ||
| 850 | return "11ng-ht20"; | ||
| 851 | case MODE_11NA_HT40: | ||
| 852 | return "11na-ht40"; | ||
| 853 | case MODE_11NG_HT40: | ||
| 854 | return "11ng-ht40"; | ||
| 855 | case MODE_11AC_VHT20: | ||
| 856 | return "11ac-vht20"; | ||
| 857 | case MODE_11AC_VHT40: | ||
| 858 | return "11ac-vht40"; | ||
| 859 | case MODE_11AC_VHT80: | ||
| 860 | return "11ac-vht80"; | ||
| 861 | case MODE_11AC_VHT20_2G: | ||
| 862 | return "11ac-vht20-2g"; | ||
| 863 | case MODE_11AC_VHT40_2G: | ||
| 864 | return "11ac-vht40-2g"; | ||
| 865 | case MODE_11AC_VHT80_2G: | ||
| 866 | return "11ac-vht80-2g"; | ||
| 867 | case MODE_UNKNOWN: | ||
| 868 | /* skip */ | ||
| 869 | break; | ||
| 870 | |||
| 871 | /* no default handler to allow compiler to check that the | ||
| 872 | * enum is fully handled */ | ||
| 873 | }; | ||
| 874 | |||
| 875 | return "<unknown>"; | ||
| 876 | } | ||
| 877 | |||
| 511 | #define WMI_CHAN_LIST_TAG 0x1 | 878 | #define WMI_CHAN_LIST_TAG 0x1 |
| 512 | #define WMI_SSID_LIST_TAG 0x2 | 879 | #define WMI_SSID_LIST_TAG 0x2 |
| 513 | #define WMI_BSSID_LIST_TAG 0x3 | 880 | #define WMI_BSSID_LIST_TAG 0x3 |
| @@ -763,13 +1130,45 @@ struct wmi_service_ready_event { | |||
| 763 | struct wlan_host_mem_req mem_reqs[1]; | 1130 | struct wlan_host_mem_req mem_reqs[1]; |
| 764 | } __packed; | 1131 | } __packed; |
| 765 | 1132 | ||
| 766 | /* | 1133 | /* This is the definition from 10.X firmware branch */ |
| 767 | * status consists of upper 16 bits fo int status and lower 16 bits of | 1134 | struct wmi_service_ready_event_10x { |
| 768 | * module ID that retuned status | 1135 | __le32 sw_version; |
| 769 | */ | 1136 | __le32 abi_version; |
| 770 | #define WLAN_INIT_STATUS_SUCCESS 0x0 | 1137 | |
| 771 | #define WLAN_GET_INIT_STATUS_REASON(status) ((status) & 0xffff) | 1138 | /* WMI_PHY_CAPABILITY */ |
| 772 | #define WLAN_GET_INIT_STATUS_MODULE_ID(status) (((status) >> 16) & 0xffff) | 1139 | __le32 phy_capability; |
| 1140 | |||
| 1141 | /* Maximum number of frag table entries that SW will populate less 1 */ | ||
| 1142 | __le32 max_frag_entry; | ||
| 1143 | __le32 wmi_service_bitmap[WMI_SERVICE_BM_SIZE]; | ||
| 1144 | __le32 num_rf_chains; | ||
| 1145 | |||
| 1146 | /* | ||
| 1147 | * The following field is only valid for service type | ||
| 1148 | * WMI_SERVICE_11AC | ||
| 1149 | */ | ||
| 1150 | __le32 ht_cap_info; /* WMI HT Capability */ | ||
| 1151 | __le32 vht_cap_info; /* VHT capability info field of 802.11ac */ | ||
| 1152 | __le32 vht_supp_mcs; /* VHT Supported MCS Set field Rx/Tx same */ | ||
| 1153 | __le32 hw_min_tx_power; | ||
| 1154 | __le32 hw_max_tx_power; | ||
| 1155 | |||
| 1156 | struct hal_reg_capabilities hal_reg_capabilities; | ||
| 1157 | |||
| 1158 | __le32 sys_cap_info; | ||
| 1159 | __le32 min_pkt_size_enable; /* Enterprise mode short pkt enable */ | ||
| 1160 | |||
| 1161 | /* | ||
| 1162 | * request to host to allocate a chuck of memory and pss it down to FW | ||
| 1163 | * via WM_INIT. FW uses this as FW extesnsion memory for saving its | ||
| 1164 | * data structures. Only valid for low latency interfaces like PCIE | ||
| 1165 | * where FW can access this memory directly (or) by DMA. | ||
| 1166 | */ | ||
| 1167 | __le32 num_mem_reqs; | ||
| 1168 | |||
| 1169 | struct wlan_host_mem_req mem_reqs[1]; | ||
| 1170 | } __packed; | ||
| 1171 | |||
| 773 | 1172 | ||
| 774 | #define WMI_SERVICE_READY_TIMEOUT_HZ (5*HZ) | 1173 | #define WMI_SERVICE_READY_TIMEOUT_HZ (5*HZ) |
| 775 | #define WMI_UNIFIED_READY_TIMEOUT_HZ (5*HZ) | 1174 | #define WMI_UNIFIED_READY_TIMEOUT_HZ (5*HZ) |
| @@ -978,6 +1377,192 @@ struct wmi_resource_config { | |||
| 978 | __le32 max_frag_entries; | 1377 | __le32 max_frag_entries; |
| 979 | } __packed; | 1378 | } __packed; |
| 980 | 1379 | ||
| 1380 | struct wmi_resource_config_10x { | ||
| 1381 | /* number of virtual devices (VAPs) to support */ | ||
| 1382 | __le32 num_vdevs; | ||
| 1383 | |||
| 1384 | /* number of peer nodes to support */ | ||
| 1385 | __le32 num_peers; | ||
| 1386 | |||
| 1387 | /* number of keys per peer */ | ||
| 1388 | __le32 num_peer_keys; | ||
| 1389 | |||
| 1390 | /* total number of TX/RX data TIDs */ | ||
| 1391 | __le32 num_tids; | ||
| 1392 | |||
| 1393 | /* | ||
| 1394 | * max skid for resolving hash collisions | ||
| 1395 | * | ||
| 1396 | * The address search table is sparse, so that if two MAC addresses | ||
| 1397 | * result in the same hash value, the second of these conflicting | ||
| 1398 | * entries can slide to the next index in the address search table, | ||
| 1399 | * and use it, if it is unoccupied. This ast_skid_limit parameter | ||
| 1400 | * specifies the upper bound on how many subsequent indices to search | ||
| 1401 | * over to find an unoccupied space. | ||
| 1402 | */ | ||
| 1403 | __le32 ast_skid_limit; | ||
| 1404 | |||
| 1405 | /* | ||
| 1406 | * the nominal chain mask for transmit | ||
| 1407 | * | ||
| 1408 | * The chain mask may be modified dynamically, e.g. to operate AP | ||
| 1409 | * tx with a reduced number of chains if no clients are associated. | ||
| 1410 | * This configuration parameter specifies the nominal chain-mask that | ||
| 1411 | * should be used when not operating with a reduced set of tx chains. | ||
| 1412 | */ | ||
| 1413 | __le32 tx_chain_mask; | ||
| 1414 | |||
| 1415 | /* | ||
| 1416 | * the nominal chain mask for receive | ||
| 1417 | * | ||
| 1418 | * The chain mask may be modified dynamically, e.g. for a client | ||
| 1419 | * to use a reduced number of chains for receive if the traffic to | ||
| 1420 | * the client is low enough that it doesn't require downlink MIMO | ||
| 1421 | * or antenna diversity. | ||
| 1422 | * This configuration parameter specifies the nominal chain-mask that | ||
| 1423 | * should be used when not operating with a reduced set of rx chains. | ||
| 1424 | */ | ||
| 1425 | __le32 rx_chain_mask; | ||
| 1426 | |||
| 1427 | /* | ||
| 1428 | * what rx reorder timeout (ms) to use for the AC | ||
| 1429 | * | ||
| 1430 | * Each WMM access class (voice, video, best-effort, background) will | ||
| 1431 | * have its own timeout value to dictate how long to wait for missing | ||
| 1432 | * rx MPDUs to arrive before flushing subsequent MPDUs that have | ||
| 1433 | * already been received. | ||
| 1434 | * This parameter specifies the timeout in milliseconds for each | ||
| 1435 | * class. | ||
| 1436 | */ | ||
| 1437 | __le32 rx_timeout_pri_vi; | ||
| 1438 | __le32 rx_timeout_pri_vo; | ||
| 1439 | __le32 rx_timeout_pri_be; | ||
| 1440 | __le32 rx_timeout_pri_bk; | ||
| 1441 | |||
| 1442 | /* | ||
| 1443 | * what mode the rx should decap packets to | ||
| 1444 | * | ||
| 1445 | * MAC can decap to RAW (no decap), native wifi or Ethernet types | ||
| 1446 | * THis setting also determines the default TX behavior, however TX | ||
| 1447 | * behavior can be modified on a per VAP basis during VAP init | ||
| 1448 | */ | ||
| 1449 | __le32 rx_decap_mode; | ||
| 1450 | |||
| 1451 | /* what is the maximum scan requests than can be queued */ | ||
| 1452 | __le32 scan_max_pending_reqs; | ||
| 1453 | |||
| 1454 | /* maximum VDEV that could use BMISS offload */ | ||
| 1455 | __le32 bmiss_offload_max_vdev; | ||
| 1456 | |||
| 1457 | /* maximum VDEV that could use offload roaming */ | ||
| 1458 | __le32 roam_offload_max_vdev; | ||
| 1459 | |||
| 1460 | /* maximum AP profiles that would push to offload roaming */ | ||
| 1461 | __le32 roam_offload_max_ap_profiles; | ||
| 1462 | |||
| 1463 | /* | ||
| 1464 | * how many groups to use for mcast->ucast conversion | ||
| 1465 | * | ||
| 1466 | * The target's WAL maintains a table to hold information regarding | ||
| 1467 | * which peers belong to a given multicast group, so that if | ||
| 1468 | * multicast->unicast conversion is enabled, the target can convert | ||
| 1469 | * multicast tx frames to a series of unicast tx frames, to each | ||
| 1470 | * peer within the multicast group. | ||
| 1471 | This num_mcast_groups configuration parameter tells the target how | ||
| 1472 | * many multicast groups to provide storage for within its multicast | ||
| 1473 | * group membership table. | ||
| 1474 | */ | ||
| 1475 | __le32 num_mcast_groups; | ||
| 1476 | |||
| 1477 | /* | ||
| 1478 | * size to alloc for the mcast membership table | ||
| 1479 | * | ||
| 1480 | * This num_mcast_table_elems configuration parameter tells the | ||
| 1481 | * target how many peer elements it needs to provide storage for in | ||
| 1482 | * its multicast group membership table. | ||
| 1483 | * These multicast group membership table elements are shared by the | ||
| 1484 | * multicast groups stored within the table. | ||
| 1485 | */ | ||
| 1486 | __le32 num_mcast_table_elems; | ||
| 1487 | |||
| 1488 | /* | ||
| 1489 | * whether/how to do multicast->unicast conversion | ||
| 1490 | * | ||
| 1491 | * This configuration parameter specifies whether the target should | ||
| 1492 | * perform multicast --> unicast conversion on transmit, and if so, | ||
| 1493 | * what to do if it finds no entries in its multicast group | ||
| 1494 | * membership table for the multicast IP address in the tx frame. | ||
| 1495 | * Configuration value: | ||
| 1496 | * 0 -> Do not perform multicast to unicast conversion. | ||
| 1497 | * 1 -> Convert multicast frames to unicast, if the IP multicast | ||
| 1498 | * address from the tx frame is found in the multicast group | ||
| 1499 | * membership table. If the IP multicast address is not found, | ||
| 1500 | * drop the frame. | ||
| 1501 | * 2 -> Convert multicast frames to unicast, if the IP multicast | ||
| 1502 | * address from the tx frame is found in the multicast group | ||
| 1503 | * membership table. If the IP multicast address is not found, | ||
| 1504 | * transmit the frame as multicast. | ||
| 1505 | */ | ||
| 1506 | __le32 mcast2ucast_mode; | ||
| 1507 | |||
| 1508 | /* | ||
| 1509 | * how much memory to allocate for a tx PPDU dbg log | ||
| 1510 | * | ||
| 1511 | * This parameter controls how much memory the target will allocate | ||
| 1512 | * to store a log of tx PPDU meta-information (how large the PPDU | ||
| 1513 | * was, when it was sent, whether it was successful, etc.) | ||
| 1514 | */ | ||
| 1515 | __le32 tx_dbg_log_size; | ||
| 1516 | |||
| 1517 | /* how many AST entries to be allocated for WDS */ | ||
| 1518 | __le32 num_wds_entries; | ||
| 1519 | |||
| 1520 | /* | ||
| 1521 | * MAC DMA burst size, e.g., For target PCI limit can be | ||
| 1522 | * 0 -default, 1 256B | ||
| 1523 | */ | ||
| 1524 | __le32 dma_burst_size; | ||
| 1525 | |||
| 1526 | /* | ||
| 1527 | * Fixed delimiters to be inserted after every MPDU to | ||
| 1528 | * account for interface latency to avoid underrun. | ||
| 1529 | */ | ||
| 1530 | __le32 mac_aggr_delim; | ||
| 1531 | |||
| 1532 | /* | ||
| 1533 | * determine whether target is responsible for detecting duplicate | ||
| 1534 | * non-aggregate MPDU and timing out stale fragments. | ||
| 1535 | * | ||
| 1536 | * A-MPDU reordering is always performed on the target. | ||
| 1537 | * | ||
| 1538 | * 0: target responsible for frag timeout and dup checking | ||
| 1539 | * 1: host responsible for frag timeout and dup checking | ||
| 1540 | */ | ||
| 1541 | __le32 rx_skip_defrag_timeout_dup_detection_check; | ||
| 1542 | |||
| 1543 | /* | ||
| 1544 | * Configuration for VoW : | ||
| 1545 | * No of Video Nodes to be supported | ||
| 1546 | * and Max no of descriptors for each Video link (node). | ||
| 1547 | */ | ||
| 1548 | __le32 vow_config; | ||
| 1549 | |||
| 1550 | /* Number of msdu descriptors target should use */ | ||
| 1551 | __le32 num_msdu_desc; | ||
| 1552 | |||
| 1553 | /* | ||
| 1554 | * Max. number of Tx fragments per MSDU | ||
| 1555 | * This parameter controls the max number of Tx fragments per MSDU. | ||
| 1556 | * This is sent by the target as part of the WMI_SERVICE_READY event | ||
| 1557 | * and is overriden by the OS shim as required. | ||
| 1558 | */ | ||
| 1559 | __le32 max_frag_entries; | ||
| 1560 | } __packed; | ||
| 1561 | |||
| 1562 | |||
| 1563 | #define NUM_UNITS_IS_NUM_VDEVS 0x1 | ||
| 1564 | #define NUM_UNITS_IS_NUM_PEERS 0x2 | ||
| 1565 | |||
| 981 | /* strucutre describing host memory chunk. */ | 1566 | /* strucutre describing host memory chunk. */ |
| 982 | struct host_memory_chunk { | 1567 | struct host_memory_chunk { |
| 983 | /* id of the request that is passed up in service ready */ | 1568 | /* id of the request that is passed up in service ready */ |
| @@ -999,6 +1584,18 @@ struct wmi_init_cmd { | |||
| 999 | struct host_memory_chunk host_mem_chunks[1]; | 1584 | struct host_memory_chunk host_mem_chunks[1]; |
| 1000 | } __packed; | 1585 | } __packed; |
| 1001 | 1586 | ||
| 1587 | /* _10x stucture is from 10.X FW API */ | ||
| 1588 | struct wmi_init_cmd_10x { | ||
| 1589 | struct wmi_resource_config_10x resource_config; | ||
| 1590 | __le32 num_host_mem_chunks; | ||
| 1591 | |||
| 1592 | /* | ||
| 1593 | * variable number of host memory chunks. | ||
| 1594 | * This should be the last element in the structure | ||
| 1595 | */ | ||
| 1596 | struct host_memory_chunk host_mem_chunks[1]; | ||
| 1597 | } __packed; | ||
| 1598 | |||
| 1002 | /* TLV for channel list */ | 1599 | /* TLV for channel list */ |
| 1003 | struct wmi_chan_list { | 1600 | struct wmi_chan_list { |
| 1004 | __le32 tag; /* WMI_CHAN_LIST_TAG */ | 1601 | __le32 tag; /* WMI_CHAN_LIST_TAG */ |
| @@ -1118,6 +1715,88 @@ struct wmi_start_scan_cmd { | |||
| 1118 | */ | 1715 | */ |
| 1119 | } __packed; | 1716 | } __packed; |
| 1120 | 1717 | ||
| 1718 | /* This is the definition from 10.X firmware branch */ | ||
| 1719 | struct wmi_start_scan_cmd_10x { | ||
| 1720 | /* Scan ID */ | ||
| 1721 | __le32 scan_id; | ||
| 1722 | |||
| 1723 | /* Scan requestor ID */ | ||
| 1724 | __le32 scan_req_id; | ||
| 1725 | |||
| 1726 | /* VDEV id(interface) that is requesting scan */ | ||
| 1727 | __le32 vdev_id; | ||
| 1728 | |||
| 1729 | /* Scan Priority, input to scan scheduler */ | ||
| 1730 | __le32 scan_priority; | ||
| 1731 | |||
| 1732 | /* Scan events subscription */ | ||
| 1733 | __le32 notify_scan_events; | ||
| 1734 | |||
| 1735 | /* dwell time in msec on active channels */ | ||
| 1736 | __le32 dwell_time_active; | ||
| 1737 | |||
| 1738 | /* dwell time in msec on passive channels */ | ||
| 1739 | __le32 dwell_time_passive; | ||
| 1740 | |||
| 1741 | /* | ||
| 1742 | * min time in msec on the BSS channel,only valid if atleast one | ||
| 1743 | * VDEV is active | ||
| 1744 | */ | ||
| 1745 | __le32 min_rest_time; | ||
| 1746 | |||
| 1747 | /* | ||
| 1748 | * max rest time in msec on the BSS channel,only valid if at least | ||
| 1749 | * one VDEV is active | ||
| 1750 | */ | ||
| 1751 | /* | ||
| 1752 | * the scanner will rest on the bss channel at least min_rest_time | ||
| 1753 | * after min_rest_time the scanner will start checking for tx/rx | ||
| 1754 | * activity on all VDEVs. if there is no activity the scanner will | ||
| 1755 | * switch to off channel. if there is activity the scanner will let | ||
| 1756 | * the radio on the bss channel until max_rest_time expires.at | ||
| 1757 | * max_rest_time scanner will switch to off channel irrespective of | ||
| 1758 | * activity. activity is determined by the idle_time parameter. | ||
| 1759 | */ | ||
| 1760 | __le32 max_rest_time; | ||
| 1761 | |||
| 1762 | /* | ||
| 1763 | * time before sending next set of probe requests. | ||
| 1764 | * The scanner keeps repeating probe requests transmission with | ||
| 1765 | * period specified by repeat_probe_time. | ||
| 1766 | * The number of probe requests specified depends on the ssid_list | ||
| 1767 | * and bssid_list | ||
| 1768 | */ | ||
| 1769 | __le32 repeat_probe_time; | ||
| 1770 | |||
| 1771 | /* time in msec between 2 consequetive probe requests with in a set. */ | ||
| 1772 | __le32 probe_spacing_time; | ||
| 1773 | |||
| 1774 | /* | ||
| 1775 | * data inactivity time in msec on bss channel that will be used by | ||
| 1776 | * scanner for measuring the inactivity. | ||
| 1777 | */ | ||
| 1778 | __le32 idle_time; | ||
| 1779 | |||
| 1780 | /* maximum time in msec allowed for scan */ | ||
| 1781 | __le32 max_scan_time; | ||
| 1782 | |||
| 1783 | /* | ||
| 1784 | * delay in msec before sending first probe request after switching | ||
| 1785 | * to a channel | ||
| 1786 | */ | ||
| 1787 | __le32 probe_delay; | ||
| 1788 | |||
| 1789 | /* Scan control flags */ | ||
| 1790 | __le32 scan_ctrl_flags; | ||
| 1791 | |||
| 1792 | /* | ||
| 1793 | * TLV (tag length value ) paramerters follow the scan_cmd structure. | ||
| 1794 | * TLV can contain channel list, bssid list, ssid list and | ||
| 1795 | * ie. the TLV tags are defined above; | ||
| 1796 | */ | ||
| 1797 | } __packed; | ||
| 1798 | |||
| 1799 | |||
| 1121 | struct wmi_ssid_arg { | 1800 | struct wmi_ssid_arg { |
| 1122 | int len; | 1801 | int len; |
| 1123 | const u8 *ssid; | 1802 | const u8 *ssid; |
| @@ -1268,7 +1947,7 @@ struct wmi_scan_event { | |||
| 1268 | * good idea to pass all the fields in the RX status | 1947 | * good idea to pass all the fields in the RX status |
| 1269 | * descriptor up to the host. | 1948 | * descriptor up to the host. |
| 1270 | */ | 1949 | */ |
| 1271 | struct wmi_mgmt_rx_hdr { | 1950 | struct wmi_mgmt_rx_hdr_v1 { |
| 1272 | __le32 channel; | 1951 | __le32 channel; |
| 1273 | __le32 snr; | 1952 | __le32 snr; |
| 1274 | __le32 rate; | 1953 | __le32 rate; |
| @@ -1277,8 +1956,18 @@ struct wmi_mgmt_rx_hdr { | |||
| 1277 | __le32 status; /* %WMI_RX_STATUS_ */ | 1956 | __le32 status; /* %WMI_RX_STATUS_ */ |
| 1278 | } __packed; | 1957 | } __packed; |
| 1279 | 1958 | ||
| 1280 | struct wmi_mgmt_rx_event { | 1959 | struct wmi_mgmt_rx_hdr_v2 { |
| 1281 | struct wmi_mgmt_rx_hdr hdr; | 1960 | struct wmi_mgmt_rx_hdr_v1 v1; |
| 1961 | __le32 rssi_ctl[4]; | ||
| 1962 | } __packed; | ||
| 1963 | |||
| 1964 | struct wmi_mgmt_rx_event_v1 { | ||
| 1965 | struct wmi_mgmt_rx_hdr_v1 hdr; | ||
| 1966 | u8 buf[0]; | ||
| 1967 | } __packed; | ||
| 1968 | |||
| 1969 | struct wmi_mgmt_rx_event_v2 { | ||
| 1970 | struct wmi_mgmt_rx_hdr_v2 hdr; | ||
| 1282 | u8 buf[0]; | 1971 | u8 buf[0]; |
| 1283 | } __packed; | 1972 | } __packed; |
| 1284 | 1973 | ||
| @@ -1465,6 +2154,60 @@ struct wmi_csa_event { | |||
| 1465 | #define VDEV_DEFAULT_STATS_UPDATE_PERIOD 500 | 2154 | #define VDEV_DEFAULT_STATS_UPDATE_PERIOD 500 |
| 1466 | #define PEER_DEFAULT_STATS_UPDATE_PERIOD 500 | 2155 | #define PEER_DEFAULT_STATS_UPDATE_PERIOD 500 |
| 1467 | 2156 | ||
| 2157 | struct wmi_pdev_param_map { | ||
| 2158 | u32 tx_chain_mask; | ||
| 2159 | u32 rx_chain_mask; | ||
| 2160 | u32 txpower_limit2g; | ||
| 2161 | u32 txpower_limit5g; | ||
| 2162 | u32 txpower_scale; | ||
| 2163 | u32 beacon_gen_mode; | ||
| 2164 | u32 beacon_tx_mode; | ||
| 2165 | u32 resmgr_offchan_mode; | ||
| 2166 | u32 protection_mode; | ||
| 2167 | u32 dynamic_bw; | ||
| 2168 | u32 non_agg_sw_retry_th; | ||
| 2169 | u32 agg_sw_retry_th; | ||
| 2170 | u32 sta_kickout_th; | ||
| 2171 | u32 ac_aggrsize_scaling; | ||
| 2172 | u32 ltr_enable; | ||
| 2173 | u32 ltr_ac_latency_be; | ||
| 2174 | u32 ltr_ac_latency_bk; | ||
| 2175 | u32 ltr_ac_latency_vi; | ||
| 2176 | u32 ltr_ac_latency_vo; | ||
| 2177 | u32 ltr_ac_latency_timeout; | ||
| 2178 | u32 ltr_sleep_override; | ||
| 2179 | u32 ltr_rx_override; | ||
| 2180 | u32 ltr_tx_activity_timeout; | ||
| 2181 | u32 l1ss_enable; | ||
| 2182 | u32 dsleep_enable; | ||
| 2183 | u32 pcielp_txbuf_flush; | ||
| 2184 | u32 pcielp_txbuf_watermark; | ||
| 2185 | u32 pcielp_txbuf_tmo_en; | ||
| 2186 | u32 pcielp_txbuf_tmo_value; | ||
| 2187 | u32 pdev_stats_update_period; | ||
| 2188 | u32 vdev_stats_update_period; | ||
| 2189 | u32 peer_stats_update_period; | ||
| 2190 | u32 bcnflt_stats_update_period; | ||
| 2191 | u32 pmf_qos; | ||
| 2192 | u32 arp_ac_override; | ||
| 2193 | u32 arpdhcp_ac_override; | ||
| 2194 | u32 dcs; | ||
| 2195 | u32 ani_enable; | ||
| 2196 | u32 ani_poll_period; | ||
| 2197 | u32 ani_listen_period; | ||
| 2198 | u32 ani_ofdm_level; | ||
| 2199 | u32 ani_cck_level; | ||
| 2200 | u32 dyntxchain; | ||
| 2201 | u32 proxy_sta; | ||
| 2202 | u32 idle_ps_config; | ||
| 2203 | u32 power_gating_sleep; | ||
| 2204 | u32 fast_channel_reset; | ||
| 2205 | u32 burst_dur; | ||
| 2206 | u32 burst_enable; | ||
| 2207 | }; | ||
| 2208 | |||
| 2209 | #define WMI_PDEV_PARAM_UNSUPPORTED 0 | ||
| 2210 | |||
| 1468 | enum wmi_pdev_param { | 2211 | enum wmi_pdev_param { |
| 1469 | /* TX chian mask */ | 2212 | /* TX chian mask */ |
| 1470 | WMI_PDEV_PARAM_TX_CHAIN_MASK = 0x1, | 2213 | WMI_PDEV_PARAM_TX_CHAIN_MASK = 0x1, |
| @@ -1564,6 +2307,97 @@ enum wmi_pdev_param { | |||
| 1564 | WMI_PDEV_PARAM_POWER_GATING_SLEEP, | 2307 | WMI_PDEV_PARAM_POWER_GATING_SLEEP, |
| 1565 | }; | 2308 | }; |
| 1566 | 2309 | ||
| 2310 | enum wmi_10x_pdev_param { | ||
| 2311 | /* TX chian mask */ | ||
| 2312 | WMI_10X_PDEV_PARAM_TX_CHAIN_MASK = 0x1, | ||
| 2313 | /* RX chian mask */ | ||
| 2314 | WMI_10X_PDEV_PARAM_RX_CHAIN_MASK, | ||
| 2315 | /* TX power limit for 2G Radio */ | ||
| 2316 | WMI_10X_PDEV_PARAM_TXPOWER_LIMIT2G, | ||
| 2317 | /* TX power limit for 5G Radio */ | ||
| 2318 | WMI_10X_PDEV_PARAM_TXPOWER_LIMIT5G, | ||
| 2319 | /* TX power scale */ | ||
| 2320 | WMI_10X_PDEV_PARAM_TXPOWER_SCALE, | ||
| 2321 | /* Beacon generation mode . 0: host, 1: target */ | ||
| 2322 | WMI_10X_PDEV_PARAM_BEACON_GEN_MODE, | ||
| 2323 | /* Beacon generation mode . 0: staggered 1: bursted */ | ||
| 2324 | WMI_10X_PDEV_PARAM_BEACON_TX_MODE, | ||
| 2325 | /* | ||
| 2326 | * Resource manager off chan mode . | ||
| 2327 | * 0: turn off off chan mode. 1: turn on offchan mode | ||
| 2328 | */ | ||
| 2329 | WMI_10X_PDEV_PARAM_RESMGR_OFFCHAN_MODE, | ||
| 2330 | /* | ||
| 2331 | * Protection mode: | ||
| 2332 | * 0: no protection 1:use CTS-to-self 2: use RTS/CTS | ||
| 2333 | */ | ||
| 2334 | WMI_10X_PDEV_PARAM_PROTECTION_MODE, | ||
| 2335 | /* Dynamic bandwidth 0: disable 1: enable */ | ||
| 2336 | WMI_10X_PDEV_PARAM_DYNAMIC_BW, | ||
| 2337 | /* Non aggregrate/ 11g sw retry threshold.0-disable */ | ||
| 2338 | WMI_10X_PDEV_PARAM_NON_AGG_SW_RETRY_TH, | ||
| 2339 | /* aggregrate sw retry threshold. 0-disable*/ | ||
| 2340 | WMI_10X_PDEV_PARAM_AGG_SW_RETRY_TH, | ||
| 2341 | /* Station kickout threshold (non of consecutive failures).0-disable */ | ||
| 2342 | WMI_10X_PDEV_PARAM_STA_KICKOUT_TH, | ||
| 2343 | /* Aggerate size scaling configuration per AC */ | ||
| 2344 | WMI_10X_PDEV_PARAM_AC_AGGRSIZE_SCALING, | ||
| 2345 | /* LTR enable */ | ||
| 2346 | WMI_10X_PDEV_PARAM_LTR_ENABLE, | ||
| 2347 | /* LTR latency for BE, in us */ | ||
| 2348 | WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_BE, | ||
| 2349 | /* LTR latency for BK, in us */ | ||
| 2350 | WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_BK, | ||
| 2351 | /* LTR latency for VI, in us */ | ||
| 2352 | WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_VI, | ||
| 2353 | /* LTR latency for VO, in us */ | ||
| 2354 | WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_VO, | ||
| 2355 | /* LTR AC latency timeout, in ms */ | ||
| 2356 | WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT, | ||
| 2357 | /* LTR platform latency override, in us */ | ||
| 2358 | WMI_10X_PDEV_PARAM_LTR_SLEEP_OVERRIDE, | ||
| 2359 | /* LTR-RX override, in us */ | ||
| 2360 | WMI_10X_PDEV_PARAM_LTR_RX_OVERRIDE, | ||
| 2361 | /* Tx activity timeout for LTR, in us */ | ||
| 2362 | WMI_10X_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT, | ||
| 2363 | /* L1SS state machine enable */ | ||
| 2364 | WMI_10X_PDEV_PARAM_L1SS_ENABLE, | ||
| 2365 | /* Deep sleep state machine enable */ | ||
| 2366 | WMI_10X_PDEV_PARAM_DSLEEP_ENABLE, | ||
| 2367 | /* pdev level stats update period in ms */ | ||
| 2368 | WMI_10X_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD, | ||
| 2369 | /* vdev level stats update period in ms */ | ||
| 2370 | WMI_10X_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD, | ||
| 2371 | /* peer level stats update period in ms */ | ||
| 2372 | WMI_10X_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD, | ||
| 2373 | /* beacon filter status update period */ | ||
| 2374 | WMI_10X_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD, | ||
| 2375 | /* QOS Mgmt frame protection MFP/PMF 0: disable, 1: enable */ | ||
| 2376 | WMI_10X_PDEV_PARAM_PMF_QOS, | ||
| 2377 | /* Access category on which ARP and DHCP frames are sent */ | ||
| 2378 | WMI_10X_PDEV_PARAM_ARPDHCP_AC_OVERRIDE, | ||
| 2379 | /* DCS configuration */ | ||
| 2380 | WMI_10X_PDEV_PARAM_DCS, | ||
| 2381 | /* Enable/Disable ANI on target */ | ||
| 2382 | WMI_10X_PDEV_PARAM_ANI_ENABLE, | ||
| 2383 | /* configure the ANI polling period */ | ||
| 2384 | WMI_10X_PDEV_PARAM_ANI_POLL_PERIOD, | ||
| 2385 | /* configure the ANI listening period */ | ||
| 2386 | WMI_10X_PDEV_PARAM_ANI_LISTEN_PERIOD, | ||
| 2387 | /* configure OFDM immunity level */ | ||
| 2388 | WMI_10X_PDEV_PARAM_ANI_OFDM_LEVEL, | ||
| 2389 | /* configure CCK immunity level */ | ||
| 2390 | WMI_10X_PDEV_PARAM_ANI_CCK_LEVEL, | ||
| 2391 | /* Enable/Disable CDD for 1x1 STAs in rate control module */ | ||
| 2392 | WMI_10X_PDEV_PARAM_DYNTXCHAIN, | ||
| 2393 | /* Enable/Disable Fast channel reset*/ | ||
| 2394 | WMI_10X_PDEV_PARAM_FAST_CHANNEL_RESET, | ||
| 2395 | /* Set Bursting DUR */ | ||
| 2396 | WMI_10X_PDEV_PARAM_BURST_DUR, | ||
| 2397 | /* Set Bursting Enable*/ | ||
| 2398 | WMI_10X_PDEV_PARAM_BURST_ENABLE, | ||
| 2399 | }; | ||
| 2400 | |||
| 1567 | struct wmi_pdev_set_param_cmd { | 2401 | struct wmi_pdev_set_param_cmd { |
| 1568 | __le32 param_id; | 2402 | __le32 param_id; |
| 1569 | __le32 param_value; | 2403 | __le32 param_value; |
| @@ -2088,6 +2922,61 @@ enum wmi_rate_preamble { | |||
| 2088 | /* Value to disable fixed rate setting */ | 2922 | /* Value to disable fixed rate setting */ |
| 2089 | #define WMI_FIXED_RATE_NONE (0xff) | 2923 | #define WMI_FIXED_RATE_NONE (0xff) |
| 2090 | 2924 | ||
| 2925 | struct wmi_vdev_param_map { | ||
| 2926 | u32 rts_threshold; | ||
| 2927 | u32 fragmentation_threshold; | ||
| 2928 | u32 beacon_interval; | ||
| 2929 | u32 listen_interval; | ||
| 2930 | u32 multicast_rate; | ||
| 2931 | u32 mgmt_tx_rate; | ||
| 2932 | u32 slot_time; | ||
| 2933 | u32 preamble; | ||
| 2934 | u32 swba_time; | ||
| 2935 | u32 wmi_vdev_stats_update_period; | ||
| 2936 | u32 wmi_vdev_pwrsave_ageout_time; | ||
| 2937 | u32 wmi_vdev_host_swba_interval; | ||
| 2938 | u32 dtim_period; | ||
| 2939 | u32 wmi_vdev_oc_scheduler_air_time_limit; | ||
| 2940 | u32 wds; | ||
| 2941 | u32 atim_window; | ||
| 2942 | u32 bmiss_count_max; | ||
| 2943 | u32 bmiss_first_bcnt; | ||
| 2944 | u32 bmiss_final_bcnt; | ||
| 2945 | u32 feature_wmm; | ||
| 2946 | u32 chwidth; | ||
| 2947 | u32 chextoffset; | ||
| 2948 | u32 disable_htprotection; | ||
| 2949 | u32 sta_quickkickout; | ||
| 2950 | u32 mgmt_rate; | ||
| 2951 | u32 protection_mode; | ||
| 2952 | u32 fixed_rate; | ||
| 2953 | u32 sgi; | ||
| 2954 | u32 ldpc; | ||
| 2955 | u32 tx_stbc; | ||
| 2956 | u32 rx_stbc; | ||
| 2957 | u32 intra_bss_fwd; | ||
| 2958 | u32 def_keyid; | ||
| 2959 | u32 nss; | ||
| 2960 | u32 bcast_data_rate; | ||
| 2961 | u32 mcast_data_rate; | ||
| 2962 | u32 mcast_indicate; | ||
| 2963 | u32 dhcp_indicate; | ||
| 2964 | u32 unknown_dest_indicate; | ||
| 2965 | u32 ap_keepalive_min_idle_inactive_time_secs; | ||
| 2966 | u32 ap_keepalive_max_idle_inactive_time_secs; | ||
| 2967 | u32 ap_keepalive_max_unresponsive_time_secs; | ||
| 2968 | u32 ap_enable_nawds; | ||
| 2969 | u32 mcast2ucast_set; | ||
| 2970 | u32 enable_rtscts; | ||
| 2971 | u32 txbf; | ||
| 2972 | u32 packet_powersave; | ||
| 2973 | u32 drop_unencry; | ||
| 2974 | u32 tx_encap_type; | ||
| 2975 | u32 ap_detect_out_of_sync_sleeping_sta_time_secs; | ||
| 2976 | }; | ||
| 2977 | |||
| 2978 | #define WMI_VDEV_PARAM_UNSUPPORTED 0 | ||
| 2979 | |||
| 2091 | /* the definition of different VDEV parameters */ | 2980 | /* the definition of different VDEV parameters */ |
| 2092 | enum wmi_vdev_param { | 2981 | enum wmi_vdev_param { |
| 2093 | /* RTS Threshold */ | 2982 | /* RTS Threshold */ |
| @@ -2219,6 +3108,121 @@ enum wmi_vdev_param { | |||
| 2219 | WMI_VDEV_PARAM_TX_ENCAP_TYPE, | 3108 | WMI_VDEV_PARAM_TX_ENCAP_TYPE, |
| 2220 | }; | 3109 | }; |
| 2221 | 3110 | ||
| 3111 | /* the definition of different VDEV parameters */ | ||
| 3112 | enum wmi_10x_vdev_param { | ||
| 3113 | /* RTS Threshold */ | ||
| 3114 | WMI_10X_VDEV_PARAM_RTS_THRESHOLD = 0x1, | ||
| 3115 | /* Fragmentation threshold */ | ||
| 3116 | WMI_10X_VDEV_PARAM_FRAGMENTATION_THRESHOLD, | ||
| 3117 | /* beacon interval in TUs */ | ||
| 3118 | WMI_10X_VDEV_PARAM_BEACON_INTERVAL, | ||
| 3119 | /* Listen interval in TUs */ | ||
| 3120 | WMI_10X_VDEV_PARAM_LISTEN_INTERVAL, | ||
| 3121 | /* muticast rate in Mbps */ | ||
| 3122 | WMI_10X_VDEV_PARAM_MULTICAST_RATE, | ||
| 3123 | /* management frame rate in Mbps */ | ||
| 3124 | WMI_10X_VDEV_PARAM_MGMT_TX_RATE, | ||
| 3125 | /* slot time (long vs short) */ | ||
| 3126 | WMI_10X_VDEV_PARAM_SLOT_TIME, | ||
| 3127 | /* preamble (long vs short) */ | ||
| 3128 | WMI_10X_VDEV_PARAM_PREAMBLE, | ||
| 3129 | /* SWBA time (time before tbtt in msec) */ | ||
| 3130 | WMI_10X_VDEV_PARAM_SWBA_TIME, | ||
| 3131 | /* time period for updating VDEV stats */ | ||
| 3132 | WMI_10X_VDEV_STATS_UPDATE_PERIOD, | ||
| 3133 | /* age out time in msec for frames queued for station in power save */ | ||
| 3134 | WMI_10X_VDEV_PWRSAVE_AGEOUT_TIME, | ||
| 3135 | /* | ||
| 3136 | * Host SWBA interval (time in msec before tbtt for SWBA event | ||
| 3137 | * generation). | ||
| 3138 | */ | ||
| 3139 | WMI_10X_VDEV_HOST_SWBA_INTERVAL, | ||
| 3140 | /* DTIM period (specified in units of num beacon intervals) */ | ||
| 3141 | WMI_10X_VDEV_PARAM_DTIM_PERIOD, | ||
| 3142 | /* | ||
| 3143 | * scheduler air time limit for this VDEV. used by off chan | ||
| 3144 | * scheduler. | ||
| 3145 | */ | ||
| 3146 | WMI_10X_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT, | ||
| 3147 | /* enable/dsiable WDS for this VDEV */ | ||
| 3148 | WMI_10X_VDEV_PARAM_WDS, | ||
| 3149 | /* ATIM Window */ | ||
| 3150 | WMI_10X_VDEV_PARAM_ATIM_WINDOW, | ||
| 3151 | /* BMISS max */ | ||
| 3152 | WMI_10X_VDEV_PARAM_BMISS_COUNT_MAX, | ||
| 3153 | /* WMM enables/disabled */ | ||
| 3154 | WMI_10X_VDEV_PARAM_FEATURE_WMM, | ||
| 3155 | /* Channel width */ | ||
| 3156 | WMI_10X_VDEV_PARAM_CHWIDTH, | ||
| 3157 | /* Channel Offset */ | ||
| 3158 | WMI_10X_VDEV_PARAM_CHEXTOFFSET, | ||
| 3159 | /* Disable HT Protection */ | ||
| 3160 | WMI_10X_VDEV_PARAM_DISABLE_HTPROTECTION, | ||
| 3161 | /* Quick STA Kickout */ | ||
| 3162 | WMI_10X_VDEV_PARAM_STA_QUICKKICKOUT, | ||
| 3163 | /* Rate to be used with Management frames */ | ||
| 3164 | WMI_10X_VDEV_PARAM_MGMT_RATE, | ||
| 3165 | /* Protection Mode */ | ||
| 3166 | WMI_10X_VDEV_PARAM_PROTECTION_MODE, | ||
| 3167 | /* Fixed rate setting */ | ||
| 3168 | WMI_10X_VDEV_PARAM_FIXED_RATE, | ||
| 3169 | /* Short GI Enable/Disable */ | ||
| 3170 | WMI_10X_VDEV_PARAM_SGI, | ||
| 3171 | /* Enable LDPC */ | ||
| 3172 | WMI_10X_VDEV_PARAM_LDPC, | ||
| 3173 | /* Enable Tx STBC */ | ||
| 3174 | WMI_10X_VDEV_PARAM_TX_STBC, | ||
| 3175 | /* Enable Rx STBC */ | ||
| 3176 | WMI_10X_VDEV_PARAM_RX_STBC, | ||
| 3177 | /* Intra BSS forwarding */ | ||
| 3178 | WMI_10X_VDEV_PARAM_INTRA_BSS_FWD, | ||
| 3179 | /* Setting Default xmit key for Vdev */ | ||
| 3180 | WMI_10X_VDEV_PARAM_DEF_KEYID, | ||
| 3181 | /* NSS width */ | ||
| 3182 | WMI_10X_VDEV_PARAM_NSS, | ||
| 3183 | /* Set the custom rate for the broadcast data frames */ | ||
| 3184 | WMI_10X_VDEV_PARAM_BCAST_DATA_RATE, | ||
| 3185 | /* Set the custom rate (rate-code) for multicast data frames */ | ||
| 3186 | WMI_10X_VDEV_PARAM_MCAST_DATA_RATE, | ||
| 3187 | /* Tx multicast packet indicate Enable/Disable */ | ||
| 3188 | WMI_10X_VDEV_PARAM_MCAST_INDICATE, | ||
| 3189 | /* Tx DHCP packet indicate Enable/Disable */ | ||
| 3190 | WMI_10X_VDEV_PARAM_DHCP_INDICATE, | ||
| 3191 | /* Enable host inspection of Tx unicast packet to unknown destination */ | ||
| 3192 | WMI_10X_VDEV_PARAM_UNKNOWN_DEST_INDICATE, | ||
| 3193 | |||
| 3194 | /* The minimum amount of time AP begins to consider STA inactive */ | ||
| 3195 | WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS, | ||
| 3196 | |||
| 3197 | /* | ||
| 3198 | * An associated STA is considered inactive when there is no recent | ||
| 3199 | * TX/RX activity and no downlink frames are buffered for it. Once a | ||
| 3200 | * STA exceeds the maximum idle inactive time, the AP will send an | ||
| 3201 | * 802.11 data-null as a keep alive to verify the STA is still | ||
| 3202 | * associated. If the STA does ACK the data-null, or if the data-null | ||
| 3203 | * is buffered and the STA does not retrieve it, the STA will be | ||
| 3204 | * considered unresponsive | ||
| 3205 | * (see WMI_10X_VDEV_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS). | ||
| 3206 | */ | ||
| 3207 | WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS, | ||
| 3208 | |||
| 3209 | /* | ||
| 3210 | * An associated STA is considered unresponsive if there is no recent | ||
| 3211 | * TX/RX activity and downlink frames are buffered for it. Once a STA | ||
| 3212 | * exceeds the maximum unresponsive time, the AP will send a | ||
| 3213 | * WMI_10X_STA_KICKOUT event to the host so the STA can be deleted. */ | ||
| 3214 | WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS, | ||
| 3215 | |||
| 3216 | /* Enable NAWDS : MCAST INSPECT Enable, NAWDS Flag set */ | ||
| 3217 | WMI_10X_VDEV_PARAM_AP_ENABLE_NAWDS, | ||
| 3218 | |||
| 3219 | WMI_10X_VDEV_PARAM_MCAST2UCAST_SET, | ||
| 3220 | /* Enable/Disable RTS-CTS */ | ||
| 3221 | WMI_10X_VDEV_PARAM_ENABLE_RTSCTS, | ||
| 3222 | |||
| 3223 | WMI_10X_VDEV_PARAM_AP_DETECT_OUT_OF_SYNC_SLEEPING_STA_TIME_SECS, | ||
| 3224 | }; | ||
| 3225 | |||
| 2222 | /* slot time long */ | 3226 | /* slot time long */ |
| 2223 | #define WMI_VDEV_SLOT_TIME_LONG 0x1 | 3227 | #define WMI_VDEV_SLOT_TIME_LONG 0x1 |
| 2224 | /* slot time short */ | 3228 | /* slot time short */ |
| @@ -3000,7 +4004,6 @@ struct wmi_force_fw_hang_cmd { | |||
| 3000 | 4004 | ||
| 3001 | #define WMI_MAX_EVENT 0x1000 | 4005 | #define WMI_MAX_EVENT 0x1000 |
| 3002 | /* Maximum number of pending TXed WMI packets */ | 4006 | /* Maximum number of pending TXed WMI packets */ |
| 3003 | #define WMI_MAX_PENDING_TX_COUNT 128 | ||
| 3004 | #define WMI_SKB_HEADROOM sizeof(struct wmi_cmd_hdr) | 4007 | #define WMI_SKB_HEADROOM sizeof(struct wmi_cmd_hdr) |
| 3005 | 4008 | ||
| 3006 | /* By default disable power save for IBSS */ | 4009 | /* By default disable power save for IBSS */ |
| @@ -3013,7 +4016,6 @@ int ath10k_wmi_attach(struct ath10k *ar); | |||
| 3013 | void ath10k_wmi_detach(struct ath10k *ar); | 4016 | void ath10k_wmi_detach(struct ath10k *ar); |
| 3014 | int ath10k_wmi_wait_for_service_ready(struct ath10k *ar); | 4017 | int ath10k_wmi_wait_for_service_ready(struct ath10k *ar); |
| 3015 | int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar); | 4018 | int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar); |
| 3016 | void ath10k_wmi_flush_tx(struct ath10k *ar); | ||
| 3017 | 4019 | ||
| 3018 | int ath10k_wmi_connect_htc_service(struct ath10k *ar); | 4020 | int ath10k_wmi_connect_htc_service(struct ath10k *ar); |
| 3019 | int ath10k_wmi_pdev_set_channel(struct ath10k *ar, | 4021 | int ath10k_wmi_pdev_set_channel(struct ath10k *ar, |
| @@ -3022,8 +4024,7 @@ int ath10k_wmi_pdev_suspend_target(struct ath10k *ar); | |||
| 3022 | int ath10k_wmi_pdev_resume_target(struct ath10k *ar); | 4024 | int ath10k_wmi_pdev_resume_target(struct ath10k *ar); |
| 3023 | int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g, | 4025 | int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g, |
| 3024 | u16 rd5g, u16 ctl2g, u16 ctl5g); | 4026 | u16 rd5g, u16 ctl2g, u16 ctl5g); |
| 3025 | int ath10k_wmi_pdev_set_param(struct ath10k *ar, enum wmi_pdev_param id, | 4027 | int ath10k_wmi_pdev_set_param(struct ath10k *ar, u32 id, u32 value); |
| 3026 | u32 value); | ||
| 3027 | int ath10k_wmi_cmd_init(struct ath10k *ar); | 4028 | int ath10k_wmi_cmd_init(struct ath10k *ar); |
| 3028 | int ath10k_wmi_start_scan(struct ath10k *ar, const struct wmi_start_scan_arg *); | 4029 | int ath10k_wmi_start_scan(struct ath10k *ar, const struct wmi_start_scan_arg *); |
| 3029 | void ath10k_wmi_start_scan_init(struct ath10k *ar, struct wmi_start_scan_arg *); | 4030 | void ath10k_wmi_start_scan_init(struct ath10k *ar, struct wmi_start_scan_arg *); |
| @@ -3043,7 +4044,7 @@ int ath10k_wmi_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid, | |||
| 3043 | const u8 *bssid); | 4044 | const u8 *bssid); |
| 3044 | int ath10k_wmi_vdev_down(struct ath10k *ar, u32 vdev_id); | 4045 | int ath10k_wmi_vdev_down(struct ath10k *ar, u32 vdev_id); |
| 3045 | int ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id, | 4046 | int ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id, |
| 3046 | enum wmi_vdev_param param_id, u32 param_value); | 4047 | u32 param_id, u32 param_value); |
| 3047 | int ath10k_wmi_vdev_install_key(struct ath10k *ar, | 4048 | int ath10k_wmi_vdev_install_key(struct ath10k *ar, |
| 3048 | const struct wmi_vdev_install_key_arg *arg); | 4049 | const struct wmi_vdev_install_key_arg *arg); |
| 3049 | int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id, | 4050 | int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id, |
| @@ -3066,11 +4067,13 @@ int ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac, | |||
| 3066 | enum wmi_ap_ps_peer_param param_id, u32 value); | 4067 | enum wmi_ap_ps_peer_param param_id, u32 value); |
| 3067 | int ath10k_wmi_scan_chan_list(struct ath10k *ar, | 4068 | int ath10k_wmi_scan_chan_list(struct ath10k *ar, |
| 3068 | const struct wmi_scan_chan_list_arg *arg); | 4069 | const struct wmi_scan_chan_list_arg *arg); |
| 3069 | int ath10k_wmi_beacon_send(struct ath10k *ar, const struct wmi_bcn_tx_arg *arg); | 4070 | int ath10k_wmi_beacon_send_nowait(struct ath10k *ar, |
| 4071 | const struct wmi_bcn_tx_arg *arg); | ||
| 3070 | int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar, | 4072 | int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar, |
| 3071 | const struct wmi_pdev_set_wmm_params_arg *arg); | 4073 | const struct wmi_pdev_set_wmm_params_arg *arg); |
| 3072 | int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id); | 4074 | int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id); |
| 3073 | int ath10k_wmi_force_fw_hang(struct ath10k *ar, | 4075 | int ath10k_wmi_force_fw_hang(struct ath10k *ar, |
| 3074 | enum wmi_force_fw_hang_type type, u32 delay_ms); | 4076 | enum wmi_force_fw_hang_type type, u32 delay_ms); |
| 4077 | int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb); | ||
| 3075 | 4078 | ||
| 3076 | #endif /* _WMI_H_ */ | 4079 | #endif /* _WMI_H_ */ |
diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c index e9bc9e616b69..79bffe165cab 100644 --- a/drivers/net/wireless/ath/ath5k/ahb.c +++ b/drivers/net/wireless/ath/ath5k/ahb.c | |||
| @@ -37,12 +37,9 @@ ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) | |||
| 37 | { | 37 | { |
| 38 | struct ath5k_hw *ah = common->priv; | 38 | struct ath5k_hw *ah = common->priv; |
| 39 | struct platform_device *pdev = to_platform_device(ah->dev); | 39 | struct platform_device *pdev = to_platform_device(ah->dev); |
| 40 | struct ar231x_board_config *bcfg = pdev->dev.platform_data; | 40 | struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev); |
| 41 | u16 *eeprom, *eeprom_end; | 41 | u16 *eeprom, *eeprom_end; |
| 42 | 42 | ||
| 43 | |||
| 44 | |||
| 45 | bcfg = pdev->dev.platform_data; | ||
| 46 | eeprom = (u16 *) bcfg->radio; | 43 | eeprom = (u16 *) bcfg->radio; |
| 47 | eeprom_end = ((void *) bcfg->config) + BOARD_CONFIG_BUFSZ; | 44 | eeprom_end = ((void *) bcfg->config) + BOARD_CONFIG_BUFSZ; |
| 48 | 45 | ||
| @@ -57,7 +54,7 @@ ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) | |||
| 57 | int ath5k_hw_read_srev(struct ath5k_hw *ah) | 54 | int ath5k_hw_read_srev(struct ath5k_hw *ah) |
| 58 | { | 55 | { |
| 59 | struct platform_device *pdev = to_platform_device(ah->dev); | 56 | struct platform_device *pdev = to_platform_device(ah->dev); |
| 60 | struct ar231x_board_config *bcfg = pdev->dev.platform_data; | 57 | struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev); |
| 61 | ah->ah_mac_srev = bcfg->devid; | 58 | ah->ah_mac_srev = bcfg->devid; |
| 62 | return 0; | 59 | return 0; |
| 63 | } | 60 | } |
| @@ -65,7 +62,7 @@ int ath5k_hw_read_srev(struct ath5k_hw *ah) | |||
| 65 | static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) | 62 | static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) |
| 66 | { | 63 | { |
| 67 | struct platform_device *pdev = to_platform_device(ah->dev); | 64 | struct platform_device *pdev = to_platform_device(ah->dev); |
| 68 | struct ar231x_board_config *bcfg = pdev->dev.platform_data; | 65 | struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev); |
| 69 | u8 *cfg_mac; | 66 | u8 *cfg_mac; |
| 70 | 67 | ||
| 71 | if (to_platform_device(ah->dev)->id == 0) | 68 | if (to_platform_device(ah->dev)->id == 0) |
| @@ -87,7 +84,7 @@ static const struct ath_bus_ops ath_ahb_bus_ops = { | |||
| 87 | /*Initialization*/ | 84 | /*Initialization*/ |
| 88 | static int ath_ahb_probe(struct platform_device *pdev) | 85 | static int ath_ahb_probe(struct platform_device *pdev) |
| 89 | { | 86 | { |
| 90 | struct ar231x_board_config *bcfg = pdev->dev.platform_data; | 87 | struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev); |
| 91 | struct ath5k_hw *ah; | 88 | struct ath5k_hw *ah; |
| 92 | struct ieee80211_hw *hw; | 89 | struct ieee80211_hw *hw; |
| 93 | struct resource *res; | 90 | struct resource *res; |
| @@ -96,7 +93,7 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
| 96 | int ret = 0; | 93 | int ret = 0; |
| 97 | u32 reg; | 94 | u32 reg; |
| 98 | 95 | ||
| 99 | if (!pdev->dev.platform_data) { | 96 | if (!dev_get_platdata(&pdev->dev)) { |
| 100 | dev_err(&pdev->dev, "no platform data specified\n"); | 97 | dev_err(&pdev->dev, "no platform data specified\n"); |
| 101 | ret = -EINVAL; | 98 | ret = -EINVAL; |
| 102 | goto err_out; | 99 | goto err_out; |
| @@ -193,7 +190,7 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
| 193 | 190 | ||
| 194 | static int ath_ahb_remove(struct platform_device *pdev) | 191 | static int ath_ahb_remove(struct platform_device *pdev) |
| 195 | { | 192 | { |
| 196 | struct ar231x_board_config *bcfg = pdev->dev.platform_data; | 193 | struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev); |
| 197 | struct ieee80211_hw *hw = platform_get_drvdata(pdev); | 194 | struct ieee80211_hw *hw = platform_get_drvdata(pdev); |
| 198 | struct ath5k_hw *ah; | 195 | struct ath5k_hw *ah; |
| 199 | u32 reg; | 196 | u32 reg; |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 48161edec8de..69f58b073e85 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
| @@ -1663,15 +1663,15 @@ ath5k_tx_frame_completed(struct ath5k_hw *ah, struct sk_buff *skb, | |||
| 1663 | ah->stats.tx_bytes_count += skb->len; | 1663 | ah->stats.tx_bytes_count += skb->len; |
| 1664 | info = IEEE80211_SKB_CB(skb); | 1664 | info = IEEE80211_SKB_CB(skb); |
| 1665 | 1665 | ||
| 1666 | size = min_t(int, sizeof(info->status.rates), sizeof(bf->rates)); | ||
| 1667 | memcpy(info->status.rates, bf->rates, size); | ||
| 1668 | |||
| 1666 | tries[0] = info->status.rates[0].count; | 1669 | tries[0] = info->status.rates[0].count; |
| 1667 | tries[1] = info->status.rates[1].count; | 1670 | tries[1] = info->status.rates[1].count; |
| 1668 | tries[2] = info->status.rates[2].count; | 1671 | tries[2] = info->status.rates[2].count; |
| 1669 | 1672 | ||
| 1670 | ieee80211_tx_info_clear_status(info); | 1673 | ieee80211_tx_info_clear_status(info); |
| 1671 | 1674 | ||
| 1672 | size = min_t(int, sizeof(info->status.rates), sizeof(bf->rates)); | ||
| 1673 | memcpy(info->status.rates, bf->rates, size); | ||
| 1674 | |||
| 1675 | for (i = 0; i < ts->ts_final_idx; i++) { | 1675 | for (i = 0; i < ts->ts_final_idx; i++) { |
| 1676 | struct ieee80211_tx_rate *r = | 1676 | struct ieee80211_tx_rate *r = |
| 1677 | &info->status.rates[i]; | 1677 | &info->status.rates[i]; |
diff --git a/drivers/net/wireless/ath/ath6kl/common.h b/drivers/net/wireless/ath/ath6kl/common.h index 98a886154d9c..05debf700a84 100644 --- a/drivers/net/wireless/ath/ath6kl/common.h +++ b/drivers/net/wireless/ath/ath6kl/common.h | |||
| @@ -22,8 +22,7 @@ | |||
| 22 | 22 | ||
| 23 | #define ATH6KL_MAX_IE 256 | 23 | #define ATH6KL_MAX_IE 256 |
| 24 | 24 | ||
| 25 | extern __printf(2, 3) | 25 | __printf(2, 3) int ath6kl_printk(const char *level, const char *fmt, ...); |
| 26 | int ath6kl_printk(const char *level, const char *fmt, ...); | ||
| 27 | 26 | ||
| 28 | /* | 27 | /* |
| 29 | * Reflects the version of binary interface exposed by ATH6KL target | 28 | * Reflects the version of binary interface exposed by ATH6KL target |
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index 74369de00fb5..ca9ba005f287 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h | |||
| @@ -50,11 +50,10 @@ enum ATH6K_DEBUG_MASK { | |||
| 50 | }; | 50 | }; |
| 51 | 51 | ||
| 52 | extern unsigned int debug_mask; | 52 | extern unsigned int debug_mask; |
| 53 | extern __printf(2, 3) | 53 | __printf(2, 3) int ath6kl_printk(const char *level, const char *fmt, ...); |
| 54 | int ath6kl_printk(const char *level, const char *fmt, ...); | 54 | __printf(1, 2) int ath6kl_info(const char *fmt, ...); |
| 55 | extern __printf(1, 2) int ath6kl_info(const char *fmt, ...); | 55 | __printf(1, 2) int ath6kl_err(const char *fmt, ...); |
| 56 | extern __printf(1, 2) int ath6kl_err(const char *fmt, ...); | 56 | __printf(1, 2) int ath6kl_warn(const char *fmt, ...); |
| 57 | extern __printf(1, 2) int ath6kl_warn(const char *fmt, ...); | ||
| 58 | 57 | ||
| 59 | enum ath6kl_war { | 58 | enum ath6kl_war { |
| 60 | ATH6KL_WAR_INVALID_RATE, | 59 | ATH6KL_WAR_INVALID_RATE, |
diff --git a/drivers/net/wireless/ath/ath6kl/htc.h b/drivers/net/wireless/ath/ath6kl/htc.h index a2c8ff809793..14cab1403dd6 100644 --- a/drivers/net/wireless/ath/ath6kl/htc.h +++ b/drivers/net/wireless/ath/ath6kl/htc.h | |||
| @@ -60,7 +60,7 @@ | |||
| 60 | /* disable credit flow control on a specific service */ | 60 | /* disable credit flow control on a specific service */ |
| 61 | #define HTC_CONN_FLGS_DISABLE_CRED_FLOW_CTRL (1 << 3) | 61 | #define HTC_CONN_FLGS_DISABLE_CRED_FLOW_CTRL (1 << 3) |
| 62 | #define HTC_CONN_FLGS_SET_RECV_ALLOC_SHIFT 8 | 62 | #define HTC_CONN_FLGS_SET_RECV_ALLOC_SHIFT 8 |
| 63 | #define HTC_CONN_FLGS_SET_RECV_ALLOC_MASK 0xFF00 | 63 | #define HTC_CONN_FLGS_SET_RECV_ALLOC_MASK 0xFF00U |
| 64 | 64 | ||
| 65 | /* connect response status codes */ | 65 | /* connect response status codes */ |
| 66 | #define HTC_SERVICE_SUCCESS 0 | 66 | #define HTC_SERVICE_SUCCESS 0 |
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 7944c25c9a43..32f139e2e897 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig | |||
| @@ -84,6 +84,26 @@ config ATH9K_DFS_CERTIFIED | |||
| 84 | developed. At this point enabling this option won't do anything | 84 | developed. At this point enabling this option won't do anything |
| 85 | except increase code size. | 85 | except increase code size. |
| 86 | 86 | ||
| 87 | config ATH9K_TX99 | ||
| 88 | bool "Atheros ath9k TX99 testing support" | ||
| 89 | depends on CFG80211_CERTIFICATION_ONUS | ||
| 90 | default n | ||
| 91 | ---help--- | ||
| 92 | Say N. This should only be enabled on systems undergoing | ||
| 93 | certification testing and evaluation in a controlled environment. | ||
| 94 | Enabling this will only enable TX99 support, all other modes of | ||
| 95 | operation will be disabled. | ||
| 96 | |||
| 97 | TX99 support enables Specific Absorption Rate (SAR) testing. | ||
| 98 | SAR is the unit of measurement for the amount of radio frequency(RF) | ||
| 99 | absorbed by the body when using a wireless device. The RF exposure | ||
| 100 | limits used are expressed in the terms of SAR, which is a measure | ||
| 101 | of the electric and magnetic field strength and power density for | ||
| 102 | transmitters operating at frequencies from 300 kHz to 100 GHz. | ||
| 103 | Regulatory bodies around the world require that wireless device | ||
| 104 | be evaluated to meet the RF exposure limits set forth in the | ||
| 105 | governmental SAR regulations. | ||
| 106 | |||
| 87 | config ATH9K_LEGACY_RATE_CONTROL | 107 | config ATH9K_LEGACY_RATE_CONTROL |
| 88 | bool "Atheros ath9k rate control" | 108 | bool "Atheros ath9k rate control" |
| 89 | depends on ATH9K | 109 | depends on ATH9K |
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 75ee9e7704ce..6205ef5a9321 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
| @@ -14,9 +14,7 @@ ath9k-$(CONFIG_ATH9K_AHB) += ahb.o | |||
| 14 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o | 14 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o |
| 15 | ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o | 15 | ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o |
| 16 | ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += \ | 16 | ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += \ |
| 17 | dfs.o \ | 17 | dfs.o |
| 18 | dfs_pattern_detector.o \ | ||
| 19 | dfs_pri_detector.o | ||
| 20 | ath9k-$(CONFIG_PM_SLEEP) += wow.o | 18 | ath9k-$(CONFIG_PM_SLEEP) += wow.o |
| 21 | 19 | ||
| 22 | obj-$(CONFIG_ATH9K) += ath9k.o | 20 | obj-$(CONFIG_ATH9K) += ath9k.o |
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 072e4b531067..2dff2765769b 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c | |||
| @@ -54,7 +54,7 @@ static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) | |||
| 54 | struct platform_device *pdev = to_platform_device(sc->dev); | 54 | struct platform_device *pdev = to_platform_device(sc->dev); |
| 55 | struct ath9k_platform_data *pdata; | 55 | struct ath9k_platform_data *pdata; |
| 56 | 56 | ||
| 57 | pdata = (struct ath9k_platform_data *) pdev->dev.platform_data; | 57 | pdata = dev_get_platdata(&pdev->dev); |
| 58 | if (off >= (ARRAY_SIZE(pdata->eeprom_data))) { | 58 | if (off >= (ARRAY_SIZE(pdata->eeprom_data))) { |
| 59 | ath_err(common, | 59 | ath_err(common, |
| 60 | "%s: flash read failed, offset %08x is out of range\n", | 60 | "%s: flash read failed, offset %08x is out of range\n", |
| @@ -84,7 +84,7 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
| 84 | struct ath_hw *ah; | 84 | struct ath_hw *ah; |
| 85 | char hw_name[64]; | 85 | char hw_name[64]; |
| 86 | 86 | ||
| 87 | if (!pdev->dev.platform_data) { | 87 | if (!dev_get_platdata(&pdev->dev)) { |
| 88 | dev_err(&pdev->dev, "no platform data specified\n"); | 88 | dev_err(&pdev->dev, "no platform data specified\n"); |
| 89 | return -EINVAL; | 89 | return -EINVAL; |
| 90 | } | 90 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index be466b0ef7a7..d28923b7435b 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
| @@ -338,10 +338,9 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) | |||
| 338 | aniState->cckNoiseImmunityLevel != | 338 | aniState->cckNoiseImmunityLevel != |
| 339 | ATH9K_ANI_CCK_DEF_LEVEL) { | 339 | ATH9K_ANI_CCK_DEF_LEVEL) { |
| 340 | ath_dbg(common, ANI, | 340 | ath_dbg(common, ANI, |
| 341 | "Restore defaults: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n", | 341 | "Restore defaults: opmode %u chan %d Mhz is_scanning=%d ofdm:%d cck:%d\n", |
| 342 | ah->opmode, | 342 | ah->opmode, |
| 343 | chan->channel, | 343 | chan->channel, |
| 344 | chan->channelFlags, | ||
| 345 | is_scanning, | 344 | is_scanning, |
| 346 | aniState->ofdmNoiseImmunityLevel, | 345 | aniState->ofdmNoiseImmunityLevel, |
| 347 | aniState->cckNoiseImmunityLevel); | 346 | aniState->cckNoiseImmunityLevel); |
| @@ -354,10 +353,9 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) | |||
| 354 | * restore historical levels for this channel | 353 | * restore historical levels for this channel |
| 355 | */ | 354 | */ |
| 356 | ath_dbg(common, ANI, | 355 | ath_dbg(common, ANI, |
| 357 | "Restore history: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n", | 356 | "Restore history: opmode %u chan %d Mhz is_scanning=%d ofdm:%d cck:%d\n", |
| 358 | ah->opmode, | 357 | ah->opmode, |
| 359 | chan->channel, | 358 | chan->channel, |
| 360 | chan->channelFlags, | ||
| 361 | is_scanning, | 359 | is_scanning, |
| 362 | aniState->ofdmNoiseImmunityLevel, | 360 | aniState->ofdmNoiseImmunityLevel, |
| 363 | aniState->cckNoiseImmunityLevel); | 361 | aniState->cckNoiseImmunityLevel); |
diff --git a/drivers/net/wireless/ath/ath9k/antenna.c b/drivers/net/wireless/ath/ath9k/antenna.c index dd1cc73d7946..bd048cc69a33 100644 --- a/drivers/net/wireless/ath/ath9k/antenna.c +++ b/drivers/net/wireless/ath/ath9k/antenna.c | |||
| @@ -332,7 +332,7 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb, | |||
| 332 | } | 332 | } |
| 333 | 333 | ||
| 334 | if (antcomb->rssi_lna2 > antcomb->rssi_lna1 + | 334 | if (antcomb->rssi_lna2 > antcomb->rssi_lna1 + |
| 335 | ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA) | 335 | div_ant_conf->lna1_lna2_switch_delta) |
| 336 | div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2; | 336 | div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2; |
| 337 | else | 337 | else |
| 338 | div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1; | 338 | div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1; |
| @@ -554,42 +554,22 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, | |||
| 554 | ant_conf->fast_div_bias = 0x1; | 554 | ant_conf->fast_div_bias = 0x1; |
| 555 | break; | 555 | break; |
| 556 | case 0x10: /* LNA2 A-B */ | 556 | case 0x10: /* LNA2 A-B */ |
| 557 | if ((antcomb->scan == 0) && | 557 | ant_conf->fast_div_bias = 0x2; |
| 558 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) { | ||
| 559 | ant_conf->fast_div_bias = 0x3f; | ||
| 560 | } else { | ||
| 561 | ant_conf->fast_div_bias = 0x1; | ||
| 562 | } | ||
| 563 | break; | 558 | break; |
| 564 | case 0x12: /* LNA2 LNA1 */ | 559 | case 0x12: /* LNA2 LNA1 */ |
| 565 | ant_conf->fast_div_bias = 0x39; | 560 | ant_conf->fast_div_bias = 0x3f; |
| 566 | break; | 561 | break; |
| 567 | case 0x13: /* LNA2 A+B */ | 562 | case 0x13: /* LNA2 A+B */ |
| 568 | if ((antcomb->scan == 0) && | 563 | ant_conf->fast_div_bias = 0x2; |
| 569 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) { | ||
| 570 | ant_conf->fast_div_bias = 0x3f; | ||
| 571 | } else { | ||
| 572 | ant_conf->fast_div_bias = 0x1; | ||
| 573 | } | ||
| 574 | break; | 564 | break; |
| 575 | case 0x20: /* LNA1 A-B */ | 565 | case 0x20: /* LNA1 A-B */ |
| 576 | if ((antcomb->scan == 0) && | 566 | ant_conf->fast_div_bias = 0x3; |
| 577 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) { | ||
| 578 | ant_conf->fast_div_bias = 0x3f; | ||
| 579 | } else { | ||
| 580 | ant_conf->fast_div_bias = 0x4; | ||
| 581 | } | ||
| 582 | break; | 567 | break; |
| 583 | case 0x21: /* LNA1 LNA2 */ | 568 | case 0x21: /* LNA1 LNA2 */ |
| 584 | ant_conf->fast_div_bias = 0x6; | 569 | ant_conf->fast_div_bias = 0x3; |
| 585 | break; | 570 | break; |
| 586 | case 0x23: /* LNA1 A+B */ | 571 | case 0x23: /* LNA1 A+B */ |
| 587 | if ((antcomb->scan == 0) && | 572 | ant_conf->fast_div_bias = 0x3; |
| 588 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) { | ||
| 589 | ant_conf->fast_div_bias = 0x3f; | ||
| 590 | } else { | ||
| 591 | ant_conf->fast_div_bias = 0x6; | ||
| 592 | } | ||
| 593 | break; | 573 | break; |
| 594 | case 0x30: /* A+B A-B */ | 574 | case 0x30: /* A+B A-B */ |
| 595 | ant_conf->fast_div_bias = 0x1; | 575 | ant_conf->fast_div_bias = 0x1; |
| @@ -638,7 +618,7 @@ static void ath_ant_try_scan(struct ath_ant_comb *antcomb, | |||
| 638 | antcomb->rssi_sub = alt_rssi_avg; | 618 | antcomb->rssi_sub = alt_rssi_avg; |
| 639 | antcomb->scan = false; | 619 | antcomb->scan = false; |
| 640 | if (antcomb->rssi_lna2 > | 620 | if (antcomb->rssi_lna2 > |
| 641 | (antcomb->rssi_lna1 + ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) { | 621 | (antcomb->rssi_lna1 + conf->lna1_lna2_switch_delta)) { |
| 642 | /* use LNA2 as main LNA */ | 622 | /* use LNA2 as main LNA */ |
| 643 | if ((antcomb->rssi_add > antcomb->rssi_lna1) && | 623 | if ((antcomb->rssi_add > antcomb->rssi_lna1) && |
| 644 | (antcomb->rssi_add > antcomb->rssi_sub)) { | 624 | (antcomb->rssi_add > antcomb->rssi_sub)) { |
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index 08656473c63e..ff415e863ee9 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c | |||
| @@ -626,12 +626,11 @@ static void ar5008_hw_override_ini(struct ath_hw *ah, | |||
| 626 | if (AR_SREV_9287_11_OR_LATER(ah)) | 626 | if (AR_SREV_9287_11_OR_LATER(ah)) |
| 627 | val = val & (~AR_PCU_MISC_MODE2_HWWAR2); | 627 | val = val & (~AR_PCU_MISC_MODE2_HWWAR2); |
| 628 | 628 | ||
| 629 | val |= AR_PCU_MISC_MODE2_CFP_IGNORE; | ||
| 630 | |||
| 629 | REG_WRITE(ah, AR_PCU_MISC_MODE2, val); | 631 | REG_WRITE(ah, AR_PCU_MISC_MODE2, val); |
| 630 | } | 632 | } |
| 631 | 633 | ||
| 632 | REG_SET_BIT(ah, AR_PHY_CCK_DETECT, | ||
| 633 | AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); | ||
| 634 | |||
| 635 | if (AR_SREV_9280_20_OR_LATER(ah)) | 634 | if (AR_SREV_9280_20_OR_LATER(ah)) |
| 636 | return; | 635 | return; |
| 637 | /* | 636 | /* |
| @@ -667,14 +666,13 @@ static void ar5008_hw_set_channel_regs(struct ath_hw *ah, | |||
| 667 | if (IS_CHAN_HT40(chan)) { | 666 | if (IS_CHAN_HT40(chan)) { |
| 668 | phymode |= AR_PHY_FC_DYN2040_EN; | 667 | phymode |= AR_PHY_FC_DYN2040_EN; |
| 669 | 668 | ||
| 670 | if ((chan->chanmode == CHANNEL_A_HT40PLUS) || | 669 | if (IS_CHAN_HT40PLUS(chan)) |
| 671 | (chan->chanmode == CHANNEL_G_HT40PLUS)) | ||
| 672 | phymode |= AR_PHY_FC_DYN2040_PRI_CH; | 670 | phymode |= AR_PHY_FC_DYN2040_PRI_CH; |
| 673 | 671 | ||
| 674 | } | 672 | } |
| 675 | REG_WRITE(ah, AR_PHY_TURBO, phymode); | 673 | REG_WRITE(ah, AR_PHY_TURBO, phymode); |
| 676 | 674 | ||
| 677 | ath9k_hw_set11nmac2040(ah); | 675 | ath9k_hw_set11nmac2040(ah, chan); |
| 678 | 676 | ||
| 679 | ENABLE_REGWRITE_BUFFER(ah); | 677 | ENABLE_REGWRITE_BUFFER(ah); |
| 680 | 678 | ||
| @@ -692,31 +690,12 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, | |||
| 692 | int i, regWrites = 0; | 690 | int i, regWrites = 0; |
| 693 | u32 modesIndex, freqIndex; | 691 | u32 modesIndex, freqIndex; |
| 694 | 692 | ||
| 695 | switch (chan->chanmode) { | 693 | if (IS_CHAN_5GHZ(chan)) { |
| 696 | case CHANNEL_A: | ||
| 697 | case CHANNEL_A_HT20: | ||
| 698 | modesIndex = 1; | ||
| 699 | freqIndex = 1; | ||
| 700 | break; | ||
| 701 | case CHANNEL_A_HT40PLUS: | ||
| 702 | case CHANNEL_A_HT40MINUS: | ||
| 703 | modesIndex = 2; | ||
| 704 | freqIndex = 1; | 694 | freqIndex = 1; |
| 705 | break; | 695 | modesIndex = IS_CHAN_HT40(chan) ? 2 : 1; |
| 706 | case CHANNEL_G: | 696 | } else { |
| 707 | case CHANNEL_G_HT20: | ||
| 708 | case CHANNEL_B: | ||
| 709 | modesIndex = 4; | ||
| 710 | freqIndex = 2; | ||
| 711 | break; | ||
| 712 | case CHANNEL_G_HT40PLUS: | ||
| 713 | case CHANNEL_G_HT40MINUS: | ||
| 714 | modesIndex = 3; | ||
| 715 | freqIndex = 2; | 697 | freqIndex = 2; |
| 716 | break; | 698 | modesIndex = IS_CHAN_HT40(chan) ? 3 : 4; |
| 717 | |||
| 718 | default: | ||
| 719 | return -EINVAL; | ||
| 720 | } | 699 | } |
| 721 | 700 | ||
| 722 | /* | 701 | /* |
| @@ -815,8 +794,10 @@ static void ar5008_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan) | |||
| 815 | if (chan == NULL) | 794 | if (chan == NULL) |
| 816 | return; | 795 | return; |
| 817 | 796 | ||
| 818 | rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan)) | 797 | if (IS_CHAN_2GHZ(chan)) |
| 819 | ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; | 798 | rfMode |= AR_PHY_MODE_DYNAMIC; |
| 799 | else | ||
| 800 | rfMode |= AR_PHY_MODE_OFDM; | ||
| 820 | 801 | ||
| 821 | if (!AR_SREV_9280_20_OR_LATER(ah)) | 802 | if (!AR_SREV_9280_20_OR_LATER(ah)) |
| 822 | rfMode |= (IS_CHAN_5GHZ(chan)) ? | 803 | rfMode |= (IS_CHAN_5GHZ(chan)) ? |
| @@ -1219,12 +1200,11 @@ static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah) | |||
| 1219 | 1200 | ||
| 1220 | iniDef = &aniState->iniDef; | 1201 | iniDef = &aniState->iniDef; |
| 1221 | 1202 | ||
| 1222 | ath_dbg(common, ANI, "ver %d.%d opmode %u chan %d Mhz/0x%x\n", | 1203 | ath_dbg(common, ANI, "ver %d.%d opmode %u chan %d Mhz\n", |
| 1223 | ah->hw_version.macVersion, | 1204 | ah->hw_version.macVersion, |
| 1224 | ah->hw_version.macRev, | 1205 | ah->hw_version.macRev, |
| 1225 | ah->opmode, | 1206 | ah->opmode, |
| 1226 | chan->channel, | 1207 | chan->channel); |
| 1227 | chan->channelFlags); | ||
| 1228 | 1208 | ||
| 1229 | val = REG_READ(ah, AR_PHY_SFCORR); | 1209 | val = REG_READ(ah, AR_PHY_SFCORR); |
| 1230 | iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH); | 1210 | iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index 9f589744a9f9..cdc74005650c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c | |||
| @@ -33,15 +33,12 @@ static bool ar9002_hw_is_cal_supported(struct ath_hw *ah, | |||
| 33 | bool supported = false; | 33 | bool supported = false; |
| 34 | switch (ah->supp_cals & cal_type) { | 34 | switch (ah->supp_cals & cal_type) { |
| 35 | case IQ_MISMATCH_CAL: | 35 | case IQ_MISMATCH_CAL: |
| 36 | /* Run IQ Mismatch for non-CCK only */ | 36 | supported = true; |
| 37 | if (!IS_CHAN_B(chan)) | ||
| 38 | supported = true; | ||
| 39 | break; | 37 | break; |
| 40 | case ADC_GAIN_CAL: | 38 | case ADC_GAIN_CAL: |
| 41 | case ADC_DC_CAL: | 39 | case ADC_DC_CAL: |
| 42 | /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */ | 40 | /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */ |
| 43 | if (!IS_CHAN_B(chan) && | 41 | if (!((IS_CHAN_2GHZ(chan) || IS_CHAN_A_FAST_CLOCK(ah, chan)) && |
| 44 | !((IS_CHAN_2GHZ(chan) || IS_CHAN_A_FAST_CLOCK(ah, chan)) && | ||
| 45 | IS_CHAN_HT20(chan))) | 42 | IS_CHAN_HT20(chan))) |
| 46 | supported = true; | 43 | supported = true; |
| 47 | break; | 44 | break; |
| @@ -671,7 +668,7 @@ static bool ar9002_hw_calibrate(struct ath_hw *ah, | |||
| 671 | 668 | ||
| 672 | nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF); | 669 | nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF); |
| 673 | if (ah->caldata) | 670 | if (ah->caldata) |
| 674 | nfcal_pending = ah->caldata->nfcal_pending; | 671 | nfcal_pending = test_bit(NFCAL_PENDING, &ah->caldata->cal_flags); |
| 675 | 672 | ||
| 676 | if (currCal && !nfcal && | 673 | if (currCal && !nfcal && |
| 677 | (currCal->calState == CAL_RUNNING || | 674 | (currCal->calState == CAL_RUNNING || |
| @@ -861,7 +858,7 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
| 861 | ar9002_hw_pa_cal(ah, true); | 858 | ar9002_hw_pa_cal(ah, true); |
| 862 | 859 | ||
| 863 | if (ah->caldata) | 860 | if (ah->caldata) |
| 864 | ah->caldata->nfcal_pending = true; | 861 | set_bit(NFCAL_PENDING, &ah->caldata->cal_flags); |
| 865 | 862 | ||
| 866 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; | 863 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; |
| 867 | 864 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index fb61b081d172..5c95fd9e9c9e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c | |||
| @@ -419,28 +419,10 @@ void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan) | |||
| 419 | u32 modesIndex; | 419 | u32 modesIndex; |
| 420 | int i; | 420 | int i; |
| 421 | 421 | ||
| 422 | switch (chan->chanmode) { | 422 | if (IS_CHAN_5GHZ(chan)) |
| 423 | case CHANNEL_A: | 423 | modesIndex = IS_CHAN_HT40(chan) ? 2 : 1; |
| 424 | case CHANNEL_A_HT20: | 424 | else |
| 425 | modesIndex = 1; | 425 | modesIndex = IS_CHAN_HT40(chan) ? 3 : 4; |
| 426 | break; | ||
| 427 | case CHANNEL_A_HT40PLUS: | ||
| 428 | case CHANNEL_A_HT40MINUS: | ||
| 429 | modesIndex = 2; | ||
| 430 | break; | ||
| 431 | case CHANNEL_G: | ||
| 432 | case CHANNEL_G_HT20: | ||
| 433 | case CHANNEL_B: | ||
| 434 | modesIndex = 4; | ||
| 435 | break; | ||
| 436 | case CHANNEL_G_HT40PLUS: | ||
| 437 | case CHANNEL_G_HT40MINUS: | ||
| 438 | modesIndex = 3; | ||
| 439 | break; | ||
| 440 | |||
| 441 | default: | ||
| 442 | return; | ||
| 443 | } | ||
| 444 | 426 | ||
| 445 | ENABLE_REGWRITE_BUFFER(ah); | 427 | ENABLE_REGWRITE_BUFFER(ah); |
| 446 | 428 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index 1fc1fa955d44..f087117b2e6b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c | |||
| @@ -485,7 +485,7 @@ static void ar9002_hw_do_getnf(struct ath_hw *ah, | |||
| 485 | if (IS_CHAN_HT40(ah->curchan)) | 485 | if (IS_CHAN_HT40(ah->curchan)) |
| 486 | nfarray[3] = sign_extend32(nf, 8); | 486 | nfarray[3] = sign_extend32(nf, 8); |
| 487 | 487 | ||
| 488 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) | 488 | if (!(ah->rxchainmask & BIT(1))) |
| 489 | return; | 489 | return; |
| 490 | 490 | ||
| 491 | nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR9280_PHY_CH1_MINCCA_PWR); | 491 | nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR9280_PHY_CH1_MINCCA_PWR); |
| @@ -532,6 +532,7 @@ static void ar9002_hw_antdiv_comb_conf_get(struct ath_hw *ah, | |||
| 532 | AR_PHY_9285_ANT_DIV_ALT_LNACONF_S; | 532 | AR_PHY_9285_ANT_DIV_ALT_LNACONF_S; |
| 533 | antconf->fast_div_bias = (regval & AR_PHY_9285_FAST_DIV_BIAS) >> | 533 | antconf->fast_div_bias = (regval & AR_PHY_9285_FAST_DIV_BIAS) >> |
| 534 | AR_PHY_9285_FAST_DIV_BIAS_S; | 534 | AR_PHY_9285_FAST_DIV_BIAS_S; |
| 535 | antconf->lna1_lna2_switch_delta = -1; | ||
| 535 | antconf->lna1_lna2_delta = -3; | 536 | antconf->lna1_lna2_delta = -3; |
| 536 | antconf->div_group = 0; | 537 | antconf->div_group = 0; |
| 537 | } | 538 | } |
| @@ -679,6 +680,26 @@ static void ar9002_hw_spectral_scan_wait(struct ath_hw *ah) | |||
| 679 | } | 680 | } |
| 680 | } | 681 | } |
| 681 | 682 | ||
| 683 | static void ar9002_hw_tx99_start(struct ath_hw *ah, u32 qnum) | ||
| 684 | { | ||
| 685 | REG_SET_BIT(ah, 0x9864, 0x7f000); | ||
| 686 | REG_SET_BIT(ah, 0x9924, 0x7f00fe); | ||
| 687 | REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); | ||
| 688 | REG_WRITE(ah, AR_CR, AR_CR_RXD); | ||
| 689 | REG_WRITE(ah, AR_DLCL_IFS(qnum), 0); | ||
| 690 | REG_WRITE(ah, AR_D_GBL_IFS_SIFS, 20); | ||
| 691 | REG_WRITE(ah, AR_D_GBL_IFS_EIFS, 20); | ||
| 692 | REG_WRITE(ah, AR_D_FPCTL, 0x10|qnum); | ||
| 693 | REG_WRITE(ah, AR_TIME_OUT, 0x00000400); | ||
| 694 | REG_WRITE(ah, AR_DRETRY_LIMIT(qnum), 0xffffffff); | ||
| 695 | REG_SET_BIT(ah, AR_QMISC(qnum), AR_Q_MISC_DCU_EARLY_TERM_REQ); | ||
| 696 | } | ||
| 697 | |||
| 698 | static void ar9002_hw_tx99_stop(struct ath_hw *ah) | ||
| 699 | { | ||
| 700 | REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); | ||
| 701 | } | ||
| 702 | |||
| 682 | void ar9002_hw_attach_phy_ops(struct ath_hw *ah) | 703 | void ar9002_hw_attach_phy_ops(struct ath_hw *ah) |
| 683 | { | 704 | { |
| 684 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | 705 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); |
| @@ -700,6 +721,8 @@ void ar9002_hw_attach_phy_ops(struct ath_hw *ah) | |||
| 700 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | 721 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT |
| 701 | ops->set_bt_ant_diversity = ar9002_hw_set_bt_ant_diversity; | 722 | ops->set_bt_ant_diversity = ar9002_hw_set_bt_ant_diversity; |
| 702 | #endif | 723 | #endif |
| 724 | ops->tx99_start = ar9002_hw_tx99_start; | ||
| 725 | ops->tx99_stop = ar9002_hw_tx99_stop; | ||
| 703 | 726 | ||
| 704 | ar9002_hw_set_nf_limits(ah); | 727 | ar9002_hw_set_nf_limits(ah); |
| 705 | } | 728 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 6988e1d081f2..22934d3ca544 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
| @@ -727,8 +727,12 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, | |||
| 727 | REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0, | 727 | REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0, |
| 728 | AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1); | 728 | AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1); |
| 729 | 729 | ||
| 730 | if (caldata) | 730 | if (caldata) { |
| 731 | caldata->done_txiqcal_once = is_reusable; | 731 | if (is_reusable) |
| 732 | set_bit(TXIQCAL_DONE, &caldata->cal_flags); | ||
| 733 | else | ||
| 734 | clear_bit(TXIQCAL_DONE, &caldata->cal_flags); | ||
| 735 | } | ||
| 732 | 736 | ||
| 733 | return; | 737 | return; |
| 734 | } | 738 | } |
| @@ -961,18 +965,44 @@ static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g) | |||
| 961 | } | 965 | } |
| 962 | 966 | ||
| 963 | static void ar9003_hw_do_manual_peak_cal(struct ath_hw *ah, | 967 | static void ar9003_hw_do_manual_peak_cal(struct ath_hw *ah, |
| 964 | struct ath9k_channel *chan) | 968 | struct ath9k_channel *chan, |
| 969 | bool run_rtt_cal) | ||
| 965 | { | 970 | { |
| 971 | struct ath9k_hw_cal_data *caldata = ah->caldata; | ||
| 966 | int i; | 972 | int i; |
| 967 | 973 | ||
| 968 | if (!AR_SREV_9462(ah) && !AR_SREV_9565(ah) && !AR_SREV_9485(ah)) | 974 | if (!AR_SREV_9462(ah) && !AR_SREV_9565(ah) && !AR_SREV_9485(ah)) |
| 969 | return; | 975 | return; |
| 970 | 976 | ||
| 977 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_RTT) && !run_rtt_cal) | ||
| 978 | return; | ||
| 979 | |||
| 971 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { | 980 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { |
| 972 | if (!(ah->rxchainmask & (1 << i))) | 981 | if (!(ah->rxchainmask & (1 << i))) |
| 973 | continue; | 982 | continue; |
| 974 | ar9003_hw_manual_peak_cal(ah, i, IS_CHAN_2GHZ(chan)); | 983 | ar9003_hw_manual_peak_cal(ah, i, IS_CHAN_2GHZ(chan)); |
| 975 | } | 984 | } |
| 985 | |||
| 986 | if (caldata) | ||
| 987 | set_bit(SW_PKDET_DONE, &caldata->cal_flags); | ||
| 988 | |||
| 989 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_RTT) && caldata) { | ||
| 990 | if (IS_CHAN_2GHZ(chan)){ | ||
| 991 | caldata->caldac[0] = REG_READ_FIELD(ah, | ||
| 992 | AR_PHY_65NM_RXRF_AGC(0), | ||
| 993 | AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR); | ||
| 994 | caldata->caldac[1] = REG_READ_FIELD(ah, | ||
| 995 | AR_PHY_65NM_RXRF_AGC(1), | ||
| 996 | AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR); | ||
| 997 | } else { | ||
| 998 | caldata->caldac[0] = REG_READ_FIELD(ah, | ||
| 999 | AR_PHY_65NM_RXRF_AGC(0), | ||
| 1000 | AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR); | ||
| 1001 | caldata->caldac[1] = REG_READ_FIELD(ah, | ||
| 1002 | AR_PHY_65NM_RXRF_AGC(1), | ||
| 1003 | AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR); | ||
| 1004 | } | ||
| 1005 | } | ||
| 976 | } | 1006 | } |
| 977 | 1007 | ||
| 978 | static void ar9003_hw_cl_cal_post_proc(struct ath_hw *ah, bool is_reusable) | 1008 | static void ar9003_hw_cl_cal_post_proc(struct ath_hw *ah, bool is_reusable) |
| @@ -990,7 +1020,7 @@ static void ar9003_hw_cl_cal_post_proc(struct ath_hw *ah, bool is_reusable) | |||
| 990 | txclcal_done = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & | 1020 | txclcal_done = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & |
| 991 | AR_PHY_AGC_CONTROL_CLC_SUCCESS); | 1021 | AR_PHY_AGC_CONTROL_CLC_SUCCESS); |
| 992 | 1022 | ||
| 993 | if (caldata->done_txclcal_once) { | 1023 | if (test_bit(TXCLCAL_DONE, &caldata->cal_flags)) { |
| 994 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { | 1024 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { |
| 995 | if (!(ah->txchainmask & (1 << i))) | 1025 | if (!(ah->txchainmask & (1 << i))) |
| 996 | continue; | 1026 | continue; |
| @@ -1006,7 +1036,7 @@ static void ar9003_hw_cl_cal_post_proc(struct ath_hw *ah, bool is_reusable) | |||
| 1006 | caldata->tx_clcal[i][j] = | 1036 | caldata->tx_clcal[i][j] = |
| 1007 | REG_READ(ah, CL_TAB_ENTRY(cl_idx[i])); | 1037 | REG_READ(ah, CL_TAB_ENTRY(cl_idx[i])); |
| 1008 | } | 1038 | } |
| 1009 | caldata->done_txclcal_once = true; | 1039 | set_bit(TXCLCAL_DONE, &caldata->cal_flags); |
| 1010 | } | 1040 | } |
| 1011 | } | 1041 | } |
| 1012 | 1042 | ||
| @@ -1019,6 +1049,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
| 1019 | bool is_reusable = true, status = true; | 1049 | bool is_reusable = true, status = true; |
| 1020 | bool run_rtt_cal = false, run_agc_cal, sep_iq_cal = false; | 1050 | bool run_rtt_cal = false, run_agc_cal, sep_iq_cal = false; |
| 1021 | bool rtt = !!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT); | 1051 | bool rtt = !!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT); |
| 1052 | u32 rx_delay = 0; | ||
| 1022 | u32 agc_ctrl = 0, agc_supp_cals = AR_PHY_AGC_CONTROL_OFFSET_CAL | | 1053 | u32 agc_ctrl = 0, agc_supp_cals = AR_PHY_AGC_CONTROL_OFFSET_CAL | |
| 1023 | AR_PHY_AGC_CONTROL_FLTR_CAL | | 1054 | AR_PHY_AGC_CONTROL_FLTR_CAL | |
| 1024 | AR_PHY_AGC_CONTROL_PKDET_CAL; | 1055 | AR_PHY_AGC_CONTROL_PKDET_CAL; |
| @@ -1042,17 +1073,22 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
| 1042 | ar9003_hw_rtt_clear_hist(ah); | 1073 | ar9003_hw_rtt_clear_hist(ah); |
| 1043 | } | 1074 | } |
| 1044 | 1075 | ||
| 1045 | if (rtt && !run_rtt_cal) { | 1076 | if (rtt) { |
| 1046 | agc_ctrl = REG_READ(ah, AR_PHY_AGC_CONTROL); | 1077 | if (!run_rtt_cal) { |
| 1047 | agc_supp_cals &= agc_ctrl; | 1078 | agc_ctrl = REG_READ(ah, AR_PHY_AGC_CONTROL); |
| 1048 | agc_ctrl &= ~(AR_PHY_AGC_CONTROL_OFFSET_CAL | | 1079 | agc_supp_cals &= agc_ctrl; |
| 1049 | AR_PHY_AGC_CONTROL_FLTR_CAL | | 1080 | agc_ctrl &= ~(AR_PHY_AGC_CONTROL_OFFSET_CAL | |
| 1050 | AR_PHY_AGC_CONTROL_PKDET_CAL); | 1081 | AR_PHY_AGC_CONTROL_FLTR_CAL | |
| 1051 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl); | 1082 | AR_PHY_AGC_CONTROL_PKDET_CAL); |
| 1083 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl); | ||
| 1084 | } else { | ||
| 1085 | if (ah->ah_flags & AH_FASTCC) | ||
| 1086 | run_agc_cal = true; | ||
| 1087 | } | ||
| 1052 | } | 1088 | } |
| 1053 | 1089 | ||
| 1054 | if (ah->enabled_cals & TX_CL_CAL) { | 1090 | if (ah->enabled_cals & TX_CL_CAL) { |
| 1055 | if (caldata && caldata->done_txclcal_once) | 1091 | if (caldata && test_bit(TXCLCAL_DONE, &caldata->cal_flags)) |
| 1056 | REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, | 1092 | REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, |
| 1057 | AR_PHY_CL_CAL_ENABLE); | 1093 | AR_PHY_CL_CAL_ENABLE); |
| 1058 | else { | 1094 | else { |
| @@ -1076,14 +1112,14 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
| 1076 | * AGC calibration | 1112 | * AGC calibration |
| 1077 | */ | 1113 | */ |
| 1078 | if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) { | 1114 | if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) { |
| 1079 | if (caldata && !caldata->done_txiqcal_once) | 1115 | if (caldata && !test_bit(TXIQCAL_DONE, &caldata->cal_flags)) |
| 1080 | REG_SET_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0, | 1116 | REG_SET_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0, |
| 1081 | AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL); | 1117 | AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL); |
| 1082 | else | 1118 | else |
| 1083 | REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0, | 1119 | REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0, |
| 1084 | AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL); | 1120 | AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL); |
| 1085 | txiqcal_done = run_agc_cal = true; | 1121 | txiqcal_done = run_agc_cal = true; |
| 1086 | } else if (caldata && !caldata->done_txiqcal_once) { | 1122 | } else if (caldata && !test_bit(TXIQCAL_DONE, &caldata->cal_flags)) { |
| 1087 | run_agc_cal = true; | 1123 | run_agc_cal = true; |
| 1088 | sep_iq_cal = true; | 1124 | sep_iq_cal = true; |
| 1089 | } | 1125 | } |
| @@ -1099,6 +1135,15 @@ skip_tx_iqcal: | |||
| 1099 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); | 1135 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); |
| 1100 | } | 1136 | } |
| 1101 | 1137 | ||
| 1138 | if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) { | ||
| 1139 | rx_delay = REG_READ(ah, AR_PHY_RX_DELAY); | ||
| 1140 | /* Disable BB_active */ | ||
| 1141 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); | ||
| 1142 | udelay(5); | ||
| 1143 | REG_WRITE(ah, AR_PHY_RX_DELAY, AR_PHY_RX_DELAY_DELAY); | ||
| 1144 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); | ||
| 1145 | } | ||
| 1146 | |||
| 1102 | if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) { | 1147 | if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) { |
| 1103 | /* Calibrate the AGC */ | 1148 | /* Calibrate the AGC */ |
| 1104 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, | 1149 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, |
| @@ -1110,7 +1155,12 @@ skip_tx_iqcal: | |||
| 1110 | AR_PHY_AGC_CONTROL_CAL, | 1155 | AR_PHY_AGC_CONTROL_CAL, |
| 1111 | 0, AH_WAIT_TIMEOUT); | 1156 | 0, AH_WAIT_TIMEOUT); |
| 1112 | 1157 | ||
| 1113 | ar9003_hw_do_manual_peak_cal(ah, chan); | 1158 | ar9003_hw_do_manual_peak_cal(ah, chan, run_rtt_cal); |
| 1159 | } | ||
| 1160 | |||
| 1161 | if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) { | ||
| 1162 | REG_WRITE(ah, AR_PHY_RX_DELAY, rx_delay); | ||
| 1163 | udelay(5); | ||
| 1114 | } | 1164 | } |
| 1115 | 1165 | ||
| 1116 | if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal) | 1166 | if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal) |
| @@ -1133,19 +1183,23 @@ skip_tx_iqcal: | |||
| 1133 | 1183 | ||
| 1134 | if (txiqcal_done) | 1184 | if (txiqcal_done) |
| 1135 | ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable); | 1185 | ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable); |
| 1136 | else if (caldata && caldata->done_txiqcal_once) | 1186 | else if (caldata && test_bit(TXIQCAL_DONE, &caldata->cal_flags)) |
| 1137 | ar9003_hw_tx_iq_cal_reload(ah); | 1187 | ar9003_hw_tx_iq_cal_reload(ah); |
| 1138 | 1188 | ||
| 1139 | ar9003_hw_cl_cal_post_proc(ah, is_reusable); | 1189 | ar9003_hw_cl_cal_post_proc(ah, is_reusable); |
| 1140 | 1190 | ||
| 1141 | if (run_rtt_cal && caldata) { | 1191 | if (run_rtt_cal && caldata) { |
| 1142 | if (is_reusable) { | 1192 | if (is_reusable) { |
| 1143 | if (!ath9k_hw_rfbus_req(ah)) | 1193 | if (!ath9k_hw_rfbus_req(ah)) { |
| 1144 | ath_err(ath9k_hw_common(ah), | 1194 | ath_err(ath9k_hw_common(ah), |
| 1145 | "Could not stop baseband\n"); | 1195 | "Could not stop baseband\n"); |
| 1146 | else | 1196 | } else { |
| 1147 | ar9003_hw_rtt_fill_hist(ah); | 1197 | ar9003_hw_rtt_fill_hist(ah); |
| 1148 | 1198 | ||
| 1199 | if (test_bit(SW_PKDET_DONE, &caldata->cal_flags)) | ||
| 1200 | ar9003_hw_rtt_load_hist(ah); | ||
| 1201 | } | ||
| 1202 | |||
| 1149 | ath9k_hw_rfbus_done(ah); | 1203 | ath9k_hw_rfbus_done(ah); |
| 1150 | } | 1204 | } |
| 1151 | 1205 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index f4864807e15b..1ec52356b5a1 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
| @@ -2991,7 +2991,10 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, | |||
| 2991 | case EEP_CHAIN_MASK_REDUCE: | 2991 | case EEP_CHAIN_MASK_REDUCE: |
| 2992 | return (pBase->miscConfiguration >> 0x3) & 0x1; | 2992 | return (pBase->miscConfiguration >> 0x3) & 0x1; |
| 2993 | case EEP_ANT_DIV_CTL1: | 2993 | case EEP_ANT_DIV_CTL1: |
| 2994 | return eep->base_ext1.ant_div_control; | 2994 | if (AR_SREV_9565(ah)) |
| 2995 | return AR9300_EEP_ANTDIV_CONTROL_DEFAULT_VALUE; | ||
| 2996 | else | ||
| 2997 | return eep->base_ext1.ant_div_control; | ||
| 2995 | case EEP_ANTENNA_GAIN_5G: | 2998 | case EEP_ANTENNA_GAIN_5G: |
| 2996 | return eep->modalHeader5G.antennaGain; | 2999 | return eep->modalHeader5G.antennaGain; |
| 2997 | case EEP_ANTENNA_GAIN_2G: | 3000 | case EEP_ANTENNA_GAIN_2G: |
| @@ -3424,12 +3427,12 @@ static u32 ath9k_hw_ar9003_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, | |||
| 3424 | struct ar9300_base_eep_hdr *pBase; | 3427 | struct ar9300_base_eep_hdr *pBase; |
| 3425 | 3428 | ||
| 3426 | if (!dump_base_hdr) { | 3429 | if (!dump_base_hdr) { |
| 3427 | len += snprintf(buf + len, size - len, | 3430 | len += scnprintf(buf + len, size - len, |
| 3428 | "%20s :\n", "2GHz modal Header"); | 3431 | "%20s :\n", "2GHz modal Header"); |
| 3429 | len = ar9003_dump_modal_eeprom(buf, len, size, | 3432 | len = ar9003_dump_modal_eeprom(buf, len, size, |
| 3430 | &eep->modalHeader2G); | 3433 | &eep->modalHeader2G); |
| 3431 | len += snprintf(buf + len, size - len, | 3434 | len += scnprintf(buf + len, size - len, |
| 3432 | "%20s :\n", "5GHz modal Header"); | 3435 | "%20s :\n", "5GHz modal Header"); |
| 3433 | len = ar9003_dump_modal_eeprom(buf, len, size, | 3436 | len = ar9003_dump_modal_eeprom(buf, len, size, |
| 3434 | &eep->modalHeader5G); | 3437 | &eep->modalHeader5G); |
| 3435 | goto out; | 3438 | goto out; |
| @@ -3479,8 +3482,8 @@ static u32 ath9k_hw_ar9003_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, | |||
| 3479 | PR_EEP("Rx Gain", pBase->txrxgain & 0xf); | 3482 | PR_EEP("Rx Gain", pBase->txrxgain & 0xf); |
| 3480 | PR_EEP("SW Reg", le32_to_cpu(pBase->swreg)); | 3483 | PR_EEP("SW Reg", le32_to_cpu(pBase->swreg)); |
| 3481 | 3484 | ||
| 3482 | len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress", | 3485 | len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress", |
| 3483 | ah->eeprom.ar9300_eep.macAddr); | 3486 | ah->eeprom.ar9300_eep.macAddr); |
| 3484 | out: | 3487 | out: |
| 3485 | if (len > size) | 3488 | if (len > size) |
| 3486 | len = size; | 3489 | len = size; |
| @@ -3656,9 +3659,23 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) | |||
| 3656 | if (AR_SREV_9565(ah)) { | 3659 | if (AR_SREV_9565(ah)) { |
| 3657 | if (common->bt_ant_diversity) { | 3660 | if (common->bt_ant_diversity) { |
| 3658 | regval |= (1 << AR_PHY_ANT_SW_RX_PROT_S); | 3661 | regval |= (1 << AR_PHY_ANT_SW_RX_PROT_S); |
| 3662 | |||
| 3663 | REG_SET_BIT(ah, AR_PHY_RESTART, | ||
| 3664 | AR_PHY_RESTART_ENABLE_DIV_M2FLAG); | ||
| 3665 | |||
| 3666 | /* Force WLAN LNA diversity ON */ | ||
| 3667 | REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, | ||
| 3668 | AR_BTCOEX_WL_LNADIV_FORCE_ON); | ||
| 3659 | } else { | 3669 | } else { |
| 3660 | regval &= ~(1 << AR_PHY_ANT_DIV_LNADIV_S); | 3670 | regval &= ~(1 << AR_PHY_ANT_DIV_LNADIV_S); |
| 3661 | regval &= ~(1 << AR_PHY_ANT_SW_RX_PROT_S); | 3671 | regval &= ~(1 << AR_PHY_ANT_SW_RX_PROT_S); |
| 3672 | |||
| 3673 | REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL, | ||
| 3674 | (1 << AR_PHY_ANT_SW_RX_PROT_S)); | ||
| 3675 | |||
| 3676 | /* Force WLAN LNA diversity OFF */ | ||
| 3677 | REG_CLR_BIT(ah, AR_BTCOEX_WL_LNADIV, | ||
| 3678 | AR_BTCOEX_WL_LNADIV_FORCE_ON); | ||
| 3662 | } | 3679 | } |
| 3663 | } | 3680 | } |
| 3664 | 3681 | ||
| @@ -3669,7 +3686,8 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) | |||
| 3669 | regval &= (~AR_FAST_DIV_ENABLE); | 3686 | regval &= (~AR_FAST_DIV_ENABLE); |
| 3670 | regval |= ((value >> 7) & 0x1) << AR_FAST_DIV_ENABLE_S; | 3687 | regval |= ((value >> 7) & 0x1) << AR_FAST_DIV_ENABLE_S; |
| 3671 | 3688 | ||
| 3672 | if (AR_SREV_9485(ah) && common->bt_ant_diversity) | 3689 | if ((AR_SREV_9485(ah) || AR_SREV_9565(ah)) |
| 3690 | && common->bt_ant_diversity) | ||
| 3673 | regval |= AR_FAST_DIV_ENABLE; | 3691 | regval |= AR_FAST_DIV_ENABLE; |
| 3674 | 3692 | ||
| 3675 | REG_WRITE(ah, AR_PHY_CCK_DETECT, regval); | 3693 | REG_WRITE(ah, AR_PHY_CCK_DETECT, regval); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index 75d4fb41962f..0e5daa58a4fc 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | |||
| @@ -52,6 +52,8 @@ | |||
| 52 | #define AR9300_PAPRD_SCALE_2 0x70000000 | 52 | #define AR9300_PAPRD_SCALE_2 0x70000000 |
| 53 | #define AR9300_PAPRD_SCALE_2_S 28 | 53 | #define AR9300_PAPRD_SCALE_2_S 28 |
| 54 | 54 | ||
| 55 | #define AR9300_EEP_ANTDIV_CONTROL_DEFAULT_VALUE 0xc9 | ||
| 56 | |||
| 55 | /* Delta from which to start power to pdadc table */ | 57 | /* Delta from which to start power to pdadc table */ |
| 56 | /* This offset is used in both open loop and closed loop power control | 58 | /* This offset is used in both open loop and closed loop power control |
| 57 | * schemes. In open loop power control, it is not really needed, but for | 59 | * schemes. In open loop power control, it is not really needed, but for |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 608bb4824e2a..b07f164d65cf 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c | |||
| @@ -364,6 +364,8 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) | |||
| 364 | 364 | ||
| 365 | INIT_INI_ARRAY(&ah->iniModesFastClock, | 365 | INIT_INI_ARRAY(&ah->iniModesFastClock, |
| 366 | ar9565_1p0_modes_fast_clock); | 366 | ar9565_1p0_modes_fast_clock); |
| 367 | INIT_INI_ARRAY(&ah->iniCckfirJapan2484, | ||
| 368 | ar9565_1p0_baseband_core_txfir_coeff_japan_2484); | ||
| 367 | } else { | 369 | } else { |
| 368 | /* mac */ | 370 | /* mac */ |
| 369 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], | 371 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], |
| @@ -628,6 +630,9 @@ static void ar9003_rx_gain_table_mode0(struct ath_hw *ah) | |||
| 628 | else if (AR_SREV_9462_20(ah)) | 630 | else if (AR_SREV_9462_20(ah)) |
| 629 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 631 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
| 630 | ar9462_common_rx_gain_table_2p0); | 632 | ar9462_common_rx_gain_table_2p0); |
| 633 | else if (AR_SREV_9565(ah)) | ||
| 634 | INIT_INI_ARRAY(&ah->iniModesRxGain, | ||
| 635 | ar9565_1p0_Common_rx_gain_table); | ||
| 631 | else | 636 | else |
| 632 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 637 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
| 633 | ar9300Common_rx_gain_table_2p2); | 638 | ar9300Common_rx_gain_table_2p2); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/drivers/net/wireless/ath/ath9k/ar9003_mci.c index 8dd069259e7b..7b94a6c7db3d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mci.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.c | |||
| @@ -753,9 +753,9 @@ int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 753 | 1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT); | 753 | 1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT); |
| 754 | 754 | ||
| 755 | if (caldata) { | 755 | if (caldata) { |
| 756 | caldata->done_txiqcal_once = false; | 756 | clear_bit(TXIQCAL_DONE, &caldata->cal_flags); |
| 757 | caldata->done_txclcal_once = false; | 757 | clear_bit(TXCLCAL_DONE, &caldata->cal_flags); |
| 758 | caldata->rtt_done = false; | 758 | clear_bit(RTT_DONE, &caldata->cal_flags); |
| 759 | } | 759 | } |
| 760 | 760 | ||
| 761 | if (!ath9k_hw_init_cal(ah, chan)) | 761 | if (!ath9k_hw_init_cal(ah, chan)) |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index e897648d3233..11f53589a3f3 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
| @@ -551,8 +551,7 @@ static void ar9003_hw_set_channel_regs(struct ath_hw *ah, | |||
| 551 | if (IS_CHAN_HT40(chan)) { | 551 | if (IS_CHAN_HT40(chan)) { |
| 552 | phymode |= AR_PHY_GC_DYN2040_EN; | 552 | phymode |= AR_PHY_GC_DYN2040_EN; |
| 553 | /* Configure control (primary) channel at +-10MHz */ | 553 | /* Configure control (primary) channel at +-10MHz */ |
| 554 | if ((chan->chanmode == CHANNEL_A_HT40PLUS) || | 554 | if (IS_CHAN_HT40PLUS(chan)) |
| 555 | (chan->chanmode == CHANNEL_G_HT40PLUS)) | ||
| 556 | phymode |= AR_PHY_GC_DYN2040_PRI_CH; | 555 | phymode |= AR_PHY_GC_DYN2040_PRI_CH; |
| 557 | 556 | ||
| 558 | } | 557 | } |
| @@ -565,7 +564,7 @@ static void ar9003_hw_set_channel_regs(struct ath_hw *ah, | |||
| 565 | REG_WRITE(ah, AR_PHY_GEN_CTRL, phymode); | 564 | REG_WRITE(ah, AR_PHY_GEN_CTRL, phymode); |
| 566 | 565 | ||
| 567 | /* Configure MAC for 20/40 operation */ | 566 | /* Configure MAC for 20/40 operation */ |
| 568 | ath9k_hw_set11nmac2040(ah); | 567 | ath9k_hw_set11nmac2040(ah, chan); |
| 569 | 568 | ||
| 570 | /* global transmit timeout (25 TUs default)*/ | 569 | /* global transmit timeout (25 TUs default)*/ |
| 571 | REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S); | 570 | REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S); |
| @@ -627,11 +626,10 @@ static void ar9003_hw_override_ini(struct ath_hw *ah) | |||
| 627 | * MAC addr only will fail. | 626 | * MAC addr only will fail. |
| 628 | */ | 627 | */ |
| 629 | val = REG_READ(ah, AR_PCU_MISC_MODE2) & (~AR_ADHOC_MCAST_KEYID_ENABLE); | 628 | val = REG_READ(ah, AR_PCU_MISC_MODE2) & (~AR_ADHOC_MCAST_KEYID_ENABLE); |
| 630 | REG_WRITE(ah, AR_PCU_MISC_MODE2, | 629 | val |= AR_AGG_WEP_ENABLE_FIX | |
| 631 | val | AR_AGG_WEP_ENABLE_FIX | AR_AGG_WEP_ENABLE); | 630 | AR_AGG_WEP_ENABLE | |
| 632 | 631 | AR_PCU_MISC_MODE2_CFP_IGNORE; | |
| 633 | REG_SET_BIT(ah, AR_PHY_CCK_DETECT, | 632 | REG_WRITE(ah, AR_PCU_MISC_MODE2, val); |
| 634 | AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); | ||
| 635 | 633 | ||
| 636 | if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { | 634 | if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { |
| 637 | REG_WRITE(ah, AR_GLB_SWREG_DISCONT_MODE, | 635 | REG_WRITE(ah, AR_GLB_SWREG_DISCONT_MODE, |
| @@ -683,41 +681,22 @@ static int ar9550_hw_get_modes_txgain_index(struct ath_hw *ah, | |||
| 683 | { | 681 | { |
| 684 | int ret; | 682 | int ret; |
| 685 | 683 | ||
| 686 | switch (chan->chanmode) { | 684 | if (IS_CHAN_2GHZ(chan)) { |
| 687 | case CHANNEL_A: | 685 | if (IS_CHAN_HT40(chan)) |
| 688 | case CHANNEL_A_HT20: | 686 | return 7; |
| 689 | if (chan->channel <= 5350) | ||
| 690 | ret = 1; | ||
| 691 | else if ((chan->channel > 5350) && (chan->channel <= 5600)) | ||
| 692 | ret = 3; | ||
| 693 | else | ||
| 694 | ret = 5; | ||
| 695 | break; | ||
| 696 | |||
| 697 | case CHANNEL_A_HT40PLUS: | ||
| 698 | case CHANNEL_A_HT40MINUS: | ||
| 699 | if (chan->channel <= 5350) | ||
| 700 | ret = 2; | ||
| 701 | else if ((chan->channel > 5350) && (chan->channel <= 5600)) | ||
| 702 | ret = 4; | ||
| 703 | else | 687 | else |
| 704 | ret = 6; | 688 | return 8; |
| 705 | break; | 689 | } |
| 706 | |||
| 707 | case CHANNEL_G: | ||
| 708 | case CHANNEL_G_HT20: | ||
| 709 | case CHANNEL_B: | ||
| 710 | ret = 8; | ||
| 711 | break; | ||
| 712 | 690 | ||
| 713 | case CHANNEL_G_HT40PLUS: | 691 | if (chan->channel <= 5350) |
| 714 | case CHANNEL_G_HT40MINUS: | 692 | ret = 1; |
| 715 | ret = 7; | 693 | else if ((chan->channel > 5350) && (chan->channel <= 5600)) |
| 716 | break; | 694 | ret = 3; |
| 695 | else | ||
| 696 | ret = 5; | ||
| 717 | 697 | ||
| 718 | default: | 698 | if (IS_CHAN_HT40(chan)) |
| 719 | ret = -EINVAL; | 699 | ret++; |
| 720 | } | ||
| 721 | 700 | ||
| 722 | return ret; | 701 | return ret; |
| 723 | } | 702 | } |
| @@ -728,28 +707,10 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, | |||
| 728 | unsigned int regWrites = 0, i; | 707 | unsigned int regWrites = 0, i; |
| 729 | u32 modesIndex; | 708 | u32 modesIndex; |
| 730 | 709 | ||
| 731 | switch (chan->chanmode) { | 710 | if (IS_CHAN_5GHZ(chan)) |
| 732 | case CHANNEL_A: | 711 | modesIndex = IS_CHAN_HT40(chan) ? 2 : 1; |
| 733 | case CHANNEL_A_HT20: | 712 | else |
| 734 | modesIndex = 1; | 713 | modesIndex = IS_CHAN_HT40(chan) ? 3 : 4; |
| 735 | break; | ||
| 736 | case CHANNEL_A_HT40PLUS: | ||
| 737 | case CHANNEL_A_HT40MINUS: | ||
| 738 | modesIndex = 2; | ||
| 739 | break; | ||
| 740 | case CHANNEL_G: | ||
| 741 | case CHANNEL_G_HT20: | ||
| 742 | case CHANNEL_B: | ||
| 743 | modesIndex = 4; | ||
| 744 | break; | ||
| 745 | case CHANNEL_G_HT40PLUS: | ||
| 746 | case CHANNEL_G_HT40MINUS: | ||
| 747 | modesIndex = 3; | ||
| 748 | break; | ||
| 749 | |||
| 750 | default: | ||
| 751 | return -EINVAL; | ||
| 752 | } | ||
| 753 | 714 | ||
| 754 | /* | 715 | /* |
| 755 | * SOC, MAC, BB, RADIO initvals. | 716 | * SOC, MAC, BB, RADIO initvals. |
| @@ -847,8 +808,10 @@ static void ar9003_hw_set_rfmode(struct ath_hw *ah, | |||
| 847 | if (chan == NULL) | 808 | if (chan == NULL) |
| 848 | return; | 809 | return; |
| 849 | 810 | ||
| 850 | rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan)) | 811 | if (IS_CHAN_2GHZ(chan)) |
| 851 | ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; | 812 | rfMode |= AR_PHY_MODE_DYNAMIC; |
| 813 | else | ||
| 814 | rfMode |= AR_PHY_MODE_OFDM; | ||
| 852 | 815 | ||
| 853 | if (IS_CHAN_A_FAST_CLOCK(ah, chan)) | 816 | if (IS_CHAN_A_FAST_CLOCK(ah, chan)) |
| 854 | rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE); | 817 | rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE); |
| @@ -1274,12 +1237,11 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah) | |||
| 1274 | aniState = &ah->ani; | 1237 | aniState = &ah->ani; |
| 1275 | iniDef = &aniState->iniDef; | 1238 | iniDef = &aniState->iniDef; |
| 1276 | 1239 | ||
| 1277 | ath_dbg(common, ANI, "ver %d.%d opmode %u chan %d Mhz/0x%x\n", | 1240 | ath_dbg(common, ANI, "ver %d.%d opmode %u chan %d Mhz\n", |
| 1278 | ah->hw_version.macVersion, | 1241 | ah->hw_version.macVersion, |
| 1279 | ah->hw_version.macRev, | 1242 | ah->hw_version.macRev, |
| 1280 | ah->opmode, | 1243 | ah->opmode, |
| 1281 | chan->channel, | 1244 | chan->channel); |
| 1282 | chan->channelFlags); | ||
| 1283 | 1245 | ||
| 1284 | val = REG_READ(ah, AR_PHY_SFCORR); | 1246 | val = REG_READ(ah, AR_PHY_SFCORR); |
| 1285 | iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH); | 1247 | iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH); |
| @@ -1375,15 +1337,19 @@ static void ar9003_hw_antdiv_comb_conf_get(struct ath_hw *ah, | |||
| 1375 | AR_PHY_ANT_FAST_DIV_BIAS_S; | 1337 | AR_PHY_ANT_FAST_DIV_BIAS_S; |
| 1376 | 1338 | ||
| 1377 | if (AR_SREV_9330_11(ah)) { | 1339 | if (AR_SREV_9330_11(ah)) { |
| 1340 | antconf->lna1_lna2_switch_delta = -1; | ||
| 1378 | antconf->lna1_lna2_delta = -9; | 1341 | antconf->lna1_lna2_delta = -9; |
| 1379 | antconf->div_group = 1; | 1342 | antconf->div_group = 1; |
| 1380 | } else if (AR_SREV_9485(ah)) { | 1343 | } else if (AR_SREV_9485(ah)) { |
| 1344 | antconf->lna1_lna2_switch_delta = -1; | ||
| 1381 | antconf->lna1_lna2_delta = -9; | 1345 | antconf->lna1_lna2_delta = -9; |
| 1382 | antconf->div_group = 2; | 1346 | antconf->div_group = 2; |
| 1383 | } else if (AR_SREV_9565(ah)) { | 1347 | } else if (AR_SREV_9565(ah)) { |
| 1384 | antconf->lna1_lna2_delta = -3; | 1348 | antconf->lna1_lna2_switch_delta = 3; |
| 1349 | antconf->lna1_lna2_delta = -9; | ||
| 1385 | antconf->div_group = 3; | 1350 | antconf->div_group = 3; |
| 1386 | } else { | 1351 | } else { |
| 1352 | antconf->lna1_lna2_switch_delta = -1; | ||
| 1387 | antconf->lna1_lna2_delta = -3; | 1353 | antconf->lna1_lna2_delta = -3; |
| 1388 | antconf->div_group = 0; | 1354 | antconf->div_group = 0; |
| 1389 | } | 1355 | } |
| @@ -1489,17 +1455,24 @@ static void ar9003_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable) | |||
| 1489 | } else if (AR_SREV_9565(ah)) { | 1455 | } else if (AR_SREV_9565(ah)) { |
| 1490 | if (enable) { | 1456 | if (enable) { |
| 1491 | REG_SET_BIT(ah, AR_PHY_MC_GAIN_CTRL, | 1457 | REG_SET_BIT(ah, AR_PHY_MC_GAIN_CTRL, |
| 1458 | AR_ANT_DIV_ENABLE); | ||
| 1459 | REG_SET_BIT(ah, AR_PHY_MC_GAIN_CTRL, | ||
| 1492 | (1 << AR_PHY_ANT_SW_RX_PROT_S)); | 1460 | (1 << AR_PHY_ANT_SW_RX_PROT_S)); |
| 1493 | if (ah->curchan && IS_CHAN_2GHZ(ah->curchan)) | 1461 | REG_SET_BIT(ah, AR_PHY_CCK_DETECT, |
| 1494 | REG_SET_BIT(ah, AR_PHY_RESTART, | 1462 | AR_FAST_DIV_ENABLE); |
| 1495 | AR_PHY_RESTART_ENABLE_DIV_M2FLAG); | 1463 | REG_SET_BIT(ah, AR_PHY_RESTART, |
| 1464 | AR_PHY_RESTART_ENABLE_DIV_M2FLAG); | ||
| 1496 | REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, | 1465 | REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, |
| 1497 | AR_BTCOEX_WL_LNADIV_FORCE_ON); | 1466 | AR_BTCOEX_WL_LNADIV_FORCE_ON); |
| 1498 | } else { | 1467 | } else { |
| 1499 | REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL, AR_ANT_DIV_ENABLE); | 1468 | REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL, |
| 1469 | AR_ANT_DIV_ENABLE); | ||
| 1500 | REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL, | 1470 | REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL, |
| 1501 | (1 << AR_PHY_ANT_SW_RX_PROT_S)); | 1471 | (1 << AR_PHY_ANT_SW_RX_PROT_S)); |
| 1502 | REG_CLR_BIT(ah, AR_PHY_CCK_DETECT, AR_FAST_DIV_ENABLE); | 1472 | REG_CLR_BIT(ah, AR_PHY_CCK_DETECT, |
| 1473 | AR_FAST_DIV_ENABLE); | ||
| 1474 | REG_CLR_BIT(ah, AR_PHY_RESTART, | ||
| 1475 | AR_PHY_RESTART_ENABLE_DIV_M2FLAG); | ||
| 1503 | REG_CLR_BIT(ah, AR_BTCOEX_WL_LNADIV, | 1476 | REG_CLR_BIT(ah, AR_BTCOEX_WL_LNADIV, |
| 1504 | AR_BTCOEX_WL_LNADIV_FORCE_ON); | 1477 | AR_BTCOEX_WL_LNADIV_FORCE_ON); |
| 1505 | 1478 | ||
| @@ -1526,28 +1499,10 @@ static int ar9003_hw_fast_chan_change(struct ath_hw *ah, | |||
| 1526 | unsigned int regWrites = 0; | 1499 | unsigned int regWrites = 0; |
| 1527 | u32 modesIndex; | 1500 | u32 modesIndex; |
| 1528 | 1501 | ||
| 1529 | switch (chan->chanmode) { | 1502 | if (IS_CHAN_5GHZ(chan)) |
| 1530 | case CHANNEL_A: | 1503 | modesIndex = IS_CHAN_HT40(chan) ? 2 : 1; |
| 1531 | case CHANNEL_A_HT20: | 1504 | else |
| 1532 | modesIndex = 1; | 1505 | modesIndex = IS_CHAN_HT40(chan) ? 3 : 4; |
| 1533 | break; | ||
| 1534 | case CHANNEL_A_HT40PLUS: | ||
| 1535 | case CHANNEL_A_HT40MINUS: | ||
| 1536 | modesIndex = 2; | ||
| 1537 | break; | ||
| 1538 | case CHANNEL_G: | ||
| 1539 | case CHANNEL_G_HT20: | ||
| 1540 | case CHANNEL_B: | ||
| 1541 | modesIndex = 4; | ||
| 1542 | break; | ||
| 1543 | case CHANNEL_G_HT40PLUS: | ||
| 1544 | case CHANNEL_G_HT40MINUS: | ||
| 1545 | modesIndex = 3; | ||
| 1546 | break; | ||
| 1547 | |||
| 1548 | default: | ||
| 1549 | return -EINVAL; | ||
| 1550 | } | ||
| 1551 | 1506 | ||
| 1552 | if (modesIndex == ah->modes_index) { | 1507 | if (modesIndex == ah->modes_index) { |
| 1553 | *ini_reloaded = false; | 1508 | *ini_reloaded = false; |
| @@ -1662,6 +1617,98 @@ static void ar9003_hw_spectral_scan_wait(struct ath_hw *ah) | |||
| 1662 | } | 1617 | } |
| 1663 | } | 1618 | } |
| 1664 | 1619 | ||
| 1620 | static void ar9003_hw_tx99_start(struct ath_hw *ah, u32 qnum) | ||
| 1621 | { | ||
| 1622 | REG_SET_BIT(ah, AR_PHY_TEST, PHY_AGC_CLR); | ||
| 1623 | REG_SET_BIT(ah, 0x9864, 0x7f000); | ||
| 1624 | REG_SET_BIT(ah, 0x9924, 0x7f00fe); | ||
| 1625 | REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); | ||
| 1626 | REG_WRITE(ah, AR_CR, AR_CR_RXD); | ||
| 1627 | REG_WRITE(ah, AR_DLCL_IFS(qnum), 0); | ||
| 1628 | REG_WRITE(ah, AR_D_GBL_IFS_SIFS, 20); /* 50 OK */ | ||
| 1629 | REG_WRITE(ah, AR_D_GBL_IFS_EIFS, 20); | ||
| 1630 | REG_WRITE(ah, AR_TIME_OUT, 0x00000400); | ||
| 1631 | REG_WRITE(ah, AR_DRETRY_LIMIT(qnum), 0xffffffff); | ||
| 1632 | REG_SET_BIT(ah, AR_QMISC(qnum), AR_Q_MISC_DCU_EARLY_TERM_REQ); | ||
| 1633 | } | ||
| 1634 | |||
| 1635 | static void ar9003_hw_tx99_stop(struct ath_hw *ah) | ||
| 1636 | { | ||
| 1637 | REG_CLR_BIT(ah, AR_PHY_TEST, PHY_AGC_CLR); | ||
| 1638 | REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); | ||
| 1639 | } | ||
| 1640 | |||
| 1641 | static void ar9003_hw_tx99_set_txpower(struct ath_hw *ah, u8 txpower) | ||
| 1642 | { | ||
| 1643 | static s16 p_pwr_array[ar9300RateSize] = { 0 }; | ||
| 1644 | unsigned int i; | ||
| 1645 | |||
| 1646 | if (txpower <= MAX_RATE_POWER) { | ||
| 1647 | for (i = 0; i < ar9300RateSize; i++) | ||
| 1648 | p_pwr_array[i] = txpower; | ||
| 1649 | } else { | ||
| 1650 | for (i = 0; i < ar9300RateSize; i++) | ||
| 1651 | p_pwr_array[i] = MAX_RATE_POWER; | ||
| 1652 | } | ||
| 1653 | |||
| 1654 | REG_WRITE(ah, 0xa458, 0); | ||
| 1655 | |||
| 1656 | REG_WRITE(ah, 0xa3c0, | ||
| 1657 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 24) | | ||
| 1658 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 16) | | ||
| 1659 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 8) | | ||
| 1660 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 0)); | ||
| 1661 | REG_WRITE(ah, 0xa3c4, | ||
| 1662 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_54], 24) | | ||
| 1663 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_48], 16) | | ||
| 1664 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_36], 8) | | ||
| 1665 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 0)); | ||
| 1666 | REG_WRITE(ah, 0xa3c8, | ||
| 1667 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 24) | | ||
| 1668 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 16) | | ||
| 1669 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 0)); | ||
| 1670 | REG_WRITE(ah, 0xa3cc, | ||
| 1671 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_11S], 24) | | ||
| 1672 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_11L], 16) | | ||
| 1673 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_5S], 8) | | ||
| 1674 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 0)); | ||
| 1675 | REG_WRITE(ah, 0xa3d0, | ||
| 1676 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_5], 24) | | ||
| 1677 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_4], 16) | | ||
| 1678 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_1_3_9_11_17_19], 8)| | ||
| 1679 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_0_8_16], 0)); | ||
| 1680 | REG_WRITE(ah, 0xa3d4, | ||
| 1681 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_13], 24) | | ||
| 1682 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_12], 16) | | ||
| 1683 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_7], 8) | | ||
| 1684 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_6], 0)); | ||
| 1685 | REG_WRITE(ah, 0xa3e4, | ||
| 1686 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_21], 24) | | ||
| 1687 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_20], 16) | | ||
| 1688 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_15], 8) | | ||
| 1689 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_14], 0)); | ||
| 1690 | REG_WRITE(ah, 0xa3e8, | ||
| 1691 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_23], 24) | | ||
| 1692 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_22], 16) | | ||
| 1693 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_23], 8) | | ||
| 1694 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT20_22], 0)); | ||
| 1695 | REG_WRITE(ah, 0xa3d8, | ||
| 1696 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_5], 24) | | ||
| 1697 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_4], 16) | | ||
| 1698 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_1_3_9_11_17_19], 8) | | ||
| 1699 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_0_8_16], 0)); | ||
| 1700 | REG_WRITE(ah, 0xa3dc, | ||
| 1701 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_13], 24) | | ||
| 1702 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_12], 16) | | ||
| 1703 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_7], 8) | | ||
| 1704 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_6], 0)); | ||
| 1705 | REG_WRITE(ah, 0xa3ec, | ||
| 1706 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_21], 24) | | ||
| 1707 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_20], 16) | | ||
| 1708 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_15], 8) | | ||
| 1709 | ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_14], 0)); | ||
| 1710 | } | ||
| 1711 | |||
| 1665 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | 1712 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah) |
| 1666 | { | 1713 | { |
| 1667 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | 1714 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); |
| @@ -1701,6 +1748,9 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | |||
| 1701 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | 1748 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT |
| 1702 | ops->set_bt_ant_diversity = ar9003_hw_set_bt_ant_diversity; | 1749 | ops->set_bt_ant_diversity = ar9003_hw_set_bt_ant_diversity; |
| 1703 | #endif | 1750 | #endif |
| 1751 | ops->tx99_start = ar9003_hw_tx99_start; | ||
| 1752 | ops->tx99_stop = ar9003_hw_tx99_stop; | ||
| 1753 | ops->tx99_set_txpower = ar9003_hw_tx99_set_txpower; | ||
| 1704 | 1754 | ||
| 1705 | ar9003_hw_set_nf_limits(ah); | 1755 | ar9003_hw_set_nf_limits(ah); |
| 1706 | ar9003_hw_set_radar_conf(ah); | 1756 | ar9003_hw_set_radar_conf(ah); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 6fd752321e36..fca624322dc8 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h | |||
| @@ -343,8 +343,12 @@ | |||
| 343 | 343 | ||
| 344 | #define AR_PHY_CCA_NOM_VAL_9462_2GHZ -127 | 344 | #define AR_PHY_CCA_NOM_VAL_9462_2GHZ -127 |
| 345 | #define AR_PHY_CCA_MIN_GOOD_VAL_9462_2GHZ -127 | 345 | #define AR_PHY_CCA_MIN_GOOD_VAL_9462_2GHZ -127 |
| 346 | #define AR_PHY_CCA_MAX_GOOD_VAL_9462_2GHZ -60 | ||
| 347 | #define AR_PHY_CCA_MAX_GOOD_VAL_9462_FCC_2GHZ -95 | ||
| 346 | #define AR_PHY_CCA_NOM_VAL_9462_5GHZ -127 | 348 | #define AR_PHY_CCA_NOM_VAL_9462_5GHZ -127 |
| 347 | #define AR_PHY_CCA_MIN_GOOD_VAL_9462_5GHZ -127 | 349 | #define AR_PHY_CCA_MIN_GOOD_VAL_9462_5GHZ -127 |
| 350 | #define AR_PHY_CCA_MAX_GOOD_VAL_9462_5GHZ -60 | ||
| 351 | #define AR_PHY_CCA_MAX_GOOD_VAL_9462_FCC_5GHZ -100 | ||
| 348 | 352 | ||
| 349 | #define AR_PHY_CCA_NOM_VAL_9330_2GHZ -118 | 353 | #define AR_PHY_CCA_NOM_VAL_9330_2GHZ -118 |
| 350 | 354 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_rtt.c b/drivers/net/wireless/ath/ath9k/ar9003_rtt.c index 74de3539c2c8..934418872e8e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_rtt.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_rtt.c | |||
| @@ -118,6 +118,27 @@ void ar9003_hw_rtt_load_hist(struct ath_hw *ah) | |||
| 118 | } | 118 | } |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | static void ar9003_hw_patch_rtt(struct ath_hw *ah, int index, int chain) | ||
| 122 | { | ||
| 123 | int agc, caldac; | ||
| 124 | |||
| 125 | if (!test_bit(SW_PKDET_DONE, &ah->caldata->cal_flags)) | ||
| 126 | return; | ||
| 127 | |||
| 128 | if ((index != 5) || (chain >= 2)) | ||
| 129 | return; | ||
| 130 | |||
| 131 | agc = REG_READ_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), | ||
| 132 | AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE); | ||
| 133 | if (!agc) | ||
| 134 | return; | ||
| 135 | |||
| 136 | caldac = ah->caldata->caldac[chain]; | ||
| 137 | ah->caldata->rtt_table[chain][index] &= 0xFFFF05FF; | ||
| 138 | caldac = (caldac & 0x20) | ((caldac & 0x1F) << 7); | ||
| 139 | ah->caldata->rtt_table[chain][index] |= (caldac << 4); | ||
| 140 | } | ||
| 141 | |||
| 121 | static int ar9003_hw_rtt_fill_hist_entry(struct ath_hw *ah, u8 chain, u32 index) | 142 | static int ar9003_hw_rtt_fill_hist_entry(struct ath_hw *ah, u8 chain, u32 index) |
| 122 | { | 143 | { |
| 123 | u32 val; | 144 | u32 val; |
| @@ -155,13 +176,16 @@ void ar9003_hw_rtt_fill_hist(struct ath_hw *ah) | |||
| 155 | for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) { | 176 | for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) { |
| 156 | ah->caldata->rtt_table[chain][i] = | 177 | ah->caldata->rtt_table[chain][i] = |
| 157 | ar9003_hw_rtt_fill_hist_entry(ah, chain, i); | 178 | ar9003_hw_rtt_fill_hist_entry(ah, chain, i); |
| 179 | |||
| 180 | ar9003_hw_patch_rtt(ah, i, chain); | ||
| 181 | |||
| 158 | ath_dbg(ath9k_hw_common(ah), CALIBRATE, | 182 | ath_dbg(ath9k_hw_common(ah), CALIBRATE, |
| 159 | "RTT value at idx %d, chain %d is: 0x%x\n", | 183 | "RTT value at idx %d, chain %d is: 0x%x\n", |
| 160 | i, chain, ah->caldata->rtt_table[chain][i]); | 184 | i, chain, ah->caldata->rtt_table[chain][i]); |
| 161 | } | 185 | } |
| 162 | } | 186 | } |
| 163 | 187 | ||
| 164 | ah->caldata->rtt_done = true; | 188 | set_bit(RTT_DONE, &ah->caldata->cal_flags); |
| 165 | } | 189 | } |
| 166 | 190 | ||
| 167 | void ar9003_hw_rtt_clear_hist(struct ath_hw *ah) | 191 | void ar9003_hw_rtt_clear_hist(struct ath_hw *ah) |
| @@ -176,7 +200,7 @@ void ar9003_hw_rtt_clear_hist(struct ath_hw *ah) | |||
| 176 | } | 200 | } |
| 177 | 201 | ||
| 178 | if (ah->caldata) | 202 | if (ah->caldata) |
| 179 | ah->caldata->rtt_done = false; | 203 | clear_bit(RTT_DONE, &ah->caldata->cal_flags); |
| 180 | } | 204 | } |
| 181 | 205 | ||
| 182 | bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan) | 206 | bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan) |
| @@ -186,11 +210,37 @@ bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan) | |||
| 186 | if (!ah->caldata) | 210 | if (!ah->caldata) |
| 187 | return false; | 211 | return false; |
| 188 | 212 | ||
| 189 | if (!ah->caldata->rtt_done) | 213 | if (test_bit(SW_PKDET_DONE, &ah->caldata->cal_flags)) { |
| 214 | if (IS_CHAN_2GHZ(chan)){ | ||
| 215 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(0), | ||
| 216 | AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, | ||
| 217 | ah->caldata->caldac[0]); | ||
| 218 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(1), | ||
| 219 | AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, | ||
| 220 | ah->caldata->caldac[1]); | ||
| 221 | } else { | ||
| 222 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(0), | ||
| 223 | AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR, | ||
| 224 | ah->caldata->caldac[0]); | ||
| 225 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(1), | ||
| 226 | AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR, | ||
| 227 | ah->caldata->caldac[1]); | ||
| 228 | } | ||
| 229 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(1), | ||
| 230 | AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE, 0x1); | ||
| 231 | REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(0), | ||
| 232 | AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE, 0x1); | ||
| 233 | } | ||
| 234 | |||
| 235 | if (!test_bit(RTT_DONE, &ah->caldata->cal_flags)) | ||
| 190 | return false; | 236 | return false; |
| 191 | 237 | ||
| 192 | ar9003_hw_rtt_enable(ah); | 238 | ar9003_hw_rtt_enable(ah); |
| 193 | ar9003_hw_rtt_set_mask(ah, 0x10); | 239 | |
| 240 | if (test_bit(SW_PKDET_DONE, &ah->caldata->cal_flags)) | ||
| 241 | ar9003_hw_rtt_set_mask(ah, 0x30); | ||
| 242 | else | ||
| 243 | ar9003_hw_rtt_set_mask(ah, 0x10); | ||
| 194 | 244 | ||
| 195 | if (!ath9k_hw_rfbus_req(ah)) { | 245 | if (!ath9k_hw_rfbus_req(ah)) { |
| 196 | ath_err(ath9k_hw_common(ah), "Could not stop baseband\n"); | 246 | ath_err(ath9k_hw_common(ah), "Could not stop baseband\n"); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h index 88ff1d7b53ab..6f899c692647 100644 --- a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h | |||
| @@ -20,7 +20,17 @@ | |||
| 20 | 20 | ||
| 21 | /* AR9485 1.1 */ | 21 | /* AR9485 1.1 */ |
| 22 | 22 | ||
| 23 | #define ar9485_1_1_mac_postamble ar9300_2p2_mac_postamble | 23 | static const u32 ar9485_1_1_mac_postamble[][5] = { |
| 24 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
| 25 | {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, | ||
| 26 | {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, | ||
| 27 | {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, | ||
| 28 | {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, | ||
| 29 | {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, | ||
| 30 | {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, | ||
| 31 | {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, | ||
| 32 | {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, | ||
| 33 | }; | ||
| 24 | 34 | ||
| 25 | static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1[][2] = { | 35 | static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1[][2] = { |
| 26 | /* Addr allmodes */ | 36 | /* Addr allmodes */ |
| @@ -34,6 +44,7 @@ static const u32 ar9485Common_wo_xlna_rx_gain_1_1[][2] = { | |||
| 34 | {0x00009e00, 0x037216a0}, | 44 | {0x00009e00, 0x037216a0}, |
| 35 | {0x00009e04, 0x00182020}, | 45 | {0x00009e04, 0x00182020}, |
| 36 | {0x00009e18, 0x00000000}, | 46 | {0x00009e18, 0x00000000}, |
| 47 | {0x00009e20, 0x000003a8}, | ||
| 37 | {0x00009e2c, 0x00004121}, | 48 | {0x00009e2c, 0x00004121}, |
| 38 | {0x00009e44, 0x02282324}, | 49 | {0x00009e44, 0x02282324}, |
| 39 | {0x0000a000, 0x00060005}, | 50 | {0x0000a000, 0x00060005}, |
| @@ -174,7 +185,7 @@ static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = { | |||
| 174 | {0x0000a2e0, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552}, | 185 | {0x0000a2e0, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552}, |
| 175 | {0x0000a2e4, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552}, | 186 | {0x0000a2e4, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552}, |
| 176 | {0x0000a2e8, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552}, | 187 | {0x0000a2e8, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552}, |
| 177 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, | 188 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050da, 0x000050da}, |
| 178 | {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 189 | {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
| 179 | {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, | 190 | {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, |
| 180 | {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, | 191 | {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, |
| @@ -200,14 +211,14 @@ static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = { | |||
| 200 | {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, | 211 | {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, |
| 201 | {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, | 212 | {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, |
| 202 | {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, | 213 | {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, |
| 203 | {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, | 214 | {0x0000a560, 0x900fff0b, 0x900fff0b, 0x62001eee, 0x62001eee}, |
| 204 | {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, | 215 | {0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001ff6, 0x66001ff6}, |
| 205 | {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | 216 | {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001ff6, 0x66001ff6}, |
| 206 | {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | 217 | {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001ff6, 0x66001ff6}, |
| 207 | {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | 218 | {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001ff6, 0x66001ff6}, |
| 208 | {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | 219 | {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001ff6, 0x66001ff6}, |
| 209 | {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | 220 | {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001ff6, 0x66001ff6}, |
| 210 | {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | 221 | {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001ff6, 0x66001ff6}, |
| 211 | {0x0000a580, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 222 | {0x0000a580, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
| 212 | {0x0000a584, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 223 | {0x0000a584, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
| 213 | {0x0000a588, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 224 | {0x0000a588, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
| @@ -263,6 +274,11 @@ static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = { | |||
| 263 | static const u32 ar9485Modes_green_ob_db_tx_gain_1_1[][5] = { | 274 | static const u32 ar9485Modes_green_ob_db_tx_gain_1_1[][5] = { |
| 264 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 275 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
| 265 | {0x000098bc, 0x00000003, 0x00000003, 0x00000003, 0x00000003}, | 276 | {0x000098bc, 0x00000003, 0x00000003, 0x00000003, 0x00000003}, |
| 277 | {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0x7999a83a, 0x7999a83a}, | ||
| 278 | {0x0000a2dc, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552}, | ||
| 279 | {0x0000a2e0, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552}, | ||
| 280 | {0x0000a2e4, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552}, | ||
| 281 | {0x0000a2e8, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552}, | ||
| 266 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, | 282 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, |
| 267 | {0x0000a458, 0x80000000, 0x80000000, 0x80000000, 0x80000000}, | 283 | {0x0000a458, 0x80000000, 0x80000000, 0x80000000, 0x80000000}, |
| 268 | {0x0000a500, 0x00022200, 0x00022200, 0x00000006, 0x00000006}, | 284 | {0x0000a500, 0x00022200, 0x00022200, 0x00000006, 0x00000006}, |
| @@ -297,6 +313,22 @@ static const u32 ar9485Modes_green_ob_db_tx_gain_1_1[][5] = { | |||
| 297 | {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | 313 | {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, |
| 298 | {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | 314 | {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, |
| 299 | {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | 315 | {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, |
| 316 | {0x0000a580, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 317 | {0x0000a584, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 318 | {0x0000a588, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 319 | {0x0000a58c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 320 | {0x0000a590, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 321 | {0x0000a594, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 322 | {0x0000a598, 0x00000000, 0x00000000, 0x01404501, 0x01404501}, | ||
| 323 | {0x0000a59c, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02}, | ||
| 324 | {0x0000a5a0, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02}, | ||
| 325 | {0x0000a5a4, 0x00000000, 0x00000000, 0x02808803, 0x02808803}, | ||
| 326 | {0x0000a5a8, 0x00000000, 0x00000000, 0x04c14b04, 0x04c14b04}, | ||
| 327 | {0x0000a5ac, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305}, | ||
| 328 | {0x0000a5b0, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305}, | ||
| 329 | {0x0000a5b4, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305}, | ||
| 330 | {0x0000a5b8, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305}, | ||
| 331 | {0x0000a5bc, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305}, | ||
| 300 | {0x0000b500, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | 332 | {0x0000b500, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, |
| 301 | {0x0000b504, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | 333 | {0x0000b504, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, |
| 302 | {0x0000b508, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | 334 | {0x0000b508, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, |
| @@ -341,6 +373,100 @@ static const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = { | |||
| 341 | {0x0000a2e0, 0x00000000, 0x00000000, 0xffc63a84, 0xffc63a84}, | 373 | {0x0000a2e0, 0x00000000, 0x00000000, 0xffc63a84, 0xffc63a84}, |
| 342 | {0x0000a2e4, 0x00000000, 0x00000000, 0xfe0fc000, 0xfe0fc000}, | 374 | {0x0000a2e4, 0x00000000, 0x00000000, 0xfe0fc000, 0xfe0fc000}, |
| 343 | {0x0000a2e8, 0x00000000, 0x00000000, 0xfff00000, 0xfff00000}, | 375 | {0x0000a2e8, 0x00000000, 0x00000000, 0xfff00000, 0xfff00000}, |
| 376 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050da, 0x000050da}, | ||
| 377 | {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 378 | {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, | ||
| 379 | {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, | ||
| 380 | {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, | ||
| 381 | {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, | ||
| 382 | {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, | ||
| 383 | {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, | ||
| 384 | {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, | ||
| 385 | {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, | ||
| 386 | {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603}, | ||
| 387 | {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605}, | ||
| 388 | {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03}, | ||
| 389 | {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04}, | ||
| 390 | {0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20}, | ||
| 391 | {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21}, | ||
| 392 | {0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62}, | ||
| 393 | {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63}, | ||
| 394 | {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65}, | ||
| 395 | {0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66}, | ||
| 396 | {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645}, | ||
| 397 | {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, | ||
| 398 | {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, | ||
| 399 | {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, | ||
| 400 | {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, | ||
| 401 | {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, | ||
| 402 | {0x0000a560, 0x900fff0b, 0x900fff0b, 0x62001eee, 0x62001eee}, | ||
| 403 | {0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001ff6, 0x66001ff6}, | ||
| 404 | {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001ff6, 0x66001ff6}, | ||
| 405 | {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001ff6, 0x66001ff6}, | ||
| 406 | {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001ff6, 0x66001ff6}, | ||
| 407 | {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001ff6, 0x66001ff6}, | ||
| 408 | {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001ff6, 0x66001ff6}, | ||
| 409 | {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001ff6, 0x66001ff6}, | ||
| 410 | {0x0000a580, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 411 | {0x0000a584, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 412 | {0x0000a588, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 413 | {0x0000a58c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 414 | {0x0000a590, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 415 | {0x0000a594, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 416 | {0x0000a598, 0x00000000, 0x00000000, 0x01404501, 0x01404501}, | ||
| 417 | {0x0000a59c, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02}, | ||
| 418 | {0x0000a5a0, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02}, | ||
| 419 | {0x0000a5a4, 0x00000000, 0x00000000, 0x02808803, 0x02808803}, | ||
| 420 | {0x0000a5a8, 0x00000000, 0x00000000, 0x04c14b04, 0x04c14b04}, | ||
| 421 | {0x0000a5ac, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305}, | ||
| 422 | {0x0000a5b0, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305}, | ||
| 423 | {0x0000a5b4, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305}, | ||
| 424 | {0x0000a5b8, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305}, | ||
| 425 | {0x0000a5bc, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305}, | ||
| 426 | {0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 427 | {0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 428 | {0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 429 | {0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 430 | {0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 431 | {0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 432 | {0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 433 | {0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 434 | {0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 435 | {0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 436 | {0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 437 | {0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 438 | {0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 439 | {0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 440 | {0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 441 | {0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 442 | {0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 443 | {0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 444 | {0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 445 | {0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 446 | {0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 447 | {0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 448 | {0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 449 | {0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 450 | {0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 451 | {0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 452 | {0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 453 | {0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 454 | {0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 455 | {0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 456 | {0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 457 | {0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 458 | {0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db}, | ||
| 459 | {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260}, | ||
| 460 | }; | ||
| 461 | |||
| 462 | static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = { | ||
| 463 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
| 464 | {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, | ||
| 465 | {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0x7999a83a, 0x7999a83a}, | ||
| 466 | {0x0000a2dc, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552}, | ||
| 467 | {0x0000a2e0, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552}, | ||
| 468 | {0x0000a2e4, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552}, | ||
| 469 | {0x0000a2e8, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552}, | ||
| 344 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, | 470 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, |
| 345 | {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 471 | {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
| 346 | {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, | 472 | {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, |
| @@ -427,7 +553,7 @@ static const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = { | |||
| 427 | {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260}, | 553 | {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260}, |
| 428 | }; | 554 | }; |
| 429 | 555 | ||
| 430 | static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = { | 556 | static const u32 ar9485_modes_lowest_ob_db_tx_gain_1_1[][5] = { |
| 431 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 557 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
| 432 | {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, | 558 | {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, |
| 433 | {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0x7999a83a, 0x7999a83a}, | 559 | {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0x7999a83a, 0x7999a83a}, |
| @@ -521,12 +647,15 @@ static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = { | |||
| 521 | {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260}, | 647 | {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260}, |
| 522 | }; | 648 | }; |
| 523 | 649 | ||
| 524 | #define ar9485_modes_lowest_ob_db_tx_gain_1_1 ar9485Modes_low_ob_db_tx_gain_1_1 | ||
| 525 | |||
| 526 | static const u32 ar9485Modes_green_spur_ob_db_tx_gain_1_1[][5] = { | 650 | static const u32 ar9485Modes_green_spur_ob_db_tx_gain_1_1[][5] = { |
| 527 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 651 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
| 528 | {0x000098bc, 0x00000003, 0x00000003, 0x00000003, 0x00000003}, | 652 | {0x000098bc, 0x00000003, 0x00000003, 0x00000003, 0x00000003}, |
| 529 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, | 653 | {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0x7999a83a, 0x7999a83a}, |
| 654 | {0x0000a2dc, 0x00000000, 0x00000000, 0xffad452a, 0xffad452a}, | ||
| 655 | {0x0000a2e0, 0x00000000, 0x00000000, 0xffc98634, 0xffc98634}, | ||
| 656 | {0x0000a2e4, 0x00000000, 0x00000000, 0xfff60780, 0xfff60780}, | ||
| 657 | {0x0000a2e8, 0x00000000, 0x00000000, 0xfffff800, 0xfffff800}, | ||
| 658 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | ||
| 530 | {0x0000a458, 0x80000000, 0x80000000, 0x80000000, 0x80000000}, | 659 | {0x0000a458, 0x80000000, 0x80000000, 0x80000000, 0x80000000}, |
| 531 | {0x0000a500, 0x00022200, 0x00022200, 0x00000006, 0x00000006}, | 660 | {0x0000a500, 0x00022200, 0x00022200, 0x00000006, 0x00000006}, |
| 532 | {0x0000a504, 0x05062002, 0x05062002, 0x03000201, 0x03000201}, | 661 | {0x0000a504, 0x05062002, 0x05062002, 0x03000201, 0x03000201}, |
| @@ -543,23 +672,39 @@ static const u32 ar9485Modes_green_spur_ob_db_tx_gain_1_1[][5] = { | |||
| 543 | {0x0000a530, 0x48023ec6, 0x48023ec6, 0x310006e0, 0x310006e0}, | 672 | {0x0000a530, 0x48023ec6, 0x48023ec6, 0x310006e0, 0x310006e0}, |
| 544 | {0x0000a534, 0x4d023f01, 0x4d023f01, 0x330006e0, 0x330006e0}, | 673 | {0x0000a534, 0x4d023f01, 0x4d023f01, 0x330006e0, 0x330006e0}, |
| 545 | {0x0000a538, 0x53023f4b, 0x53023f4b, 0x3e0008e3, 0x3e0008e3}, | 674 | {0x0000a538, 0x53023f4b, 0x53023f4b, 0x3e0008e3, 0x3e0008e3}, |
| 546 | {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x410008e5, 0x410008e5}, | 675 | {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x430008e6, 0x430008e6}, |
| 547 | {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x430008e6, 0x430008e6}, | 676 | {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4a0008ec, 0x4a0008ec}, |
| 548 | {0x0000a544, 0x6502feca, 0x6502feca, 0x4a0008ec, 0x4a0008ec}, | 677 | {0x0000a544, 0x6502feca, 0x6502feca, 0x4e0008f1, 0x4e0008f1}, |
| 549 | {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4e0008f1, 0x4e0008f1}, | 678 | {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x520008f3, 0x520008f3}, |
| 550 | {0x0000a54c, 0x7203feca, 0x7203feca, 0x520008f3, 0x520008f3}, | 679 | {0x0000a54c, 0x7203feca, 0x7203feca, 0x54000eed, 0x54000eed}, |
| 551 | {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x54000eed, 0x54000eed}, | 680 | {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x58000ef1, 0x58000ef1}, |
| 552 | {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x58000ef1, 0x58000ef1}, | 681 | {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5c000ef3, 0x5c000ef3}, |
| 553 | {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5c000ef3, 0x5c000ef3}, | 682 | {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x62000ef6, 0x62000ef6}, |
| 554 | {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x60000ef5, 0x60000ef5}, | 683 | {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001ff0, 0x66001ff0}, |
| 555 | {0x0000a560, 0x900fff0b, 0x900fff0b, 0x62000ef6, 0x62000ef6}, | 684 | {0x0000a560, 0x900fff0b, 0x900fff0b, 0x68001ff6, 0x68001ff6}, |
| 556 | {0x0000a564, 0x960fffcb, 0x960fffcb, 0x62000ef6, 0x62000ef6}, | 685 | {0x0000a564, 0x960fffcb, 0x960fffcb, 0x68001ff6, 0x68001ff6}, |
| 557 | {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x62000ef6, 0x62000ef6}, | 686 | {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x68001ff6, 0x68001ff6}, |
| 558 | {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x62000ef6, 0x62000ef6}, | 687 | {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x68001ff6, 0x68001ff6}, |
| 559 | {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x62000ef6, 0x62000ef6}, | 688 | {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x68001ff6, 0x68001ff6}, |
| 560 | {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x62000ef6, 0x62000ef6}, | 689 | {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x68001ff6, 0x68001ff6}, |
| 561 | {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x62000ef6, 0x62000ef6}, | 690 | {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x68001ff6, 0x68001ff6}, |
| 562 | {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x62000ef6, 0x62000ef6}, | 691 | {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x68001ff6, 0x68001ff6}, |
| 692 | {0x0000a580, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 693 | {0x0000a584, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 694 | {0x0000a588, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
| 695 | {0x0000a58c, 0x00000000, 0x00000000, 0x01804000, 0x01804000}, | ||
| 696 | {0x0000a590, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02}, | ||
| 697 | {0x0000a594, 0x00000000, 0x00000000, 0x0340ca02, 0x0340ca02}, | ||
| 698 | {0x0000a598, 0x00000000, 0x00000000, 0x0340cd03, 0x0340cd03}, | ||
| 699 | {0x0000a59c, 0x00000000, 0x00000000, 0x0340cd03, 0x0340cd03}, | ||
| 700 | {0x0000a5a0, 0x00000000, 0x00000000, 0x06415304, 0x06415304}, | ||
| 701 | {0x0000a5a4, 0x00000000, 0x00000000, 0x04c11905, 0x04c11905}, | ||
| 702 | {0x0000a5a8, 0x00000000, 0x00000000, 0x06415905, 0x06415905}, | ||
| 703 | {0x0000a5ac, 0x00000000, 0x00000000, 0x06415905, 0x06415905}, | ||
| 704 | {0x0000a5b0, 0x00000000, 0x00000000, 0x06415905, 0x06415905}, | ||
| 705 | {0x0000a5b4, 0x00000000, 0x00000000, 0x06415905, 0x06415905}, | ||
| 706 | {0x0000a5b8, 0x00000000, 0x00000000, 0x06415905, 0x06415905}, | ||
| 707 | {0x0000a5bc, 0x00000000, 0x00000000, 0x06415905, 0x06415905}, | ||
| 563 | {0x0000b500, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | 708 | {0x0000b500, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, |
| 564 | {0x0000b504, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | 709 | {0x0000b504, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, |
| 565 | {0x0000b508, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | 710 | {0x0000b508, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, |
| @@ -823,6 +968,7 @@ static const u32 ar9485_common_rx_gain_1_1[][2] = { | |||
| 823 | {0x00009e00, 0x03721b20}, | 968 | {0x00009e00, 0x03721b20}, |
| 824 | {0x00009e04, 0x00082020}, | 969 | {0x00009e04, 0x00082020}, |
| 825 | {0x00009e18, 0x0300501e}, | 970 | {0x00009e18, 0x0300501e}, |
| 971 | {0x00009e20, 0x000003ba}, | ||
| 826 | {0x00009e2c, 0x00002e21}, | 972 | {0x00009e2c, 0x00002e21}, |
| 827 | {0x00009e44, 0x02182324}, | 973 | {0x00009e44, 0x02182324}, |
| 828 | {0x0000a000, 0x00060005}, | 974 | {0x0000a000, 0x00060005}, |
| @@ -1001,7 +1147,6 @@ static const u32 ar9485_1_1_baseband_postamble[][5] = { | |||
| 1001 | {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec80d2e, 0x7ec80d2e}, | 1147 | {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec80d2e, 0x7ec80d2e}, |
| 1002 | {0x00009e14, 0x31395d53, 0x31396053, 0x312e6053, 0x312e5d53}, | 1148 | {0x00009e14, 0x31395d53, 0x31396053, 0x312e6053, 0x312e5d53}, |
| 1003 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, | 1149 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, |
| 1004 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, | ||
| 1005 | {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222}, | 1150 | {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222}, |
| 1006 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010}, | 1151 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010}, |
| 1007 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, | 1152 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, |
| @@ -1020,7 +1165,7 @@ static const u32 ar9485_1_1_baseband_postamble[][5] = { | |||
| 1020 | {0x0000a284, 0x00000000, 0x00000000, 0x000002a0, 0x000002a0}, | 1165 | {0x0000a284, 0x00000000, 0x00000000, 0x000002a0, 0x000002a0}, |
| 1021 | {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1166 | {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
| 1022 | {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1167 | {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
| 1023 | {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00058d18, 0x00058d18}, | 1168 | {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, |
| 1024 | {0x0000a2d0, 0x00071981, 0x00071981, 0x00071982, 0x00071982}, | 1169 | {0x0000a2d0, 0x00071981, 0x00071981, 0x00071982, 0x00071982}, |
| 1025 | {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, | 1170 | {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, |
| 1026 | {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1171 | {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
| @@ -1206,6 +1351,11 @@ static const u32 ar9485_1_1_mac_core[][2] = { | |||
| 1206 | {0x000083d0, 0x000301ff}, | 1351 | {0x000083d0, 0x000301ff}, |
| 1207 | }; | 1352 | }; |
| 1208 | 1353 | ||
| 1209 | #define ar9485_1_1_baseband_core_txfir_coeff_japan_2484 ar9462_2p0_baseband_core_txfir_coeff_japan_2484 | 1354 | static const u32 ar9485_1_1_baseband_core_txfir_coeff_japan_2484[][2] = { |
| 1355 | /* Addr allmodes */ | ||
| 1356 | {0x0000a398, 0x00000000}, | ||
| 1357 | {0x0000a39c, 0x6f7f0301}, | ||
| 1358 | {0x0000a3a0, 0xca9228ee}, | ||
| 1359 | }; | ||
| 1210 | 1360 | ||
| 1211 | #endif /* INITVALS_9485_H */ | 1361 | #endif /* INITVALS_9485_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h index e85a8b076c22..a8c757b6124f 100644 --- a/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h | |||
| @@ -272,9 +272,9 @@ static const u32 ar9565_1p0_baseband_core[][2] = { | |||
| 272 | {0x0000a398, 0x001f0e0f}, | 272 | {0x0000a398, 0x001f0e0f}, |
| 273 | {0x0000a39c, 0x0075393f}, | 273 | {0x0000a39c, 0x0075393f}, |
| 274 | {0x0000a3a0, 0xb79f6427}, | 274 | {0x0000a3a0, 0xb79f6427}, |
| 275 | {0x0000a3a4, 0x00000000}, | 275 | {0x0000a3a4, 0x00000011}, |
| 276 | {0x0000a3a8, 0xaaaaaaaa}, | 276 | {0x0000a3a8, 0xaaaaaa6e}, |
| 277 | {0x0000a3ac, 0x3c466478}, | 277 | {0x0000a3ac, 0x3c466455}, |
| 278 | {0x0000a3c0, 0x20202020}, | 278 | {0x0000a3c0, 0x20202020}, |
| 279 | {0x0000a3c4, 0x22222220}, | 279 | {0x0000a3c4, 0x22222220}, |
| 280 | {0x0000a3c8, 0x20200020}, | 280 | {0x0000a3c8, 0x20200020}, |
| @@ -295,11 +295,11 @@ static const u32 ar9565_1p0_baseband_core[][2] = { | |||
| 295 | {0x0000a404, 0x00000000}, | 295 | {0x0000a404, 0x00000000}, |
| 296 | {0x0000a408, 0x0e79e5c6}, | 296 | {0x0000a408, 0x0e79e5c6}, |
| 297 | {0x0000a40c, 0x00820820}, | 297 | {0x0000a40c, 0x00820820}, |
| 298 | {0x0000a414, 0x1ce739ce}, | 298 | {0x0000a414, 0x1ce739c5}, |
| 299 | {0x0000a418, 0x2d001dce}, | 299 | {0x0000a418, 0x2d001dce}, |
| 300 | {0x0000a41c, 0x1ce739ce}, | 300 | {0x0000a41c, 0x1ce739c5}, |
| 301 | {0x0000a420, 0x000001ce}, | 301 | {0x0000a420, 0x000001ce}, |
| 302 | {0x0000a424, 0x1ce739ce}, | 302 | {0x0000a424, 0x1ce739c5}, |
| 303 | {0x0000a428, 0x000001ce}, | 303 | {0x0000a428, 0x000001ce}, |
| 304 | {0x0000a42c, 0x1ce739ce}, | 304 | {0x0000a42c, 0x1ce739ce}, |
| 305 | {0x0000a430, 0x1ce739ce}, | 305 | {0x0000a430, 0x1ce739ce}, |
| @@ -351,9 +351,9 @@ static const u32 ar9565_1p0_baseband_postamble[][5] = { | |||
| 351 | {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e}, | 351 | {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e}, |
| 352 | {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 352 | {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
| 353 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, | 353 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, |
| 354 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, | 354 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003a4, 0x000003a4}, |
| 355 | {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, | 355 | {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, |
| 356 | {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222}, | 356 | {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946220, 0xcf946220}, |
| 357 | {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, | 357 | {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, |
| 358 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, | 358 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, |
| 359 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, | 359 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, |
| @@ -452,6 +452,7 @@ static const u32 ar9565_1p0_Common_rx_gain_table[][2] = { | |||
| 452 | /* Addr allmodes */ | 452 | /* Addr allmodes */ |
| 453 | {0x00004050, 0x00300300}, | 453 | {0x00004050, 0x00300300}, |
| 454 | {0x0000406c, 0x00100000}, | 454 | {0x0000406c, 0x00100000}, |
| 455 | {0x00009e20, 0x000003b6}, | ||
| 455 | {0x0000a000, 0x00010000}, | 456 | {0x0000a000, 0x00010000}, |
| 456 | {0x0000a004, 0x00030002}, | 457 | {0x0000a004, 0x00030002}, |
| 457 | {0x0000a008, 0x00050004}, | 458 | {0x0000a008, 0x00050004}, |
| @@ -1230,4 +1231,11 @@ static const u32 ar9565_1p0_modes_high_power_tx_gain_table[][5] = { | |||
| 1230 | {0x00016054, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1231 | {0x00016054, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
| 1231 | }; | 1232 | }; |
| 1232 | 1233 | ||
| 1234 | static const u32 ar9565_1p0_baseband_core_txfir_coeff_japan_2484[][2] = { | ||
| 1235 | /* Addr allmodes */ | ||
| 1236 | {0x0000a398, 0x00000000}, | ||
| 1237 | {0x0000a39c, 0x6f7f0301}, | ||
| 1238 | {0x0000a3a0, 0xca9228ee}, | ||
| 1239 | }; | ||
| 1240 | |||
| 1233 | #endif /* INITVALS_9565_1P0_H */ | 1241 | #endif /* INITVALS_9565_1P0_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 2ee35f677c0e..e7a38d844a6a 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
| @@ -64,7 +64,6 @@ struct ath_node; | |||
| 64 | 64 | ||
| 65 | struct ath_config { | 65 | struct ath_config { |
| 66 | u16 txpowlimit; | 66 | u16 txpowlimit; |
| 67 | u8 cabqReadytime; | ||
| 68 | }; | 67 | }; |
| 69 | 68 | ||
| 70 | /*************************/ | 69 | /*************************/ |
| @@ -207,6 +206,14 @@ struct ath_frame_info { | |||
| 207 | u8 baw_tracked : 1; | 206 | u8 baw_tracked : 1; |
| 208 | }; | 207 | }; |
| 209 | 208 | ||
| 209 | struct ath_rxbuf { | ||
| 210 | struct list_head list; | ||
| 211 | struct sk_buff *bf_mpdu; | ||
| 212 | void *bf_desc; | ||
| 213 | dma_addr_t bf_daddr; | ||
| 214 | dma_addr_t bf_buf_addr; | ||
| 215 | }; | ||
| 216 | |||
| 210 | struct ath_buf_state { | 217 | struct ath_buf_state { |
| 211 | u8 bf_type; | 218 | u8 bf_type; |
| 212 | u8 bfs_paprd; | 219 | u8 bfs_paprd; |
| @@ -307,7 +314,7 @@ struct ath_rx { | |||
| 307 | struct ath_descdma rxdma; | 314 | struct ath_descdma rxdma; |
| 308 | struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX]; | 315 | struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX]; |
| 309 | 316 | ||
| 310 | struct ath_buf *buf_hold; | 317 | struct ath_rxbuf *buf_hold; |
| 311 | struct sk_buff *frag; | 318 | struct sk_buff *frag; |
| 312 | 319 | ||
| 313 | u32 ampdu_ref; | 320 | u32 ampdu_ref; |
| @@ -459,8 +466,8 @@ void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type); | |||
| 459 | 466 | ||
| 460 | #define ATH_DUMP_BTCOEX(_s, _val) \ | 467 | #define ATH_DUMP_BTCOEX(_s, _val) \ |
| 461 | do { \ | 468 | do { \ |
| 462 | len += snprintf(buf + len, size - len, \ | 469 | len += scnprintf(buf + len, size - len, \ |
| 463 | "%20s : %10d\n", _s, (_val)); \ | 470 | "%20s : %10d\n", _s, (_val)); \ |
| 464 | } while (0) | 471 | } while (0) |
| 465 | 472 | ||
| 466 | enum bt_op_flags { | 473 | enum bt_op_flags { |
| @@ -581,7 +588,6 @@ static inline void ath_fill_led_pin(struct ath_softc *sc) | |||
| 581 | #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO_LOW_RSSI 50 | 588 | #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO_LOW_RSSI 50 |
| 582 | #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2_LOW_RSSI 50 | 589 | #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2_LOW_RSSI 50 |
| 583 | 590 | ||
| 584 | #define ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA -1 | ||
| 585 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_HI -4 | 591 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_HI -4 |
| 586 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_MID -2 | 592 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_MID -2 |
| 587 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_LOW 2 | 593 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_LOW 2 |
| @@ -626,12 +632,15 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs); | |||
| 626 | /* Main driver core */ | 632 | /* Main driver core */ |
| 627 | /********************/ | 633 | /********************/ |
| 628 | 634 | ||
| 629 | #define ATH9K_PCI_CUS198 0x0001 | 635 | #define ATH9K_PCI_CUS198 0x0001 |
| 630 | #define ATH9K_PCI_CUS230 0x0002 | 636 | #define ATH9K_PCI_CUS230 0x0002 |
| 631 | #define ATH9K_PCI_CUS217 0x0004 | 637 | #define ATH9K_PCI_CUS217 0x0004 |
| 632 | #define ATH9K_PCI_WOW 0x0008 | 638 | #define ATH9K_PCI_CUS252 0x0008 |
| 633 | #define ATH9K_PCI_BT_ANT_DIV 0x0010 | 639 | #define ATH9K_PCI_WOW 0x0010 |
| 634 | #define ATH9K_PCI_D3_L1_WAR 0x0020 | 640 | #define ATH9K_PCI_BT_ANT_DIV 0x0020 |
| 641 | #define ATH9K_PCI_D3_L1_WAR 0x0040 | ||
| 642 | #define ATH9K_PCI_AR9565_1ANT 0x0080 | ||
| 643 | #define ATH9K_PCI_AR9565_2ANT 0x0100 | ||
| 635 | 644 | ||
| 636 | /* | 645 | /* |
| 637 | * Default cache line size, in bytes. | 646 | * Default cache line size, in bytes. |
| @@ -769,6 +778,11 @@ struct ath_softc { | |||
| 769 | enum spectral_mode spectral_mode; | 778 | enum spectral_mode spectral_mode; |
| 770 | struct ath_spec_scan spec_config; | 779 | struct ath_spec_scan spec_config; |
| 771 | 780 | ||
| 781 | struct ieee80211_vif *tx99_vif; | ||
| 782 | struct sk_buff *tx99_skb; | ||
| 783 | bool tx99_state; | ||
| 784 | s16 tx99_power; | ||
| 785 | |||
| 772 | #ifdef CONFIG_PM_SLEEP | 786 | #ifdef CONFIG_PM_SLEEP |
| 773 | atomic_t wow_got_bmiss_intr; | 787 | atomic_t wow_got_bmiss_intr; |
| 774 | atomic_t wow_sleep_proc_intr; /* in the middle of WoW sleep ? */ | 788 | atomic_t wow_sleep_proc_intr; /* in the middle of WoW sleep ? */ |
| @@ -877,6 +891,7 @@ static inline u8 spectral_bitmap_weight(u8 *bins) | |||
| 877 | */ | 891 | */ |
| 878 | enum ath_fft_sample_type { | 892 | enum ath_fft_sample_type { |
| 879 | ATH_FFT_SAMPLE_HT20 = 1, | 893 | ATH_FFT_SAMPLE_HT20 = 1, |
| 894 | ATH_FFT_SAMPLE_HT20_40, | ||
| 880 | }; | 895 | }; |
| 881 | 896 | ||
| 882 | struct fft_sample_tlv { | 897 | struct fft_sample_tlv { |
| @@ -903,6 +918,39 @@ struct fft_sample_ht20 { | |||
| 903 | u8 data[SPECTRAL_HT20_NUM_BINS]; | 918 | u8 data[SPECTRAL_HT20_NUM_BINS]; |
| 904 | } __packed; | 919 | } __packed; |
| 905 | 920 | ||
| 921 | struct fft_sample_ht20_40 { | ||
| 922 | struct fft_sample_tlv tlv; | ||
| 923 | |||
| 924 | u8 channel_type; | ||
| 925 | __be16 freq; | ||
| 926 | |||
| 927 | s8 lower_rssi; | ||
| 928 | s8 upper_rssi; | ||
| 929 | |||
| 930 | __be64 tsf; | ||
| 931 | |||
| 932 | s8 lower_noise; | ||
| 933 | s8 upper_noise; | ||
| 934 | |||
| 935 | __be16 lower_max_magnitude; | ||
| 936 | __be16 upper_max_magnitude; | ||
| 937 | |||
| 938 | u8 lower_max_index; | ||
| 939 | u8 upper_max_index; | ||
| 940 | |||
| 941 | u8 lower_bitmap_weight; | ||
| 942 | u8 upper_bitmap_weight; | ||
| 943 | |||
| 944 | u8 max_exp; | ||
| 945 | |||
| 946 | u8 data[SPECTRAL_HT20_40_NUM_BINS]; | ||
| 947 | } __packed; | ||
| 948 | |||
| 949 | int ath9k_tx99_init(struct ath_softc *sc); | ||
| 950 | void ath9k_tx99_deinit(struct ath_softc *sc); | ||
| 951 | int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb, | ||
| 952 | struct ath_tx_control *txctl); | ||
| 953 | |||
| 906 | void ath9k_tasklet(unsigned long data); | 954 | void ath9k_tasklet(unsigned long data); |
| 907 | int ath_cabq_update(struct ath_softc *); | 955 | int ath_cabq_update(struct ath_softc *); |
| 908 | 956 | ||
| @@ -924,7 +972,6 @@ void ath9k_deinit_device(struct ath_softc *sc); | |||
| 924 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); | 972 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); |
| 925 | void ath9k_reload_chainmask_settings(struct ath_softc *sc); | 973 | void ath9k_reload_chainmask_settings(struct ath_softc *sc); |
| 926 | 974 | ||
| 927 | bool ath9k_uses_beacons(int type); | ||
| 928 | void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw); | 975 | void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw); |
| 929 | int ath9k_spectral_scan_config(struct ieee80211_hw *hw, | 976 | int ath9k_spectral_scan_config(struct ieee80211_hw *hw, |
| 930 | enum spectral_mode spectral_mode); | 977 | enum spectral_mode spectral_mode); |
| @@ -952,7 +999,7 @@ void ath9k_ps_restore(struct ath_softc *sc); | |||
| 952 | u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate); | 999 | u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate); |
| 953 | 1000 | ||
| 954 | void ath_start_rfkill_poll(struct ath_softc *sc); | 1001 | void ath_start_rfkill_poll(struct ath_softc *sc); |
| 955 | extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw); | 1002 | void ath9k_rfkill_poll_state(struct ieee80211_hw *hw); |
| 956 | void ath9k_calculate_iter_data(struct ieee80211_hw *hw, | 1003 | void ath9k_calculate_iter_data(struct ieee80211_hw *hw, |
| 957 | struct ieee80211_vif *vif, | 1004 | struct ieee80211_vif *vif, |
| 958 | struct ath9k_vif_iter_data *iter_data); | 1005 | struct ath9k_vif_iter_data *iter_data); |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index b5c16b3a37b9..17be35392bb4 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
| @@ -334,6 +334,8 @@ void ath9k_beacon_tasklet(unsigned long data) | |||
| 334 | if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) { | 334 | if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) { |
| 335 | sc->beacon.bmisscnt++; | 335 | sc->beacon.bmisscnt++; |
| 336 | 336 | ||
| 337 | ath9k_hw_check_nav(ah); | ||
| 338 | |||
| 337 | if (!ath9k_hw_check_alive(ah)) | 339 | if (!ath9k_hw_check_alive(ah)) |
| 338 | ieee80211_queue_work(sc->hw, &sc->hw_check_work); | 340 | ieee80211_queue_work(sc->hw, &sc->hw_check_work); |
| 339 | 341 | ||
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 5e8219a91e25..278365b8a895 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
| @@ -63,13 +63,13 @@ static s16 ath9k_hw_get_default_nf(struct ath_hw *ah, | |||
| 63 | return ath9k_hw_get_nf_limits(ah, chan)->nominal; | 63 | return ath9k_hw_get_nf_limits(ah, chan)->nominal; |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) | 66 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan, |
| 67 | s16 nf) | ||
| 67 | { | 68 | { |
| 68 | s8 noise = ATH_DEFAULT_NOISE_FLOOR; | 69 | s8 noise = ATH_DEFAULT_NOISE_FLOOR; |
| 69 | 70 | ||
| 70 | if (chan && chan->noisefloor) { | 71 | if (nf) { |
| 71 | s8 delta = chan->noisefloor - | 72 | s8 delta = nf - ATH9K_NF_CAL_NOISE_THRESH - |
| 72 | ATH9K_NF_CAL_NOISE_THRESH - | ||
| 73 | ath9k_hw_get_default_nf(ah, chan); | 73 | ath9k_hw_get_default_nf(ah, chan); |
| 74 | if (delta > 0) | 74 | if (delta > 0) |
| 75 | noise += delta; | 75 | noise += delta; |
| @@ -119,7 +119,7 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah, | |||
| 119 | ath_dbg(common, CALIBRATE, | 119 | ath_dbg(common, CALIBRATE, |
| 120 | "NFmid[%d] (%d) > MAX (%d), %s\n", | 120 | "NFmid[%d] (%d) > MAX (%d), %s\n", |
| 121 | i, h[i].privNF, limit->max, | 121 | i, h[i].privNF, limit->max, |
| 122 | (cal->nfcal_interference ? | 122 | (test_bit(NFCAL_INTF, &cal->cal_flags) ? |
| 123 | "not corrected (due to interference)" : | 123 | "not corrected (due to interference)" : |
| 124 | "correcting to MAX")); | 124 | "correcting to MAX")); |
| 125 | 125 | ||
| @@ -130,7 +130,7 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah, | |||
| 130 | * we bypass this limit here in order to better deal | 130 | * we bypass this limit here in order to better deal |
| 131 | * with our environment. | 131 | * with our environment. |
| 132 | */ | 132 | */ |
| 133 | if (!cal->nfcal_interference) | 133 | if (!test_bit(NFCAL_INTF, &cal->cal_flags)) |
| 134 | h[i].privNF = limit->max; | 134 | h[i].privNF = limit->max; |
| 135 | } | 135 | } |
| 136 | } | 136 | } |
| @@ -141,7 +141,7 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah, | |||
| 141 | * Re-enable the enforcement of the NF maximum again. | 141 | * Re-enable the enforcement of the NF maximum again. |
| 142 | */ | 142 | */ |
| 143 | if (!high_nf_mid) | 143 | if (!high_nf_mid) |
| 144 | cal->nfcal_interference = false; | 144 | clear_bit(NFCAL_INTF, &cal->cal_flags); |
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah, | 147 | static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah, |
| @@ -186,7 +186,6 @@ void ath9k_hw_reset_calibration(struct ath_hw *ah, | |||
| 186 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah) | 186 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah) |
| 187 | { | 187 | { |
| 188 | struct ath_common *common = ath9k_hw_common(ah); | 188 | struct ath_common *common = ath9k_hw_common(ah); |
| 189 | struct ieee80211_conf *conf = &common->hw->conf; | ||
| 190 | struct ath9k_cal_list *currCal = ah->cal_list_curr; | 189 | struct ath9k_cal_list *currCal = ah->cal_list_curr; |
| 191 | 190 | ||
| 192 | if (!ah->caldata) | 191 | if (!ah->caldata) |
| @@ -208,7 +207,7 @@ bool ath9k_hw_reset_calvalid(struct ath_hw *ah) | |||
| 208 | return true; | 207 | return true; |
| 209 | 208 | ||
| 210 | ath_dbg(common, CALIBRATE, "Resetting Cal %d state for channel %u\n", | 209 | ath_dbg(common, CALIBRATE, "Resetting Cal %d state for channel %u\n", |
| 211 | currCal->calData->calType, conf->chandef.chan->center_freq); | 210 | currCal->calData->calType, ah->curchan->chan->center_freq); |
| 212 | 211 | ||
| 213 | ah->caldata->CalValid &= ~currCal->calData->calType; | 212 | ah->caldata->CalValid &= ~currCal->calData->calType; |
| 214 | currCal->calState = CAL_WAITING; | 213 | currCal->calState = CAL_WAITING; |
| @@ -220,7 +219,7 @@ EXPORT_SYMBOL(ath9k_hw_reset_calvalid); | |||
| 220 | void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update) | 219 | void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update) |
| 221 | { | 220 | { |
| 222 | if (ah->caldata) | 221 | if (ah->caldata) |
| 223 | ah->caldata->nfcal_pending = true; | 222 | set_bit(NFCAL_PENDING, &ah->caldata->cal_flags); |
| 224 | 223 | ||
| 225 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, | 224 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, |
| 226 | AR_PHY_AGC_CONTROL_ENABLE_NF); | 225 | AR_PHY_AGC_CONTROL_ENABLE_NF); |
| @@ -242,7 +241,6 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
| 242 | int32_t val; | 241 | int32_t val; |
| 243 | u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; | 242 | u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; |
| 244 | struct ath_common *common = ath9k_hw_common(ah); | 243 | struct ath_common *common = ath9k_hw_common(ah); |
| 245 | struct ieee80211_conf *conf = &common->hw->conf; | ||
| 246 | s16 default_nf = ath9k_hw_get_default_nf(ah, chan); | 244 | s16 default_nf = ath9k_hw_get_default_nf(ah, chan); |
| 247 | 245 | ||
| 248 | if (ah->caldata) | 246 | if (ah->caldata) |
| @@ -252,7 +250,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
| 252 | if (chainmask & (1 << i)) { | 250 | if (chainmask & (1 << i)) { |
| 253 | s16 nfval; | 251 | s16 nfval; |
| 254 | 252 | ||
| 255 | if ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)) | 253 | if ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(chan)) |
| 256 | continue; | 254 | continue; |
| 257 | 255 | ||
| 258 | if (h) | 256 | if (h) |
| @@ -314,7 +312,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
| 314 | ENABLE_REGWRITE_BUFFER(ah); | 312 | ENABLE_REGWRITE_BUFFER(ah); |
| 315 | for (i = 0; i < NUM_NF_READINGS; i++) { | 313 | for (i = 0; i < NUM_NF_READINGS; i++) { |
| 316 | if (chainmask & (1 << i)) { | 314 | if (chainmask & (1 << i)) { |
| 317 | if ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)) | 315 | if ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(chan)) |
| 318 | continue; | 316 | continue; |
| 319 | 317 | ||
| 320 | val = REG_READ(ah, ah->nf_regs[i]); | 318 | val = REG_READ(ah, ah->nf_regs[i]); |
| @@ -391,10 +389,10 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
| 391 | } | 389 | } |
| 392 | 390 | ||
| 393 | h = caldata->nfCalHist; | 391 | h = caldata->nfCalHist; |
| 394 | caldata->nfcal_pending = false; | 392 | clear_bit(NFCAL_PENDING, &caldata->cal_flags); |
| 395 | ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray); | 393 | ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray); |
| 396 | chan->noisefloor = h[0].privNF; | 394 | chan->noisefloor = h[0].privNF; |
| 397 | ah->noise = ath9k_hw_getchan_noise(ah, chan); | 395 | ah->noise = ath9k_hw_getchan_noise(ah, chan, chan->noisefloor); |
| 398 | return true; | 396 | return true; |
| 399 | } | 397 | } |
| 400 | EXPORT_SYMBOL(ath9k_hw_getnf); | 398 | EXPORT_SYMBOL(ath9k_hw_getnf); |
| @@ -408,7 +406,6 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, | |||
| 408 | 406 | ||
| 409 | ah->caldata->channel = chan->channel; | 407 | ah->caldata->channel = chan->channel; |
| 410 | ah->caldata->channelFlags = chan->channelFlags; | 408 | ah->caldata->channelFlags = chan->channelFlags; |
| 411 | ah->caldata->chanmode = chan->chanmode; | ||
| 412 | h = ah->caldata->nfCalHist; | 409 | h = ah->caldata->nfCalHist; |
| 413 | default_nf = ath9k_hw_get_default_nf(ah, chan); | 410 | default_nf = ath9k_hw_get_default_nf(ah, chan); |
| 414 | for (i = 0; i < NUM_NF_READINGS; i++) { | 411 | for (i = 0; i < NUM_NF_READINGS; i++) { |
| @@ -437,12 +434,12 @@ void ath9k_hw_bstuck_nfcal(struct ath_hw *ah) | |||
| 437 | * the baseband update the internal NF value itself, similar to | 434 | * the baseband update the internal NF value itself, similar to |
| 438 | * what is being done after a full reset. | 435 | * what is being done after a full reset. |
| 439 | */ | 436 | */ |
| 440 | if (!caldata->nfcal_pending) | 437 | if (!test_bit(NFCAL_PENDING, &caldata->cal_flags)) |
| 441 | ath9k_hw_start_nfcal(ah, true); | 438 | ath9k_hw_start_nfcal(ah, true); |
| 442 | else if (!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF)) | 439 | else if (!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF)) |
| 443 | ath9k_hw_getnf(ah, ah->curchan); | 440 | ath9k_hw_getnf(ah, ah->curchan); |
| 444 | 441 | ||
| 445 | caldata->nfcal_interference = true; | 442 | set_bit(NFCAL_INTF, &caldata->cal_flags); |
| 446 | } | 443 | } |
| 447 | EXPORT_SYMBOL(ath9k_hw_bstuck_nfcal); | 444 | EXPORT_SYMBOL(ath9k_hw_bstuck_nfcal); |
| 448 | 445 | ||
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index 3d70b8c2bcdd..b8ed95e9a335 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h | |||
| @@ -116,7 +116,8 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, | |||
| 116 | void ath9k_hw_bstuck_nfcal(struct ath_hw *ah); | 116 | void ath9k_hw_bstuck_nfcal(struct ath_hw *ah); |
| 117 | void ath9k_hw_reset_calibration(struct ath_hw *ah, | 117 | void ath9k_hw_reset_calibration(struct ath_hw *ah, |
| 118 | struct ath9k_cal_list *currCal); | 118 | struct ath9k_cal_list *currCal); |
| 119 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); | 119 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan, |
| 120 | s16 nf); | ||
| 120 | 121 | ||
| 121 | 122 | ||
| 122 | #endif /* CALIB_H */ | 123 | #endif /* CALIB_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index d3063c21e16c..a7e5a05b2eff 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c | |||
| @@ -49,103 +49,64 @@ int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb) | |||
| 49 | } | 49 | } |
| 50 | EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype); | 50 | EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype); |
| 51 | 51 | ||
| 52 | static u32 ath9k_get_extchanmode(struct cfg80211_chan_def *chandef) | ||
| 53 | { | ||
| 54 | u32 chanmode = 0; | ||
| 55 | |||
| 56 | switch (chandef->chan->band) { | ||
| 57 | case IEEE80211_BAND_2GHZ: | ||
| 58 | switch (chandef->width) { | ||
| 59 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
| 60 | case NL80211_CHAN_WIDTH_20: | ||
| 61 | chanmode = CHANNEL_G_HT20; | ||
| 62 | break; | ||
| 63 | case NL80211_CHAN_WIDTH_40: | ||
| 64 | if (chandef->center_freq1 > chandef->chan->center_freq) | ||
| 65 | chanmode = CHANNEL_G_HT40PLUS; | ||
| 66 | else | ||
| 67 | chanmode = CHANNEL_G_HT40MINUS; | ||
| 68 | break; | ||
| 69 | default: | ||
| 70 | break; | ||
| 71 | } | ||
| 72 | break; | ||
| 73 | case IEEE80211_BAND_5GHZ: | ||
| 74 | switch (chandef->width) { | ||
| 75 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
| 76 | case NL80211_CHAN_WIDTH_20: | ||
| 77 | chanmode = CHANNEL_A_HT20; | ||
| 78 | break; | ||
| 79 | case NL80211_CHAN_WIDTH_40: | ||
| 80 | if (chandef->center_freq1 > chandef->chan->center_freq) | ||
| 81 | chanmode = CHANNEL_A_HT40PLUS; | ||
| 82 | else | ||
| 83 | chanmode = CHANNEL_A_HT40MINUS; | ||
| 84 | break; | ||
| 85 | default: | ||
| 86 | break; | ||
| 87 | } | ||
| 88 | break; | ||
| 89 | default: | ||
| 90 | break; | ||
| 91 | } | ||
| 92 | |||
| 93 | return chanmode; | ||
| 94 | } | ||
| 95 | |||
| 96 | /* | 52 | /* |
| 97 | * Update internal channel flags. | 53 | * Update internal channel flags. |
| 98 | */ | 54 | */ |
| 99 | void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, | 55 | static void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, |
| 100 | struct cfg80211_chan_def *chandef) | 56 | struct cfg80211_chan_def *chandef) |
| 101 | { | 57 | { |
| 102 | ichan->channel = chandef->chan->center_freq; | 58 | struct ieee80211_channel *chan = chandef->chan; |
| 103 | ichan->chan = chandef->chan; | 59 | u16 flags = 0; |
| 104 | 60 | ||
| 105 | if (chandef->chan->band == IEEE80211_BAND_2GHZ) { | 61 | ichan->channel = chan->center_freq; |
| 106 | ichan->chanmode = CHANNEL_G; | 62 | ichan->chan = chan; |
| 107 | ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM; | 63 | |
| 108 | } else { | 64 | if (chan->band == IEEE80211_BAND_5GHZ) |
| 109 | ichan->chanmode = CHANNEL_A; | 65 | flags |= CHANNEL_5GHZ; |
| 110 | ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; | ||
| 111 | } | ||
| 112 | 66 | ||
| 113 | switch (chandef->width) { | 67 | switch (chandef->width) { |
| 114 | case NL80211_CHAN_WIDTH_5: | 68 | case NL80211_CHAN_WIDTH_5: |
| 115 | ichan->channelFlags |= CHANNEL_QUARTER; | 69 | flags |= CHANNEL_QUARTER; |
| 116 | break; | 70 | break; |
| 117 | case NL80211_CHAN_WIDTH_10: | 71 | case NL80211_CHAN_WIDTH_10: |
| 118 | ichan->channelFlags |= CHANNEL_HALF; | 72 | flags |= CHANNEL_HALF; |
| 119 | break; | 73 | break; |
| 120 | case NL80211_CHAN_WIDTH_20_NOHT: | 74 | case NL80211_CHAN_WIDTH_20_NOHT: |
| 121 | break; | 75 | break; |
| 122 | case NL80211_CHAN_WIDTH_20: | 76 | case NL80211_CHAN_WIDTH_20: |
| 77 | flags |= CHANNEL_HT; | ||
| 78 | break; | ||
| 123 | case NL80211_CHAN_WIDTH_40: | 79 | case NL80211_CHAN_WIDTH_40: |
| 124 | ichan->chanmode = ath9k_get_extchanmode(chandef); | 80 | if (chandef->center_freq1 > chandef->chan->center_freq) |
| 81 | flags |= CHANNEL_HT40PLUS | CHANNEL_HT; | ||
| 82 | else | ||
| 83 | flags |= CHANNEL_HT40MINUS | CHANNEL_HT; | ||
| 125 | break; | 84 | break; |
| 126 | default: | 85 | default: |
| 127 | WARN_ON(1); | 86 | WARN_ON(1); |
| 128 | } | 87 | } |
| 88 | |||
| 89 | ichan->channelFlags = flags; | ||
| 129 | } | 90 | } |
| 130 | EXPORT_SYMBOL(ath9k_cmn_update_ichannel); | ||
| 131 | 91 | ||
| 132 | /* | 92 | /* |
| 133 | * Get the internal channel reference. | 93 | * Get the internal channel reference. |
| 134 | */ | 94 | */ |
| 135 | struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, | 95 | struct ath9k_channel *ath9k_cmn_get_channel(struct ieee80211_hw *hw, |
| 136 | struct ath_hw *ah) | 96 | struct ath_hw *ah, |
| 97 | struct cfg80211_chan_def *chandef) | ||
| 137 | { | 98 | { |
| 138 | struct ieee80211_channel *curchan = hw->conf.chandef.chan; | 99 | struct ieee80211_channel *curchan = chandef->chan; |
| 139 | struct ath9k_channel *channel; | 100 | struct ath9k_channel *channel; |
| 140 | u8 chan_idx; | 101 | u8 chan_idx; |
| 141 | 102 | ||
| 142 | chan_idx = curchan->hw_value; | 103 | chan_idx = curchan->hw_value; |
| 143 | channel = &ah->channels[chan_idx]; | 104 | channel = &ah->channels[chan_idx]; |
| 144 | ath9k_cmn_update_ichannel(channel, &hw->conf.chandef); | 105 | ath9k_cmn_update_ichannel(channel, chandef); |
| 145 | 106 | ||
| 146 | return channel; | 107 | return channel; |
| 147 | } | 108 | } |
| 148 | EXPORT_SYMBOL(ath9k_cmn_get_curchannel); | 109 | EXPORT_SYMBOL(ath9k_cmn_get_channel); |
| 149 | 110 | ||
| 150 | int ath9k_cmn_count_streams(unsigned int chainmask, int max) | 111 | int ath9k_cmn_count_streams(unsigned int chainmask, int max) |
| 151 | { | 112 | { |
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index e039bcbfbd79..eb85e1bdca88 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h | |||
| @@ -43,10 +43,9 @@ | |||
| 43 | (((x) + ((mul)/2)) / (mul)) | 43 | (((x) + ((mul)/2)) / (mul)) |
| 44 | 44 | ||
| 45 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); | 45 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); |
| 46 | void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, | 46 | struct ath9k_channel *ath9k_cmn_get_channel(struct ieee80211_hw *hw, |
| 47 | struct cfg80211_chan_def *chandef); | 47 | struct ath_hw *ah, |
| 48 | struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, | 48 | struct cfg80211_chan_def *chandef); |
| 49 | struct ath_hw *ah); | ||
| 50 | int ath9k_cmn_count_streams(unsigned int chainmask, int max); | 49 | int ath9k_cmn_count_streams(unsigned int chainmask, int max); |
| 51 | void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, | 50 | void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, |
| 52 | enum ath_stomp_type stomp_type); | 51 | 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 c088744a6bfb..83a2c59f680b 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
| @@ -104,37 +104,37 @@ static ssize_t read_file_ani(struct file *file, char __user *user_buf, | |||
| 104 | return -ENOMEM; | 104 | return -ENOMEM; |
| 105 | 105 | ||
| 106 | if (common->disable_ani) { | 106 | if (common->disable_ani) { |
| 107 | len += snprintf(buf + len, size - len, "%s: %s\n", | 107 | len += scnprintf(buf + len, size - len, "%s: %s\n", |
| 108 | "ANI", "DISABLED"); | 108 | "ANI", "DISABLED"); |
| 109 | goto exit; | 109 | goto exit; |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | len += snprintf(buf + len, size - len, "%15s: %s\n", | 112 | len += scnprintf(buf + len, size - len, "%15s: %s\n", |
| 113 | "ANI", "ENABLED"); | 113 | "ANI", "ENABLED"); |
| 114 | len += snprintf(buf + len, size - len, "%15s: %u\n", | 114 | len += scnprintf(buf + len, size - len, "%15s: %u\n", |
| 115 | "ANI RESET", ah->stats.ast_ani_reset); | 115 | "ANI RESET", ah->stats.ast_ani_reset); |
| 116 | len += snprintf(buf + len, size - len, "%15s: %u\n", | 116 | len += scnprintf(buf + len, size - len, "%15s: %u\n", |
| 117 | "SPUR UP", ah->stats.ast_ani_spurup); | 117 | "SPUR UP", ah->stats.ast_ani_spurup); |
| 118 | len += snprintf(buf + len, size - len, "%15s: %u\n", | 118 | len += scnprintf(buf + len, size - len, "%15s: %u\n", |
| 119 | "SPUR DOWN", ah->stats.ast_ani_spurup); | 119 | "SPUR DOWN", ah->stats.ast_ani_spurup); |
| 120 | len += snprintf(buf + len, size - len, "%15s: %u\n", | 120 | len += scnprintf(buf + len, size - len, "%15s: %u\n", |
| 121 | "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon); | 121 | "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon); |
| 122 | len += snprintf(buf + len, size - len, "%15s: %u\n", | 122 | len += scnprintf(buf + len, size - len, "%15s: %u\n", |
| 123 | "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff); | 123 | "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff); |
| 124 | len += snprintf(buf + len, size - len, "%15s: %u\n", | 124 | len += scnprintf(buf + len, size - len, "%15s: %u\n", |
| 125 | "MRC-CCK ON", ah->stats.ast_ani_ccklow); | 125 | "MRC-CCK ON", ah->stats.ast_ani_ccklow); |
| 126 | len += snprintf(buf + len, size - len, "%15s: %u\n", | 126 | len += scnprintf(buf + len, size - len, "%15s: %u\n", |
| 127 | "MRC-CCK OFF", ah->stats.ast_ani_cckhigh); | 127 | "MRC-CCK OFF", ah->stats.ast_ani_cckhigh); |
| 128 | len += snprintf(buf + len, size - len, "%15s: %u\n", | 128 | len += scnprintf(buf + len, size - len, "%15s: %u\n", |
| 129 | "FIR-STEP UP", ah->stats.ast_ani_stepup); | 129 | "FIR-STEP UP", ah->stats.ast_ani_stepup); |
| 130 | len += snprintf(buf + len, size - len, "%15s: %u\n", | 130 | len += scnprintf(buf + len, size - len, "%15s: %u\n", |
| 131 | "FIR-STEP DOWN", ah->stats.ast_ani_stepdown); | 131 | "FIR-STEP DOWN", ah->stats.ast_ani_stepdown); |
| 132 | len += snprintf(buf + len, size - len, "%15s: %u\n", | 132 | len += scnprintf(buf + len, size - len, "%15s: %u\n", |
| 133 | "INV LISTENTIME", ah->stats.ast_ani_lneg_or_lzero); | 133 | "INV LISTENTIME", ah->stats.ast_ani_lneg_or_lzero); |
| 134 | len += snprintf(buf + len, size - len, "%15s: %u\n", | 134 | len += scnprintf(buf + len, size - len, "%15s: %u\n", |
| 135 | "OFDM ERRORS", ah->stats.ast_ani_ofdmerrs); | 135 | "OFDM ERRORS", ah->stats.ast_ani_ofdmerrs); |
| 136 | len += snprintf(buf + len, size - len, "%15s: %u\n", | 136 | len += scnprintf(buf + len, size - len, "%15s: %u\n", |
| 137 | "CCK ERRORS", ah->stats.ast_ani_cckerrs); | 137 | "CCK ERRORS", ah->stats.ast_ani_cckerrs); |
| 138 | exit: | 138 | exit: |
| 139 | if (len > size) | 139 | if (len > size) |
| 140 | len = size; | 140 | len = size; |
| @@ -280,70 +280,70 @@ static ssize_t read_file_antenna_diversity(struct file *file, | |||
| 280 | return -ENOMEM; | 280 | return -ENOMEM; |
| 281 | 281 | ||
| 282 | if (!(pCap->hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)) { | 282 | if (!(pCap->hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)) { |
| 283 | len += snprintf(buf + len, size - len, "%s\n", | 283 | len += scnprintf(buf + len, size - len, "%s\n", |
| 284 | "Antenna Diversity Combining is disabled"); | 284 | "Antenna Diversity Combining is disabled"); |
| 285 | goto exit; | 285 | goto exit; |
| 286 | } | 286 | } |
| 287 | 287 | ||
| 288 | ath9k_ps_wakeup(sc); | 288 | ath9k_ps_wakeup(sc); |
| 289 | ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf); | 289 | ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf); |
| 290 | len += snprintf(buf + len, size - len, "Current MAIN config : %s\n", | 290 | len += scnprintf(buf + len, size - len, "Current MAIN config : %s\n", |
| 291 | lna_conf_str[div_ant_conf.main_lna_conf]); | 291 | lna_conf_str[div_ant_conf.main_lna_conf]); |
| 292 | len += snprintf(buf + len, size - len, "Current ALT config : %s\n", | 292 | len += scnprintf(buf + len, size - len, "Current ALT config : %s\n", |
| 293 | lna_conf_str[div_ant_conf.alt_lna_conf]); | 293 | lna_conf_str[div_ant_conf.alt_lna_conf]); |
| 294 | len += snprintf(buf + len, size - len, "Average MAIN RSSI : %d\n", | 294 | len += scnprintf(buf + len, size - len, "Average MAIN RSSI : %d\n", |
| 295 | as_main->rssi_avg); | 295 | as_main->rssi_avg); |
| 296 | len += snprintf(buf + len, size - len, "Average ALT RSSI : %d\n\n", | 296 | len += scnprintf(buf + len, size - len, "Average ALT RSSI : %d\n\n", |
| 297 | as_alt->rssi_avg); | 297 | as_alt->rssi_avg); |
| 298 | ath9k_ps_restore(sc); | 298 | ath9k_ps_restore(sc); |
| 299 | 299 | ||
| 300 | len += snprintf(buf + len, size - len, "Packet Receive Cnt:\n"); | 300 | len += scnprintf(buf + len, size - len, "Packet Receive Cnt:\n"); |
| 301 | len += snprintf(buf + len, size - len, "-------------------\n"); | 301 | len += scnprintf(buf + len, size - len, "-------------------\n"); |
| 302 | 302 | ||
| 303 | len += snprintf(buf + len, size - len, "%30s%15s\n", | 303 | len += scnprintf(buf + len, size - len, "%30s%15s\n", |
| 304 | "MAIN", "ALT"); | 304 | "MAIN", "ALT"); |
| 305 | len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n", | 305 | len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n", |
| 306 | "TOTAL COUNT", | 306 | "TOTAL COUNT", |
| 307 | as_main->recv_cnt, | 307 | as_main->recv_cnt, |
| 308 | as_alt->recv_cnt); | 308 | as_alt->recv_cnt); |
| 309 | len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n", | 309 | len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n", |
| 310 | "LNA1", | 310 | "LNA1", |
| 311 | as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1], | 311 | as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1], |
| 312 | as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1]); | 312 | as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1]); |
| 313 | len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n", | 313 | len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n", |
| 314 | "LNA2", | 314 | "LNA2", |
| 315 | as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA2], | 315 | as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA2], |
| 316 | as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA2]); | 316 | as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA2]); |
| 317 | len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n", | 317 | len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n", |
| 318 | "LNA1 + LNA2", | 318 | "LNA1 + LNA2", |
| 319 | as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2], | 319 | as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2], |
| 320 | as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2]); | 320 | as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2]); |
| 321 | len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n", | 321 | len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n", |
| 322 | "LNA1 - LNA2", | 322 | "LNA1 - LNA2", |
| 323 | as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2], | 323 | as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2], |
| 324 | as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2]); | 324 | as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2]); |
| 325 | 325 | ||
| 326 | len += snprintf(buf + len, size - len, "\nLNA Config Attempts:\n"); | 326 | len += scnprintf(buf + len, size - len, "\nLNA Config Attempts:\n"); |
| 327 | len += snprintf(buf + len, size - len, "--------------------\n"); | 327 | len += scnprintf(buf + len, size - len, "--------------------\n"); |
| 328 | 328 | ||
| 329 | len += snprintf(buf + len, size - len, "%30s%15s\n", | 329 | len += scnprintf(buf + len, size - len, "%30s%15s\n", |
| 330 | "MAIN", "ALT"); | 330 | "MAIN", "ALT"); |
| 331 | len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n", | 331 | len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n", |
| 332 | "LNA1", | 332 | "LNA1", |
| 333 | as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1], | 333 | as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1], |
| 334 | as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1]); | 334 | as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1]); |
| 335 | len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n", | 335 | len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n", |
| 336 | "LNA2", | 336 | "LNA2", |
| 337 | as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA2], | 337 | as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA2], |
| 338 | as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA2]); | 338 | as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA2]); |
| 339 | len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n", | 339 | len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n", |
| 340 | "LNA1 + LNA2", | 340 | "LNA1 + LNA2", |
| 341 | as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2], | 341 | as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2], |
| 342 | as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2]); | 342 | as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2]); |
| 343 | len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n", | 343 | len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n", |
| 344 | "LNA1 - LNA2", | 344 | "LNA1 - LNA2", |
| 345 | as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2], | 345 | as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2], |
| 346 | as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2]); | 346 | as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2]); |
| 347 | 347 | ||
| 348 | exit: | 348 | exit: |
| 349 | if (len > size) | 349 | if (len > size) |
| @@ -385,21 +385,21 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf, | |||
| 385 | (AR_MACMISC_MISC_OBS_BUS_1 << | 385 | (AR_MACMISC_MISC_OBS_BUS_1 << |
| 386 | AR_MACMISC_MISC_OBS_BUS_MSB_S))); | 386 | AR_MACMISC_MISC_OBS_BUS_MSB_S))); |
| 387 | 387 | ||
| 388 | len += snprintf(buf + len, DMA_BUF_LEN - len, | 388 | len += scnprintf(buf + len, DMA_BUF_LEN - len, |
| 389 | "Raw DMA Debug values:\n"); | 389 | "Raw DMA Debug values:\n"); |
| 390 | 390 | ||
| 391 | for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) { | 391 | for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) { |
| 392 | if (i % 4 == 0) | 392 | if (i % 4 == 0) |
| 393 | len += snprintf(buf + len, DMA_BUF_LEN - len, "\n"); | 393 | len += scnprintf(buf + len, DMA_BUF_LEN - len, "\n"); |
| 394 | 394 | ||
| 395 | val[i] = REG_READ_D(ah, AR_DMADBG_0 + (i * sizeof(u32))); | 395 | val[i] = REG_READ_D(ah, AR_DMADBG_0 + (i * sizeof(u32))); |
| 396 | len += snprintf(buf + len, DMA_BUF_LEN - len, "%d: %08x ", | 396 | len += scnprintf(buf + len, DMA_BUF_LEN - len, "%d: %08x ", |
| 397 | i, val[i]); | 397 | i, val[i]); |
| 398 | } | 398 | } |
| 399 | 399 | ||
| 400 | len += snprintf(buf + len, DMA_BUF_LEN - len, "\n\n"); | 400 | len += scnprintf(buf + len, DMA_BUF_LEN - len, "\n\n"); |
| 401 | len += snprintf(buf + len, DMA_BUF_LEN - len, | 401 | len += scnprintf(buf + len, DMA_BUF_LEN - len, |
| 402 | "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n"); | 402 | "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n"); |
| 403 | 403 | ||
| 404 | for (i = 0; i < ATH9K_NUM_QUEUES; i++, qcuOffset += 4, dcuOffset += 5) { | 404 | for (i = 0; i < ATH9K_NUM_QUEUES; i++, qcuOffset += 4, dcuOffset += 5) { |
| 405 | if (i == 8) { | 405 | if (i == 8) { |
| @@ -412,39 +412,39 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf, | |||
| 412 | dcuBase++; | 412 | dcuBase++; |
| 413 | } | 413 | } |
| 414 | 414 | ||
| 415 | len += snprintf(buf + len, DMA_BUF_LEN - len, | 415 | len += scnprintf(buf + len, DMA_BUF_LEN - len, |
| 416 | "%2d %2x %1x %2x %2x\n", | 416 | "%2d %2x %1x %2x %2x\n", |
| 417 | i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset, | 417 | i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset, |
| 418 | (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3), | 418 | (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3), |
| 419 | val[2] & (0x7 << (i * 3)) >> (i * 3), | 419 | val[2] & (0x7 << (i * 3)) >> (i * 3), |
| 420 | (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset); | 420 | (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset); |
| 421 | } | 421 | } |
| 422 | 422 | ||
| 423 | len += snprintf(buf + len, DMA_BUF_LEN - len, "\n"); | 423 | len += scnprintf(buf + len, DMA_BUF_LEN - len, "\n"); |
| 424 | 424 | ||
| 425 | len += snprintf(buf + len, DMA_BUF_LEN - len, | 425 | len += scnprintf(buf + len, DMA_BUF_LEN - len, |
| 426 | "qcu_stitch state: %2x qcu_fetch state: %2x\n", | 426 | "qcu_stitch state: %2x qcu_fetch state: %2x\n", |
| 427 | (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22); | 427 | (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22); |
| 428 | len += snprintf(buf + len, DMA_BUF_LEN - len, | 428 | len += scnprintf(buf + len, DMA_BUF_LEN - len, |
| 429 | "qcu_complete state: %2x dcu_complete state: %2x\n", | 429 | "qcu_complete state: %2x dcu_complete state: %2x\n", |
| 430 | (val[3] & 0x1c000000) >> 26, (val[6] & 0x3)); | 430 | (val[3] & 0x1c000000) >> 26, (val[6] & 0x3)); |
| 431 | len += snprintf(buf + len, DMA_BUF_LEN - len, | 431 | len += scnprintf(buf + len, DMA_BUF_LEN - len, |
| 432 | "dcu_arb state: %2x dcu_fp state: %2x\n", | 432 | "dcu_arb state: %2x dcu_fp state: %2x\n", |
| 433 | (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27); | 433 | (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27); |
| 434 | len += snprintf(buf + len, DMA_BUF_LEN - len, | 434 | len += scnprintf(buf + len, DMA_BUF_LEN - len, |
| 435 | "chan_idle_dur: %3d chan_idle_dur_valid: %1d\n", | 435 | "chan_idle_dur: %3d chan_idle_dur_valid: %1d\n", |
| 436 | (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10); | 436 | (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10); |
| 437 | len += snprintf(buf + len, DMA_BUF_LEN - len, | 437 | len += scnprintf(buf + len, DMA_BUF_LEN - len, |
| 438 | "txfifo_valid_0: %1d txfifo_valid_1: %1d\n", | 438 | "txfifo_valid_0: %1d txfifo_valid_1: %1d\n", |
| 439 | (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12); | 439 | (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12); |
| 440 | len += snprintf(buf + len, DMA_BUF_LEN - len, | 440 | len += scnprintf(buf + len, DMA_BUF_LEN - len, |
| 441 | "txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n", | 441 | "txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n", |
| 442 | (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17); | 442 | (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17); |
| 443 | 443 | ||
| 444 | len += snprintf(buf + len, DMA_BUF_LEN - len, "pcu observe: 0x%x\n", | 444 | len += scnprintf(buf + len, DMA_BUF_LEN - len, "pcu observe: 0x%x\n", |
| 445 | REG_READ_D(ah, AR_OBS_BUS_1)); | 445 | REG_READ_D(ah, AR_OBS_BUS_1)); |
| 446 | len += snprintf(buf + len, DMA_BUF_LEN - len, | 446 | len += scnprintf(buf + len, DMA_BUF_LEN - len, |
| 447 | "AR_CR: 0x%x\n", REG_READ_D(ah, AR_CR)); | 447 | "AR_CR: 0x%x\n", REG_READ_D(ah, AR_CR)); |
| 448 | 448 | ||
| 449 | ath9k_ps_restore(sc); | 449 | ath9k_ps_restore(sc); |
| 450 | 450 | ||
| @@ -530,9 +530,9 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, | |||
| 530 | 530 | ||
| 531 | #define PR_IS(a, s) \ | 531 | #define PR_IS(a, s) \ |
| 532 | do { \ | 532 | do { \ |
| 533 | len += snprintf(buf + len, mxlen - len, \ | 533 | len += scnprintf(buf + len, mxlen - len, \ |
| 534 | "%21s: %10u\n", a, \ | 534 | "%21s: %10u\n", a, \ |
| 535 | sc->debug.stats.istats.s); \ | 535 | sc->debug.stats.istats.s); \ |
| 536 | } while (0) | 536 | } while (0) |
| 537 | 537 | ||
| 538 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { | 538 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { |
| @@ -563,8 +563,8 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, | |||
| 563 | PR_IS("GENTIMER", gen_timer); | 563 | PR_IS("GENTIMER", gen_timer); |
| 564 | PR_IS("TOTAL", total); | 564 | PR_IS("TOTAL", total); |
| 565 | 565 | ||
| 566 | len += snprintf(buf + len, mxlen - len, | 566 | len += scnprintf(buf + len, mxlen - len, |
| 567 | "SYNC_CAUSE stats:\n"); | 567 | "SYNC_CAUSE stats:\n"); |
| 568 | 568 | ||
| 569 | PR_IS("Sync-All", sync_cause_all); | 569 | PR_IS("Sync-All", sync_cause_all); |
| 570 | PR_IS("RTC-IRQ", sync_rtc_irq); | 570 | PR_IS("RTC-IRQ", sync_rtc_irq); |
| @@ -655,16 +655,16 @@ static ssize_t print_queue(struct ath_softc *sc, struct ath_txq *txq, | |||
| 655 | 655 | ||
| 656 | ath_txq_lock(sc, txq); | 656 | ath_txq_lock(sc, txq); |
| 657 | 657 | ||
| 658 | len += snprintf(buf + len, size - len, "%s: %d ", | 658 | len += scnprintf(buf + len, size - len, "%s: %d ", |
| 659 | "qnum", txq->axq_qnum); | 659 | "qnum", txq->axq_qnum); |
| 660 | len += snprintf(buf + len, size - len, "%s: %2d ", | 660 | len += scnprintf(buf + len, size - len, "%s: %2d ", |
| 661 | "qdepth", txq->axq_depth); | 661 | "qdepth", txq->axq_depth); |
| 662 | len += snprintf(buf + len, size - len, "%s: %2d ", | 662 | len += scnprintf(buf + len, size - len, "%s: %2d ", |
| 663 | "ampdu-depth", txq->axq_ampdu_depth); | 663 | "ampdu-depth", txq->axq_ampdu_depth); |
| 664 | len += snprintf(buf + len, size - len, "%s: %3d ", | 664 | len += scnprintf(buf + len, size - len, "%s: %3d ", |
| 665 | "pending", txq->pending_frames); | 665 | "pending", txq->pending_frames); |
| 666 | len += snprintf(buf + len, size - len, "%s: %d\n", | 666 | len += scnprintf(buf + len, size - len, "%s: %d\n", |
| 667 | "stopped", txq->stopped); | 667 | "stopped", txq->stopped); |
| 668 | 668 | ||
| 669 | ath_txq_unlock(sc, txq); | 669 | ath_txq_unlock(sc, txq); |
| 670 | return len; | 670 | return len; |
| @@ -687,11 +687,11 @@ static ssize_t read_file_queues(struct file *file, char __user *user_buf, | |||
| 687 | 687 | ||
| 688 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { | 688 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { |
| 689 | txq = sc->tx.txq_map[i]; | 689 | txq = sc->tx.txq_map[i]; |
| 690 | len += snprintf(buf + len, size - len, "(%s): ", qname[i]); | 690 | len += scnprintf(buf + len, size - len, "(%s): ", qname[i]); |
| 691 | len += print_queue(sc, txq, buf + len, size - len); | 691 | len += print_queue(sc, txq, buf + len, size - len); |
| 692 | } | 692 | } |
| 693 | 693 | ||
| 694 | len += snprintf(buf + len, size - len, "(CAB): "); | 694 | len += scnprintf(buf + len, size - len, "(CAB): "); |
| 695 | len += print_queue(sc, sc->beacon.cabq, buf + len, size - len); | 695 | len += print_queue(sc, sc->beacon.cabq, buf + len, size - len); |
| 696 | 696 | ||
| 697 | if (len > size) | 697 | if (len > size) |
| @@ -716,80 +716,82 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf, | |||
| 716 | unsigned int reg; | 716 | unsigned int reg; |
| 717 | u32 rxfilter; | 717 | u32 rxfilter; |
| 718 | 718 | ||
| 719 | len += snprintf(buf + len, sizeof(buf) - len, | 719 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 720 | "BSSID: %pM\n", common->curbssid); | 720 | "BSSID: %pM\n", common->curbssid); |
| 721 | len += snprintf(buf + len, sizeof(buf) - len, | 721 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 722 | "BSSID-MASK: %pM\n", common->bssidmask); | 722 | "BSSID-MASK: %pM\n", common->bssidmask); |
| 723 | len += snprintf(buf + len, sizeof(buf) - len, | 723 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 724 | "OPMODE: %s\n", ath_opmode_to_string(sc->sc_ah->opmode)); | 724 | "OPMODE: %s\n", |
| 725 | ath_opmode_to_string(sc->sc_ah->opmode)); | ||
| 725 | 726 | ||
| 726 | ath9k_ps_wakeup(sc); | 727 | ath9k_ps_wakeup(sc); |
| 727 | rxfilter = ath9k_hw_getrxfilter(sc->sc_ah); | 728 | rxfilter = ath9k_hw_getrxfilter(sc->sc_ah); |
| 728 | ath9k_ps_restore(sc); | 729 | ath9k_ps_restore(sc); |
| 729 | 730 | ||
| 730 | len += snprintf(buf + len, sizeof(buf) - len, | 731 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 731 | "RXFILTER: 0x%x", rxfilter); | 732 | "RXFILTER: 0x%x", rxfilter); |
| 732 | 733 | ||
| 733 | if (rxfilter & ATH9K_RX_FILTER_UCAST) | 734 | if (rxfilter & ATH9K_RX_FILTER_UCAST) |
| 734 | len += snprintf(buf + len, sizeof(buf) - len, " UCAST"); | 735 | len += scnprintf(buf + len, sizeof(buf) - len, " UCAST"); |
| 735 | if (rxfilter & ATH9K_RX_FILTER_MCAST) | 736 | if (rxfilter & ATH9K_RX_FILTER_MCAST) |
| 736 | len += snprintf(buf + len, sizeof(buf) - len, " MCAST"); | 737 | len += scnprintf(buf + len, sizeof(buf) - len, " MCAST"); |
| 737 | if (rxfilter & ATH9K_RX_FILTER_BCAST) | 738 | if (rxfilter & ATH9K_RX_FILTER_BCAST) |
| 738 | len += snprintf(buf + len, sizeof(buf) - len, " BCAST"); | 739 | len += scnprintf(buf + len, sizeof(buf) - len, " BCAST"); |
| 739 | if (rxfilter & ATH9K_RX_FILTER_CONTROL) | 740 | if (rxfilter & ATH9K_RX_FILTER_CONTROL) |
| 740 | len += snprintf(buf + len, sizeof(buf) - len, " CONTROL"); | 741 | len += scnprintf(buf + len, sizeof(buf) - len, " CONTROL"); |
| 741 | if (rxfilter & ATH9K_RX_FILTER_BEACON) | 742 | if (rxfilter & ATH9K_RX_FILTER_BEACON) |
| 742 | len += snprintf(buf + len, sizeof(buf) - len, " BEACON"); | 743 | len += scnprintf(buf + len, sizeof(buf) - len, " BEACON"); |
| 743 | if (rxfilter & ATH9K_RX_FILTER_PROM) | 744 | if (rxfilter & ATH9K_RX_FILTER_PROM) |
| 744 | len += snprintf(buf + len, sizeof(buf) - len, " PROM"); | 745 | len += scnprintf(buf + len, sizeof(buf) - len, " PROM"); |
| 745 | if (rxfilter & ATH9K_RX_FILTER_PROBEREQ) | 746 | if (rxfilter & ATH9K_RX_FILTER_PROBEREQ) |
| 746 | len += snprintf(buf + len, sizeof(buf) - len, " PROBEREQ"); | 747 | len += scnprintf(buf + len, sizeof(buf) - len, " PROBEREQ"); |
| 747 | if (rxfilter & ATH9K_RX_FILTER_PHYERR) | 748 | if (rxfilter & ATH9K_RX_FILTER_PHYERR) |
| 748 | len += snprintf(buf + len, sizeof(buf) - len, " PHYERR"); | 749 | len += scnprintf(buf + len, sizeof(buf) - len, " PHYERR"); |
| 749 | if (rxfilter & ATH9K_RX_FILTER_MYBEACON) | 750 | if (rxfilter & ATH9K_RX_FILTER_MYBEACON) |
| 750 | len += snprintf(buf + len, sizeof(buf) - len, " MYBEACON"); | 751 | len += scnprintf(buf + len, sizeof(buf) - len, " MYBEACON"); |
| 751 | if (rxfilter & ATH9K_RX_FILTER_COMP_BAR) | 752 | if (rxfilter & ATH9K_RX_FILTER_COMP_BAR) |
| 752 | len += snprintf(buf + len, sizeof(buf) - len, " COMP_BAR"); | 753 | len += scnprintf(buf + len, sizeof(buf) - len, " COMP_BAR"); |
| 753 | if (rxfilter & ATH9K_RX_FILTER_PSPOLL) | 754 | if (rxfilter & ATH9K_RX_FILTER_PSPOLL) |
| 754 | len += snprintf(buf + len, sizeof(buf) - len, " PSPOLL"); | 755 | len += scnprintf(buf + len, sizeof(buf) - len, " PSPOLL"); |
| 755 | if (rxfilter & ATH9K_RX_FILTER_PHYRADAR) | 756 | if (rxfilter & ATH9K_RX_FILTER_PHYRADAR) |
| 756 | len += snprintf(buf + len, sizeof(buf) - len, " PHYRADAR"); | 757 | len += scnprintf(buf + len, sizeof(buf) - len, " PHYRADAR"); |
| 757 | if (rxfilter & ATH9K_RX_FILTER_MCAST_BCAST_ALL) | 758 | if (rxfilter & ATH9K_RX_FILTER_MCAST_BCAST_ALL) |
| 758 | len += snprintf(buf + len, sizeof(buf) - len, " MCAST_BCAST_ALL"); | 759 | len += scnprintf(buf + len, sizeof(buf) - len, " MCAST_BCAST_ALL"); |
| 759 | if (rxfilter & ATH9K_RX_FILTER_CONTROL_WRAPPER) | 760 | if (rxfilter & ATH9K_RX_FILTER_CONTROL_WRAPPER) |
| 760 | len += snprintf(buf + len, sizeof(buf) - len, " CONTROL_WRAPPER"); | 761 | len += scnprintf(buf + len, sizeof(buf) - len, " CONTROL_WRAPPER"); |
| 761 | 762 | ||
| 762 | len += snprintf(buf + len, sizeof(buf) - len, "\n"); | 763 | len += scnprintf(buf + len, sizeof(buf) - len, "\n"); |
| 763 | 764 | ||
| 764 | reg = sc->sc_ah->imask; | 765 | reg = sc->sc_ah->imask; |
| 765 | 766 | ||
| 766 | len += snprintf(buf + len, sizeof(buf) - len, "INTERRUPT-MASK: 0x%x", reg); | 767 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 768 | "INTERRUPT-MASK: 0x%x", reg); | ||
| 767 | 769 | ||
| 768 | if (reg & ATH9K_INT_SWBA) | 770 | if (reg & ATH9K_INT_SWBA) |
| 769 | len += snprintf(buf + len, sizeof(buf) - len, " SWBA"); | 771 | len += scnprintf(buf + len, sizeof(buf) - len, " SWBA"); |
| 770 | if (reg & ATH9K_INT_BMISS) | 772 | if (reg & ATH9K_INT_BMISS) |
| 771 | len += snprintf(buf + len, sizeof(buf) - len, " BMISS"); | 773 | len += scnprintf(buf + len, sizeof(buf) - len, " BMISS"); |
| 772 | if (reg & ATH9K_INT_CST) | 774 | if (reg & ATH9K_INT_CST) |
| 773 | len += snprintf(buf + len, sizeof(buf) - len, " CST"); | 775 | len += scnprintf(buf + len, sizeof(buf) - len, " CST"); |
| 774 | if (reg & ATH9K_INT_RX) | 776 | if (reg & ATH9K_INT_RX) |
| 775 | len += snprintf(buf + len, sizeof(buf) - len, " RX"); | 777 | len += scnprintf(buf + len, sizeof(buf) - len, " RX"); |
| 776 | if (reg & ATH9K_INT_RXHP) | 778 | if (reg & ATH9K_INT_RXHP) |
| 777 | len += snprintf(buf + len, sizeof(buf) - len, " RXHP"); | 779 | len += scnprintf(buf + len, sizeof(buf) - len, " RXHP"); |
| 778 | if (reg & ATH9K_INT_RXLP) | 780 | if (reg & ATH9K_INT_RXLP) |
| 779 | len += snprintf(buf + len, sizeof(buf) - len, " RXLP"); | 781 | len += scnprintf(buf + len, sizeof(buf) - len, " RXLP"); |
| 780 | if (reg & ATH9K_INT_BB_WATCHDOG) | 782 | if (reg & ATH9K_INT_BB_WATCHDOG) |
| 781 | len += snprintf(buf + len, sizeof(buf) - len, " BB_WATCHDOG"); | 783 | len += scnprintf(buf + len, sizeof(buf) - len, " BB_WATCHDOG"); |
| 782 | 784 | ||
| 783 | len += snprintf(buf + len, sizeof(buf) - len, "\n"); | 785 | len += scnprintf(buf + len, sizeof(buf) - len, "\n"); |
| 784 | 786 | ||
| 785 | ath9k_calculate_iter_data(hw, NULL, &iter_data); | 787 | ath9k_calculate_iter_data(hw, NULL, &iter_data); |
| 786 | 788 | ||
| 787 | len += snprintf(buf + len, sizeof(buf) - len, | 789 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 788 | "VIF-COUNTS: AP: %i STA: %i MESH: %i WDS: %i" | 790 | "VIF-COUNTS: AP: %i STA: %i MESH: %i WDS: %i" |
| 789 | " ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n", | 791 | " ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n", |
| 790 | iter_data.naps, iter_data.nstations, iter_data.nmeshes, | 792 | iter_data.naps, iter_data.nstations, iter_data.nmeshes, |
| 791 | iter_data.nwds, iter_data.nadhocs, | 793 | iter_data.nwds, iter_data.nadhocs, |
| 792 | sc->nvifs, sc->nbcnvifs); | 794 | sc->nvifs, sc->nbcnvifs); |
| 793 | 795 | ||
| 794 | if (len > sizeof(buf)) | 796 | if (len > sizeof(buf)) |
| 795 | len = sizeof(buf); | 797 | len = sizeof(buf); |
| @@ -805,27 +807,27 @@ static ssize_t read_file_reset(struct file *file, char __user *user_buf, | |||
| 805 | char buf[512]; | 807 | char buf[512]; |
| 806 | unsigned int len = 0; | 808 | unsigned int len = 0; |
| 807 | 809 | ||
| 808 | len += snprintf(buf + len, sizeof(buf) - len, | 810 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 809 | "%17s: %2d\n", "Baseband Hang", | 811 | "%17s: %2d\n", "Baseband Hang", |
| 810 | sc->debug.stats.reset[RESET_TYPE_BB_HANG]); | 812 | sc->debug.stats.reset[RESET_TYPE_BB_HANG]); |
| 811 | len += snprintf(buf + len, sizeof(buf) - len, | 813 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 812 | "%17s: %2d\n", "Baseband Watchdog", | 814 | "%17s: %2d\n", "Baseband Watchdog", |
| 813 | sc->debug.stats.reset[RESET_TYPE_BB_WATCHDOG]); | 815 | sc->debug.stats.reset[RESET_TYPE_BB_WATCHDOG]); |
| 814 | len += snprintf(buf + len, sizeof(buf) - len, | 816 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 815 | "%17s: %2d\n", "Fatal HW Error", | 817 | "%17s: %2d\n", "Fatal HW Error", |
| 816 | sc->debug.stats.reset[RESET_TYPE_FATAL_INT]); | 818 | sc->debug.stats.reset[RESET_TYPE_FATAL_INT]); |
| 817 | len += snprintf(buf + len, sizeof(buf) - len, | 819 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 818 | "%17s: %2d\n", "TX HW error", | 820 | "%17s: %2d\n", "TX HW error", |
| 819 | sc->debug.stats.reset[RESET_TYPE_TX_ERROR]); | 821 | sc->debug.stats.reset[RESET_TYPE_TX_ERROR]); |
| 820 | len += snprintf(buf + len, sizeof(buf) - len, | 822 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 821 | "%17s: %2d\n", "TX Path Hang", | 823 | "%17s: %2d\n", "TX Path Hang", |
| 822 | sc->debug.stats.reset[RESET_TYPE_TX_HANG]); | 824 | sc->debug.stats.reset[RESET_TYPE_TX_HANG]); |
| 823 | len += snprintf(buf + len, sizeof(buf) - len, | 825 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 824 | "%17s: %2d\n", "PLL RX Hang", | 826 | "%17s: %2d\n", "PLL RX Hang", |
| 825 | sc->debug.stats.reset[RESET_TYPE_PLL_HANG]); | 827 | sc->debug.stats.reset[RESET_TYPE_PLL_HANG]); |
| 826 | len += snprintf(buf + len, sizeof(buf) - len, | 828 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 827 | "%17s: %2d\n", "MCI Reset", | 829 | "%17s: %2d\n", "MCI Reset", |
| 828 | sc->debug.stats.reset[RESET_TYPE_MCI]); | 830 | sc->debug.stats.reset[RESET_TYPE_MCI]); |
| 829 | 831 | ||
| 830 | if (len > sizeof(buf)) | 832 | if (len > sizeof(buf)) |
| 831 | len = sizeof(buf); | 833 | len = sizeof(buf); |
| @@ -902,14 +904,14 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
| 902 | size_t count, loff_t *ppos) | 904 | size_t count, loff_t *ppos) |
| 903 | { | 905 | { |
| 904 | #define PHY_ERR(s, p) \ | 906 | #define PHY_ERR(s, p) \ |
| 905 | len += snprintf(buf + len, size - len, "%22s : %10u\n", s, \ | 907 | len += scnprintf(buf + len, size - len, "%22s : %10u\n", s, \ |
| 906 | sc->debug.stats.rxstats.phy_err_stats[p]); | 908 | sc->debug.stats.rxstats.phy_err_stats[p]); |
| 907 | 909 | ||
| 908 | #define RXS_ERR(s, e) \ | 910 | #define RXS_ERR(s, e) \ |
| 909 | do { \ | 911 | do { \ |
| 910 | len += snprintf(buf + len, size - len, \ | 912 | len += scnprintf(buf + len, size - len, \ |
| 911 | "%22s : %10u\n", s, \ | 913 | "%22s : %10u\n", s, \ |
| 912 | sc->debug.stats.rxstats.e); \ | 914 | sc->debug.stats.rxstats.e);\ |
| 913 | } while (0) | 915 | } while (0) |
| 914 | 916 | ||
| 915 | struct ath_softc *sc = file->private_data; | 917 | struct ath_softc *sc = file->private_data; |
| @@ -1048,6 +1050,9 @@ static ssize_t write_file_spec_scan_ctl(struct file *file, | |||
| 1048 | char buf[32]; | 1050 | char buf[32]; |
| 1049 | ssize_t len; | 1051 | ssize_t len; |
| 1050 | 1052 | ||
| 1053 | if (config_enabled(CONFIG_ATH9K_TX99)) | ||
| 1054 | return -EOPNOTSUPP; | ||
| 1055 | |||
| 1051 | len = min(count, sizeof(buf) - 1); | 1056 | len = min(count, sizeof(buf) - 1); |
| 1052 | if (copy_from_user(buf, user_buf, len)) | 1057 | if (copy_from_user(buf, user_buf, len)) |
| 1053 | return -EFAULT; | 1058 | return -EFAULT; |
| @@ -1439,22 +1444,22 @@ static ssize_t read_file_dump_nfcal(struct file *file, char __user *user_buf, | |||
| 1439 | if (!buf) | 1444 | if (!buf) |
| 1440 | return -ENOMEM; | 1445 | return -ENOMEM; |
| 1441 | 1446 | ||
| 1442 | len += snprintf(buf + len, size - len, | 1447 | len += scnprintf(buf + len, size - len, |
| 1443 | "Channel Noise Floor : %d\n", ah->noise); | 1448 | "Channel Noise Floor : %d\n", ah->noise); |
| 1444 | len += snprintf(buf + len, size - len, | 1449 | len += scnprintf(buf + len, size - len, |
| 1445 | "Chain | privNF | # Readings | NF Readings\n"); | 1450 | "Chain | privNF | # Readings | NF Readings\n"); |
| 1446 | for (i = 0; i < NUM_NF_READINGS; i++) { | 1451 | for (i = 0; i < NUM_NF_READINGS; i++) { |
| 1447 | if (!(chainmask & (1 << i)) || | 1452 | if (!(chainmask & (1 << i)) || |
| 1448 | ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))) | 1453 | ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))) |
| 1449 | continue; | 1454 | continue; |
| 1450 | 1455 | ||
| 1451 | nread = AR_PHY_CCA_FILTERWINDOW_LENGTH - h[i].invalidNFcount; | 1456 | nread = AR_PHY_CCA_FILTERWINDOW_LENGTH - h[i].invalidNFcount; |
| 1452 | len += snprintf(buf + len, size - len, " %d\t %d\t %d\t\t", | 1457 | len += scnprintf(buf + len, size - len, " %d\t %d\t %d\t\t", |
| 1453 | i, h[i].privNF, nread); | 1458 | i, h[i].privNF, nread); |
| 1454 | for (j = 0; j < nread; j++) | 1459 | for (j = 0; j < nread; j++) |
| 1455 | len += snprintf(buf + len, size - len, | 1460 | len += scnprintf(buf + len, size - len, |
| 1456 | " %d", h[i].nfCalBuffer[j]); | 1461 | " %d", h[i].nfCalBuffer[j]); |
| 1457 | len += snprintf(buf + len, size - len, "\n"); | 1462 | len += scnprintf(buf + len, size - len, "\n"); |
| 1458 | } | 1463 | } |
| 1459 | 1464 | ||
| 1460 | if (len > size) | 1465 | if (len > size) |
| @@ -1543,8 +1548,8 @@ static ssize_t read_file_btcoex(struct file *file, char __user *user_buf, | |||
| 1543 | return -ENOMEM; | 1548 | return -ENOMEM; |
| 1544 | 1549 | ||
| 1545 | if (!sc->sc_ah->common.btcoex_enabled) { | 1550 | if (!sc->sc_ah->common.btcoex_enabled) { |
| 1546 | len = snprintf(buf, size, "%s\n", | 1551 | len = scnprintf(buf, size, "%s\n", |
| 1547 | "BTCOEX is disabled"); | 1552 | "BTCOEX is disabled"); |
| 1548 | goto exit; | 1553 | goto exit; |
| 1549 | } | 1554 | } |
| 1550 | 1555 | ||
| @@ -1582,43 +1587,43 @@ static ssize_t read_file_node_stat(struct file *file, char __user *user_buf, | |||
| 1582 | return -ENOMEM; | 1587 | return -ENOMEM; |
| 1583 | 1588 | ||
| 1584 | if (!an->sta->ht_cap.ht_supported) { | 1589 | if (!an->sta->ht_cap.ht_supported) { |
| 1585 | len = snprintf(buf, size, "%s\n", | 1590 | len = scnprintf(buf, size, "%s\n", |
| 1586 | "HT not supported"); | 1591 | "HT not supported"); |
| 1587 | goto exit; | 1592 | goto exit; |
| 1588 | } | 1593 | } |
| 1589 | 1594 | ||
| 1590 | len = snprintf(buf, size, "Max-AMPDU: %d\n", | 1595 | len = scnprintf(buf, size, "Max-AMPDU: %d\n", |
| 1591 | an->maxampdu); | 1596 | an->maxampdu); |
| 1592 | len += snprintf(buf + len, size - len, "MPDU Density: %d\n\n", | 1597 | len += scnprintf(buf + len, size - len, "MPDU Density: %d\n\n", |
| 1593 | an->mpdudensity); | 1598 | an->mpdudensity); |
| 1594 | 1599 | ||
| 1595 | len += snprintf(buf + len, size - len, | 1600 | len += scnprintf(buf + len, size - len, |
| 1596 | "%2s%7s\n", "AC", "SCHED"); | 1601 | "%2s%7s\n", "AC", "SCHED"); |
| 1597 | 1602 | ||
| 1598 | for (acno = 0, ac = &an->ac[acno]; | 1603 | for (acno = 0, ac = &an->ac[acno]; |
| 1599 | acno < IEEE80211_NUM_ACS; acno++, ac++) { | 1604 | acno < IEEE80211_NUM_ACS; acno++, ac++) { |
| 1600 | txq = ac->txq; | 1605 | txq = ac->txq; |
| 1601 | ath_txq_lock(sc, txq); | 1606 | ath_txq_lock(sc, txq); |
| 1602 | len += snprintf(buf + len, size - len, | 1607 | len += scnprintf(buf + len, size - len, |
| 1603 | "%2d%7d\n", | 1608 | "%2d%7d\n", |
| 1604 | acno, ac->sched); | 1609 | acno, ac->sched); |
| 1605 | ath_txq_unlock(sc, txq); | 1610 | ath_txq_unlock(sc, txq); |
| 1606 | } | 1611 | } |
| 1607 | 1612 | ||
| 1608 | len += snprintf(buf + len, size - len, | 1613 | len += scnprintf(buf + len, size - len, |
| 1609 | "\n%3s%11s%10s%10s%10s%10s%9s%6s%8s\n", | 1614 | "\n%3s%11s%10s%10s%10s%10s%9s%6s%8s\n", |
| 1610 | "TID", "SEQ_START", "SEQ_NEXT", "BAW_SIZE", | 1615 | "TID", "SEQ_START", "SEQ_NEXT", "BAW_SIZE", |
| 1611 | "BAW_HEAD", "BAW_TAIL", "BAR_IDX", "SCHED", "PAUSED"); | 1616 | "BAW_HEAD", "BAW_TAIL", "BAR_IDX", "SCHED", "PAUSED"); |
| 1612 | 1617 | ||
| 1613 | for (tidno = 0, tid = &an->tid[tidno]; | 1618 | for (tidno = 0, tid = &an->tid[tidno]; |
| 1614 | tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { | 1619 | tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { |
| 1615 | txq = tid->ac->txq; | 1620 | txq = tid->ac->txq; |
| 1616 | ath_txq_lock(sc, txq); | 1621 | ath_txq_lock(sc, txq); |
| 1617 | len += snprintf(buf + len, size - len, | 1622 | len += scnprintf(buf + len, size - len, |
| 1618 | "%3d%11d%10d%10d%10d%10d%9d%6d%8d\n", | 1623 | "%3d%11d%10d%10d%10d%10d%9d%6d%8d\n", |
| 1619 | tid->tidno, tid->seq_start, tid->seq_next, | 1624 | tid->tidno, tid->seq_start, tid->seq_next, |
| 1620 | tid->baw_size, tid->baw_head, tid->baw_tail, | 1625 | tid->baw_size, tid->baw_head, tid->baw_tail, |
| 1621 | tid->bar_index, tid->sched, tid->paused); | 1626 | tid->bar_index, tid->sched, tid->paused); |
| 1622 | ath_txq_unlock(sc, txq); | 1627 | ath_txq_unlock(sc, txq); |
| 1623 | } | 1628 | } |
| 1624 | exit: | 1629 | exit: |
| @@ -1773,6 +1778,111 @@ void ath9k_deinit_debug(struct ath_softc *sc) | |||
| 1773 | } | 1778 | } |
| 1774 | } | 1779 | } |
| 1775 | 1780 | ||
| 1781 | static ssize_t read_file_tx99(struct file *file, char __user *user_buf, | ||
| 1782 | size_t count, loff_t *ppos) | ||
| 1783 | { | ||
| 1784 | struct ath_softc *sc = file->private_data; | ||
| 1785 | char buf[3]; | ||
| 1786 | unsigned int len; | ||
| 1787 | |||
| 1788 | len = sprintf(buf, "%d\n", sc->tx99_state); | ||
| 1789 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
| 1790 | } | ||
| 1791 | |||
| 1792 | static ssize_t write_file_tx99(struct file *file, const char __user *user_buf, | ||
| 1793 | size_t count, loff_t *ppos) | ||
| 1794 | { | ||
| 1795 | struct ath_softc *sc = file->private_data; | ||
| 1796 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
| 1797 | char buf[32]; | ||
| 1798 | bool start; | ||
| 1799 | ssize_t len; | ||
| 1800 | int r; | ||
| 1801 | |||
| 1802 | if (sc->nvifs > 1) | ||
| 1803 | return -EOPNOTSUPP; | ||
| 1804 | |||
| 1805 | len = min(count, sizeof(buf) - 1); | ||
| 1806 | if (copy_from_user(buf, user_buf, len)) | ||
| 1807 | return -EFAULT; | ||
| 1808 | |||
| 1809 | if (strtobool(buf, &start)) | ||
| 1810 | return -EINVAL; | ||
| 1811 | |||
| 1812 | if (start == sc->tx99_state) { | ||
| 1813 | if (!start) | ||
| 1814 | return count; | ||
| 1815 | ath_dbg(common, XMIT, "Resetting TX99\n"); | ||
| 1816 | ath9k_tx99_deinit(sc); | ||
| 1817 | } | ||
| 1818 | |||
| 1819 | if (!start) { | ||
| 1820 | ath9k_tx99_deinit(sc); | ||
| 1821 | return count; | ||
| 1822 | } | ||
| 1823 | |||
| 1824 | r = ath9k_tx99_init(sc); | ||
| 1825 | if (r) | ||
| 1826 | return r; | ||
| 1827 | |||
| 1828 | return count; | ||
| 1829 | } | ||
| 1830 | |||
| 1831 | static const struct file_operations fops_tx99 = { | ||
| 1832 | .read = read_file_tx99, | ||
| 1833 | .write = write_file_tx99, | ||
| 1834 | .open = simple_open, | ||
| 1835 | .owner = THIS_MODULE, | ||
| 1836 | .llseek = default_llseek, | ||
| 1837 | }; | ||
| 1838 | |||
| 1839 | static ssize_t read_file_tx99_power(struct file *file, | ||
| 1840 | char __user *user_buf, | ||
| 1841 | size_t count, loff_t *ppos) | ||
| 1842 | { | ||
| 1843 | struct ath_softc *sc = file->private_data; | ||
| 1844 | char buf[32]; | ||
| 1845 | unsigned int len; | ||
| 1846 | |||
| 1847 | len = sprintf(buf, "%d (%d dBm)\n", | ||
| 1848 | sc->tx99_power, | ||
| 1849 | sc->tx99_power / 2); | ||
| 1850 | |||
| 1851 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
| 1852 | } | ||
| 1853 | |||
| 1854 | static ssize_t write_file_tx99_power(struct file *file, | ||
| 1855 | const char __user *user_buf, | ||
| 1856 | size_t count, loff_t *ppos) | ||
| 1857 | { | ||
| 1858 | struct ath_softc *sc = file->private_data; | ||
| 1859 | int r; | ||
| 1860 | u8 tx_power; | ||
| 1861 | |||
| 1862 | r = kstrtou8_from_user(user_buf, count, 0, &tx_power); | ||
| 1863 | if (r) | ||
| 1864 | return r; | ||
| 1865 | |||
| 1866 | if (tx_power > MAX_RATE_POWER) | ||
| 1867 | return -EINVAL; | ||
| 1868 | |||
| 1869 | sc->tx99_power = tx_power; | ||
| 1870 | |||
| 1871 | ath9k_ps_wakeup(sc); | ||
| 1872 | ath9k_hw_tx99_set_txpower(sc->sc_ah, sc->tx99_power); | ||
| 1873 | ath9k_ps_restore(sc); | ||
| 1874 | |||
| 1875 | return count; | ||
| 1876 | } | ||
| 1877 | |||
| 1878 | static const struct file_operations fops_tx99_power = { | ||
| 1879 | .read = read_file_tx99_power, | ||
| 1880 | .write = write_file_tx99_power, | ||
| 1881 | .open = simple_open, | ||
| 1882 | .owner = THIS_MODULE, | ||
| 1883 | .llseek = default_llseek, | ||
| 1884 | }; | ||
| 1885 | |||
| 1776 | int ath9k_init_debug(struct ath_hw *ah) | 1886 | int ath9k_init_debug(struct ath_hw *ah) |
| 1777 | { | 1887 | { |
| 1778 | struct ath_common *common = ath9k_hw_common(ah); | 1888 | struct ath_common *common = ath9k_hw_common(ah); |
| @@ -1864,5 +1974,15 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
| 1864 | debugfs_create_file("btcoex", S_IRUSR, sc->debug.debugfs_phy, sc, | 1974 | debugfs_create_file("btcoex", S_IRUSR, sc->debug.debugfs_phy, sc, |
| 1865 | &fops_btcoex); | 1975 | &fops_btcoex); |
| 1866 | #endif | 1976 | #endif |
| 1977 | if (config_enabled(CONFIG_ATH9K_TX99) && | ||
| 1978 | AR_SREV_9300_20_OR_LATER(ah)) { | ||
| 1979 | debugfs_create_file("tx99", S_IRUSR | S_IWUSR, | ||
| 1980 | sc->debug.debugfs_phy, sc, | ||
| 1981 | &fops_tx99); | ||
| 1982 | debugfs_create_file("tx99_power", S_IRUSR | S_IWUSR, | ||
| 1983 | sc->debug.debugfs_phy, sc, | ||
| 1984 | &fops_tx99_power); | ||
| 1985 | } | ||
| 1986 | |||
| 1867 | return 0; | 1987 | return 0; |
| 1868 | } | 1988 | } |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 6e1556fa2f3e..d6e3fa4299a4 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
| @@ -193,12 +193,12 @@ struct ath_tx_stats { | |||
| 193 | #define TXSTATS sc->debug.stats.txstats | 193 | #define TXSTATS sc->debug.stats.txstats |
| 194 | #define PR(str, elem) \ | 194 | #define PR(str, elem) \ |
| 195 | do { \ | 195 | do { \ |
| 196 | len += snprintf(buf + len, size - len, \ | 196 | len += scnprintf(buf + len, size - len, \ |
| 197 | "%s%13u%11u%10u%10u\n", str, \ | 197 | "%s%13u%11u%10u%10u\n", str, \ |
| 198 | TXSTATS[PR_QNUM(IEEE80211_AC_BE)].elem, \ | 198 | TXSTATS[PR_QNUM(IEEE80211_AC_BE)].elem,\ |
| 199 | TXSTATS[PR_QNUM(IEEE80211_AC_BK)].elem, \ | 199 | TXSTATS[PR_QNUM(IEEE80211_AC_BK)].elem,\ |
| 200 | TXSTATS[PR_QNUM(IEEE80211_AC_VI)].elem, \ | 200 | TXSTATS[PR_QNUM(IEEE80211_AC_VI)].elem,\ |
| 201 | TXSTATS[PR_QNUM(IEEE80211_AC_VO)].elem); \ | 201 | TXSTATS[PR_QNUM(IEEE80211_AC_VO)].elem); \ |
| 202 | } while(0) | 202 | } while(0) |
| 203 | 203 | ||
| 204 | #define RX_STAT_INC(c) (sc->debug.stats.rxstats.c++) | 204 | #define RX_STAT_INC(c) (sc->debug.stats.rxstats.c++) |
diff --git a/drivers/net/wireless/ath/ath9k/dfs.h b/drivers/net/wireless/ath/ath9k/dfs.h index 3c839f06a06a..c6fa3d5b5d74 100644 --- a/drivers/net/wireless/ath/ath9k/dfs.h +++ b/drivers/net/wireless/ath/ath9k/dfs.h | |||
| @@ -17,7 +17,7 @@ | |||
| 17 | 17 | ||
| 18 | #ifndef ATH9K_DFS_H | 18 | #ifndef ATH9K_DFS_H |
| 19 | #define ATH9K_DFS_H | 19 | #define ATH9K_DFS_H |
| 20 | #include "dfs_pattern_detector.h" | 20 | #include "../dfs_pattern_detector.h" |
| 21 | 21 | ||
| 22 | #if defined(CONFIG_ATH9K_DFS_CERTIFIED) | 22 | #if defined(CONFIG_ATH9K_DFS_CERTIFIED) |
| 23 | /** | 23 | /** |
diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.c b/drivers/net/wireless/ath/ath9k/dfs_debug.c index 3c6e4138a95d..90b8342d1ed4 100644 --- a/drivers/net/wireless/ath/ath9k/dfs_debug.c +++ b/drivers/net/wireless/ath/ath9k/dfs_debug.c | |||
| @@ -20,16 +20,16 @@ | |||
| 20 | 20 | ||
| 21 | #include "ath9k.h" | 21 | #include "ath9k.h" |
| 22 | #include "dfs_debug.h" | 22 | #include "dfs_debug.h" |
| 23 | #include "../dfs_pattern_detector.h" | ||
| 23 | 24 | ||
| 24 | 25 | static struct ath_dfs_pool_stats dfs_pool_stats = { 0 }; | |
| 25 | struct ath_dfs_pool_stats global_dfs_pool_stats = { 0 }; | ||
| 26 | 26 | ||
| 27 | #define ATH9K_DFS_STAT(s, p) \ | 27 | #define ATH9K_DFS_STAT(s, p) \ |
| 28 | len += snprintf(buf + len, size - len, "%28s : %10u\n", s, \ | 28 | len += scnprintf(buf + len, size - len, "%28s : %10u\n", s, \ |
| 29 | sc->debug.stats.dfs_stats.p); | 29 | sc->debug.stats.dfs_stats.p); |
| 30 | #define ATH9K_DFS_POOL_STAT(s, p) \ | 30 | #define ATH9K_DFS_POOL_STAT(s, p) \ |
| 31 | len += snprintf(buf + len, size - len, "%28s : %10u\n", s, \ | 31 | len += scnprintf(buf + len, size - len, "%28s : %10u\n", s, \ |
| 32 | global_dfs_pool_stats.p); | 32 | dfs_pool_stats.p); |
| 33 | 33 | ||
| 34 | static ssize_t read_file_dfs(struct file *file, char __user *user_buf, | 34 | static ssize_t read_file_dfs(struct file *file, char __user *user_buf, |
| 35 | size_t count, loff_t *ppos) | 35 | size_t count, loff_t *ppos) |
| @@ -44,12 +44,15 @@ static ssize_t read_file_dfs(struct file *file, char __user *user_buf, | |||
| 44 | if (buf == NULL) | 44 | if (buf == NULL) |
| 45 | return -ENOMEM; | 45 | return -ENOMEM; |
| 46 | 46 | ||
| 47 | len += snprintf(buf + len, size - len, "DFS support for " | 47 | if (sc->dfs_detector) |
| 48 | "macVersion = 0x%x, macRev = 0x%x: %s\n", | 48 | dfs_pool_stats = sc->dfs_detector->get_stats(sc->dfs_detector); |
| 49 | hw_ver->macVersion, hw_ver->macRev, | 49 | |
| 50 | (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_DFS) ? | 50 | len += scnprintf(buf + len, size - len, "DFS support for " |
| 51 | "macVersion = 0x%x, macRev = 0x%x: %s\n", | ||
| 52 | hw_ver->macVersion, hw_ver->macRev, | ||
| 53 | (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_DFS) ? | ||
| 51 | "enabled" : "disabled"); | 54 | "enabled" : "disabled"); |
| 52 | len += snprintf(buf + len, size - len, "Pulse detector statistics:\n"); | 55 | len += scnprintf(buf + len, size - len, "Pulse detector statistics:\n"); |
| 53 | ATH9K_DFS_STAT("pulse events reported ", pulses_total); | 56 | ATH9K_DFS_STAT("pulse events reported ", pulses_total); |
| 54 | ATH9K_DFS_STAT("invalid pulse events ", pulses_no_dfs); | 57 | ATH9K_DFS_STAT("invalid pulse events ", pulses_no_dfs); |
| 55 | ATH9K_DFS_STAT("DFS pulses detected ", pulses_detected); | 58 | ATH9K_DFS_STAT("DFS pulses detected ", pulses_detected); |
| @@ -59,11 +62,12 @@ static ssize_t read_file_dfs(struct file *file, char __user *user_buf, | |||
| 59 | ATH9K_DFS_STAT("Primary channel pulses ", pri_phy_errors); | 62 | ATH9K_DFS_STAT("Primary channel pulses ", pri_phy_errors); |
| 60 | ATH9K_DFS_STAT("Secondary channel pulses", ext_phy_errors); | 63 | ATH9K_DFS_STAT("Secondary channel pulses", ext_phy_errors); |
| 61 | ATH9K_DFS_STAT("Dual channel pulses ", dc_phy_errors); | 64 | ATH9K_DFS_STAT("Dual channel pulses ", dc_phy_errors); |
| 62 | len += snprintf(buf + len, size - len, "Radar detector statistics " | 65 | len += scnprintf(buf + len, size - len, "Radar detector statistics " |
| 63 | "(current DFS region: %d)\n", sc->dfs_detector->region); | 66 | "(current DFS region: %d)\n", |
| 67 | sc->dfs_detector->region); | ||
| 64 | ATH9K_DFS_STAT("Pulse events processed ", pulses_processed); | 68 | ATH9K_DFS_STAT("Pulse events processed ", pulses_processed); |
| 65 | ATH9K_DFS_STAT("Radars detected ", radar_detected); | 69 | ATH9K_DFS_STAT("Radars detected ", radar_detected); |
| 66 | len += snprintf(buf + len, size - len, "Global Pool statistics:\n"); | 70 | len += scnprintf(buf + len, size - len, "Global Pool statistics:\n"); |
| 67 | ATH9K_DFS_POOL_STAT("Pool references ", pool_reference); | 71 | ATH9K_DFS_POOL_STAT("Pool references ", pool_reference); |
| 68 | ATH9K_DFS_POOL_STAT("Pulses allocated ", pulse_allocated); | 72 | ATH9K_DFS_POOL_STAT("Pulses allocated ", pulse_allocated); |
| 69 | ATH9K_DFS_POOL_STAT("Pulses alloc error ", pulse_alloc_error); | 73 | ATH9K_DFS_POOL_STAT("Pulses alloc error ", pulse_alloc_error); |
diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.h b/drivers/net/wireless/ath/ath9k/dfs_debug.h index e36810a4b585..0a7ddf4c88c9 100644 --- a/drivers/net/wireless/ath/ath9k/dfs_debug.h +++ b/drivers/net/wireless/ath/ath9k/dfs_debug.h | |||
| @@ -51,25 +51,11 @@ struct ath_dfs_stats { | |||
| 51 | u32 radar_detected; | 51 | u32 radar_detected; |
| 52 | }; | 52 | }; |
| 53 | 53 | ||
| 54 | /** | ||
| 55 | * struct ath_dfs_pool_stats - DFS Statistics for global pools | ||
| 56 | */ | ||
| 57 | struct ath_dfs_pool_stats { | ||
| 58 | u32 pool_reference; | ||
| 59 | u32 pulse_allocated; | ||
| 60 | u32 pulse_alloc_error; | ||
| 61 | u32 pulse_used; | ||
| 62 | u32 pseq_allocated; | ||
| 63 | u32 pseq_alloc_error; | ||
| 64 | u32 pseq_used; | ||
| 65 | }; | ||
| 66 | #if defined(CONFIG_ATH9K_DFS_DEBUGFS) | 54 | #if defined(CONFIG_ATH9K_DFS_DEBUGFS) |
| 67 | 55 | ||
| 68 | #define DFS_STAT_INC(sc, c) (sc->debug.stats.dfs_stats.c++) | 56 | #define DFS_STAT_INC(sc, c) (sc->debug.stats.dfs_stats.c++) |
| 69 | void ath9k_dfs_init_debug(struct ath_softc *sc); | 57 | void ath9k_dfs_init_debug(struct ath_softc *sc); |
| 70 | 58 | ||
| 71 | #define DFS_POOL_STAT_INC(c) (global_dfs_pool_stats.c++) | ||
| 72 | #define DFS_POOL_STAT_DEC(c) (global_dfs_pool_stats.c--) | ||
| 73 | extern struct ath_dfs_pool_stats global_dfs_pool_stats; | 59 | extern struct ath_dfs_pool_stats global_dfs_pool_stats; |
| 74 | 60 | ||
| 75 | #else | 61 | #else |
| @@ -77,8 +63,6 @@ extern struct ath_dfs_pool_stats global_dfs_pool_stats; | |||
| 77 | #define DFS_STAT_INC(sc, c) do { } while (0) | 63 | #define DFS_STAT_INC(sc, c) do { } while (0) |
| 78 | static inline void ath9k_dfs_init_debug(struct ath_softc *sc) { } | 64 | static inline void ath9k_dfs_init_debug(struct ath_softc *sc) { } |
| 79 | 65 | ||
| 80 | #define DFS_POOL_STAT_INC(c) do { } while (0) | ||
| 81 | #define DFS_POOL_STAT_DEC(c) do { } while (0) | ||
| 82 | #endif /* CONFIG_ATH9K_DFS_DEBUGFS */ | 66 | #endif /* CONFIG_ATH9K_DFS_DEBUGFS */ |
| 83 | 67 | ||
| 84 | #endif /* ATH9K_DFS_DEBUG_H */ | 68 | #endif /* ATH9K_DFS_DEBUG_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 9ea8e4b779c9..b4091716e9b3 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c | |||
| @@ -129,10 +129,10 @@ static u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, | |||
| 129 | struct base_eep_header_4k *pBase = &eep->baseEepHeader; | 129 | struct base_eep_header_4k *pBase = &eep->baseEepHeader; |
| 130 | 130 | ||
| 131 | if (!dump_base_hdr) { | 131 | if (!dump_base_hdr) { |
| 132 | len += snprintf(buf + len, size - len, | 132 | len += scnprintf(buf + len, size - len, |
| 133 | "%20s :\n", "2GHz modal Header"); | 133 | "%20s :\n", "2GHz modal Header"); |
| 134 | len = ath9k_dump_4k_modal_eeprom(buf, len, size, | 134 | len = ath9k_dump_4k_modal_eeprom(buf, len, size, |
| 135 | &eep->modalHeader); | 135 | &eep->modalHeader); |
| 136 | goto out; | 136 | goto out; |
| 137 | } | 137 | } |
| 138 | 138 | ||
| @@ -160,8 +160,8 @@ static u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, | |||
| 160 | PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF); | 160 | PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF); |
| 161 | PR_EEP("TX Gain type", pBase->txGainType); | 161 | PR_EEP("TX Gain type", pBase->txGainType); |
| 162 | 162 | ||
| 163 | len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress", | 163 | len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress", |
| 164 | pBase->macAddr); | 164 | pBase->macAddr); |
| 165 | 165 | ||
| 166 | out: | 166 | out: |
| 167 | if (len > size) | 167 | if (len > size) |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 3ae1f3df0637..e1d0c217c104 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c | |||
| @@ -125,8 +125,8 @@ static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, | |||
| 125 | struct base_eep_ar9287_header *pBase = &eep->baseEepHeader; | 125 | struct base_eep_ar9287_header *pBase = &eep->baseEepHeader; |
| 126 | 126 | ||
| 127 | if (!dump_base_hdr) { | 127 | if (!dump_base_hdr) { |
| 128 | len += snprintf(buf + len, size - len, | 128 | len += scnprintf(buf + len, size - len, |
| 129 | "%20s :\n", "2GHz modal Header"); | 129 | "%20s :\n", "2GHz modal Header"); |
| 130 | len = ar9287_dump_modal_eeprom(buf, len, size, | 130 | len = ar9287_dump_modal_eeprom(buf, len, size, |
| 131 | &eep->modalHeader); | 131 | &eep->modalHeader); |
| 132 | goto out; | 132 | goto out; |
| @@ -157,8 +157,8 @@ static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, | |||
| 157 | PR_EEP("Power Table Offset", pBase->pwrTableOffset); | 157 | PR_EEP("Power Table Offset", pBase->pwrTableOffset); |
| 158 | PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl); | 158 | PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl); |
| 159 | 159 | ||
| 160 | len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress", | 160 | len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress", |
| 161 | pBase->macAddr); | 161 | pBase->macAddr); |
| 162 | 162 | ||
| 163 | out: | 163 | out: |
| 164 | if (len > size) | 164 | if (len > size) |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 1c25368b3836..39107e31e79a 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c | |||
| @@ -205,12 +205,12 @@ static u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, | |||
| 205 | struct base_eep_header *pBase = &eep->baseEepHeader; | 205 | struct base_eep_header *pBase = &eep->baseEepHeader; |
| 206 | 206 | ||
| 207 | if (!dump_base_hdr) { | 207 | if (!dump_base_hdr) { |
| 208 | len += snprintf(buf + len, size - len, | 208 | len += scnprintf(buf + len, size - len, |
| 209 | "%20s :\n", "2GHz modal Header"); | 209 | "%20s :\n", "2GHz modal Header"); |
| 210 | len = ath9k_def_dump_modal_eeprom(buf, len, size, | 210 | len = ath9k_def_dump_modal_eeprom(buf, len, size, |
| 211 | &eep->modalHeader[0]); | 211 | &eep->modalHeader[0]); |
| 212 | len += snprintf(buf + len, size - len, | 212 | len += scnprintf(buf + len, size - len, |
| 213 | "%20s :\n", "5GHz modal Header"); | 213 | "%20s :\n", "5GHz modal Header"); |
| 214 | len = ath9k_def_dump_modal_eeprom(buf, len, size, | 214 | len = ath9k_def_dump_modal_eeprom(buf, len, size, |
| 215 | &eep->modalHeader[1]); | 215 | &eep->modalHeader[1]); |
| 216 | goto out; | 216 | goto out; |
| @@ -240,8 +240,8 @@ static u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, | |||
| 240 | PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF); | 240 | PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF); |
| 241 | PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl); | 241 | PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl); |
| 242 | 242 | ||
| 243 | len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress", | 243 | len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress", |
| 244 | pBase->macAddr); | 244 | pBase->macAddr); |
| 245 | 245 | ||
| 246 | out: | 246 | out: |
| 247 | if (len > size) | 247 | if (len > size) |
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 4b412aaf4f36..c34f21241da9 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c | |||
| @@ -522,22 +522,22 @@ static int ath9k_dump_mci_btcoex(struct ath_softc *sc, u8 *buf, u32 size) | |||
| 522 | ATH_DUMP_BTCOEX("Concurrent Tx", btcoex_hw->mci.concur_tx); | 522 | ATH_DUMP_BTCOEX("Concurrent Tx", btcoex_hw->mci.concur_tx); |
| 523 | ATH_DUMP_BTCOEX("Concurrent RSSI cnt", btcoex->rssi_count); | 523 | ATH_DUMP_BTCOEX("Concurrent RSSI cnt", btcoex->rssi_count); |
| 524 | 524 | ||
| 525 | len += snprintf(buf + len, size - len, "BT Weights: "); | 525 | len += scnprintf(buf + len, size - len, "BT Weights: "); |
| 526 | for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++) | 526 | for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++) |
| 527 | len += snprintf(buf + len, size - len, "%08x ", | 527 | len += scnprintf(buf + len, size - len, "%08x ", |
| 528 | btcoex_hw->bt_weight[i]); | 528 | btcoex_hw->bt_weight[i]); |
| 529 | len += snprintf(buf + len, size - len, "\n"); | 529 | len += scnprintf(buf + len, size - len, "\n"); |
| 530 | len += snprintf(buf + len, size - len, "WLAN Weights: "); | 530 | len += scnprintf(buf + len, size - len, "WLAN Weights: "); |
| 531 | for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++) | 531 | for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++) |
| 532 | len += snprintf(buf + len, size - len, "%08x ", | 532 | len += scnprintf(buf + len, size - len, "%08x ", |
| 533 | btcoex_hw->wlan_weight[i]); | 533 | btcoex_hw->wlan_weight[i]); |
| 534 | len += snprintf(buf + len, size - len, "\n"); | 534 | len += scnprintf(buf + len, size - len, "\n"); |
| 535 | len += snprintf(buf + len, size - len, "Tx Priorities: "); | 535 | len += scnprintf(buf + len, size - len, "Tx Priorities: "); |
| 536 | for (i = 0; i < ATH_BTCOEX_STOMP_MAX; i++) | 536 | for (i = 0; i < ATH_BTCOEX_STOMP_MAX; i++) |
| 537 | len += snprintf(buf + len, size - len, "%08x ", | 537 | len += scnprintf(buf + len, size - len, "%08x ", |
| 538 | btcoex_hw->tx_prio[i]); | 538 | btcoex_hw->tx_prio[i]); |
| 539 | 539 | ||
| 540 | len += snprintf(buf + len, size - len, "\n"); | 540 | len += scnprintf(buf + len, size - len, "\n"); |
| 541 | 541 | ||
| 542 | return len; | 542 | return len; |
| 543 | } | 543 | } |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c index c1b45e2f8481..fb071ee4fcfb 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c | |||
| @@ -37,29 +37,29 @@ static ssize_t read_file_tgt_int_stats(struct file *file, char __user *user_buf, | |||
| 37 | 37 | ||
| 38 | ath9k_htc_ps_restore(priv); | 38 | ath9k_htc_ps_restore(priv); |
| 39 | 39 | ||
| 40 | len += snprintf(buf + len, sizeof(buf) - len, | 40 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 41 | "%20s : %10u\n", "RX", | 41 | "%20s : %10u\n", "RX", |
| 42 | be32_to_cpu(cmd_rsp.rx)); | 42 | be32_to_cpu(cmd_rsp.rx)); |
| 43 | 43 | ||
| 44 | len += snprintf(buf + len, sizeof(buf) - len, | 44 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 45 | "%20s : %10u\n", "RXORN", | 45 | "%20s : %10u\n", "RXORN", |
| 46 | be32_to_cpu(cmd_rsp.rxorn)); | 46 | be32_to_cpu(cmd_rsp.rxorn)); |
| 47 | 47 | ||
| 48 | len += snprintf(buf + len, sizeof(buf) - len, | 48 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 49 | "%20s : %10u\n", "RXEOL", | 49 | "%20s : %10u\n", "RXEOL", |
| 50 | be32_to_cpu(cmd_rsp.rxeol)); | 50 | be32_to_cpu(cmd_rsp.rxeol)); |
| 51 | 51 | ||
| 52 | len += snprintf(buf + len, sizeof(buf) - len, | 52 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 53 | "%20s : %10u\n", "TXURN", | 53 | "%20s : %10u\n", "TXURN", |
| 54 | be32_to_cpu(cmd_rsp.txurn)); | 54 | be32_to_cpu(cmd_rsp.txurn)); |
| 55 | 55 | ||
| 56 | len += snprintf(buf + len, sizeof(buf) - len, | 56 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 57 | "%20s : %10u\n", "TXTO", | 57 | "%20s : %10u\n", "TXTO", |
| 58 | be32_to_cpu(cmd_rsp.txto)); | 58 | be32_to_cpu(cmd_rsp.txto)); |
| 59 | 59 | ||
| 60 | len += snprintf(buf + len, sizeof(buf) - len, | 60 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 61 | "%20s : %10u\n", "CST", | 61 | "%20s : %10u\n", "CST", |
| 62 | be32_to_cpu(cmd_rsp.cst)); | 62 | be32_to_cpu(cmd_rsp.cst)); |
| 63 | 63 | ||
| 64 | if (len > sizeof(buf)) | 64 | if (len > sizeof(buf)) |
| 65 | len = sizeof(buf); | 65 | len = sizeof(buf); |
| @@ -95,41 +95,41 @@ static ssize_t read_file_tgt_tx_stats(struct file *file, char __user *user_buf, | |||
| 95 | 95 | ||
| 96 | ath9k_htc_ps_restore(priv); | 96 | ath9k_htc_ps_restore(priv); |
| 97 | 97 | ||
| 98 | len += snprintf(buf + len, sizeof(buf) - len, | 98 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 99 | "%20s : %10u\n", "Xretries", | 99 | "%20s : %10u\n", "Xretries", |
| 100 | be32_to_cpu(cmd_rsp.xretries)); | 100 | be32_to_cpu(cmd_rsp.xretries)); |
| 101 | 101 | ||
| 102 | len += snprintf(buf + len, sizeof(buf) - len, | 102 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 103 | "%20s : %10u\n", "FifoErr", | 103 | "%20s : %10u\n", "FifoErr", |
| 104 | be32_to_cpu(cmd_rsp.fifoerr)); | 104 | be32_to_cpu(cmd_rsp.fifoerr)); |
| 105 | 105 | ||
| 106 | len += snprintf(buf + len, sizeof(buf) - len, | 106 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 107 | "%20s : %10u\n", "Filtered", | 107 | "%20s : %10u\n", "Filtered", |
| 108 | be32_to_cpu(cmd_rsp.filtered)); | 108 | be32_to_cpu(cmd_rsp.filtered)); |
| 109 | 109 | ||
| 110 | len += snprintf(buf + len, sizeof(buf) - len, | 110 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 111 | "%20s : %10u\n", "TimerExp", | 111 | "%20s : %10u\n", "TimerExp", |
| 112 | be32_to_cpu(cmd_rsp.timer_exp)); | 112 | be32_to_cpu(cmd_rsp.timer_exp)); |
| 113 | 113 | ||
| 114 | len += snprintf(buf + len, sizeof(buf) - len, | 114 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 115 | "%20s : %10u\n", "ShortRetries", | 115 | "%20s : %10u\n", "ShortRetries", |
| 116 | be32_to_cpu(cmd_rsp.shortretries)); | 116 | be32_to_cpu(cmd_rsp.shortretries)); |
| 117 | 117 | ||
| 118 | len += snprintf(buf + len, sizeof(buf) - len, | 118 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 119 | "%20s : %10u\n", "LongRetries", | 119 | "%20s : %10u\n", "LongRetries", |
| 120 | be32_to_cpu(cmd_rsp.longretries)); | 120 | be32_to_cpu(cmd_rsp.longretries)); |
| 121 | 121 | ||
| 122 | len += snprintf(buf + len, sizeof(buf) - len, | 122 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 123 | "%20s : %10u\n", "QueueNull", | 123 | "%20s : %10u\n", "QueueNull", |
| 124 | be32_to_cpu(cmd_rsp.qnull)); | 124 | be32_to_cpu(cmd_rsp.qnull)); |
| 125 | 125 | ||
| 126 | len += snprintf(buf + len, sizeof(buf) - len, | 126 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 127 | "%20s : %10u\n", "EncapFail", | 127 | "%20s : %10u\n", "EncapFail", |
| 128 | be32_to_cpu(cmd_rsp.encap_fail)); | 128 | be32_to_cpu(cmd_rsp.encap_fail)); |
| 129 | 129 | ||
| 130 | len += snprintf(buf + len, sizeof(buf) - len, | 130 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 131 | "%20s : %10u\n", "NoBuf", | 131 | "%20s : %10u\n", "NoBuf", |
| 132 | be32_to_cpu(cmd_rsp.nobuf)); | 132 | be32_to_cpu(cmd_rsp.nobuf)); |
| 133 | 133 | ||
| 134 | if (len > sizeof(buf)) | 134 | if (len > sizeof(buf)) |
| 135 | len = sizeof(buf); | 135 | len = sizeof(buf); |
| @@ -165,17 +165,17 @@ static ssize_t read_file_tgt_rx_stats(struct file *file, char __user *user_buf, | |||
| 165 | 165 | ||
| 166 | ath9k_htc_ps_restore(priv); | 166 | ath9k_htc_ps_restore(priv); |
| 167 | 167 | ||
| 168 | len += snprintf(buf + len, sizeof(buf) - len, | 168 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 169 | "%20s : %10u\n", "NoBuf", | 169 | "%20s : %10u\n", "NoBuf", |
| 170 | be32_to_cpu(cmd_rsp.nobuf)); | 170 | be32_to_cpu(cmd_rsp.nobuf)); |
| 171 | 171 | ||
| 172 | len += snprintf(buf + len, sizeof(buf) - len, | 172 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 173 | "%20s : %10u\n", "HostSend", | 173 | "%20s : %10u\n", "HostSend", |
| 174 | be32_to_cpu(cmd_rsp.host_send)); | 174 | be32_to_cpu(cmd_rsp.host_send)); |
| 175 | 175 | ||
| 176 | len += snprintf(buf + len, sizeof(buf) - len, | 176 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 177 | "%20s : %10u\n", "HostDone", | 177 | "%20s : %10u\n", "HostDone", |
| 178 | be32_to_cpu(cmd_rsp.host_done)); | 178 | be32_to_cpu(cmd_rsp.host_done)); |
| 179 | 179 | ||
| 180 | if (len > sizeof(buf)) | 180 | if (len > sizeof(buf)) |
| 181 | len = sizeof(buf); | 181 | len = sizeof(buf); |
| @@ -197,37 +197,37 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | |||
| 197 | char buf[512]; | 197 | char buf[512]; |
| 198 | unsigned int len = 0; | 198 | unsigned int len = 0; |
| 199 | 199 | ||
| 200 | len += snprintf(buf + len, sizeof(buf) - len, | 200 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 201 | "%20s : %10u\n", "Buffers queued", | 201 | "%20s : %10u\n", "Buffers queued", |
| 202 | priv->debug.tx_stats.buf_queued); | 202 | priv->debug.tx_stats.buf_queued); |
| 203 | len += snprintf(buf + len, sizeof(buf) - len, | 203 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 204 | "%20s : %10u\n", "Buffers completed", | 204 | "%20s : %10u\n", "Buffers completed", |
| 205 | priv->debug.tx_stats.buf_completed); | 205 | priv->debug.tx_stats.buf_completed); |
| 206 | len += snprintf(buf + len, sizeof(buf) - len, | 206 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 207 | "%20s : %10u\n", "SKBs queued", | 207 | "%20s : %10u\n", "SKBs queued", |
| 208 | priv->debug.tx_stats.skb_queued); | 208 | priv->debug.tx_stats.skb_queued); |
| 209 | len += snprintf(buf + len, sizeof(buf) - len, | 209 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 210 | "%20s : %10u\n", "SKBs success", | 210 | "%20s : %10u\n", "SKBs success", |
| 211 | priv->debug.tx_stats.skb_success); | 211 | priv->debug.tx_stats.skb_success); |
| 212 | len += snprintf(buf + len, sizeof(buf) - len, | 212 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 213 | "%20s : %10u\n", "SKBs failed", | 213 | "%20s : %10u\n", "SKBs failed", |
| 214 | priv->debug.tx_stats.skb_failed); | 214 | priv->debug.tx_stats.skb_failed); |
| 215 | len += snprintf(buf + len, sizeof(buf) - len, | 215 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 216 | "%20s : %10u\n", "CAB queued", | 216 | "%20s : %10u\n", "CAB queued", |
| 217 | priv->debug.tx_stats.cab_queued); | 217 | priv->debug.tx_stats.cab_queued); |
| 218 | 218 | ||
| 219 | len += snprintf(buf + len, sizeof(buf) - len, | 219 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 220 | "%20s : %10u\n", "BE queued", | 220 | "%20s : %10u\n", "BE queued", |
| 221 | priv->debug.tx_stats.queue_stats[IEEE80211_AC_BE]); | 221 | priv->debug.tx_stats.queue_stats[IEEE80211_AC_BE]); |
| 222 | len += snprintf(buf + len, sizeof(buf) - len, | 222 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 223 | "%20s : %10u\n", "BK queued", | 223 | "%20s : %10u\n", "BK queued", |
| 224 | priv->debug.tx_stats.queue_stats[IEEE80211_AC_BK]); | 224 | priv->debug.tx_stats.queue_stats[IEEE80211_AC_BK]); |
| 225 | len += snprintf(buf + len, sizeof(buf) - len, | 225 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 226 | "%20s : %10u\n", "VI queued", | 226 | "%20s : %10u\n", "VI queued", |
| 227 | priv->debug.tx_stats.queue_stats[IEEE80211_AC_VI]); | 227 | priv->debug.tx_stats.queue_stats[IEEE80211_AC_VI]); |
| 228 | len += snprintf(buf + len, sizeof(buf) - len, | 228 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 229 | "%20s : %10u\n", "VO queued", | 229 | "%20s : %10u\n", "VO queued", |
| 230 | priv->debug.tx_stats.queue_stats[IEEE80211_AC_VO]); | 230 | priv->debug.tx_stats.queue_stats[IEEE80211_AC_VO]); |
| 231 | 231 | ||
| 232 | if (len > sizeof(buf)) | 232 | if (len > sizeof(buf)) |
| 233 | len = sizeof(buf); | 233 | len = sizeof(buf); |
| @@ -273,8 +273,8 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
| 273 | size_t count, loff_t *ppos) | 273 | size_t count, loff_t *ppos) |
| 274 | { | 274 | { |
| 275 | #define PHY_ERR(s, p) \ | 275 | #define PHY_ERR(s, p) \ |
| 276 | len += snprintf(buf + len, size - len, "%20s : %10u\n", s, \ | 276 | len += scnprintf(buf + len, size - len, "%20s : %10u\n", s, \ |
| 277 | priv->debug.rx_stats.err_phy_stats[p]); | 277 | priv->debug.rx_stats.err_phy_stats[p]); |
| 278 | 278 | ||
| 279 | struct ath9k_htc_priv *priv = file->private_data; | 279 | struct ath9k_htc_priv *priv = file->private_data; |
| 280 | char *buf; | 280 | char *buf; |
| @@ -285,37 +285,37 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
| 285 | if (buf == NULL) | 285 | if (buf == NULL) |
| 286 | return -ENOMEM; | 286 | return -ENOMEM; |
| 287 | 287 | ||
| 288 | len += snprintf(buf + len, size - len, | 288 | len += scnprintf(buf + len, size - len, |
| 289 | "%20s : %10u\n", "SKBs allocated", | 289 | "%20s : %10u\n", "SKBs allocated", |
| 290 | priv->debug.rx_stats.skb_allocated); | 290 | priv->debug.rx_stats.skb_allocated); |
| 291 | len += snprintf(buf + len, size - len, | 291 | len += scnprintf(buf + len, size - len, |
| 292 | "%20s : %10u\n", "SKBs completed", | 292 | "%20s : %10u\n", "SKBs completed", |
| 293 | priv->debug.rx_stats.skb_completed); | 293 | priv->debug.rx_stats.skb_completed); |
| 294 | len += snprintf(buf + len, size - len, | 294 | len += scnprintf(buf + len, size - len, |
| 295 | "%20s : %10u\n", "SKBs Dropped", | 295 | "%20s : %10u\n", "SKBs Dropped", |
| 296 | priv->debug.rx_stats.skb_dropped); | 296 | priv->debug.rx_stats.skb_dropped); |
| 297 | 297 | ||
| 298 | len += snprintf(buf + len, size - len, | 298 | len += scnprintf(buf + len, size - len, |
| 299 | "%20s : %10u\n", "CRC ERR", | 299 | "%20s : %10u\n", "CRC ERR", |
| 300 | priv->debug.rx_stats.err_crc); | 300 | priv->debug.rx_stats.err_crc); |
| 301 | len += snprintf(buf + len, size - len, | 301 | len += scnprintf(buf + len, size - len, |
| 302 | "%20s : %10u\n", "DECRYPT CRC ERR", | 302 | "%20s : %10u\n", "DECRYPT CRC ERR", |
| 303 | priv->debug.rx_stats.err_decrypt_crc); | 303 | priv->debug.rx_stats.err_decrypt_crc); |
| 304 | len += snprintf(buf + len, size - len, | 304 | len += scnprintf(buf + len, size - len, |
| 305 | "%20s : %10u\n", "MIC ERR", | 305 | "%20s : %10u\n", "MIC ERR", |
| 306 | priv->debug.rx_stats.err_mic); | 306 | priv->debug.rx_stats.err_mic); |
| 307 | len += snprintf(buf + len, size - len, | 307 | len += scnprintf(buf + len, size - len, |
| 308 | "%20s : %10u\n", "PRE-DELIM CRC ERR", | 308 | "%20s : %10u\n", "PRE-DELIM CRC ERR", |
| 309 | priv->debug.rx_stats.err_pre_delim); | 309 | priv->debug.rx_stats.err_pre_delim); |
| 310 | len += snprintf(buf + len, size - len, | 310 | len += scnprintf(buf + len, size - len, |
| 311 | "%20s : %10u\n", "POST-DELIM CRC ERR", | 311 | "%20s : %10u\n", "POST-DELIM CRC ERR", |
| 312 | priv->debug.rx_stats.err_post_delim); | 312 | priv->debug.rx_stats.err_post_delim); |
| 313 | len += snprintf(buf + len, size - len, | 313 | len += scnprintf(buf + len, size - len, |
| 314 | "%20s : %10u\n", "DECRYPT BUSY ERR", | 314 | "%20s : %10u\n", "DECRYPT BUSY ERR", |
| 315 | priv->debug.rx_stats.err_decrypt_busy); | 315 | priv->debug.rx_stats.err_decrypt_busy); |
| 316 | len += snprintf(buf + len, size - len, | 316 | len += scnprintf(buf + len, size - len, |
| 317 | "%20s : %10u\n", "TOTAL PHY ERR", | 317 | "%20s : %10u\n", "TOTAL PHY ERR", |
| 318 | priv->debug.rx_stats.err_phy); | 318 | priv->debug.rx_stats.err_phy); |
| 319 | 319 | ||
| 320 | 320 | ||
| 321 | PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN); | 321 | PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN); |
| @@ -372,16 +372,16 @@ static ssize_t read_file_slot(struct file *file, char __user *user_buf, | |||
| 372 | 372 | ||
| 373 | spin_lock_bh(&priv->tx.tx_lock); | 373 | spin_lock_bh(&priv->tx.tx_lock); |
| 374 | 374 | ||
| 375 | len += snprintf(buf + len, sizeof(buf) - len, "TX slot bitmap : "); | 375 | len += scnprintf(buf + len, sizeof(buf) - len, "TX slot bitmap : "); |
| 376 | 376 | ||
| 377 | len += bitmap_scnprintf(buf + len, sizeof(buf) - len, | 377 | len += bitmap_scnprintf(buf + len, sizeof(buf) - len, |
| 378 | priv->tx.tx_slot, MAX_TX_BUF_NUM); | 378 | priv->tx.tx_slot, MAX_TX_BUF_NUM); |
| 379 | 379 | ||
| 380 | len += snprintf(buf + len, sizeof(buf) - len, "\n"); | 380 | len += scnprintf(buf + len, sizeof(buf) - len, "\n"); |
| 381 | 381 | ||
| 382 | len += snprintf(buf + len, sizeof(buf) - len, | 382 | len += scnprintf(buf + len, sizeof(buf) - len, |
| 383 | "Used slots : %d\n", | 383 | "Used slots : %d\n", |
| 384 | bitmap_weight(priv->tx.tx_slot, MAX_TX_BUF_NUM)); | 384 | bitmap_weight(priv->tx.tx_slot, MAX_TX_BUF_NUM)); |
| 385 | 385 | ||
| 386 | spin_unlock_bh(&priv->tx.tx_lock); | 386 | spin_unlock_bh(&priv->tx.tx_lock); |
| 387 | 387 | ||
| @@ -405,30 +405,30 @@ static ssize_t read_file_queue(struct file *file, char __user *user_buf, | |||
| 405 | char buf[512]; | 405 | char buf[512]; |
| 406 | unsigned int len = 0; | 406 | unsigned int len = 0; |
| 407 | 407 | ||
| 408 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | 408 | len += scnprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", |
| 409 | "Mgmt endpoint", skb_queue_len(&priv->tx.mgmt_ep_queue)); | 409 | "Mgmt endpoint", skb_queue_len(&priv->tx.mgmt_ep_queue)); |
| 410 | 410 | ||
| 411 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | 411 | len += scnprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", |
| 412 | "Cab endpoint", skb_queue_len(&priv->tx.cab_ep_queue)); | 412 | "Cab endpoint", skb_queue_len(&priv->tx.cab_ep_queue)); |
| 413 | 413 | ||
| 414 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | 414 | len += scnprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", |
| 415 | "Data BE endpoint", skb_queue_len(&priv->tx.data_be_queue)); | 415 | "Data BE endpoint", skb_queue_len(&priv->tx.data_be_queue)); |
| 416 | 416 | ||
| 417 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | 417 | len += scnprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", |
| 418 | "Data BK endpoint", skb_queue_len(&priv->tx.data_bk_queue)); | 418 | "Data BK endpoint", skb_queue_len(&priv->tx.data_bk_queue)); |
| 419 | 419 | ||
| 420 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | 420 | len += scnprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", |
| 421 | "Data VI endpoint", skb_queue_len(&priv->tx.data_vi_queue)); | 421 | "Data VI endpoint", skb_queue_len(&priv->tx.data_vi_queue)); |
| 422 | 422 | ||
| 423 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | 423 | len += scnprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", |
| 424 | "Data VO endpoint", skb_queue_len(&priv->tx.data_vo_queue)); | 424 | "Data VO endpoint", skb_queue_len(&priv->tx.data_vo_queue)); |
| 425 | 425 | ||
| 426 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | 426 | len += scnprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", |
| 427 | "Failed queue", skb_queue_len(&priv->tx.tx_failed)); | 427 | "Failed queue", skb_queue_len(&priv->tx.tx_failed)); |
| 428 | 428 | ||
| 429 | spin_lock_bh(&priv->tx.tx_lock); | 429 | spin_lock_bh(&priv->tx.tx_lock); |
| 430 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | 430 | len += scnprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", |
| 431 | "Queued count", priv->tx.queued_cnt); | 431 | "Queued count", priv->tx.queued_cnt); |
| 432 | spin_unlock_bh(&priv->tx.tx_lock); | 432 | spin_unlock_bh(&priv->tx.tx_lock); |
| 433 | 433 | ||
| 434 | if (len > sizeof(buf)) | 434 | if (len > sizeof(buf)) |
| @@ -507,70 +507,70 @@ static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf, | |||
| 507 | if (buf == NULL) | 507 | if (buf == NULL) |
| 508 | return -ENOMEM; | 508 | return -ENOMEM; |
| 509 | 509 | ||
| 510 | len += snprintf(buf + len, size - len, | 510 | len += scnprintf(buf + len, size - len, |
| 511 | "%20s : %10d\n", "Major Version", | 511 | "%20s : %10d\n", "Major Version", |
| 512 | pBase->version >> 12); | 512 | pBase->version >> 12); |
| 513 | len += snprintf(buf + len, size - len, | 513 | len += scnprintf(buf + len, size - len, |
| 514 | "%20s : %10d\n", "Minor Version", | 514 | "%20s : %10d\n", "Minor Version", |
| 515 | pBase->version & 0xFFF); | 515 | pBase->version & 0xFFF); |
| 516 | len += snprintf(buf + len, size - len, | 516 | len += scnprintf(buf + len, size - len, |
| 517 | "%20s : %10d\n", "Checksum", | 517 | "%20s : %10d\n", "Checksum", |
| 518 | pBase->checksum); | 518 | pBase->checksum); |
| 519 | len += snprintf(buf + len, size - len, | 519 | len += scnprintf(buf + len, size - len, |
| 520 | "%20s : %10d\n", "Length", | 520 | "%20s : %10d\n", "Length", |
| 521 | pBase->length); | 521 | pBase->length); |
| 522 | len += snprintf(buf + len, size - len, | 522 | len += scnprintf(buf + len, size - len, |
| 523 | "%20s : %10d\n", "RegDomain1", | 523 | "%20s : %10d\n", "RegDomain1", |
| 524 | pBase->regDmn[0]); | 524 | pBase->regDmn[0]); |
| 525 | len += snprintf(buf + len, size - len, | 525 | len += scnprintf(buf + len, size - len, |
| 526 | "%20s : %10d\n", "RegDomain2", | 526 | "%20s : %10d\n", "RegDomain2", |
| 527 | pBase->regDmn[1]); | 527 | pBase->regDmn[1]); |
| 528 | len += snprintf(buf + len, size - len, | 528 | len += scnprintf(buf + len, size - len, |
| 529 | "%20s : %10d\n", | 529 | "%20s : %10d\n", |
| 530 | "TX Mask", pBase->txMask); | 530 | "TX Mask", pBase->txMask); |
| 531 | len += snprintf(buf + len, size - len, | 531 | len += scnprintf(buf + len, size - len, |
| 532 | "%20s : %10d\n", | 532 | "%20s : %10d\n", |
| 533 | "RX Mask", pBase->rxMask); | 533 | "RX Mask", pBase->rxMask); |
| 534 | len += snprintf(buf + len, size - len, | 534 | len += scnprintf(buf + len, size - len, |
| 535 | "%20s : %10d\n", | 535 | "%20s : %10d\n", |
| 536 | "Allow 5GHz", | 536 | "Allow 5GHz", |
| 537 | !!(pBase->opCapFlags & AR5416_OPFLAGS_11A)); | 537 | !!(pBase->opCapFlags & AR5416_OPFLAGS_11A)); |
| 538 | len += snprintf(buf + len, size - len, | 538 | len += scnprintf(buf + len, size - len, |
| 539 | "%20s : %10d\n", | 539 | "%20s : %10d\n", |
| 540 | "Allow 2GHz", | 540 | "Allow 2GHz", |
| 541 | !!(pBase->opCapFlags & AR5416_OPFLAGS_11G)); | 541 | !!(pBase->opCapFlags & AR5416_OPFLAGS_11G)); |
| 542 | len += snprintf(buf + len, size - len, | 542 | len += scnprintf(buf + len, size - len, |
| 543 | "%20s : %10d\n", | 543 | "%20s : %10d\n", |
| 544 | "Disable 2GHz HT20", | 544 | "Disable 2GHz HT20", |
| 545 | !!(pBase->opCapFlags & AR5416_OPFLAGS_N_2G_HT20)); | 545 | !!(pBase->opCapFlags & AR5416_OPFLAGS_N_2G_HT20)); |
| 546 | len += snprintf(buf + len, size - len, | 546 | len += scnprintf(buf + len, size - len, |
| 547 | "%20s : %10d\n", | 547 | "%20s : %10d\n", |
| 548 | "Disable 2GHz HT40", | 548 | "Disable 2GHz HT40", |
| 549 | !!(pBase->opCapFlags & AR5416_OPFLAGS_N_2G_HT40)); | 549 | !!(pBase->opCapFlags & AR5416_OPFLAGS_N_2G_HT40)); |
| 550 | len += snprintf(buf + len, size - len, | 550 | len += scnprintf(buf + len, size - len, |
| 551 | "%20s : %10d\n", | 551 | "%20s : %10d\n", |
| 552 | "Disable 5Ghz HT20", | 552 | "Disable 5Ghz HT20", |
| 553 | !!(pBase->opCapFlags & AR5416_OPFLAGS_N_5G_HT20)); | 553 | !!(pBase->opCapFlags & AR5416_OPFLAGS_N_5G_HT20)); |
| 554 | len += snprintf(buf + len, size - len, | 554 | len += scnprintf(buf + len, size - len, |
| 555 | "%20s : %10d\n", | 555 | "%20s : %10d\n", |
| 556 | "Disable 5Ghz HT40", | 556 | "Disable 5Ghz HT40", |
| 557 | !!(pBase->opCapFlags & AR5416_OPFLAGS_N_5G_HT40)); | 557 | !!(pBase->opCapFlags & AR5416_OPFLAGS_N_5G_HT40)); |
| 558 | len += snprintf(buf + len, size - len, | 558 | len += scnprintf(buf + len, size - len, |
| 559 | "%20s : %10d\n", | 559 | "%20s : %10d\n", |
| 560 | "Big Endian", | 560 | "Big Endian", |
| 561 | !!(pBase->eepMisc & 0x01)); | 561 | !!(pBase->eepMisc & 0x01)); |
| 562 | len += snprintf(buf + len, size - len, | 562 | len += scnprintf(buf + len, size - len, |
| 563 | "%20s : %10d\n", | 563 | "%20s : %10d\n", |
| 564 | "Cal Bin Major Ver", | 564 | "Cal Bin Major Ver", |
| 565 | (pBase->binBuildNumber >> 24) & 0xFF); | 565 | (pBase->binBuildNumber >> 24) & 0xFF); |
| 566 | len += snprintf(buf + len, size - len, | 566 | len += scnprintf(buf + len, size - len, |
| 567 | "%20s : %10d\n", | 567 | "%20s : %10d\n", |
| 568 | "Cal Bin Minor Ver", | 568 | "Cal Bin Minor Ver", |
| 569 | (pBase->binBuildNumber >> 16) & 0xFF); | 569 | (pBase->binBuildNumber >> 16) & 0xFF); |
| 570 | len += snprintf(buf + len, size - len, | 570 | len += scnprintf(buf + len, size - len, |
| 571 | "%20s : %10d\n", | 571 | "%20s : %10d\n", |
| 572 | "Cal Bin Build", | 572 | "Cal Bin Build", |
| 573 | (pBase->binBuildNumber >> 8) & 0xFF); | 573 | (pBase->binBuildNumber >> 8) & 0xFF); |
| 574 | 574 | ||
| 575 | /* | 575 | /* |
| 576 | * UB91 specific data. | 576 | * UB91 specific data. |
| @@ -579,10 +579,10 @@ static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf, | |||
| 579 | struct base_eep_header_4k *pBase4k = | 579 | struct base_eep_header_4k *pBase4k = |
| 580 | &priv->ah->eeprom.map4k.baseEepHeader; | 580 | &priv->ah->eeprom.map4k.baseEepHeader; |
| 581 | 581 | ||
| 582 | len += snprintf(buf + len, size - len, | 582 | len += scnprintf(buf + len, size - len, |
| 583 | "%20s : %10d\n", | 583 | "%20s : %10d\n", |
| 584 | "TX Gain type", | 584 | "TX Gain type", |
| 585 | pBase4k->txGainType); | 585 | pBase4k->txGainType); |
| 586 | } | 586 | } |
| 587 | 587 | ||
| 588 | /* | 588 | /* |
| @@ -592,19 +592,19 @@ static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf, | |||
| 592 | struct base_eep_ar9287_header *pBase9287 = | 592 | struct base_eep_ar9287_header *pBase9287 = |
| 593 | &priv->ah->eeprom.map9287.baseEepHeader; | 593 | &priv->ah->eeprom.map9287.baseEepHeader; |
| 594 | 594 | ||
| 595 | len += snprintf(buf + len, size - len, | 595 | len += scnprintf(buf + len, size - len, |
| 596 | "%20s : %10ddB\n", | 596 | "%20s : %10ddB\n", |
| 597 | "Power Table Offset", | 597 | "Power Table Offset", |
| 598 | pBase9287->pwrTableOffset); | 598 | pBase9287->pwrTableOffset); |
| 599 | 599 | ||
| 600 | len += snprintf(buf + len, size - len, | 600 | len += scnprintf(buf + len, size - len, |
| 601 | "%20s : %10d\n", | 601 | "%20s : %10d\n", |
| 602 | "OpenLoop Power Ctrl", | 602 | "OpenLoop Power Ctrl", |
| 603 | pBase9287->openLoopPwrCntl); | 603 | pBase9287->openLoopPwrCntl); |
| 604 | } | 604 | } |
| 605 | 605 | ||
| 606 | len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress", | 606 | len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress", |
| 607 | pBase->macAddr); | 607 | pBase->macAddr); |
| 608 | if (len > size) | 608 | if (len > size) |
| 609 | len = size; | 609 | len = size; |
| 610 | 610 | ||
| @@ -627,8 +627,8 @@ static ssize_t read_4k_modal_eeprom(struct file *file, | |||
| 627 | { | 627 | { |
| 628 | #define PR_EEP(_s, _val) \ | 628 | #define PR_EEP(_s, _val) \ |
| 629 | do { \ | 629 | do { \ |
| 630 | len += snprintf(buf + len, size - len, "%20s : %10d\n", \ | 630 | len += scnprintf(buf + len, size - len, "%20s : %10d\n",\ |
| 631 | _s, (_val)); \ | 631 | _s, (_val)); \ |
| 632 | } while (0) | 632 | } while (0) |
| 633 | 633 | ||
| 634 | struct ath9k_htc_priv *priv = file->private_data; | 634 | struct ath9k_htc_priv *priv = file->private_data; |
| @@ -708,12 +708,12 @@ static ssize_t read_def_modal_eeprom(struct file *file, | |||
| 708 | do { \ | 708 | do { \ |
| 709 | if (pBase->opCapFlags & AR5416_OPFLAGS_11G) { \ | 709 | if (pBase->opCapFlags & AR5416_OPFLAGS_11G) { \ |
| 710 | pModal = &priv->ah->eeprom.def.modalHeader[1]; \ | 710 | pModal = &priv->ah->eeprom.def.modalHeader[1]; \ |
| 711 | len += snprintf(buf + len, size - len, "%20s : %8d%7s", \ | 711 | len += scnprintf(buf + len, size - len, "%20s : %8d%7s", \ |
| 712 | _s, (_val), "|"); \ | 712 | _s, (_val), "|"); \ |
| 713 | } \ | 713 | } \ |
| 714 | if (pBase->opCapFlags & AR5416_OPFLAGS_11A) { \ | 714 | if (pBase->opCapFlags & AR5416_OPFLAGS_11A) { \ |
| 715 | pModal = &priv->ah->eeprom.def.modalHeader[0]; \ | 715 | pModal = &priv->ah->eeprom.def.modalHeader[0]; \ |
| 716 | len += snprintf(buf + len, size - len, "%9d\n", \ | 716 | len += scnprintf(buf + len, size - len, "%9d\n",\ |
| 717 | (_val)); \ | 717 | (_val)); \ |
| 718 | } \ | 718 | } \ |
| 719 | } while (0) | 719 | } while (0) |
| @@ -729,10 +729,10 @@ static ssize_t read_def_modal_eeprom(struct file *file, | |||
| 729 | if (buf == NULL) | 729 | if (buf == NULL) |
| 730 | return -ENOMEM; | 730 | return -ENOMEM; |
| 731 | 731 | ||
| 732 | len += snprintf(buf + len, size - len, | 732 | len += scnprintf(buf + len, size - len, |
| 733 | "%31s %15s\n", "2G", "5G"); | 733 | "%31s %15s\n", "2G", "5G"); |
| 734 | len += snprintf(buf + len, size - len, | 734 | len += scnprintf(buf + len, size - len, |
| 735 | "%32s %16s\n", "====", "====\n"); | 735 | "%32s %16s\n", "====", "====\n"); |
| 736 | 736 | ||
| 737 | PR_EEP("Chain0 Ant. Control", pModal->antCtrlChain[0]); | 737 | PR_EEP("Chain0 Ant. Control", pModal->antCtrlChain[0]); |
| 738 | PR_EEP("Chain1 Ant. Control", pModal->antCtrlChain[1]); | 738 | PR_EEP("Chain1 Ant. Control", pModal->antCtrlChain[1]); |
| @@ -814,8 +814,8 @@ static ssize_t read_9287_modal_eeprom(struct file *file, | |||
| 814 | { | 814 | { |
| 815 | #define PR_EEP(_s, _val) \ | 815 | #define PR_EEP(_s, _val) \ |
| 816 | do { \ | 816 | do { \ |
| 817 | len += snprintf(buf + len, size - len, "%20s : %10d\n", \ | 817 | len += scnprintf(buf + len, size - len, "%20s : %10d\n",\ |
| 818 | _s, (_val)); \ | 818 | _s, (_val)); \ |
| 819 | } while (0) | 819 | } while (0) |
| 820 | 820 | ||
| 821 | struct ath9k_htc_priv *priv = file->private_data; | 821 | struct ath9k_htc_priv *priv = file->private_data; |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index d44258172c0f..9a2657fdd9cc 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
| @@ -24,30 +24,10 @@ | |||
| 24 | static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv, | 24 | static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv, |
| 25 | struct ath9k_channel *ichan) | 25 | struct ath9k_channel *ichan) |
| 26 | { | 26 | { |
| 27 | enum htc_phymode mode; | 27 | if (IS_CHAN_5GHZ(ichan)) |
| 28 | 28 | return HTC_MODE_11NA; | |
| 29 | mode = -EINVAL; | ||
| 30 | |||
| 31 | switch (ichan->chanmode) { | ||
| 32 | case CHANNEL_G: | ||
| 33 | case CHANNEL_G_HT20: | ||
| 34 | case CHANNEL_G_HT40PLUS: | ||
| 35 | case CHANNEL_G_HT40MINUS: | ||
| 36 | mode = HTC_MODE_11NG; | ||
| 37 | break; | ||
| 38 | case CHANNEL_A: | ||
| 39 | case CHANNEL_A_HT20: | ||
| 40 | case CHANNEL_A_HT40PLUS: | ||
| 41 | case CHANNEL_A_HT40MINUS: | ||
| 42 | mode = HTC_MODE_11NA; | ||
| 43 | break; | ||
| 44 | default: | ||
| 45 | break; | ||
| 46 | } | ||
| 47 | 29 | ||
| 48 | WARN_ON(mode < 0); | 30 | return HTC_MODE_11NG; |
| 49 | |||
| 50 | return mode; | ||
| 51 | } | 31 | } |
| 52 | 32 | ||
| 53 | bool ath9k_htc_setpower(struct ath9k_htc_priv *priv, | 33 | bool ath9k_htc_setpower(struct ath9k_htc_priv *priv, |
| @@ -926,7 +906,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
| 926 | WMI_CMD(WMI_FLUSH_RECV_CMDID); | 906 | WMI_CMD(WMI_FLUSH_RECV_CMDID); |
| 927 | 907 | ||
| 928 | /* setup initial channel */ | 908 | /* setup initial channel */ |
| 929 | init_channel = ath9k_cmn_get_curchannel(hw, ah); | 909 | init_channel = ath9k_cmn_get_channel(hw, ah, &hw->conf.chandef); |
| 930 | 910 | ||
| 931 | ret = ath9k_hw_reset(ah, init_channel, ah->caldata, false); | 911 | ret = ath9k_hw_reset(ah, init_channel, ah->caldata, false); |
| 932 | if (ret) { | 912 | if (ret) { |
| @@ -1208,9 +1188,7 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) | |||
| 1208 | ath_dbg(common, CONFIG, "Set channel: %d MHz\n", | 1188 | ath_dbg(common, CONFIG, "Set channel: %d MHz\n", |
| 1209 | curchan->center_freq); | 1189 | curchan->center_freq); |
| 1210 | 1190 | ||
| 1211 | ath9k_cmn_update_ichannel(&priv->ah->channels[pos], | 1191 | ath9k_cmn_get_channel(hw, priv->ah, &hw->conf.chandef); |
| 1212 | &hw->conf.chandef); | ||
| 1213 | |||
| 1214 | if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) { | 1192 | if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) { |
| 1215 | ath_err(common, "Unable to set channel\n"); | 1193 | ath_err(common, "Unable to set channel\n"); |
| 1216 | ret = -EINVAL; | 1194 | ret = -EINVAL; |
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 83f4927aeaca..4f9378ddf07f 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h | |||
| @@ -78,6 +78,22 @@ static inline void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah, | |||
| 78 | ath9k_hw_ops(ah)->antdiv_comb_conf_set(ah, antconf); | 78 | ath9k_hw_ops(ah)->antdiv_comb_conf_set(ah, antconf); |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | static inline void ath9k_hw_tx99_start(struct ath_hw *ah, u32 qnum) | ||
| 82 | { | ||
| 83 | ath9k_hw_ops(ah)->tx99_start(ah, qnum); | ||
| 84 | } | ||
| 85 | |||
| 86 | static inline void ath9k_hw_tx99_stop(struct ath_hw *ah) | ||
| 87 | { | ||
| 88 | ath9k_hw_ops(ah)->tx99_stop(ah); | ||
| 89 | } | ||
| 90 | |||
| 91 | static inline void ath9k_hw_tx99_set_txpower(struct ath_hw *ah, u8 power) | ||
| 92 | { | ||
| 93 | if (ath9k_hw_ops(ah)->tx99_set_txpower) | ||
| 94 | ath9k_hw_ops(ah)->tx99_set_txpower(ah, power); | ||
| 95 | } | ||
| 96 | |||
| 81 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | 97 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT |
| 82 | 98 | ||
| 83 | static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable) | 99 | static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable) |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index ecc6ec4a1edb..54b04155e43b 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
| @@ -130,29 +130,29 @@ void ath9k_debug_sync_cause(struct ath_common *common, u32 sync_cause) | |||
| 130 | 130 | ||
| 131 | static void ath9k_hw_set_clockrate(struct ath_hw *ah) | 131 | static void ath9k_hw_set_clockrate(struct ath_hw *ah) |
| 132 | { | 132 | { |
| 133 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | ||
| 134 | struct ath_common *common = ath9k_hw_common(ah); | 133 | struct ath_common *common = ath9k_hw_common(ah); |
| 134 | struct ath9k_channel *chan = ah->curchan; | ||
| 135 | unsigned int clockrate; | 135 | unsigned int clockrate; |
| 136 | 136 | ||
| 137 | /* AR9287 v1.3+ uses async FIFO and runs the MAC at 117 MHz */ | 137 | /* AR9287 v1.3+ uses async FIFO and runs the MAC at 117 MHz */ |
| 138 | if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) | 138 | if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) |
| 139 | clockrate = 117; | 139 | clockrate = 117; |
| 140 | else if (!ah->curchan) /* should really check for CCK instead */ | 140 | else if (!chan) /* should really check for CCK instead */ |
| 141 | clockrate = ATH9K_CLOCK_RATE_CCK; | 141 | clockrate = ATH9K_CLOCK_RATE_CCK; |
| 142 | else if (conf->chandef.chan->band == IEEE80211_BAND_2GHZ) | 142 | else if (IS_CHAN_2GHZ(chan)) |
| 143 | clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM; | 143 | clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM; |
| 144 | else if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK) | 144 | else if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK) |
| 145 | clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM; | 145 | clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM; |
| 146 | else | 146 | else |
| 147 | clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM; | 147 | clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM; |
| 148 | 148 | ||
| 149 | if (conf_is_ht40(conf)) | 149 | if (IS_CHAN_HT40(chan)) |
| 150 | clockrate *= 2; | 150 | clockrate *= 2; |
| 151 | 151 | ||
| 152 | if (ah->curchan) { | 152 | if (ah->curchan) { |
| 153 | if (IS_CHAN_HALF_RATE(ah->curchan)) | 153 | if (IS_CHAN_HALF_RATE(chan)) |
| 154 | clockrate /= 2; | 154 | clockrate /= 2; |
| 155 | if (IS_CHAN_QUARTER_RATE(ah->curchan)) | 155 | if (IS_CHAN_QUARTER_RATE(chan)) |
| 156 | clockrate /= 4; | 156 | clockrate /= 4; |
| 157 | } | 157 | } |
| 158 | 158 | ||
| @@ -190,10 +190,7 @@ EXPORT_SYMBOL(ath9k_hw_wait); | |||
| 190 | void ath9k_hw_synth_delay(struct ath_hw *ah, struct ath9k_channel *chan, | 190 | void ath9k_hw_synth_delay(struct ath_hw *ah, struct ath9k_channel *chan, |
| 191 | int hw_delay) | 191 | int hw_delay) |
| 192 | { | 192 | { |
| 193 | if (IS_CHAN_B(chan)) | 193 | hw_delay /= 10; |
| 194 | hw_delay = (4 * hw_delay) / 22; | ||
| 195 | else | ||
| 196 | hw_delay /= 10; | ||
| 197 | 194 | ||
| 198 | if (IS_CHAN_HALF_RATE(chan)) | 195 | if (IS_CHAN_HALF_RATE(chan)) |
| 199 | hw_delay *= 2; | 196 | hw_delay *= 2; |
| @@ -294,8 +291,7 @@ void ath9k_hw_get_channel_centers(struct ath_hw *ah, | |||
| 294 | return; | 291 | return; |
| 295 | } | 292 | } |
| 296 | 293 | ||
| 297 | if ((chan->chanmode == CHANNEL_A_HT40PLUS) || | 294 | if (IS_CHAN_HT40PLUS(chan)) { |
| 298 | (chan->chanmode == CHANNEL_G_HT40PLUS)) { | ||
| 299 | centers->synth_center = | 295 | centers->synth_center = |
| 300 | chan->channel + HT40_CHANNEL_CENTER_SHIFT; | 296 | chan->channel + HT40_CHANNEL_CENTER_SHIFT; |
| 301 | extoff = 1; | 297 | extoff = 1; |
| @@ -549,6 +545,18 @@ static int ath9k_hw_post_init(struct ath_hw *ah) | |||
| 549 | 545 | ||
| 550 | ath9k_hw_ani_init(ah); | 546 | ath9k_hw_ani_init(ah); |
| 551 | 547 | ||
| 548 | /* | ||
| 549 | * EEPROM needs to be initialized before we do this. | ||
| 550 | * This is required for regulatory compliance. | ||
| 551 | */ | ||
| 552 | if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { | ||
| 553 | u16 regdmn = ah->eep_ops->get_eeprom(ah, EEP_REG_0); | ||
| 554 | if ((regdmn & 0xF0) == CTL_FCC) { | ||
| 555 | ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9462_FCC_2GHZ; | ||
| 556 | ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9462_FCC_5GHZ; | ||
| 557 | } | ||
| 558 | } | ||
| 559 | |||
| 552 | return 0; | 560 | return 0; |
| 553 | } | 561 | } |
| 554 | 562 | ||
| @@ -1030,7 +1038,6 @@ static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) | |||
| 1030 | void ath9k_hw_init_global_settings(struct ath_hw *ah) | 1038 | void ath9k_hw_init_global_settings(struct ath_hw *ah) |
| 1031 | { | 1039 | { |
| 1032 | struct ath_common *common = ath9k_hw_common(ah); | 1040 | struct ath_common *common = ath9k_hw_common(ah); |
| 1033 | struct ieee80211_conf *conf = &common->hw->conf; | ||
| 1034 | const struct ath9k_channel *chan = ah->curchan; | 1041 | const struct ath9k_channel *chan = ah->curchan; |
| 1035 | int acktimeout, ctstimeout, ack_offset = 0; | 1042 | int acktimeout, ctstimeout, ack_offset = 0; |
| 1036 | int slottime; | 1043 | int slottime; |
| @@ -1105,8 +1112,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) | |||
| 1105 | * BA frames in some implementations, but it has been found to fix ACK | 1112 | * BA frames in some implementations, but it has been found to fix ACK |
| 1106 | * timeout issues in other cases as well. | 1113 | * timeout issues in other cases as well. |
| 1107 | */ | 1114 | */ |
| 1108 | if (conf->chandef.chan && | 1115 | if (IS_CHAN_2GHZ(chan) && |
| 1109 | conf->chandef.chan->band == IEEE80211_BAND_2GHZ && | ||
| 1110 | !IS_CHAN_HALF_RATE(chan) && !IS_CHAN_QUARTER_RATE(chan)) { | 1116 | !IS_CHAN_HALF_RATE(chan) && !IS_CHAN_QUARTER_RATE(chan)) { |
| 1111 | acktimeout += 64 - sifstime - ah->slottime; | 1117 | acktimeout += 64 - sifstime - ah->slottime; |
| 1112 | ctstimeout += 48 - sifstime - ah->slottime; | 1118 | ctstimeout += 48 - sifstime - ah->slottime; |
| @@ -1148,9 +1154,7 @@ u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan) | |||
| 1148 | { | 1154 | { |
| 1149 | u32 ctl = ath_regd_get_band_ctl(reg, chan->chan->band); | 1155 | u32 ctl = ath_regd_get_band_ctl(reg, chan->chan->band); |
| 1150 | 1156 | ||
| 1151 | if (IS_CHAN_B(chan)) | 1157 | if (IS_CHAN_2GHZ(chan)) |
| 1152 | ctl |= CTL_11B; | ||
| 1153 | else if (IS_CHAN_G(chan)) | ||
| 1154 | ctl |= CTL_11G; | 1158 | ctl |= CTL_11G; |
| 1155 | else | 1159 | else |
| 1156 | ctl |= CTL_11A; | 1160 | ctl |= CTL_11A; |
| @@ -1498,10 +1502,8 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, | |||
| 1498 | int r; | 1502 | int r; |
| 1499 | 1503 | ||
| 1500 | if (pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) { | 1504 | if (pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) { |
| 1501 | u32 cur = ah->curchan->channelFlags & (CHANNEL_2GHZ | CHANNEL_5GHZ); | 1505 | band_switch = IS_CHAN_5GHZ(ah->curchan) != IS_CHAN_5GHZ(chan); |
| 1502 | u32 new = chan->channelFlags & (CHANNEL_2GHZ | CHANNEL_5GHZ); | 1506 | mode_diff = (chan->channelFlags != ah->curchan->channelFlags); |
| 1503 | band_switch = (cur != new); | ||
| 1504 | mode_diff = (chan->chanmode != ah->curchan->chanmode); | ||
| 1505 | } | 1507 | } |
| 1506 | 1508 | ||
| 1507 | for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { | 1509 | for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { |
| @@ -1540,9 +1542,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, | |||
| 1540 | ath9k_hw_set_clockrate(ah); | 1542 | ath9k_hw_set_clockrate(ah); |
| 1541 | ath9k_hw_apply_txpower(ah, chan, false); | 1543 | ath9k_hw_apply_txpower(ah, chan, false); |
| 1542 | 1544 | ||
| 1543 | if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) | 1545 | ath9k_hw_set_delta_slope(ah, chan); |
| 1544 | ath9k_hw_set_delta_slope(ah, chan); | ||
| 1545 | |||
| 1546 | ath9k_hw_spur_mitigate_freq(ah, chan); | 1546 | ath9k_hw_spur_mitigate_freq(ah, chan); |
| 1547 | 1547 | ||
| 1548 | if (band_switch || ini_reloaded) | 1548 | if (band_switch || ini_reloaded) |
| @@ -1644,6 +1644,19 @@ hang_check_iter: | |||
| 1644 | return true; | 1644 | return true; |
| 1645 | } | 1645 | } |
| 1646 | 1646 | ||
| 1647 | void ath9k_hw_check_nav(struct ath_hw *ah) | ||
| 1648 | { | ||
| 1649 | struct ath_common *common = ath9k_hw_common(ah); | ||
| 1650 | u32 val; | ||
| 1651 | |||
| 1652 | val = REG_READ(ah, AR_NAV); | ||
| 1653 | if (val != 0xdeadbeef && val > 0x7fff) { | ||
| 1654 | ath_dbg(common, BSTUCK, "Abnormal NAV: 0x%x\n", val); | ||
| 1655 | REG_WRITE(ah, AR_NAV, 0); | ||
| 1656 | } | ||
| 1657 | } | ||
| 1658 | EXPORT_SYMBOL(ath9k_hw_check_nav); | ||
| 1659 | |||
| 1647 | bool ath9k_hw_check_alive(struct ath_hw *ah) | 1660 | bool ath9k_hw_check_alive(struct ath_hw *ah) |
| 1648 | { | 1661 | { |
| 1649 | int count = 50; | 1662 | int count = 50; |
| @@ -1799,20 +1812,11 @@ static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan) | |||
| 1799 | goto fail; | 1812 | goto fail; |
| 1800 | 1813 | ||
| 1801 | /* | 1814 | /* |
| 1802 | * If cross-band fcc is not supoprted, bail out if | 1815 | * If cross-band fcc is not supoprted, bail out if channelFlags differ. |
| 1803 | * either channelFlags or chanmode differ. | ||
| 1804 | * | ||
| 1805 | * chanmode will be different if the HT operating mode | ||
| 1806 | * changes because of CSA. | ||
| 1807 | */ | 1816 | */ |
| 1808 | if (!(pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH)) { | 1817 | if (!(pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) && |
| 1809 | if ((chan->channelFlags & CHANNEL_ALL) != | 1818 | chan->channelFlags != ah->curchan->channelFlags) |
| 1810 | (ah->curchan->channelFlags & CHANNEL_ALL)) | 1819 | goto fail; |
| 1811 | goto fail; | ||
| 1812 | |||
| 1813 | if (chan->chanmode != ah->curchan->chanmode) | ||
| 1814 | goto fail; | ||
| 1815 | } | ||
| 1816 | 1820 | ||
| 1817 | if (!ath9k_hw_check_alive(ah)) | 1821 | if (!ath9k_hw_check_alive(ah)) |
| 1818 | goto fail; | 1822 | goto fail; |
| @@ -1822,9 +1826,9 @@ static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan) | |||
| 1822 | * re-using are present. | 1826 | * re-using are present. |
| 1823 | */ | 1827 | */ |
| 1824 | if (AR_SREV_9462(ah) && (ah->caldata && | 1828 | if (AR_SREV_9462(ah) && (ah->caldata && |
| 1825 | (!ah->caldata->done_txiqcal_once || | 1829 | (!test_bit(TXIQCAL_DONE, &ah->caldata->cal_flags) || |
| 1826 | !ah->caldata->done_txclcal_once || | 1830 | !test_bit(TXCLCAL_DONE, &ah->caldata->cal_flags) || |
| 1827 | !ah->caldata->rtt_done))) | 1831 | !test_bit(RTT_DONE, &ah->caldata->cal_flags)))) |
| 1828 | goto fail; | 1832 | goto fail; |
| 1829 | 1833 | ||
| 1830 | ath_dbg(common, RESET, "FastChannelChange for %d -> %d\n", | 1834 | ath_dbg(common, RESET, "FastChannelChange for %d -> %d\n", |
| @@ -1874,15 +1878,14 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 1874 | 1878 | ||
| 1875 | ah->caldata = caldata; | 1879 | ah->caldata = caldata; |
| 1876 | if (caldata && (chan->channel != caldata->channel || | 1880 | if (caldata && (chan->channel != caldata->channel || |
| 1877 | chan->channelFlags != caldata->channelFlags || | 1881 | chan->channelFlags != caldata->channelFlags)) { |
| 1878 | chan->chanmode != caldata->chanmode)) { | ||
| 1879 | /* Operating channel changed, reset channel calibration data */ | 1882 | /* Operating channel changed, reset channel calibration data */ |
| 1880 | memset(caldata, 0, sizeof(*caldata)); | 1883 | memset(caldata, 0, sizeof(*caldata)); |
| 1881 | ath9k_init_nfcal_hist_buffer(ah, chan); | 1884 | ath9k_init_nfcal_hist_buffer(ah, chan); |
| 1882 | } else if (caldata) { | 1885 | } else if (caldata) { |
| 1883 | caldata->paprd_packet_sent = false; | 1886 | clear_bit(PAPRD_PACKET_SENT, &caldata->cal_flags); |
| 1884 | } | 1887 | } |
| 1885 | ah->noise = ath9k_hw_getchan_noise(ah, chan); | 1888 | ah->noise = ath9k_hw_getchan_noise(ah, chan, chan->noisefloor); |
| 1886 | 1889 | ||
| 1887 | if (fastcc) { | 1890 | if (fastcc) { |
| 1888 | r = ath9k_hw_do_fastcc(ah, chan); | 1891 | r = ath9k_hw_do_fastcc(ah, chan); |
| @@ -1964,9 +1967,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 1964 | 1967 | ||
| 1965 | ath9k_hw_init_mfp(ah); | 1968 | ath9k_hw_init_mfp(ah); |
| 1966 | 1969 | ||
| 1967 | if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) | 1970 | ath9k_hw_set_delta_slope(ah, chan); |
| 1968 | ath9k_hw_set_delta_slope(ah, chan); | ||
| 1969 | |||
| 1970 | ath9k_hw_spur_mitigate_freq(ah, chan); | 1971 | ath9k_hw_spur_mitigate_freq(ah, chan); |
| 1971 | ah->eep_ops->set_board_values(ah, chan); | 1972 | ah->eep_ops->set_board_values(ah, chan); |
| 1972 | 1973 | ||
| @@ -2017,8 +2018,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 2017 | ath9k_hw_init_bb(ah, chan); | 2018 | ath9k_hw_init_bb(ah, chan); |
| 2018 | 2019 | ||
| 2019 | if (caldata) { | 2020 | if (caldata) { |
| 2020 | caldata->done_txiqcal_once = false; | 2021 | clear_bit(TXIQCAL_DONE, &caldata->cal_flags); |
| 2021 | caldata->done_txclcal_once = false; | 2022 | clear_bit(TXCLCAL_DONE, &caldata->cal_flags); |
| 2022 | } | 2023 | } |
| 2023 | if (!ath9k_hw_init_cal(ah, chan)) | 2024 | if (!ath9k_hw_init_cal(ah, chan)) |
| 2024 | return -EIO; | 2025 | return -EIO; |
| @@ -2943,12 +2944,11 @@ void ath9k_hw_set_tsfadjust(struct ath_hw *ah, bool set) | |||
| 2943 | } | 2944 | } |
| 2944 | EXPORT_SYMBOL(ath9k_hw_set_tsfadjust); | 2945 | EXPORT_SYMBOL(ath9k_hw_set_tsfadjust); |
| 2945 | 2946 | ||
| 2946 | void ath9k_hw_set11nmac2040(struct ath_hw *ah) | 2947 | void ath9k_hw_set11nmac2040(struct ath_hw *ah, struct ath9k_channel *chan) |
| 2947 | { | 2948 | { |
| 2948 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | ||
| 2949 | u32 macmode; | 2949 | u32 macmode; |
| 2950 | 2950 | ||
| 2951 | if (conf_is_ht40(conf) && !ah->config.cwm_ignore_extcca) | 2951 | if (IS_CHAN_HT40(chan) && !ah->config.cwm_ignore_extcca) |
| 2952 | macmode = AR_2040_JOINED_RX_CLEAR; | 2952 | macmode = AR_2040_JOINED_RX_CLEAR; |
| 2953 | else | 2953 | else |
| 2954 | macmode = 0; | 2954 | macmode = 0; |
| @@ -3240,19 +3240,19 @@ void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len) | |||
| 3240 | 3240 | ||
| 3241 | /* chipsets >= AR9280 are single-chip */ | 3241 | /* chipsets >= AR9280 are single-chip */ |
| 3242 | if (AR_SREV_9280_20_OR_LATER(ah)) { | 3242 | if (AR_SREV_9280_20_OR_LATER(ah)) { |
| 3243 | used = snprintf(hw_name, len, | 3243 | used = scnprintf(hw_name, len, |
| 3244 | "Atheros AR%s Rev:%x", | 3244 | "Atheros AR%s Rev:%x", |
| 3245 | ath9k_hw_mac_bb_name(ah->hw_version.macVersion), | 3245 | ath9k_hw_mac_bb_name(ah->hw_version.macVersion), |
| 3246 | ah->hw_version.macRev); | 3246 | ah->hw_version.macRev); |
| 3247 | } | 3247 | } |
| 3248 | else { | 3248 | else { |
| 3249 | used = snprintf(hw_name, len, | 3249 | used = scnprintf(hw_name, len, |
| 3250 | "Atheros AR%s MAC/BB Rev:%x AR%s RF Rev:%x", | 3250 | "Atheros AR%s MAC/BB Rev:%x AR%s RF Rev:%x", |
| 3251 | ath9k_hw_mac_bb_name(ah->hw_version.macVersion), | 3251 | ath9k_hw_mac_bb_name(ah->hw_version.macVersion), |
| 3252 | ah->hw_version.macRev, | 3252 | ah->hw_version.macRev, |
| 3253 | ath9k_hw_rf_name((ah->hw_version.analog5GhzRev & | 3253 | ath9k_hw_rf_name((ah->hw_version.analog5GhzRev |
| 3254 | AR_RADIO_SREV_MAJOR)), | 3254 | & AR_RADIO_SREV_MAJOR)), |
| 3255 | ah->hw_version.phyRev); | 3255 | ah->hw_version.phyRev); |
| 3256 | } | 3256 | } |
| 3257 | 3257 | ||
| 3258 | hw_name[used] = '\0'; | 3258 | hw_name[used] = '\0'; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 69a907b55a73..9ea24f1cba73 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
| @@ -98,8 +98,8 @@ | |||
| 98 | 98 | ||
| 99 | #define PR_EEP(_s, _val) \ | 99 | #define PR_EEP(_s, _val) \ |
| 100 | do { \ | 100 | do { \ |
| 101 | len += snprintf(buf + len, size - len, "%20s : %10d\n", \ | 101 | len += scnprintf(buf + len, size - len, "%20s : %10d\n",\ |
| 102 | _s, (_val)); \ | 102 | _s, (_val)); \ |
| 103 | } while (0) | 103 | } while (0) |
| 104 | 104 | ||
| 105 | #define SM(_v, _f) (((_v) << _f##_S) & _f) | 105 | #define SM(_v, _f) (((_v) << _f##_S) & _f) |
| @@ -369,55 +369,30 @@ enum ath9k_int { | |||
| 369 | ATH9K_INT_NOCARD = 0xffffffff | 369 | ATH9K_INT_NOCARD = 0xffffffff |
| 370 | }; | 370 | }; |
| 371 | 371 | ||
| 372 | #define CHANNEL_CCK 0x00020 | ||
| 373 | #define CHANNEL_OFDM 0x00040 | ||
| 374 | #define CHANNEL_2GHZ 0x00080 | ||
| 375 | #define CHANNEL_5GHZ 0x00100 | ||
| 376 | #define CHANNEL_PASSIVE 0x00200 | ||
| 377 | #define CHANNEL_DYN 0x00400 | ||
| 378 | #define CHANNEL_HALF 0x04000 | ||
| 379 | #define CHANNEL_QUARTER 0x08000 | ||
| 380 | #define CHANNEL_HT20 0x10000 | ||
| 381 | #define CHANNEL_HT40PLUS 0x20000 | ||
| 382 | #define CHANNEL_HT40MINUS 0x40000 | ||
| 383 | |||
| 384 | #define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM) | ||
| 385 | #define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK) | ||
| 386 | #define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM) | ||
| 387 | #define CHANNEL_G_HT20 (CHANNEL_2GHZ|CHANNEL_HT20) | ||
| 388 | #define CHANNEL_A_HT20 (CHANNEL_5GHZ|CHANNEL_HT20) | ||
| 389 | #define CHANNEL_G_HT40PLUS (CHANNEL_2GHZ|CHANNEL_HT40PLUS) | ||
| 390 | #define CHANNEL_G_HT40MINUS (CHANNEL_2GHZ|CHANNEL_HT40MINUS) | ||
| 391 | #define CHANNEL_A_HT40PLUS (CHANNEL_5GHZ|CHANNEL_HT40PLUS) | ||
| 392 | #define CHANNEL_A_HT40MINUS (CHANNEL_5GHZ|CHANNEL_HT40MINUS) | ||
| 393 | #define CHANNEL_ALL \ | ||
| 394 | (CHANNEL_OFDM| \ | ||
| 395 | CHANNEL_CCK| \ | ||
| 396 | CHANNEL_2GHZ | \ | ||
| 397 | CHANNEL_5GHZ | \ | ||
| 398 | CHANNEL_HT20 | \ | ||
| 399 | CHANNEL_HT40PLUS | \ | ||
| 400 | CHANNEL_HT40MINUS) | ||
| 401 | |||
| 402 | #define MAX_RTT_TABLE_ENTRY 6 | 372 | #define MAX_RTT_TABLE_ENTRY 6 |
| 403 | #define MAX_IQCAL_MEASUREMENT 8 | 373 | #define MAX_IQCAL_MEASUREMENT 8 |
| 404 | #define MAX_CL_TAB_ENTRY 16 | 374 | #define MAX_CL_TAB_ENTRY 16 |
| 405 | #define CL_TAB_ENTRY(reg_base) (reg_base + (4 * j)) | 375 | #define CL_TAB_ENTRY(reg_base) (reg_base + (4 * j)) |
| 406 | 376 | ||
| 377 | enum ath9k_cal_flags { | ||
| 378 | RTT_DONE, | ||
| 379 | PAPRD_PACKET_SENT, | ||
| 380 | PAPRD_DONE, | ||
| 381 | NFCAL_PENDING, | ||
| 382 | NFCAL_INTF, | ||
| 383 | TXIQCAL_DONE, | ||
| 384 | TXCLCAL_DONE, | ||
| 385 | SW_PKDET_DONE, | ||
| 386 | }; | ||
| 387 | |||
| 407 | struct ath9k_hw_cal_data { | 388 | struct ath9k_hw_cal_data { |
| 408 | u16 channel; | 389 | u16 channel; |
| 409 | u32 channelFlags; | 390 | u16 channelFlags; |
| 410 | u32 chanmode; | 391 | unsigned long cal_flags; |
| 411 | int32_t CalValid; | 392 | int32_t CalValid; |
| 412 | int8_t iCoff; | 393 | int8_t iCoff; |
| 413 | int8_t qCoff; | 394 | int8_t qCoff; |
| 414 | bool rtt_done; | 395 | u8 caldac[2]; |
| 415 | bool paprd_packet_sent; | ||
| 416 | bool paprd_done; | ||
| 417 | bool nfcal_pending; | ||
| 418 | bool nfcal_interference; | ||
| 419 | bool done_txiqcal_once; | ||
| 420 | bool done_txclcal_once; | ||
| 421 | u16 small_signal_gain[AR9300_MAX_CHAINS]; | 396 | u16 small_signal_gain[AR9300_MAX_CHAINS]; |
| 422 | u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ]; | 397 | u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ]; |
| 423 | u32 num_measures[AR9300_MAX_CHAINS]; | 398 | u32 num_measures[AR9300_MAX_CHAINS]; |
| @@ -430,33 +405,34 @@ struct ath9k_hw_cal_data { | |||
| 430 | struct ath9k_channel { | 405 | struct ath9k_channel { |
| 431 | struct ieee80211_channel *chan; | 406 | struct ieee80211_channel *chan; |
| 432 | u16 channel; | 407 | u16 channel; |
| 433 | u32 channelFlags; | 408 | u16 channelFlags; |
| 434 | u32 chanmode; | ||
| 435 | s16 noisefloor; | 409 | s16 noisefloor; |
| 436 | }; | 410 | }; |
| 437 | 411 | ||
| 438 | #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ | 412 | #define CHANNEL_5GHZ BIT(0) |
| 439 | (((_c)->channelFlags & CHANNEL_G_HT20) == CHANNEL_G_HT20) || \ | 413 | #define CHANNEL_HALF BIT(1) |
| 440 | (((_c)->channelFlags & CHANNEL_G_HT40PLUS) == CHANNEL_G_HT40PLUS) || \ | 414 | #define CHANNEL_QUARTER BIT(2) |
| 441 | (((_c)->channelFlags & CHANNEL_G_HT40MINUS) == CHANNEL_G_HT40MINUS)) | 415 | #define CHANNEL_HT BIT(3) |
| 442 | #define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0) | 416 | #define CHANNEL_HT40PLUS BIT(4) |
| 443 | #define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0) | 417 | #define CHANNEL_HT40MINUS BIT(5) |
| 444 | #define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0) | 418 | |
| 445 | #define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0) | 419 | #define IS_CHAN_5GHZ(_c) (!!((_c)->channelFlags & CHANNEL_5GHZ)) |
| 446 | #define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0) | 420 | #define IS_CHAN_2GHZ(_c) (!IS_CHAN_5GHZ(_c)) |
| 421 | |||
| 422 | #define IS_CHAN_HALF_RATE(_c) (!!((_c)->channelFlags & CHANNEL_HALF)) | ||
| 423 | #define IS_CHAN_QUARTER_RATE(_c) (!!((_c)->channelFlags & CHANNEL_QUARTER)) | ||
| 447 | #define IS_CHAN_A_FAST_CLOCK(_ah, _c) \ | 424 | #define IS_CHAN_A_FAST_CLOCK(_ah, _c) \ |
| 448 | ((((_c)->channelFlags & CHANNEL_5GHZ) != 0) && \ | 425 | (IS_CHAN_5GHZ(_c) && ((_ah)->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)) |
| 449 | ((_ah)->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)) | 426 | |
| 450 | 427 | #define IS_CHAN_HT(_c) ((_c)->channelFlags & CHANNEL_HT) | |
| 451 | /* These macros check chanmode and not channelFlags */ | 428 | |
| 452 | #define IS_CHAN_B(_c) ((_c)->chanmode == CHANNEL_B) | 429 | #define IS_CHAN_HT20(_c) (IS_CHAN_HT(_c) && !IS_CHAN_HT40(_c)) |
| 453 | #define IS_CHAN_HT20(_c) (((_c)->chanmode == CHANNEL_A_HT20) || \ | 430 | |
| 454 | ((_c)->chanmode == CHANNEL_G_HT20)) | 431 | #define IS_CHAN_HT40(_c) \ |
| 455 | #define IS_CHAN_HT40(_c) (((_c)->chanmode == CHANNEL_A_HT40PLUS) || \ | 432 | (!!((_c)->channelFlags & (CHANNEL_HT40PLUS | CHANNEL_HT40MINUS))) |
| 456 | ((_c)->chanmode == CHANNEL_A_HT40MINUS) || \ | 433 | |
| 457 | ((_c)->chanmode == CHANNEL_G_HT40PLUS) || \ | 434 | #define IS_CHAN_HT40PLUS(_c) ((_c)->channelFlags & CHANNEL_HT40PLUS) |
| 458 | ((_c)->chanmode == CHANNEL_G_HT40MINUS)) | 435 | #define IS_CHAN_HT40MINUS(_c) ((_c)->channelFlags & CHANNEL_HT40MINUS) |
| 459 | #define IS_CHAN_HT(_c) (IS_CHAN_HT20((_c)) || IS_CHAN_HT40((_c))) | ||
| 460 | 436 | ||
| 461 | enum ath9k_power_mode { | 437 | enum ath9k_power_mode { |
| 462 | ATH9K_PM_AWAKE = 0, | 438 | ATH9K_PM_AWAKE = 0, |
| @@ -558,6 +534,7 @@ struct ath_hw_antcomb_conf { | |||
| 558 | u8 main_gaintb; | 534 | u8 main_gaintb; |
| 559 | u8 alt_gaintb; | 535 | u8 alt_gaintb; |
| 560 | int lna1_lna2_delta; | 536 | int lna1_lna2_delta; |
| 537 | int lna1_lna2_switch_delta; | ||
| 561 | u8 div_group; | 538 | u8 div_group; |
| 562 | }; | 539 | }; |
| 563 | 540 | ||
| @@ -726,6 +703,10 @@ struct ath_hw_ops { | |||
| 726 | void (*spectral_scan_trigger)(struct ath_hw *ah); | 703 | void (*spectral_scan_trigger)(struct ath_hw *ah); |
| 727 | void (*spectral_scan_wait)(struct ath_hw *ah); | 704 | void (*spectral_scan_wait)(struct ath_hw *ah); |
| 728 | 705 | ||
| 706 | void (*tx99_start)(struct ath_hw *ah, u32 qnum); | ||
| 707 | void (*tx99_stop)(struct ath_hw *ah); | ||
| 708 | void (*tx99_set_txpower)(struct ath_hw *ah, u8 power); | ||
| 709 | |||
| 729 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | 710 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT |
| 730 | void (*set_bt_ant_diversity)(struct ath_hw *hw, bool enable); | 711 | void (*set_bt_ant_diversity)(struct ath_hw *hw, bool enable); |
| 731 | #endif | 712 | #endif |
| @@ -1026,10 +1007,11 @@ void ath9k_hw_reset_tsf(struct ath_hw *ah); | |||
| 1026 | void ath9k_hw_set_tsfadjust(struct ath_hw *ah, bool set); | 1007 | void ath9k_hw_set_tsfadjust(struct ath_hw *ah, bool set); |
| 1027 | void ath9k_hw_init_global_settings(struct ath_hw *ah); | 1008 | void ath9k_hw_init_global_settings(struct ath_hw *ah); |
| 1028 | u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah); | 1009 | u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah); |
| 1029 | void ath9k_hw_set11nmac2040(struct ath_hw *ah); | 1010 | void ath9k_hw_set11nmac2040(struct ath_hw *ah, struct ath9k_channel *chan); |
| 1030 | void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); | 1011 | void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); |
| 1031 | void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, | 1012 | void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, |
| 1032 | const struct ath9k_beacon_state *bs); | 1013 | const struct ath9k_beacon_state *bs); |
| 1014 | void ath9k_hw_check_nav(struct ath_hw *ah); | ||
| 1033 | bool ath9k_hw_check_alive(struct ath_hw *ah); | 1015 | bool ath9k_hw_check_alive(struct ath_hw *ah); |
| 1034 | 1016 | ||
| 1035 | bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); | 1017 | bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 9a1f349f9260..d8643ebabd30 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
| @@ -347,7 +347,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
| 347 | { | 347 | { |
| 348 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 348 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
| 349 | u8 *ds; | 349 | u8 *ds; |
| 350 | struct ath_buf *bf; | ||
| 351 | int i, bsize, desc_len; | 350 | int i, bsize, desc_len; |
| 352 | 351 | ||
| 353 | ath_dbg(common, CONFIG, "%s DMA: %u buffers %u desc/buf\n", | 352 | ath_dbg(common, CONFIG, "%s DMA: %u buffers %u desc/buf\n", |
| @@ -399,33 +398,68 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
| 399 | ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); | 398 | ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); |
| 400 | 399 | ||
| 401 | /* allocate buffers */ | 400 | /* allocate buffers */ |
| 402 | bsize = sizeof(struct ath_buf) * nbuf; | 401 | if (is_tx) { |
| 403 | bf = devm_kzalloc(sc->dev, bsize, GFP_KERNEL); | 402 | struct ath_buf *bf; |
| 404 | if (!bf) | 403 | |
| 405 | return -ENOMEM; | 404 | bsize = sizeof(struct ath_buf) * nbuf; |
| 405 | bf = devm_kzalloc(sc->dev, bsize, GFP_KERNEL); | ||
| 406 | if (!bf) | ||
| 407 | return -ENOMEM; | ||
| 408 | |||
| 409 | for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) { | ||
| 410 | bf->bf_desc = ds; | ||
| 411 | bf->bf_daddr = DS2PHYS(dd, ds); | ||
| 412 | |||
| 413 | if (!(sc->sc_ah->caps.hw_caps & | ||
| 414 | ATH9K_HW_CAP_4KB_SPLITTRANS)) { | ||
| 415 | /* | ||
| 416 | * Skip descriptor addresses which can cause 4KB | ||
| 417 | * boundary crossing (addr + length) with a 32 dword | ||
| 418 | * descriptor fetch. | ||
| 419 | */ | ||
| 420 | while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { | ||
| 421 | BUG_ON((caddr_t) bf->bf_desc >= | ||
| 422 | ((caddr_t) dd->dd_desc + | ||
| 423 | dd->dd_desc_len)); | ||
| 424 | |||
| 425 | ds += (desc_len * ndesc); | ||
| 426 | bf->bf_desc = ds; | ||
| 427 | bf->bf_daddr = DS2PHYS(dd, ds); | ||
| 428 | } | ||
| 429 | } | ||
| 430 | list_add_tail(&bf->list, head); | ||
| 431 | } | ||
| 432 | } else { | ||
| 433 | struct ath_rxbuf *bf; | ||
| 406 | 434 | ||
| 407 | for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) { | 435 | bsize = sizeof(struct ath_rxbuf) * nbuf; |
| 408 | bf->bf_desc = ds; | 436 | bf = devm_kzalloc(sc->dev, bsize, GFP_KERNEL); |
| 409 | bf->bf_daddr = DS2PHYS(dd, ds); | 437 | if (!bf) |
| 410 | 438 | return -ENOMEM; | |
| 411 | if (!(sc->sc_ah->caps.hw_caps & | 439 | |
| 412 | ATH9K_HW_CAP_4KB_SPLITTRANS)) { | 440 | for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) { |
| 413 | /* | 441 | bf->bf_desc = ds; |
| 414 | * Skip descriptor addresses which can cause 4KB | 442 | bf->bf_daddr = DS2PHYS(dd, ds); |
| 415 | * boundary crossing (addr + length) with a 32 dword | 443 | |
| 416 | * descriptor fetch. | 444 | if (!(sc->sc_ah->caps.hw_caps & |
| 417 | */ | 445 | ATH9K_HW_CAP_4KB_SPLITTRANS)) { |
| 418 | while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { | 446 | /* |
| 419 | BUG_ON((caddr_t) bf->bf_desc >= | 447 | * Skip descriptor addresses which can cause 4KB |
| 420 | ((caddr_t) dd->dd_desc + | 448 | * boundary crossing (addr + length) with a 32 dword |
| 421 | dd->dd_desc_len)); | 449 | * descriptor fetch. |
| 422 | 450 | */ | |
| 423 | ds += (desc_len * ndesc); | 451 | while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { |
| 424 | bf->bf_desc = ds; | 452 | BUG_ON((caddr_t) bf->bf_desc >= |
| 425 | bf->bf_daddr = DS2PHYS(dd, ds); | 453 | ((caddr_t) dd->dd_desc + |
| 454 | dd->dd_desc_len)); | ||
| 455 | |||
| 456 | ds += (desc_len * ndesc); | ||
| 457 | bf->bf_desc = ds; | ||
| 458 | bf->bf_daddr = DS2PHYS(dd, ds); | ||
| 459 | } | ||
| 426 | } | 460 | } |
| 461 | list_add_tail(&bf->list, head); | ||
| 427 | } | 462 | } |
| 428 | list_add_tail(&bf->list, head); | ||
| 429 | } | 463 | } |
| 430 | return 0; | 464 | return 0; |
| 431 | } | 465 | } |
| @@ -437,7 +471,6 @@ static int ath9k_init_queues(struct ath_softc *sc) | |||
| 437 | sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah); | 471 | sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah); |
| 438 | sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); | 472 | sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); |
| 439 | 473 | ||
| 440 | sc->config.cabqReadytime = ATH_CABQ_READY_TIME; | ||
| 441 | ath_cabq_update(sc); | 474 | ath_cabq_update(sc); |
| 442 | 475 | ||
| 443 | sc->tx.uapsdq = ath_txq_setup(sc, ATH9K_TX_QUEUE_UAPSD, 0); | 476 | sc->tx.uapsdq = ath_txq_setup(sc, ATH9K_TX_QUEUE_UAPSD, 0); |
| @@ -547,6 +580,26 @@ static void ath9k_init_platform(struct ath_softc *sc) | |||
| 547 | if (sc->driver_data & ATH9K_PCI_CUS217) | 580 | if (sc->driver_data & ATH9K_PCI_CUS217) |
| 548 | ath_info(common, "CUS217 card detected\n"); | 581 | ath_info(common, "CUS217 card detected\n"); |
| 549 | 582 | ||
| 583 | if (sc->driver_data & ATH9K_PCI_CUS252) | ||
| 584 | ath_info(common, "CUS252 card detected\n"); | ||
| 585 | |||
| 586 | if (sc->driver_data & ATH9K_PCI_AR9565_1ANT) | ||
| 587 | ath_info(common, "WB335 1-ANT card detected\n"); | ||
| 588 | |||
| 589 | if (sc->driver_data & ATH9K_PCI_AR9565_2ANT) | ||
| 590 | ath_info(common, "WB335 2-ANT card detected\n"); | ||
| 591 | |||
| 592 | /* | ||
| 593 | * Some WB335 cards do not support antenna diversity. Since | ||
| 594 | * we use a hardcoded value for AR9565 instead of using the | ||
| 595 | * EEPROM/OTP data, remove the combining feature from | ||
| 596 | * the HW capabilities bitmap. | ||
| 597 | */ | ||
| 598 | if (sc->driver_data & (ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_AR9565_2ANT)) { | ||
| 599 | if (!(sc->driver_data & ATH9K_PCI_BT_ANT_DIV)) | ||
| 600 | pCap->hw_caps &= ~ATH9K_HW_CAP_ANT_DIV_COMB; | ||
| 601 | } | ||
| 602 | |||
| 550 | if (sc->driver_data & ATH9K_PCI_BT_ANT_DIV) { | 603 | if (sc->driver_data & ATH9K_PCI_BT_ANT_DIV) { |
| 551 | pCap->hw_caps |= ATH9K_HW_CAP_BT_ANT_DIV; | 604 | pCap->hw_caps |= ATH9K_HW_CAP_BT_ANT_DIV; |
| 552 | ath_info(common, "Set BT/WLAN RX diversity capability\n"); | 605 | ath_info(common, "Set BT/WLAN RX diversity capability\n"); |
| @@ -627,7 +680,9 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, | |||
| 627 | sc->sc_ah = ah; | 680 | sc->sc_ah = ah; |
| 628 | pCap = &ah->caps; | 681 | pCap = &ah->caps; |
| 629 | 682 | ||
| 630 | sc->dfs_detector = dfs_pattern_detector_init(ah, NL80211_DFS_UNSET); | 683 | common = ath9k_hw_common(ah); |
| 684 | sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET); | ||
| 685 | sc->tx99_power = MAX_RATE_POWER + 1; | ||
| 631 | 686 | ||
| 632 | if (!pdata) { | 687 | if (!pdata) { |
| 633 | ah->ah_flags |= AH_USE_EEPROM; | 688 | ah->ah_flags |= AH_USE_EEPROM; |
| @@ -641,7 +696,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, | |||
| 641 | ah->external_reset = pdata->external_reset; | 696 | ah->external_reset = pdata->external_reset; |
| 642 | } | 697 | } |
| 643 | 698 | ||
| 644 | common = ath9k_hw_common(ah); | ||
| 645 | common->ops = &ah->reg_ops; | 699 | common->ops = &ah->reg_ops; |
| 646 | common->bus_ops = bus_ops; | 700 | common->bus_ops = bus_ops; |
| 647 | common->ah = ah; | 701 | common->ah = ah; |
| @@ -732,6 +786,7 @@ err_queues: | |||
| 732 | ath9k_hw_deinit(ah); | 786 | ath9k_hw_deinit(ah); |
| 733 | err_hw: | 787 | err_hw: |
| 734 | ath9k_eeprom_release(sc); | 788 | ath9k_eeprom_release(sc); |
| 789 | dev_kfree_skb_any(sc->tx99_skb); | ||
| 735 | return ret; | 790 | return ret; |
| 736 | } | 791 | } |
| 737 | 792 | ||
| @@ -748,7 +803,7 @@ static void ath9k_init_band_txpower(struct ath_softc *sc, int band) | |||
| 748 | chan = &sband->channels[i]; | 803 | chan = &sband->channels[i]; |
| 749 | ah->curchan = &ah->channels[chan->hw_value]; | 804 | ah->curchan = &ah->channels[chan->hw_value]; |
| 750 | cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_HT20); | 805 | cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_HT20); |
| 751 | ath9k_cmn_update_ichannel(ah->curchan, &chandef); | 806 | ath9k_cmn_get_channel(sc->hw, ah, &chandef); |
| 752 | ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true); | 807 | ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true); |
| 753 | } | 808 | } |
| 754 | } | 809 | } |
| @@ -789,9 +844,9 @@ static const struct ieee80211_iface_limit if_limits[] = { | |||
| 789 | BIT(NL80211_IFTYPE_P2P_GO) }, | 844 | BIT(NL80211_IFTYPE_P2P_GO) }, |
| 790 | }; | 845 | }; |
| 791 | 846 | ||
| 792 | |||
| 793 | static const struct ieee80211_iface_limit if_dfs_limits[] = { | 847 | static const struct ieee80211_iface_limit if_dfs_limits[] = { |
| 794 | { .max = 1, .types = BIT(NL80211_IFTYPE_AP) }, | 848 | { .max = 1, .types = BIT(NL80211_IFTYPE_AP) | |
| 849 | BIT(NL80211_IFTYPE_ADHOC) }, | ||
| 795 | }; | 850 | }; |
| 796 | 851 | ||
| 797 | static const struct ieee80211_iface_combination if_comb[] = { | 852 | static const struct ieee80211_iface_combination if_comb[] = { |
| @@ -850,17 +905,18 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
| 850 | 905 | ||
| 851 | hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; | 906 | hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; |
| 852 | 907 | ||
| 853 | hw->wiphy->interface_modes = | 908 | if (!config_enabled(CONFIG_ATH9K_TX99)) { |
| 854 | BIT(NL80211_IFTYPE_P2P_GO) | | 909 | hw->wiphy->interface_modes = |
| 855 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | 910 | BIT(NL80211_IFTYPE_P2P_GO) | |
| 856 | BIT(NL80211_IFTYPE_AP) | | 911 | BIT(NL80211_IFTYPE_P2P_CLIENT) | |
| 857 | BIT(NL80211_IFTYPE_WDS) | | 912 | BIT(NL80211_IFTYPE_AP) | |
| 858 | BIT(NL80211_IFTYPE_STATION) | | 913 | BIT(NL80211_IFTYPE_WDS) | |
| 859 | BIT(NL80211_IFTYPE_ADHOC) | | 914 | BIT(NL80211_IFTYPE_STATION) | |
| 860 | BIT(NL80211_IFTYPE_MESH_POINT); | 915 | BIT(NL80211_IFTYPE_ADHOC) | |
| 861 | 916 | BIT(NL80211_IFTYPE_MESH_POINT); | |
| 862 | hw->wiphy->iface_combinations = if_comb; | 917 | hw->wiphy->iface_combinations = if_comb; |
| 863 | hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); | 918 | hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); |
| 919 | } | ||
| 864 | 920 | ||
| 865 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 921 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
| 866 | 922 | ||
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c index 2f831db396ac..aed7e29dc50f 100644 --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c | |||
| @@ -28,6 +28,13 @@ void ath_tx_complete_poll_work(struct work_struct *work) | |||
| 28 | int i; | 28 | int i; |
| 29 | bool needreset = false; | 29 | bool needreset = false; |
| 30 | 30 | ||
| 31 | |||
| 32 | if (sc->tx99_state) { | ||
| 33 | ath_dbg(ath9k_hw_common(sc->sc_ah), RESET, | ||
| 34 | "skip tx hung detection on tx99\n"); | ||
| 35 | return; | ||
| 36 | } | ||
| 37 | |||
| 31 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { | 38 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { |
| 32 | txq = sc->tx.txq_map[i]; | 39 | txq = sc->tx.txq_map[i]; |
| 33 | 40 | ||
| @@ -70,7 +77,7 @@ void ath_hw_check(struct work_struct *work) | |||
| 70 | ath9k_ps_wakeup(sc); | 77 | ath9k_ps_wakeup(sc); |
| 71 | is_alive = ath9k_hw_check_alive(sc->sc_ah); | 78 | is_alive = ath9k_hw_check_alive(sc->sc_ah); |
| 72 | 79 | ||
| 73 | if (is_alive && !AR_SREV_9300(sc->sc_ah)) | 80 | if ((is_alive && !AR_SREV_9300(sc->sc_ah)) || sc->tx99_state) |
| 74 | goto out; | 81 | goto out; |
| 75 | else if (!is_alive && AR_SREV_9300(sc->sc_ah)) { | 82 | else if (!is_alive && AR_SREV_9300(sc->sc_ah)) { |
| 76 | ath_dbg(common, RESET, | 83 | ath_dbg(common, RESET, |
| @@ -141,6 +148,9 @@ void ath_hw_pll_work(struct work_struct *work) | |||
| 141 | if (!test_bit(SC_OP_BEACONS, &sc->sc_flags)) | 148 | if (!test_bit(SC_OP_BEACONS, &sc->sc_flags)) |
| 142 | return; | 149 | return; |
| 143 | 150 | ||
| 151 | if (sc->tx99_state) | ||
| 152 | return; | ||
| 153 | |||
| 144 | ath9k_ps_wakeup(sc); | 154 | ath9k_ps_wakeup(sc); |
| 145 | pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah); | 155 | pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah); |
| 146 | ath9k_ps_restore(sc); | 156 | ath9k_ps_restore(sc); |
| @@ -184,7 +194,7 @@ static void ath_paprd_activate(struct ath_softc *sc) | |||
| 184 | struct ath9k_hw_cal_data *caldata = ah->caldata; | 194 | struct ath9k_hw_cal_data *caldata = ah->caldata; |
| 185 | int chain; | 195 | int chain; |
| 186 | 196 | ||
| 187 | if (!caldata || !caldata->paprd_done) { | 197 | if (!caldata || !test_bit(PAPRD_DONE, &caldata->cal_flags)) { |
| 188 | ath_dbg(common, CALIBRATE, "Failed to activate PAPRD\n"); | 198 | ath_dbg(common, CALIBRATE, "Failed to activate PAPRD\n"); |
| 189 | return; | 199 | return; |
| 190 | } | 200 | } |
| @@ -256,7 +266,9 @@ void ath_paprd_calibrate(struct work_struct *work) | |||
| 256 | int len = 1800; | 266 | int len = 1800; |
| 257 | int ret; | 267 | int ret; |
| 258 | 268 | ||
| 259 | if (!caldata || !caldata->paprd_packet_sent || caldata->paprd_done) { | 269 | if (!caldata || |
| 270 | !test_bit(PAPRD_PACKET_SENT, &caldata->cal_flags) || | ||
| 271 | test_bit(PAPRD_DONE, &caldata->cal_flags)) { | ||
| 260 | ath_dbg(common, CALIBRATE, "Skipping PAPRD calibration\n"); | 272 | ath_dbg(common, CALIBRATE, "Skipping PAPRD calibration\n"); |
| 261 | return; | 273 | return; |
| 262 | } | 274 | } |
| @@ -316,7 +328,7 @@ void ath_paprd_calibrate(struct work_struct *work) | |||
| 316 | kfree_skb(skb); | 328 | kfree_skb(skb); |
| 317 | 329 | ||
| 318 | if (chain_ok) { | 330 | if (chain_ok) { |
| 319 | caldata->paprd_done = true; | 331 | set_bit(PAPRD_DONE, &caldata->cal_flags); |
| 320 | ath_paprd_activate(sc); | 332 | ath_paprd_activate(sc); |
| 321 | } | 333 | } |
| 322 | 334 | ||
| @@ -343,7 +355,7 @@ void ath_ani_calibrate(unsigned long data) | |||
| 343 | u32 cal_interval, short_cal_interval, long_cal_interval; | 355 | u32 cal_interval, short_cal_interval, long_cal_interval; |
| 344 | unsigned long flags; | 356 | unsigned long flags; |
| 345 | 357 | ||
| 346 | if (ah->caldata && ah->caldata->nfcal_interference) | 358 | if (ah->caldata && test_bit(NFCAL_INTF, &ah->caldata->cal_flags)) |
| 347 | long_cal_interval = ATH_LONG_CALINTERVAL_INT; | 359 | long_cal_interval = ATH_LONG_CALINTERVAL_INT; |
| 348 | else | 360 | else |
| 349 | long_cal_interval = ATH_LONG_CALINTERVAL; | 361 | long_cal_interval = ATH_LONG_CALINTERVAL; |
| @@ -432,7 +444,7 @@ set_timer: | |||
| 432 | mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); | 444 | mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); |
| 433 | 445 | ||
| 434 | if (ar9003_is_paprd_enabled(ah) && ah->caldata) { | 446 | if (ar9003_is_paprd_enabled(ah) && ah->caldata) { |
| 435 | if (!ah->caldata->paprd_done) { | 447 | if (!test_bit(PAPRD_DONE, &ah->caldata->cal_flags)) { |
| 436 | ieee80211_queue_work(sc->hw, &sc->paprd_work); | 448 | ieee80211_queue_work(sc->hw, &sc->paprd_work); |
| 437 | } else if (!ah->paprd_table_write_done) { | 449 | } else if (!ah->paprd_table_write_done) { |
| 438 | ath9k_ps_wakeup(sc); | 450 | ath9k_ps_wakeup(sc); |
| @@ -516,7 +528,8 @@ void ath_update_survey_nf(struct ath_softc *sc, int channel) | |||
| 516 | 528 | ||
| 517 | if (chan->noisefloor) { | 529 | if (chan->noisefloor) { |
| 518 | survey->filled |= SURVEY_INFO_NOISE_DBM; | 530 | survey->filled |= SURVEY_INFO_NOISE_DBM; |
| 519 | survey->noise = ath9k_hw_getchan_noise(ah, chan); | 531 | survey->noise = ath9k_hw_getchan_noise(ah, chan, |
| 532 | chan->noisefloor); | ||
| 520 | } | 533 | } |
| 521 | } | 534 | } |
| 522 | 535 | ||
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index a3eff0986a3f..6a18f9d3e9cc 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
| @@ -374,7 +374,6 @@ EXPORT_SYMBOL(ath9k_hw_releasetxqueue); | |||
| 374 | bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) | 374 | bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) |
| 375 | { | 375 | { |
| 376 | struct ath_common *common = ath9k_hw_common(ah); | 376 | struct ath_common *common = ath9k_hw_common(ah); |
| 377 | struct ath9k_channel *chan = ah->curchan; | ||
| 378 | struct ath9k_tx_queue_info *qi; | 377 | struct ath9k_tx_queue_info *qi; |
| 379 | u32 cwMin, chanCwMin, value; | 378 | u32 cwMin, chanCwMin, value; |
| 380 | 379 | ||
| @@ -387,10 +386,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) | |||
| 387 | ath_dbg(common, QUEUE, "Reset TX queue: %u\n", q); | 386 | ath_dbg(common, QUEUE, "Reset TX queue: %u\n", q); |
| 388 | 387 | ||
| 389 | if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) { | 388 | if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) { |
| 390 | if (chan && IS_CHAN_B(chan)) | 389 | chanCwMin = INIT_CWMIN; |
| 391 | chanCwMin = INIT_CWMIN_11B; | ||
| 392 | else | ||
| 393 | chanCwMin = INIT_CWMIN; | ||
| 394 | 390 | ||
| 395 | for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1); | 391 | for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1); |
| 396 | } else | 392 | } else |
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index bfccaceed44e..e3eed81f2439 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
| @@ -603,8 +603,6 @@ enum ath9k_tx_queue_flags { | |||
| 603 | #define ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS 0x00000001 | 603 | #define ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS 0x00000001 |
| 604 | 604 | ||
| 605 | #define ATH9K_DECOMP_MASK_SIZE 128 | 605 | #define ATH9K_DECOMP_MASK_SIZE 128 |
| 606 | #define ATH9K_READY_TIME_LO_BOUND 50 | ||
| 607 | #define ATH9K_READY_TIME_HI_BOUND 96 | ||
| 608 | 606 | ||
| 609 | enum ath9k_pkt_type { | 607 | enum ath9k_pkt_type { |
| 610 | ATH9K_PKT_TYPE_NORMAL = 0, | 608 | ATH9K_PKT_TYPE_NORMAL = 0, |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 709301f88dcd..74f452c7b166 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
| @@ -312,17 +312,91 @@ out: | |||
| 312 | * by reseting the chip. To accomplish this we must first cleanup any pending | 312 | * by reseting the chip. To accomplish this we must first cleanup any pending |
| 313 | * DMA, then restart stuff. | 313 | * DMA, then restart stuff. |
| 314 | */ | 314 | */ |
| 315 | static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | 315 | static int ath_set_channel(struct ath_softc *sc, struct cfg80211_chan_def *chandef) |
| 316 | struct ath9k_channel *hchan) | ||
| 317 | { | 316 | { |
| 317 | struct ath_hw *ah = sc->sc_ah; | ||
| 318 | struct ath_common *common = ath9k_hw_common(ah); | ||
| 319 | struct ieee80211_hw *hw = sc->hw; | ||
| 320 | struct ath9k_channel *hchan; | ||
| 321 | struct ieee80211_channel *chan = chandef->chan; | ||
| 322 | unsigned long flags; | ||
| 323 | bool offchannel; | ||
| 324 | int pos = chan->hw_value; | ||
| 325 | int old_pos = -1; | ||
| 318 | int r; | 326 | int r; |
| 319 | 327 | ||
| 320 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) | 328 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) |
| 321 | return -EIO; | 329 | return -EIO; |
| 322 | 330 | ||
| 331 | offchannel = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL); | ||
| 332 | |||
| 333 | if (ah->curchan) | ||
| 334 | old_pos = ah->curchan - &ah->channels[0]; | ||
| 335 | |||
| 336 | ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n", | ||
| 337 | chan->center_freq, chandef->width); | ||
| 338 | |||
| 339 | /* update survey stats for the old channel before switching */ | ||
| 340 | spin_lock_irqsave(&common->cc_lock, flags); | ||
| 341 | ath_update_survey_stats(sc); | ||
| 342 | spin_unlock_irqrestore(&common->cc_lock, flags); | ||
| 343 | |||
| 344 | ath9k_cmn_get_channel(hw, ah, chandef); | ||
| 345 | |||
| 346 | /* | ||
| 347 | * If the operating channel changes, change the survey in-use flags | ||
| 348 | * along with it. | ||
| 349 | * Reset the survey data for the new channel, unless we're switching | ||
| 350 | * back to the operating channel from an off-channel operation. | ||
| 351 | */ | ||
| 352 | if (!offchannel && sc->cur_survey != &sc->survey[pos]) { | ||
| 353 | if (sc->cur_survey) | ||
| 354 | sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE; | ||
| 355 | |||
| 356 | sc->cur_survey = &sc->survey[pos]; | ||
| 357 | |||
| 358 | memset(sc->cur_survey, 0, sizeof(struct survey_info)); | ||
| 359 | sc->cur_survey->filled |= SURVEY_INFO_IN_USE; | ||
| 360 | } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) { | ||
| 361 | memset(&sc->survey[pos], 0, sizeof(struct survey_info)); | ||
| 362 | } | ||
| 363 | |||
| 364 | hchan = &sc->sc_ah->channels[pos]; | ||
| 323 | r = ath_reset_internal(sc, hchan); | 365 | r = ath_reset_internal(sc, hchan); |
| 366 | if (r) | ||
| 367 | return r; | ||
| 324 | 368 | ||
| 325 | return r; | 369 | /* |
| 370 | * The most recent snapshot of channel->noisefloor for the old | ||
| 371 | * channel is only available after the hardware reset. Copy it to | ||
| 372 | * the survey stats now. | ||
| 373 | */ | ||
| 374 | if (old_pos >= 0) | ||
| 375 | ath_update_survey_nf(sc, old_pos); | ||
| 376 | |||
| 377 | /* | ||
| 378 | * Enable radar pulse detection if on a DFS channel. Spectral | ||
| 379 | * scanning and radar detection can not be used concurrently. | ||
| 380 | */ | ||
| 381 | if (hw->conf.radar_enabled) { | ||
| 382 | u32 rxfilter; | ||
| 383 | |||
| 384 | /* set HW specific DFS configuration */ | ||
| 385 | ath9k_hw_set_radar_params(ah); | ||
| 386 | rxfilter = ath9k_hw_getrxfilter(ah); | ||
| 387 | rxfilter |= ATH9K_RX_FILTER_PHYRADAR | | ||
| 388 | ATH9K_RX_FILTER_PHYERR; | ||
| 389 | ath9k_hw_setrxfilter(ah, rxfilter); | ||
| 390 | ath_dbg(common, DFS, "DFS enabled at freq %d\n", | ||
| 391 | chan->center_freq); | ||
| 392 | } else { | ||
| 393 | /* perform spectral scan if requested. */ | ||
| 394 | if (test_bit(SC_OP_SCANNING, &sc->sc_flags) && | ||
| 395 | sc->spectral_mode == SPECTRAL_CHANSCAN) | ||
| 396 | ath9k_spectral_scan_trigger(hw); | ||
| 397 | } | ||
| 398 | |||
| 399 | return 0; | ||
| 326 | } | 400 | } |
| 327 | 401 | ||
| 328 | static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, | 402 | static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, |
| @@ -372,6 +446,13 @@ void ath9k_tasklet(unsigned long data) | |||
| 372 | type = RESET_TYPE_BB_WATCHDOG; | 446 | type = RESET_TYPE_BB_WATCHDOG; |
| 373 | 447 | ||
| 374 | ath9k_queue_reset(sc, type); | 448 | ath9k_queue_reset(sc, type); |
| 449 | |||
| 450 | /* | ||
| 451 | * Increment the ref. counter here so that | ||
| 452 | * interrupts are enabled in the reset routine. | ||
| 453 | */ | ||
| 454 | atomic_inc(&ah->intr_ref_cnt); | ||
| 455 | ath_dbg(common, ANY, "FATAL: Skipping interrupts\n"); | ||
| 375 | goto out; | 456 | goto out; |
| 376 | } | 457 | } |
| 377 | 458 | ||
| @@ -410,10 +491,9 @@ void ath9k_tasklet(unsigned long data) | |||
| 410 | 491 | ||
| 411 | ath9k_btcoex_handle_interrupt(sc, status); | 492 | ath9k_btcoex_handle_interrupt(sc, status); |
| 412 | 493 | ||
| 413 | out: | ||
| 414 | /* re-enable hardware interrupt */ | 494 | /* re-enable hardware interrupt */ |
| 415 | ath9k_hw_enable_interrupts(ah); | 495 | ath9k_hw_enable_interrupts(ah); |
| 416 | 496 | out: | |
| 417 | spin_unlock(&sc->sc_pcu_lock); | 497 | spin_unlock(&sc->sc_pcu_lock); |
| 418 | ath9k_ps_restore(sc); | 498 | ath9k_ps_restore(sc); |
| 419 | } | 499 | } |
| @@ -594,7 +674,7 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
| 594 | ath9k_ps_wakeup(sc); | 674 | ath9k_ps_wakeup(sc); |
| 595 | mutex_lock(&sc->mutex); | 675 | mutex_lock(&sc->mutex); |
| 596 | 676 | ||
| 597 | init_channel = ath9k_cmn_get_curchannel(hw, ah); | 677 | init_channel = ath9k_cmn_get_channel(hw, ah, &hw->conf.chandef); |
| 598 | 678 | ||
| 599 | /* Reset SERDES registers */ | 679 | /* Reset SERDES registers */ |
| 600 | ath9k_hw_configpcipowersave(ah, false); | 680 | ath9k_hw_configpcipowersave(ah, false); |
| @@ -797,7 +877,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
| 797 | } | 877 | } |
| 798 | 878 | ||
| 799 | if (!ah->curchan) | 879 | if (!ah->curchan) |
| 800 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); | 880 | ah->curchan = ath9k_cmn_get_channel(hw, ah, &hw->conf.chandef); |
| 801 | 881 | ||
| 802 | ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); | 882 | ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); |
| 803 | ath9k_hw_phy_disable(ah); | 883 | ath9k_hw_phy_disable(ah); |
| @@ -816,7 +896,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
| 816 | ath_dbg(common, CONFIG, "Driver halt\n"); | 896 | ath_dbg(common, CONFIG, "Driver halt\n"); |
| 817 | } | 897 | } |
| 818 | 898 | ||
| 819 | bool ath9k_uses_beacons(int type) | 899 | static bool ath9k_uses_beacons(int type) |
| 820 | { | 900 | { |
| 821 | switch (type) { | 901 | switch (type) { |
| 822 | case NL80211_IFTYPE_AP: | 902 | case NL80211_IFTYPE_AP: |
| @@ -966,6 +1046,14 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
| 966 | 1046 | ||
| 967 | mutex_lock(&sc->mutex); | 1047 | mutex_lock(&sc->mutex); |
| 968 | 1048 | ||
| 1049 | if (config_enabled(CONFIG_ATH9K_TX99)) { | ||
| 1050 | if (sc->nvifs >= 1) { | ||
| 1051 | mutex_unlock(&sc->mutex); | ||
| 1052 | return -EOPNOTSUPP; | ||
| 1053 | } | ||
| 1054 | sc->tx99_vif = vif; | ||
| 1055 | } | ||
| 1056 | |||
| 969 | ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type); | 1057 | ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type); |
| 970 | sc->nvifs++; | 1058 | sc->nvifs++; |
| 971 | 1059 | ||
| @@ -994,9 +1082,15 @@ static int ath9k_change_interface(struct ieee80211_hw *hw, | |||
| 994 | struct ath_softc *sc = hw->priv; | 1082 | struct ath_softc *sc = hw->priv; |
| 995 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1083 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
| 996 | 1084 | ||
| 997 | ath_dbg(common, CONFIG, "Change Interface\n"); | ||
| 998 | mutex_lock(&sc->mutex); | 1085 | mutex_lock(&sc->mutex); |
| 999 | 1086 | ||
| 1087 | if (config_enabled(CONFIG_ATH9K_TX99)) { | ||
| 1088 | mutex_unlock(&sc->mutex); | ||
| 1089 | return -EOPNOTSUPP; | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | ath_dbg(common, CONFIG, "Change Interface\n"); | ||
| 1093 | |||
| 1000 | if (ath9k_uses_beacons(vif->type)) | 1094 | if (ath9k_uses_beacons(vif->type)) |
| 1001 | ath9k_beacon_remove_slot(sc, vif); | 1095 | ath9k_beacon_remove_slot(sc, vif); |
| 1002 | 1096 | ||
| @@ -1026,6 +1120,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
| 1026 | mutex_lock(&sc->mutex); | 1120 | mutex_lock(&sc->mutex); |
| 1027 | 1121 | ||
| 1028 | sc->nvifs--; | 1122 | sc->nvifs--; |
| 1123 | sc->tx99_vif = NULL; | ||
| 1029 | 1124 | ||
| 1030 | if (ath9k_uses_beacons(vif->type)) | 1125 | if (ath9k_uses_beacons(vif->type)) |
| 1031 | ath9k_beacon_remove_slot(sc, vif); | 1126 | ath9k_beacon_remove_slot(sc, vif); |
| @@ -1047,6 +1142,9 @@ static void ath9k_enable_ps(struct ath_softc *sc) | |||
| 1047 | struct ath_hw *ah = sc->sc_ah; | 1142 | struct ath_hw *ah = sc->sc_ah; |
| 1048 | struct ath_common *common = ath9k_hw_common(ah); | 1143 | struct ath_common *common = ath9k_hw_common(ah); |
| 1049 | 1144 | ||
| 1145 | if (config_enabled(CONFIG_ATH9K_TX99)) | ||
| 1146 | return; | ||
| 1147 | |||
| 1050 | sc->ps_enabled = true; | 1148 | sc->ps_enabled = true; |
| 1051 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { | 1149 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { |
| 1052 | if ((ah->imask & ATH9K_INT_TIM_TIMER) == 0) { | 1150 | if ((ah->imask & ATH9K_INT_TIM_TIMER) == 0) { |
| @@ -1063,6 +1161,9 @@ static void ath9k_disable_ps(struct ath_softc *sc) | |||
| 1063 | struct ath_hw *ah = sc->sc_ah; | 1161 | struct ath_hw *ah = sc->sc_ah; |
| 1064 | struct ath_common *common = ath9k_hw_common(ah); | 1162 | struct ath_common *common = ath9k_hw_common(ah); |
| 1065 | 1163 | ||
| 1164 | if (config_enabled(CONFIG_ATH9K_TX99)) | ||
| 1165 | return; | ||
| 1166 | |||
| 1066 | sc->ps_enabled = false; | 1167 | sc->ps_enabled = false; |
| 1067 | ath9k_hw_setpower(ah, ATH9K_PM_AWAKE); | 1168 | ath9k_hw_setpower(ah, ATH9K_PM_AWAKE); |
| 1068 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { | 1169 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { |
| @@ -1086,6 +1187,9 @@ void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw) | |||
| 1086 | struct ath_common *common = ath9k_hw_common(ah); | 1187 | struct ath_common *common = ath9k_hw_common(ah); |
| 1087 | u32 rxfilter; | 1188 | u32 rxfilter; |
| 1088 | 1189 | ||
| 1190 | if (config_enabled(CONFIG_ATH9K_TX99)) | ||
| 1191 | return; | ||
| 1192 | |||
| 1089 | if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { | 1193 | if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { |
| 1090 | ath_err(common, "spectrum analyzer not implemented on this hardware\n"); | 1194 | ath_err(common, "spectrum analyzer not implemented on this hardware\n"); |
| 1091 | return; | 1195 | return; |
| @@ -1201,81 +1305,12 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
| 1201 | } | 1305 | } |
| 1202 | 1306 | ||
| 1203 | if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) { | 1307 | if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) { |
| 1204 | struct ieee80211_channel *curchan = hw->conf.chandef.chan; | 1308 | if (ath_set_channel(sc, &hw->conf.chandef) < 0) { |
| 1205 | int pos = curchan->hw_value; | ||
| 1206 | int old_pos = -1; | ||
| 1207 | unsigned long flags; | ||
| 1208 | |||
| 1209 | if (ah->curchan) | ||
| 1210 | old_pos = ah->curchan - &ah->channels[0]; | ||
| 1211 | |||
| 1212 | ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n", | ||
| 1213 | curchan->center_freq, hw->conf.chandef.width); | ||
| 1214 | |||
| 1215 | /* update survey stats for the old channel before switching */ | ||
| 1216 | spin_lock_irqsave(&common->cc_lock, flags); | ||
| 1217 | ath_update_survey_stats(sc); | ||
| 1218 | spin_unlock_irqrestore(&common->cc_lock, flags); | ||
| 1219 | |||
| 1220 | ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos], | ||
| 1221 | &conf->chandef); | ||
| 1222 | |||
| 1223 | /* | ||
| 1224 | * If the operating channel changes, change the survey in-use flags | ||
| 1225 | * along with it. | ||
| 1226 | * Reset the survey data for the new channel, unless we're switching | ||
| 1227 | * back to the operating channel from an off-channel operation. | ||
| 1228 | */ | ||
| 1229 | if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) && | ||
| 1230 | sc->cur_survey != &sc->survey[pos]) { | ||
| 1231 | |||
| 1232 | if (sc->cur_survey) | ||
| 1233 | sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE; | ||
| 1234 | |||
| 1235 | sc->cur_survey = &sc->survey[pos]; | ||
| 1236 | |||
| 1237 | memset(sc->cur_survey, 0, sizeof(struct survey_info)); | ||
| 1238 | sc->cur_survey->filled |= SURVEY_INFO_IN_USE; | ||
| 1239 | } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) { | ||
| 1240 | memset(&sc->survey[pos], 0, sizeof(struct survey_info)); | ||
| 1241 | } | ||
| 1242 | |||
| 1243 | if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) { | ||
| 1244 | ath_err(common, "Unable to set channel\n"); | 1309 | ath_err(common, "Unable to set channel\n"); |
| 1245 | mutex_unlock(&sc->mutex); | 1310 | mutex_unlock(&sc->mutex); |
| 1246 | ath9k_ps_restore(sc); | 1311 | ath9k_ps_restore(sc); |
| 1247 | return -EINVAL; | 1312 | return -EINVAL; |
| 1248 | } | 1313 | } |
| 1249 | |||
| 1250 | /* | ||
| 1251 | * The most recent snapshot of channel->noisefloor for the old | ||
| 1252 | * channel is only available after the hardware reset. Copy it to | ||
| 1253 | * the survey stats now. | ||
| 1254 | */ | ||
| 1255 | if (old_pos >= 0) | ||
| 1256 | ath_update_survey_nf(sc, old_pos); | ||
| 1257 | |||
| 1258 | /* | ||
| 1259 | * Enable radar pulse detection if on a DFS channel. Spectral | ||
| 1260 | * scanning and radar detection can not be used concurrently. | ||
| 1261 | */ | ||
| 1262 | if (hw->conf.radar_enabled) { | ||
| 1263 | u32 rxfilter; | ||
| 1264 | |||
| 1265 | /* set HW specific DFS configuration */ | ||
| 1266 | ath9k_hw_set_radar_params(ah); | ||
| 1267 | rxfilter = ath9k_hw_getrxfilter(ah); | ||
| 1268 | rxfilter |= ATH9K_RX_FILTER_PHYRADAR | | ||
| 1269 | ATH9K_RX_FILTER_PHYERR; | ||
| 1270 | ath9k_hw_setrxfilter(ah, rxfilter); | ||
| 1271 | ath_dbg(common, DFS, "DFS enabled at freq %d\n", | ||
| 1272 | curchan->center_freq); | ||
| 1273 | } else { | ||
| 1274 | /* perform spectral scan if requested. */ | ||
| 1275 | if (test_bit(SC_OP_SCANNING, &sc->sc_flags) && | ||
| 1276 | sc->spectral_mode == SPECTRAL_CHANSCAN) | ||
| 1277 | ath9k_spectral_scan_trigger(hw); | ||
| 1278 | } | ||
| 1279 | } | 1314 | } |
| 1280 | 1315 | ||
| 1281 | if (changed & IEEE80211_CONF_CHANGE_POWER) { | 1316 | if (changed & IEEE80211_CONF_CHANGE_POWER) { |
| @@ -1734,6 +1769,9 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx, | |||
| 1734 | unsigned long flags; | 1769 | unsigned long flags; |
| 1735 | int pos; | 1770 | int pos; |
| 1736 | 1771 | ||
| 1772 | if (config_enabled(CONFIG_ATH9K_TX99)) | ||
| 1773 | return -EOPNOTSUPP; | ||
| 1774 | |||
| 1737 | spin_lock_irqsave(&common->cc_lock, flags); | 1775 | spin_lock_irqsave(&common->cc_lock, flags); |
| 1738 | if (idx == 0) | 1776 | if (idx == 0) |
| 1739 | ath_update_survey_stats(sc); | 1777 | ath_update_survey_stats(sc); |
| @@ -1766,6 +1804,9 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) | |||
| 1766 | struct ath_softc *sc = hw->priv; | 1804 | struct ath_softc *sc = hw->priv; |
| 1767 | struct ath_hw *ah = sc->sc_ah; | 1805 | struct ath_hw *ah = sc->sc_ah; |
| 1768 | 1806 | ||
| 1807 | if (config_enabled(CONFIG_ATH9K_TX99)) | ||
| 1808 | return; | ||
| 1809 | |||
| 1769 | mutex_lock(&sc->mutex); | 1810 | mutex_lock(&sc->mutex); |
| 1770 | ah->coverage_class = coverage_class; | 1811 | ah->coverage_class = coverage_class; |
| 1771 | 1812 | ||
| @@ -2332,6 +2373,134 @@ static void ath9k_channel_switch_beacon(struct ieee80211_hw *hw, | |||
| 2332 | sc->csa_vif = vif; | 2373 | sc->csa_vif = vif; |
| 2333 | } | 2374 | } |
| 2334 | 2375 | ||
| 2376 | static void ath9k_tx99_stop(struct ath_softc *sc) | ||
| 2377 | { | ||
| 2378 | struct ath_hw *ah = sc->sc_ah; | ||
| 2379 | struct ath_common *common = ath9k_hw_common(ah); | ||
| 2380 | |||
| 2381 | ath_drain_all_txq(sc); | ||
| 2382 | ath_startrecv(sc); | ||
| 2383 | |||
| 2384 | ath9k_hw_set_interrupts(ah); | ||
| 2385 | ath9k_hw_enable_interrupts(ah); | ||
| 2386 | |||
| 2387 | ieee80211_wake_queues(sc->hw); | ||
| 2388 | |||
| 2389 | kfree_skb(sc->tx99_skb); | ||
| 2390 | sc->tx99_skb = NULL; | ||
| 2391 | sc->tx99_state = false; | ||
| 2392 | |||
| 2393 | ath9k_hw_tx99_stop(sc->sc_ah); | ||
| 2394 | ath_dbg(common, XMIT, "TX99 stopped\n"); | ||
| 2395 | } | ||
| 2396 | |||
| 2397 | static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc) | ||
| 2398 | { | ||
| 2399 | static u8 PN9Data[] = {0xff, 0x87, 0xb8, 0x59, 0xb7, 0xa1, 0xcc, 0x24, | ||
| 2400 | 0x57, 0x5e, 0x4b, 0x9c, 0x0e, 0xe9, 0xea, 0x50, | ||
| 2401 | 0x2a, 0xbe, 0xb4, 0x1b, 0xb6, 0xb0, 0x5d, 0xf1, | ||
| 2402 | 0xe6, 0x9a, 0xe3, 0x45, 0xfd, 0x2c, 0x53, 0x18, | ||
| 2403 | 0x0c, 0xca, 0xc9, 0xfb, 0x49, 0x37, 0xe5, 0xa8, | ||
| 2404 | 0x51, 0x3b, 0x2f, 0x61, 0xaa, 0x72, 0x18, 0x84, | ||
| 2405 | 0x02, 0x23, 0x23, 0xab, 0x63, 0x89, 0x51, 0xb3, | ||
| 2406 | 0xe7, 0x8b, 0x72, 0x90, 0x4c, 0xe8, 0xfb, 0xc0}; | ||
| 2407 | u32 len = 1200; | ||
| 2408 | struct ieee80211_hw *hw = sc->hw; | ||
| 2409 | struct ieee80211_hdr *hdr; | ||
| 2410 | struct ieee80211_tx_info *tx_info; | ||
| 2411 | struct sk_buff *skb; | ||
| 2412 | |||
| 2413 | skb = alloc_skb(len, GFP_KERNEL); | ||
| 2414 | if (!skb) | ||
| 2415 | return NULL; | ||
| 2416 | |||
| 2417 | skb_put(skb, len); | ||
| 2418 | |||
| 2419 | memset(skb->data, 0, len); | ||
| 2420 | |||
| 2421 | hdr = (struct ieee80211_hdr *)skb->data; | ||
| 2422 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA); | ||
| 2423 | hdr->duration_id = 0; | ||
| 2424 | |||
| 2425 | memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN); | ||
| 2426 | memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); | ||
| 2427 | memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); | ||
| 2428 | |||
| 2429 | hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); | ||
| 2430 | |||
| 2431 | tx_info = IEEE80211_SKB_CB(skb); | ||
| 2432 | memset(tx_info, 0, sizeof(*tx_info)); | ||
| 2433 | tx_info->band = hw->conf.chandef.chan->band; | ||
| 2434 | tx_info->flags = IEEE80211_TX_CTL_NO_ACK; | ||
| 2435 | tx_info->control.vif = sc->tx99_vif; | ||
| 2436 | |||
| 2437 | memcpy(skb->data + sizeof(*hdr), PN9Data, sizeof(PN9Data)); | ||
| 2438 | |||
| 2439 | return skb; | ||
| 2440 | } | ||
| 2441 | |||
| 2442 | void ath9k_tx99_deinit(struct ath_softc *sc) | ||
| 2443 | { | ||
| 2444 | ath_reset(sc); | ||
| 2445 | |||
| 2446 | ath9k_ps_wakeup(sc); | ||
| 2447 | ath9k_tx99_stop(sc); | ||
| 2448 | ath9k_ps_restore(sc); | ||
| 2449 | } | ||
| 2450 | |||
| 2451 | int ath9k_tx99_init(struct ath_softc *sc) | ||
| 2452 | { | ||
| 2453 | struct ieee80211_hw *hw = sc->hw; | ||
| 2454 | struct ath_hw *ah = sc->sc_ah; | ||
| 2455 | struct ath_common *common = ath9k_hw_common(ah); | ||
| 2456 | struct ath_tx_control txctl; | ||
| 2457 | int r; | ||
| 2458 | |||
| 2459 | if (sc->sc_flags & SC_OP_INVALID) { | ||
| 2460 | ath_err(common, | ||
| 2461 | "driver is in invalid state unable to use TX99"); | ||
| 2462 | return -EINVAL; | ||
| 2463 | } | ||
| 2464 | |||
| 2465 | sc->tx99_skb = ath9k_build_tx99_skb(sc); | ||
| 2466 | if (!sc->tx99_skb) | ||
| 2467 | return -ENOMEM; | ||
| 2468 | |||
| 2469 | memset(&txctl, 0, sizeof(txctl)); | ||
| 2470 | txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; | ||
| 2471 | |||
| 2472 | ath_reset(sc); | ||
| 2473 | |||
| 2474 | ath9k_ps_wakeup(sc); | ||
| 2475 | |||
| 2476 | ath9k_hw_disable_interrupts(ah); | ||
| 2477 | atomic_set(&ah->intr_ref_cnt, -1); | ||
| 2478 | ath_drain_all_txq(sc); | ||
| 2479 | ath_stoprecv(sc); | ||
| 2480 | |||
| 2481 | sc->tx99_state = true; | ||
| 2482 | |||
| 2483 | ieee80211_stop_queues(hw); | ||
| 2484 | |||
| 2485 | if (sc->tx99_power == MAX_RATE_POWER + 1) | ||
| 2486 | sc->tx99_power = MAX_RATE_POWER; | ||
| 2487 | |||
| 2488 | ath9k_hw_tx99_set_txpower(ah, sc->tx99_power); | ||
| 2489 | r = ath9k_tx99_send(sc, sc->tx99_skb, &txctl); | ||
| 2490 | if (r) { | ||
| 2491 | ath_dbg(common, XMIT, "Failed to xmit TX99 skb\n"); | ||
| 2492 | return r; | ||
| 2493 | } | ||
| 2494 | |||
| 2495 | ath_dbg(common, XMIT, "TX99 xmit started using %d ( %ddBm)\n", | ||
| 2496 | sc->tx99_power, | ||
| 2497 | sc->tx99_power / 2); | ||
| 2498 | |||
| 2499 | /* We leave the harware awake as it will be chugging on */ | ||
| 2500 | |||
| 2501 | return 0; | ||
| 2502 | } | ||
| 2503 | |||
| 2335 | struct ieee80211_ops ath9k_ops = { | 2504 | struct ieee80211_ops ath9k_ops = { |
| 2336 | .tx = ath9k_tx, | 2505 | .tx = ath9k_tx, |
| 2337 | .start = ath9k_start, | 2506 | .start = ath9k_start, |
diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c index 815bee21c19a..0ac1b5f04256 100644 --- a/drivers/net/wireless/ath/ath9k/mci.c +++ b/drivers/net/wireless/ath/ath9k/mci.c | |||
| @@ -661,9 +661,9 @@ void ath9k_mci_update_wlan_channels(struct ath_softc *sc, bool allow_all) | |||
| 661 | chan_start = wlan_chan - 10; | 661 | chan_start = wlan_chan - 10; |
| 662 | chan_end = wlan_chan + 10; | 662 | chan_end = wlan_chan + 10; |
| 663 | 663 | ||
| 664 | if (chan->chanmode == CHANNEL_G_HT40PLUS) | 664 | if (IS_CHAN_HT40PLUS(chan)) |
| 665 | chan_end += 20; | 665 | chan_end += 20; |
| 666 | else if (chan->chanmode == CHANNEL_G_HT40MINUS) | 666 | else if (IS_CHAN_HT40MINUS(chan)) |
| 667 | chan_start -= 20; | 667 | chan_start -= 20; |
| 668 | 668 | ||
| 669 | /* adjust side band */ | 669 | /* adjust side band */ |
| @@ -707,11 +707,11 @@ void ath9k_mci_set_txpower(struct ath_softc *sc, bool setchannel, | |||
| 707 | 707 | ||
| 708 | if (setchannel) { | 708 | if (setchannel) { |
| 709 | struct ath9k_hw_cal_data *caldata = &sc->caldata; | 709 | struct ath9k_hw_cal_data *caldata = &sc->caldata; |
| 710 | if ((caldata->chanmode == CHANNEL_G_HT40PLUS) && | 710 | if (IS_CHAN_HT40PLUS(ah->curchan) && |
| 711 | (ah->curchan->channel > caldata->channel) && | 711 | (ah->curchan->channel > caldata->channel) && |
| 712 | (ah->curchan->channel <= caldata->channel + 20)) | 712 | (ah->curchan->channel <= caldata->channel + 20)) |
| 713 | return; | 713 | return; |
| 714 | if ((caldata->chanmode == CHANNEL_G_HT40MINUS) && | 714 | if (IS_CHAN_HT40MINUS(ah->curchan) && |
| 715 | (ah->curchan->channel < caldata->channel) && | 715 | (ah->curchan->channel < caldata->channel) && |
| 716 | (ah->curchan->channel >= caldata->channel - 20)) | 716 | (ah->curchan->channel >= caldata->channel - 20)) |
| 717 | return; | 717 | return; |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index d089a7cf01c4..7e4c2524b630 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
| @@ -269,7 +269,200 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { | |||
| 269 | 269 | ||
| 270 | { PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E AR9462 */ | 270 | { PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E AR9462 */ |
| 271 | { PCI_VDEVICE(ATHEROS, 0x0037) }, /* PCI-E AR1111/AR9485 */ | 271 | { PCI_VDEVICE(ATHEROS, 0x0037) }, /* PCI-E AR1111/AR9485 */ |
| 272 | { PCI_VDEVICE(ATHEROS, 0x0036) }, /* PCI-E AR9565 */ | 272 | |
| 273 | /* CUS252 */ | ||
| 274 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 275 | 0x0036, | ||
| 276 | PCI_VENDOR_ID_ATHEROS, | ||
| 277 | 0x3028), | ||
| 278 | .driver_data = ATH9K_PCI_CUS252 | | ||
| 279 | ATH9K_PCI_AR9565_2ANT | | ||
| 280 | ATH9K_PCI_BT_ANT_DIV }, | ||
| 281 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 282 | 0x0036, | ||
| 283 | PCI_VENDOR_ID_AZWAVE, | ||
| 284 | 0x2176), | ||
| 285 | .driver_data = ATH9K_PCI_CUS252 | | ||
| 286 | ATH9K_PCI_AR9565_2ANT | | ||
| 287 | ATH9K_PCI_BT_ANT_DIV }, | ||
| 288 | |||
| 289 | /* WB335 1-ANT */ | ||
| 290 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 291 | 0x0036, | ||
| 292 | PCI_VENDOR_ID_FOXCONN, | ||
| 293 | 0xE068), | ||
| 294 | .driver_data = ATH9K_PCI_AR9565_1ANT }, | ||
| 295 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 296 | 0x0036, | ||
| 297 | 0x185F, /* WNC */ | ||
| 298 | 0xA119), | ||
| 299 | .driver_data = ATH9K_PCI_AR9565_1ANT }, | ||
| 300 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 301 | 0x0036, | ||
| 302 | 0x11AD, /* LITEON */ | ||
| 303 | 0x0632), | ||
| 304 | .driver_data = ATH9K_PCI_AR9565_1ANT }, | ||
| 305 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 306 | 0x0036, | ||
| 307 | 0x11AD, /* LITEON */ | ||
| 308 | 0x6671), | ||
| 309 | .driver_data = ATH9K_PCI_AR9565_1ANT }, | ||
| 310 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 311 | 0x0036, | ||
| 312 | 0x1B9A, /* XAVI */ | ||
| 313 | 0x2811), | ||
| 314 | .driver_data = ATH9K_PCI_AR9565_1ANT }, | ||
| 315 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 316 | 0x0036, | ||
| 317 | 0x1B9A, /* XAVI */ | ||
| 318 | 0x2812), | ||
| 319 | .driver_data = ATH9K_PCI_AR9565_1ANT }, | ||
| 320 | |||
| 321 | /* WB335 1-ANT / Antenna Diversity */ | ||
| 322 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 323 | 0x0036, | ||
| 324 | PCI_VENDOR_ID_ATHEROS, | ||
| 325 | 0x3025), | ||
| 326 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 327 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 328 | 0x0036, | ||
| 329 | PCI_VENDOR_ID_ATHEROS, | ||
| 330 | 0x3026), | ||
| 331 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 332 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 333 | 0x0036, | ||
| 334 | PCI_VENDOR_ID_ATHEROS, | ||
| 335 | 0x302B), | ||
| 336 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 337 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 338 | 0x0036, | ||
| 339 | PCI_VENDOR_ID_FOXCONN, | ||
| 340 | 0xE069), | ||
| 341 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 342 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 343 | 0x0036, | ||
| 344 | 0x185F, /* WNC */ | ||
| 345 | 0x3028), | ||
| 346 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 347 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 348 | 0x0036, | ||
| 349 | 0x11AD, /* LITEON */ | ||
| 350 | 0x0622), | ||
| 351 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 352 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 353 | 0x0036, | ||
| 354 | 0x11AD, /* LITEON */ | ||
| 355 | 0x0672), | ||
| 356 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 357 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 358 | 0x0036, | ||
| 359 | 0x11AD, /* LITEON */ | ||
| 360 | 0x0662), | ||
| 361 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 362 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 363 | 0x0036, | ||
| 364 | PCI_VENDOR_ID_AZWAVE, | ||
| 365 | 0x213A), | ||
| 366 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 367 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 368 | 0x0036, | ||
| 369 | PCI_VENDOR_ID_LENOVO, | ||
| 370 | 0x3026), | ||
| 371 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 372 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 373 | 0x0036, | ||
| 374 | PCI_VENDOR_ID_HP, | ||
| 375 | 0x18E3), | ||
| 376 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 377 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 378 | 0x0036, | ||
| 379 | PCI_VENDOR_ID_HP, | ||
| 380 | 0x217F), | ||
| 381 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 382 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 383 | 0x0036, | ||
| 384 | PCI_VENDOR_ID_DELL, | ||
| 385 | 0x020E), | ||
| 386 | .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 387 | |||
| 388 | /* WB335 2-ANT */ | ||
| 389 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 390 | 0x0036, | ||
| 391 | PCI_VENDOR_ID_SAMSUNG, | ||
| 392 | 0x411A), | ||
| 393 | .driver_data = ATH9K_PCI_AR9565_2ANT }, | ||
| 394 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 395 | 0x0036, | ||
| 396 | PCI_VENDOR_ID_SAMSUNG, | ||
| 397 | 0x411B), | ||
| 398 | .driver_data = ATH9K_PCI_AR9565_2ANT }, | ||
| 399 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 400 | 0x0036, | ||
| 401 | PCI_VENDOR_ID_SAMSUNG, | ||
| 402 | 0x411C), | ||
| 403 | .driver_data = ATH9K_PCI_AR9565_2ANT }, | ||
| 404 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 405 | 0x0036, | ||
| 406 | PCI_VENDOR_ID_SAMSUNG, | ||
| 407 | 0x411D), | ||
| 408 | .driver_data = ATH9K_PCI_AR9565_2ANT }, | ||
| 409 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 410 | 0x0036, | ||
| 411 | PCI_VENDOR_ID_SAMSUNG, | ||
| 412 | 0x411E), | ||
| 413 | .driver_data = ATH9K_PCI_AR9565_2ANT }, | ||
| 414 | |||
| 415 | /* WB335 2-ANT / Antenna-Diversity */ | ||
| 416 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 417 | 0x0036, | ||
| 418 | PCI_VENDOR_ID_ATHEROS, | ||
| 419 | 0x3027), | ||
| 420 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 421 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 422 | 0x0036, | ||
| 423 | PCI_VENDOR_ID_ATHEROS, | ||
| 424 | 0x302C), | ||
| 425 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 426 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 427 | 0x0036, | ||
| 428 | 0x11AD, /* LITEON */ | ||
| 429 | 0x0642), | ||
| 430 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 431 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 432 | 0x0036, | ||
| 433 | 0x11AD, /* LITEON */ | ||
| 434 | 0x0652), | ||
| 435 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 436 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 437 | 0x0036, | ||
| 438 | 0x11AD, /* LITEON */ | ||
| 439 | 0x0612), | ||
| 440 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 441 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 442 | 0x0036, | ||
| 443 | PCI_VENDOR_ID_AZWAVE, | ||
| 444 | 0x2130), | ||
| 445 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 446 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 447 | 0x0036, | ||
| 448 | 0x144F, /* ASKEY */ | ||
| 449 | 0x7202), | ||
| 450 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 451 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 452 | 0x0036, | ||
| 453 | 0x1B9A, /* XAVI */ | ||
| 454 | 0x2810), | ||
| 455 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 456 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | ||
| 457 | 0x0036, | ||
| 458 | 0x185F, /* WNC */ | ||
| 459 | 0x3027), | ||
| 460 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | ||
| 461 | |||
| 462 | /* PCI-E AR9565 (WB335) */ | ||
| 463 | { PCI_VDEVICE(ATHEROS, 0x0036), | ||
| 464 | .driver_data = ATH9K_PCI_BT_ANT_DIV }, | ||
| 465 | |||
| 273 | { 0 } | 466 | { 0 } |
| 274 | }; | 467 | }; |
| 275 | 468 | ||
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index d3d7c51fa6c8..d829bb62a3fc 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
| @@ -1387,31 +1387,31 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, | |||
| 1387 | int used_mcs = 0, used_htmode = 0; | 1387 | int used_mcs = 0, used_htmode = 0; |
| 1388 | 1388 | ||
| 1389 | if (WLAN_RC_PHY_HT(rc->rate_table->info[i].phy)) { | 1389 | if (WLAN_RC_PHY_HT(rc->rate_table->info[i].phy)) { |
| 1390 | used_mcs = snprintf(mcs, 5, "%d", | 1390 | used_mcs = scnprintf(mcs, 5, "%d", |
| 1391 | rc->rate_table->info[i].ratecode); | 1391 | rc->rate_table->info[i].ratecode); |
| 1392 | 1392 | ||
| 1393 | if (WLAN_RC_PHY_40(rc->rate_table->info[i].phy)) | 1393 | if (WLAN_RC_PHY_40(rc->rate_table->info[i].phy)) |
| 1394 | used_htmode = snprintf(htmode, 5, "HT40"); | 1394 | used_htmode = scnprintf(htmode, 5, "HT40"); |
| 1395 | else if (WLAN_RC_PHY_20(rc->rate_table->info[i].phy)) | 1395 | else if (WLAN_RC_PHY_20(rc->rate_table->info[i].phy)) |
| 1396 | used_htmode = snprintf(htmode, 5, "HT20"); | 1396 | used_htmode = scnprintf(htmode, 5, "HT20"); |
| 1397 | else | 1397 | else |
| 1398 | used_htmode = snprintf(htmode, 5, "????"); | 1398 | used_htmode = scnprintf(htmode, 5, "????"); |
| 1399 | } | 1399 | } |
| 1400 | 1400 | ||
| 1401 | mcs[used_mcs] = '\0'; | 1401 | mcs[used_mcs] = '\0'; |
| 1402 | htmode[used_htmode] = '\0'; | 1402 | htmode[used_htmode] = '\0'; |
| 1403 | 1403 | ||
| 1404 | len += snprintf(buf + len, max - len, | 1404 | len += scnprintf(buf + len, max - len, |
| 1405 | "%6s %6s %3u.%d: " | 1405 | "%6s %6s %3u.%d: " |
| 1406 | "%10u %10u %10u %10u\n", | 1406 | "%10u %10u %10u %10u\n", |
| 1407 | htmode, | 1407 | htmode, |
| 1408 | mcs, | 1408 | mcs, |
| 1409 | ratekbps / 1000, | 1409 | ratekbps / 1000, |
| 1410 | (ratekbps % 1000) / 100, | 1410 | (ratekbps % 1000) / 100, |
| 1411 | stats->success, | 1411 | stats->success, |
| 1412 | stats->retries, | 1412 | stats->retries, |
| 1413 | stats->xretries, | 1413 | stats->xretries, |
| 1414 | stats->per); | 1414 | stats->per); |
| 1415 | } | 1415 | } |
| 1416 | 1416 | ||
| 1417 | if (len > max) | 1417 | if (len > max) |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index ab9e3a8410bc..95ddca5495d4 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | #include "ath9k.h" | 19 | #include "ath9k.h" |
| 20 | #include "ar9003_mac.h" | 20 | #include "ar9003_mac.h" |
| 21 | 21 | ||
| 22 | #define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb)) | 22 | #define SKB_CB_ATHBUF(__skb) (*((struct ath_rxbuf **)__skb->cb)) |
| 23 | 23 | ||
| 24 | static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) | 24 | static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) |
| 25 | { | 25 | { |
| @@ -35,7 +35,7 @@ static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) | |||
| 35 | * buffer (or rx fifo). This can incorrectly acknowledge packets | 35 | * buffer (or rx fifo). This can incorrectly acknowledge packets |
| 36 | * to a sender if last desc is self-linked. | 36 | * to a sender if last desc is self-linked. |
| 37 | */ | 37 | */ |
| 38 | static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) | 38 | static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf) |
| 39 | { | 39 | { |
| 40 | struct ath_hw *ah = sc->sc_ah; | 40 | struct ath_hw *ah = sc->sc_ah; |
| 41 | struct ath_common *common = ath9k_hw_common(ah); | 41 | struct ath_common *common = ath9k_hw_common(ah); |
| @@ -68,7 +68,7 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) | |||
| 68 | sc->rx.rxlink = &ds->ds_link; | 68 | sc->rx.rxlink = &ds->ds_link; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_buf *bf) | 71 | static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf) |
| 72 | { | 72 | { |
| 73 | if (sc->rx.buf_hold) | 73 | if (sc->rx.buf_hold) |
| 74 | ath_rx_buf_link(sc, sc->rx.buf_hold); | 74 | ath_rx_buf_link(sc, sc->rx.buf_hold); |
| @@ -112,13 +112,13 @@ static bool ath_rx_edma_buf_link(struct ath_softc *sc, | |||
| 112 | struct ath_hw *ah = sc->sc_ah; | 112 | struct ath_hw *ah = sc->sc_ah; |
| 113 | struct ath_rx_edma *rx_edma; | 113 | struct ath_rx_edma *rx_edma; |
| 114 | struct sk_buff *skb; | 114 | struct sk_buff *skb; |
| 115 | struct ath_buf *bf; | 115 | struct ath_rxbuf *bf; |
| 116 | 116 | ||
| 117 | rx_edma = &sc->rx.rx_edma[qtype]; | 117 | rx_edma = &sc->rx.rx_edma[qtype]; |
| 118 | if (skb_queue_len(&rx_edma->rx_fifo) >= rx_edma->rx_fifo_hwsize) | 118 | if (skb_queue_len(&rx_edma->rx_fifo) >= rx_edma->rx_fifo_hwsize) |
| 119 | return false; | 119 | return false; |
| 120 | 120 | ||
| 121 | bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); | 121 | bf = list_first_entry(&sc->rx.rxbuf, struct ath_rxbuf, list); |
| 122 | list_del_init(&bf->list); | 122 | list_del_init(&bf->list); |
| 123 | 123 | ||
| 124 | skb = bf->bf_mpdu; | 124 | skb = bf->bf_mpdu; |
| @@ -138,7 +138,7 @@ static void ath_rx_addbuffer_edma(struct ath_softc *sc, | |||
| 138 | enum ath9k_rx_qtype qtype) | 138 | enum ath9k_rx_qtype qtype) |
| 139 | { | 139 | { |
| 140 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 140 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
| 141 | struct ath_buf *bf, *tbf; | 141 | struct ath_rxbuf *bf, *tbf; |
| 142 | 142 | ||
| 143 | if (list_empty(&sc->rx.rxbuf)) { | 143 | if (list_empty(&sc->rx.rxbuf)) { |
| 144 | ath_dbg(common, QUEUE, "No free rx buf available\n"); | 144 | ath_dbg(common, QUEUE, "No free rx buf available\n"); |
| @@ -154,7 +154,7 @@ static void ath_rx_addbuffer_edma(struct ath_softc *sc, | |||
| 154 | static void ath_rx_remove_buffer(struct ath_softc *sc, | 154 | static void ath_rx_remove_buffer(struct ath_softc *sc, |
| 155 | enum ath9k_rx_qtype qtype) | 155 | enum ath9k_rx_qtype qtype) |
| 156 | { | 156 | { |
| 157 | struct ath_buf *bf; | 157 | struct ath_rxbuf *bf; |
| 158 | struct ath_rx_edma *rx_edma; | 158 | struct ath_rx_edma *rx_edma; |
| 159 | struct sk_buff *skb; | 159 | struct sk_buff *skb; |
| 160 | 160 | ||
| @@ -171,7 +171,7 @@ static void ath_rx_edma_cleanup(struct ath_softc *sc) | |||
| 171 | { | 171 | { |
| 172 | struct ath_hw *ah = sc->sc_ah; | 172 | struct ath_hw *ah = sc->sc_ah; |
| 173 | struct ath_common *common = ath9k_hw_common(ah); | 173 | struct ath_common *common = ath9k_hw_common(ah); |
| 174 | struct ath_buf *bf; | 174 | struct ath_rxbuf *bf; |
| 175 | 175 | ||
| 176 | ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP); | 176 | ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP); |
| 177 | ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP); | 177 | ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP); |
| @@ -199,7 +199,7 @@ static int ath_rx_edma_init(struct ath_softc *sc, int nbufs) | |||
| 199 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 199 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
| 200 | struct ath_hw *ah = sc->sc_ah; | 200 | struct ath_hw *ah = sc->sc_ah; |
| 201 | struct sk_buff *skb; | 201 | struct sk_buff *skb; |
| 202 | struct ath_buf *bf; | 202 | struct ath_rxbuf *bf; |
| 203 | int error = 0, i; | 203 | int error = 0, i; |
| 204 | u32 size; | 204 | u32 size; |
| 205 | 205 | ||
| @@ -211,7 +211,7 @@ static int ath_rx_edma_init(struct ath_softc *sc, int nbufs) | |||
| 211 | ath_rx_edma_init_queue(&sc->rx.rx_edma[ATH9K_RX_QUEUE_HP], | 211 | ath_rx_edma_init_queue(&sc->rx.rx_edma[ATH9K_RX_QUEUE_HP], |
| 212 | ah->caps.rx_hp_qdepth); | 212 | ah->caps.rx_hp_qdepth); |
| 213 | 213 | ||
| 214 | size = sizeof(struct ath_buf) * nbufs; | 214 | size = sizeof(struct ath_rxbuf) * nbufs; |
| 215 | bf = devm_kzalloc(sc->dev, size, GFP_KERNEL); | 215 | bf = devm_kzalloc(sc->dev, size, GFP_KERNEL); |
| 216 | if (!bf) | 216 | if (!bf) |
| 217 | return -ENOMEM; | 217 | return -ENOMEM; |
| @@ -271,7 +271,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) | |||
| 271 | { | 271 | { |
| 272 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 272 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
| 273 | struct sk_buff *skb; | 273 | struct sk_buff *skb; |
| 274 | struct ath_buf *bf; | 274 | struct ath_rxbuf *bf; |
| 275 | int error = 0; | 275 | int error = 0; |
| 276 | 276 | ||
| 277 | spin_lock_init(&sc->sc_pcu_lock); | 277 | spin_lock_init(&sc->sc_pcu_lock); |
| @@ -332,7 +332,7 @@ void ath_rx_cleanup(struct ath_softc *sc) | |||
| 332 | struct ath_hw *ah = sc->sc_ah; | 332 | struct ath_hw *ah = sc->sc_ah; |
| 333 | struct ath_common *common = ath9k_hw_common(ah); | 333 | struct ath_common *common = ath9k_hw_common(ah); |
| 334 | struct sk_buff *skb; | 334 | struct sk_buff *skb; |
| 335 | struct ath_buf *bf; | 335 | struct ath_rxbuf *bf; |
| 336 | 336 | ||
| 337 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { | 337 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { |
| 338 | ath_rx_edma_cleanup(sc); | 338 | ath_rx_edma_cleanup(sc); |
| @@ -375,6 +375,9 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
| 375 | { | 375 | { |
| 376 | u32 rfilt; | 376 | u32 rfilt; |
| 377 | 377 | ||
| 378 | if (config_enabled(CONFIG_ATH9K_TX99)) | ||
| 379 | return 0; | ||
| 380 | |||
| 378 | rfilt = ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST | 381 | rfilt = ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST |
| 379 | | ATH9K_RX_FILTER_MCAST; | 382 | | ATH9K_RX_FILTER_MCAST; |
| 380 | 383 | ||
| @@ -427,7 +430,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
| 427 | int ath_startrecv(struct ath_softc *sc) | 430 | int ath_startrecv(struct ath_softc *sc) |
| 428 | { | 431 | { |
| 429 | struct ath_hw *ah = sc->sc_ah; | 432 | struct ath_hw *ah = sc->sc_ah; |
| 430 | struct ath_buf *bf, *tbf; | 433 | struct ath_rxbuf *bf, *tbf; |
| 431 | 434 | ||
| 432 | if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { | 435 | if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { |
| 433 | ath_edma_start_recv(sc); | 436 | ath_edma_start_recv(sc); |
| @@ -447,7 +450,7 @@ int ath_startrecv(struct ath_softc *sc) | |||
| 447 | if (list_empty(&sc->rx.rxbuf)) | 450 | if (list_empty(&sc->rx.rxbuf)) |
| 448 | goto start_recv; | 451 | goto start_recv; |
| 449 | 452 | ||
| 450 | bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); | 453 | bf = list_first_entry(&sc->rx.rxbuf, struct ath_rxbuf, list); |
| 451 | ath9k_hw_putrxbuf(ah, bf->bf_daddr); | 454 | ath9k_hw_putrxbuf(ah, bf->bf_daddr); |
| 452 | ath9k_hw_rxena(ah); | 455 | ath9k_hw_rxena(ah); |
| 453 | 456 | ||
| @@ -603,13 +606,13 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb, bool mybeacon) | |||
| 603 | static bool ath_edma_get_buffers(struct ath_softc *sc, | 606 | static bool ath_edma_get_buffers(struct ath_softc *sc, |
| 604 | enum ath9k_rx_qtype qtype, | 607 | enum ath9k_rx_qtype qtype, |
| 605 | struct ath_rx_status *rs, | 608 | struct ath_rx_status *rs, |
| 606 | struct ath_buf **dest) | 609 | struct ath_rxbuf **dest) |
| 607 | { | 610 | { |
| 608 | struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype]; | 611 | struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype]; |
| 609 | struct ath_hw *ah = sc->sc_ah; | 612 | struct ath_hw *ah = sc->sc_ah; |
| 610 | struct ath_common *common = ath9k_hw_common(ah); | 613 | struct ath_common *common = ath9k_hw_common(ah); |
| 611 | struct sk_buff *skb; | 614 | struct sk_buff *skb; |
| 612 | struct ath_buf *bf; | 615 | struct ath_rxbuf *bf; |
| 613 | int ret; | 616 | int ret; |
| 614 | 617 | ||
| 615 | skb = skb_peek(&rx_edma->rx_fifo); | 618 | skb = skb_peek(&rx_edma->rx_fifo); |
| @@ -653,11 +656,11 @@ static bool ath_edma_get_buffers(struct ath_softc *sc, | |||
| 653 | return true; | 656 | return true; |
| 654 | } | 657 | } |
| 655 | 658 | ||
| 656 | static struct ath_buf *ath_edma_get_next_rx_buf(struct ath_softc *sc, | 659 | static struct ath_rxbuf *ath_edma_get_next_rx_buf(struct ath_softc *sc, |
| 657 | struct ath_rx_status *rs, | 660 | struct ath_rx_status *rs, |
| 658 | enum ath9k_rx_qtype qtype) | 661 | enum ath9k_rx_qtype qtype) |
| 659 | { | 662 | { |
| 660 | struct ath_buf *bf = NULL; | 663 | struct ath_rxbuf *bf = NULL; |
| 661 | 664 | ||
| 662 | while (ath_edma_get_buffers(sc, qtype, rs, &bf)) { | 665 | while (ath_edma_get_buffers(sc, qtype, rs, &bf)) { |
| 663 | if (!bf) | 666 | if (!bf) |
| @@ -668,13 +671,13 @@ static struct ath_buf *ath_edma_get_next_rx_buf(struct ath_softc *sc, | |||
| 668 | return NULL; | 671 | return NULL; |
| 669 | } | 672 | } |
| 670 | 673 | ||
| 671 | static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, | 674 | static struct ath_rxbuf *ath_get_next_rx_buf(struct ath_softc *sc, |
| 672 | struct ath_rx_status *rs) | 675 | struct ath_rx_status *rs) |
| 673 | { | 676 | { |
| 674 | struct ath_hw *ah = sc->sc_ah; | 677 | struct ath_hw *ah = sc->sc_ah; |
| 675 | struct ath_common *common = ath9k_hw_common(ah); | 678 | struct ath_common *common = ath9k_hw_common(ah); |
| 676 | struct ath_desc *ds; | 679 | struct ath_desc *ds; |
| 677 | struct ath_buf *bf; | 680 | struct ath_rxbuf *bf; |
| 678 | int ret; | 681 | int ret; |
| 679 | 682 | ||
| 680 | if (list_empty(&sc->rx.rxbuf)) { | 683 | if (list_empty(&sc->rx.rxbuf)) { |
| @@ -682,7 +685,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, | |||
| 682 | return NULL; | 685 | return NULL; |
| 683 | } | 686 | } |
| 684 | 687 | ||
| 685 | bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); | 688 | bf = list_first_entry(&sc->rx.rxbuf, struct ath_rxbuf, list); |
| 686 | if (bf == sc->rx.buf_hold) | 689 | if (bf == sc->rx.buf_hold) |
| 687 | return NULL; | 690 | return NULL; |
| 688 | 691 | ||
| @@ -702,7 +705,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, | |||
| 702 | ret = ath9k_hw_rxprocdesc(ah, ds, rs); | 705 | ret = ath9k_hw_rxprocdesc(ah, ds, rs); |
| 703 | if (ret == -EINPROGRESS) { | 706 | if (ret == -EINPROGRESS) { |
| 704 | struct ath_rx_status trs; | 707 | struct ath_rx_status trs; |
| 705 | struct ath_buf *tbf; | 708 | struct ath_rxbuf *tbf; |
| 706 | struct ath_desc *tds; | 709 | struct ath_desc *tds; |
| 707 | 710 | ||
| 708 | memset(&trs, 0, sizeof(trs)); | 711 | memset(&trs, 0, sizeof(trs)); |
| @@ -711,7 +714,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, | |||
| 711 | return NULL; | 714 | return NULL; |
| 712 | } | 715 | } |
| 713 | 716 | ||
| 714 | tbf = list_entry(bf->list.next, struct ath_buf, list); | 717 | tbf = list_entry(bf->list.next, struct ath_rxbuf, list); |
| 715 | 718 | ||
| 716 | /* | 719 | /* |
| 717 | * On some hardware the descriptor status words could | 720 | * On some hardware the descriptor status words could |
| @@ -972,14 +975,15 @@ static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, | |||
| 972 | { | 975 | { |
| 973 | #ifdef CONFIG_ATH9K_DEBUGFS | 976 | #ifdef CONFIG_ATH9K_DEBUGFS |
| 974 | struct ath_hw *ah = sc->sc_ah; | 977 | struct ath_hw *ah = sc->sc_ah; |
| 975 | u8 bins[SPECTRAL_HT20_NUM_BINS]; | 978 | u8 num_bins, *bins, *vdata = (u8 *)hdr; |
| 976 | u8 *vdata = (u8 *)hdr; | 979 | struct fft_sample_ht20 fft_sample_20; |
| 977 | struct fft_sample_ht20 fft_sample; | 980 | struct fft_sample_ht20_40 fft_sample_40; |
| 981 | struct fft_sample_tlv *tlv; | ||
| 978 | struct ath_radar_info *radar_info; | 982 | struct ath_radar_info *radar_info; |
| 979 | struct ath_ht20_mag_info *mag_info; | ||
| 980 | int len = rs->rs_datalen; | 983 | int len = rs->rs_datalen; |
| 981 | int dc_pos; | 984 | int dc_pos; |
| 982 | u16 length, max_magnitude; | 985 | u16 fft_len, length, freq = ah->curchan->chan->center_freq; |
| 986 | enum nl80211_channel_type chan_type; | ||
| 983 | 987 | ||
| 984 | /* AR9280 and before report via ATH9K_PHYERR_RADAR, AR93xx and newer | 988 | /* AR9280 and before report via ATH9K_PHYERR_RADAR, AR93xx and newer |
| 985 | * via ATH9K_PHYERR_SPECTRAL. Haven't seen ATH9K_PHYERR_FALSE_RADAR_EXT | 989 | * via ATH9K_PHYERR_SPECTRAL. Haven't seen ATH9K_PHYERR_FALSE_RADAR_EXT |
| @@ -997,45 +1001,44 @@ static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, | |||
| 997 | if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK)) | 1001 | if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK)) |
| 998 | return 0; | 1002 | return 0; |
| 999 | 1003 | ||
| 1000 | /* Variation in the data length is possible and will be fixed later. | 1004 | chan_type = cfg80211_get_chandef_type(&sc->hw->conf.chandef); |
| 1001 | * Note that we only support HT20 for now. | 1005 | if ((chan_type == NL80211_CHAN_HT40MINUS) || |
| 1002 | * | 1006 | (chan_type == NL80211_CHAN_HT40PLUS)) { |
| 1003 | * TODO: add HT20_40 support as well. | 1007 | fft_len = SPECTRAL_HT20_40_TOTAL_DATA_LEN; |
| 1004 | */ | 1008 | num_bins = SPECTRAL_HT20_40_NUM_BINS; |
| 1005 | if ((len > SPECTRAL_HT20_TOTAL_DATA_LEN + 2) || | 1009 | bins = (u8 *)fft_sample_40.data; |
| 1006 | (len < SPECTRAL_HT20_TOTAL_DATA_LEN - 1)) | 1010 | } else { |
| 1007 | return 1; | 1011 | fft_len = SPECTRAL_HT20_TOTAL_DATA_LEN; |
| 1008 | 1012 | num_bins = SPECTRAL_HT20_NUM_BINS; | |
| 1009 | fft_sample.tlv.type = ATH_FFT_SAMPLE_HT20; | 1013 | bins = (u8 *)fft_sample_20.data; |
| 1010 | length = sizeof(fft_sample) - sizeof(fft_sample.tlv); | 1014 | } |
| 1011 | fft_sample.tlv.length = __cpu_to_be16(length); | ||
| 1012 | 1015 | ||
| 1013 | fft_sample.freq = __cpu_to_be16(ah->curchan->chan->center_freq); | 1016 | /* Variation in the data length is possible and will be fixed later */ |
| 1014 | fft_sample.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0); | 1017 | if ((len > fft_len + 2) || (len < fft_len - 1)) |
| 1015 | fft_sample.noise = ah->noise; | 1018 | return 1; |
| 1016 | 1019 | ||
| 1017 | switch (len - SPECTRAL_HT20_TOTAL_DATA_LEN) { | 1020 | switch (len - fft_len) { |
| 1018 | case 0: | 1021 | case 0: |
| 1019 | /* length correct, nothing to do. */ | 1022 | /* length correct, nothing to do. */ |
| 1020 | memcpy(bins, vdata, SPECTRAL_HT20_NUM_BINS); | 1023 | memcpy(bins, vdata, num_bins); |
| 1021 | break; | 1024 | break; |
| 1022 | case -1: | 1025 | case -1: |
| 1023 | /* first byte missing, duplicate it. */ | 1026 | /* first byte missing, duplicate it. */ |
| 1024 | memcpy(&bins[1], vdata, SPECTRAL_HT20_NUM_BINS - 1); | 1027 | memcpy(&bins[1], vdata, num_bins - 1); |
| 1025 | bins[0] = vdata[0]; | 1028 | bins[0] = vdata[0]; |
| 1026 | break; | 1029 | break; |
| 1027 | case 2: | 1030 | case 2: |
| 1028 | /* MAC added 2 extra bytes at bin 30 and 32, remove them. */ | 1031 | /* MAC added 2 extra bytes at bin 30 and 32, remove them. */ |
| 1029 | memcpy(bins, vdata, 30); | 1032 | memcpy(bins, vdata, 30); |
| 1030 | bins[30] = vdata[31]; | 1033 | bins[30] = vdata[31]; |
| 1031 | memcpy(&bins[31], &vdata[33], SPECTRAL_HT20_NUM_BINS - 31); | 1034 | memcpy(&bins[31], &vdata[33], num_bins - 31); |
| 1032 | break; | 1035 | break; |
| 1033 | case 1: | 1036 | case 1: |
| 1034 | /* MAC added 2 extra bytes AND first byte is missing. */ | 1037 | /* MAC added 2 extra bytes AND first byte is missing. */ |
| 1035 | bins[0] = vdata[0]; | 1038 | bins[0] = vdata[0]; |
| 1036 | memcpy(&bins[0], vdata, 30); | 1039 | memcpy(&bins[1], vdata, 30); |
| 1037 | bins[31] = vdata[31]; | 1040 | bins[31] = vdata[31]; |
| 1038 | memcpy(&bins[32], &vdata[33], SPECTRAL_HT20_NUM_BINS - 32); | 1041 | memcpy(&bins[32], &vdata[33], num_bins - 32); |
| 1039 | break; | 1042 | break; |
| 1040 | default: | 1043 | default: |
| 1041 | return 1; | 1044 | return 1; |
| @@ -1044,23 +1047,93 @@ static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, | |||
| 1044 | /* DC value (value in the middle) is the blind spot of the spectral | 1047 | /* DC value (value in the middle) is the blind spot of the spectral |
| 1045 | * sample and invalid, interpolate it. | 1048 | * sample and invalid, interpolate it. |
| 1046 | */ | 1049 | */ |
| 1047 | dc_pos = SPECTRAL_HT20_NUM_BINS / 2; | 1050 | dc_pos = num_bins / 2; |
| 1048 | bins[dc_pos] = (bins[dc_pos + 1] + bins[dc_pos - 1]) / 2; | 1051 | bins[dc_pos] = (bins[dc_pos + 1] + bins[dc_pos - 1]) / 2; |
| 1049 | 1052 | ||
| 1050 | /* mag data is at the end of the frame, in front of radar_info */ | 1053 | if ((chan_type == NL80211_CHAN_HT40MINUS) || |
| 1051 | mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1; | 1054 | (chan_type == NL80211_CHAN_HT40PLUS)) { |
| 1055 | s8 lower_rssi, upper_rssi; | ||
| 1056 | s16 ext_nf; | ||
| 1057 | u8 lower_max_index, upper_max_index; | ||
| 1058 | u8 lower_bitmap_w, upper_bitmap_w; | ||
| 1059 | u16 lower_mag, upper_mag; | ||
| 1060 | struct ath9k_hw_cal_data *caldata = ah->caldata; | ||
| 1061 | struct ath_ht20_40_mag_info *mag_info; | ||
| 1062 | |||
| 1063 | if (caldata) | ||
| 1064 | ext_nf = ath9k_hw_getchan_noise(ah, ah->curchan, | ||
| 1065 | caldata->nfCalHist[3].privNF); | ||
| 1066 | else | ||
| 1067 | ext_nf = ATH_DEFAULT_NOISE_FLOOR; | ||
| 1068 | |||
| 1069 | length = sizeof(fft_sample_40) - sizeof(struct fft_sample_tlv); | ||
| 1070 | fft_sample_40.tlv.type = ATH_FFT_SAMPLE_HT20_40; | ||
| 1071 | fft_sample_40.tlv.length = __cpu_to_be16(length); | ||
| 1072 | fft_sample_40.freq = __cpu_to_be16(freq); | ||
| 1073 | fft_sample_40.channel_type = chan_type; | ||
| 1074 | |||
| 1075 | if (chan_type == NL80211_CHAN_HT40PLUS) { | ||
| 1076 | lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0); | ||
| 1077 | upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ext0); | ||
| 1052 | 1078 | ||
| 1053 | /* copy raw bins without scaling them */ | 1079 | fft_sample_40.lower_noise = ah->noise; |
| 1054 | memcpy(fft_sample.data, bins, SPECTRAL_HT20_NUM_BINS); | 1080 | fft_sample_40.upper_noise = ext_nf; |
| 1055 | fft_sample.max_exp = mag_info->max_exp & 0xf; | 1081 | } else { |
| 1082 | lower_rssi = fix_rssi_inv_only(rs->rs_rssi_ext0); | ||
| 1083 | upper_rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0); | ||
| 1056 | 1084 | ||
| 1057 | max_magnitude = spectral_max_magnitude(mag_info->all_bins); | 1085 | fft_sample_40.lower_noise = ext_nf; |
| 1058 | fft_sample.max_magnitude = __cpu_to_be16(max_magnitude); | 1086 | fft_sample_40.upper_noise = ah->noise; |
| 1059 | fft_sample.max_index = spectral_max_index(mag_info->all_bins); | 1087 | } |
| 1060 | fft_sample.bitmap_weight = spectral_bitmap_weight(mag_info->all_bins); | 1088 | fft_sample_40.lower_rssi = lower_rssi; |
| 1061 | fft_sample.tsf = __cpu_to_be64(tsf); | 1089 | fft_sample_40.upper_rssi = upper_rssi; |
| 1090 | |||
| 1091 | mag_info = ((struct ath_ht20_40_mag_info *)radar_info) - 1; | ||
| 1092 | lower_mag = spectral_max_magnitude(mag_info->lower_bins); | ||
| 1093 | upper_mag = spectral_max_magnitude(mag_info->upper_bins); | ||
| 1094 | fft_sample_40.lower_max_magnitude = __cpu_to_be16(lower_mag); | ||
| 1095 | fft_sample_40.upper_max_magnitude = __cpu_to_be16(upper_mag); | ||
| 1096 | lower_max_index = spectral_max_index(mag_info->lower_bins); | ||
| 1097 | upper_max_index = spectral_max_index(mag_info->upper_bins); | ||
| 1098 | fft_sample_40.lower_max_index = lower_max_index; | ||
| 1099 | fft_sample_40.upper_max_index = upper_max_index; | ||
| 1100 | lower_bitmap_w = spectral_bitmap_weight(mag_info->lower_bins); | ||
| 1101 | upper_bitmap_w = spectral_bitmap_weight(mag_info->upper_bins); | ||
| 1102 | fft_sample_40.lower_bitmap_weight = lower_bitmap_w; | ||
| 1103 | fft_sample_40.upper_bitmap_weight = upper_bitmap_w; | ||
| 1104 | fft_sample_40.max_exp = mag_info->max_exp & 0xf; | ||
| 1105 | |||
| 1106 | fft_sample_40.tsf = __cpu_to_be64(tsf); | ||
| 1107 | |||
| 1108 | tlv = (struct fft_sample_tlv *)&fft_sample_40; | ||
| 1109 | } else { | ||
| 1110 | u8 max_index, bitmap_w; | ||
| 1111 | u16 magnitude; | ||
| 1112 | struct ath_ht20_mag_info *mag_info; | ||
| 1113 | |||
| 1114 | length = sizeof(fft_sample_20) - sizeof(struct fft_sample_tlv); | ||
| 1115 | fft_sample_20.tlv.type = ATH_FFT_SAMPLE_HT20; | ||
| 1116 | fft_sample_20.tlv.length = __cpu_to_be16(length); | ||
| 1117 | fft_sample_20.freq = __cpu_to_be16(freq); | ||
| 1118 | |||
| 1119 | fft_sample_20.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0); | ||
| 1120 | fft_sample_20.noise = ah->noise; | ||
| 1121 | |||
| 1122 | mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1; | ||
| 1123 | magnitude = spectral_max_magnitude(mag_info->all_bins); | ||
| 1124 | fft_sample_20.max_magnitude = __cpu_to_be16(magnitude); | ||
| 1125 | max_index = spectral_max_index(mag_info->all_bins); | ||
| 1126 | fft_sample_20.max_index = max_index; | ||
| 1127 | bitmap_w = spectral_bitmap_weight(mag_info->all_bins); | ||
| 1128 | fft_sample_20.bitmap_weight = bitmap_w; | ||
| 1129 | fft_sample_20.max_exp = mag_info->max_exp & 0xf; | ||
| 1130 | |||
| 1131 | fft_sample_20.tsf = __cpu_to_be64(tsf); | ||
| 1132 | |||
| 1133 | tlv = (struct fft_sample_tlv *)&fft_sample_20; | ||
| 1134 | } | ||
| 1062 | 1135 | ||
| 1063 | ath_debug_send_fft_sample(sc, &fft_sample.tlv); | 1136 | ath_debug_send_fft_sample(sc, tlv); |
| 1064 | return 1; | 1137 | return 1; |
| 1065 | #else | 1138 | #else |
| 1066 | return 0; | 1139 | return 0; |
| @@ -1308,7 +1381,7 @@ static void ath9k_apply_ampdu_details(struct ath_softc *sc, | |||
| 1308 | 1381 | ||
| 1309 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | 1382 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) |
| 1310 | { | 1383 | { |
| 1311 | struct ath_buf *bf; | 1384 | struct ath_rxbuf *bf; |
| 1312 | struct sk_buff *skb = NULL, *requeue_skb, *hdr_skb; | 1385 | struct sk_buff *skb = NULL, *requeue_skb, *hdr_skb; |
| 1313 | struct ieee80211_rx_status *rxs; | 1386 | struct ieee80211_rx_status *rxs; |
| 1314 | struct ath_hw *ah = sc->sc_ah; | 1387 | struct ath_hw *ah = sc->sc_ah; |
diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index fde6da619f30..0db37f230018 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h | |||
| @@ -39,7 +39,7 @@ struct wmi_fw_version { | |||
| 39 | struct wmi_event_swba { | 39 | struct wmi_event_swba { |
| 40 | __be64 tsf; | 40 | __be64 tsf; |
| 41 | u8 beacon_pending; | 41 | u8 beacon_pending; |
| 42 | }; | 42 | } __packed; |
| 43 | 43 | ||
| 44 | /* | 44 | /* |
| 45 | * 64 - HTC header - WMI header - 1 / txstatus | 45 | * 64 - HTC header - WMI header - 1 / txstatus |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index dd30452df966..09cdbcd09739 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
| @@ -1241,12 +1241,13 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf, | |||
| 1241 | if (bf->bf_next) | 1241 | if (bf->bf_next) |
| 1242 | info.link = bf->bf_next->bf_daddr; | 1242 | info.link = bf->bf_next->bf_daddr; |
| 1243 | else | 1243 | else |
| 1244 | info.link = 0; | 1244 | info.link = (sc->tx99_state) ? bf->bf_daddr : 0; |
| 1245 | 1245 | ||
| 1246 | if (!bf_first) { | 1246 | if (!bf_first) { |
| 1247 | bf_first = bf; | 1247 | bf_first = bf; |
| 1248 | 1248 | ||
| 1249 | info.flags = ATH9K_TXDESC_INTREQ; | 1249 | if (!sc->tx99_state) |
| 1250 | info.flags = ATH9K_TXDESC_INTREQ; | ||
| 1250 | if ((tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) || | 1251 | if ((tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) || |
| 1251 | txq == sc->tx.uapsdq) | 1252 | txq == sc->tx.uapsdq) |
| 1252 | info.flags |= ATH9K_TXDESC_CLRDMASK; | 1253 | info.flags |= ATH9K_TXDESC_CLRDMASK; |
| @@ -1704,16 +1705,9 @@ int ath_cabq_update(struct ath_softc *sc) | |||
| 1704 | int qnum = sc->beacon.cabq->axq_qnum; | 1705 | int qnum = sc->beacon.cabq->axq_qnum; |
| 1705 | 1706 | ||
| 1706 | ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi); | 1707 | ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi); |
| 1707 | /* | ||
| 1708 | * Ensure the readytime % is within the bounds. | ||
| 1709 | */ | ||
| 1710 | if (sc->config.cabqReadytime < ATH9K_READY_TIME_LO_BOUND) | ||
| 1711 | sc->config.cabqReadytime = ATH9K_READY_TIME_LO_BOUND; | ||
| 1712 | else if (sc->config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND) | ||
| 1713 | sc->config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND; | ||
| 1714 | 1708 | ||
| 1715 | qi.tqi_readyTime = (cur_conf->beacon_interval * | 1709 | qi.tqi_readyTime = (cur_conf->beacon_interval * |
| 1716 | sc->config.cabqReadytime) / 100; | 1710 | ATH_CABQ_READY_TIME) / 100; |
| 1717 | ath_txq_update(sc, qnum, &qi); | 1711 | ath_txq_update(sc, qnum, &qi); |
| 1718 | 1712 | ||
| 1719 | return 0; | 1713 | return 0; |
| @@ -1948,7 +1942,7 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, | |||
| 1948 | txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc); | 1942 | txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc); |
| 1949 | } | 1943 | } |
| 1950 | 1944 | ||
| 1951 | if (!edma) { | 1945 | if (!edma || sc->tx99_state) { |
| 1952 | TX_STAT_INC(txq->axq_qnum, txstart); | 1946 | TX_STAT_INC(txq->axq_qnum, txstart); |
| 1953 | ath9k_hw_txstart(ah, txq->axq_qnum); | 1947 | ath9k_hw_txstart(ah, txq->axq_qnum); |
| 1954 | } | 1948 | } |
| @@ -2027,6 +2021,9 @@ static void setup_frame_info(struct ieee80211_hw *hw, | |||
| 2027 | fi->keyix = ATH9K_TXKEYIX_INVALID; | 2021 | fi->keyix = ATH9K_TXKEYIX_INVALID; |
| 2028 | fi->keytype = keytype; | 2022 | fi->keytype = keytype; |
| 2029 | fi->framelen = framelen; | 2023 | fi->framelen = framelen; |
| 2024 | |||
| 2025 | if (!rate) | ||
| 2026 | return; | ||
| 2030 | fi->rtscts_rate = rate->hw_value; | 2027 | fi->rtscts_rate = rate->hw_value; |
| 2031 | if (short_preamble) | 2028 | if (short_preamble) |
| 2032 | fi->rtscts_rate |= rate->hw_value_short; | 2029 | fi->rtscts_rate |= rate->hw_value_short; |
| @@ -2037,8 +2034,7 @@ u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate) | |||
| 2037 | struct ath_hw *ah = sc->sc_ah; | 2034 | struct ath_hw *ah = sc->sc_ah; |
| 2038 | struct ath9k_channel *curchan = ah->curchan; | 2035 | struct ath9k_channel *curchan = ah->curchan; |
| 2039 | 2036 | ||
| 2040 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && | 2037 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && IS_CHAN_5GHZ(curchan) && |
| 2041 | (curchan->channelFlags & CHANNEL_5GHZ) && | ||
| 2042 | (chainmask == 0x7) && (rate < 0x90)) | 2038 | (chainmask == 0x7) && (rate < 0x90)) |
| 2043 | return 0x3; | 2039 | return 0x3; |
| 2044 | else if (AR_SREV_9462(ah) && ath9k_hw_btcoex_is_enabled(ah) && | 2040 | else if (AR_SREV_9462(ah) && ath9k_hw_btcoex_is_enabled(ah) && |
| @@ -2329,7 +2325,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
| 2329 | ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb); | 2325 | ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb); |
| 2330 | 2326 | ||
| 2331 | if (sc->sc_ah->caldata) | 2327 | if (sc->sc_ah->caldata) |
| 2332 | sc->sc_ah->caldata->paprd_packet_sent = true; | 2328 | set_bit(PAPRD_PACKET_SENT, &sc->sc_ah->caldata->cal_flags); |
| 2333 | 2329 | ||
| 2334 | if (!(tx_flags & ATH_TX_ERROR)) | 2330 | if (!(tx_flags & ATH_TX_ERROR)) |
| 2335 | /* Frame was ACKed */ | 2331 | /* Frame was ACKed */ |
| @@ -2379,6 +2375,8 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | |||
| 2379 | 2375 | ||
| 2380 | dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE); | 2376 | dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE); |
| 2381 | bf->bf_buf_addr = 0; | 2377 | bf->bf_buf_addr = 0; |
| 2378 | if (sc->tx99_state) | ||
| 2379 | goto skip_tx_complete; | ||
| 2382 | 2380 | ||
| 2383 | if (bf->bf_state.bfs_paprd) { | 2381 | if (bf->bf_state.bfs_paprd) { |
| 2384 | if (time_after(jiffies, | 2382 | if (time_after(jiffies, |
| @@ -2391,6 +2389,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | |||
| 2391 | ath_debug_stat_tx(sc, bf, ts, txq, tx_flags); | 2389 | ath_debug_stat_tx(sc, bf, ts, txq, tx_flags); |
| 2392 | ath_tx_complete(sc, skb, tx_flags, txq); | 2390 | ath_tx_complete(sc, skb, tx_flags, txq); |
| 2393 | } | 2391 | } |
| 2392 | skip_tx_complete: | ||
| 2394 | /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't | 2393 | /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't |
| 2395 | * accidentally reference it later. | 2394 | * accidentally reference it later. |
| 2396 | */ | 2395 | */ |
| @@ -2749,3 +2748,46 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) | |||
| 2749 | ath_txq_unlock(sc, txq); | 2748 | ath_txq_unlock(sc, txq); |
| 2750 | } | 2749 | } |
| 2751 | } | 2750 | } |
| 2751 | |||
| 2752 | int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb, | ||
| 2753 | struct ath_tx_control *txctl) | ||
| 2754 | { | ||
| 2755 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
| 2756 | struct ath_frame_info *fi = get_frame_info(skb); | ||
| 2757 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
| 2758 | struct ath_buf *bf; | ||
| 2759 | int padpos, padsize; | ||
| 2760 | |||
| 2761 | padpos = ieee80211_hdrlen(hdr->frame_control); | ||
| 2762 | padsize = padpos & 3; | ||
| 2763 | |||
| 2764 | if (padsize && skb->len > padpos) { | ||
| 2765 | if (skb_headroom(skb) < padsize) { | ||
| 2766 | ath_dbg(common, XMIT, | ||
| 2767 | "tx99 padding failed\n"); | ||
| 2768 | return -EINVAL; | ||
| 2769 | } | ||
| 2770 | |||
| 2771 | skb_push(skb, padsize); | ||
| 2772 | memmove(skb->data, skb->data + padsize, padpos); | ||
| 2773 | } | ||
| 2774 | |||
| 2775 | fi->keyix = ATH9K_TXKEYIX_INVALID; | ||
| 2776 | fi->framelen = skb->len + FCS_LEN; | ||
| 2777 | fi->keytype = ATH9K_KEY_TYPE_CLEAR; | ||
| 2778 | |||
| 2779 | bf = ath_tx_setup_buffer(sc, txctl->txq, NULL, skb); | ||
| 2780 | if (!bf) { | ||
| 2781 | ath_dbg(common, XMIT, "tx99 buffer setup failed\n"); | ||
| 2782 | return -EINVAL; | ||
| 2783 | } | ||
| 2784 | |||
| 2785 | ath_set_rates(sc->tx99_vif, NULL, bf); | ||
| 2786 | |||
| 2787 | ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, bf->bf_daddr); | ||
| 2788 | ath9k_hw_tx99_start(sc->sc_ah, txctl->txq->axq_qnum); | ||
| 2789 | |||
| 2790 | ath_tx_send_normal(sc, txctl->txq, NULL, skb); | ||
| 2791 | |||
| 2792 | return 0; | ||
| 2793 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c b/drivers/net/wireless/ath/dfs_pattern_detector.c index 491305c81fce..a1a69c5db409 100644 --- a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c +++ b/drivers/net/wireless/ath/dfs_pattern_detector.c | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | 19 | ||
| 20 | #include "dfs_pattern_detector.h" | 20 | #include "dfs_pattern_detector.h" |
| 21 | #include "dfs_pri_detector.h" | 21 | #include "dfs_pri_detector.h" |
| 22 | #include "ath9k.h" | 22 | #include "ath.h" |
| 23 | 23 | ||
| 24 | /* | 24 | /* |
| 25 | * tolerated deviation of radar time stamp in usecs on both sides | 25 | * tolerated deviation of radar time stamp in usecs on both sides |
| @@ -143,7 +143,6 @@ channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq) | |||
| 143 | { | 143 | { |
| 144 | u32 sz, i; | 144 | u32 sz, i; |
| 145 | struct channel_detector *cd; | 145 | struct channel_detector *cd; |
| 146 | struct ath_common *common = ath9k_hw_common(dpd->ah); | ||
| 147 | 146 | ||
| 148 | cd = kmalloc(sizeof(*cd), GFP_ATOMIC); | 147 | cd = kmalloc(sizeof(*cd), GFP_ATOMIC); |
| 149 | if (cd == NULL) | 148 | if (cd == NULL) |
| @@ -167,7 +166,7 @@ channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq) | |||
| 167 | return cd; | 166 | return cd; |
| 168 | 167 | ||
| 169 | fail: | 168 | fail: |
| 170 | ath_dbg(common, DFS, | 169 | ath_dbg(dpd->common, DFS, |
| 171 | "failed to allocate channel_detector for freq=%d\n", freq); | 170 | "failed to allocate channel_detector for freq=%d\n", freq); |
| 172 | channel_detector_exit(dpd, cd); | 171 | channel_detector_exit(dpd, cd); |
| 173 | return NULL; | 172 | return NULL; |
| @@ -242,7 +241,7 @@ dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event) | |||
| 242 | struct pri_detector *pd = cd->detectors[i]; | 241 | struct pri_detector *pd = cd->detectors[i]; |
| 243 | struct pri_sequence *ps = pd->add_pulse(pd, event); | 242 | struct pri_sequence *ps = pd->add_pulse(pd, event); |
| 244 | if (ps != NULL) { | 243 | if (ps != NULL) { |
| 245 | ath_dbg(ath9k_hw_common(dpd->ah), DFS, | 244 | ath_dbg(dpd->common, DFS, |
| 246 | "DFS: radar found on freq=%d: id=%d, pri=%d, " | 245 | "DFS: radar found on freq=%d: id=%d, pri=%d, " |
| 247 | "count=%d, count_false=%d\n", | 246 | "count=%d, count_false=%d\n", |
| 248 | event->freq, pd->rs->type_id, | 247 | event->freq, pd->rs->type_id, |
| @@ -254,6 +253,12 @@ dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event) | |||
| 254 | return false; | 253 | return false; |
| 255 | } | 254 | } |
| 256 | 255 | ||
| 256 | static struct ath_dfs_pool_stats | ||
| 257 | dpd_get_stats(struct dfs_pattern_detector *dpd) | ||
| 258 | { | ||
| 259 | return global_dfs_pool_stats; | ||
| 260 | } | ||
| 261 | |||
| 257 | static bool dpd_set_domain(struct dfs_pattern_detector *dpd, | 262 | static bool dpd_set_domain(struct dfs_pattern_detector *dpd, |
| 258 | enum nl80211_dfs_regions region) | 263 | enum nl80211_dfs_regions region) |
| 259 | { | 264 | { |
| @@ -284,14 +289,18 @@ static struct dfs_pattern_detector default_dpd = { | |||
| 284 | .exit = dpd_exit, | 289 | .exit = dpd_exit, |
| 285 | .set_dfs_domain = dpd_set_domain, | 290 | .set_dfs_domain = dpd_set_domain, |
| 286 | .add_pulse = dpd_add_pulse, | 291 | .add_pulse = dpd_add_pulse, |
| 292 | .get_stats = dpd_get_stats, | ||
| 287 | .region = NL80211_DFS_UNSET, | 293 | .region = NL80211_DFS_UNSET, |
| 288 | }; | 294 | }; |
| 289 | 295 | ||
| 290 | struct dfs_pattern_detector * | 296 | struct dfs_pattern_detector * |
| 291 | dfs_pattern_detector_init(struct ath_hw *ah, enum nl80211_dfs_regions region) | 297 | dfs_pattern_detector_init(struct ath_common *common, |
| 298 | enum nl80211_dfs_regions region) | ||
| 292 | { | 299 | { |
| 293 | struct dfs_pattern_detector *dpd; | 300 | struct dfs_pattern_detector *dpd; |
| 294 | struct ath_common *common = ath9k_hw_common(ah); | 301 | |
| 302 | if (!config_enabled(CONFIG_CFG80211_CERTIFICATION_ONUS)) | ||
| 303 | return NULL; | ||
| 295 | 304 | ||
| 296 | dpd = kmalloc(sizeof(*dpd), GFP_KERNEL); | 305 | dpd = kmalloc(sizeof(*dpd), GFP_KERNEL); |
| 297 | if (dpd == NULL) | 306 | if (dpd == NULL) |
| @@ -300,7 +309,7 @@ dfs_pattern_detector_init(struct ath_hw *ah, enum nl80211_dfs_regions region) | |||
| 300 | *dpd = default_dpd; | 309 | *dpd = default_dpd; |
| 301 | INIT_LIST_HEAD(&dpd->channel_detectors); | 310 | INIT_LIST_HEAD(&dpd->channel_detectors); |
| 302 | 311 | ||
| 303 | dpd->ah = ah; | 312 | dpd->common = common; |
| 304 | if (dpd->set_dfs_domain(dpd, region)) | 313 | if (dpd->set_dfs_domain(dpd, region)) |
| 305 | return dpd; | 314 | return dpd; |
| 306 | 315 | ||
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h b/drivers/net/wireless/ath/dfs_pattern_detector.h index 90a5abcc4265..dde2652b787c 100644 --- a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h +++ b/drivers/net/wireless/ath/dfs_pattern_detector.h | |||
| @@ -22,6 +22,19 @@ | |||
| 22 | #include <linux/nl80211.h> | 22 | #include <linux/nl80211.h> |
| 23 | 23 | ||
| 24 | /** | 24 | /** |
| 25 | * struct ath_dfs_pool_stats - DFS Statistics for global pools | ||
| 26 | */ | ||
| 27 | struct ath_dfs_pool_stats { | ||
| 28 | u32 pool_reference; | ||
| 29 | u32 pulse_allocated; | ||
| 30 | u32 pulse_alloc_error; | ||
| 31 | u32 pulse_used; | ||
| 32 | u32 pseq_allocated; | ||
| 33 | u32 pseq_alloc_error; | ||
| 34 | u32 pseq_used; | ||
| 35 | }; | ||
| 36 | |||
| 37 | /** | ||
| 25 | * struct pulse_event - describing pulses reported by PHY | 38 | * struct pulse_event - describing pulses reported by PHY |
| 26 | * @ts: pulse time stamp in us | 39 | * @ts: pulse time stamp in us |
| 27 | * @freq: channel frequency in MHz | 40 | * @freq: channel frequency in MHz |
| @@ -77,11 +90,12 @@ struct dfs_pattern_detector { | |||
| 77 | bool (*add_pulse)(struct dfs_pattern_detector *dpd, | 90 | bool (*add_pulse)(struct dfs_pattern_detector *dpd, |
| 78 | struct pulse_event *pe); | 91 | struct pulse_event *pe); |
| 79 | 92 | ||
| 93 | struct ath_dfs_pool_stats (*get_stats)(struct dfs_pattern_detector *dpd); | ||
| 80 | enum nl80211_dfs_regions region; | 94 | enum nl80211_dfs_regions region; |
| 81 | u8 num_radar_types; | 95 | u8 num_radar_types; |
| 82 | u64 last_pulse_ts; | 96 | u64 last_pulse_ts; |
| 83 | /* needed for ath_dbg() */ | 97 | /* needed for ath_dbg() */ |
| 84 | struct ath_hw *ah; | 98 | struct ath_common *common; |
| 85 | 99 | ||
| 86 | const struct radar_detector_specs *radar_spec; | 100 | const struct radar_detector_specs *radar_spec; |
| 87 | struct list_head channel_detectors; | 101 | struct list_head channel_detectors; |
| @@ -92,15 +106,7 @@ struct dfs_pattern_detector { | |||
| 92 | * @param region: DFS domain to be used, can be NL80211_DFS_UNSET at creation | 106 | * @param region: DFS domain to be used, can be NL80211_DFS_UNSET at creation |
| 93 | * @return instance pointer on success, NULL otherwise | 107 | * @return instance pointer on success, NULL otherwise |
| 94 | */ | 108 | */ |
| 95 | #if defined(CONFIG_ATH9K_DFS_CERTIFIED) | ||
| 96 | extern struct dfs_pattern_detector * | 109 | extern struct dfs_pattern_detector * |
| 97 | dfs_pattern_detector_init(struct ath_hw *ah, enum nl80211_dfs_regions region); | 110 | dfs_pattern_detector_init(struct ath_common *common, |
| 98 | #else | 111 | enum nl80211_dfs_regions region); |
| 99 | static inline struct dfs_pattern_detector * | ||
| 100 | dfs_pattern_detector_init(struct ath_hw *ah, enum nl80211_dfs_regions region) | ||
| 101 | { | ||
| 102 | return NULL; | ||
| 103 | } | ||
| 104 | #endif /* CONFIG_ATH9K_DFS_CERTIFIED */ | ||
| 105 | |||
| 106 | #endif /* DFS_PATTERN_DETECTOR_H */ | 112 | #endif /* DFS_PATTERN_DETECTOR_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c b/drivers/net/wireless/ath/dfs_pri_detector.c index 5ba4b6fe37c0..43b608178884 100644 --- a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c +++ b/drivers/net/wireless/ath/dfs_pri_detector.c | |||
| @@ -17,10 +17,14 @@ | |||
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <linux/spinlock.h> | 18 | #include <linux/spinlock.h> |
| 19 | 19 | ||
| 20 | #include "ath9k.h" | 20 | #include "ath.h" |
| 21 | #include "dfs_pattern_detector.h" | 21 | #include "dfs_pattern_detector.h" |
| 22 | #include "dfs_pri_detector.h" | 22 | #include "dfs_pri_detector.h" |
| 23 | #include "dfs_debug.h" | 23 | |
| 24 | struct ath_dfs_pool_stats global_dfs_pool_stats = {}; | ||
| 25 | |||
| 26 | #define DFS_POOL_STAT_INC(c) (global_dfs_pool_stats.c++) | ||
| 27 | #define DFS_POOL_STAT_DEC(c) (global_dfs_pool_stats.c--) | ||
| 24 | 28 | ||
| 25 | /** | 29 | /** |
| 26 | * struct pulse_elem - elements in pulse queue | 30 | * struct pulse_elem - elements in pulse queue |
| @@ -392,7 +396,7 @@ static struct pri_sequence *pri_detector_add_pulse(struct pri_detector *de, | |||
| 392 | 396 | ||
| 393 | if (!pseq_handler_create_sequences(de, ts, max_updated_seq)) { | 397 | if (!pseq_handler_create_sequences(de, ts, max_updated_seq)) { |
| 394 | pri_detector_reset(de, ts); | 398 | pri_detector_reset(de, ts); |
| 395 | return false; | 399 | return NULL; |
| 396 | } | 400 | } |
| 397 | 401 | ||
| 398 | ps = pseq_handler_check_detection(de); | 402 | ps = pseq_handler_check_detection(de); |
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.h b/drivers/net/wireless/ath/dfs_pri_detector.h index 723962d1abc6..79f0fff4d1e6 100644 --- a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.h +++ b/drivers/net/wireless/ath/dfs_pri_detector.h | |||
| @@ -19,6 +19,8 @@ | |||
| 19 | 19 | ||
| 20 | #include <linux/list.h> | 20 | #include <linux/list.h> |
| 21 | 21 | ||
| 22 | extern struct ath_dfs_pool_stats global_dfs_pool_stats; | ||
| 23 | |||
| 22 | /** | 24 | /** |
| 23 | * struct pri_sequence - sequence of pulses matching one PRI | 25 | * struct pri_sequence - sequence of pulses matching one PRI |
| 24 | * @head: list_head | 26 | * @head: list_head |
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 7d077c752dd5..c00687e05688 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c | |||
| @@ -356,14 +356,131 @@ static u16 ath_regd_find_country_by_name(char *alpha2) | |||
| 356 | return -1; | 356 | return -1; |
| 357 | } | 357 | } |
| 358 | 358 | ||
| 359 | static int __ath_reg_dyn_country(struct wiphy *wiphy, | ||
| 360 | struct ath_regulatory *reg, | ||
| 361 | struct regulatory_request *request) | ||
| 362 | { | ||
| 363 | u16 country_code; | ||
| 364 | |||
| 365 | if (!ath_is_world_regd(reg)) | ||
| 366 | return -EINVAL; | ||
| 367 | |||
| 368 | country_code = ath_regd_find_country_by_name(request->alpha2); | ||
| 369 | if (country_code == (u16) -1) | ||
| 370 | return -EINVAL; | ||
| 371 | |||
| 372 | reg->current_rd = COUNTRY_ERD_FLAG; | ||
| 373 | reg->current_rd |= country_code; | ||
| 374 | |||
| 375 | __ath_regd_init(reg); | ||
| 376 | |||
| 377 | ath_reg_apply_world_flags(wiphy, request->initiator, reg); | ||
| 378 | |||
| 379 | return 0; | ||
| 380 | } | ||
| 381 | |||
| 382 | static void ath_reg_dyn_country(struct wiphy *wiphy, | ||
| 383 | struct ath_regulatory *reg, | ||
| 384 | struct regulatory_request *request) | ||
| 385 | { | ||
| 386 | if (__ath_reg_dyn_country(wiphy, reg, request)) | ||
| 387 | return; | ||
| 388 | |||
| 389 | printk(KERN_DEBUG "ath: regdomain 0x%0x " | ||
| 390 | "dynamically updated by %s\n", | ||
| 391 | reg->current_rd, | ||
| 392 | reg_initiator_name(request->initiator)); | ||
| 393 | } | ||
| 394 | |||
| 395 | static bool dynamic_country_user_possible(struct ath_regulatory *reg) | ||
| 396 | { | ||
| 397 | if (config_enabled(CONFIG_ATH_REG_DYNAMIC_USER_CERT_TESTING)) | ||
| 398 | return true; | ||
| 399 | |||
| 400 | switch (reg->country_code) { | ||
| 401 | case CTRY_UNITED_STATES: | ||
| 402 | case CTRY_JAPAN1: | ||
| 403 | case CTRY_JAPAN2: | ||
| 404 | case CTRY_JAPAN3: | ||
| 405 | case CTRY_JAPAN4: | ||
| 406 | case CTRY_JAPAN5: | ||
| 407 | case CTRY_JAPAN6: | ||
| 408 | case CTRY_JAPAN7: | ||
| 409 | case CTRY_JAPAN8: | ||
| 410 | case CTRY_JAPAN9: | ||
| 411 | case CTRY_JAPAN10: | ||
| 412 | case CTRY_JAPAN11: | ||
| 413 | case CTRY_JAPAN12: | ||
| 414 | case CTRY_JAPAN13: | ||
| 415 | case CTRY_JAPAN14: | ||
| 416 | case CTRY_JAPAN15: | ||
| 417 | case CTRY_JAPAN16: | ||
| 418 | case CTRY_JAPAN17: | ||
| 419 | case CTRY_JAPAN18: | ||
| 420 | case CTRY_JAPAN19: | ||
| 421 | case CTRY_JAPAN20: | ||
| 422 | case CTRY_JAPAN21: | ||
| 423 | case CTRY_JAPAN22: | ||
| 424 | case CTRY_JAPAN23: | ||
| 425 | case CTRY_JAPAN24: | ||
| 426 | case CTRY_JAPAN25: | ||
| 427 | case CTRY_JAPAN26: | ||
| 428 | case CTRY_JAPAN27: | ||
| 429 | case CTRY_JAPAN28: | ||
| 430 | case CTRY_JAPAN29: | ||
| 431 | case CTRY_JAPAN30: | ||
| 432 | case CTRY_JAPAN31: | ||
| 433 | case CTRY_JAPAN32: | ||
| 434 | case CTRY_JAPAN33: | ||
| 435 | case CTRY_JAPAN34: | ||
| 436 | case CTRY_JAPAN35: | ||
| 437 | case CTRY_JAPAN36: | ||
| 438 | case CTRY_JAPAN37: | ||
| 439 | case CTRY_JAPAN38: | ||
| 440 | case CTRY_JAPAN39: | ||
| 441 | case CTRY_JAPAN40: | ||
| 442 | case CTRY_JAPAN41: | ||
| 443 | case CTRY_JAPAN42: | ||
| 444 | case CTRY_JAPAN43: | ||
| 445 | case CTRY_JAPAN44: | ||
| 446 | case CTRY_JAPAN45: | ||
| 447 | case CTRY_JAPAN46: | ||
| 448 | case CTRY_JAPAN47: | ||
| 449 | case CTRY_JAPAN48: | ||
| 450 | case CTRY_JAPAN49: | ||
| 451 | case CTRY_JAPAN50: | ||
| 452 | case CTRY_JAPAN51: | ||
| 453 | case CTRY_JAPAN52: | ||
| 454 | case CTRY_JAPAN53: | ||
| 455 | case CTRY_JAPAN54: | ||
| 456 | case CTRY_JAPAN55: | ||
| 457 | case CTRY_JAPAN56: | ||
| 458 | case CTRY_JAPAN57: | ||
| 459 | case CTRY_JAPAN58: | ||
| 460 | case CTRY_JAPAN59: | ||
| 461 | return false; | ||
| 462 | } | ||
| 463 | |||
| 464 | return true; | ||
| 465 | } | ||
| 466 | |||
| 467 | static void ath_reg_dyn_country_user(struct wiphy *wiphy, | ||
| 468 | struct ath_regulatory *reg, | ||
| 469 | struct regulatory_request *request) | ||
| 470 | { | ||
| 471 | if (!config_enabled(CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS)) | ||
| 472 | return; | ||
| 473 | if (!dynamic_country_user_possible(reg)) | ||
| 474 | return; | ||
| 475 | ath_reg_dyn_country(wiphy, reg, request); | ||
| 476 | } | ||
| 477 | |||
| 359 | void ath_reg_notifier_apply(struct wiphy *wiphy, | 478 | void ath_reg_notifier_apply(struct wiphy *wiphy, |
| 360 | struct regulatory_request *request, | 479 | struct regulatory_request *request, |
| 361 | struct ath_regulatory *reg) | 480 | struct ath_regulatory *reg) |
| 362 | { | 481 | { |
| 363 | struct ath_common *common = container_of(reg, struct ath_common, | 482 | struct ath_common *common = container_of(reg, struct ath_common, |
| 364 | regulatory); | 483 | regulatory); |
| 365 | u16 country_code; | ||
| 366 | |||
| 367 | /* We always apply this */ | 484 | /* We always apply this */ |
| 368 | ath_reg_apply_radar_flags(wiphy); | 485 | ath_reg_apply_radar_flags(wiphy); |
| 369 | 486 | ||
| @@ -388,25 +505,12 @@ void ath_reg_notifier_apply(struct wiphy *wiphy, | |||
| 388 | sizeof(struct ath_regulatory)); | 505 | sizeof(struct ath_regulatory)); |
| 389 | break; | 506 | break; |
| 390 | case NL80211_REGDOM_SET_BY_DRIVER: | 507 | case NL80211_REGDOM_SET_BY_DRIVER: |
| 508 | break; | ||
| 391 | case NL80211_REGDOM_SET_BY_USER: | 509 | case NL80211_REGDOM_SET_BY_USER: |
| 510 | ath_reg_dyn_country_user(wiphy, reg, request); | ||
| 392 | break; | 511 | break; |
| 393 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: | 512 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: |
| 394 | if (!ath_is_world_regd(reg)) | 513 | ath_reg_dyn_country(wiphy, reg, request); |
| 395 | break; | ||
| 396 | |||
| 397 | country_code = ath_regd_find_country_by_name(request->alpha2); | ||
| 398 | if (country_code == (u16) -1) | ||
| 399 | break; | ||
| 400 | |||
| 401 | reg->current_rd = COUNTRY_ERD_FLAG; | ||
| 402 | reg->current_rd |= country_code; | ||
| 403 | |||
| 404 | printk(KERN_DEBUG "ath: regdomain 0x%0x updated by CountryIE\n", | ||
| 405 | reg->current_rd); | ||
| 406 | __ath_regd_init(reg); | ||
| 407 | |||
| 408 | ath_reg_apply_world_flags(wiphy, request->initiator, reg); | ||
| 409 | |||
| 410 | break; | 514 | break; |
| 411 | } | 515 | } |
| 412 | } | 516 | } |
diff --git a/drivers/net/wireless/ath/wcn36xx/Kconfig b/drivers/net/wireless/ath/wcn36xx/Kconfig new file mode 100644 index 000000000000..591ebaea8265 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/Kconfig | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | config WCN36XX | ||
| 2 | tristate "Qualcomm Atheros WCN3660/3680 support" | ||
| 3 | depends on MAC80211 && HAS_DMA | ||
| 4 | ---help--- | ||
| 5 | This module adds support for wireless adapters based on | ||
| 6 | Qualcomm Atheros WCN3660 and WCN3680 mobile chipsets. | ||
| 7 | |||
| 8 | If you choose to build a module, it'll be called wcn36xx. | ||
| 9 | |||
| 10 | config WCN36XX_DEBUGFS | ||
| 11 | bool "WCN36XX debugfs support" | ||
| 12 | depends on WCN36XX | ||
| 13 | ---help--- | ||
| 14 | Enabled debugfs support | ||
| 15 | |||
| 16 | If unsure, say Y to make it easier to debug problems. | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/Makefile b/drivers/net/wireless/ath/wcn36xx/Makefile new file mode 100644 index 000000000000..50c43b4382ba --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/Makefile | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | obj-$(CONFIG_WCN36XX) := wcn36xx.o | ||
| 2 | wcn36xx-y += main.o \ | ||
| 3 | dxe.o \ | ||
| 4 | txrx.o \ | ||
| 5 | smd.o \ | ||
| 6 | pmc.o \ | ||
| 7 | debug.o | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/debug.c b/drivers/net/wireless/ath/wcn36xx/debug.c new file mode 100644 index 000000000000..5b84f7ae0b1e --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/debug.c | |||
| @@ -0,0 +1,181 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 18 | |||
| 19 | #include <linux/debugfs.h> | ||
| 20 | #include <linux/uaccess.h> | ||
| 21 | #include "wcn36xx.h" | ||
| 22 | #include "debug.h" | ||
| 23 | #include "pmc.h" | ||
| 24 | |||
| 25 | #ifdef CONFIG_WCN36XX_DEBUGFS | ||
| 26 | |||
| 27 | static ssize_t read_file_bool_bmps(struct file *file, char __user *user_buf, | ||
| 28 | size_t count, loff_t *ppos) | ||
| 29 | { | ||
| 30 | struct wcn36xx *wcn = file->private_data; | ||
| 31 | struct wcn36xx_vif *vif_priv = NULL; | ||
| 32 | struct ieee80211_vif *vif = NULL; | ||
| 33 | char buf[3]; | ||
| 34 | |||
| 35 | list_for_each_entry(vif_priv, &wcn->vif_list, list) { | ||
| 36 | vif = container_of((void *)vif_priv, | ||
| 37 | struct ieee80211_vif, | ||
| 38 | drv_priv); | ||
| 39 | if (NL80211_IFTYPE_STATION == vif->type) { | ||
| 40 | if (vif_priv->pw_state == WCN36XX_BMPS) | ||
| 41 | buf[0] = '1'; | ||
| 42 | else | ||
| 43 | buf[0] = '0'; | ||
| 44 | break; | ||
| 45 | } | ||
| 46 | } | ||
| 47 | buf[1] = '\n'; | ||
| 48 | buf[2] = 0x00; | ||
| 49 | |||
| 50 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | ||
| 51 | } | ||
| 52 | |||
| 53 | static ssize_t write_file_bool_bmps(struct file *file, | ||
| 54 | const char __user *user_buf, | ||
| 55 | size_t count, loff_t *ppos) | ||
| 56 | { | ||
| 57 | struct wcn36xx *wcn = file->private_data; | ||
| 58 | struct wcn36xx_vif *vif_priv = NULL; | ||
| 59 | struct ieee80211_vif *vif = NULL; | ||
| 60 | |||
| 61 | char buf[32]; | ||
| 62 | int buf_size; | ||
| 63 | |||
| 64 | buf_size = min(count, (sizeof(buf)-1)); | ||
| 65 | if (copy_from_user(buf, user_buf, buf_size)) | ||
| 66 | return -EFAULT; | ||
| 67 | |||
| 68 | switch (buf[0]) { | ||
| 69 | case 'y': | ||
| 70 | case 'Y': | ||
| 71 | case '1': | ||
| 72 | list_for_each_entry(vif_priv, &wcn->vif_list, list) { | ||
| 73 | vif = container_of((void *)vif_priv, | ||
| 74 | struct ieee80211_vif, | ||
| 75 | drv_priv); | ||
| 76 | if (NL80211_IFTYPE_STATION == vif->type) { | ||
| 77 | wcn36xx_enable_keep_alive_null_packet(wcn, vif); | ||
| 78 | wcn36xx_pmc_enter_bmps_state(wcn, vif); | ||
| 79 | } | ||
| 80 | } | ||
| 81 | break; | ||
| 82 | case 'n': | ||
| 83 | case 'N': | ||
| 84 | case '0': | ||
| 85 | list_for_each_entry(vif_priv, &wcn->vif_list, list) { | ||
| 86 | vif = container_of((void *)vif_priv, | ||
| 87 | struct ieee80211_vif, | ||
| 88 | drv_priv); | ||
| 89 | if (NL80211_IFTYPE_STATION == vif->type) | ||
| 90 | wcn36xx_pmc_exit_bmps_state(wcn, vif); | ||
| 91 | } | ||
| 92 | break; | ||
| 93 | } | ||
| 94 | |||
| 95 | return count; | ||
| 96 | } | ||
| 97 | |||
| 98 | static const struct file_operations fops_wcn36xx_bmps = { | ||
| 99 | .open = simple_open, | ||
| 100 | .read = read_file_bool_bmps, | ||
| 101 | .write = write_file_bool_bmps, | ||
| 102 | }; | ||
| 103 | |||
| 104 | static ssize_t write_file_dump(struct file *file, | ||
| 105 | const char __user *user_buf, | ||
| 106 | size_t count, loff_t *ppos) | ||
| 107 | { | ||
| 108 | struct wcn36xx *wcn = file->private_data; | ||
| 109 | char buf[255], *tmp; | ||
| 110 | int buf_size; | ||
| 111 | u32 arg[WCN36xx_MAX_DUMP_ARGS]; | ||
| 112 | int i; | ||
| 113 | |||
| 114 | memset(buf, 0, sizeof(buf)); | ||
| 115 | memset(arg, 0, sizeof(arg)); | ||
| 116 | |||
| 117 | buf_size = min(count, (sizeof(buf) - 1)); | ||
| 118 | if (copy_from_user(buf, user_buf, buf_size)) | ||
| 119 | return -EFAULT; | ||
| 120 | |||
| 121 | tmp = buf; | ||
| 122 | |||
| 123 | for (i = 0; i < WCN36xx_MAX_DUMP_ARGS; i++) { | ||
| 124 | char *begin; | ||
| 125 | begin = strsep(&tmp, " "); | ||
| 126 | if (begin == NULL) | ||
| 127 | break; | ||
| 128 | |||
| 129 | if (kstrtoul(begin, 0, (unsigned long *)(arg + i)) != 0) | ||
| 130 | break; | ||
| 131 | } | ||
| 132 | |||
| 133 | wcn36xx_info("DUMP args is %d %d %d %d %d\n", arg[0], arg[1], arg[2], | ||
| 134 | arg[3], arg[4]); | ||
| 135 | wcn36xx_smd_dump_cmd_req(wcn, arg[0], arg[1], arg[2], arg[3], arg[4]); | ||
| 136 | |||
| 137 | return count; | ||
| 138 | } | ||
| 139 | |||
| 140 | static const struct file_operations fops_wcn36xx_dump = { | ||
| 141 | .open = simple_open, | ||
| 142 | .write = write_file_dump, | ||
| 143 | }; | ||
| 144 | |||
| 145 | #define ADD_FILE(name, mode, fop, priv_data) \ | ||
| 146 | do { \ | ||
| 147 | struct dentry *d; \ | ||
| 148 | d = debugfs_create_file(__stringify(name), \ | ||
| 149 | mode, dfs->rootdir, \ | ||
| 150 | priv_data, fop); \ | ||
| 151 | dfs->file_##name.dentry = d; \ | ||
| 152 | if (IS_ERR(d)) { \ | ||
| 153 | wcn36xx_warn("Create the debugfs entry failed");\ | ||
| 154 | dfs->file_##name.dentry = NULL; \ | ||
| 155 | } \ | ||
| 156 | } while (0) | ||
| 157 | |||
| 158 | |||
| 159 | void wcn36xx_debugfs_init(struct wcn36xx *wcn) | ||
| 160 | { | ||
| 161 | struct wcn36xx_dfs_entry *dfs = &wcn->dfs; | ||
| 162 | |||
| 163 | dfs->rootdir = debugfs_create_dir(KBUILD_MODNAME, | ||
| 164 | wcn->hw->wiphy->debugfsdir); | ||
| 165 | if (IS_ERR(dfs->rootdir)) { | ||
| 166 | wcn36xx_warn("Create the debugfs failed\n"); | ||
| 167 | dfs->rootdir = NULL; | ||
| 168 | } | ||
| 169 | |||
| 170 | ADD_FILE(bmps_switcher, S_IRUSR | S_IWUSR, | ||
| 171 | &fops_wcn36xx_bmps, wcn); | ||
| 172 | ADD_FILE(dump, S_IWUSR, &fops_wcn36xx_dump, wcn); | ||
| 173 | } | ||
| 174 | |||
| 175 | void wcn36xx_debugfs_exit(struct wcn36xx *wcn) | ||
| 176 | { | ||
| 177 | struct wcn36xx_dfs_entry *dfs = &wcn->dfs; | ||
| 178 | debugfs_remove_recursive(dfs->rootdir); | ||
| 179 | } | ||
| 180 | |||
| 181 | #endif /* CONFIG_WCN36XX_DEBUGFS */ | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/debug.h b/drivers/net/wireless/ath/wcn36xx/debug.h new file mode 100644 index 000000000000..46307aa562d3 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/debug.h | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef _WCN36XX_DEBUG_H_ | ||
| 18 | #define _WCN36XX_DEBUG_H_ | ||
| 19 | |||
| 20 | #include <linux/kernel.h> | ||
| 21 | |||
| 22 | #define WCN36xx_MAX_DUMP_ARGS 5 | ||
| 23 | |||
| 24 | #ifdef CONFIG_WCN36XX_DEBUGFS | ||
| 25 | struct wcn36xx_dfs_file { | ||
| 26 | struct dentry *dentry; | ||
| 27 | u32 value; | ||
| 28 | }; | ||
| 29 | |||
| 30 | struct wcn36xx_dfs_entry { | ||
| 31 | struct dentry *rootdir; | ||
| 32 | struct wcn36xx_dfs_file file_bmps_switcher; | ||
| 33 | struct wcn36xx_dfs_file file_dump; | ||
| 34 | }; | ||
| 35 | |||
| 36 | void wcn36xx_debugfs_init(struct wcn36xx *wcn); | ||
| 37 | void wcn36xx_debugfs_exit(struct wcn36xx *wcn); | ||
| 38 | |||
| 39 | #else | ||
| 40 | static inline void wcn36xx_debugfs_init(struct wcn36xx *wcn) | ||
| 41 | { | ||
| 42 | } | ||
| 43 | static inline void wcn36xx_debugfs_exit(struct wcn36xx *wcn) | ||
| 44 | { | ||
| 45 | } | ||
| 46 | |||
| 47 | #endif /* CONFIG_WCN36XX_DEBUGFS */ | ||
| 48 | |||
| 49 | #endif /* _WCN36XX_DEBUG_H_ */ | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c new file mode 100644 index 000000000000..ee25786b4447 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c | |||
| @@ -0,0 +1,805 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | /* DXE - DMA transfer engine | ||
| 18 | * we have 2 channels(High prio and Low prio) for TX and 2 channels for RX. | ||
| 19 | * through low channels data packets are transfered | ||
| 20 | * through high channels managment packets are transfered | ||
| 21 | */ | ||
| 22 | |||
| 23 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 24 | |||
| 25 | #include <linux/interrupt.h> | ||
| 26 | #include "wcn36xx.h" | ||
| 27 | #include "txrx.h" | ||
| 28 | |||
| 29 | void *wcn36xx_dxe_get_next_bd(struct wcn36xx *wcn, bool is_low) | ||
| 30 | { | ||
| 31 | struct wcn36xx_dxe_ch *ch = is_low ? | ||
| 32 | &wcn->dxe_tx_l_ch : | ||
| 33 | &wcn->dxe_tx_h_ch; | ||
| 34 | |||
| 35 | return ch->head_blk_ctl->bd_cpu_addr; | ||
| 36 | } | ||
| 37 | |||
| 38 | static void wcn36xx_dxe_write_register(struct wcn36xx *wcn, int addr, int data) | ||
| 39 | { | ||
| 40 | wcn36xx_dbg(WCN36XX_DBG_DXE, | ||
| 41 | "wcn36xx_dxe_write_register: addr=%x, data=%x\n", | ||
| 42 | addr, data); | ||
| 43 | |||
| 44 | writel(data, wcn->mmio + addr); | ||
| 45 | } | ||
| 46 | |||
| 47 | static void wcn36xx_dxe_read_register(struct wcn36xx *wcn, int addr, int *data) | ||
| 48 | { | ||
| 49 | *data = readl(wcn->mmio + addr); | ||
| 50 | |||
| 51 | wcn36xx_dbg(WCN36XX_DBG_DXE, | ||
| 52 | "wcn36xx_dxe_read_register: addr=%x, data=%x\n", | ||
| 53 | addr, *data); | ||
| 54 | } | ||
| 55 | |||
| 56 | static void wcn36xx_dxe_free_ctl_block(struct wcn36xx_dxe_ch *ch) | ||
| 57 | { | ||
| 58 | struct wcn36xx_dxe_ctl *ctl = ch->head_blk_ctl, *next; | ||
| 59 | int i; | ||
| 60 | |||
| 61 | for (i = 0; i < ch->desc_num && ctl; i++) { | ||
| 62 | next = ctl->next; | ||
| 63 | kfree(ctl); | ||
| 64 | ctl = next; | ||
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 68 | static int wcn36xx_dxe_allocate_ctl_block(struct wcn36xx_dxe_ch *ch) | ||
| 69 | { | ||
| 70 | struct wcn36xx_dxe_ctl *prev_ctl = NULL; | ||
| 71 | struct wcn36xx_dxe_ctl *cur_ctl = NULL; | ||
| 72 | int i; | ||
| 73 | |||
| 74 | for (i = 0; i < ch->desc_num; i++) { | ||
| 75 | cur_ctl = kzalloc(sizeof(*cur_ctl), GFP_KERNEL); | ||
| 76 | if (!cur_ctl) | ||
| 77 | goto out_fail; | ||
| 78 | |||
| 79 | cur_ctl->ctl_blk_order = i; | ||
| 80 | if (i == 0) { | ||
| 81 | ch->head_blk_ctl = cur_ctl; | ||
| 82 | ch->tail_blk_ctl = cur_ctl; | ||
| 83 | } else if (ch->desc_num - 1 == i) { | ||
| 84 | prev_ctl->next = cur_ctl; | ||
| 85 | cur_ctl->next = ch->head_blk_ctl; | ||
| 86 | } else { | ||
| 87 | prev_ctl->next = cur_ctl; | ||
| 88 | } | ||
| 89 | prev_ctl = cur_ctl; | ||
| 90 | } | ||
| 91 | |||
| 92 | return 0; | ||
| 93 | |||
| 94 | out_fail: | ||
| 95 | wcn36xx_dxe_free_ctl_block(ch); | ||
| 96 | return -ENOMEM; | ||
| 97 | } | ||
| 98 | |||
| 99 | int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn) | ||
| 100 | { | ||
| 101 | int ret; | ||
| 102 | |||
| 103 | wcn->dxe_tx_l_ch.ch_type = WCN36XX_DXE_CH_TX_L; | ||
| 104 | wcn->dxe_tx_h_ch.ch_type = WCN36XX_DXE_CH_TX_H; | ||
| 105 | wcn->dxe_rx_l_ch.ch_type = WCN36XX_DXE_CH_RX_L; | ||
| 106 | wcn->dxe_rx_h_ch.ch_type = WCN36XX_DXE_CH_RX_H; | ||
| 107 | |||
| 108 | wcn->dxe_tx_l_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_TX_L; | ||
| 109 | wcn->dxe_tx_h_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_TX_H; | ||
| 110 | wcn->dxe_rx_l_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_RX_L; | ||
| 111 | wcn->dxe_rx_h_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_RX_H; | ||
| 112 | |||
| 113 | wcn->dxe_tx_l_ch.dxe_wq = WCN36XX_DXE_WQ_TX_L; | ||
| 114 | wcn->dxe_tx_h_ch.dxe_wq = WCN36XX_DXE_WQ_TX_H; | ||
| 115 | |||
| 116 | wcn->dxe_tx_l_ch.ctrl_bd = WCN36XX_DXE_CTRL_TX_L_BD; | ||
| 117 | wcn->dxe_tx_h_ch.ctrl_bd = WCN36XX_DXE_CTRL_TX_H_BD; | ||
| 118 | |||
| 119 | wcn->dxe_tx_l_ch.ctrl_skb = WCN36XX_DXE_CTRL_TX_L_SKB; | ||
| 120 | wcn->dxe_tx_h_ch.ctrl_skb = WCN36XX_DXE_CTRL_TX_H_SKB; | ||
| 121 | |||
| 122 | wcn->dxe_tx_l_ch.reg_ctrl = WCN36XX_DXE_REG_CTL_TX_L; | ||
| 123 | wcn->dxe_tx_h_ch.reg_ctrl = WCN36XX_DXE_REG_CTL_TX_H; | ||
| 124 | |||
| 125 | wcn->dxe_tx_l_ch.def_ctrl = WCN36XX_DXE_CH_DEFAULT_CTL_TX_L; | ||
| 126 | wcn->dxe_tx_h_ch.def_ctrl = WCN36XX_DXE_CH_DEFAULT_CTL_TX_H; | ||
| 127 | |||
| 128 | /* DXE control block allocation */ | ||
| 129 | ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_tx_l_ch); | ||
| 130 | if (ret) | ||
| 131 | goto out_err; | ||
| 132 | ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_tx_h_ch); | ||
| 133 | if (ret) | ||
| 134 | goto out_err; | ||
| 135 | ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_rx_l_ch); | ||
| 136 | if (ret) | ||
| 137 | goto out_err; | ||
| 138 | ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_rx_h_ch); | ||
| 139 | if (ret) | ||
| 140 | goto out_err; | ||
| 141 | |||
| 142 | /* Initialize SMSM state Clear TX Enable RING EMPTY STATE */ | ||
| 143 | ret = wcn->ctrl_ops->smsm_change_state( | ||
| 144 | WCN36XX_SMSM_WLAN_TX_ENABLE, | ||
| 145 | WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY); | ||
| 146 | |||
| 147 | return 0; | ||
| 148 | |||
| 149 | out_err: | ||
| 150 | wcn36xx_err("Failed to allocate DXE control blocks\n"); | ||
| 151 | wcn36xx_dxe_free_ctl_blks(wcn); | ||
| 152 | return -ENOMEM; | ||
| 153 | } | ||
| 154 | |||
| 155 | void wcn36xx_dxe_free_ctl_blks(struct wcn36xx *wcn) | ||
| 156 | { | ||
| 157 | wcn36xx_dxe_free_ctl_block(&wcn->dxe_tx_l_ch); | ||
| 158 | wcn36xx_dxe_free_ctl_block(&wcn->dxe_tx_h_ch); | ||
| 159 | wcn36xx_dxe_free_ctl_block(&wcn->dxe_rx_l_ch); | ||
| 160 | wcn36xx_dxe_free_ctl_block(&wcn->dxe_rx_h_ch); | ||
| 161 | } | ||
| 162 | |||
| 163 | static int wcn36xx_dxe_init_descs(struct wcn36xx_dxe_ch *wcn_ch) | ||
| 164 | { | ||
| 165 | struct wcn36xx_dxe_desc *cur_dxe = NULL; | ||
| 166 | struct wcn36xx_dxe_desc *prev_dxe = NULL; | ||
| 167 | struct wcn36xx_dxe_ctl *cur_ctl = NULL; | ||
| 168 | size_t size; | ||
| 169 | int i; | ||
| 170 | |||
| 171 | size = wcn_ch->desc_num * sizeof(struct wcn36xx_dxe_desc); | ||
| 172 | wcn_ch->cpu_addr = dma_alloc_coherent(NULL, size, &wcn_ch->dma_addr, | ||
| 173 | GFP_KERNEL); | ||
| 174 | if (!wcn_ch->cpu_addr) | ||
| 175 | return -ENOMEM; | ||
| 176 | |||
| 177 | memset(wcn_ch->cpu_addr, 0, size); | ||
| 178 | |||
| 179 | cur_dxe = (struct wcn36xx_dxe_desc *)wcn_ch->cpu_addr; | ||
| 180 | cur_ctl = wcn_ch->head_blk_ctl; | ||
| 181 | |||
| 182 | for (i = 0; i < wcn_ch->desc_num; i++) { | ||
| 183 | cur_ctl->desc = cur_dxe; | ||
| 184 | cur_ctl->desc_phy_addr = wcn_ch->dma_addr + | ||
| 185 | i * sizeof(struct wcn36xx_dxe_desc); | ||
| 186 | |||
| 187 | switch (wcn_ch->ch_type) { | ||
| 188 | case WCN36XX_DXE_CH_TX_L: | ||
| 189 | cur_dxe->ctrl = WCN36XX_DXE_CTRL_TX_L; | ||
| 190 | cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_L; | ||
| 191 | break; | ||
| 192 | case WCN36XX_DXE_CH_TX_H: | ||
| 193 | cur_dxe->ctrl = WCN36XX_DXE_CTRL_TX_H; | ||
| 194 | cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_H; | ||
| 195 | break; | ||
| 196 | case WCN36XX_DXE_CH_RX_L: | ||
| 197 | cur_dxe->ctrl = WCN36XX_DXE_CTRL_RX_L; | ||
| 198 | cur_dxe->src_addr_l = WCN36XX_DXE_WQ_RX_L; | ||
| 199 | break; | ||
| 200 | case WCN36XX_DXE_CH_RX_H: | ||
| 201 | cur_dxe->ctrl = WCN36XX_DXE_CTRL_RX_H; | ||
| 202 | cur_dxe->src_addr_l = WCN36XX_DXE_WQ_RX_H; | ||
| 203 | break; | ||
| 204 | } | ||
| 205 | if (0 == i) { | ||
| 206 | cur_dxe->phy_next_l = 0; | ||
| 207 | } else if ((0 < i) && (i < wcn_ch->desc_num - 1)) { | ||
| 208 | prev_dxe->phy_next_l = | ||
| 209 | cur_ctl->desc_phy_addr; | ||
| 210 | } else if (i == (wcn_ch->desc_num - 1)) { | ||
| 211 | prev_dxe->phy_next_l = | ||
| 212 | cur_ctl->desc_phy_addr; | ||
| 213 | cur_dxe->phy_next_l = | ||
| 214 | wcn_ch->head_blk_ctl->desc_phy_addr; | ||
| 215 | } | ||
| 216 | cur_ctl = cur_ctl->next; | ||
| 217 | prev_dxe = cur_dxe; | ||
| 218 | cur_dxe++; | ||
| 219 | } | ||
| 220 | |||
| 221 | return 0; | ||
| 222 | } | ||
| 223 | |||
| 224 | static void wcn36xx_dxe_init_tx_bd(struct wcn36xx_dxe_ch *ch, | ||
| 225 | struct wcn36xx_dxe_mem_pool *pool) | ||
| 226 | { | ||
| 227 | int i, chunk_size = pool->chunk_size; | ||
| 228 | dma_addr_t bd_phy_addr = pool->phy_addr; | ||
| 229 | void *bd_cpu_addr = pool->virt_addr; | ||
| 230 | struct wcn36xx_dxe_ctl *cur = ch->head_blk_ctl; | ||
| 231 | |||
| 232 | for (i = 0; i < ch->desc_num; i++) { | ||
| 233 | /* Only every second dxe needs a bd pointer, | ||
| 234 | the other will point to the skb data */ | ||
| 235 | if (!(i & 1)) { | ||
| 236 | cur->bd_phy_addr = bd_phy_addr; | ||
| 237 | cur->bd_cpu_addr = bd_cpu_addr; | ||
| 238 | bd_phy_addr += chunk_size; | ||
| 239 | bd_cpu_addr += chunk_size; | ||
| 240 | } else { | ||
| 241 | cur->bd_phy_addr = 0; | ||
| 242 | cur->bd_cpu_addr = NULL; | ||
| 243 | } | ||
| 244 | cur = cur->next; | ||
| 245 | } | ||
| 246 | } | ||
| 247 | |||
| 248 | static int wcn36xx_dxe_enable_ch_int(struct wcn36xx *wcn, u16 wcn_ch) | ||
| 249 | { | ||
| 250 | int reg_data = 0; | ||
| 251 | |||
| 252 | wcn36xx_dxe_read_register(wcn, | ||
| 253 | WCN36XX_DXE_INT_MASK_REG, | ||
| 254 | ®_data); | ||
| 255 | |||
| 256 | reg_data |= wcn_ch; | ||
| 257 | |||
| 258 | wcn36xx_dxe_write_register(wcn, | ||
| 259 | WCN36XX_DXE_INT_MASK_REG, | ||
| 260 | (int)reg_data); | ||
| 261 | return 0; | ||
| 262 | } | ||
| 263 | |||
| 264 | static int wcn36xx_dxe_fill_skb(struct wcn36xx_dxe_ctl *ctl) | ||
| 265 | { | ||
| 266 | struct wcn36xx_dxe_desc *dxe = ctl->desc; | ||
| 267 | struct sk_buff *skb; | ||
| 268 | |||
| 269 | skb = alloc_skb(WCN36XX_PKT_SIZE, GFP_ATOMIC); | ||
| 270 | if (skb == NULL) | ||
| 271 | return -ENOMEM; | ||
| 272 | |||
| 273 | dxe->dst_addr_l = dma_map_single(NULL, | ||
| 274 | skb_tail_pointer(skb), | ||
| 275 | WCN36XX_PKT_SIZE, | ||
| 276 | DMA_FROM_DEVICE); | ||
| 277 | ctl->skb = skb; | ||
| 278 | |||
| 279 | return 0; | ||
| 280 | } | ||
| 281 | |||
| 282 | static int wcn36xx_dxe_ch_alloc_skb(struct wcn36xx *wcn, | ||
| 283 | struct wcn36xx_dxe_ch *wcn_ch) | ||
| 284 | { | ||
| 285 | int i; | ||
| 286 | struct wcn36xx_dxe_ctl *cur_ctl = NULL; | ||
| 287 | |||
| 288 | cur_ctl = wcn_ch->head_blk_ctl; | ||
| 289 | |||
| 290 | for (i = 0; i < wcn_ch->desc_num; i++) { | ||
| 291 | wcn36xx_dxe_fill_skb(cur_ctl); | ||
| 292 | cur_ctl = cur_ctl->next; | ||
| 293 | } | ||
| 294 | |||
| 295 | return 0; | ||
| 296 | } | ||
| 297 | |||
| 298 | static void wcn36xx_dxe_ch_free_skbs(struct wcn36xx *wcn, | ||
| 299 | struct wcn36xx_dxe_ch *wcn_ch) | ||
| 300 | { | ||
| 301 | struct wcn36xx_dxe_ctl *cur = wcn_ch->head_blk_ctl; | ||
| 302 | int i; | ||
| 303 | |||
| 304 | for (i = 0; i < wcn_ch->desc_num; i++) { | ||
| 305 | kfree_skb(cur->skb); | ||
| 306 | cur = cur->next; | ||
| 307 | } | ||
| 308 | } | ||
| 309 | |||
| 310 | void wcn36xx_dxe_tx_ack_ind(struct wcn36xx *wcn, u32 status) | ||
| 311 | { | ||
| 312 | struct ieee80211_tx_info *info; | ||
| 313 | struct sk_buff *skb; | ||
| 314 | unsigned long flags; | ||
| 315 | |||
| 316 | spin_lock_irqsave(&wcn->dxe_lock, flags); | ||
| 317 | skb = wcn->tx_ack_skb; | ||
| 318 | wcn->tx_ack_skb = NULL; | ||
| 319 | spin_unlock_irqrestore(&wcn->dxe_lock, flags); | ||
| 320 | |||
| 321 | if (!skb) { | ||
| 322 | wcn36xx_warn("Spurious TX complete indication\n"); | ||
| 323 | return; | ||
| 324 | } | ||
| 325 | |||
| 326 | info = IEEE80211_SKB_CB(skb); | ||
| 327 | |||
| 328 | if (status == 1) | ||
| 329 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
| 330 | |||
| 331 | wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ack status: %d\n", status); | ||
| 332 | |||
| 333 | ieee80211_tx_status_irqsafe(wcn->hw, skb); | ||
| 334 | ieee80211_wake_queues(wcn->hw); | ||
| 335 | } | ||
| 336 | |||
| 337 | static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) | ||
| 338 | { | ||
| 339 | struct wcn36xx_dxe_ctl *ctl = ch->tail_blk_ctl; | ||
| 340 | struct ieee80211_tx_info *info; | ||
| 341 | unsigned long flags; | ||
| 342 | |||
| 343 | /* | ||
| 344 | * Make at least one loop of do-while because in case ring is | ||
| 345 | * completely full head and tail are pointing to the same element | ||
| 346 | * and while-do will not make any cycles. | ||
| 347 | */ | ||
| 348 | do { | ||
| 349 | if (ctl->skb) { | ||
| 350 | dma_unmap_single(NULL, ctl->desc->src_addr_l, | ||
| 351 | ctl->skb->len, DMA_TO_DEVICE); | ||
| 352 | info = IEEE80211_SKB_CB(ctl->skb); | ||
| 353 | if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) { | ||
| 354 | /* Keep frame until TX status comes */ | ||
| 355 | ieee80211_free_txskb(wcn->hw, ctl->skb); | ||
| 356 | } | ||
| 357 | spin_lock_irqsave(&ctl->skb_lock, flags); | ||
| 358 | if (wcn->queues_stopped) { | ||
| 359 | wcn->queues_stopped = false; | ||
| 360 | ieee80211_wake_queues(wcn->hw); | ||
| 361 | } | ||
| 362 | spin_unlock_irqrestore(&ctl->skb_lock, flags); | ||
| 363 | |||
| 364 | ctl->skb = NULL; | ||
| 365 | } | ||
| 366 | ctl = ctl->next; | ||
| 367 | } while (ctl != ch->head_blk_ctl && | ||
| 368 | !(ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)); | ||
| 369 | |||
| 370 | ch->tail_blk_ctl = ctl; | ||
| 371 | } | ||
| 372 | |||
| 373 | static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) | ||
| 374 | { | ||
| 375 | struct wcn36xx *wcn = (struct wcn36xx *)dev; | ||
| 376 | int int_src, int_reason; | ||
| 377 | |||
| 378 | wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_INT_SRC_RAW_REG, &int_src); | ||
| 379 | |||
| 380 | if (int_src & WCN36XX_INT_MASK_CHAN_TX_H) { | ||
| 381 | wcn36xx_dxe_read_register(wcn, | ||
| 382 | WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_H, | ||
| 383 | &int_reason); | ||
| 384 | |||
| 385 | /* TODO: Check int_reason */ | ||
| 386 | |||
| 387 | wcn36xx_dxe_write_register(wcn, | ||
| 388 | WCN36XX_DXE_0_INT_CLR, | ||
| 389 | WCN36XX_INT_MASK_CHAN_TX_H); | ||
| 390 | |||
| 391 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_ED_CLR, | ||
| 392 | WCN36XX_INT_MASK_CHAN_TX_H); | ||
| 393 | wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready high\n"); | ||
| 394 | reap_tx_dxes(wcn, &wcn->dxe_tx_h_ch); | ||
| 395 | } | ||
| 396 | |||
| 397 | if (int_src & WCN36XX_INT_MASK_CHAN_TX_L) { | ||
| 398 | wcn36xx_dxe_read_register(wcn, | ||
| 399 | WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_L, | ||
| 400 | &int_reason); | ||
| 401 | /* TODO: Check int_reason */ | ||
| 402 | |||
| 403 | wcn36xx_dxe_write_register(wcn, | ||
| 404 | WCN36XX_DXE_0_INT_CLR, | ||
| 405 | WCN36XX_INT_MASK_CHAN_TX_L); | ||
| 406 | |||
| 407 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_ED_CLR, | ||
| 408 | WCN36XX_INT_MASK_CHAN_TX_L); | ||
| 409 | wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready low\n"); | ||
| 410 | reap_tx_dxes(wcn, &wcn->dxe_tx_l_ch); | ||
| 411 | } | ||
| 412 | |||
| 413 | return IRQ_HANDLED; | ||
| 414 | } | ||
| 415 | |||
| 416 | static irqreturn_t wcn36xx_irq_rx_ready(int irq, void *dev) | ||
| 417 | { | ||
| 418 | struct wcn36xx *wcn = (struct wcn36xx *)dev; | ||
| 419 | |||
| 420 | disable_irq_nosync(wcn->rx_irq); | ||
| 421 | wcn36xx_dxe_rx_frame(wcn); | ||
| 422 | enable_irq(wcn->rx_irq); | ||
| 423 | return IRQ_HANDLED; | ||
| 424 | } | ||
| 425 | |||
| 426 | static int wcn36xx_dxe_request_irqs(struct wcn36xx *wcn) | ||
| 427 | { | ||
| 428 | int ret; | ||
| 429 | |||
| 430 | ret = request_irq(wcn->tx_irq, wcn36xx_irq_tx_complete, | ||
| 431 | IRQF_TRIGGER_HIGH, "wcn36xx_tx", wcn); | ||
| 432 | if (ret) { | ||
| 433 | wcn36xx_err("failed to alloc tx irq\n"); | ||
| 434 | goto out_err; | ||
| 435 | } | ||
| 436 | |||
| 437 | ret = request_irq(wcn->rx_irq, wcn36xx_irq_rx_ready, IRQF_TRIGGER_HIGH, | ||
| 438 | "wcn36xx_rx", wcn); | ||
| 439 | if (ret) { | ||
| 440 | wcn36xx_err("failed to alloc rx irq\n"); | ||
| 441 | goto out_txirq; | ||
| 442 | } | ||
| 443 | |||
| 444 | enable_irq_wake(wcn->rx_irq); | ||
| 445 | |||
| 446 | return 0; | ||
| 447 | |||
| 448 | out_txirq: | ||
| 449 | free_irq(wcn->tx_irq, wcn); | ||
| 450 | out_err: | ||
| 451 | return ret; | ||
| 452 | |||
| 453 | } | ||
| 454 | |||
| 455 | static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn, | ||
| 456 | struct wcn36xx_dxe_ch *ch) | ||
| 457 | { | ||
| 458 | struct wcn36xx_dxe_ctl *ctl = ch->head_blk_ctl; | ||
| 459 | struct wcn36xx_dxe_desc *dxe = ctl->desc; | ||
| 460 | dma_addr_t dma_addr; | ||
| 461 | struct sk_buff *skb; | ||
| 462 | |||
| 463 | while (!(dxe->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)) { | ||
| 464 | skb = ctl->skb; | ||
| 465 | dma_addr = dxe->dst_addr_l; | ||
| 466 | wcn36xx_dxe_fill_skb(ctl); | ||
| 467 | |||
| 468 | switch (ch->ch_type) { | ||
| 469 | case WCN36XX_DXE_CH_RX_L: | ||
| 470 | dxe->ctrl = WCN36XX_DXE_CTRL_RX_L; | ||
| 471 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_ENCH_ADDR, | ||
| 472 | WCN36XX_DXE_INT_CH1_MASK); | ||
| 473 | break; | ||
| 474 | case WCN36XX_DXE_CH_RX_H: | ||
| 475 | dxe->ctrl = WCN36XX_DXE_CTRL_RX_H; | ||
| 476 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_ENCH_ADDR, | ||
| 477 | WCN36XX_DXE_INT_CH3_MASK); | ||
| 478 | break; | ||
| 479 | default: | ||
| 480 | wcn36xx_warn("Unknown channel\n"); | ||
| 481 | } | ||
| 482 | |||
| 483 | dma_unmap_single(NULL, dma_addr, WCN36XX_PKT_SIZE, | ||
| 484 | DMA_FROM_DEVICE); | ||
| 485 | wcn36xx_rx_skb(wcn, skb); | ||
| 486 | ctl = ctl->next; | ||
| 487 | dxe = ctl->desc; | ||
| 488 | } | ||
| 489 | |||
| 490 | ch->head_blk_ctl = ctl; | ||
| 491 | |||
| 492 | return 0; | ||
| 493 | } | ||
| 494 | |||
| 495 | void wcn36xx_dxe_rx_frame(struct wcn36xx *wcn) | ||
| 496 | { | ||
| 497 | int int_src; | ||
| 498 | |||
| 499 | wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_INT_SRC_RAW_REG, &int_src); | ||
| 500 | |||
| 501 | /* RX_LOW_PRI */ | ||
| 502 | if (int_src & WCN36XX_DXE_INT_CH1_MASK) { | ||
| 503 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_CLR, | ||
| 504 | WCN36XX_DXE_INT_CH1_MASK); | ||
| 505 | wcn36xx_rx_handle_packets(wcn, &(wcn->dxe_rx_l_ch)); | ||
| 506 | } | ||
| 507 | |||
| 508 | /* RX_HIGH_PRI */ | ||
| 509 | if (int_src & WCN36XX_DXE_INT_CH3_MASK) { | ||
| 510 | /* Clean up all the INT within this channel */ | ||
| 511 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_CLR, | ||
| 512 | WCN36XX_DXE_INT_CH3_MASK); | ||
| 513 | wcn36xx_rx_handle_packets(wcn, &(wcn->dxe_rx_h_ch)); | ||
| 514 | } | ||
| 515 | |||
| 516 | if (!int_src) | ||
| 517 | wcn36xx_warn("No DXE interrupt pending\n"); | ||
| 518 | } | ||
| 519 | |||
| 520 | int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn) | ||
| 521 | { | ||
| 522 | size_t s; | ||
| 523 | void *cpu_addr; | ||
| 524 | |||
| 525 | /* Allocate BD headers for MGMT frames */ | ||
| 526 | |||
| 527 | /* Where this come from ask QC */ | ||
| 528 | wcn->mgmt_mem_pool.chunk_size = WCN36XX_BD_CHUNK_SIZE + | ||
| 529 | 16 - (WCN36XX_BD_CHUNK_SIZE % 8); | ||
| 530 | |||
| 531 | s = wcn->mgmt_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_H; | ||
| 532 | cpu_addr = dma_alloc_coherent(NULL, s, &wcn->mgmt_mem_pool.phy_addr, | ||
| 533 | GFP_KERNEL); | ||
| 534 | if (!cpu_addr) | ||
| 535 | goto out_err; | ||
| 536 | |||
| 537 | wcn->mgmt_mem_pool.virt_addr = cpu_addr; | ||
| 538 | memset(cpu_addr, 0, s); | ||
| 539 | |||
| 540 | /* Allocate BD headers for DATA frames */ | ||
| 541 | |||
| 542 | /* Where this come from ask QC */ | ||
| 543 | wcn->data_mem_pool.chunk_size = WCN36XX_BD_CHUNK_SIZE + | ||
| 544 | 16 - (WCN36XX_BD_CHUNK_SIZE % 8); | ||
| 545 | |||
| 546 | s = wcn->data_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_L; | ||
| 547 | cpu_addr = dma_alloc_coherent(NULL, s, &wcn->data_mem_pool.phy_addr, | ||
| 548 | GFP_KERNEL); | ||
| 549 | if (!cpu_addr) | ||
| 550 | goto out_err; | ||
| 551 | |||
| 552 | wcn->data_mem_pool.virt_addr = cpu_addr; | ||
| 553 | memset(cpu_addr, 0, s); | ||
| 554 | |||
| 555 | return 0; | ||
| 556 | |||
| 557 | out_err: | ||
| 558 | wcn36xx_dxe_free_mem_pools(wcn); | ||
| 559 | wcn36xx_err("Failed to allocate BD mempool\n"); | ||
| 560 | return -ENOMEM; | ||
| 561 | } | ||
| 562 | |||
| 563 | void wcn36xx_dxe_free_mem_pools(struct wcn36xx *wcn) | ||
| 564 | { | ||
| 565 | if (wcn->mgmt_mem_pool.virt_addr) | ||
| 566 | dma_free_coherent(NULL, wcn->mgmt_mem_pool.chunk_size * | ||
| 567 | WCN36XX_DXE_CH_DESC_NUMB_TX_H, | ||
| 568 | wcn->mgmt_mem_pool.virt_addr, | ||
| 569 | wcn->mgmt_mem_pool.phy_addr); | ||
| 570 | |||
| 571 | if (wcn->data_mem_pool.virt_addr) { | ||
| 572 | dma_free_coherent(NULL, wcn->data_mem_pool.chunk_size * | ||
| 573 | WCN36XX_DXE_CH_DESC_NUMB_TX_L, | ||
| 574 | wcn->data_mem_pool.virt_addr, | ||
| 575 | wcn->data_mem_pool.phy_addr); | ||
| 576 | } | ||
| 577 | } | ||
| 578 | |||
| 579 | int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, | ||
| 580 | struct wcn36xx_vif *vif_priv, | ||
| 581 | struct sk_buff *skb, | ||
| 582 | bool is_low) | ||
| 583 | { | ||
| 584 | struct wcn36xx_dxe_ctl *ctl = NULL; | ||
| 585 | struct wcn36xx_dxe_desc *desc = NULL; | ||
| 586 | struct wcn36xx_dxe_ch *ch = NULL; | ||
| 587 | unsigned long flags; | ||
| 588 | |||
| 589 | ch = is_low ? &wcn->dxe_tx_l_ch : &wcn->dxe_tx_h_ch; | ||
| 590 | |||
| 591 | ctl = ch->head_blk_ctl; | ||
| 592 | |||
| 593 | spin_lock_irqsave(&ctl->next->skb_lock, flags); | ||
| 594 | |||
| 595 | /* | ||
| 596 | * If skb is not null that means that we reached the tail of the ring | ||
| 597 | * hence ring is full. Stop queues to let mac80211 back off until ring | ||
| 598 | * has an empty slot again. | ||
| 599 | */ | ||
| 600 | if (NULL != ctl->next->skb) { | ||
| 601 | ieee80211_stop_queues(wcn->hw); | ||
| 602 | wcn->queues_stopped = true; | ||
| 603 | spin_unlock_irqrestore(&ctl->next->skb_lock, flags); | ||
| 604 | return -EBUSY; | ||
| 605 | } | ||
| 606 | spin_unlock_irqrestore(&ctl->next->skb_lock, flags); | ||
| 607 | |||
| 608 | ctl->skb = NULL; | ||
| 609 | desc = ctl->desc; | ||
| 610 | |||
| 611 | /* Set source address of the BD we send */ | ||
| 612 | desc->src_addr_l = ctl->bd_phy_addr; | ||
| 613 | |||
| 614 | desc->dst_addr_l = ch->dxe_wq; | ||
| 615 | desc->fr_len = sizeof(struct wcn36xx_tx_bd); | ||
| 616 | desc->ctrl = ch->ctrl_bd; | ||
| 617 | |||
| 618 | wcn36xx_dbg(WCN36XX_DBG_DXE, "DXE TX\n"); | ||
| 619 | |||
| 620 | wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "DESC1 >>> ", | ||
| 621 | (char *)desc, sizeof(*desc)); | ||
| 622 | wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, | ||
| 623 | "BD >>> ", (char *)ctl->bd_cpu_addr, | ||
| 624 | sizeof(struct wcn36xx_tx_bd)); | ||
| 625 | |||
| 626 | /* Set source address of the SKB we send */ | ||
| 627 | ctl = ctl->next; | ||
| 628 | ctl->skb = skb; | ||
| 629 | desc = ctl->desc; | ||
| 630 | if (ctl->bd_cpu_addr) { | ||
| 631 | wcn36xx_err("bd_cpu_addr cannot be NULL for skb DXE\n"); | ||
| 632 | return -EINVAL; | ||
| 633 | } | ||
| 634 | |||
| 635 | desc->src_addr_l = dma_map_single(NULL, | ||
| 636 | ctl->skb->data, | ||
| 637 | ctl->skb->len, | ||
| 638 | DMA_TO_DEVICE); | ||
| 639 | |||
| 640 | desc->dst_addr_l = ch->dxe_wq; | ||
| 641 | desc->fr_len = ctl->skb->len; | ||
| 642 | |||
| 643 | /* set dxe descriptor to VALID */ | ||
| 644 | desc->ctrl = ch->ctrl_skb; | ||
| 645 | |||
| 646 | wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "DESC2 >>> ", | ||
| 647 | (char *)desc, sizeof(*desc)); | ||
| 648 | wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "SKB >>> ", | ||
| 649 | (char *)ctl->skb->data, ctl->skb->len); | ||
| 650 | |||
| 651 | /* Move the head of the ring to the next empty descriptor */ | ||
| 652 | ch->head_blk_ctl = ctl->next; | ||
| 653 | |||
| 654 | /* | ||
| 655 | * When connected and trying to send data frame chip can be in sleep | ||
| 656 | * mode and writing to the register will not wake up the chip. Instead | ||
| 657 | * notify chip about new frame through SMSM bus. | ||
| 658 | */ | ||
| 659 | if (is_low && vif_priv->pw_state == WCN36XX_BMPS) { | ||
| 660 | wcn->ctrl_ops->smsm_change_state( | ||
| 661 | 0, | ||
| 662 | WCN36XX_SMSM_WLAN_TX_ENABLE); | ||
| 663 | } else { | ||
| 664 | /* indicate End Of Packet and generate interrupt on descriptor | ||
| 665 | * done. | ||
| 666 | */ | ||
| 667 | wcn36xx_dxe_write_register(wcn, | ||
| 668 | ch->reg_ctrl, ch->def_ctrl); | ||
| 669 | } | ||
| 670 | |||
| 671 | return 0; | ||
| 672 | } | ||
| 673 | |||
| 674 | int wcn36xx_dxe_init(struct wcn36xx *wcn) | ||
| 675 | { | ||
| 676 | int reg_data = 0, ret; | ||
| 677 | |||
| 678 | reg_data = WCN36XX_DXE_REG_RESET; | ||
| 679 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CSR_RESET, reg_data); | ||
| 680 | |||
| 681 | /* Setting interrupt path */ | ||
| 682 | reg_data = WCN36XX_DXE_CCU_INT; | ||
| 683 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CCU_INT, reg_data); | ||
| 684 | |||
| 685 | /***************************************/ | ||
| 686 | /* Init descriptors for TX LOW channel */ | ||
| 687 | /***************************************/ | ||
| 688 | wcn36xx_dxe_init_descs(&wcn->dxe_tx_l_ch); | ||
| 689 | wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_l_ch, &wcn->data_mem_pool); | ||
| 690 | |||
| 691 | /* Write channel head to a NEXT register */ | ||
| 692 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_L, | ||
| 693 | wcn->dxe_tx_l_ch.head_blk_ctl->desc_phy_addr); | ||
| 694 | |||
| 695 | /* Program DMA destination addr for TX LOW */ | ||
| 696 | wcn36xx_dxe_write_register(wcn, | ||
| 697 | WCN36XX_DXE_CH_DEST_ADDR_TX_L, | ||
| 698 | WCN36XX_DXE_WQ_TX_L); | ||
| 699 | |||
| 700 | wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, ®_data); | ||
| 701 | wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_L); | ||
| 702 | |||
| 703 | /***************************************/ | ||
| 704 | /* Init descriptors for TX HIGH channel */ | ||
| 705 | /***************************************/ | ||
| 706 | wcn36xx_dxe_init_descs(&wcn->dxe_tx_h_ch); | ||
| 707 | wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_h_ch, &wcn->mgmt_mem_pool); | ||
| 708 | |||
| 709 | /* Write channel head to a NEXT register */ | ||
| 710 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_H, | ||
| 711 | wcn->dxe_tx_h_ch.head_blk_ctl->desc_phy_addr); | ||
| 712 | |||
| 713 | /* Program DMA destination addr for TX HIGH */ | ||
| 714 | wcn36xx_dxe_write_register(wcn, | ||
| 715 | WCN36XX_DXE_CH_DEST_ADDR_TX_H, | ||
| 716 | WCN36XX_DXE_WQ_TX_H); | ||
| 717 | |||
| 718 | wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, ®_data); | ||
| 719 | |||
| 720 | /* Enable channel interrupts */ | ||
| 721 | wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_H); | ||
| 722 | |||
| 723 | /***************************************/ | ||
| 724 | /* Init descriptors for RX LOW channel */ | ||
| 725 | /***************************************/ | ||
| 726 | wcn36xx_dxe_init_descs(&wcn->dxe_rx_l_ch); | ||
| 727 | |||
| 728 | /* For RX we need to preallocated buffers */ | ||
| 729 | wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch); | ||
| 730 | |||
| 731 | /* Write channel head to a NEXT register */ | ||
| 732 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_L, | ||
| 733 | wcn->dxe_rx_l_ch.head_blk_ctl->desc_phy_addr); | ||
| 734 | |||
| 735 | /* Write DMA source address */ | ||
| 736 | wcn36xx_dxe_write_register(wcn, | ||
| 737 | WCN36XX_DXE_CH_SRC_ADDR_RX_L, | ||
| 738 | WCN36XX_DXE_WQ_RX_L); | ||
| 739 | |||
| 740 | /* Program preallocated destination address */ | ||
| 741 | wcn36xx_dxe_write_register(wcn, | ||
| 742 | WCN36XX_DXE_CH_DEST_ADDR_RX_L, | ||
| 743 | wcn->dxe_rx_l_ch.head_blk_ctl->desc->phy_next_l); | ||
| 744 | |||
| 745 | /* Enable default control registers */ | ||
| 746 | wcn36xx_dxe_write_register(wcn, | ||
| 747 | WCN36XX_DXE_REG_CTL_RX_L, | ||
| 748 | WCN36XX_DXE_CH_DEFAULT_CTL_RX_L); | ||
| 749 | |||
| 750 | /* Enable channel interrupts */ | ||
| 751 | wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_L); | ||
| 752 | |||
| 753 | /***************************************/ | ||
| 754 | /* Init descriptors for RX HIGH channel */ | ||
| 755 | /***************************************/ | ||
| 756 | wcn36xx_dxe_init_descs(&wcn->dxe_rx_h_ch); | ||
| 757 | |||
| 758 | /* For RX we need to prealocat buffers */ | ||
| 759 | wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_h_ch); | ||
| 760 | |||
| 761 | /* Write chanel head to a NEXT register */ | ||
| 762 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_H, | ||
| 763 | wcn->dxe_rx_h_ch.head_blk_ctl->desc_phy_addr); | ||
| 764 | |||
| 765 | /* Write DMA source address */ | ||
| 766 | wcn36xx_dxe_write_register(wcn, | ||
| 767 | WCN36XX_DXE_CH_SRC_ADDR_RX_H, | ||
| 768 | WCN36XX_DXE_WQ_RX_H); | ||
| 769 | |||
| 770 | /* Program preallocated destination address */ | ||
| 771 | wcn36xx_dxe_write_register(wcn, | ||
| 772 | WCN36XX_DXE_CH_DEST_ADDR_RX_H, | ||
| 773 | wcn->dxe_rx_h_ch.head_blk_ctl->desc->phy_next_l); | ||
| 774 | |||
| 775 | /* Enable default control registers */ | ||
| 776 | wcn36xx_dxe_write_register(wcn, | ||
| 777 | WCN36XX_DXE_REG_CTL_RX_H, | ||
| 778 | WCN36XX_DXE_CH_DEFAULT_CTL_RX_H); | ||
| 779 | |||
| 780 | /* Enable channel interrupts */ | ||
| 781 | wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_H); | ||
| 782 | |||
| 783 | ret = wcn36xx_dxe_request_irqs(wcn); | ||
| 784 | if (ret < 0) | ||
| 785 | goto out_err; | ||
| 786 | |||
| 787 | return 0; | ||
| 788 | |||
| 789 | out_err: | ||
| 790 | return ret; | ||
| 791 | } | ||
| 792 | |||
| 793 | void wcn36xx_dxe_deinit(struct wcn36xx *wcn) | ||
| 794 | { | ||
| 795 | free_irq(wcn->tx_irq, wcn); | ||
| 796 | free_irq(wcn->rx_irq, wcn); | ||
| 797 | |||
| 798 | if (wcn->tx_ack_skb) { | ||
| 799 | ieee80211_tx_status_irqsafe(wcn->hw, wcn->tx_ack_skb); | ||
| 800 | wcn->tx_ack_skb = NULL; | ||
| 801 | } | ||
| 802 | |||
| 803 | wcn36xx_dxe_ch_free_skbs(wcn, &wcn->dxe_rx_l_ch); | ||
| 804 | wcn36xx_dxe_ch_free_skbs(wcn, &wcn->dxe_rx_h_ch); | ||
| 805 | } | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.h b/drivers/net/wireless/ath/wcn36xx/dxe.h new file mode 100644 index 000000000000..c88562f85de1 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/dxe.h | |||
| @@ -0,0 +1,284 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef _DXE_H_ | ||
| 18 | #define _DXE_H_ | ||
| 19 | |||
| 20 | #include "wcn36xx.h" | ||
| 21 | |||
| 22 | /* | ||
| 23 | TX_LOW = DMA0 | ||
| 24 | TX_HIGH = DMA4 | ||
| 25 | RX_LOW = DMA1 | ||
| 26 | RX_HIGH = DMA3 | ||
| 27 | H2H_TEST_RX_TX = DMA2 | ||
| 28 | */ | ||
| 29 | |||
| 30 | /* DXE registers */ | ||
| 31 | #define WCN36XX_DXE_MEM_BASE 0x03000000 | ||
| 32 | #define WCN36XX_DXE_MEM_REG 0x202000 | ||
| 33 | |||
| 34 | #define WCN36XX_DXE_CCU_INT 0xA0011 | ||
| 35 | #define WCN36XX_DXE_REG_CCU_INT 0x200b10 | ||
| 36 | |||
| 37 | /* TODO This must calculated properly but not hardcoded */ | ||
| 38 | #define WCN36XX_DXE_CTRL_TX_L 0x328a44 | ||
| 39 | #define WCN36XX_DXE_CTRL_TX_H 0x32ce44 | ||
| 40 | #define WCN36XX_DXE_CTRL_RX_L 0x12ad2f | ||
| 41 | #define WCN36XX_DXE_CTRL_RX_H 0x12d12f | ||
| 42 | #define WCN36XX_DXE_CTRL_TX_H_BD 0x30ce45 | ||
| 43 | #define WCN36XX_DXE_CTRL_TX_H_SKB 0x32ce4d | ||
| 44 | #define WCN36XX_DXE_CTRL_TX_L_BD 0x308a45 | ||
| 45 | #define WCN36XX_DXE_CTRL_TX_L_SKB 0x328a4d | ||
| 46 | |||
| 47 | /* TODO This must calculated properly but not hardcoded */ | ||
| 48 | #define WCN36XX_DXE_WQ_TX_L 0x17 | ||
| 49 | #define WCN36XX_DXE_WQ_TX_H 0x17 | ||
| 50 | #define WCN36XX_DXE_WQ_RX_L 0xB | ||
| 51 | #define WCN36XX_DXE_WQ_RX_H 0x4 | ||
| 52 | |||
| 53 | /* DXE descriptor control filed */ | ||
| 54 | #define WCN36XX_DXE_CTRL_VALID_MASK (0x00000001) | ||
| 55 | |||
| 56 | /* TODO This must calculated properly but not hardcoded */ | ||
| 57 | /* DXE default control register values */ | ||
| 58 | #define WCN36XX_DXE_CH_DEFAULT_CTL_RX_L 0x847EAD2F | ||
| 59 | #define WCN36XX_DXE_CH_DEFAULT_CTL_RX_H 0x84FED12F | ||
| 60 | #define WCN36XX_DXE_CH_DEFAULT_CTL_TX_H 0x853ECF4D | ||
| 61 | #define WCN36XX_DXE_CH_DEFAULT_CTL_TX_L 0x843e8b4d | ||
| 62 | |||
| 63 | /* Common DXE registers */ | ||
| 64 | #define WCN36XX_DXE_MEM_CSR (WCN36XX_DXE_MEM_REG + 0x00) | ||
| 65 | #define WCN36XX_DXE_REG_CSR_RESET (WCN36XX_DXE_MEM_REG + 0x00) | ||
| 66 | #define WCN36XX_DXE_ENCH_ADDR (WCN36XX_DXE_MEM_REG + 0x04) | ||
| 67 | #define WCN36XX_DXE_REG_CH_EN (WCN36XX_DXE_MEM_REG + 0x08) | ||
| 68 | #define WCN36XX_DXE_REG_CH_DONE (WCN36XX_DXE_MEM_REG + 0x0C) | ||
| 69 | #define WCN36XX_DXE_REG_CH_ERR (WCN36XX_DXE_MEM_REG + 0x10) | ||
| 70 | #define WCN36XX_DXE_INT_MASK_REG (WCN36XX_DXE_MEM_REG + 0x18) | ||
| 71 | #define WCN36XX_DXE_INT_SRC_RAW_REG (WCN36XX_DXE_MEM_REG + 0x20) | ||
| 72 | /* #define WCN36XX_DXE_INT_CH6_MASK 0x00000040 */ | ||
| 73 | /* #define WCN36XX_DXE_INT_CH5_MASK 0x00000020 */ | ||
| 74 | #define WCN36XX_DXE_INT_CH4_MASK 0x00000010 | ||
| 75 | #define WCN36XX_DXE_INT_CH3_MASK 0x00000008 | ||
| 76 | /* #define WCN36XX_DXE_INT_CH2_MASK 0x00000004 */ | ||
| 77 | #define WCN36XX_DXE_INT_CH1_MASK 0x00000002 | ||
| 78 | #define WCN36XX_DXE_INT_CH0_MASK 0x00000001 | ||
| 79 | #define WCN36XX_DXE_0_INT_CLR (WCN36XX_DXE_MEM_REG + 0x30) | ||
| 80 | #define WCN36XX_DXE_0_INT_ED_CLR (WCN36XX_DXE_MEM_REG + 0x34) | ||
| 81 | #define WCN36XX_DXE_0_INT_DONE_CLR (WCN36XX_DXE_MEM_REG + 0x38) | ||
| 82 | #define WCN36XX_DXE_0_INT_ERR_CLR (WCN36XX_DXE_MEM_REG + 0x3C) | ||
| 83 | |||
| 84 | #define WCN36XX_DXE_0_CH0_STATUS (WCN36XX_DXE_MEM_REG + 0x404) | ||
| 85 | #define WCN36XX_DXE_0_CH1_STATUS (WCN36XX_DXE_MEM_REG + 0x444) | ||
| 86 | #define WCN36XX_DXE_0_CH2_STATUS (WCN36XX_DXE_MEM_REG + 0x484) | ||
| 87 | #define WCN36XX_DXE_0_CH3_STATUS (WCN36XX_DXE_MEM_REG + 0x4C4) | ||
| 88 | #define WCN36XX_DXE_0_CH4_STATUS (WCN36XX_DXE_MEM_REG + 0x504) | ||
| 89 | |||
| 90 | #define WCN36XX_DXE_REG_RESET 0x5c89 | ||
| 91 | |||
| 92 | /* Temporary BMU Workqueue 4 */ | ||
| 93 | #define WCN36XX_DXE_BMU_WQ_RX_LOW 0xB | ||
| 94 | #define WCN36XX_DXE_BMU_WQ_RX_HIGH 0x4 | ||
| 95 | /* DMA channel offset */ | ||
| 96 | #define WCN36XX_DXE_TX_LOW_OFFSET 0x400 | ||
| 97 | #define WCN36XX_DXE_TX_HIGH_OFFSET 0x500 | ||
| 98 | #define WCN36XX_DXE_RX_LOW_OFFSET 0x440 | ||
| 99 | #define WCN36XX_DXE_RX_HIGH_OFFSET 0x4C0 | ||
| 100 | |||
| 101 | /* Address of the next DXE descriptor */ | ||
| 102 | #define WCN36XX_DXE_CH_NEXT_DESC_ADDR 0x001C | ||
| 103 | #define WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_L (WCN36XX_DXE_MEM_REG + \ | ||
| 104 | WCN36XX_DXE_TX_LOW_OFFSET + \ | ||
| 105 | WCN36XX_DXE_CH_NEXT_DESC_ADDR) | ||
| 106 | #define WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_H (WCN36XX_DXE_MEM_REG + \ | ||
| 107 | WCN36XX_DXE_TX_HIGH_OFFSET + \ | ||
| 108 | WCN36XX_DXE_CH_NEXT_DESC_ADDR) | ||
| 109 | #define WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_L (WCN36XX_DXE_MEM_REG + \ | ||
| 110 | WCN36XX_DXE_RX_LOW_OFFSET + \ | ||
| 111 | WCN36XX_DXE_CH_NEXT_DESC_ADDR) | ||
| 112 | #define WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_H (WCN36XX_DXE_MEM_REG + \ | ||
| 113 | WCN36XX_DXE_RX_HIGH_OFFSET + \ | ||
| 114 | WCN36XX_DXE_CH_NEXT_DESC_ADDR) | ||
| 115 | |||
| 116 | /* DXE Descriptor source address */ | ||
| 117 | #define WCN36XX_DXE_CH_SRC_ADDR 0x000C | ||
| 118 | #define WCN36XX_DXE_CH_SRC_ADDR_RX_L (WCN36XX_DXE_MEM_REG + \ | ||
| 119 | WCN36XX_DXE_RX_LOW_OFFSET + \ | ||
| 120 | WCN36XX_DXE_CH_SRC_ADDR) | ||
| 121 | #define WCN36XX_DXE_CH_SRC_ADDR_RX_H (WCN36XX_DXE_MEM_REG + \ | ||
| 122 | WCN36XX_DXE_RX_HIGH_OFFSET + \ | ||
| 123 | WCN36XX_DXE_CH_SRC_ADDR) | ||
| 124 | |||
| 125 | /* DXE Descriptor address destination address */ | ||
| 126 | #define WCN36XX_DXE_CH_DEST_ADDR 0x0014 | ||
| 127 | #define WCN36XX_DXE_CH_DEST_ADDR_TX_L (WCN36XX_DXE_MEM_REG + \ | ||
| 128 | WCN36XX_DXE_TX_LOW_OFFSET + \ | ||
| 129 | WCN36XX_DXE_CH_DEST_ADDR) | ||
| 130 | #define WCN36XX_DXE_CH_DEST_ADDR_TX_H (WCN36XX_DXE_MEM_REG + \ | ||
| 131 | WCN36XX_DXE_TX_HIGH_OFFSET + \ | ||
| 132 | WCN36XX_DXE_CH_DEST_ADDR) | ||
| 133 | #define WCN36XX_DXE_CH_DEST_ADDR_RX_L (WCN36XX_DXE_MEM_REG + \ | ||
| 134 | WCN36XX_DXE_RX_LOW_OFFSET + \ | ||
| 135 | WCN36XX_DXE_CH_DEST_ADDR) | ||
| 136 | #define WCN36XX_DXE_CH_DEST_ADDR_RX_H (WCN36XX_DXE_MEM_REG + \ | ||
| 137 | WCN36XX_DXE_RX_HIGH_OFFSET + \ | ||
| 138 | WCN36XX_DXE_CH_DEST_ADDR) | ||
| 139 | |||
| 140 | /* Interrupt status */ | ||
| 141 | #define WCN36XX_DXE_CH_STATUS_REG_ADDR 0x0004 | ||
| 142 | #define WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_L (WCN36XX_DXE_MEM_REG + \ | ||
| 143 | WCN36XX_DXE_TX_LOW_OFFSET + \ | ||
| 144 | WCN36XX_DXE_CH_STATUS_REG_ADDR) | ||
| 145 | #define WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_H (WCN36XX_DXE_MEM_REG + \ | ||
| 146 | WCN36XX_DXE_TX_HIGH_OFFSET + \ | ||
| 147 | WCN36XX_DXE_CH_STATUS_REG_ADDR) | ||
| 148 | #define WCN36XX_DXE_CH_STATUS_REG_ADDR_RX_L (WCN36XX_DXE_MEM_REG + \ | ||
| 149 | WCN36XX_DXE_RX_LOW_OFFSET + \ | ||
| 150 | WCN36XX_DXE_CH_STATUS_REG_ADDR) | ||
| 151 | #define WCN36XX_DXE_CH_STATUS_REG_ADDR_RX_H (WCN36XX_DXE_MEM_REG + \ | ||
| 152 | WCN36XX_DXE_RX_HIGH_OFFSET + \ | ||
| 153 | WCN36XX_DXE_CH_STATUS_REG_ADDR) | ||
| 154 | |||
| 155 | |||
| 156 | /* DXE default control register */ | ||
| 157 | #define WCN36XX_DXE_REG_CTL_RX_L (WCN36XX_DXE_MEM_REG + \ | ||
| 158 | WCN36XX_DXE_RX_LOW_OFFSET) | ||
| 159 | #define WCN36XX_DXE_REG_CTL_RX_H (WCN36XX_DXE_MEM_REG + \ | ||
| 160 | WCN36XX_DXE_RX_HIGH_OFFSET) | ||
| 161 | #define WCN36XX_DXE_REG_CTL_TX_H (WCN36XX_DXE_MEM_REG + \ | ||
| 162 | WCN36XX_DXE_TX_HIGH_OFFSET) | ||
| 163 | #define WCN36XX_DXE_REG_CTL_TX_L (WCN36XX_DXE_MEM_REG + \ | ||
| 164 | WCN36XX_DXE_TX_LOW_OFFSET) | ||
| 165 | |||
| 166 | #define WCN36XX_SMSM_WLAN_TX_ENABLE 0x00000400 | ||
| 167 | #define WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY 0x00000200 | ||
| 168 | |||
| 169 | |||
| 170 | /* Interrupt control channel mask */ | ||
| 171 | #define WCN36XX_INT_MASK_CHAN_TX_L 0x00000001 | ||
| 172 | #define WCN36XX_INT_MASK_CHAN_RX_L 0x00000002 | ||
| 173 | #define WCN36XX_INT_MASK_CHAN_RX_H 0x00000008 | ||
| 174 | #define WCN36XX_INT_MASK_CHAN_TX_H 0x00000010 | ||
| 175 | |||
| 176 | #define WCN36XX_BD_CHUNK_SIZE 128 | ||
| 177 | |||
| 178 | #define WCN36XX_PKT_SIZE 0xF20 | ||
| 179 | enum wcn36xx_dxe_ch_type { | ||
| 180 | WCN36XX_DXE_CH_TX_L, | ||
| 181 | WCN36XX_DXE_CH_TX_H, | ||
| 182 | WCN36XX_DXE_CH_RX_L, | ||
| 183 | WCN36XX_DXE_CH_RX_H | ||
| 184 | }; | ||
| 185 | |||
| 186 | /* amount of descriptors per channel */ | ||
| 187 | enum wcn36xx_dxe_ch_desc_num { | ||
| 188 | WCN36XX_DXE_CH_DESC_NUMB_TX_L = 128, | ||
| 189 | WCN36XX_DXE_CH_DESC_NUMB_TX_H = 10, | ||
| 190 | WCN36XX_DXE_CH_DESC_NUMB_RX_L = 512, | ||
| 191 | WCN36XX_DXE_CH_DESC_NUMB_RX_H = 40 | ||
| 192 | }; | ||
| 193 | |||
| 194 | /** | ||
| 195 | * struct wcn36xx_dxe_desc - describes descriptor of one DXE buffer | ||
| 196 | * | ||
| 197 | * @ctrl: is a union that consists of following bits: | ||
| 198 | * union { | ||
| 199 | * u32 valid :1; //0 = DMA stop, 1 = DMA continue with this | ||
| 200 | * //descriptor | ||
| 201 | * u32 transfer_type :2; //0 = Host to Host space | ||
| 202 | * u32 eop :1; //End of Packet | ||
| 203 | * u32 bd_handling :1; //if transferType = Host to BMU, then 0 | ||
| 204 | * // means first 128 bytes contain BD, and 1 | ||
| 205 | * // means create new empty BD | ||
| 206 | * u32 siq :1; // SIQ | ||
| 207 | * u32 diq :1; // DIQ | ||
| 208 | * u32 pdu_rel :1; //0 = don't release BD and PDUs when done, | ||
| 209 | * // 1 = release them | ||
| 210 | * u32 bthld_sel :4; //BMU Threshold Select | ||
| 211 | * u32 prio :3; //Specifies the priority level to use for | ||
| 212 | * // the transfer | ||
| 213 | * u32 stop_channel :1; //1 = DMA stops processing further, channel | ||
| 214 | * //requires re-enabling after this | ||
| 215 | * u32 intr :1; //Interrupt on Descriptor Done | ||
| 216 | * u32 rsvd :1; //reserved | ||
| 217 | * u32 size :14;//14 bits used - ignored for BMU transfers, | ||
| 218 | * //only used for host to host transfers? | ||
| 219 | * } ctrl; | ||
| 220 | */ | ||
| 221 | struct wcn36xx_dxe_desc { | ||
| 222 | u32 ctrl; | ||
| 223 | u32 fr_len; | ||
| 224 | |||
| 225 | u32 src_addr_l; | ||
| 226 | u32 dst_addr_l; | ||
| 227 | u32 phy_next_l; | ||
| 228 | u32 src_addr_h; | ||
| 229 | u32 dst_addr_h; | ||
| 230 | u32 phy_next_h; | ||
| 231 | } __packed; | ||
| 232 | |||
| 233 | /* DXE Control block */ | ||
| 234 | struct wcn36xx_dxe_ctl { | ||
| 235 | struct wcn36xx_dxe_ctl *next; | ||
| 236 | struct wcn36xx_dxe_desc *desc; | ||
| 237 | unsigned int desc_phy_addr; | ||
| 238 | int ctl_blk_order; | ||
| 239 | struct sk_buff *skb; | ||
| 240 | spinlock_t skb_lock; | ||
| 241 | void *bd_cpu_addr; | ||
| 242 | dma_addr_t bd_phy_addr; | ||
| 243 | }; | ||
| 244 | |||
| 245 | struct wcn36xx_dxe_ch { | ||
| 246 | enum wcn36xx_dxe_ch_type ch_type; | ||
| 247 | void *cpu_addr; | ||
| 248 | dma_addr_t dma_addr; | ||
| 249 | enum wcn36xx_dxe_ch_desc_num desc_num; | ||
| 250 | /* DXE control block ring */ | ||
| 251 | struct wcn36xx_dxe_ctl *head_blk_ctl; | ||
| 252 | struct wcn36xx_dxe_ctl *tail_blk_ctl; | ||
| 253 | |||
| 254 | /* DXE channel specific configs */ | ||
| 255 | u32 dxe_wq; | ||
| 256 | u32 ctrl_bd; | ||
| 257 | u32 ctrl_skb; | ||
| 258 | u32 reg_ctrl; | ||
| 259 | u32 def_ctrl; | ||
| 260 | }; | ||
| 261 | |||
| 262 | /* Memory Pool for BD headers */ | ||
| 263 | struct wcn36xx_dxe_mem_pool { | ||
| 264 | int chunk_size; | ||
| 265 | void *virt_addr; | ||
| 266 | dma_addr_t phy_addr; | ||
| 267 | }; | ||
| 268 | |||
| 269 | struct wcn36xx_vif; | ||
| 270 | int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn); | ||
| 271 | void wcn36xx_dxe_free_mem_pools(struct wcn36xx *wcn); | ||
| 272 | void wcn36xx_dxe_rx_frame(struct wcn36xx *wcn); | ||
| 273 | int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn); | ||
| 274 | void wcn36xx_dxe_free_ctl_blks(struct wcn36xx *wcn); | ||
| 275 | int wcn36xx_dxe_init(struct wcn36xx *wcn); | ||
| 276 | void wcn36xx_dxe_deinit(struct wcn36xx *wcn); | ||
| 277 | int wcn36xx_dxe_init_channels(struct wcn36xx *wcn); | ||
| 278 | int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, | ||
| 279 | struct wcn36xx_vif *vif_priv, | ||
| 280 | struct sk_buff *skb, | ||
| 281 | bool is_low); | ||
| 282 | void wcn36xx_dxe_tx_ack_ind(struct wcn36xx *wcn, u32 status); | ||
| 283 | void *wcn36xx_dxe_get_next_bd(struct wcn36xx *wcn, bool is_low); | ||
| 284 | #endif /* _DXE_H_ */ | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h new file mode 100644 index 000000000000..c02dbc618724 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/hal.h | |||
| @@ -0,0 +1,4657 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef _HAL_H_ | ||
| 18 | #define _HAL_H_ | ||
| 19 | |||
| 20 | /*--------------------------------------------------------------------------- | ||
| 21 | API VERSIONING INFORMATION | ||
| 22 | |||
| 23 | The RIVA API is versioned as MAJOR.MINOR.VERSION.REVISION | ||
| 24 | The MAJOR is incremented for major product/architecture changes | ||
| 25 | (and then MINOR/VERSION/REVISION are zeroed) | ||
| 26 | The MINOR is incremented for minor product/architecture changes | ||
| 27 | (and then VERSION/REVISION are zeroed) | ||
| 28 | The VERSION is incremented if a significant API change occurs | ||
| 29 | (and then REVISION is zeroed) | ||
| 30 | The REVISION is incremented if an insignificant API change occurs | ||
| 31 | or if a new API is added | ||
| 32 | All values are in the range 0..255 (ie they are 8-bit values) | ||
| 33 | ---------------------------------------------------------------------------*/ | ||
| 34 | #define WCN36XX_HAL_VER_MAJOR 1 | ||
| 35 | #define WCN36XX_HAL_VER_MINOR 4 | ||
| 36 | #define WCN36XX_HAL_VER_VERSION 1 | ||
| 37 | #define WCN36XX_HAL_VER_REVISION 2 | ||
| 38 | |||
| 39 | /* This is to force compiler to use the maximum of an int ( 4 bytes ) */ | ||
| 40 | #define WCN36XX_HAL_MAX_ENUM_SIZE 0x7FFFFFFF | ||
| 41 | #define WCN36XX_HAL_MSG_TYPE_MAX_ENUM_SIZE 0x7FFF | ||
| 42 | |||
| 43 | /* Max no. of transmit categories */ | ||
| 44 | #define STACFG_MAX_TC 8 | ||
| 45 | |||
| 46 | /* The maximum value of access category */ | ||
| 47 | #define WCN36XX_HAL_MAX_AC 4 | ||
| 48 | |||
| 49 | #define WCN36XX_HAL_IPV4_ADDR_LEN 4 | ||
| 50 | |||
| 51 | #define WALN_HAL_STA_INVALID_IDX 0xFF | ||
| 52 | #define WCN36XX_HAL_BSS_INVALID_IDX 0xFF | ||
| 53 | |||
| 54 | /* Default Beacon template size */ | ||
| 55 | #define BEACON_TEMPLATE_SIZE 0x180 | ||
| 56 | |||
| 57 | /* Param Change Bitmap sent to HAL */ | ||
| 58 | #define PARAM_BCN_INTERVAL_CHANGED (1 << 0) | ||
| 59 | #define PARAM_SHORT_PREAMBLE_CHANGED (1 << 1) | ||
| 60 | #define PARAM_SHORT_SLOT_TIME_CHANGED (1 << 2) | ||
| 61 | #define PARAM_llACOEXIST_CHANGED (1 << 3) | ||
| 62 | #define PARAM_llBCOEXIST_CHANGED (1 << 4) | ||
| 63 | #define PARAM_llGCOEXIST_CHANGED (1 << 5) | ||
| 64 | #define PARAM_HT20MHZCOEXIST_CHANGED (1<<6) | ||
| 65 | #define PARAM_NON_GF_DEVICES_PRESENT_CHANGED (1<<7) | ||
| 66 | #define PARAM_RIFS_MODE_CHANGED (1<<8) | ||
| 67 | #define PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED (1<<9) | ||
| 68 | #define PARAM_OBSS_MODE_CHANGED (1<<10) | ||
| 69 | #define PARAM_BEACON_UPDATE_MASK \ | ||
| 70 | (PARAM_BCN_INTERVAL_CHANGED | \ | ||
| 71 | PARAM_SHORT_PREAMBLE_CHANGED | \ | ||
| 72 | PARAM_SHORT_SLOT_TIME_CHANGED | \ | ||
| 73 | PARAM_llACOEXIST_CHANGED | \ | ||
| 74 | PARAM_llBCOEXIST_CHANGED | \ | ||
| 75 | PARAM_llGCOEXIST_CHANGED | \ | ||
| 76 | PARAM_HT20MHZCOEXIST_CHANGED | \ | ||
| 77 | PARAM_NON_GF_DEVICES_PRESENT_CHANGED | \ | ||
| 78 | PARAM_RIFS_MODE_CHANGED | \ | ||
| 79 | PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED | \ | ||
| 80 | PARAM_OBSS_MODE_CHANGED) | ||
| 81 | |||
| 82 | /* dump command response Buffer size */ | ||
| 83 | #define DUMPCMD_RSP_BUFFER 100 | ||
| 84 | |||
| 85 | /* version string max length (including NULL) */ | ||
| 86 | #define WCN36XX_HAL_VERSION_LENGTH 64 | ||
| 87 | |||
| 88 | /* message types for messages exchanged between WDI and HAL */ | ||
| 89 | enum wcn36xx_hal_host_msg_type { | ||
| 90 | /* Init/De-Init */ | ||
| 91 | WCN36XX_HAL_START_REQ = 0, | ||
| 92 | WCN36XX_HAL_START_RSP = 1, | ||
| 93 | WCN36XX_HAL_STOP_REQ = 2, | ||
| 94 | WCN36XX_HAL_STOP_RSP = 3, | ||
| 95 | |||
| 96 | /* Scan */ | ||
| 97 | WCN36XX_HAL_INIT_SCAN_REQ = 4, | ||
| 98 | WCN36XX_HAL_INIT_SCAN_RSP = 5, | ||
| 99 | WCN36XX_HAL_START_SCAN_REQ = 6, | ||
| 100 | WCN36XX_HAL_START_SCAN_RSP = 7, | ||
| 101 | WCN36XX_HAL_END_SCAN_REQ = 8, | ||
| 102 | WCN36XX_HAL_END_SCAN_RSP = 9, | ||
| 103 | WCN36XX_HAL_FINISH_SCAN_REQ = 10, | ||
| 104 | WCN36XX_HAL_FINISH_SCAN_RSP = 11, | ||
| 105 | |||
| 106 | /* HW STA configuration/deconfiguration */ | ||
| 107 | WCN36XX_HAL_CONFIG_STA_REQ = 12, | ||
| 108 | WCN36XX_HAL_CONFIG_STA_RSP = 13, | ||
| 109 | WCN36XX_HAL_DELETE_STA_REQ = 14, | ||
| 110 | WCN36XX_HAL_DELETE_STA_RSP = 15, | ||
| 111 | WCN36XX_HAL_CONFIG_BSS_REQ = 16, | ||
| 112 | WCN36XX_HAL_CONFIG_BSS_RSP = 17, | ||
| 113 | WCN36XX_HAL_DELETE_BSS_REQ = 18, | ||
| 114 | WCN36XX_HAL_DELETE_BSS_RSP = 19, | ||
| 115 | |||
| 116 | /* Infra STA asscoiation */ | ||
| 117 | WCN36XX_HAL_JOIN_REQ = 20, | ||
| 118 | WCN36XX_HAL_JOIN_RSP = 21, | ||
| 119 | WCN36XX_HAL_POST_ASSOC_REQ = 22, | ||
| 120 | WCN36XX_HAL_POST_ASSOC_RSP = 23, | ||
| 121 | |||
| 122 | /* Security */ | ||
| 123 | WCN36XX_HAL_SET_BSSKEY_REQ = 24, | ||
| 124 | WCN36XX_HAL_SET_BSSKEY_RSP = 25, | ||
| 125 | WCN36XX_HAL_SET_STAKEY_REQ = 26, | ||
| 126 | WCN36XX_HAL_SET_STAKEY_RSP = 27, | ||
| 127 | WCN36XX_HAL_RMV_BSSKEY_REQ = 28, | ||
| 128 | WCN36XX_HAL_RMV_BSSKEY_RSP = 29, | ||
| 129 | WCN36XX_HAL_RMV_STAKEY_REQ = 30, | ||
| 130 | WCN36XX_HAL_RMV_STAKEY_RSP = 31, | ||
| 131 | |||
| 132 | /* Qos Related */ | ||
| 133 | WCN36XX_HAL_ADD_TS_REQ = 32, | ||
| 134 | WCN36XX_HAL_ADD_TS_RSP = 33, | ||
| 135 | WCN36XX_HAL_DEL_TS_REQ = 34, | ||
| 136 | WCN36XX_HAL_DEL_TS_RSP = 35, | ||
| 137 | WCN36XX_HAL_UPD_EDCA_PARAMS_REQ = 36, | ||
| 138 | WCN36XX_HAL_UPD_EDCA_PARAMS_RSP = 37, | ||
| 139 | WCN36XX_HAL_ADD_BA_REQ = 38, | ||
| 140 | WCN36XX_HAL_ADD_BA_RSP = 39, | ||
| 141 | WCN36XX_HAL_DEL_BA_REQ = 40, | ||
| 142 | WCN36XX_HAL_DEL_BA_RSP = 41, | ||
| 143 | |||
| 144 | WCN36XX_HAL_CH_SWITCH_REQ = 42, | ||
| 145 | WCN36XX_HAL_CH_SWITCH_RSP = 43, | ||
| 146 | WCN36XX_HAL_SET_LINK_ST_REQ = 44, | ||
| 147 | WCN36XX_HAL_SET_LINK_ST_RSP = 45, | ||
| 148 | WCN36XX_HAL_GET_STATS_REQ = 46, | ||
| 149 | WCN36XX_HAL_GET_STATS_RSP = 47, | ||
| 150 | WCN36XX_HAL_UPDATE_CFG_REQ = 48, | ||
| 151 | WCN36XX_HAL_UPDATE_CFG_RSP = 49, | ||
| 152 | |||
| 153 | WCN36XX_HAL_MISSED_BEACON_IND = 50, | ||
| 154 | WCN36XX_HAL_UNKNOWN_ADDR2_FRAME_RX_IND = 51, | ||
| 155 | WCN36XX_HAL_MIC_FAILURE_IND = 52, | ||
| 156 | WCN36XX_HAL_FATAL_ERROR_IND = 53, | ||
| 157 | WCN36XX_HAL_SET_KEYDONE_MSG = 54, | ||
| 158 | |||
| 159 | /* NV Interface */ | ||
| 160 | WCN36XX_HAL_DOWNLOAD_NV_REQ = 55, | ||
| 161 | WCN36XX_HAL_DOWNLOAD_NV_RSP = 56, | ||
| 162 | |||
| 163 | WCN36XX_HAL_ADD_BA_SESSION_REQ = 57, | ||
| 164 | WCN36XX_HAL_ADD_BA_SESSION_RSP = 58, | ||
| 165 | WCN36XX_HAL_TRIGGER_BA_REQ = 59, | ||
| 166 | WCN36XX_HAL_TRIGGER_BA_RSP = 60, | ||
| 167 | WCN36XX_HAL_UPDATE_BEACON_REQ = 61, | ||
| 168 | WCN36XX_HAL_UPDATE_BEACON_RSP = 62, | ||
| 169 | WCN36XX_HAL_SEND_BEACON_REQ = 63, | ||
| 170 | WCN36XX_HAL_SEND_BEACON_RSP = 64, | ||
| 171 | |||
| 172 | WCN36XX_HAL_SET_BCASTKEY_REQ = 65, | ||
| 173 | WCN36XX_HAL_SET_BCASTKEY_RSP = 66, | ||
| 174 | WCN36XX_HAL_DELETE_STA_CONTEXT_IND = 67, | ||
| 175 | WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ = 68, | ||
| 176 | WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_RSP = 69, | ||
| 177 | |||
| 178 | /* PTT interface support */ | ||
| 179 | WCN36XX_HAL_PROCESS_PTT_REQ = 70, | ||
| 180 | WCN36XX_HAL_PROCESS_PTT_RSP = 71, | ||
| 181 | |||
| 182 | /* BTAMP related events */ | ||
| 183 | WCN36XX_HAL_SIGNAL_BTAMP_EVENT_REQ = 72, | ||
| 184 | WCN36XX_HAL_SIGNAL_BTAMP_EVENT_RSP = 73, | ||
| 185 | WCN36XX_HAL_TL_HAL_FLUSH_AC_REQ = 74, | ||
| 186 | WCN36XX_HAL_TL_HAL_FLUSH_AC_RSP = 75, | ||
| 187 | |||
| 188 | WCN36XX_HAL_ENTER_IMPS_REQ = 76, | ||
| 189 | WCN36XX_HAL_EXIT_IMPS_REQ = 77, | ||
| 190 | WCN36XX_HAL_ENTER_BMPS_REQ = 78, | ||
| 191 | WCN36XX_HAL_EXIT_BMPS_REQ = 79, | ||
| 192 | WCN36XX_HAL_ENTER_UAPSD_REQ = 80, | ||
| 193 | WCN36XX_HAL_EXIT_UAPSD_REQ = 81, | ||
| 194 | WCN36XX_HAL_UPDATE_UAPSD_PARAM_REQ = 82, | ||
| 195 | WCN36XX_HAL_CONFIGURE_RXP_FILTER_REQ = 83, | ||
| 196 | WCN36XX_HAL_ADD_BCN_FILTER_REQ = 84, | ||
| 197 | WCN36XX_HAL_REM_BCN_FILTER_REQ = 85, | ||
| 198 | WCN36XX_HAL_ADD_WOWL_BCAST_PTRN = 86, | ||
| 199 | WCN36XX_HAL_DEL_WOWL_BCAST_PTRN = 87, | ||
| 200 | WCN36XX_HAL_ENTER_WOWL_REQ = 88, | ||
| 201 | WCN36XX_HAL_EXIT_WOWL_REQ = 89, | ||
| 202 | WCN36XX_HAL_HOST_OFFLOAD_REQ = 90, | ||
| 203 | WCN36XX_HAL_SET_RSSI_THRESH_REQ = 91, | ||
| 204 | WCN36XX_HAL_GET_RSSI_REQ = 92, | ||
| 205 | WCN36XX_HAL_SET_UAPSD_AC_PARAMS_REQ = 93, | ||
| 206 | WCN36XX_HAL_CONFIGURE_APPS_CPU_WAKEUP_STATE_REQ = 94, | ||
| 207 | |||
| 208 | WCN36XX_HAL_ENTER_IMPS_RSP = 95, | ||
| 209 | WCN36XX_HAL_EXIT_IMPS_RSP = 96, | ||
| 210 | WCN36XX_HAL_ENTER_BMPS_RSP = 97, | ||
| 211 | WCN36XX_HAL_EXIT_BMPS_RSP = 98, | ||
| 212 | WCN36XX_HAL_ENTER_UAPSD_RSP = 99, | ||
| 213 | WCN36XX_HAL_EXIT_UAPSD_RSP = 100, | ||
| 214 | WCN36XX_HAL_SET_UAPSD_AC_PARAMS_RSP = 101, | ||
| 215 | WCN36XX_HAL_UPDATE_UAPSD_PARAM_RSP = 102, | ||
| 216 | WCN36XX_HAL_CONFIGURE_RXP_FILTER_RSP = 103, | ||
| 217 | WCN36XX_HAL_ADD_BCN_FILTER_RSP = 104, | ||
| 218 | WCN36XX_HAL_REM_BCN_FILTER_RSP = 105, | ||
| 219 | WCN36XX_HAL_SET_RSSI_THRESH_RSP = 106, | ||
| 220 | WCN36XX_HAL_HOST_OFFLOAD_RSP = 107, | ||
| 221 | WCN36XX_HAL_ADD_WOWL_BCAST_PTRN_RSP = 108, | ||
| 222 | WCN36XX_HAL_DEL_WOWL_BCAST_PTRN_RSP = 109, | ||
| 223 | WCN36XX_HAL_ENTER_WOWL_RSP = 110, | ||
| 224 | WCN36XX_HAL_EXIT_WOWL_RSP = 111, | ||
| 225 | WCN36XX_HAL_RSSI_NOTIFICATION_IND = 112, | ||
| 226 | WCN36XX_HAL_GET_RSSI_RSP = 113, | ||
| 227 | WCN36XX_HAL_CONFIGURE_APPS_CPU_WAKEUP_STATE_RSP = 114, | ||
| 228 | |||
| 229 | /* 11k related events */ | ||
| 230 | WCN36XX_HAL_SET_MAX_TX_POWER_REQ = 115, | ||
| 231 | WCN36XX_HAL_SET_MAX_TX_POWER_RSP = 116, | ||
| 232 | |||
| 233 | /* 11R related msgs */ | ||
| 234 | WCN36XX_HAL_AGGR_ADD_TS_REQ = 117, | ||
| 235 | WCN36XX_HAL_AGGR_ADD_TS_RSP = 118, | ||
| 236 | |||
| 237 | /* P2P WLAN_FEATURE_P2P */ | ||
| 238 | WCN36XX_HAL_SET_P2P_GONOA_REQ = 119, | ||
| 239 | WCN36XX_HAL_SET_P2P_GONOA_RSP = 120, | ||
| 240 | |||
| 241 | /* WLAN Dump commands */ | ||
| 242 | WCN36XX_HAL_DUMP_COMMAND_REQ = 121, | ||
| 243 | WCN36XX_HAL_DUMP_COMMAND_RSP = 122, | ||
| 244 | |||
| 245 | /* OEM_DATA FEATURE SUPPORT */ | ||
| 246 | WCN36XX_HAL_START_OEM_DATA_REQ = 123, | ||
| 247 | WCN36XX_HAL_START_OEM_DATA_RSP = 124, | ||
| 248 | |||
| 249 | /* ADD SELF STA REQ and RSP */ | ||
| 250 | WCN36XX_HAL_ADD_STA_SELF_REQ = 125, | ||
| 251 | WCN36XX_HAL_ADD_STA_SELF_RSP = 126, | ||
| 252 | |||
| 253 | /* DEL SELF STA SUPPORT */ | ||
| 254 | WCN36XX_HAL_DEL_STA_SELF_REQ = 127, | ||
| 255 | WCN36XX_HAL_DEL_STA_SELF_RSP = 128, | ||
| 256 | |||
| 257 | /* Coex Indication */ | ||
| 258 | WCN36XX_HAL_COEX_IND = 129, | ||
| 259 | |||
| 260 | /* Tx Complete Indication */ | ||
| 261 | WCN36XX_HAL_OTA_TX_COMPL_IND = 130, | ||
| 262 | |||
| 263 | /* Host Suspend/resume messages */ | ||
| 264 | WCN36XX_HAL_HOST_SUSPEND_IND = 131, | ||
| 265 | WCN36XX_HAL_HOST_RESUME_REQ = 132, | ||
| 266 | WCN36XX_HAL_HOST_RESUME_RSP = 133, | ||
| 267 | |||
| 268 | WCN36XX_HAL_SET_TX_POWER_REQ = 134, | ||
| 269 | WCN36XX_HAL_SET_TX_POWER_RSP = 135, | ||
| 270 | WCN36XX_HAL_GET_TX_POWER_REQ = 136, | ||
| 271 | WCN36XX_HAL_GET_TX_POWER_RSP = 137, | ||
| 272 | |||
| 273 | WCN36XX_HAL_P2P_NOA_ATTR_IND = 138, | ||
| 274 | |||
| 275 | WCN36XX_HAL_ENABLE_RADAR_DETECT_REQ = 139, | ||
| 276 | WCN36XX_HAL_ENABLE_RADAR_DETECT_RSP = 140, | ||
| 277 | WCN36XX_HAL_GET_TPC_REPORT_REQ = 141, | ||
| 278 | WCN36XX_HAL_GET_TPC_REPORT_RSP = 142, | ||
| 279 | WCN36XX_HAL_RADAR_DETECT_IND = 143, | ||
| 280 | WCN36XX_HAL_RADAR_DETECT_INTR_IND = 144, | ||
| 281 | WCN36XX_HAL_KEEP_ALIVE_REQ = 145, | ||
| 282 | WCN36XX_HAL_KEEP_ALIVE_RSP = 146, | ||
| 283 | |||
| 284 | /* PNO messages */ | ||
| 285 | WCN36XX_HAL_SET_PREF_NETWORK_REQ = 147, | ||
| 286 | WCN36XX_HAL_SET_PREF_NETWORK_RSP = 148, | ||
| 287 | WCN36XX_HAL_SET_RSSI_FILTER_REQ = 149, | ||
| 288 | WCN36XX_HAL_SET_RSSI_FILTER_RSP = 150, | ||
| 289 | WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ = 151, | ||
| 290 | WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP = 152, | ||
| 291 | WCN36XX_HAL_PREF_NETW_FOUND_IND = 153, | ||
| 292 | |||
| 293 | WCN36XX_HAL_SET_TX_PER_TRACKING_REQ = 154, | ||
| 294 | WCN36XX_HAL_SET_TX_PER_TRACKING_RSP = 155, | ||
| 295 | WCN36XX_HAL_TX_PER_HIT_IND = 156, | ||
| 296 | |||
| 297 | WCN36XX_HAL_8023_MULTICAST_LIST_REQ = 157, | ||
| 298 | WCN36XX_HAL_8023_MULTICAST_LIST_RSP = 158, | ||
| 299 | |||
| 300 | WCN36XX_HAL_SET_PACKET_FILTER_REQ = 159, | ||
| 301 | WCN36XX_HAL_SET_PACKET_FILTER_RSP = 160, | ||
| 302 | WCN36XX_HAL_PACKET_FILTER_MATCH_COUNT_REQ = 161, | ||
| 303 | WCN36XX_HAL_PACKET_FILTER_MATCH_COUNT_RSP = 162, | ||
| 304 | WCN36XX_HAL_CLEAR_PACKET_FILTER_REQ = 163, | ||
| 305 | WCN36XX_HAL_CLEAR_PACKET_FILTER_RSP = 164, | ||
| 306 | |||
| 307 | /* | ||
| 308 | * This is temp fix. Should be removed once Host and Riva code is | ||
| 309 | * in sync. | ||
| 310 | */ | ||
| 311 | WCN36XX_HAL_INIT_SCAN_CON_REQ = 165, | ||
| 312 | |||
| 313 | WCN36XX_HAL_SET_POWER_PARAMS_REQ = 166, | ||
| 314 | WCN36XX_HAL_SET_POWER_PARAMS_RSP = 167, | ||
| 315 | |||
| 316 | WCN36XX_HAL_TSM_STATS_REQ = 168, | ||
| 317 | WCN36XX_HAL_TSM_STATS_RSP = 169, | ||
| 318 | |||
| 319 | /* wake reason indication (WOW) */ | ||
| 320 | WCN36XX_HAL_WAKE_REASON_IND = 170, | ||
| 321 | |||
| 322 | /* GTK offload support */ | ||
| 323 | WCN36XX_HAL_GTK_OFFLOAD_REQ = 171, | ||
| 324 | WCN36XX_HAL_GTK_OFFLOAD_RSP = 172, | ||
| 325 | WCN36XX_HAL_GTK_OFFLOAD_GETINFO_REQ = 173, | ||
| 326 | WCN36XX_HAL_GTK_OFFLOAD_GETINFO_RSP = 174, | ||
| 327 | |||
| 328 | WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ = 175, | ||
| 329 | WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP = 176, | ||
| 330 | WCN36XX_HAL_EXCLUDE_UNENCRYPTED_IND = 177, | ||
| 331 | |||
| 332 | WCN36XX_HAL_SET_THERMAL_MITIGATION_REQ = 178, | ||
| 333 | WCN36XX_HAL_SET_THERMAL_MITIGATION_RSP = 179, | ||
| 334 | |||
| 335 | WCN36XX_HAL_UPDATE_VHT_OP_MODE_REQ = 182, | ||
| 336 | WCN36XX_HAL_UPDATE_VHT_OP_MODE_RSP = 183, | ||
| 337 | |||
| 338 | WCN36XX_HAL_P2P_NOA_START_IND = 184, | ||
| 339 | |||
| 340 | WCN36XX_HAL_GET_ROAM_RSSI_REQ = 185, | ||
| 341 | WCN36XX_HAL_GET_ROAM_RSSI_RSP = 186, | ||
| 342 | |||
| 343 | WCN36XX_HAL_CLASS_B_STATS_IND = 187, | ||
| 344 | WCN36XX_HAL_DEL_BA_IND = 188, | ||
| 345 | WCN36XX_HAL_DHCP_START_IND = 189, | ||
| 346 | WCN36XX_HAL_DHCP_STOP_IND = 190, | ||
| 347 | |||
| 348 | WCN36XX_HAL_MSG_MAX = WCN36XX_HAL_MSG_TYPE_MAX_ENUM_SIZE | ||
| 349 | }; | ||
| 350 | |||
| 351 | /* Enumeration for Version */ | ||
| 352 | enum wcn36xx_hal_host_msg_version { | ||
| 353 | WCN36XX_HAL_MSG_VERSION0 = 0, | ||
| 354 | WCN36XX_HAL_MSG_VERSION1 = 1, | ||
| 355 | /* define as 2 bytes data */ | ||
| 356 | WCN36XX_HAL_MSG_WCNSS_CTRL_VERSION = 0x7FFF, | ||
| 357 | WCN36XX_HAL_MSG_VERSION_MAX_FIELD = WCN36XX_HAL_MSG_WCNSS_CTRL_VERSION | ||
| 358 | }; | ||
| 359 | |||
| 360 | enum driver_type { | ||
| 361 | DRIVER_TYPE_PRODUCTION = 0, | ||
| 362 | DRIVER_TYPE_MFG = 1, | ||
| 363 | DRIVER_TYPE_DVT = 2, | ||
| 364 | DRIVER_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
| 365 | }; | ||
| 366 | |||
| 367 | enum wcn36xx_hal_stop_type { | ||
| 368 | HAL_STOP_TYPE_SYS_RESET, | ||
| 369 | HAL_STOP_TYPE_SYS_DEEP_SLEEP, | ||
| 370 | HAL_STOP_TYPE_RF_KILL, | ||
| 371 | HAL_STOP_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
| 372 | }; | ||
| 373 | |||
| 374 | enum wcn36xx_hal_sys_mode { | ||
| 375 | HAL_SYS_MODE_NORMAL, | ||
| 376 | HAL_SYS_MODE_LEARN, | ||
| 377 | HAL_SYS_MODE_SCAN, | ||
| 378 | HAL_SYS_MODE_PROMISC, | ||
| 379 | HAL_SYS_MODE_SUSPEND_LINK, | ||
| 380 | HAL_SYS_MODE_ROAM_SCAN, | ||
| 381 | HAL_SYS_MODE_ROAM_SUSPEND_LINK, | ||
| 382 | HAL_SYS_MODE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
| 383 | }; | ||
| 384 | |||
| 385 | enum phy_chan_bond_state { | ||
| 386 | /* 20MHz IF bandwidth centered on IF carrier */ | ||
| 387 | PHY_SINGLE_CHANNEL_CENTERED = 0, | ||
| 388 | |||
| 389 | /* 40MHz IF bandwidth with lower 20MHz supporting the primary channel */ | ||
| 390 | PHY_DOUBLE_CHANNEL_LOW_PRIMARY = 1, | ||
| 391 | |||
| 392 | /* 40MHz IF bandwidth centered on IF carrier */ | ||
| 393 | PHY_DOUBLE_CHANNEL_CENTERED = 2, | ||
| 394 | |||
| 395 | /* 40MHz IF bandwidth with higher 20MHz supporting the primary ch */ | ||
| 396 | PHY_DOUBLE_CHANNEL_HIGH_PRIMARY = 3, | ||
| 397 | |||
| 398 | /* 20/40MHZ offset LOW 40/80MHZ offset CENTERED */ | ||
| 399 | PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED = 4, | ||
| 400 | |||
| 401 | /* 20/40MHZ offset CENTERED 40/80MHZ offset CENTERED */ | ||
| 402 | PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED = 5, | ||
| 403 | |||
| 404 | /* 20/40MHZ offset HIGH 40/80MHZ offset CENTERED */ | ||
| 405 | PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED = 6, | ||
| 406 | |||
| 407 | /* 20/40MHZ offset LOW 40/80MHZ offset LOW */ | ||
| 408 | PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW = 7, | ||
| 409 | |||
| 410 | /* 20/40MHZ offset HIGH 40/80MHZ offset LOW */ | ||
| 411 | PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW = 8, | ||
| 412 | |||
| 413 | /* 20/40MHZ offset LOW 40/80MHZ offset HIGH */ | ||
| 414 | PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH = 9, | ||
| 415 | |||
| 416 | /* 20/40MHZ offset-HIGH 40/80MHZ offset HIGH */ | ||
| 417 | PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH = 10, | ||
| 418 | |||
| 419 | PHY_CHANNEL_BONDING_STATE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
| 420 | }; | ||
| 421 | |||
| 422 | /* Spatial Multiplexing(SM) Power Save mode */ | ||
| 423 | enum wcn36xx_hal_ht_mimo_state { | ||
| 424 | /* Static SM Power Save mode */ | ||
| 425 | WCN36XX_HAL_HT_MIMO_PS_STATIC = 0, | ||
| 426 | |||
| 427 | /* Dynamic SM Power Save mode */ | ||
| 428 | WCN36XX_HAL_HT_MIMO_PS_DYNAMIC = 1, | ||
| 429 | |||
| 430 | /* reserved */ | ||
| 431 | WCN36XX_HAL_HT_MIMO_PS_NA = 2, | ||
| 432 | |||
| 433 | /* SM Power Save disabled */ | ||
| 434 | WCN36XX_HAL_HT_MIMO_PS_NO_LIMIT = 3, | ||
| 435 | |||
| 436 | WCN36XX_HAL_HT_MIMO_PS_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
| 437 | }; | ||
| 438 | |||
| 439 | /* each station added has a rate mode which specifies the sta attributes */ | ||
| 440 | enum sta_rate_mode { | ||
| 441 | STA_TAURUS = 0, | ||
| 442 | STA_TITAN, | ||
| 443 | STA_POLARIS, | ||
| 444 | STA_11b, | ||
| 445 | STA_11bg, | ||
| 446 | STA_11a, | ||
| 447 | STA_11n, | ||
| 448 | STA_11ac, | ||
| 449 | STA_INVALID_RATE_MODE = WCN36XX_HAL_MAX_ENUM_SIZE | ||
| 450 | }; | ||
| 451 | |||
| 452 | /* 1,2,5.5,11 */ | ||
| 453 | #define WCN36XX_HAL_NUM_DSSS_RATES 4 | ||
| 454 | |||
| 455 | /* 6,9,12,18,24,36,48,54 */ | ||
| 456 | #define WCN36XX_HAL_NUM_OFDM_RATES 8 | ||
| 457 | |||
| 458 | /* 72,96,108 */ | ||
| 459 | #define WCN36XX_HAL_NUM_POLARIS_RATES 3 | ||
| 460 | |||
| 461 | #define WCN36XX_HAL_MAC_MAX_SUPPORTED_MCS_SET 16 | ||
| 462 | |||
| 463 | enum wcn36xx_hal_bss_type { | ||
| 464 | WCN36XX_HAL_INFRASTRUCTURE_MODE, | ||
| 465 | |||
| 466 | /* Added for softAP support */ | ||
| 467 | WCN36XX_HAL_INFRA_AP_MODE, | ||
| 468 | |||
| 469 | WCN36XX_HAL_IBSS_MODE, | ||
| 470 | |||
| 471 | /* Added for BT-AMP support */ | ||
| 472 | WCN36XX_HAL_BTAMP_STA_MODE, | ||
| 473 | |||
| 474 | /* Added for BT-AMP support */ | ||
| 475 | WCN36XX_HAL_BTAMP_AP_MODE, | ||
| 476 | |||
| 477 | WCN36XX_HAL_AUTO_MODE, | ||
| 478 | |||
| 479 | WCN36XX_HAL_DONOT_USE_BSS_TYPE = WCN36XX_HAL_MAX_ENUM_SIZE | ||
| 480 | }; | ||
| 481 | |||
| 482 | enum wcn36xx_hal_nw_type { | ||
| 483 | WCN36XX_HAL_11A_NW_TYPE, | ||
| 484 | WCN36XX_HAL_11B_NW_TYPE, | ||
| 485 | WCN36XX_HAL_11G_NW_TYPE, | ||
| 486 | WCN36XX_HAL_11N_NW_TYPE, | ||
| 487 | WCN36XX_HAL_DONOT_USE_NW_TYPE = WCN36XX_HAL_MAX_ENUM_SIZE | ||
| 488 | }; | ||
| 489 | |||
| 490 | #define WCN36XX_HAL_MAC_RATESET_EID_MAX 12 | ||
| 491 | |||
| 492 | enum wcn36xx_hal_ht_operating_mode { | ||
| 493 | /* No Protection */ | ||
| 494 | WCN36XX_HAL_HT_OP_MODE_PURE, | ||
| 495 | |||
| 496 | /* Overlap Legacy device present, protection is optional */ | ||
| 497 | WCN36XX_HAL_HT_OP_MODE_OVERLAP_LEGACY, | ||
| 498 | |||
| 499 | /* No legacy device, but 20 MHz HT present */ | ||
| 500 | WCN36XX_HAL_HT_OP_MODE_NO_LEGACY_20MHZ_HT, | ||
| 501 | |||
| 502 | /* Protection is required */ | ||
| 503 | WCN36XX_HAL_HT_OP_MODE_MIXED, | ||
| 504 | |||
| 505 | WCN36XX_HAL_HT_OP_MODE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
| 506 | }; | ||
| 507 | |||
| 508 | /* Encryption type enum used with peer */ | ||
| 509 | enum ani_ed_type { | ||
| 510 | WCN36XX_HAL_ED_NONE, | ||
| 511 | WCN36XX_HAL_ED_WEP40, | ||
| 512 | WCN36XX_HAL_ED_WEP104, | ||
| 513 | WCN36XX_HAL_ED_TKIP, | ||
| 514 | WCN36XX_HAL_ED_CCMP, | ||
| 515 | WCN36XX_HAL_ED_WPI, | ||
| 516 | WCN36XX_HAL_ED_AES_128_CMAC, | ||
| 517 | WCN36XX_HAL_ED_NOT_IMPLEMENTED = WCN36XX_HAL_MAX_ENUM_SIZE | ||
| 518 | }; | ||
| 519 | |||
| 520 | #define WLAN_MAX_KEY_RSC_LEN 16 | ||
| 521 | #define WLAN_WAPI_KEY_RSC_LEN 16 | ||
| 522 | |||
| 523 | /* MAX key length when ULA is used */ | ||
| 524 | #define WCN36XX_HAL_MAC_MAX_KEY_LENGTH 32 | ||
| 525 | #define WCN36XX_HAL_MAC_MAX_NUM_OF_DEFAULT_KEYS 4 | ||
| 526 | |||
| 527 | /* | ||
| 528 | * Enum to specify whether key is used for TX only, RX only or both. | ||
| 529 | */ | ||
| 530 | enum ani_key_direction { | ||
| 531 | WCN36XX_HAL_TX_ONLY, | ||
| 532 | WCN36XX_HAL_RX_ONLY, | ||
| 533 | WCN36XX_HAL_TX_RX, | ||
| 534 | WCN36XX_HAL_TX_DEFAULT, | ||
| 535 | WCN36XX_HAL_DONOT_USE_KEY_DIRECTION = WCN36XX_HAL_MAX_ENUM_SIZE | ||
| 536 | }; | ||
| 537 | |||
| 538 | enum ani_wep_type { | ||
| 539 | WCN36XX_HAL_WEP_STATIC, | ||
| 540 | WCN36XX_HAL_WEP_DYNAMIC, | ||
| 541 | WCN36XX_HAL_WEP_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
| 542 | }; | ||
| 543 | |||
| 544 | enum wcn36xx_hal_link_state { | ||
| 545 | |||
| 546 | WCN36XX_HAL_LINK_IDLE_STATE = 0, | ||
| 547 | WCN36XX_HAL_LINK_PREASSOC_STATE = 1, | ||
| 548 | WCN36XX_HAL_LINK_POSTASSOC_STATE = 2, | ||
| 549 | WCN36XX_HAL_LINK_AP_STATE = 3, | ||
| 550 | WCN36XX_HAL_LINK_IBSS_STATE = 4, | ||
| 551 | |||
| 552 | /* BT-AMP Case */ | ||
| 553 | WCN36XX_HAL_LINK_BTAMP_PREASSOC_STATE = 5, | ||
| 554 | WCN36XX_HAL_LINK_BTAMP_POSTASSOC_STATE = 6, | ||
| 555 | WCN36XX_HAL_LINK_BTAMP_AP_STATE = 7, | ||
| 556 | WCN36XX_HAL_LINK_BTAMP_STA_STATE = 8, | ||
| 557 | |||
| 558 | /* Reserved for HAL Internal Use */ | ||
| 559 | WCN36XX_HAL_LINK_LEARN_STATE = 9, | ||
| 560 | WCN36XX_HAL_LINK_SCAN_STATE = 10, | ||
| 561 | WCN36XX_HAL_LINK_FINISH_SCAN_STATE = 11, | ||
| 562 | WCN36XX_HAL_LINK_INIT_CAL_STATE = 12, | ||
| 563 | WCN36XX_HAL_LINK_FINISH_CAL_STATE = 13, | ||
| 564 | WCN36XX_HAL_LINK_LISTEN_STATE = 14, | ||
| 565 | |||
| 566 | WCN36XX_HAL_LINK_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
| 567 | }; | ||
| 568 | |||
| 569 | enum wcn36xx_hal_stats_mask { | ||
| 570 | HAL_SUMMARY_STATS_INFO = 0x00000001, | ||
| 571 | HAL_GLOBAL_CLASS_A_STATS_INFO = 0x00000002, | ||
| 572 | HAL_GLOBAL_CLASS_B_STATS_INFO = 0x00000004, | ||
| 573 | HAL_GLOBAL_CLASS_C_STATS_INFO = 0x00000008, | ||
| 574 | HAL_GLOBAL_CLASS_D_STATS_INFO = 0x00000010, | ||
| 575 | HAL_PER_STA_STATS_INFO = 0x00000020 | ||
| 576 | }; | ||
| 577 | |||
| 578 | /* BT-AMP events type */ | ||
| 579 | enum bt_amp_event_type { | ||
| 580 | BTAMP_EVENT_CONNECTION_START, | ||
| 581 | BTAMP_EVENT_CONNECTION_STOP, | ||
| 582 | BTAMP_EVENT_CONNECTION_TERMINATED, | ||
| 583 | |||
| 584 | /* This and beyond are invalid values */ | ||
| 585 | BTAMP_EVENT_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE, | ||
| 586 | }; | ||
| 587 | |||
| 588 | /* PE Statistics */ | ||
| 589 | enum pe_stats_mask { | ||
| 590 | PE_SUMMARY_STATS_INFO = 0x00000001, | ||
| 591 | PE_GLOBAL_CLASS_A_STATS_INFO = 0x00000002, | ||
| 592 | PE_GLOBAL_CLASS_B_STATS_INFO = 0x00000004, | ||
| 593 | PE_GLOBAL_CLASS_C_STATS_INFO = 0x00000008, | ||
| 594 | PE_GLOBAL_CLASS_D_STATS_INFO = 0x00000010, | ||
| 595 | PE_PER_STA_STATS_INFO = 0x00000020, | ||
| 596 | |||
| 597 | /* This and beyond are invalid values */ | ||
| 598 | PE_STATS_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
| 599 | }; | ||
| 600 | |||
| 601 | /* | ||
| 602 | * Configuration Parameter IDs | ||
| 603 | */ | ||
| 604 | #define WCN36XX_HAL_CFG_STA_ID 0 | ||
| 605 | #define WCN36XX_HAL_CFG_CURRENT_TX_ANTENNA 1 | ||
| 606 | #define WCN36XX_HAL_CFG_CURRENT_RX_ANTENNA 2 | ||
| 607 | #define WCN36XX_HAL_CFG_LOW_GAIN_OVERRIDE 3 | ||
| 608 | #define WCN36XX_HAL_CFG_POWER_STATE_PER_CHAIN 4 | ||
| 609 | #define WCN36XX_HAL_CFG_CAL_PERIOD 5 | ||
| 610 | #define WCN36XX_HAL_CFG_CAL_CONTROL 6 | ||
| 611 | #define WCN36XX_HAL_CFG_PROXIMITY 7 | ||
| 612 | #define WCN36XX_HAL_CFG_NETWORK_DENSITY 8 | ||
| 613 | #define WCN36XX_HAL_CFG_MAX_MEDIUM_TIME 9 | ||
| 614 | #define WCN36XX_HAL_CFG_MAX_MPDUS_IN_AMPDU 10 | ||
| 615 | #define WCN36XX_HAL_CFG_RTS_THRESHOLD 11 | ||
| 616 | #define WCN36XX_HAL_CFG_SHORT_RETRY_LIMIT 12 | ||
| 617 | #define WCN36XX_HAL_CFG_LONG_RETRY_LIMIT 13 | ||
| 618 | #define WCN36XX_HAL_CFG_FRAGMENTATION_THRESHOLD 14 | ||
| 619 | #define WCN36XX_HAL_CFG_DYNAMIC_THRESHOLD_ZERO 15 | ||
| 620 | #define WCN36XX_HAL_CFG_DYNAMIC_THRESHOLD_ONE 16 | ||
| 621 | #define WCN36XX_HAL_CFG_DYNAMIC_THRESHOLD_TWO 17 | ||
| 622 | #define WCN36XX_HAL_CFG_FIXED_RATE 18 | ||
| 623 | #define WCN36XX_HAL_CFG_RETRYRATE_POLICY 19 | ||
| 624 | #define WCN36XX_HAL_CFG_RETRYRATE_SECONDARY 20 | ||
| 625 | #define WCN36XX_HAL_CFG_RETRYRATE_TERTIARY 21 | ||
| 626 | #define WCN36XX_HAL_CFG_FORCE_POLICY_PROTECTION 22 | ||
| 627 | #define WCN36XX_HAL_CFG_FIXED_RATE_MULTICAST_24GHZ 23 | ||
| 628 | #define WCN36XX_HAL_CFG_FIXED_RATE_MULTICAST_5GHZ 24 | ||
| 629 | #define WCN36XX_HAL_CFG_DEFAULT_RATE_INDEX_24GHZ 25 | ||
| 630 | #define WCN36XX_HAL_CFG_DEFAULT_RATE_INDEX_5GHZ 26 | ||
| 631 | #define WCN36XX_HAL_CFG_MAX_BA_SESSIONS 27 | ||
| 632 | #define WCN36XX_HAL_CFG_PS_DATA_INACTIVITY_TIMEOUT 28 | ||
| 633 | #define WCN36XX_HAL_CFG_PS_ENABLE_BCN_FILTER 29 | ||
| 634 | #define WCN36XX_HAL_CFG_PS_ENABLE_RSSI_MONITOR 30 | ||
| 635 | #define WCN36XX_HAL_CFG_NUM_BEACON_PER_RSSI_AVERAGE 31 | ||
| 636 | #define WCN36XX_HAL_CFG_STATS_PERIOD 32 | ||
| 637 | #define WCN36XX_HAL_CFG_CFP_MAX_DURATION 33 | ||
| 638 | #define WCN36XX_HAL_CFG_FRAME_TRANS_ENABLED 34 | ||
| 639 | #define WCN36XX_HAL_CFG_DTIM_PERIOD 35 | ||
| 640 | #define WCN36XX_HAL_CFG_EDCA_WMM_ACBK 36 | ||
| 641 | #define WCN36XX_HAL_CFG_EDCA_WMM_ACBE 37 | ||
| 642 | #define WCN36XX_HAL_CFG_EDCA_WMM_ACVO 38 | ||
| 643 | #define WCN36XX_HAL_CFG_EDCA_WMM_ACVI 39 | ||
| 644 | #define WCN36XX_HAL_CFG_BA_THRESHOLD_HIGH 40 | ||
| 645 | #define WCN36XX_HAL_CFG_MAX_BA_BUFFERS 41 | ||
| 646 | #define WCN36XX_HAL_CFG_RPE_POLLING_THRESHOLD 42 | ||
| 647 | #define WCN36XX_HAL_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG 43 | ||
| 648 | #define WCN36XX_HAL_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG 44 | ||
| 649 | #define WCN36XX_HAL_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG 45 | ||
| 650 | #define WCN36XX_HAL_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG 46 | ||
| 651 | #define WCN36XX_HAL_CFG_NO_OF_ONCHIP_REORDER_SESSIONS 47 | ||
| 652 | #define WCN36XX_HAL_CFG_PS_LISTEN_INTERVAL 48 | ||
| 653 | #define WCN36XX_HAL_CFG_PS_HEART_BEAT_THRESHOLD 49 | ||
| 654 | #define WCN36XX_HAL_CFG_PS_NTH_BEACON_FILTER 50 | ||
| 655 | #define WCN36XX_HAL_CFG_PS_MAX_PS_POLL 51 | ||
| 656 | #define WCN36XX_HAL_CFG_PS_MIN_RSSI_THRESHOLD 52 | ||
| 657 | #define WCN36XX_HAL_CFG_PS_RSSI_FILTER_PERIOD 53 | ||
| 658 | #define WCN36XX_HAL_CFG_PS_BROADCAST_FRAME_FILTER_ENABLE 54 | ||
| 659 | #define WCN36XX_HAL_CFG_PS_IGNORE_DTIM 55 | ||
| 660 | #define WCN36XX_HAL_CFG_PS_ENABLE_BCN_EARLY_TERM 56 | ||
| 661 | #define WCN36XX_HAL_CFG_DYNAMIC_PS_POLL_VALUE 57 | ||
| 662 | #define WCN36XX_HAL_CFG_PS_NULLDATA_AP_RESP_TIMEOUT 58 | ||
| 663 | #define WCN36XX_HAL_CFG_TELE_BCN_WAKEUP_EN 59 | ||
| 664 | #define WCN36XX_HAL_CFG_TELE_BCN_TRANS_LI 60 | ||
| 665 | #define WCN36XX_HAL_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS 61 | ||
| 666 | #define WCN36XX_HAL_CFG_TELE_BCN_MAX_LI 62 | ||
| 667 | #define WCN36XX_HAL_CFG_TELE_BCN_MAX_LI_IDLE_BCNS 63 | ||
| 668 | #define WCN36XX_HAL_CFG_TX_PWR_CTRL_ENABLE 64 | ||
| 669 | #define WCN36XX_HAL_CFG_VALID_RADAR_CHANNEL_LIST 65 | ||
| 670 | #define WCN36XX_HAL_CFG_TX_POWER_24_20 66 | ||
| 671 | #define WCN36XX_HAL_CFG_TX_POWER_24_40 67 | ||
| 672 | #define WCN36XX_HAL_CFG_TX_POWER_50_20 68 | ||
| 673 | #define WCN36XX_HAL_CFG_TX_POWER_50_40 69 | ||
| 674 | #define WCN36XX_HAL_CFG_MCAST_BCAST_FILTER_SETTING 70 | ||
| 675 | #define WCN36XX_HAL_CFG_BCN_EARLY_TERM_WAKEUP_INTERVAL 71 | ||
| 676 | #define WCN36XX_HAL_CFG_MAX_TX_POWER_2_4 72 | ||
| 677 | #define WCN36XX_HAL_CFG_MAX_TX_POWER_5 73 | ||
| 678 | #define WCN36XX_HAL_CFG_INFRA_STA_KEEP_ALIVE_PERIOD 74 | ||
| 679 | #define WCN36XX_HAL_CFG_ENABLE_CLOSE_LOOP 75 | ||
| 680 | #define WCN36XX_HAL_CFG_BTC_EXECUTION_MODE 76 | ||
| 681 | #define WCN36XX_HAL_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK 77 | ||
| 682 | #define WCN36XX_HAL_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS 78 | ||
| 683 | #define WCN36XX_HAL_CFG_PS_TX_INACTIVITY_TIMEOUT 79 | ||
| 684 | #define WCN36XX_HAL_CFG_WCNSS_API_VERSION 80 | ||
| 685 | #define WCN36XX_HAL_CFG_AP_KEEPALIVE_TIMEOUT 81 | ||
| 686 | #define WCN36XX_HAL_CFG_GO_KEEPALIVE_TIMEOUT 82 | ||
| 687 | #define WCN36XX_HAL_CFG_ENABLE_MC_ADDR_LIST 83 | ||
| 688 | #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_INQ_BT 84 | ||
| 689 | #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_PAGE_BT 85 | ||
| 690 | #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_CONN_BT 86 | ||
| 691 | #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_LE_BT 87 | ||
| 692 | #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_INQ_WLAN 88 | ||
| 693 | #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_PAGE_WLAN 89 | ||
| 694 | #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_CONN_WLAN 90 | ||
| 695 | #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_LE_WLAN 91 | ||
| 696 | #define WCN36XX_HAL_CFG_BTC_DYN_MAX_LEN_BT 92 | ||
| 697 | #define WCN36XX_HAL_CFG_BTC_DYN_MAX_LEN_WLAN 93 | ||
| 698 | #define WCN36XX_HAL_CFG_BTC_MAX_SCO_BLOCK_PERC 94 | ||
| 699 | #define WCN36XX_HAL_CFG_BTC_DHCP_PROT_ON_A2DP 95 | ||
| 700 | #define WCN36XX_HAL_CFG_BTC_DHCP_PROT_ON_SCO 96 | ||
| 701 | #define WCN36XX_HAL_CFG_ENABLE_UNICAST_FILTER 97 | ||
| 702 | #define WCN36XX_HAL_CFG_MAX_ASSOC_LIMIT 98 | ||
| 703 | #define WCN36XX_HAL_CFG_ENABLE_LPWR_IMG_TRANSITION 99 | ||
| 704 | #define WCN36XX_HAL_CFG_ENABLE_MCC_ADAPTIVE_SCHEDULER 100 | ||
| 705 | #define WCN36XX_HAL_CFG_ENABLE_DETECT_PS_SUPPORT 101 | ||
| 706 | #define WCN36XX_HAL_CFG_AP_LINK_MONITOR_TIMEOUT 102 | ||
| 707 | #define WCN36XX_HAL_CFG_BTC_DWELL_TIME_MULTIPLIER 103 | ||
| 708 | #define WCN36XX_HAL_CFG_ENABLE_TDLS_OXYGEN_MODE 104 | ||
| 709 | #define WCN36XX_HAL_CFG_MAX_PARAMS 105 | ||
| 710 | |||
| 711 | /* Message definitons - All the messages below need to be packed */ | ||
| 712 | |||
| 713 | /* Definition for HAL API Version. */ | ||
| 714 | struct wcnss_wlan_version { | ||
| 715 | u8 revision; | ||
| 716 | u8 version; | ||
| 717 | u8 minor; | ||
| 718 | u8 major; | ||
| 719 | } __packed; | ||
| 720 | |||
| 721 | /* Definition for Encryption Keys */ | ||
| 722 | struct wcn36xx_hal_keys { | ||
| 723 | u8 id; | ||
| 724 | |||
| 725 | /* 0 for multicast */ | ||
| 726 | u8 unicast; | ||
| 727 | |||
| 728 | enum ani_key_direction direction; | ||
| 729 | |||
| 730 | /* Usage is unknown */ | ||
| 731 | u8 rsc[WLAN_MAX_KEY_RSC_LEN]; | ||
| 732 | |||
| 733 | /* =1 for authenticator,=0 for supplicant */ | ||
| 734 | u8 pae_role; | ||
| 735 | |||
| 736 | u16 length; | ||
| 737 | u8 key[WCN36XX_HAL_MAC_MAX_KEY_LENGTH]; | ||
| 738 | } __packed; | ||
| 739 | |||
| 740 | /* | ||
| 741 | * set_sta_key_params Moving here since it is shared by | ||
| 742 | * configbss/setstakey msgs | ||
| 743 | */ | ||
| 744 | struct wcn36xx_hal_set_sta_key_params { | ||
| 745 | /* STA Index */ | ||
| 746 | u16 sta_index; | ||
| 747 | |||
| 748 | /* Encryption Type used with peer */ | ||
| 749 | enum ani_ed_type enc_type; | ||
| 750 | |||
| 751 | /* STATIC/DYNAMIC - valid only for WEP */ | ||
| 752 | enum ani_wep_type wep_type; | ||
| 753 | |||
| 754 | /* Default WEP key, valid only for static WEP, must between 0 and 3. */ | ||
| 755 | u8 def_wep_idx; | ||
| 756 | |||
| 757 | /* valid only for non-static WEP encyrptions */ | ||
| 758 | struct wcn36xx_hal_keys key[WCN36XX_HAL_MAC_MAX_NUM_OF_DEFAULT_KEYS]; | ||
| 759 | |||
| 760 | /* | ||
| 761 | * Control for Replay Count, 1= Single TID based replay count on Tx | ||
| 762 | * 0 = Per TID based replay count on TX | ||
| 763 | */ | ||
| 764 | u8 single_tid_rc; | ||
| 765 | |||
| 766 | } __packed; | ||
| 767 | |||
| 768 | /* 4-byte control message header used by HAL*/ | ||
| 769 | struct wcn36xx_hal_msg_header { | ||
| 770 | enum wcn36xx_hal_host_msg_type msg_type:16; | ||
| 771 | enum wcn36xx_hal_host_msg_version msg_version:16; | ||
| 772 | u32 len; | ||
| 773 | } __packed; | ||
| 774 | |||
| 775 | /* Config format required by HAL for each CFG item*/ | ||
| 776 | struct wcn36xx_hal_cfg { | ||
| 777 | /* Cfg Id. The Id required by HAL is exported by HAL | ||
| 778 | * in shared header file between UMAC and HAL.*/ | ||
| 779 | u16 id; | ||
| 780 | |||
| 781 | /* Length of the Cfg. This parameter is used to go to next cfg | ||
| 782 | * in the TLV format.*/ | ||
| 783 | u16 len; | ||
| 784 | |||
| 785 | /* Padding bytes for unaligned address's */ | ||
| 786 | u16 pad_bytes; | ||
| 787 | |||
| 788 | /* Reserve bytes for making cfgVal to align address */ | ||
| 789 | u16 reserve; | ||
| 790 | |||
| 791 | /* Following the uCfgLen field there should be a 'uCfgLen' bytes | ||
| 792 | * containing the uCfgValue ; u8 uCfgValue[uCfgLen] */ | ||
| 793 | } __packed; | ||
| 794 | |||
| 795 | struct wcn36xx_hal_mac_start_parameters { | ||
| 796 | /* Drive Type - Production or FTM etc */ | ||
| 797 | enum driver_type type; | ||
| 798 | |||
| 799 | /* Length of the config buffer */ | ||
| 800 | u32 len; | ||
| 801 | |||
| 802 | /* Following this there is a TLV formatted buffer of length | ||
| 803 | * "len" bytes containing all config values. | ||
| 804 | * The TLV is expected to be formatted like this: | ||
| 805 | * 0 15 31 31+CFG_LEN-1 length-1 | ||
| 806 | * | CFG_ID | CFG_LEN | CFG_BODY | CFG_ID |......| | ||
| 807 | */ | ||
| 808 | } __packed; | ||
| 809 | |||
| 810 | struct wcn36xx_hal_mac_start_req_msg { | ||
| 811 | /* config buffer must start in TLV format just here */ | ||
| 812 | struct wcn36xx_hal_msg_header header; | ||
| 813 | struct wcn36xx_hal_mac_start_parameters params; | ||
| 814 | } __packed; | ||
| 815 | |||
| 816 | struct wcn36xx_hal_mac_start_rsp_params { | ||
| 817 | /* success or failure */ | ||
| 818 | u16 status; | ||
| 819 | |||
| 820 | /* Max number of STA supported by the device */ | ||
| 821 | u8 stations; | ||
| 822 | |||
| 823 | /* Max number of BSS supported by the device */ | ||
| 824 | u8 bssids; | ||
| 825 | |||
| 826 | /* API Version */ | ||
| 827 | struct wcnss_wlan_version version; | ||
| 828 | |||
| 829 | /* CRM build information */ | ||
| 830 | u8 crm_version[WCN36XX_HAL_VERSION_LENGTH]; | ||
| 831 | |||
| 832 | /* hardware/chipset/misc version information */ | ||
| 833 | u8 wlan_version[WCN36XX_HAL_VERSION_LENGTH]; | ||
| 834 | |||
| 835 | } __packed; | ||
| 836 | |||
| 837 | struct wcn36xx_hal_mac_start_rsp_msg { | ||
| 838 | struct wcn36xx_hal_msg_header header; | ||
| 839 | struct wcn36xx_hal_mac_start_rsp_params start_rsp_params; | ||
| 840 | } __packed; | ||
| 841 | |||
| 842 | struct wcn36xx_hal_mac_stop_req_params { | ||
| 843 | /* The reason for which the device is being stopped */ | ||
| 844 | enum wcn36xx_hal_stop_type reason; | ||
| 845 | |||
| 846 | } __packed; | ||
| 847 | |||
| 848 | struct wcn36xx_hal_mac_stop_req_msg { | ||
| 849 | struct wcn36xx_hal_msg_header header; | ||
| 850 | struct wcn36xx_hal_mac_stop_req_params stop_req_params; | ||
| 851 | } __packed; | ||
| 852 | |||
| 853 | struct wcn36xx_hal_mac_stop_rsp_msg { | ||
| 854 | struct wcn36xx_hal_msg_header header; | ||
| 855 | |||
| 856 | /* success or failure */ | ||
| 857 | u32 status; | ||
| 858 | } __packed; | ||
| 859 | |||
| 860 | struct wcn36xx_hal_update_cfg_req_msg { | ||
| 861 | /* | ||
| 862 | * Note: The length specified in tHalUpdateCfgReqMsg messages should be | ||
| 863 | * header.msgLen = sizeof(tHalUpdateCfgReqMsg) + uConfigBufferLen | ||
| 864 | */ | ||
| 865 | struct wcn36xx_hal_msg_header header; | ||
| 866 | |||
| 867 | /* Length of the config buffer. Allows UMAC to update multiple CFGs */ | ||
| 868 | u32 len; | ||
| 869 | |||
| 870 | /* | ||
| 871 | * Following this there is a TLV formatted buffer of length | ||
| 872 | * "uConfigBufferLen" bytes containing all config values. | ||
| 873 | * The TLV is expected to be formatted like this: | ||
| 874 | * 0 15 31 31+CFG_LEN-1 length-1 | ||
| 875 | * | CFG_ID | CFG_LEN | CFG_BODY | CFG_ID |......| | ||
| 876 | */ | ||
| 877 | |||
| 878 | } __packed; | ||
| 879 | |||
| 880 | struct wcn36xx_hal_update_cfg_rsp_msg { | ||
| 881 | struct wcn36xx_hal_msg_header header; | ||
| 882 | |||
| 883 | /* success or failure */ | ||
| 884 | u32 status; | ||
| 885 | |||
| 886 | } __packed; | ||
| 887 | |||
| 888 | /* Frame control field format (2 bytes) */ | ||
| 889 | struct wcn36xx_hal_mac_frame_ctl { | ||
| 890 | |||
| 891 | #ifndef ANI_LITTLE_BIT_ENDIAN | ||
| 892 | |||
| 893 | u8 subType:4; | ||
| 894 | u8 type:2; | ||
| 895 | u8 protVer:2; | ||
| 896 | |||
| 897 | u8 order:1; | ||
| 898 | u8 wep:1; | ||
| 899 | u8 moreData:1; | ||
| 900 | u8 powerMgmt:1; | ||
| 901 | u8 retry:1; | ||
| 902 | u8 moreFrag:1; | ||
| 903 | u8 fromDS:1; | ||
| 904 | u8 toDS:1; | ||
| 905 | |||
| 906 | #else | ||
| 907 | |||
| 908 | u8 protVer:2; | ||
| 909 | u8 type:2; | ||
| 910 | u8 subType:4; | ||
| 911 | |||
| 912 | u8 toDS:1; | ||
| 913 | u8 fromDS:1; | ||
| 914 | u8 moreFrag:1; | ||
| 915 | u8 retry:1; | ||
| 916 | u8 powerMgmt:1; | ||
| 917 | u8 moreData:1; | ||
| 918 | u8 wep:1; | ||
| 919 | u8 order:1; | ||
| 920 | |||
| 921 | #endif | ||
| 922 | |||
| 923 | }; | ||
| 924 | |||
| 925 | /* Sequence control field */ | ||
| 926 | struct wcn36xx_hal_mac_seq_ctl { | ||
| 927 | u8 fragNum:4; | ||
| 928 | u8 seqNumLo:4; | ||
| 929 | u8 seqNumHi:8; | ||
| 930 | }; | ||
| 931 | |||
| 932 | /* Management header format */ | ||
| 933 | struct wcn36xx_hal_mac_mgmt_hdr { | ||
| 934 | struct wcn36xx_hal_mac_frame_ctl fc; | ||
| 935 | u8 durationLo; | ||
| 936 | u8 durationHi; | ||
| 937 | u8 da[6]; | ||
| 938 | u8 sa[6]; | ||
| 939 | u8 bssId[6]; | ||
| 940 | struct wcn36xx_hal_mac_seq_ctl seqControl; | ||
| 941 | }; | ||
| 942 | |||
| 943 | /* FIXME: pronto v1 apparently has 4 */ | ||
| 944 | #define WCN36XX_HAL_NUM_BSSID 2 | ||
| 945 | |||
| 946 | /* Scan Entry to hold active BSS idx's */ | ||
| 947 | struct wcn36xx_hal_scan_entry { | ||
| 948 | u8 bss_index[WCN36XX_HAL_NUM_BSSID]; | ||
| 949 | u8 active_bss_count; | ||
| 950 | }; | ||
| 951 | |||
| 952 | struct wcn36xx_hal_init_scan_req_msg { | ||
| 953 | struct wcn36xx_hal_msg_header header; | ||
| 954 | |||
| 955 | /* LEARN - AP Role | ||
| 956 | SCAN - STA Role */ | ||
| 957 | enum wcn36xx_hal_sys_mode mode; | ||
| 958 | |||
| 959 | /* BSSID of the BSS */ | ||
| 960 | u8 bssid[ETH_ALEN]; | ||
| 961 | |||
| 962 | /* Whether BSS needs to be notified */ | ||
| 963 | u8 notify; | ||
| 964 | |||
| 965 | /* Kind of frame to be used for notifying the BSS (Data Null, QoS | ||
| 966 | * Null, or CTS to Self). Must always be a valid frame type. */ | ||
| 967 | u8 frame_type; | ||
| 968 | |||
| 969 | /* UMAC has the option of passing the MAC frame to be used for | ||
| 970 | * notifying the BSS. If non-zero, HAL will use the MAC frame | ||
| 971 | * buffer pointed to by macMgmtHdr. If zero, HAL will generate the | ||
| 972 | * appropriate MAC frame based on frameType. */ | ||
| 973 | u8 frame_len; | ||
| 974 | |||
| 975 | /* Following the framelength there is a MAC frame buffer if | ||
| 976 | * frameLength is non-zero. */ | ||
| 977 | struct wcn36xx_hal_mac_mgmt_hdr mac_mgmt_hdr; | ||
| 978 | |||
| 979 | /* Entry to hold number of active BSS idx's */ | ||
| 980 | struct wcn36xx_hal_scan_entry scan_entry; | ||
| 981 | }; | ||
| 982 | |||
| 983 | struct wcn36xx_hal_init_scan_con_req_msg { | ||
| 984 | struct wcn36xx_hal_msg_header header; | ||
| 985 | |||
| 986 | /* LEARN - AP Role | ||
| 987 | SCAN - STA Role */ | ||
| 988 | enum wcn36xx_hal_sys_mode mode; | ||
| 989 | |||
| 990 | /* BSSID of the BSS */ | ||
| 991 | u8 bssid[ETH_ALEN]; | ||
| 992 | |||
| 993 | /* Whether BSS needs to be notified */ | ||
| 994 | u8 notify; | ||
| 995 | |||
| 996 | /* Kind of frame to be used for notifying the BSS (Data Null, QoS | ||
| 997 | * Null, or CTS to Self). Must always be a valid frame type. */ | ||
| 998 | u8 frame_type; | ||
| 999 | |||
| 1000 | /* UMAC has the option of passing the MAC frame to be used for | ||
| 1001 | * notifying the BSS. If non-zero, HAL will use the MAC frame | ||
| 1002 | * buffer pointed to by macMgmtHdr. If zero, HAL will generate the | ||
| 1003 | * appropriate MAC frame based on frameType. */ | ||
| 1004 | u8 frame_length; | ||
| 1005 | |||
| 1006 | /* Following the framelength there is a MAC frame buffer if | ||
| 1007 | * frameLength is non-zero. */ | ||
| 1008 | struct wcn36xx_hal_mac_mgmt_hdr mac_mgmt_hdr; | ||
| 1009 | |||
| 1010 | /* Entry to hold number of active BSS idx's */ | ||
| 1011 | struct wcn36xx_hal_scan_entry scan_entry; | ||
| 1012 | |||
| 1013 | /* Single NoA usage in Scanning */ | ||
| 1014 | u8 use_noa; | ||
| 1015 | |||
| 1016 | /* Indicates the scan duration (in ms) */ | ||
| 1017 | u16 scan_duration; | ||
| 1018 | |||
| 1019 | }; | ||
| 1020 | |||
| 1021 | struct wcn36xx_hal_init_scan_rsp_msg { | ||
| 1022 | struct wcn36xx_hal_msg_header header; | ||
| 1023 | |||
| 1024 | /* success or failure */ | ||
| 1025 | u32 status; | ||
| 1026 | |||
| 1027 | } __packed; | ||
| 1028 | |||
| 1029 | struct wcn36xx_hal_start_scan_req_msg { | ||
| 1030 | struct wcn36xx_hal_msg_header header; | ||
| 1031 | |||
| 1032 | /* Indicates the channel to scan */ | ||
| 1033 | u8 scan_channel; | ||
| 1034 | } __packed; | ||
| 1035 | |||
| 1036 | struct wcn36xx_hal_start_rsp_msg { | ||
| 1037 | struct wcn36xx_hal_msg_header header; | ||
| 1038 | |||
| 1039 | /* success or failure */ | ||
| 1040 | u32 status; | ||
| 1041 | |||
| 1042 | u32 start_tsf[2]; | ||
| 1043 | u8 tx_mgmt_power; | ||
| 1044 | |||
| 1045 | } __packed; | ||
| 1046 | |||
| 1047 | struct wcn36xx_hal_end_scan_req_msg { | ||
| 1048 | struct wcn36xx_hal_msg_header header; | ||
| 1049 | |||
| 1050 | /* Indicates the channel to stop scanning. Not used really. But | ||
| 1051 | * retained for symmetry with "start Scan" message. It can also | ||
| 1052 | * help in error check if needed. */ | ||
| 1053 | u8 scan_channel; | ||
| 1054 | } __packed; | ||
| 1055 | |||
| 1056 | struct wcn36xx_hal_end_scan_rsp_msg { | ||
| 1057 | struct wcn36xx_hal_msg_header header; | ||
| 1058 | |||
| 1059 | /* success or failure */ | ||
| 1060 | u32 status; | ||
| 1061 | } __packed; | ||
| 1062 | |||
| 1063 | struct wcn36xx_hal_finish_scan_req_msg { | ||
| 1064 | struct wcn36xx_hal_msg_header header; | ||
| 1065 | |||
| 1066 | /* Identifies the operational state of the AP/STA | ||
| 1067 | * LEARN - AP Role SCAN - STA Role */ | ||
| 1068 | enum wcn36xx_hal_sys_mode mode; | ||
| 1069 | |||
| 1070 | /* Operating channel to tune to. */ | ||
| 1071 | u8 oper_channel; | ||
| 1072 | |||
| 1073 | /* Channel Bonding state If 20/40 MHz is operational, this will | ||
| 1074 | * indicate the 40 MHz extension channel in combination with the | ||
| 1075 | * control channel */ | ||
| 1076 | enum phy_chan_bond_state cb_state; | ||
| 1077 | |||
| 1078 | /* BSSID of the BSS */ | ||
| 1079 | u8 bssid[ETH_ALEN]; | ||
| 1080 | |||
| 1081 | /* Whether BSS needs to be notified */ | ||
| 1082 | u8 notify; | ||
| 1083 | |||
| 1084 | /* Kind of frame to be used for notifying the BSS (Data Null, QoS | ||
| 1085 | * Null, or CTS to Self). Must always be a valid frame type. */ | ||
| 1086 | u8 frame_type; | ||
| 1087 | |||
| 1088 | /* UMAC has the option of passing the MAC frame to be used for | ||
| 1089 | * notifying the BSS. If non-zero, HAL will use the MAC frame | ||
| 1090 | * buffer pointed to by macMgmtHdr. If zero, HAL will generate the | ||
| 1091 | * appropriate MAC frame based on frameType. */ | ||
| 1092 | u8 frame_length; | ||
| 1093 | |||
| 1094 | /* Following the framelength there is a MAC frame buffer if | ||
| 1095 | * frameLength is non-zero. */ | ||
| 1096 | struct wcn36xx_hal_mac_mgmt_hdr mac_mgmt_hdr; | ||
| 1097 | |||
| 1098 | /* Entry to hold number of active BSS idx's */ | ||
| 1099 | struct wcn36xx_hal_scan_entry scan_entry; | ||
| 1100 | |||
| 1101 | } __packed; | ||
| 1102 | |||
| 1103 | struct wcn36xx_hal_finish_scan_rsp_msg { | ||
| 1104 | struct wcn36xx_hal_msg_header header; | ||
| 1105 | |||
| 1106 | /* success or failure */ | ||
| 1107 | u32 status; | ||
| 1108 | |||
| 1109 | } __packed; | ||
| 1110 | |||
| 1111 | enum wcn36xx_hal_rate_index { | ||
| 1112 | HW_RATE_INDEX_1MBPS = 0x82, | ||
| 1113 | HW_RATE_INDEX_2MBPS = 0x84, | ||
| 1114 | HW_RATE_INDEX_5_5MBPS = 0x8B, | ||
| 1115 | HW_RATE_INDEX_6MBPS = 0x0C, | ||
| 1116 | HW_RATE_INDEX_9MBPS = 0x12, | ||
| 1117 | HW_RATE_INDEX_11MBPS = 0x96, | ||
| 1118 | HW_RATE_INDEX_12MBPS = 0x18, | ||
| 1119 | HW_RATE_INDEX_18MBPS = 0x24, | ||
| 1120 | HW_RATE_INDEX_24MBPS = 0x30, | ||
| 1121 | HW_RATE_INDEX_36MBPS = 0x48, | ||
| 1122 | HW_RATE_INDEX_48MBPS = 0x60, | ||
| 1123 | HW_RATE_INDEX_54MBPS = 0x6C | ||
| 1124 | }; | ||
| 1125 | |||
| 1126 | struct wcn36xx_hal_supported_rates { | ||
| 1127 | /* | ||
| 1128 | * For Self STA Entry: this represents Self Mode. | ||
| 1129 | * For Peer Stations, this represents the mode of the peer. | ||
| 1130 | * On Station: | ||
| 1131 | * | ||
| 1132 | * --this mode is updated when PE adds the Self Entry. | ||
| 1133 | * | ||
| 1134 | * -- OR when PE sends 'ADD_BSS' message and station context in BSS | ||
| 1135 | * is used to indicate the mode of the AP. | ||
| 1136 | * | ||
| 1137 | * ON AP: | ||
| 1138 | * | ||
| 1139 | * -- this mode is updated when PE sends 'ADD_BSS' and Sta entry | ||
| 1140 | * for that BSS is used to indicate the self mode of the AP. | ||
| 1141 | * | ||
| 1142 | * -- OR when a station is associated, PE sends 'ADD_STA' message | ||
| 1143 | * with this mode updated. | ||
| 1144 | */ | ||
| 1145 | |||
| 1146 | enum sta_rate_mode op_rate_mode; | ||
| 1147 | |||
| 1148 | /* 11b, 11a and aniLegacyRates are IE rates which gives rate in | ||
| 1149 | * unit of 500Kbps */ | ||
| 1150 | u16 dsss_rates[WCN36XX_HAL_NUM_DSSS_RATES]; | ||
| 1151 | u16 ofdm_rates[WCN36XX_HAL_NUM_OFDM_RATES]; | ||
| 1152 | u16 legacy_rates[WCN36XX_HAL_NUM_POLARIS_RATES]; | ||
| 1153 | u16 reserved; | ||
| 1154 | |||
| 1155 | /* Taurus only supports 26 Titan Rates(no ESF/concat Rates will be | ||
| 1156 | * supported) First 26 bits are reserved for those Titan rates and | ||
| 1157 | * the last 4 bits(bit28-31) for Taurus, 2(bit26-27) bits are | ||
| 1158 | * reserved. */ | ||
| 1159 | /* Titan and Taurus Rates */ | ||
| 1160 | u32 enhanced_rate_bitmap; | ||
| 1161 | |||
| 1162 | /* | ||
| 1163 | * 0-76 bits used, remaining reserved | ||
| 1164 | * bits 0-15 and 32 should be set. | ||
| 1165 | */ | ||
| 1166 | u8 supported_mcs_set[WCN36XX_HAL_MAC_MAX_SUPPORTED_MCS_SET]; | ||
| 1167 | |||
| 1168 | /* | ||
| 1169 | * RX Highest Supported Data Rate defines the highest data | ||
| 1170 | * rate that the STA is able to receive, in unites of 1Mbps. | ||
| 1171 | * This value is derived from "Supported MCS Set field" inside | ||
| 1172 | * the HT capability element. | ||
| 1173 | */ | ||
| 1174 | u16 rx_highest_data_rate; | ||
| 1175 | |||
| 1176 | } __packed; | ||
| 1177 | |||
| 1178 | struct wcn36xx_hal_config_sta_params { | ||
| 1179 | /* BSSID of STA */ | ||
| 1180 | u8 bssid[ETH_ALEN]; | ||
| 1181 | |||
| 1182 | /* ASSOC ID, as assigned by UMAC */ | ||
| 1183 | u16 aid; | ||
| 1184 | |||
| 1185 | /* STA entry Type: 0 - Self, 1 - Other/Peer, 2 - BSSID, 3 - BCAST */ | ||
| 1186 | u8 type; | ||
| 1187 | |||
| 1188 | /* Short Preamble Supported. */ | ||
| 1189 | u8 short_preamble_supported; | ||
| 1190 | |||
| 1191 | /* MAC Address of STA */ | ||
| 1192 | u8 mac[ETH_ALEN]; | ||
| 1193 | |||
| 1194 | /* Listen interval of the STA */ | ||
| 1195 | u16 listen_interval; | ||
| 1196 | |||
| 1197 | /* Support for 11e/WMM */ | ||
| 1198 | u8 wmm_enabled; | ||
| 1199 | |||
| 1200 | /* 11n HT capable STA */ | ||
| 1201 | u8 ht_capable; | ||
| 1202 | |||
| 1203 | /* TX Width Set: 0 - 20 MHz only, 1 - 20/40 MHz */ | ||
| 1204 | u8 tx_channel_width_set; | ||
| 1205 | |||
| 1206 | /* RIFS mode 0 - NA, 1 - Allowed */ | ||
| 1207 | u8 rifs_mode; | ||
| 1208 | |||
| 1209 | /* L-SIG TXOP Protection mechanism | ||
| 1210 | 0 - No Support, 1 - Supported | ||
| 1211 | SG - there is global field */ | ||
| 1212 | u8 lsig_txop_protection; | ||
| 1213 | |||
| 1214 | /* Max Ampdu Size supported by STA. TPE programming. | ||
| 1215 | 0 : 8k , 1 : 16k, 2 : 32k, 3 : 64k */ | ||
| 1216 | u8 max_ampdu_size; | ||
| 1217 | |||
| 1218 | /* Max Ampdu density. Used by RA. 3 : 0~7 : 2^(11nAMPDUdensity -4) */ | ||
| 1219 | u8 max_ampdu_density; | ||
| 1220 | |||
| 1221 | /* Max AMSDU size 1 : 3839 bytes, 0 : 7935 bytes */ | ||
| 1222 | u8 max_amsdu_size; | ||
| 1223 | |||
| 1224 | /* Short GI support for 40Mhz packets */ | ||
| 1225 | u8 sgi_40mhz; | ||
| 1226 | |||
| 1227 | /* Short GI support for 20Mhz packets */ | ||
| 1228 | u8 sgi_20Mhz; | ||
| 1229 | |||
| 1230 | /* TODO move this parameter to the end for 3680 */ | ||
| 1231 | /* These rates are the intersection of peer and self capabilities. */ | ||
| 1232 | struct wcn36xx_hal_supported_rates supported_rates; | ||
| 1233 | |||
| 1234 | /* Robust Management Frame (RMF) enabled/disabled */ | ||
| 1235 | u8 rmf; | ||
| 1236 | |||
| 1237 | /* The unicast encryption type in the association */ | ||
| 1238 | u32 encrypt_type; | ||
| 1239 | |||
| 1240 | /* HAL should update the existing STA entry, if this flag is set. UMAC | ||
| 1241 | will set this flag in case of RE-ASSOC, where we want to reuse the | ||
| 1242 | old STA ID. 0 = Add, 1 = Update */ | ||
| 1243 | u8 action; | ||
| 1244 | |||
| 1245 | /* U-APSD Flags: 1b per AC. Encoded as follows: | ||
| 1246 | b7 b6 b5 b4 b3 b2 b1 b0 = | ||
| 1247 | X X X X BE BK VI VO */ | ||
| 1248 | u8 uapsd; | ||
| 1249 | |||
| 1250 | /* Max SP Length */ | ||
| 1251 | u8 max_sp_len; | ||
| 1252 | |||
| 1253 | /* 11n Green Field preamble support | ||
| 1254 | 0 - Not supported, 1 - Supported */ | ||
| 1255 | u8 green_field_capable; | ||
| 1256 | |||
| 1257 | /* MIMO Power Save mode */ | ||
| 1258 | enum wcn36xx_hal_ht_mimo_state mimo_ps; | ||
| 1259 | |||
| 1260 | /* Delayed BA Support */ | ||
| 1261 | u8 delayed_ba_support; | ||
| 1262 | |||
| 1263 | /* Max AMPDU duration in 32us */ | ||
| 1264 | u8 max_ampdu_duration; | ||
| 1265 | |||
| 1266 | /* HT STA should set it to 1 if it is enabled in BSS. HT STA should | ||
| 1267 | * set it to 0 if AP does not support it. This indication is sent | ||
| 1268 | * to HAL and HAL uses this flag to pickup up appropriate 40Mhz | ||
| 1269 | * rates. */ | ||
| 1270 | u8 dsss_cck_mode_40mhz; | ||
| 1271 | |||
| 1272 | /* Valid STA Idx when action=Update. Set to 0xFF when invalid! | ||
| 1273 | * Retained for backward compalibity with existing HAL code */ | ||
| 1274 | u8 sta_index; | ||
| 1275 | |||
| 1276 | /* BSSID of BSS to which station is associated. Set to 0xFF when | ||
| 1277 | * invalid. Retained for backward compalibity with existing HAL | ||
| 1278 | * code */ | ||
| 1279 | u8 bssid_index; | ||
| 1280 | |||
| 1281 | u8 p2p; | ||
| 1282 | |||
| 1283 | /* TODO add this parameter for 3680. */ | ||
| 1284 | /* Reserved to align next field on a dword boundary */ | ||
| 1285 | /* u8 reserved; */ | ||
| 1286 | } __packed; | ||
| 1287 | |||
| 1288 | struct wcn36xx_hal_config_sta_req_msg { | ||
| 1289 | struct wcn36xx_hal_msg_header header; | ||
| 1290 | struct wcn36xx_hal_config_sta_params sta_params; | ||
| 1291 | } __packed; | ||
| 1292 | |||
| 1293 | struct wcn36xx_hal_config_sta_params_v1 { | ||
| 1294 | /* BSSID of STA */ | ||
| 1295 | u8 bssid[ETH_ALEN]; | ||
| 1296 | |||
| 1297 | /* ASSOC ID, as assigned by UMAC */ | ||
| 1298 | u16 aid; | ||
| 1299 | |||
| 1300 | /* STA entry Type: 0 - Self, 1 - Other/Peer, 2 - BSSID, 3 - BCAST */ | ||
| 1301 | u8 type; | ||
| 1302 | |||
| 1303 | /* Short Preamble Supported. */ | ||
| 1304 | u8 short_preamble_supported; | ||
| 1305 | |||
| 1306 | /* MAC Address of STA */ | ||
| 1307 | u8 mac[ETH_ALEN]; | ||
| 1308 | |||
| 1309 | /* Listen interval of the STA */ | ||
| 1310 | u16 listen_interval; | ||
| 1311 | |||
| 1312 | /* Support for 11e/WMM */ | ||
| 1313 | u8 wmm_enabled; | ||
| 1314 | |||
| 1315 | /* 11n HT capable STA */ | ||
| 1316 | u8 ht_capable; | ||
| 1317 | |||
| 1318 | /* TX Width Set: 0 - 20 MHz only, 1 - 20/40 MHz */ | ||
| 1319 | u8 tx_channel_width_set; | ||
| 1320 | |||
| 1321 | /* RIFS mode 0 - NA, 1 - Allowed */ | ||
| 1322 | u8 rifs_mode; | ||
| 1323 | |||
| 1324 | /* L-SIG TXOP Protection mechanism | ||
| 1325 | 0 - No Support, 1 - Supported | ||
| 1326 | SG - there is global field */ | ||
| 1327 | u8 lsig_txop_protection; | ||
| 1328 | |||
| 1329 | /* Max Ampdu Size supported by STA. TPE programming. | ||
| 1330 | 0 : 8k , 1 : 16k, 2 : 32k, 3 : 64k */ | ||
| 1331 | u8 max_ampdu_size; | ||
| 1332 | |||
| 1333 | /* Max Ampdu density. Used by RA. 3 : 0~7 : 2^(11nAMPDUdensity -4) */ | ||
| 1334 | u8 max_ampdu_density; | ||
| 1335 | |||
| 1336 | /* Max AMSDU size 1 : 3839 bytes, 0 : 7935 bytes */ | ||
| 1337 | u8 max_amsdu_size; | ||
| 1338 | |||
| 1339 | /* Short GI support for 40Mhz packets */ | ||
| 1340 | u8 sgi_40mhz; | ||
| 1341 | |||
| 1342 | /* Short GI support for 20Mhz packets */ | ||
| 1343 | u8 sgi_20Mhz; | ||
| 1344 | |||
| 1345 | /* Robust Management Frame (RMF) enabled/disabled */ | ||
| 1346 | u8 rmf; | ||
| 1347 | |||
| 1348 | /* The unicast encryption type in the association */ | ||
| 1349 | u32 encrypt_type; | ||
| 1350 | |||
| 1351 | /* HAL should update the existing STA entry, if this flag is set. UMAC | ||
| 1352 | will set this flag in case of RE-ASSOC, where we want to reuse the | ||
| 1353 | old STA ID. 0 = Add, 1 = Update */ | ||
| 1354 | u8 action; | ||
| 1355 | |||
| 1356 | /* U-APSD Flags: 1b per AC. Encoded as follows: | ||
| 1357 | b7 b6 b5 b4 b3 b2 b1 b0 = | ||
| 1358 | X X X X BE BK VI VO */ | ||
| 1359 | u8 uapsd; | ||
| 1360 | |||
| 1361 | /* Max SP Length */ | ||
| 1362 | u8 max_sp_len; | ||
| 1363 | |||
| 1364 | /* 11n Green Field preamble support | ||
| 1365 | 0 - Not supported, 1 - Supported */ | ||
| 1366 | u8 green_field_capable; | ||
| 1367 | |||
| 1368 | /* MIMO Power Save mode */ | ||
| 1369 | enum wcn36xx_hal_ht_mimo_state mimo_ps; | ||
| 1370 | |||
| 1371 | /* Delayed BA Support */ | ||
| 1372 | u8 delayed_ba_support; | ||
| 1373 | |||
| 1374 | /* Max AMPDU duration in 32us */ | ||
| 1375 | u8 max_ampdu_duration; | ||
| 1376 | |||
| 1377 | /* HT STA should set it to 1 if it is enabled in BSS. HT STA should | ||
| 1378 | * set it to 0 if AP does not support it. This indication is sent | ||
| 1379 | * to HAL and HAL uses this flag to pickup up appropriate 40Mhz | ||
| 1380 | * rates. */ | ||
| 1381 | u8 dsss_cck_mode_40mhz; | ||
| 1382 | |||
| 1383 | /* Valid STA Idx when action=Update. Set to 0xFF when invalid! | ||
| 1384 | * Retained for backward compalibity with existing HAL code */ | ||
| 1385 | u8 sta_index; | ||
| 1386 | |||
| 1387 | /* BSSID of BSS to which station is associated. Set to 0xFF when | ||
| 1388 | * invalid. Retained for backward compalibity with existing HAL | ||
| 1389 | * code */ | ||
| 1390 | u8 bssid_index; | ||
| 1391 | |||
| 1392 | u8 p2p; | ||
| 1393 | |||
| 1394 | /* Reserved to align next field on a dword boundary */ | ||
| 1395 | u8 reserved; | ||
| 1396 | |||
| 1397 | /* These rates are the intersection of peer and self capabilities. */ | ||
| 1398 | struct wcn36xx_hal_supported_rates supported_rates; | ||
| 1399 | } __packed; | ||
| 1400 | |||
| 1401 | struct wcn36xx_hal_config_sta_req_msg_v1 { | ||
| 1402 | struct wcn36xx_hal_msg_header header; | ||
| 1403 | struct wcn36xx_hal_config_sta_params_v1 sta_params; | ||
| 1404 | } __packed; | ||
| 1405 | |||
| 1406 | struct config_sta_rsp_params { | ||
| 1407 | /* success or failure */ | ||
| 1408 | u32 status; | ||
| 1409 | |||
| 1410 | /* Station index; valid only when 'status' field value SUCCESS */ | ||
| 1411 | u8 sta_index; | ||
| 1412 | |||
| 1413 | /* BSSID Index of BSS to which the station is associated */ | ||
| 1414 | u8 bssid_index; | ||
| 1415 | |||
| 1416 | /* DPU Index for PTK */ | ||
| 1417 | u8 dpu_index; | ||
| 1418 | |||
| 1419 | /* DPU Index for GTK */ | ||
| 1420 | u8 bcast_dpu_index; | ||
| 1421 | |||
| 1422 | /* DPU Index for IGTK */ | ||
| 1423 | u8 bcast_mgmt_dpu_idx; | ||
| 1424 | |||
| 1425 | /* PTK DPU signature */ | ||
| 1426 | u8 uc_ucast_sig; | ||
| 1427 | |||
| 1428 | /* GTK DPU isignature */ | ||
| 1429 | u8 uc_bcast_sig; | ||
| 1430 | |||
| 1431 | /* IGTK DPU signature */ | ||
| 1432 | u8 uc_mgmt_sig; | ||
| 1433 | |||
| 1434 | u8 p2p; | ||
| 1435 | |||
| 1436 | } __packed; | ||
| 1437 | |||
| 1438 | struct wcn36xx_hal_config_sta_rsp_msg { | ||
| 1439 | struct wcn36xx_hal_msg_header header; | ||
| 1440 | |||
| 1441 | struct config_sta_rsp_params params; | ||
| 1442 | } __packed; | ||
| 1443 | |||
| 1444 | /* Delete STA Request message */ | ||
| 1445 | struct wcn36xx_hal_delete_sta_req_msg { | ||
| 1446 | struct wcn36xx_hal_msg_header header; | ||
| 1447 | |||
| 1448 | /* Index of STA to delete */ | ||
| 1449 | u8 sta_index; | ||
| 1450 | |||
| 1451 | } __packed; | ||
| 1452 | |||
| 1453 | /* Delete STA Response message */ | ||
| 1454 | struct wcn36xx_hal_delete_sta_rsp_msg { | ||
| 1455 | struct wcn36xx_hal_msg_header header; | ||
| 1456 | |||
| 1457 | /* success or failure */ | ||
| 1458 | u32 status; | ||
| 1459 | |||
| 1460 | /* Index of STA deleted */ | ||
| 1461 | u8 sta_id; | ||
| 1462 | } __packed; | ||
| 1463 | |||
| 1464 | /* 12 Bytes long because this structure can be used to represent rate and | ||
| 1465 | * extended rate set IEs. The parser assume this to be at least 12 */ | ||
| 1466 | struct wcn36xx_hal_rate_set { | ||
| 1467 | u8 num_rates; | ||
| 1468 | u8 rate[WCN36XX_HAL_MAC_RATESET_EID_MAX]; | ||
| 1469 | } __packed; | ||
| 1470 | |||
| 1471 | /* access category record */ | ||
| 1472 | struct wcn36xx_hal_aci_aifsn { | ||
| 1473 | #ifndef ANI_LITTLE_BIT_ENDIAN | ||
| 1474 | u8 rsvd:1; | ||
| 1475 | u8 aci:2; | ||
| 1476 | u8 acm:1; | ||
| 1477 | u8 aifsn:4; | ||
| 1478 | #else | ||
| 1479 | u8 aifsn:4; | ||
| 1480 | u8 acm:1; | ||
| 1481 | u8 aci:2; | ||
| 1482 | u8 rsvd:1; | ||
| 1483 | #endif | ||
| 1484 | } __packed; | ||
| 1485 | |||
| 1486 | /* contention window size */ | ||
| 1487 | struct wcn36xx_hal_mac_cw { | ||
| 1488 | #ifndef ANI_LITTLE_BIT_ENDIAN | ||
| 1489 | u8 max:4; | ||
| 1490 | u8 min:4; | ||
| 1491 | #else | ||
| 1492 | u8 min:4; | ||
| 1493 | u8 max:4; | ||
| 1494 | #endif | ||
| 1495 | } __packed; | ||
| 1496 | |||
| 1497 | struct wcn36xx_hal_edca_param_record { | ||
| 1498 | struct wcn36xx_hal_aci_aifsn aci; | ||
| 1499 | struct wcn36xx_hal_mac_cw cw; | ||
| 1500 | u16 txop_limit; | ||
| 1501 | } __packed; | ||
| 1502 | |||
| 1503 | struct wcn36xx_hal_mac_ssid { | ||
| 1504 | u8 length; | ||
| 1505 | u8 ssid[32]; | ||
| 1506 | } __packed; | ||
| 1507 | |||
| 1508 | /* Concurrency role. These are generic IDs that identify the various roles | ||
| 1509 | * in the software system. */ | ||
| 1510 | enum wcn36xx_hal_con_mode { | ||
| 1511 | WCN36XX_HAL_STA_MODE = 0, | ||
| 1512 | |||
| 1513 | /* to support softAp mode . This is misleading. | ||
| 1514 | It means AP MODE only. */ | ||
| 1515 | WCN36XX_HAL_STA_SAP_MODE = 1, | ||
| 1516 | |||
| 1517 | WCN36XX_HAL_P2P_CLIENT_MODE, | ||
| 1518 | WCN36XX_HAL_P2P_GO_MODE, | ||
| 1519 | WCN36XX_HAL_MONITOR_MODE, | ||
| 1520 | }; | ||
| 1521 | |||
| 1522 | /* This is a bit pattern to be set for each mode | ||
| 1523 | * bit 0 - sta mode | ||
| 1524 | * bit 1 - ap mode | ||
| 1525 | * bit 2 - p2p client mode | ||
| 1526 | * bit 3 - p2p go mode */ | ||
| 1527 | enum wcn36xx_hal_concurrency_mode { | ||
| 1528 | HAL_STA = 1, | ||
| 1529 | HAL_SAP = 2, | ||
| 1530 | |||
| 1531 | /* to support sta, softAp mode . This means STA+AP mode */ | ||
| 1532 | HAL_STA_SAP = 3, | ||
| 1533 | |||
| 1534 | HAL_P2P_CLIENT = 4, | ||
| 1535 | HAL_P2P_GO = 8, | ||
| 1536 | HAL_MAX_CONCURRENCY_PERSONA = 4 | ||
| 1537 | }; | ||
| 1538 | |||
| 1539 | struct wcn36xx_hal_config_bss_params { | ||
| 1540 | /* BSSID */ | ||
| 1541 | u8 bssid[ETH_ALEN]; | ||
| 1542 | |||
| 1543 | /* Self Mac Address */ | ||
| 1544 | u8 self_mac_addr[ETH_ALEN]; | ||
| 1545 | |||
| 1546 | /* BSS type */ | ||
| 1547 | enum wcn36xx_hal_bss_type bss_type; | ||
| 1548 | |||
| 1549 | /* Operational Mode: AP =0, STA = 1 */ | ||
| 1550 | u8 oper_mode; | ||
| 1551 | |||
| 1552 | /* Network Type */ | ||
| 1553 | enum wcn36xx_hal_nw_type nw_type; | ||
| 1554 | |||
| 1555 | /* Used to classify PURE_11G/11G_MIXED to program MTU */ | ||
| 1556 | u8 short_slot_time_supported; | ||
| 1557 | |||
| 1558 | /* Co-exist with 11a STA */ | ||
| 1559 | u8 lla_coexist; | ||
| 1560 | |||
| 1561 | /* Co-exist with 11b STA */ | ||
| 1562 | u8 llb_coexist; | ||
| 1563 | |||
| 1564 | /* Co-exist with 11g STA */ | ||
| 1565 | u8 llg_coexist; | ||
| 1566 | |||
| 1567 | /* Coexistence with 11n STA */ | ||
| 1568 | u8 ht20_coexist; | ||
| 1569 | |||
| 1570 | /* Non GF coexist flag */ | ||
| 1571 | u8 lln_non_gf_coexist; | ||
| 1572 | |||
| 1573 | /* TXOP protection support */ | ||
| 1574 | u8 lsig_tx_op_protection_full_support; | ||
| 1575 | |||
| 1576 | /* RIFS mode */ | ||
| 1577 | u8 rifs_mode; | ||
| 1578 | |||
| 1579 | /* Beacon Interval in TU */ | ||
| 1580 | u16 beacon_interval; | ||
| 1581 | |||
| 1582 | /* DTIM period */ | ||
| 1583 | u8 dtim_period; | ||
| 1584 | |||
| 1585 | /* TX Width Set: 0 - 20 MHz only, 1 - 20/40 MHz */ | ||
| 1586 | u8 tx_channel_width_set; | ||
| 1587 | |||
| 1588 | /* Operating channel */ | ||
| 1589 | u8 oper_channel; | ||
| 1590 | |||
| 1591 | /* Extension channel for channel bonding */ | ||
| 1592 | u8 ext_channel; | ||
| 1593 | |||
| 1594 | /* Reserved to align next field on a dword boundary */ | ||
| 1595 | u8 reserved; | ||
| 1596 | |||
| 1597 | /* TODO move sta to the end for 3680 */ | ||
| 1598 | /* Context of the station being added in HW | ||
| 1599 | * Add a STA entry for "itself" - | ||
| 1600 | * | ||
| 1601 | * On AP - Add the AP itself in an "STA context" | ||
| 1602 | * | ||
| 1603 | * On STA - Add the AP to which this STA is joining in an | ||
| 1604 | * "STA context" | ||
| 1605 | */ | ||
| 1606 | struct wcn36xx_hal_config_sta_params sta; | ||
| 1607 | /* SSID of the BSS */ | ||
| 1608 | struct wcn36xx_hal_mac_ssid ssid; | ||
| 1609 | |||
| 1610 | /* HAL should update the existing BSS entry, if this flag is set. | ||
| 1611 | * UMAC will set this flag in case of reassoc, where we want to | ||
| 1612 | * resue the the old BSSID and still return success 0 = Add, 1 = | ||
| 1613 | * Update */ | ||
| 1614 | u8 action; | ||
| 1615 | |||
| 1616 | /* MAC Rate Set */ | ||
| 1617 | struct wcn36xx_hal_rate_set rateset; | ||
| 1618 | |||
| 1619 | /* Enable/Disable HT capabilities of the BSS */ | ||
| 1620 | u8 ht; | ||
| 1621 | |||
| 1622 | /* Enable/Disable OBSS protection */ | ||
| 1623 | u8 obss_prot_enabled; | ||
| 1624 | |||
| 1625 | /* RMF enabled/disabled */ | ||
| 1626 | u8 rmf; | ||
| 1627 | |||
| 1628 | /* HT Operating Mode operating mode of the 802.11n STA */ | ||
| 1629 | enum wcn36xx_hal_ht_operating_mode ht_oper_mode; | ||
| 1630 | |||
| 1631 | /* Dual CTS Protection: 0 - Unused, 1 - Used */ | ||
| 1632 | u8 dual_cts_protection; | ||
| 1633 | |||
| 1634 | /* Probe Response Max retries */ | ||
| 1635 | u8 max_probe_resp_retry_limit; | ||
| 1636 | |||
| 1637 | /* To Enable Hidden ssid */ | ||
| 1638 | u8 hidden_ssid; | ||
| 1639 | |||
| 1640 | /* To Enable Disable FW Proxy Probe Resp */ | ||
| 1641 | u8 proxy_probe_resp; | ||
| 1642 | |||
| 1643 | /* Boolean to indicate if EDCA params are valid. UMAC might not | ||
| 1644 | * have valid EDCA params or might not desire to apply EDCA params | ||
| 1645 | * during config BSS. 0 implies Not Valid ; Non-Zero implies | ||
| 1646 | * valid */ | ||
| 1647 | u8 edca_params_valid; | ||
| 1648 | |||
| 1649 | /* EDCA Parameters for Best Effort Access Category */ | ||
| 1650 | struct wcn36xx_hal_edca_param_record acbe; | ||
| 1651 | |||
| 1652 | /* EDCA Parameters forBackground Access Category */ | ||
| 1653 | struct wcn36xx_hal_edca_param_record acbk; | ||
| 1654 | |||
| 1655 | /* EDCA Parameters for Video Access Category */ | ||
| 1656 | struct wcn36xx_hal_edca_param_record acvi; | ||
| 1657 | |||
| 1658 | /* EDCA Parameters for Voice Access Category */ | ||
| 1659 | struct wcn36xx_hal_edca_param_record acvo; | ||
| 1660 | |||
| 1661 | /* Ext Bss Config Msg if set */ | ||
| 1662 | u8 ext_set_sta_key_param_valid; | ||
| 1663 | |||
| 1664 | /* SetStaKeyParams for ext bss msg */ | ||
| 1665 | struct wcn36xx_hal_set_sta_key_params ext_set_sta_key_param; | ||
| 1666 | |||
| 1667 | /* Persona for the BSS can be STA,AP,GO,CLIENT value same as enum | ||
| 1668 | * wcn36xx_hal_con_mode */ | ||
| 1669 | u8 wcn36xx_hal_persona; | ||
| 1670 | |||
| 1671 | u8 spectrum_mgt_enable; | ||
| 1672 | |||
| 1673 | /* HAL fills in the tx power used for mgmt frames in txMgmtPower */ | ||
| 1674 | s8 tx_mgmt_power; | ||
| 1675 | |||
| 1676 | /* maxTxPower has max power to be used after applying the power | ||
| 1677 | * constraint if any */ | ||
| 1678 | s8 max_tx_power; | ||
| 1679 | } __packed; | ||
| 1680 | |||
| 1681 | struct wcn36xx_hal_config_bss_req_msg { | ||
| 1682 | struct wcn36xx_hal_msg_header header; | ||
| 1683 | struct wcn36xx_hal_config_bss_params bss_params; | ||
| 1684 | } __packed; | ||
| 1685 | |||
| 1686 | struct wcn36xx_hal_config_bss_params_v1 { | ||
| 1687 | /* BSSID */ | ||
| 1688 | u8 bssid[ETH_ALEN]; | ||
| 1689 | |||
| 1690 | /* Self Mac Address */ | ||
| 1691 | u8 self_mac_addr[ETH_ALEN]; | ||
| 1692 | |||
| 1693 | /* BSS type */ | ||
| 1694 | enum wcn36xx_hal_bss_type bss_type; | ||
| 1695 | |||
| 1696 | /* Operational Mode: AP =0, STA = 1 */ | ||
| 1697 | u8 oper_mode; | ||
| 1698 | |||
| 1699 | /* Network Type */ | ||
| 1700 | enum wcn36xx_hal_nw_type nw_type; | ||
| 1701 | |||
| 1702 | /* Used to classify PURE_11G/11G_MIXED to program MTU */ | ||
| 1703 | u8 short_slot_time_supported; | ||
| 1704 | |||
| 1705 | /* Co-exist with 11a STA */ | ||
| 1706 | u8 lla_coexist; | ||
| 1707 | |||
| 1708 | /* Co-exist with 11b STA */ | ||
| 1709 | u8 llb_coexist; | ||
| 1710 | |||
| 1711 | /* Co-exist with 11g STA */ | ||
| 1712 | u8 llg_coexist; | ||
| 1713 | |||
| 1714 | /* Coexistence with 11n STA */ | ||
| 1715 | u8 ht20_coexist; | ||
| 1716 | |||
| 1717 | /* Non GF coexist flag */ | ||
| 1718 | u8 lln_non_gf_coexist; | ||
| 1719 | |||
| 1720 | /* TXOP protection support */ | ||
| 1721 | u8 lsig_tx_op_protection_full_support; | ||
| 1722 | |||
| 1723 | /* RIFS mode */ | ||
| 1724 | u8 rifs_mode; | ||
| 1725 | |||
| 1726 | /* Beacon Interval in TU */ | ||
| 1727 | u16 beacon_interval; | ||
| 1728 | |||
| 1729 | /* DTIM period */ | ||
| 1730 | u8 dtim_period; | ||
| 1731 | |||
| 1732 | /* TX Width Set: 0 - 20 MHz only, 1 - 20/40 MHz */ | ||
| 1733 | u8 tx_channel_width_set; | ||
| 1734 | |||
| 1735 | /* Operating channel */ | ||
| 1736 | u8 oper_channel; | ||
| 1737 | |||
| 1738 | /* Extension channel for channel bonding */ | ||
| 1739 | u8 ext_channel; | ||
| 1740 | |||
| 1741 | /* Reserved to align next field on a dword boundary */ | ||
| 1742 | u8 reserved; | ||
| 1743 | |||
| 1744 | /* SSID of the BSS */ | ||
| 1745 | struct wcn36xx_hal_mac_ssid ssid; | ||
| 1746 | |||
| 1747 | /* HAL should update the existing BSS entry, if this flag is set. | ||
| 1748 | * UMAC will set this flag in case of reassoc, where we want to | ||
| 1749 | * resue the the old BSSID and still return success 0 = Add, 1 = | ||
| 1750 | * Update */ | ||
| 1751 | u8 action; | ||
| 1752 | |||
| 1753 | /* MAC Rate Set */ | ||
| 1754 | struct wcn36xx_hal_rate_set rateset; | ||
| 1755 | |||
| 1756 | /* Enable/Disable HT capabilities of the BSS */ | ||
| 1757 | u8 ht; | ||
| 1758 | |||
| 1759 | /* Enable/Disable OBSS protection */ | ||
| 1760 | u8 obss_prot_enabled; | ||
| 1761 | |||
| 1762 | /* RMF enabled/disabled */ | ||
| 1763 | u8 rmf; | ||
| 1764 | |||
| 1765 | /* HT Operating Mode operating mode of the 802.11n STA */ | ||
| 1766 | enum wcn36xx_hal_ht_operating_mode ht_oper_mode; | ||
| 1767 | |||
| 1768 | /* Dual CTS Protection: 0 - Unused, 1 - Used */ | ||
| 1769 | u8 dual_cts_protection; | ||
| 1770 | |||
| 1771 | /* Probe Response Max retries */ | ||
| 1772 | u8 max_probe_resp_retry_limit; | ||
| 1773 | |||
| 1774 | /* To Enable Hidden ssid */ | ||
| 1775 | u8 hidden_ssid; | ||
| 1776 | |||
| 1777 | /* To Enable Disable FW Proxy Probe Resp */ | ||
| 1778 | u8 proxy_probe_resp; | ||
| 1779 | |||
| 1780 | /* Boolean to indicate if EDCA params are valid. UMAC might not | ||
| 1781 | * have valid EDCA params or might not desire to apply EDCA params | ||
| 1782 | * during config BSS. 0 implies Not Valid ; Non-Zero implies | ||
| 1783 | * valid */ | ||
| 1784 | u8 edca_params_valid; | ||
| 1785 | |||
| 1786 | /* EDCA Parameters for Best Effort Access Category */ | ||
| 1787 | struct wcn36xx_hal_edca_param_record acbe; | ||
| 1788 | |||
| 1789 | /* EDCA Parameters forBackground Access Category */ | ||
| 1790 | struct wcn36xx_hal_edca_param_record acbk; | ||
| 1791 | |||
| 1792 | /* EDCA Parameters for Video Access Category */ | ||
| 1793 | struct wcn36xx_hal_edca_param_record acvi; | ||
| 1794 | |||
| 1795 | /* EDCA Parameters for Voice Access Category */ | ||
| 1796 | struct wcn36xx_hal_edca_param_record acvo; | ||
| 1797 | |||
| 1798 | /* Ext Bss Config Msg if set */ | ||
| 1799 | u8 ext_set_sta_key_param_valid; | ||
| 1800 | |||
| 1801 | /* SetStaKeyParams for ext bss msg */ | ||
| 1802 | struct wcn36xx_hal_set_sta_key_params ext_set_sta_key_param; | ||
| 1803 | |||
| 1804 | /* Persona for the BSS can be STA,AP,GO,CLIENT value same as enum | ||
| 1805 | * wcn36xx_hal_con_mode */ | ||
| 1806 | u8 wcn36xx_hal_persona; | ||
| 1807 | |||
| 1808 | u8 spectrum_mgt_enable; | ||
| 1809 | |||
| 1810 | /* HAL fills in the tx power used for mgmt frames in txMgmtPower */ | ||
| 1811 | s8 tx_mgmt_power; | ||
| 1812 | |||
| 1813 | /* maxTxPower has max power to be used after applying the power | ||
| 1814 | * constraint if any */ | ||
| 1815 | s8 max_tx_power; | ||
| 1816 | |||
| 1817 | /* Context of the station being added in HW | ||
| 1818 | * Add a STA entry for "itself" - | ||
| 1819 | * | ||
| 1820 | * On AP - Add the AP itself in an "STA context" | ||
| 1821 | * | ||
| 1822 | * On STA - Add the AP to which this STA is joining in an | ||
| 1823 | * "STA context" | ||
| 1824 | */ | ||
| 1825 | struct wcn36xx_hal_config_sta_params_v1 sta; | ||
| 1826 | } __packed; | ||
| 1827 | |||
| 1828 | struct wcn36xx_hal_config_bss_req_msg_v1 { | ||
| 1829 | struct wcn36xx_hal_msg_header header; | ||
| 1830 | struct wcn36xx_hal_config_bss_params_v1 bss_params; | ||
| 1831 | } __packed; | ||
| 1832 | |||
| 1833 | struct wcn36xx_hal_config_bss_rsp_params { | ||
| 1834 | /* Success or Failure */ | ||
| 1835 | u32 status; | ||
| 1836 | |||
| 1837 | /* BSS index allocated by HAL */ | ||
| 1838 | u8 bss_index; | ||
| 1839 | |||
| 1840 | /* DPU descriptor index for PTK */ | ||
| 1841 | u8 dpu_desc_index; | ||
| 1842 | |||
| 1843 | /* PTK DPU signature */ | ||
| 1844 | u8 ucast_dpu_signature; | ||
| 1845 | |||
| 1846 | /* DPU descriptor index for GTK */ | ||
| 1847 | u8 bcast_dpu_desc_indx; | ||
| 1848 | |||
| 1849 | /* GTK DPU signature */ | ||
| 1850 | u8 bcast_dpu_signature; | ||
| 1851 | |||
| 1852 | /* DPU descriptor for IGTK */ | ||
| 1853 | u8 mgmt_dpu_desc_index; | ||
| 1854 | |||
| 1855 | /* IGTK DPU signature */ | ||
| 1856 | u8 mgmt_dpu_signature; | ||
| 1857 | |||
| 1858 | /* Station Index for BSS entry */ | ||
| 1859 | u8 bss_sta_index; | ||
| 1860 | |||
| 1861 | /* Self station index for this BSS */ | ||
| 1862 | u8 bss_self_sta_index; | ||
| 1863 | |||
| 1864 | /* Bcast station for buffering bcast frames in AP role */ | ||
| 1865 | u8 bss_bcast_sta_idx; | ||
| 1866 | |||
| 1867 | /* MAC Address of STA(PEER/SELF) in staContext of configBSSReq */ | ||
| 1868 | u8 mac[ETH_ALEN]; | ||
| 1869 | |||
| 1870 | /* HAL fills in the tx power used for mgmt frames in this field. */ | ||
| 1871 | s8 tx_mgmt_power; | ||
| 1872 | |||
| 1873 | } __packed; | ||
| 1874 | |||
| 1875 | struct wcn36xx_hal_config_bss_rsp_msg { | ||
| 1876 | struct wcn36xx_hal_msg_header header; | ||
| 1877 | struct wcn36xx_hal_config_bss_rsp_params bss_rsp_params; | ||
| 1878 | } __packed; | ||
| 1879 | |||
| 1880 | struct wcn36xx_hal_delete_bss_req_msg { | ||
| 1881 | struct wcn36xx_hal_msg_header header; | ||
| 1882 | |||
| 1883 | /* BSS index to be deleted */ | ||
| 1884 | u8 bss_index; | ||
| 1885 | |||
| 1886 | } __packed; | ||
| 1887 | |||
| 1888 | struct wcn36xx_hal_delete_bss_rsp_msg { | ||
| 1889 | struct wcn36xx_hal_msg_header header; | ||
| 1890 | |||
| 1891 | /* Success or Failure */ | ||
| 1892 | u32 status; | ||
| 1893 | |||
| 1894 | /* BSS index that has been deleted */ | ||
| 1895 | u8 bss_index; | ||
| 1896 | |||
| 1897 | } __packed; | ||
| 1898 | |||
| 1899 | struct wcn36xx_hal_join_req_msg { | ||
| 1900 | struct wcn36xx_hal_msg_header header; | ||
| 1901 | |||
| 1902 | /* Indicates the BSSID to which STA is going to associate */ | ||
| 1903 | u8 bssid[ETH_ALEN]; | ||
| 1904 | |||
| 1905 | /* Indicates the channel to switch to. */ | ||
| 1906 | u8 channel; | ||
| 1907 | |||
| 1908 | /* Self STA MAC */ | ||
| 1909 | u8 self_sta_mac_addr[ETH_ALEN]; | ||
| 1910 | |||
| 1911 | /* Local power constraint */ | ||
| 1912 | u8 local_power_constraint; | ||
| 1913 | |||
| 1914 | /* Secondary channel offset */ | ||
| 1915 | enum phy_chan_bond_state secondary_channel_offset; | ||
| 1916 | |||
| 1917 | /* link State */ | ||
| 1918 | enum wcn36xx_hal_link_state link_state; | ||
| 1919 | |||
| 1920 | /* Max TX power */ | ||
| 1921 | s8 max_tx_power; | ||
| 1922 | } __packed; | ||
| 1923 | |||
| 1924 | struct wcn36xx_hal_join_rsp_msg { | ||
| 1925 | struct wcn36xx_hal_msg_header header; | ||
| 1926 | |||
| 1927 | /* success or failure */ | ||
| 1928 | u32 status; | ||
| 1929 | |||
| 1930 | /* HAL fills in the tx power used for mgmt frames in this field */ | ||
| 1931 | u8 tx_mgmt_power; | ||
| 1932 | } __packed; | ||
| 1933 | |||
| 1934 | struct post_assoc_req_msg { | ||
| 1935 | struct wcn36xx_hal_msg_header header; | ||
| 1936 | |||
| 1937 | struct wcn36xx_hal_config_sta_params sta_params; | ||
| 1938 | struct wcn36xx_hal_config_bss_params bss_params; | ||
| 1939 | }; | ||
| 1940 | |||
| 1941 | struct post_assoc_rsp_msg { | ||
| 1942 | struct wcn36xx_hal_msg_header header; | ||
| 1943 | struct config_sta_rsp_params sta_rsp_params; | ||
| 1944 | struct wcn36xx_hal_config_bss_rsp_params bss_rsp_params; | ||
| 1945 | }; | ||
| 1946 | |||
| 1947 | /* This is used to create a set of WEP keys for a given BSS. */ | ||
| 1948 | struct wcn36xx_hal_set_bss_key_req_msg { | ||
| 1949 | struct wcn36xx_hal_msg_header header; | ||
| 1950 | |||
| 1951 | /* BSS Index of the BSS */ | ||
| 1952 | u8 bss_idx; | ||
| 1953 | |||
| 1954 | /* Encryption Type used with peer */ | ||
| 1955 | enum ani_ed_type enc_type; | ||
| 1956 | |||
| 1957 | /* Number of keys */ | ||
| 1958 | u8 num_keys; | ||
| 1959 | |||
| 1960 | /* Array of keys. */ | ||
| 1961 | struct wcn36xx_hal_keys keys[WCN36XX_HAL_MAC_MAX_NUM_OF_DEFAULT_KEYS]; | ||
| 1962 | |||
| 1963 | /* Control for Replay Count, 1= Single TID based replay count on Tx | ||
| 1964 | * 0 = Per TID based replay count on TX */ | ||
| 1965 | u8 single_tid_rc; | ||
| 1966 | } __packed; | ||
| 1967 | |||
| 1968 | /* tagged version of set bss key */ | ||
| 1969 | struct wcn36xx_hal_set_bss_key_req_msg_tagged { | ||
| 1970 | struct wcn36xx_hal_set_bss_key_req_msg Msg; | ||
| 1971 | u32 tag; | ||
| 1972 | } __packed; | ||
| 1973 | |||
| 1974 | struct wcn36xx_hal_set_bss_key_rsp_msg { | ||
| 1975 | struct wcn36xx_hal_msg_header header; | ||
| 1976 | |||
| 1977 | /* success or failure */ | ||
| 1978 | u32 status; | ||
| 1979 | } __packed; | ||
| 1980 | |||
| 1981 | /* | ||
| 1982 | * This is used configure the key information on a given station. | ||
| 1983 | * When the sec_type is WEP40 or WEP104, the def_wep_idx is used to locate | ||
| 1984 | * a preconfigured key from a BSS the station assoicated with; otherwise | ||
| 1985 | * a new key descriptor is created based on the key field. | ||
| 1986 | */ | ||
| 1987 | struct wcn36xx_hal_set_sta_key_req_msg { | ||
| 1988 | struct wcn36xx_hal_msg_header header; | ||
| 1989 | struct wcn36xx_hal_set_sta_key_params set_sta_key_params; | ||
| 1990 | } __packed; | ||
| 1991 | |||
| 1992 | struct wcn36xx_hal_set_sta_key_rsp_msg { | ||
| 1993 | struct wcn36xx_hal_msg_header header; | ||
| 1994 | |||
| 1995 | /* success or failure */ | ||
| 1996 | u32 status; | ||
| 1997 | } __packed; | ||
| 1998 | |||
| 1999 | struct wcn36xx_hal_remove_bss_key_req_msg { | ||
| 2000 | struct wcn36xx_hal_msg_header header; | ||
| 2001 | |||
| 2002 | /* BSS Index of the BSS */ | ||
| 2003 | u8 bss_idx; | ||
| 2004 | |||
| 2005 | /* Encryption Type used with peer */ | ||
| 2006 | enum ani_ed_type enc_type; | ||
| 2007 | |||
| 2008 | /* Key Id */ | ||
| 2009 | u8 key_id; | ||
| 2010 | |||
| 2011 | /* STATIC/DYNAMIC. Used in Nullifying in Key Descriptors for | ||
| 2012 | * Static/Dynamic keys */ | ||
| 2013 | enum ani_wep_type wep_type; | ||
| 2014 | } __packed; | ||
| 2015 | |||
| 2016 | struct wcn36xx_hal_remove_bss_key_rsp_msg { | ||
| 2017 | struct wcn36xx_hal_msg_header header; | ||
| 2018 | |||
| 2019 | /* success or failure */ | ||
| 2020 | u32 status; | ||
| 2021 | } __packed; | ||
| 2022 | |||
| 2023 | /* | ||
| 2024 | * This is used by PE to Remove the key information on a given station. | ||
| 2025 | */ | ||
| 2026 | struct wcn36xx_hal_remove_sta_key_req_msg { | ||
| 2027 | struct wcn36xx_hal_msg_header header; | ||
| 2028 | |||
| 2029 | /* STA Index */ | ||
| 2030 | u16 sta_idx; | ||
| 2031 | |||
| 2032 | /* Encryption Type used with peer */ | ||
| 2033 | enum ani_ed_type enc_type; | ||
| 2034 | |||
| 2035 | /* Key Id */ | ||
| 2036 | u8 key_id; | ||
| 2037 | |||
| 2038 | /* Whether to invalidate the Broadcast key or Unicast key. In case | ||
| 2039 | * of WEP, the same key is used for both broadcast and unicast. */ | ||
| 2040 | u8 unicast; | ||
| 2041 | |||
| 2042 | } __packed; | ||
| 2043 | |||
| 2044 | struct wcn36xx_hal_remove_sta_key_rsp_msg { | ||
| 2045 | struct wcn36xx_hal_msg_header header; | ||
| 2046 | |||
| 2047 | /*success or failure */ | ||
| 2048 | u32 status; | ||
| 2049 | |||
| 2050 | } __packed; | ||
| 2051 | |||
| 2052 | #ifdef FEATURE_OEM_DATA_SUPPORT | ||
| 2053 | |||
| 2054 | #ifndef OEM_DATA_REQ_SIZE | ||
| 2055 | #define OEM_DATA_REQ_SIZE 134 | ||
| 2056 | #endif | ||
| 2057 | |||
| 2058 | #ifndef OEM_DATA_RSP_SIZE | ||
| 2059 | #define OEM_DATA_RSP_SIZE 1968 | ||
| 2060 | #endif | ||
| 2061 | |||
| 2062 | struct start_oem_data_req_msg { | ||
| 2063 | struct wcn36xx_hal_msg_header header; | ||
| 2064 | |||
| 2065 | u32 status; | ||
| 2066 | tSirMacAddr self_mac_addr; | ||
| 2067 | u8 oem_data_req[OEM_DATA_REQ_SIZE]; | ||
| 2068 | |||
| 2069 | }; | ||
| 2070 | |||
| 2071 | struct start_oem_data_rsp_msg { | ||
| 2072 | struct wcn36xx_hal_msg_header header; | ||
| 2073 | |||
| 2074 | u8 oem_data_rsp[OEM_DATA_RSP_SIZE]; | ||
| 2075 | }; | ||
| 2076 | |||
| 2077 | #endif | ||
| 2078 | |||
| 2079 | struct wcn36xx_hal_switch_channel_req_msg { | ||
| 2080 | struct wcn36xx_hal_msg_header header; | ||
| 2081 | |||
| 2082 | /* Channel number */ | ||
| 2083 | u8 channel_number; | ||
| 2084 | |||
| 2085 | /* Local power constraint */ | ||
| 2086 | u8 local_power_constraint; | ||
| 2087 | |||
| 2088 | /* Secondary channel offset */ | ||
| 2089 | enum phy_chan_bond_state secondary_channel_offset; | ||
| 2090 | |||
| 2091 | /* HAL fills in the tx power used for mgmt frames in this field. */ | ||
| 2092 | u8 tx_mgmt_power; | ||
| 2093 | |||
| 2094 | /* Max TX power */ | ||
| 2095 | u8 max_tx_power; | ||
| 2096 | |||
| 2097 | /* Self STA MAC */ | ||
| 2098 | u8 self_sta_mac_addr[ETH_ALEN]; | ||
| 2099 | |||
| 2100 | /* VO WIFI comment: BSSID needed to identify session. As the | ||
| 2101 | * request has power constraints, this should be applied only to | ||
| 2102 | * that session Since MTU timing and EDCA are sessionized, this | ||
| 2103 | * struct needs to be sessionized and bssid needs to be out of the | ||
| 2104 | * VOWifi feature flag V IMP: Keep bssId field at the end of this | ||
| 2105 | * msg. It is used to mantain backward compatbility by way of | ||
| 2106 | * ignoring if using new host/old FW or old host/new FW since it is | ||
| 2107 | * at the end of this struct | ||
| 2108 | */ | ||
| 2109 | u8 bssid[ETH_ALEN]; | ||
| 2110 | } __packed; | ||
| 2111 | |||
| 2112 | struct wcn36xx_hal_switch_channel_rsp_msg { | ||
| 2113 | struct wcn36xx_hal_msg_header header; | ||
| 2114 | |||
| 2115 | /* Status */ | ||
| 2116 | u32 status; | ||
| 2117 | |||
| 2118 | /* Channel number - same as in request */ | ||
| 2119 | u8 channel_number; | ||
| 2120 | |||
| 2121 | /* HAL fills in the tx power used for mgmt frames in this field */ | ||
| 2122 | u8 tx_mgmt_power; | ||
| 2123 | |||
| 2124 | /* BSSID needed to identify session - same as in request */ | ||
| 2125 | u8 bssid[ETH_ALEN]; | ||
| 2126 | |||
| 2127 | } __packed; | ||
| 2128 | |||
| 2129 | struct update_edca_params_req_msg { | ||
| 2130 | struct wcn36xx_hal_msg_header header; | ||
| 2131 | |||
| 2132 | /*BSS Index */ | ||
| 2133 | u16 bss_index; | ||
| 2134 | |||
| 2135 | /* Best Effort */ | ||
| 2136 | struct wcn36xx_hal_edca_param_record acbe; | ||
| 2137 | |||
| 2138 | /* Background */ | ||
| 2139 | struct wcn36xx_hal_edca_param_record acbk; | ||
| 2140 | |||
| 2141 | /* Video */ | ||
| 2142 | struct wcn36xx_hal_edca_param_record acvi; | ||
| 2143 | |||
| 2144 | /* Voice */ | ||
| 2145 | struct wcn36xx_hal_edca_param_record acvo; | ||
| 2146 | }; | ||
| 2147 | |||
| 2148 | struct update_edca_params_rsp_msg { | ||
| 2149 | struct wcn36xx_hal_msg_header header; | ||
| 2150 | |||
| 2151 | /* success or failure */ | ||
| 2152 | u32 status; | ||
| 2153 | }; | ||
| 2154 | |||
| 2155 | struct dpu_stats_params { | ||
| 2156 | /* Index of STA to which the statistics */ | ||
| 2157 | u16 sta_index; | ||
| 2158 | |||
| 2159 | /* Encryption mode */ | ||
| 2160 | u8 enc_mode; | ||
| 2161 | |||
| 2162 | /* status */ | ||
| 2163 | u32 status; | ||
| 2164 | |||
| 2165 | /* Statistics */ | ||
| 2166 | u32 send_blocks; | ||
| 2167 | u32 recv_blocks; | ||
| 2168 | u32 replays; | ||
| 2169 | u8 mic_error_cnt; | ||
| 2170 | u32 prot_excl_cnt; | ||
| 2171 | u16 format_err_cnt; | ||
| 2172 | u16 un_decryptable_cnt; | ||
| 2173 | u32 decrypt_err_cnt; | ||
| 2174 | u32 decrypt_ok_cnt; | ||
| 2175 | }; | ||
| 2176 | |||
| 2177 | struct wcn36xx_hal_stats_req_msg { | ||
| 2178 | struct wcn36xx_hal_msg_header header; | ||
| 2179 | |||
| 2180 | /* Valid STA Idx for per STA stats request */ | ||
| 2181 | u32 sta_id; | ||
| 2182 | |||
| 2183 | /* Categories of stats requested as specified in eHalStatsMask */ | ||
| 2184 | u32 stats_mask; | ||
| 2185 | }; | ||
| 2186 | |||
| 2187 | struct ani_summary_stats_info { | ||
| 2188 | /* Total number of packets(per AC) that were successfully | ||
| 2189 | * transmitted with retries */ | ||
| 2190 | u32 retry_cnt[4]; | ||
| 2191 | |||
| 2192 | /* The number of MSDU packets and MMPDU frames per AC that the | ||
| 2193 | * 802.11 station successfully transmitted after more than one | ||
| 2194 | * retransmission attempt */ | ||
| 2195 | u32 multiple_retry_cnt[4]; | ||
| 2196 | |||
| 2197 | /* Total number of packets(per AC) that were successfully | ||
| 2198 | * transmitted (with and without retries, including multi-cast, | ||
| 2199 | * broadcast) */ | ||
| 2200 | u32 tx_frm_cnt[4]; | ||
| 2201 | |||
| 2202 | /* Total number of packets that were successfully received (after | ||
| 2203 | * appropriate filter rules including multi-cast, broadcast) */ | ||
| 2204 | u32 rx_frm_cnt; | ||
| 2205 | |||
| 2206 | /* Total number of duplicate frames received successfully */ | ||
| 2207 | u32 frm_dup_cnt; | ||
| 2208 | |||
| 2209 | /* Total number packets(per AC) failed to transmit */ | ||
| 2210 | u32 fail_cnt[4]; | ||
| 2211 | |||
| 2212 | /* Total number of RTS/CTS sequence failures for transmission of a | ||
| 2213 | * packet */ | ||
| 2214 | u32 rts_fail_cnt; | ||
| 2215 | |||
| 2216 | /* Total number packets failed transmit because of no ACK from the | ||
| 2217 | * remote entity */ | ||
| 2218 | u32 ack_fail_cnt; | ||
| 2219 | |||
| 2220 | /* Total number of RTS/CTS sequence success for transmission of a | ||
| 2221 | * packet */ | ||
| 2222 | u32 rts_succ_cnt; | ||
| 2223 | |||
| 2224 | /* The sum of the receive error count and dropped-receive-buffer | ||
| 2225 | * error count. HAL will provide this as a sum of (FCS error) + | ||
| 2226 | * (Fail get BD/PDU in HW) */ | ||
| 2227 | u32 rx_discard_cnt; | ||
| 2228 | |||
| 2229 | /* | ||
| 2230 | * The receive error count. HAL will provide the RxP FCS error | ||
| 2231 | * global counter. */ | ||
| 2232 | u32 rx_error_cnt; | ||
| 2233 | |||
| 2234 | /* The sum of the transmit-directed byte count, transmit-multicast | ||
| 2235 | * byte count and transmit-broadcast byte count. HAL will sum TPE | ||
| 2236 | * UC/MC/BCAST global counters to provide this. */ | ||
| 2237 | u32 tx_byte_cnt; | ||
| 2238 | }; | ||
| 2239 | |||
| 2240 | /* defines tx_rate_flags */ | ||
| 2241 | enum tx_rate_info { | ||
| 2242 | /* Legacy rates */ | ||
| 2243 | HAL_TX_RATE_LEGACY = 0x1, | ||
| 2244 | |||
| 2245 | /* HT20 rates */ | ||
| 2246 | HAL_TX_RATE_HT20 = 0x2, | ||
| 2247 | |||
| 2248 | /* HT40 rates */ | ||
| 2249 | HAL_TX_RATE_HT40 = 0x4, | ||
| 2250 | |||
| 2251 | /* Rate with Short guard interval */ | ||
| 2252 | HAL_TX_RATE_SGI = 0x8, | ||
| 2253 | |||
| 2254 | /* Rate with Long guard interval */ | ||
| 2255 | HAL_TX_RATE_LGI = 0x10 | ||
| 2256 | }; | ||
| 2257 | |||
| 2258 | struct ani_global_class_a_stats_info { | ||
| 2259 | /* The number of MPDU frames received by the 802.11 station for | ||
| 2260 | * MSDU packets or MMPDU frames */ | ||
| 2261 | u32 rx_frag_cnt; | ||
| 2262 | |||
| 2263 | /* The number of MPDU frames received by the 802.11 station for | ||
| 2264 | * MSDU packets or MMPDU frames when a promiscuous packet filter | ||
| 2265 | * was enabled */ | ||
| 2266 | u32 promiscuous_rx_frag_cnt; | ||
| 2267 | |||
| 2268 | /* The receiver input sensitivity referenced to a FER of 8% at an | ||
| 2269 | * MPDU length of 1024 bytes at the antenna connector. Each element | ||
| 2270 | * of the array shall correspond to a supported rate and the order | ||
| 2271 | * shall be the same as the supporteRates parameter. */ | ||
| 2272 | u32 rx_input_sensitivity; | ||
| 2273 | |||
| 2274 | /* The maximum transmit power in dBm upto one decimal. for eg: if | ||
| 2275 | * it is 10.5dBm, the value would be 105 */ | ||
| 2276 | u32 max_pwr; | ||
| 2277 | |||
| 2278 | /* Number of times the receiver failed to synchronize with the | ||
| 2279 | * incoming signal after detecting the sync in the preamble of the | ||
| 2280 | * transmitted PLCP protocol data unit. */ | ||
| 2281 | u32 sync_fail_cnt; | ||
| 2282 | |||
| 2283 | /* Legacy transmit rate, in units of 500 kbit/sec, for the most | ||
| 2284 | * recently transmitted frame */ | ||
| 2285 | u32 tx_rate; | ||
| 2286 | |||
| 2287 | /* mcs index for HT20 and HT40 rates */ | ||
| 2288 | u32 mcs_index; | ||
| 2289 | |||
| 2290 | /* to differentiate between HT20 and HT40 rates; short and long | ||
| 2291 | * guard interval */ | ||
| 2292 | u32 tx_rate_flags; | ||
| 2293 | }; | ||
| 2294 | |||
| 2295 | struct ani_global_security_stats { | ||
| 2296 | /* The number of unencrypted received MPDU frames that the MAC | ||
| 2297 | * layer discarded when the IEEE 802.11 dot11ExcludeUnencrypted | ||
| 2298 | * management information base (MIB) object is enabled */ | ||
| 2299 | u32 rx_wep_unencrypted_frm_cnt; | ||
| 2300 | |||
| 2301 | /* The number of received MSDU packets that that the 802.11 station | ||
| 2302 | * discarded because of MIC failures */ | ||
| 2303 | u32 rx_mic_fail_cnt; | ||
| 2304 | |||
| 2305 | /* The number of encrypted MPDU frames that the 802.11 station | ||
| 2306 | * failed to decrypt because of a TKIP ICV error */ | ||
| 2307 | u32 tkip_icv_err; | ||
| 2308 | |||
| 2309 | /* The number of received MPDU frames that the 802.11 discarded | ||
| 2310 | * because of an invalid AES-CCMP format */ | ||
| 2311 | u32 aes_ccmp_format_err; | ||
| 2312 | |||
| 2313 | /* The number of received MPDU frames that the 802.11 station | ||
| 2314 | * discarded because of the AES-CCMP replay protection procedure */ | ||
| 2315 | u32 aes_ccmp_replay_cnt; | ||
| 2316 | |||
| 2317 | /* The number of received MPDU frames that the 802.11 station | ||
| 2318 | * discarded because of errors detected by the AES-CCMP decryption | ||
| 2319 | * algorithm */ | ||
| 2320 | u32 aes_ccmp_decrpt_err; | ||
| 2321 | |||
| 2322 | /* The number of encrypted MPDU frames received for which a WEP | ||
| 2323 | * decryption key was not available on the 802.11 station */ | ||
| 2324 | u32 wep_undecryptable_cnt; | ||
| 2325 | |||
| 2326 | /* The number of encrypted MPDU frames that the 802.11 station | ||
| 2327 | * failed to decrypt because of a WEP ICV error */ | ||
| 2328 | u32 wep_icv_err; | ||
| 2329 | |||
| 2330 | /* The number of received encrypted packets that the 802.11 station | ||
| 2331 | * successfully decrypted */ | ||
| 2332 | u32 rx_decrypt_succ_cnt; | ||
| 2333 | |||
| 2334 | /* The number of encrypted packets that the 802.11 station failed | ||
| 2335 | * to decrypt */ | ||
| 2336 | u32 rx_decrypt_fail_cnt; | ||
| 2337 | }; | ||
| 2338 | |||
| 2339 | struct ani_global_class_b_stats_info { | ||
| 2340 | struct ani_global_security_stats uc_stats; | ||
| 2341 | struct ani_global_security_stats mc_bc_stats; | ||
| 2342 | }; | ||
| 2343 | |||
| 2344 | struct ani_global_class_c_stats_info { | ||
| 2345 | /* This counter shall be incremented for a received A-MSDU frame | ||
| 2346 | * with the stations MAC address in the address 1 field or an | ||
| 2347 | * A-MSDU frame with a group address in the address 1 field */ | ||
| 2348 | u32 rx_amsdu_cnt; | ||
| 2349 | |||
| 2350 | /* This counter shall be incremented when the MAC receives an AMPDU | ||
| 2351 | * from the PHY */ | ||
| 2352 | u32 rx_ampdu_cnt; | ||
| 2353 | |||
| 2354 | /* This counter shall be incremented when a Frame is transmitted | ||
| 2355 | * only on the primary channel */ | ||
| 2356 | u32 tx_20_frm_cnt; | ||
| 2357 | |||
| 2358 | /* This counter shall be incremented when a Frame is received only | ||
| 2359 | * on the primary channel */ | ||
| 2360 | u32 rx_20_frm_cnt; | ||
| 2361 | |||
| 2362 | /* This counter shall be incremented by the number of MPDUs | ||
| 2363 | * received in the A-MPDU when an A-MPDU is received */ | ||
| 2364 | u32 rx_mpdu_in_ampdu_cnt; | ||
| 2365 | |||
| 2366 | /* This counter shall be incremented when an MPDU delimiter has a | ||
| 2367 | * CRC error when this is the first CRC error in the received AMPDU | ||
| 2368 | * or when the previous delimiter has been decoded correctly */ | ||
| 2369 | u32 ampdu_delimiter_crc_err; | ||
| 2370 | }; | ||
| 2371 | |||
| 2372 | struct ani_per_sta_stats_info { | ||
| 2373 | /* The number of MPDU frames that the 802.11 station transmitted | ||
| 2374 | * and acknowledged through a received 802.11 ACK frame */ | ||
| 2375 | u32 tx_frag_cnt[4]; | ||
| 2376 | |||
| 2377 | /* This counter shall be incremented when an A-MPDU is transmitted */ | ||
| 2378 | u32 tx_ampdu_cnt; | ||
| 2379 | |||
| 2380 | /* This counter shall increment by the number of MPDUs in the AMPDU | ||
| 2381 | * when an A-MPDU is transmitted */ | ||
| 2382 | u32 tx_mpdu_in_ampdu_cnt; | ||
| 2383 | }; | ||
| 2384 | |||
| 2385 | struct wcn36xx_hal_stats_rsp_msg { | ||
| 2386 | struct wcn36xx_hal_msg_header header; | ||
| 2387 | |||
| 2388 | /* Success or Failure */ | ||
| 2389 | u32 status; | ||
| 2390 | |||
| 2391 | /* STA Idx */ | ||
| 2392 | u32 sta_index; | ||
| 2393 | |||
| 2394 | /* Categories of STATS being returned as per eHalStatsMask */ | ||
| 2395 | u32 stats_mask; | ||
| 2396 | |||
| 2397 | /* message type is same as the request type */ | ||
| 2398 | u16 msg_type; | ||
| 2399 | |||
| 2400 | /* length of the entire request, includes the pStatsBuf length too */ | ||
| 2401 | u16 msg_len; | ||
| 2402 | }; | ||
| 2403 | |||
| 2404 | struct wcn36xx_hal_set_link_state_req_msg { | ||
| 2405 | struct wcn36xx_hal_msg_header header; | ||
| 2406 | |||
| 2407 | u8 bssid[ETH_ALEN]; | ||
| 2408 | enum wcn36xx_hal_link_state state; | ||
| 2409 | u8 self_mac_addr[ETH_ALEN]; | ||
| 2410 | |||
| 2411 | } __packed; | ||
| 2412 | |||
| 2413 | struct set_link_state_rsp_msg { | ||
| 2414 | struct wcn36xx_hal_msg_header header; | ||
| 2415 | |||
| 2416 | /* success or failure */ | ||
| 2417 | u32 status; | ||
| 2418 | }; | ||
| 2419 | |||
| 2420 | /* TSPEC Params */ | ||
| 2421 | struct wcn36xx_hal_ts_info_tfc { | ||
| 2422 | #ifndef ANI_LITTLE_BIT_ENDIAN | ||
| 2423 | u16 ackPolicy:2; | ||
| 2424 | u16 userPrio:3; | ||
| 2425 | u16 psb:1; | ||
| 2426 | u16 aggregation:1; | ||
| 2427 | u16 accessPolicy:2; | ||
| 2428 | u16 direction:2; | ||
| 2429 | u16 tsid:4; | ||
| 2430 | u16 trafficType:1; | ||
| 2431 | #else | ||
| 2432 | u16 trafficType:1; | ||
| 2433 | u16 tsid:4; | ||
| 2434 | u16 direction:2; | ||
| 2435 | u16 accessPolicy:2; | ||
| 2436 | u16 aggregation:1; | ||
| 2437 | u16 psb:1; | ||
| 2438 | u16 userPrio:3; | ||
| 2439 | u16 ackPolicy:2; | ||
| 2440 | #endif | ||
| 2441 | }; | ||
| 2442 | |||
| 2443 | /* Flag to schedule the traffic type */ | ||
| 2444 | struct wcn36xx_hal_ts_info_sch { | ||
| 2445 | #ifndef ANI_LITTLE_BIT_ENDIAN | ||
| 2446 | u8 rsvd:7; | ||
| 2447 | u8 schedule:1; | ||
| 2448 | #else | ||
| 2449 | u8 schedule:1; | ||
| 2450 | u8 rsvd:7; | ||
| 2451 | #endif | ||
| 2452 | }; | ||
| 2453 | |||
| 2454 | /* Traffic and scheduling info */ | ||
| 2455 | struct wcn36xx_hal_ts_info { | ||
| 2456 | struct wcn36xx_hal_ts_info_tfc traffic; | ||
| 2457 | struct wcn36xx_hal_ts_info_sch schedule; | ||
| 2458 | }; | ||
| 2459 | |||
| 2460 | /* Information elements */ | ||
| 2461 | struct wcn36xx_hal_tspec_ie { | ||
| 2462 | u8 type; | ||
| 2463 | u8 length; | ||
| 2464 | struct wcn36xx_hal_ts_info ts_info; | ||
| 2465 | u16 nom_msdu_size; | ||
| 2466 | u16 max_msdu_size; | ||
| 2467 | u32 min_svc_interval; | ||
| 2468 | u32 max_svc_interval; | ||
| 2469 | u32 inact_interval; | ||
| 2470 | u32 suspend_interval; | ||
| 2471 | u32 svc_start_time; | ||
| 2472 | u32 min_data_rate; | ||
| 2473 | u32 mean_data_rate; | ||
| 2474 | u32 peak_data_rate; | ||
| 2475 | u32 max_burst_sz; | ||
| 2476 | u32 delay_bound; | ||
| 2477 | u32 min_phy_rate; | ||
| 2478 | u16 surplus_bw; | ||
| 2479 | u16 medium_time; | ||
| 2480 | }; | ||
| 2481 | |||
| 2482 | struct add_ts_req_msg { | ||
| 2483 | struct wcn36xx_hal_msg_header header; | ||
| 2484 | |||
| 2485 | /* Station Index */ | ||
| 2486 | u16 sta_index; | ||
| 2487 | |||
| 2488 | /* TSPEC handler uniquely identifying a TSPEC for a STA in a BSS */ | ||
| 2489 | u16 tspec_index; | ||
| 2490 | |||
| 2491 | /* To program TPE with required parameters */ | ||
| 2492 | struct wcn36xx_hal_tspec_ie tspec; | ||
| 2493 | |||
| 2494 | /* U-APSD Flags: 1b per AC. Encoded as follows: | ||
| 2495 | b7 b6 b5 b4 b3 b2 b1 b0 = | ||
| 2496 | X X X X BE BK VI VO */ | ||
| 2497 | u8 uapsd; | ||
| 2498 | |||
| 2499 | /* These parameters are for all the access categories */ | ||
| 2500 | |||
| 2501 | /* Service Interval */ | ||
| 2502 | u32 service_interval[WCN36XX_HAL_MAX_AC]; | ||
| 2503 | |||
| 2504 | /* Suspend Interval */ | ||
| 2505 | u32 suspend_interval[WCN36XX_HAL_MAX_AC]; | ||
| 2506 | |||
| 2507 | /* Delay Interval */ | ||
| 2508 | u32 delay_interval[WCN36XX_HAL_MAX_AC]; | ||
| 2509 | }; | ||
| 2510 | |||
| 2511 | struct add_rs_rsp_msg { | ||
| 2512 | struct wcn36xx_hal_msg_header header; | ||
| 2513 | |||
| 2514 | /* success or failure */ | ||
| 2515 | u32 status; | ||
| 2516 | }; | ||
| 2517 | |||
| 2518 | struct del_ts_req_msg { | ||
| 2519 | struct wcn36xx_hal_msg_header header; | ||
| 2520 | |||
| 2521 | /* Station Index */ | ||
| 2522 | u16 sta_index; | ||
| 2523 | |||
| 2524 | /* TSPEC identifier uniquely identifying a TSPEC for a STA in a BSS */ | ||
| 2525 | u16 tspec_index; | ||
| 2526 | |||
| 2527 | /* To lookup station id using the mac address */ | ||
| 2528 | u8 bssid[ETH_ALEN]; | ||
| 2529 | }; | ||
| 2530 | |||
| 2531 | struct del_ts_rsp_msg { | ||
| 2532 | struct wcn36xx_hal_msg_header header; | ||
| 2533 | |||
| 2534 | /* success or failure */ | ||
| 2535 | u32 status; | ||
| 2536 | }; | ||
| 2537 | |||
| 2538 | /* End of TSpec Parameters */ | ||
| 2539 | |||
| 2540 | /* Start of BLOCK ACK related Parameters */ | ||
| 2541 | |||
| 2542 | struct wcn36xx_hal_add_ba_session_req_msg { | ||
| 2543 | struct wcn36xx_hal_msg_header header; | ||
| 2544 | |||
| 2545 | /* Station Index */ | ||
| 2546 | u16 sta_index; | ||
| 2547 | |||
| 2548 | /* Peer MAC Address */ | ||
| 2549 | u8 mac_addr[ETH_ALEN]; | ||
| 2550 | |||
| 2551 | /* ADDBA Action Frame dialog token | ||
| 2552 | HAL will not interpret this object */ | ||
| 2553 | u8 dialog_token; | ||
| 2554 | |||
| 2555 | /* TID for which the BA is being setup | ||
| 2556 | This identifies the TC or TS of interest */ | ||
| 2557 | u8 tid; | ||
| 2558 | |||
| 2559 | /* 0 - Delayed BA (Not supported) | ||
| 2560 | 1 - Immediate BA */ | ||
| 2561 | u8 policy; | ||
| 2562 | |||
| 2563 | /* Indicates the number of buffers for this TID (baTID) | ||
| 2564 | NOTE - This is the requested buffer size. When this | ||
| 2565 | is processed by HAL and subsequently by HDD, it is | ||
| 2566 | possible that HDD may change this buffer size. Any | ||
| 2567 | change in the buffer size should be noted by PE and | ||
| 2568 | advertized appropriately in the ADDBA response */ | ||
| 2569 | u16 buffer_size; | ||
| 2570 | |||
| 2571 | /* BA timeout in TU's 0 means no timeout will occur */ | ||
| 2572 | u16 timeout; | ||
| 2573 | |||
| 2574 | /* b0..b3 - Fragment Number - Always set to 0 | ||
| 2575 | b4..b15 - Starting Sequence Number of first MSDU | ||
| 2576 | for which this BA is setup */ | ||
| 2577 | u16 ssn; | ||
| 2578 | |||
| 2579 | /* ADDBA direction | ||
| 2580 | 1 - Originator | ||
| 2581 | 0 - Recipient */ | ||
| 2582 | u8 direction; | ||
| 2583 | } __packed; | ||
| 2584 | |||
| 2585 | struct wcn36xx_hal_add_ba_session_rsp_msg { | ||
| 2586 | struct wcn36xx_hal_msg_header header; | ||
| 2587 | |||
| 2588 | /* success or failure */ | ||
| 2589 | u32 status; | ||
| 2590 | |||
| 2591 | /* Dialog token */ | ||
| 2592 | u8 dialog_token; | ||
| 2593 | |||
| 2594 | /* TID for which the BA session has been setup */ | ||
| 2595 | u8 ba_tid; | ||
| 2596 | |||
| 2597 | /* BA Buffer Size allocated for the current BA session */ | ||
| 2598 | u8 ba_buffer_size; | ||
| 2599 | |||
| 2600 | u8 ba_session_id; | ||
| 2601 | |||
| 2602 | /* Reordering Window buffer */ | ||
| 2603 | u8 win_size; | ||
| 2604 | |||
| 2605 | /* Station Index to id the sta */ | ||
| 2606 | u8 sta_index; | ||
| 2607 | |||
| 2608 | /* Starting Sequence Number */ | ||
| 2609 | u16 ssn; | ||
| 2610 | } __packed; | ||
| 2611 | |||
| 2612 | struct wcn36xx_hal_add_ba_req_msg { | ||
| 2613 | struct wcn36xx_hal_msg_header header; | ||
| 2614 | |||
| 2615 | /* Session Id */ | ||
| 2616 | u8 session_id; | ||
| 2617 | |||
| 2618 | /* Reorder Window Size */ | ||
| 2619 | u8 win_size; | ||
| 2620 | /* Old FW 1.2.2.4 does not support this*/ | ||
| 2621 | #ifdef FEATURE_ON_CHIP_REORDERING | ||
| 2622 | u8 reordering_done_on_chip; | ||
| 2623 | #endif | ||
| 2624 | } __packed; | ||
| 2625 | |||
| 2626 | struct wcn36xx_hal_add_ba_rsp_msg { | ||
| 2627 | struct wcn36xx_hal_msg_header header; | ||
| 2628 | |||
| 2629 | /* success or failure */ | ||
| 2630 | u32 status; | ||
| 2631 | |||
| 2632 | /* Dialog token */ | ||
| 2633 | u8 dialog_token; | ||
| 2634 | } __packed; | ||
| 2635 | |||
| 2636 | struct add_ba_info { | ||
| 2637 | u16 ba_enable:1; | ||
| 2638 | u16 starting_seq_num:12; | ||
| 2639 | u16 reserved:3; | ||
| 2640 | }; | ||
| 2641 | |||
| 2642 | struct wcn36xx_hal_trigger_ba_rsp_candidate { | ||
| 2643 | u8 sta_addr[ETH_ALEN]; | ||
| 2644 | struct add_ba_info ba_info[STACFG_MAX_TC]; | ||
| 2645 | } __packed; | ||
| 2646 | |||
| 2647 | struct wcn36xx_hal_trigget_ba_req_candidate { | ||
| 2648 | u8 sta_index; | ||
| 2649 | u8 tid_bitmap; | ||
| 2650 | } __packed; | ||
| 2651 | |||
| 2652 | struct wcn36xx_hal_trigger_ba_req_msg { | ||
| 2653 | struct wcn36xx_hal_msg_header header; | ||
| 2654 | |||
| 2655 | /* Session Id */ | ||
| 2656 | u8 session_id; | ||
| 2657 | |||
| 2658 | /* baCandidateCnt is followed by trigger BA | ||
| 2659 | * Candidate List(tTriggerBaCandidate) | ||
| 2660 | */ | ||
| 2661 | u16 candidate_cnt; | ||
| 2662 | |||
| 2663 | } __packed; | ||
| 2664 | |||
| 2665 | struct wcn36xx_hal_trigger_ba_rsp_msg { | ||
| 2666 | struct wcn36xx_hal_msg_header header; | ||
| 2667 | |||
| 2668 | /* TO SUPPORT BT-AMP */ | ||
| 2669 | u8 bssid[ETH_ALEN]; | ||
| 2670 | |||
| 2671 | /* success or failure */ | ||
| 2672 | u32 status; | ||
| 2673 | |||
| 2674 | /* baCandidateCnt is followed by trigger BA | ||
| 2675 | * Rsp Candidate List(tTriggerRspBaCandidate) | ||
| 2676 | */ | ||
| 2677 | u16 candidate_cnt; | ||
| 2678 | } __packed; | ||
| 2679 | |||
| 2680 | struct wcn36xx_hal_del_ba_req_msg { | ||
| 2681 | struct wcn36xx_hal_msg_header header; | ||
| 2682 | |||
| 2683 | /* Station Index */ | ||
| 2684 | u16 sta_index; | ||
| 2685 | |||
| 2686 | /* TID for which the BA session is being deleted */ | ||
| 2687 | u8 tid; | ||
| 2688 | |||
| 2689 | /* DELBA direction | ||
| 2690 | 1 - Originator | ||
| 2691 | 0 - Recipient */ | ||
| 2692 | u8 direction; | ||
| 2693 | } __packed; | ||
| 2694 | |||
| 2695 | struct wcn36xx_hal_del_ba_rsp_msg { | ||
| 2696 | struct wcn36xx_hal_msg_header header; | ||
| 2697 | |||
| 2698 | /* success or failure */ | ||
| 2699 | u32 status; | ||
| 2700 | } __packed; | ||
| 2701 | |||
| 2702 | struct tsm_stats_req_msg { | ||
| 2703 | struct wcn36xx_hal_msg_header header; | ||
| 2704 | |||
| 2705 | /* Traffic Id */ | ||
| 2706 | u8 tid; | ||
| 2707 | |||
| 2708 | u8 bssid[ETH_ALEN]; | ||
| 2709 | }; | ||
| 2710 | |||
| 2711 | struct tsm_stats_rsp_msg { | ||
| 2712 | struct wcn36xx_hal_msg_header header; | ||
| 2713 | |||
| 2714 | /*success or failure */ | ||
| 2715 | u32 status; | ||
| 2716 | |||
| 2717 | /* Uplink Packet Queue delay */ | ||
| 2718 | u16 uplink_pkt_queue_delay; | ||
| 2719 | |||
| 2720 | /* Uplink Packet Queue delay histogram */ | ||
| 2721 | u16 uplink_pkt_queue_delay_hist[4]; | ||
| 2722 | |||
| 2723 | /* Uplink Packet Transmit delay */ | ||
| 2724 | u32 uplink_pkt_tx_delay; | ||
| 2725 | |||
| 2726 | /* Uplink Packet loss */ | ||
| 2727 | u16 uplink_pkt_loss; | ||
| 2728 | |||
| 2729 | /* Uplink Packet count */ | ||
| 2730 | u16 uplink_pkt_count; | ||
| 2731 | |||
| 2732 | /* Roaming count */ | ||
| 2733 | u8 roaming_count; | ||
| 2734 | |||
| 2735 | /* Roaming Delay */ | ||
| 2736 | u16 roaming_delay; | ||
| 2737 | }; | ||
| 2738 | |||
| 2739 | struct set_key_done_msg { | ||
| 2740 | struct wcn36xx_hal_msg_header header; | ||
| 2741 | |||
| 2742 | /*bssid of the keys */ | ||
| 2743 | u8 bssidx; | ||
| 2744 | u8 enc_type; | ||
| 2745 | }; | ||
| 2746 | |||
| 2747 | struct wcn36xx_hal_nv_img_download_req_msg { | ||
| 2748 | /* Note: The length specified in wcn36xx_hal_nv_img_download_req_msg | ||
| 2749 | * messages should be | ||
| 2750 | * header.len = sizeof(wcn36xx_hal_nv_img_download_req_msg) + | ||
| 2751 | * nv_img_buffer_size */ | ||
| 2752 | struct wcn36xx_hal_msg_header header; | ||
| 2753 | |||
| 2754 | /* Fragment sequence number of the NV Image. Note that NV Image | ||
| 2755 | * might not fit into one message due to size limitation of the SMD | ||
| 2756 | * channel FIFO. UMAC can hence choose to chop the NV blob into | ||
| 2757 | * multiple fragments starting with seqeunce number 0, 1, 2 etc. | ||
| 2758 | * The last fragment MUST be indicated by marking the | ||
| 2759 | * isLastFragment field to 1. Note that all the NV blobs would be | ||
| 2760 | * concatenated together by HAL without any padding bytes in | ||
| 2761 | * between.*/ | ||
| 2762 | u16 frag_number; | ||
| 2763 | |||
| 2764 | /* Is this the last fragment? When set to 1 it indicates that no | ||
| 2765 | * more fragments will be sent by UMAC and HAL can concatenate all | ||
| 2766 | * the NV blobs rcvd & proceed with the parsing. HAL would generate | ||
| 2767 | * a WCN36XX_HAL_DOWNLOAD_NV_RSP to the WCN36XX_HAL_DOWNLOAD_NV_REQ | ||
| 2768 | * after it receives each fragment */ | ||
| 2769 | u16 last_fragment; | ||
| 2770 | |||
| 2771 | /* NV Image size (number of bytes) */ | ||
| 2772 | u32 nv_img_buffer_size; | ||
| 2773 | |||
| 2774 | /* Following the 'nv_img_buffer_size', there should be | ||
| 2775 | * nv_img_buffer_size bytes of NV Image i.e. | ||
| 2776 | * u8[nv_img_buffer_size] */ | ||
| 2777 | } __packed; | ||
| 2778 | |||
| 2779 | struct wcn36xx_hal_nv_img_download_rsp_msg { | ||
| 2780 | struct wcn36xx_hal_msg_header header; | ||
| 2781 | |||
| 2782 | /* Success or Failure. HAL would generate a | ||
| 2783 | * WCN36XX_HAL_DOWNLOAD_NV_RSP after each fragment */ | ||
| 2784 | u32 status; | ||
| 2785 | } __packed; | ||
| 2786 | |||
| 2787 | struct wcn36xx_hal_nv_store_ind { | ||
| 2788 | /* Note: The length specified in tHalNvStoreInd messages should be | ||
| 2789 | * header.msgLen = sizeof(tHalNvStoreInd) + nvBlobSize */ | ||
| 2790 | struct wcn36xx_hal_msg_header header; | ||
| 2791 | |||
| 2792 | /* NV Item */ | ||
| 2793 | u32 table_id; | ||
| 2794 | |||
| 2795 | /* Size of NV Blob */ | ||
| 2796 | u32 nv_blob_size; | ||
| 2797 | |||
| 2798 | /* Following the 'nvBlobSize', there should be nvBlobSize bytes of | ||
| 2799 | * NV blob i.e. u8[nvBlobSize] */ | ||
| 2800 | }; | ||
| 2801 | |||
| 2802 | /* End of Block Ack Related Parameters */ | ||
| 2803 | |||
| 2804 | #define WCN36XX_HAL_CIPHER_SEQ_CTR_SIZE 6 | ||
| 2805 | |||
| 2806 | /* Definition for MIC failure indication MAC reports this each time a MIC | ||
| 2807 | * failure occures on Rx TKIP packet | ||
| 2808 | */ | ||
| 2809 | struct mic_failure_ind_msg { | ||
| 2810 | struct wcn36xx_hal_msg_header header; | ||
| 2811 | |||
| 2812 | u8 bssid[ETH_ALEN]; | ||
| 2813 | |||
| 2814 | /* address used to compute MIC */ | ||
| 2815 | u8 src_addr[ETH_ALEN]; | ||
| 2816 | |||
| 2817 | /* transmitter address */ | ||
| 2818 | u8 ta_addr[ETH_ALEN]; | ||
| 2819 | |||
| 2820 | u8 dst_addr[ETH_ALEN]; | ||
| 2821 | |||
| 2822 | u8 multicast; | ||
| 2823 | |||
| 2824 | /* first byte of IV */ | ||
| 2825 | u8 iv1; | ||
| 2826 | |||
| 2827 | /* second byte of IV */ | ||
| 2828 | u8 key_id; | ||
| 2829 | |||
| 2830 | /* sequence number */ | ||
| 2831 | u8 tsc[WCN36XX_HAL_CIPHER_SEQ_CTR_SIZE]; | ||
| 2832 | |||
| 2833 | /* receive address */ | ||
| 2834 | u8 rx_addr[ETH_ALEN]; | ||
| 2835 | }; | ||
| 2836 | |||
| 2837 | struct update_vht_op_mode_req_msg { | ||
| 2838 | struct wcn36xx_hal_msg_header header; | ||
| 2839 | |||
| 2840 | u16 op_mode; | ||
| 2841 | u16 sta_id; | ||
| 2842 | }; | ||
| 2843 | |||
| 2844 | struct update_vht_op_mode_params_rsp_msg { | ||
| 2845 | struct wcn36xx_hal_msg_header header; | ||
| 2846 | |||
| 2847 | u32 status; | ||
| 2848 | }; | ||
| 2849 | |||
| 2850 | struct update_beacon_req_msg { | ||
| 2851 | struct wcn36xx_hal_msg_header header; | ||
| 2852 | |||
| 2853 | u8 bss_index; | ||
| 2854 | |||
| 2855 | /* shortPreamble mode. HAL should update all the STA rates when it | ||
| 2856 | * receives this message */ | ||
| 2857 | u8 short_preamble; | ||
| 2858 | |||
| 2859 | /* short Slot time. */ | ||
| 2860 | u8 short_slot_time; | ||
| 2861 | |||
| 2862 | /* Beacon Interval */ | ||
| 2863 | u16 beacon_interval; | ||
| 2864 | |||
| 2865 | /* Protection related */ | ||
| 2866 | u8 lla_coexist; | ||
| 2867 | u8 llb_coexist; | ||
| 2868 | u8 llg_coexist; | ||
| 2869 | u8 ht20_coexist; | ||
| 2870 | u8 lln_non_gf_coexist; | ||
| 2871 | u8 lsig_tx_op_protection_full_support; | ||
| 2872 | u8 rifs_mode; | ||
| 2873 | |||
| 2874 | u16 param_change_bitmap; | ||
| 2875 | }; | ||
| 2876 | |||
| 2877 | struct update_beacon_rsp_msg { | ||
| 2878 | struct wcn36xx_hal_msg_header header; | ||
| 2879 | u32 status; | ||
| 2880 | }; | ||
| 2881 | |||
| 2882 | struct wcn36xx_hal_send_beacon_req_msg { | ||
| 2883 | struct wcn36xx_hal_msg_header header; | ||
| 2884 | |||
| 2885 | /* length of the template. */ | ||
| 2886 | u32 beacon_length; | ||
| 2887 | |||
| 2888 | /* Beacon data. */ | ||
| 2889 | u8 beacon[BEACON_TEMPLATE_SIZE]; | ||
| 2890 | |||
| 2891 | u8 bssid[ETH_ALEN]; | ||
| 2892 | |||
| 2893 | /* TIM IE offset from the beginning of the template. */ | ||
| 2894 | u32 tim_ie_offset; | ||
| 2895 | |||
| 2896 | /* P2P IE offset from the begining of the template */ | ||
| 2897 | u16 p2p_ie_offset; | ||
| 2898 | } __packed; | ||
| 2899 | |||
| 2900 | struct send_beacon_rsp_msg { | ||
| 2901 | struct wcn36xx_hal_msg_header header; | ||
| 2902 | u32 status; | ||
| 2903 | } __packed; | ||
| 2904 | |||
| 2905 | struct enable_radar_req_msg { | ||
| 2906 | struct wcn36xx_hal_msg_header header; | ||
| 2907 | |||
| 2908 | u8 bssid[ETH_ALEN]; | ||
| 2909 | u8 channel; | ||
| 2910 | }; | ||
| 2911 | |||
| 2912 | struct enable_radar_rsp_msg { | ||
| 2913 | struct wcn36xx_hal_msg_header header; | ||
| 2914 | |||
| 2915 | /* Link Parameters */ | ||
| 2916 | u8 bssid[ETH_ALEN]; | ||
| 2917 | |||
| 2918 | /* success or failure */ | ||
| 2919 | u32 status; | ||
| 2920 | }; | ||
| 2921 | |||
| 2922 | struct radar_detect_intr_ind_msg { | ||
| 2923 | struct wcn36xx_hal_msg_header header; | ||
| 2924 | |||
| 2925 | u8 radar_det_channel; | ||
| 2926 | }; | ||
| 2927 | |||
| 2928 | struct radar_detect_ind_msg { | ||
| 2929 | struct wcn36xx_hal_msg_header header; | ||
| 2930 | |||
| 2931 | /* channel number in which the RADAR detected */ | ||
| 2932 | u8 channel_number; | ||
| 2933 | |||
| 2934 | /* RADAR pulse width in usecond */ | ||
| 2935 | u16 radar_pulse_width; | ||
| 2936 | |||
| 2937 | /* Number of RADAR pulses */ | ||
| 2938 | u16 num_radar_pulse; | ||
| 2939 | }; | ||
| 2940 | |||
| 2941 | struct wcn36xx_hal_get_tpc_report_req_msg { | ||
| 2942 | struct wcn36xx_hal_msg_header header; | ||
| 2943 | |||
| 2944 | u8 sta[ETH_ALEN]; | ||
| 2945 | u8 dialog_token; | ||
| 2946 | u8 txpower; | ||
| 2947 | }; | ||
| 2948 | |||
| 2949 | struct wcn36xx_hal_get_tpc_report_rsp_msg { | ||
| 2950 | struct wcn36xx_hal_msg_header header; | ||
| 2951 | |||
| 2952 | /* success or failure */ | ||
| 2953 | u32 status; | ||
| 2954 | }; | ||
| 2955 | |||
| 2956 | struct wcn36xx_hal_send_probe_resp_req_msg { | ||
| 2957 | struct wcn36xx_hal_msg_header header; | ||
| 2958 | |||
| 2959 | u8 probe_resp_template[BEACON_TEMPLATE_SIZE]; | ||
| 2960 | u32 probe_resp_template_len; | ||
| 2961 | u32 proxy_probe_req_valid_ie_bmap[8]; | ||
| 2962 | u8 bssid[ETH_ALEN]; | ||
| 2963 | }; | ||
| 2964 | |||
| 2965 | struct send_probe_resp_rsp_msg { | ||
| 2966 | struct wcn36xx_hal_msg_header header; | ||
| 2967 | |||
| 2968 | /* success or failure */ | ||
| 2969 | u32 status; | ||
| 2970 | }; | ||
| 2971 | |||
| 2972 | struct send_unknown_frame_rx_ind_msg { | ||
| 2973 | struct wcn36xx_hal_msg_header header; | ||
| 2974 | |||
| 2975 | /* success or failure */ | ||
| 2976 | u32 status; | ||
| 2977 | }; | ||
| 2978 | |||
| 2979 | struct wcn36xx_hal_delete_sta_context_ind_msg { | ||
| 2980 | struct wcn36xx_hal_msg_header header; | ||
| 2981 | |||
| 2982 | u16 aid; | ||
| 2983 | u16 sta_id; | ||
| 2984 | |||
| 2985 | /* TO SUPPORT BT-AMP */ | ||
| 2986 | u8 bssid[ETH_ALEN]; | ||
| 2987 | |||
| 2988 | /* HAL copies bssid from the sta table. */ | ||
| 2989 | u8 addr2[ETH_ALEN]; | ||
| 2990 | |||
| 2991 | /* To unify the keepalive / unknown A2 / tim-based disa */ | ||
| 2992 | u16 reason_code; | ||
| 2993 | } __packed; | ||
| 2994 | |||
| 2995 | struct indicate_del_sta { | ||
| 2996 | struct wcn36xx_hal_msg_header header; | ||
| 2997 | u8 aid; | ||
| 2998 | u8 sta_index; | ||
| 2999 | u8 bss_index; | ||
| 3000 | u8 reason_code; | ||
| 3001 | u32 status; | ||
| 3002 | }; | ||
| 3003 | |||
| 3004 | struct bt_amp_event_msg { | ||
| 3005 | struct wcn36xx_hal_msg_header header; | ||
| 3006 | |||
| 3007 | enum bt_amp_event_type btAmpEventType; | ||
| 3008 | }; | ||
| 3009 | |||
| 3010 | struct bt_amp_event_rsp { | ||
| 3011 | struct wcn36xx_hal_msg_header header; | ||
| 3012 | |||
| 3013 | /* success or failure */ | ||
| 3014 | u32 status; | ||
| 3015 | }; | ||
| 3016 | |||
| 3017 | struct tl_hal_flush_ac_req_msg { | ||
| 3018 | struct wcn36xx_hal_msg_header header; | ||
| 3019 | |||
| 3020 | /* Station Index. originates from HAL */ | ||
| 3021 | u8 sta_id; | ||
| 3022 | |||
| 3023 | /* TID for which the transmit queue is being flushed */ | ||
| 3024 | u8 tid; | ||
| 3025 | }; | ||
| 3026 | |||
| 3027 | struct tl_hal_flush_ac_rsp_msg { | ||
| 3028 | struct wcn36xx_hal_msg_header header; | ||
| 3029 | |||
| 3030 | /* Station Index. originates from HAL */ | ||
| 3031 | u8 sta_id; | ||
| 3032 | |||
| 3033 | /* TID for which the transmit queue is being flushed */ | ||
| 3034 | u8 tid; | ||
| 3035 | |||
| 3036 | /* success or failure */ | ||
| 3037 | u32 status; | ||
| 3038 | }; | ||
| 3039 | |||
| 3040 | struct wcn36xx_hal_enter_imps_req_msg { | ||
| 3041 | struct wcn36xx_hal_msg_header header; | ||
| 3042 | }; | ||
| 3043 | |||
| 3044 | struct wcn36xx_hal_exit_imps_req { | ||
| 3045 | struct wcn36xx_hal_msg_header header; | ||
| 3046 | }; | ||
| 3047 | |||
| 3048 | struct wcn36xx_hal_enter_bmps_req_msg { | ||
| 3049 | struct wcn36xx_hal_msg_header header; | ||
| 3050 | |||
| 3051 | u8 bss_index; | ||
| 3052 | |||
| 3053 | /* TBTT value derived from the last beacon */ | ||
| 3054 | #ifndef BUILD_QWPTTSTATIC | ||
| 3055 | u64 tbtt; | ||
| 3056 | #endif | ||
| 3057 | u8 dtim_count; | ||
| 3058 | |||
| 3059 | /* DTIM period given to HAL during association may not be valid, if | ||
| 3060 | * association is based on ProbeRsp instead of beacon. */ | ||
| 3061 | u8 dtim_period; | ||
| 3062 | |||
| 3063 | /* For CCX and 11R Roaming */ | ||
| 3064 | u32 rssi_filter_period; | ||
| 3065 | |||
| 3066 | u32 num_beacon_per_rssi_average; | ||
| 3067 | u8 rssi_filter_enable; | ||
| 3068 | } __packed; | ||
| 3069 | |||
| 3070 | struct wcn36xx_hal_exit_bmps_req_msg { | ||
| 3071 | struct wcn36xx_hal_msg_header header; | ||
| 3072 | |||
| 3073 | u8 send_data_null; | ||
| 3074 | u8 bss_index; | ||
| 3075 | } __packed; | ||
| 3076 | |||
| 3077 | struct wcn36xx_hal_missed_beacon_ind_msg { | ||
| 3078 | struct wcn36xx_hal_msg_header header; | ||
| 3079 | |||
| 3080 | u8 bss_index; | ||
| 3081 | } __packed; | ||
| 3082 | |||
| 3083 | /* Beacon Filtering data structures */ | ||
| 3084 | |||
| 3085 | /* The above structure would be followed by multiple of below mentioned | ||
| 3086 | * structure | ||
| 3087 | */ | ||
| 3088 | struct beacon_filter_ie { | ||
| 3089 | u8 element_id; | ||
| 3090 | u8 check_ie_presence; | ||
| 3091 | u8 offset; | ||
| 3092 | u8 value; | ||
| 3093 | u8 bitmask; | ||
| 3094 | u8 ref; | ||
| 3095 | }; | ||
| 3096 | |||
| 3097 | struct wcn36xx_hal_add_bcn_filter_req_msg { | ||
| 3098 | struct wcn36xx_hal_msg_header header; | ||
| 3099 | |||
| 3100 | u16 capability_info; | ||
| 3101 | u16 capability_mask; | ||
| 3102 | u16 beacon_interval; | ||
| 3103 | u16 ie_num; | ||
| 3104 | u8 bss_index; | ||
| 3105 | u8 reserved; | ||
| 3106 | }; | ||
| 3107 | |||
| 3108 | struct wcn36xx_hal_rem_bcn_filter_req { | ||
| 3109 | struct wcn36xx_hal_msg_header header; | ||
| 3110 | |||
| 3111 | u8 ie_Count; | ||
| 3112 | u8 rem_ie_id[1]; | ||
| 3113 | }; | ||
| 3114 | |||
| 3115 | #define WCN36XX_HAL_IPV4_ARP_REPLY_OFFLOAD 0 | ||
| 3116 | #define WCN36XX_HAL_IPV6_NEIGHBOR_DISCOVERY_OFFLOAD 1 | ||
| 3117 | #define WCN36XX_HAL_IPV6_NS_OFFLOAD 2 | ||
| 3118 | #define WCN36XX_HAL_IPV6_ADDR_LEN 16 | ||
| 3119 | #define WCN36XX_HAL_OFFLOAD_DISABLE 0 | ||
| 3120 | #define WCN36XX_HAL_OFFLOAD_ENABLE 1 | ||
| 3121 | #define WCN36XX_HAL_OFFLOAD_BCAST_FILTER_ENABLE 0x2 | ||
| 3122 | #define WCN36XX_HAL_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE \ | ||
| 3123 | (HAL_OFFLOAD_ENABLE|HAL_OFFLOAD_BCAST_FILTER_ENABLE) | ||
| 3124 | |||
| 3125 | struct wcn36xx_hal_ns_offload_params { | ||
| 3126 | u8 src_ipv6_addr[WCN36XX_HAL_IPV6_ADDR_LEN]; | ||
| 3127 | u8 self_ipv6_addr[WCN36XX_HAL_IPV6_ADDR_LEN]; | ||
| 3128 | |||
| 3129 | /* Only support 2 possible Network Advertisement IPv6 address */ | ||
| 3130 | u8 target_ipv6_addr1[WCN36XX_HAL_IPV6_ADDR_LEN]; | ||
| 3131 | u8 target_ipv6_addr2[WCN36XX_HAL_IPV6_ADDR_LEN]; | ||
| 3132 | |||
| 3133 | u8 self_addr[ETH_ALEN]; | ||
| 3134 | u8 src_ipv6_addr_valid:1; | ||
| 3135 | u8 target_ipv6_addr1_valid:1; | ||
| 3136 | u8 target_ipv6_addr2_valid:1; | ||
| 3137 | u8 reserved1:5; | ||
| 3138 | |||
| 3139 | /* make it DWORD aligned */ | ||
| 3140 | u8 reserved2; | ||
| 3141 | |||
| 3142 | /* slot index for this offload */ | ||
| 3143 | u32 slot_index; | ||
| 3144 | u8 bss_index; | ||
| 3145 | }; | ||
| 3146 | |||
| 3147 | struct wcn36xx_hal_host_offload_req { | ||
| 3148 | u8 offload_Type; | ||
| 3149 | |||
| 3150 | /* enable or disable */ | ||
| 3151 | u8 enable; | ||
| 3152 | |||
| 3153 | union { | ||
| 3154 | u8 host_ipv4_addr[4]; | ||
| 3155 | u8 host_ipv6_addr[WCN36XX_HAL_IPV6_ADDR_LEN]; | ||
| 3156 | } u; | ||
| 3157 | }; | ||
| 3158 | |||
| 3159 | struct wcn36xx_hal_host_offload_req_msg { | ||
| 3160 | struct wcn36xx_hal_msg_header header; | ||
| 3161 | struct wcn36xx_hal_host_offload_req host_offload_params; | ||
| 3162 | struct wcn36xx_hal_ns_offload_params ns_offload_params; | ||
| 3163 | }; | ||
| 3164 | |||
| 3165 | /* Packet Types. */ | ||
| 3166 | #define WCN36XX_HAL_KEEP_ALIVE_NULL_PKT 1 | ||
| 3167 | #define WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP 2 | ||
| 3168 | |||
| 3169 | /* Enable or disable keep alive */ | ||
| 3170 | #define WCN36XX_HAL_KEEP_ALIVE_DISABLE 0 | ||
| 3171 | #define WCN36XX_HAL_KEEP_ALIVE_ENABLE 1 | ||
| 3172 | #define WCN36XX_KEEP_ALIVE_TIME_PERIOD 30 /* unit: s */ | ||
| 3173 | |||
| 3174 | /* Keep Alive request. */ | ||
| 3175 | struct wcn36xx_hal_keep_alive_req_msg { | ||
| 3176 | struct wcn36xx_hal_msg_header header; | ||
| 3177 | |||
| 3178 | u8 packet_type; | ||
| 3179 | u32 time_period; | ||
| 3180 | u8 host_ipv4_addr[WCN36XX_HAL_IPV4_ADDR_LEN]; | ||
| 3181 | u8 dest_ipv4_addr[WCN36XX_HAL_IPV4_ADDR_LEN]; | ||
| 3182 | u8 dest_addr[ETH_ALEN]; | ||
| 3183 | u8 bss_index; | ||
| 3184 | } __packed; | ||
| 3185 | |||
| 3186 | struct wcn36xx_hal_rssi_threshold_req_msg { | ||
| 3187 | struct wcn36xx_hal_msg_header header; | ||
| 3188 | |||
| 3189 | s8 threshold1:8; | ||
| 3190 | s8 threshold2:8; | ||
| 3191 | s8 threshold3:8; | ||
| 3192 | u8 thres1_pos_notify:1; | ||
| 3193 | u8 thres1_neg_notify:1; | ||
| 3194 | u8 thres2_pos_notify:1; | ||
| 3195 | u8 thres2_neg_notify:1; | ||
| 3196 | u8 thres3_pos_notify:1; | ||
| 3197 | u8 thres3_neg_notify:1; | ||
| 3198 | u8 reserved10:2; | ||
| 3199 | }; | ||
| 3200 | |||
| 3201 | struct wcn36xx_hal_enter_uapsd_req_msg { | ||
| 3202 | struct wcn36xx_hal_msg_header header; | ||
| 3203 | |||
| 3204 | u8 bk_delivery:1; | ||
| 3205 | u8 be_delivery:1; | ||
| 3206 | u8 vi_delivery:1; | ||
| 3207 | u8 vo_delivery:1; | ||
| 3208 | u8 bk_trigger:1; | ||
| 3209 | u8 be_trigger:1; | ||
| 3210 | u8 vi_trigger:1; | ||
| 3211 | u8 vo_trigger:1; | ||
| 3212 | u8 bss_index; | ||
| 3213 | }; | ||
| 3214 | |||
| 3215 | struct wcn36xx_hal_exit_uapsd_req_msg { | ||
| 3216 | struct wcn36xx_hal_msg_header header; | ||
| 3217 | u8 bss_index; | ||
| 3218 | }; | ||
| 3219 | |||
| 3220 | #define WCN36XX_HAL_WOWL_BCAST_PATTERN_MAX_SIZE 128 | ||
| 3221 | #define WCN36XX_HAL_WOWL_BCAST_MAX_NUM_PATTERNS 16 | ||
| 3222 | |||
| 3223 | struct wcn36xx_hal_wowl_add_bcast_ptrn_req_msg { | ||
| 3224 | struct wcn36xx_hal_msg_header header; | ||
| 3225 | |||
| 3226 | /* Pattern ID */ | ||
| 3227 | u8 id; | ||
| 3228 | |||
| 3229 | /* Pattern byte offset from beginning of the 802.11 packet to start | ||
| 3230 | * of the wake-up pattern */ | ||
| 3231 | u8 byte_Offset; | ||
| 3232 | |||
| 3233 | /* Non-Zero Pattern size */ | ||
| 3234 | u8 size; | ||
| 3235 | |||
| 3236 | /* Pattern */ | ||
| 3237 | u8 pattern[WCN36XX_HAL_WOWL_BCAST_PATTERN_MAX_SIZE]; | ||
| 3238 | |||
| 3239 | /* Non-zero pattern mask size */ | ||
| 3240 | u8 mask_size; | ||
| 3241 | |||
| 3242 | /* Pattern mask */ | ||
| 3243 | u8 mask[WCN36XX_HAL_WOWL_BCAST_PATTERN_MAX_SIZE]; | ||
| 3244 | |||
| 3245 | /* Extra pattern */ | ||
| 3246 | u8 extra[WCN36XX_HAL_WOWL_BCAST_PATTERN_MAX_SIZE]; | ||
| 3247 | |||
| 3248 | /* Extra pattern mask */ | ||
| 3249 | u8 mask_extra[WCN36XX_HAL_WOWL_BCAST_PATTERN_MAX_SIZE]; | ||
| 3250 | |||
| 3251 | u8 bss_index; | ||
| 3252 | }; | ||
| 3253 | |||
| 3254 | struct wcn36xx_hal_wow_del_bcast_ptrn_req_msg { | ||
| 3255 | struct wcn36xx_hal_msg_header header; | ||
| 3256 | |||
| 3257 | /* Pattern ID of the wakeup pattern to be deleted */ | ||
| 3258 | u8 id; | ||
| 3259 | u8 bss_index; | ||
| 3260 | }; | ||
| 3261 | |||
| 3262 | struct wcn36xx_hal_wowl_enter_req_msg { | ||
| 3263 | struct wcn36xx_hal_msg_header header; | ||
| 3264 | |||
| 3265 | /* Enables/disables magic packet filtering */ | ||
| 3266 | u8 magic_packet_enable; | ||
| 3267 | |||
| 3268 | /* Magic pattern */ | ||
| 3269 | u8 magic_pattern[ETH_ALEN]; | ||
| 3270 | |||
| 3271 | /* Enables/disables packet pattern filtering in firmware. Enabling | ||
| 3272 | * this flag enables broadcast pattern matching in Firmware. If | ||
| 3273 | * unicast pattern matching is also desired, | ||
| 3274 | * ucUcastPatternFilteringEnable flag must be set tot true as well | ||
| 3275 | */ | ||
| 3276 | u8 pattern_filtering_enable; | ||
| 3277 | |||
| 3278 | /* Enables/disables unicast packet pattern filtering. This flag | ||
| 3279 | * specifies whether we want to do pattern match on unicast packets | ||
| 3280 | * as well and not just broadcast packets. This flag has no effect | ||
| 3281 | * if the ucPatternFilteringEnable (main controlling flag) is set | ||
| 3282 | * to false | ||
| 3283 | */ | ||
| 3284 | u8 ucast_pattern_filtering_enable; | ||
| 3285 | |||
| 3286 | /* This configuration is valid only when magicPktEnable=1. It | ||
| 3287 | * requests hardware to wake up when it receives the Channel Switch | ||
| 3288 | * Action Frame. | ||
| 3289 | */ | ||
| 3290 | u8 wow_channel_switch_receive; | ||
| 3291 | |||
| 3292 | /* This configuration is valid only when magicPktEnable=1. It | ||
| 3293 | * requests hardware to wake up when it receives the | ||
| 3294 | * Deauthentication Frame. | ||
| 3295 | */ | ||
| 3296 | u8 wow_deauth_receive; | ||
| 3297 | |||
| 3298 | /* This configuration is valid only when magicPktEnable=1. It | ||
| 3299 | * requests hardware to wake up when it receives the Disassociation | ||
| 3300 | * Frame. | ||
| 3301 | */ | ||
| 3302 | u8 wow_disassoc_receive; | ||
| 3303 | |||
| 3304 | /* This configuration is valid only when magicPktEnable=1. It | ||
| 3305 | * requests hardware to wake up when it has missed consecutive | ||
| 3306 | * beacons. This is a hardware register configuration (NOT a | ||
| 3307 | * firmware configuration). | ||
| 3308 | */ | ||
| 3309 | u8 wow_max_missed_beacons; | ||
| 3310 | |||
| 3311 | /* This configuration is valid only when magicPktEnable=1. This is | ||
| 3312 | * a timeout value in units of microsec. It requests hardware to | ||
| 3313 | * unconditionally wake up after it has stayed in WoWLAN mode for | ||
| 3314 | * some time. Set 0 to disable this feature. | ||
| 3315 | */ | ||
| 3316 | u8 wow_max_sleep; | ||
| 3317 | |||
| 3318 | /* This configuration directs the WoW packet filtering to look for | ||
| 3319 | * EAP-ID requests embedded in EAPOL frames and use this as a wake | ||
| 3320 | * source. | ||
| 3321 | */ | ||
| 3322 | u8 wow_eap_id_request_enable; | ||
| 3323 | |||
| 3324 | /* This configuration directs the WoW packet filtering to look for | ||
| 3325 | * EAPOL-4WAY requests and use this as a wake source. | ||
| 3326 | */ | ||
| 3327 | u8 wow_eapol_4way_enable; | ||
| 3328 | |||
| 3329 | /* This configuration allows a host wakeup on an network scan | ||
| 3330 | * offload match. | ||
| 3331 | */ | ||
| 3332 | u8 wow_net_scan_offload_match; | ||
| 3333 | |||
| 3334 | /* This configuration allows a host wakeup on any GTK rekeying | ||
| 3335 | * error. | ||
| 3336 | */ | ||
| 3337 | u8 wow_gtk_rekey_error; | ||
| 3338 | |||
| 3339 | /* This configuration allows a host wakeup on BSS connection loss. | ||
| 3340 | */ | ||
| 3341 | u8 wow_bss_connection_loss; | ||
| 3342 | |||
| 3343 | u8 bss_index; | ||
| 3344 | }; | ||
| 3345 | |||
| 3346 | struct wcn36xx_hal_wowl_exit_req_msg { | ||
| 3347 | struct wcn36xx_hal_msg_header header; | ||
| 3348 | |||
| 3349 | u8 bss_index; | ||
| 3350 | }; | ||
| 3351 | |||
| 3352 | struct wcn36xx_hal_get_rssi_req_msg { | ||
| 3353 | struct wcn36xx_hal_msg_header header; | ||
| 3354 | }; | ||
| 3355 | |||
| 3356 | struct wcn36xx_hal_get_roam_rssi_req_msg { | ||
| 3357 | struct wcn36xx_hal_msg_header header; | ||
| 3358 | |||
| 3359 | /* Valid STA Idx for per STA stats request */ | ||
| 3360 | u32 sta_id; | ||
| 3361 | }; | ||
| 3362 | |||
| 3363 | struct wcn36xx_hal_set_uapsd_ac_params_req_msg { | ||
| 3364 | struct wcn36xx_hal_msg_header header; | ||
| 3365 | |||
| 3366 | /* STA index */ | ||
| 3367 | u8 sta_idx; | ||
| 3368 | |||
| 3369 | /* Access Category */ | ||
| 3370 | u8 ac; | ||
| 3371 | |||
| 3372 | /* User Priority */ | ||
| 3373 | u8 up; | ||
| 3374 | |||
| 3375 | /* Service Interval */ | ||
| 3376 | u32 service_interval; | ||
| 3377 | |||
| 3378 | /* Suspend Interval */ | ||
| 3379 | u32 suspend_interval; | ||
| 3380 | |||
| 3381 | /* Delay Interval */ | ||
| 3382 | u32 delay_interval; | ||
| 3383 | }; | ||
| 3384 | |||
| 3385 | struct wcn36xx_hal_configure_rxp_filter_req_msg { | ||
| 3386 | struct wcn36xx_hal_msg_header header; | ||
| 3387 | |||
| 3388 | u8 set_mcst_bcst_filter_setting; | ||
| 3389 | u8 set_mcst_bcst_filter; | ||
| 3390 | }; | ||
| 3391 | |||
| 3392 | struct wcn36xx_hal_enter_imps_rsp_msg { | ||
| 3393 | struct wcn36xx_hal_msg_header header; | ||
| 3394 | |||
| 3395 | /* success or failure */ | ||
| 3396 | u32 status; | ||
| 3397 | }; | ||
| 3398 | |||
| 3399 | struct wcn36xx_hal_exit_imps_rsp_msg { | ||
| 3400 | struct wcn36xx_hal_msg_header header; | ||
| 3401 | |||
| 3402 | /* success or failure */ | ||
| 3403 | u32 status; | ||
| 3404 | }; | ||
| 3405 | |||
| 3406 | struct wcn36xx_hal_enter_bmps_rsp_msg { | ||
| 3407 | struct wcn36xx_hal_msg_header header; | ||
| 3408 | |||
| 3409 | /* success or failure */ | ||
| 3410 | u32 status; | ||
| 3411 | |||
| 3412 | u8 bss_index; | ||
| 3413 | } __packed; | ||
| 3414 | |||
| 3415 | struct wcn36xx_hal_exit_bmps_rsp_msg { | ||
| 3416 | struct wcn36xx_hal_msg_header header; | ||
| 3417 | |||
| 3418 | /* success or failure */ | ||
| 3419 | u32 status; | ||
| 3420 | |||
| 3421 | u8 bss_index; | ||
| 3422 | } __packed; | ||
| 3423 | |||
| 3424 | struct wcn36xx_hal_enter_uapsd_rsp_msg { | ||
| 3425 | struct wcn36xx_hal_msg_header header; | ||
| 3426 | |||
| 3427 | /* success or failure */ | ||
| 3428 | u32 status; | ||
| 3429 | |||
| 3430 | u8 bss_index; | ||
| 3431 | }; | ||
| 3432 | |||
| 3433 | struct wcn36xx_hal_exit_uapsd_rsp_msg { | ||
| 3434 | struct wcn36xx_hal_msg_header header; | ||
| 3435 | |||
| 3436 | /* success or failure */ | ||
| 3437 | u32 status; | ||
| 3438 | |||
| 3439 | u8 bss_index; | ||
| 3440 | }; | ||
| 3441 | |||
| 3442 | struct wcn36xx_hal_rssi_notification_ind_msg { | ||
| 3443 | struct wcn36xx_hal_msg_header header; | ||
| 3444 | |||
| 3445 | u32 rssi_thres1_pos_cross:1; | ||
| 3446 | u32 rssi_thres1_neg_cross:1; | ||
| 3447 | u32 rssi_thres2_pos_cross:1; | ||
| 3448 | u32 rssi_thres2_neg_cross:1; | ||
| 3449 | u32 rssi_thres3_pos_cross:1; | ||
| 3450 | u32 rssi_thres3_neg_cross:1; | ||
| 3451 | u32 avg_rssi:8; | ||
| 3452 | u32 reserved:18; | ||
| 3453 | |||
| 3454 | }; | ||
| 3455 | |||
| 3456 | struct wcn36xx_hal_get_rssio_rsp_msg { | ||
| 3457 | struct wcn36xx_hal_msg_header header; | ||
| 3458 | |||
| 3459 | /* success or failure */ | ||
| 3460 | u32 status; | ||
| 3461 | s8 rssi; | ||
| 3462 | |||
| 3463 | }; | ||
| 3464 | |||
| 3465 | struct wcn36xx_hal_get_roam_rssi_rsp_msg { | ||
| 3466 | struct wcn36xx_hal_msg_header header; | ||
| 3467 | |||
| 3468 | /* success or failure */ | ||
| 3469 | u32 status; | ||
| 3470 | |||
| 3471 | u8 sta_id; | ||
| 3472 | s8 rssi; | ||
| 3473 | }; | ||
| 3474 | |||
| 3475 | struct wcn36xx_hal_wowl_enter_rsp_msg { | ||
| 3476 | struct wcn36xx_hal_msg_header header; | ||
| 3477 | |||
| 3478 | /* success or failure */ | ||
| 3479 | u32 status; | ||
| 3480 | u8 bss_index; | ||
| 3481 | }; | ||
| 3482 | |||
| 3483 | struct wcn36xx_hal_wowl_exit_rsp_msg { | ||
| 3484 | struct wcn36xx_hal_msg_header header; | ||
| 3485 | |||
| 3486 | /* success or failure */ | ||
| 3487 | u32 status; | ||
| 3488 | u8 bss_index; | ||
| 3489 | }; | ||
| 3490 | |||
| 3491 | struct wcn36xx_hal_add_bcn_filter_rsp_msg { | ||
| 3492 | struct wcn36xx_hal_msg_header header; | ||
| 3493 | |||
| 3494 | /* success or failure */ | ||
| 3495 | u32 status; | ||
| 3496 | }; | ||
| 3497 | |||
| 3498 | struct wcn36xx_hal_rem_bcn_filter_rsp_msg { | ||
| 3499 | struct wcn36xx_hal_msg_header header; | ||
| 3500 | |||
| 3501 | /* success or failure */ | ||
| 3502 | u32 status; | ||
| 3503 | }; | ||
| 3504 | |||
| 3505 | struct wcn36xx_hal_add_wowl_bcast_ptrn_rsp_msg { | ||
| 3506 | struct wcn36xx_hal_msg_header header; | ||
| 3507 | |||
| 3508 | /* success or failure */ | ||
| 3509 | u32 status; | ||
| 3510 | u8 bss_index; | ||
| 3511 | }; | ||
| 3512 | |||
| 3513 | struct wcn36xx_hal_del_wowl_bcast_ptrn_rsp_msg { | ||
| 3514 | struct wcn36xx_hal_msg_header header; | ||
| 3515 | |||
| 3516 | /* success or failure */ | ||
| 3517 | u32 status; | ||
| 3518 | u8 bss_index; | ||
| 3519 | }; | ||
| 3520 | |||
| 3521 | struct wcn36xx_hal_host_offload_rsp_msg { | ||
| 3522 | struct wcn36xx_hal_msg_header header; | ||
| 3523 | |||
| 3524 | /* success or failure */ | ||
| 3525 | u32 status; | ||
| 3526 | }; | ||
| 3527 | |||
| 3528 | struct wcn36xx_hal_keep_alive_rsp_msg { | ||
| 3529 | struct wcn36xx_hal_msg_header header; | ||
| 3530 | |||
| 3531 | /* success or failure */ | ||
| 3532 | u32 status; | ||
| 3533 | }; | ||
| 3534 | |||
| 3535 | struct wcn36xx_hal_set_rssi_thresh_rsp_msg { | ||
| 3536 | struct wcn36xx_hal_msg_header header; | ||
| 3537 | |||
| 3538 | /* success or failure */ | ||
| 3539 | u32 status; | ||
| 3540 | }; | ||
| 3541 | |||
| 3542 | struct wcn36xx_hal_set_uapsd_ac_params_rsp_msg { | ||
| 3543 | struct wcn36xx_hal_msg_header header; | ||
| 3544 | |||
| 3545 | /* success or failure */ | ||
| 3546 | u32 status; | ||
| 3547 | }; | ||
| 3548 | |||
| 3549 | struct wcn36xx_hal_configure_rxp_filter_rsp_msg { | ||
| 3550 | struct wcn36xx_hal_msg_header header; | ||
| 3551 | |||
| 3552 | /* success or failure */ | ||
| 3553 | u32 status; | ||
| 3554 | }; | ||
| 3555 | |||
| 3556 | struct set_max_tx_pwr_req { | ||
| 3557 | struct wcn36xx_hal_msg_header header; | ||
| 3558 | |||
| 3559 | /* BSSID is needed to identify which session issued this request. | ||
| 3560 | * As the request has power constraints, this should be applied | ||
| 3561 | * only to that session */ | ||
| 3562 | u8 bssid[ETH_ALEN]; | ||
| 3563 | |||
| 3564 | u8 self_addr[ETH_ALEN]; | ||
| 3565 | |||
| 3566 | /* In request, power == MaxTx power to be used. */ | ||
| 3567 | u8 power; | ||
| 3568 | }; | ||
| 3569 | |||
| 3570 | struct set_max_tx_pwr_rsp_msg { | ||
| 3571 | struct wcn36xx_hal_msg_header header; | ||
| 3572 | |||
| 3573 | /* power == tx power used for management frames */ | ||
| 3574 | u8 power; | ||
| 3575 | |||
| 3576 | /* success or failure */ | ||
| 3577 | u32 status; | ||
| 3578 | }; | ||
| 3579 | |||
| 3580 | struct set_tx_pwr_req_msg { | ||
| 3581 | struct wcn36xx_hal_msg_header header; | ||
| 3582 | |||
| 3583 | /* TX Power in milli watts */ | ||
| 3584 | u32 tx_power; | ||
| 3585 | |||
| 3586 | u8 bss_index; | ||
| 3587 | }; | ||
| 3588 | |||
| 3589 | struct set_tx_pwr_rsp_msg { | ||
| 3590 | struct wcn36xx_hal_msg_header header; | ||
| 3591 | |||
| 3592 | /* success or failure */ | ||
| 3593 | u32 status; | ||
| 3594 | }; | ||
| 3595 | |||
| 3596 | struct get_tx_pwr_req_msg { | ||
| 3597 | struct wcn36xx_hal_msg_header header; | ||
| 3598 | |||
| 3599 | u8 sta_id; | ||
| 3600 | }; | ||
| 3601 | |||
| 3602 | struct get_tx_pwr_rsp_msg { | ||
| 3603 | struct wcn36xx_hal_msg_header header; | ||
| 3604 | |||
| 3605 | /* success or failure */ | ||
| 3606 | u32 status; | ||
| 3607 | |||
| 3608 | /* TX Power in milli watts */ | ||
| 3609 | u32 tx_power; | ||
| 3610 | }; | ||
| 3611 | |||
| 3612 | struct set_p2p_gonoa_req_msg { | ||
| 3613 | struct wcn36xx_hal_msg_header header; | ||
| 3614 | |||
| 3615 | u8 opp_ps; | ||
| 3616 | u32 ct_window; | ||
| 3617 | u8 count; | ||
| 3618 | u32 duration; | ||
| 3619 | u32 interval; | ||
| 3620 | u32 single_noa_duration; | ||
| 3621 | u8 ps_selection; | ||
| 3622 | }; | ||
| 3623 | |||
| 3624 | struct set_p2p_gonoa_rsp_msg { | ||
| 3625 | struct wcn36xx_hal_msg_header header; | ||
| 3626 | |||
| 3627 | /* success or failure */ | ||
| 3628 | u32 status; | ||
| 3629 | }; | ||
| 3630 | |||
| 3631 | struct wcn36xx_hal_add_sta_self_req { | ||
| 3632 | struct wcn36xx_hal_msg_header header; | ||
| 3633 | |||
| 3634 | u8 self_addr[ETH_ALEN]; | ||
| 3635 | u32 status; | ||
| 3636 | } __packed; | ||
| 3637 | |||
| 3638 | struct wcn36xx_hal_add_sta_self_rsp_msg { | ||
| 3639 | struct wcn36xx_hal_msg_header header; | ||
| 3640 | |||
| 3641 | /* success or failure */ | ||
| 3642 | u32 status; | ||
| 3643 | |||
| 3644 | /* Self STA Index */ | ||
| 3645 | u8 self_sta_index; | ||
| 3646 | |||
| 3647 | /* DPU Index (IGTK, PTK, GTK all same) */ | ||
| 3648 | u8 dpu_index; | ||
| 3649 | |||
| 3650 | /* DPU Signature */ | ||
| 3651 | u8 dpu_signature; | ||
| 3652 | } __packed; | ||
| 3653 | |||
| 3654 | struct wcn36xx_hal_del_sta_self_req_msg { | ||
| 3655 | struct wcn36xx_hal_msg_header header; | ||
| 3656 | |||
| 3657 | u8 self_addr[ETH_ALEN]; | ||
| 3658 | } __packed; | ||
| 3659 | |||
| 3660 | struct wcn36xx_hal_del_sta_self_rsp_msg { | ||
| 3661 | struct wcn36xx_hal_msg_header header; | ||
| 3662 | |||
| 3663 | /*success or failure */ | ||
| 3664 | u32 status; | ||
| 3665 | |||
| 3666 | u8 self_addr[ETH_ALEN]; | ||
| 3667 | } __packed; | ||
| 3668 | |||
| 3669 | struct aggr_add_ts_req { | ||
| 3670 | struct wcn36xx_hal_msg_header header; | ||
| 3671 | |||
| 3672 | /* Station Index */ | ||
| 3673 | u16 sta_idx; | ||
| 3674 | |||
| 3675 | /* TSPEC handler uniquely identifying a TSPEC for a STA in a BSS. | ||
| 3676 | * This will carry the bitmap with the bit positions representing | ||
| 3677 | * different AC.s */ | ||
| 3678 | u16 tspec_index; | ||
| 3679 | |||
| 3680 | /* Tspec info per AC To program TPE with required parameters */ | ||
| 3681 | struct wcn36xx_hal_tspec_ie tspec[WCN36XX_HAL_MAX_AC]; | ||
| 3682 | |||
| 3683 | /* U-APSD Flags: 1b per AC. Encoded as follows: | ||
| 3684 | b7 b6 b5 b4 b3 b2 b1 b0 = | ||
| 3685 | X X X X BE BK VI VO */ | ||
| 3686 | u8 uapsd; | ||
| 3687 | |||
| 3688 | /* These parameters are for all the access categories */ | ||
| 3689 | |||
| 3690 | /* Service Interval */ | ||
| 3691 | u32 service_interval[WCN36XX_HAL_MAX_AC]; | ||
| 3692 | |||
| 3693 | /* Suspend Interval */ | ||
| 3694 | u32 suspend_interval[WCN36XX_HAL_MAX_AC]; | ||
| 3695 | |||
| 3696 | /* Delay Interval */ | ||
| 3697 | u32 delay_interval[WCN36XX_HAL_MAX_AC]; | ||
| 3698 | }; | ||
| 3699 | |||
| 3700 | struct aggr_add_ts_rsp_msg { | ||
| 3701 | struct wcn36xx_hal_msg_header header; | ||
| 3702 | |||
| 3703 | /* success or failure */ | ||
| 3704 | u32 status0; | ||
| 3705 | |||
| 3706 | /* FIXME PRIMA for future use for 11R */ | ||
| 3707 | u32 status1; | ||
| 3708 | }; | ||
| 3709 | |||
| 3710 | struct wcn36xx_hal_configure_apps_cpu_wakeup_state_req_msg { | ||
| 3711 | struct wcn36xx_hal_msg_header header; | ||
| 3712 | |||
| 3713 | u8 is_apps_cpu_awake; | ||
| 3714 | }; | ||
| 3715 | |||
| 3716 | struct wcn36xx_hal_configure_apps_cpu_wakeup_state_rsp_msg { | ||
| 3717 | struct wcn36xx_hal_msg_header header; | ||
| 3718 | |||
| 3719 | /* success or failure */ | ||
| 3720 | u32 status; | ||
| 3721 | }; | ||
| 3722 | |||
| 3723 | struct wcn36xx_hal_dump_cmd_req_msg { | ||
| 3724 | struct wcn36xx_hal_msg_header header; | ||
| 3725 | |||
| 3726 | u32 arg1; | ||
| 3727 | u32 arg2; | ||
| 3728 | u32 arg3; | ||
| 3729 | u32 arg4; | ||
| 3730 | u32 arg5; | ||
| 3731 | } __packed; | ||
| 3732 | |||
| 3733 | struct wcn36xx_hal_dump_cmd_rsp_msg { | ||
| 3734 | struct wcn36xx_hal_msg_header header; | ||
| 3735 | |||
| 3736 | /* success or failure */ | ||
| 3737 | u32 status; | ||
| 3738 | |||
| 3739 | /* Length of the responce message */ | ||
| 3740 | u32 rsp_length; | ||
| 3741 | |||
| 3742 | /* FIXME: Currently considering the the responce will be less than | ||
| 3743 | * 100bytes */ | ||
| 3744 | u8 rsp_buffer[DUMPCMD_RSP_BUFFER]; | ||
| 3745 | } __packed; | ||
| 3746 | |||
| 3747 | #define WLAN_COEX_IND_DATA_SIZE (4) | ||
| 3748 | #define WLAN_COEX_IND_TYPE_DISABLE_HB_MONITOR (0) | ||
| 3749 | #define WLAN_COEX_IND_TYPE_ENABLE_HB_MONITOR (1) | ||
| 3750 | |||
| 3751 | struct coex_ind_msg { | ||
| 3752 | struct wcn36xx_hal_msg_header header; | ||
| 3753 | |||
| 3754 | /* Coex Indication Type */ | ||
| 3755 | u32 type; | ||
| 3756 | |||
| 3757 | /* Coex Indication Data */ | ||
| 3758 | u32 data[WLAN_COEX_IND_DATA_SIZE]; | ||
| 3759 | }; | ||
| 3760 | |||
| 3761 | struct wcn36xx_hal_tx_compl_ind_msg { | ||
| 3762 | struct wcn36xx_hal_msg_header header; | ||
| 3763 | |||
| 3764 | /* Tx Complete Indication Success or Failure */ | ||
| 3765 | u32 status; | ||
| 3766 | }; | ||
| 3767 | |||
| 3768 | struct wcn36xx_hal_wlan_host_suspend_ind_msg { | ||
| 3769 | struct wcn36xx_hal_msg_header header; | ||
| 3770 | |||
| 3771 | u32 configured_mcst_bcst_filter_setting; | ||
| 3772 | u32 active_session_count; | ||
| 3773 | }; | ||
| 3774 | |||
| 3775 | struct wcn36xx_hal_wlan_exclude_unencrpted_ind_msg { | ||
| 3776 | struct wcn36xx_hal_msg_header header; | ||
| 3777 | |||
| 3778 | u8 dot11_exclude_unencrypted; | ||
| 3779 | u8 bssid[ETH_ALEN]; | ||
| 3780 | }; | ||
| 3781 | |||
| 3782 | struct noa_attr_ind_msg { | ||
| 3783 | struct wcn36xx_hal_msg_header header; | ||
| 3784 | |||
| 3785 | u8 index; | ||
| 3786 | u8 opp_ps_flag; | ||
| 3787 | u16 ctwin; | ||
| 3788 | |||
| 3789 | u16 noa1_interval_count; | ||
| 3790 | u16 bss_index; | ||
| 3791 | u32 noa1_duration; | ||
| 3792 | u32 noa1_interval; | ||
| 3793 | u32 noa1_starttime; | ||
| 3794 | |||
| 3795 | u16 noa2_interval_count; | ||
| 3796 | u16 reserved2; | ||
| 3797 | u32 noa2_duration; | ||
| 3798 | u32 noa2_interval; | ||
| 3799 | u32 noa2_start_time; | ||
| 3800 | |||
| 3801 | u32 status; | ||
| 3802 | }; | ||
| 3803 | |||
| 3804 | struct noa_start_ind_msg { | ||
| 3805 | struct wcn36xx_hal_msg_header header; | ||
| 3806 | |||
| 3807 | u32 status; | ||
| 3808 | u32 bss_index; | ||
| 3809 | }; | ||
| 3810 | |||
| 3811 | struct wcn36xx_hal_wlan_host_resume_req_msg { | ||
| 3812 | struct wcn36xx_hal_msg_header header; | ||
| 3813 | |||
| 3814 | u8 configured_mcst_bcst_filter_setting; | ||
| 3815 | }; | ||
| 3816 | |||
| 3817 | struct wcn36xx_hal_host_resume_rsp_msg { | ||
| 3818 | struct wcn36xx_hal_msg_header header; | ||
| 3819 | |||
| 3820 | /* success or failure */ | ||
| 3821 | u32 status; | ||
| 3822 | }; | ||
| 3823 | |||
| 3824 | struct wcn36xx_hal_del_ba_ind_msg { | ||
| 3825 | struct wcn36xx_hal_msg_header header; | ||
| 3826 | |||
| 3827 | u16 sta_idx; | ||
| 3828 | |||
| 3829 | /* Peer MAC Address, whose BA session has timed out */ | ||
| 3830 | u8 peer_addr[ETH_ALEN]; | ||
| 3831 | |||
| 3832 | /* TID for which a BA session timeout is being triggered */ | ||
| 3833 | u8 ba_tid; | ||
| 3834 | |||
| 3835 | /* DELBA direction | ||
| 3836 | * 1 - Originator | ||
| 3837 | * 0 - Recipient | ||
| 3838 | */ | ||
| 3839 | u8 direction; | ||
| 3840 | |||
| 3841 | u32 reason_code; | ||
| 3842 | |||
| 3843 | /* TO SUPPORT BT-AMP */ | ||
| 3844 | u8 bssid[ETH_ALEN]; | ||
| 3845 | }; | ||
| 3846 | |||
| 3847 | /* PNO Messages */ | ||
| 3848 | |||
| 3849 | /* Max number of channels that a network can be found on */ | ||
| 3850 | #define WCN36XX_HAL_PNO_MAX_NETW_CHANNELS 26 | ||
| 3851 | |||
| 3852 | /* Max number of channels that a network can be found on */ | ||
| 3853 | #define WCN36XX_HAL_PNO_MAX_NETW_CHANNELS_EX 60 | ||
| 3854 | |||
| 3855 | /* Maximum numbers of networks supported by PNO */ | ||
| 3856 | #define WCN36XX_HAL_PNO_MAX_SUPP_NETWORKS 16 | ||
| 3857 | |||
| 3858 | /* The number of scan time intervals that can be programmed into PNO */ | ||
| 3859 | #define WCN36XX_HAL_PNO_MAX_SCAN_TIMERS 10 | ||
| 3860 | |||
| 3861 | /* Maximum size of the probe template */ | ||
| 3862 | #define WCN36XX_HAL_PNO_MAX_PROBE_SIZE 450 | ||
| 3863 | |||
| 3864 | /* Type of PNO enabling: | ||
| 3865 | * | ||
| 3866 | * Immediate - scanning will start immediately and PNO procedure will be | ||
| 3867 | * repeated based on timer | ||
| 3868 | * | ||
| 3869 | * Suspend - scanning will start at suspend | ||
| 3870 | * | ||
| 3871 | * Resume - scanning will start on system resume | ||
| 3872 | */ | ||
| 3873 | enum pno_mode { | ||
| 3874 | PNO_MODE_IMMEDIATE, | ||
| 3875 | PNO_MODE_ON_SUSPEND, | ||
| 3876 | PNO_MODE_ON_RESUME, | ||
| 3877 | PNO_MODE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
| 3878 | }; | ||
| 3879 | |||
| 3880 | /* Authentication type */ | ||
| 3881 | enum auth_type { | ||
| 3882 | AUTH_TYPE_ANY = 0, | ||
| 3883 | AUTH_TYPE_OPEN_SYSTEM = 1, | ||
| 3884 | |||
| 3885 | /* Upper layer authentication types */ | ||
| 3886 | AUTH_TYPE_WPA = 2, | ||
| 3887 | AUTH_TYPE_WPA_PSK = 3, | ||
| 3888 | |||
| 3889 | AUTH_TYPE_RSN = 4, | ||
| 3890 | AUTH_TYPE_RSN_PSK = 5, | ||
| 3891 | AUTH_TYPE_FT_RSN = 6, | ||
| 3892 | AUTH_TYPE_FT_RSN_PSK = 7, | ||
| 3893 | AUTH_TYPE_WAPI_WAI_CERTIFICATE = 8, | ||
| 3894 | AUTH_TYPE_WAPI_WAI_PSK = 9, | ||
| 3895 | |||
| 3896 | AUTH_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
| 3897 | }; | ||
| 3898 | |||
| 3899 | /* Encryption type */ | ||
| 3900 | enum ed_type { | ||
| 3901 | ED_ANY = 0, | ||
| 3902 | ED_NONE = 1, | ||
| 3903 | ED_WEP = 2, | ||
| 3904 | ED_TKIP = 3, | ||
| 3905 | ED_CCMP = 4, | ||
| 3906 | ED_WPI = 5, | ||
| 3907 | |||
| 3908 | ED_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
| 3909 | }; | ||
| 3910 | |||
| 3911 | /* SSID broadcast type */ | ||
| 3912 | enum ssid_bcast_type { | ||
| 3913 | BCAST_UNKNOWN = 0, | ||
| 3914 | BCAST_NORMAL = 1, | ||
| 3915 | BCAST_HIDDEN = 2, | ||
| 3916 | |||
| 3917 | BCAST_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
| 3918 | }; | ||
| 3919 | |||
| 3920 | /* The network description for which PNO will have to look for */ | ||
| 3921 | struct network_type { | ||
| 3922 | /* SSID of the BSS */ | ||
| 3923 | struct wcn36xx_hal_mac_ssid ssid; | ||
| 3924 | |||
| 3925 | /* Authentication type for the network */ | ||
| 3926 | enum auth_type authentication; | ||
| 3927 | |||
| 3928 | /* Encryption type for the network */ | ||
| 3929 | enum ed_type encryption; | ||
| 3930 | |||
| 3931 | /* Indicate the channel on which the Network can be found 0 - if | ||
| 3932 | * all channels */ | ||
| 3933 | u8 channel_count; | ||
| 3934 | u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS]; | ||
| 3935 | |||
| 3936 | /* Indicates the RSSI threshold for the network to be considered */ | ||
| 3937 | u8 rssi_threshold; | ||
| 3938 | }; | ||
| 3939 | |||
| 3940 | struct scan_timer { | ||
| 3941 | /* How much it should wait */ | ||
| 3942 | u32 value; | ||
| 3943 | |||
| 3944 | /* How many times it should repeat that wait value 0 - keep using | ||
| 3945 | * this timer until PNO is disabled */ | ||
| 3946 | u32 repeat; | ||
| 3947 | |||
| 3948 | /* e.g: 2 3 4 0 - it will wait 2s between consecutive scans for 3 | ||
| 3949 | * times - after that it will wait 4s between consecutive scans | ||
| 3950 | * until disabled */ | ||
| 3951 | }; | ||
| 3952 | |||
| 3953 | /* The network parameters to be sent to the PNO algorithm */ | ||
| 3954 | struct scan_timers_type { | ||
| 3955 | /* set to 0 if you wish for PNO to use its default telescopic timer */ | ||
| 3956 | u8 count; | ||
| 3957 | |||
| 3958 | /* A set value represents the amount of time that PNO will wait | ||
| 3959 | * between two consecutive scan procedures If the desired is for a | ||
| 3960 | * uniform timer that fires always at the exact same interval - one | ||
| 3961 | * single value is to be set If there is a desire for a more | ||
| 3962 | * complex - telescopic like timer multiple values can be set - | ||
| 3963 | * once PNO reaches the end of the array it will continue scanning | ||
| 3964 | * at intervals presented by the last value */ | ||
| 3965 | struct scan_timer values[WCN36XX_HAL_PNO_MAX_SCAN_TIMERS]; | ||
| 3966 | }; | ||
| 3967 | |||
| 3968 | /* Preferred network list request */ | ||
| 3969 | struct set_pref_netw_list_req { | ||
| 3970 | struct wcn36xx_hal_msg_header header; | ||
| 3971 | |||
| 3972 | /* Enable PNO */ | ||
| 3973 | u32 enable; | ||
| 3974 | |||
| 3975 | /* Immediate, On Suspend, On Resume */ | ||
| 3976 | enum pno_mode mode; | ||
| 3977 | |||
| 3978 | /* Number of networks sent for PNO */ | ||
| 3979 | u32 networks_count; | ||
| 3980 | |||
| 3981 | /* The networks that PNO needs to look for */ | ||
| 3982 | struct network_type networks[WCN36XX_HAL_PNO_MAX_SUPP_NETWORKS]; | ||
| 3983 | |||
| 3984 | /* The scan timers required for PNO */ | ||
| 3985 | struct scan_timers_type scan_timers; | ||
| 3986 | |||
| 3987 | /* Probe template for 2.4GHz band */ | ||
| 3988 | u16 band_24g_probe_size; | ||
| 3989 | u8 band_24g_probe_template[WCN36XX_HAL_PNO_MAX_PROBE_SIZE]; | ||
| 3990 | |||
| 3991 | /* Probe template for 5GHz band */ | ||
| 3992 | u16 band_5g_probe_size; | ||
| 3993 | u8 band_5g_probe_template[WCN36XX_HAL_PNO_MAX_PROBE_SIZE]; | ||
| 3994 | }; | ||
| 3995 | |||
| 3996 | /* The network description for which PNO will have to look for */ | ||
| 3997 | struct network_type_new { | ||
| 3998 | /* SSID of the BSS */ | ||
| 3999 | struct wcn36xx_hal_mac_ssid ssid; | ||
| 4000 | |||
| 4001 | /* Authentication type for the network */ | ||
| 4002 | enum auth_type authentication; | ||
| 4003 | |||
| 4004 | /* Encryption type for the network */ | ||
| 4005 | enum ed_type encryption; | ||
| 4006 | |||
| 4007 | /* SSID broadcast type, normal, hidden or unknown */ | ||
| 4008 | enum ssid_bcast_type bcast_network_type; | ||
| 4009 | |||
| 4010 | /* Indicate the channel on which the Network can be found 0 - if | ||
| 4011 | * all channels */ | ||
| 4012 | u8 channel_count; | ||
| 4013 | u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS]; | ||
| 4014 | |||
| 4015 | /* Indicates the RSSI threshold for the network to be considered */ | ||
| 4016 | u8 rssi_threshold; | ||
| 4017 | }; | ||
| 4018 | |||
| 4019 | /* Preferred network list request new */ | ||
| 4020 | struct set_pref_netw_list_req_new { | ||
| 4021 | struct wcn36xx_hal_msg_header header; | ||
| 4022 | |||
| 4023 | /* Enable PNO */ | ||
| 4024 | u32 enable; | ||
| 4025 | |||
| 4026 | /* Immediate, On Suspend, On Resume */ | ||
| 4027 | enum pno_mode mode; | ||
| 4028 | |||
| 4029 | /* Number of networks sent for PNO */ | ||
| 4030 | u32 networks_count; | ||
| 4031 | |||
| 4032 | /* The networks that PNO needs to look for */ | ||
| 4033 | struct network_type_new networks[WCN36XX_HAL_PNO_MAX_SUPP_NETWORKS]; | ||
| 4034 | |||
| 4035 | /* The scan timers required for PNO */ | ||
| 4036 | struct scan_timers_type scan_timers; | ||
| 4037 | |||
| 4038 | /* Probe template for 2.4GHz band */ | ||
| 4039 | u16 band_24g_probe_size; | ||
| 4040 | u8 band_24g_probe_template[WCN36XX_HAL_PNO_MAX_PROBE_SIZE]; | ||
| 4041 | |||
| 4042 | /* Probe template for 5GHz band */ | ||
| 4043 | u16 band_5g_probe_size; | ||
| 4044 | u8 band_5g_probe_template[WCN36XX_HAL_PNO_MAX_PROBE_SIZE]; | ||
| 4045 | }; | ||
| 4046 | |||
| 4047 | /* Preferred network list response */ | ||
| 4048 | struct set_pref_netw_list_resp { | ||
| 4049 | struct wcn36xx_hal_msg_header header; | ||
| 4050 | |||
| 4051 | /* status of the request - just to indicate that PNO has | ||
| 4052 | * acknowledged the request and will start scanning */ | ||
| 4053 | u32 status; | ||
| 4054 | }; | ||
| 4055 | |||
| 4056 | /* Preferred network found indication */ | ||
| 4057 | struct pref_netw_found_ind { | ||
| 4058 | |||
| 4059 | struct wcn36xx_hal_msg_header header; | ||
| 4060 | |||
| 4061 | /* Network that was found with the highest RSSI */ | ||
| 4062 | struct wcn36xx_hal_mac_ssid ssid; | ||
| 4063 | |||
| 4064 | /* Indicates the RSSI */ | ||
| 4065 | u8 rssi; | ||
| 4066 | }; | ||
| 4067 | |||
| 4068 | /* RSSI Filter request */ | ||
| 4069 | struct set_rssi_filter_req { | ||
| 4070 | struct wcn36xx_hal_msg_header header; | ||
| 4071 | |||
| 4072 | /* RSSI Threshold */ | ||
| 4073 | u8 rssi_threshold; | ||
| 4074 | }; | ||
| 4075 | |||
| 4076 | /* Set RSSI filter resp */ | ||
| 4077 | struct set_rssi_filter_resp { | ||
| 4078 | struct wcn36xx_hal_msg_header header; | ||
| 4079 | |||
| 4080 | /* status of the request */ | ||
| 4081 | u32 status; | ||
| 4082 | }; | ||
| 4083 | |||
| 4084 | /* Update scan params - sent from host to PNO to be used during PNO | ||
| 4085 | * scanningx */ | ||
| 4086 | struct wcn36xx_hal_update_scan_params_req { | ||
| 4087 | |||
| 4088 | struct wcn36xx_hal_msg_header header; | ||
| 4089 | |||
| 4090 | /* Host setting for 11d */ | ||
| 4091 | u8 dot11d_enabled; | ||
| 4092 | |||
| 4093 | /* Lets PNO know that host has determined the regulatory domain */ | ||
| 4094 | u8 dot11d_resolved; | ||
| 4095 | |||
| 4096 | /* Channels on which PNO is allowed to scan */ | ||
| 4097 | u8 channel_count; | ||
| 4098 | u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS]; | ||
| 4099 | |||
| 4100 | /* Minimum channel time */ | ||
| 4101 | u16 active_min_ch_time; | ||
| 4102 | |||
| 4103 | /* Maximum channel time */ | ||
| 4104 | u16 active_max_ch_time; | ||
| 4105 | |||
| 4106 | /* Minimum channel time */ | ||
| 4107 | u16 passive_min_ch_time; | ||
| 4108 | |||
| 4109 | /* Maximum channel time */ | ||
| 4110 | u16 passive_max_ch_time; | ||
| 4111 | |||
| 4112 | /* Cb State */ | ||
| 4113 | enum phy_chan_bond_state state; | ||
| 4114 | } __packed; | ||
| 4115 | |||
| 4116 | /* Update scan params - sent from host to PNO to be used during PNO | ||
| 4117 | * scanningx */ | ||
| 4118 | struct update_scan_params_req_ex { | ||
| 4119 | |||
| 4120 | struct wcn36xx_hal_msg_header header; | ||
| 4121 | |||
| 4122 | /* Host setting for 11d */ | ||
| 4123 | u8 dot11d_enabled; | ||
| 4124 | |||
| 4125 | /* Lets PNO know that host has determined the regulatory domain */ | ||
| 4126 | u8 dot11d_resolved; | ||
| 4127 | |||
| 4128 | /* Channels on which PNO is allowed to scan */ | ||
| 4129 | u8 channel_count; | ||
| 4130 | u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS_EX]; | ||
| 4131 | |||
| 4132 | /* Minimum channel time */ | ||
| 4133 | u16 active_min_ch_time; | ||
| 4134 | |||
| 4135 | /* Maximum channel time */ | ||
| 4136 | u16 active_max_ch_time; | ||
| 4137 | |||
| 4138 | /* Minimum channel time */ | ||
| 4139 | u16 passive_min_ch_time; | ||
| 4140 | |||
| 4141 | /* Maximum channel time */ | ||
| 4142 | u16 passive_max_ch_time; | ||
| 4143 | |||
| 4144 | /* Cb State */ | ||
| 4145 | enum phy_chan_bond_state state; | ||
| 4146 | }; | ||
| 4147 | |||
| 4148 | /* Update scan params - sent from host to PNO to be used during PNO | ||
| 4149 | * scanningx */ | ||
| 4150 | struct wcn36xx_hal_update_scan_params_resp { | ||
| 4151 | |||
| 4152 | struct wcn36xx_hal_msg_header header; | ||
| 4153 | |||
| 4154 | /* status of the request */ | ||
| 4155 | u32 status; | ||
| 4156 | } __packed; | ||
| 4157 | |||
| 4158 | struct wcn36xx_hal_set_tx_per_tracking_req_msg { | ||
| 4159 | struct wcn36xx_hal_msg_header header; | ||
| 4160 | |||
| 4161 | /* 0: disable, 1:enable */ | ||
| 4162 | u8 tx_per_tracking_enable; | ||
| 4163 | |||
| 4164 | /* Check period, unit is sec. */ | ||
| 4165 | u8 tx_per_tracking_period; | ||
| 4166 | |||
| 4167 | /* (Fail TX packet)/(Total TX packet) ratio, the unit is 10%. */ | ||
| 4168 | u8 tx_per_tracking_ratio; | ||
| 4169 | |||
| 4170 | /* A watermark of check number, once the tx packet exceed this | ||
| 4171 | * number, we do the check, default is 5 */ | ||
| 4172 | u32 tx_per_tracking_watermark; | ||
| 4173 | }; | ||
| 4174 | |||
| 4175 | struct wcn36xx_hal_set_tx_per_tracking_rsp_msg { | ||
| 4176 | struct wcn36xx_hal_msg_header header; | ||
| 4177 | |||
| 4178 | /* success or failure */ | ||
| 4179 | u32 status; | ||
| 4180 | |||
| 4181 | }; | ||
| 4182 | |||
| 4183 | struct tx_per_hit_ind_msg { | ||
| 4184 | struct wcn36xx_hal_msg_header header; | ||
| 4185 | }; | ||
| 4186 | |||
| 4187 | /* Packet Filtering Definitions Begin */ | ||
| 4188 | #define WCN36XX_HAL_PROTOCOL_DATA_LEN 8 | ||
| 4189 | #define WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS 240 | ||
| 4190 | #define WCN36XX_HAL_MAX_NUM_FILTERS 20 | ||
| 4191 | #define WCN36XX_HAL_MAX_CMP_PER_FILTER 10 | ||
| 4192 | |||
| 4193 | enum wcn36xx_hal_receive_packet_filter_type { | ||
| 4194 | HAL_RCV_FILTER_TYPE_INVALID, | ||
| 4195 | HAL_RCV_FILTER_TYPE_FILTER_PKT, | ||
| 4196 | HAL_RCV_FILTER_TYPE_BUFFER_PKT, | ||
| 4197 | HAL_RCV_FILTER_TYPE_MAX_ENUM_SIZE | ||
| 4198 | }; | ||
| 4199 | |||
| 4200 | enum wcn36xx_hal_rcv_pkt_flt_protocol_type { | ||
| 4201 | HAL_FILTER_PROTO_TYPE_INVALID, | ||
| 4202 | HAL_FILTER_PROTO_TYPE_MAC, | ||
| 4203 | HAL_FILTER_PROTO_TYPE_ARP, | ||
| 4204 | HAL_FILTER_PROTO_TYPE_IPV4, | ||
| 4205 | HAL_FILTER_PROTO_TYPE_IPV6, | ||
| 4206 | HAL_FILTER_PROTO_TYPE_UDP, | ||
| 4207 | HAL_FILTER_PROTO_TYPE_MAX | ||
| 4208 | }; | ||
| 4209 | |||
| 4210 | enum wcn36xx_hal_rcv_pkt_flt_cmp_flag_type { | ||
| 4211 | HAL_FILTER_CMP_TYPE_INVALID, | ||
| 4212 | HAL_FILTER_CMP_TYPE_EQUAL, | ||
| 4213 | HAL_FILTER_CMP_TYPE_MASK_EQUAL, | ||
| 4214 | HAL_FILTER_CMP_TYPE_NOT_EQUAL, | ||
| 4215 | HAL_FILTER_CMP_TYPE_MAX | ||
| 4216 | }; | ||
| 4217 | |||
| 4218 | struct wcn36xx_hal_rcv_pkt_filter_params { | ||
| 4219 | u8 protocol_layer; | ||
| 4220 | u8 cmp_flag; | ||
| 4221 | |||
| 4222 | /* Length of the data to compare */ | ||
| 4223 | u16 data_length; | ||
| 4224 | |||
| 4225 | /* from start of the respective frame header */ | ||
| 4226 | u8 data_offset; | ||
| 4227 | |||
| 4228 | /* Reserved field */ | ||
| 4229 | u8 reserved; | ||
| 4230 | |||
| 4231 | /* Data to compare */ | ||
| 4232 | u8 compare_data[WCN36XX_HAL_PROTOCOL_DATA_LEN]; | ||
| 4233 | |||
| 4234 | /* Mask to be applied on the received packet data before compare */ | ||
| 4235 | u8 data_mask[WCN36XX_HAL_PROTOCOL_DATA_LEN]; | ||
| 4236 | }; | ||
| 4237 | |||
| 4238 | struct wcn36xx_hal_sessionized_rcv_pkt_filter_cfg_type { | ||
| 4239 | u8 id; | ||
| 4240 | u8 type; | ||
| 4241 | u8 params_count; | ||
| 4242 | u32 coleasce_time; | ||
| 4243 | u8 bss_index; | ||
| 4244 | struct wcn36xx_hal_rcv_pkt_filter_params params[1]; | ||
| 4245 | }; | ||
| 4246 | |||
| 4247 | struct wcn36xx_hal_set_rcv_pkt_filter_req_msg { | ||
| 4248 | struct wcn36xx_hal_msg_header header; | ||
| 4249 | |||
| 4250 | u8 id; | ||
| 4251 | u8 type; | ||
| 4252 | u8 params_count; | ||
| 4253 | u32 coalesce_time; | ||
| 4254 | struct wcn36xx_hal_rcv_pkt_filter_params params[1]; | ||
| 4255 | }; | ||
| 4256 | |||
| 4257 | struct wcn36xx_hal_rcv_flt_mc_addr_list_type { | ||
| 4258 | /* from start of the respective frame header */ | ||
| 4259 | u8 data_offset; | ||
| 4260 | |||
| 4261 | u32 mc_addr_count; | ||
| 4262 | u8 mc_addr[ETH_ALEN][WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS]; | ||
| 4263 | u8 bss_index; | ||
| 4264 | }; | ||
| 4265 | |||
| 4266 | struct wcn36xx_hal_set_pkt_filter_rsp_msg { | ||
| 4267 | struct wcn36xx_hal_msg_header header; | ||
| 4268 | |||
| 4269 | /* success or failure */ | ||
| 4270 | u32 status; | ||
| 4271 | |||
| 4272 | u8 bss_index; | ||
| 4273 | }; | ||
| 4274 | |||
| 4275 | struct wcn36xx_hal_rcv_flt_pkt_match_cnt_req_msg { | ||
| 4276 | struct wcn36xx_hal_msg_header header; | ||
| 4277 | |||
| 4278 | u8 bss_index; | ||
| 4279 | }; | ||
| 4280 | |||
| 4281 | struct wcn36xx_hal_rcv_flt_pkt_match_cnt { | ||
| 4282 | u8 id; | ||
| 4283 | u32 match_cnt; | ||
| 4284 | }; | ||
| 4285 | |||
| 4286 | struct wcn36xx_hal_rcv_flt_pkt_match_cnt_rsp_msg { | ||
| 4287 | struct wcn36xx_hal_msg_header header; | ||
| 4288 | |||
| 4289 | /* Success or Failure */ | ||
| 4290 | u32 status; | ||
| 4291 | |||
| 4292 | u32 match_count; | ||
| 4293 | struct wcn36xx_hal_rcv_flt_pkt_match_cnt | ||
| 4294 | matches[WCN36XX_HAL_MAX_NUM_FILTERS]; | ||
| 4295 | u8 bss_index; | ||
| 4296 | }; | ||
| 4297 | |||
| 4298 | struct wcn36xx_hal_rcv_flt_pkt_clear_param { | ||
| 4299 | /* only valid for response message */ | ||
| 4300 | u32 status; | ||
| 4301 | u8 id; | ||
| 4302 | u8 bss_index; | ||
| 4303 | }; | ||
| 4304 | |||
| 4305 | struct wcn36xx_hal_rcv_flt_pkt_clear_req_msg { | ||
| 4306 | struct wcn36xx_hal_msg_header header; | ||
| 4307 | struct wcn36xx_hal_rcv_flt_pkt_clear_param param; | ||
| 4308 | }; | ||
| 4309 | |||
| 4310 | struct wcn36xx_hal_rcv_flt_pkt_clear_rsp_msg { | ||
| 4311 | struct wcn36xx_hal_msg_header header; | ||
| 4312 | struct wcn36xx_hal_rcv_flt_pkt_clear_param param; | ||
| 4313 | }; | ||
| 4314 | |||
| 4315 | struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg { | ||
| 4316 | struct wcn36xx_hal_msg_header header; | ||
| 4317 | struct wcn36xx_hal_rcv_flt_mc_addr_list_type mc_addr_list; | ||
| 4318 | }; | ||
| 4319 | |||
| 4320 | struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_rsp_msg { | ||
| 4321 | struct wcn36xx_hal_msg_header header; | ||
| 4322 | u32 status; | ||
| 4323 | u8 bss_index; | ||
| 4324 | }; | ||
| 4325 | |||
| 4326 | /* Packet Filtering Definitions End */ | ||
| 4327 | |||
| 4328 | struct wcn36xx_hal_set_power_params_req_msg { | ||
| 4329 | struct wcn36xx_hal_msg_header header; | ||
| 4330 | |||
| 4331 | /* Ignore DTIM */ | ||
| 4332 | u32 ignore_dtim; | ||
| 4333 | |||
| 4334 | /* DTIM Period */ | ||
| 4335 | u32 dtim_period; | ||
| 4336 | |||
| 4337 | /* Listen Interval */ | ||
| 4338 | u32 listen_interval; | ||
| 4339 | |||
| 4340 | /* Broadcast Multicast Filter */ | ||
| 4341 | u32 bcast_mcast_filter; | ||
| 4342 | |||
| 4343 | /* Beacon Early Termination */ | ||
| 4344 | u32 enable_bet; | ||
| 4345 | |||
| 4346 | /* Beacon Early Termination Interval */ | ||
| 4347 | u32 bet_interval; | ||
| 4348 | } __packed; | ||
| 4349 | |||
| 4350 | struct wcn36xx_hal_set_power_params_resp { | ||
| 4351 | |||
| 4352 | struct wcn36xx_hal_msg_header header; | ||
| 4353 | |||
| 4354 | /* status of the request */ | ||
| 4355 | u32 status; | ||
| 4356 | } __packed; | ||
| 4357 | |||
| 4358 | /* Capability bitmap exchange definitions and macros starts */ | ||
| 4359 | |||
| 4360 | enum place_holder_in_cap_bitmap { | ||
| 4361 | MCC = 0, | ||
| 4362 | P2P = 1, | ||
| 4363 | DOT11AC = 2, | ||
| 4364 | SLM_SESSIONIZATION = 3, | ||
| 4365 | DOT11AC_OPMODE = 4, | ||
| 4366 | SAP32STA = 5, | ||
| 4367 | TDLS = 6, | ||
| 4368 | P2P_GO_NOA_DECOUPLE_INIT_SCAN = 7, | ||
| 4369 | WLANACTIVE_OFFLOAD = 8, | ||
| 4370 | BEACON_OFFLOAD = 9, | ||
| 4371 | SCAN_OFFLOAD = 10, | ||
| 4372 | ROAM_OFFLOAD = 11, | ||
| 4373 | BCN_MISS_OFFLOAD = 12, | ||
| 4374 | STA_POWERSAVE = 13, | ||
| 4375 | STA_ADVANCED_PWRSAVE = 14, | ||
| 4376 | AP_UAPSD = 15, | ||
| 4377 | AP_DFS = 16, | ||
| 4378 | BLOCKACK = 17, | ||
| 4379 | PHY_ERR = 18, | ||
| 4380 | BCN_FILTER = 19, | ||
| 4381 | RTT = 20, | ||
| 4382 | RATECTRL = 21, | ||
| 4383 | WOW = 22, | ||
| 4384 | MAX_FEATURE_SUPPORTED = 128, | ||
| 4385 | }; | ||
| 4386 | |||
| 4387 | struct wcn36xx_hal_feat_caps_msg { | ||
| 4388 | |||
| 4389 | struct wcn36xx_hal_msg_header header; | ||
| 4390 | |||
| 4391 | u32 feat_caps[4]; | ||
| 4392 | } __packed; | ||
| 4393 | |||
| 4394 | /* status codes to help debug rekey failures */ | ||
| 4395 | enum gtk_rekey_status { | ||
| 4396 | WCN36XX_HAL_GTK_REKEY_STATUS_SUCCESS = 0, | ||
| 4397 | |||
| 4398 | /* rekey detected, but not handled */ | ||
| 4399 | WCN36XX_HAL_GTK_REKEY_STATUS_NOT_HANDLED = 1, | ||
| 4400 | |||
| 4401 | /* MIC check error on M1 */ | ||
| 4402 | WCN36XX_HAL_GTK_REKEY_STATUS_MIC_ERROR = 2, | ||
| 4403 | |||
| 4404 | /* decryption error on M1 */ | ||
| 4405 | WCN36XX_HAL_GTK_REKEY_STATUS_DECRYPT_ERROR = 3, | ||
| 4406 | |||
| 4407 | /* M1 replay detected */ | ||
| 4408 | WCN36XX_HAL_GTK_REKEY_STATUS_REPLAY_ERROR = 4, | ||
| 4409 | |||
| 4410 | /* missing GTK key descriptor in M1 */ | ||
| 4411 | WCN36XX_HAL_GTK_REKEY_STATUS_MISSING_KDE = 5, | ||
| 4412 | |||
| 4413 | /* missing iGTK key descriptor in M1 */ | ||
| 4414 | WCN36XX_HAL_GTK_REKEY_STATUS_MISSING_IGTK_KDE = 6, | ||
| 4415 | |||
| 4416 | /* key installation error */ | ||
| 4417 | WCN36XX_HAL_GTK_REKEY_STATUS_INSTALL_ERROR = 7, | ||
| 4418 | |||
| 4419 | /* iGTK key installation error */ | ||
| 4420 | WCN36XX_HAL_GTK_REKEY_STATUS_IGTK_INSTALL_ERROR = 8, | ||
| 4421 | |||
| 4422 | /* GTK rekey M2 response TX error */ | ||
| 4423 | WCN36XX_HAL_GTK_REKEY_STATUS_RESP_TX_ERROR = 9, | ||
| 4424 | |||
| 4425 | /* non-specific general error */ | ||
| 4426 | WCN36XX_HAL_GTK_REKEY_STATUS_GEN_ERROR = 255 | ||
| 4427 | }; | ||
| 4428 | |||
| 4429 | /* wake reason types */ | ||
| 4430 | enum wake_reason_type { | ||
| 4431 | WCN36XX_HAL_WAKE_REASON_NONE = 0, | ||
| 4432 | |||
| 4433 | /* magic packet match */ | ||
| 4434 | WCN36XX_HAL_WAKE_REASON_MAGIC_PACKET = 1, | ||
| 4435 | |||
| 4436 | /* host defined pattern match */ | ||
| 4437 | WCN36XX_HAL_WAKE_REASON_PATTERN_MATCH = 2, | ||
| 4438 | |||
| 4439 | /* EAP-ID frame detected */ | ||
| 4440 | WCN36XX_HAL_WAKE_REASON_EAPID_PACKET = 3, | ||
| 4441 | |||
| 4442 | /* start of EAPOL 4-way handshake detected */ | ||
| 4443 | WCN36XX_HAL_WAKE_REASON_EAPOL4WAY_PACKET = 4, | ||
| 4444 | |||
| 4445 | /* network scan offload match */ | ||
| 4446 | WCN36XX_HAL_WAKE_REASON_NETSCAN_OFFL_MATCH = 5, | ||
| 4447 | |||
| 4448 | /* GTK rekey status wakeup (see status) */ | ||
| 4449 | WCN36XX_HAL_WAKE_REASON_GTK_REKEY_STATUS = 6, | ||
| 4450 | |||
| 4451 | /* BSS connection lost */ | ||
| 4452 | WCN36XX_HAL_WAKE_REASON_BSS_CONN_LOST = 7, | ||
| 4453 | }; | ||
| 4454 | |||
| 4455 | /* | ||
| 4456 | Wake Packet which is saved at tWakeReasonParams.DataStart | ||
| 4457 | This data is sent for any wake reasons that involve a packet-based wakeup : | ||
| 4458 | |||
| 4459 | WCN36XX_HAL_WAKE_REASON_TYPE_MAGIC_PACKET | ||
| 4460 | WCN36XX_HAL_WAKE_REASON_TYPE_PATTERN_MATCH | ||
| 4461 | WCN36XX_HAL_WAKE_REASON_TYPE_EAPID_PACKET | ||
| 4462 | WCN36XX_HAL_WAKE_REASON_TYPE_EAPOL4WAY_PACKET | ||
| 4463 | WCN36XX_HAL_WAKE_REASON_TYPE_GTK_REKEY_STATUS | ||
| 4464 | |||
| 4465 | The information is provided to the host for auditing and debug purposes | ||
| 4466 | |||
| 4467 | */ | ||
| 4468 | |||
| 4469 | /* Wake reason indication */ | ||
| 4470 | struct wcn36xx_hal_wake_reason_ind { | ||
| 4471 | struct wcn36xx_hal_msg_header header; | ||
| 4472 | |||
| 4473 | /* see tWakeReasonType */ | ||
| 4474 | u32 reason; | ||
| 4475 | |||
| 4476 | /* argument specific to the reason type */ | ||
| 4477 | u32 reason_arg; | ||
| 4478 | |||
| 4479 | /* length of optional data stored in this message, in case HAL | ||
| 4480 | * truncates the data (i.e. data packets) this length will be less | ||
| 4481 | * than the actual length */ | ||
| 4482 | u32 stored_data_len; | ||
| 4483 | |||
| 4484 | /* actual length of data */ | ||
| 4485 | u32 actual_data_len; | ||
| 4486 | |||
| 4487 | /* variable length start of data (length == storedDataLen) see | ||
| 4488 | * specific wake type */ | ||
| 4489 | u8 data_start[1]; | ||
| 4490 | |||
| 4491 | u32 bss_index:8; | ||
| 4492 | u32 reserved:24; | ||
| 4493 | }; | ||
| 4494 | |||
| 4495 | #define WCN36XX_HAL_GTK_KEK_BYTES 16 | ||
| 4496 | #define WCN36XX_HAL_GTK_KCK_BYTES 16 | ||
| 4497 | |||
| 4498 | #define WCN36XX_HAL_GTK_OFFLOAD_FLAGS_DISABLE (1 << 0) | ||
| 4499 | |||
| 4500 | #define GTK_SET_BSS_KEY_TAG 0x1234AA55 | ||
| 4501 | |||
| 4502 | struct wcn36xx_hal_gtk_offload_req_msg { | ||
| 4503 | struct wcn36xx_hal_msg_header header; | ||
| 4504 | |||
| 4505 | /* optional flags */ | ||
| 4506 | u32 flags; | ||
| 4507 | |||
| 4508 | /* Key confirmation key */ | ||
| 4509 | u8 kck[WCN36XX_HAL_GTK_KCK_BYTES]; | ||
| 4510 | |||
| 4511 | /* key encryption key */ | ||
| 4512 | u8 kek[WCN36XX_HAL_GTK_KEK_BYTES]; | ||
| 4513 | |||
| 4514 | /* replay counter */ | ||
| 4515 | u64 key_replay_counter; | ||
| 4516 | |||
| 4517 | u8 bss_index; | ||
| 4518 | }; | ||
| 4519 | |||
| 4520 | struct wcn36xx_hal_gtk_offload_rsp_msg { | ||
| 4521 | struct wcn36xx_hal_msg_header header; | ||
| 4522 | |||
| 4523 | /* success or failure */ | ||
| 4524 | u32 status; | ||
| 4525 | |||
| 4526 | u8 bss_index; | ||
| 4527 | }; | ||
| 4528 | |||
| 4529 | struct wcn36xx_hal_gtk_offload_get_info_req_msg { | ||
| 4530 | struct wcn36xx_hal_msg_header header; | ||
| 4531 | u8 bss_index; | ||
| 4532 | }; | ||
| 4533 | |||
| 4534 | struct wcn36xx_hal_gtk_offload_get_info_rsp_msg { | ||
| 4535 | struct wcn36xx_hal_msg_header header; | ||
| 4536 | |||
| 4537 | /* success or failure */ | ||
| 4538 | u32 status; | ||
| 4539 | |||
| 4540 | /* last rekey status when the rekey was offloaded */ | ||
| 4541 | u32 last_rekey_status; | ||
| 4542 | |||
| 4543 | /* current replay counter value */ | ||
| 4544 | u64 key_replay_counter; | ||
| 4545 | |||
| 4546 | /* total rekey attempts */ | ||
| 4547 | u32 total_rekey_count; | ||
| 4548 | |||
| 4549 | /* successful GTK rekeys */ | ||
| 4550 | u32 gtk_rekey_count; | ||
| 4551 | |||
| 4552 | /* successful iGTK rekeys */ | ||
| 4553 | u32 igtk_rekey_count; | ||
| 4554 | |||
| 4555 | u8 bss_index; | ||
| 4556 | }; | ||
| 4557 | |||
| 4558 | struct dhcp_info { | ||
| 4559 | /* Indicates the device mode which indicates about the DHCP activity */ | ||
| 4560 | u8 device_mode; | ||
| 4561 | |||
| 4562 | u8 addr[ETH_ALEN]; | ||
| 4563 | }; | ||
| 4564 | |||
| 4565 | struct dhcp_ind_status { | ||
| 4566 | struct wcn36xx_hal_msg_header header; | ||
| 4567 | |||
| 4568 | /* success or failure */ | ||
| 4569 | u32 status; | ||
| 4570 | }; | ||
| 4571 | |||
| 4572 | /* | ||
| 4573 | * Thermal Mitigation mode of operation. | ||
| 4574 | * | ||
| 4575 | * WCN36XX_HAL_THERMAL_MITIGATION_MODE_0 - Based on AMPDU disabling aggregation | ||
| 4576 | * | ||
| 4577 | * WCN36XX_HAL_THERMAL_MITIGATION_MODE_1 - Based on AMPDU disabling aggregation | ||
| 4578 | * and reducing transmit power | ||
| 4579 | * | ||
| 4580 | * WCN36XX_HAL_THERMAL_MITIGATION_MODE_2 - Not supported */ | ||
| 4581 | enum wcn36xx_hal_thermal_mitigation_mode_type { | ||
| 4582 | HAL_THERMAL_MITIGATION_MODE_INVALID = -1, | ||
| 4583 | HAL_THERMAL_MITIGATION_MODE_0, | ||
| 4584 | HAL_THERMAL_MITIGATION_MODE_1, | ||
| 4585 | HAL_THERMAL_MITIGATION_MODE_2, | ||
| 4586 | HAL_THERMAL_MITIGATION_MODE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE, | ||
| 4587 | }; | ||
| 4588 | |||
| 4589 | |||
| 4590 | /* | ||
| 4591 | * Thermal Mitigation level. | ||
| 4592 | * Note the levels are incremental i.e WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_2 = | ||
| 4593 | * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_0 + | ||
| 4594 | * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_1 | ||
| 4595 | * | ||
| 4596 | * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_0 - lowest level of thermal mitigation. | ||
| 4597 | * This level indicates normal mode of operation | ||
| 4598 | * | ||
| 4599 | * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_1 - 1st level of thermal mitigation | ||
| 4600 | * | ||
| 4601 | * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_2 - 2nd level of thermal mitigation | ||
| 4602 | * | ||
| 4603 | * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_3 - 3rd level of thermal mitigation | ||
| 4604 | * | ||
| 4605 | * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_4 - 4th level of thermal mitigation | ||
| 4606 | */ | ||
| 4607 | enum wcn36xx_hal_thermal_mitigation_level_type { | ||
| 4608 | HAL_THERMAL_MITIGATION_LEVEL_INVALID = -1, | ||
| 4609 | HAL_THERMAL_MITIGATION_LEVEL_0, | ||
| 4610 | HAL_THERMAL_MITIGATION_LEVEL_1, | ||
| 4611 | HAL_THERMAL_MITIGATION_LEVEL_2, | ||
| 4612 | HAL_THERMAL_MITIGATION_LEVEL_3, | ||
| 4613 | HAL_THERMAL_MITIGATION_LEVEL_4, | ||
| 4614 | HAL_THERMAL_MITIGATION_LEVEL_MAX = WCN36XX_HAL_MAX_ENUM_SIZE, | ||
| 4615 | }; | ||
| 4616 | |||
| 4617 | |||
| 4618 | /* WCN36XX_HAL_SET_THERMAL_MITIGATION_REQ */ | ||
| 4619 | struct set_thermal_mitigation_req_msg { | ||
| 4620 | struct wcn36xx_hal_msg_header header; | ||
| 4621 | |||
| 4622 | /* Thermal Mitigation Operation Mode */ | ||
| 4623 | enum wcn36xx_hal_thermal_mitigation_mode_type mode; | ||
| 4624 | |||
| 4625 | /* Thermal Mitigation Level */ | ||
| 4626 | enum wcn36xx_hal_thermal_mitigation_level_type level; | ||
| 4627 | }; | ||
| 4628 | |||
| 4629 | struct set_thermal_mitigation_resp { | ||
| 4630 | |||
| 4631 | struct wcn36xx_hal_msg_header header; | ||
| 4632 | |||
| 4633 | /* status of the request */ | ||
| 4634 | u32 status; | ||
| 4635 | }; | ||
| 4636 | |||
| 4637 | /* Per STA Class B Statistics. Class B statistics are STA TX/RX stats | ||
| 4638 | * provided to FW from Host via periodic messages */ | ||
| 4639 | struct stats_class_b_ind { | ||
| 4640 | struct wcn36xx_hal_msg_header header; | ||
| 4641 | |||
| 4642 | /* Duration over which this stats was collected */ | ||
| 4643 | u32 duration; | ||
| 4644 | |||
| 4645 | /* Per STA Stats */ | ||
| 4646 | |||
| 4647 | /* TX stats */ | ||
| 4648 | u32 tx_bytes_pushed; | ||
| 4649 | u32 tx_packets_pushed; | ||
| 4650 | |||
| 4651 | /* RX stats */ | ||
| 4652 | u32 rx_bytes_rcvd; | ||
| 4653 | u32 rx_packets_rcvd; | ||
| 4654 | u32 rx_time_total; | ||
| 4655 | }; | ||
| 4656 | |||
| 4657 | #endif /* _HAL_H_ */ | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c new file mode 100644 index 000000000000..7839b31e4826 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/main.c | |||
| @@ -0,0 +1,1036 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 18 | |||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/platform_device.h> | ||
| 21 | #include "wcn36xx.h" | ||
| 22 | |||
| 23 | unsigned int wcn36xx_dbg_mask; | ||
| 24 | module_param_named(debug_mask, wcn36xx_dbg_mask, uint, 0644); | ||
| 25 | MODULE_PARM_DESC(debug_mask, "Debugging mask"); | ||
| 26 | |||
| 27 | #define CHAN2G(_freq, _idx) { \ | ||
| 28 | .band = IEEE80211_BAND_2GHZ, \ | ||
| 29 | .center_freq = (_freq), \ | ||
| 30 | .hw_value = (_idx), \ | ||
| 31 | .max_power = 25, \ | ||
| 32 | } | ||
| 33 | |||
| 34 | #define CHAN5G(_freq, _idx) { \ | ||
| 35 | .band = IEEE80211_BAND_5GHZ, \ | ||
| 36 | .center_freq = (_freq), \ | ||
| 37 | .hw_value = (_idx), \ | ||
| 38 | .max_power = 25, \ | ||
| 39 | } | ||
| 40 | |||
| 41 | /* The wcn firmware expects channel values to matching | ||
| 42 | * their mnemonic values. So use these for .hw_value. */ | ||
| 43 | static struct ieee80211_channel wcn_2ghz_channels[] = { | ||
| 44 | CHAN2G(2412, 1), /* Channel 1 */ | ||
| 45 | CHAN2G(2417, 2), /* Channel 2 */ | ||
| 46 | CHAN2G(2422, 3), /* Channel 3 */ | ||
| 47 | CHAN2G(2427, 4), /* Channel 4 */ | ||
| 48 | CHAN2G(2432, 5), /* Channel 5 */ | ||
| 49 | CHAN2G(2437, 6), /* Channel 6 */ | ||
| 50 | CHAN2G(2442, 7), /* Channel 7 */ | ||
| 51 | CHAN2G(2447, 8), /* Channel 8 */ | ||
| 52 | CHAN2G(2452, 9), /* Channel 9 */ | ||
| 53 | CHAN2G(2457, 10), /* Channel 10 */ | ||
| 54 | CHAN2G(2462, 11), /* Channel 11 */ | ||
| 55 | CHAN2G(2467, 12), /* Channel 12 */ | ||
| 56 | CHAN2G(2472, 13), /* Channel 13 */ | ||
| 57 | CHAN2G(2484, 14) /* Channel 14 */ | ||
| 58 | |||
| 59 | }; | ||
| 60 | |||
| 61 | static struct ieee80211_channel wcn_5ghz_channels[] = { | ||
| 62 | CHAN5G(5180, 36), | ||
| 63 | CHAN5G(5200, 40), | ||
| 64 | CHAN5G(5220, 44), | ||
| 65 | CHAN5G(5240, 48), | ||
| 66 | CHAN5G(5260, 52), | ||
| 67 | CHAN5G(5280, 56), | ||
| 68 | CHAN5G(5300, 60), | ||
| 69 | CHAN5G(5320, 64), | ||
| 70 | CHAN5G(5500, 100), | ||
| 71 | CHAN5G(5520, 104), | ||
| 72 | CHAN5G(5540, 108), | ||
| 73 | CHAN5G(5560, 112), | ||
| 74 | CHAN5G(5580, 116), | ||
| 75 | CHAN5G(5600, 120), | ||
| 76 | CHAN5G(5620, 124), | ||
| 77 | CHAN5G(5640, 128), | ||
| 78 | CHAN5G(5660, 132), | ||
| 79 | CHAN5G(5700, 140), | ||
| 80 | CHAN5G(5745, 149), | ||
| 81 | CHAN5G(5765, 153), | ||
| 82 | CHAN5G(5785, 157), | ||
| 83 | CHAN5G(5805, 161), | ||
| 84 | CHAN5G(5825, 165) | ||
| 85 | }; | ||
| 86 | |||
| 87 | #define RATE(_bitrate, _hw_rate, _flags) { \ | ||
| 88 | .bitrate = (_bitrate), \ | ||
| 89 | .flags = (_flags), \ | ||
| 90 | .hw_value = (_hw_rate), \ | ||
| 91 | .hw_value_short = (_hw_rate) \ | ||
| 92 | } | ||
| 93 | |||
| 94 | static struct ieee80211_rate wcn_2ghz_rates[] = { | ||
| 95 | RATE(10, HW_RATE_INDEX_1MBPS, 0), | ||
| 96 | RATE(20, HW_RATE_INDEX_2MBPS, IEEE80211_RATE_SHORT_PREAMBLE), | ||
| 97 | RATE(55, HW_RATE_INDEX_5_5MBPS, IEEE80211_RATE_SHORT_PREAMBLE), | ||
| 98 | RATE(110, HW_RATE_INDEX_11MBPS, IEEE80211_RATE_SHORT_PREAMBLE), | ||
| 99 | RATE(60, HW_RATE_INDEX_6MBPS, 0), | ||
| 100 | RATE(90, HW_RATE_INDEX_9MBPS, 0), | ||
| 101 | RATE(120, HW_RATE_INDEX_12MBPS, 0), | ||
| 102 | RATE(180, HW_RATE_INDEX_18MBPS, 0), | ||
| 103 | RATE(240, HW_RATE_INDEX_24MBPS, 0), | ||
| 104 | RATE(360, HW_RATE_INDEX_36MBPS, 0), | ||
| 105 | RATE(480, HW_RATE_INDEX_48MBPS, 0), | ||
| 106 | RATE(540, HW_RATE_INDEX_54MBPS, 0) | ||
| 107 | }; | ||
| 108 | |||
| 109 | static struct ieee80211_rate wcn_5ghz_rates[] = { | ||
| 110 | RATE(60, HW_RATE_INDEX_6MBPS, 0), | ||
| 111 | RATE(90, HW_RATE_INDEX_9MBPS, 0), | ||
| 112 | RATE(120, HW_RATE_INDEX_12MBPS, 0), | ||
| 113 | RATE(180, HW_RATE_INDEX_18MBPS, 0), | ||
| 114 | RATE(240, HW_RATE_INDEX_24MBPS, 0), | ||
| 115 | RATE(360, HW_RATE_INDEX_36MBPS, 0), | ||
| 116 | RATE(480, HW_RATE_INDEX_48MBPS, 0), | ||
| 117 | RATE(540, HW_RATE_INDEX_54MBPS, 0) | ||
| 118 | }; | ||
| 119 | |||
| 120 | static struct ieee80211_supported_band wcn_band_2ghz = { | ||
| 121 | .channels = wcn_2ghz_channels, | ||
| 122 | .n_channels = ARRAY_SIZE(wcn_2ghz_channels), | ||
| 123 | .bitrates = wcn_2ghz_rates, | ||
| 124 | .n_bitrates = ARRAY_SIZE(wcn_2ghz_rates), | ||
| 125 | .ht_cap = { | ||
| 126 | .cap = IEEE80211_HT_CAP_GRN_FLD | | ||
| 127 | IEEE80211_HT_CAP_SGI_20 | | ||
| 128 | IEEE80211_HT_CAP_DSSSCCK40 | | ||
| 129 | IEEE80211_HT_CAP_LSIG_TXOP_PROT, | ||
| 130 | .ht_supported = true, | ||
| 131 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, | ||
| 132 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, | ||
| 133 | .mcs = { | ||
| 134 | .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, | ||
| 135 | .rx_highest = cpu_to_le16(72), | ||
| 136 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, | ||
| 137 | } | ||
| 138 | } | ||
| 139 | }; | ||
| 140 | |||
| 141 | static struct ieee80211_supported_band wcn_band_5ghz = { | ||
| 142 | .channels = wcn_5ghz_channels, | ||
| 143 | .n_channels = ARRAY_SIZE(wcn_5ghz_channels), | ||
| 144 | .bitrates = wcn_5ghz_rates, | ||
| 145 | .n_bitrates = ARRAY_SIZE(wcn_5ghz_rates), | ||
| 146 | .ht_cap = { | ||
| 147 | .cap = IEEE80211_HT_CAP_GRN_FLD | | ||
| 148 | IEEE80211_HT_CAP_SGI_20 | | ||
| 149 | IEEE80211_HT_CAP_DSSSCCK40 | | ||
| 150 | IEEE80211_HT_CAP_LSIG_TXOP_PROT | | ||
| 151 | IEEE80211_HT_CAP_SGI_40 | | ||
| 152 | IEEE80211_HT_CAP_SUP_WIDTH_20_40, | ||
| 153 | .ht_supported = true, | ||
| 154 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, | ||
| 155 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, | ||
| 156 | .mcs = { | ||
| 157 | .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, | ||
| 158 | .rx_highest = cpu_to_le16(72), | ||
| 159 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, | ||
| 160 | } | ||
| 161 | } | ||
| 162 | }; | ||
| 163 | |||
| 164 | #ifdef CONFIG_PM | ||
| 165 | |||
| 166 | static const struct wiphy_wowlan_support wowlan_support = { | ||
| 167 | .flags = WIPHY_WOWLAN_ANY | ||
| 168 | }; | ||
| 169 | |||
| 170 | #endif | ||
| 171 | |||
| 172 | static inline u8 get_sta_index(struct ieee80211_vif *vif, | ||
| 173 | struct wcn36xx_sta *sta_priv) | ||
| 174 | { | ||
| 175 | return NL80211_IFTYPE_STATION == vif->type ? | ||
| 176 | sta_priv->bss_sta_index : | ||
| 177 | sta_priv->sta_index; | ||
| 178 | } | ||
| 179 | |||
| 180 | static int wcn36xx_start(struct ieee80211_hw *hw) | ||
| 181 | { | ||
| 182 | struct wcn36xx *wcn = hw->priv; | ||
| 183 | int ret; | ||
| 184 | |||
| 185 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac start\n"); | ||
| 186 | |||
| 187 | /* SMD initialization */ | ||
| 188 | ret = wcn36xx_smd_open(wcn); | ||
| 189 | if (ret) { | ||
| 190 | wcn36xx_err("Failed to open smd channel: %d\n", ret); | ||
| 191 | goto out_err; | ||
| 192 | } | ||
| 193 | |||
| 194 | /* Allocate memory pools for Mgmt BD headers and Data BD headers */ | ||
| 195 | ret = wcn36xx_dxe_allocate_mem_pools(wcn); | ||
| 196 | if (ret) { | ||
| 197 | wcn36xx_err("Failed to alloc DXE mempool: %d\n", ret); | ||
| 198 | goto out_smd_close; | ||
| 199 | } | ||
| 200 | |||
| 201 | ret = wcn36xx_dxe_alloc_ctl_blks(wcn); | ||
| 202 | if (ret) { | ||
| 203 | wcn36xx_err("Failed to alloc DXE ctl blocks: %d\n", ret); | ||
| 204 | goto out_free_dxe_pool; | ||
| 205 | } | ||
| 206 | |||
| 207 | wcn->hal_buf = kmalloc(WCN36XX_HAL_BUF_SIZE, GFP_KERNEL); | ||
| 208 | if (!wcn->hal_buf) { | ||
| 209 | wcn36xx_err("Failed to allocate smd buf\n"); | ||
| 210 | ret = -ENOMEM; | ||
| 211 | goto out_free_dxe_ctl; | ||
| 212 | } | ||
| 213 | |||
| 214 | ret = wcn36xx_smd_load_nv(wcn); | ||
| 215 | if (ret) { | ||
| 216 | wcn36xx_err("Failed to push NV to chip\n"); | ||
| 217 | goto out_free_smd_buf; | ||
| 218 | } | ||
| 219 | |||
| 220 | ret = wcn36xx_smd_start(wcn); | ||
| 221 | if (ret) { | ||
| 222 | wcn36xx_err("Failed to start chip\n"); | ||
| 223 | goto out_free_smd_buf; | ||
| 224 | } | ||
| 225 | |||
| 226 | /* DMA channel initialization */ | ||
| 227 | ret = wcn36xx_dxe_init(wcn); | ||
| 228 | if (ret) { | ||
| 229 | wcn36xx_err("DXE init failed\n"); | ||
| 230 | goto out_smd_stop; | ||
| 231 | } | ||
| 232 | |||
| 233 | wcn36xx_debugfs_init(wcn); | ||
| 234 | |||
| 235 | if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { | ||
| 236 | ret = wcn36xx_smd_feature_caps_exchange(wcn); | ||
| 237 | if (ret) | ||
| 238 | wcn36xx_warn("Exchange feature caps failed\n"); | ||
| 239 | } | ||
| 240 | INIT_LIST_HEAD(&wcn->vif_list); | ||
| 241 | return 0; | ||
| 242 | |||
| 243 | out_smd_stop: | ||
| 244 | wcn36xx_smd_stop(wcn); | ||
| 245 | out_free_smd_buf: | ||
| 246 | kfree(wcn->hal_buf); | ||
| 247 | out_free_dxe_pool: | ||
| 248 | wcn36xx_dxe_free_mem_pools(wcn); | ||
| 249 | out_free_dxe_ctl: | ||
| 250 | wcn36xx_dxe_free_ctl_blks(wcn); | ||
| 251 | out_smd_close: | ||
| 252 | wcn36xx_smd_close(wcn); | ||
| 253 | out_err: | ||
| 254 | return ret; | ||
| 255 | } | ||
| 256 | |||
| 257 | static void wcn36xx_stop(struct ieee80211_hw *hw) | ||
| 258 | { | ||
| 259 | struct wcn36xx *wcn = hw->priv; | ||
| 260 | |||
| 261 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac stop\n"); | ||
| 262 | |||
| 263 | wcn36xx_debugfs_exit(wcn); | ||
| 264 | wcn36xx_smd_stop(wcn); | ||
| 265 | wcn36xx_dxe_deinit(wcn); | ||
| 266 | wcn36xx_smd_close(wcn); | ||
| 267 | |||
| 268 | wcn36xx_dxe_free_mem_pools(wcn); | ||
| 269 | wcn36xx_dxe_free_ctl_blks(wcn); | ||
| 270 | |||
| 271 | kfree(wcn->hal_buf); | ||
| 272 | } | ||
| 273 | |||
| 274 | static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed) | ||
| 275 | { | ||
| 276 | struct wcn36xx *wcn = hw->priv; | ||
| 277 | struct ieee80211_vif *vif = NULL; | ||
| 278 | struct wcn36xx_vif *tmp; | ||
| 279 | |||
| 280 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac config changed 0x%08x\n", changed); | ||
| 281 | |||
| 282 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | ||
| 283 | int ch = WCN36XX_HW_CHANNEL(wcn); | ||
| 284 | wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n", | ||
| 285 | ch); | ||
| 286 | list_for_each_entry(tmp, &wcn->vif_list, list) { | ||
| 287 | vif = container_of((void *)tmp, | ||
| 288 | struct ieee80211_vif, | ||
| 289 | drv_priv); | ||
| 290 | wcn36xx_smd_switch_channel(wcn, vif, ch); | ||
| 291 | } | ||
| 292 | } | ||
| 293 | |||
| 294 | return 0; | ||
| 295 | } | ||
| 296 | |||
| 297 | #define WCN36XX_SUPPORTED_FILTERS (0) | ||
| 298 | |||
| 299 | static void wcn36xx_configure_filter(struct ieee80211_hw *hw, | ||
| 300 | unsigned int changed, | ||
| 301 | unsigned int *total, u64 multicast) | ||
| 302 | { | ||
| 303 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n"); | ||
| 304 | |||
| 305 | *total &= WCN36XX_SUPPORTED_FILTERS; | ||
| 306 | } | ||
| 307 | |||
| 308 | static void wcn36xx_tx(struct ieee80211_hw *hw, | ||
| 309 | struct ieee80211_tx_control *control, | ||
| 310 | struct sk_buff *skb) | ||
| 311 | { | ||
| 312 | struct wcn36xx *wcn = hw->priv; | ||
| 313 | struct wcn36xx_sta *sta_priv = NULL; | ||
| 314 | |||
| 315 | if (control->sta) | ||
| 316 | sta_priv = (struct wcn36xx_sta *)control->sta->drv_priv; | ||
| 317 | |||
| 318 | if (wcn36xx_start_tx(wcn, sta_priv, skb)) | ||
| 319 | ieee80211_free_txskb(wcn->hw, skb); | ||
| 320 | } | ||
| 321 | |||
| 322 | static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | ||
| 323 | struct ieee80211_vif *vif, | ||
| 324 | struct ieee80211_sta *sta, | ||
| 325 | struct ieee80211_key_conf *key_conf) | ||
| 326 | { | ||
| 327 | struct wcn36xx *wcn = hw->priv; | ||
| 328 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
| 329 | struct wcn36xx_sta *sta_priv = vif_priv->sta; | ||
| 330 | int ret = 0; | ||
| 331 | u8 key[WLAN_MAX_KEY_LEN]; | ||
| 332 | |||
| 333 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 set key\n"); | ||
| 334 | wcn36xx_dbg(WCN36XX_DBG_MAC, "Key: cmd=0x%x algo:0x%x, id:%d, len:%d flags 0x%x\n", | ||
| 335 | cmd, key_conf->cipher, key_conf->keyidx, | ||
| 336 | key_conf->keylen, key_conf->flags); | ||
| 337 | wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "KEY: ", | ||
| 338 | key_conf->key, | ||
| 339 | key_conf->keylen); | ||
| 340 | |||
| 341 | switch (key_conf->cipher) { | ||
| 342 | case WLAN_CIPHER_SUITE_WEP40: | ||
| 343 | vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40; | ||
| 344 | break; | ||
| 345 | case WLAN_CIPHER_SUITE_WEP104: | ||
| 346 | vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40; | ||
| 347 | break; | ||
| 348 | case WLAN_CIPHER_SUITE_CCMP: | ||
| 349 | vif_priv->encrypt_type = WCN36XX_HAL_ED_CCMP; | ||
| 350 | break; | ||
| 351 | case WLAN_CIPHER_SUITE_TKIP: | ||
| 352 | vif_priv->encrypt_type = WCN36XX_HAL_ED_TKIP; | ||
| 353 | break; | ||
| 354 | default: | ||
| 355 | wcn36xx_err("Unsupported key type 0x%x\n", | ||
| 356 | key_conf->cipher); | ||
| 357 | ret = -EOPNOTSUPP; | ||
| 358 | goto out; | ||
| 359 | } | ||
| 360 | |||
| 361 | switch (cmd) { | ||
| 362 | case SET_KEY: | ||
| 363 | if (WCN36XX_HAL_ED_TKIP == vif_priv->encrypt_type) { | ||
| 364 | /* | ||
| 365 | * Supplicant is sending key in the wrong order: | ||
| 366 | * Temporal Key (16 b) - TX MIC (8 b) - RX MIC (8 b) | ||
| 367 | * but HW expects it to be in the order as described in | ||
| 368 | * IEEE 802.11 spec (see chapter 11.7) like this: | ||
| 369 | * Temporal Key (16 b) - RX MIC (8 b) - TX MIC (8 b) | ||
| 370 | */ | ||
| 371 | memcpy(key, key_conf->key, 16); | ||
| 372 | memcpy(key + 16, key_conf->key + 24, 8); | ||
| 373 | memcpy(key + 24, key_conf->key + 16, 8); | ||
| 374 | } else { | ||
| 375 | memcpy(key, key_conf->key, key_conf->keylen); | ||
| 376 | } | ||
| 377 | |||
| 378 | if (IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags) { | ||
| 379 | sta_priv->is_data_encrypted = true; | ||
| 380 | /* Reconfigure bss with encrypt_type */ | ||
| 381 | if (NL80211_IFTYPE_STATION == vif->type) | ||
| 382 | wcn36xx_smd_config_bss(wcn, | ||
| 383 | vif, | ||
| 384 | sta, | ||
| 385 | sta->addr, | ||
| 386 | true); | ||
| 387 | |||
| 388 | wcn36xx_smd_set_stakey(wcn, | ||
| 389 | vif_priv->encrypt_type, | ||
| 390 | key_conf->keyidx, | ||
| 391 | key_conf->keylen, | ||
| 392 | key, | ||
| 393 | get_sta_index(vif, sta_priv)); | ||
| 394 | } else { | ||
| 395 | wcn36xx_smd_set_bsskey(wcn, | ||
| 396 | vif_priv->encrypt_type, | ||
| 397 | key_conf->keyidx, | ||
| 398 | key_conf->keylen, | ||
| 399 | key); | ||
| 400 | if ((WLAN_CIPHER_SUITE_WEP40 == key_conf->cipher) || | ||
| 401 | (WLAN_CIPHER_SUITE_WEP104 == key_conf->cipher)) { | ||
| 402 | sta_priv->is_data_encrypted = true; | ||
| 403 | wcn36xx_smd_set_stakey(wcn, | ||
| 404 | vif_priv->encrypt_type, | ||
| 405 | key_conf->keyidx, | ||
| 406 | key_conf->keylen, | ||
| 407 | key, | ||
| 408 | get_sta_index(vif, sta_priv)); | ||
| 409 | } | ||
| 410 | } | ||
| 411 | break; | ||
| 412 | case DISABLE_KEY: | ||
| 413 | if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) { | ||
| 414 | wcn36xx_smd_remove_bsskey(wcn, | ||
| 415 | vif_priv->encrypt_type, | ||
| 416 | key_conf->keyidx); | ||
| 417 | } else { | ||
| 418 | sta_priv->is_data_encrypted = false; | ||
| 419 | /* do not remove key if disassociated */ | ||
| 420 | if (sta_priv->aid) | ||
| 421 | wcn36xx_smd_remove_stakey(wcn, | ||
| 422 | vif_priv->encrypt_type, | ||
| 423 | key_conf->keyidx, | ||
| 424 | get_sta_index(vif, sta_priv)); | ||
| 425 | } | ||
| 426 | break; | ||
| 427 | default: | ||
| 428 | wcn36xx_err("Unsupported key cmd 0x%x\n", cmd); | ||
| 429 | ret = -EOPNOTSUPP; | ||
| 430 | goto out; | ||
| 431 | break; | ||
| 432 | } | ||
| 433 | |||
| 434 | out: | ||
| 435 | return ret; | ||
| 436 | } | ||
| 437 | |||
| 438 | static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw) | ||
| 439 | { | ||
| 440 | struct wcn36xx *wcn = hw->priv; | ||
| 441 | |||
| 442 | wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN); | ||
| 443 | wcn36xx_smd_start_scan(wcn); | ||
| 444 | } | ||
| 445 | |||
| 446 | static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw) | ||
| 447 | { | ||
| 448 | struct wcn36xx *wcn = hw->priv; | ||
| 449 | |||
| 450 | wcn36xx_smd_end_scan(wcn); | ||
| 451 | wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN); | ||
| 452 | } | ||
| 453 | |||
| 454 | static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta, | ||
| 455 | enum ieee80211_band band) | ||
| 456 | { | ||
| 457 | int i, size; | ||
| 458 | u16 *rates_table; | ||
| 459 | struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; | ||
| 460 | u32 rates = sta->supp_rates[band]; | ||
| 461 | |||
| 462 | memset(&sta_priv->supported_rates, 0, | ||
| 463 | sizeof(sta_priv->supported_rates)); | ||
| 464 | sta_priv->supported_rates.op_rate_mode = STA_11n; | ||
| 465 | |||
| 466 | size = ARRAY_SIZE(sta_priv->supported_rates.dsss_rates); | ||
| 467 | rates_table = sta_priv->supported_rates.dsss_rates; | ||
| 468 | if (band == IEEE80211_BAND_2GHZ) { | ||
| 469 | for (i = 0; i < size; i++) { | ||
| 470 | if (rates & 0x01) { | ||
| 471 | rates_table[i] = wcn_2ghz_rates[i].hw_value; | ||
| 472 | rates = rates >> 1; | ||
| 473 | } | ||
| 474 | } | ||
| 475 | } | ||
| 476 | |||
| 477 | size = ARRAY_SIZE(sta_priv->supported_rates.ofdm_rates); | ||
| 478 | rates_table = sta_priv->supported_rates.ofdm_rates; | ||
| 479 | for (i = 0; i < size; i++) { | ||
| 480 | if (rates & 0x01) { | ||
| 481 | rates_table[i] = wcn_5ghz_rates[i].hw_value; | ||
| 482 | rates = rates >> 1; | ||
| 483 | } | ||
| 484 | } | ||
| 485 | |||
| 486 | if (sta->ht_cap.ht_supported) { | ||
| 487 | BUILD_BUG_ON(sizeof(sta->ht_cap.mcs.rx_mask) > | ||
| 488 | sizeof(sta_priv->supported_rates.supported_mcs_set)); | ||
| 489 | memcpy(sta_priv->supported_rates.supported_mcs_set, | ||
| 490 | sta->ht_cap.mcs.rx_mask, | ||
| 491 | sizeof(sta->ht_cap.mcs.rx_mask)); | ||
| 492 | } | ||
| 493 | } | ||
| 494 | void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates) | ||
| 495 | { | ||
| 496 | u16 ofdm_rates[WCN36XX_HAL_NUM_OFDM_RATES] = { | ||
| 497 | HW_RATE_INDEX_6MBPS, | ||
| 498 | HW_RATE_INDEX_9MBPS, | ||
| 499 | HW_RATE_INDEX_12MBPS, | ||
| 500 | HW_RATE_INDEX_18MBPS, | ||
| 501 | HW_RATE_INDEX_24MBPS, | ||
| 502 | HW_RATE_INDEX_36MBPS, | ||
| 503 | HW_RATE_INDEX_48MBPS, | ||
| 504 | HW_RATE_INDEX_54MBPS | ||
| 505 | }; | ||
| 506 | u16 dsss_rates[WCN36XX_HAL_NUM_DSSS_RATES] = { | ||
| 507 | HW_RATE_INDEX_1MBPS, | ||
| 508 | HW_RATE_INDEX_2MBPS, | ||
| 509 | HW_RATE_INDEX_5_5MBPS, | ||
| 510 | HW_RATE_INDEX_11MBPS | ||
| 511 | }; | ||
| 512 | |||
| 513 | rates->op_rate_mode = STA_11n; | ||
| 514 | memcpy(rates->dsss_rates, dsss_rates, | ||
| 515 | sizeof(*dsss_rates) * WCN36XX_HAL_NUM_DSSS_RATES); | ||
| 516 | memcpy(rates->ofdm_rates, ofdm_rates, | ||
| 517 | sizeof(*ofdm_rates) * WCN36XX_HAL_NUM_OFDM_RATES); | ||
| 518 | rates->supported_mcs_set[0] = 0xFF; | ||
| 519 | } | ||
| 520 | static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, | ||
| 521 | struct ieee80211_vif *vif, | ||
| 522 | struct ieee80211_bss_conf *bss_conf, | ||
| 523 | u32 changed) | ||
| 524 | { | ||
| 525 | struct wcn36xx *wcn = hw->priv; | ||
| 526 | struct sk_buff *skb = NULL; | ||
| 527 | u16 tim_off, tim_len; | ||
| 528 | enum wcn36xx_hal_link_state link_state; | ||
| 529 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
| 530 | |||
| 531 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n", | ||
| 532 | vif, changed); | ||
| 533 | |||
| 534 | if (changed & BSS_CHANGED_BEACON_INFO) { | ||
| 535 | wcn36xx_dbg(WCN36XX_DBG_MAC, | ||
| 536 | "mac bss changed dtim period %d\n", | ||
| 537 | bss_conf->dtim_period); | ||
| 538 | |||
| 539 | vif_priv->dtim_period = bss_conf->dtim_period; | ||
| 540 | } | ||
| 541 | |||
| 542 | if (changed & BSS_CHANGED_PS) { | ||
| 543 | wcn36xx_dbg(WCN36XX_DBG_MAC, | ||
| 544 | "mac bss PS set %d\n", | ||
| 545 | bss_conf->ps); | ||
| 546 | if (bss_conf->ps) { | ||
| 547 | wcn36xx_pmc_enter_bmps_state(wcn, vif); | ||
| 548 | } else { | ||
| 549 | wcn36xx_pmc_exit_bmps_state(wcn, vif); | ||
| 550 | } | ||
| 551 | } | ||
| 552 | |||
| 553 | if (changed & BSS_CHANGED_BSSID) { | ||
| 554 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed_bssid %pM\n", | ||
| 555 | bss_conf->bssid); | ||
| 556 | |||
| 557 | if (!is_zero_ether_addr(bss_conf->bssid)) { | ||
| 558 | vif_priv->is_joining = true; | ||
| 559 | vif_priv->bss_index = 0xff; | ||
| 560 | wcn36xx_smd_join(wcn, bss_conf->bssid, | ||
| 561 | vif->addr, WCN36XX_HW_CHANNEL(wcn)); | ||
| 562 | wcn36xx_smd_config_bss(wcn, vif, NULL, | ||
| 563 | bss_conf->bssid, false); | ||
| 564 | } else { | ||
| 565 | vif_priv->is_joining = false; | ||
| 566 | wcn36xx_smd_delete_bss(wcn, vif); | ||
| 567 | } | ||
| 568 | } | ||
| 569 | |||
| 570 | if (changed & BSS_CHANGED_SSID) { | ||
| 571 | wcn36xx_dbg(WCN36XX_DBG_MAC, | ||
| 572 | "mac bss changed ssid\n"); | ||
| 573 | wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "ssid ", | ||
| 574 | bss_conf->ssid, bss_conf->ssid_len); | ||
| 575 | |||
| 576 | vif_priv->ssid.length = bss_conf->ssid_len; | ||
| 577 | memcpy(&vif_priv->ssid.ssid, | ||
| 578 | bss_conf->ssid, | ||
| 579 | bss_conf->ssid_len); | ||
| 580 | } | ||
| 581 | |||
| 582 | if (changed & BSS_CHANGED_ASSOC) { | ||
| 583 | vif_priv->is_joining = false; | ||
| 584 | if (bss_conf->assoc) { | ||
| 585 | struct ieee80211_sta *sta; | ||
| 586 | struct wcn36xx_sta *sta_priv; | ||
| 587 | |||
| 588 | wcn36xx_dbg(WCN36XX_DBG_MAC, | ||
| 589 | "mac assoc bss %pM vif %pM AID=%d\n", | ||
| 590 | bss_conf->bssid, | ||
| 591 | vif->addr, | ||
| 592 | bss_conf->aid); | ||
| 593 | |||
| 594 | rcu_read_lock(); | ||
| 595 | sta = ieee80211_find_sta(vif, bss_conf->bssid); | ||
| 596 | if (!sta) { | ||
| 597 | wcn36xx_err("sta %pM is not found\n", | ||
| 598 | bss_conf->bssid); | ||
| 599 | rcu_read_unlock(); | ||
| 600 | goto out; | ||
| 601 | } | ||
| 602 | sta_priv = (struct wcn36xx_sta *)sta->drv_priv; | ||
| 603 | |||
| 604 | wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn)); | ||
| 605 | |||
| 606 | wcn36xx_smd_set_link_st(wcn, bss_conf->bssid, | ||
| 607 | vif->addr, | ||
| 608 | WCN36XX_HAL_LINK_POSTASSOC_STATE); | ||
| 609 | wcn36xx_smd_config_bss(wcn, vif, sta, | ||
| 610 | bss_conf->bssid, | ||
| 611 | true); | ||
| 612 | sta_priv->aid = bss_conf->aid; | ||
| 613 | /* | ||
| 614 | * config_sta must be called from because this is the | ||
| 615 | * place where AID is available. | ||
| 616 | */ | ||
| 617 | wcn36xx_smd_config_sta(wcn, vif, sta); | ||
| 618 | rcu_read_unlock(); | ||
| 619 | } else { | ||
| 620 | wcn36xx_dbg(WCN36XX_DBG_MAC, | ||
| 621 | "disassociated bss %pM vif %pM AID=%d\n", | ||
| 622 | bss_conf->bssid, | ||
| 623 | vif->addr, | ||
| 624 | bss_conf->aid); | ||
| 625 | wcn36xx_smd_set_link_st(wcn, | ||
| 626 | bss_conf->bssid, | ||
| 627 | vif->addr, | ||
| 628 | WCN36XX_HAL_LINK_IDLE_STATE); | ||
| 629 | } | ||
| 630 | } | ||
| 631 | |||
| 632 | if (changed & BSS_CHANGED_AP_PROBE_RESP) { | ||
| 633 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed ap probe resp\n"); | ||
| 634 | skb = ieee80211_proberesp_get(hw, vif); | ||
| 635 | if (!skb) { | ||
| 636 | wcn36xx_err("failed to alloc probereq skb\n"); | ||
| 637 | goto out; | ||
| 638 | } | ||
| 639 | |||
| 640 | wcn36xx_smd_update_proberesp_tmpl(wcn, vif, skb); | ||
| 641 | dev_kfree_skb(skb); | ||
| 642 | } | ||
| 643 | |||
| 644 | if (changed & BSS_CHANGED_BEACON_ENABLED) { | ||
| 645 | wcn36xx_dbg(WCN36XX_DBG_MAC, | ||
| 646 | "mac bss changed beacon enabled %d\n", | ||
| 647 | bss_conf->enable_beacon); | ||
| 648 | |||
| 649 | if (bss_conf->enable_beacon) { | ||
| 650 | vif_priv->bss_index = 0xff; | ||
| 651 | wcn36xx_smd_config_bss(wcn, vif, NULL, | ||
| 652 | vif->addr, false); | ||
| 653 | skb = ieee80211_beacon_get_tim(hw, vif, &tim_off, | ||
| 654 | &tim_len); | ||
| 655 | if (!skb) { | ||
| 656 | wcn36xx_err("failed to alloc beacon skb\n"); | ||
| 657 | goto out; | ||
| 658 | } | ||
| 659 | wcn36xx_smd_send_beacon(wcn, vif, skb, tim_off, 0); | ||
| 660 | dev_kfree_skb(skb); | ||
| 661 | |||
| 662 | if (vif->type == NL80211_IFTYPE_ADHOC || | ||
| 663 | vif->type == NL80211_IFTYPE_MESH_POINT) | ||
| 664 | link_state = WCN36XX_HAL_LINK_IBSS_STATE; | ||
| 665 | else | ||
| 666 | link_state = WCN36XX_HAL_LINK_AP_STATE; | ||
| 667 | |||
| 668 | wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr, | ||
| 669 | link_state); | ||
| 670 | } else { | ||
| 671 | wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr, | ||
| 672 | WCN36XX_HAL_LINK_IDLE_STATE); | ||
| 673 | wcn36xx_smd_delete_bss(wcn, vif); | ||
| 674 | } | ||
| 675 | } | ||
| 676 | out: | ||
| 677 | return; | ||
| 678 | } | ||
| 679 | |||
| 680 | /* this is required when using IEEE80211_HW_HAS_RATE_CONTROL */ | ||
| 681 | static int wcn36xx_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | ||
| 682 | { | ||
| 683 | struct wcn36xx *wcn = hw->priv; | ||
| 684 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac set RTS threshold %d\n", value); | ||
| 685 | |||
| 686 | wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_RTS_THRESHOLD, value); | ||
| 687 | return 0; | ||
| 688 | } | ||
| 689 | |||
| 690 | static void wcn36xx_remove_interface(struct ieee80211_hw *hw, | ||
| 691 | struct ieee80211_vif *vif) | ||
| 692 | { | ||
| 693 | struct wcn36xx *wcn = hw->priv; | ||
| 694 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
| 695 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif); | ||
| 696 | |||
| 697 | list_del(&vif_priv->list); | ||
| 698 | wcn36xx_smd_delete_sta_self(wcn, vif->addr); | ||
| 699 | } | ||
| 700 | |||
| 701 | static int wcn36xx_add_interface(struct ieee80211_hw *hw, | ||
| 702 | struct ieee80211_vif *vif) | ||
| 703 | { | ||
| 704 | struct wcn36xx *wcn = hw->priv; | ||
| 705 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
| 706 | |||
| 707 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac add interface vif %p type %d\n", | ||
| 708 | vif, vif->type); | ||
| 709 | |||
| 710 | if (!(NL80211_IFTYPE_STATION == vif->type || | ||
| 711 | NL80211_IFTYPE_AP == vif->type || | ||
| 712 | NL80211_IFTYPE_ADHOC == vif->type || | ||
| 713 | NL80211_IFTYPE_MESH_POINT == vif->type)) { | ||
| 714 | wcn36xx_warn("Unsupported interface type requested: %d\n", | ||
| 715 | vif->type); | ||
| 716 | return -EOPNOTSUPP; | ||
| 717 | } | ||
| 718 | |||
| 719 | list_add(&vif_priv->list, &wcn->vif_list); | ||
| 720 | wcn36xx_smd_add_sta_self(wcn, vif); | ||
| 721 | |||
| 722 | return 0; | ||
| 723 | } | ||
| 724 | |||
| 725 | static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
| 726 | struct ieee80211_sta *sta) | ||
| 727 | { | ||
| 728 | struct wcn36xx *wcn = hw->priv; | ||
| 729 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
| 730 | struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; | ||
| 731 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n", | ||
| 732 | vif, sta->addr); | ||
| 733 | |||
| 734 | vif_priv->sta = sta_priv; | ||
| 735 | sta_priv->vif = vif_priv; | ||
| 736 | /* | ||
| 737 | * For STA mode HW will be configured on BSS_CHANGED_ASSOC because | ||
| 738 | * at this stage AID is not available yet. | ||
| 739 | */ | ||
| 740 | if (NL80211_IFTYPE_STATION != vif->type) { | ||
| 741 | wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn)); | ||
| 742 | sta_priv->aid = sta->aid; | ||
| 743 | wcn36xx_smd_config_sta(wcn, vif, sta); | ||
| 744 | } | ||
| 745 | return 0; | ||
| 746 | } | ||
| 747 | |||
| 748 | static int wcn36xx_sta_remove(struct ieee80211_hw *hw, | ||
| 749 | struct ieee80211_vif *vif, | ||
| 750 | struct ieee80211_sta *sta) | ||
| 751 | { | ||
| 752 | struct wcn36xx *wcn = hw->priv; | ||
| 753 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
| 754 | struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; | ||
| 755 | |||
| 756 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n", | ||
| 757 | vif, sta->addr, sta_priv->sta_index); | ||
| 758 | |||
| 759 | wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index); | ||
| 760 | vif_priv->sta = NULL; | ||
| 761 | sta_priv->vif = NULL; | ||
| 762 | return 0; | ||
| 763 | } | ||
| 764 | |||
| 765 | #ifdef CONFIG_PM | ||
| 766 | |||
| 767 | static int wcn36xx_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wow) | ||
| 768 | { | ||
| 769 | struct wcn36xx *wcn = hw->priv; | ||
| 770 | |||
| 771 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac suspend\n"); | ||
| 772 | |||
| 773 | flush_workqueue(wcn->hal_ind_wq); | ||
| 774 | wcn36xx_smd_set_power_params(wcn, true); | ||
| 775 | return 0; | ||
| 776 | } | ||
| 777 | |||
| 778 | static int wcn36xx_resume(struct ieee80211_hw *hw) | ||
| 779 | { | ||
| 780 | struct wcn36xx *wcn = hw->priv; | ||
| 781 | |||
| 782 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac resume\n"); | ||
| 783 | |||
| 784 | flush_workqueue(wcn->hal_ind_wq); | ||
| 785 | wcn36xx_smd_set_power_params(wcn, false); | ||
| 786 | return 0; | ||
| 787 | } | ||
| 788 | |||
| 789 | #endif | ||
| 790 | |||
| 791 | static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, | ||
| 792 | struct ieee80211_vif *vif, | ||
| 793 | enum ieee80211_ampdu_mlme_action action, | ||
| 794 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, | ||
| 795 | u8 buf_size) | ||
| 796 | { | ||
| 797 | struct wcn36xx *wcn = hw->priv; | ||
| 798 | struct wcn36xx_sta *sta_priv = NULL; | ||
| 799 | |||
| 800 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n", | ||
| 801 | action, tid); | ||
| 802 | |||
| 803 | sta_priv = (struct wcn36xx_sta *)sta->drv_priv; | ||
| 804 | |||
| 805 | switch (action) { | ||
| 806 | case IEEE80211_AMPDU_RX_START: | ||
| 807 | sta_priv->tid = tid; | ||
| 808 | wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 0, | ||
| 809 | get_sta_index(vif, sta_priv)); | ||
| 810 | wcn36xx_smd_add_ba(wcn); | ||
| 811 | wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv)); | ||
| 812 | ieee80211_start_tx_ba_session(sta, tid, 0); | ||
| 813 | break; | ||
| 814 | case IEEE80211_AMPDU_RX_STOP: | ||
| 815 | wcn36xx_smd_del_ba(wcn, tid, get_sta_index(vif, sta_priv)); | ||
| 816 | break; | ||
| 817 | case IEEE80211_AMPDU_TX_START: | ||
| 818 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
| 819 | break; | ||
| 820 | case IEEE80211_AMPDU_TX_OPERATIONAL: | ||
| 821 | wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 1, | ||
| 822 | get_sta_index(vif, sta_priv)); | ||
| 823 | break; | ||
| 824 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | ||
| 825 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | ||
| 826 | case IEEE80211_AMPDU_TX_STOP_CONT: | ||
| 827 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
| 828 | break; | ||
| 829 | default: | ||
| 830 | wcn36xx_err("Unknown AMPDU action\n"); | ||
| 831 | } | ||
| 832 | |||
| 833 | return 0; | ||
| 834 | } | ||
| 835 | |||
| 836 | static const struct ieee80211_ops wcn36xx_ops = { | ||
| 837 | .start = wcn36xx_start, | ||
| 838 | .stop = wcn36xx_stop, | ||
| 839 | .add_interface = wcn36xx_add_interface, | ||
| 840 | .remove_interface = wcn36xx_remove_interface, | ||
| 841 | #ifdef CONFIG_PM | ||
| 842 | .suspend = wcn36xx_suspend, | ||
| 843 | .resume = wcn36xx_resume, | ||
| 844 | #endif | ||
| 845 | .config = wcn36xx_config, | ||
| 846 | .configure_filter = wcn36xx_configure_filter, | ||
| 847 | .tx = wcn36xx_tx, | ||
| 848 | .set_key = wcn36xx_set_key, | ||
| 849 | .sw_scan_start = wcn36xx_sw_scan_start, | ||
| 850 | .sw_scan_complete = wcn36xx_sw_scan_complete, | ||
| 851 | .bss_info_changed = wcn36xx_bss_info_changed, | ||
| 852 | .set_rts_threshold = wcn36xx_set_rts_threshold, | ||
| 853 | .sta_add = wcn36xx_sta_add, | ||
| 854 | .sta_remove = wcn36xx_sta_remove, | ||
| 855 | .ampdu_action = wcn36xx_ampdu_action, | ||
| 856 | }; | ||
| 857 | |||
| 858 | static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) | ||
| 859 | { | ||
| 860 | int ret = 0; | ||
| 861 | |||
| 862 | static const u32 cipher_suites[] = { | ||
| 863 | WLAN_CIPHER_SUITE_WEP40, | ||
| 864 | WLAN_CIPHER_SUITE_WEP104, | ||
| 865 | WLAN_CIPHER_SUITE_TKIP, | ||
| 866 | WLAN_CIPHER_SUITE_CCMP, | ||
| 867 | }; | ||
| 868 | |||
| 869 | wcn->hw->flags = IEEE80211_HW_SIGNAL_DBM | | ||
| 870 | IEEE80211_HW_HAS_RATE_CONTROL | | ||
| 871 | IEEE80211_HW_SUPPORTS_PS | | ||
| 872 | IEEE80211_HW_CONNECTION_MONITOR | | ||
| 873 | IEEE80211_HW_AMPDU_AGGREGATION | | ||
| 874 | IEEE80211_HW_TIMING_BEACON_ONLY; | ||
| 875 | |||
| 876 | wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | ||
| 877 | BIT(NL80211_IFTYPE_AP) | | ||
| 878 | BIT(NL80211_IFTYPE_ADHOC) | | ||
| 879 | BIT(NL80211_IFTYPE_MESH_POINT); | ||
| 880 | |||
| 881 | wcn->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wcn_band_2ghz; | ||
| 882 | wcn->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wcn_band_5ghz; | ||
| 883 | |||
| 884 | wcn->hw->wiphy->cipher_suites = cipher_suites; | ||
| 885 | wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | ||
| 886 | |||
| 887 | wcn->hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; | ||
| 888 | |||
| 889 | #ifdef CONFIG_PM | ||
| 890 | wcn->hw->wiphy->wowlan = &wowlan_support; | ||
| 891 | #endif | ||
| 892 | |||
| 893 | wcn->hw->max_listen_interval = 200; | ||
| 894 | |||
| 895 | wcn->hw->queues = 4; | ||
| 896 | |||
| 897 | SET_IEEE80211_DEV(wcn->hw, wcn->dev); | ||
| 898 | |||
| 899 | wcn->hw->sta_data_size = sizeof(struct wcn36xx_sta); | ||
| 900 | wcn->hw->vif_data_size = sizeof(struct wcn36xx_vif); | ||
| 901 | |||
| 902 | return ret; | ||
| 903 | } | ||
| 904 | |||
| 905 | static int wcn36xx_platform_get_resources(struct wcn36xx *wcn, | ||
| 906 | struct platform_device *pdev) | ||
| 907 | { | ||
| 908 | struct resource *res; | ||
| 909 | /* Set TX IRQ */ | ||
| 910 | res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, | ||
| 911 | "wcnss_wlantx_irq"); | ||
| 912 | if (!res) { | ||
| 913 | wcn36xx_err("failed to get tx_irq\n"); | ||
| 914 | return -ENOENT; | ||
| 915 | } | ||
| 916 | wcn->tx_irq = res->start; | ||
| 917 | |||
| 918 | /* Set RX IRQ */ | ||
| 919 | res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, | ||
| 920 | "wcnss_wlanrx_irq"); | ||
| 921 | if (!res) { | ||
| 922 | wcn36xx_err("failed to get rx_irq\n"); | ||
| 923 | return -ENOENT; | ||
| 924 | } | ||
| 925 | wcn->rx_irq = res->start; | ||
| 926 | |||
| 927 | /* Map the memory */ | ||
| 928 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | ||
| 929 | "wcnss_mmio"); | ||
| 930 | if (!res) { | ||
| 931 | wcn36xx_err("failed to get mmio\n"); | ||
| 932 | return -ENOENT; | ||
| 933 | } | ||
| 934 | wcn->mmio = ioremap(res->start, resource_size(res)); | ||
| 935 | if (!wcn->mmio) { | ||
| 936 | wcn36xx_err("failed to map io memory\n"); | ||
| 937 | return -ENOMEM; | ||
| 938 | } | ||
| 939 | return 0; | ||
| 940 | } | ||
| 941 | |||
| 942 | static int wcn36xx_probe(struct platform_device *pdev) | ||
| 943 | { | ||
| 944 | struct ieee80211_hw *hw; | ||
| 945 | struct wcn36xx *wcn; | ||
| 946 | int ret; | ||
| 947 | u8 addr[ETH_ALEN]; | ||
| 948 | |||
| 949 | wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n"); | ||
| 950 | |||
| 951 | hw = ieee80211_alloc_hw(sizeof(struct wcn36xx), &wcn36xx_ops); | ||
| 952 | if (!hw) { | ||
| 953 | wcn36xx_err("failed to alloc hw\n"); | ||
| 954 | ret = -ENOMEM; | ||
| 955 | goto out_err; | ||
| 956 | } | ||
| 957 | platform_set_drvdata(pdev, hw); | ||
| 958 | wcn = hw->priv; | ||
| 959 | wcn->hw = hw; | ||
| 960 | wcn->dev = &pdev->dev; | ||
| 961 | wcn->ctrl_ops = pdev->dev.platform_data; | ||
| 962 | |||
| 963 | mutex_init(&wcn->hal_mutex); | ||
| 964 | |||
| 965 | if (!wcn->ctrl_ops->get_hw_mac(addr)) { | ||
| 966 | wcn36xx_info("mac address: %pM\n", addr); | ||
| 967 | SET_IEEE80211_PERM_ADDR(wcn->hw, addr); | ||
| 968 | } | ||
| 969 | |||
| 970 | ret = wcn36xx_platform_get_resources(wcn, pdev); | ||
| 971 | if (ret) | ||
| 972 | goto out_wq; | ||
| 973 | |||
| 974 | wcn36xx_init_ieee80211(wcn); | ||
| 975 | ret = ieee80211_register_hw(wcn->hw); | ||
| 976 | if (ret) | ||
| 977 | goto out_unmap; | ||
| 978 | |||
| 979 | return 0; | ||
| 980 | |||
| 981 | out_unmap: | ||
| 982 | iounmap(wcn->mmio); | ||
| 983 | out_wq: | ||
| 984 | ieee80211_free_hw(hw); | ||
| 985 | out_err: | ||
| 986 | return ret; | ||
| 987 | } | ||
| 988 | static int wcn36xx_remove(struct platform_device *pdev) | ||
| 989 | { | ||
| 990 | struct ieee80211_hw *hw = platform_get_drvdata(pdev); | ||
| 991 | struct wcn36xx *wcn = hw->priv; | ||
| 992 | wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n"); | ||
| 993 | |||
| 994 | mutex_destroy(&wcn->hal_mutex); | ||
| 995 | |||
| 996 | ieee80211_unregister_hw(hw); | ||
| 997 | iounmap(wcn->mmio); | ||
| 998 | ieee80211_free_hw(hw); | ||
| 999 | |||
| 1000 | return 0; | ||
| 1001 | } | ||
| 1002 | static const struct platform_device_id wcn36xx_platform_id_table[] = { | ||
| 1003 | { | ||
| 1004 | .name = "wcn36xx", | ||
| 1005 | .driver_data = 0 | ||
| 1006 | }, | ||
| 1007 | {} | ||
| 1008 | }; | ||
| 1009 | MODULE_DEVICE_TABLE(platform, wcn36xx_platform_id_table); | ||
| 1010 | |||
| 1011 | static struct platform_driver wcn36xx_driver = { | ||
| 1012 | .probe = wcn36xx_probe, | ||
| 1013 | .remove = wcn36xx_remove, | ||
| 1014 | .driver = { | ||
| 1015 | .name = "wcn36xx", | ||
| 1016 | .owner = THIS_MODULE, | ||
| 1017 | }, | ||
| 1018 | .id_table = wcn36xx_platform_id_table, | ||
| 1019 | }; | ||
| 1020 | |||
| 1021 | static int __init wcn36xx_init(void) | ||
| 1022 | { | ||
| 1023 | platform_driver_register(&wcn36xx_driver); | ||
| 1024 | return 0; | ||
| 1025 | } | ||
| 1026 | module_init(wcn36xx_init); | ||
| 1027 | |||
| 1028 | static void __exit wcn36xx_exit(void) | ||
| 1029 | { | ||
| 1030 | platform_driver_unregister(&wcn36xx_driver); | ||
| 1031 | } | ||
| 1032 | module_exit(wcn36xx_exit); | ||
| 1033 | |||
| 1034 | MODULE_LICENSE("Dual BSD/GPL"); | ||
| 1035 | MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com"); | ||
| 1036 | MODULE_FIRMWARE(WLAN_NV_FILE); | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/pmc.c b/drivers/net/wireless/ath/wcn36xx/pmc.c new file mode 100644 index 000000000000..28b515c81b0e --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/pmc.c | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 18 | |||
| 19 | #include "wcn36xx.h" | ||
| 20 | |||
| 21 | int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn, | ||
| 22 | struct ieee80211_vif *vif) | ||
| 23 | { | ||
| 24 | int ret = 0; | ||
| 25 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
| 26 | /* TODO: Make sure the TX chain clean */ | ||
| 27 | ret = wcn36xx_smd_enter_bmps(wcn, vif); | ||
| 28 | if (!ret) { | ||
| 29 | wcn36xx_dbg(WCN36XX_DBG_PMC, "Entered BMPS\n"); | ||
| 30 | vif_priv->pw_state = WCN36XX_BMPS; | ||
| 31 | } else { | ||
| 32 | /* | ||
| 33 | * One of the reasons why HW will not enter BMPS is because | ||
| 34 | * driver is trying to enter bmps before first beacon was | ||
| 35 | * received just after auth complete | ||
| 36 | */ | ||
| 37 | wcn36xx_err("Can not enter BMPS!\n"); | ||
| 38 | } | ||
| 39 | return ret; | ||
| 40 | } | ||
| 41 | |||
| 42 | int wcn36xx_pmc_exit_bmps_state(struct wcn36xx *wcn, | ||
| 43 | struct ieee80211_vif *vif) | ||
| 44 | { | ||
| 45 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
| 46 | |||
| 47 | if (WCN36XX_BMPS != vif_priv->pw_state) { | ||
| 48 | wcn36xx_err("Not in BMPS mode, no need to exit from BMPS mode!\n"); | ||
| 49 | return -EINVAL; | ||
| 50 | } | ||
| 51 | wcn36xx_smd_exit_bmps(wcn, vif); | ||
| 52 | vif_priv->pw_state = WCN36XX_FULL_POWER; | ||
| 53 | return 0; | ||
| 54 | } | ||
| 55 | |||
| 56 | int wcn36xx_enable_keep_alive_null_packet(struct wcn36xx *wcn, | ||
| 57 | struct ieee80211_vif *vif) | ||
| 58 | { | ||
| 59 | wcn36xx_dbg(WCN36XX_DBG_PMC, "%s\n", __func__); | ||
| 60 | return wcn36xx_smd_keep_alive_req(wcn, vif, | ||
| 61 | WCN36XX_HAL_KEEP_ALIVE_NULL_PKT); | ||
| 62 | } | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/pmc.h b/drivers/net/wireless/ath/wcn36xx/pmc.h new file mode 100644 index 000000000000..f72ed68b5a07 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/pmc.h | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef _WCN36XX_PMC_H_ | ||
| 18 | #define _WCN36XX_PMC_H_ | ||
| 19 | |||
| 20 | struct wcn36xx; | ||
| 21 | |||
| 22 | enum wcn36xx_power_state { | ||
| 23 | WCN36XX_FULL_POWER, | ||
| 24 | WCN36XX_BMPS | ||
| 25 | }; | ||
| 26 | |||
| 27 | int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn, | ||
| 28 | struct ieee80211_vif *vif); | ||
| 29 | int wcn36xx_pmc_exit_bmps_state(struct wcn36xx *wcn, | ||
| 30 | struct ieee80211_vif *vif); | ||
| 31 | int wcn36xx_enable_keep_alive_null_packet(struct wcn36xx *wcn, | ||
| 32 | struct ieee80211_vif *vif); | ||
| 33 | #endif /* _WCN36XX_PMC_H_ */ | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c new file mode 100644 index 000000000000..f8c3a10510c2 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/smd.c | |||
| @@ -0,0 +1,2126 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 18 | |||
| 19 | #include <linux/etherdevice.h> | ||
| 20 | #include <linux/firmware.h> | ||
| 21 | #include <linux/bitops.h> | ||
| 22 | #include "smd.h" | ||
| 23 | |||
| 24 | static int put_cfg_tlv_u32(struct wcn36xx *wcn, size_t *len, u32 id, u32 value) | ||
| 25 | { | ||
| 26 | struct wcn36xx_hal_cfg *entry; | ||
| 27 | u32 *val; | ||
| 28 | |||
| 29 | if (*len + sizeof(*entry) + sizeof(u32) >= WCN36XX_HAL_BUF_SIZE) { | ||
| 30 | wcn36xx_err("Not enough room for TLV entry\n"); | ||
| 31 | return -ENOMEM; | ||
| 32 | } | ||
| 33 | |||
| 34 | entry = (struct wcn36xx_hal_cfg *) (wcn->hal_buf + *len); | ||
| 35 | entry->id = id; | ||
| 36 | entry->len = sizeof(u32); | ||
| 37 | entry->pad_bytes = 0; | ||
| 38 | entry->reserve = 0; | ||
| 39 | |||
| 40 | val = (u32 *) (entry + 1); | ||
| 41 | *val = value; | ||
| 42 | |||
| 43 | *len += sizeof(*entry) + sizeof(u32); | ||
| 44 | |||
| 45 | return 0; | ||
| 46 | } | ||
| 47 | |||
| 48 | static void wcn36xx_smd_set_bss_nw_type(struct wcn36xx *wcn, | ||
| 49 | struct ieee80211_sta *sta, | ||
| 50 | struct wcn36xx_hal_config_bss_params *bss_params) | ||
| 51 | { | ||
| 52 | if (IEEE80211_BAND_5GHZ == WCN36XX_BAND(wcn)) | ||
| 53 | bss_params->nw_type = WCN36XX_HAL_11A_NW_TYPE; | ||
| 54 | else if (sta && sta->ht_cap.ht_supported) | ||
| 55 | bss_params->nw_type = WCN36XX_HAL_11N_NW_TYPE; | ||
| 56 | else if (sta && (sta->supp_rates[IEEE80211_BAND_2GHZ] & 0x7f)) | ||
| 57 | bss_params->nw_type = WCN36XX_HAL_11G_NW_TYPE; | ||
| 58 | else | ||
| 59 | bss_params->nw_type = WCN36XX_HAL_11B_NW_TYPE; | ||
| 60 | } | ||
| 61 | |||
| 62 | static inline u8 is_cap_supported(unsigned long caps, unsigned long flag) | ||
| 63 | { | ||
| 64 | return caps & flag ? 1 : 0; | ||
| 65 | } | ||
| 66 | static void wcn36xx_smd_set_bss_ht_params(struct ieee80211_vif *vif, | ||
| 67 | struct ieee80211_sta *sta, | ||
| 68 | struct wcn36xx_hal_config_bss_params *bss_params) | ||
| 69 | { | ||
| 70 | if (sta && sta->ht_cap.ht_supported) { | ||
| 71 | unsigned long caps = sta->ht_cap.cap; | ||
| 72 | bss_params->ht = sta->ht_cap.ht_supported; | ||
| 73 | bss_params->tx_channel_width_set = is_cap_supported(caps, | ||
| 74 | IEEE80211_HT_CAP_SUP_WIDTH_20_40); | ||
| 75 | bss_params->lsig_tx_op_protection_full_support = | ||
| 76 | is_cap_supported(caps, | ||
| 77 | IEEE80211_HT_CAP_LSIG_TXOP_PROT); | ||
| 78 | |||
| 79 | bss_params->ht_oper_mode = vif->bss_conf.ht_operation_mode; | ||
| 80 | bss_params->lln_non_gf_coexist = | ||
| 81 | !!(vif->bss_conf.ht_operation_mode & | ||
| 82 | IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); | ||
| 83 | /* IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT */ | ||
| 84 | bss_params->dual_cts_protection = 0; | ||
| 85 | /* IEEE80211_HT_OP_MODE_PROTECTION_20MHZ */ | ||
| 86 | bss_params->ht20_coexist = 0; | ||
| 87 | } | ||
| 88 | } | ||
| 89 | |||
| 90 | static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta *sta, | ||
| 91 | struct wcn36xx_hal_config_sta_params *sta_params) | ||
| 92 | { | ||
| 93 | if (sta->ht_cap.ht_supported) { | ||
| 94 | unsigned long caps = sta->ht_cap.cap; | ||
| 95 | sta_params->ht_capable = sta->ht_cap.ht_supported; | ||
| 96 | sta_params->tx_channel_width_set = is_cap_supported(caps, | ||
| 97 | IEEE80211_HT_CAP_SUP_WIDTH_20_40); | ||
| 98 | sta_params->lsig_txop_protection = is_cap_supported(caps, | ||
| 99 | IEEE80211_HT_CAP_LSIG_TXOP_PROT); | ||
| 100 | |||
| 101 | sta_params->max_ampdu_size = sta->ht_cap.ampdu_factor; | ||
| 102 | sta_params->max_ampdu_density = sta->ht_cap.ampdu_density; | ||
| 103 | sta_params->max_amsdu_size = is_cap_supported(caps, | ||
| 104 | IEEE80211_HT_CAP_MAX_AMSDU); | ||
| 105 | sta_params->sgi_20Mhz = is_cap_supported(caps, | ||
| 106 | IEEE80211_HT_CAP_SGI_20); | ||
| 107 | sta_params->sgi_40mhz = is_cap_supported(caps, | ||
| 108 | IEEE80211_HT_CAP_SGI_40); | ||
| 109 | sta_params->green_field_capable = is_cap_supported(caps, | ||
| 110 | IEEE80211_HT_CAP_GRN_FLD); | ||
| 111 | sta_params->delayed_ba_support = is_cap_supported(caps, | ||
| 112 | IEEE80211_HT_CAP_DELAY_BA); | ||
| 113 | sta_params->dsss_cck_mode_40mhz = is_cap_supported(caps, | ||
| 114 | IEEE80211_HT_CAP_DSSSCCK40); | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, | ||
| 119 | struct ieee80211_vif *vif, | ||
| 120 | struct ieee80211_sta *sta, | ||
| 121 | struct wcn36xx_hal_config_sta_params *sta_params) | ||
| 122 | { | ||
| 123 | struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; | ||
| 124 | struct wcn36xx_sta *priv_sta = NULL; | ||
| 125 | if (vif->type == NL80211_IFTYPE_ADHOC || | ||
| 126 | vif->type == NL80211_IFTYPE_AP || | ||
| 127 | vif->type == NL80211_IFTYPE_MESH_POINT) { | ||
| 128 | sta_params->type = 1; | ||
| 129 | sta_params->sta_index = 0xFF; | ||
| 130 | } else { | ||
| 131 | sta_params->type = 0; | ||
| 132 | sta_params->sta_index = 1; | ||
| 133 | } | ||
| 134 | |||
| 135 | sta_params->listen_interval = WCN36XX_LISTEN_INTERVAL(wcn); | ||
| 136 | |||
| 137 | /* | ||
| 138 | * In STA mode ieee80211_sta contains bssid and ieee80211_vif | ||
| 139 | * contains our mac address. In AP mode we are bssid so vif | ||
| 140 | * contains bssid and ieee80211_sta contains mac. | ||
| 141 | */ | ||
| 142 | if (NL80211_IFTYPE_STATION == vif->type) | ||
| 143 | memcpy(&sta_params->mac, vif->addr, ETH_ALEN); | ||
| 144 | else | ||
| 145 | memcpy(&sta_params->bssid, vif->addr, ETH_ALEN); | ||
| 146 | |||
| 147 | sta_params->encrypt_type = priv_vif->encrypt_type; | ||
| 148 | sta_params->short_preamble_supported = | ||
| 149 | !(WCN36XX_FLAGS(wcn) & | ||
| 150 | IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE); | ||
| 151 | |||
| 152 | sta_params->rifs_mode = 0; | ||
| 153 | sta_params->rmf = 0; | ||
| 154 | sta_params->action = 0; | ||
| 155 | sta_params->uapsd = 0; | ||
| 156 | sta_params->mimo_ps = WCN36XX_HAL_HT_MIMO_PS_STATIC; | ||
| 157 | sta_params->max_ampdu_duration = 0; | ||
| 158 | sta_params->bssid_index = priv_vif->bss_index; | ||
| 159 | sta_params->p2p = 0; | ||
| 160 | |||
| 161 | if (sta) { | ||
| 162 | priv_sta = (struct wcn36xx_sta *)sta->drv_priv; | ||
| 163 | if (NL80211_IFTYPE_STATION == vif->type) | ||
| 164 | memcpy(&sta_params->bssid, sta->addr, ETH_ALEN); | ||
| 165 | else | ||
| 166 | memcpy(&sta_params->mac, sta->addr, ETH_ALEN); | ||
| 167 | sta_params->wmm_enabled = sta->wme; | ||
| 168 | sta_params->max_sp_len = sta->max_sp; | ||
| 169 | sta_params->aid = priv_sta->aid; | ||
| 170 | wcn36xx_smd_set_sta_ht_params(sta, sta_params); | ||
| 171 | memcpy(&sta_params->supported_rates, &priv_sta->supported_rates, | ||
| 172 | sizeof(priv_sta->supported_rates)); | ||
| 173 | } else { | ||
| 174 | wcn36xx_set_default_rates(&sta_params->supported_rates); | ||
| 175 | } | ||
| 176 | } | ||
| 177 | |||
| 178 | static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len) | ||
| 179 | { | ||
| 180 | int ret = 0; | ||
| 181 | wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "HAL >>> ", wcn->hal_buf, len); | ||
| 182 | |||
| 183 | init_completion(&wcn->hal_rsp_compl); | ||
| 184 | ret = wcn->ctrl_ops->tx(wcn->hal_buf, len); | ||
| 185 | if (ret) { | ||
| 186 | wcn36xx_err("HAL TX failed\n"); | ||
| 187 | goto out; | ||
| 188 | } | ||
| 189 | if (wait_for_completion_timeout(&wcn->hal_rsp_compl, | ||
| 190 | msecs_to_jiffies(HAL_MSG_TIMEOUT)) <= 0) { | ||
| 191 | wcn36xx_err("Timeout while waiting SMD response\n"); | ||
| 192 | ret = -ETIME; | ||
| 193 | goto out; | ||
| 194 | } | ||
| 195 | out: | ||
| 196 | return ret; | ||
| 197 | } | ||
| 198 | |||
| 199 | #define INIT_HAL_MSG(msg_body, type) \ | ||
| 200 | do { \ | ||
| 201 | memset(&msg_body, 0, sizeof(msg_body)); \ | ||
| 202 | msg_body.header.msg_type = type; \ | ||
| 203 | msg_body.header.msg_version = WCN36XX_HAL_MSG_VERSION0; \ | ||
| 204 | msg_body.header.len = sizeof(msg_body); \ | ||
| 205 | } while (0) \ | ||
| 206 | |||
| 207 | #define PREPARE_HAL_BUF(send_buf, msg_body) \ | ||
| 208 | do { \ | ||
| 209 | memset(send_buf, 0, msg_body.header.len); \ | ||
| 210 | memcpy(send_buf, &msg_body, sizeof(msg_body)); \ | ||
| 211 | } while (0) \ | ||
| 212 | |||
| 213 | static int wcn36xx_smd_rsp_status_check(void *buf, size_t len) | ||
| 214 | { | ||
| 215 | struct wcn36xx_fw_msg_status_rsp *rsp; | ||
| 216 | |||
| 217 | if (len < sizeof(struct wcn36xx_hal_msg_header) + | ||
| 218 | sizeof(struct wcn36xx_fw_msg_status_rsp)) | ||
| 219 | return -EIO; | ||
| 220 | |||
| 221 | rsp = (struct wcn36xx_fw_msg_status_rsp *) | ||
| 222 | (buf + sizeof(struct wcn36xx_hal_msg_header)); | ||
| 223 | |||
| 224 | if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status) | ||
| 225 | return rsp->status; | ||
| 226 | |||
| 227 | return 0; | ||
| 228 | } | ||
| 229 | |||
| 230 | int wcn36xx_smd_load_nv(struct wcn36xx *wcn) | ||
| 231 | { | ||
| 232 | const struct firmware *nv; | ||
| 233 | struct nv_data *nv_d; | ||
| 234 | struct wcn36xx_hal_nv_img_download_req_msg msg_body; | ||
| 235 | int fw_bytes_left; | ||
| 236 | int ret; | ||
| 237 | u16 fm_offset = 0; | ||
| 238 | |||
| 239 | ret = request_firmware(&nv, WLAN_NV_FILE, wcn->dev); | ||
| 240 | if (ret) { | ||
| 241 | wcn36xx_err("Failed to load nv file %s: %d\n", | ||
| 242 | WLAN_NV_FILE, ret); | ||
| 243 | goto out_free_nv; | ||
| 244 | } | ||
| 245 | |||
| 246 | nv_d = (struct nv_data *)nv->data; | ||
| 247 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_DOWNLOAD_NV_REQ); | ||
| 248 | |||
| 249 | msg_body.header.len += WCN36XX_NV_FRAGMENT_SIZE; | ||
| 250 | |||
| 251 | msg_body.frag_number = 0; | ||
| 252 | /* hal_buf must be protected with mutex */ | ||
| 253 | mutex_lock(&wcn->hal_mutex); | ||
| 254 | |||
| 255 | do { | ||
| 256 | fw_bytes_left = nv->size - fm_offset - 4; | ||
| 257 | if (fw_bytes_left > WCN36XX_NV_FRAGMENT_SIZE) { | ||
| 258 | msg_body.last_fragment = 0; | ||
| 259 | msg_body.nv_img_buffer_size = WCN36XX_NV_FRAGMENT_SIZE; | ||
| 260 | } else { | ||
| 261 | msg_body.last_fragment = 1; | ||
| 262 | msg_body.nv_img_buffer_size = fw_bytes_left; | ||
| 263 | |||
| 264 | /* Do not forget update general message len */ | ||
| 265 | msg_body.header.len = sizeof(msg_body) + fw_bytes_left; | ||
| 266 | |||
| 267 | } | ||
| 268 | |||
| 269 | /* Add load NV request message header */ | ||
| 270 | memcpy(wcn->hal_buf, &msg_body, sizeof(msg_body)); | ||
| 271 | |||
| 272 | /* Add NV body itself */ | ||
| 273 | memcpy(wcn->hal_buf + sizeof(msg_body), | ||
| 274 | &nv_d->table + fm_offset, | ||
| 275 | msg_body.nv_img_buffer_size); | ||
| 276 | |||
| 277 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 278 | if (ret) | ||
| 279 | goto out_unlock; | ||
| 280 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, | ||
| 281 | wcn->hal_rsp_len); | ||
| 282 | if (ret) { | ||
| 283 | wcn36xx_err("hal_load_nv response failed err=%d\n", | ||
| 284 | ret); | ||
| 285 | goto out_unlock; | ||
| 286 | } | ||
| 287 | msg_body.frag_number++; | ||
| 288 | fm_offset += WCN36XX_NV_FRAGMENT_SIZE; | ||
| 289 | |||
| 290 | } while (msg_body.last_fragment != 1); | ||
| 291 | |||
| 292 | out_unlock: | ||
| 293 | mutex_unlock(&wcn->hal_mutex); | ||
| 294 | out_free_nv: | ||
| 295 | release_firmware(nv); | ||
| 296 | |||
| 297 | return ret; | ||
| 298 | } | ||
| 299 | |||
| 300 | static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len) | ||
| 301 | { | ||
| 302 | struct wcn36xx_hal_mac_start_rsp_msg *rsp; | ||
| 303 | |||
| 304 | if (len < sizeof(*rsp)) | ||
| 305 | return -EIO; | ||
| 306 | |||
| 307 | rsp = (struct wcn36xx_hal_mac_start_rsp_msg *)buf; | ||
| 308 | |||
| 309 | if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->start_rsp_params.status) | ||
| 310 | return -EIO; | ||
| 311 | |||
| 312 | memcpy(wcn->crm_version, rsp->start_rsp_params.crm_version, | ||
| 313 | WCN36XX_HAL_VERSION_LENGTH); | ||
| 314 | memcpy(wcn->wlan_version, rsp->start_rsp_params.wlan_version, | ||
| 315 | WCN36XX_HAL_VERSION_LENGTH); | ||
| 316 | |||
| 317 | /* null terminate the strings, just in case */ | ||
| 318 | wcn->crm_version[WCN36XX_HAL_VERSION_LENGTH] = '\0'; | ||
| 319 | wcn->wlan_version[WCN36XX_HAL_VERSION_LENGTH] = '\0'; | ||
| 320 | |||
| 321 | wcn->fw_revision = rsp->start_rsp_params.version.revision; | ||
| 322 | wcn->fw_version = rsp->start_rsp_params.version.version; | ||
| 323 | wcn->fw_minor = rsp->start_rsp_params.version.minor; | ||
| 324 | wcn->fw_major = rsp->start_rsp_params.version.major; | ||
| 325 | |||
| 326 | wcn36xx_info("firmware WLAN version '%s' and CRM version '%s'\n", | ||
| 327 | wcn->wlan_version, wcn->crm_version); | ||
| 328 | |||
| 329 | wcn36xx_info("firmware API %u.%u.%u.%u, %u stations, %u bssids\n", | ||
| 330 | wcn->fw_major, wcn->fw_minor, | ||
| 331 | wcn->fw_version, wcn->fw_revision, | ||
| 332 | rsp->start_rsp_params.stations, | ||
| 333 | rsp->start_rsp_params.bssids); | ||
| 334 | |||
| 335 | return 0; | ||
| 336 | } | ||
| 337 | |||
| 338 | int wcn36xx_smd_start(struct wcn36xx *wcn) | ||
| 339 | { | ||
| 340 | struct wcn36xx_hal_mac_start_req_msg msg_body; | ||
| 341 | int ret = 0; | ||
| 342 | |||
| 343 | mutex_lock(&wcn->hal_mutex); | ||
| 344 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_REQ); | ||
| 345 | |||
| 346 | msg_body.params.type = DRIVER_TYPE_PRODUCTION; | ||
| 347 | msg_body.params.len = 0; | ||
| 348 | |||
| 349 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 350 | |||
| 351 | wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start type %d\n", | ||
| 352 | msg_body.params.type); | ||
| 353 | |||
| 354 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 355 | if (ret) { | ||
| 356 | wcn36xx_err("Sending hal_start failed\n"); | ||
| 357 | goto out; | ||
| 358 | } | ||
| 359 | |||
| 360 | ret = wcn36xx_smd_start_rsp(wcn, wcn->hal_buf, wcn->hal_rsp_len); | ||
| 361 | if (ret) { | ||
| 362 | wcn36xx_err("hal_start response failed err=%d\n", ret); | ||
| 363 | goto out; | ||
| 364 | } | ||
| 365 | |||
| 366 | out: | ||
| 367 | mutex_unlock(&wcn->hal_mutex); | ||
| 368 | return ret; | ||
| 369 | } | ||
| 370 | |||
| 371 | int wcn36xx_smd_stop(struct wcn36xx *wcn) | ||
| 372 | { | ||
| 373 | struct wcn36xx_hal_mac_stop_req_msg msg_body; | ||
| 374 | int ret = 0; | ||
| 375 | |||
| 376 | mutex_lock(&wcn->hal_mutex); | ||
| 377 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_STOP_REQ); | ||
| 378 | |||
| 379 | msg_body.stop_req_params.reason = HAL_STOP_TYPE_RF_KILL; | ||
| 380 | |||
| 381 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 382 | |||
| 383 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 384 | if (ret) { | ||
| 385 | wcn36xx_err("Sending hal_stop failed\n"); | ||
| 386 | goto out; | ||
| 387 | } | ||
| 388 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 389 | if (ret) { | ||
| 390 | wcn36xx_err("hal_stop response failed err=%d\n", ret); | ||
| 391 | goto out; | ||
| 392 | } | ||
| 393 | out: | ||
| 394 | mutex_unlock(&wcn->hal_mutex); | ||
| 395 | return ret; | ||
| 396 | } | ||
| 397 | |||
| 398 | int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode) | ||
| 399 | { | ||
| 400 | struct wcn36xx_hal_init_scan_req_msg msg_body; | ||
| 401 | int ret = 0; | ||
| 402 | |||
| 403 | mutex_lock(&wcn->hal_mutex); | ||
| 404 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_INIT_SCAN_REQ); | ||
| 405 | |||
| 406 | msg_body.mode = mode; | ||
| 407 | |||
| 408 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 409 | |||
| 410 | wcn36xx_dbg(WCN36XX_DBG_HAL, "hal init scan mode %d\n", msg_body.mode); | ||
| 411 | |||
| 412 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 413 | if (ret) { | ||
| 414 | wcn36xx_err("Sending hal_init_scan failed\n"); | ||
| 415 | goto out; | ||
| 416 | } | ||
| 417 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 418 | if (ret) { | ||
| 419 | wcn36xx_err("hal_init_scan response failed err=%d\n", ret); | ||
| 420 | goto out; | ||
| 421 | } | ||
| 422 | out: | ||
| 423 | mutex_unlock(&wcn->hal_mutex); | ||
| 424 | return ret; | ||
| 425 | } | ||
| 426 | |||
| 427 | int wcn36xx_smd_start_scan(struct wcn36xx *wcn) | ||
| 428 | { | ||
| 429 | struct wcn36xx_hal_start_scan_req_msg msg_body; | ||
| 430 | int ret = 0; | ||
| 431 | |||
| 432 | mutex_lock(&wcn->hal_mutex); | ||
| 433 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_SCAN_REQ); | ||
| 434 | |||
| 435 | msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn); | ||
| 436 | |||
| 437 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 438 | |||
| 439 | wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start scan channel %d\n", | ||
| 440 | msg_body.scan_channel); | ||
| 441 | |||
| 442 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 443 | if (ret) { | ||
| 444 | wcn36xx_err("Sending hal_start_scan failed\n"); | ||
| 445 | goto out; | ||
| 446 | } | ||
| 447 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 448 | if (ret) { | ||
| 449 | wcn36xx_err("hal_start_scan response failed err=%d\n", ret); | ||
| 450 | goto out; | ||
| 451 | } | ||
| 452 | out: | ||
| 453 | mutex_unlock(&wcn->hal_mutex); | ||
| 454 | return ret; | ||
| 455 | } | ||
| 456 | |||
| 457 | int wcn36xx_smd_end_scan(struct wcn36xx *wcn) | ||
| 458 | { | ||
| 459 | struct wcn36xx_hal_end_scan_req_msg msg_body; | ||
| 460 | int ret = 0; | ||
| 461 | |||
| 462 | mutex_lock(&wcn->hal_mutex); | ||
| 463 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_END_SCAN_REQ); | ||
| 464 | |||
| 465 | msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn); | ||
| 466 | |||
| 467 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 468 | |||
| 469 | wcn36xx_dbg(WCN36XX_DBG_HAL, "hal end scan channel %d\n", | ||
| 470 | msg_body.scan_channel); | ||
| 471 | |||
| 472 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 473 | if (ret) { | ||
| 474 | wcn36xx_err("Sending hal_end_scan failed\n"); | ||
| 475 | goto out; | ||
| 476 | } | ||
| 477 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 478 | if (ret) { | ||
| 479 | wcn36xx_err("hal_end_scan response failed err=%d\n", ret); | ||
| 480 | goto out; | ||
| 481 | } | ||
| 482 | out: | ||
| 483 | mutex_unlock(&wcn->hal_mutex); | ||
| 484 | return ret; | ||
| 485 | } | ||
| 486 | |||
| 487 | int wcn36xx_smd_finish_scan(struct wcn36xx *wcn, | ||
| 488 | enum wcn36xx_hal_sys_mode mode) | ||
| 489 | { | ||
| 490 | struct wcn36xx_hal_finish_scan_req_msg msg_body; | ||
| 491 | int ret = 0; | ||
| 492 | |||
| 493 | mutex_lock(&wcn->hal_mutex); | ||
| 494 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_FINISH_SCAN_REQ); | ||
| 495 | |||
| 496 | msg_body.mode = mode; | ||
| 497 | |||
| 498 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 499 | |||
| 500 | wcn36xx_dbg(WCN36XX_DBG_HAL, "hal finish scan mode %d\n", | ||
| 501 | msg_body.mode); | ||
| 502 | |||
| 503 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 504 | if (ret) { | ||
| 505 | wcn36xx_err("Sending hal_finish_scan failed\n"); | ||
| 506 | goto out; | ||
| 507 | } | ||
| 508 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 509 | if (ret) { | ||
| 510 | wcn36xx_err("hal_finish_scan response failed err=%d\n", ret); | ||
| 511 | goto out; | ||
| 512 | } | ||
| 513 | out: | ||
| 514 | mutex_unlock(&wcn->hal_mutex); | ||
| 515 | return ret; | ||
| 516 | } | ||
| 517 | |||
| 518 | static int wcn36xx_smd_switch_channel_rsp(void *buf, size_t len) | ||
| 519 | { | ||
| 520 | struct wcn36xx_hal_switch_channel_rsp_msg *rsp; | ||
| 521 | int ret = 0; | ||
| 522 | |||
| 523 | ret = wcn36xx_smd_rsp_status_check(buf, len); | ||
| 524 | if (ret) | ||
| 525 | return ret; | ||
| 526 | rsp = (struct wcn36xx_hal_switch_channel_rsp_msg *)buf; | ||
| 527 | wcn36xx_dbg(WCN36XX_DBG_HAL, "channel switched to: %d, status: %d\n", | ||
| 528 | rsp->channel_number, rsp->status); | ||
| 529 | return ret; | ||
| 530 | } | ||
| 531 | |||
| 532 | int wcn36xx_smd_switch_channel(struct wcn36xx *wcn, | ||
| 533 | struct ieee80211_vif *vif, int ch) | ||
| 534 | { | ||
| 535 | struct wcn36xx_hal_switch_channel_req_msg msg_body; | ||
| 536 | int ret = 0; | ||
| 537 | |||
| 538 | mutex_lock(&wcn->hal_mutex); | ||
| 539 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_CH_SWITCH_REQ); | ||
| 540 | |||
| 541 | msg_body.channel_number = (u8)ch; | ||
| 542 | msg_body.tx_mgmt_power = 0xbf; | ||
| 543 | msg_body.max_tx_power = 0xbf; | ||
| 544 | memcpy(msg_body.self_sta_mac_addr, vif->addr, ETH_ALEN); | ||
| 545 | |||
| 546 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 547 | |||
| 548 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 549 | if (ret) { | ||
| 550 | wcn36xx_err("Sending hal_switch_channel failed\n"); | ||
| 551 | goto out; | ||
| 552 | } | ||
| 553 | ret = wcn36xx_smd_switch_channel_rsp(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 554 | if (ret) { | ||
| 555 | wcn36xx_err("hal_switch_channel response failed err=%d\n", ret); | ||
| 556 | goto out; | ||
| 557 | } | ||
| 558 | out: | ||
| 559 | mutex_unlock(&wcn->hal_mutex); | ||
| 560 | return ret; | ||
| 561 | } | ||
| 562 | |||
| 563 | static int wcn36xx_smd_update_scan_params_rsp(void *buf, size_t len) | ||
| 564 | { | ||
| 565 | struct wcn36xx_hal_update_scan_params_resp *rsp; | ||
| 566 | |||
| 567 | rsp = (struct wcn36xx_hal_update_scan_params_resp *)buf; | ||
| 568 | |||
| 569 | /* Remove the PNO version bit */ | ||
| 570 | rsp->status &= (~(WCN36XX_FW_MSG_PNO_VERSION_MASK)); | ||
| 571 | |||
| 572 | if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status) { | ||
| 573 | wcn36xx_warn("error response from update scan\n"); | ||
| 574 | return rsp->status; | ||
| 575 | } | ||
| 576 | |||
| 577 | return 0; | ||
| 578 | } | ||
| 579 | |||
| 580 | int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn) | ||
| 581 | { | ||
| 582 | struct wcn36xx_hal_update_scan_params_req msg_body; | ||
| 583 | int ret = 0; | ||
| 584 | |||
| 585 | mutex_lock(&wcn->hal_mutex); | ||
| 586 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ); | ||
| 587 | |||
| 588 | msg_body.dot11d_enabled = 0; | ||
| 589 | msg_body.dot11d_resolved = 0; | ||
| 590 | msg_body.channel_count = 26; | ||
| 591 | msg_body.active_min_ch_time = 60; | ||
| 592 | msg_body.active_max_ch_time = 120; | ||
| 593 | msg_body.passive_min_ch_time = 60; | ||
| 594 | msg_body.passive_max_ch_time = 110; | ||
| 595 | msg_body.state = 0; | ||
| 596 | |||
| 597 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 598 | |||
| 599 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
| 600 | "hal update scan params channel_count %d\n", | ||
| 601 | msg_body.channel_count); | ||
| 602 | |||
| 603 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 604 | if (ret) { | ||
| 605 | wcn36xx_err("Sending hal_update_scan_params failed\n"); | ||
| 606 | goto out; | ||
| 607 | } | ||
| 608 | ret = wcn36xx_smd_update_scan_params_rsp(wcn->hal_buf, | ||
| 609 | wcn->hal_rsp_len); | ||
| 610 | if (ret) { | ||
| 611 | wcn36xx_err("hal_update_scan_params response failed err=%d\n", | ||
| 612 | ret); | ||
| 613 | goto out; | ||
| 614 | } | ||
| 615 | out: | ||
| 616 | mutex_unlock(&wcn->hal_mutex); | ||
| 617 | return ret; | ||
| 618 | } | ||
| 619 | |||
| 620 | static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn, | ||
| 621 | struct ieee80211_vif *vif, | ||
| 622 | void *buf, | ||
| 623 | size_t len) | ||
| 624 | { | ||
| 625 | struct wcn36xx_hal_add_sta_self_rsp_msg *rsp; | ||
| 626 | struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; | ||
| 627 | |||
| 628 | if (len < sizeof(*rsp)) | ||
| 629 | return -EINVAL; | ||
| 630 | |||
| 631 | rsp = (struct wcn36xx_hal_add_sta_self_rsp_msg *)buf; | ||
| 632 | |||
| 633 | if (rsp->status != WCN36XX_FW_MSG_RESULT_SUCCESS) { | ||
| 634 | wcn36xx_warn("hal add sta self failure: %d\n", | ||
| 635 | rsp->status); | ||
| 636 | return rsp->status; | ||
| 637 | } | ||
| 638 | |||
| 639 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
| 640 | "hal add sta self status %d self_sta_index %d dpu_index %d\n", | ||
| 641 | rsp->status, rsp->self_sta_index, rsp->dpu_index); | ||
| 642 | |||
| 643 | priv_vif->self_sta_index = rsp->self_sta_index; | ||
| 644 | priv_vif->self_dpu_desc_index = rsp->dpu_index; | ||
| 645 | |||
| 646 | return 0; | ||
| 647 | } | ||
| 648 | |||
| 649 | int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif) | ||
| 650 | { | ||
| 651 | struct wcn36xx_hal_add_sta_self_req msg_body; | ||
| 652 | int ret = 0; | ||
| 653 | |||
| 654 | mutex_lock(&wcn->hal_mutex); | ||
| 655 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_STA_SELF_REQ); | ||
| 656 | |||
| 657 | memcpy(&msg_body.self_addr, vif->addr, ETH_ALEN); | ||
| 658 | |||
| 659 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 660 | |||
| 661 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
| 662 | "hal add sta self self_addr %pM status %d\n", | ||
| 663 | msg_body.self_addr, msg_body.status); | ||
| 664 | |||
| 665 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 666 | if (ret) { | ||
| 667 | wcn36xx_err("Sending hal_add_sta_self failed\n"); | ||
| 668 | goto out; | ||
| 669 | } | ||
| 670 | ret = wcn36xx_smd_add_sta_self_rsp(wcn, | ||
| 671 | vif, | ||
| 672 | wcn->hal_buf, | ||
| 673 | wcn->hal_rsp_len); | ||
| 674 | if (ret) { | ||
| 675 | wcn36xx_err("hal_add_sta_self response failed err=%d\n", ret); | ||
| 676 | goto out; | ||
| 677 | } | ||
| 678 | out: | ||
| 679 | mutex_unlock(&wcn->hal_mutex); | ||
| 680 | return ret; | ||
| 681 | } | ||
| 682 | |||
| 683 | int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr) | ||
| 684 | { | ||
| 685 | struct wcn36xx_hal_del_sta_self_req_msg msg_body; | ||
| 686 | int ret = 0; | ||
| 687 | |||
| 688 | mutex_lock(&wcn->hal_mutex); | ||
| 689 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_STA_SELF_REQ); | ||
| 690 | |||
| 691 | memcpy(&msg_body.self_addr, addr, ETH_ALEN); | ||
| 692 | |||
| 693 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 694 | |||
| 695 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 696 | if (ret) { | ||
| 697 | wcn36xx_err("Sending hal_delete_sta_self failed\n"); | ||
| 698 | goto out; | ||
| 699 | } | ||
| 700 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 701 | if (ret) { | ||
| 702 | wcn36xx_err("hal_delete_sta_self response failed err=%d\n", | ||
| 703 | ret); | ||
| 704 | goto out; | ||
| 705 | } | ||
| 706 | out: | ||
| 707 | mutex_unlock(&wcn->hal_mutex); | ||
| 708 | return ret; | ||
| 709 | } | ||
| 710 | |||
| 711 | int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index) | ||
| 712 | { | ||
| 713 | struct wcn36xx_hal_delete_sta_req_msg msg_body; | ||
| 714 | int ret = 0; | ||
| 715 | |||
| 716 | mutex_lock(&wcn->hal_mutex); | ||
| 717 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_STA_REQ); | ||
| 718 | |||
| 719 | msg_body.sta_index = sta_index; | ||
| 720 | |||
| 721 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 722 | |||
| 723 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
| 724 | "hal delete sta sta_index %d\n", | ||
| 725 | msg_body.sta_index); | ||
| 726 | |||
| 727 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 728 | if (ret) { | ||
| 729 | wcn36xx_err("Sending hal_delete_sta failed\n"); | ||
| 730 | goto out; | ||
| 731 | } | ||
| 732 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 733 | if (ret) { | ||
| 734 | wcn36xx_err("hal_delete_sta response failed err=%d\n", ret); | ||
| 735 | goto out; | ||
| 736 | } | ||
| 737 | out: | ||
| 738 | mutex_unlock(&wcn->hal_mutex); | ||
| 739 | return ret; | ||
| 740 | } | ||
| 741 | |||
| 742 | static int wcn36xx_smd_join_rsp(void *buf, size_t len) | ||
| 743 | { | ||
| 744 | struct wcn36xx_hal_join_rsp_msg *rsp; | ||
| 745 | |||
| 746 | if (wcn36xx_smd_rsp_status_check(buf, len)) | ||
| 747 | return -EIO; | ||
| 748 | |||
| 749 | rsp = (struct wcn36xx_hal_join_rsp_msg *)buf; | ||
| 750 | |||
| 751 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
| 752 | "hal rsp join status %d tx_mgmt_power %d\n", | ||
| 753 | rsp->status, rsp->tx_mgmt_power); | ||
| 754 | |||
| 755 | return 0; | ||
| 756 | } | ||
| 757 | |||
| 758 | int wcn36xx_smd_join(struct wcn36xx *wcn, const u8 *bssid, u8 *vif, u8 ch) | ||
| 759 | { | ||
| 760 | struct wcn36xx_hal_join_req_msg msg_body; | ||
| 761 | int ret = 0; | ||
| 762 | |||
| 763 | mutex_lock(&wcn->hal_mutex); | ||
| 764 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_JOIN_REQ); | ||
| 765 | |||
| 766 | memcpy(&msg_body.bssid, bssid, ETH_ALEN); | ||
| 767 | memcpy(&msg_body.self_sta_mac_addr, vif, ETH_ALEN); | ||
| 768 | msg_body.channel = ch; | ||
| 769 | |||
| 770 | if (conf_is_ht40_minus(&wcn->hw->conf)) | ||
| 771 | msg_body.secondary_channel_offset = | ||
| 772 | PHY_DOUBLE_CHANNEL_HIGH_PRIMARY; | ||
| 773 | else if (conf_is_ht40_plus(&wcn->hw->conf)) | ||
| 774 | msg_body.secondary_channel_offset = | ||
| 775 | PHY_DOUBLE_CHANNEL_LOW_PRIMARY; | ||
| 776 | else | ||
| 777 | msg_body.secondary_channel_offset = | ||
| 778 | PHY_SINGLE_CHANNEL_CENTERED; | ||
| 779 | |||
| 780 | msg_body.link_state = WCN36XX_HAL_LINK_PREASSOC_STATE; | ||
| 781 | |||
| 782 | msg_body.max_tx_power = 0xbf; | ||
| 783 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 784 | |||
| 785 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
| 786 | "hal join req bssid %pM self_sta_mac_addr %pM channel %d link_state %d\n", | ||
| 787 | msg_body.bssid, msg_body.self_sta_mac_addr, | ||
| 788 | msg_body.channel, msg_body.link_state); | ||
| 789 | |||
| 790 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 791 | if (ret) { | ||
| 792 | wcn36xx_err("Sending hal_join failed\n"); | ||
| 793 | goto out; | ||
| 794 | } | ||
| 795 | ret = wcn36xx_smd_join_rsp(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 796 | if (ret) { | ||
| 797 | wcn36xx_err("hal_join response failed err=%d\n", ret); | ||
| 798 | goto out; | ||
| 799 | } | ||
| 800 | out: | ||
| 801 | mutex_unlock(&wcn->hal_mutex); | ||
| 802 | return ret; | ||
| 803 | } | ||
| 804 | |||
| 805 | int wcn36xx_smd_set_link_st(struct wcn36xx *wcn, const u8 *bssid, | ||
| 806 | const u8 *sta_mac, | ||
| 807 | enum wcn36xx_hal_link_state state) | ||
| 808 | { | ||
| 809 | struct wcn36xx_hal_set_link_state_req_msg msg_body; | ||
| 810 | int ret = 0; | ||
| 811 | |||
| 812 | mutex_lock(&wcn->hal_mutex); | ||
| 813 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_LINK_ST_REQ); | ||
| 814 | |||
| 815 | memcpy(&msg_body.bssid, bssid, ETH_ALEN); | ||
| 816 | memcpy(&msg_body.self_mac_addr, sta_mac, ETH_ALEN); | ||
| 817 | msg_body.state = state; | ||
| 818 | |||
| 819 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 820 | |||
| 821 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
| 822 | "hal set link state bssid %pM self_mac_addr %pM state %d\n", | ||
| 823 | msg_body.bssid, msg_body.self_mac_addr, msg_body.state); | ||
| 824 | |||
| 825 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 826 | if (ret) { | ||
| 827 | wcn36xx_err("Sending hal_set_link_st failed\n"); | ||
| 828 | goto out; | ||
| 829 | } | ||
| 830 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 831 | if (ret) { | ||
| 832 | wcn36xx_err("hal_set_link_st response failed err=%d\n", ret); | ||
| 833 | goto out; | ||
| 834 | } | ||
| 835 | out: | ||
| 836 | mutex_unlock(&wcn->hal_mutex); | ||
| 837 | return ret; | ||
| 838 | } | ||
| 839 | |||
| 840 | static void wcn36xx_smd_convert_sta_to_v1(struct wcn36xx *wcn, | ||
| 841 | const struct wcn36xx_hal_config_sta_params *orig, | ||
| 842 | struct wcn36xx_hal_config_sta_params_v1 *v1) | ||
| 843 | { | ||
| 844 | /* convert orig to v1 format */ | ||
| 845 | memcpy(&v1->bssid, orig->bssid, ETH_ALEN); | ||
| 846 | memcpy(&v1->mac, orig->mac, ETH_ALEN); | ||
| 847 | v1->aid = orig->aid; | ||
| 848 | v1->type = orig->type; | ||
| 849 | v1->listen_interval = orig->listen_interval; | ||
| 850 | v1->ht_capable = orig->ht_capable; | ||
| 851 | |||
| 852 | v1->max_ampdu_size = orig->max_ampdu_size; | ||
| 853 | v1->max_ampdu_density = orig->max_ampdu_density; | ||
| 854 | v1->sgi_40mhz = orig->sgi_40mhz; | ||
| 855 | v1->sgi_20Mhz = orig->sgi_20Mhz; | ||
| 856 | |||
| 857 | memcpy(&v1->supported_rates, &orig->supported_rates, | ||
| 858 | sizeof(orig->supported_rates)); | ||
| 859 | v1->sta_index = orig->sta_index; | ||
| 860 | } | ||
| 861 | |||
| 862 | static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn, | ||
| 863 | struct ieee80211_sta *sta, | ||
| 864 | void *buf, | ||
| 865 | size_t len) | ||
| 866 | { | ||
| 867 | struct wcn36xx_hal_config_sta_rsp_msg *rsp; | ||
| 868 | struct config_sta_rsp_params *params; | ||
| 869 | struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; | ||
| 870 | |||
| 871 | if (len < sizeof(*rsp)) | ||
| 872 | return -EINVAL; | ||
| 873 | |||
| 874 | rsp = (struct wcn36xx_hal_config_sta_rsp_msg *)buf; | ||
| 875 | params = &rsp->params; | ||
| 876 | |||
| 877 | if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) { | ||
| 878 | wcn36xx_warn("hal config sta response failure: %d\n", | ||
| 879 | params->status); | ||
| 880 | return -EIO; | ||
| 881 | } | ||
| 882 | |||
| 883 | sta_priv->sta_index = params->sta_index; | ||
| 884 | sta_priv->dpu_desc_index = params->dpu_index; | ||
| 885 | |||
| 886 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
| 887 | "hal config sta rsp status %d sta_index %d bssid_index %d p2p %d\n", | ||
| 888 | params->status, params->sta_index, params->bssid_index, | ||
| 889 | params->p2p); | ||
| 890 | |||
| 891 | return 0; | ||
| 892 | } | ||
| 893 | |||
| 894 | static int wcn36xx_smd_config_sta_v1(struct wcn36xx *wcn, | ||
| 895 | const struct wcn36xx_hal_config_sta_req_msg *orig) | ||
| 896 | { | ||
| 897 | struct wcn36xx_hal_config_sta_req_msg_v1 msg_body; | ||
| 898 | struct wcn36xx_hal_config_sta_params_v1 *sta = &msg_body.sta_params; | ||
| 899 | |||
| 900 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_STA_REQ); | ||
| 901 | |||
| 902 | wcn36xx_smd_convert_sta_to_v1(wcn, &orig->sta_params, | ||
| 903 | &msg_body.sta_params); | ||
| 904 | |||
| 905 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 906 | |||
| 907 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
| 908 | "hal config sta v1 action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n", | ||
| 909 | sta->action, sta->sta_index, sta->bssid_index, | ||
| 910 | sta->bssid, sta->type, sta->mac, sta->aid); | ||
| 911 | |||
| 912 | return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 913 | } | ||
| 914 | |||
| 915 | int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif, | ||
| 916 | struct ieee80211_sta *sta) | ||
| 917 | { | ||
| 918 | struct wcn36xx_hal_config_sta_req_msg msg; | ||
| 919 | struct wcn36xx_hal_config_sta_params *sta_params; | ||
| 920 | int ret = 0; | ||
| 921 | |||
| 922 | mutex_lock(&wcn->hal_mutex); | ||
| 923 | INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_STA_REQ); | ||
| 924 | |||
| 925 | sta_params = &msg.sta_params; | ||
| 926 | |||
| 927 | wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params); | ||
| 928 | |||
| 929 | if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { | ||
| 930 | ret = wcn36xx_smd_config_sta_v1(wcn, &msg); | ||
| 931 | } else { | ||
| 932 | PREPARE_HAL_BUF(wcn->hal_buf, msg); | ||
| 933 | |||
| 934 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
| 935 | "hal config sta action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n", | ||
| 936 | sta_params->action, sta_params->sta_index, | ||
| 937 | sta_params->bssid_index, sta_params->bssid, | ||
| 938 | sta_params->type, sta_params->mac, sta_params->aid); | ||
| 939 | |||
| 940 | ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len); | ||
| 941 | } | ||
| 942 | if (ret) { | ||
| 943 | wcn36xx_err("Sending hal_config_sta failed\n"); | ||
| 944 | goto out; | ||
| 945 | } | ||
| 946 | ret = wcn36xx_smd_config_sta_rsp(wcn, | ||
| 947 | sta, | ||
| 948 | wcn->hal_buf, | ||
| 949 | wcn->hal_rsp_len); | ||
| 950 | if (ret) { | ||
| 951 | wcn36xx_err("hal_config_sta response failed err=%d\n", ret); | ||
| 952 | goto out; | ||
| 953 | } | ||
| 954 | out: | ||
| 955 | mutex_unlock(&wcn->hal_mutex); | ||
| 956 | return ret; | ||
| 957 | } | ||
| 958 | |||
| 959 | static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn, | ||
| 960 | const struct wcn36xx_hal_config_bss_req_msg *orig) | ||
| 961 | { | ||
| 962 | struct wcn36xx_hal_config_bss_req_msg_v1 msg_body; | ||
| 963 | struct wcn36xx_hal_config_bss_params_v1 *bss = &msg_body.bss_params; | ||
| 964 | struct wcn36xx_hal_config_sta_params_v1 *sta = &bss->sta; | ||
| 965 | |||
| 966 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_BSS_REQ); | ||
| 967 | |||
| 968 | /* convert orig to v1 */ | ||
| 969 | memcpy(&msg_body.bss_params.bssid, | ||
| 970 | &orig->bss_params.bssid, ETH_ALEN); | ||
| 971 | memcpy(&msg_body.bss_params.self_mac_addr, | ||
| 972 | &orig->bss_params.self_mac_addr, ETH_ALEN); | ||
| 973 | |||
| 974 | msg_body.bss_params.bss_type = orig->bss_params.bss_type; | ||
| 975 | msg_body.bss_params.oper_mode = orig->bss_params.oper_mode; | ||
| 976 | msg_body.bss_params.nw_type = orig->bss_params.nw_type; | ||
| 977 | |||
| 978 | msg_body.bss_params.short_slot_time_supported = | ||
| 979 | orig->bss_params.short_slot_time_supported; | ||
| 980 | msg_body.bss_params.lla_coexist = orig->bss_params.lla_coexist; | ||
| 981 | msg_body.bss_params.llb_coexist = orig->bss_params.llb_coexist; | ||
| 982 | msg_body.bss_params.llg_coexist = orig->bss_params.llg_coexist; | ||
| 983 | msg_body.bss_params.ht20_coexist = orig->bss_params.ht20_coexist; | ||
| 984 | msg_body.bss_params.lln_non_gf_coexist = | ||
| 985 | orig->bss_params.lln_non_gf_coexist; | ||
| 986 | |||
| 987 | msg_body.bss_params.lsig_tx_op_protection_full_support = | ||
| 988 | orig->bss_params.lsig_tx_op_protection_full_support; | ||
| 989 | msg_body.bss_params.rifs_mode = orig->bss_params.rifs_mode; | ||
| 990 | msg_body.bss_params.beacon_interval = orig->bss_params.beacon_interval; | ||
| 991 | msg_body.bss_params.dtim_period = orig->bss_params.dtim_period; | ||
| 992 | msg_body.bss_params.tx_channel_width_set = | ||
| 993 | orig->bss_params.tx_channel_width_set; | ||
| 994 | msg_body.bss_params.oper_channel = orig->bss_params.oper_channel; | ||
| 995 | msg_body.bss_params.ext_channel = orig->bss_params.ext_channel; | ||
| 996 | |||
| 997 | msg_body.bss_params.reserved = orig->bss_params.reserved; | ||
| 998 | |||
| 999 | memcpy(&msg_body.bss_params.ssid, | ||
| 1000 | &orig->bss_params.ssid, | ||
| 1001 | sizeof(orig->bss_params.ssid)); | ||
| 1002 | |||
| 1003 | msg_body.bss_params.action = orig->bss_params.action; | ||
| 1004 | msg_body.bss_params.rateset = orig->bss_params.rateset; | ||
| 1005 | msg_body.bss_params.ht = orig->bss_params.ht; | ||
| 1006 | msg_body.bss_params.obss_prot_enabled = | ||
| 1007 | orig->bss_params.obss_prot_enabled; | ||
| 1008 | msg_body.bss_params.rmf = orig->bss_params.rmf; | ||
| 1009 | msg_body.bss_params.ht_oper_mode = orig->bss_params.ht_oper_mode; | ||
| 1010 | msg_body.bss_params.dual_cts_protection = | ||
| 1011 | orig->bss_params.dual_cts_protection; | ||
| 1012 | |||
| 1013 | msg_body.bss_params.max_probe_resp_retry_limit = | ||
| 1014 | orig->bss_params.max_probe_resp_retry_limit; | ||
| 1015 | msg_body.bss_params.hidden_ssid = orig->bss_params.hidden_ssid; | ||
| 1016 | msg_body.bss_params.proxy_probe_resp = | ||
| 1017 | orig->bss_params.proxy_probe_resp; | ||
| 1018 | msg_body.bss_params.edca_params_valid = | ||
| 1019 | orig->bss_params.edca_params_valid; | ||
| 1020 | |||
| 1021 | memcpy(&msg_body.bss_params.acbe, | ||
| 1022 | &orig->bss_params.acbe, | ||
| 1023 | sizeof(orig->bss_params.acbe)); | ||
| 1024 | memcpy(&msg_body.bss_params.acbk, | ||
| 1025 | &orig->bss_params.acbk, | ||
| 1026 | sizeof(orig->bss_params.acbk)); | ||
| 1027 | memcpy(&msg_body.bss_params.acvi, | ||
| 1028 | &orig->bss_params.acvi, | ||
| 1029 | sizeof(orig->bss_params.acvi)); | ||
| 1030 | memcpy(&msg_body.bss_params.acvo, | ||
| 1031 | &orig->bss_params.acvo, | ||
| 1032 | sizeof(orig->bss_params.acvo)); | ||
| 1033 | |||
| 1034 | msg_body.bss_params.ext_set_sta_key_param_valid = | ||
| 1035 | orig->bss_params.ext_set_sta_key_param_valid; | ||
| 1036 | |||
| 1037 | memcpy(&msg_body.bss_params.ext_set_sta_key_param, | ||
| 1038 | &orig->bss_params.ext_set_sta_key_param, | ||
| 1039 | sizeof(orig->bss_params.acvo)); | ||
| 1040 | |||
| 1041 | msg_body.bss_params.wcn36xx_hal_persona = | ||
| 1042 | orig->bss_params.wcn36xx_hal_persona; | ||
| 1043 | msg_body.bss_params.spectrum_mgt_enable = | ||
| 1044 | orig->bss_params.spectrum_mgt_enable; | ||
| 1045 | msg_body.bss_params.tx_mgmt_power = orig->bss_params.tx_mgmt_power; | ||
| 1046 | msg_body.bss_params.max_tx_power = orig->bss_params.max_tx_power; | ||
| 1047 | |||
| 1048 | wcn36xx_smd_convert_sta_to_v1(wcn, &orig->bss_params.sta, | ||
| 1049 | &msg_body.bss_params.sta); | ||
| 1050 | |||
| 1051 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 1052 | |||
| 1053 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
| 1054 | "hal config bss v1 bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n", | ||
| 1055 | bss->bssid, bss->self_mac_addr, bss->bss_type, | ||
| 1056 | bss->oper_mode, bss->nw_type); | ||
| 1057 | |||
| 1058 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
| 1059 | "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n", | ||
| 1060 | sta->bssid, sta->action, sta->sta_index, | ||
| 1061 | sta->bssid_index, sta->aid, sta->type, sta->mac); | ||
| 1062 | |||
| 1063 | return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 1064 | } | ||
| 1065 | |||
| 1066 | |||
| 1067 | static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn, | ||
| 1068 | struct ieee80211_vif *vif, | ||
| 1069 | void *buf, | ||
| 1070 | size_t len) | ||
| 1071 | { | ||
| 1072 | struct wcn36xx_hal_config_bss_rsp_msg *rsp; | ||
| 1073 | struct wcn36xx_hal_config_bss_rsp_params *params; | ||
| 1074 | struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; | ||
| 1075 | |||
| 1076 | if (len < sizeof(*rsp)) | ||
| 1077 | return -EINVAL; | ||
| 1078 | |||
| 1079 | rsp = (struct wcn36xx_hal_config_bss_rsp_msg *)buf; | ||
| 1080 | params = &rsp->bss_rsp_params; | ||
| 1081 | |||
| 1082 | if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) { | ||
| 1083 | wcn36xx_warn("hal config bss response failure: %d\n", | ||
| 1084 | params->status); | ||
| 1085 | return -EIO; | ||
| 1086 | } | ||
| 1087 | |||
| 1088 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
| 1089 | "hal config bss rsp status %d bss_idx %d dpu_desc_index %d" | ||
| 1090 | " sta_idx %d self_idx %d bcast_idx %d mac %pM" | ||
| 1091 | " power %d ucast_dpu_signature %d\n", | ||
| 1092 | params->status, params->bss_index, params->dpu_desc_index, | ||
| 1093 | params->bss_sta_index, params->bss_self_sta_index, | ||
| 1094 | params->bss_bcast_sta_idx, params->mac, | ||
| 1095 | params->tx_mgmt_power, params->ucast_dpu_signature); | ||
| 1096 | |||
| 1097 | priv_vif->bss_index = params->bss_index; | ||
| 1098 | |||
| 1099 | if (priv_vif->sta) { | ||
| 1100 | priv_vif->sta->bss_sta_index = params->bss_sta_index; | ||
| 1101 | priv_vif->sta->bss_dpu_desc_index = params->dpu_desc_index; | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | priv_vif->ucast_dpu_signature = params->ucast_dpu_signature; | ||
| 1105 | |||
| 1106 | return 0; | ||
| 1107 | } | ||
| 1108 | |||
| 1109 | int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, | ||
| 1110 | struct ieee80211_sta *sta, const u8 *bssid, | ||
| 1111 | bool update) | ||
| 1112 | { | ||
| 1113 | struct wcn36xx_hal_config_bss_req_msg msg; | ||
| 1114 | struct wcn36xx_hal_config_bss_params *bss; | ||
| 1115 | struct wcn36xx_hal_config_sta_params *sta_params; | ||
| 1116 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
| 1117 | int ret = 0; | ||
| 1118 | |||
| 1119 | mutex_lock(&wcn->hal_mutex); | ||
| 1120 | INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_BSS_REQ); | ||
| 1121 | |||
| 1122 | bss = &msg.bss_params; | ||
| 1123 | sta_params = &bss->sta; | ||
| 1124 | |||
| 1125 | WARN_ON(is_zero_ether_addr(bssid)); | ||
| 1126 | |||
| 1127 | memcpy(&bss->bssid, bssid, ETH_ALEN); | ||
| 1128 | |||
| 1129 | memcpy(bss->self_mac_addr, vif->addr, ETH_ALEN); | ||
| 1130 | |||
| 1131 | if (vif->type == NL80211_IFTYPE_STATION) { | ||
| 1132 | bss->bss_type = WCN36XX_HAL_INFRASTRUCTURE_MODE; | ||
| 1133 | |||
| 1134 | /* STA */ | ||
| 1135 | bss->oper_mode = 1; | ||
| 1136 | bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_MODE; | ||
| 1137 | } else if (vif->type == NL80211_IFTYPE_AP) { | ||
| 1138 | bss->bss_type = WCN36XX_HAL_INFRA_AP_MODE; | ||
| 1139 | |||
| 1140 | /* AP */ | ||
| 1141 | bss->oper_mode = 0; | ||
| 1142 | bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_SAP_MODE; | ||
| 1143 | } else if (vif->type == NL80211_IFTYPE_ADHOC || | ||
| 1144 | vif->type == NL80211_IFTYPE_MESH_POINT) { | ||
| 1145 | bss->bss_type = WCN36XX_HAL_IBSS_MODE; | ||
| 1146 | |||
| 1147 | /* STA */ | ||
| 1148 | bss->oper_mode = 1; | ||
| 1149 | } else { | ||
| 1150 | wcn36xx_warn("Unknown type for bss config: %d\n", vif->type); | ||
| 1151 | } | ||
| 1152 | |||
| 1153 | if (vif->type == NL80211_IFTYPE_STATION) | ||
| 1154 | wcn36xx_smd_set_bss_nw_type(wcn, sta, bss); | ||
| 1155 | else | ||
| 1156 | bss->nw_type = WCN36XX_HAL_11N_NW_TYPE; | ||
| 1157 | |||
| 1158 | bss->short_slot_time_supported = vif->bss_conf.use_short_slot; | ||
| 1159 | bss->lla_coexist = 0; | ||
| 1160 | bss->llb_coexist = 0; | ||
| 1161 | bss->llg_coexist = 0; | ||
| 1162 | bss->rifs_mode = 0; | ||
| 1163 | bss->beacon_interval = vif->bss_conf.beacon_int; | ||
| 1164 | bss->dtim_period = vif_priv->dtim_period; | ||
| 1165 | |||
| 1166 | wcn36xx_smd_set_bss_ht_params(vif, sta, bss); | ||
| 1167 | |||
| 1168 | bss->oper_channel = WCN36XX_HW_CHANNEL(wcn); | ||
| 1169 | |||
| 1170 | if (conf_is_ht40_minus(&wcn->hw->conf)) | ||
| 1171 | bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_BELOW; | ||
| 1172 | else if (conf_is_ht40_plus(&wcn->hw->conf)) | ||
| 1173 | bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | ||
| 1174 | else | ||
| 1175 | bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_NONE; | ||
| 1176 | |||
| 1177 | bss->reserved = 0; | ||
| 1178 | wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params); | ||
| 1179 | |||
| 1180 | /* wcn->ssid is only valid in AP and IBSS mode */ | ||
| 1181 | bss->ssid.length = vif_priv->ssid.length; | ||
| 1182 | memcpy(bss->ssid.ssid, vif_priv->ssid.ssid, vif_priv->ssid.length); | ||
| 1183 | |||
| 1184 | bss->obss_prot_enabled = 0; | ||
| 1185 | bss->rmf = 0; | ||
| 1186 | bss->max_probe_resp_retry_limit = 0; | ||
| 1187 | bss->hidden_ssid = vif->bss_conf.hidden_ssid; | ||
| 1188 | bss->proxy_probe_resp = 0; | ||
| 1189 | bss->edca_params_valid = 0; | ||
| 1190 | |||
| 1191 | /* FIXME: set acbe, acbk, acvi and acvo */ | ||
| 1192 | |||
| 1193 | bss->ext_set_sta_key_param_valid = 0; | ||
| 1194 | |||
| 1195 | /* FIXME: set ext_set_sta_key_param */ | ||
| 1196 | |||
| 1197 | bss->spectrum_mgt_enable = 0; | ||
| 1198 | bss->tx_mgmt_power = 0; | ||
| 1199 | bss->max_tx_power = WCN36XX_MAX_POWER(wcn); | ||
| 1200 | |||
| 1201 | bss->action = update; | ||
| 1202 | |||
| 1203 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
| 1204 | "hal config bss bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n", | ||
| 1205 | bss->bssid, bss->self_mac_addr, bss->bss_type, | ||
| 1206 | bss->oper_mode, bss->nw_type); | ||
| 1207 | |||
| 1208 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
| 1209 | "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n", | ||
| 1210 | sta_params->bssid, sta_params->action, | ||
| 1211 | sta_params->sta_index, sta_params->bssid_index, | ||
| 1212 | sta_params->aid, sta_params->type, | ||
| 1213 | sta_params->mac); | ||
| 1214 | |||
| 1215 | if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { | ||
| 1216 | ret = wcn36xx_smd_config_bss_v1(wcn, &msg); | ||
| 1217 | } else { | ||
| 1218 | PREPARE_HAL_BUF(wcn->hal_buf, msg); | ||
| 1219 | |||
| 1220 | ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len); | ||
| 1221 | } | ||
| 1222 | if (ret) { | ||
| 1223 | wcn36xx_err("Sending hal_config_bss failed\n"); | ||
| 1224 | goto out; | ||
| 1225 | } | ||
| 1226 | ret = wcn36xx_smd_config_bss_rsp(wcn, | ||
| 1227 | vif, | ||
| 1228 | wcn->hal_buf, | ||
| 1229 | wcn->hal_rsp_len); | ||
| 1230 | if (ret) { | ||
| 1231 | wcn36xx_err("hal_config_bss response failed err=%d\n", ret); | ||
| 1232 | goto out; | ||
| 1233 | } | ||
| 1234 | out: | ||
| 1235 | mutex_unlock(&wcn->hal_mutex); | ||
| 1236 | return ret; | ||
| 1237 | } | ||
| 1238 | |||
| 1239 | int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif) | ||
| 1240 | { | ||
| 1241 | struct wcn36xx_hal_delete_bss_req_msg msg_body; | ||
| 1242 | struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; | ||
| 1243 | int ret = 0; | ||
| 1244 | |||
| 1245 | mutex_lock(&wcn->hal_mutex); | ||
| 1246 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_BSS_REQ); | ||
| 1247 | |||
| 1248 | msg_body.bss_index = priv_vif->bss_index; | ||
| 1249 | |||
| 1250 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 1251 | |||
| 1252 | wcn36xx_dbg(WCN36XX_DBG_HAL, "hal delete bss %d\n", msg_body.bss_index); | ||
| 1253 | |||
| 1254 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 1255 | if (ret) { | ||
| 1256 | wcn36xx_err("Sending hal_delete_bss failed\n"); | ||
| 1257 | goto out; | ||
| 1258 | } | ||
| 1259 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 1260 | if (ret) { | ||
| 1261 | wcn36xx_err("hal_delete_bss response failed err=%d\n", ret); | ||
| 1262 | goto out; | ||
| 1263 | } | ||
| 1264 | out: | ||
| 1265 | mutex_unlock(&wcn->hal_mutex); | ||
| 1266 | return ret; | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif, | ||
| 1270 | struct sk_buff *skb_beacon, u16 tim_off, | ||
| 1271 | u16 p2p_off) | ||
| 1272 | { | ||
| 1273 | struct wcn36xx_hal_send_beacon_req_msg msg_body; | ||
| 1274 | int ret = 0; | ||
| 1275 | |||
| 1276 | mutex_lock(&wcn->hal_mutex); | ||
| 1277 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ); | ||
| 1278 | |||
| 1279 | /* TODO need to find out why this is needed? */ | ||
| 1280 | msg_body.beacon_length = skb_beacon->len + 6; | ||
| 1281 | |||
| 1282 | if (BEACON_TEMPLATE_SIZE > msg_body.beacon_length) { | ||
| 1283 | memcpy(&msg_body.beacon, &skb_beacon->len, sizeof(u32)); | ||
| 1284 | memcpy(&(msg_body.beacon[4]), skb_beacon->data, | ||
| 1285 | skb_beacon->len); | ||
| 1286 | } else { | ||
| 1287 | wcn36xx_err("Beacon is to big: beacon size=%d\n", | ||
| 1288 | msg_body.beacon_length); | ||
| 1289 | return -ENOMEM; | ||
| 1290 | } | ||
| 1291 | memcpy(msg_body.bssid, vif->addr, ETH_ALEN); | ||
| 1292 | |||
| 1293 | /* TODO need to find out why this is needed? */ | ||
| 1294 | msg_body.tim_ie_offset = tim_off+4; | ||
| 1295 | msg_body.p2p_ie_offset = p2p_off; | ||
| 1296 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 1297 | |||
| 1298 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
| 1299 | "hal send beacon beacon_length %d\n", | ||
| 1300 | msg_body.beacon_length); | ||
| 1301 | |||
| 1302 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 1303 | if (ret) { | ||
| 1304 | wcn36xx_err("Sending hal_send_beacon failed\n"); | ||
| 1305 | goto out; | ||
| 1306 | } | ||
| 1307 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 1308 | if (ret) { | ||
| 1309 | wcn36xx_err("hal_send_beacon response failed err=%d\n", ret); | ||
| 1310 | goto out; | ||
| 1311 | } | ||
| 1312 | out: | ||
| 1313 | mutex_unlock(&wcn->hal_mutex); | ||
| 1314 | return ret; | ||
| 1315 | } | ||
| 1316 | |||
| 1317 | int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn, | ||
| 1318 | struct ieee80211_vif *vif, | ||
| 1319 | struct sk_buff *skb) | ||
| 1320 | { | ||
| 1321 | struct wcn36xx_hal_send_probe_resp_req_msg msg; | ||
| 1322 | int ret = 0; | ||
| 1323 | |||
| 1324 | mutex_lock(&wcn->hal_mutex); | ||
| 1325 | INIT_HAL_MSG(msg, WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ); | ||
| 1326 | |||
| 1327 | if (skb->len > BEACON_TEMPLATE_SIZE) { | ||
| 1328 | wcn36xx_warn("probe response template is too big: %d\n", | ||
| 1329 | skb->len); | ||
| 1330 | return -E2BIG; | ||
| 1331 | } | ||
| 1332 | |||
| 1333 | msg.probe_resp_template_len = skb->len; | ||
| 1334 | memcpy(&msg.probe_resp_template, skb->data, skb->len); | ||
| 1335 | |||
| 1336 | memcpy(msg.bssid, vif->addr, ETH_ALEN); | ||
| 1337 | |||
| 1338 | PREPARE_HAL_BUF(wcn->hal_buf, msg); | ||
| 1339 | |||
| 1340 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
| 1341 | "hal update probe rsp len %d bssid %pM\n", | ||
| 1342 | msg.probe_resp_template_len, msg.bssid); | ||
| 1343 | |||
| 1344 | ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len); | ||
| 1345 | if (ret) { | ||
| 1346 | wcn36xx_err("Sending hal_update_proberesp_tmpl failed\n"); | ||
| 1347 | goto out; | ||
| 1348 | } | ||
| 1349 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 1350 | if (ret) { | ||
| 1351 | wcn36xx_err("hal_update_proberesp_tmpl response failed err=%d\n", | ||
| 1352 | ret); | ||
| 1353 | goto out; | ||
| 1354 | } | ||
| 1355 | out: | ||
| 1356 | mutex_unlock(&wcn->hal_mutex); | ||
| 1357 | return ret; | ||
| 1358 | } | ||
| 1359 | |||
| 1360 | int wcn36xx_smd_set_stakey(struct wcn36xx *wcn, | ||
| 1361 | enum ani_ed_type enc_type, | ||
| 1362 | u8 keyidx, | ||
| 1363 | u8 keylen, | ||
| 1364 | u8 *key, | ||
| 1365 | u8 sta_index) | ||
| 1366 | { | ||
| 1367 | struct wcn36xx_hal_set_sta_key_req_msg msg_body; | ||
| 1368 | int ret = 0; | ||
| 1369 | |||
| 1370 | mutex_lock(&wcn->hal_mutex); | ||
| 1371 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_STAKEY_REQ); | ||
| 1372 | |||
| 1373 | msg_body.set_sta_key_params.sta_index = sta_index; | ||
| 1374 | msg_body.set_sta_key_params.enc_type = enc_type; | ||
| 1375 | |||
| 1376 | msg_body.set_sta_key_params.key[0].id = keyidx; | ||
| 1377 | msg_body.set_sta_key_params.key[0].unicast = 1; | ||
| 1378 | msg_body.set_sta_key_params.key[0].direction = WCN36XX_HAL_TX_RX; | ||
| 1379 | msg_body.set_sta_key_params.key[0].pae_role = 0; | ||
| 1380 | msg_body.set_sta_key_params.key[0].length = keylen; | ||
| 1381 | memcpy(msg_body.set_sta_key_params.key[0].key, key, keylen); | ||
| 1382 | msg_body.set_sta_key_params.single_tid_rc = 1; | ||
| 1383 | |||
| 1384 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 1385 | |||
| 1386 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 1387 | if (ret) { | ||
| 1388 | wcn36xx_err("Sending hal_set_stakey failed\n"); | ||
| 1389 | goto out; | ||
| 1390 | } | ||
| 1391 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 1392 | if (ret) { | ||
| 1393 | wcn36xx_err("hal_set_stakey response failed err=%d\n", ret); | ||
| 1394 | goto out; | ||
| 1395 | } | ||
| 1396 | out: | ||
| 1397 | mutex_unlock(&wcn->hal_mutex); | ||
| 1398 | return ret; | ||
| 1399 | } | ||
| 1400 | |||
| 1401 | int wcn36xx_smd_set_bsskey(struct wcn36xx *wcn, | ||
| 1402 | enum ani_ed_type enc_type, | ||
| 1403 | u8 keyidx, | ||
| 1404 | u8 keylen, | ||
| 1405 | u8 *key) | ||
| 1406 | { | ||
| 1407 | struct wcn36xx_hal_set_bss_key_req_msg msg_body; | ||
| 1408 | int ret = 0; | ||
| 1409 | |||
| 1410 | mutex_lock(&wcn->hal_mutex); | ||
| 1411 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_BSSKEY_REQ); | ||
| 1412 | msg_body.bss_idx = 0; | ||
| 1413 | msg_body.enc_type = enc_type; | ||
| 1414 | msg_body.num_keys = 1; | ||
| 1415 | msg_body.keys[0].id = keyidx; | ||
| 1416 | msg_body.keys[0].unicast = 0; | ||
| 1417 | msg_body.keys[0].direction = WCN36XX_HAL_RX_ONLY; | ||
| 1418 | msg_body.keys[0].pae_role = 0; | ||
| 1419 | msg_body.keys[0].length = keylen; | ||
| 1420 | memcpy(msg_body.keys[0].key, key, keylen); | ||
| 1421 | |||
| 1422 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 1423 | |||
| 1424 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 1425 | if (ret) { | ||
| 1426 | wcn36xx_err("Sending hal_set_bsskey failed\n"); | ||
| 1427 | goto out; | ||
| 1428 | } | ||
| 1429 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 1430 | if (ret) { | ||
| 1431 | wcn36xx_err("hal_set_bsskey response failed err=%d\n", ret); | ||
| 1432 | goto out; | ||
| 1433 | } | ||
| 1434 | out: | ||
| 1435 | mutex_unlock(&wcn->hal_mutex); | ||
| 1436 | return ret; | ||
| 1437 | } | ||
| 1438 | |||
| 1439 | int wcn36xx_smd_remove_stakey(struct wcn36xx *wcn, | ||
| 1440 | enum ani_ed_type enc_type, | ||
| 1441 | u8 keyidx, | ||
| 1442 | u8 sta_index) | ||
| 1443 | { | ||
| 1444 | struct wcn36xx_hal_remove_sta_key_req_msg msg_body; | ||
| 1445 | int ret = 0; | ||
| 1446 | |||
| 1447 | mutex_lock(&wcn->hal_mutex); | ||
| 1448 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_STAKEY_REQ); | ||
| 1449 | |||
| 1450 | msg_body.sta_idx = sta_index; | ||
| 1451 | msg_body.enc_type = enc_type; | ||
| 1452 | msg_body.key_id = keyidx; | ||
| 1453 | |||
| 1454 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 1455 | |||
| 1456 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 1457 | if (ret) { | ||
| 1458 | wcn36xx_err("Sending hal_remove_stakey failed\n"); | ||
| 1459 | goto out; | ||
| 1460 | } | ||
| 1461 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 1462 | if (ret) { | ||
| 1463 | wcn36xx_err("hal_remove_stakey response failed err=%d\n", ret); | ||
| 1464 | goto out; | ||
| 1465 | } | ||
| 1466 | out: | ||
| 1467 | mutex_unlock(&wcn->hal_mutex); | ||
| 1468 | return ret; | ||
| 1469 | } | ||
| 1470 | |||
| 1471 | int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn, | ||
| 1472 | enum ani_ed_type enc_type, | ||
| 1473 | u8 keyidx) | ||
| 1474 | { | ||
| 1475 | struct wcn36xx_hal_remove_bss_key_req_msg msg_body; | ||
| 1476 | int ret = 0; | ||
| 1477 | |||
| 1478 | mutex_lock(&wcn->hal_mutex); | ||
| 1479 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_BSSKEY_REQ); | ||
| 1480 | msg_body.bss_idx = 0; | ||
| 1481 | msg_body.enc_type = enc_type; | ||
| 1482 | msg_body.key_id = keyidx; | ||
| 1483 | |||
| 1484 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 1485 | |||
| 1486 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 1487 | if (ret) { | ||
| 1488 | wcn36xx_err("Sending hal_remove_bsskey failed\n"); | ||
| 1489 | goto out; | ||
| 1490 | } | ||
| 1491 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 1492 | if (ret) { | ||
| 1493 | wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret); | ||
| 1494 | goto out; | ||
| 1495 | } | ||
| 1496 | out: | ||
| 1497 | mutex_unlock(&wcn->hal_mutex); | ||
| 1498 | return ret; | ||
| 1499 | } | ||
| 1500 | |||
| 1501 | int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) | ||
| 1502 | { | ||
| 1503 | struct wcn36xx_hal_enter_bmps_req_msg msg_body; | ||
| 1504 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
| 1505 | int ret = 0; | ||
| 1506 | |||
| 1507 | mutex_lock(&wcn->hal_mutex); | ||
| 1508 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_BMPS_REQ); | ||
| 1509 | |||
| 1510 | msg_body.bss_index = vif_priv->bss_index; | ||
| 1511 | msg_body.tbtt = vif->bss_conf.sync_tsf; | ||
| 1512 | msg_body.dtim_period = vif_priv->dtim_period; | ||
| 1513 | |||
| 1514 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 1515 | |||
| 1516 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 1517 | if (ret) { | ||
| 1518 | wcn36xx_err("Sending hal_enter_bmps failed\n"); | ||
| 1519 | goto out; | ||
| 1520 | } | ||
| 1521 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 1522 | if (ret) { | ||
| 1523 | wcn36xx_err("hal_enter_bmps response failed err=%d\n", ret); | ||
| 1524 | goto out; | ||
| 1525 | } | ||
| 1526 | out: | ||
| 1527 | mutex_unlock(&wcn->hal_mutex); | ||
| 1528 | return ret; | ||
| 1529 | } | ||
| 1530 | |||
| 1531 | int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) | ||
| 1532 | { | ||
| 1533 | struct wcn36xx_hal_enter_bmps_req_msg msg_body; | ||
| 1534 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
| 1535 | int ret = 0; | ||
| 1536 | |||
| 1537 | mutex_lock(&wcn->hal_mutex); | ||
| 1538 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_BMPS_REQ); | ||
| 1539 | |||
| 1540 | msg_body.bss_index = vif_priv->bss_index; | ||
| 1541 | |||
| 1542 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 1543 | |||
| 1544 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 1545 | if (ret) { | ||
| 1546 | wcn36xx_err("Sending hal_exit_bmps failed\n"); | ||
| 1547 | goto out; | ||
| 1548 | } | ||
| 1549 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 1550 | if (ret) { | ||
| 1551 | wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret); | ||
| 1552 | goto out; | ||
| 1553 | } | ||
| 1554 | out: | ||
| 1555 | mutex_unlock(&wcn->hal_mutex); | ||
| 1556 | return ret; | ||
| 1557 | } | ||
| 1558 | int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim) | ||
| 1559 | { | ||
| 1560 | struct wcn36xx_hal_set_power_params_req_msg msg_body; | ||
| 1561 | int ret = 0; | ||
| 1562 | |||
| 1563 | mutex_lock(&wcn->hal_mutex); | ||
| 1564 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_POWER_PARAMS_REQ); | ||
| 1565 | |||
| 1566 | /* | ||
| 1567 | * When host is down ignore every second dtim | ||
| 1568 | */ | ||
| 1569 | if (ignore_dtim) { | ||
| 1570 | msg_body.ignore_dtim = 1; | ||
| 1571 | msg_body.dtim_period = 2; | ||
| 1572 | } | ||
| 1573 | msg_body.listen_interval = WCN36XX_LISTEN_INTERVAL(wcn); | ||
| 1574 | |||
| 1575 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 1576 | |||
| 1577 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 1578 | if (ret) { | ||
| 1579 | wcn36xx_err("Sending hal_set_power_params failed\n"); | ||
| 1580 | goto out; | ||
| 1581 | } | ||
| 1582 | |||
| 1583 | out: | ||
| 1584 | mutex_unlock(&wcn->hal_mutex); | ||
| 1585 | return ret; | ||
| 1586 | } | ||
| 1587 | /* Notice: This function should be called after associated, or else it | ||
| 1588 | * will be invalid | ||
| 1589 | */ | ||
| 1590 | int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn, | ||
| 1591 | struct ieee80211_vif *vif, | ||
| 1592 | int packet_type) | ||
| 1593 | { | ||
| 1594 | struct wcn36xx_hal_keep_alive_req_msg msg_body; | ||
| 1595 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
| 1596 | int ret = 0; | ||
| 1597 | |||
| 1598 | mutex_lock(&wcn->hal_mutex); | ||
| 1599 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_KEEP_ALIVE_REQ); | ||
| 1600 | |||
| 1601 | if (packet_type == WCN36XX_HAL_KEEP_ALIVE_NULL_PKT) { | ||
| 1602 | msg_body.bss_index = vif_priv->bss_index; | ||
| 1603 | msg_body.packet_type = WCN36XX_HAL_KEEP_ALIVE_NULL_PKT; | ||
| 1604 | msg_body.time_period = WCN36XX_KEEP_ALIVE_TIME_PERIOD; | ||
| 1605 | } else if (packet_type == WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP) { | ||
| 1606 | /* TODO: it also support ARP response type */ | ||
| 1607 | } else { | ||
| 1608 | wcn36xx_warn("unknow keep alive packet type %d\n", packet_type); | ||
| 1609 | return -EINVAL; | ||
| 1610 | } | ||
| 1611 | |||
| 1612 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 1613 | |||
| 1614 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 1615 | if (ret) { | ||
| 1616 | wcn36xx_err("Sending hal_exit_bmps failed\n"); | ||
| 1617 | goto out; | ||
| 1618 | } | ||
| 1619 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 1620 | if (ret) { | ||
| 1621 | wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret); | ||
| 1622 | goto out; | ||
| 1623 | } | ||
| 1624 | out: | ||
| 1625 | mutex_unlock(&wcn->hal_mutex); | ||
| 1626 | return ret; | ||
| 1627 | } | ||
| 1628 | |||
| 1629 | int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2, | ||
| 1630 | u32 arg3, u32 arg4, u32 arg5) | ||
| 1631 | { | ||
| 1632 | struct wcn36xx_hal_dump_cmd_req_msg msg_body; | ||
| 1633 | int ret = 0; | ||
| 1634 | |||
| 1635 | mutex_lock(&wcn->hal_mutex); | ||
| 1636 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_DUMP_COMMAND_REQ); | ||
| 1637 | |||
| 1638 | msg_body.arg1 = arg1; | ||
| 1639 | msg_body.arg2 = arg2; | ||
| 1640 | msg_body.arg3 = arg3; | ||
| 1641 | msg_body.arg4 = arg4; | ||
| 1642 | msg_body.arg5 = arg5; | ||
| 1643 | |||
| 1644 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 1645 | |||
| 1646 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 1647 | if (ret) { | ||
| 1648 | wcn36xx_err("Sending hal_dump_cmd failed\n"); | ||
| 1649 | goto out; | ||
| 1650 | } | ||
| 1651 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 1652 | if (ret) { | ||
| 1653 | wcn36xx_err("hal_dump_cmd response failed err=%d\n", ret); | ||
| 1654 | goto out; | ||
| 1655 | } | ||
| 1656 | out: | ||
| 1657 | mutex_unlock(&wcn->hal_mutex); | ||
| 1658 | return ret; | ||
| 1659 | } | ||
| 1660 | |||
| 1661 | static inline void set_feat_caps(u32 *bitmap, | ||
| 1662 | enum place_holder_in_cap_bitmap cap) | ||
| 1663 | { | ||
| 1664 | int arr_idx, bit_idx; | ||
| 1665 | |||
| 1666 | if (cap < 0 || cap > 127) { | ||
| 1667 | wcn36xx_warn("error cap idx %d\n", cap); | ||
| 1668 | return; | ||
| 1669 | } | ||
| 1670 | |||
| 1671 | arr_idx = cap / 32; | ||
| 1672 | bit_idx = cap % 32; | ||
| 1673 | bitmap[arr_idx] |= (1 << bit_idx); | ||
| 1674 | } | ||
| 1675 | |||
| 1676 | static inline int get_feat_caps(u32 *bitmap, | ||
| 1677 | enum place_holder_in_cap_bitmap cap) | ||
| 1678 | { | ||
| 1679 | int arr_idx, bit_idx; | ||
| 1680 | int ret = 0; | ||
| 1681 | |||
| 1682 | if (cap < 0 || cap > 127) { | ||
| 1683 | wcn36xx_warn("error cap idx %d\n", cap); | ||
| 1684 | return -EINVAL; | ||
| 1685 | } | ||
| 1686 | |||
| 1687 | arr_idx = cap / 32; | ||
| 1688 | bit_idx = cap % 32; | ||
| 1689 | ret = (bitmap[arr_idx] & (1 << bit_idx)) ? 1 : 0; | ||
| 1690 | return ret; | ||
| 1691 | } | ||
| 1692 | |||
| 1693 | static inline void clear_feat_caps(u32 *bitmap, | ||
| 1694 | enum place_holder_in_cap_bitmap cap) | ||
| 1695 | { | ||
| 1696 | int arr_idx, bit_idx; | ||
| 1697 | |||
| 1698 | if (cap < 0 || cap > 127) { | ||
| 1699 | wcn36xx_warn("error cap idx %d\n", cap); | ||
| 1700 | return; | ||
| 1701 | } | ||
| 1702 | |||
| 1703 | arr_idx = cap / 32; | ||
| 1704 | bit_idx = cap % 32; | ||
| 1705 | bitmap[arr_idx] &= ~(1 << bit_idx); | ||
| 1706 | } | ||
| 1707 | |||
| 1708 | int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn) | ||
| 1709 | { | ||
| 1710 | struct wcn36xx_hal_feat_caps_msg msg_body; | ||
| 1711 | int ret = 0; | ||
| 1712 | |||
| 1713 | mutex_lock(&wcn->hal_mutex); | ||
| 1714 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ); | ||
| 1715 | |||
| 1716 | set_feat_caps(msg_body.feat_caps, STA_POWERSAVE); | ||
| 1717 | |||
| 1718 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 1719 | |||
| 1720 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 1721 | if (ret) { | ||
| 1722 | wcn36xx_err("Sending hal_feature_caps_exchange failed\n"); | ||
| 1723 | goto out; | ||
| 1724 | } | ||
| 1725 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 1726 | if (ret) { | ||
| 1727 | wcn36xx_err("hal_feature_caps_exchange response failed err=%d\n", | ||
| 1728 | ret); | ||
| 1729 | goto out; | ||
| 1730 | } | ||
| 1731 | out: | ||
| 1732 | mutex_unlock(&wcn->hal_mutex); | ||
| 1733 | return ret; | ||
| 1734 | } | ||
| 1735 | |||
| 1736 | int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn, | ||
| 1737 | struct ieee80211_sta *sta, | ||
| 1738 | u16 tid, | ||
| 1739 | u16 *ssn, | ||
| 1740 | u8 direction, | ||
| 1741 | u8 sta_index) | ||
| 1742 | { | ||
| 1743 | struct wcn36xx_hal_add_ba_session_req_msg msg_body; | ||
| 1744 | int ret = 0; | ||
| 1745 | |||
| 1746 | mutex_lock(&wcn->hal_mutex); | ||
| 1747 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_SESSION_REQ); | ||
| 1748 | |||
| 1749 | msg_body.sta_index = sta_index; | ||
| 1750 | memcpy(&msg_body.mac_addr, sta->addr, ETH_ALEN); | ||
| 1751 | msg_body.dialog_token = 0x10; | ||
| 1752 | msg_body.tid = tid; | ||
| 1753 | |||
| 1754 | /* Immediate BA because Delayed BA is not supported */ | ||
| 1755 | msg_body.policy = 1; | ||
| 1756 | msg_body.buffer_size = WCN36XX_AGGR_BUFFER_SIZE; | ||
| 1757 | msg_body.timeout = 0; | ||
| 1758 | if (ssn) | ||
| 1759 | msg_body.ssn = *ssn; | ||
| 1760 | msg_body.direction = direction; | ||
| 1761 | |||
| 1762 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 1763 | |||
| 1764 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 1765 | if (ret) { | ||
| 1766 | wcn36xx_err("Sending hal_add_ba_session failed\n"); | ||
| 1767 | goto out; | ||
| 1768 | } | ||
| 1769 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 1770 | if (ret) { | ||
| 1771 | wcn36xx_err("hal_add_ba_session response failed err=%d\n", ret); | ||
| 1772 | goto out; | ||
| 1773 | } | ||
| 1774 | out: | ||
| 1775 | mutex_unlock(&wcn->hal_mutex); | ||
| 1776 | return ret; | ||
| 1777 | } | ||
| 1778 | |||
| 1779 | int wcn36xx_smd_add_ba(struct wcn36xx *wcn) | ||
| 1780 | { | ||
| 1781 | struct wcn36xx_hal_add_ba_req_msg msg_body; | ||
| 1782 | int ret = 0; | ||
| 1783 | |||
| 1784 | mutex_lock(&wcn->hal_mutex); | ||
| 1785 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_REQ); | ||
| 1786 | |||
| 1787 | msg_body.session_id = 0; | ||
| 1788 | msg_body.win_size = WCN36XX_AGGR_BUFFER_SIZE; | ||
| 1789 | |||
| 1790 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 1791 | |||
| 1792 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 1793 | if (ret) { | ||
| 1794 | wcn36xx_err("Sending hal_add_ba failed\n"); | ||
| 1795 | goto out; | ||
| 1796 | } | ||
| 1797 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 1798 | if (ret) { | ||
| 1799 | wcn36xx_err("hal_add_ba response failed err=%d\n", ret); | ||
| 1800 | goto out; | ||
| 1801 | } | ||
| 1802 | out: | ||
| 1803 | mutex_unlock(&wcn->hal_mutex); | ||
| 1804 | return ret; | ||
| 1805 | } | ||
| 1806 | |||
| 1807 | int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index) | ||
| 1808 | { | ||
| 1809 | struct wcn36xx_hal_del_ba_req_msg msg_body; | ||
| 1810 | int ret = 0; | ||
| 1811 | |||
| 1812 | mutex_lock(&wcn->hal_mutex); | ||
| 1813 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_BA_REQ); | ||
| 1814 | |||
| 1815 | msg_body.sta_index = sta_index; | ||
| 1816 | msg_body.tid = tid; | ||
| 1817 | msg_body.direction = 0; | ||
| 1818 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 1819 | |||
| 1820 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 1821 | if (ret) { | ||
| 1822 | wcn36xx_err("Sending hal_del_ba failed\n"); | ||
| 1823 | goto out; | ||
| 1824 | } | ||
| 1825 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 1826 | if (ret) { | ||
| 1827 | wcn36xx_err("hal_del_ba response failed err=%d\n", ret); | ||
| 1828 | goto out; | ||
| 1829 | } | ||
| 1830 | out: | ||
| 1831 | mutex_unlock(&wcn->hal_mutex); | ||
| 1832 | return ret; | ||
| 1833 | } | ||
| 1834 | |||
| 1835 | int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index) | ||
| 1836 | { | ||
| 1837 | struct wcn36xx_hal_trigger_ba_req_msg msg_body; | ||
| 1838 | struct wcn36xx_hal_trigget_ba_req_candidate *candidate; | ||
| 1839 | int ret = 0; | ||
| 1840 | |||
| 1841 | mutex_lock(&wcn->hal_mutex); | ||
| 1842 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_TRIGGER_BA_REQ); | ||
| 1843 | |||
| 1844 | msg_body.session_id = 0; | ||
| 1845 | msg_body.candidate_cnt = 1; | ||
| 1846 | msg_body.header.len += sizeof(*candidate); | ||
| 1847 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 1848 | |||
| 1849 | candidate = (struct wcn36xx_hal_trigget_ba_req_candidate *) | ||
| 1850 | (wcn->hal_buf + sizeof(msg_body)); | ||
| 1851 | candidate->sta_index = sta_index; | ||
| 1852 | candidate->tid_bitmap = 1; | ||
| 1853 | |||
| 1854 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
| 1855 | if (ret) { | ||
| 1856 | wcn36xx_err("Sending hal_trigger_ba failed\n"); | ||
| 1857 | goto out; | ||
| 1858 | } | ||
| 1859 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 1860 | if (ret) { | ||
| 1861 | wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret); | ||
| 1862 | goto out; | ||
| 1863 | } | ||
| 1864 | out: | ||
| 1865 | mutex_unlock(&wcn->hal_mutex); | ||
| 1866 | return ret; | ||
| 1867 | } | ||
| 1868 | |||
| 1869 | static int wcn36xx_smd_tx_compl_ind(struct wcn36xx *wcn, void *buf, size_t len) | ||
| 1870 | { | ||
| 1871 | struct wcn36xx_hal_tx_compl_ind_msg *rsp = buf; | ||
| 1872 | |||
| 1873 | if (len != sizeof(*rsp)) { | ||
| 1874 | wcn36xx_warn("Bad TX complete indication\n"); | ||
| 1875 | return -EIO; | ||
| 1876 | } | ||
| 1877 | |||
| 1878 | wcn36xx_dxe_tx_ack_ind(wcn, rsp->status); | ||
| 1879 | |||
| 1880 | return 0; | ||
| 1881 | } | ||
| 1882 | |||
| 1883 | static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn, | ||
| 1884 | void *buf, | ||
| 1885 | size_t len) | ||
| 1886 | { | ||
| 1887 | struct wcn36xx_hal_missed_beacon_ind_msg *rsp = buf; | ||
| 1888 | struct ieee80211_vif *vif = NULL; | ||
| 1889 | struct wcn36xx_vif *tmp; | ||
| 1890 | |||
| 1891 | /* Old FW does not have bss index */ | ||
| 1892 | if (wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { | ||
| 1893 | list_for_each_entry(tmp, &wcn->vif_list, list) { | ||
| 1894 | wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n", | ||
| 1895 | tmp->bss_index); | ||
| 1896 | vif = container_of((void *)tmp, | ||
| 1897 | struct ieee80211_vif, | ||
| 1898 | drv_priv); | ||
| 1899 | ieee80211_connection_loss(vif); | ||
| 1900 | } | ||
| 1901 | return 0; | ||
| 1902 | } | ||
| 1903 | |||
| 1904 | if (len != sizeof(*rsp)) { | ||
| 1905 | wcn36xx_warn("Corrupted missed beacon indication\n"); | ||
| 1906 | return -EIO; | ||
| 1907 | } | ||
| 1908 | |||
| 1909 | list_for_each_entry(tmp, &wcn->vif_list, list) { | ||
| 1910 | if (tmp->bss_index == rsp->bss_index) { | ||
| 1911 | wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n", | ||
| 1912 | rsp->bss_index); | ||
| 1913 | vif = container_of((void *)tmp, | ||
| 1914 | struct ieee80211_vif, | ||
| 1915 | drv_priv); | ||
| 1916 | ieee80211_connection_loss(vif); | ||
| 1917 | return 0; | ||
| 1918 | } | ||
| 1919 | } | ||
| 1920 | |||
| 1921 | wcn36xx_warn("BSS index %d not found\n", rsp->bss_index); | ||
| 1922 | return -ENOENT; | ||
| 1923 | } | ||
| 1924 | |||
| 1925 | static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn, | ||
| 1926 | void *buf, | ||
| 1927 | size_t len) | ||
| 1928 | { | ||
| 1929 | struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf; | ||
| 1930 | struct wcn36xx_vif *tmp; | ||
| 1931 | struct ieee80211_sta *sta = NULL; | ||
| 1932 | |||
| 1933 | if (len != sizeof(*rsp)) { | ||
| 1934 | wcn36xx_warn("Corrupted delete sta indication\n"); | ||
| 1935 | return -EIO; | ||
| 1936 | } | ||
| 1937 | |||
| 1938 | list_for_each_entry(tmp, &wcn->vif_list, list) { | ||
| 1939 | if (sta && (tmp->sta->sta_index == rsp->sta_id)) { | ||
| 1940 | sta = container_of((void *)tmp->sta, | ||
| 1941 | struct ieee80211_sta, | ||
| 1942 | drv_priv); | ||
| 1943 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
| 1944 | "delete station indication %pM index %d\n", | ||
| 1945 | rsp->addr2, | ||
| 1946 | rsp->sta_id); | ||
| 1947 | ieee80211_report_low_ack(sta, 0); | ||
| 1948 | return 0; | ||
| 1949 | } | ||
| 1950 | } | ||
| 1951 | |||
| 1952 | wcn36xx_warn("STA with addr %pM and index %d not found\n", | ||
| 1953 | rsp->addr2, | ||
| 1954 | rsp->sta_id); | ||
| 1955 | return -ENOENT; | ||
| 1956 | } | ||
| 1957 | |||
| 1958 | int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value) | ||
| 1959 | { | ||
| 1960 | struct wcn36xx_hal_update_cfg_req_msg msg_body, *body; | ||
| 1961 | size_t len; | ||
| 1962 | int ret = 0; | ||
| 1963 | |||
| 1964 | mutex_lock(&wcn->hal_mutex); | ||
| 1965 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_CFG_REQ); | ||
| 1966 | |||
| 1967 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
| 1968 | |||
| 1969 | body = (struct wcn36xx_hal_update_cfg_req_msg *) wcn->hal_buf; | ||
| 1970 | len = msg_body.header.len; | ||
| 1971 | |||
| 1972 | put_cfg_tlv_u32(wcn, &len, cfg_id, value); | ||
| 1973 | body->header.len = len; | ||
| 1974 | body->len = len - sizeof(*body); | ||
| 1975 | |||
| 1976 | ret = wcn36xx_smd_send_and_wait(wcn, body->header.len); | ||
| 1977 | if (ret) { | ||
| 1978 | wcn36xx_err("Sending hal_update_cfg failed\n"); | ||
| 1979 | goto out; | ||
| 1980 | } | ||
| 1981 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
| 1982 | if (ret) { | ||
| 1983 | wcn36xx_err("hal_update_cfg response failed err=%d\n", ret); | ||
| 1984 | goto out; | ||
| 1985 | } | ||
| 1986 | out: | ||
| 1987 | mutex_unlock(&wcn->hal_mutex); | ||
| 1988 | return ret; | ||
| 1989 | } | ||
| 1990 | static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len) | ||
| 1991 | { | ||
| 1992 | struct wcn36xx_hal_msg_header *msg_header = buf; | ||
| 1993 | struct wcn36xx_hal_ind_msg *msg_ind; | ||
| 1994 | wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len); | ||
| 1995 | |||
| 1996 | switch (msg_header->msg_type) { | ||
| 1997 | case WCN36XX_HAL_START_RSP: | ||
| 1998 | case WCN36XX_HAL_CONFIG_STA_RSP: | ||
| 1999 | case WCN36XX_HAL_CONFIG_BSS_RSP: | ||
| 2000 | case WCN36XX_HAL_ADD_STA_SELF_RSP: | ||
| 2001 | case WCN36XX_HAL_STOP_RSP: | ||
| 2002 | case WCN36XX_HAL_DEL_STA_SELF_RSP: | ||
| 2003 | case WCN36XX_HAL_DELETE_STA_RSP: | ||
| 2004 | case WCN36XX_HAL_INIT_SCAN_RSP: | ||
| 2005 | case WCN36XX_HAL_START_SCAN_RSP: | ||
| 2006 | case WCN36XX_HAL_END_SCAN_RSP: | ||
| 2007 | case WCN36XX_HAL_FINISH_SCAN_RSP: | ||
| 2008 | case WCN36XX_HAL_DOWNLOAD_NV_RSP: | ||
| 2009 | case WCN36XX_HAL_DELETE_BSS_RSP: | ||
| 2010 | case WCN36XX_HAL_SEND_BEACON_RSP: | ||
| 2011 | case WCN36XX_HAL_SET_LINK_ST_RSP: | ||
| 2012 | case WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_RSP: | ||
| 2013 | case WCN36XX_HAL_SET_BSSKEY_RSP: | ||
| 2014 | case WCN36XX_HAL_SET_STAKEY_RSP: | ||
| 2015 | case WCN36XX_HAL_RMV_STAKEY_RSP: | ||
| 2016 | case WCN36XX_HAL_RMV_BSSKEY_RSP: | ||
| 2017 | case WCN36XX_HAL_ENTER_BMPS_RSP: | ||
| 2018 | case WCN36XX_HAL_SET_POWER_PARAMS_RSP: | ||
| 2019 | case WCN36XX_HAL_EXIT_BMPS_RSP: | ||
| 2020 | case WCN36XX_HAL_KEEP_ALIVE_RSP: | ||
| 2021 | case WCN36XX_HAL_DUMP_COMMAND_RSP: | ||
| 2022 | case WCN36XX_HAL_ADD_BA_SESSION_RSP: | ||
| 2023 | case WCN36XX_HAL_ADD_BA_RSP: | ||
| 2024 | case WCN36XX_HAL_DEL_BA_RSP: | ||
| 2025 | case WCN36XX_HAL_TRIGGER_BA_RSP: | ||
| 2026 | case WCN36XX_HAL_UPDATE_CFG_RSP: | ||
| 2027 | case WCN36XX_HAL_JOIN_RSP: | ||
| 2028 | case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP: | ||
| 2029 | case WCN36XX_HAL_CH_SWITCH_RSP: | ||
| 2030 | case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP: | ||
| 2031 | memcpy(wcn->hal_buf, buf, len); | ||
| 2032 | wcn->hal_rsp_len = len; | ||
| 2033 | complete(&wcn->hal_rsp_compl); | ||
| 2034 | break; | ||
| 2035 | |||
| 2036 | case WCN36XX_HAL_OTA_TX_COMPL_IND: | ||
| 2037 | case WCN36XX_HAL_MISSED_BEACON_IND: | ||
| 2038 | case WCN36XX_HAL_DELETE_STA_CONTEXT_IND: | ||
| 2039 | mutex_lock(&wcn->hal_ind_mutex); | ||
| 2040 | msg_ind = kmalloc(sizeof(*msg_ind), GFP_KERNEL); | ||
| 2041 | msg_ind->msg_len = len; | ||
| 2042 | msg_ind->msg = kmalloc(len, GFP_KERNEL); | ||
| 2043 | memcpy(msg_ind->msg, buf, len); | ||
| 2044 | list_add_tail(&msg_ind->list, &wcn->hal_ind_queue); | ||
| 2045 | queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work); | ||
| 2046 | wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n"); | ||
| 2047 | mutex_unlock(&wcn->hal_ind_mutex); | ||
| 2048 | break; | ||
| 2049 | default: | ||
| 2050 | wcn36xx_err("SMD_EVENT (%d) not supported\n", | ||
| 2051 | msg_header->msg_type); | ||
| 2052 | } | ||
| 2053 | } | ||
| 2054 | static void wcn36xx_ind_smd_work(struct work_struct *work) | ||
| 2055 | { | ||
| 2056 | struct wcn36xx *wcn = | ||
| 2057 | container_of(work, struct wcn36xx, hal_ind_work); | ||
| 2058 | struct wcn36xx_hal_msg_header *msg_header; | ||
| 2059 | struct wcn36xx_hal_ind_msg *hal_ind_msg; | ||
| 2060 | |||
| 2061 | mutex_lock(&wcn->hal_ind_mutex); | ||
| 2062 | |||
| 2063 | hal_ind_msg = list_first_entry(&wcn->hal_ind_queue, | ||
| 2064 | struct wcn36xx_hal_ind_msg, | ||
| 2065 | list); | ||
| 2066 | |||
| 2067 | msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg; | ||
| 2068 | |||
| 2069 | switch (msg_header->msg_type) { | ||
| 2070 | case WCN36XX_HAL_OTA_TX_COMPL_IND: | ||
| 2071 | wcn36xx_smd_tx_compl_ind(wcn, | ||
| 2072 | hal_ind_msg->msg, | ||
| 2073 | hal_ind_msg->msg_len); | ||
| 2074 | break; | ||
| 2075 | case WCN36XX_HAL_MISSED_BEACON_IND: | ||
| 2076 | wcn36xx_smd_missed_beacon_ind(wcn, | ||
| 2077 | hal_ind_msg->msg, | ||
| 2078 | hal_ind_msg->msg_len); | ||
| 2079 | break; | ||
| 2080 | case WCN36XX_HAL_DELETE_STA_CONTEXT_IND: | ||
| 2081 | wcn36xx_smd_delete_sta_context_ind(wcn, | ||
| 2082 | hal_ind_msg->msg, | ||
| 2083 | hal_ind_msg->msg_len); | ||
| 2084 | break; | ||
| 2085 | default: | ||
| 2086 | wcn36xx_err("SMD_EVENT (%d) not supported\n", | ||
| 2087 | msg_header->msg_type); | ||
| 2088 | } | ||
| 2089 | list_del(wcn->hal_ind_queue.next); | ||
| 2090 | kfree(hal_ind_msg->msg); | ||
| 2091 | kfree(hal_ind_msg); | ||
| 2092 | mutex_unlock(&wcn->hal_ind_mutex); | ||
| 2093 | } | ||
| 2094 | int wcn36xx_smd_open(struct wcn36xx *wcn) | ||
| 2095 | { | ||
| 2096 | int ret = 0; | ||
| 2097 | wcn->hal_ind_wq = create_freezable_workqueue("wcn36xx_smd_ind"); | ||
| 2098 | if (!wcn->hal_ind_wq) { | ||
| 2099 | wcn36xx_err("failed to allocate wq\n"); | ||
| 2100 | ret = -ENOMEM; | ||
| 2101 | goto out; | ||
| 2102 | } | ||
| 2103 | INIT_WORK(&wcn->hal_ind_work, wcn36xx_ind_smd_work); | ||
| 2104 | INIT_LIST_HEAD(&wcn->hal_ind_queue); | ||
| 2105 | mutex_init(&wcn->hal_ind_mutex); | ||
| 2106 | |||
| 2107 | ret = wcn->ctrl_ops->open(wcn, wcn36xx_smd_rsp_process); | ||
| 2108 | if (ret) { | ||
| 2109 | wcn36xx_err("failed to open control channel\n"); | ||
| 2110 | goto free_wq; | ||
| 2111 | } | ||
| 2112 | |||
| 2113 | return ret; | ||
| 2114 | |||
| 2115 | free_wq: | ||
| 2116 | destroy_workqueue(wcn->hal_ind_wq); | ||
| 2117 | out: | ||
| 2118 | return ret; | ||
| 2119 | } | ||
| 2120 | |||
| 2121 | void wcn36xx_smd_close(struct wcn36xx *wcn) | ||
| 2122 | { | ||
| 2123 | wcn->ctrl_ops->close(); | ||
| 2124 | destroy_workqueue(wcn->hal_ind_wq); | ||
| 2125 | mutex_destroy(&wcn->hal_ind_mutex); | ||
| 2126 | } | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h new file mode 100644 index 000000000000..e7c39019c6f1 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/smd.h | |||
| @@ -0,0 +1,127 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef _SMD_H_ | ||
| 18 | #define _SMD_H_ | ||
| 19 | |||
| 20 | #include "wcn36xx.h" | ||
| 21 | |||
| 22 | /* Max shared size is 4k but we take less.*/ | ||
| 23 | #define WCN36XX_NV_FRAGMENT_SIZE 3072 | ||
| 24 | |||
| 25 | #define WCN36XX_HAL_BUF_SIZE 4096 | ||
| 26 | |||
| 27 | #define HAL_MSG_TIMEOUT 200 | ||
| 28 | #define WCN36XX_SMSM_WLAN_TX_ENABLE 0x00000400 | ||
| 29 | #define WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY 0x00000200 | ||
| 30 | /* The PNO version info be contained in the rsp msg */ | ||
| 31 | #define WCN36XX_FW_MSG_PNO_VERSION_MASK 0x8000 | ||
| 32 | |||
| 33 | enum wcn36xx_fw_msg_result { | ||
| 34 | WCN36XX_FW_MSG_RESULT_SUCCESS = 0, | ||
| 35 | WCN36XX_FW_MSG_RESULT_SUCCESS_SYNC = 1, | ||
| 36 | |||
| 37 | WCN36XX_FW_MSG_RESULT_MEM_FAIL = 5, | ||
| 38 | }; | ||
| 39 | |||
| 40 | /******************************/ | ||
| 41 | /* SMD requests and responses */ | ||
| 42 | /******************************/ | ||
| 43 | struct wcn36xx_fw_msg_status_rsp { | ||
| 44 | u32 status; | ||
| 45 | } __packed; | ||
| 46 | |||
| 47 | struct wcn36xx_hal_ind_msg { | ||
| 48 | struct list_head list; | ||
| 49 | u8 *msg; | ||
| 50 | size_t msg_len; | ||
| 51 | }; | ||
| 52 | |||
| 53 | struct wcn36xx; | ||
| 54 | |||
| 55 | int wcn36xx_smd_open(struct wcn36xx *wcn); | ||
| 56 | void wcn36xx_smd_close(struct wcn36xx *wcn); | ||
| 57 | |||
| 58 | int wcn36xx_smd_load_nv(struct wcn36xx *wcn); | ||
| 59 | int wcn36xx_smd_start(struct wcn36xx *wcn); | ||
| 60 | int wcn36xx_smd_stop(struct wcn36xx *wcn); | ||
| 61 | int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode); | ||
| 62 | int wcn36xx_smd_start_scan(struct wcn36xx *wcn); | ||
| 63 | int wcn36xx_smd_end_scan(struct wcn36xx *wcn); | ||
| 64 | int wcn36xx_smd_finish_scan(struct wcn36xx *wcn, | ||
| 65 | enum wcn36xx_hal_sys_mode mode); | ||
| 66 | int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn); | ||
| 67 | int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif); | ||
| 68 | int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr); | ||
| 69 | int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index); | ||
| 70 | int wcn36xx_smd_join(struct wcn36xx *wcn, const u8 *bssid, u8 *vif, u8 ch); | ||
| 71 | int wcn36xx_smd_set_link_st(struct wcn36xx *wcn, const u8 *bssid, | ||
| 72 | const u8 *sta_mac, | ||
| 73 | enum wcn36xx_hal_link_state state); | ||
| 74 | int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, | ||
| 75 | struct ieee80211_sta *sta, const u8 *bssid, | ||
| 76 | bool update); | ||
| 77 | int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif); | ||
| 78 | int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif, | ||
| 79 | struct ieee80211_sta *sta); | ||
| 80 | int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif, | ||
| 81 | struct sk_buff *skb_beacon, u16 tim_off, | ||
| 82 | u16 p2p_off); | ||
| 83 | int wcn36xx_smd_switch_channel(struct wcn36xx *wcn, | ||
| 84 | struct ieee80211_vif *vif, int ch); | ||
| 85 | int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn, | ||
| 86 | struct ieee80211_vif *vif, | ||
| 87 | struct sk_buff *skb); | ||
| 88 | int wcn36xx_smd_set_stakey(struct wcn36xx *wcn, | ||
| 89 | enum ani_ed_type enc_type, | ||
| 90 | u8 keyidx, | ||
| 91 | u8 keylen, | ||
| 92 | u8 *key, | ||
| 93 | u8 sta_index); | ||
| 94 | int wcn36xx_smd_set_bsskey(struct wcn36xx *wcn, | ||
| 95 | enum ani_ed_type enc_type, | ||
| 96 | u8 keyidx, | ||
| 97 | u8 keylen, | ||
| 98 | u8 *key); | ||
| 99 | int wcn36xx_smd_remove_stakey(struct wcn36xx *wcn, | ||
| 100 | enum ani_ed_type enc_type, | ||
| 101 | u8 keyidx, | ||
| 102 | u8 sta_index); | ||
| 103 | int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn, | ||
| 104 | enum ani_ed_type enc_type, | ||
| 105 | u8 keyidx); | ||
| 106 | int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif); | ||
| 107 | int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif); | ||
| 108 | int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim); | ||
| 109 | int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn, | ||
| 110 | struct ieee80211_vif *vif, | ||
| 111 | int packet_type); | ||
| 112 | int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2, | ||
| 113 | u32 arg3, u32 arg4, u32 arg5); | ||
| 114 | int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn); | ||
| 115 | |||
| 116 | int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn, | ||
| 117 | struct ieee80211_sta *sta, | ||
| 118 | u16 tid, | ||
| 119 | u16 *ssn, | ||
| 120 | u8 direction, | ||
| 121 | u8 sta_index); | ||
| 122 | int wcn36xx_smd_add_ba(struct wcn36xx *wcn); | ||
| 123 | int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index); | ||
| 124 | int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index); | ||
| 125 | |||
| 126 | int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value); | ||
| 127 | #endif /* _SMD_H_ */ | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.c b/drivers/net/wireless/ath/wcn36xx/txrx.c new file mode 100644 index 000000000000..b2b60e30caaf --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/txrx.c | |||
| @@ -0,0 +1,284 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 18 | |||
| 19 | #include "txrx.h" | ||
| 20 | |||
| 21 | static inline int get_rssi0(struct wcn36xx_rx_bd *bd) | ||
| 22 | { | ||
| 23 | return 100 - ((bd->phy_stat0 >> 24) & 0xff); | ||
| 24 | } | ||
| 25 | |||
| 26 | int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb) | ||
| 27 | { | ||
| 28 | struct ieee80211_rx_status status; | ||
| 29 | struct ieee80211_hdr *hdr; | ||
| 30 | struct wcn36xx_rx_bd *bd; | ||
| 31 | u16 fc, sn; | ||
| 32 | |||
| 33 | /* | ||
| 34 | * All fields must be 0, otherwise it can lead to | ||
| 35 | * unexpected consequences. | ||
| 36 | */ | ||
| 37 | memset(&status, 0, sizeof(status)); | ||
| 38 | |||
| 39 | bd = (struct wcn36xx_rx_bd *)skb->data; | ||
| 40 | buff_to_be((u32 *)bd, sizeof(*bd)/sizeof(u32)); | ||
| 41 | wcn36xx_dbg_dump(WCN36XX_DBG_RX_DUMP, | ||
| 42 | "BD <<< ", (char *)bd, | ||
| 43 | sizeof(struct wcn36xx_rx_bd)); | ||
| 44 | |||
| 45 | skb_put(skb, bd->pdu.mpdu_header_off + bd->pdu.mpdu_len); | ||
| 46 | skb_pull(skb, bd->pdu.mpdu_header_off); | ||
| 47 | |||
| 48 | status.mactime = 10; | ||
| 49 | status.freq = WCN36XX_CENTER_FREQ(wcn); | ||
| 50 | status.band = WCN36XX_BAND(wcn); | ||
| 51 | status.signal = -get_rssi0(bd); | ||
| 52 | status.antenna = 1; | ||
| 53 | status.rate_idx = 1; | ||
| 54 | status.flag = 0; | ||
| 55 | status.rx_flags = 0; | ||
| 56 | status.flag |= RX_FLAG_IV_STRIPPED | | ||
| 57 | RX_FLAG_MMIC_STRIPPED | | ||
| 58 | RX_FLAG_DECRYPTED; | ||
| 59 | |||
| 60 | wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%x status->vendor_radiotap_len=%x\n", | ||
| 61 | status.flag, status.vendor_radiotap_len); | ||
| 62 | |||
| 63 | memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); | ||
| 64 | |||
| 65 | hdr = (struct ieee80211_hdr *) skb->data; | ||
| 66 | fc = __le16_to_cpu(hdr->frame_control); | ||
| 67 | sn = IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl)); | ||
| 68 | |||
| 69 | if (ieee80211_is_beacon(hdr->frame_control)) { | ||
| 70 | wcn36xx_dbg(WCN36XX_DBG_BEACON, "beacon skb %p len %d fc %04x sn %d\n", | ||
| 71 | skb, skb->len, fc, sn); | ||
| 72 | wcn36xx_dbg_dump(WCN36XX_DBG_BEACON_DUMP, "SKB <<< ", | ||
| 73 | (char *)skb->data, skb->len); | ||
| 74 | } else { | ||
| 75 | wcn36xx_dbg(WCN36XX_DBG_RX, "rx skb %p len %d fc %04x sn %d\n", | ||
| 76 | skb, skb->len, fc, sn); | ||
| 77 | wcn36xx_dbg_dump(WCN36XX_DBG_RX_DUMP, "SKB <<< ", | ||
| 78 | (char *)skb->data, skb->len); | ||
| 79 | } | ||
| 80 | |||
| 81 | ieee80211_rx_irqsafe(wcn->hw, skb); | ||
| 82 | |||
| 83 | return 0; | ||
| 84 | } | ||
| 85 | |||
| 86 | static void wcn36xx_set_tx_pdu(struct wcn36xx_tx_bd *bd, | ||
| 87 | u32 mpdu_header_len, | ||
| 88 | u32 len, | ||
| 89 | u16 tid) | ||
| 90 | { | ||
| 91 | bd->pdu.mpdu_header_len = mpdu_header_len; | ||
| 92 | bd->pdu.mpdu_header_off = sizeof(*bd); | ||
| 93 | bd->pdu.mpdu_data_off = bd->pdu.mpdu_header_len + | ||
| 94 | bd->pdu.mpdu_header_off; | ||
| 95 | bd->pdu.mpdu_len = len; | ||
| 96 | bd->pdu.tid = tid; | ||
| 97 | } | ||
| 98 | |||
| 99 | static inline struct wcn36xx_vif *get_vif_by_addr(struct wcn36xx *wcn, | ||
| 100 | u8 *addr) | ||
| 101 | { | ||
| 102 | struct wcn36xx_vif *vif_priv = NULL; | ||
| 103 | struct ieee80211_vif *vif = NULL; | ||
| 104 | list_for_each_entry(vif_priv, &wcn->vif_list, list) { | ||
| 105 | vif = container_of((void *)vif_priv, | ||
| 106 | struct ieee80211_vif, | ||
| 107 | drv_priv); | ||
| 108 | if (memcmp(vif->addr, addr, ETH_ALEN) == 0) | ||
| 109 | return vif_priv; | ||
| 110 | } | ||
| 111 | wcn36xx_warn("vif %pM not found\n", addr); | ||
| 112 | return NULL; | ||
| 113 | } | ||
| 114 | static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd, | ||
| 115 | struct wcn36xx *wcn, | ||
| 116 | struct wcn36xx_vif **vif_priv, | ||
| 117 | struct wcn36xx_sta *sta_priv, | ||
| 118 | struct ieee80211_hdr *hdr, | ||
| 119 | bool bcast) | ||
| 120 | { | ||
| 121 | struct ieee80211_vif *vif = NULL; | ||
| 122 | struct wcn36xx_vif *__vif_priv = NULL; | ||
| 123 | bd->bd_rate = WCN36XX_BD_RATE_DATA; | ||
| 124 | |||
| 125 | /* | ||
| 126 | * For not unicast frames mac80211 will not set sta pointer so use | ||
| 127 | * self_sta_index instead. | ||
| 128 | */ | ||
| 129 | if (sta_priv) { | ||
| 130 | __vif_priv = sta_priv->vif; | ||
| 131 | vif = container_of((void *)__vif_priv, | ||
| 132 | struct ieee80211_vif, | ||
| 133 | drv_priv); | ||
| 134 | |||
| 135 | if (vif->type == NL80211_IFTYPE_STATION) { | ||
| 136 | bd->sta_index = sta_priv->bss_sta_index; | ||
| 137 | bd->dpu_desc_idx = sta_priv->bss_dpu_desc_index; | ||
| 138 | } else if (vif->type == NL80211_IFTYPE_AP || | ||
| 139 | vif->type == NL80211_IFTYPE_ADHOC || | ||
| 140 | vif->type == NL80211_IFTYPE_MESH_POINT) { | ||
| 141 | bd->sta_index = sta_priv->sta_index; | ||
| 142 | bd->dpu_desc_idx = sta_priv->dpu_desc_index; | ||
| 143 | } | ||
| 144 | } else { | ||
| 145 | __vif_priv = get_vif_by_addr(wcn, hdr->addr2); | ||
| 146 | bd->sta_index = __vif_priv->self_sta_index; | ||
| 147 | bd->dpu_desc_idx = __vif_priv->self_dpu_desc_index; | ||
| 148 | } | ||
| 149 | |||
| 150 | bd->dpu_sign = __vif_priv->ucast_dpu_signature; | ||
| 151 | |||
| 152 | if (ieee80211_is_nullfunc(hdr->frame_control) || | ||
| 153 | (sta_priv && !sta_priv->is_data_encrypted)) | ||
| 154 | bd->dpu_ne = 1; | ||
| 155 | |||
| 156 | if (bcast) { | ||
| 157 | bd->ub = 1; | ||
| 158 | bd->ack_policy = 1; | ||
| 159 | } | ||
| 160 | *vif_priv = __vif_priv; | ||
| 161 | } | ||
| 162 | |||
| 163 | static void wcn36xx_set_tx_mgmt(struct wcn36xx_tx_bd *bd, | ||
| 164 | struct wcn36xx *wcn, | ||
| 165 | struct wcn36xx_vif **vif_priv, | ||
| 166 | struct ieee80211_hdr *hdr, | ||
| 167 | bool bcast) | ||
| 168 | { | ||
| 169 | struct wcn36xx_vif *__vif_priv = | ||
| 170 | get_vif_by_addr(wcn, hdr->addr2); | ||
| 171 | bd->sta_index = __vif_priv->self_sta_index; | ||
| 172 | bd->dpu_desc_idx = __vif_priv->self_dpu_desc_index; | ||
| 173 | bd->dpu_ne = 1; | ||
| 174 | |||
| 175 | /* default rate for unicast */ | ||
| 176 | if (ieee80211_is_mgmt(hdr->frame_control)) | ||
| 177 | bd->bd_rate = (WCN36XX_BAND(wcn) == IEEE80211_BAND_5GHZ) ? | ||
| 178 | WCN36XX_BD_RATE_CTRL : | ||
| 179 | WCN36XX_BD_RATE_MGMT; | ||
| 180 | else if (ieee80211_is_ctl(hdr->frame_control)) | ||
| 181 | bd->bd_rate = WCN36XX_BD_RATE_CTRL; | ||
| 182 | else | ||
| 183 | wcn36xx_warn("frame control type unknown\n"); | ||
| 184 | |||
| 185 | /* | ||
| 186 | * In joining state trick hardware that probe is sent as | ||
| 187 | * unicast even if address is broadcast. | ||
| 188 | */ | ||
| 189 | if (__vif_priv->is_joining && | ||
| 190 | ieee80211_is_probe_req(hdr->frame_control)) | ||
| 191 | bcast = false; | ||
| 192 | |||
| 193 | if (bcast) { | ||
| 194 | /* broadcast */ | ||
| 195 | bd->ub = 1; | ||
| 196 | /* No ack needed not unicast */ | ||
| 197 | bd->ack_policy = 1; | ||
| 198 | bd->queue_id = WCN36XX_TX_B_WQ_ID; | ||
| 199 | } else | ||
| 200 | bd->queue_id = WCN36XX_TX_U_WQ_ID; | ||
| 201 | *vif_priv = __vif_priv; | ||
| 202 | } | ||
| 203 | |||
| 204 | int wcn36xx_start_tx(struct wcn36xx *wcn, | ||
| 205 | struct wcn36xx_sta *sta_priv, | ||
| 206 | struct sk_buff *skb) | ||
| 207 | { | ||
| 208 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
| 209 | struct wcn36xx_vif *vif_priv = NULL; | ||
| 210 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
| 211 | unsigned long flags; | ||
| 212 | bool is_low = ieee80211_is_data(hdr->frame_control); | ||
| 213 | bool bcast = is_broadcast_ether_addr(hdr->addr1) || | ||
| 214 | is_multicast_ether_addr(hdr->addr1); | ||
| 215 | struct wcn36xx_tx_bd *bd = wcn36xx_dxe_get_next_bd(wcn, is_low); | ||
| 216 | |||
| 217 | if (!bd) { | ||
| 218 | /* | ||
| 219 | * TX DXE are used in pairs. One for the BD and one for the | ||
| 220 | * actual frame. The BD DXE's has a preallocated buffer while | ||
| 221 | * the skb ones does not. If this isn't true something is really | ||
| 222 | * wierd. TODO: Recover from this situation | ||
| 223 | */ | ||
| 224 | |||
| 225 | wcn36xx_err("bd address may not be NULL for BD DXE\n"); | ||
| 226 | return -EINVAL; | ||
| 227 | } | ||
| 228 | |||
| 229 | memset(bd, 0, sizeof(*bd)); | ||
| 230 | |||
| 231 | wcn36xx_dbg(WCN36XX_DBG_TX, | ||
| 232 | "tx skb %p len %d fc %04x sn %d %s %s\n", | ||
| 233 | skb, skb->len, __le16_to_cpu(hdr->frame_control), | ||
| 234 | IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl)), | ||
| 235 | is_low ? "low" : "high", bcast ? "bcast" : "ucast"); | ||
| 236 | |||
| 237 | wcn36xx_dbg_dump(WCN36XX_DBG_TX_DUMP, "", skb->data, skb->len); | ||
| 238 | |||
| 239 | bd->dpu_rf = WCN36XX_BMU_WQ_TX; | ||
| 240 | |||
| 241 | bd->tx_comp = info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
| 242 | if (bd->tx_comp) { | ||
| 243 | wcn36xx_dbg(WCN36XX_DBG_DXE, "TX_ACK status requested\n"); | ||
| 244 | spin_lock_irqsave(&wcn->dxe_lock, flags); | ||
| 245 | if (wcn->tx_ack_skb) { | ||
| 246 | spin_unlock_irqrestore(&wcn->dxe_lock, flags); | ||
| 247 | wcn36xx_warn("tx_ack_skb already set\n"); | ||
| 248 | return -EINVAL; | ||
| 249 | } | ||
| 250 | |||
| 251 | wcn->tx_ack_skb = skb; | ||
| 252 | spin_unlock_irqrestore(&wcn->dxe_lock, flags); | ||
| 253 | |||
| 254 | /* Only one at a time is supported by fw. Stop the TX queues | ||
| 255 | * until the ack status gets back. | ||
| 256 | * | ||
| 257 | * TODO: Add watchdog in case FW does not answer | ||
| 258 | */ | ||
| 259 | ieee80211_stop_queues(wcn->hw); | ||
| 260 | } | ||
| 261 | |||
| 262 | /* Data frames served first*/ | ||
| 263 | if (is_low) { | ||
| 264 | wcn36xx_set_tx_data(bd, wcn, &vif_priv, sta_priv, hdr, bcast); | ||
| 265 | wcn36xx_set_tx_pdu(bd, | ||
| 266 | ieee80211_is_data_qos(hdr->frame_control) ? | ||
| 267 | sizeof(struct ieee80211_qos_hdr) : | ||
| 268 | sizeof(struct ieee80211_hdr_3addr), | ||
| 269 | skb->len, sta_priv ? sta_priv->tid : 0); | ||
| 270 | } else { | ||
| 271 | /* MGMT and CTRL frames are handeld here*/ | ||
| 272 | wcn36xx_set_tx_mgmt(bd, wcn, &vif_priv, hdr, bcast); | ||
| 273 | wcn36xx_set_tx_pdu(bd, | ||
| 274 | ieee80211_is_data_qos(hdr->frame_control) ? | ||
| 275 | sizeof(struct ieee80211_qos_hdr) : | ||
| 276 | sizeof(struct ieee80211_hdr_3addr), | ||
| 277 | skb->len, WCN36XX_TID); | ||
| 278 | } | ||
| 279 | |||
| 280 | buff_to_be((u32 *)bd, sizeof(*bd)/sizeof(u32)); | ||
| 281 | bd->tx_bd_sign = 0xbdbdbdbd; | ||
| 282 | |||
| 283 | return wcn36xx_dxe_tx_frame(wcn, vif_priv, skb, is_low); | ||
| 284 | } | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.h b/drivers/net/wireless/ath/wcn36xx/txrx.h new file mode 100644 index 000000000000..bbfbcf808c77 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/txrx.h | |||
| @@ -0,0 +1,160 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef _TXRX_H_ | ||
| 18 | #define _TXRX_H_ | ||
| 19 | |||
| 20 | #include <linux/etherdevice.h> | ||
| 21 | #include "wcn36xx.h" | ||
| 22 | |||
| 23 | /* TODO describe all properties */ | ||
| 24 | #define WCN36XX_802_11_HEADER_LEN 24 | ||
| 25 | #define WCN36XX_BMU_WQ_TX 25 | ||
| 26 | #define WCN36XX_TID 7 | ||
| 27 | /* broadcast wq ID */ | ||
| 28 | #define WCN36XX_TX_B_WQ_ID 0xA | ||
| 29 | #define WCN36XX_TX_U_WQ_ID 0x9 | ||
| 30 | /* bd_rate */ | ||
| 31 | #define WCN36XX_BD_RATE_DATA 0 | ||
| 32 | #define WCN36XX_BD_RATE_MGMT 2 | ||
| 33 | #define WCN36XX_BD_RATE_CTRL 3 | ||
| 34 | |||
| 35 | struct wcn36xx_pdu { | ||
| 36 | u32 dpu_fb:8; | ||
| 37 | u32 adu_fb:8; | ||
| 38 | u32 pdu_id:16; | ||
| 39 | |||
| 40 | /* 0x04*/ | ||
| 41 | u32 tail_pdu_idx:16; | ||
| 42 | u32 head_pdu_idx:16; | ||
| 43 | |||
| 44 | /* 0x08*/ | ||
| 45 | u32 pdu_count:7; | ||
| 46 | u32 mpdu_data_off:9; | ||
| 47 | u32 mpdu_header_off:8; | ||
| 48 | u32 mpdu_header_len:8; | ||
| 49 | |||
| 50 | /* 0x0c*/ | ||
| 51 | u32 reserved4:8; | ||
| 52 | u32 tid:4; | ||
| 53 | u32 reserved3:4; | ||
| 54 | u32 mpdu_len:16; | ||
| 55 | }; | ||
| 56 | |||
| 57 | struct wcn36xx_rx_bd { | ||
| 58 | u32 bdt:2; | ||
| 59 | u32 ft:1; | ||
| 60 | u32 dpu_ne:1; | ||
| 61 | u32 rx_key_id:3; | ||
| 62 | u32 ub:1; | ||
| 63 | u32 rmf:1; | ||
| 64 | u32 uma_bypass:1; | ||
| 65 | u32 csr11:1; | ||
| 66 | u32 reserved0:1; | ||
| 67 | u32 scan_learn:1; | ||
| 68 | u32 rx_ch:4; | ||
| 69 | u32 rtsf:1; | ||
| 70 | u32 bsf:1; | ||
| 71 | u32 a2hf:1; | ||
| 72 | u32 st_auf:1; | ||
| 73 | u32 dpu_sign:3; | ||
| 74 | u32 dpu_rf:8; | ||
| 75 | |||
| 76 | struct wcn36xx_pdu pdu; | ||
| 77 | |||
| 78 | /* 0x14*/ | ||
| 79 | u32 addr3:8; | ||
| 80 | u32 addr2:8; | ||
| 81 | u32 addr1:8; | ||
| 82 | u32 dpu_desc_idx:8; | ||
| 83 | |||
| 84 | /* 0x18*/ | ||
| 85 | u32 rxp_flags:23; | ||
| 86 | u32 rate_id:9; | ||
| 87 | |||
| 88 | u32 phy_stat0; | ||
| 89 | u32 phy_stat1; | ||
| 90 | |||
| 91 | /* 0x24 */ | ||
| 92 | u32 rx_times; | ||
| 93 | |||
| 94 | u32 pmi_cmd[6]; | ||
| 95 | |||
| 96 | /* 0x40 */ | ||
| 97 | u32 reserved7:4; | ||
| 98 | u32 reorder_slot_id:6; | ||
| 99 | u32 reorder_fwd_id:6; | ||
| 100 | u32 reserved6:12; | ||
| 101 | u32 reorder_code:4; | ||
| 102 | |||
| 103 | /* 0x44 */ | ||
| 104 | u32 exp_seq_num:12; | ||
| 105 | u32 cur_seq_num:12; | ||
| 106 | u32 fr_type_subtype:8; | ||
| 107 | |||
| 108 | /* 0x48 */ | ||
| 109 | u32 msdu_size:16; | ||
| 110 | u32 sub_fr_id:4; | ||
| 111 | u32 proc_order:4; | ||
| 112 | u32 reserved9:4; | ||
| 113 | u32 aef:1; | ||
| 114 | u32 lsf:1; | ||
| 115 | u32 esf:1; | ||
| 116 | u32 asf:1; | ||
| 117 | }; | ||
| 118 | |||
| 119 | struct wcn36xx_tx_bd { | ||
| 120 | u32 bdt:2; | ||
| 121 | u32 ft:1; | ||
| 122 | u32 dpu_ne:1; | ||
| 123 | u32 fw_tx_comp:1; | ||
| 124 | u32 tx_comp:1; | ||
| 125 | u32 reserved1:1; | ||
| 126 | u32 ub:1; | ||
| 127 | u32 rmf:1; | ||
| 128 | u32 reserved0:12; | ||
| 129 | u32 dpu_sign:3; | ||
| 130 | u32 dpu_rf:8; | ||
| 131 | |||
| 132 | struct wcn36xx_pdu pdu; | ||
| 133 | |||
| 134 | /* 0x14*/ | ||
| 135 | u32 reserved5:7; | ||
| 136 | u32 queue_id:5; | ||
| 137 | u32 bd_rate:2; | ||
| 138 | u32 ack_policy:2; | ||
| 139 | u32 sta_index:8; | ||
| 140 | u32 dpu_desc_idx:8; | ||
| 141 | |||
| 142 | u32 tx_bd_sign; | ||
| 143 | u32 reserved6; | ||
| 144 | u32 dxe_start_time; | ||
| 145 | u32 dxe_end_time; | ||
| 146 | |||
| 147 | /*u32 tcp_udp_start_off:10; | ||
| 148 | u32 header_cks:16; | ||
| 149 | u32 reserved7:6;*/ | ||
| 150 | }; | ||
| 151 | |||
| 152 | struct wcn36xx_sta; | ||
| 153 | struct wcn36xx; | ||
| 154 | |||
| 155 | int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb); | ||
| 156 | int wcn36xx_start_tx(struct wcn36xx *wcn, | ||
| 157 | struct wcn36xx_sta *sta_priv, | ||
| 158 | struct sk_buff *skb); | ||
| 159 | |||
| 160 | #endif /* _TXRX_H_ */ | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h new file mode 100644 index 000000000000..58b63833e8e7 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h | |||
| @@ -0,0 +1,238 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef _WCN36XX_H_ | ||
| 18 | #define _WCN36XX_H_ | ||
| 19 | |||
| 20 | #include <linux/completion.h> | ||
| 21 | #include <linux/printk.h> | ||
| 22 | #include <linux/spinlock.h> | ||
| 23 | #include <net/mac80211.h> | ||
| 24 | |||
| 25 | #include "hal.h" | ||
| 26 | #include "smd.h" | ||
| 27 | #include "txrx.h" | ||
| 28 | #include "dxe.h" | ||
| 29 | #include "pmc.h" | ||
| 30 | #include "debug.h" | ||
| 31 | |||
| 32 | #define WLAN_NV_FILE "wlan/prima/WCNSS_qcom_wlan_nv.bin" | ||
| 33 | #define WCN36XX_AGGR_BUFFER_SIZE 64 | ||
| 34 | |||
| 35 | extern unsigned int wcn36xx_dbg_mask; | ||
| 36 | |||
| 37 | enum wcn36xx_debug_mask { | ||
| 38 | WCN36XX_DBG_DXE = 0x00000001, | ||
| 39 | WCN36XX_DBG_DXE_DUMP = 0x00000002, | ||
| 40 | WCN36XX_DBG_SMD = 0x00000004, | ||
| 41 | WCN36XX_DBG_SMD_DUMP = 0x00000008, | ||
| 42 | WCN36XX_DBG_RX = 0x00000010, | ||
| 43 | WCN36XX_DBG_RX_DUMP = 0x00000020, | ||
| 44 | WCN36XX_DBG_TX = 0x00000040, | ||
| 45 | WCN36XX_DBG_TX_DUMP = 0x00000080, | ||
| 46 | WCN36XX_DBG_HAL = 0x00000100, | ||
| 47 | WCN36XX_DBG_HAL_DUMP = 0x00000200, | ||
| 48 | WCN36XX_DBG_MAC = 0x00000400, | ||
| 49 | WCN36XX_DBG_BEACON = 0x00000800, | ||
| 50 | WCN36XX_DBG_BEACON_DUMP = 0x00001000, | ||
| 51 | WCN36XX_DBG_PMC = 0x00002000, | ||
| 52 | WCN36XX_DBG_PMC_DUMP = 0x00004000, | ||
| 53 | WCN36XX_DBG_ANY = 0xffffffff, | ||
| 54 | }; | ||
| 55 | |||
| 56 | #define wcn36xx_err(fmt, arg...) \ | ||
| 57 | printk(KERN_ERR pr_fmt("ERROR " fmt), ##arg); | ||
| 58 | |||
| 59 | #define wcn36xx_warn(fmt, arg...) \ | ||
| 60 | printk(KERN_WARNING pr_fmt("WARNING " fmt), ##arg) | ||
| 61 | |||
| 62 | #define wcn36xx_info(fmt, arg...) \ | ||
| 63 | printk(KERN_INFO pr_fmt(fmt), ##arg) | ||
| 64 | |||
| 65 | #define wcn36xx_dbg(mask, fmt, arg...) do { \ | ||
| 66 | if (wcn36xx_dbg_mask & mask) \ | ||
| 67 | printk(KERN_DEBUG pr_fmt(fmt), ##arg); \ | ||
| 68 | } while (0) | ||
| 69 | |||
| 70 | #define wcn36xx_dbg_dump(mask, prefix_str, buf, len) do { \ | ||
| 71 | if (wcn36xx_dbg_mask & mask) \ | ||
| 72 | print_hex_dump(KERN_DEBUG, pr_fmt(prefix_str), \ | ||
| 73 | DUMP_PREFIX_OFFSET, 32, 1, \ | ||
| 74 | buf, len, false); \ | ||
| 75 | } while (0) | ||
| 76 | |||
| 77 | #define WCN36XX_HW_CHANNEL(__wcn) (__wcn->hw->conf.chandef.chan->hw_value) | ||
| 78 | #define WCN36XX_BAND(__wcn) (__wcn->hw->conf.chandef.chan->band) | ||
| 79 | #define WCN36XX_CENTER_FREQ(__wcn) (__wcn->hw->conf.chandef.chan->center_freq) | ||
| 80 | #define WCN36XX_LISTEN_INTERVAL(__wcn) (__wcn->hw->conf.listen_interval) | ||
| 81 | #define WCN36XX_FLAGS(__wcn) (__wcn->hw->flags) | ||
| 82 | #define WCN36XX_MAX_POWER(__wcn) (__wcn->hw->conf.chandef.chan->max_power) | ||
| 83 | |||
| 84 | static inline void buff_to_be(u32 *buf, size_t len) | ||
| 85 | { | ||
| 86 | int i; | ||
| 87 | for (i = 0; i < len; i++) | ||
| 88 | buf[i] = cpu_to_be32(buf[i]); | ||
| 89 | } | ||
| 90 | |||
| 91 | struct nv_data { | ||
| 92 | int is_valid; | ||
| 93 | u8 table; | ||
| 94 | }; | ||
| 95 | |||
| 96 | /* Interface for platform control path | ||
| 97 | * | ||
| 98 | * @open: hook must be called when wcn36xx wants to open control channel. | ||
| 99 | * @tx: sends a buffer. | ||
| 100 | */ | ||
| 101 | struct wcn36xx_platform_ctrl_ops { | ||
| 102 | int (*open)(void *drv_priv, void *rsp_cb); | ||
| 103 | void (*close)(void); | ||
| 104 | int (*tx)(char *buf, size_t len); | ||
| 105 | int (*get_hw_mac)(u8 *addr); | ||
| 106 | int (*smsm_change_state)(u32 clear_mask, u32 set_mask); | ||
| 107 | }; | ||
| 108 | |||
| 109 | /** | ||
| 110 | * struct wcn36xx_vif - holds VIF related fields | ||
| 111 | * | ||
| 112 | * @bss_index: bss_index is initially set to 0xFF. bss_index is received from | ||
| 113 | * HW after first config_bss call and must be used in delete_bss and | ||
| 114 | * enter/exit_bmps. | ||
| 115 | */ | ||
| 116 | struct wcn36xx_vif { | ||
| 117 | struct list_head list; | ||
| 118 | struct wcn36xx_sta *sta; | ||
| 119 | u8 dtim_period; | ||
| 120 | enum ani_ed_type encrypt_type; | ||
| 121 | bool is_joining; | ||
| 122 | struct wcn36xx_hal_mac_ssid ssid; | ||
| 123 | |||
| 124 | /* Power management */ | ||
| 125 | enum wcn36xx_power_state pw_state; | ||
| 126 | |||
| 127 | u8 bss_index; | ||
| 128 | u8 ucast_dpu_signature; | ||
| 129 | /* Returned from WCN36XX_HAL_ADD_STA_SELF_RSP */ | ||
| 130 | u8 self_sta_index; | ||
| 131 | u8 self_dpu_desc_index; | ||
| 132 | }; | ||
| 133 | |||
| 134 | /** | ||
| 135 | * struct wcn36xx_sta - holds STA related fields | ||
| 136 | * | ||
| 137 | * @tid: traffic ID that is used during AMPDU and in TX BD. | ||
| 138 | * @sta_index: STA index is returned from HW after config_sta call and is | ||
| 139 | * used in both SMD channel and TX BD. | ||
| 140 | * @dpu_desc_index: DPU descriptor index is returned from HW after config_sta | ||
| 141 | * call and is used in TX BD. | ||
| 142 | * @bss_sta_index: STA index is returned from HW after config_bss call and is | ||
| 143 | * used in both SMD channel and TX BD. See table bellow when it is used. | ||
| 144 | * @bss_dpu_desc_index: DPU descriptor index is returned from HW after | ||
| 145 | * config_bss call and is used in TX BD. | ||
| 146 | * ______________________________________________ | ||
| 147 | * | | STA | AP | | ||
| 148 | * |______________|_____________|_______________| | ||
| 149 | * | TX BD |bss_sta_index| sta_index | | ||
| 150 | * |______________|_____________|_______________| | ||
| 151 | * |all SMD calls |bss_sta_index| sta_index | | ||
| 152 | * |______________|_____________|_______________| | ||
| 153 | * |smd_delete_sta| sta_index | sta_index | | ||
| 154 | * |______________|_____________|_______________| | ||
| 155 | */ | ||
| 156 | struct wcn36xx_sta { | ||
| 157 | struct wcn36xx_vif *vif; | ||
| 158 | u16 aid; | ||
| 159 | u16 tid; | ||
| 160 | u8 sta_index; | ||
| 161 | u8 dpu_desc_index; | ||
| 162 | u8 bss_sta_index; | ||
| 163 | u8 bss_dpu_desc_index; | ||
| 164 | bool is_data_encrypted; | ||
| 165 | /* Rates */ | ||
| 166 | struct wcn36xx_hal_supported_rates supported_rates; | ||
| 167 | }; | ||
| 168 | struct wcn36xx_dxe_ch; | ||
| 169 | struct wcn36xx { | ||
| 170 | struct ieee80211_hw *hw; | ||
| 171 | struct device *dev; | ||
| 172 | struct list_head vif_list; | ||
| 173 | |||
| 174 | u8 fw_revision; | ||
| 175 | u8 fw_version; | ||
| 176 | u8 fw_minor; | ||
| 177 | u8 fw_major; | ||
| 178 | |||
| 179 | /* extra byte for the NULL termination */ | ||
| 180 | u8 crm_version[WCN36XX_HAL_VERSION_LENGTH + 1]; | ||
| 181 | u8 wlan_version[WCN36XX_HAL_VERSION_LENGTH + 1]; | ||
| 182 | |||
| 183 | /* IRQs */ | ||
| 184 | int tx_irq; | ||
| 185 | int rx_irq; | ||
| 186 | void __iomem *mmio; | ||
| 187 | |||
| 188 | struct wcn36xx_platform_ctrl_ops *ctrl_ops; | ||
| 189 | /* | ||
| 190 | * smd_buf must be protected with smd_mutex to garantee | ||
| 191 | * that all messages are sent one after another | ||
| 192 | */ | ||
| 193 | u8 *hal_buf; | ||
| 194 | size_t hal_rsp_len; | ||
| 195 | struct mutex hal_mutex; | ||
| 196 | struct completion hal_rsp_compl; | ||
| 197 | struct workqueue_struct *hal_ind_wq; | ||
| 198 | struct work_struct hal_ind_work; | ||
| 199 | struct mutex hal_ind_mutex; | ||
| 200 | struct list_head hal_ind_queue; | ||
| 201 | |||
| 202 | /* DXE channels */ | ||
| 203 | struct wcn36xx_dxe_ch dxe_tx_l_ch; /* TX low */ | ||
| 204 | struct wcn36xx_dxe_ch dxe_tx_h_ch; /* TX high */ | ||
| 205 | struct wcn36xx_dxe_ch dxe_rx_l_ch; /* RX low */ | ||
| 206 | struct wcn36xx_dxe_ch dxe_rx_h_ch; /* RX high */ | ||
| 207 | |||
| 208 | /* For synchronization of DXE resources from BH, IRQ and WQ contexts */ | ||
| 209 | spinlock_t dxe_lock; | ||
| 210 | bool queues_stopped; | ||
| 211 | |||
| 212 | /* Memory pools */ | ||
| 213 | struct wcn36xx_dxe_mem_pool mgmt_mem_pool; | ||
| 214 | struct wcn36xx_dxe_mem_pool data_mem_pool; | ||
| 215 | |||
| 216 | struct sk_buff *tx_ack_skb; | ||
| 217 | |||
| 218 | #ifdef CONFIG_WCN36XX_DEBUGFS | ||
| 219 | /* Debug file system entry */ | ||
| 220 | struct wcn36xx_dfs_entry dfs; | ||
| 221 | #endif /* CONFIG_WCN36XX_DEBUGFS */ | ||
| 222 | |||
| 223 | }; | ||
| 224 | |||
| 225 | static inline bool wcn36xx_is_fw_version(struct wcn36xx *wcn, | ||
| 226 | u8 major, | ||
| 227 | u8 minor, | ||
| 228 | u8 version, | ||
| 229 | u8 revision) | ||
| 230 | { | ||
| 231 | return (wcn->fw_major == major && | ||
| 232 | wcn->fw_minor == minor && | ||
| 233 | wcn->fw_version == version && | ||
| 234 | wcn->fw_revision == revision); | ||
| 235 | } | ||
| 236 | void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates); | ||
| 237 | |||
| 238 | #endif /* _WCN36XX_H_ */ | ||
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 61c302a6bdea..5b340769d5bb 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c | |||
| @@ -316,8 +316,8 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, | |||
| 316 | } | 316 | } |
| 317 | conn.channel = ch - 1; | 317 | conn.channel = ch - 1; |
| 318 | 318 | ||
| 319 | memcpy(conn.bssid, bss->bssid, 6); | 319 | memcpy(conn.bssid, bss->bssid, ETH_ALEN); |
| 320 | memcpy(conn.dst_mac, bss->bssid, 6); | 320 | memcpy(conn.dst_mac, bss->bssid, ETH_ALEN); |
| 321 | /* | 321 | /* |
| 322 | * FW don't support scan after connection attempt | 322 | * FW don't support scan after connection attempt |
| 323 | */ | 323 | */ |
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c index eb1dc7ad80fb..eeceab39cda2 100644 --- a/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c | |||
| @@ -197,7 +197,6 @@ static void wil_pcie_remove(struct pci_dev *pdev) | |||
| 197 | pci_iounmap(pdev, wil->csr); | 197 | pci_iounmap(pdev, wil->csr); |
| 198 | pci_release_region(pdev, 0); | 198 | pci_release_region(pdev, 0); |
| 199 | pci_disable_device(pdev); | 199 | pci_disable_device(pdev); |
| 200 | pci_set_drvdata(pdev, NULL); | ||
| 201 | } | 200 | } |
| 202 | 201 | ||
| 203 | static DEFINE_PCI_DEVICE_TABLE(wil6210_pcie_ids) = { | 202 | static DEFINE_PCI_DEVICE_TABLE(wil6210_pcie_ids) = { |
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index b827d51c30a3..0d950f209dae 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c | |||
| @@ -844,18 +844,18 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) | |||
| 844 | if (priv->wep_is_on) | 844 | if (priv->wep_is_on) |
| 845 | frame_ctl |= IEEE80211_FCTL_PROTECTED; | 845 | frame_ctl |= IEEE80211_FCTL_PROTECTED; |
| 846 | if (priv->operating_mode == IW_MODE_ADHOC) { | 846 | if (priv->operating_mode == IW_MODE_ADHOC) { |
| 847 | skb_copy_from_linear_data(skb, &header.addr1, 6); | 847 | skb_copy_from_linear_data(skb, &header.addr1, ETH_ALEN); |
| 848 | memcpy(&header.addr2, dev->dev_addr, 6); | 848 | memcpy(&header.addr2, dev->dev_addr, ETH_ALEN); |
| 849 | memcpy(&header.addr3, priv->BSSID, 6); | 849 | memcpy(&header.addr3, priv->BSSID, ETH_ALEN); |
| 850 | } else { | 850 | } else { |
| 851 | frame_ctl |= IEEE80211_FCTL_TODS; | 851 | frame_ctl |= IEEE80211_FCTL_TODS; |
| 852 | memcpy(&header.addr1, priv->CurrentBSSID, 6); | 852 | memcpy(&header.addr1, priv->CurrentBSSID, ETH_ALEN); |
| 853 | memcpy(&header.addr2, dev->dev_addr, 6); | 853 | memcpy(&header.addr2, dev->dev_addr, ETH_ALEN); |
| 854 | skb_copy_from_linear_data(skb, &header.addr3, 6); | 854 | skb_copy_from_linear_data(skb, &header.addr3, ETH_ALEN); |
| 855 | } | 855 | } |
| 856 | 856 | ||
| 857 | if (priv->use_wpa) | 857 | if (priv->use_wpa) |
| 858 | memcpy(&header.addr4, SNAP_RFC1024, 6); | 858 | memcpy(&header.addr4, SNAP_RFC1024, ETH_ALEN); |
| 859 | 859 | ||
| 860 | header.frame_control = cpu_to_le16(frame_ctl); | 860 | header.frame_control = cpu_to_le16(frame_ctl); |
| 861 | /* Copy the wireless header into the card */ | 861 | /* Copy the wireless header into the card */ |
| @@ -929,11 +929,11 @@ static void fast_rx_path(struct atmel_private *priv, | |||
| 929 | } | 929 | } |
| 930 | } | 930 | } |
| 931 | 931 | ||
| 932 | memcpy(skbp, header->addr1, 6); /* destination address */ | 932 | memcpy(skbp, header->addr1, ETH_ALEN); /* destination address */ |
| 933 | if (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FROMDS) | 933 | if (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FROMDS) |
| 934 | memcpy(&skbp[6], header->addr3, 6); | 934 | memcpy(&skbp[ETH_ALEN], header->addr3, ETH_ALEN); |
| 935 | else | 935 | else |
| 936 | memcpy(&skbp[6], header->addr2, 6); /* source address */ | 936 | memcpy(&skbp[ETH_ALEN], header->addr2, ETH_ALEN); /* source address */ |
| 937 | 937 | ||
| 938 | skb->protocol = eth_type_trans(skb, priv->dev); | 938 | skb->protocol = eth_type_trans(skb, priv->dev); |
| 939 | skb->ip_summed = CHECKSUM_NONE; | 939 | skb->ip_summed = CHECKSUM_NONE; |
| @@ -969,14 +969,14 @@ static void frag_rx_path(struct atmel_private *priv, | |||
| 969 | u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no, | 969 | u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no, |
| 970 | u8 frag_no, int more_frags) | 970 | u8 frag_no, int more_frags) |
| 971 | { | 971 | { |
| 972 | u8 mac4[6]; | 972 | u8 mac4[ETH_ALEN]; |
| 973 | u8 source[6]; | 973 | u8 source[ETH_ALEN]; |
| 974 | struct sk_buff *skb; | 974 | struct sk_buff *skb; |
| 975 | 975 | ||
| 976 | if (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FROMDS) | 976 | if (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FROMDS) |
| 977 | memcpy(source, header->addr3, 6); | 977 | memcpy(source, header->addr3, ETH_ALEN); |
| 978 | else | 978 | else |
| 979 | memcpy(source, header->addr2, 6); | 979 | memcpy(source, header->addr2, ETH_ALEN); |
| 980 | 980 | ||
| 981 | rx_packet_loc += 24; /* skip header */ | 981 | rx_packet_loc += 24; /* skip header */ |
| 982 | 982 | ||
| @@ -984,9 +984,9 @@ static void frag_rx_path(struct atmel_private *priv, | |||
| 984 | msdu_size -= 4; | 984 | msdu_size -= 4; |
| 985 | 985 | ||
| 986 | if (frag_no == 0) { /* first fragment */ | 986 | if (frag_no == 0) { /* first fragment */ |
| 987 | atmel_copy_to_host(priv->dev, mac4, rx_packet_loc, 6); | 987 | atmel_copy_to_host(priv->dev, mac4, rx_packet_loc, ETH_ALEN); |
| 988 | msdu_size -= 6; | 988 | msdu_size -= ETH_ALEN; |
| 989 | rx_packet_loc += 6; | 989 | rx_packet_loc += ETH_ALEN; |
| 990 | 990 | ||
| 991 | if (priv->do_rx_crc) | 991 | if (priv->do_rx_crc) |
| 992 | crc = crc32_le(crc, mac4, 6); | 992 | crc = crc32_le(crc, mac4, 6); |
| @@ -994,9 +994,9 @@ static void frag_rx_path(struct atmel_private *priv, | |||
| 994 | priv->frag_seq = seq_no; | 994 | priv->frag_seq = seq_no; |
| 995 | priv->frag_no = 1; | 995 | priv->frag_no = 1; |
| 996 | priv->frag_len = msdu_size; | 996 | priv->frag_len = msdu_size; |
| 997 | memcpy(priv->frag_source, source, 6); | 997 | memcpy(priv->frag_source, source, ETH_ALEN); |
| 998 | memcpy(&priv->rx_buf[6], source, 6); | 998 | memcpy(&priv->rx_buf[ETH_ALEN], source, ETH_ALEN); |
| 999 | memcpy(priv->rx_buf, header->addr1, 6); | 999 | memcpy(priv->rx_buf, header->addr1, ETH_ALEN); |
| 1000 | 1000 | ||
| 1001 | atmel_copy_to_host(priv->dev, &priv->rx_buf[12], rx_packet_loc, msdu_size); | 1001 | atmel_copy_to_host(priv->dev, &priv->rx_buf[12], rx_packet_loc, msdu_size); |
| 1002 | 1002 | ||
| @@ -1006,13 +1006,13 @@ static void frag_rx_path(struct atmel_private *priv, | |||
| 1006 | atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + msdu_size, 4); | 1006 | atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + msdu_size, 4); |
| 1007 | if ((crc ^ 0xffffffff) != netcrc) { | 1007 | if ((crc ^ 0xffffffff) != netcrc) { |
| 1008 | priv->dev->stats.rx_crc_errors++; | 1008 | priv->dev->stats.rx_crc_errors++; |
| 1009 | memset(priv->frag_source, 0xff, 6); | 1009 | memset(priv->frag_source, 0xff, ETH_ALEN); |
| 1010 | } | 1010 | } |
| 1011 | } | 1011 | } |
| 1012 | 1012 | ||
| 1013 | } else if (priv->frag_no == frag_no && | 1013 | } else if (priv->frag_no == frag_no && |
| 1014 | priv->frag_seq == seq_no && | 1014 | priv->frag_seq == seq_no && |
| 1015 | memcmp(priv->frag_source, source, 6) == 0) { | 1015 | memcmp(priv->frag_source, source, ETH_ALEN) == 0) { |
| 1016 | 1016 | ||
| 1017 | atmel_copy_to_host(priv->dev, &priv->rx_buf[12 + priv->frag_len], | 1017 | atmel_copy_to_host(priv->dev, &priv->rx_buf[12 + priv->frag_len], |
| 1018 | rx_packet_loc, msdu_size); | 1018 | rx_packet_loc, msdu_size); |
| @@ -1024,7 +1024,7 @@ static void frag_rx_path(struct atmel_private *priv, | |||
| 1024 | atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + msdu_size, 4); | 1024 | atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + msdu_size, 4); |
| 1025 | if ((crc ^ 0xffffffff) != netcrc) { | 1025 | if ((crc ^ 0xffffffff) != netcrc) { |
| 1026 | priv->dev->stats.rx_crc_errors++; | 1026 | priv->dev->stats.rx_crc_errors++; |
| 1027 | memset(priv->frag_source, 0xff, 6); | 1027 | memset(priv->frag_source, 0xff, ETH_ALEN); |
| 1028 | more_frags = 1; /* don't send broken assembly */ | 1028 | more_frags = 1; /* don't send broken assembly */ |
| 1029 | } | 1029 | } |
| 1030 | } | 1030 | } |
| @@ -1033,7 +1033,7 @@ static void frag_rx_path(struct atmel_private *priv, | |||
| 1033 | priv->frag_no++; | 1033 | priv->frag_no++; |
| 1034 | 1034 | ||
| 1035 | if (!more_frags) { /* last one */ | 1035 | if (!more_frags) { /* last one */ |
| 1036 | memset(priv->frag_source, 0xff, 6); | 1036 | memset(priv->frag_source, 0xff, ETH_ALEN); |
| 1037 | if (!(skb = dev_alloc_skb(priv->frag_len + 14))) { | 1037 | if (!(skb = dev_alloc_skb(priv->frag_len + 14))) { |
| 1038 | priv->dev->stats.rx_dropped++; | 1038 | priv->dev->stats.rx_dropped++; |
| 1039 | } else { | 1039 | } else { |
| @@ -1129,7 +1129,7 @@ static void rx_done_irq(struct atmel_private *priv) | |||
| 1129 | atmel_copy_to_host(priv->dev, (unsigned char *)&priv->rx_buf, rx_packet_loc + 24, msdu_size); | 1129 | atmel_copy_to_host(priv->dev, (unsigned char *)&priv->rx_buf, rx_packet_loc + 24, msdu_size); |
| 1130 | 1130 | ||
| 1131 | /* we use the same buffer for frag reassembly and control packets */ | 1131 | /* we use the same buffer for frag reassembly and control packets */ |
| 1132 | memset(priv->frag_source, 0xff, 6); | 1132 | memset(priv->frag_source, 0xff, ETH_ALEN); |
| 1133 | 1133 | ||
| 1134 | if (priv->do_rx_crc) { | 1134 | if (priv->do_rx_crc) { |
| 1135 | /* last 4 octets is crc */ | 1135 | /* last 4 octets is crc */ |
| @@ -1557,7 +1557,7 @@ struct net_device *init_atmel_card(unsigned short irq, unsigned long port, | |||
| 1557 | priv->last_qual = jiffies; | 1557 | priv->last_qual = jiffies; |
| 1558 | priv->last_beacon_timestamp = 0; | 1558 | priv->last_beacon_timestamp = 0; |
| 1559 | memset(priv->frag_source, 0xff, sizeof(priv->frag_source)); | 1559 | memset(priv->frag_source, 0xff, sizeof(priv->frag_source)); |
| 1560 | memset(priv->BSSID, 0, 6); | 1560 | memset(priv->BSSID, 0, ETH_ALEN); |
| 1561 | priv->CurrentBSSID[0] = 0xFF; /* Initialize to something invalid.... */ | 1561 | priv->CurrentBSSID[0] = 0xFF; /* Initialize to something invalid.... */ |
| 1562 | priv->station_was_associated = 0; | 1562 | priv->station_was_associated = 0; |
| 1563 | 1563 | ||
| @@ -1718,7 +1718,7 @@ static int atmel_get_wap(struct net_device *dev, | |||
| 1718 | char *extra) | 1718 | char *extra) |
| 1719 | { | 1719 | { |
| 1720 | struct atmel_private *priv = netdev_priv(dev); | 1720 | struct atmel_private *priv = netdev_priv(dev); |
| 1721 | memcpy(awrq->sa_data, priv->CurrentBSSID, 6); | 1721 | memcpy(awrq->sa_data, priv->CurrentBSSID, ETH_ALEN); |
| 1722 | awrq->sa_family = ARPHRD_ETHER; | 1722 | awrq->sa_family = ARPHRD_ETHER; |
| 1723 | 1723 | ||
| 1724 | return 0; | 1724 | return 0; |
| @@ -2356,7 +2356,7 @@ static int atmel_get_scan(struct net_device *dev, | |||
| 2356 | for (i = 0; i < priv->BSS_list_entries; i++) { | 2356 | for (i = 0; i < priv->BSS_list_entries; i++) { |
| 2357 | iwe.cmd = SIOCGIWAP; | 2357 | iwe.cmd = SIOCGIWAP; |
| 2358 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | 2358 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; |
| 2359 | memcpy(iwe.u.ap_addr.sa_data, priv->BSSinfo[i].BSSID, 6); | 2359 | memcpy(iwe.u.ap_addr.sa_data, priv->BSSinfo[i].BSSID, ETH_ALEN); |
| 2360 | current_ev = iwe_stream_add_event(info, current_ev, | 2360 | current_ev = iwe_stream_add_event(info, current_ev, |
| 2361 | extra + IW_SCAN_MAX_DATA, | 2361 | extra + IW_SCAN_MAX_DATA, |
| 2362 | &iwe, IW_EV_ADDR_LEN); | 2362 | &iwe, IW_EV_ADDR_LEN); |
| @@ -2760,7 +2760,7 @@ static void atmel_enter_state(struct atmel_private *priv, int new_state) | |||
| 2760 | static void atmel_scan(struct atmel_private *priv, int specific_ssid) | 2760 | static void atmel_scan(struct atmel_private *priv, int specific_ssid) |
| 2761 | { | 2761 | { |
| 2762 | struct { | 2762 | struct { |
| 2763 | u8 BSSID[6]; | 2763 | u8 BSSID[ETH_ALEN]; |
| 2764 | u8 SSID[MAX_SSID_LENGTH]; | 2764 | u8 SSID[MAX_SSID_LENGTH]; |
| 2765 | u8 scan_type; | 2765 | u8 scan_type; |
| 2766 | u8 channel; | 2766 | u8 channel; |
| @@ -2771,7 +2771,7 @@ static void atmel_scan(struct atmel_private *priv, int specific_ssid) | |||
| 2771 | u8 SSID_size; | 2771 | u8 SSID_size; |
| 2772 | } cmd; | 2772 | } cmd; |
| 2773 | 2773 | ||
| 2774 | memset(cmd.BSSID, 0xff, 6); | 2774 | memset(cmd.BSSID, 0xff, ETH_ALEN); |
| 2775 | 2775 | ||
| 2776 | if (priv->fast_scan) { | 2776 | if (priv->fast_scan) { |
| 2777 | cmd.SSID_size = priv->SSID_size; | 2777 | cmd.SSID_size = priv->SSID_size; |
| @@ -2816,7 +2816,7 @@ static void join(struct atmel_private *priv, int type) | |||
| 2816 | 2816 | ||
| 2817 | cmd.SSID_size = priv->SSID_size; | 2817 | cmd.SSID_size = priv->SSID_size; |
| 2818 | memcpy(cmd.SSID, priv->SSID, priv->SSID_size); | 2818 | memcpy(cmd.SSID, priv->SSID, priv->SSID_size); |
| 2819 | memcpy(cmd.BSSID, priv->CurrentBSSID, 6); | 2819 | memcpy(cmd.BSSID, priv->CurrentBSSID, ETH_ALEN); |
| 2820 | cmd.channel = (priv->channel & 0x7f); | 2820 | cmd.channel = (priv->channel & 0x7f); |
| 2821 | cmd.BSS_type = type; | 2821 | cmd.BSS_type = type; |
| 2822 | cmd.timeout = cpu_to_le16(2000); | 2822 | cmd.timeout = cpu_to_le16(2000); |
| @@ -2837,7 +2837,7 @@ static void start(struct atmel_private *priv, int type) | |||
| 2837 | 2837 | ||
| 2838 | cmd.SSID_size = priv->SSID_size; | 2838 | cmd.SSID_size = priv->SSID_size; |
| 2839 | memcpy(cmd.SSID, priv->SSID, priv->SSID_size); | 2839 | memcpy(cmd.SSID, priv->SSID, priv->SSID_size); |
| 2840 | memcpy(cmd.BSSID, priv->BSSID, 6); | 2840 | memcpy(cmd.BSSID, priv->BSSID, ETH_ALEN); |
| 2841 | cmd.BSS_type = type; | 2841 | cmd.BSS_type = type; |
| 2842 | cmd.channel = (priv->channel & 0x7f); | 2842 | cmd.channel = (priv->channel & 0x7f); |
| 2843 | 2843 | ||
| @@ -2883,9 +2883,9 @@ static void send_authentication_request(struct atmel_private *priv, u16 system, | |||
| 2883 | header.frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH); | 2883 | header.frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH); |
| 2884 | header.duration_id = cpu_to_le16(0x8000); | 2884 | header.duration_id = cpu_to_le16(0x8000); |
| 2885 | header.seq_ctrl = 0; | 2885 | header.seq_ctrl = 0; |
| 2886 | memcpy(header.addr1, priv->CurrentBSSID, 6); | 2886 | memcpy(header.addr1, priv->CurrentBSSID, ETH_ALEN); |
| 2887 | memcpy(header.addr2, priv->dev->dev_addr, 6); | 2887 | memcpy(header.addr2, priv->dev->dev_addr, ETH_ALEN); |
| 2888 | memcpy(header.addr3, priv->CurrentBSSID, 6); | 2888 | memcpy(header.addr3, priv->CurrentBSSID, ETH_ALEN); |
| 2889 | 2889 | ||
| 2890 | if (priv->wep_is_on && priv->CurrentAuthentTransactionSeqNum != 1) | 2890 | if (priv->wep_is_on && priv->CurrentAuthentTransactionSeqNum != 1) |
| 2891 | /* no WEP for authentication frames with TrSeqNo 1 */ | 2891 | /* no WEP for authentication frames with TrSeqNo 1 */ |
| @@ -2916,7 +2916,7 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc) | |||
| 2916 | struct ass_req_format { | 2916 | struct ass_req_format { |
| 2917 | __le16 capability; | 2917 | __le16 capability; |
| 2918 | __le16 listen_interval; | 2918 | __le16 listen_interval; |
| 2919 | u8 ap[6]; /* nothing after here directly accessible */ | 2919 | u8 ap[ETH_ALEN]; /* nothing after here directly accessible */ |
| 2920 | u8 ssid_el_id; | 2920 | u8 ssid_el_id; |
| 2921 | u8 ssid_len; | 2921 | u8 ssid_len; |
| 2922 | u8 ssid[MAX_SSID_LENGTH]; | 2922 | u8 ssid[MAX_SSID_LENGTH]; |
| @@ -2930,9 +2930,9 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc) | |||
| 2930 | header.duration_id = cpu_to_le16(0x8000); | 2930 | header.duration_id = cpu_to_le16(0x8000); |
| 2931 | header.seq_ctrl = 0; | 2931 | header.seq_ctrl = 0; |
| 2932 | 2932 | ||
| 2933 | memcpy(header.addr1, priv->CurrentBSSID, 6); | 2933 | memcpy(header.addr1, priv->CurrentBSSID, ETH_ALEN); |
| 2934 | memcpy(header.addr2, priv->dev->dev_addr, 6); | 2934 | memcpy(header.addr2, priv->dev->dev_addr, ETH_ALEN); |
| 2935 | memcpy(header.addr3, priv->CurrentBSSID, 6); | 2935 | memcpy(header.addr3, priv->CurrentBSSID, ETH_ALEN); |
| 2936 | 2936 | ||
| 2937 | body.capability = cpu_to_le16(WLAN_CAPABILITY_ESS); | 2937 | body.capability = cpu_to_le16(WLAN_CAPABILITY_ESS); |
| 2938 | if (priv->wep_is_on) | 2938 | if (priv->wep_is_on) |
| @@ -2944,7 +2944,7 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc) | |||
| 2944 | 2944 | ||
| 2945 | /* current AP address - only in reassoc frame */ | 2945 | /* current AP address - only in reassoc frame */ |
| 2946 | if (is_reassoc) { | 2946 | if (is_reassoc) { |
| 2947 | memcpy(body.ap, priv->CurrentBSSID, 6); | 2947 | memcpy(body.ap, priv->CurrentBSSID, ETH_ALEN); |
| 2948 | ssid_el_p = &body.ssid_el_id; | 2948 | ssid_el_p = &body.ssid_el_id; |
| 2949 | bodysize = 18 + priv->SSID_size; | 2949 | bodysize = 18 + priv->SSID_size; |
| 2950 | } else { | 2950 | } else { |
| @@ -3021,7 +3021,7 @@ static void store_bss_info(struct atmel_private *priv, | |||
| 3021 | int i, index; | 3021 | int i, index; |
| 3022 | 3022 | ||
| 3023 | for (index = -1, i = 0; i < priv->BSS_list_entries; i++) | 3023 | for (index = -1, i = 0; i < priv->BSS_list_entries; i++) |
| 3024 | if (memcmp(bss, priv->BSSinfo[i].BSSID, 6) == 0) | 3024 | if (memcmp(bss, priv->BSSinfo[i].BSSID, ETH_ALEN) == 0) |
| 3025 | index = i; | 3025 | index = i; |
| 3026 | 3026 | ||
| 3027 | /* If we process a probe and an entry from this BSS exists | 3027 | /* If we process a probe and an entry from this BSS exists |
| @@ -3032,7 +3032,7 @@ static void store_bss_info(struct atmel_private *priv, | |||
| 3032 | if (priv->BSS_list_entries == MAX_BSS_ENTRIES) | 3032 | if (priv->BSS_list_entries == MAX_BSS_ENTRIES) |
| 3033 | return; | 3033 | return; |
| 3034 | index = priv->BSS_list_entries++; | 3034 | index = priv->BSS_list_entries++; |
| 3035 | memcpy(priv->BSSinfo[index].BSSID, bss, 6); | 3035 | memcpy(priv->BSSinfo[index].BSSID, bss, ETH_ALEN); |
| 3036 | priv->BSSinfo[index].RSSI = rssi; | 3036 | priv->BSSinfo[index].RSSI = rssi; |
| 3037 | } else { | 3037 | } else { |
| 3038 | if (rssi > priv->BSSinfo[index].RSSI) | 3038 | if (rssi > priv->BSSinfo[index].RSSI) |
| @@ -3212,7 +3212,7 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype) | |||
| 3212 | if (subtype == IEEE80211_STYPE_REASSOC_RESP && | 3212 | if (subtype == IEEE80211_STYPE_REASSOC_RESP && |
| 3213 | status != WLAN_STATUS_ASSOC_DENIED_RATES && | 3213 | status != WLAN_STATUS_ASSOC_DENIED_RATES && |
| 3214 | status != WLAN_STATUS_CAPS_UNSUPPORTED && | 3214 | status != WLAN_STATUS_CAPS_UNSUPPORTED && |
| 3215 | priv->AssociationRequestRetryCnt < MAX_ASSOCIATION_RETRIES) { | 3215 | priv->ReAssociationRequestRetryCnt < MAX_ASSOCIATION_RETRIES) { |
| 3216 | mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES); | 3216 | mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES); |
| 3217 | priv->ReAssociationRequestRetryCnt++; | 3217 | priv->ReAssociationRequestRetryCnt++; |
| 3218 | send_association_request(priv, 1); | 3218 | send_association_request(priv, 1); |
| @@ -3235,7 +3235,7 @@ static void atmel_join_bss(struct atmel_private *priv, int bss_index) | |||
| 3235 | { | 3235 | { |
| 3236 | struct bss_info *bss = &priv->BSSinfo[bss_index]; | 3236 | struct bss_info *bss = &priv->BSSinfo[bss_index]; |
| 3237 | 3237 | ||
| 3238 | memcpy(priv->CurrentBSSID, bss->BSSID, 6); | 3238 | memcpy(priv->CurrentBSSID, bss->BSSID, ETH_ALEN); |
| 3239 | memcpy(priv->SSID, bss->SSID, priv->SSID_size = bss->SSIDsize); | 3239 | memcpy(priv->SSID, bss->SSID, priv->SSID_size = bss->SSIDsize); |
| 3240 | 3240 | ||
| 3241 | /* The WPA stuff cares about the current AP address */ | 3241 | /* The WPA stuff cares about the current AP address */ |
| @@ -3767,7 +3767,7 @@ static int probe_atmel_card(struct net_device *dev) | |||
| 3767 | 0x00, 0x04, 0x25, 0x00, 0x00, 0x00 | 3767 | 0x00, 0x04, 0x25, 0x00, 0x00, 0x00 |
| 3768 | }; | 3768 | }; |
| 3769 | printk(KERN_ALERT "%s: *** Invalid MAC address. UPGRADE Firmware ****\n", dev->name); | 3769 | printk(KERN_ALERT "%s: *** Invalid MAC address. UPGRADE Firmware ****\n", dev->name); |
| 3770 | memcpy(dev->dev_addr, default_mac, 6); | 3770 | memcpy(dev->dev_addr, default_mac, ETH_ALEN); |
| 3771 | } | 3771 | } |
| 3772 | } | 3772 | } |
| 3773 | 3773 | ||
| @@ -3819,7 +3819,7 @@ static void build_wpa_mib(struct atmel_private *priv) | |||
| 3819 | 3819 | ||
| 3820 | struct { /* NB this is matched to the hardware, don't change. */ | 3820 | struct { /* NB this is matched to the hardware, don't change. */ |
| 3821 | u8 cipher_default_key_value[MAX_ENCRYPTION_KEYS][MAX_ENCRYPTION_KEY_SIZE]; | 3821 | u8 cipher_default_key_value[MAX_ENCRYPTION_KEYS][MAX_ENCRYPTION_KEY_SIZE]; |
| 3822 | u8 receiver_address[6]; | 3822 | u8 receiver_address[ETH_ALEN]; |
| 3823 | u8 wep_is_on; | 3823 | u8 wep_is_on; |
| 3824 | u8 default_key; /* 0..3 */ | 3824 | u8 default_key; /* 0..3 */ |
| 3825 | u8 group_key; | 3825 | u8 group_key; |
| @@ -3837,7 +3837,7 @@ static void build_wpa_mib(struct atmel_private *priv) | |||
| 3837 | 3837 | ||
| 3838 | mib.wep_is_on = priv->wep_is_on; | 3838 | mib.wep_is_on = priv->wep_is_on; |
| 3839 | mib.exclude_unencrypted = priv->exclude_unencrypted; | 3839 | mib.exclude_unencrypted = priv->exclude_unencrypted; |
| 3840 | memcpy(mib.receiver_address, priv->CurrentBSSID, 6); | 3840 | memcpy(mib.receiver_address, priv->CurrentBSSID, ETH_ALEN); |
| 3841 | 3841 | ||
| 3842 | /* zero all the keys before adding in valid ones. */ | 3842 | /* zero all the keys before adding in valid ones. */ |
| 3843 | memset(mib.cipher_default_key_value, 0, sizeof(mib.cipher_default_key_value)); | 3843 | memset(mib.cipher_default_key_value, 0, sizeof(mib.cipher_default_key_value)); |
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 7c970d3ae358..05ee7f10cc8f 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c | |||
| @@ -164,7 +164,8 @@ static void b43_nphy_rf_ctl_override_rev7(struct b43_wldev *dev, u16 field, | |||
| 164 | } | 164 | } |
| 165 | en_addr = en_addrs[override][i]; | 165 | en_addr = en_addrs[override][i]; |
| 166 | 166 | ||
| 167 | val_addr = (i == 0) ? e->val_addr_core0 : e->val_addr_core1; | 167 | if (e) |
| 168 | val_addr = (i == 0) ? e->val_addr_core0 : e->val_addr_core1; | ||
| 168 | 169 | ||
| 169 | if (off) { | 170 | if (off) { |
| 170 | b43_phy_mask(dev, en_addr, ~en_mask); | 171 | b43_phy_mask(dev, en_addr, ~en_mask); |
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 8cb206a89083..4ae63f4ddfb2 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c | |||
| @@ -278,7 +278,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, | |||
| 278 | else | 278 | else |
| 279 | txhdr->phy_rate = b43_plcp_get_ratecode_cck(rate); | 279 | txhdr->phy_rate = b43_plcp_get_ratecode_cck(rate); |
| 280 | txhdr->mac_frame_ctl = wlhdr->frame_control; | 280 | txhdr->mac_frame_ctl = wlhdr->frame_control; |
| 281 | memcpy(txhdr->tx_receiver, wlhdr->addr1, 6); | 281 | memcpy(txhdr->tx_receiver, wlhdr->addr1, ETH_ALEN); |
| 282 | 282 | ||
| 283 | /* Calculate duration for fallback rate */ | 283 | /* Calculate duration for fallback rate */ |
| 284 | if ((rate_fb == rate) || | 284 | if ((rate_fb == rate) || |
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c index 849a28c80302..86588c9ff0f2 100644 --- a/drivers/net/wireless/b43legacy/xmit.c +++ b/drivers/net/wireless/b43legacy/xmit.c | |||
| @@ -215,7 +215,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, | |||
| 215 | rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value); | 215 | rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value); |
| 216 | 216 | ||
| 217 | txhdr->mac_frame_ctl = wlhdr->frame_control; | 217 | txhdr->mac_frame_ctl = wlhdr->frame_control; |
| 218 | memcpy(txhdr->tx_receiver, wlhdr->addr1, 6); | 218 | memcpy(txhdr->tx_receiver, wlhdr->addr1, ETH_ALEN); |
| 219 | 219 | ||
| 220 | /* Calculate duration for fallback rate */ | 220 | /* Calculate duration for fallback rate */ |
| 221 | if ((rate_fb->hw_value == rate) || | 221 | if ((rate_fb->hw_value == rate) || |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index e13b1a65c65f..3e10b801eee8 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
| @@ -26,7 +26,6 @@ | |||
| 26 | #include <linux/mmc/sdio.h> | 26 | #include <linux/mmc/sdio.h> |
| 27 | #include <linux/mmc/sdio_func.h> | 27 | #include <linux/mmc/sdio_func.h> |
| 28 | #include <linux/mmc/card.h> | 28 | #include <linux/mmc/card.h> |
| 29 | #include <linux/mmc/host.h> | ||
| 30 | #include <linux/platform_data/brcmfmac-sdio.h> | 29 | #include <linux/platform_data/brcmfmac-sdio.h> |
| 31 | 30 | ||
| 32 | #include <defs.h> | 31 | #include <defs.h> |
| @@ -239,7 +238,9 @@ brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
| 239 | func_num = SDIO_FUNC_1; | 238 | func_num = SDIO_FUNC_1; |
| 240 | reg_size = 4; | 239 | reg_size = 4; |
| 241 | 240 | ||
| 242 | brcmf_sdio_addrprep(sdiodev, reg_size, &addr); | 241 | ret = brcmf_sdio_addrprep(sdiodev, reg_size, &addr); |
| 242 | if (ret) | ||
| 243 | goto done; | ||
| 243 | } | 244 | } |
| 244 | 245 | ||
| 245 | do { | 246 | do { |
| @@ -255,6 +256,7 @@ brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
| 255 | func_num, addr, data, 4); | 256 | func_num, addr, data, 4); |
| 256 | } while (ret != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); | 257 | } while (ret != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); |
| 257 | 258 | ||
| 259 | done: | ||
| 258 | if (ret != 0) | 260 | if (ret != 0) |
| 259 | brcmf_err("failed with %d\n", ret); | 261 | brcmf_err("failed with %d\n", ret); |
| 260 | 262 | ||
| @@ -315,8 +317,36 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
| 315 | *ret = retval; | 317 | *ret = retval; |
| 316 | } | 318 | } |
| 317 | 319 | ||
| 320 | static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, | ||
| 321 | bool write, u32 addr, struct sk_buff *pkt) | ||
| 322 | { | ||
| 323 | unsigned int req_sz; | ||
| 324 | |||
| 325 | brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait); | ||
| 326 | if (brcmf_pm_resume_error(sdiodev)) | ||
| 327 | return -EIO; | ||
| 328 | |||
| 329 | /* Single skb use the standard mmc interface */ | ||
| 330 | req_sz = pkt->len + 3; | ||
| 331 | req_sz &= (uint)~3; | ||
| 332 | |||
| 333 | if (write) | ||
| 334 | return sdio_memcpy_toio(sdiodev->func[fn], addr, | ||
| 335 | ((u8 *)(pkt->data)), | ||
| 336 | req_sz); | ||
| 337 | else if (fn == 1) | ||
| 338 | return sdio_memcpy_fromio(sdiodev->func[fn], | ||
| 339 | ((u8 *)(pkt->data)), | ||
| 340 | addr, req_sz); | ||
| 341 | else | ||
| 342 | /* function 2 read is FIFO operation */ | ||
| 343 | return sdio_readsb(sdiodev->func[fn], | ||
| 344 | ((u8 *)(pkt->data)), addr, | ||
| 345 | req_sz); | ||
| 346 | } | ||
| 347 | |||
| 318 | /** | 348 | /** |
| 319 | * brcmf_sdio_buffrw - SDIO interface function for block data access | 349 | * brcmf_sdio_sglist_rw - SDIO interface function for block data access |
| 320 | * @sdiodev: brcmfmac sdio device | 350 | * @sdiodev: brcmfmac sdio device |
| 321 | * @fn: SDIO function number | 351 | * @fn: SDIO function number |
| 322 | * @write: direction flag | 352 | * @write: direction flag |
| @@ -327,12 +357,13 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
| 327 | * stack for block data access. It assumes that the skb passed down by the | 357 | * stack for block data access. It assumes that the skb passed down by the |
| 328 | * caller has already been padded and aligned. | 358 | * caller has already been padded and aligned. |
| 329 | */ | 359 | */ |
| 330 | static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, | 360 | static int brcmf_sdio_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn, |
| 331 | bool write, u32 addr, struct sk_buff_head *pktlist) | 361 | bool write, u32 addr, |
| 362 | struct sk_buff_head *pktlist) | ||
| 332 | { | 363 | { |
| 333 | unsigned int req_sz, func_blk_sz, sg_cnt, sg_data_sz, pkt_offset; | 364 | unsigned int req_sz, func_blk_sz, sg_cnt, sg_data_sz, pkt_offset; |
| 334 | unsigned int max_blks, max_req_sz, orig_offset, dst_offset; | 365 | unsigned int max_req_sz, orig_offset, dst_offset; |
| 335 | unsigned short max_seg_sz, seg_sz; | 366 | unsigned short max_seg_cnt, seg_sz; |
| 336 | unsigned char *pkt_data, *orig_data, *dst_data; | 367 | unsigned char *pkt_data, *orig_data, *dst_data; |
| 337 | struct sk_buff *pkt_next = NULL, *local_pkt_next; | 368 | struct sk_buff *pkt_next = NULL, *local_pkt_next; |
| 338 | struct sk_buff_head local_list, *target_list; | 369 | struct sk_buff_head local_list, *target_list; |
| @@ -341,7 +372,6 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
| 341 | struct mmc_data mmc_dat; | 372 | struct mmc_data mmc_dat; |
| 342 | struct sg_table st; | 373 | struct sg_table st; |
| 343 | struct scatterlist *sgl; | 374 | struct scatterlist *sgl; |
| 344 | struct mmc_host *host; | ||
| 345 | int ret = 0; | 375 | int ret = 0; |
| 346 | 376 | ||
| 347 | if (!pktlist->qlen) | 377 | if (!pktlist->qlen) |
| @@ -351,27 +381,6 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
| 351 | if (brcmf_pm_resume_error(sdiodev)) | 381 | if (brcmf_pm_resume_error(sdiodev)) |
| 352 | return -EIO; | 382 | return -EIO; |
| 353 | 383 | ||
| 354 | /* Single skb use the standard mmc interface */ | ||
| 355 | if (pktlist->qlen == 1) { | ||
| 356 | pkt_next = pktlist->next; | ||
| 357 | req_sz = pkt_next->len + 3; | ||
| 358 | req_sz &= (uint)~3; | ||
| 359 | |||
| 360 | if (write) | ||
| 361 | return sdio_memcpy_toio(sdiodev->func[fn], addr, | ||
| 362 | ((u8 *)(pkt_next->data)), | ||
| 363 | req_sz); | ||
| 364 | else if (fn == 1) | ||
| 365 | return sdio_memcpy_fromio(sdiodev->func[fn], | ||
| 366 | ((u8 *)(pkt_next->data)), | ||
| 367 | addr, req_sz); | ||
| 368 | else | ||
| 369 | /* function 2 read is FIFO operation */ | ||
| 370 | return sdio_readsb(sdiodev->func[fn], | ||
| 371 | ((u8 *)(pkt_next->data)), addr, | ||
| 372 | req_sz); | ||
| 373 | } | ||
| 374 | |||
| 375 | target_list = pktlist; | 384 | target_list = pktlist; |
| 376 | /* for host with broken sg support, prepare a page aligned list */ | 385 | /* for host with broken sg support, prepare a page aligned list */ |
| 377 | __skb_queue_head_init(&local_list); | 386 | __skb_queue_head_init(&local_list); |
| @@ -398,38 +407,46 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
| 398 | target_list = &local_list; | 407 | target_list = &local_list; |
| 399 | } | 408 | } |
| 400 | 409 | ||
| 401 | host = sdiodev->func[fn]->card->host; | ||
| 402 | func_blk_sz = sdiodev->func[fn]->cur_blksize; | 410 | func_blk_sz = sdiodev->func[fn]->cur_blksize; |
| 403 | /* Blocks per command is limited by host count, host transfer | 411 | max_req_sz = sdiodev->max_request_size; |
| 404 | * size and the maximum for IO_RW_EXTENDED of 511 blocks. | 412 | max_seg_cnt = min_t(unsigned short, sdiodev->max_segment_count, |
| 405 | */ | 413 | target_list->qlen); |
| 406 | max_blks = min_t(unsigned int, host->max_blk_count, 511u); | ||
| 407 | max_req_sz = min_t(unsigned int, host->max_req_size, | ||
| 408 | max_blks * func_blk_sz); | ||
| 409 | max_seg_sz = min_t(unsigned short, host->max_segs, SG_MAX_SINGLE_ALLOC); | ||
| 410 | max_seg_sz = min_t(unsigned short, max_seg_sz, target_list->qlen); | ||
| 411 | seg_sz = target_list->qlen; | 414 | seg_sz = target_list->qlen; |
| 412 | pkt_offset = 0; | 415 | pkt_offset = 0; |
| 413 | pkt_next = target_list->next; | 416 | pkt_next = target_list->next; |
| 414 | 417 | ||
| 415 | if (sg_alloc_table(&st, max_seg_sz, GFP_KERNEL)) { | 418 | if (sg_alloc_table(&st, max_seg_cnt, GFP_KERNEL)) { |
| 416 | ret = -ENOMEM; | 419 | ret = -ENOMEM; |
| 417 | goto exit; | 420 | goto exit; |
| 418 | } | 421 | } |
| 419 | 422 | ||
| 423 | memset(&mmc_req, 0, sizeof(struct mmc_request)); | ||
| 424 | memset(&mmc_cmd, 0, sizeof(struct mmc_command)); | ||
| 425 | memset(&mmc_dat, 0, sizeof(struct mmc_data)); | ||
| 426 | |||
| 427 | mmc_dat.sg = st.sgl; | ||
| 428 | mmc_dat.blksz = func_blk_sz; | ||
| 429 | mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; | ||
| 430 | mmc_cmd.opcode = SD_IO_RW_EXTENDED; | ||
| 431 | mmc_cmd.arg = write ? 1<<31 : 0; /* write flag */ | ||
| 432 | mmc_cmd.arg |= (fn & 0x7) << 28; /* SDIO func num */ | ||
| 433 | mmc_cmd.arg |= 1<<27; /* block mode */ | ||
| 434 | /* for function 1 the addr will be incremented */ | ||
| 435 | mmc_cmd.arg |= (fn == 1) ? 1<<26 : 0; | ||
| 436 | mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC; | ||
| 437 | mmc_req.cmd = &mmc_cmd; | ||
| 438 | mmc_req.data = &mmc_dat; | ||
| 439 | |||
| 420 | while (seg_sz) { | 440 | while (seg_sz) { |
| 421 | req_sz = 0; | 441 | req_sz = 0; |
| 422 | sg_cnt = 0; | 442 | sg_cnt = 0; |
| 423 | memset(&mmc_req, 0, sizeof(struct mmc_request)); | ||
| 424 | memset(&mmc_cmd, 0, sizeof(struct mmc_command)); | ||
| 425 | memset(&mmc_dat, 0, sizeof(struct mmc_data)); | ||
| 426 | sgl = st.sgl; | 443 | sgl = st.sgl; |
| 427 | /* prep sg table */ | 444 | /* prep sg table */ |
| 428 | while (pkt_next != (struct sk_buff *)target_list) { | 445 | while (pkt_next != (struct sk_buff *)target_list) { |
| 429 | pkt_data = pkt_next->data + pkt_offset; | 446 | pkt_data = pkt_next->data + pkt_offset; |
| 430 | sg_data_sz = pkt_next->len - pkt_offset; | 447 | sg_data_sz = pkt_next->len - pkt_offset; |
| 431 | if (sg_data_sz > host->max_seg_size) | 448 | if (sg_data_sz > sdiodev->max_segment_size) |
| 432 | sg_data_sz = host->max_seg_size; | 449 | sg_data_sz = sdiodev->max_segment_size; |
| 433 | if (sg_data_sz > max_req_sz - req_sz) | 450 | if (sg_data_sz > max_req_sz - req_sz) |
| 434 | sg_data_sz = max_req_sz - req_sz; | 451 | sg_data_sz = max_req_sz - req_sz; |
| 435 | 452 | ||
| @@ -444,7 +461,7 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
| 444 | pkt_next = pkt_next->next; | 461 | pkt_next = pkt_next->next; |
| 445 | } | 462 | } |
| 446 | 463 | ||
| 447 | if (req_sz >= max_req_sz || sg_cnt >= max_seg_sz) | 464 | if (req_sz >= max_req_sz || sg_cnt >= max_seg_cnt) |
| 448 | break; | 465 | break; |
| 449 | } | 466 | } |
| 450 | seg_sz -= sg_cnt; | 467 | seg_sz -= sg_cnt; |
| @@ -455,27 +472,17 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
| 455 | ret = -ENOTBLK; | 472 | ret = -ENOTBLK; |
| 456 | goto exit; | 473 | goto exit; |
| 457 | } | 474 | } |
| 458 | mmc_dat.sg = st.sgl; | 475 | |
| 459 | mmc_dat.sg_len = sg_cnt; | 476 | mmc_dat.sg_len = sg_cnt; |
| 460 | mmc_dat.blksz = func_blk_sz; | ||
| 461 | mmc_dat.blocks = req_sz / func_blk_sz; | 477 | mmc_dat.blocks = req_sz / func_blk_sz; |
| 462 | mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; | ||
| 463 | mmc_cmd.opcode = SD_IO_RW_EXTENDED; | ||
| 464 | mmc_cmd.arg = write ? 1<<31 : 0; /* write flag */ | ||
| 465 | mmc_cmd.arg |= (fn & 0x7) << 28; /* SDIO func num */ | ||
| 466 | mmc_cmd.arg |= 1<<27; /* block mode */ | ||
| 467 | /* incrementing addr for function 1 */ | ||
| 468 | mmc_cmd.arg |= (fn == 1) ? 1<<26 : 0; | ||
| 469 | mmc_cmd.arg |= (addr & 0x1FFFF) << 9; /* address */ | 478 | mmc_cmd.arg |= (addr & 0x1FFFF) << 9; /* address */ |
| 470 | mmc_cmd.arg |= mmc_dat.blocks & 0x1FF; /* block count */ | 479 | mmc_cmd.arg |= mmc_dat.blocks & 0x1FF; /* block count */ |
| 471 | mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC; | 480 | /* incrementing addr for function 1 */ |
| 472 | mmc_req.cmd = &mmc_cmd; | ||
| 473 | mmc_req.data = &mmc_dat; | ||
| 474 | if (fn == 1) | 481 | if (fn == 1) |
| 475 | addr += req_sz; | 482 | addr += req_sz; |
| 476 | 483 | ||
| 477 | mmc_set_data_timeout(&mmc_dat, sdiodev->func[fn]->card); | 484 | mmc_set_data_timeout(&mmc_dat, sdiodev->func[fn]->card); |
| 478 | mmc_wait_for_req(host, &mmc_req); | 485 | mmc_wait_for_req(sdiodev->func[fn]->card->host, &mmc_req); |
| 479 | 486 | ||
| 480 | ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error; | 487 | ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error; |
| 481 | if (ret != 0) { | 488 | if (ret != 0) { |
| @@ -546,7 +553,6 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
| 546 | { | 553 | { |
| 547 | uint width; | 554 | uint width; |
| 548 | int err = 0; | 555 | int err = 0; |
| 549 | struct sk_buff_head pkt_list; | ||
| 550 | 556 | ||
| 551 | brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n", | 557 | brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n", |
| 552 | fn, addr, pkt->len); | 558 | fn, addr, pkt->len); |
| @@ -556,19 +562,17 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
| 556 | if (err) | 562 | if (err) |
| 557 | goto done; | 563 | goto done; |
| 558 | 564 | ||
| 559 | skb_queue_head_init(&pkt_list); | 565 | err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pkt); |
| 560 | skb_queue_tail(&pkt_list, pkt); | ||
| 561 | err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, &pkt_list); | ||
| 562 | skb_dequeue_tail(&pkt_list); | ||
| 563 | 566 | ||
| 564 | done: | 567 | done: |
| 565 | return err; | 568 | return err; |
| 566 | } | 569 | } |
| 567 | 570 | ||
| 568 | int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | 571 | int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, |
| 569 | uint flags, struct sk_buff_head *pktq) | 572 | uint flags, struct sk_buff_head *pktq, uint totlen) |
| 570 | { | 573 | { |
| 571 | uint incr_fix; | 574 | struct sk_buff *glom_skb; |
| 575 | struct sk_buff *skb; | ||
| 572 | uint width; | 576 | uint width; |
| 573 | int err = 0; | 577 | int err = 0; |
| 574 | 578 | ||
| @@ -580,8 +584,22 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
| 580 | if (err) | 584 | if (err) |
| 581 | goto done; | 585 | goto done; |
| 582 | 586 | ||
| 583 | incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; | 587 | if (pktq->qlen == 1) |
| 584 | err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pktq); | 588 | err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pktq->next); |
| 589 | else if (!sdiodev->sg_support) { | ||
| 590 | glom_skb = brcmu_pkt_buf_get_skb(totlen); | ||
| 591 | if (!glom_skb) | ||
| 592 | return -ENOMEM; | ||
| 593 | err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, glom_skb); | ||
| 594 | if (err) | ||
| 595 | goto done; | ||
| 596 | |||
| 597 | skb_queue_walk(pktq, skb) { | ||
| 598 | memcpy(skb->data, glom_skb->data, skb->len); | ||
| 599 | skb_pull(glom_skb, skb->len); | ||
| 600 | } | ||
| 601 | } else | ||
| 602 | err = brcmf_sdio_sglist_rw(sdiodev, fn, false, addr, pktq); | ||
| 585 | 603 | ||
| 586 | done: | 604 | done: |
| 587 | return err; | 605 | return err; |
| @@ -592,7 +610,7 @@ brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
| 592 | uint flags, u8 *buf, uint nbytes) | 610 | uint flags, u8 *buf, uint nbytes) |
| 593 | { | 611 | { |
| 594 | struct sk_buff *mypkt; | 612 | struct sk_buff *mypkt; |
| 595 | struct sk_buff_head pktq; | 613 | uint width; |
| 596 | int err; | 614 | int err; |
| 597 | 615 | ||
| 598 | mypkt = brcmu_pkt_buf_get_skb(nbytes); | 616 | mypkt = brcmu_pkt_buf_get_skb(nbytes); |
| @@ -603,10 +621,12 @@ brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
| 603 | } | 621 | } |
| 604 | 622 | ||
| 605 | memcpy(mypkt->data, buf, nbytes); | 623 | memcpy(mypkt->data, buf, nbytes); |
| 606 | __skb_queue_head_init(&pktq); | 624 | |
| 607 | __skb_queue_tail(&pktq, mypkt); | 625 | width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; |
| 608 | err = brcmf_sdcard_send_pkt(sdiodev, addr, fn, flags, &pktq); | 626 | err = brcmf_sdio_addrprep(sdiodev, width, &addr); |
| 609 | __skb_dequeue_tail(&pktq); | 627 | |
| 628 | if (!err) | ||
| 629 | err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, mypkt); | ||
| 610 | 630 | ||
| 611 | brcmu_pkt_buf_free_skb(mypkt); | 631 | brcmu_pkt_buf_free_skb(mypkt); |
| 612 | return err; | 632 | return err; |
| @@ -617,16 +637,26 @@ int | |||
| 617 | brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | 637 | brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, |
| 618 | uint flags, struct sk_buff_head *pktq) | 638 | uint flags, struct sk_buff_head *pktq) |
| 619 | { | 639 | { |
| 640 | struct sk_buff *skb; | ||
| 620 | uint width; | 641 | uint width; |
| 621 | int err = 0; | 642 | int err; |
| 622 | 643 | ||
| 623 | brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n", | 644 | brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n", |
| 624 | fn, addr, pktq->qlen); | 645 | fn, addr, pktq->qlen); |
| 625 | 646 | ||
| 626 | width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; | 647 | width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; |
| 627 | brcmf_sdio_addrprep(sdiodev, width, &addr); | 648 | err = brcmf_sdio_addrprep(sdiodev, width, &addr); |
| 649 | if (err) | ||
| 650 | return err; | ||
| 628 | 651 | ||
| 629 | err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, pktq); | 652 | if (pktq->qlen == 1 || !sdiodev->sg_support) |
| 653 | skb_queue_walk(pktq, skb) { | ||
| 654 | err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, skb); | ||
| 655 | if (err) | ||
| 656 | break; | ||
| 657 | } | ||
| 658 | else | ||
| 659 | err = brcmf_sdio_sglist_rw(sdiodev, fn, true, addr, pktq); | ||
| 630 | 660 | ||
| 631 | return err; | 661 | return err; |
| 632 | } | 662 | } |
| @@ -639,7 +669,6 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, | |||
| 639 | struct sk_buff *pkt; | 669 | struct sk_buff *pkt; |
| 640 | u32 sdaddr; | 670 | u32 sdaddr; |
| 641 | uint dsize; | 671 | uint dsize; |
| 642 | struct sk_buff_head pkt_list; | ||
| 643 | 672 | ||
| 644 | dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size); | 673 | dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size); |
| 645 | pkt = dev_alloc_skb(dsize); | 674 | pkt = dev_alloc_skb(dsize); |
| @@ -648,7 +677,6 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, | |||
| 648 | return -EIO; | 677 | return -EIO; |
| 649 | } | 678 | } |
| 650 | pkt->priority = 0; | 679 | pkt->priority = 0; |
| 651 | skb_queue_head_init(&pkt_list); | ||
| 652 | 680 | ||
| 653 | /* Determine initial transfer parameters */ | 681 | /* Determine initial transfer parameters */ |
| 654 | sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK; | 682 | sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK; |
| @@ -676,10 +704,8 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, | |||
| 676 | skb_put(pkt, dsize); | 704 | skb_put(pkt, dsize); |
| 677 | if (write) | 705 | if (write) |
| 678 | memcpy(pkt->data, data, dsize); | 706 | memcpy(pkt->data, data, dsize); |
| 679 | skb_queue_tail(&pkt_list, pkt); | ||
| 680 | bcmerror = brcmf_sdio_buffrw(sdiodev, SDIO_FUNC_1, write, | 707 | bcmerror = brcmf_sdio_buffrw(sdiodev, SDIO_FUNC_1, write, |
| 681 | sdaddr, &pkt_list); | 708 | sdaddr, pkt); |
| 682 | skb_dequeue_tail(&pkt_list); | ||
| 683 | if (bcmerror) { | 709 | if (bcmerror) { |
| 684 | brcmf_err("membytes transfer failed\n"); | 710 | brcmf_err("membytes transfer failed\n"); |
| 685 | break; | 711 | break; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index c3462b75bd08..905704e335d7 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/mmc/sdio_func.h> | 21 | #include <linux/mmc/sdio_func.h> |
| 22 | #include <linux/mmc/sdio_ids.h> | 22 | #include <linux/mmc/sdio_ids.h> |
| 23 | #include <linux/mmc/card.h> | 23 | #include <linux/mmc/card.h> |
| 24 | #include <linux/mmc/host.h> | ||
| 24 | #include <linux/suspend.h> | 25 | #include <linux/suspend.h> |
| 25 | #include <linux/errno.h> | 26 | #include <linux/errno.h> |
| 26 | #include <linux/sched.h> /* request_irq() */ | 27 | #include <linux/sched.h> /* request_irq() */ |
| @@ -34,6 +35,7 @@ | |||
| 34 | #include <brcmu_utils.h> | 35 | #include <brcmu_utils.h> |
| 35 | #include <brcmu_wifi.h> | 36 | #include <brcmu_wifi.h> |
| 36 | #include "sdio_host.h" | 37 | #include "sdio_host.h" |
| 38 | #include "sdio_chip.h" | ||
| 37 | #include "dhd_dbg.h" | 39 | #include "dhd_dbg.h" |
| 38 | #include "dhd_bus.h" | 40 | #include "dhd_bus.h" |
| 39 | 41 | ||
| @@ -41,13 +43,6 @@ | |||
| 41 | 43 | ||
| 42 | #define DMA_ALIGN_MASK 0x03 | 44 | #define DMA_ALIGN_MASK 0x03 |
| 43 | 45 | ||
| 44 | #define SDIO_DEVICE_ID_BROADCOM_43143 43143 | ||
| 45 | #define SDIO_DEVICE_ID_BROADCOM_43241 0x4324 | ||
| 46 | #define SDIO_DEVICE_ID_BROADCOM_4329 0x4329 | ||
| 47 | #define SDIO_DEVICE_ID_BROADCOM_4330 0x4330 | ||
| 48 | #define SDIO_DEVICE_ID_BROADCOM_4334 0x4334 | ||
| 49 | #define SDIO_DEVICE_ID_BROADCOM_4335 0x4335 | ||
| 50 | |||
| 51 | #define SDIO_FUNC1_BLOCKSIZE 64 | 46 | #define SDIO_FUNC1_BLOCKSIZE 64 |
| 52 | #define SDIO_FUNC2_BLOCKSIZE 512 | 47 | #define SDIO_FUNC2_BLOCKSIZE 512 |
| 53 | 48 | ||
| @@ -58,7 +53,8 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = { | |||
| 58 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)}, | 53 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)}, |
| 59 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)}, | 54 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)}, |
| 60 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)}, | 55 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)}, |
| 61 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4335)}, | 56 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, |
| 57 | SDIO_DEVICE_ID_BROADCOM_4335_4339)}, | ||
| 62 | { /* end: all zeroes */ }, | 58 | { /* end: all zeroes */ }, |
| 63 | }; | 59 | }; |
| 64 | MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); | 60 | MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); |
| @@ -320,6 +316,8 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, | |||
| 320 | int err; | 316 | int err; |
| 321 | struct brcmf_sdio_dev *sdiodev; | 317 | struct brcmf_sdio_dev *sdiodev; |
| 322 | struct brcmf_bus *bus_if; | 318 | struct brcmf_bus *bus_if; |
| 319 | struct mmc_host *host; | ||
| 320 | uint max_blocks; | ||
| 323 | 321 | ||
| 324 | brcmf_dbg(SDIO, "Enter\n"); | 322 | brcmf_dbg(SDIO, "Enter\n"); |
| 325 | brcmf_dbg(SDIO, "Class=%x\n", func->class); | 323 | brcmf_dbg(SDIO, "Class=%x\n", func->class); |
| @@ -366,6 +364,20 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, | |||
| 366 | brcmf_err("F2 error, probe failed %d...\n", err); | 364 | brcmf_err("F2 error, probe failed %d...\n", err); |
| 367 | goto fail; | 365 | goto fail; |
| 368 | } | 366 | } |
| 367 | |||
| 368 | /* | ||
| 369 | * determine host related variables after brcmf_sdio_probe() | ||
| 370 | * as func->cur_blksize is properly set and F2 init has been | ||
| 371 | * completed successfully. | ||
| 372 | */ | ||
| 373 | host = func->card->host; | ||
| 374 | sdiodev->sg_support = host->max_segs > 1; | ||
| 375 | max_blocks = min_t(uint, host->max_blk_count, 511u); | ||
| 376 | sdiodev->max_request_size = min_t(uint, host->max_req_size, | ||
| 377 | max_blocks * func->cur_blksize); | ||
| 378 | sdiodev->max_segment_count = min_t(uint, host->max_segs, | ||
| 379 | SG_MAX_SINGLE_ALLOC); | ||
| 380 | sdiodev->max_segment_size = host->max_seg_size; | ||
| 369 | brcmf_dbg(SDIO, "F2 init completed...\n"); | 381 | brcmf_dbg(SDIO, "F2 init completed...\n"); |
| 370 | return 0; | 382 | return 0; |
| 371 | 383 | ||
| @@ -466,7 +478,7 @@ static int brcmf_sdio_pd_probe(struct platform_device *pdev) | |||
| 466 | { | 478 | { |
| 467 | brcmf_dbg(SDIO, "Enter\n"); | 479 | brcmf_dbg(SDIO, "Enter\n"); |
| 468 | 480 | ||
| 469 | brcmfmac_sdio_pdata = pdev->dev.platform_data; | 481 | brcmfmac_sdio_pdata = dev_get_platdata(&pdev->dev); |
| 470 | 482 | ||
| 471 | if (brcmfmac_sdio_pdata->power_on) | 483 | if (brcmfmac_sdio_pdata->power_on) |
| 472 | brcmfmac_sdio_pdata->power_on(); | 484 | brcmfmac_sdio_pdata->power_on(); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index 2eb9e642c9bf..899a2ada5b82 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h | |||
| @@ -97,8 +97,6 @@ | |||
| 97 | #define WLC_PHY_TYPE_LCN 8 | 97 | #define WLC_PHY_TYPE_LCN 8 |
| 98 | #define WLC_PHY_TYPE_NULL 0xf | 98 | #define WLC_PHY_TYPE_NULL 0xf |
| 99 | 99 | ||
| 100 | #define BRCMF_EVENTING_MASK_LEN 16 | ||
| 101 | |||
| 102 | #define TOE_TX_CSUM_OL 0x00000001 | 100 | #define TOE_TX_CSUM_OL 0x00000001 |
| 103 | #define TOE_RX_CSUM_OL 0x00000002 | 101 | #define TOE_RX_CSUM_OL 0x00000002 |
| 104 | 102 | ||
| @@ -632,29 +630,29 @@ struct brcmf_skb_reorder_data { | |||
| 632 | u8 *reorder; | 630 | u8 *reorder; |
| 633 | }; | 631 | }; |
| 634 | 632 | ||
| 635 | extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev); | 633 | int brcmf_netdev_wait_pend8021x(struct net_device *ndev); |
| 636 | 634 | ||
| 637 | /* Return pointer to interface name */ | 635 | /* Return pointer to interface name */ |
| 638 | extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx); | 636 | char *brcmf_ifname(struct brcmf_pub *drvr, int idx); |
| 639 | 637 | ||
| 640 | /* Query dongle */ | 638 | /* Query dongle */ |
| 641 | extern int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, | 639 | int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, |
| 642 | uint cmd, void *buf, uint len); | 640 | void *buf, uint len); |
| 643 | extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, | 641 | int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, |
| 644 | void *buf, uint len); | 642 | void *buf, uint len); |
| 645 | 643 | ||
| 646 | /* Remove any protocol-specific data header. */ | 644 | /* Remove any protocol-specific data header. */ |
| 647 | extern int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, | 645 | int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, |
| 648 | struct sk_buff *rxp); | 646 | struct sk_buff *rxp); |
| 649 | 647 | ||
| 650 | extern int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked); | 648 | int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked); |
| 651 | extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, | 649 | struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, |
| 652 | s32 ifidx, char *name, u8 *mac_addr); | 650 | char *name, u8 *mac_addr); |
| 653 | extern void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx); | 651 | void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx); |
| 654 | void brcmf_txflowblock_if(struct brcmf_if *ifp, | 652 | void brcmf_txflowblock_if(struct brcmf_if *ifp, |
| 655 | enum brcmf_netif_stop_reason reason, bool state); | 653 | enum brcmf_netif_stop_reason reason, bool state); |
| 656 | extern u32 brcmf_get_chip_info(struct brcmf_if *ifp); | 654 | u32 brcmf_get_chip_info(struct brcmf_if *ifp); |
| 657 | extern void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, | 655 | void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, |
| 658 | bool success); | 656 | bool success); |
| 659 | 657 | ||
| 660 | #endif /* _BRCMF_H_ */ | 658 | #endif /* _BRCMF_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h index 74156f84180c..a6eb09e5d46f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h | |||
| @@ -132,35 +132,34 @@ struct pktq *brcmf_bus_gettxq(struct brcmf_bus *bus) | |||
| 132 | * interface functions from common layer | 132 | * interface functions from common layer |
| 133 | */ | 133 | */ |
| 134 | 134 | ||
| 135 | extern bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, | 135 | bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, struct sk_buff *pkt, |
| 136 | struct sk_buff *pkt, int prec); | 136 | int prec); |
| 137 | 137 | ||
| 138 | /* Receive frame for delivery to OS. Callee disposes of rxp. */ | 138 | /* Receive frame for delivery to OS. Callee disposes of rxp. */ |
| 139 | extern void brcmf_rx_frames(struct device *dev, struct sk_buff_head *rxlist); | 139 | void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp); |
| 140 | 140 | ||
| 141 | /* Indication from bus module regarding presence/insertion of dongle. */ | 141 | /* Indication from bus module regarding presence/insertion of dongle. */ |
| 142 | extern int brcmf_attach(uint bus_hdrlen, struct device *dev); | 142 | int brcmf_attach(uint bus_hdrlen, struct device *dev); |
| 143 | /* Indication from bus module regarding removal/absence of dongle */ | 143 | /* Indication from bus module regarding removal/absence of dongle */ |
| 144 | extern void brcmf_detach(struct device *dev); | 144 | void brcmf_detach(struct device *dev); |
| 145 | /* Indication from bus module that dongle should be reset */ | 145 | /* Indication from bus module that dongle should be reset */ |
| 146 | extern void brcmf_dev_reset(struct device *dev); | 146 | void brcmf_dev_reset(struct device *dev); |
| 147 | /* Indication from bus module to change flow-control state */ | 147 | /* Indication from bus module to change flow-control state */ |
| 148 | extern void brcmf_txflowblock(struct device *dev, bool state); | 148 | void brcmf_txflowblock(struct device *dev, bool state); |
| 149 | 149 | ||
| 150 | /* Notify the bus has transferred the tx packet to firmware */ | 150 | /* Notify the bus has transferred the tx packet to firmware */ |
| 151 | extern void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, | 151 | void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success); |
| 152 | bool success); | ||
| 153 | 152 | ||
| 154 | extern int brcmf_bus_start(struct device *dev); | 153 | int brcmf_bus_start(struct device *dev); |
| 155 | 154 | ||
| 156 | #ifdef CONFIG_BRCMFMAC_SDIO | 155 | #ifdef CONFIG_BRCMFMAC_SDIO |
| 157 | extern void brcmf_sdio_exit(void); | 156 | void brcmf_sdio_exit(void); |
| 158 | extern void brcmf_sdio_init(void); | 157 | void brcmf_sdio_init(void); |
| 159 | extern void brcmf_sdio_register(void); | 158 | void brcmf_sdio_register(void); |
| 160 | #endif | 159 | #endif |
| 161 | #ifdef CONFIG_BRCMFMAC_USB | 160 | #ifdef CONFIG_BRCMFMAC_USB |
| 162 | extern void brcmf_usb_exit(void); | 161 | void brcmf_usb_exit(void); |
| 163 | extern void brcmf_usb_register(void); | 162 | void brcmf_usb_register(void); |
| 164 | #endif | 163 | #endif |
| 165 | 164 | ||
| 166 | #endif /* _BRCMF_BUS_H_ */ | 165 | #endif /* _BRCMF_BUS_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index 40e7f854e10f..64e9cff241b9 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | |||
| @@ -509,9 +509,8 @@ netif_rx: | |||
| 509 | } | 509 | } |
| 510 | } | 510 | } |
| 511 | 511 | ||
| 512 | void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) | 512 | void brcmf_rx_frame(struct device *dev, struct sk_buff *skb) |
| 513 | { | 513 | { |
| 514 | struct sk_buff *skb, *pnext; | ||
| 515 | struct brcmf_if *ifp; | 514 | struct brcmf_if *ifp; |
| 516 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 515 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
| 517 | struct brcmf_pub *drvr = bus_if->drvr; | 516 | struct brcmf_pub *drvr = bus_if->drvr; |
| @@ -519,29 +518,24 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) | |||
| 519 | u8 ifidx; | 518 | u8 ifidx; |
| 520 | int ret; | 519 | int ret; |
| 521 | 520 | ||
| 522 | brcmf_dbg(DATA, "Enter: %s: count=%u\n", dev_name(dev), | 521 | brcmf_dbg(DATA, "Enter: %s: rxp=%p\n", dev_name(dev), skb); |
| 523 | skb_queue_len(skb_list)); | ||
| 524 | 522 | ||
| 525 | skb_queue_walk_safe(skb_list, skb, pnext) { | 523 | /* process and remove protocol-specific header */ |
| 526 | skb_unlink(skb, skb_list); | 524 | ret = brcmf_proto_hdrpull(drvr, true, &ifidx, skb); |
| 527 | 525 | ifp = drvr->iflist[ifidx]; | |
| 528 | /* process and remove protocol-specific header */ | ||
| 529 | ret = brcmf_proto_hdrpull(drvr, true, &ifidx, skb); | ||
| 530 | ifp = drvr->iflist[ifidx]; | ||
| 531 | |||
| 532 | if (ret || !ifp || !ifp->ndev) { | ||
| 533 | if ((ret != -ENODATA) && ifp) | ||
| 534 | ifp->stats.rx_errors++; | ||
| 535 | brcmu_pkt_buf_free_skb(skb); | ||
| 536 | continue; | ||
| 537 | } | ||
| 538 | 526 | ||
| 539 | rd = (struct brcmf_skb_reorder_data *)skb->cb; | 527 | if (ret || !ifp || !ifp->ndev) { |
| 540 | if (rd->reorder) | 528 | if ((ret != -ENODATA) && ifp) |
| 541 | brcmf_rxreorder_process_info(ifp, rd->reorder, skb); | 529 | ifp->stats.rx_errors++; |
| 542 | else | 530 | brcmu_pkt_buf_free_skb(skb); |
| 543 | brcmf_netif_rx(ifp, skb); | 531 | return; |
| 544 | } | 532 | } |
| 533 | |||
| 534 | rd = (struct brcmf_skb_reorder_data *)skb->cb; | ||
| 535 | if (rd->reorder) | ||
| 536 | brcmf_rxreorder_process_info(ifp, rd->reorder, skb); | ||
| 537 | else | ||
| 538 | brcmf_netif_rx(ifp, skb); | ||
| 545 | } | 539 | } |
| 546 | 540 | ||
| 547 | void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, | 541 | void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h index ef9179883748..53c6e710f2cb 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h | |||
| @@ -22,21 +22,21 @@ | |||
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | /* Linkage, sets prot link and updates hdrlen in pub */ | 24 | /* Linkage, sets prot link and updates hdrlen in pub */ |
| 25 | extern int brcmf_proto_attach(struct brcmf_pub *drvr); | 25 | int brcmf_proto_attach(struct brcmf_pub *drvr); |
| 26 | 26 | ||
| 27 | /* Unlink, frees allocated protocol memory (including brcmf_proto) */ | 27 | /* Unlink, frees allocated protocol memory (including brcmf_proto) */ |
| 28 | extern void brcmf_proto_detach(struct brcmf_pub *drvr); | 28 | void brcmf_proto_detach(struct brcmf_pub *drvr); |
| 29 | 29 | ||
| 30 | /* Stop protocol: sync w/dongle state. */ | 30 | /* Stop protocol: sync w/dongle state. */ |
| 31 | extern void brcmf_proto_stop(struct brcmf_pub *drvr); | 31 | void brcmf_proto_stop(struct brcmf_pub *drvr); |
| 32 | 32 | ||
| 33 | /* Add any protocol-specific data header. | 33 | /* Add any protocol-specific data header. |
| 34 | * Caller must reserve prot_hdrlen prepend space. | 34 | * Caller must reserve prot_hdrlen prepend space. |
| 35 | */ | 35 | */ |
| 36 | extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx, u8 offset, | 36 | void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx, u8 offset, |
| 37 | struct sk_buff *txp); | 37 | struct sk_buff *txp); |
| 38 | 38 | ||
| 39 | /* Sets dongle media info (drv_version, mac address). */ | 39 | /* Sets dongle media info (drv_version, mac address). */ |
| 40 | extern int brcmf_c_preinit_dcmds(struct brcmf_if *ifp); | 40 | int brcmf_c_preinit_dcmds(struct brcmf_if *ifp); |
| 41 | 41 | ||
| 42 | #endif /* _BRCMF_PROTO_H_ */ | 42 | #endif /* _BRCMF_PROTO_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 1aa75d5951b8..b02953c4ade7 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
| @@ -275,11 +275,6 @@ struct rte_console { | |||
| 275 | /* Flags for SDH calls */ | 275 | /* Flags for SDH calls */ |
| 276 | #define F2SYNC (SDIO_REQ_4BYTE | SDIO_REQ_FIXED) | 276 | #define F2SYNC (SDIO_REQ_4BYTE | SDIO_REQ_FIXED) |
| 277 | 277 | ||
| 278 | #define BRCMF_SDIO_FW_NAME "brcm/brcmfmac-sdio.bin" | ||
| 279 | #define BRCMF_SDIO_NV_NAME "brcm/brcmfmac-sdio.txt" | ||
| 280 | MODULE_FIRMWARE(BRCMF_SDIO_FW_NAME); | ||
| 281 | MODULE_FIRMWARE(BRCMF_SDIO_NV_NAME); | ||
| 282 | |||
| 283 | #define BRCMF_IDLE_IMMEDIATE (-1) /* Enter idle immediately */ | 278 | #define BRCMF_IDLE_IMMEDIATE (-1) /* Enter idle immediately */ |
| 284 | #define BRCMF_IDLE_ACTIVE 0 /* Do not request any SD clock change | 279 | #define BRCMF_IDLE_ACTIVE 0 /* Do not request any SD clock change |
| 285 | * when idle | 280 | * when idle |
| @@ -454,9 +449,6 @@ struct brcmf_sdio { | |||
| 454 | struct work_struct datawork; | 449 | struct work_struct datawork; |
| 455 | atomic_t dpc_tskcnt; | 450 | atomic_t dpc_tskcnt; |
| 456 | 451 | ||
| 457 | const struct firmware *firmware; | ||
| 458 | u32 fw_ptr; | ||
| 459 | |||
| 460 | bool txoff; /* Transmit flow-controlled */ | 452 | bool txoff; /* Transmit flow-controlled */ |
| 461 | struct brcmf_sdio_count sdcnt; | 453 | struct brcmf_sdio_count sdcnt; |
| 462 | bool sr_enabled; /* SaveRestore enabled */ | 454 | bool sr_enabled; /* SaveRestore enabled */ |
| @@ -493,6 +485,100 @@ enum brcmf_sdio_frmtype { | |||
| 493 | BRCMF_SDIO_FT_SUB, | 485 | BRCMF_SDIO_FT_SUB, |
| 494 | }; | 486 | }; |
| 495 | 487 | ||
| 488 | #define BCM43143_FIRMWARE_NAME "brcm/brcmfmac43143-sdio.bin" | ||
| 489 | #define BCM43143_NVRAM_NAME "brcm/brcmfmac43143-sdio.txt" | ||
| 490 | #define BCM43241B0_FIRMWARE_NAME "brcm/brcmfmac43241b0-sdio.bin" | ||
| 491 | #define BCM43241B0_NVRAM_NAME "brcm/brcmfmac43241b0-sdio.txt" | ||
| 492 | #define BCM43241B4_FIRMWARE_NAME "brcm/brcmfmac43241b4-sdio.bin" | ||
| 493 | #define BCM43241B4_NVRAM_NAME "brcm/brcmfmac43241b4-sdio.txt" | ||
| 494 | #define BCM4329_FIRMWARE_NAME "brcm/brcmfmac4329-sdio.bin" | ||
| 495 | #define BCM4329_NVRAM_NAME "brcm/brcmfmac4329-sdio.txt" | ||
| 496 | #define BCM4330_FIRMWARE_NAME "brcm/brcmfmac4330-sdio.bin" | ||
| 497 | #define BCM4330_NVRAM_NAME "brcm/brcmfmac4330-sdio.txt" | ||
| 498 | #define BCM4334_FIRMWARE_NAME "brcm/brcmfmac4334-sdio.bin" | ||
| 499 | #define BCM4334_NVRAM_NAME "brcm/brcmfmac4334-sdio.txt" | ||
| 500 | #define BCM4335_FIRMWARE_NAME "brcm/brcmfmac4335-sdio.bin" | ||
| 501 | #define BCM4335_NVRAM_NAME "brcm/brcmfmac4335-sdio.txt" | ||
| 502 | |||
| 503 | MODULE_FIRMWARE(BCM43143_FIRMWARE_NAME); | ||
| 504 | MODULE_FIRMWARE(BCM43143_NVRAM_NAME); | ||
| 505 | MODULE_FIRMWARE(BCM43241B0_FIRMWARE_NAME); | ||
| 506 | MODULE_FIRMWARE(BCM43241B0_NVRAM_NAME); | ||
| 507 | MODULE_FIRMWARE(BCM43241B4_FIRMWARE_NAME); | ||
| 508 | MODULE_FIRMWARE(BCM43241B4_NVRAM_NAME); | ||
| 509 | MODULE_FIRMWARE(BCM4329_FIRMWARE_NAME); | ||
| 510 | MODULE_FIRMWARE(BCM4329_NVRAM_NAME); | ||
| 511 | MODULE_FIRMWARE(BCM4330_FIRMWARE_NAME); | ||
| 512 | MODULE_FIRMWARE(BCM4330_NVRAM_NAME); | ||
| 513 | MODULE_FIRMWARE(BCM4334_FIRMWARE_NAME); | ||
| 514 | MODULE_FIRMWARE(BCM4334_NVRAM_NAME); | ||
| 515 | MODULE_FIRMWARE(BCM4335_FIRMWARE_NAME); | ||
| 516 | MODULE_FIRMWARE(BCM4335_NVRAM_NAME); | ||
| 517 | |||
| 518 | struct brcmf_firmware_names { | ||
| 519 | u32 chipid; | ||
| 520 | u32 revmsk; | ||
| 521 | const char *bin; | ||
| 522 | const char *nv; | ||
| 523 | }; | ||
| 524 | |||
| 525 | enum brcmf_firmware_type { | ||
| 526 | BRCMF_FIRMWARE_BIN, | ||
| 527 | BRCMF_FIRMWARE_NVRAM | ||
| 528 | }; | ||
| 529 | |||
| 530 | #define BRCMF_FIRMWARE_NVRAM(name) \ | ||
| 531 | name ## _FIRMWARE_NAME, name ## _NVRAM_NAME | ||
| 532 | |||
| 533 | static const struct brcmf_firmware_names brcmf_fwname_data[] = { | ||
| 534 | { BCM43143_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43143) }, | ||
| 535 | { BCM43241_CHIP_ID, 0x0000001F, BRCMF_FIRMWARE_NVRAM(BCM43241B0) }, | ||
| 536 | { BCM43241_CHIP_ID, 0xFFFFFFE0, BRCMF_FIRMWARE_NVRAM(BCM43241B4) }, | ||
| 537 | { BCM4329_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4329) }, | ||
| 538 | { BCM4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) }, | ||
| 539 | { BCM4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) }, | ||
| 540 | { BCM4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) } | ||
| 541 | }; | ||
| 542 | |||
| 543 | |||
| 544 | static const struct firmware *brcmf_sdbrcm_get_fw(struct brcmf_sdio *bus, | ||
| 545 | enum brcmf_firmware_type type) | ||
| 546 | { | ||
| 547 | const struct firmware *fw; | ||
| 548 | const char *name; | ||
| 549 | int err, i; | ||
| 550 | |||
| 551 | for (i = 0; i < ARRAY_SIZE(brcmf_fwname_data); i++) { | ||
| 552 | if (brcmf_fwname_data[i].chipid == bus->ci->chip && | ||
| 553 | brcmf_fwname_data[i].revmsk & BIT(bus->ci->chiprev)) { | ||
| 554 | switch (type) { | ||
| 555 | case BRCMF_FIRMWARE_BIN: | ||
| 556 | name = brcmf_fwname_data[i].bin; | ||
| 557 | break; | ||
| 558 | case BRCMF_FIRMWARE_NVRAM: | ||
| 559 | name = brcmf_fwname_data[i].nv; | ||
| 560 | break; | ||
| 561 | default: | ||
| 562 | brcmf_err("invalid firmware type (%d)\n", type); | ||
| 563 | return NULL; | ||
| 564 | } | ||
| 565 | goto found; | ||
| 566 | } | ||
| 567 | } | ||
| 568 | brcmf_err("Unknown chipid %d [%d]\n", | ||
| 569 | bus->ci->chip, bus->ci->chiprev); | ||
| 570 | return NULL; | ||
| 571 | |||
| 572 | found: | ||
| 573 | err = request_firmware(&fw, name, &bus->sdiodev->func[2]->dev); | ||
| 574 | if ((err) || (!fw)) { | ||
| 575 | brcmf_err("fail to request firmware %s (%d)\n", name, err); | ||
| 576 | return NULL; | ||
| 577 | } | ||
| 578 | |||
| 579 | return fw; | ||
| 580 | } | ||
| 581 | |||
| 496 | static void pkt_align(struct sk_buff *p, int len, int align) | 582 | static void pkt_align(struct sk_buff *p, int len, int align) |
| 497 | { | 583 | { |
| 498 | uint datalign; | 584 | uint datalign; |
| @@ -1061,6 +1147,8 @@ static int brcmf_sdio_hdparse(struct brcmf_sdio *bus, u8 *header, | |||
| 1061 | u8 rx_seq, fc, tx_seq_max; | 1147 | u8 rx_seq, fc, tx_seq_max; |
| 1062 | u32 swheader; | 1148 | u32 swheader; |
| 1063 | 1149 | ||
| 1150 | trace_brcmf_sdpcm_hdr(false, header); | ||
| 1151 | |||
| 1064 | /* hw header */ | 1152 | /* hw header */ |
| 1065 | len = get_unaligned_le16(header); | 1153 | len = get_unaligned_le16(header); |
| 1066 | checksum = get_unaligned_le16(header + sizeof(u16)); | 1154 | checksum = get_unaligned_le16(header + sizeof(u16)); |
| @@ -1183,6 +1271,7 @@ static void brcmf_sdio_hdpack(struct brcmf_sdio *bus, u8 *header, | |||
| 1183 | SDPCM_DOFFSET_MASK; | 1271 | SDPCM_DOFFSET_MASK; |
| 1184 | *(((__le32 *)header) + 1) = cpu_to_le32(sw_header); | 1272 | *(((__le32 *)header) + 1) = cpu_to_le32(sw_header); |
| 1185 | *(((__le32 *)header) + 2) = 0; | 1273 | *(((__le32 *)header) + 2) = 0; |
| 1274 | trace_brcmf_sdpcm_hdr(true, header); | ||
| 1186 | } | 1275 | } |
| 1187 | 1276 | ||
| 1188 | static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | 1277 | static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) |
| @@ -1303,7 +1392,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
| 1303 | sdio_claim_host(bus->sdiodev->func[1]); | 1392 | sdio_claim_host(bus->sdiodev->func[1]); |
| 1304 | errcode = brcmf_sdcard_recv_chain(bus->sdiodev, | 1393 | errcode = brcmf_sdcard_recv_chain(bus->sdiodev, |
| 1305 | bus->sdiodev->sbwad, | 1394 | bus->sdiodev->sbwad, |
| 1306 | SDIO_FUNC_2, F2SYNC, &bus->glom); | 1395 | SDIO_FUNC_2, F2SYNC, &bus->glom, dlen); |
| 1307 | sdio_release_host(bus->sdiodev->func[1]); | 1396 | sdio_release_host(bus->sdiodev->func[1]); |
| 1308 | bus->sdcnt.f2rxdata++; | 1397 | bus->sdcnt.f2rxdata++; |
| 1309 | 1398 | ||
| @@ -1406,13 +1495,12 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
| 1406 | bus->glom.qlen, pfirst, pfirst->data, | 1495 | bus->glom.qlen, pfirst, pfirst->data, |
| 1407 | pfirst->len, pfirst->next, | 1496 | pfirst->len, pfirst->next, |
| 1408 | pfirst->prev); | 1497 | pfirst->prev); |
| 1498 | skb_unlink(pfirst, &bus->glom); | ||
| 1499 | brcmf_rx_frame(bus->sdiodev->dev, pfirst); | ||
| 1500 | bus->sdcnt.rxglompkts++; | ||
| 1409 | } | 1501 | } |
| 1410 | /* sent any remaining packets up */ | ||
| 1411 | if (bus->glom.qlen) | ||
| 1412 | brcmf_rx_frames(bus->sdiodev->dev, &bus->glom); | ||
| 1413 | 1502 | ||
| 1414 | bus->sdcnt.rxglomframes++; | 1503 | bus->sdcnt.rxglomframes++; |
| 1415 | bus->sdcnt.rxglompkts += bus->glom.qlen; | ||
| 1416 | } | 1504 | } |
| 1417 | return num; | 1505 | return num; |
| 1418 | } | 1506 | } |
| @@ -1557,7 +1645,6 @@ static void brcmf_pad(struct brcmf_sdio *bus, u16 *pad, u16 *rdlen) | |||
| 1557 | static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | 1645 | static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) |
| 1558 | { | 1646 | { |
| 1559 | struct sk_buff *pkt; /* Packet for event or data frames */ | 1647 | struct sk_buff *pkt; /* Packet for event or data frames */ |
| 1560 | struct sk_buff_head pktlist; /* needed for bus interface */ | ||
| 1561 | u16 pad; /* Number of pad bytes to read */ | 1648 | u16 pad; /* Number of pad bytes to read */ |
| 1562 | uint rxleft = 0; /* Remaining number of frames allowed */ | 1649 | uint rxleft = 0; /* Remaining number of frames allowed */ |
| 1563 | int ret; /* Return code from calls */ | 1650 | int ret; /* Return code from calls */ |
| @@ -1759,9 +1846,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
| 1759 | continue; | 1846 | continue; |
| 1760 | } | 1847 | } |
| 1761 | 1848 | ||
| 1762 | skb_queue_head_init(&pktlist); | 1849 | brcmf_rx_frame(bus->sdiodev->dev, pkt); |
| 1763 | skb_queue_tail(&pktlist, pkt); | ||
| 1764 | brcmf_rx_frames(bus->sdiodev->dev, &pktlist); | ||
| 1765 | } | 1850 | } |
| 1766 | 1851 | ||
| 1767 | rxcount = maxframes - rxleft; | 1852 | rxcount = maxframes - rxleft; |
| @@ -1786,10 +1871,65 @@ brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus) | |||
| 1786 | return; | 1871 | return; |
| 1787 | } | 1872 | } |
| 1788 | 1873 | ||
| 1874 | /** | ||
| 1875 | * struct brcmf_skbuff_cb reserves first two bytes in sk_buff::cb for | ||
| 1876 | * bus layer usage. | ||
| 1877 | */ | ||
| 1789 | /* flag marking a dummy skb added for DMA alignment requirement */ | 1878 | /* flag marking a dummy skb added for DMA alignment requirement */ |
| 1790 | #define DUMMY_SKB_FLAG 0x10000 | 1879 | #define ALIGN_SKB_FLAG 0x8000 |
| 1791 | /* bit mask of data length chopped from the previous packet */ | 1880 | /* bit mask of data length chopped from the previous packet */ |
| 1792 | #define DUMMY_SKB_CHOP_LEN_MASK 0xffff | 1881 | #define ALIGN_SKB_CHOP_LEN_MASK 0x7fff |
| 1882 | |||
| 1883 | static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio_dev *sdiodev, | ||
| 1884 | struct sk_buff_head *pktq, | ||
| 1885 | struct sk_buff *pkt, uint chan) | ||
| 1886 | { | ||
| 1887 | struct sk_buff *pkt_pad; | ||
| 1888 | u16 tail_pad, tail_chop, sg_align; | ||
| 1889 | unsigned int blksize; | ||
| 1890 | u8 *dat_buf; | ||
| 1891 | int ntail; | ||
| 1892 | |||
| 1893 | blksize = sdiodev->func[SDIO_FUNC_2]->cur_blksize; | ||
| 1894 | sg_align = 4; | ||
| 1895 | if (sdiodev->pdata && sdiodev->pdata->sd_sgentry_align > 4) | ||
| 1896 | sg_align = sdiodev->pdata->sd_sgentry_align; | ||
| 1897 | /* sg entry alignment should be a divisor of block size */ | ||
| 1898 | WARN_ON(blksize % sg_align); | ||
| 1899 | |||
| 1900 | /* Check tail padding */ | ||
| 1901 | pkt_pad = NULL; | ||
| 1902 | tail_chop = pkt->len % sg_align; | ||
| 1903 | tail_pad = sg_align - tail_chop; | ||
| 1904 | tail_pad += blksize - (pkt->len + tail_pad) % blksize; | ||
| 1905 | if (skb_tailroom(pkt) < tail_pad && pkt->len > blksize) { | ||
| 1906 | pkt_pad = brcmu_pkt_buf_get_skb(tail_pad + tail_chop); | ||
| 1907 | if (pkt_pad == NULL) | ||
| 1908 | return -ENOMEM; | ||
| 1909 | memcpy(pkt_pad->data, | ||
| 1910 | pkt->data + pkt->len - tail_chop, | ||
| 1911 | tail_chop); | ||
| 1912 | *(u32 *)(pkt_pad->cb) = ALIGN_SKB_FLAG + tail_chop; | ||
| 1913 | skb_trim(pkt, pkt->len - tail_chop); | ||
| 1914 | __skb_queue_after(pktq, pkt, pkt_pad); | ||
| 1915 | } else { | ||
| 1916 | ntail = pkt->data_len + tail_pad - | ||
| 1917 | (pkt->end - pkt->tail); | ||
| 1918 | if (skb_cloned(pkt) || ntail > 0) | ||
| 1919 | if (pskb_expand_head(pkt, 0, ntail, GFP_ATOMIC)) | ||
| 1920 | return -ENOMEM; | ||
| 1921 | if (skb_linearize(pkt)) | ||
| 1922 | return -ENOMEM; | ||
| 1923 | dat_buf = (u8 *)(pkt->data); | ||
| 1924 | __skb_put(pkt, tail_pad); | ||
| 1925 | } | ||
| 1926 | |||
| 1927 | if (pkt_pad) | ||
| 1928 | return pkt->len + tail_chop; | ||
| 1929 | else | ||
| 1930 | return pkt->len - tail_pad; | ||
| 1931 | } | ||
| 1932 | |||
| 1793 | /** | 1933 | /** |
| 1794 | * brcmf_sdio_txpkt_prep - packet preparation for transmit | 1934 | * brcmf_sdio_txpkt_prep - packet preparation for transmit |
| 1795 | * @bus: brcmf_sdio structure pointer | 1935 | * @bus: brcmf_sdio structure pointer |
| @@ -1806,24 +1946,16 @@ static int | |||
| 1806 | brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq, | 1946 | brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq, |
| 1807 | uint chan) | 1947 | uint chan) |
| 1808 | { | 1948 | { |
| 1809 | u16 head_pad, tail_pad, tail_chop, head_align, sg_align; | 1949 | u16 head_pad, head_align; |
| 1810 | int ntail; | 1950 | struct sk_buff *pkt_next; |
| 1811 | struct sk_buff *pkt_next, *pkt_new; | ||
| 1812 | u8 *dat_buf; | 1951 | u8 *dat_buf; |
| 1813 | unsigned blksize = bus->sdiodev->func[SDIO_FUNC_2]->cur_blksize; | 1952 | int err; |
| 1814 | struct brcmf_sdio_hdrinfo hd_info = {0}; | 1953 | struct brcmf_sdio_hdrinfo hd_info = {0}; |
| 1815 | 1954 | ||
| 1816 | /* SDIO ADMA requires at least 32 bit alignment */ | 1955 | /* SDIO ADMA requires at least 32 bit alignment */ |
| 1817 | head_align = 4; | 1956 | head_align = 4; |
| 1818 | sg_align = 4; | 1957 | if (bus->sdiodev->pdata && bus->sdiodev->pdata->sd_head_align > 4) |
| 1819 | if (bus->sdiodev->pdata) { | 1958 | head_align = bus->sdiodev->pdata->sd_head_align; |
| 1820 | head_align = bus->sdiodev->pdata->sd_head_align > 4 ? | ||
| 1821 | bus->sdiodev->pdata->sd_head_align : 4; | ||
| 1822 | sg_align = bus->sdiodev->pdata->sd_sgentry_align > 4 ? | ||
| 1823 | bus->sdiodev->pdata->sd_sgentry_align : 4; | ||
| 1824 | } | ||
| 1825 | /* sg entry alignment should be a divisor of block size */ | ||
| 1826 | WARN_ON(blksize % sg_align); | ||
| 1827 | 1959 | ||
| 1828 | pkt_next = pktq->next; | 1960 | pkt_next = pktq->next; |
| 1829 | dat_buf = (u8 *)(pkt_next->data); | 1961 | dat_buf = (u8 *)(pkt_next->data); |
| @@ -1842,40 +1974,20 @@ brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq, | |||
| 1842 | memset(dat_buf, 0, head_pad + bus->tx_hdrlen); | 1974 | memset(dat_buf, 0, head_pad + bus->tx_hdrlen); |
| 1843 | } | 1975 | } |
| 1844 | 1976 | ||
| 1845 | /* Check tail padding */ | 1977 | if (bus->sdiodev->sg_support && pktq->qlen > 1) { |
| 1846 | pkt_new = NULL; | 1978 | err = brcmf_sdio_txpkt_prep_sg(bus->sdiodev, pktq, |
| 1847 | tail_chop = pkt_next->len % sg_align; | 1979 | pkt_next, chan); |
| 1848 | tail_pad = sg_align - tail_chop; | 1980 | if (err < 0) |
| 1849 | tail_pad += blksize - (pkt_next->len + tail_pad) % blksize; | 1981 | return err; |
| 1850 | if (skb_tailroom(pkt_next) < tail_pad && pkt_next->len > blksize) { | 1982 | hd_info.len = (u16)err; |
| 1851 | pkt_new = brcmu_pkt_buf_get_skb(tail_pad + tail_chop); | ||
| 1852 | if (pkt_new == NULL) | ||
| 1853 | return -ENOMEM; | ||
| 1854 | memcpy(pkt_new->data, | ||
| 1855 | pkt_next->data + pkt_next->len - tail_chop, | ||
| 1856 | tail_chop); | ||
| 1857 | *(u32 *)(pkt_new->cb) = DUMMY_SKB_FLAG + tail_chop; | ||
| 1858 | skb_trim(pkt_next, pkt_next->len - tail_chop); | ||
| 1859 | __skb_queue_after(pktq, pkt_next, pkt_new); | ||
| 1860 | } else { | 1983 | } else { |
| 1861 | ntail = pkt_next->data_len + tail_pad - | 1984 | hd_info.len = pkt_next->len; |
| 1862 | (pkt_next->end - pkt_next->tail); | ||
| 1863 | if (skb_cloned(pkt_next) || ntail > 0) | ||
| 1864 | if (pskb_expand_head(pkt_next, 0, ntail, GFP_ATOMIC)) | ||
| 1865 | return -ENOMEM; | ||
| 1866 | if (skb_linearize(pkt_next)) | ||
| 1867 | return -ENOMEM; | ||
| 1868 | dat_buf = (u8 *)(pkt_next->data); | ||
| 1869 | __skb_put(pkt_next, tail_pad); | ||
| 1870 | } | 1985 | } |
| 1871 | 1986 | ||
| 1872 | /* Now prep the header */ | ||
| 1873 | if (pkt_new) | ||
| 1874 | hd_info.len = pkt_next->len + tail_chop; | ||
| 1875 | else | ||
| 1876 | hd_info.len = pkt_next->len - tail_pad; | ||
| 1877 | hd_info.channel = chan; | 1987 | hd_info.channel = chan; |
| 1878 | hd_info.dat_offset = head_pad + bus->tx_hdrlen; | 1988 | hd_info.dat_offset = head_pad + bus->tx_hdrlen; |
| 1989 | |||
| 1990 | /* Now fill the header */ | ||
| 1879 | brcmf_sdio_hdpack(bus, dat_buf, &hd_info); | 1991 | brcmf_sdio_hdpack(bus, dat_buf, &hd_info); |
| 1880 | 1992 | ||
| 1881 | if (BRCMF_BYTES_ON() && | 1993 | if (BRCMF_BYTES_ON() && |
| @@ -1908,8 +2020,8 @@ brcmf_sdio_txpkt_postp(struct brcmf_sdio *bus, struct sk_buff_head *pktq) | |||
| 1908 | 2020 | ||
| 1909 | skb_queue_walk_safe(pktq, pkt_next, tmp) { | 2021 | skb_queue_walk_safe(pktq, pkt_next, tmp) { |
| 1910 | dummy_flags = *(u32 *)(pkt_next->cb); | 2022 | dummy_flags = *(u32 *)(pkt_next->cb); |
| 1911 | if (dummy_flags & DUMMY_SKB_FLAG) { | 2023 | if (dummy_flags & ALIGN_SKB_FLAG) { |
| 1912 | chop_len = dummy_flags & DUMMY_SKB_CHOP_LEN_MASK; | 2024 | chop_len = dummy_flags & ALIGN_SKB_CHOP_LEN_MASK; |
| 1913 | if (chop_len) { | 2025 | if (chop_len) { |
| 1914 | pkt_prev = pkt_next->prev; | 2026 | pkt_prev = pkt_next->prev; |
| 1915 | memcpy(pkt_prev->data + pkt_prev->len, | 2027 | memcpy(pkt_prev->data + pkt_prev->len, |
| @@ -3037,69 +3149,43 @@ static bool brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter) | |||
| 3037 | return true; | 3149 | return true; |
| 3038 | } | 3150 | } |
| 3039 | 3151 | ||
| 3040 | static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_sdio *bus) | ||
| 3041 | { | ||
| 3042 | if (bus->firmware->size < bus->fw_ptr + len) | ||
| 3043 | len = bus->firmware->size - bus->fw_ptr; | ||
| 3044 | |||
| 3045 | memcpy(buf, &bus->firmware->data[bus->fw_ptr], len); | ||
| 3046 | bus->fw_ptr += len; | ||
| 3047 | return len; | ||
| 3048 | } | ||
| 3049 | |||
| 3050 | static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus) | 3152 | static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus) |
| 3051 | { | 3153 | { |
| 3154 | const struct firmware *fw; | ||
| 3155 | int err; | ||
| 3052 | int offset; | 3156 | int offset; |
| 3053 | uint len; | 3157 | int address; |
| 3054 | u8 *memblock = NULL, *memptr; | 3158 | int len; |
| 3055 | int ret; | 3159 | |
| 3056 | u8 idx; | 3160 | fw = brcmf_sdbrcm_get_fw(bus, BRCMF_FIRMWARE_BIN); |
| 3057 | 3161 | if (fw == NULL) | |
| 3058 | brcmf_dbg(INFO, "Enter\n"); | 3162 | return -ENOENT; |
| 3059 | 3163 | ||
| 3060 | ret = request_firmware(&bus->firmware, BRCMF_SDIO_FW_NAME, | 3164 | if (brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_ARM_CR4) != |
| 3061 | &bus->sdiodev->func[2]->dev); | 3165 | BRCMF_MAX_CORENUM) |
| 3062 | if (ret) { | 3166 | memcpy(&bus->ci->rst_vec, fw->data, sizeof(bus->ci->rst_vec)); |
| 3063 | brcmf_err("Fail to request firmware %d\n", ret); | 3167 | |
| 3064 | return ret; | 3168 | err = 0; |
| 3065 | } | 3169 | offset = 0; |
| 3066 | bus->fw_ptr = 0; | 3170 | address = bus->ci->rambase; |
| 3067 | 3171 | while (offset < fw->size) { | |
| 3068 | memptr = memblock = kmalloc(MEMBLOCK + BRCMF_SDALIGN, GFP_ATOMIC); | 3172 | len = ((offset + MEMBLOCK) < fw->size) ? MEMBLOCK : |
| 3069 | if (memblock == NULL) { | 3173 | fw->size - offset; |
| 3070 | ret = -ENOMEM; | 3174 | err = brcmf_sdio_ramrw(bus->sdiodev, true, address, |
| 3071 | goto err; | 3175 | (u8 *)&fw->data[offset], len); |
| 3072 | } | 3176 | if (err) { |
| 3073 | if ((u32)(unsigned long)memblock % BRCMF_SDALIGN) | ||
| 3074 | memptr += (BRCMF_SDALIGN - | ||
| 3075 | ((u32)(unsigned long)memblock % BRCMF_SDALIGN)); | ||
| 3076 | |||
| 3077 | offset = bus->ci->rambase; | ||
| 3078 | |||
| 3079 | /* Download image */ | ||
| 3080 | len = brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus); | ||
| 3081 | idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_ARM_CR4); | ||
| 3082 | if (BRCMF_MAX_CORENUM != idx) | ||
| 3083 | memcpy(&bus->ci->rst_vec, memptr, sizeof(bus->ci->rst_vec)); | ||
| 3084 | while (len) { | ||
| 3085 | ret = brcmf_sdio_ramrw(bus->sdiodev, true, offset, memptr, len); | ||
| 3086 | if (ret) { | ||
| 3087 | brcmf_err("error %d on writing %d membytes at 0x%08x\n", | 3177 | brcmf_err("error %d on writing %d membytes at 0x%08x\n", |
| 3088 | ret, MEMBLOCK, offset); | 3178 | err, len, address); |
| 3089 | goto err; | 3179 | goto failure; |
| 3090 | } | 3180 | } |
| 3091 | 3181 | offset += len; | |
| 3092 | offset += MEMBLOCK; | 3182 | address += len; |
| 3093 | len = brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus); | ||
| 3094 | } | 3183 | } |
| 3095 | 3184 | ||
| 3096 | err: | 3185 | failure: |
| 3097 | kfree(memblock); | 3186 | release_firmware(fw); |
| 3098 | |||
| 3099 | release_firmware(bus->firmware); | ||
| 3100 | bus->fw_ptr = 0; | ||
| 3101 | 3187 | ||
| 3102 | return ret; | 3188 | return err; |
| 3103 | } | 3189 | } |
| 3104 | 3190 | ||
| 3105 | /* | 3191 | /* |
| @@ -3111,7 +3197,8 @@ err: | |||
| 3111 | * by two NULs. | 3197 | * by two NULs. |
| 3112 | */ | 3198 | */ |
| 3113 | 3199 | ||
| 3114 | static int brcmf_process_nvram_vars(struct brcmf_sdio *bus) | 3200 | static int brcmf_process_nvram_vars(struct brcmf_sdio *bus, |
| 3201 | const struct firmware *nv) | ||
| 3115 | { | 3202 | { |
| 3116 | char *varbuf; | 3203 | char *varbuf; |
| 3117 | char *dp; | 3204 | char *dp; |
| @@ -3120,12 +3207,12 @@ static int brcmf_process_nvram_vars(struct brcmf_sdio *bus) | |||
| 3120 | int ret = 0; | 3207 | int ret = 0; |
| 3121 | uint buf_len, n, len; | 3208 | uint buf_len, n, len; |
| 3122 | 3209 | ||
| 3123 | len = bus->firmware->size; | 3210 | len = nv->size; |
| 3124 | varbuf = vmalloc(len); | 3211 | varbuf = vmalloc(len); |
| 3125 | if (!varbuf) | 3212 | if (!varbuf) |
| 3126 | return -ENOMEM; | 3213 | return -ENOMEM; |
| 3127 | 3214 | ||
| 3128 | memcpy(varbuf, bus->firmware->data, len); | 3215 | memcpy(varbuf, nv->data, len); |
| 3129 | dp = varbuf; | 3216 | dp = varbuf; |
| 3130 | 3217 | ||
| 3131 | findNewline = false; | 3218 | findNewline = false; |
| @@ -3177,18 +3264,16 @@ err: | |||
| 3177 | 3264 | ||
| 3178 | static int brcmf_sdbrcm_download_nvram(struct brcmf_sdio *bus) | 3265 | static int brcmf_sdbrcm_download_nvram(struct brcmf_sdio *bus) |
| 3179 | { | 3266 | { |
| 3267 | const struct firmware *nv; | ||
| 3180 | int ret; | 3268 | int ret; |
| 3181 | 3269 | ||
| 3182 | ret = request_firmware(&bus->firmware, BRCMF_SDIO_NV_NAME, | 3270 | nv = brcmf_sdbrcm_get_fw(bus, BRCMF_FIRMWARE_NVRAM); |
| 3183 | &bus->sdiodev->func[2]->dev); | 3271 | if (nv == NULL) |
| 3184 | if (ret) { | 3272 | return -ENOENT; |
| 3185 | brcmf_err("Fail to request nvram %d\n", ret); | ||
| 3186 | return ret; | ||
| 3187 | } | ||
| 3188 | 3273 | ||
| 3189 | ret = brcmf_process_nvram_vars(bus); | 3274 | ret = brcmf_process_nvram_vars(bus, nv); |
| 3190 | 3275 | ||
| 3191 | release_firmware(bus->firmware); | 3276 | release_firmware(nv); |
| 3192 | 3277 | ||
| 3193 | return ret; | 3278 | return ret; |
| 3194 | } | 3279 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h index e679214b3c98..14bc24dc5bae 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h | |||
| @@ -102,7 +102,8 @@ struct brcmf_event; | |||
| 102 | BRCMF_ENUM_DEF(DCS_REQUEST, 73) \ | 102 | BRCMF_ENUM_DEF(DCS_REQUEST, 73) \ |
| 103 | BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \ | 103 | BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \ |
| 104 | BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75) \ | 104 | BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75) \ |
| 105 | BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127) | 105 | BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127) \ |
| 106 | BRCMF_ENUM_DEF(PSTA_PRIMARY_INTF_IND, 128) | ||
| 106 | 107 | ||
| 107 | #define BRCMF_ENUM_DEF(id, val) \ | 108 | #define BRCMF_ENUM_DEF(id, val) \ |
| 108 | BRCMF_E_##id = (val), | 109 | BRCMF_E_##id = (val), |
| @@ -114,6 +115,8 @@ enum brcmf_fweh_event_code { | |||
| 114 | }; | 115 | }; |
| 115 | #undef BRCMF_ENUM_DEF | 116 | #undef BRCMF_ENUM_DEF |
| 116 | 117 | ||
| 118 | #define BRCMF_EVENTING_MASK_LEN DIV_ROUND_UP(BRCMF_E_LAST, 8) | ||
| 119 | |||
| 117 | /* flags field values in struct brcmf_event_msg */ | 120 | /* flags field values in struct brcmf_event_msg */ |
| 118 | #define BRCMF_EVENT_MSG_LINK 0x01 | 121 | #define BRCMF_EVENT_MSG_LINK 0x01 |
| 119 | #define BRCMF_EVENT_MSG_FLUSHTXQ 0x02 | 122 | #define BRCMF_EVENT_MSG_FLUSHTXQ 0x02 |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 82f9140f3d35..d0cd0bf95c5a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | |||
| @@ -168,6 +168,7 @@ enum brcmf_fws_skb_state { | |||
| 168 | /** | 168 | /** |
| 169 | * struct brcmf_skbuff_cb - control buffer associated with skbuff. | 169 | * struct brcmf_skbuff_cb - control buffer associated with skbuff. |
| 170 | * | 170 | * |
| 171 | * @bus_flags: 2 bytes reserved for bus specific parameters | ||
| 171 | * @if_flags: holds interface index and packet related flags. | 172 | * @if_flags: holds interface index and packet related flags. |
| 172 | * @htod: host to device packet identifier (used in PKTTAG tlv). | 173 | * @htod: host to device packet identifier (used in PKTTAG tlv). |
| 173 | * @state: transmit state of the packet. | 174 | * @state: transmit state of the packet. |
| @@ -177,6 +178,7 @@ enum brcmf_fws_skb_state { | |||
| 177 | * provides 48 bytes of storage so this structure should not exceed that. | 178 | * provides 48 bytes of storage so this structure should not exceed that. |
| 178 | */ | 179 | */ |
| 179 | struct brcmf_skbuff_cb { | 180 | struct brcmf_skbuff_cb { |
| 181 | u16 bus_flags; | ||
| 180 | u16 if_flags; | 182 | u16 if_flags; |
| 181 | u32 htod; | 183 | u32 htod; |
| 182 | enum brcmf_fws_skb_state state; | 184 | enum brcmf_fws_skb_state state; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c index ca72177388b9..2096a14ef1fb 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
| 19 | #include <linux/netdevice.h> | 19 | #include <linux/netdevice.h> |
| 20 | #include <linux/mmc/card.h> | 20 | #include <linux/mmc/card.h> |
| 21 | #include <linux/mmc/sdio_func.h> | ||
| 21 | #include <linux/ssb/ssb_regs.h> | 22 | #include <linux/ssb/ssb_regs.h> |
| 22 | #include <linux/bcma/bcma.h> | 23 | #include <linux/bcma/bcma.h> |
| 23 | 24 | ||
| @@ -136,6 +137,8 @@ brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev *sdiodev, | |||
| 136 | u8 idx; | 137 | u8 idx; |
| 137 | 138 | ||
| 138 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); | 139 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); |
| 140 | if (idx == BRCMF_MAX_CORENUM) | ||
| 141 | return false; | ||
| 139 | 142 | ||
| 140 | regdata = brcmf_sdio_regrl(sdiodev, | 143 | regdata = brcmf_sdio_regrl(sdiodev, |
| 141 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), | 144 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), |
| @@ -154,6 +157,8 @@ brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev, | |||
| 154 | bool ret; | 157 | bool ret; |
| 155 | 158 | ||
| 156 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); | 159 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); |
| 160 | if (idx == BRCMF_MAX_CORENUM) | ||
| 161 | return false; | ||
| 157 | 162 | ||
| 158 | regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | 163 | regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, |
| 159 | NULL); | 164 | NULL); |
| @@ -261,6 +266,8 @@ brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev, | |||
| 261 | u32 regdata; | 266 | u32 regdata; |
| 262 | 267 | ||
| 263 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); | 268 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); |
| 269 | if (idx == BRCMF_MAX_CORENUM) | ||
| 270 | return; | ||
| 264 | 271 | ||
| 265 | /* if core is already in reset, just return */ | 272 | /* if core is already in reset, just return */ |
| 266 | regdata = brcmf_sdio_regrl(sdiodev, | 273 | regdata = brcmf_sdio_regrl(sdiodev, |
| @@ -304,6 +311,8 @@ brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev, | |||
| 304 | u8 idx; | 311 | u8 idx; |
| 305 | 312 | ||
| 306 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); | 313 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); |
| 314 | if (idx == BRCMF_MAX_CORENUM) | ||
| 315 | return; | ||
| 307 | 316 | ||
| 308 | /* | 317 | /* |
| 309 | * Must do the disable sequence first to work for | 318 | * Must do the disable sequence first to work for |
| @@ -368,6 +377,8 @@ brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev, | |||
| 368 | u32 regdata; | 377 | u32 regdata; |
| 369 | 378 | ||
| 370 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); | 379 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); |
| 380 | if (idx == BRCMF_MAX_CORENUM) | ||
| 381 | return; | ||
| 371 | 382 | ||
| 372 | /* must disable first to work for arbitrary current core state */ | 383 | /* must disable first to work for arbitrary current core state */ |
| 373 | brcmf_sdio_ai_coredisable(sdiodev, ci, coreid, core_bits); | 384 | brcmf_sdio_ai_coredisable(sdiodev, ci, coreid, core_bits); |
| @@ -444,6 +455,9 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev, | |||
| 444 | NULL); | 455 | NULL); |
| 445 | ci->chip = regdata & CID_ID_MASK; | 456 | ci->chip = regdata & CID_ID_MASK; |
| 446 | ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT; | 457 | ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT; |
| 458 | if (sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 && | ||
| 459 | ci->chiprev >= 2) | ||
| 460 | ci->chip = BCM4339_CHIP_ID; | ||
| 447 | ci->socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT; | 461 | ci->socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT; |
| 448 | 462 | ||
| 449 | brcmf_dbg(INFO, "chipid=0x%x chiprev=%d\n", ci->chip, ci->chiprev); | 463 | brcmf_dbg(INFO, "chipid=0x%x chiprev=%d\n", ci->chip, ci->chiprev); |
| @@ -541,6 +555,20 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev, | |||
| 541 | ci->ramsize = 0xc0000; | 555 | ci->ramsize = 0xc0000; |
| 542 | ci->rambase = 0x180000; | 556 | ci->rambase = 0x180000; |
| 543 | break; | 557 | break; |
| 558 | case BCM4339_CHIP_ID: | ||
| 559 | ci->c_inf[0].wrapbase = 0x18100000; | ||
| 560 | ci->c_inf[0].cib = 0x2e084411; | ||
| 561 | ci->c_inf[1].id = BCMA_CORE_SDIO_DEV; | ||
| 562 | ci->c_inf[1].base = 0x18005000; | ||
| 563 | ci->c_inf[1].wrapbase = 0x18105000; | ||
| 564 | ci->c_inf[1].cib = 0x15004211; | ||
| 565 | ci->c_inf[2].id = BCMA_CORE_ARM_CR4; | ||
| 566 | ci->c_inf[2].base = 0x18002000; | ||
| 567 | ci->c_inf[2].wrapbase = 0x18102000; | ||
| 568 | ci->c_inf[2].cib = 0x04084411; | ||
| 569 | ci->ramsize = 0xc0000; | ||
| 570 | ci->rambase = 0x180000; | ||
| 571 | break; | ||
| 544 | default: | 572 | default: |
| 545 | brcmf_err("chipid 0x%x is not supported\n", ci->chip); | 573 | brcmf_err("chipid 0x%x is not supported\n", ci->chip); |
| 546 | return -ENODEV; | 574 | return -ENODEV; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h index 83c041f1bf4a..507c61c991fa 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h | |||
| @@ -54,6 +54,14 @@ | |||
| 54 | 54 | ||
| 55 | #define BRCMF_MAX_CORENUM 6 | 55 | #define BRCMF_MAX_CORENUM 6 |
| 56 | 56 | ||
| 57 | /* SDIO device ID */ | ||
| 58 | #define SDIO_DEVICE_ID_BROADCOM_43143 43143 | ||
| 59 | #define SDIO_DEVICE_ID_BROADCOM_43241 0x4324 | ||
| 60 | #define SDIO_DEVICE_ID_BROADCOM_4329 0x4329 | ||
| 61 | #define SDIO_DEVICE_ID_BROADCOM_4330 0x4330 | ||
| 62 | #define SDIO_DEVICE_ID_BROADCOM_4334 0x4334 | ||
| 63 | #define SDIO_DEVICE_ID_BROADCOM_4335_4339 0x4335 | ||
| 64 | |||
| 57 | struct chip_core_info { | 65 | struct chip_core_info { |
| 58 | u16 id; | 66 | u16 id; |
| 59 | u16 rev; | 67 | u16 rev; |
| @@ -215,17 +223,16 @@ struct sdpcmd_regs { | |||
| 215 | u16 PAD[0x80]; | 223 | u16 PAD[0x80]; |
| 216 | }; | 224 | }; |
| 217 | 225 | ||
| 218 | extern int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev, | 226 | int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev, |
| 219 | struct chip_info **ci_ptr, u32 regs); | 227 | struct chip_info **ci_ptr, u32 regs); |
| 220 | extern void brcmf_sdio_chip_detach(struct chip_info **ci_ptr); | 228 | void brcmf_sdio_chip_detach(struct chip_info **ci_ptr); |
| 221 | extern void brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, | 229 | void brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, |
| 222 | struct chip_info *ci, | 230 | struct chip_info *ci, u32 drivestrength); |
| 223 | u32 drivestrength); | 231 | u8 brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid); |
| 224 | extern u8 brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid); | 232 | void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev, |
| 225 | extern void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev, | 233 | struct chip_info *ci); |
| 226 | struct chip_info *ci); | 234 | bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev, |
| 227 | extern bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev, | 235 | struct chip_info *ci, char *nvram_dat, |
| 228 | struct chip_info *ci, char *nvram_dat, | 236 | uint nvram_sz); |
| 229 | uint nvram_sz); | ||
| 230 | 237 | ||
| 231 | #endif /* _BRCMFMAC_SDIO_CHIP_H_ */ | 238 | #endif /* _BRCMFMAC_SDIO_CHIP_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h index 2b5407f002e5..fc0d4f0129db 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h | |||
| @@ -178,21 +178,25 @@ struct brcmf_sdio_dev { | |||
| 178 | bool irq_en; /* irq enable flags */ | 178 | bool irq_en; /* irq enable flags */ |
| 179 | spinlock_t irq_en_lock; | 179 | spinlock_t irq_en_lock; |
| 180 | bool irq_wake; /* irq wake enable flags */ | 180 | bool irq_wake; /* irq wake enable flags */ |
| 181 | bool sg_support; | ||
| 182 | uint max_request_size; | ||
| 183 | ushort max_segment_count; | ||
| 184 | uint max_segment_size; | ||
| 181 | }; | 185 | }; |
| 182 | 186 | ||
| 183 | /* Register/deregister interrupt handler. */ | 187 | /* Register/deregister interrupt handler. */ |
| 184 | extern int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev); | 188 | int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev); |
| 185 | extern int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev); | 189 | int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev); |
| 186 | 190 | ||
| 187 | /* sdio device register access interface */ | 191 | /* sdio device register access interface */ |
| 188 | extern u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret); | 192 | u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret); |
| 189 | extern u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret); | 193 | u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret); |
| 190 | extern void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, | 194 | void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, u8 data, |
| 191 | u8 data, int *ret); | 195 | int *ret); |
| 192 | extern void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, | 196 | void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, u32 data, |
| 193 | u32 data, int *ret); | 197 | int *ret); |
| 194 | extern int brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | 198 | int brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, |
| 195 | void *data, bool write); | 199 | void *data, bool write); |
| 196 | 200 | ||
| 197 | /* Buffer transfer to/from device (client) core via cmd53. | 201 | /* Buffer transfer to/from device (client) core via cmd53. |
| 198 | * fn: function number | 202 | * fn: function number |
| @@ -206,22 +210,17 @@ extern int brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
| 206 | * Returns 0 or error code. | 210 | * Returns 0 or error code. |
| 207 | * NOTE: Async operation is not currently supported. | 211 | * NOTE: Async operation is not currently supported. |
| 208 | */ | 212 | */ |
| 209 | extern int | 213 | int brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, |
| 210 | brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | 214 | uint flags, struct sk_buff_head *pktq); |
| 211 | uint flags, struct sk_buff_head *pktq); | 215 | int brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, |
| 212 | extern int | 216 | uint flags, u8 *buf, uint nbytes); |
| 213 | brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | 217 | |
| 214 | uint flags, u8 *buf, uint nbytes); | 218 | int brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, |
| 215 | 219 | uint flags, struct sk_buff *pkt); | |
| 216 | extern int | 220 | int brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, |
| 217 | brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | 221 | uint flags, u8 *buf, uint nbytes); |
| 218 | uint flags, struct sk_buff *pkt); | 222 | int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, |
| 219 | extern int | 223 | uint flags, struct sk_buff_head *pktq, uint totlen); |
| 220 | brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | ||
| 221 | uint flags, u8 *buf, uint nbytes); | ||
| 222 | extern int | ||
| 223 | brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | ||
| 224 | uint flags, struct sk_buff_head *pktq); | ||
| 225 | 224 | ||
| 226 | /* Flags bits */ | 225 | /* Flags bits */ |
| 227 | 226 | ||
| @@ -237,46 +236,43 @@ brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
| 237 | * nbytes: number of bytes to transfer to/from buf | 236 | * nbytes: number of bytes to transfer to/from buf |
| 238 | * Returns 0 or error code. | 237 | * Returns 0 or error code. |
| 239 | */ | 238 | */ |
| 240 | extern int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, | 239 | int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr, |
| 241 | u32 addr, u8 *buf, uint nbytes); | 240 | u8 *buf, uint nbytes); |
| 242 | extern int brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, | 241 | int brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, |
| 243 | u32 address, u8 *data, uint size); | 242 | u8 *data, uint size); |
| 244 | 243 | ||
| 245 | /* Issue an abort to the specified function */ | 244 | /* Issue an abort to the specified function */ |
| 246 | extern int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn); | 245 | int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn); |
| 247 | 246 | ||
| 248 | /* platform specific/high level functions */ | 247 | /* platform specific/high level functions */ |
| 249 | extern int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev); | 248 | int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev); |
| 250 | extern int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev); | 249 | int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev); |
| 251 | 250 | ||
| 252 | /* attach, return handler on success, NULL if failed. | 251 | /* attach, return handler on success, NULL if failed. |
| 253 | * The handler shall be provided by all subsequent calls. No local cache | 252 | * The handler shall be provided by all subsequent calls. No local cache |
| 254 | * cfghdl points to the starting address of pci device mapped memory | 253 | * cfghdl points to the starting address of pci device mapped memory |
| 255 | */ | 254 | */ |
| 256 | extern int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev); | 255 | int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev); |
| 257 | extern void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev); | 256 | void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev); |
| 258 | 257 | ||
| 259 | /* read or write one byte using cmd52 */ | 258 | /* read or write one byte using cmd52 */ |
| 260 | extern int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, | 259 | int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint fnc, |
| 261 | uint fnc, uint addr, u8 *byte); | 260 | uint addr, u8 *byte); |
| 262 | 261 | ||
| 263 | /* read or write 2/4 bytes using cmd53 */ | 262 | /* read or write 2/4 bytes using cmd53 */ |
| 264 | extern int | 263 | int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, uint rw, uint fnc, |
| 265 | brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, | 264 | uint addr, u32 *word, uint nbyte); |
| 266 | uint rw, uint fnc, uint addr, | ||
| 267 | u32 *word, uint nbyte); | ||
| 268 | 265 | ||
| 269 | /* Watchdog timer interface for pm ops */ | 266 | /* Watchdog timer interface for pm ops */ |
| 270 | extern void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, | 267 | void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable); |
| 271 | bool enable); | ||
| 272 | 268 | ||
| 273 | extern void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev); | 269 | void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev); |
| 274 | extern void brcmf_sdbrcm_disconnect(void *ptr); | 270 | void brcmf_sdbrcm_disconnect(void *ptr); |
| 275 | extern void brcmf_sdbrcm_isr(void *arg); | 271 | void brcmf_sdbrcm_isr(void *arg); |
| 276 | 272 | ||
| 277 | extern void brcmf_sdbrcm_wd_timer(struct brcmf_sdio *bus, uint wdtick); | 273 | void brcmf_sdbrcm_wd_timer(struct brcmf_sdio *bus, uint wdtick); |
| 278 | 274 | ||
| 279 | extern void brcmf_pm_resume_wait(struct brcmf_sdio_dev *sdiodev, | 275 | void brcmf_pm_resume_wait(struct brcmf_sdio_dev *sdiodev, |
| 280 | wait_queue_head_t *wq); | 276 | wait_queue_head_t *wq); |
| 281 | extern bool brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev); | 277 | bool brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev); |
| 282 | #endif /* _BRCM_SDH_H_ */ | 278 | #endif /* _BRCM_SDH_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h index bc2917112899..3c67529b9074 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h | |||
| @@ -78,13 +78,15 @@ TRACE_EVENT(brcmf_hexdump, | |||
| 78 | TP_ARGS(data, len), | 78 | TP_ARGS(data, len), |
| 79 | TP_STRUCT__entry( | 79 | TP_STRUCT__entry( |
| 80 | __field(unsigned long, len) | 80 | __field(unsigned long, len) |
| 81 | __field(unsigned long, addr) | ||
| 81 | __dynamic_array(u8, hdata, len) | 82 | __dynamic_array(u8, hdata, len) |
| 82 | ), | 83 | ), |
| 83 | TP_fast_assign( | 84 | TP_fast_assign( |
| 84 | __entry->len = len; | 85 | __entry->len = len; |
| 86 | __entry->addr = (unsigned long)data; | ||
| 85 | memcpy(__get_dynamic_array(hdata), data, len); | 87 | memcpy(__get_dynamic_array(hdata), data, len); |
| 86 | ), | 88 | ), |
| 87 | TP_printk("hexdump [length=%lu]", __entry->len) | 89 | TP_printk("hexdump [addr=%lx, length=%lu]", __entry->addr, __entry->len) |
| 88 | ); | 90 | ); |
| 89 | 91 | ||
| 90 | TRACE_EVENT(brcmf_bdchdr, | 92 | TRACE_EVENT(brcmf_bdchdr, |
| @@ -108,6 +110,23 @@ TRACE_EVENT(brcmf_bdchdr, | |||
| 108 | TP_printk("bdc: prio=%d siglen=%d", __entry->prio, __entry->siglen) | 110 | TP_printk("bdc: prio=%d siglen=%d", __entry->prio, __entry->siglen) |
| 109 | ); | 111 | ); |
| 110 | 112 | ||
| 113 | TRACE_EVENT(brcmf_sdpcm_hdr, | ||
| 114 | TP_PROTO(bool tx, void *data), | ||
| 115 | TP_ARGS(tx, data), | ||
| 116 | TP_STRUCT__entry( | ||
| 117 | __field(u8, tx) | ||
| 118 | __field(u16, len) | ||
| 119 | __array(u8, hdr, 12) | ||
| 120 | ), | ||
| 121 | TP_fast_assign( | ||
| 122 | memcpy(__entry->hdr, data, 12); | ||
| 123 | __entry->len = __entry->hdr[0] | (__entry->hdr[1] << 8); | ||
| 124 | __entry->tx = tx ? 1 : 0; | ||
| 125 | ), | ||
| 126 | TP_printk("sdpcm: %s len %u, seq %d", __entry->tx ? "TX" : "RX", | ||
| 127 | __entry->len, __entry->hdr[4]) | ||
| 128 | ); | ||
| 129 | |||
| 111 | #ifdef CONFIG_BRCM_TRACING | 130 | #ifdef CONFIG_BRCM_TRACING |
| 112 | 131 | ||
| 113 | #undef TRACE_INCLUDE_PATH | 132 | #undef TRACE_INCLUDE_PATH |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index f4aea47e0730..422f44c63175 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c | |||
| @@ -435,7 +435,6 @@ static void brcmf_usb_rx_complete(struct urb *urb) | |||
| 435 | struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context; | 435 | struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context; |
| 436 | struct brcmf_usbdev_info *devinfo = req->devinfo; | 436 | struct brcmf_usbdev_info *devinfo = req->devinfo; |
| 437 | struct sk_buff *skb; | 437 | struct sk_buff *skb; |
| 438 | struct sk_buff_head skbq; | ||
| 439 | 438 | ||
| 440 | brcmf_dbg(USB, "Enter, urb->status=%d\n", urb->status); | 439 | brcmf_dbg(USB, "Enter, urb->status=%d\n", urb->status); |
| 441 | brcmf_usb_del_fromq(devinfo, req); | 440 | brcmf_usb_del_fromq(devinfo, req); |
| @@ -450,10 +449,8 @@ static void brcmf_usb_rx_complete(struct urb *urb) | |||
| 450 | } | 449 | } |
| 451 | 450 | ||
| 452 | if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) { | 451 | if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) { |
| 453 | skb_queue_head_init(&skbq); | ||
| 454 | skb_queue_tail(&skbq, skb); | ||
| 455 | skb_put(skb, urb->actual_length); | 452 | skb_put(skb, urb->actual_length); |
| 456 | brcmf_rx_frames(devinfo->dev, &skbq); | 453 | brcmf_rx_frame(devinfo->dev, skb); |
| 457 | brcmf_usb_rx_refill(devinfo, req); | 454 | brcmf_usb_rx_refill(devinfo, req); |
| 458 | } else { | 455 | } else { |
| 459 | brcmu_pkt_buf_free_skb(skb); | 456 | brcmu_pkt_buf_free_skb(skb); |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h index a8a267b5b87a..2d08c155c23b 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h | |||
| @@ -172,19 +172,19 @@ struct si_info { | |||
| 172 | 172 | ||
| 173 | 173 | ||
| 174 | /* AMBA Interconnect exported externs */ | 174 | /* AMBA Interconnect exported externs */ |
| 175 | extern u32 ai_core_cflags(struct bcma_device *core, u32 mask, u32 val); | 175 | u32 ai_core_cflags(struct bcma_device *core, u32 mask, u32 val); |
| 176 | 176 | ||
| 177 | /* === exported functions === */ | 177 | /* === exported functions === */ |
| 178 | extern struct si_pub *ai_attach(struct bcma_bus *pbus); | 178 | struct si_pub *ai_attach(struct bcma_bus *pbus); |
| 179 | extern void ai_detach(struct si_pub *sih); | 179 | void ai_detach(struct si_pub *sih); |
| 180 | extern uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val); | 180 | uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val); |
| 181 | extern void ai_clkctl_init(struct si_pub *sih); | 181 | void ai_clkctl_init(struct si_pub *sih); |
| 182 | extern u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih); | 182 | u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih); |
| 183 | extern bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode); | 183 | bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode); |
| 184 | extern bool ai_deviceremoved(struct si_pub *sih); | 184 | bool ai_deviceremoved(struct si_pub *sih); |
| 185 | 185 | ||
| 186 | /* Enable Ex-PA for 4313 */ | 186 | /* Enable Ex-PA for 4313 */ |
| 187 | extern void ai_epa_4313war(struct si_pub *sih); | 187 | void ai_epa_4313war(struct si_pub *sih); |
| 188 | 188 | ||
| 189 | static inline u32 ai_get_cccaps(struct si_pub *sih) | 189 | static inline u32 ai_get_cccaps(struct si_pub *sih) |
| 190 | { | 190 | { |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h index 73d01e586109..03bdcf29bd50 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h | |||
| @@ -37,17 +37,17 @@ struct brcms_ampdu_session { | |||
| 37 | u16 dma_len; | 37 | u16 dma_len; |
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| 40 | extern void brcms_c_ampdu_reset_session(struct brcms_ampdu_session *session, | 40 | void brcms_c_ampdu_reset_session(struct brcms_ampdu_session *session, |
| 41 | struct brcms_c_info *wlc); | 41 | struct brcms_c_info *wlc); |
| 42 | extern int brcms_c_ampdu_add_frame(struct brcms_ampdu_session *session, | 42 | int brcms_c_ampdu_add_frame(struct brcms_ampdu_session *session, |
| 43 | struct sk_buff *p); | 43 | struct sk_buff *p); |
| 44 | extern void brcms_c_ampdu_finalize(struct brcms_ampdu_session *session); | 44 | void brcms_c_ampdu_finalize(struct brcms_ampdu_session *session); |
| 45 | 45 | ||
| 46 | extern struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc); | 46 | struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc); |
| 47 | extern void brcms_c_ampdu_detach(struct ampdu_info *ampdu); | 47 | void brcms_c_ampdu_detach(struct ampdu_info *ampdu); |
| 48 | extern void brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb, | 48 | void brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb, |
| 49 | struct sk_buff *p, struct tx_status *txs); | 49 | struct sk_buff *p, struct tx_status *txs); |
| 50 | extern void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc); | 50 | void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc); |
| 51 | extern void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu); | 51 | void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu); |
| 52 | 52 | ||
| 53 | #endif /* _BRCM_AMPDU_H_ */ | 53 | #endif /* _BRCM_AMPDU_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/antsel.h b/drivers/net/wireless/brcm80211/brcmsmac/antsel.h index 97ea3881a8ec..a3d487ab1964 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/antsel.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/antsel.h | |||
| @@ -17,13 +17,11 @@ | |||
| 17 | #ifndef _BRCM_ANTSEL_H_ | 17 | #ifndef _BRCM_ANTSEL_H_ |
| 18 | #define _BRCM_ANTSEL_H_ | 18 | #define _BRCM_ANTSEL_H_ |
| 19 | 19 | ||
| 20 | extern struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc); | 20 | struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc); |
| 21 | extern void brcms_c_antsel_detach(struct antsel_info *asi); | 21 | void brcms_c_antsel_detach(struct antsel_info *asi); |
| 22 | extern void brcms_c_antsel_init(struct antsel_info *asi); | 22 | void brcms_c_antsel_init(struct antsel_info *asi); |
| 23 | extern void brcms_c_antsel_antcfg_get(struct antsel_info *asi, bool usedef, | 23 | void brcms_c_antsel_antcfg_get(struct antsel_info *asi, bool usedef, bool sel, |
| 24 | bool sel, | 24 | u8 id, u8 fbid, u8 *antcfg, u8 *fbantcfg); |
| 25 | u8 id, u8 fbid, u8 *antcfg, | 25 | u8 brcms_c_antsel_antsel2id(struct antsel_info *asi, u16 antsel); |
| 26 | u8 *fbantcfg); | ||
| 27 | extern u8 brcms_c_antsel_antsel2id(struct antsel_info *asi, u16 antsel); | ||
| 28 | 26 | ||
| 29 | #endif /* _BRCM_ANTSEL_H_ */ | 27 | #endif /* _BRCM_ANTSEL_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.h b/drivers/net/wireless/brcm80211/brcmsmac/channel.h index 006483a0abe6..39dd3a5b2979 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/channel.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.h | |||
| @@ -32,20 +32,16 @@ | |||
| 32 | 32 | ||
| 33 | #define BRCMS_DFS_EU (BRCMS_DFS_TPC | BRCMS_RADAR_TYPE_EU) /* Flag for DFS EU */ | 33 | #define BRCMS_DFS_EU (BRCMS_DFS_TPC | BRCMS_RADAR_TYPE_EU) /* Flag for DFS EU */ |
| 34 | 34 | ||
| 35 | extern struct brcms_cm_info * | 35 | struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc); |
| 36 | brcms_c_channel_mgr_attach(struct brcms_c_info *wlc); | ||
| 37 | 36 | ||
| 38 | extern void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm); | 37 | void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm); |
| 39 | 38 | ||
| 40 | extern bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, | 39 | bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec); |
| 41 | u16 chspec); | ||
| 42 | 40 | ||
| 43 | extern void brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, | 41 | void brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec, |
| 44 | u16 chanspec, | 42 | struct txpwr_limits *txpwr); |
| 45 | struct txpwr_limits *txpwr); | 43 | void brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec, |
| 46 | extern void brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, | 44 | u8 local_constraint_qdbm); |
| 47 | u16 chanspec, | 45 | void brcms_c_regd_init(struct brcms_c_info *wlc); |
| 48 | u8 local_constraint_qdbm); | ||
| 49 | extern void brcms_c_regd_init(struct brcms_c_info *wlc); | ||
| 50 | 46 | ||
| 51 | #endif /* _WLC_CHANNEL_H */ | 47 | #endif /* _WLC_CHANNEL_H */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h index 4090032e81a2..198053dfc310 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h | |||
| @@ -88,26 +88,26 @@ struct brcms_info { | |||
| 88 | }; | 88 | }; |
| 89 | 89 | ||
| 90 | /* misc callbacks */ | 90 | /* misc callbacks */ |
| 91 | extern void brcms_init(struct brcms_info *wl); | 91 | void brcms_init(struct brcms_info *wl); |
| 92 | extern uint brcms_reset(struct brcms_info *wl); | 92 | uint brcms_reset(struct brcms_info *wl); |
| 93 | extern void brcms_intrson(struct brcms_info *wl); | 93 | void brcms_intrson(struct brcms_info *wl); |
| 94 | extern u32 brcms_intrsoff(struct brcms_info *wl); | 94 | u32 brcms_intrsoff(struct brcms_info *wl); |
| 95 | extern void brcms_intrsrestore(struct brcms_info *wl, u32 macintmask); | 95 | void brcms_intrsrestore(struct brcms_info *wl, u32 macintmask); |
| 96 | extern int brcms_up(struct brcms_info *wl); | 96 | int brcms_up(struct brcms_info *wl); |
| 97 | extern void brcms_down(struct brcms_info *wl); | 97 | void brcms_down(struct brcms_info *wl); |
| 98 | extern void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif, | 98 | void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif, |
| 99 | bool state, int prio); | 99 | bool state, int prio); |
| 100 | extern bool brcms_rfkill_set_hw_state(struct brcms_info *wl); | 100 | bool brcms_rfkill_set_hw_state(struct brcms_info *wl); |
| 101 | 101 | ||
| 102 | /* timer functions */ | 102 | /* timer functions */ |
| 103 | extern struct brcms_timer *brcms_init_timer(struct brcms_info *wl, | 103 | struct brcms_timer *brcms_init_timer(struct brcms_info *wl, |
| 104 | void (*fn) (void *arg), void *arg, | 104 | void (*fn) (void *arg), void *arg, |
| 105 | const char *name); | 105 | const char *name); |
| 106 | extern void brcms_free_timer(struct brcms_timer *timer); | 106 | void brcms_free_timer(struct brcms_timer *timer); |
| 107 | extern void brcms_add_timer(struct brcms_timer *timer, uint ms, int periodic); | 107 | void brcms_add_timer(struct brcms_timer *timer, uint ms, int periodic); |
| 108 | extern bool brcms_del_timer(struct brcms_timer *timer); | 108 | bool brcms_del_timer(struct brcms_timer *timer); |
| 109 | extern void brcms_dpc(unsigned long data); | 109 | void brcms_dpc(unsigned long data); |
| 110 | extern void brcms_timer(struct brcms_timer *t); | 110 | void brcms_timer(struct brcms_timer *t); |
| 111 | extern void brcms_fatal_error(struct brcms_info *wl); | 111 | void brcms_fatal_error(struct brcms_info *wl); |
| 112 | 112 | ||
| 113 | #endif /* _BRCM_MAC80211_IF_H_ */ | 113 | #endif /* _BRCM_MAC80211_IF_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index 4608e0eb1493..8138f1cff4e5 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c | |||
| @@ -1906,14 +1906,14 @@ static void brcms_c_get_macaddr(struct brcms_hardware *wlc_hw, u8 etheraddr[ETH_ | |||
| 1906 | 1906 | ||
| 1907 | /* If macaddr exists, use it (Sromrev4, CIS, ...). */ | 1907 | /* If macaddr exists, use it (Sromrev4, CIS, ...). */ |
| 1908 | if (!is_zero_ether_addr(sprom->il0mac)) { | 1908 | if (!is_zero_ether_addr(sprom->il0mac)) { |
| 1909 | memcpy(etheraddr, sprom->il0mac, 6); | 1909 | memcpy(etheraddr, sprom->il0mac, ETH_ALEN); |
| 1910 | return; | 1910 | return; |
| 1911 | } | 1911 | } |
| 1912 | 1912 | ||
| 1913 | if (wlc_hw->_nbands > 1) | 1913 | if (wlc_hw->_nbands > 1) |
| 1914 | memcpy(etheraddr, sprom->et1mac, 6); | 1914 | memcpy(etheraddr, sprom->et1mac, ETH_ALEN); |
| 1915 | else | 1915 | else |
| 1916 | memcpy(etheraddr, sprom->il0mac, 6); | 1916 | memcpy(etheraddr, sprom->il0mac, ETH_ALEN); |
| 1917 | } | 1917 | } |
| 1918 | 1918 | ||
| 1919 | /* power both the pll and external oscillator on/off */ | 1919 | /* power both the pll and external oscillator on/off */ |
| @@ -5695,7 +5695,7 @@ static bool brcms_c_chipmatch_pci(struct bcma_device *core) | |||
| 5695 | return true; | 5695 | return true; |
| 5696 | if ((device == BCM43224_D11N_ID) || (device == BCM43225_D11N2G_ID)) | 5696 | if ((device == BCM43224_D11N_ID) || (device == BCM43225_D11N2G_ID)) |
| 5697 | return true; | 5697 | return true; |
| 5698 | if (device == BCM4313_D11N2G_ID) | 5698 | if (device == BCM4313_D11N2G_ID || device == BCM4313_CHIP_ID) |
| 5699 | return true; | 5699 | return true; |
| 5700 | if ((device == BCM43236_D11N_ID) || (device == BCM43236_D11N2G_ID)) | 5700 | if ((device == BCM43236_D11N_ID) || (device == BCM43236_D11N2G_ID)) |
| 5701 | return true; | 5701 | return true; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.h b/drivers/net/wireless/brcm80211/brcmsmac/main.h index b5d7a38b53fe..c4d135cff04a 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h | |||
| @@ -616,66 +616,54 @@ struct brcms_bss_cfg { | |||
| 616 | struct brcms_bss_info *current_bss; | 616 | struct brcms_bss_info *current_bss; |
| 617 | }; | 617 | }; |
| 618 | 618 | ||
| 619 | extern int brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, | 619 | int brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p); |
| 620 | struct sk_buff *p); | 620 | int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo, |
| 621 | extern int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo, | 621 | uint *blocks); |
| 622 | uint *blocks); | 622 | |
| 623 | 623 | int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config); | |
| 624 | extern int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config); | 624 | void brcms_c_mac_promisc(struct brcms_c_info *wlc, uint filter_flags); |
| 625 | extern void brcms_c_mac_promisc(struct brcms_c_info *wlc, uint filter_flags); | 625 | u16 brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec, uint mac_len); |
| 626 | extern u16 brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec, | 626 | u32 brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, u32 rspec, |
| 627 | uint mac_len); | 627 | bool use_rspec, u16 mimo_ctlchbw); |
| 628 | extern u32 brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, | 628 | u16 brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only, |
| 629 | u32 rspec, | 629 | u32 rts_rate, u32 frame_rate, |
| 630 | bool use_rspec, u16 mimo_ctlchbw); | 630 | u8 rts_preamble_type, u8 frame_preamble_type, |
| 631 | extern u16 brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only, | 631 | uint frame_len, bool ba); |
| 632 | u32 rts_rate, | 632 | void brcms_c_inval_dma_pkts(struct brcms_hardware *hw, |
| 633 | u32 frame_rate, | 633 | struct ieee80211_sta *sta, void (*dma_callback_fn)); |
| 634 | u8 rts_preamble_type, | 634 | void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend); |
| 635 | u8 frame_preamble_type, uint frame_len, | 635 | int brcms_c_set_nmode(struct brcms_c_info *wlc); |
| 636 | bool ba); | 636 | void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc, u32 bcn_rate); |
| 637 | extern void brcms_c_inval_dma_pkts(struct brcms_hardware *hw, | 637 | void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw, u8 antsel_type); |
| 638 | struct ieee80211_sta *sta, | 638 | void brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, u16 chanspec, |
| 639 | void (*dma_callback_fn)); | 639 | bool mute, struct txpwr_limits *txpwr); |
| 640 | extern void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend); | 640 | void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset, u16 v); |
| 641 | extern int brcms_c_set_nmode(struct brcms_c_info *wlc); | 641 | u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset); |
| 642 | extern void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc, | 642 | void brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask, u16 val, |
| 643 | u32 bcn_rate); | 643 | int bands); |
| 644 | extern void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw, | 644 | void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags); |
| 645 | u8 antsel_type); | 645 | void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val); |
| 646 | extern void brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, | 646 | void brcms_b_phy_reset(struct brcms_hardware *wlc_hw); |
| 647 | u16 chanspec, | 647 | void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw); |
| 648 | bool mute, struct txpwr_limits *txpwr); | 648 | void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw); |
| 649 | extern void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset, | 649 | void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw, |
| 650 | u16 v); | 650 | u32 override_bit); |
| 651 | extern u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset); | 651 | void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw, |
| 652 | extern void brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask, | 652 | u32 override_bit); |
| 653 | u16 val, int bands); | 653 | void brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, int offset, |
| 654 | extern void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags); | 654 | int len, void *buf); |
| 655 | extern void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val); | 655 | u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate); |
| 656 | extern void brcms_b_phy_reset(struct brcms_hardware *wlc_hw); | 656 | void brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw, uint offset, |
| 657 | extern void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw); | 657 | const void *buf, int len, u32 sel); |
| 658 | extern void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw); | 658 | void brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset, |
| 659 | extern void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw, | 659 | void *buf, int len, u32 sel); |
| 660 | u32 override_bit); | 660 | void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode); |
| 661 | extern void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw, | 661 | u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw); |
| 662 | u32 override_bit); | 662 | void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk); |
| 663 | extern void brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, | 663 | void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk); |
| 664 | int offset, int len, void *buf); | 664 | void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on); |
| 665 | extern u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate); | 665 | void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant); |
| 666 | extern void brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw, | 666 | void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw, u8 stf_mode); |
| 667 | uint offset, const void *buf, int len, | 667 | void brcms_c_init_scb(struct scb *scb); |
| 668 | u32 sel); | ||
| 669 | extern void brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset, | ||
| 670 | void *buf, int len, u32 sel); | ||
| 671 | extern void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode); | ||
| 672 | extern u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw); | ||
| 673 | extern void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk); | ||
| 674 | extern void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk); | ||
| 675 | extern void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on); | ||
| 676 | extern void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant); | ||
| 677 | extern void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw, | ||
| 678 | u8 stf_mode); | ||
| 679 | extern void brcms_c_init_scb(struct scb *scb); | ||
| 680 | 668 | ||
| 681 | #endif /* _BRCM_MAIN_H_ */ | 669 | #endif /* _BRCM_MAIN_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h index e34a71e7d242..4d3734f48d9c 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h | |||
| @@ -179,121 +179,106 @@ struct shared_phy_params { | |||
| 179 | }; | 179 | }; |
| 180 | 180 | ||
| 181 | 181 | ||
| 182 | extern struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp); | 182 | struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp); |
| 183 | extern struct brcms_phy_pub *wlc_phy_attach(struct shared_phy *sh, | 183 | struct brcms_phy_pub *wlc_phy_attach(struct shared_phy *sh, |
| 184 | struct bcma_device *d11core, | 184 | struct bcma_device *d11core, int bandtype, |
| 185 | int bandtype, struct wiphy *wiphy); | 185 | struct wiphy *wiphy); |
| 186 | extern void wlc_phy_detach(struct brcms_phy_pub *ppi); | 186 | void wlc_phy_detach(struct brcms_phy_pub *ppi); |
| 187 | 187 | ||
| 188 | extern bool wlc_phy_get_phyversion(struct brcms_phy_pub *pih, u16 *phytype, | 188 | bool wlc_phy_get_phyversion(struct brcms_phy_pub *pih, u16 *phytype, |
| 189 | u16 *phyrev, u16 *radioid, | 189 | u16 *phyrev, u16 *radioid, u16 *radiover); |
| 190 | u16 *radiover); | 190 | bool wlc_phy_get_encore(struct brcms_phy_pub *pih); |
| 191 | extern bool wlc_phy_get_encore(struct brcms_phy_pub *pih); | 191 | u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih); |
| 192 | extern u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih); | 192 | |
| 193 | 193 | void wlc_phy_hw_clk_state_upd(struct brcms_phy_pub *ppi, bool newstate); | |
| 194 | extern void wlc_phy_hw_clk_state_upd(struct brcms_phy_pub *ppi, bool newstate); | 194 | void wlc_phy_hw_state_upd(struct brcms_phy_pub *ppi, bool newstate); |
| 195 | extern void wlc_phy_hw_state_upd(struct brcms_phy_pub *ppi, bool newstate); | 195 | void wlc_phy_init(struct brcms_phy_pub *ppi, u16 chanspec); |
| 196 | extern void wlc_phy_init(struct brcms_phy_pub *ppi, u16 chanspec); | 196 | void wlc_phy_watchdog(struct brcms_phy_pub *ppi); |
| 197 | extern void wlc_phy_watchdog(struct brcms_phy_pub *ppi); | 197 | int wlc_phy_down(struct brcms_phy_pub *ppi); |
| 198 | extern int wlc_phy_down(struct brcms_phy_pub *ppi); | 198 | u32 wlc_phy_clk_bwbits(struct brcms_phy_pub *pih); |
| 199 | extern u32 wlc_phy_clk_bwbits(struct brcms_phy_pub *pih); | 199 | void wlc_phy_cal_init(struct brcms_phy_pub *ppi); |
| 200 | extern void wlc_phy_cal_init(struct brcms_phy_pub *ppi); | 200 | void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init); |
| 201 | extern void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init); | 201 | |
| 202 | 202 | void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, u16 chanspec); | |
| 203 | extern void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, | 203 | u16 wlc_phy_chanspec_get(struct brcms_phy_pub *ppi); |
| 204 | u16 chanspec); | 204 | void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi, u16 newch); |
| 205 | extern u16 wlc_phy_chanspec_get(struct brcms_phy_pub *ppi); | 205 | u16 wlc_phy_bw_state_get(struct brcms_phy_pub *ppi); |
| 206 | extern void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi, | 206 | void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw); |
| 207 | u16 newch); | 207 | |
| 208 | extern u16 wlc_phy_bw_state_get(struct brcms_phy_pub *ppi); | 208 | int wlc_phy_rssi_compute(struct brcms_phy_pub *pih, struct d11rxhdr *rxh); |
| 209 | extern void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw); | 209 | void wlc_phy_por_inform(struct brcms_phy_pub *ppi); |
| 210 | 210 | void wlc_phy_noise_sample_intr(struct brcms_phy_pub *ppi); | |
| 211 | extern int wlc_phy_rssi_compute(struct brcms_phy_pub *pih, | 211 | bool wlc_phy_bist_check_phy(struct brcms_phy_pub *ppi); |
| 212 | struct d11rxhdr *rxh); | 212 | |
| 213 | extern void wlc_phy_por_inform(struct brcms_phy_pub *ppi); | 213 | void wlc_phy_set_deaf(struct brcms_phy_pub *ppi, bool user_flag); |
| 214 | extern void wlc_phy_noise_sample_intr(struct brcms_phy_pub *ppi); | 214 | |
| 215 | extern bool wlc_phy_bist_check_phy(struct brcms_phy_pub *ppi); | 215 | void wlc_phy_switch_radio(struct brcms_phy_pub *ppi, bool on); |
| 216 | 216 | void wlc_phy_anacore(struct brcms_phy_pub *ppi, bool on); | |
| 217 | extern void wlc_phy_set_deaf(struct brcms_phy_pub *ppi, bool user_flag); | 217 | |
| 218 | 218 | ||
| 219 | extern void wlc_phy_switch_radio(struct brcms_phy_pub *ppi, bool on); | 219 | void wlc_phy_BSSinit(struct brcms_phy_pub *ppi, bool bonlyap, int rssi); |
| 220 | extern void wlc_phy_anacore(struct brcms_phy_pub *ppi, bool on); | 220 | |
| 221 | 221 | void wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub *ppi, | |
| 222 | 222 | bool wide_filter); | |
| 223 | extern void wlc_phy_BSSinit(struct brcms_phy_pub *ppi, bool bonlyap, int rssi); | 223 | void wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band, |
| 224 | 224 | struct brcms_chanvec *channels); | |
| 225 | extern void wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub *ppi, | 225 | u16 wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, uint band); |
| 226 | bool wide_filter); | 226 | |
| 227 | extern void wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band, | 227 | void wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint chan, u8 *_min_, |
| 228 | struct brcms_chanvec *channels); | 228 | u8 *_max_, int rate); |
| 229 | extern u16 wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, | 229 | void wlc_phy_txpower_sromlimit_max_get(struct brcms_phy_pub *ppi, uint chan, |
| 230 | uint band); | 230 | u8 *_max_, u8 *_min_); |
| 231 | 231 | void wlc_phy_txpower_boardlimit_band(struct brcms_phy_pub *ppi, uint band, | |
| 232 | extern void wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint chan, | 232 | s32 *, s32 *, u32 *); |
| 233 | u8 *_min_, u8 *_max_, int rate); | 233 | void wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi, struct txpwr_limits *, |
| 234 | extern void wlc_phy_txpower_sromlimit_max_get(struct brcms_phy_pub *ppi, | 234 | u16 chanspec); |
| 235 | uint chan, u8 *_max_, u8 *_min_); | 235 | int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm, bool *override); |
| 236 | extern void wlc_phy_txpower_boardlimit_band(struct brcms_phy_pub *ppi, | 236 | int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, bool override); |
| 237 | uint band, s32 *, s32 *, u32 *); | 237 | void wlc_phy_txpower_target_set(struct brcms_phy_pub *ppi, |
| 238 | extern void wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi, | 238 | struct txpwr_limits *); |
| 239 | struct txpwr_limits *, | 239 | bool wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub *ppi); |
| 240 | u16 chanspec); | 240 | void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi, bool hwpwrctrl); |
| 241 | extern int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm, | 241 | u8 wlc_phy_txpower_get_target_min(struct brcms_phy_pub *ppi); |
| 242 | bool *override); | 242 | u8 wlc_phy_txpower_get_target_max(struct brcms_phy_pub *ppi); |
| 243 | extern int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, | 243 | bool wlc_phy_txpower_ipa_ison(struct brcms_phy_pub *pih); |
| 244 | bool override); | 244 | |
| 245 | extern void wlc_phy_txpower_target_set(struct brcms_phy_pub *ppi, | 245 | void wlc_phy_stf_chain_init(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain); |
| 246 | struct txpwr_limits *); | 246 | void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain); |
| 247 | extern bool wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub *ppi); | 247 | void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain, u8 *rxchain); |
| 248 | extern void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi, | 248 | u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih); |
| 249 | bool hwpwrctrl); | 249 | s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih, u16 chanspec); |
| 250 | extern u8 wlc_phy_txpower_get_target_min(struct brcms_phy_pub *ppi); | 250 | void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool val); |
| 251 | extern u8 wlc_phy_txpower_get_target_max(struct brcms_phy_pub *ppi); | 251 | |
| 252 | extern bool wlc_phy_txpower_ipa_ison(struct brcms_phy_pub *pih); | 252 | void wlc_phy_cal_perical(struct brcms_phy_pub *ppi, u8 reason); |
| 253 | 253 | void wlc_phy_noise_sample_request_external(struct brcms_phy_pub *ppi); | |
| 254 | extern void wlc_phy_stf_chain_init(struct brcms_phy_pub *pih, u8 txchain, | 254 | void wlc_phy_edcrs_lock(struct brcms_phy_pub *pih, bool lock); |
| 255 | u8 rxchain); | 255 | void wlc_phy_cal_papd_recal(struct brcms_phy_pub *ppi); |
| 256 | extern void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain, | 256 | |
| 257 | u8 rxchain); | 257 | void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val); |
| 258 | extern void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain, | 258 | void wlc_phy_clear_tssi(struct brcms_phy_pub *ppi); |
| 259 | u8 *rxchain); | 259 | void wlc_phy_hold_upd(struct brcms_phy_pub *ppi, u32 id, bool val); |
| 260 | extern u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih); | 260 | void wlc_phy_mute_upd(struct brcms_phy_pub *ppi, bool val, u32 flags); |
| 261 | extern s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih, | 261 | |
| 262 | u16 chanspec); | 262 | void wlc_phy_antsel_type_set(struct brcms_phy_pub *ppi, u8 antsel_type); |
| 263 | extern void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool val); | 263 | |
| 264 | 264 | void wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi, | |
| 265 | extern void wlc_phy_cal_perical(struct brcms_phy_pub *ppi, u8 reason); | 265 | struct tx_power *power, uint channel); |
| 266 | extern void wlc_phy_noise_sample_request_external(struct brcms_phy_pub *ppi); | 266 | |
| 267 | extern void wlc_phy_edcrs_lock(struct brcms_phy_pub *pih, bool lock); | 267 | void wlc_phy_initcal_enable(struct brcms_phy_pub *pih, bool initcal); |
| 268 | extern void wlc_phy_cal_papd_recal(struct brcms_phy_pub *ppi); | 268 | bool wlc_phy_test_ison(struct brcms_phy_pub *ppi); |
| 269 | 269 | void wlc_phy_txpwr_percent_set(struct brcms_phy_pub *ppi, u8 txpwr_percent); | |
| 270 | extern void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val); | 270 | void wlc_phy_ofdm_rateset_war(struct brcms_phy_pub *pih, bool war); |
| 271 | extern void wlc_phy_clear_tssi(struct brcms_phy_pub *ppi); | 271 | void wlc_phy_bf_preempt_enable(struct brcms_phy_pub *pih, bool bf_preempt); |
| 272 | extern void wlc_phy_hold_upd(struct brcms_phy_pub *ppi, u32 id, bool val); | 272 | void wlc_phy_machwcap_set(struct brcms_phy_pub *ppi, u32 machwcap); |
| 273 | extern void wlc_phy_mute_upd(struct brcms_phy_pub *ppi, bool val, u32 flags); | 273 | |
| 274 | 274 | void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end); | |
| 275 | extern void wlc_phy_antsel_type_set(struct brcms_phy_pub *ppi, u8 antsel_type); | 275 | |
| 276 | 276 | void wlc_phy_freqtrack_start(struct brcms_phy_pub *ppi); | |
| 277 | extern void wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi, | 277 | void wlc_phy_freqtrack_end(struct brcms_phy_pub *ppi); |
| 278 | struct tx_power *power, uint channel); | 278 | |
| 279 | 279 | const u8 *wlc_phy_get_ofdm_rate_lookup(void); | |
| 280 | extern void wlc_phy_initcal_enable(struct brcms_phy_pub *pih, bool initcal); | 280 | |
| 281 | extern bool wlc_phy_test_ison(struct brcms_phy_pub *ppi); | 281 | s8 wlc_phy_get_tx_power_offset_by_mcs(struct brcms_phy_pub *ppi, |
| 282 | extern void wlc_phy_txpwr_percent_set(struct brcms_phy_pub *ppi, | 282 | u8 mcs_offset); |
| 283 | u8 txpwr_percent); | 283 | s8 wlc_phy_get_tx_power_offset(struct brcms_phy_pub *ppi, u8 tbl_offset); |
| 284 | extern void wlc_phy_ofdm_rateset_war(struct brcms_phy_pub *pih, bool war); | ||
| 285 | extern void wlc_phy_bf_preempt_enable(struct brcms_phy_pub *pih, | ||
| 286 | bool bf_preempt); | ||
| 287 | extern void wlc_phy_machwcap_set(struct brcms_phy_pub *ppi, u32 machwcap); | ||
| 288 | |||
| 289 | extern void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end); | ||
| 290 | |||
| 291 | extern void wlc_phy_freqtrack_start(struct brcms_phy_pub *ppi); | ||
| 292 | extern void wlc_phy_freqtrack_end(struct brcms_phy_pub *ppi); | ||
| 293 | |||
| 294 | extern const u8 *wlc_phy_get_ofdm_rate_lookup(void); | ||
| 295 | |||
| 296 | extern s8 wlc_phy_get_tx_power_offset_by_mcs(struct brcms_phy_pub *ppi, | ||
| 297 | u8 mcs_offset); | ||
| 298 | extern s8 wlc_phy_get_tx_power_offset(struct brcms_phy_pub *ppi, u8 tbl_offset); | ||
| 299 | #endif /* _BRCM_PHY_HAL_H_ */ | 284 | #endif /* _BRCM_PHY_HAL_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h index 1dc767c31653..4960f7d26804 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h | |||
| @@ -910,113 +910,103 @@ struct lcnphy_radio_regs { | |||
| 910 | u8 do_init_g; | 910 | u8 do_init_g; |
| 911 | }; | 911 | }; |
| 912 | 912 | ||
| 913 | extern u16 read_phy_reg(struct brcms_phy *pi, u16 addr); | 913 | u16 read_phy_reg(struct brcms_phy *pi, u16 addr); |
| 914 | extern void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val); | 914 | void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val); |
| 915 | extern void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val); | 915 | void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val); |
| 916 | extern void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val); | 916 | void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val); |
| 917 | extern void mod_phy_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val); | 917 | void mod_phy_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val); |
| 918 | 918 | ||
| 919 | extern u16 read_radio_reg(struct brcms_phy *pi, u16 addr); | 919 | u16 read_radio_reg(struct brcms_phy *pi, u16 addr); |
| 920 | extern void or_radio_reg(struct brcms_phy *pi, u16 addr, u16 val); | 920 | void or_radio_reg(struct brcms_phy *pi, u16 addr, u16 val); |
| 921 | extern void and_radio_reg(struct brcms_phy *pi, u16 addr, u16 val); | 921 | void and_radio_reg(struct brcms_phy *pi, u16 addr, u16 val); |
| 922 | extern void mod_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask, | 922 | void mod_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val); |
| 923 | u16 val); | 923 | void xor_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask); |
| 924 | extern void xor_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask); | 924 | |
| 925 | 925 | void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val); | |
| 926 | extern void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val); | 926 | |
| 927 | 927 | void wlc_phyreg_enter(struct brcms_phy_pub *pih); | |
| 928 | extern void wlc_phyreg_enter(struct brcms_phy_pub *pih); | 928 | void wlc_phyreg_exit(struct brcms_phy_pub *pih); |
| 929 | extern void wlc_phyreg_exit(struct brcms_phy_pub *pih); | 929 | void wlc_radioreg_enter(struct brcms_phy_pub *pih); |
| 930 | extern void wlc_radioreg_enter(struct brcms_phy_pub *pih); | 930 | void wlc_radioreg_exit(struct brcms_phy_pub *pih); |
| 931 | extern void wlc_radioreg_exit(struct brcms_phy_pub *pih); | 931 | |
| 932 | 932 | void wlc_phy_read_table(struct brcms_phy *pi, | |
| 933 | extern void wlc_phy_read_table(struct brcms_phy *pi, | 933 | const struct phytbl_info *ptbl_info, |
| 934 | const struct phytbl_info *ptbl_info, | 934 | u16 tblAddr, u16 tblDataHi, u16 tblDatalo); |
| 935 | u16 tblAddr, u16 tblDataHi, | 935 | void wlc_phy_write_table(struct brcms_phy *pi, |
| 936 | u16 tblDatalo); | 936 | const struct phytbl_info *ptbl_info, |
| 937 | extern void wlc_phy_write_table(struct brcms_phy *pi, | 937 | u16 tblAddr, u16 tblDataHi, u16 tblDatalo); |
| 938 | const struct phytbl_info *ptbl_info, | 938 | void wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, uint tbl_offset, |
| 939 | u16 tblAddr, u16 tblDataHi, u16 tblDatalo); | 939 | u16 tblAddr, u16 tblDataHi, u16 tblDataLo); |
| 940 | extern void wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, | 940 | void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val); |
| 941 | uint tbl_offset, u16 tblAddr, u16 tblDataHi, | 941 | |
| 942 | u16 tblDataLo); | 942 | void write_phy_channel_reg(struct brcms_phy *pi, uint val); |
| 943 | extern void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val); | 943 | void wlc_phy_txpower_update_shm(struct brcms_phy *pi); |
| 944 | 944 | ||
| 945 | extern void write_phy_channel_reg(struct brcms_phy *pi, uint val); | 945 | u8 wlc_phy_nbits(s32 value); |
| 946 | extern void wlc_phy_txpower_update_shm(struct brcms_phy *pi); | 946 | void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_dB, u8 core); |
| 947 | 947 | ||
| 948 | extern u8 wlc_phy_nbits(s32 value); | 948 | uint wlc_phy_init_radio_regs_allbands(struct brcms_phy *pi, |
| 949 | extern void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_dB, u8 core); | 949 | struct radio_20xx_regs *radioregs); |
| 950 | 950 | uint wlc_phy_init_radio_regs(struct brcms_phy *pi, | |
| 951 | extern uint wlc_phy_init_radio_regs_allbands(struct brcms_phy *pi, | 951 | const struct radio_regs *radioregs, |
| 952 | struct radio_20xx_regs *radioregs); | 952 | u16 core_offset); |
| 953 | extern uint wlc_phy_init_radio_regs(struct brcms_phy *pi, | 953 | |
| 954 | const struct radio_regs *radioregs, | 954 | void wlc_phy_txpower_ipa_upd(struct brcms_phy *pi); |
| 955 | u16 core_offset); | 955 | |
| 956 | 956 | void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on); | |
| 957 | extern void wlc_phy_txpower_ipa_upd(struct brcms_phy *pi); | 957 | void wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real, s32 *eps_imag); |
| 958 | 958 | ||
| 959 | extern void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on); | 959 | void wlc_phy_cal_perical_mphase_reset(struct brcms_phy *pi); |
| 960 | extern void wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real, | 960 | void wlc_phy_cal_perical_mphase_restart(struct brcms_phy *pi); |
| 961 | s32 *eps_imag); | 961 | |
| 962 | 962 | bool wlc_phy_attach_nphy(struct brcms_phy *pi); | |
| 963 | extern void wlc_phy_cal_perical_mphase_reset(struct brcms_phy *pi); | 963 | bool wlc_phy_attach_lcnphy(struct brcms_phy *pi); |
| 964 | extern void wlc_phy_cal_perical_mphase_restart(struct brcms_phy *pi); | 964 | |
| 965 | 965 | void wlc_phy_detach_lcnphy(struct brcms_phy *pi); | |
| 966 | extern bool wlc_phy_attach_nphy(struct brcms_phy *pi); | 966 | |
| 967 | extern bool wlc_phy_attach_lcnphy(struct brcms_phy *pi); | 967 | void wlc_phy_init_nphy(struct brcms_phy *pi); |
| 968 | 968 | void wlc_phy_init_lcnphy(struct brcms_phy *pi); | |
| 969 | extern void wlc_phy_detach_lcnphy(struct brcms_phy *pi); | 969 | |
| 970 | 970 | void wlc_phy_cal_init_nphy(struct brcms_phy *pi); | |
| 971 | extern void wlc_phy_init_nphy(struct brcms_phy *pi); | 971 | void wlc_phy_cal_init_lcnphy(struct brcms_phy *pi); |
| 972 | extern void wlc_phy_init_lcnphy(struct brcms_phy *pi); | 972 | |
| 973 | 973 | void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, u16 chanspec); | |
| 974 | extern void wlc_phy_cal_init_nphy(struct brcms_phy *pi); | 974 | void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec); |
| 975 | extern void wlc_phy_cal_init_lcnphy(struct brcms_phy *pi); | 975 | void wlc_phy_chanspec_set_fixup_lcnphy(struct brcms_phy *pi, u16 chanspec); |
| 976 | 976 | int wlc_phy_channel2freq(uint channel); | |
| 977 | extern void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, | 977 | int wlc_phy_chanspec_freq2bandrange_lpssn(uint); |
| 978 | u16 chanspec); | 978 | int wlc_phy_chanspec_bandrange_get(struct brcms_phy *, u16 chanspec); |
| 979 | extern void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, | 979 | |
| 980 | u16 chanspec); | 980 | void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode); |
| 981 | extern void wlc_phy_chanspec_set_fixup_lcnphy(struct brcms_phy *pi, | 981 | s8 wlc_lcnphy_get_current_tx_pwr_idx(struct brcms_phy *pi); |
| 982 | u16 chanspec); | 982 | |
| 983 | extern int wlc_phy_channel2freq(uint channel); | 983 | void wlc_phy_txpower_recalc_target_nphy(struct brcms_phy *pi); |
| 984 | extern int wlc_phy_chanspec_freq2bandrange_lpssn(uint); | 984 | void wlc_lcnphy_txpower_recalc_target(struct brcms_phy *pi); |
| 985 | extern int wlc_phy_chanspec_bandrange_get(struct brcms_phy *, u16 chanspec); | 985 | void wlc_phy_txpower_recalc_target_lcnphy(struct brcms_phy *pi); |
| 986 | 986 | ||
| 987 | extern void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode); | 987 | void wlc_lcnphy_set_tx_pwr_by_index(struct brcms_phy *pi, int index); |
| 988 | extern s8 wlc_lcnphy_get_current_tx_pwr_idx(struct brcms_phy *pi); | 988 | void wlc_lcnphy_tx_pu(struct brcms_phy *pi, bool bEnable); |
| 989 | 989 | void wlc_lcnphy_stop_tx_tone(struct brcms_phy *pi); | |
| 990 | extern void wlc_phy_txpower_recalc_target_nphy(struct brcms_phy *pi); | 990 | void wlc_lcnphy_start_tx_tone(struct brcms_phy *pi, s32 f_kHz, u16 max_val, |
| 991 | extern void wlc_lcnphy_txpower_recalc_target(struct brcms_phy *pi); | 991 | bool iqcalmode); |
| 992 | extern void wlc_phy_txpower_recalc_target_lcnphy(struct brcms_phy *pi); | 992 | |
| 993 | 993 | void wlc_phy_txpower_sromlimit_get_nphy(struct brcms_phy *pi, uint chan, | |
| 994 | extern void wlc_lcnphy_set_tx_pwr_by_index(struct brcms_phy *pi, int index); | 994 | u8 *max_pwr, u8 rate_id); |
| 995 | extern void wlc_lcnphy_tx_pu(struct brcms_phy *pi, bool bEnable); | 995 | void wlc_phy_ofdm_to_mcs_powers_nphy(u8 *power, u8 rate_mcs_start, |
| 996 | extern void wlc_lcnphy_stop_tx_tone(struct brcms_phy *pi); | 996 | u8 rate_mcs_end, u8 rate_ofdm_start); |
| 997 | extern void wlc_lcnphy_start_tx_tone(struct brcms_phy *pi, s32 f_kHz, | 997 | void wlc_phy_mcs_to_ofdm_powers_nphy(u8 *power, u8 rate_ofdm_start, |
| 998 | u16 max_val, bool iqcalmode); | 998 | u8 rate_ofdm_end, u8 rate_mcs_start); |
| 999 | 999 | ||
| 1000 | extern void wlc_phy_txpower_sromlimit_get_nphy(struct brcms_phy *pi, uint chan, | 1000 | u16 wlc_lcnphy_tempsense(struct brcms_phy *pi, bool mode); |
| 1001 | u8 *max_pwr, u8 rate_id); | 1001 | s16 wlc_lcnphy_tempsense_new(struct brcms_phy *pi, bool mode); |
| 1002 | extern void wlc_phy_ofdm_to_mcs_powers_nphy(u8 *power, u8 rate_mcs_start, | 1002 | s8 wlc_lcnphy_tempsense_degree(struct brcms_phy *pi, bool mode); |
| 1003 | u8 rate_mcs_end, | 1003 | s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode); |
| 1004 | u8 rate_ofdm_start); | 1004 | void wlc_phy_carrier_suppress_lcnphy(struct brcms_phy *pi); |
| 1005 | extern void wlc_phy_mcs_to_ofdm_powers_nphy(u8 *power, | 1005 | void wlc_lcnphy_crsuprs(struct brcms_phy *pi, int channel); |
| 1006 | u8 rate_ofdm_start, | 1006 | void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode); |
| 1007 | u8 rate_ofdm_end, | 1007 | void wlc_2064_vco_cal(struct brcms_phy *pi); |
| 1008 | u8 rate_mcs_start); | 1008 | |
| 1009 | 1009 | void wlc_phy_txpower_recalc_target(struct brcms_phy *pi); | |
| 1010 | extern u16 wlc_lcnphy_tempsense(struct brcms_phy *pi, bool mode); | ||
| 1011 | extern s16 wlc_lcnphy_tempsense_new(struct brcms_phy *pi, bool mode); | ||
| 1012 | extern s8 wlc_lcnphy_tempsense_degree(struct brcms_phy *pi, bool mode); | ||
| 1013 | extern s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode); | ||
| 1014 | extern void wlc_phy_carrier_suppress_lcnphy(struct brcms_phy *pi); | ||
| 1015 | extern void wlc_lcnphy_crsuprs(struct brcms_phy *pi, int channel); | ||
| 1016 | extern void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode); | ||
| 1017 | extern void wlc_2064_vco_cal(struct brcms_phy *pi); | ||
| 1018 | |||
| 1019 | extern void wlc_phy_txpower_recalc_target(struct brcms_phy *pi); | ||
| 1020 | 1010 | ||
| 1021 | #define LCNPHY_TBL_ID_PAPDCOMPDELTATBL 0x18 | 1011 | #define LCNPHY_TBL_ID_PAPDCOMPDELTATBL 0x18 |
| 1022 | #define LCNPHY_TX_POWER_TABLE_SIZE 128 | 1012 | #define LCNPHY_TX_POWER_TABLE_SIZE 128 |
| @@ -1030,26 +1020,24 @@ extern void wlc_phy_txpower_recalc_target(struct brcms_phy *pi); | |||
| 1030 | 1020 | ||
| 1031 | #define LCNPHY_TX_PWR_CTRL_TEMPBASED 0xE001 | 1021 | #define LCNPHY_TX_PWR_CTRL_TEMPBASED 0xE001 |
| 1032 | 1022 | ||
| 1033 | extern void wlc_lcnphy_write_table(struct brcms_phy *pi, | 1023 | void wlc_lcnphy_write_table(struct brcms_phy *pi, |
| 1034 | const struct phytbl_info *pti); | 1024 | const struct phytbl_info *pti); |
| 1035 | extern void wlc_lcnphy_read_table(struct brcms_phy *pi, | 1025 | void wlc_lcnphy_read_table(struct brcms_phy *pi, struct phytbl_info *pti); |
| 1036 | struct phytbl_info *pti); | 1026 | void wlc_lcnphy_set_tx_iqcc(struct brcms_phy *pi, u16 a, u16 b); |
| 1037 | extern void wlc_lcnphy_set_tx_iqcc(struct brcms_phy *pi, u16 a, u16 b); | 1027 | void wlc_lcnphy_set_tx_locc(struct brcms_phy *pi, u16 didq); |
| 1038 | extern void wlc_lcnphy_set_tx_locc(struct brcms_phy *pi, u16 didq); | 1028 | void wlc_lcnphy_get_tx_iqcc(struct brcms_phy *pi, u16 *a, u16 *b); |
| 1039 | extern void wlc_lcnphy_get_tx_iqcc(struct brcms_phy *pi, u16 *a, u16 *b); | 1029 | u16 wlc_lcnphy_get_tx_locc(struct brcms_phy *pi); |
| 1040 | extern u16 wlc_lcnphy_get_tx_locc(struct brcms_phy *pi); | 1030 | void wlc_lcnphy_get_radio_loft(struct brcms_phy *pi, u8 *ei0, u8 *eq0, u8 *fi0, |
| 1041 | extern void wlc_lcnphy_get_radio_loft(struct brcms_phy *pi, u8 *ei0, | 1031 | u8 *fq0); |
| 1042 | u8 *eq0, u8 *fi0, u8 *fq0); | 1032 | void wlc_lcnphy_calib_modes(struct brcms_phy *pi, uint mode); |
| 1043 | extern void wlc_lcnphy_calib_modes(struct brcms_phy *pi, uint mode); | 1033 | void wlc_lcnphy_deaf_mode(struct brcms_phy *pi, bool mode); |
| 1044 | extern void wlc_lcnphy_deaf_mode(struct brcms_phy *pi, bool mode); | 1034 | bool wlc_phy_tpc_isenabled_lcnphy(struct brcms_phy *pi); |
| 1045 | extern bool wlc_phy_tpc_isenabled_lcnphy(struct brcms_phy *pi); | 1035 | void wlc_lcnphy_tx_pwr_update_npt(struct brcms_phy *pi); |
| 1046 | extern void wlc_lcnphy_tx_pwr_update_npt(struct brcms_phy *pi); | 1036 | s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1); |
| 1047 | extern s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1); | 1037 | void wlc_lcnphy_get_tssi(struct brcms_phy *pi, s8 *ofdm_pwr, s8 *cck_pwr); |
| 1048 | extern void wlc_lcnphy_get_tssi(struct brcms_phy *pi, s8 *ofdm_pwr, | 1038 | void wlc_lcnphy_tx_power_adjustment(struct brcms_phy_pub *ppi); |
| 1049 | s8 *cck_pwr); | 1039 | |
| 1050 | extern void wlc_lcnphy_tx_power_adjustment(struct brcms_phy_pub *ppi); | 1040 | s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index); |
| 1051 | |||
| 1052 | extern s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index); | ||
| 1053 | 1041 | ||
| 1054 | #define NPHY_MAX_HPVGA1_INDEX 10 | 1042 | #define NPHY_MAX_HPVGA1_INDEX 10 |
| 1055 | #define NPHY_DEF_HPVGA1_INDEXLIMIT 7 | 1043 | #define NPHY_DEF_HPVGA1_INDEXLIMIT 7 |
| @@ -1060,9 +1048,8 @@ struct phy_iq_est { | |||
| 1060 | u32 q_pwr; | 1048 | u32 q_pwr; |
| 1061 | }; | 1049 | }; |
| 1062 | 1050 | ||
| 1063 | extern void wlc_phy_stay_in_carriersearch_nphy(struct brcms_phy *pi, | 1051 | void wlc_phy_stay_in_carriersearch_nphy(struct brcms_phy *pi, bool enable); |
| 1064 | bool enable); | 1052 | void wlc_nphy_deaf_mode(struct brcms_phy *pi, bool mode); |
| 1065 | extern void wlc_nphy_deaf_mode(struct brcms_phy *pi, bool mode); | ||
| 1066 | 1053 | ||
| 1067 | #define wlc_phy_write_table_nphy(pi, pti) \ | 1054 | #define wlc_phy_write_table_nphy(pi, pti) \ |
| 1068 | wlc_phy_write_table(pi, pti, 0x72, 0x74, 0x73) | 1055 | wlc_phy_write_table(pi, pti, 0x72, 0x74, 0x73) |
| @@ -1076,10 +1063,10 @@ extern void wlc_nphy_deaf_mode(struct brcms_phy *pi, bool mode); | |||
| 1076 | #define wlc_nphy_table_data_write(pi, w, v) \ | 1063 | #define wlc_nphy_table_data_write(pi, w, v) \ |
| 1077 | wlc_phy_table_data_write((pi), (w), (v)) | 1064 | wlc_phy_table_data_write((pi), (w), (v)) |
| 1078 | 1065 | ||
| 1079 | extern void wlc_phy_table_read_nphy(struct brcms_phy *pi, u32, u32 l, u32 o, | 1066 | void wlc_phy_table_read_nphy(struct brcms_phy *pi, u32, u32 l, u32 o, u32 w, |
| 1080 | u32 w, void *d); | 1067 | void *d); |
| 1081 | extern void wlc_phy_table_write_nphy(struct brcms_phy *pi, u32, u32, u32, | 1068 | void wlc_phy_table_write_nphy(struct brcms_phy *pi, u32, u32, u32, u32, |
| 1082 | u32, const void *); | 1069 | const void *); |
| 1083 | 1070 | ||
| 1084 | #define PHY_IPA(pi) \ | 1071 | #define PHY_IPA(pi) \ |
| 1085 | ((pi->ipa2g_on && CHSPEC_IS2G(pi->radio_chanspec)) || \ | 1072 | ((pi->ipa2g_on && CHSPEC_IS2G(pi->radio_chanspec)) || \ |
| @@ -1089,73 +1076,67 @@ extern void wlc_phy_table_write_nphy(struct brcms_phy *pi, u32, u32, u32, | |||
| 1089 | if (NREV_LT((pi)->pubpi.phy_rev, 3)) \ | 1076 | if (NREV_LT((pi)->pubpi.phy_rev, 3)) \ |
| 1090 | (void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) | 1077 | (void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) |
| 1091 | 1078 | ||
| 1092 | extern void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype); | 1079 | void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype); |
| 1093 | extern void wlc_phy_aci_reset_nphy(struct brcms_phy *pi); | 1080 | void wlc_phy_aci_reset_nphy(struct brcms_phy *pi); |
| 1094 | extern void wlc_phy_pa_override_nphy(struct brcms_phy *pi, bool en); | 1081 | void wlc_phy_pa_override_nphy(struct brcms_phy *pi, bool en); |
| 1095 | 1082 | ||
| 1096 | extern u8 wlc_phy_get_chan_freq_range_nphy(struct brcms_phy *pi, uint chan); | 1083 | u8 wlc_phy_get_chan_freq_range_nphy(struct brcms_phy *pi, uint chan); |
| 1097 | extern void wlc_phy_switch_radio_nphy(struct brcms_phy *pi, bool on); | 1084 | void wlc_phy_switch_radio_nphy(struct brcms_phy *pi, bool on); |
| 1098 | 1085 | ||
| 1099 | extern void wlc_phy_stf_chain_upd_nphy(struct brcms_phy *pi); | 1086 | void wlc_phy_stf_chain_upd_nphy(struct brcms_phy *pi); |
| 1100 | 1087 | ||
| 1101 | extern void wlc_phy_force_rfseq_nphy(struct brcms_phy *pi, u8 cmd); | 1088 | void wlc_phy_force_rfseq_nphy(struct brcms_phy *pi, u8 cmd); |
| 1102 | extern s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi); | 1089 | s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi); |
| 1103 | 1090 | ||
| 1104 | extern u16 wlc_phy_classifier_nphy(struct brcms_phy *pi, u16 mask, u16 val); | 1091 | u16 wlc_phy_classifier_nphy(struct brcms_phy *pi, u16 mask, u16 val); |
| 1105 | 1092 | ||
| 1106 | extern void wlc_phy_rx_iq_est_nphy(struct brcms_phy *pi, struct phy_iq_est *est, | 1093 | void wlc_phy_rx_iq_est_nphy(struct brcms_phy *pi, struct phy_iq_est *est, |
| 1107 | u16 num_samps, u8 wait_time, | 1094 | u16 num_samps, u8 wait_time, u8 wait_for_crs); |
| 1108 | u8 wait_for_crs); | 1095 | |
| 1109 | 1096 | void wlc_phy_rx_iq_coeffs_nphy(struct brcms_phy *pi, u8 write, | |
| 1110 | extern void wlc_phy_rx_iq_coeffs_nphy(struct brcms_phy *pi, u8 write, | 1097 | struct nphy_iq_comp *comp); |
| 1111 | struct nphy_iq_comp *comp); | 1098 | void wlc_phy_aci_and_noise_reduction_nphy(struct brcms_phy *pi); |
| 1112 | extern void wlc_phy_aci_and_noise_reduction_nphy(struct brcms_phy *pi); | 1099 | |
| 1113 | 1100 | void wlc_phy_rxcore_setstate_nphy(struct brcms_phy_pub *pih, u8 rxcore_bitmask); | |
| 1114 | extern void wlc_phy_rxcore_setstate_nphy(struct brcms_phy_pub *pih, | 1101 | u8 wlc_phy_rxcore_getstate_nphy(struct brcms_phy_pub *pih); |
| 1115 | u8 rxcore_bitmask); | 1102 | |
| 1116 | extern u8 wlc_phy_rxcore_getstate_nphy(struct brcms_phy_pub *pih); | 1103 | void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type); |
| 1117 | 1104 | void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi); | |
| 1118 | extern void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type); | 1105 | void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi); |
| 1119 | extern void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi); | 1106 | void wlc_phy_txpwr_papd_cal_nphy(struct brcms_phy *pi); |
| 1120 | extern void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi); | 1107 | u16 wlc_phy_txpwr_idx_get_nphy(struct brcms_phy *pi); |
| 1121 | extern void wlc_phy_txpwr_papd_cal_nphy(struct brcms_phy *pi); | 1108 | |
| 1122 | extern u16 wlc_phy_txpwr_idx_get_nphy(struct brcms_phy *pi); | 1109 | struct nphy_txgains wlc_phy_get_tx_gain_nphy(struct brcms_phy *pi); |
| 1123 | 1110 | int wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, | |
| 1124 | extern struct nphy_txgains wlc_phy_get_tx_gain_nphy(struct brcms_phy *pi); | 1111 | struct nphy_txgains target_gain, bool full, bool m); |
| 1125 | extern int wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, | 1112 | int wlc_phy_cal_rxiq_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, |
| 1126 | struct nphy_txgains target_gain, | 1113 | u8 type, bool d); |
| 1127 | bool full, bool m); | 1114 | void wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, |
| 1128 | extern int wlc_phy_cal_rxiq_nphy(struct brcms_phy *pi, | 1115 | s8 txpwrindex, bool res); |
| 1129 | struct nphy_txgains target_gain, | 1116 | void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core, u8 rssi_type); |
| 1130 | u8 type, bool d); | 1117 | int wlc_phy_poll_rssi_nphy(struct brcms_phy *pi, u8 rssi_type, |
| 1131 | extern void wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, | 1118 | s32 *rssi_buf, u8 nsamps); |
| 1132 | s8 txpwrindex, bool res); | 1119 | void wlc_phy_rssi_cal_nphy(struct brcms_phy *pi); |
| 1133 | extern void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core, u8 rssi_type); | 1120 | int wlc_phy_aci_scan_nphy(struct brcms_phy *pi); |
| 1134 | extern int wlc_phy_poll_rssi_nphy(struct brcms_phy *pi, u8 rssi_type, | 1121 | void wlc_phy_cal_txgainctrl_nphy(struct brcms_phy *pi, s32 dBm_targetpower, |
| 1135 | s32 *rssi_buf, u8 nsamps); | 1122 | bool debug); |
| 1136 | extern void wlc_phy_rssi_cal_nphy(struct brcms_phy *pi); | 1123 | int wlc_phy_tx_tone_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val, u8 mode, |
| 1137 | extern int wlc_phy_aci_scan_nphy(struct brcms_phy *pi); | 1124 | u8, bool); |
| 1138 | extern void wlc_phy_cal_txgainctrl_nphy(struct brcms_phy *pi, | 1125 | void wlc_phy_stopplayback_nphy(struct brcms_phy *pi); |
| 1139 | s32 dBm_targetpower, bool debug); | 1126 | void wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf, |
| 1140 | extern int wlc_phy_tx_tone_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val, | 1127 | u8 num_samps); |
| 1141 | u8 mode, u8, bool); | 1128 | void wlc_phy_radio205x_vcocal_nphy(struct brcms_phy *pi); |
| 1142 | extern void wlc_phy_stopplayback_nphy(struct brcms_phy *pi); | 1129 | |
| 1143 | extern void wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf, | 1130 | int wlc_phy_rssi_compute_nphy(struct brcms_phy *pi, struct d11rxhdr *rxh); |
| 1144 | u8 num_samps); | ||
| 1145 | extern void wlc_phy_radio205x_vcocal_nphy(struct brcms_phy *pi); | ||
| 1146 | |||
| 1147 | extern int wlc_phy_rssi_compute_nphy(struct brcms_phy *pi, | ||
| 1148 | struct d11rxhdr *rxh); | ||
| 1149 | 1131 | ||
| 1150 | #define NPHY_TESTPATTERN_BPHY_EVM 0 | 1132 | #define NPHY_TESTPATTERN_BPHY_EVM 0 |
| 1151 | #define NPHY_TESTPATTERN_BPHY_RFCS 1 | 1133 | #define NPHY_TESTPATTERN_BPHY_RFCS 1 |
| 1152 | 1134 | ||
| 1153 | extern void wlc_phy_nphy_tkip_rifs_war(struct brcms_phy *pi, u8 rifs); | 1135 | void wlc_phy_nphy_tkip_rifs_war(struct brcms_phy *pi, u8 rifs); |
| 1154 | 1136 | ||
| 1155 | void wlc_phy_get_pwrdet_offsets(struct brcms_phy *pi, s8 *cckoffset, | 1137 | void wlc_phy_get_pwrdet_offsets(struct brcms_phy *pi, s8 *cckoffset, |
| 1156 | s8 *ofdmoffset); | 1138 | s8 *ofdmoffset); |
| 1157 | extern s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi, | 1139 | s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi, u16 chanspec); |
| 1158 | u16 chanspec); | ||
| 1159 | 1140 | ||
| 1160 | extern bool wlc_phy_n_txpower_ipa_ison(struct brcms_phy *pih); | 1141 | bool wlc_phy_n_txpower_ipa_ison(struct brcms_phy *pih); |
| 1161 | #endif /* _BRCM_PHY_INT_H_ */ | 1142 | #endif /* _BRCM_PHY_INT_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h b/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h index 2c5b66b75970..dd8774717ade 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h | |||
| @@ -124,56 +124,49 @@ | |||
| 124 | 124 | ||
| 125 | struct brcms_phy; | 125 | struct brcms_phy; |
| 126 | 126 | ||
| 127 | extern struct phy_shim_info *wlc_phy_shim_attach(struct brcms_hardware *wlc_hw, | 127 | struct phy_shim_info *wlc_phy_shim_attach(struct brcms_hardware *wlc_hw, |
| 128 | struct brcms_info *wl, | 128 | struct brcms_info *wl, |
| 129 | struct brcms_c_info *wlc); | 129 | struct brcms_c_info *wlc); |
| 130 | extern void wlc_phy_shim_detach(struct phy_shim_info *physhim); | 130 | void wlc_phy_shim_detach(struct phy_shim_info *physhim); |
| 131 | 131 | ||
| 132 | /* PHY to WL utility functions */ | 132 | /* PHY to WL utility functions */ |
| 133 | extern struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim, | 133 | struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim, |
| 134 | void (*fn) (struct brcms_phy *pi), | 134 | void (*fn)(struct brcms_phy *pi), |
| 135 | void *arg, const char *name); | 135 | void *arg, const char *name); |
| 136 | extern void wlapi_free_timer(struct wlapi_timer *t); | 136 | void wlapi_free_timer(struct wlapi_timer *t); |
| 137 | extern void wlapi_add_timer(struct wlapi_timer *t, uint ms, int periodic); | 137 | void wlapi_add_timer(struct wlapi_timer *t, uint ms, int periodic); |
| 138 | extern bool wlapi_del_timer(struct wlapi_timer *t); | 138 | bool wlapi_del_timer(struct wlapi_timer *t); |
| 139 | extern void wlapi_intrson(struct phy_shim_info *physhim); | 139 | void wlapi_intrson(struct phy_shim_info *physhim); |
| 140 | extern u32 wlapi_intrsoff(struct phy_shim_info *physhim); | 140 | u32 wlapi_intrsoff(struct phy_shim_info *physhim); |
| 141 | extern void wlapi_intrsrestore(struct phy_shim_info *physhim, | 141 | void wlapi_intrsrestore(struct phy_shim_info *physhim, u32 macintmask); |
| 142 | u32 macintmask); | 142 | |
| 143 | 143 | void wlapi_bmac_write_shm(struct phy_shim_info *physhim, uint offset, u16 v); | |
| 144 | extern void wlapi_bmac_write_shm(struct phy_shim_info *physhim, uint offset, | 144 | u16 wlapi_bmac_read_shm(struct phy_shim_info *physhim, uint offset); |
| 145 | u16 v); | 145 | void wlapi_bmac_mhf(struct phy_shim_info *physhim, u8 idx, u16 mask, u16 val, |
| 146 | extern u16 wlapi_bmac_read_shm(struct phy_shim_info *physhim, uint offset); | 146 | int bands); |
| 147 | extern void wlapi_bmac_mhf(struct phy_shim_info *physhim, u8 idx, | 147 | void wlapi_bmac_corereset(struct phy_shim_info *physhim, u32 flags); |
| 148 | u16 mask, u16 val, int bands); | 148 | void wlapi_suspend_mac_and_wait(struct phy_shim_info *physhim); |
| 149 | extern void wlapi_bmac_corereset(struct phy_shim_info *physhim, u32 flags); | 149 | void wlapi_switch_macfreq(struct phy_shim_info *physhim, u8 spurmode); |
| 150 | extern void wlapi_suspend_mac_and_wait(struct phy_shim_info *physhim); | 150 | void wlapi_enable_mac(struct phy_shim_info *physhim); |
| 151 | extern void wlapi_switch_macfreq(struct phy_shim_info *physhim, u8 spurmode); | 151 | void wlapi_bmac_mctrl(struct phy_shim_info *physhim, u32 mask, u32 val); |
| 152 | extern void wlapi_enable_mac(struct phy_shim_info *physhim); | 152 | void wlapi_bmac_phy_reset(struct phy_shim_info *physhim); |
| 153 | extern void wlapi_bmac_mctrl(struct phy_shim_info *physhim, u32 mask, | 153 | void wlapi_bmac_bw_set(struct phy_shim_info *physhim, u16 bw); |
| 154 | u32 val); | 154 | void wlapi_bmac_phyclk_fgc(struct phy_shim_info *physhim, bool clk); |
| 155 | extern void wlapi_bmac_phy_reset(struct phy_shim_info *physhim); | 155 | void wlapi_bmac_macphyclk_set(struct phy_shim_info *physhim, bool clk); |
| 156 | extern void wlapi_bmac_bw_set(struct phy_shim_info *physhim, u16 bw); | 156 | void wlapi_bmac_core_phypll_ctl(struct phy_shim_info *physhim, bool on); |
| 157 | extern void wlapi_bmac_phyclk_fgc(struct phy_shim_info *physhim, bool clk); | 157 | void wlapi_bmac_core_phypll_reset(struct phy_shim_info *physhim); |
| 158 | extern void wlapi_bmac_macphyclk_set(struct phy_shim_info *physhim, bool clk); | 158 | void wlapi_bmac_ucode_wake_override_phyreg_set(struct phy_shim_info *physhim); |
| 159 | extern void wlapi_bmac_core_phypll_ctl(struct phy_shim_info *physhim, bool on); | 159 | void wlapi_bmac_ucode_wake_override_phyreg_clear(struct phy_shim_info *physhim); |
| 160 | extern void wlapi_bmac_core_phypll_reset(struct phy_shim_info *physhim); | 160 | void wlapi_bmac_write_template_ram(struct phy_shim_info *physhim, int o, |
| 161 | extern void wlapi_bmac_ucode_wake_override_phyreg_set(struct phy_shim_info * | 161 | int len, void *buf); |
| 162 | physhim); | 162 | u16 wlapi_bmac_rate_shm_offset(struct phy_shim_info *physhim, u8 rate); |
| 163 | extern void wlapi_bmac_ucode_wake_override_phyreg_clear(struct phy_shim_info * | 163 | void wlapi_ucode_sample_init(struct phy_shim_info *physhim); |
| 164 | physhim); | 164 | void wlapi_copyfrom_objmem(struct phy_shim_info *physhim, uint, void *buf, |
| 165 | extern void wlapi_bmac_write_template_ram(struct phy_shim_info *physhim, int o, | 165 | int, u32 sel); |
| 166 | int len, void *buf); | 166 | void wlapi_copyto_objmem(struct phy_shim_info *physhim, uint, const void *buf, |
| 167 | extern u16 wlapi_bmac_rate_shm_offset(struct phy_shim_info *physhim, | 167 | int, u32); |
| 168 | u8 rate); | 168 | |
| 169 | extern void wlapi_ucode_sample_init(struct phy_shim_info *physhim); | 169 | void wlapi_high_update_phy_mode(struct phy_shim_info *physhim, u32 phy_mode); |
| 170 | extern void wlapi_copyfrom_objmem(struct phy_shim_info *physhim, uint, | 170 | u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim); |
| 171 | void *buf, int, u32 sel); | ||
| 172 | extern void wlapi_copyto_objmem(struct phy_shim_info *physhim, uint, | ||
| 173 | const void *buf, int, u32); | ||
| 174 | |||
| 175 | extern void wlapi_high_update_phy_mode(struct phy_shim_info *physhim, | ||
| 176 | u32 phy_mode); | ||
| 177 | extern u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim); | ||
| 178 | 171 | ||
| 179 | #endif /* _BRCM_PHY_SHIM_H_ */ | 172 | #endif /* _BRCM_PHY_SHIM_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pmu.h b/drivers/net/wireless/brcm80211/brcmsmac/pmu.h index 20e2012d5a3a..a014bbc4f935 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/pmu.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/pmu.h | |||
| @@ -20,7 +20,7 @@ | |||
| 20 | 20 | ||
| 21 | #include "types.h" | 21 | #include "types.h" |
| 22 | 22 | ||
| 23 | extern u16 si_pmu_fast_pwrup_delay(struct si_pub *sih); | 23 | u16 si_pmu_fast_pwrup_delay(struct si_pub *sih); |
| 24 | extern u32 si_pmu_measure_alpclk(struct si_pub *sih); | 24 | u32 si_pmu_measure_alpclk(struct si_pub *sih); |
| 25 | 25 | ||
| 26 | #endif /* _BRCM_PMU_H_ */ | 26 | #endif /* _BRCM_PMU_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h index d36ea5e1cc49..4da38cb4f318 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h | |||
| @@ -266,83 +266,76 @@ struct brcms_antselcfg { | |||
| 266 | }; | 266 | }; |
| 267 | 267 | ||
| 268 | /* common functions for every port */ | 268 | /* common functions for every port */ |
| 269 | extern struct brcms_c_info * | 269 | struct brcms_c_info *brcms_c_attach(struct brcms_info *wl, |
| 270 | brcms_c_attach(struct brcms_info *wl, struct bcma_device *core, uint unit, | 270 | struct bcma_device *core, uint unit, |
| 271 | bool piomode, uint *perr); | 271 | bool piomode, uint *perr); |
| 272 | extern uint brcms_c_detach(struct brcms_c_info *wlc); | 272 | uint brcms_c_detach(struct brcms_c_info *wlc); |
| 273 | extern int brcms_c_up(struct brcms_c_info *wlc); | 273 | int brcms_c_up(struct brcms_c_info *wlc); |
| 274 | extern uint brcms_c_down(struct brcms_c_info *wlc); | 274 | uint brcms_c_down(struct brcms_c_info *wlc); |
| 275 | 275 | ||
| 276 | extern bool brcms_c_chipmatch(struct bcma_device *core); | 276 | bool brcms_c_chipmatch(struct bcma_device *core); |
| 277 | extern void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx); | 277 | void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx); |
| 278 | extern void brcms_c_reset(struct brcms_c_info *wlc); | 278 | void brcms_c_reset(struct brcms_c_info *wlc); |
| 279 | 279 | ||
| 280 | extern void brcms_c_intrson(struct brcms_c_info *wlc); | 280 | void brcms_c_intrson(struct brcms_c_info *wlc); |
| 281 | extern u32 brcms_c_intrsoff(struct brcms_c_info *wlc); | 281 | u32 brcms_c_intrsoff(struct brcms_c_info *wlc); |
| 282 | extern void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask); | 282 | void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask); |
| 283 | extern bool brcms_c_intrsupd(struct brcms_c_info *wlc); | 283 | bool brcms_c_intrsupd(struct brcms_c_info *wlc); |
| 284 | extern bool brcms_c_isr(struct brcms_c_info *wlc); | 284 | bool brcms_c_isr(struct brcms_c_info *wlc); |
| 285 | extern bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded); | 285 | bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded); |
| 286 | extern bool brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, | 286 | bool brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, struct sk_buff *sdu, |
| 287 | struct sk_buff *sdu, | 287 | struct ieee80211_hw *hw); |
| 288 | struct ieee80211_hw *hw); | 288 | bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid); |
| 289 | extern bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid); | 289 | void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx, int val); |
| 290 | extern void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx, | 290 | int brcms_c_get_header_len(void); |
| 291 | int val); | 291 | void brcms_c_set_addrmatch(struct brcms_c_info *wlc, int match_reg_offset, |
| 292 | extern int brcms_c_get_header_len(void); | 292 | const u8 *addr); |
| 293 | extern void brcms_c_set_addrmatch(struct brcms_c_info *wlc, | 293 | void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci, |
| 294 | int match_reg_offset, | 294 | const struct ieee80211_tx_queue_params *arg, |
| 295 | const u8 *addr); | 295 | bool suspend); |
| 296 | extern void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci, | 296 | struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc); |
| 297 | const struct ieee80211_tx_queue_params *arg, | 297 | void brcms_c_ampdu_flush(struct brcms_c_info *wlc, struct ieee80211_sta *sta, |
| 298 | bool suspend); | 298 | u16 tid); |
| 299 | extern struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc); | 299 | void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid, |
| 300 | extern void brcms_c_ampdu_flush(struct brcms_c_info *wlc, | 300 | u8 ba_wsize, uint max_rx_ampdu_bytes); |
| 301 | struct ieee80211_sta *sta, u16 tid); | 301 | int brcms_c_module_register(struct brcms_pub *pub, const char *name, |
| 302 | extern void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid, | 302 | struct brcms_info *hdl, |
| 303 | u8 ba_wsize, uint max_rx_ampdu_bytes); | 303 | int (*down_fn)(void *handle)); |
| 304 | extern int brcms_c_module_register(struct brcms_pub *pub, | 304 | int brcms_c_module_unregister(struct brcms_pub *pub, const char *name, |
| 305 | const char *name, struct brcms_info *hdl, | 305 | struct brcms_info *hdl); |
| 306 | int (*down_fn)(void *handle)); | 306 | void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc); |
| 307 | extern int brcms_c_module_unregister(struct brcms_pub *pub, const char *name, | 307 | void brcms_c_enable_mac(struct brcms_c_info *wlc); |
| 308 | struct brcms_info *hdl); | 308 | void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state); |
| 309 | extern void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc); | 309 | void brcms_c_scan_start(struct brcms_c_info *wlc); |
| 310 | extern void brcms_c_enable_mac(struct brcms_c_info *wlc); | 310 | void brcms_c_scan_stop(struct brcms_c_info *wlc); |
| 311 | extern void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state); | 311 | int brcms_c_get_curband(struct brcms_c_info *wlc); |
| 312 | extern void brcms_c_scan_start(struct brcms_c_info *wlc); | 312 | int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel); |
| 313 | extern void brcms_c_scan_stop(struct brcms_c_info *wlc); | 313 | int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl); |
| 314 | extern int brcms_c_get_curband(struct brcms_c_info *wlc); | 314 | void brcms_c_get_current_rateset(struct brcms_c_info *wlc, |
| 315 | extern int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel); | ||
| 316 | extern int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl); | ||
| 317 | extern void brcms_c_get_current_rateset(struct brcms_c_info *wlc, | ||
| 318 | struct brcm_rateset *currs); | 315 | struct brcm_rateset *currs); |
| 319 | extern int brcms_c_set_rateset(struct brcms_c_info *wlc, | 316 | int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs); |
| 320 | struct brcm_rateset *rs); | 317 | int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period); |
| 321 | extern int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period); | 318 | u16 brcms_c_get_phy_type(struct brcms_c_info *wlc, int phyidx); |
| 322 | extern u16 brcms_c_get_phy_type(struct brcms_c_info *wlc, int phyidx); | 319 | void brcms_c_set_shortslot_override(struct brcms_c_info *wlc, |
| 323 | extern void brcms_c_set_shortslot_override(struct brcms_c_info *wlc, | ||
| 324 | s8 sslot_override); | 320 | s8 sslot_override); |
| 325 | extern void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, | 321 | void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval); |
| 326 | u8 interval); | 322 | u64 brcms_c_tsf_get(struct brcms_c_info *wlc); |
| 327 | extern u64 brcms_c_tsf_get(struct brcms_c_info *wlc); | 323 | void brcms_c_tsf_set(struct brcms_c_info *wlc, u64 tsf); |
| 328 | extern void brcms_c_tsf_set(struct brcms_c_info *wlc, u64 tsf); | 324 | int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr); |
| 329 | extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr); | 325 | int brcms_c_get_tx_power(struct brcms_c_info *wlc); |
| 330 | extern int brcms_c_get_tx_power(struct brcms_c_info *wlc); | 326 | bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc); |
| 331 | extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc); | 327 | void brcms_c_mute(struct brcms_c_info *wlc, bool on); |
| 332 | extern void brcms_c_mute(struct brcms_c_info *wlc, bool on); | 328 | bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc); |
| 333 | extern bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc); | 329 | void brcms_c_start_station(struct brcms_c_info *wlc, u8 *addr); |
| 334 | extern void brcms_c_start_station(struct brcms_c_info *wlc, u8 *addr); | 330 | void brcms_c_start_ap(struct brcms_c_info *wlc, u8 *addr, const u8 *bssid, |
| 335 | extern void brcms_c_start_ap(struct brcms_c_info *wlc, u8 *addr, | 331 | u8 *ssid, size_t ssid_len); |
| 336 | const u8 *bssid, u8 *ssid, size_t ssid_len); | 332 | void brcms_c_start_adhoc(struct brcms_c_info *wlc, u8 *addr); |
| 337 | extern void brcms_c_start_adhoc(struct brcms_c_info *wlc, u8 *addr); | 333 | void brcms_c_update_beacon(struct brcms_c_info *wlc); |
| 338 | extern void brcms_c_update_beacon(struct brcms_c_info *wlc); | 334 | void brcms_c_set_new_beacon(struct brcms_c_info *wlc, struct sk_buff *beacon, |
| 339 | extern void brcms_c_set_new_beacon(struct brcms_c_info *wlc, | 335 | u16 tim_offset, u16 dtim_period); |
| 340 | struct sk_buff *beacon, u16 tim_offset, | 336 | void brcms_c_set_new_probe_resp(struct brcms_c_info *wlc, |
| 341 | u16 dtim_period); | 337 | struct sk_buff *probe_resp); |
| 342 | extern void brcms_c_set_new_probe_resp(struct brcms_c_info *wlc, | 338 | void brcms_c_enable_probe_resp(struct brcms_c_info *wlc, bool enable); |
| 343 | struct sk_buff *probe_resp); | 339 | void brcms_c_set_ssid(struct brcms_c_info *wlc, u8 *ssid, size_t ssid_len); |
| 344 | extern void brcms_c_enable_probe_resp(struct brcms_c_info *wlc, bool enable); | ||
| 345 | extern void brcms_c_set_ssid(struct brcms_c_info *wlc, u8 *ssid, | ||
| 346 | size_t ssid_len); | ||
| 347 | 340 | ||
| 348 | #endif /* _BRCM_PUB_H_ */ | 341 | #endif /* _BRCM_PUB_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/rate.h b/drivers/net/wireless/brcm80211/brcmsmac/rate.h index 980d578825cc..5bb88b78ed64 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/rate.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/rate.h | |||
| @@ -216,34 +216,30 @@ static inline u8 cck_phy2mac_rate(u8 signal) | |||
| 216 | 216 | ||
| 217 | /* sanitize, and sort a rateset with the basic bit(s) preserved, validate | 217 | /* sanitize, and sort a rateset with the basic bit(s) preserved, validate |
| 218 | * rateset */ | 218 | * rateset */ |
| 219 | extern bool | 219 | bool brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs, |
| 220 | brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs, | 220 | const struct brcms_c_rateset *hw_rs, |
| 221 | const struct brcms_c_rateset *hw_rs, | 221 | bool check_brate, u8 txstreams); |
| 222 | bool check_brate, u8 txstreams); | ||
| 223 | /* copy rateset src to dst as-is (no masking or sorting) */ | 222 | /* copy rateset src to dst as-is (no masking or sorting) */ |
| 224 | extern void brcms_c_rateset_copy(const struct brcms_c_rateset *src, | 223 | void brcms_c_rateset_copy(const struct brcms_c_rateset *src, |
| 225 | struct brcms_c_rateset *dst); | 224 | struct brcms_c_rateset *dst); |
| 226 | 225 | ||
| 227 | /* would be nice to have these documented ... */ | 226 | /* would be nice to have these documented ... */ |
| 228 | extern u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp); | 227 | u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp); |
| 229 | 228 | ||
| 230 | extern void brcms_c_rateset_filter(struct brcms_c_rateset *src, | 229 | void brcms_c_rateset_filter(struct brcms_c_rateset *src, |
| 231 | struct brcms_c_rateset *dst, bool basic_only, u8 rates, uint xmask, | 230 | struct brcms_c_rateset *dst, bool basic_only, |
| 232 | bool mcsallow); | 231 | u8 rates, uint xmask, bool mcsallow); |
| 233 | 232 | ||
| 234 | extern void | 233 | void brcms_c_rateset_default(struct brcms_c_rateset *rs_tgt, |
| 235 | brcms_c_rateset_default(struct brcms_c_rateset *rs_tgt, | 234 | const struct brcms_c_rateset *rs_hw, uint phy_type, |
| 236 | const struct brcms_c_rateset *rs_hw, uint phy_type, | 235 | int bandtype, bool cck_only, uint rate_mask, |
| 237 | int bandtype, bool cck_only, uint rate_mask, | 236 | bool mcsallow, u8 bw, u8 txstreams); |
| 238 | bool mcsallow, u8 bw, u8 txstreams); | 237 | |
| 239 | 238 | s16 brcms_c_rate_legacy_phyctl(uint rate); | |
| 240 | extern s16 brcms_c_rate_legacy_phyctl(uint rate); | 239 | |
| 241 | 240 | void brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams); | |
| 242 | extern void brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams); | 241 | void brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset); |
| 243 | extern void brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset); | 242 | void brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset, u8 txstreams); |
| 244 | extern void brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset, | 243 | void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset, u8 bw); |
| 245 | u8 txstreams); | ||
| 246 | extern void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset, | ||
| 247 | u8 bw); | ||
| 248 | 244 | ||
| 249 | #endif /* _BRCM_RATE_H_ */ | 245 | #endif /* _BRCM_RATE_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/stf.h b/drivers/net/wireless/brcm80211/brcmsmac/stf.h index 19f6580f69be..ba9493009a33 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/stf.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/stf.h | |||
| @@ -19,24 +19,19 @@ | |||
| 19 | 19 | ||
| 20 | #include "types.h" | 20 | #include "types.h" |
| 21 | 21 | ||
| 22 | extern int brcms_c_stf_attach(struct brcms_c_info *wlc); | 22 | int brcms_c_stf_attach(struct brcms_c_info *wlc); |
| 23 | extern void brcms_c_stf_detach(struct brcms_c_info *wlc); | 23 | void brcms_c_stf_detach(struct brcms_c_info *wlc); |
| 24 | 24 | ||
| 25 | extern void brcms_c_tempsense_upd(struct brcms_c_info *wlc); | 25 | void brcms_c_tempsense_upd(struct brcms_c_info *wlc); |
| 26 | extern void brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, | 26 | void brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, |
| 27 | u16 *ss_algo_channel, | 27 | u16 *ss_algo_channel, u16 chanspec); |
| 28 | u16 chanspec); | 28 | int brcms_c_stf_ss_update(struct brcms_c_info *wlc, struct brcms_band *band); |
| 29 | extern int brcms_c_stf_ss_update(struct brcms_c_info *wlc, | 29 | void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc); |
| 30 | struct brcms_band *band); | 30 | int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val, bool force); |
| 31 | extern void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc); | 31 | bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val); |
| 32 | extern int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val, | 32 | void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc); |
| 33 | bool force); | 33 | void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc); |
| 34 | extern bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val); | 34 | u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, u32 rspec); |
| 35 | extern void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc); | 35 | u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc, u32 rspec); |
| 36 | extern void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc); | ||
| 37 | extern u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, | ||
| 38 | u32 rspec); | ||
| 39 | extern u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc, | ||
| 40 | u32 rspec); | ||
| 41 | 36 | ||
| 42 | #endif /* _BRCM_STF_H_ */ | 37 | #endif /* _BRCM_STF_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.h b/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.h index 18750a814b4f..c87dd89bcb78 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.h | |||
| @@ -43,16 +43,14 @@ struct brcms_ucode { | |||
| 43 | u32 *bcm43xx_bomminor; | 43 | u32 *bcm43xx_bomminor; |
| 44 | }; | 44 | }; |
| 45 | 45 | ||
| 46 | extern int | 46 | int brcms_ucode_data_init(struct brcms_info *wl, struct brcms_ucode *ucode); |
| 47 | brcms_ucode_data_init(struct brcms_info *wl, struct brcms_ucode *ucode); | ||
| 48 | 47 | ||
| 49 | extern void brcms_ucode_data_free(struct brcms_ucode *ucode); | 48 | void brcms_ucode_data_free(struct brcms_ucode *ucode); |
| 50 | 49 | ||
| 51 | extern int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, | 50 | int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, unsigned int idx); |
| 52 | unsigned int idx); | 51 | int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes, |
| 53 | extern int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes, | 52 | unsigned int idx); |
| 54 | unsigned int idx); | 53 | void brcms_ucode_free_buf(void *); |
| 55 | extern void brcms_ucode_free_buf(void *); | 54 | int brcms_check_firmwares(struct brcms_info *wl); |
| 56 | extern int brcms_check_firmwares(struct brcms_info *wl); | ||
| 57 | 55 | ||
| 58 | #endif /* _BRCM_UCODE_H_ */ | 56 | #endif /* _BRCM_UCODE_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h index c1fe245bb07e..84113ea16f84 100644 --- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h | |||
| @@ -41,5 +41,6 @@ | |||
| 41 | #define BCM4331_CHIP_ID 0x4331 | 41 | #define BCM4331_CHIP_ID 0x4331 |
| 42 | #define BCM4334_CHIP_ID 0x4334 | 42 | #define BCM4334_CHIP_ID 0x4334 |
| 43 | #define BCM4335_CHIP_ID 0x4335 | 43 | #define BCM4335_CHIP_ID 0x4335 |
| 44 | #define BCM4339_CHIP_ID 0x4339 | ||
| 44 | 45 | ||
| 45 | #endif /* _BRCM_HW_IDS_H_ */ | 46 | #endif /* _BRCM_HW_IDS_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_d11.h b/drivers/net/wireless/brcm80211/include/brcmu_d11.h index 92623f02b1c0..8660a2cba098 100644 --- a/drivers/net/wireless/brcm80211/include/brcmu_d11.h +++ b/drivers/net/wireless/brcm80211/include/brcmu_d11.h | |||
| @@ -140,6 +140,6 @@ struct brcmu_d11inf { | |||
| 140 | void (*decchspec)(struct brcmu_chan *ch); | 140 | void (*decchspec)(struct brcmu_chan *ch); |
| 141 | }; | 141 | }; |
| 142 | 142 | ||
| 143 | extern void brcmu_d11_attach(struct brcmu_d11inf *d11inf); | 143 | void brcmu_d11_attach(struct brcmu_d11inf *d11inf); |
| 144 | 144 | ||
| 145 | #endif /* _BRCMU_CHANNELS_H_ */ | 145 | #endif /* _BRCMU_CHANNELS_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_utils.h b/drivers/net/wireless/brcm80211/include/brcmu_utils.h index 898cacb8d01d..8ba445b3fd72 100644 --- a/drivers/net/wireless/brcm80211/include/brcmu_utils.h +++ b/drivers/net/wireless/brcm80211/include/brcmu_utils.h | |||
| @@ -114,31 +114,29 @@ static inline struct sk_buff *pktq_ppeek_tail(struct pktq *pq, int prec) | |||
| 114 | return skb_peek_tail(&pq->q[prec].skblist); | 114 | return skb_peek_tail(&pq->q[prec].skblist); |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | extern struct sk_buff *brcmu_pktq_penq(struct pktq *pq, int prec, | 117 | struct sk_buff *brcmu_pktq_penq(struct pktq *pq, int prec, struct sk_buff *p); |
| 118 | struct sk_buff *p); | 118 | struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec, |
| 119 | extern struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec, | 119 | struct sk_buff *p); |
| 120 | struct sk_buff *p); | 120 | struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec); |
| 121 | extern struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec); | 121 | struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec); |
| 122 | extern struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec); | 122 | struct sk_buff *brcmu_pktq_pdeq_match(struct pktq *pq, int prec, |
| 123 | extern struct sk_buff *brcmu_pktq_pdeq_match(struct pktq *pq, int prec, | 123 | bool (*match_fn)(struct sk_buff *p, |
| 124 | bool (*match_fn)(struct sk_buff *p, | 124 | void *arg), |
| 125 | void *arg), | 125 | void *arg); |
| 126 | void *arg); | ||
| 127 | 126 | ||
| 128 | /* packet primitives */ | 127 | /* packet primitives */ |
| 129 | extern struct sk_buff *brcmu_pkt_buf_get_skb(uint len); | 128 | struct sk_buff *brcmu_pkt_buf_get_skb(uint len); |
| 130 | extern void brcmu_pkt_buf_free_skb(struct sk_buff *skb); | 129 | void brcmu_pkt_buf_free_skb(struct sk_buff *skb); |
| 131 | 130 | ||
| 132 | /* Empty the queue at particular precedence level */ | 131 | /* Empty the queue at particular precedence level */ |
| 133 | /* callback function fn(pkt, arg) returns true if pkt belongs to if */ | 132 | /* callback function fn(pkt, arg) returns true if pkt belongs to if */ |
| 134 | extern void brcmu_pktq_pflush(struct pktq *pq, int prec, | 133 | void brcmu_pktq_pflush(struct pktq *pq, int prec, bool dir, |
| 135 | bool dir, bool (*fn)(struct sk_buff *, void *), void *arg); | 134 | bool (*fn)(struct sk_buff *, void *), void *arg); |
| 136 | 135 | ||
| 137 | /* operations on a set of precedences in packet queue */ | 136 | /* operations on a set of precedences in packet queue */ |
| 138 | 137 | ||
| 139 | extern int brcmu_pktq_mlen(struct pktq *pq, uint prec_bmp); | 138 | int brcmu_pktq_mlen(struct pktq *pq, uint prec_bmp); |
| 140 | extern struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp, | 139 | struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out); |
| 141 | int *prec_out); | ||
| 142 | 140 | ||
| 143 | /* operations on packet queue as a whole */ | 141 | /* operations on packet queue as a whole */ |
| 144 | 142 | ||
| @@ -167,11 +165,11 @@ static inline bool pktq_empty(struct pktq *pq) | |||
| 167 | return pq->len == 0; | 165 | return pq->len == 0; |
| 168 | } | 166 | } |
| 169 | 167 | ||
| 170 | extern void brcmu_pktq_init(struct pktq *pq, int num_prec, int max_len); | 168 | void brcmu_pktq_init(struct pktq *pq, int num_prec, int max_len); |
| 171 | /* prec_out may be NULL if caller is not interested in return value */ | 169 | /* prec_out may be NULL if caller is not interested in return value */ |
| 172 | extern struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out); | 170 | struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out); |
| 173 | extern void brcmu_pktq_flush(struct pktq *pq, bool dir, | 171 | void brcmu_pktq_flush(struct pktq *pq, bool dir, |
| 174 | bool (*fn)(struct sk_buff *, void *), void *arg); | 172 | bool (*fn)(struct sk_buff *, void *), void *arg); |
| 175 | 173 | ||
| 176 | /* externs */ | 174 | /* externs */ |
| 177 | /* ip address */ | 175 | /* ip address */ |
| @@ -204,13 +202,13 @@ static inline u16 brcmu_maskget16(u16 var, u16 mask, u8 shift) | |||
| 204 | /* externs */ | 202 | /* externs */ |
| 205 | /* format/print */ | 203 | /* format/print */ |
| 206 | #ifdef DEBUG | 204 | #ifdef DEBUG |
| 207 | extern void brcmu_prpkt(const char *msg, struct sk_buff *p0); | 205 | void brcmu_prpkt(const char *msg, struct sk_buff *p0); |
| 208 | #else | 206 | #else |
| 209 | #define brcmu_prpkt(a, b) | 207 | #define brcmu_prpkt(a, b) |
| 210 | #endif /* DEBUG */ | 208 | #endif /* DEBUG */ |
| 211 | 209 | ||
| 212 | #ifdef DEBUG | 210 | #ifdef DEBUG |
| 213 | extern __printf(3, 4) | 211 | __printf(3, 4) |
| 214 | void brcmu_dbg_hex_dump(const void *data, size_t size, const char *fmt, ...); | 212 | void brcmu_dbg_hex_dump(const void *data, size_t size, const char *fmt, ...); |
| 215 | #else | 213 | #else |
| 216 | __printf(3, 4) | 214 | __printf(3, 4) |
diff --git a/drivers/net/wireless/cw1200/cw1200_spi.c b/drivers/net/wireless/cw1200/cw1200_spi.c index 755a0c8edfe1..40078f5f932e 100644 --- a/drivers/net/wireless/cw1200/cw1200_spi.c +++ b/drivers/net/wireless/cw1200/cw1200_spi.c | |||
| @@ -365,7 +365,7 @@ static struct hwbus_ops cw1200_spi_hwbus_ops = { | |||
| 365 | static int cw1200_spi_probe(struct spi_device *func) | 365 | static int cw1200_spi_probe(struct spi_device *func) |
| 366 | { | 366 | { |
| 367 | const struct cw1200_platform_data_spi *plat_data = | 367 | const struct cw1200_platform_data_spi *plat_data = |
| 368 | func->dev.platform_data; | 368 | dev_get_platdata(&func->dev); |
| 369 | struct hwbus_priv *self; | 369 | struct hwbus_priv *self; |
| 370 | int status; | 370 | int status; |
| 371 | 371 | ||
| @@ -443,7 +443,7 @@ static int cw1200_spi_disconnect(struct spi_device *func) | |||
| 443 | } | 443 | } |
| 444 | kfree(self); | 444 | kfree(self); |
| 445 | } | 445 | } |
| 446 | cw1200_spi_off(func->dev.platform_data); | 446 | cw1200_spi_off(dev_get_platdata(&func->dev)); |
| 447 | 447 | ||
| 448 | return 0; | 448 | return 0; |
| 449 | } | 449 | } |
diff --git a/drivers/net/wireless/hostap/hostap_info.c b/drivers/net/wireless/hostap/hostap_info.c index 970a48baaf80..de7c4ffec309 100644 --- a/drivers/net/wireless/hostap/hostap_info.c +++ b/drivers/net/wireless/hostap/hostap_info.c | |||
| @@ -217,7 +217,7 @@ static void prism2_host_roaming(local_info_t *local) | |||
| 217 | } | 217 | } |
| 218 | } | 218 | } |
| 219 | 219 | ||
| 220 | memcpy(req.bssid, selected->bssid, 6); | 220 | memcpy(req.bssid, selected->bssid, ETH_ALEN); |
| 221 | req.channel = selected->chid; | 221 | req.channel = selected->chid; |
| 222 | spin_unlock_irqrestore(&local->lock, flags); | 222 | spin_unlock_irqrestore(&local->lock, flags); |
| 223 | 223 | ||
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 6b823a1ab789..81903e33d5b1 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c | |||
| @@ -2698,7 +2698,7 @@ static u16 eeprom_read_u16(struct ipw_priv *priv, u8 addr) | |||
| 2698 | /* data's copy of the eeprom data */ | 2698 | /* data's copy of the eeprom data */ |
| 2699 | static void eeprom_parse_mac(struct ipw_priv *priv, u8 * mac) | 2699 | static void eeprom_parse_mac(struct ipw_priv *priv, u8 * mac) |
| 2700 | { | 2700 | { |
| 2701 | memcpy(mac, &priv->eeprom[EEPROM_MAC_ADDRESS], 6); | 2701 | memcpy(mac, &priv->eeprom[EEPROM_MAC_ADDRESS], ETH_ALEN); |
| 2702 | } | 2702 | } |
| 2703 | 2703 | ||
| 2704 | static void ipw_read_eeprom(struct ipw_priv *priv) | 2704 | static void ipw_read_eeprom(struct ipw_priv *priv) |
| @@ -11885,7 +11885,6 @@ static int ipw_pci_probe(struct pci_dev *pdev, | |||
| 11885 | pci_release_regions(pdev); | 11885 | pci_release_regions(pdev); |
| 11886 | out_pci_disable_device: | 11886 | out_pci_disable_device: |
| 11887 | pci_disable_device(pdev); | 11887 | pci_disable_device(pdev); |
| 11888 | pci_set_drvdata(pdev, NULL); | ||
| 11889 | out_free_libipw: | 11888 | out_free_libipw: |
| 11890 | free_libipw(priv->net_dev, 0); | 11889 | free_libipw(priv->net_dev, 0); |
| 11891 | out: | 11890 | out: |
| @@ -11966,7 +11965,6 @@ static void ipw_pci_remove(struct pci_dev *pdev) | |||
| 11966 | iounmap(priv->hw_base); | 11965 | iounmap(priv->hw_base); |
| 11967 | pci_release_regions(pdev); | 11966 | pci_release_regions(pdev); |
| 11968 | pci_disable_device(pdev); | 11967 | pci_disable_device(pdev); |
| 11969 | pci_set_drvdata(pdev, NULL); | ||
| 11970 | /* wiphy_unregister needs to be here, before free_libipw */ | 11968 | /* wiphy_unregister needs to be here, before free_libipw */ |
| 11971 | wiphy_unregister(priv->ieee->wdev.wiphy); | 11969 | wiphy_unregister(priv->ieee->wdev.wiphy); |
| 11972 | kfree(priv->ieee->a_band.channels); | 11970 | kfree(priv->ieee->a_band.channels); |
diff --git a/drivers/net/wireless/ipw2x00/libipw.h b/drivers/net/wireless/ipw2x00/libipw.h index 6eede52ad8c0..5ce2f59d3378 100644 --- a/drivers/net/wireless/ipw2x00/libipw.h +++ b/drivers/net/wireless/ipw2x00/libipw.h | |||
| @@ -950,66 +950,55 @@ static inline int libipw_is_cck_rate(u8 rate) | |||
| 950 | } | 950 | } |
| 951 | 951 | ||
| 952 | /* libipw.c */ | 952 | /* libipw.c */ |
| 953 | extern void free_libipw(struct net_device *dev, int monitor); | 953 | void free_libipw(struct net_device *dev, int monitor); |
| 954 | extern struct net_device *alloc_libipw(int sizeof_priv, int monitor); | 954 | struct net_device *alloc_libipw(int sizeof_priv, int monitor); |
| 955 | extern int libipw_change_mtu(struct net_device *dev, int new_mtu); | 955 | int libipw_change_mtu(struct net_device *dev, int new_mtu); |
| 956 | 956 | ||
| 957 | extern void libipw_networks_age(struct libipw_device *ieee, | 957 | void libipw_networks_age(struct libipw_device *ieee, unsigned long age_secs); |
| 958 | unsigned long age_secs); | ||
| 959 | 958 | ||
| 960 | extern int libipw_set_encryption(struct libipw_device *ieee); | 959 | int libipw_set_encryption(struct libipw_device *ieee); |
| 961 | 960 | ||
| 962 | /* libipw_tx.c */ | 961 | /* libipw_tx.c */ |
| 963 | extern netdev_tx_t libipw_xmit(struct sk_buff *skb, | 962 | netdev_tx_t libipw_xmit(struct sk_buff *skb, struct net_device *dev); |
| 964 | struct net_device *dev); | 963 | void libipw_txb_free(struct libipw_txb *); |
| 965 | extern void libipw_txb_free(struct libipw_txb *); | ||
| 966 | 964 | ||
| 967 | /* libipw_rx.c */ | 965 | /* libipw_rx.c */ |
| 968 | extern void libipw_rx_any(struct libipw_device *ieee, | 966 | void libipw_rx_any(struct libipw_device *ieee, struct sk_buff *skb, |
| 969 | struct sk_buff *skb, struct libipw_rx_stats *stats); | 967 | struct libipw_rx_stats *stats); |
| 970 | extern int libipw_rx(struct libipw_device *ieee, struct sk_buff *skb, | 968 | int libipw_rx(struct libipw_device *ieee, struct sk_buff *skb, |
| 971 | struct libipw_rx_stats *rx_stats); | 969 | struct libipw_rx_stats *rx_stats); |
| 972 | /* make sure to set stats->len */ | 970 | /* make sure to set stats->len */ |
| 973 | extern void libipw_rx_mgt(struct libipw_device *ieee, | 971 | void libipw_rx_mgt(struct libipw_device *ieee, struct libipw_hdr_4addr *header, |
| 974 | struct libipw_hdr_4addr *header, | 972 | struct libipw_rx_stats *stats); |
| 975 | struct libipw_rx_stats *stats); | 973 | void libipw_network_reset(struct libipw_network *network); |
| 976 | extern void libipw_network_reset(struct libipw_network *network); | ||
| 977 | 974 | ||
| 978 | /* libipw_geo.c */ | 975 | /* libipw_geo.c */ |
| 979 | extern const struct libipw_geo *libipw_get_geo(struct libipw_device | 976 | const struct libipw_geo *libipw_get_geo(struct libipw_device *ieee); |
| 980 | *ieee); | 977 | void libipw_set_geo(struct libipw_device *ieee, const struct libipw_geo *geo); |
| 981 | extern void libipw_set_geo(struct libipw_device *ieee, | 978 | |
| 982 | const struct libipw_geo *geo); | 979 | int libipw_is_valid_channel(struct libipw_device *ieee, u8 channel); |
| 983 | 980 | int libipw_channel_to_index(struct libipw_device *ieee, u8 channel); | |
| 984 | extern int libipw_is_valid_channel(struct libipw_device *ieee, | 981 | u8 libipw_freq_to_channel(struct libipw_device *ieee, u32 freq); |
| 985 | u8 channel); | 982 | u8 libipw_get_channel_flags(struct libipw_device *ieee, u8 channel); |
| 986 | extern int libipw_channel_to_index(struct libipw_device *ieee, | 983 | const struct libipw_channel *libipw_get_channel(struct libipw_device *ieee, |
| 987 | u8 channel); | 984 | u8 channel); |
| 988 | extern u8 libipw_freq_to_channel(struct libipw_device *ieee, u32 freq); | 985 | u32 libipw_channel_to_freq(struct libipw_device *ieee, u8 channel); |
| 989 | extern u8 libipw_get_channel_flags(struct libipw_device *ieee, | ||
| 990 | u8 channel); | ||
| 991 | extern const struct libipw_channel *libipw_get_channel(struct | ||
| 992 | libipw_device | ||
| 993 | *ieee, u8 channel); | ||
| 994 | extern u32 libipw_channel_to_freq(struct libipw_device * ieee, | ||
| 995 | u8 channel); | ||
| 996 | 986 | ||
| 997 | /* libipw_wx.c */ | 987 | /* libipw_wx.c */ |
| 998 | extern int libipw_wx_get_scan(struct libipw_device *ieee, | 988 | int libipw_wx_get_scan(struct libipw_device *ieee, struct iw_request_info *info, |
| 999 | struct iw_request_info *info, | 989 | union iwreq_data *wrqu, char *key); |
| 1000 | union iwreq_data *wrqu, char *key); | 990 | int libipw_wx_set_encode(struct libipw_device *ieee, |
| 1001 | extern int libipw_wx_set_encode(struct libipw_device *ieee, | 991 | struct iw_request_info *info, union iwreq_data *wrqu, |
| 1002 | struct iw_request_info *info, | 992 | char *key); |
| 1003 | union iwreq_data *wrqu, char *key); | 993 | int libipw_wx_get_encode(struct libipw_device *ieee, |
| 1004 | extern int libipw_wx_get_encode(struct libipw_device *ieee, | 994 | struct iw_request_info *info, union iwreq_data *wrqu, |
| 1005 | struct iw_request_info *info, | 995 | char *key); |
| 1006 | union iwreq_data *wrqu, char *key); | 996 | int libipw_wx_set_encodeext(struct libipw_device *ieee, |
| 1007 | extern int libipw_wx_set_encodeext(struct libipw_device *ieee, | 997 | struct iw_request_info *info, |
| 1008 | struct iw_request_info *info, | 998 | union iwreq_data *wrqu, char *extra); |
| 1009 | union iwreq_data *wrqu, char *extra); | 999 | int libipw_wx_get_encodeext(struct libipw_device *ieee, |
| 1010 | extern int libipw_wx_get_encodeext(struct libipw_device *ieee, | 1000 | struct iw_request_info *info, |
| 1011 | struct iw_request_info *info, | 1001 | union iwreq_data *wrqu, char *extra); |
| 1012 | union iwreq_data *wrqu, char *extra); | ||
| 1013 | 1002 | ||
| 1014 | static inline void libipw_increment_scans(struct libipw_device *ieee) | 1003 | static inline void libipw_increment_scans(struct libipw_device *ieee) |
| 1015 | { | 1004 | { |
diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index 9581d07a4242..dea3b50d68b9 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c | |||
| @@ -3811,7 +3811,6 @@ out_iounmap: | |||
| 3811 | out_pci_release_regions: | 3811 | out_pci_release_regions: |
| 3812 | pci_release_regions(pdev); | 3812 | pci_release_regions(pdev); |
| 3813 | out_pci_disable_device: | 3813 | out_pci_disable_device: |
| 3814 | pci_set_drvdata(pdev, NULL); | ||
| 3815 | pci_disable_device(pdev); | 3814 | pci_disable_device(pdev); |
| 3816 | out_ieee80211_free_hw: | 3815 | out_ieee80211_free_hw: |
| 3817 | ieee80211_free_hw(il->hw); | 3816 | ieee80211_free_hw(il->hw); |
| @@ -3888,7 +3887,6 @@ il3945_pci_remove(struct pci_dev *pdev) | |||
| 3888 | iounmap(il->hw_base); | 3887 | iounmap(il->hw_base); |
| 3889 | pci_release_regions(pdev); | 3888 | pci_release_regions(pdev); |
| 3890 | pci_disable_device(pdev); | 3889 | pci_disable_device(pdev); |
| 3891 | pci_set_drvdata(pdev, NULL); | ||
| 3892 | 3890 | ||
| 3893 | il_free_channel_map(il); | 3891 | il_free_channel_map(il); |
| 3894 | il_free_geos(il); | 3892 | il_free_geos(il); |
diff --git a/drivers/net/wireless/iwlegacy/3945.h b/drivers/net/wireless/iwlegacy/3945.h index 9a8703def0ba..00030d43a194 100644 --- a/drivers/net/wireless/iwlegacy/3945.h +++ b/drivers/net/wireless/iwlegacy/3945.h | |||
| @@ -189,15 +189,14 @@ struct il3945_ibss_seq { | |||
| 189 | * for use by iwl-*.c | 189 | * for use by iwl-*.c |
| 190 | * | 190 | * |
| 191 | *****************************************************************************/ | 191 | *****************************************************************************/ |
| 192 | extern int il3945_calc_db_from_ratio(int sig_ratio); | 192 | int il3945_calc_db_from_ratio(int sig_ratio); |
| 193 | extern void il3945_rx_replenish(void *data); | 193 | void il3945_rx_replenish(void *data); |
| 194 | extern void il3945_rx_queue_reset(struct il_priv *il, struct il_rx_queue *rxq); | 194 | void il3945_rx_queue_reset(struct il_priv *il, struct il_rx_queue *rxq); |
| 195 | extern unsigned int il3945_fill_beacon_frame(struct il_priv *il, | 195 | unsigned int il3945_fill_beacon_frame(struct il_priv *il, |
| 196 | struct ieee80211_hdr *hdr, | 196 | struct ieee80211_hdr *hdr, int left); |
| 197 | int left); | 197 | int il3945_dump_nic_event_log(struct il_priv *il, bool full_log, char **buf, |
| 198 | extern int il3945_dump_nic_event_log(struct il_priv *il, bool full_log, | 198 | bool display); |
| 199 | char **buf, bool display); | 199 | void il3945_dump_nic_error_log(struct il_priv *il); |
| 200 | extern void il3945_dump_nic_error_log(struct il_priv *il); | ||
| 201 | 200 | ||
| 202 | /****************************************************************************** | 201 | /****************************************************************************** |
| 203 | * | 202 | * |
| @@ -215,39 +214,36 @@ extern void il3945_dump_nic_error_log(struct il_priv *il); | |||
| 215 | * il3945_mac_ <-- mac80211 callback | 214 | * il3945_mac_ <-- mac80211 callback |
| 216 | * | 215 | * |
| 217 | ****************************************************************************/ | 216 | ****************************************************************************/ |
| 218 | extern void il3945_hw_handler_setup(struct il_priv *il); | 217 | void il3945_hw_handler_setup(struct il_priv *il); |
| 219 | extern void il3945_hw_setup_deferred_work(struct il_priv *il); | 218 | void il3945_hw_setup_deferred_work(struct il_priv *il); |
| 220 | extern void il3945_hw_cancel_deferred_work(struct il_priv *il); | 219 | void il3945_hw_cancel_deferred_work(struct il_priv *il); |
| 221 | extern int il3945_hw_rxq_stop(struct il_priv *il); | 220 | int il3945_hw_rxq_stop(struct il_priv *il); |
| 222 | extern int il3945_hw_set_hw_params(struct il_priv *il); | 221 | int il3945_hw_set_hw_params(struct il_priv *il); |
| 223 | extern int il3945_hw_nic_init(struct il_priv *il); | 222 | int il3945_hw_nic_init(struct il_priv *il); |
| 224 | extern int il3945_hw_nic_stop_master(struct il_priv *il); | 223 | int il3945_hw_nic_stop_master(struct il_priv *il); |
| 225 | extern void il3945_hw_txq_ctx_free(struct il_priv *il); | 224 | void il3945_hw_txq_ctx_free(struct il_priv *il); |
| 226 | extern void il3945_hw_txq_ctx_stop(struct il_priv *il); | 225 | void il3945_hw_txq_ctx_stop(struct il_priv *il); |
| 227 | extern int il3945_hw_nic_reset(struct il_priv *il); | 226 | int il3945_hw_nic_reset(struct il_priv *il); |
| 228 | extern int il3945_hw_txq_attach_buf_to_tfd(struct il_priv *il, | 227 | int il3945_hw_txq_attach_buf_to_tfd(struct il_priv *il, struct il_tx_queue *txq, |
| 229 | struct il_tx_queue *txq, | 228 | dma_addr_t addr, u16 len, u8 reset, u8 pad); |
| 230 | dma_addr_t addr, u16 len, u8 reset, | 229 | void il3945_hw_txq_free_tfd(struct il_priv *il, struct il_tx_queue *txq); |
| 231 | u8 pad); | 230 | int il3945_hw_get_temperature(struct il_priv *il); |
| 232 | extern void il3945_hw_txq_free_tfd(struct il_priv *il, struct il_tx_queue *txq); | 231 | int il3945_hw_tx_queue_init(struct il_priv *il, struct il_tx_queue *txq); |
| 233 | extern int il3945_hw_get_temperature(struct il_priv *il); | 232 | unsigned int il3945_hw_get_beacon_cmd(struct il_priv *il, |
| 234 | extern int il3945_hw_tx_queue_init(struct il_priv *il, struct il_tx_queue *txq); | 233 | struct il3945_frame *frame, u8 rate); |
| 235 | extern unsigned int il3945_hw_get_beacon_cmd(struct il_priv *il, | ||
| 236 | struct il3945_frame *frame, | ||
| 237 | u8 rate); | ||
| 238 | void il3945_hw_build_tx_cmd_rate(struct il_priv *il, struct il_device_cmd *cmd, | 234 | void il3945_hw_build_tx_cmd_rate(struct il_priv *il, struct il_device_cmd *cmd, |
| 239 | struct ieee80211_tx_info *info, | 235 | struct ieee80211_tx_info *info, |
| 240 | struct ieee80211_hdr *hdr, int sta_id); | 236 | struct ieee80211_hdr *hdr, int sta_id); |
| 241 | extern int il3945_hw_reg_send_txpower(struct il_priv *il); | 237 | int il3945_hw_reg_send_txpower(struct il_priv *il); |
| 242 | extern int il3945_hw_reg_set_txpower(struct il_priv *il, s8 power); | 238 | int il3945_hw_reg_set_txpower(struct il_priv *il, s8 power); |
| 243 | extern void il3945_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb); | 239 | void il3945_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb); |
| 244 | void il3945_hdl_c_stats(struct il_priv *il, struct il_rx_buf *rxb); | 240 | void il3945_hdl_c_stats(struct il_priv *il, struct il_rx_buf *rxb); |
| 245 | extern void il3945_disable_events(struct il_priv *il); | 241 | void il3945_disable_events(struct il_priv *il); |
| 246 | extern int il4965_get_temperature(const struct il_priv *il); | 242 | int il4965_get_temperature(const struct il_priv *il); |
| 247 | extern void il3945_post_associate(struct il_priv *il); | 243 | void il3945_post_associate(struct il_priv *il); |
| 248 | extern void il3945_config_ap(struct il_priv *il); | 244 | void il3945_config_ap(struct il_priv *il); |
| 249 | 245 | ||
| 250 | extern int il3945_commit_rxon(struct il_priv *il); | 246 | int il3945_commit_rxon(struct il_priv *il); |
| 251 | 247 | ||
| 252 | /** | 248 | /** |
| 253 | * il3945_hw_find_station - Find station id for a given BSSID | 249 | * il3945_hw_find_station - Find station id for a given BSSID |
| @@ -257,14 +253,14 @@ extern int il3945_commit_rxon(struct il_priv *il); | |||
| 257 | * not yet been merged into a single common layer for managing the | 253 | * not yet been merged into a single common layer for managing the |
| 258 | * station tables. | 254 | * station tables. |
| 259 | */ | 255 | */ |
| 260 | extern u8 il3945_hw_find_station(struct il_priv *il, const u8 * bssid); | 256 | u8 il3945_hw_find_station(struct il_priv *il, const u8 *bssid); |
| 261 | 257 | ||
| 262 | extern __le32 il3945_get_antenna_flags(const struct il_priv *il); | 258 | __le32 il3945_get_antenna_flags(const struct il_priv *il); |
| 263 | extern int il3945_init_hw_rate_table(struct il_priv *il); | 259 | int il3945_init_hw_rate_table(struct il_priv *il); |
| 264 | extern void il3945_reg_txpower_periodic(struct il_priv *il); | 260 | void il3945_reg_txpower_periodic(struct il_priv *il); |
| 265 | extern int il3945_txpower_set_from_eeprom(struct il_priv *il); | 261 | int il3945_txpower_set_from_eeprom(struct il_priv *il); |
| 266 | 262 | ||
| 267 | extern int il3945_rs_next_rate(struct il_priv *il, int rate); | 263 | int il3945_rs_next_rate(struct il_priv *il, int rate); |
| 268 | 264 | ||
| 269 | /* scanning */ | 265 | /* scanning */ |
| 270 | int il3945_request_scan(struct il_priv *il, struct ieee80211_vif *vif); | 266 | int il3945_request_scan(struct il_priv *il, struct ieee80211_vif *vif); |
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 5ab50a5b48b1..3982ab76f375 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c | |||
| @@ -6706,7 +6706,6 @@ out_free_eeprom: | |||
| 6706 | out_iounmap: | 6706 | out_iounmap: |
| 6707 | iounmap(il->hw_base); | 6707 | iounmap(il->hw_base); |
| 6708 | out_pci_release_regions: | 6708 | out_pci_release_regions: |
| 6709 | pci_set_drvdata(pdev, NULL); | ||
| 6710 | pci_release_regions(pdev); | 6709 | pci_release_regions(pdev); |
| 6711 | out_pci_disable_device: | 6710 | out_pci_disable_device: |
| 6712 | pci_disable_device(pdev); | 6711 | pci_disable_device(pdev); |
| @@ -6787,7 +6786,6 @@ il4965_pci_remove(struct pci_dev *pdev) | |||
| 6787 | iounmap(il->hw_base); | 6786 | iounmap(il->hw_base); |
| 6788 | pci_release_regions(pdev); | 6787 | pci_release_regions(pdev); |
| 6789 | pci_disable_device(pdev); | 6788 | pci_disable_device(pdev); |
| 6790 | pci_set_drvdata(pdev, NULL); | ||
| 6791 | 6789 | ||
| 6792 | il4965_uninit_drv(il); | 6790 | il4965_uninit_drv(il); |
| 6793 | 6791 | ||
diff --git a/drivers/net/wireless/iwlegacy/4965.h b/drivers/net/wireless/iwlegacy/4965.h index 1b15b0b2292b..337dfcf3bbde 100644 --- a/drivers/net/wireless/iwlegacy/4965.h +++ b/drivers/net/wireless/iwlegacy/4965.h | |||
| @@ -272,7 +272,7 @@ il4965_hw_valid_rtc_data_addr(u32 addr) | |||
| 272 | ((t) < IL_TX_POWER_TEMPERATURE_MIN || \ | 272 | ((t) < IL_TX_POWER_TEMPERATURE_MIN || \ |
| 273 | (t) > IL_TX_POWER_TEMPERATURE_MAX) | 273 | (t) > IL_TX_POWER_TEMPERATURE_MAX) |
| 274 | 274 | ||
| 275 | extern void il4965_temperature_calib(struct il_priv *il); | 275 | void il4965_temperature_calib(struct il_priv *il); |
| 276 | /********************* END TEMPERATURE ***************************************/ | 276 | /********************* END TEMPERATURE ***************************************/ |
| 277 | 277 | ||
| 278 | /********************* START TXPOWER *****************************************/ | 278 | /********************* START TXPOWER *****************************************/ |
diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index 83f8ed8a5528..ad123d66ab6c 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h | |||
| @@ -858,9 +858,9 @@ struct il_hw_params { | |||
| 858 | * il4965_mac_ <-- mac80211 callback | 858 | * il4965_mac_ <-- mac80211 callback |
| 859 | * | 859 | * |
| 860 | ****************************************************************************/ | 860 | ****************************************************************************/ |
| 861 | extern void il4965_update_chain_flags(struct il_priv *il); | 861 | void il4965_update_chain_flags(struct il_priv *il); |
| 862 | extern const u8 il_bcast_addr[ETH_ALEN]; | 862 | extern const u8 il_bcast_addr[ETH_ALEN]; |
| 863 | extern int il_queue_space(const struct il_queue *q); | 863 | int il_queue_space(const struct il_queue *q); |
| 864 | static inline int | 864 | static inline int |
| 865 | il_queue_used(const struct il_queue *q, int i) | 865 | il_queue_used(const struct il_queue *q, int i) |
| 866 | { | 866 | { |
| @@ -1727,7 +1727,7 @@ int il_alloc_txq_mem(struct il_priv *il); | |||
| 1727 | void il_free_txq_mem(struct il_priv *il); | 1727 | void il_free_txq_mem(struct il_priv *il); |
| 1728 | 1728 | ||
| 1729 | #ifdef CONFIG_IWLEGACY_DEBUGFS | 1729 | #ifdef CONFIG_IWLEGACY_DEBUGFS |
| 1730 | extern void il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len); | 1730 | void il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len); |
| 1731 | #else | 1731 | #else |
| 1732 | static inline void | 1732 | static inline void |
| 1733 | il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len) | 1733 | il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len) |
| @@ -1760,12 +1760,12 @@ void il_chswitch_done(struct il_priv *il, bool is_success); | |||
| 1760 | /***************************************************** | 1760 | /***************************************************** |
| 1761 | * TX | 1761 | * TX |
| 1762 | ******************************************************/ | 1762 | ******************************************************/ |
| 1763 | extern void il_txq_update_write_ptr(struct il_priv *il, struct il_tx_queue *txq); | 1763 | void il_txq_update_write_ptr(struct il_priv *il, struct il_tx_queue *txq); |
| 1764 | extern int il_tx_queue_init(struct il_priv *il, u32 txq_id); | 1764 | int il_tx_queue_init(struct il_priv *il, u32 txq_id); |
| 1765 | extern void il_tx_queue_reset(struct il_priv *il, u32 txq_id); | 1765 | void il_tx_queue_reset(struct il_priv *il, u32 txq_id); |
| 1766 | extern void il_tx_queue_unmap(struct il_priv *il, int txq_id); | 1766 | void il_tx_queue_unmap(struct il_priv *il, int txq_id); |
| 1767 | extern void il_tx_queue_free(struct il_priv *il, int txq_id); | 1767 | void il_tx_queue_free(struct il_priv *il, int txq_id); |
| 1768 | extern void il_setup_watchdog(struct il_priv *il); | 1768 | void il_setup_watchdog(struct il_priv *il); |
| 1769 | /***************************************************** | 1769 | /***************************************************** |
| 1770 | * TX power | 1770 | * TX power |
| 1771 | ****************************************************/ | 1771 | ****************************************************/ |
| @@ -1931,10 +1931,10 @@ il_is_ready_rf(struct il_priv *il) | |||
| 1931 | return il_is_ready(il); | 1931 | return il_is_ready(il); |
| 1932 | } | 1932 | } |
| 1933 | 1933 | ||
| 1934 | extern void il_send_bt_config(struct il_priv *il); | 1934 | void il_send_bt_config(struct il_priv *il); |
| 1935 | extern int il_send_stats_request(struct il_priv *il, u8 flags, bool clear); | 1935 | int il_send_stats_request(struct il_priv *il, u8 flags, bool clear); |
| 1936 | extern void il_apm_stop(struct il_priv *il); | 1936 | void il_apm_stop(struct il_priv *il); |
| 1937 | extern void _il_apm_stop(struct il_priv *il); | 1937 | void _il_apm_stop(struct il_priv *il); |
| 1938 | 1938 | ||
| 1939 | int il_apm_init(struct il_priv *il); | 1939 | int il_apm_init(struct il_priv *il); |
| 1940 | 1940 | ||
| @@ -1968,15 +1968,15 @@ void il_tx_cmd_protection(struct il_priv *il, struct ieee80211_tx_info *info, | |||
| 1968 | 1968 | ||
| 1969 | irqreturn_t il_isr(int irq, void *data); | 1969 | irqreturn_t il_isr(int irq, void *data); |
| 1970 | 1970 | ||
| 1971 | extern void il_set_bit(struct il_priv *p, u32 r, u32 m); | 1971 | void il_set_bit(struct il_priv *p, u32 r, u32 m); |
| 1972 | extern void il_clear_bit(struct il_priv *p, u32 r, u32 m); | 1972 | void il_clear_bit(struct il_priv *p, u32 r, u32 m); |
| 1973 | extern bool _il_grab_nic_access(struct il_priv *il); | 1973 | bool _il_grab_nic_access(struct il_priv *il); |
| 1974 | extern int _il_poll_bit(struct il_priv *il, u32 addr, u32 bits, u32 mask, int timeout); | 1974 | int _il_poll_bit(struct il_priv *il, u32 addr, u32 bits, u32 mask, int timeout); |
| 1975 | extern int il_poll_bit(struct il_priv *il, u32 addr, u32 mask, int timeout); | 1975 | int il_poll_bit(struct il_priv *il, u32 addr, u32 mask, int timeout); |
| 1976 | extern u32 il_rd_prph(struct il_priv *il, u32 reg); | 1976 | u32 il_rd_prph(struct il_priv *il, u32 reg); |
| 1977 | extern void il_wr_prph(struct il_priv *il, u32 addr, u32 val); | 1977 | void il_wr_prph(struct il_priv *il, u32 addr, u32 val); |
| 1978 | extern u32 il_read_targ_mem(struct il_priv *il, u32 addr); | 1978 | u32 il_read_targ_mem(struct il_priv *il, u32 addr); |
| 1979 | extern void il_write_targ_mem(struct il_priv *il, u32 addr, u32 val); | 1979 | void il_write_targ_mem(struct il_priv *il, u32 addr, u32 val); |
| 1980 | 1980 | ||
| 1981 | static inline void | 1981 | static inline void |
| 1982 | _il_write8(struct il_priv *il, u32 ofs, u8 val) | 1982 | _il_write8(struct il_priv *il, u32 ofs, u8 val) |
| @@ -2868,13 +2868,13 @@ il4965_first_antenna(u8 mask) | |||
| 2868 | * The specific throughput table used is based on the type of network | 2868 | * The specific throughput table used is based on the type of network |
| 2869 | * the associated with, including A, B, G, and G w/ TGG protection | 2869 | * the associated with, including A, B, G, and G w/ TGG protection |
| 2870 | */ | 2870 | */ |
| 2871 | extern void il3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id); | 2871 | void il3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id); |
| 2872 | 2872 | ||
| 2873 | /* Initialize station's rate scaling information after adding station */ | 2873 | /* Initialize station's rate scaling information after adding station */ |
| 2874 | extern void il4965_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta, | 2874 | void il4965_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta, |
| 2875 | u8 sta_id); | 2875 | u8 sta_id); |
| 2876 | extern void il3945_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta, | 2876 | void il3945_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta, |
| 2877 | u8 sta_id); | 2877 | u8 sta_id); |
| 2878 | 2878 | ||
| 2879 | /** | 2879 | /** |
| 2880 | * il_rate_control_register - Register the rate control algorithm callbacks | 2880 | * il_rate_control_register - Register the rate control algorithm callbacks |
| @@ -2886,8 +2886,8 @@ extern void il3945_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta, | |||
| 2886 | * ieee80211_register_hw | 2886 | * ieee80211_register_hw |
| 2887 | * | 2887 | * |
| 2888 | */ | 2888 | */ |
| 2889 | extern int il4965_rate_control_register(void); | 2889 | int il4965_rate_control_register(void); |
| 2890 | extern int il3945_rate_control_register(void); | 2890 | int il3945_rate_control_register(void); |
| 2891 | 2891 | ||
| 2892 | /** | 2892 | /** |
| 2893 | * il_rate_control_unregister - Unregister the rate control callbacks | 2893 | * il_rate_control_unregister - Unregister the rate control callbacks |
| @@ -2895,11 +2895,11 @@ extern int il3945_rate_control_register(void); | |||
| 2895 | * This should be called after calling ieee80211_unregister_hw, but before | 2895 | * This should be called after calling ieee80211_unregister_hw, but before |
| 2896 | * the driver is unloaded. | 2896 | * the driver is unloaded. |
| 2897 | */ | 2897 | */ |
| 2898 | extern void il4965_rate_control_unregister(void); | 2898 | void il4965_rate_control_unregister(void); |
| 2899 | extern void il3945_rate_control_unregister(void); | 2899 | void il3945_rate_control_unregister(void); |
| 2900 | 2900 | ||
| 2901 | extern int il_power_update_mode(struct il_priv *il, bool force); | 2901 | int il_power_update_mode(struct il_priv *il, bool force); |
| 2902 | extern void il_power_initialize(struct il_priv *il); | 2902 | void il_power_initialize(struct il_priv *il); |
| 2903 | 2903 | ||
| 2904 | extern u32 il_debug_level; | 2904 | extern u32 il_debug_level; |
| 2905 | 2905 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h index f2a86ffc3b4c..23d5f0275ce9 100644 --- a/drivers/net/wireless/iwlwifi/dvm/agn.h +++ b/drivers/net/wireless/iwlwifi/dvm/agn.h | |||
| @@ -397,7 +397,7 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) | |||
| 397 | return cpu_to_le32(flags|(u32)rate); | 397 | return cpu_to_le32(flags|(u32)rate); |
| 398 | } | 398 | } |
| 399 | 399 | ||
| 400 | extern int iwl_alive_start(struct iwl_priv *priv); | 400 | int iwl_alive_start(struct iwl_priv *priv); |
| 401 | 401 | ||
| 402 | #ifdef CONFIG_IWLWIFI_DEBUG | 402 | #ifdef CONFIG_IWLWIFI_DEBUG |
| 403 | void iwl_print_rx_config_cmd(struct iwl_priv *priv, | 403 | void iwl_print_rx_config_cmd(struct iwl_priv *priv, |
diff --git a/drivers/net/wireless/iwlwifi/dvm/dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h index a79fdd137f95..7434d9edf3b7 100644 --- a/drivers/net/wireless/iwlwifi/dvm/dev.h +++ b/drivers/net/wireless/iwlwifi/dvm/dev.h | |||
| @@ -270,7 +270,7 @@ struct iwl_sensitivity_ranges { | |||
| 270 | * iwlXXXX_ <-- Hardware specific (implemented in iwl-XXXX.c for XXXX) | 270 | * iwlXXXX_ <-- Hardware specific (implemented in iwl-XXXX.c for XXXX) |
| 271 | * | 271 | * |
| 272 | ****************************************************************************/ | 272 | ****************************************************************************/ |
| 273 | extern void iwl_update_chain_flags(struct iwl_priv *priv); | 273 | void iwl_update_chain_flags(struct iwl_priv *priv); |
| 274 | extern const u8 iwl_bcast_addr[ETH_ALEN]; | 274 | extern const u8 iwl_bcast_addr[ETH_ALEN]; |
| 275 | 275 | ||
| 276 | #define IWL_OPERATION_MODE_AUTO 0 | 276 | #define IWL_OPERATION_MODE_AUTO 0 |
diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.h b/drivers/net/wireless/iwlwifi/dvm/rs.h index 5d83cab22d62..26fc550cd68c 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rs.h +++ b/drivers/net/wireless/iwlwifi/dvm/rs.h | |||
| @@ -407,8 +407,8 @@ static inline u8 first_antenna(u8 mask) | |||
| 407 | 407 | ||
| 408 | 408 | ||
| 409 | /* Initialize station's rate scaling information after adding station */ | 409 | /* Initialize station's rate scaling information after adding station */ |
| 410 | extern void iwl_rs_rate_init(struct iwl_priv *priv, | 410 | void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, |
| 411 | struct ieee80211_sta *sta, u8 sta_id); | 411 | u8 sta_id); |
| 412 | 412 | ||
| 413 | /** | 413 | /** |
| 414 | * iwl_rate_control_register - Register the rate control algorithm callbacks | 414 | * iwl_rate_control_register - Register the rate control algorithm callbacks |
| @@ -420,7 +420,7 @@ extern void iwl_rs_rate_init(struct iwl_priv *priv, | |||
| 420 | * ieee80211_register_hw | 420 | * ieee80211_register_hw |
| 421 | * | 421 | * |
| 422 | */ | 422 | */ |
| 423 | extern int iwlagn_rate_control_register(void); | 423 | int iwlagn_rate_control_register(void); |
| 424 | 424 | ||
| 425 | /** | 425 | /** |
| 426 | * iwl_rate_control_unregister - Unregister the rate control callbacks | 426 | * iwl_rate_control_unregister - Unregister the rate control callbacks |
| @@ -428,6 +428,6 @@ extern int iwlagn_rate_control_register(void); | |||
| 428 | * This should be called after calling ieee80211_unregister_hw, but before | 428 | * This should be called after calling ieee80211_unregister_hw, but before |
| 429 | * the driver is unloaded. | 429 | * the driver is unloaded. |
| 430 | */ | 430 | */ |
| 431 | extern void iwlagn_rate_control_unregister(void); | 431 | void iwlagn_rate_control_unregister(void); |
| 432 | 432 | ||
| 433 | #endif /* __iwl_agn__rs__ */ | 433 | #endif /* __iwl_agn__rs__ */ |
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index da442b81370a..1fef5240e6ad 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c | |||
| @@ -433,27 +433,19 @@ int iwlagn_tx_skb(struct iwl_priv *priv, | |||
| 433 | /* Copy MAC header from skb into command buffer */ | 433 | /* Copy MAC header from skb into command buffer */ |
| 434 | memcpy(tx_cmd->hdr, hdr, hdr_len); | 434 | memcpy(tx_cmd->hdr, hdr, hdr_len); |
| 435 | 435 | ||
| 436 | txq_id = info->hw_queue; | ||
| 437 | |||
| 436 | if (is_agg) | 438 | if (is_agg) |
| 437 | txq_id = priv->tid_data[sta_id][tid].agg.txq_id; | 439 | txq_id = priv->tid_data[sta_id][tid].agg.txq_id; |
| 438 | else if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { | 440 | else if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { |
| 439 | /* | 441 | /* |
| 440 | * Send this frame after DTIM -- there's a special queue | ||
| 441 | * reserved for this for contexts that support AP mode. | ||
| 442 | */ | ||
| 443 | txq_id = ctx->mcast_queue; | ||
| 444 | |||
| 445 | /* | ||
| 446 | * The microcode will clear the more data | 442 | * The microcode will clear the more data |
| 447 | * bit in the last frame it transmits. | 443 | * bit in the last frame it transmits. |
| 448 | */ | 444 | */ |
| 449 | hdr->frame_control |= | 445 | hdr->frame_control |= |
| 450 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 446 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); |
| 451 | } else if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) | 447 | } |
| 452 | txq_id = IWL_AUX_QUEUE; | ||
| 453 | else | ||
| 454 | txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)]; | ||
| 455 | 448 | ||
| 456 | WARN_ON_ONCE(!is_agg && txq_id != info->hw_queue); | ||
| 457 | WARN_ON_ONCE(is_agg && | 449 | WARN_ON_ONCE(is_agg && |
| 458 | priv->queue_to_mac80211[txq_id] != info->hw_queue); | 450 | priv->queue_to_mac80211[txq_id] != info->hw_queue); |
| 459 | 451 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c index 86270b69cd02..63637949a146 100644 --- a/drivers/net/wireless/iwlwifi/dvm/ucode.c +++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c | |||
| @@ -330,15 +330,14 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, | |||
| 330 | enum iwl_ucode_type old_type; | 330 | enum iwl_ucode_type old_type; |
| 331 | static const u8 alive_cmd[] = { REPLY_ALIVE }; | 331 | static const u8 alive_cmd[] = { REPLY_ALIVE }; |
| 332 | 332 | ||
| 333 | old_type = priv->cur_ucode; | ||
| 334 | priv->cur_ucode = ucode_type; | ||
| 335 | fw = iwl_get_ucode_image(priv, ucode_type); | 333 | fw = iwl_get_ucode_image(priv, ucode_type); |
| 334 | if (WARN_ON(!fw)) | ||
| 335 | return -EINVAL; | ||
| 336 | 336 | ||
| 337 | old_type = priv->cur_ucode; | ||
| 338 | priv->cur_ucode = ucode_type; | ||
| 337 | priv->ucode_loaded = false; | 339 | priv->ucode_loaded = false; |
| 338 | 340 | ||
| 339 | if (!fw) | ||
| 340 | return -EINVAL; | ||
| 341 | |||
| 342 | iwl_init_notification_wait(&priv->notif_wait, &alive_wait, | 341 | iwl_init_notification_wait(&priv->notif_wait, &alive_wait, |
| 343 | alive_cmd, ARRAY_SIZE(alive_cmd), | 342 | alive_cmd, ARRAY_SIZE(alive_cmd), |
| 344 | iwl_alive_fn, &alive_data); | 343 | iwl_alive_fn, &alive_data); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index 76e14c046d94..85879dbaa402 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c | |||
| @@ -83,6 +83,8 @@ | |||
| 83 | #define IWL7260_TX_POWER_VERSION 0xffff /* meaningless */ | 83 | #define IWL7260_TX_POWER_VERSION 0xffff /* meaningless */ |
| 84 | #define IWL3160_NVM_VERSION 0x709 | 84 | #define IWL3160_NVM_VERSION 0x709 |
| 85 | #define IWL3160_TX_POWER_VERSION 0xffff /* meaningless */ | 85 | #define IWL3160_TX_POWER_VERSION 0xffff /* meaningless */ |
| 86 | #define IWL7265_NVM_VERSION 0x0a1d | ||
| 87 | #define IWL7265_TX_POWER_VERSION 0xffff /* meaningless */ | ||
| 86 | 88 | ||
| 87 | #define IWL7260_FW_PRE "iwlwifi-7260-" | 89 | #define IWL7260_FW_PRE "iwlwifi-7260-" |
| 88 | #define IWL7260_MODULE_FIRMWARE(api) IWL7260_FW_PRE __stringify(api) ".ucode" | 90 | #define IWL7260_MODULE_FIRMWARE(api) IWL7260_FW_PRE __stringify(api) ".ucode" |
| @@ -90,6 +92,9 @@ | |||
| 90 | #define IWL3160_FW_PRE "iwlwifi-3160-" | 92 | #define IWL3160_FW_PRE "iwlwifi-3160-" |
| 91 | #define IWL3160_MODULE_FIRMWARE(api) IWL3160_FW_PRE __stringify(api) ".ucode" | 93 | #define IWL3160_MODULE_FIRMWARE(api) IWL3160_FW_PRE __stringify(api) ".ucode" |
| 92 | 94 | ||
| 95 | #define IWL7265_FW_PRE "iwlwifi-7265-" | ||
| 96 | #define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode" | ||
| 97 | |||
| 93 | static const struct iwl_base_params iwl7000_base_params = { | 98 | static const struct iwl_base_params iwl7000_base_params = { |
| 94 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 99 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
| 95 | .num_of_queues = IWLAGN_NUM_QUEUES, | 100 | .num_of_queues = IWLAGN_NUM_QUEUES, |
| @@ -182,5 +187,14 @@ const struct iwl_cfg iwl3160_n_cfg = { | |||
| 182 | .nvm_calib_ver = IWL3160_TX_POWER_VERSION, | 187 | .nvm_calib_ver = IWL3160_TX_POWER_VERSION, |
| 183 | }; | 188 | }; |
| 184 | 189 | ||
| 190 | const struct iwl_cfg iwl7265_2ac_cfg = { | ||
| 191 | .name = "Intel(R) Dual Band Wireless AC 7265", | ||
| 192 | .fw_name_pre = IWL7265_FW_PRE, | ||
| 193 | IWL_DEVICE_7000, | ||
| 194 | .ht_params = &iwl7000_ht_params, | ||
| 195 | .nvm_ver = IWL7265_NVM_VERSION, | ||
| 196 | .nvm_calib_ver = IWL7265_TX_POWER_VERSION, | ||
| 197 | }; | ||
| 198 | |||
| 185 | MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); | 199 | MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); |
| 186 | MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK)); | 200 | MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index b03c25e14903..18f232e8e812 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h | |||
| @@ -293,6 +293,7 @@ extern const struct iwl_cfg iwl7260_n_cfg; | |||
| 293 | extern const struct iwl_cfg iwl3160_2ac_cfg; | 293 | extern const struct iwl_cfg iwl3160_2ac_cfg; |
| 294 | extern const struct iwl_cfg iwl3160_2n_cfg; | 294 | extern const struct iwl_cfg iwl3160_2n_cfg; |
| 295 | extern const struct iwl_cfg iwl3160_n_cfg; | 295 | extern const struct iwl_cfg iwl3160_n_cfg; |
| 296 | extern const struct iwl_cfg iwl7265_2ac_cfg; | ||
| 296 | #endif /* CONFIG_IWLMVM */ | 297 | #endif /* CONFIG_IWLMVM */ |
| 297 | 298 | ||
| 298 | #endif /* __IWL_CONFIG_H__ */ | 299 | #endif /* __IWL_CONFIG_H__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index a276af476e2d..54a4fdc631b7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
| @@ -394,6 +394,38 @@ | |||
| 394 | #define CSR_DRAM_INT_TBL_ENABLE (1 << 31) | 394 | #define CSR_DRAM_INT_TBL_ENABLE (1 << 31) |
| 395 | #define CSR_DRAM_INIT_TBL_WRAP_CHECK (1 << 27) | 395 | #define CSR_DRAM_INIT_TBL_WRAP_CHECK (1 << 27) |
| 396 | 396 | ||
| 397 | /* SECURE boot registers */ | ||
| 398 | #define CSR_SECURE_BOOT_CONFIG_ADDR (0x100) | ||
| 399 | enum secure_boot_config_reg { | ||
| 400 | CSR_SECURE_BOOT_CONFIG_INSPECTOR_BURNED_IN_OTP = 0x00000001, | ||
| 401 | CSR_SECURE_BOOT_CONFIG_INSPECTOR_NOT_REQ = 0x00000002, | ||
| 402 | }; | ||
| 403 | |||
| 404 | #define CSR_SECURE_BOOT_CPU1_STATUS_ADDR (0x100) | ||
| 405 | #define CSR_SECURE_BOOT_CPU2_STATUS_ADDR (0x100) | ||
| 406 | enum secure_boot_status_reg { | ||
| 407 | CSR_SECURE_BOOT_CPU_STATUS_VERF_STATUS = 0x00000003, | ||
| 408 | CSR_SECURE_BOOT_CPU_STATUS_VERF_COMPLETED = 0x00000002, | ||
| 409 | CSR_SECURE_BOOT_CPU_STATUS_VERF_SUCCESS = 0x00000004, | ||
| 410 | CSR_SECURE_BOOT_CPU_STATUS_VERF_FAIL = 0x00000008, | ||
| 411 | CSR_SECURE_BOOT_CPU_STATUS_SIGN_VERF_FAIL = 0x00000010, | ||
| 412 | }; | ||
| 413 | |||
| 414 | #define CSR_UCODE_LOAD_STATUS_ADDR (0x100) | ||
| 415 | enum secure_load_status_reg { | ||
| 416 | CSR_CPU_STATUS_LOADING_STARTED = 0x00000001, | ||
| 417 | CSR_CPU_STATUS_LOADING_COMPLETED = 0x00000002, | ||
| 418 | CSR_CPU_STATUS_NUM_OF_LAST_COMPLETED = 0x000000F8, | ||
| 419 | CSR_CPU_STATUS_NUM_OF_LAST_LOADED_BLOCK = 0x0000FF00, | ||
| 420 | }; | ||
| 421 | |||
| 422 | #define CSR_SECURE_INSPECTOR_CODE_ADDR (0x100) | ||
| 423 | #define CSR_SECURE_INSPECTOR_DATA_ADDR (0x100) | ||
| 424 | |||
| 425 | #define CSR_SECURE_TIME_OUT (100) | ||
| 426 | |||
| 427 | #define FH_TCSR_0_REG0 (0x1D00) | ||
| 428 | |||
| 397 | /* | 429 | /* |
| 398 | * HBUS (Host-side Bus) | 430 | * HBUS (Host-side Bus) |
| 399 | * | 431 | * |
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 99e1da3123c9..ff570027e9dd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
| @@ -483,6 +483,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, | |||
| 483 | const u8 *tlv_data; | 483 | const u8 *tlv_data; |
| 484 | char buildstr[25]; | 484 | char buildstr[25]; |
| 485 | u32 build; | 485 | u32 build; |
| 486 | int num_of_cpus; | ||
| 486 | 487 | ||
| 487 | if (len < sizeof(*ucode)) { | 488 | if (len < sizeof(*ucode)) { |
| 488 | IWL_ERR(drv, "uCode has invalid length: %zd\n", len); | 489 | IWL_ERR(drv, "uCode has invalid length: %zd\n", len); |
| @@ -692,6 +693,42 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, | |||
| 692 | goto invalid_tlv_len; | 693 | goto invalid_tlv_len; |
| 693 | drv->fw.phy_config = le32_to_cpup((__le32 *)tlv_data); | 694 | drv->fw.phy_config = le32_to_cpup((__le32 *)tlv_data); |
| 694 | break; | 695 | break; |
| 696 | case IWL_UCODE_TLV_SECURE_SEC_RT: | ||
| 697 | iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR, | ||
| 698 | tlv_len); | ||
| 699 | drv->fw.mvm_fw = true; | ||
| 700 | drv->fw.img[IWL_UCODE_REGULAR].is_secure = true; | ||
| 701 | break; | ||
| 702 | case IWL_UCODE_TLV_SECURE_SEC_INIT: | ||
| 703 | iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_INIT, | ||
| 704 | tlv_len); | ||
| 705 | drv->fw.mvm_fw = true; | ||
| 706 | drv->fw.img[IWL_UCODE_INIT].is_secure = true; | ||
| 707 | break; | ||
| 708 | case IWL_UCODE_TLV_SECURE_SEC_WOWLAN: | ||
| 709 | iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_WOWLAN, | ||
| 710 | tlv_len); | ||
| 711 | drv->fw.mvm_fw = true; | ||
| 712 | drv->fw.img[IWL_UCODE_WOWLAN].is_secure = true; | ||
| 713 | break; | ||
| 714 | case IWL_UCODE_TLV_NUM_OF_CPU: | ||
| 715 | if (tlv_len != sizeof(u32)) | ||
| 716 | goto invalid_tlv_len; | ||
| 717 | num_of_cpus = | ||
| 718 | le32_to_cpup((__le32 *)tlv_data); | ||
| 719 | |||
| 720 | if (num_of_cpus == 2) { | ||
| 721 | drv->fw.img[IWL_UCODE_REGULAR].is_dual_cpus = | ||
| 722 | true; | ||
| 723 | drv->fw.img[IWL_UCODE_INIT].is_dual_cpus = | ||
| 724 | true; | ||
| 725 | drv->fw.img[IWL_UCODE_WOWLAN].is_dual_cpus = | ||
| 726 | true; | ||
| 727 | } else if ((num_of_cpus > 2) || (num_of_cpus < 1)) { | ||
| 728 | IWL_ERR(drv, "Driver support upto 2 CPUs\n"); | ||
| 729 | return -EINVAL; | ||
| 730 | } | ||
| 731 | break; | ||
| 695 | default: | 732 | default: |
| 696 | IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type); | 733 | IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type); |
| 697 | break; | 734 | break; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index 8b6c6fd95ed0..6c6c35c5228c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h | |||
| @@ -121,6 +121,10 @@ enum iwl_ucode_tlv_type { | |||
| 121 | IWL_UCODE_TLV_SEC_WOWLAN = 21, | 121 | IWL_UCODE_TLV_SEC_WOWLAN = 21, |
| 122 | IWL_UCODE_TLV_DEF_CALIB = 22, | 122 | IWL_UCODE_TLV_DEF_CALIB = 22, |
| 123 | IWL_UCODE_TLV_PHY_SKU = 23, | 123 | IWL_UCODE_TLV_PHY_SKU = 23, |
| 124 | IWL_UCODE_TLV_SECURE_SEC_RT = 24, | ||
| 125 | IWL_UCODE_TLV_SECURE_SEC_INIT = 25, | ||
| 126 | IWL_UCODE_TLV_SECURE_SEC_WOWLAN = 26, | ||
| 127 | IWL_UCODE_TLV_NUM_OF_CPU = 27, | ||
| 124 | }; | 128 | }; |
| 125 | 129 | ||
| 126 | struct iwl_ucode_tlv { | 130 | struct iwl_ucode_tlv { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h index a1223680bc70..75db087120c3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h | |||
| @@ -75,11 +75,23 @@ | |||
| 75 | * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P. | 75 | * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P. |
| 76 | * @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS | 76 | * @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS |
| 77 | * @IWL_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD | 77 | * @IWL_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD |
| 78 | * @IWL_UCODE_TLV_FLAGS_SHORT_BL: 16 entries of black list instead of 64 in scan | ||
| 79 | * offload profile config command. | ||
| 78 | * @IWL_UCODE_TLV_FLAGS_RX_ENERGY_API: supports rx signal strength api | 80 | * @IWL_UCODE_TLV_FLAGS_RX_ENERGY_API: supports rx signal strength api |
| 79 | * @IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2: using the new time event API. | 81 | * @IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2: using the new time event API. |
| 80 | * @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six | 82 | * @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six |
| 81 | * (rather than two) IPv6 addresses | 83 | * (rather than two) IPv6 addresses |
| 82 | * @IWL_UCODE_TLV_FLAGS_BF_UPDATED: new beacon filtering API | 84 | * @IWL_UCODE_TLV_FLAGS_BF_UPDATED: new beacon filtering API |
| 85 | * @IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID: not sending a probe with the SSID element | ||
| 86 | * from the probe request template. | ||
| 87 | * @IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API: modified D3 API to allow keeping | ||
| 88 | * connection when going back to D0 | ||
| 89 | * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL: new NS offload (small version) | ||
| 90 | * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE: new NS offload (large version) | ||
| 91 | * @IWL_UCODE_TLV_FLAGS_SCHED_SCAN: this uCode image supports scheduled scan. | ||
| 92 | * @IWL_UCODE_TLV_FLAGS_STA_KEY_CMD: new ADD_STA and ADD_STA_KEY command API | ||
| 93 | * @IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD: support device wide power command | ||
| 94 | * containing CAM (Continuous Active Mode) indication. | ||
| 83 | */ | 95 | */ |
| 84 | enum iwl_ucode_tlv_flag { | 96 | enum iwl_ucode_tlv_flag { |
| 85 | IWL_UCODE_TLV_FLAGS_PAN = BIT(0), | 97 | IWL_UCODE_TLV_FLAGS_PAN = BIT(0), |
| @@ -87,11 +99,21 @@ enum iwl_ucode_tlv_flag { | |||
| 87 | IWL_UCODE_TLV_FLAGS_MFP = BIT(2), | 99 | IWL_UCODE_TLV_FLAGS_MFP = BIT(2), |
| 88 | IWL_UCODE_TLV_FLAGS_P2P = BIT(3), | 100 | IWL_UCODE_TLV_FLAGS_P2P = BIT(3), |
| 89 | IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4), | 101 | IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4), |
| 90 | IWL_UCODE_TLV_FLAGS_UAPSD = BIT(6), | 102 | IWL_UCODE_TLV_FLAGS_NEWBT_COEX = BIT(5), |
| 103 | IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT = BIT(6), | ||
| 104 | IWL_UCODE_TLV_FLAGS_SHORT_BL = BIT(7), | ||
| 91 | IWL_UCODE_TLV_FLAGS_RX_ENERGY_API = BIT(8), | 105 | IWL_UCODE_TLV_FLAGS_RX_ENERGY_API = BIT(8), |
| 92 | IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2 = BIT(9), | 106 | IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2 = BIT(9), |
| 93 | IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS = BIT(10), | 107 | IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS = BIT(10), |
| 94 | IWL_UCODE_TLV_FLAGS_BF_UPDATED = BIT(11), | 108 | IWL_UCODE_TLV_FLAGS_BF_UPDATED = BIT(11), |
| 109 | IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID = BIT(12), | ||
| 110 | IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API = BIT(14), | ||
| 111 | IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL = BIT(15), | ||
| 112 | IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE = BIT(16), | ||
| 113 | IWL_UCODE_TLV_FLAGS_SCHED_SCAN = BIT(17), | ||
| 114 | IWL_UCODE_TLV_FLAGS_STA_KEY_CMD = BIT(19), | ||
| 115 | IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD = BIT(20), | ||
| 116 | IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT = BIT(24), | ||
| 95 | }; | 117 | }; |
| 96 | 118 | ||
| 97 | /* The default calibrate table size if not specified by firmware file */ | 119 | /* The default calibrate table size if not specified by firmware file */ |
| @@ -133,7 +155,8 @@ enum iwl_ucode_sec { | |||
| 133 | * For 16.0 uCode and above, there is no differentiation between sections, | 155 | * For 16.0 uCode and above, there is no differentiation between sections, |
| 134 | * just an offset to the HW address. | 156 | * just an offset to the HW address. |
| 135 | */ | 157 | */ |
| 136 | #define IWL_UCODE_SECTION_MAX 4 | 158 | #define IWL_UCODE_SECTION_MAX 6 |
| 159 | #define IWL_UCODE_FIRST_SECTION_OF_SECOND_CPU (IWL_UCODE_SECTION_MAX/2) | ||
| 137 | 160 | ||
| 138 | struct iwl_ucode_capabilities { | 161 | struct iwl_ucode_capabilities { |
| 139 | u32 max_probe_length; | 162 | u32 max_probe_length; |
| @@ -150,6 +173,8 @@ struct fw_desc { | |||
| 150 | 173 | ||
| 151 | struct fw_img { | 174 | struct fw_img { |
| 152 | struct fw_desc sec[IWL_UCODE_SECTION_MAX]; | 175 | struct fw_desc sec[IWL_UCODE_SECTION_MAX]; |
| 176 | bool is_secure; | ||
| 177 | bool is_dual_cpus; | ||
| 153 | }; | 178 | }; |
| 154 | 179 | ||
| 155 | /* uCode version contains 4 values: Major/Minor/API/Serial */ | 180 | /* uCode version contains 4 values: Major/Minor/API/Serial */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index dfa4d2e3aaa2..ad8e19a56eca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c | |||
| @@ -34,7 +34,6 @@ | |||
| 34 | #include "iwl-csr.h" | 34 | #include "iwl-csr.h" |
| 35 | #include "iwl-debug.h" | 35 | #include "iwl-debug.h" |
| 36 | #include "iwl-fh.h" | 36 | #include "iwl-fh.h" |
| 37 | #include "iwl-csr.h" | ||
| 38 | 37 | ||
| 39 | #define IWL_POLL_INTERVAL 10 /* microseconds */ | 38 | #define IWL_POLL_INTERVAL 10 /* microseconds */ |
| 40 | 39 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index ff8cc75c189d..a70c7b9d9bad 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h | |||
| @@ -97,6 +97,8 @@ | |||
| 97 | 97 | ||
| 98 | #define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800) | 98 | #define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800) |
| 99 | 99 | ||
| 100 | #define APMG_RTC_INT_STT_RFKILL (0x10000000) | ||
| 101 | |||
| 100 | /* Device system time */ | 102 | /* Device system time */ |
| 101 | #define DEVICE_SYSTEM_TIME_REG 0xA0206C | 103 | #define DEVICE_SYSTEM_TIME_REG 0xA0206C |
| 102 | 104 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 80b47508647c..143292b4dbbf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
| @@ -344,7 +344,7 @@ struct iwl_trans_config { | |||
| 344 | u8 cmd_queue; | 344 | u8 cmd_queue; |
| 345 | u8 cmd_fifo; | 345 | u8 cmd_fifo; |
| 346 | const u8 *no_reclaim_cmds; | 346 | const u8 *no_reclaim_cmds; |
| 347 | int n_no_reclaim_cmds; | 347 | unsigned int n_no_reclaim_cmds; |
| 348 | 348 | ||
| 349 | bool rx_buf_size_8k; | 349 | bool rx_buf_size_8k; |
| 350 | bool bc_table_dword; | 350 | bool bc_table_dword; |
| @@ -601,7 +601,7 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans, | |||
| 601 | { | 601 | { |
| 602 | int ret; | 602 | int ret; |
| 603 | 603 | ||
| 604 | if (trans->state != IWL_TRANS_FW_ALIVE) { | 604 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) { |
| 605 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); | 605 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); |
| 606 | return -EIO; | 606 | return -EIO; |
| 607 | } | 607 | } |
| @@ -640,8 +640,8 @@ static inline void iwl_trans_free_tx_cmd(struct iwl_trans *trans, | |||
| 640 | static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, | 640 | static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, |
| 641 | struct iwl_device_cmd *dev_cmd, int queue) | 641 | struct iwl_device_cmd *dev_cmd, int queue) |
| 642 | { | 642 | { |
| 643 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, | 643 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) |
| 644 | "%s bad state = %d", __func__, trans->state); | 644 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); |
| 645 | 645 | ||
| 646 | return trans->ops->tx(trans, skb, dev_cmd, queue); | 646 | return trans->ops->tx(trans, skb, dev_cmd, queue); |
| 647 | } | 647 | } |
| @@ -649,16 +649,16 @@ static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
| 649 | static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue, | 649 | static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue, |
| 650 | int ssn, struct sk_buff_head *skbs) | 650 | int ssn, struct sk_buff_head *skbs) |
| 651 | { | 651 | { |
| 652 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, | 652 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) |
| 653 | "%s bad state = %d", __func__, trans->state); | 653 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); |
| 654 | 654 | ||
| 655 | trans->ops->reclaim(trans, queue, ssn, skbs); | 655 | trans->ops->reclaim(trans, queue, ssn, skbs); |
| 656 | } | 656 | } |
| 657 | 657 | ||
| 658 | static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue) | 658 | static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue) |
| 659 | { | 659 | { |
| 660 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, | 660 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) |
| 661 | "%s bad state = %d", __func__, trans->state); | 661 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); |
| 662 | 662 | ||
| 663 | trans->ops->txq_disable(trans, queue); | 663 | trans->ops->txq_disable(trans, queue); |
| 664 | } | 664 | } |
| @@ -669,8 +669,8 @@ static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue, | |||
| 669 | { | 669 | { |
| 670 | might_sleep(); | 670 | might_sleep(); |
| 671 | 671 | ||
| 672 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, | 672 | if (unlikely((trans->state != IWL_TRANS_FW_ALIVE))) |
| 673 | "%s bad state = %d", __func__, trans->state); | 673 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); |
| 674 | 674 | ||
| 675 | trans->ops->txq_enable(trans, queue, fifo, sta_id, tid, | 675 | trans->ops->txq_enable(trans, queue, fifo, sta_id, tid, |
| 676 | frame_limit, ssn); | 676 | frame_limit, ssn); |
| @@ -685,8 +685,8 @@ static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue, | |||
| 685 | 685 | ||
| 686 | static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans) | 686 | static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans) |
| 687 | { | 687 | { |
| 688 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, | 688 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) |
| 689 | "%s bad state = %d", __func__, trans->state); | 689 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); |
| 690 | 690 | ||
| 691 | return trans->ops->wait_tx_queue_empty(trans); | 691 | return trans->ops->wait_tx_queue_empty(trans); |
| 692 | } | 692 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c index 0fad98b85f60..5d066cbc5ac7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c | |||
| @@ -98,126 +98,258 @@ static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { | |||
| 98 | 98 | ||
| 99 | #undef EVENT_PRIO_ANT | 99 | #undef EVENT_PRIO_ANT |
| 100 | 100 | ||
| 101 | /* BT Antenna Coupling Threshold (dB) */ | ||
| 102 | #define IWL_BT_ANTENNA_COUPLING_THRESHOLD (35) | ||
| 103 | #define IWL_BT_LOAD_FORCE_SISO_THRESHOLD (3) | ||
| 104 | |||
| 105 | #define BT_ENABLE_REDUCED_TXPOWER_THRESHOLD (-62) | 101 | #define BT_ENABLE_REDUCED_TXPOWER_THRESHOLD (-62) |
| 106 | #define BT_DISABLE_REDUCED_TXPOWER_THRESHOLD (-65) | 102 | #define BT_DISABLE_REDUCED_TXPOWER_THRESHOLD (-65) |
| 107 | #define BT_REDUCED_TX_POWER_BIT BIT(7) | 103 | #define BT_ANTENNA_COUPLING_THRESHOLD (30) |
| 108 | |||
| 109 | static inline bool is_loose_coex(void) | ||
| 110 | { | ||
| 111 | return iwlwifi_mod_params.ant_coupling > | ||
| 112 | IWL_BT_ANTENNA_COUPLING_THRESHOLD; | ||
| 113 | } | ||
| 114 | 104 | ||
| 115 | int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm) | 105 | int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm) |
| 116 | { | 106 | { |
| 107 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWBT_COEX)) | ||
| 108 | return 0; | ||
| 109 | |||
| 117 | return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, CMD_SYNC, | 110 | return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, CMD_SYNC, |
| 118 | sizeof(struct iwl_bt_coex_prio_tbl_cmd), | 111 | sizeof(struct iwl_bt_coex_prio_tbl_cmd), |
| 119 | &iwl_bt_prio_tbl); | 112 | &iwl_bt_prio_tbl); |
| 120 | } | 113 | } |
| 121 | 114 | ||
| 122 | static int iwl_send_bt_env(struct iwl_mvm *mvm, u8 action, u8 type) | 115 | const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = { |
| 123 | { | ||
| 124 | struct iwl_bt_coex_prot_env_cmd env_cmd; | ||
| 125 | int ret; | ||
| 126 | |||
| 127 | env_cmd.action = action; | ||
| 128 | env_cmd.type = type; | ||
| 129 | ret = iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PROT_ENV, CMD_SYNC, | ||
| 130 | sizeof(env_cmd), &env_cmd); | ||
| 131 | if (ret) | ||
| 132 | IWL_ERR(mvm, "failed to send BT env command\n"); | ||
| 133 | return ret; | ||
| 134 | } | ||
| 135 | |||
| 136 | enum iwl_bt_kill_msk { | ||
| 137 | BT_KILL_MSK_DEFAULT, | ||
| 138 | BT_KILL_MSK_SCO_HID_A2DP, | ||
| 139 | BT_KILL_MSK_REDUCED_TXPOW, | ||
| 140 | BT_KILL_MSK_MAX, | ||
| 141 | }; | ||
| 142 | |||
| 143 | static const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = { | ||
| 144 | [BT_KILL_MSK_DEFAULT] = 0xffff0000, | 116 | [BT_KILL_MSK_DEFAULT] = 0xffff0000, |
| 145 | [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff, | 117 | [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff, |
| 146 | [BT_KILL_MSK_REDUCED_TXPOW] = 0, | 118 | [BT_KILL_MSK_REDUCED_TXPOW] = 0, |
| 147 | }; | 119 | }; |
| 148 | 120 | ||
| 149 | static const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = { | 121 | const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = { |
| 150 | [BT_KILL_MSK_DEFAULT] = 0xffff0000, | 122 | [BT_KILL_MSK_DEFAULT] = 0xffff0000, |
| 151 | [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff, | 123 | [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff, |
| 152 | [BT_KILL_MSK_REDUCED_TXPOW] = 0, | 124 | [BT_KILL_MSK_REDUCED_TXPOW] = 0, |
| 153 | }; | 125 | }; |
| 154 | 126 | ||
| 155 | #define IWL_BT_DEFAULT_BOOST (0xf0f0f0f0) | 127 | static const __le32 iwl_bt_prio_boost[BT_COEX_BOOST_SIZE] = { |
| 156 | 128 | cpu_to_le32(0xf0f0f0f0), | |
| 157 | /* Tight Coex */ | 129 | cpu_to_le32(0xc0c0c0c0), |
| 158 | static const __le32 iwl_tight_lookup[BT_COEX_LUT_SIZE] = { | 130 | cpu_to_le32(0xfcfcfcfc), |
| 159 | cpu_to_le32(0xaaaaaaaa), | 131 | cpu_to_le32(0xff00ff00), |
| 160 | cpu_to_le32(0xaaaaaaaa), | ||
| 161 | cpu_to_le32(0xaeaaaaaa), | ||
| 162 | cpu_to_le32(0xaaaaaaaa), | ||
| 163 | cpu_to_le32(0xcc00ff28), | ||
| 164 | cpu_to_le32(0x0000aaaa), | ||
| 165 | cpu_to_le32(0xcc00aaaa), | ||
| 166 | cpu_to_le32(0x0000aaaa), | ||
| 167 | cpu_to_le32(0xc0004000), | ||
| 168 | cpu_to_le32(0x00000000), | ||
| 169 | cpu_to_le32(0xf0005000), | ||
| 170 | cpu_to_le32(0xf0005000), | ||
| 171 | }; | 132 | }; |
| 172 | 133 | ||
| 173 | /* Loose Coex */ | 134 | static const __le32 iwl_single_shared_ant[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = { |
| 174 | static const __le32 iwl_loose_lookup[BT_COEX_LUT_SIZE] = { | 135 | { |
| 175 | cpu_to_le32(0xaaaaaaaa), | 136 | cpu_to_le32(0x40000000), |
| 176 | cpu_to_le32(0xaaaaaaaa), | 137 | cpu_to_le32(0x00000000), |
| 177 | cpu_to_le32(0xaaaaaaaa), | 138 | cpu_to_le32(0x44000000), |
| 178 | cpu_to_le32(0xaaaaaaaa), | 139 | cpu_to_le32(0x00000000), |
| 179 | cpu_to_le32(0xcc00ff28), | 140 | cpu_to_le32(0x40000000), |
| 180 | cpu_to_le32(0x0000aaaa), | 141 | cpu_to_le32(0x00000000), |
| 181 | cpu_to_le32(0xcc00aaaa), | 142 | cpu_to_le32(0x44000000), |
| 182 | cpu_to_le32(0x0000aaaa), | 143 | cpu_to_le32(0x00000000), |
| 183 | cpu_to_le32(0x00000000), | 144 | cpu_to_le32(0xc0004000), |
| 184 | cpu_to_le32(0x00000000), | 145 | cpu_to_le32(0xf0005000), |
| 185 | cpu_to_le32(0xf0005000), | 146 | cpu_to_le32(0xc0004000), |
| 186 | cpu_to_le32(0xf0005000), | 147 | cpu_to_le32(0xf0005000), |
| 148 | }, | ||
| 149 | { | ||
| 150 | cpu_to_le32(0x40000000), | ||
| 151 | cpu_to_le32(0x00000000), | ||
| 152 | cpu_to_le32(0x44000000), | ||
| 153 | cpu_to_le32(0x00000000), | ||
| 154 | cpu_to_le32(0x40000000), | ||
| 155 | cpu_to_le32(0x00000000), | ||
| 156 | cpu_to_le32(0x44000000), | ||
| 157 | cpu_to_le32(0x00000000), | ||
| 158 | cpu_to_le32(0xc0004000), | ||
| 159 | cpu_to_le32(0xf0005000), | ||
| 160 | cpu_to_le32(0xc0004000), | ||
| 161 | cpu_to_le32(0xf0005000), | ||
| 162 | }, | ||
| 163 | { | ||
| 164 | cpu_to_le32(0x40000000), | ||
| 165 | cpu_to_le32(0x00000000), | ||
| 166 | cpu_to_le32(0x44000000), | ||
| 167 | cpu_to_le32(0x00000000), | ||
| 168 | cpu_to_le32(0x40000000), | ||
| 169 | cpu_to_le32(0x00000000), | ||
| 170 | cpu_to_le32(0x44000000), | ||
| 171 | cpu_to_le32(0x00000000), | ||
| 172 | cpu_to_le32(0xc0004000), | ||
| 173 | cpu_to_le32(0xf0005000), | ||
| 174 | cpu_to_le32(0xc0004000), | ||
| 175 | cpu_to_le32(0xf0005000), | ||
| 176 | }, | ||
| 187 | }; | 177 | }; |
| 188 | 178 | ||
| 189 | /* Full concurrency */ | 179 | static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = { |
| 190 | static const __le32 iwl_concurrent_lookup[BT_COEX_LUT_SIZE] = { | 180 | { |
| 191 | cpu_to_le32(0xaaaaaaaa), | 181 | /* Tight */ |
| 192 | cpu_to_le32(0xaaaaaaaa), | 182 | cpu_to_le32(0xaaaaaaaa), |
| 193 | cpu_to_le32(0xaaaaaaaa), | 183 | cpu_to_le32(0xaaaaaaaa), |
| 194 | cpu_to_le32(0xaaaaaaaa), | 184 | cpu_to_le32(0xaeaaaaaa), |
| 195 | cpu_to_le32(0xaaaaaaaa), | 185 | cpu_to_le32(0xaaaaaaaa), |
| 196 | cpu_to_le32(0xaaaaaaaa), | 186 | cpu_to_le32(0xcc00ff28), |
| 197 | cpu_to_le32(0xaaaaaaaa), | 187 | cpu_to_le32(0x0000aaaa), |
| 198 | cpu_to_le32(0xaaaaaaaa), | 188 | cpu_to_le32(0xcc00aaaa), |
| 199 | cpu_to_le32(0x00000000), | 189 | cpu_to_le32(0x0000aaaa), |
| 200 | cpu_to_le32(0x00000000), | 190 | cpu_to_le32(0xc0004000), |
| 201 | cpu_to_le32(0x00000000), | 191 | cpu_to_le32(0x00000000), |
| 202 | cpu_to_le32(0x00000000), | 192 | cpu_to_le32(0xf0005000), |
| 193 | cpu_to_le32(0xf0005000), | ||
| 194 | }, | ||
| 195 | { | ||
| 196 | /* Loose */ | ||
| 197 | cpu_to_le32(0xaaaaaaaa), | ||
| 198 | cpu_to_le32(0xaaaaaaaa), | ||
| 199 | cpu_to_le32(0xaaaaaaaa), | ||
| 200 | cpu_to_le32(0xaaaaaaaa), | ||
| 201 | cpu_to_le32(0xcc00ff28), | ||
| 202 | cpu_to_le32(0x0000aaaa), | ||
| 203 | cpu_to_le32(0xcc00aaaa), | ||
| 204 | cpu_to_le32(0x0000aaaa), | ||
| 205 | cpu_to_le32(0x00000000), | ||
| 206 | cpu_to_le32(0x00000000), | ||
| 207 | cpu_to_le32(0xf0005000), | ||
| 208 | cpu_to_le32(0xf0005000), | ||
| 209 | }, | ||
| 210 | { | ||
| 211 | /* Tx Tx disabled */ | ||
| 212 | cpu_to_le32(0xaaaaaaaa), | ||
| 213 | cpu_to_le32(0xaaaaaaaa), | ||
| 214 | cpu_to_le32(0xaaaaaaaa), | ||
| 215 | cpu_to_le32(0xaaaaaaaa), | ||
| 216 | cpu_to_le32(0xcc00ff28), | ||
| 217 | cpu_to_le32(0x0000aaaa), | ||
| 218 | cpu_to_le32(0xcc00aaaa), | ||
| 219 | cpu_to_le32(0x0000aaaa), | ||
| 220 | cpu_to_le32(0xC0004000), | ||
| 221 | cpu_to_le32(0xC0004000), | ||
| 222 | cpu_to_le32(0xF0005000), | ||
| 223 | cpu_to_le32(0xF0005000), | ||
| 224 | }, | ||
| 203 | }; | 225 | }; |
| 204 | 226 | ||
| 205 | /* single shared antenna */ | 227 | /* 20MHz / 40MHz below / 40Mhz above*/ |
| 206 | static const __le32 iwl_single_shared_ant_lookup[BT_COEX_LUT_SIZE] = { | 228 | static const __le64 iwl_ci_mask[][3] = { |
| 207 | cpu_to_le32(0x40000000), | 229 | /* dummy entry for channel 0 */ |
| 208 | cpu_to_le32(0x00000000), | 230 | {cpu_to_le64(0), cpu_to_le64(0), cpu_to_le64(0)}, |
| 209 | cpu_to_le32(0x44000000), | 231 | { |
| 210 | cpu_to_le32(0x00000000), | 232 | cpu_to_le64(0x0000001FFFULL), |
| 211 | cpu_to_le32(0x40000000), | 233 | cpu_to_le64(0x0ULL), |
| 212 | cpu_to_le32(0x00000000), | 234 | cpu_to_le64(0x00007FFFFFULL), |
| 213 | cpu_to_le32(0x44000000), | 235 | }, |
| 214 | cpu_to_le32(0x00000000), | 236 | { |
| 215 | cpu_to_le32(0xC0004000), | 237 | cpu_to_le64(0x000000FFFFULL), |
| 216 | cpu_to_le32(0xF0005000), | 238 | cpu_to_le64(0x0ULL), |
| 217 | cpu_to_le32(0xC0004000), | 239 | cpu_to_le64(0x0003FFFFFFULL), |
| 218 | cpu_to_le32(0xF0005000), | 240 | }, |
| 241 | { | ||
| 242 | cpu_to_le64(0x000003FFFCULL), | ||
| 243 | cpu_to_le64(0x0ULL), | ||
| 244 | cpu_to_le64(0x000FFFFFFCULL), | ||
| 245 | }, | ||
| 246 | { | ||
| 247 | cpu_to_le64(0x00001FFFE0ULL), | ||
| 248 | cpu_to_le64(0x0ULL), | ||
| 249 | cpu_to_le64(0x007FFFFFE0ULL), | ||
| 250 | }, | ||
| 251 | { | ||
| 252 | cpu_to_le64(0x00007FFF80ULL), | ||
| 253 | cpu_to_le64(0x00007FFFFFULL), | ||
| 254 | cpu_to_le64(0x01FFFFFF80ULL), | ||
| 255 | }, | ||
| 256 | { | ||
| 257 | cpu_to_le64(0x0003FFFC00ULL), | ||
| 258 | cpu_to_le64(0x0003FFFFFFULL), | ||
| 259 | cpu_to_le64(0x0FFFFFFC00ULL), | ||
| 260 | }, | ||
| 261 | { | ||
| 262 | cpu_to_le64(0x000FFFF000ULL), | ||
| 263 | cpu_to_le64(0x000FFFFFFCULL), | ||
| 264 | cpu_to_le64(0x3FFFFFF000ULL), | ||
| 265 | }, | ||
| 266 | { | ||
| 267 | cpu_to_le64(0x007FFF8000ULL), | ||
| 268 | cpu_to_le64(0x007FFFFFE0ULL), | ||
| 269 | cpu_to_le64(0xFFFFFF8000ULL), | ||
| 270 | }, | ||
| 271 | { | ||
| 272 | cpu_to_le64(0x01FFFE0000ULL), | ||
| 273 | cpu_to_le64(0x01FFFFFF80ULL), | ||
| 274 | cpu_to_le64(0xFFFFFE0000ULL), | ||
| 275 | }, | ||
| 276 | { | ||
| 277 | cpu_to_le64(0x0FFFF00000ULL), | ||
| 278 | cpu_to_le64(0x0FFFFFFC00ULL), | ||
| 279 | cpu_to_le64(0x0ULL), | ||
| 280 | }, | ||
| 281 | { | ||
| 282 | cpu_to_le64(0x3FFFC00000ULL), | ||
| 283 | cpu_to_le64(0x3FFFFFF000ULL), | ||
| 284 | cpu_to_le64(0x0) | ||
| 285 | }, | ||
| 286 | { | ||
| 287 | cpu_to_le64(0xFFFE000000ULL), | ||
| 288 | cpu_to_le64(0xFFFFFF8000ULL), | ||
| 289 | cpu_to_le64(0x0) | ||
| 290 | }, | ||
| 291 | { | ||
| 292 | cpu_to_le64(0xFFF8000000ULL), | ||
| 293 | cpu_to_le64(0xFFFFFE0000ULL), | ||
| 294 | cpu_to_le64(0x0) | ||
| 295 | }, | ||
| 296 | { | ||
| 297 | cpu_to_le64(0xFE00000000ULL), | ||
| 298 | cpu_to_le64(0x0ULL), | ||
| 299 | cpu_to_le64(0x0) | ||
| 300 | }, | ||
| 219 | }; | 301 | }; |
| 220 | 302 | ||
| 303 | static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = { | ||
| 304 | cpu_to_le32(0x22002200), | ||
| 305 | cpu_to_le32(0x33113311), | ||
| 306 | }; | ||
| 307 | |||
| 308 | static enum iwl_bt_coex_lut_type | ||
| 309 | iwl_get_coex_type(struct iwl_mvm *mvm, const struct ieee80211_vif *vif) | ||
| 310 | { | ||
| 311 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
| 312 | enum iwl_bt_coex_lut_type ret; | ||
| 313 | u16 phy_ctx_id; | ||
| 314 | |||
| 315 | /* | ||
| 316 | * Checking that we hold mvm->mutex is a good idea, but the rate | ||
| 317 | * control can't acquire the mutex since it runs in Tx path. | ||
| 318 | * So this is racy in that case, but in the worst case, the AMPDU | ||
| 319 | * size limit will be wrong for a short time which is not a big | ||
| 320 | * issue. | ||
| 321 | */ | ||
| 322 | |||
| 323 | rcu_read_lock(); | ||
| 324 | |||
| 325 | chanctx_conf = rcu_dereference(vif->chanctx_conf); | ||
| 326 | |||
| 327 | if (!chanctx_conf || | ||
| 328 | chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ) { | ||
| 329 | rcu_read_unlock(); | ||
| 330 | return BT_COEX_LOOSE_LUT; | ||
| 331 | } | ||
| 332 | |||
| 333 | ret = BT_COEX_TX_DIS_LUT; | ||
| 334 | |||
| 335 | if (mvm->cfg->bt_shared_single_ant) { | ||
| 336 | rcu_read_unlock(); | ||
| 337 | return ret; | ||
| 338 | } | ||
| 339 | |||
| 340 | phy_ctx_id = *((u16 *)chanctx_conf->drv_priv); | ||
| 341 | |||
| 342 | if (mvm->last_bt_ci_cmd.primary_ch_phy_id == phy_ctx_id) | ||
| 343 | ret = le32_to_cpu(mvm->last_bt_notif.primary_ch_lut); | ||
| 344 | else if (mvm->last_bt_ci_cmd.secondary_ch_phy_id == phy_ctx_id) | ||
| 345 | ret = le32_to_cpu(mvm->last_bt_notif.secondary_ch_lut); | ||
| 346 | /* else - default = TX TX disallowed */ | ||
| 347 | |||
| 348 | rcu_read_unlock(); | ||
| 349 | |||
| 350 | return ret; | ||
| 351 | } | ||
| 352 | |||
| 221 | int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | 353 | int iwl_send_bt_init_conf(struct iwl_mvm *mvm) |
| 222 | { | 354 | { |
| 223 | struct iwl_bt_coex_cmd *bt_cmd; | 355 | struct iwl_bt_coex_cmd *bt_cmd; |
| @@ -228,17 +360,10 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | |||
| 228 | .flags = CMD_SYNC, | 360 | .flags = CMD_SYNC, |
| 229 | }; | 361 | }; |
| 230 | int ret; | 362 | int ret; |
| 363 | u32 flags; | ||
| 231 | 364 | ||
| 232 | /* go to CALIB state in internal BT-Coex state machine */ | 365 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWBT_COEX)) |
| 233 | ret = iwl_send_bt_env(mvm, BT_COEX_ENV_OPEN, | 366 | return 0; |
| 234 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); | ||
| 235 | if (ret) | ||
| 236 | return ret; | ||
| 237 | |||
| 238 | ret = iwl_send_bt_env(mvm, BT_COEX_ENV_CLOSE, | ||
| 239 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); | ||
| 240 | if (ret) | ||
| 241 | return ret; | ||
| 242 | 367 | ||
| 243 | bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL); | 368 | bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL); |
| 244 | if (!bt_cmd) | 369 | if (!bt_cmd) |
| @@ -246,40 +371,52 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | |||
| 246 | cmd.data[0] = bt_cmd; | 371 | cmd.data[0] = bt_cmd; |
| 247 | 372 | ||
| 248 | bt_cmd->max_kill = 5; | 373 | bt_cmd->max_kill = 5; |
| 249 | bt_cmd->bt3_time_t7_value = 1; | 374 | bt_cmd->bt4_antenna_isolation_thr = BT_ANTENNA_COUPLING_THRESHOLD, |
| 250 | bt_cmd->bt3_prio_sample_time = 2; | 375 | bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling, |
| 251 | bt_cmd->bt3_timer_t2_value = 0xc; | 376 | bt_cmd->bt4_tx_tx_delta_freq_thr = 15, |
| 377 | bt_cmd->bt4_tx_rx_max_freq0 = 15, | ||
| 252 | 378 | ||
| 253 | bt_cmd->flags = iwlwifi_mod_params.bt_coex_active ? | 379 | flags = iwlwifi_mod_params.bt_coex_active ? |
| 254 | BT_COEX_NW : BT_COEX_DISABLE; | 380 | BT_COEX_NW : BT_COEX_DISABLE; |
| 255 | bt_cmd->flags |= BT_CH_PRIMARY_EN | BT_SYNC_2_BT_DISABLE; | 381 | flags |= BT_CH_PRIMARY_EN | BT_CH_SECONDARY_EN | BT_SYNC_2_BT_DISABLE; |
| 382 | bt_cmd->flags = cpu_to_le32(flags); | ||
| 256 | 383 | ||
| 257 | bt_cmd->valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE | | 384 | bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_ENABLE | |
| 258 | BT_VALID_BT_PRIO_BOOST | | 385 | BT_VALID_BT_PRIO_BOOST | |
| 259 | BT_VALID_MAX_KILL | | 386 | BT_VALID_MAX_KILL | |
| 260 | BT_VALID_3W_TMRS | | 387 | BT_VALID_3W_TMRS | |
| 261 | BT_VALID_KILL_ACK | | 388 | BT_VALID_KILL_ACK | |
| 262 | BT_VALID_KILL_CTS | | 389 | BT_VALID_KILL_CTS | |
| 263 | BT_VALID_REDUCED_TX_POWER | | 390 | BT_VALID_REDUCED_TX_POWER | |
| 264 | BT_VALID_LUT); | 391 | BT_VALID_LUT | |
| 392 | BT_VALID_WIFI_RX_SW_PRIO_BOOST | | ||
| 393 | BT_VALID_WIFI_TX_SW_PRIO_BOOST | | ||
| 394 | BT_VALID_MULTI_PRIO_LUT | | ||
| 395 | BT_VALID_CORUN_LUT_20 | | ||
| 396 | BT_VALID_CORUN_LUT_40 | | ||
| 397 | BT_VALID_ANT_ISOLATION | | ||
| 398 | BT_VALID_ANT_ISOLATION_THRS | | ||
| 399 | BT_VALID_TXTX_DELTA_FREQ_THRS | | ||
| 400 | BT_VALID_TXRX_MAX_FREQ_0); | ||
| 265 | 401 | ||
| 266 | if (mvm->cfg->bt_shared_single_ant) | 402 | if (mvm->cfg->bt_shared_single_ant) |
| 267 | memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant_lookup, | 403 | memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant, |
| 268 | sizeof(iwl_single_shared_ant_lookup)); | 404 | sizeof(iwl_single_shared_ant)); |
| 269 | else if (is_loose_coex()) | ||
| 270 | memcpy(&bt_cmd->decision_lut, iwl_loose_lookup, | ||
| 271 | sizeof(iwl_tight_lookup)); | ||
| 272 | else | 405 | else |
| 273 | memcpy(&bt_cmd->decision_lut, iwl_tight_lookup, | 406 | memcpy(&bt_cmd->decision_lut, iwl_combined_lookup, |
| 274 | sizeof(iwl_tight_lookup)); | 407 | sizeof(iwl_combined_lookup)); |
| 275 | 408 | ||
| 276 | bt_cmd->bt_prio_boost = cpu_to_le32(IWL_BT_DEFAULT_BOOST); | 409 | memcpy(&bt_cmd->bt_prio_boost, iwl_bt_prio_boost, |
| 410 | sizeof(iwl_bt_prio_boost)); | ||
| 411 | memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut, | ||
| 412 | sizeof(iwl_bt_mprio_lut)); | ||
| 277 | bt_cmd->kill_ack_msk = | 413 | bt_cmd->kill_ack_msk = |
| 278 | cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]); | 414 | cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]); |
| 279 | bt_cmd->kill_cts_msk = | 415 | bt_cmd->kill_cts_msk = |
| 280 | cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]); | 416 | cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]); |
| 281 | 417 | ||
| 282 | memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); | 418 | memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); |
| 419 | memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd)); | ||
| 283 | 420 | ||
| 284 | ret = iwl_mvm_send_cmd(mvm, &cmd); | 421 | ret = iwl_mvm_send_cmd(mvm, &cmd); |
| 285 | 422 | ||
| @@ -334,13 +471,17 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm, | |||
| 334 | if (!bt_cmd) | 471 | if (!bt_cmd) |
| 335 | return -ENOMEM; | 472 | return -ENOMEM; |
| 336 | cmd.data[0] = bt_cmd; | 473 | cmd.data[0] = bt_cmd; |
| 474 | bt_cmd->flags = cpu_to_le32(BT_COEX_NW); | ||
| 337 | 475 | ||
| 338 | bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]); | 476 | bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]); |
| 339 | bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]); | 477 | bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]); |
| 340 | bt_cmd->valid_bit_msk = | 478 | bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE | |
| 341 | cpu_to_le16(BT_VALID_KILL_ACK | BT_VALID_KILL_CTS); | 479 | BT_VALID_KILL_ACK | |
| 480 | BT_VALID_KILL_CTS); | ||
| 342 | 481 | ||
| 343 | IWL_DEBUG_COEX(mvm, "bt_kill_msk = %d\n", bt_kill_msk); | 482 | IWL_DEBUG_COEX(mvm, "ACK Kill msk = 0x%08x, CTS Kill msk = 0x%08x\n", |
| 483 | iwl_bt_ack_kill_msk[bt_kill_msk], | ||
| 484 | iwl_bt_cts_kill_msk[bt_kill_msk]); | ||
| 344 | 485 | ||
| 345 | ret = iwl_mvm_send_cmd(mvm, &cmd); | 486 | ret = iwl_mvm_send_cmd(mvm, &cmd); |
| 346 | 487 | ||
| @@ -364,12 +505,16 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, | |||
| 364 | struct iwl_mvm_sta *mvmsta; | 505 | struct iwl_mvm_sta *mvmsta; |
| 365 | int ret; | 506 | int ret; |
| 366 | 507 | ||
| 367 | /* This can happen if the station has been removed right now */ | ||
| 368 | if (sta_id == IWL_MVM_STATION_COUNT) | 508 | if (sta_id == IWL_MVM_STATION_COUNT) |
| 369 | return 0; | 509 | return 0; |
| 370 | 510 | ||
| 371 | sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id], | 511 | sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id], |
| 372 | lockdep_is_held(&mvm->mutex)); | 512 | lockdep_is_held(&mvm->mutex)); |
| 513 | |||
| 514 | /* This can happen if the station has been removed right now */ | ||
| 515 | if (IS_ERR_OR_NULL(sta)) | ||
| 516 | return 0; | ||
| 517 | |||
| 373 | mvmsta = (void *)sta->drv_priv; | 518 | mvmsta = (void *)sta->drv_priv; |
| 374 | 519 | ||
| 375 | /* nothing to do */ | 520 | /* nothing to do */ |
| @@ -380,8 +525,10 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, | |||
| 380 | if (!bt_cmd) | 525 | if (!bt_cmd) |
| 381 | return -ENOMEM; | 526 | return -ENOMEM; |
| 382 | cmd.data[0] = bt_cmd; | 527 | cmd.data[0] = bt_cmd; |
| 528 | bt_cmd->flags = cpu_to_le32(BT_COEX_NW); | ||
| 383 | 529 | ||
| 384 | bt_cmd->valid_bit_msk = cpu_to_le16(BT_VALID_REDUCED_TX_POWER), | 530 | bt_cmd->valid_bit_msk = |
| 531 | cpu_to_le32(BT_VALID_ENABLE | BT_VALID_REDUCED_TX_POWER); | ||
| 385 | bt_cmd->bt_reduced_tx_power = sta_id; | 532 | bt_cmd->bt_reduced_tx_power = sta_id; |
| 386 | 533 | ||
| 387 | if (enable) | 534 | if (enable) |
| @@ -403,8 +550,25 @@ struct iwl_bt_iterator_data { | |||
| 403 | struct iwl_mvm *mvm; | 550 | struct iwl_mvm *mvm; |
| 404 | u32 num_bss_ifaces; | 551 | u32 num_bss_ifaces; |
| 405 | bool reduced_tx_power; | 552 | bool reduced_tx_power; |
| 553 | struct ieee80211_chanctx_conf *primary; | ||
| 554 | struct ieee80211_chanctx_conf *secondary; | ||
| 406 | }; | 555 | }; |
| 407 | 556 | ||
| 557 | static inline | ||
| 558 | void iwl_mvm_bt_coex_enable_rssi_event(struct iwl_mvm *mvm, | ||
| 559 | struct ieee80211_vif *vif, | ||
| 560 | bool enable, int rssi) | ||
| 561 | { | ||
| 562 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 563 | |||
| 564 | mvmvif->bf_data.last_bt_coex_event = rssi; | ||
| 565 | mvmvif->bf_data.bt_coex_max_thold = | ||
| 566 | enable ? BT_ENABLE_REDUCED_TXPOWER_THRESHOLD : 0; | ||
| 567 | mvmvif->bf_data.bt_coex_min_thold = | ||
| 568 | enable ? BT_DISABLE_REDUCED_TXPOWER_THRESHOLD : 0; | ||
| 569 | } | ||
| 570 | |||
| 571 | /* must be called under rcu_read_lock */ | ||
| 408 | static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | 572 | static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, |
| 409 | struct ieee80211_vif *vif) | 573 | struct ieee80211_vif *vif) |
| 410 | { | 574 | { |
| @@ -413,65 +577,94 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
| 413 | struct iwl_mvm *mvm = data->mvm; | 577 | struct iwl_mvm *mvm = data->mvm; |
| 414 | struct ieee80211_chanctx_conf *chanctx_conf; | 578 | struct ieee80211_chanctx_conf *chanctx_conf; |
| 415 | enum ieee80211_smps_mode smps_mode; | 579 | enum ieee80211_smps_mode smps_mode; |
| 416 | enum ieee80211_band band; | ||
| 417 | int ave_rssi; | 580 | int ave_rssi; |
| 418 | 581 | ||
| 419 | lockdep_assert_held(&mvm->mutex); | 582 | lockdep_assert_held(&mvm->mutex); |
| 420 | if (vif->type != NL80211_IFTYPE_STATION) | ||
| 421 | return; | ||
| 422 | 583 | ||
| 423 | rcu_read_lock(); | 584 | if (vif->type != NL80211_IFTYPE_STATION && |
| 424 | chanctx_conf = rcu_dereference(vif->chanctx_conf); | 585 | vif->type != NL80211_IFTYPE_AP) |
| 425 | if (chanctx_conf && chanctx_conf->def.chan) | 586 | return; |
| 426 | band = chanctx_conf->def.chan->band; | ||
| 427 | else | ||
| 428 | band = -1; | ||
| 429 | rcu_read_unlock(); | ||
| 430 | 587 | ||
| 431 | smps_mode = IEEE80211_SMPS_AUTOMATIC; | 588 | smps_mode = IEEE80211_SMPS_AUTOMATIC; |
| 432 | 589 | ||
| 433 | /* non associated BSSes aren't to be considered */ | 590 | chanctx_conf = rcu_dereference(vif->chanctx_conf); |
| 434 | if (!vif->bss_conf.assoc) | 591 | |
| 592 | /* If channel context is invalid or not on 2.4GHz .. */ | ||
| 593 | if ((!chanctx_conf || | ||
| 594 | chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) { | ||
| 595 | /* ... and it is an associated STATION, relax constraints */ | ||
| 596 | if (vif->type == NL80211_IFTYPE_STATION && vif->bss_conf.assoc) | ||
| 597 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, | ||
| 598 | smps_mode); | ||
| 599 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); | ||
| 435 | return; | 600 | return; |
| 601 | } | ||
| 602 | |||
| 603 | /* SoftAP / GO will always be primary */ | ||
| 604 | if (vif->type == NL80211_IFTYPE_AP) { | ||
| 605 | if (!mvmvif->ap_ibss_active) | ||
| 606 | return; | ||
| 436 | 607 | ||
| 437 | if (band != IEEE80211_BAND_2GHZ) { | 608 | /* the Ack / Cts kill mask must be default if AP / GO */ |
| 438 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, | 609 | data->reduced_tx_power = false; |
| 439 | smps_mode); | 610 | |
| 611 | if (chanctx_conf == data->primary) | ||
| 612 | return; | ||
| 613 | |||
| 614 | /* downgrade the current primary no matter what its type is */ | ||
| 615 | data->secondary = data->primary; | ||
| 616 | data->primary = chanctx_conf; | ||
| 440 | return; | 617 | return; |
| 441 | } | 618 | } |
| 442 | 619 | ||
| 443 | if (data->notif->bt_status) | 620 | data->num_bss_ifaces++; |
| 444 | smps_mode = IEEE80211_SMPS_DYNAMIC; | 621 | |
| 622 | /* we are now a STA / P2P Client, and take associated ones only */ | ||
| 623 | if (!vif->bss_conf.assoc) | ||
| 624 | return; | ||
| 625 | |||
| 626 | /* STA / P2P Client, try to be primary if first vif */ | ||
| 627 | if (!data->primary || data->primary == chanctx_conf) | ||
| 628 | data->primary = chanctx_conf; | ||
| 629 | else if (!data->secondary) | ||
| 630 | /* if secondary is not NULL, it might be a GO */ | ||
| 631 | data->secondary = chanctx_conf; | ||
| 445 | 632 | ||
| 446 | if (data->notif->bt_traffic_load >= IWL_BT_LOAD_FORCE_SISO_THRESHOLD) | 633 | if (le32_to_cpu(data->notif->bt_activity_grading) >= BT_HIGH_TRAFFIC) |
| 447 | smps_mode = IEEE80211_SMPS_STATIC; | 634 | smps_mode = IEEE80211_SMPS_STATIC; |
| 635 | else if (le32_to_cpu(data->notif->bt_activity_grading) >= | ||
| 636 | BT_LOW_TRAFFIC) | ||
| 637 | smps_mode = IEEE80211_SMPS_DYNAMIC; | ||
| 448 | 638 | ||
| 449 | IWL_DEBUG_COEX(data->mvm, | 639 | IWL_DEBUG_COEX(data->mvm, |
| 450 | "mac %d: bt_status %d traffic_load %d smps_req %d\n", | 640 | "mac %d: bt_status %d bt_activity_grading %d smps_req %d\n", |
| 451 | mvmvif->id, data->notif->bt_status, | 641 | mvmvif->id, data->notif->bt_status, |
| 452 | data->notif->bt_traffic_load, smps_mode); | 642 | data->notif->bt_activity_grading, smps_mode); |
| 453 | 643 | ||
| 454 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode); | 644 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode); |
| 455 | 645 | ||
| 456 | /* don't reduce the Tx power if in loose scheme */ | 646 | /* don't reduce the Tx power if in loose scheme */ |
| 457 | if (is_loose_coex()) | 647 | if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT || |
| 648 | mvm->cfg->bt_shared_single_ant) { | ||
| 649 | data->reduced_tx_power = false; | ||
| 650 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); | ||
| 458 | return; | 651 | return; |
| 652 | } | ||
| 459 | 653 | ||
| 460 | data->num_bss_ifaces++; | 654 | /* reduced Txpower only if BT is on, so ...*/ |
| 461 | 655 | if (!data->notif->bt_status) { | |
| 462 | /* reduced Txpower only if there are open BT connections, so ...*/ | ||
| 463 | if (!BT_MBOX_MSG(data->notif, 3, OPEN_CON_2)) { | ||
| 464 | /* ... cancel reduced Tx power ... */ | 656 | /* ... cancel reduced Tx power ... */ |
| 465 | if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false)) | 657 | if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false)) |
| 466 | IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); | 658 | IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); |
| 467 | data->reduced_tx_power = false; | 659 | data->reduced_tx_power = false; |
| 468 | 660 | ||
| 469 | /* ... and there is no need to get reports on RSSI any more. */ | 661 | /* ... and there is no need to get reports on RSSI any more. */ |
| 470 | ieee80211_disable_rssi_reports(vif); | 662 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); |
| 471 | return; | 663 | return; |
| 472 | } | 664 | } |
| 473 | 665 | ||
| 474 | ave_rssi = ieee80211_ave_rssi(vif); | 666 | /* try to get the avg rssi from fw */ |
| 667 | ave_rssi = mvmvif->bf_data.ave_beacon_signal; | ||
| 475 | 668 | ||
| 476 | /* if the RSSI isn't valid, fake it is very low */ | 669 | /* if the RSSI isn't valid, fake it is very low */ |
| 477 | if (!ave_rssi) | 670 | if (!ave_rssi) |
| @@ -499,8 +692,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
| 499 | } | 692 | } |
| 500 | 693 | ||
| 501 | /* Begin to monitor the RSSI: it may influence the reduced Tx power */ | 694 | /* Begin to monitor the RSSI: it may influence the reduced Tx power */ |
| 502 | ieee80211_enable_rssi_reports(vif, BT_DISABLE_REDUCED_TXPOWER_THRESHOLD, | 695 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, true, ave_rssi); |
| 503 | BT_ENABLE_REDUCED_TXPOWER_THRESHOLD); | ||
| 504 | } | 696 | } |
| 505 | 697 | ||
| 506 | static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm) | 698 | static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm) |
| @@ -510,11 +702,72 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm) | |||
| 510 | .notif = &mvm->last_bt_notif, | 702 | .notif = &mvm->last_bt_notif, |
| 511 | .reduced_tx_power = true, | 703 | .reduced_tx_power = true, |
| 512 | }; | 704 | }; |
| 705 | struct iwl_bt_coex_ci_cmd cmd = {}; | ||
| 706 | u8 ci_bw_idx; | ||
| 513 | 707 | ||
| 708 | rcu_read_lock(); | ||
| 514 | ieee80211_iterate_active_interfaces_atomic( | 709 | ieee80211_iterate_active_interfaces_atomic( |
| 515 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | 710 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, |
| 516 | iwl_mvm_bt_notif_iterator, &data); | 711 | iwl_mvm_bt_notif_iterator, &data); |
| 517 | 712 | ||
| 713 | if (data.primary) { | ||
| 714 | struct ieee80211_chanctx_conf *chan = data.primary; | ||
| 715 | if (WARN_ON(!chan->def.chan)) { | ||
| 716 | rcu_read_unlock(); | ||
| 717 | return; | ||
| 718 | } | ||
| 719 | |||
| 720 | if (chan->def.width < NL80211_CHAN_WIDTH_40) { | ||
| 721 | ci_bw_idx = 0; | ||
| 722 | cmd.co_run_bw_primary = 0; | ||
| 723 | } else { | ||
| 724 | cmd.co_run_bw_primary = 1; | ||
| 725 | if (chan->def.center_freq1 > | ||
| 726 | chan->def.chan->center_freq) | ||
| 727 | ci_bw_idx = 2; | ||
| 728 | else | ||
| 729 | ci_bw_idx = 1; | ||
| 730 | } | ||
| 731 | |||
| 732 | cmd.bt_primary_ci = | ||
| 733 | iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx]; | ||
| 734 | cmd.primary_ch_phy_id = *((u16 *)data.primary->drv_priv); | ||
| 735 | } | ||
| 736 | |||
| 737 | if (data.secondary) { | ||
| 738 | struct ieee80211_chanctx_conf *chan = data.secondary; | ||
| 739 | if (WARN_ON(!data.secondary->def.chan)) { | ||
| 740 | rcu_read_unlock(); | ||
| 741 | return; | ||
| 742 | } | ||
| 743 | |||
| 744 | if (chan->def.width < NL80211_CHAN_WIDTH_40) { | ||
| 745 | ci_bw_idx = 0; | ||
| 746 | cmd.co_run_bw_secondary = 0; | ||
| 747 | } else { | ||
| 748 | cmd.co_run_bw_secondary = 1; | ||
| 749 | if (chan->def.center_freq1 > | ||
| 750 | chan->def.chan->center_freq) | ||
| 751 | ci_bw_idx = 2; | ||
| 752 | else | ||
| 753 | ci_bw_idx = 1; | ||
| 754 | } | ||
| 755 | |||
| 756 | cmd.bt_secondary_ci = | ||
| 757 | iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx]; | ||
| 758 | cmd.secondary_ch_phy_id = *((u16 *)data.secondary->drv_priv); | ||
| 759 | } | ||
| 760 | |||
| 761 | rcu_read_unlock(); | ||
| 762 | |||
| 763 | /* Don't spam the fw with the same command over and over */ | ||
| 764 | if (memcmp(&cmd, &mvm->last_bt_ci_cmd, sizeof(cmd))) { | ||
| 765 | if (iwl_mvm_send_cmd_pdu(mvm, BT_COEX_CI, CMD_SYNC, | ||
| 766 | sizeof(cmd), &cmd)) | ||
| 767 | IWL_ERR(mvm, "Failed to send BT_CI cmd"); | ||
| 768 | memcpy(&mvm->last_bt_ci_cmd, &cmd, sizeof(cmd)); | ||
| 769 | } | ||
| 770 | |||
| 518 | /* | 771 | /* |
| 519 | * If there are no BSS / P2P client interfaces, reduced Tx Power is | 772 | * If there are no BSS / P2P client interfaces, reduced Tx Power is |
| 520 | * irrelevant since it is based on the RSSI coming from the beacon. | 773 | * irrelevant since it is based on the RSSI coming from the beacon. |
| @@ -536,12 +789,18 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, | |||
| 536 | 789 | ||
| 537 | 790 | ||
| 538 | IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n"); | 791 | IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n"); |
| 539 | IWL_DEBUG_COEX(mvm, "\tBT %salive\n", notif->bt_status ? "" : "not "); | 792 | IWL_DEBUG_COEX(mvm, "\tBT status: %s\n", |
| 793 | notif->bt_status ? "ON" : "OFF"); | ||
| 540 | IWL_DEBUG_COEX(mvm, "\tBT open conn %d\n", notif->bt_open_conn); | 794 | IWL_DEBUG_COEX(mvm, "\tBT open conn %d\n", notif->bt_open_conn); |
| 541 | IWL_DEBUG_COEX(mvm, "\tBT traffic load %d\n", notif->bt_traffic_load); | 795 | IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance); |
| 796 | IWL_DEBUG_COEX(mvm, "\tBT primary_ch_lut %d\n", | ||
| 797 | le32_to_cpu(notif->primary_ch_lut)); | ||
| 798 | IWL_DEBUG_COEX(mvm, "\tBT secondary_ch_lut %d\n", | ||
| 799 | le32_to_cpu(notif->secondary_ch_lut)); | ||
| 800 | IWL_DEBUG_COEX(mvm, "\tBT activity grading %d\n", | ||
| 801 | le32_to_cpu(notif->bt_activity_grading)); | ||
| 542 | IWL_DEBUG_COEX(mvm, "\tBT agg traffic load %d\n", | 802 | IWL_DEBUG_COEX(mvm, "\tBT agg traffic load %d\n", |
| 543 | notif->bt_agg_traffic_load); | 803 | notif->bt_agg_traffic_load); |
| 544 | IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance); | ||
| 545 | 804 | ||
| 546 | /* remember this notification for future use: rssi fluctuations */ | 805 | /* remember this notification for future use: rssi fluctuations */ |
| 547 | memcpy(&mvm->last_bt_notif, notif, sizeof(mvm->last_bt_notif)); | 806 | memcpy(&mvm->last_bt_notif, notif, sizeof(mvm->last_bt_notif)); |
| @@ -565,6 +824,18 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac, | |||
| 565 | struct ieee80211_sta *sta; | 824 | struct ieee80211_sta *sta; |
| 566 | struct iwl_mvm_sta *mvmsta; | 825 | struct iwl_mvm_sta *mvmsta; |
| 567 | 826 | ||
| 827 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
| 828 | |||
| 829 | rcu_read_lock(); | ||
| 830 | chanctx_conf = rcu_dereference(vif->chanctx_conf); | ||
| 831 | /* If channel context is invalid or not on 2.4GHz - don't count it */ | ||
| 832 | if (!chanctx_conf || | ||
| 833 | chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ) { | ||
| 834 | rcu_read_unlock(); | ||
| 835 | return; | ||
| 836 | } | ||
| 837 | rcu_read_unlock(); | ||
| 838 | |||
| 568 | if (vif->type != NL80211_IFTYPE_STATION || | 839 | if (vif->type != NL80211_IFTYPE_STATION || |
| 569 | mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT) | 840 | mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT) |
| 570 | return; | 841 | return; |
| @@ -594,15 +865,15 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 594 | }; | 865 | }; |
| 595 | int ret; | 866 | int ret; |
| 596 | 867 | ||
| 597 | mutex_lock(&mvm->mutex); | 868 | lockdep_assert_held(&mvm->mutex); |
| 598 | 869 | ||
| 599 | /* Rssi update while not associated ?! */ | 870 | /* Rssi update while not associated ?! */ |
| 600 | if (WARN_ON_ONCE(mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)) | 871 | if (WARN_ON_ONCE(mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)) |
| 601 | goto out_unlock; | 872 | return; |
| 602 | 873 | ||
| 603 | /* No open connection - reports should be disabled */ | 874 | /* No BT - reports should be disabled */ |
| 604 | if (!BT_MBOX_MSG(&mvm->last_bt_notif, 3, OPEN_CON_2)) | 875 | if (!mvm->last_bt_notif.bt_status) |
| 605 | goto out_unlock; | 876 | return; |
| 606 | 877 | ||
| 607 | IWL_DEBUG_COEX(mvm, "RSSI for %pM is now %s\n", vif->bss_conf.bssid, | 878 | IWL_DEBUG_COEX(mvm, "RSSI for %pM is now %s\n", vif->bss_conf.bssid, |
| 608 | rssi_event == RSSI_EVENT_HIGH ? "HIGH" : "LOW"); | 879 | rssi_event == RSSI_EVENT_HIGH ? "HIGH" : "LOW"); |
| @@ -611,7 +882,8 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 611 | * Check if rssi is good enough for reduced Tx power, but not in loose | 882 | * Check if rssi is good enough for reduced Tx power, but not in loose |
| 612 | * scheme. | 883 | * scheme. |
| 613 | */ | 884 | */ |
| 614 | if (rssi_event == RSSI_EVENT_LOW || is_loose_coex()) | 885 | if (rssi_event == RSSI_EVENT_LOW || mvm->cfg->bt_shared_single_ant || |
| 886 | iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT) | ||
| 615 | ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, | 887 | ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, |
| 616 | false); | 888 | false); |
| 617 | else | 889 | else |
| @@ -633,12 +905,52 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 633 | 905 | ||
| 634 | if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power)) | 906 | if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power)) |
| 635 | IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); | 907 | IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); |
| 908 | } | ||
| 636 | 909 | ||
| 637 | out_unlock: | 910 | #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) |
| 638 | mutex_unlock(&mvm->mutex); | 911 | #define LINK_QUAL_AGG_TIME_LIMIT_BT_ACT (1200) |
| 912 | |||
| 913 | u16 iwl_mvm_bt_coex_agg_time_limit(struct iwl_mvm *mvm, | ||
| 914 | struct ieee80211_sta *sta) | ||
| 915 | { | ||
| 916 | struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; | ||
| 917 | enum iwl_bt_coex_lut_type lut_type; | ||
| 918 | |||
| 919 | if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) < | ||
| 920 | BT_LOW_TRAFFIC) | ||
| 921 | return LINK_QUAL_AGG_TIME_LIMIT_DEF; | ||
| 922 | |||
| 923 | lut_type = iwl_get_coex_type(mvm, mvmsta->vif); | ||
| 924 | |||
| 925 | if (lut_type == BT_COEX_LOOSE_LUT) | ||
| 926 | return LINK_QUAL_AGG_TIME_LIMIT_DEF; | ||
| 927 | |||
| 928 | /* tight coex, high bt traffic, reduce AGG time limit */ | ||
| 929 | return LINK_QUAL_AGG_TIME_LIMIT_BT_ACT; | ||
| 639 | } | 930 | } |
| 640 | 931 | ||
| 641 | void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | 932 | bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm, |
| 933 | struct ieee80211_sta *sta) | ||
| 642 | { | 934 | { |
| 935 | struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; | ||
| 936 | |||
| 937 | if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) < | ||
| 938 | BT_HIGH_TRAFFIC) | ||
| 939 | return true; | ||
| 940 | |||
| 941 | /* | ||
| 942 | * In Tight, BT can't Rx while we Tx, so use both antennas since BT is | ||
| 943 | * already killed. | ||
| 944 | * In Loose, BT can Rx while we Tx, so forbid MIMO to let BT Rx while we | ||
| 945 | * Tx. | ||
| 946 | */ | ||
| 947 | return iwl_get_coex_type(mvm, mvmsta->vif) == BT_COEX_TIGHT_LUT; | ||
| 948 | } | ||
| 949 | |||
| 950 | void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm) | ||
| 951 | { | ||
| 952 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWBT_COEX)) | ||
| 953 | return; | ||
| 954 | |||
| 643 | iwl_mvm_bt_coex_notif_handle(mvm); | 955 | iwl_mvm_bt_coex_notif_handle(mvm); |
| 644 | } | 956 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h index 2bf29f7992ee..4b6d670c3509 100644 --- a/drivers/net/wireless/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/iwlwifi/mvm/constants.h | |||
| @@ -70,7 +70,9 @@ | |||
| 70 | #define IWL_MVM_UAPSD_RX_DATA_TIMEOUT (50 * USEC_PER_MSEC) | 70 | #define IWL_MVM_UAPSD_RX_DATA_TIMEOUT (50 * USEC_PER_MSEC) |
| 71 | #define IWL_MVM_UAPSD_TX_DATA_TIMEOUT (50 * USEC_PER_MSEC) | 71 | #define IWL_MVM_UAPSD_TX_DATA_TIMEOUT (50 * USEC_PER_MSEC) |
| 72 | #define IWL_MVM_PS_HEAVY_TX_THLD_PACKETS 20 | 72 | #define IWL_MVM_PS_HEAVY_TX_THLD_PACKETS 20 |
| 73 | #define IWL_MVM_PS_HEAVY_RX_THLD_PACKETS 20 | 73 | #define IWL_MVM_PS_HEAVY_RX_THLD_PACKETS 8 |
| 74 | #define IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS 30 | ||
| 75 | #define IWL_MVM_PS_SNOOZE_HEAVY_RX_THLD_PACKETS 20 | ||
| 74 | #define IWL_MVM_PS_HEAVY_TX_THLD_PERCENT 50 | 76 | #define IWL_MVM_PS_HEAVY_TX_THLD_PERCENT 50 |
| 75 | #define IWL_MVM_PS_HEAVY_RX_THLD_PERCENT 50 | 77 | #define IWL_MVM_PS_HEAVY_RX_THLD_PERCENT 50 |
| 76 | #define IWL_MVM_PS_SNOOZE_INTERVAL 25 | 78 | #define IWL_MVM_PS_SNOOZE_INTERVAL 25 |
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index 417639f77b01..6f45966817bb 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c | |||
| @@ -67,6 +67,7 @@ | |||
| 67 | #include <net/cfg80211.h> | 67 | #include <net/cfg80211.h> |
| 68 | #include <net/ipv6.h> | 68 | #include <net/ipv6.h> |
| 69 | #include <net/tcp.h> | 69 | #include <net/tcp.h> |
| 70 | #include <net/addrconf.h> | ||
| 70 | #include "iwl-modparams.h" | 71 | #include "iwl-modparams.h" |
| 71 | #include "fw-api.h" | 72 | #include "fw-api.h" |
| 72 | #include "mvm.h" | 73 | #include "mvm.h" |
| @@ -381,14 +382,74 @@ static int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm, | |||
| 381 | union { | 382 | union { |
| 382 | struct iwl_proto_offload_cmd_v1 v1; | 383 | struct iwl_proto_offload_cmd_v1 v1; |
| 383 | struct iwl_proto_offload_cmd_v2 v2; | 384 | struct iwl_proto_offload_cmd_v2 v2; |
| 385 | struct iwl_proto_offload_cmd_v3_small v3s; | ||
| 386 | struct iwl_proto_offload_cmd_v3_large v3l; | ||
| 384 | } cmd = {}; | 387 | } cmd = {}; |
| 388 | struct iwl_host_cmd hcmd = { | ||
| 389 | .id = PROT_OFFLOAD_CONFIG_CMD, | ||
| 390 | .flags = CMD_SYNC, | ||
| 391 | .data[0] = &cmd, | ||
| 392 | .dataflags[0] = IWL_HCMD_DFL_DUP, | ||
| 393 | }; | ||
| 385 | struct iwl_proto_offload_cmd_common *common; | 394 | struct iwl_proto_offload_cmd_common *common; |
| 386 | u32 enabled = 0, size; | 395 | u32 enabled = 0, size; |
| 396 | u32 capa_flags = mvm->fw->ucode_capa.flags; | ||
| 387 | #if IS_ENABLED(CONFIG_IPV6) | 397 | #if IS_ENABLED(CONFIG_IPV6) |
| 388 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 398 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
| 389 | int i; | 399 | int i; |
| 390 | 400 | ||
| 391 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS) { | 401 | if (capa_flags & IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL || |
| 402 | capa_flags & IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE) { | ||
| 403 | struct iwl_ns_config *nsc; | ||
| 404 | struct iwl_targ_addr *addrs; | ||
| 405 | int n_nsc, n_addrs; | ||
| 406 | int c; | ||
| 407 | |||
| 408 | if (capa_flags & IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL) { | ||
| 409 | nsc = cmd.v3s.ns_config; | ||
| 410 | n_nsc = IWL_PROTO_OFFLOAD_NUM_NS_CONFIG_V3S; | ||
| 411 | addrs = cmd.v3s.targ_addrs; | ||
| 412 | n_addrs = IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3S; | ||
| 413 | } else { | ||
| 414 | nsc = cmd.v3l.ns_config; | ||
| 415 | n_nsc = IWL_PROTO_OFFLOAD_NUM_NS_CONFIG_V3L; | ||
| 416 | addrs = cmd.v3l.targ_addrs; | ||
| 417 | n_addrs = IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3L; | ||
| 418 | } | ||
| 419 | |||
| 420 | if (mvmvif->num_target_ipv6_addrs) | ||
| 421 | enabled |= IWL_D3_PROTO_OFFLOAD_NS; | ||
| 422 | |||
| 423 | /* | ||
| 424 | * For each address we have (and that will fit) fill a target | ||
| 425 | * address struct and combine for NS offload structs with the | ||
| 426 | * solicited node addresses. | ||
| 427 | */ | ||
| 428 | for (i = 0, c = 0; | ||
| 429 | i < mvmvif->num_target_ipv6_addrs && | ||
| 430 | i < n_addrs && c < n_nsc; i++) { | ||
| 431 | struct in6_addr solicited_addr; | ||
| 432 | int j; | ||
| 433 | |||
| 434 | addrconf_addr_solict_mult(&mvmvif->target_ipv6_addrs[i], | ||
| 435 | &solicited_addr); | ||
| 436 | for (j = 0; j < c; j++) | ||
| 437 | if (ipv6_addr_cmp(&nsc[j].dest_ipv6_addr, | ||
| 438 | &solicited_addr) == 0) | ||
| 439 | break; | ||
| 440 | if (j == c) | ||
| 441 | c++; | ||
| 442 | addrs[i].addr = mvmvif->target_ipv6_addrs[i]; | ||
| 443 | addrs[i].config_num = cpu_to_le32(j); | ||
| 444 | nsc[j].dest_ipv6_addr = solicited_addr; | ||
| 445 | memcpy(nsc[j].target_mac_addr, vif->addr, ETH_ALEN); | ||
| 446 | } | ||
| 447 | |||
| 448 | if (capa_flags & IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL) | ||
| 449 | cmd.v3s.num_valid_ipv6_addrs = cpu_to_le32(i); | ||
| 450 | else | ||
| 451 | cmd.v3l.num_valid_ipv6_addrs = cpu_to_le32(i); | ||
| 452 | } else if (capa_flags & IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS) { | ||
| 392 | if (mvmvif->num_target_ipv6_addrs) { | 453 | if (mvmvif->num_target_ipv6_addrs) { |
| 393 | enabled |= IWL_D3_PROTO_OFFLOAD_NS; | 454 | enabled |= IWL_D3_PROTO_OFFLOAD_NS; |
| 394 | memcpy(cmd.v2.ndp_mac_addr, vif->addr, ETH_ALEN); | 455 | memcpy(cmd.v2.ndp_mac_addr, vif->addr, ETH_ALEN); |
| @@ -419,7 +480,13 @@ static int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm, | |||
| 419 | } | 480 | } |
| 420 | #endif | 481 | #endif |
| 421 | 482 | ||
| 422 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS) { | 483 | if (capa_flags & IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL) { |
| 484 | common = &cmd.v3s.common; | ||
| 485 | size = sizeof(cmd.v3s); | ||
| 486 | } else if (capa_flags & IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE) { | ||
| 487 | common = &cmd.v3l.common; | ||
| 488 | size = sizeof(cmd.v3l); | ||
| 489 | } else if (capa_flags & IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS) { | ||
| 423 | common = &cmd.v2.common; | 490 | common = &cmd.v2.common; |
| 424 | size = sizeof(cmd.v2); | 491 | size = sizeof(cmd.v2); |
| 425 | } else { | 492 | } else { |
| @@ -438,8 +505,8 @@ static int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm, | |||
| 438 | 505 | ||
| 439 | common->enabled = cpu_to_le32(enabled); | 506 | common->enabled = cpu_to_le32(enabled); |
| 440 | 507 | ||
| 441 | return iwl_mvm_send_cmd_pdu(mvm, PROT_OFFLOAD_CONFIG_CMD, CMD_SYNC, | 508 | hcmd.len[0] = size; |
| 442 | size, &cmd); | 509 | return iwl_mvm_send_cmd(mvm, &hcmd); |
| 443 | } | 510 | } |
| 444 | 511 | ||
| 445 | enum iwl_mvm_tcp_packet_type { | 512 | enum iwl_mvm_tcp_packet_type { |
| @@ -793,6 +860,74 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 793 | return 0; | 860 | return 0; |
| 794 | } | 861 | } |
| 795 | 862 | ||
| 863 | static int iwl_mvm_get_last_nonqos_seq(struct iwl_mvm *mvm, | ||
| 864 | struct ieee80211_vif *vif) | ||
| 865 | { | ||
| 866 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 867 | struct iwl_nonqos_seq_query_cmd query_cmd = { | ||
| 868 | .get_set_flag = cpu_to_le32(IWL_NONQOS_SEQ_GET), | ||
| 869 | .mac_id_n_color = | ||
| 870 | cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, | ||
| 871 | mvmvif->color)), | ||
| 872 | }; | ||
| 873 | struct iwl_host_cmd cmd = { | ||
| 874 | .id = NON_QOS_TX_COUNTER_CMD, | ||
| 875 | .flags = CMD_SYNC | CMD_WANT_SKB, | ||
| 876 | }; | ||
| 877 | int err; | ||
| 878 | u32 size; | ||
| 879 | |||
| 880 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API) { | ||
| 881 | cmd.data[0] = &query_cmd; | ||
| 882 | cmd.len[0] = sizeof(query_cmd); | ||
| 883 | } | ||
| 884 | |||
| 885 | err = iwl_mvm_send_cmd(mvm, &cmd); | ||
| 886 | if (err) | ||
| 887 | return err; | ||
| 888 | |||
| 889 | size = le32_to_cpu(cmd.resp_pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
| 890 | size -= sizeof(cmd.resp_pkt->hdr); | ||
| 891 | if (size < sizeof(__le16)) { | ||
| 892 | err = -EINVAL; | ||
| 893 | } else { | ||
| 894 | err = le16_to_cpup((__le16 *)cmd.resp_pkt->data); | ||
| 895 | /* new API returns next, not last-used seqno */ | ||
| 896 | if (mvm->fw->ucode_capa.flags & | ||
| 897 | IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API) | ||
| 898 | err -= 0x10; | ||
| 899 | } | ||
| 900 | |||
| 901 | iwl_free_resp(&cmd); | ||
| 902 | return err; | ||
| 903 | } | ||
| 904 | |||
| 905 | void iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | ||
| 906 | { | ||
| 907 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 908 | struct iwl_nonqos_seq_query_cmd query_cmd = { | ||
| 909 | .get_set_flag = cpu_to_le32(IWL_NONQOS_SEQ_SET), | ||
| 910 | .mac_id_n_color = | ||
| 911 | cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, | ||
| 912 | mvmvif->color)), | ||
| 913 | .value = cpu_to_le16(mvmvif->seqno), | ||
| 914 | }; | ||
| 915 | |||
| 916 | /* return if called during restart, not resume from D3 */ | ||
| 917 | if (!mvmvif->seqno_valid) | ||
| 918 | return; | ||
| 919 | |||
| 920 | mvmvif->seqno_valid = false; | ||
| 921 | |||
| 922 | if (!(mvm->fw->ucode_capa.flags & | ||
| 923 | IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API)) | ||
| 924 | return; | ||
| 925 | |||
| 926 | if (iwl_mvm_send_cmd_pdu(mvm, NON_QOS_TX_COUNTER_CMD, CMD_SYNC, | ||
| 927 | sizeof(query_cmd), &query_cmd)) | ||
| 928 | IWL_ERR(mvm, "failed to set non-QoS seqno\n"); | ||
| 929 | } | ||
| 930 | |||
| 796 | static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | 931 | static int __iwl_mvm_suspend(struct ieee80211_hw *hw, |
| 797 | struct cfg80211_wowlan *wowlan, | 932 | struct cfg80211_wowlan *wowlan, |
| 798 | bool test) | 933 | bool test) |
| @@ -829,7 +964,6 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
| 829 | }; | 964 | }; |
| 830 | int ret, i; | 965 | int ret, i; |
| 831 | int len __maybe_unused; | 966 | int len __maybe_unused; |
| 832 | u16 seq; | ||
| 833 | u8 old_aux_sta_id, old_ap_sta_id = IWL_MVM_STATION_COUNT; | 967 | u8 old_aux_sta_id, old_ap_sta_id = IWL_MVM_STATION_COUNT; |
| 834 | 968 | ||
| 835 | if (!wowlan) { | 969 | if (!wowlan) { |
| @@ -872,26 +1006,15 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
| 872 | 1006 | ||
| 873 | mvm_ap_sta = (struct iwl_mvm_sta *)ap_sta->drv_priv; | 1007 | mvm_ap_sta = (struct iwl_mvm_sta *)ap_sta->drv_priv; |
| 874 | 1008 | ||
| 875 | /* | ||
| 876 | * The D3 firmware still hardcodes the AP station ID for the | ||
| 877 | * BSS we're associated with as 0. Store the real STA ID here | ||
| 878 | * and assign 0. When we leave this function, we'll restore | ||
| 879 | * the original value for the resume code. | ||
| 880 | */ | ||
| 881 | old_ap_sta_id = mvm_ap_sta->sta_id; | ||
| 882 | mvm_ap_sta->sta_id = 0; | ||
| 883 | mvmvif->ap_sta_id = 0; | ||
| 884 | |||
| 885 | /* TODO: wowlan_config_cmd.wowlan_ba_teardown_tids */ | 1009 | /* TODO: wowlan_config_cmd.wowlan_ba_teardown_tids */ |
| 886 | 1010 | ||
| 887 | wowlan_config_cmd.is_11n_connection = ap_sta->ht_cap.ht_supported; | 1011 | wowlan_config_cmd.is_11n_connection = ap_sta->ht_cap.ht_supported; |
| 888 | 1012 | ||
| 889 | /* | 1013 | /* Query the last used seqno and set it */ |
| 890 | * We know the last used seqno, and the uCode expects to know that | 1014 | ret = iwl_mvm_get_last_nonqos_seq(mvm, vif); |
| 891 | * one, it will increment before TX. | 1015 | if (ret < 0) |
| 892 | */ | 1016 | goto out_noreset; |
| 893 | seq = mvm_ap_sta->last_seq_ctl & IEEE80211_SCTL_SEQ; | 1017 | wowlan_config_cmd.non_qos_seq = cpu_to_le16(ret); |
| 894 | wowlan_config_cmd.non_qos_seq = cpu_to_le16(seq); | ||
| 895 | 1018 | ||
| 896 | /* | 1019 | /* |
| 897 | * For QoS counters, we store the one to use next, so subtract 0x10 | 1020 | * For QoS counters, we store the one to use next, so subtract 0x10 |
| @@ -899,7 +1022,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
| 899 | * increment after using the value (i.e. store the next value to use). | 1022 | * increment after using the value (i.e. store the next value to use). |
| 900 | */ | 1023 | */ |
| 901 | for (i = 0; i < IWL_MAX_TID_COUNT; i++) { | 1024 | for (i = 0; i < IWL_MAX_TID_COUNT; i++) { |
| 902 | seq = mvm_ap_sta->tid_data[i].seq_number; | 1025 | u16 seq = mvm_ap_sta->tid_data[i].seq_number; |
| 903 | seq -= 0x10; | 1026 | seq -= 0x10; |
| 904 | wowlan_config_cmd.qos_seq[i] = cpu_to_le16(seq); | 1027 | wowlan_config_cmd.qos_seq[i] = cpu_to_le16(seq); |
| 905 | } | 1028 | } |
| @@ -945,6 +1068,16 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
| 945 | iwl_trans_stop_device(mvm->trans); | 1068 | iwl_trans_stop_device(mvm->trans); |
| 946 | 1069 | ||
| 947 | /* | 1070 | /* |
| 1071 | * The D3 firmware still hardcodes the AP station ID for the | ||
| 1072 | * BSS we're associated with as 0. Store the real STA ID here | ||
| 1073 | * and assign 0. When we leave this function, we'll restore | ||
| 1074 | * the original value for the resume code. | ||
| 1075 | */ | ||
| 1076 | old_ap_sta_id = mvm_ap_sta->sta_id; | ||
| 1077 | mvm_ap_sta->sta_id = 0; | ||
| 1078 | mvmvif->ap_sta_id = 0; | ||
| 1079 | |||
| 1080 | /* | ||
| 948 | * Set the HW restart bit -- this is mostly true as we're | 1081 | * Set the HW restart bit -- this is mostly true as we're |
| 949 | * going to load new firmware and reprogram that, though | 1082 | * going to load new firmware and reprogram that, though |
| 950 | * the reprogramming is going to be manual to avoid adding | 1083 | * the reprogramming is going to be manual to avoid adding |
| @@ -1059,6 +1192,10 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
| 1059 | if (ret) | 1192 | if (ret) |
| 1060 | goto out; | 1193 | goto out; |
| 1061 | 1194 | ||
| 1195 | ret = iwl_mvm_power_update_device_mode(mvm); | ||
| 1196 | if (ret) | ||
| 1197 | goto out; | ||
| 1198 | |||
| 1062 | ret = iwl_mvm_power_update_mode(mvm, vif); | 1199 | ret = iwl_mvm_power_update_mode(mvm, vif); |
| 1063 | if (ret) | 1200 | if (ret) |
| 1064 | goto out; | 1201 | goto out; |
| @@ -1109,16 +1246,26 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
| 1109 | return __iwl_mvm_suspend(hw, wowlan, false); | 1246 | return __iwl_mvm_suspend(hw, wowlan, false); |
| 1110 | } | 1247 | } |
| 1111 | 1248 | ||
| 1249 | /* converted data from the different status responses */ | ||
| 1250 | struct iwl_wowlan_status_data { | ||
| 1251 | u16 pattern_number; | ||
| 1252 | u16 qos_seq_ctr[8]; | ||
| 1253 | u32 wakeup_reasons; | ||
| 1254 | u32 wake_packet_length; | ||
| 1255 | u32 wake_packet_bufsize; | ||
| 1256 | const u8 *wake_packet; | ||
| 1257 | }; | ||
| 1258 | |||
| 1112 | static void iwl_mvm_report_wakeup_reasons(struct iwl_mvm *mvm, | 1259 | static void iwl_mvm_report_wakeup_reasons(struct iwl_mvm *mvm, |
| 1113 | struct ieee80211_vif *vif, | 1260 | struct ieee80211_vif *vif, |
| 1114 | struct iwl_wowlan_status *status) | 1261 | struct iwl_wowlan_status_data *status) |
| 1115 | { | 1262 | { |
| 1116 | struct sk_buff *pkt = NULL; | 1263 | struct sk_buff *pkt = NULL; |
| 1117 | struct cfg80211_wowlan_wakeup wakeup = { | 1264 | struct cfg80211_wowlan_wakeup wakeup = { |
| 1118 | .pattern_idx = -1, | 1265 | .pattern_idx = -1, |
| 1119 | }; | 1266 | }; |
| 1120 | struct cfg80211_wowlan_wakeup *wakeup_report = &wakeup; | 1267 | struct cfg80211_wowlan_wakeup *wakeup_report = &wakeup; |
| 1121 | u32 reasons = le32_to_cpu(status->wakeup_reasons); | 1268 | u32 reasons = status->wakeup_reasons; |
| 1122 | 1269 | ||
| 1123 | if (reasons == IWL_WOWLAN_WAKEUP_BY_NON_WIRELESS) { | 1270 | if (reasons == IWL_WOWLAN_WAKEUP_BY_NON_WIRELESS) { |
| 1124 | wakeup_report = NULL; | 1271 | wakeup_report = NULL; |
| @@ -1130,7 +1277,7 @@ static void iwl_mvm_report_wakeup_reasons(struct iwl_mvm *mvm, | |||
| 1130 | 1277 | ||
| 1131 | if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN) | 1278 | if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN) |
| 1132 | wakeup.pattern_idx = | 1279 | wakeup.pattern_idx = |
| 1133 | le16_to_cpu(status->pattern_number); | 1280 | status->pattern_number; |
| 1134 | 1281 | ||
| 1135 | if (reasons & (IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON | | 1282 | if (reasons & (IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON | |
| 1136 | IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH)) | 1283 | IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH)) |
| @@ -1158,8 +1305,8 @@ static void iwl_mvm_report_wakeup_reasons(struct iwl_mvm *mvm, | |||
| 1158 | wakeup.tcp_match = true; | 1305 | wakeup.tcp_match = true; |
| 1159 | 1306 | ||
| 1160 | if (status->wake_packet_bufsize) { | 1307 | if (status->wake_packet_bufsize) { |
| 1161 | int pktsize = le32_to_cpu(status->wake_packet_bufsize); | 1308 | int pktsize = status->wake_packet_bufsize; |
| 1162 | int pktlen = le32_to_cpu(status->wake_packet_length); | 1309 | int pktlen = status->wake_packet_length; |
| 1163 | const u8 *pktdata = status->wake_packet; | 1310 | const u8 *pktdata = status->wake_packet; |
| 1164 | struct ieee80211_hdr *hdr = (void *)pktdata; | 1311 | struct ieee80211_hdr *hdr = (void *)pktdata; |
| 1165 | int truncated = pktlen - pktsize; | 1312 | int truncated = pktlen - pktsize; |
| @@ -1239,8 +1386,229 @@ static void iwl_mvm_report_wakeup_reasons(struct iwl_mvm *mvm, | |||
| 1239 | kfree_skb(pkt); | 1386 | kfree_skb(pkt); |
| 1240 | } | 1387 | } |
| 1241 | 1388 | ||
| 1389 | static void iwl_mvm_aes_sc_to_seq(struct aes_sc *sc, | ||
| 1390 | struct ieee80211_key_seq *seq) | ||
| 1391 | { | ||
| 1392 | u64 pn; | ||
| 1393 | |||
| 1394 | pn = le64_to_cpu(sc->pn); | ||
| 1395 | seq->ccmp.pn[0] = pn >> 40; | ||
| 1396 | seq->ccmp.pn[1] = pn >> 32; | ||
| 1397 | seq->ccmp.pn[2] = pn >> 24; | ||
| 1398 | seq->ccmp.pn[3] = pn >> 16; | ||
| 1399 | seq->ccmp.pn[4] = pn >> 8; | ||
| 1400 | seq->ccmp.pn[5] = pn; | ||
| 1401 | } | ||
| 1402 | |||
| 1403 | static void iwl_mvm_tkip_sc_to_seq(struct tkip_sc *sc, | ||
| 1404 | struct ieee80211_key_seq *seq) | ||
| 1405 | { | ||
| 1406 | seq->tkip.iv32 = le32_to_cpu(sc->iv32); | ||
| 1407 | seq->tkip.iv16 = le16_to_cpu(sc->iv16); | ||
| 1408 | } | ||
| 1409 | |||
| 1410 | static void iwl_mvm_set_aes_rx_seq(struct aes_sc *scs, | ||
| 1411 | struct ieee80211_key_conf *key) | ||
| 1412 | { | ||
| 1413 | int tid; | ||
| 1414 | |||
| 1415 | BUILD_BUG_ON(IWL_NUM_RSC != IEEE80211_NUM_TIDS); | ||
| 1416 | |||
| 1417 | for (tid = 0; tid < IWL_NUM_RSC; tid++) { | ||
| 1418 | struct ieee80211_key_seq seq = {}; | ||
| 1419 | |||
| 1420 | iwl_mvm_aes_sc_to_seq(&scs[tid], &seq); | ||
| 1421 | ieee80211_set_key_rx_seq(key, tid, &seq); | ||
| 1422 | } | ||
| 1423 | } | ||
| 1424 | |||
| 1425 | static void iwl_mvm_set_tkip_rx_seq(struct tkip_sc *scs, | ||
| 1426 | struct ieee80211_key_conf *key) | ||
| 1427 | { | ||
| 1428 | int tid; | ||
| 1429 | |||
| 1430 | BUILD_BUG_ON(IWL_NUM_RSC != IEEE80211_NUM_TIDS); | ||
| 1431 | |||
| 1432 | for (tid = 0; tid < IWL_NUM_RSC; tid++) { | ||
| 1433 | struct ieee80211_key_seq seq = {}; | ||
| 1434 | |||
| 1435 | iwl_mvm_tkip_sc_to_seq(&scs[tid], &seq); | ||
| 1436 | ieee80211_set_key_rx_seq(key, tid, &seq); | ||
| 1437 | } | ||
| 1438 | } | ||
| 1439 | |||
| 1440 | static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key, | ||
| 1441 | struct iwl_wowlan_status_v6 *status) | ||
| 1442 | { | ||
| 1443 | union iwl_all_tsc_rsc *rsc = &status->gtk.rsc.all_tsc_rsc; | ||
| 1444 | |||
| 1445 | switch (key->cipher) { | ||
| 1446 | case WLAN_CIPHER_SUITE_CCMP: | ||
| 1447 | iwl_mvm_set_aes_rx_seq(rsc->aes.multicast_rsc, key); | ||
| 1448 | break; | ||
| 1449 | case WLAN_CIPHER_SUITE_TKIP: | ||
| 1450 | iwl_mvm_set_tkip_rx_seq(rsc->tkip.multicast_rsc, key); | ||
| 1451 | break; | ||
| 1452 | default: | ||
| 1453 | WARN_ON(1); | ||
| 1454 | } | ||
| 1455 | } | ||
| 1456 | |||
| 1457 | struct iwl_mvm_d3_gtk_iter_data { | ||
| 1458 | struct iwl_wowlan_status_v6 *status; | ||
| 1459 | void *last_gtk; | ||
| 1460 | u32 cipher; | ||
| 1461 | bool find_phase, unhandled_cipher; | ||
| 1462 | int num_keys; | ||
| 1463 | }; | ||
| 1464 | |||
| 1465 | static void iwl_mvm_d3_update_gtks(struct ieee80211_hw *hw, | ||
| 1466 | struct ieee80211_vif *vif, | ||
| 1467 | struct ieee80211_sta *sta, | ||
| 1468 | struct ieee80211_key_conf *key, | ||
| 1469 | void *_data) | ||
| 1470 | { | ||
| 1471 | struct iwl_mvm_d3_gtk_iter_data *data = _data; | ||
| 1472 | |||
| 1473 | if (data->unhandled_cipher) | ||
| 1474 | return; | ||
| 1475 | |||
| 1476 | switch (key->cipher) { | ||
| 1477 | case WLAN_CIPHER_SUITE_WEP40: | ||
| 1478 | case WLAN_CIPHER_SUITE_WEP104: | ||
| 1479 | /* ignore WEP completely, nothing to do */ | ||
| 1480 | return; | ||
| 1481 | case WLAN_CIPHER_SUITE_CCMP: | ||
| 1482 | case WLAN_CIPHER_SUITE_TKIP: | ||
| 1483 | /* we support these */ | ||
| 1484 | break; | ||
| 1485 | default: | ||
| 1486 | /* everything else (even CMAC for MFP) - disconnect from AP */ | ||
| 1487 | data->unhandled_cipher = true; | ||
| 1488 | return; | ||
| 1489 | } | ||
| 1490 | |||
| 1491 | data->num_keys++; | ||
| 1492 | |||
| 1493 | /* | ||
| 1494 | * pairwise key - update sequence counters only; | ||
| 1495 | * note that this assumes no TDLS sessions are active | ||
| 1496 | */ | ||
| 1497 | if (sta) { | ||
| 1498 | struct ieee80211_key_seq seq = {}; | ||
| 1499 | union iwl_all_tsc_rsc *sc = &data->status->gtk.rsc.all_tsc_rsc; | ||
| 1500 | |||
| 1501 | if (data->find_phase) | ||
| 1502 | return; | ||
| 1503 | |||
| 1504 | switch (key->cipher) { | ||
| 1505 | case WLAN_CIPHER_SUITE_CCMP: | ||
| 1506 | iwl_mvm_aes_sc_to_seq(&sc->aes.tsc, &seq); | ||
| 1507 | iwl_mvm_set_aes_rx_seq(sc->aes.unicast_rsc, key); | ||
| 1508 | break; | ||
| 1509 | case WLAN_CIPHER_SUITE_TKIP: | ||
| 1510 | iwl_mvm_tkip_sc_to_seq(&sc->tkip.tsc, &seq); | ||
| 1511 | iwl_mvm_set_tkip_rx_seq(sc->tkip.unicast_rsc, key); | ||
| 1512 | break; | ||
| 1513 | } | ||
| 1514 | ieee80211_set_key_tx_seq(key, &seq); | ||
| 1515 | |||
| 1516 | /* that's it for this key */ | ||
| 1517 | return; | ||
| 1518 | } | ||
| 1519 | |||
| 1520 | if (data->find_phase) { | ||
| 1521 | data->last_gtk = key; | ||
| 1522 | data->cipher = key->cipher; | ||
| 1523 | return; | ||
| 1524 | } | ||
| 1525 | |||
| 1526 | if (data->status->num_of_gtk_rekeys) | ||
| 1527 | ieee80211_remove_key(key); | ||
| 1528 | else if (data->last_gtk == key) | ||
| 1529 | iwl_mvm_set_key_rx_seq(key, data->status); | ||
| 1530 | } | ||
| 1531 | |||
| 1532 | static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm, | ||
| 1533 | struct ieee80211_vif *vif, | ||
| 1534 | struct iwl_wowlan_status_v6 *status) | ||
| 1535 | { | ||
| 1536 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 1537 | struct iwl_mvm_d3_gtk_iter_data gtkdata = { | ||
| 1538 | .status = status, | ||
| 1539 | }; | ||
| 1540 | |||
| 1541 | if (!status || !vif->bss_conf.bssid) | ||
| 1542 | return false; | ||
| 1543 | |||
| 1544 | /* find last GTK that we used initially, if any */ | ||
| 1545 | gtkdata.find_phase = true; | ||
| 1546 | ieee80211_iter_keys(mvm->hw, vif, | ||
| 1547 | iwl_mvm_d3_update_gtks, >kdata); | ||
| 1548 | /* not trying to keep connections with MFP/unhandled ciphers */ | ||
| 1549 | if (gtkdata.unhandled_cipher) | ||
| 1550 | return false; | ||
| 1551 | if (!gtkdata.num_keys) | ||
| 1552 | return true; | ||
| 1553 | if (!gtkdata.last_gtk) | ||
| 1554 | return false; | ||
| 1555 | |||
| 1556 | /* | ||
| 1557 | * invalidate all other GTKs that might still exist and update | ||
| 1558 | * the one that we used | ||
| 1559 | */ | ||
| 1560 | gtkdata.find_phase = false; | ||
| 1561 | ieee80211_iter_keys(mvm->hw, vif, | ||
| 1562 | iwl_mvm_d3_update_gtks, >kdata); | ||
| 1563 | |||
| 1564 | if (status->num_of_gtk_rekeys) { | ||
| 1565 | struct ieee80211_key_conf *key; | ||
| 1566 | struct { | ||
| 1567 | struct ieee80211_key_conf conf; | ||
| 1568 | u8 key[32]; | ||
| 1569 | } conf = { | ||
| 1570 | .conf.cipher = gtkdata.cipher, | ||
| 1571 | .conf.keyidx = status->gtk.key_index, | ||
| 1572 | }; | ||
| 1573 | |||
| 1574 | switch (gtkdata.cipher) { | ||
| 1575 | case WLAN_CIPHER_SUITE_CCMP: | ||
| 1576 | conf.conf.keylen = WLAN_KEY_LEN_CCMP; | ||
| 1577 | memcpy(conf.conf.key, status->gtk.decrypt_key, | ||
| 1578 | WLAN_KEY_LEN_CCMP); | ||
| 1579 | break; | ||
| 1580 | case WLAN_CIPHER_SUITE_TKIP: | ||
| 1581 | conf.conf.keylen = WLAN_KEY_LEN_TKIP; | ||
| 1582 | memcpy(conf.conf.key, status->gtk.decrypt_key, 16); | ||
| 1583 | /* leave TX MIC key zeroed, we don't use it anyway */ | ||
| 1584 | memcpy(conf.conf.key + | ||
| 1585 | NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY, | ||
| 1586 | status->gtk.tkip_mic_key, 8); | ||
| 1587 | break; | ||
| 1588 | } | ||
| 1589 | |||
| 1590 | key = ieee80211_gtk_rekey_add(vif, &conf.conf); | ||
| 1591 | if (IS_ERR(key)) | ||
| 1592 | return false; | ||
| 1593 | iwl_mvm_set_key_rx_seq(key, status); | ||
| 1594 | } | ||
| 1595 | |||
| 1596 | if (status->num_of_gtk_rekeys) { | ||
| 1597 | __be64 replay_ctr = | ||
| 1598 | cpu_to_be64(le64_to_cpu(status->replay_ctr)); | ||
| 1599 | ieee80211_gtk_rekey_notify(vif, vif->bss_conf.bssid, | ||
| 1600 | (void *)&replay_ctr, GFP_KERNEL); | ||
| 1601 | } | ||
| 1602 | |||
| 1603 | mvmvif->seqno_valid = true; | ||
| 1604 | /* +0x10 because the set API expects next-to-use, not last-used */ | ||
| 1605 | mvmvif->seqno = le16_to_cpu(status->non_qos_seq_ctr) + 0x10; | ||
| 1606 | |||
| 1607 | return true; | ||
| 1608 | } | ||
| 1609 | |||
| 1242 | /* releases the MVM mutex */ | 1610 | /* releases the MVM mutex */ |
| 1243 | static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | 1611 | static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, |
| 1244 | struct ieee80211_vif *vif) | 1612 | struct ieee80211_vif *vif) |
| 1245 | { | 1613 | { |
| 1246 | u32 base = mvm->error_event_table; | 1614 | u32 base = mvm->error_event_table; |
| @@ -1253,8 +1621,12 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
| 1253 | .id = WOWLAN_GET_STATUSES, | 1621 | .id = WOWLAN_GET_STATUSES, |
| 1254 | .flags = CMD_SYNC | CMD_WANT_SKB, | 1622 | .flags = CMD_SYNC | CMD_WANT_SKB, |
| 1255 | }; | 1623 | }; |
| 1256 | struct iwl_wowlan_status *status; | 1624 | struct iwl_wowlan_status_data status; |
| 1257 | int ret, len; | 1625 | struct iwl_wowlan_status_v6 *status_v6; |
| 1626 | int ret, len, status_size, i; | ||
| 1627 | bool keep; | ||
| 1628 | struct ieee80211_sta *ap_sta; | ||
| 1629 | struct iwl_mvm_sta *mvm_ap_sta; | ||
| 1258 | 1630 | ||
| 1259 | iwl_trans_read_mem_bytes(mvm->trans, base, | 1631 | iwl_trans_read_mem_bytes(mvm->trans, base, |
| 1260 | &err_info, sizeof(err_info)); | 1632 | &err_info, sizeof(err_info)); |
| @@ -1287,32 +1659,83 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
| 1287 | if (!cmd.resp_pkt) | 1659 | if (!cmd.resp_pkt) |
| 1288 | goto out_unlock; | 1660 | goto out_unlock; |
| 1289 | 1661 | ||
| 1662 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API) | ||
| 1663 | status_size = sizeof(struct iwl_wowlan_status_v6); | ||
| 1664 | else | ||
| 1665 | status_size = sizeof(struct iwl_wowlan_status_v4); | ||
| 1666 | |||
| 1290 | len = le32_to_cpu(cmd.resp_pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | 1667 | len = le32_to_cpu(cmd.resp_pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; |
| 1291 | if (len - sizeof(struct iwl_cmd_header) < sizeof(*status)) { | 1668 | if (len - sizeof(struct iwl_cmd_header) < status_size) { |
| 1292 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); | 1669 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); |
| 1293 | goto out_free_resp; | 1670 | goto out_free_resp; |
| 1294 | } | 1671 | } |
| 1295 | 1672 | ||
| 1296 | status = (void *)cmd.resp_pkt->data; | 1673 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API) { |
| 1674 | status_v6 = (void *)cmd.resp_pkt->data; | ||
| 1675 | |||
| 1676 | status.pattern_number = le16_to_cpu(status_v6->pattern_number); | ||
| 1677 | for (i = 0; i < 8; i++) | ||
| 1678 | status.qos_seq_ctr[i] = | ||
| 1679 | le16_to_cpu(status_v6->qos_seq_ctr[i]); | ||
| 1680 | status.wakeup_reasons = le32_to_cpu(status_v6->wakeup_reasons); | ||
| 1681 | status.wake_packet_length = | ||
| 1682 | le32_to_cpu(status_v6->wake_packet_length); | ||
| 1683 | status.wake_packet_bufsize = | ||
| 1684 | le32_to_cpu(status_v6->wake_packet_bufsize); | ||
| 1685 | status.wake_packet = status_v6->wake_packet; | ||
| 1686 | } else { | ||
| 1687 | struct iwl_wowlan_status_v4 *status_v4; | ||
| 1688 | status_v6 = NULL; | ||
| 1689 | status_v4 = (void *)cmd.resp_pkt->data; | ||
| 1690 | |||
| 1691 | status.pattern_number = le16_to_cpu(status_v4->pattern_number); | ||
| 1692 | for (i = 0; i < 8; i++) | ||
| 1693 | status.qos_seq_ctr[i] = | ||
| 1694 | le16_to_cpu(status_v4->qos_seq_ctr[i]); | ||
| 1695 | status.wakeup_reasons = le32_to_cpu(status_v4->wakeup_reasons); | ||
| 1696 | status.wake_packet_length = | ||
| 1697 | le32_to_cpu(status_v4->wake_packet_length); | ||
| 1698 | status.wake_packet_bufsize = | ||
| 1699 | le32_to_cpu(status_v4->wake_packet_bufsize); | ||
| 1700 | status.wake_packet = status_v4->wake_packet; | ||
| 1701 | } | ||
| 1297 | 1702 | ||
| 1298 | if (len - sizeof(struct iwl_cmd_header) != | 1703 | if (len - sizeof(struct iwl_cmd_header) != |
| 1299 | sizeof(*status) + | 1704 | status_size + ALIGN(status.wake_packet_bufsize, 4)) { |
| 1300 | ALIGN(le32_to_cpu(status->wake_packet_bufsize), 4)) { | ||
| 1301 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); | 1705 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); |
| 1302 | goto out_free_resp; | 1706 | goto out_free_resp; |
| 1303 | } | 1707 | } |
| 1304 | 1708 | ||
| 1709 | /* still at hard-coded place 0 for D3 image */ | ||
| 1710 | ap_sta = rcu_dereference_protected( | ||
| 1711 | mvm->fw_id_to_mac_id[0], | ||
| 1712 | lockdep_is_held(&mvm->mutex)); | ||
| 1713 | if (IS_ERR_OR_NULL(ap_sta)) | ||
| 1714 | goto out_free_resp; | ||
| 1715 | |||
| 1716 | mvm_ap_sta = (struct iwl_mvm_sta *)ap_sta->drv_priv; | ||
| 1717 | for (i = 0; i < IWL_MAX_TID_COUNT; i++) { | ||
| 1718 | u16 seq = status.qos_seq_ctr[i]; | ||
| 1719 | /* firmware stores last-used value, we store next value */ | ||
| 1720 | seq += 0x10; | ||
| 1721 | mvm_ap_sta->tid_data[i].seq_number = seq; | ||
| 1722 | } | ||
| 1723 | |||
| 1305 | /* now we have all the data we need, unlock to avoid mac80211 issues */ | 1724 | /* now we have all the data we need, unlock to avoid mac80211 issues */ |
| 1306 | mutex_unlock(&mvm->mutex); | 1725 | mutex_unlock(&mvm->mutex); |
| 1307 | 1726 | ||
| 1308 | iwl_mvm_report_wakeup_reasons(mvm, vif, status); | 1727 | iwl_mvm_report_wakeup_reasons(mvm, vif, &status); |
| 1728 | |||
| 1729 | keep = iwl_mvm_setup_connection_keep(mvm, vif, status_v6); | ||
| 1730 | |||
| 1309 | iwl_free_resp(&cmd); | 1731 | iwl_free_resp(&cmd); |
| 1310 | return; | 1732 | return keep; |
| 1311 | 1733 | ||
| 1312 | out_free_resp: | 1734 | out_free_resp: |
| 1313 | iwl_free_resp(&cmd); | 1735 | iwl_free_resp(&cmd); |
| 1314 | out_unlock: | 1736 | out_unlock: |
| 1315 | mutex_unlock(&mvm->mutex); | 1737 | mutex_unlock(&mvm->mutex); |
| 1738 | return false; | ||
| 1316 | } | 1739 | } |
| 1317 | 1740 | ||
| 1318 | static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm) | 1741 | static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm) |
| @@ -1335,6 +1758,17 @@ static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm) | |||
| 1335 | #endif | 1758 | #endif |
| 1336 | } | 1759 | } |
| 1337 | 1760 | ||
| 1761 | static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac, | ||
| 1762 | struct ieee80211_vif *vif) | ||
| 1763 | { | ||
| 1764 | /* skip the one we keep connection on */ | ||
| 1765 | if (data == vif) | ||
| 1766 | return; | ||
| 1767 | |||
| 1768 | if (vif->type == NL80211_IFTYPE_STATION) | ||
| 1769 | ieee80211_resume_disconnect(vif); | ||
| 1770 | } | ||
| 1771 | |||
| 1338 | static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) | 1772 | static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) |
| 1339 | { | 1773 | { |
| 1340 | struct iwl_d3_iter_data resume_iter_data = { | 1774 | struct iwl_d3_iter_data resume_iter_data = { |
| @@ -1343,6 +1777,7 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) | |||
| 1343 | struct ieee80211_vif *vif = NULL; | 1777 | struct ieee80211_vif *vif = NULL; |
| 1344 | int ret; | 1778 | int ret; |
| 1345 | enum iwl_d3_status d3_status; | 1779 | enum iwl_d3_status d3_status; |
| 1780 | bool keep = false; | ||
| 1346 | 1781 | ||
| 1347 | mutex_lock(&mvm->mutex); | 1782 | mutex_lock(&mvm->mutex); |
| 1348 | 1783 | ||
| @@ -1368,7 +1803,7 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) | |||
| 1368 | /* query SRAM first in case we want event logging */ | 1803 | /* query SRAM first in case we want event logging */ |
| 1369 | iwl_mvm_read_d3_sram(mvm); | 1804 | iwl_mvm_read_d3_sram(mvm); |
| 1370 | 1805 | ||
| 1371 | iwl_mvm_query_wakeup_reasons(mvm, vif); | 1806 | keep = iwl_mvm_query_wakeup_reasons(mvm, vif); |
| 1372 | /* has unlocked the mutex, so skip that */ | 1807 | /* has unlocked the mutex, so skip that */ |
| 1373 | goto out; | 1808 | goto out; |
| 1374 | 1809 | ||
| @@ -1376,8 +1811,10 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) | |||
| 1376 | mutex_unlock(&mvm->mutex); | 1811 | mutex_unlock(&mvm->mutex); |
| 1377 | 1812 | ||
| 1378 | out: | 1813 | out: |
| 1379 | if (!test && vif) | 1814 | if (!test) |
| 1380 | ieee80211_resume_disconnect(vif); | 1815 | ieee80211_iterate_active_interfaces_rtnl(mvm->hw, |
| 1816 | IEEE80211_IFACE_ITER_NORMAL, | ||
| 1817 | iwl_mvm_d3_disconnect_iter, keep ? vif : NULL); | ||
| 1381 | 1818 | ||
| 1382 | /* return 1 to reconfigure the device */ | 1819 | /* return 1 to reconfigure the device */ |
| 1383 | set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); | 1820 | set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index aac81b8984b0..9864d713eb2c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c | |||
| @@ -246,58 +246,56 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, | |||
| 246 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 246 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
| 247 | } | 247 | } |
| 248 | 248 | ||
| 249 | static ssize_t iwl_dbgfs_power_down_allow_write(struct file *file, | 249 | static ssize_t iwl_dbgfs_disable_power_off_read(struct file *file, |
| 250 | const char __user *user_buf, | 250 | char __user *user_buf, |
| 251 | size_t count, loff_t *ppos) | 251 | size_t count, loff_t *ppos) |
| 252 | { | 252 | { |
| 253 | struct iwl_mvm *mvm = file->private_data; | 253 | struct iwl_mvm *mvm = file->private_data; |
| 254 | char buf[8] = {}; | 254 | char buf[64]; |
| 255 | int allow; | 255 | int bufsz = sizeof(buf); |
| 256 | 256 | int pos = 0; | |
| 257 | if (!mvm->ucode_loaded) | ||
| 258 | return -EIO; | ||
| 259 | |||
| 260 | if (copy_from_user(buf, user_buf, sizeof(buf))) | ||
| 261 | return -EFAULT; | ||
| 262 | |||
| 263 | if (sscanf(buf, "%d", &allow) != 1) | ||
| 264 | return -EINVAL; | ||
| 265 | |||
| 266 | IWL_DEBUG_POWER(mvm, "%s device power down\n", | ||
| 267 | allow ? "allow" : "prevent"); | ||
| 268 | 257 | ||
| 269 | /* | 258 | pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d0=%d\n", |
| 270 | * TODO: Send REPLY_DEBUG_CMD (0xf0) when FW support it | 259 | mvm->disable_power_off); |
| 271 | */ | 260 | pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d3=%d\n", |
| 261 | mvm->disable_power_off_d3); | ||
| 272 | 262 | ||
| 273 | return count; | 263 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
| 274 | } | 264 | } |
| 275 | 265 | ||
| 276 | static ssize_t iwl_dbgfs_power_down_d3_allow_write(struct file *file, | 266 | static ssize_t iwl_dbgfs_disable_power_off_write(struct file *file, |
| 277 | const char __user *user_buf, | 267 | const char __user *user_buf, |
| 278 | size_t count, loff_t *ppos) | 268 | size_t count, loff_t *ppos) |
| 279 | { | 269 | { |
| 280 | struct iwl_mvm *mvm = file->private_data; | 270 | struct iwl_mvm *mvm = file->private_data; |
| 281 | char buf[8] = {}; | 271 | char buf[64] = {}; |
| 282 | int allow; | 272 | int ret; |
| 273 | int val; | ||
| 283 | 274 | ||
| 284 | if (copy_from_user(buf, user_buf, sizeof(buf))) | 275 | if (!mvm->ucode_loaded) |
| 276 | return -EIO; | ||
| 277 | |||
| 278 | count = min_t(size_t, count, sizeof(buf) - 1); | ||
| 279 | if (copy_from_user(buf, user_buf, count)) | ||
| 285 | return -EFAULT; | 280 | return -EFAULT; |
| 286 | 281 | ||
| 287 | if (sscanf(buf, "%d", &allow) != 1) | 282 | if (!strncmp("disable_power_off_d0=", buf, 21)) { |
| 283 | if (sscanf(buf + 21, "%d", &val) != 1) | ||
| 284 | return -EINVAL; | ||
| 285 | mvm->disable_power_off = val; | ||
| 286 | } else if (!strncmp("disable_power_off_d3=", buf, 21)) { | ||
| 287 | if (sscanf(buf + 21, "%d", &val) != 1) | ||
| 288 | return -EINVAL; | ||
| 289 | mvm->disable_power_off_d3 = val; | ||
| 290 | } else { | ||
| 288 | return -EINVAL; | 291 | return -EINVAL; |
| 292 | } | ||
| 289 | 293 | ||
| 290 | IWL_DEBUG_POWER(mvm, "%s device power down in d3\n", | 294 | mutex_lock(&mvm->mutex); |
| 291 | allow ? "allow" : "prevent"); | 295 | ret = iwl_mvm_power_update_device_mode(mvm); |
| 292 | 296 | mutex_unlock(&mvm->mutex); | |
| 293 | /* | ||
| 294 | * TODO: When WoWLAN FW alive notification happens, driver will send | ||
| 295 | * REPLY_DEBUG_CMD setting power_down_allow flag according to | ||
| 296 | * mvm->prevent_power_down_d3 | ||
| 297 | */ | ||
| 298 | mvm->prevent_power_down_d3 = !allow; | ||
| 299 | 297 | ||
| 300 | return count; | 298 | return ret ?: count; |
| 301 | } | 299 | } |
| 302 | 300 | ||
| 303 | static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm, | 301 | static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm, |
| @@ -344,6 +342,7 @@ static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm, | |||
| 344 | case MVM_DEBUGFS_PM_DISABLE_POWER_OFF: | 342 | case MVM_DEBUGFS_PM_DISABLE_POWER_OFF: |
| 345 | IWL_DEBUG_POWER(mvm, "disable_power_off=%d\n", val); | 343 | IWL_DEBUG_POWER(mvm, "disable_power_off=%d\n", val); |
| 346 | dbgfs_pm->disable_power_off = val; | 344 | dbgfs_pm->disable_power_off = val; |
| 345 | break; | ||
| 347 | case MVM_DEBUGFS_PM_LPRX_ENA: | 346 | case MVM_DEBUGFS_PM_LPRX_ENA: |
| 348 | IWL_DEBUG_POWER(mvm, "lprx %s\n", val ? "enabled" : "disabled"); | 347 | IWL_DEBUG_POWER(mvm, "lprx %s\n", val ? "enabled" : "disabled"); |
| 349 | dbgfs_pm->lprx_ena = val; | 348 | dbgfs_pm->lprx_ena = val; |
| @@ -371,7 +370,8 @@ static ssize_t iwl_dbgfs_pm_params_write(struct file *file, | |||
| 371 | int val; | 370 | int val; |
| 372 | int ret; | 371 | int ret; |
| 373 | 372 | ||
| 374 | if (copy_from_user(buf, user_buf, sizeof(buf))) | 373 | count = min_t(size_t, count, sizeof(buf) - 1); |
| 374 | if (copy_from_user(buf, user_buf, count)) | ||
| 375 | return -EFAULT; | 375 | return -EFAULT; |
| 376 | 376 | ||
| 377 | if (!strncmp("keep_alive=", buf, 11)) { | 377 | if (!strncmp("keep_alive=", buf, 11)) { |
| @@ -394,7 +394,9 @@ static ssize_t iwl_dbgfs_pm_params_write(struct file *file, | |||
| 394 | if (sscanf(buf + 16, "%d", &val) != 1) | 394 | if (sscanf(buf + 16, "%d", &val) != 1) |
| 395 | return -EINVAL; | 395 | return -EINVAL; |
| 396 | param = MVM_DEBUGFS_PM_TX_DATA_TIMEOUT; | 396 | param = MVM_DEBUGFS_PM_TX_DATA_TIMEOUT; |
| 397 | } else if (!strncmp("disable_power_off=", buf, 18)) { | 397 | } else if (!strncmp("disable_power_off=", buf, 18) && |
| 398 | !(mvm->fw->ucode_capa.flags & | ||
| 399 | IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)) { | ||
| 398 | if (sscanf(buf + 18, "%d", &val) != 1) | 400 | if (sscanf(buf + 18, "%d", &val) != 1) |
| 399 | return -EINVAL; | 401 | return -EINVAL; |
| 400 | param = MVM_DEBUGFS_PM_DISABLE_POWER_OFF; | 402 | param = MVM_DEBUGFS_PM_DISABLE_POWER_OFF; |
| @@ -581,15 +583,21 @@ static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf, | |||
| 581 | BT_MBOX_PRINT(3, UPDATE_REQUEST, true); | 583 | BT_MBOX_PRINT(3, UPDATE_REQUEST, true); |
| 582 | 584 | ||
| 583 | pos += scnprintf(buf+pos, bufsz-pos, "bt_status = %d\n", | 585 | pos += scnprintf(buf+pos, bufsz-pos, "bt_status = %d\n", |
| 584 | notif->bt_status); | 586 | notif->bt_status); |
| 585 | pos += scnprintf(buf+pos, bufsz-pos, "bt_open_conn = %d\n", | 587 | pos += scnprintf(buf+pos, bufsz-pos, "bt_open_conn = %d\n", |
| 586 | notif->bt_open_conn); | 588 | notif->bt_open_conn); |
| 587 | pos += scnprintf(buf+pos, bufsz-pos, "bt_traffic_load = %d\n", | 589 | pos += scnprintf(buf+pos, bufsz-pos, "bt_traffic_load = %d\n", |
| 588 | notif->bt_traffic_load); | 590 | notif->bt_traffic_load); |
| 589 | pos += scnprintf(buf+pos, bufsz-pos, "bt_agg_traffic_load = %d\n", | 591 | pos += scnprintf(buf+pos, bufsz-pos, "bt_agg_traffic_load = %d\n", |
| 590 | notif->bt_agg_traffic_load); | 592 | notif->bt_agg_traffic_load); |
| 591 | pos += scnprintf(buf+pos, bufsz-pos, "bt_ci_compliance = %d\n", | 593 | pos += scnprintf(buf+pos, bufsz-pos, "bt_ci_compliance = %d\n", |
| 592 | notif->bt_ci_compliance); | 594 | notif->bt_ci_compliance); |
| 595 | pos += scnprintf(buf+pos, bufsz-pos, "primary_ch_lut = %d\n", | ||
| 596 | le32_to_cpu(notif->primary_ch_lut)); | ||
| 597 | pos += scnprintf(buf+pos, bufsz-pos, "secondary_ch_lut = %d\n", | ||
| 598 | le32_to_cpu(notif->secondary_ch_lut)); | ||
| 599 | pos += scnprintf(buf+pos, bufsz-pos, "bt_activity_grading = %d\n", | ||
| 600 | le32_to_cpu(notif->bt_activity_grading)); | ||
| 593 | 601 | ||
| 594 | mutex_unlock(&mvm->mutex); | 602 | mutex_unlock(&mvm->mutex); |
| 595 | 603 | ||
| @@ -600,6 +608,38 @@ static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf, | |||
| 600 | } | 608 | } |
| 601 | #undef BT_MBOX_PRINT | 609 | #undef BT_MBOX_PRINT |
| 602 | 610 | ||
| 611 | static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf, | ||
| 612 | size_t count, loff_t *ppos) | ||
| 613 | { | ||
| 614 | struct iwl_mvm *mvm = file->private_data; | ||
| 615 | struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd; | ||
| 616 | char buf[256]; | ||
| 617 | int bufsz = sizeof(buf); | ||
| 618 | int pos = 0; | ||
| 619 | |||
| 620 | mutex_lock(&mvm->mutex); | ||
| 621 | |||
| 622 | pos += scnprintf(buf+pos, bufsz-pos, "Channel inhibition CMD\n"); | ||
| 623 | pos += scnprintf(buf+pos, bufsz-pos, | ||
| 624 | "\tPrimary Channel Bitmap 0x%016llx Fat: %d\n", | ||
| 625 | le64_to_cpu(cmd->bt_primary_ci), | ||
| 626 | !!cmd->co_run_bw_primary); | ||
| 627 | pos += scnprintf(buf+pos, bufsz-pos, | ||
| 628 | "\tSecondary Channel Bitmap 0x%016llx Fat: %d\n", | ||
| 629 | le64_to_cpu(cmd->bt_secondary_ci), | ||
| 630 | !!cmd->co_run_bw_secondary); | ||
| 631 | |||
| 632 | pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n"); | ||
| 633 | pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill Mask 0x%08x\n", | ||
| 634 | iwl_bt_ack_kill_msk[mvm->bt_kill_msk]); | ||
| 635 | pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill Mask 0x%08x\n", | ||
| 636 | iwl_bt_cts_kill_msk[mvm->bt_kill_msk]); | ||
| 637 | |||
| 638 | mutex_unlock(&mvm->mutex); | ||
| 639 | |||
| 640 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
| 641 | } | ||
| 642 | |||
| 603 | #define PRINT_STATS_LE32(_str, _val) \ | 643 | #define PRINT_STATS_LE32(_str, _val) \ |
| 604 | pos += scnprintf(buf + pos, bufsz - pos, \ | 644 | pos += scnprintf(buf + pos, bufsz - pos, \ |
| 605 | fmt_table, _str, \ | 645 | fmt_table, _str, \ |
| @@ -615,9 +655,11 @@ static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file, | |||
| 615 | int pos = 0; | 655 | int pos = 0; |
| 616 | char *buf; | 656 | char *buf; |
| 617 | int ret; | 657 | int ret; |
| 618 | int bufsz = sizeof(struct mvm_statistics_rx_phy) * 20 + | 658 | /* 43 is the size of each data line, 33 is the size of each header */ |
| 619 | sizeof(struct mvm_statistics_rx_non_phy) * 10 + | 659 | size_t bufsz = |
| 620 | sizeof(struct mvm_statistics_rx_ht_phy) * 10 + 200; | 660 | ((sizeof(struct mvm_statistics_rx) / sizeof(__le32)) * 43) + |
| 661 | (4 * 33) + 1; | ||
| 662 | |||
| 621 | struct mvm_statistics_rx_phy *ofdm; | 663 | struct mvm_statistics_rx_phy *ofdm; |
| 622 | struct mvm_statistics_rx_phy *cck; | 664 | struct mvm_statistics_rx_phy *cck; |
| 623 | struct mvm_statistics_rx_non_phy *general; | 665 | struct mvm_statistics_rx_non_phy *general; |
| @@ -712,6 +754,7 @@ static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file, | |||
| 712 | PRINT_STATS_LE32("beacon_energy_b", general->beacon_energy_b); | 754 | PRINT_STATS_LE32("beacon_energy_b", general->beacon_energy_b); |
| 713 | PRINT_STATS_LE32("beacon_energy_c", general->beacon_energy_c); | 755 | PRINT_STATS_LE32("beacon_energy_c", general->beacon_energy_c); |
| 714 | PRINT_STATS_LE32("num_bt_kills", general->num_bt_kills); | 756 | PRINT_STATS_LE32("num_bt_kills", general->num_bt_kills); |
| 757 | PRINT_STATS_LE32("mac_id", general->mac_id); | ||
| 715 | PRINT_STATS_LE32("directed_data_mpdu", general->directed_data_mpdu); | 758 | PRINT_STATS_LE32("directed_data_mpdu", general->directed_data_mpdu); |
| 716 | 759 | ||
| 717 | pos += scnprintf(buf + pos, bufsz - pos, fmt_header, | 760 | pos += scnprintf(buf + pos, bufsz - pos, fmt_header, |
| @@ -757,6 +800,59 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct file *file, | |||
| 757 | return count; | 800 | return count; |
| 758 | } | 801 | } |
| 759 | 802 | ||
| 803 | static ssize_t | ||
| 804 | iwl_dbgfs_scan_ant_rxchain_read(struct file *file, | ||
| 805 | char __user *user_buf, | ||
| 806 | size_t count, loff_t *ppos) | ||
| 807 | { | ||
| 808 | struct iwl_mvm *mvm = file->private_data; | ||
| 809 | int pos = 0; | ||
| 810 | char buf[32]; | ||
| 811 | const size_t bufsz = sizeof(buf); | ||
| 812 | |||
| 813 | /* print which antennas were set for the scan command by the user */ | ||
| 814 | pos += scnprintf(buf + pos, bufsz - pos, "Antennas for scan: "); | ||
| 815 | if (mvm->scan_rx_ant & ANT_A) | ||
| 816 | pos += scnprintf(buf + pos, bufsz - pos, "A"); | ||
| 817 | if (mvm->scan_rx_ant & ANT_B) | ||
| 818 | pos += scnprintf(buf + pos, bufsz - pos, "B"); | ||
| 819 | if (mvm->scan_rx_ant & ANT_C) | ||
| 820 | pos += scnprintf(buf + pos, bufsz - pos, "C"); | ||
| 821 | pos += scnprintf(buf + pos, bufsz - pos, " (%hhx)\n", mvm->scan_rx_ant); | ||
| 822 | |||
| 823 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
| 824 | } | ||
| 825 | |||
| 826 | static ssize_t | ||
| 827 | iwl_dbgfs_scan_ant_rxchain_write(struct file *file, | ||
| 828 | const char __user *user_buf, | ||
| 829 | size_t count, loff_t *ppos) | ||
| 830 | { | ||
| 831 | struct iwl_mvm *mvm = file->private_data; | ||
| 832 | char buf[8]; | ||
| 833 | int buf_size; | ||
| 834 | u8 scan_rx_ant; | ||
| 835 | |||
| 836 | memset(buf, 0, sizeof(buf)); | ||
| 837 | buf_size = min(count, sizeof(buf) - 1); | ||
| 838 | |||
| 839 | /* get the argument from the user and check if it is valid */ | ||
| 840 | if (copy_from_user(buf, user_buf, buf_size)) | ||
| 841 | return -EFAULT; | ||
| 842 | if (sscanf(buf, "%hhx", &scan_rx_ant) != 1) | ||
| 843 | return -EINVAL; | ||
| 844 | if (scan_rx_ant > ANT_ABC) | ||
| 845 | return -EINVAL; | ||
| 846 | if (scan_rx_ant & ~iwl_fw_valid_rx_ant(mvm->fw)) | ||
| 847 | return -EINVAL; | ||
| 848 | |||
| 849 | /* change the rx antennas for scan command */ | ||
| 850 | mvm->scan_rx_ant = scan_rx_ant; | ||
| 851 | |||
| 852 | return count; | ||
| 853 | } | ||
| 854 | |||
| 855 | |||
| 760 | static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif, | 856 | static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif, |
| 761 | enum iwl_dbgfs_bf_mask param, int value) | 857 | enum iwl_dbgfs_bf_mask param, int value) |
| 762 | { | 858 | { |
| @@ -968,7 +1064,8 @@ static ssize_t iwl_dbgfs_d3_sram_write(struct file *file, | |||
| 968 | char buf[8] = {}; | 1064 | char buf[8] = {}; |
| 969 | int store; | 1065 | int store; |
| 970 | 1066 | ||
| 971 | if (copy_from_user(buf, user_buf, sizeof(buf))) | 1067 | count = min_t(size_t, count, sizeof(buf) - 1); |
| 1068 | if (copy_from_user(buf, user_buf, count)) | ||
| 972 | return -EFAULT; | 1069 | return -EFAULT; |
| 973 | 1070 | ||
| 974 | if (sscanf(buf, "%d", &store) != 1) | 1071 | if (sscanf(buf, "%d", &store) != 1) |
| @@ -1063,10 +1160,12 @@ MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain); | |||
| 1063 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram); | 1160 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram); |
| 1064 | MVM_DEBUGFS_READ_FILE_OPS(stations); | 1161 | MVM_DEBUGFS_READ_FILE_OPS(stations); |
| 1065 | MVM_DEBUGFS_READ_FILE_OPS(bt_notif); | 1162 | MVM_DEBUGFS_READ_FILE_OPS(bt_notif); |
| 1066 | MVM_DEBUGFS_WRITE_FILE_OPS(power_down_allow); | 1163 | MVM_DEBUGFS_READ_FILE_OPS(bt_cmd); |
| 1067 | MVM_DEBUGFS_WRITE_FILE_OPS(power_down_d3_allow); | 1164 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off); |
| 1068 | MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats); | 1165 | MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats); |
| 1069 | MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart); | 1166 | MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart); |
| 1167 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain); | ||
| 1168 | |||
| 1070 | #ifdef CONFIG_PM_SLEEP | 1169 | #ifdef CONFIG_PM_SLEEP |
| 1071 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram); | 1170 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram); |
| 1072 | #endif | 1171 | #endif |
| @@ -1087,10 +1186,14 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) | |||
| 1087 | MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, S_IWUSR | S_IRUSR); | 1186 | MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, S_IWUSR | S_IRUSR); |
| 1088 | MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR); | 1187 | MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR); |
| 1089 | MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR); | 1188 | MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR); |
| 1090 | MVM_DEBUGFS_ADD_FILE(power_down_allow, mvm->debugfs_dir, S_IWUSR); | 1189 | MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR); |
| 1091 | MVM_DEBUGFS_ADD_FILE(power_down_d3_allow, mvm->debugfs_dir, S_IWUSR); | 1190 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD) |
| 1191 | MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir, | ||
| 1192 | S_IRUSR | S_IWUSR); | ||
| 1092 | MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, S_IRUSR); | 1193 | MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, S_IRUSR); |
| 1093 | MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); | 1194 | MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); |
| 1195 | MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir, | ||
| 1196 | S_IWUSR | S_IRUSR); | ||
| 1094 | #ifdef CONFIG_PM_SLEEP | 1197 | #ifdef CONFIG_PM_SLEEP |
| 1095 | MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR); | 1198 | MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR); |
| 1096 | MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, S_IRUSR); | 1199 | MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, S_IRUSR); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h index 05c61d6f384e..4ea5e24ca92d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h | |||
| @@ -82,6 +82,8 @@ | |||
| 82 | * @BT_USE_DEFAULTS: | 82 | * @BT_USE_DEFAULTS: |
| 83 | * @BT_SYNC_2_BT_DISABLE: | 83 | * @BT_SYNC_2_BT_DISABLE: |
| 84 | * @BT_COEX_CORUNNING_TBL_EN: | 84 | * @BT_COEX_CORUNNING_TBL_EN: |
| 85 | * | ||
| 86 | * The COEX_MODE must be set for each command. Even if it is not changed. | ||
| 85 | */ | 87 | */ |
| 86 | enum iwl_bt_coex_flags { | 88 | enum iwl_bt_coex_flags { |
| 87 | BT_CH_PRIMARY_EN = BIT(0), | 89 | BT_CH_PRIMARY_EN = BIT(0), |
| @@ -95,14 +97,16 @@ enum iwl_bt_coex_flags { | |||
| 95 | BT_COEX_NW = 0x3 << BT_COEX_MODE_POS, | 97 | BT_COEX_NW = 0x3 << BT_COEX_MODE_POS, |
| 96 | BT_USE_DEFAULTS = BIT(6), | 98 | BT_USE_DEFAULTS = BIT(6), |
| 97 | BT_SYNC_2_BT_DISABLE = BIT(7), | 99 | BT_SYNC_2_BT_DISABLE = BIT(7), |
| 98 | /* | 100 | BT_COEX_CORUNNING_TBL_EN = BIT(8), |
| 99 | * For future use - when the flags will be enlarged | 101 | BT_COEX_MPLUT_TBL_EN = BIT(9), |
| 100 | * BT_COEX_CORUNNING_TBL_EN = BIT(8), | 102 | /* Bit 10 is reserved */ |
| 101 | */ | 103 | BT_COEX_WF_PRIO_BOOST_CHECK_EN = BIT(11), |
| 102 | }; | 104 | }; |
| 103 | 105 | ||
| 104 | /* | 106 | /* |
| 105 | * indicates what has changed in the BT_COEX command. | 107 | * indicates what has changed in the BT_COEX command. |
| 108 | * BT_VALID_ENABLE must be set for each command. Commands without this bit will | ||
| 109 | * discarded by the firmware | ||
| 106 | */ | 110 | */ |
| 107 | enum iwl_bt_coex_valid_bit_msk { | 111 | enum iwl_bt_coex_valid_bit_msk { |
| 108 | BT_VALID_ENABLE = BIT(0), | 112 | BT_VALID_ENABLE = BIT(0), |
| @@ -121,11 +125,8 @@ enum iwl_bt_coex_valid_bit_msk { | |||
| 121 | BT_VALID_CORUN_LUT_40 = BIT(13), | 125 | BT_VALID_CORUN_LUT_40 = BIT(13), |
| 122 | BT_VALID_ANT_ISOLATION = BIT(14), | 126 | BT_VALID_ANT_ISOLATION = BIT(14), |
| 123 | BT_VALID_ANT_ISOLATION_THRS = BIT(15), | 127 | BT_VALID_ANT_ISOLATION_THRS = BIT(15), |
| 124 | /* | 128 | BT_VALID_TXTX_DELTA_FREQ_THRS = BIT(16), |
| 125 | * For future use - when the valid flags will be enlarged | 129 | BT_VALID_TXRX_MAX_FREQ_0 = BIT(17), |
| 126 | * BT_VALID_TXTX_DELTA_FREQ_THRS = BIT(16), | ||
| 127 | * BT_VALID_TXRX_MAX_FREQ_0 = BIT(17), | ||
| 128 | */ | ||
| 129 | }; | 130 | }; |
| 130 | 131 | ||
| 131 | /** | 132 | /** |
| @@ -142,48 +143,88 @@ enum iwl_bt_reduced_tx_power { | |||
| 142 | BT_REDUCED_TX_POWER_DATA = BIT(1), | 143 | BT_REDUCED_TX_POWER_DATA = BIT(1), |
| 143 | }; | 144 | }; |
| 144 | 145 | ||
| 146 | enum iwl_bt_coex_lut_type { | ||
| 147 | BT_COEX_TIGHT_LUT = 0, | ||
| 148 | BT_COEX_LOOSE_LUT, | ||
| 149 | BT_COEX_TX_DIS_LUT, | ||
| 150 | |||
| 151 | BT_COEX_MAX_LUT, | ||
| 152 | }; | ||
| 153 | |||
| 145 | #define BT_COEX_LUT_SIZE (12) | 154 | #define BT_COEX_LUT_SIZE (12) |
| 155 | #define BT_COEX_CORUN_LUT_SIZE (32) | ||
| 156 | #define BT_COEX_MULTI_PRIO_LUT_SIZE (2) | ||
| 157 | #define BT_COEX_BOOST_SIZE (4) | ||
| 158 | #define BT_REDUCED_TX_POWER_BIT BIT(7) | ||
| 146 | 159 | ||
| 147 | /** | 160 | /** |
| 148 | * struct iwl_bt_coex_cmd - bt coex configuration command | 161 | * struct iwl_bt_coex_cmd - bt coex configuration command |
| 149 | * @flags:&enum iwl_bt_coex_flags | 162 | * @flags:&enum iwl_bt_coex_flags |
| 150 | * @lead_time: | ||
| 151 | * @max_kill: | 163 | * @max_kill: |
| 152 | * @bt3_time_t7_value: | ||
| 153 | * @kill_ack_msk: | ||
| 154 | * @kill_cts_msk: | ||
| 155 | * @bt3_prio_sample_time: | ||
| 156 | * @bt3_timer_t2_value: | ||
| 157 | * @bt4_reaction_time: | ||
| 158 | * @decision_lut[12]: | ||
| 159 | * @bt_reduced_tx_power: enum %iwl_bt_reduced_tx_power | 164 | * @bt_reduced_tx_power: enum %iwl_bt_reduced_tx_power |
| 160 | * @valid_bit_msk: enum %iwl_bt_coex_valid_bit_msk | 165 | * @bt4_antenna_isolation: |
| 161 | * @bt_prio_boost: values for PTA boost register | 166 | * @bt4_antenna_isolation_thr: |
| 167 | * @bt4_tx_tx_delta_freq_thr: | ||
| 168 | * @bt4_tx_rx_max_freq0: | ||
| 169 | * @bt_prio_boost: | ||
| 162 | * @wifi_tx_prio_boost: SW boost of wifi tx priority | 170 | * @wifi_tx_prio_boost: SW boost of wifi tx priority |
| 163 | * @wifi_rx_prio_boost: SW boost of wifi rx priority | 171 | * @wifi_rx_prio_boost: SW boost of wifi rx priority |
| 172 | * @kill_ack_msk: | ||
| 173 | * @kill_cts_msk: | ||
| 174 | * @decision_lut: | ||
| 175 | * @bt4_multiprio_lut: | ||
| 176 | * @bt4_corun_lut20: | ||
| 177 | * @bt4_corun_lut40: | ||
| 178 | * @valid_bit_msk: enum %iwl_bt_coex_valid_bit_msk | ||
| 164 | * | 179 | * |
| 165 | * The structure is used for the BT_COEX command. | 180 | * The structure is used for the BT_COEX command. |
| 166 | */ | 181 | */ |
| 167 | struct iwl_bt_coex_cmd { | 182 | struct iwl_bt_coex_cmd { |
| 168 | u8 flags; | 183 | __le32 flags; |
| 169 | u8 lead_time; | ||
| 170 | u8 max_kill; | 184 | u8 max_kill; |
| 171 | u8 bt3_time_t7_value; | 185 | u8 bt_reduced_tx_power; |
| 186 | u8 reserved[2]; | ||
| 187 | |||
| 188 | u8 bt4_antenna_isolation; | ||
| 189 | u8 bt4_antenna_isolation_thr; | ||
| 190 | u8 bt4_tx_tx_delta_freq_thr; | ||
| 191 | u8 bt4_tx_rx_max_freq0; | ||
| 192 | |||
| 193 | __le32 bt_prio_boost[BT_COEX_BOOST_SIZE]; | ||
| 194 | __le32 wifi_tx_prio_boost; | ||
| 195 | __le32 wifi_rx_prio_boost; | ||
| 172 | __le32 kill_ack_msk; | 196 | __le32 kill_ack_msk; |
| 173 | __le32 kill_cts_msk; | 197 | __le32 kill_cts_msk; |
| 174 | u8 bt3_prio_sample_time; | 198 | |
| 175 | u8 bt3_timer_t2_value; | 199 | __le32 decision_lut[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE]; |
| 176 | __le16 bt4_reaction_time; | 200 | __le32 bt4_multiprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE]; |
| 177 | __le32 decision_lut[BT_COEX_LUT_SIZE]; | 201 | __le32 bt4_corun_lut20[BT_COEX_CORUN_LUT_SIZE]; |
| 178 | u8 bt_reduced_tx_power; | 202 | __le32 bt4_corun_lut40[BT_COEX_CORUN_LUT_SIZE]; |
| 179 | u8 reserved; | 203 | |
| 180 | __le16 valid_bit_msk; | 204 | __le32 valid_bit_msk; |
| 181 | __le32 bt_prio_boost; | ||
| 182 | u8 reserved2; | ||
| 183 | u8 wifi_tx_prio_boost; | ||
| 184 | __le16 wifi_rx_prio_boost; | ||
| 185 | } __packed; /* BT_COEX_CMD_API_S_VER_3 */ | 205 | } __packed; /* BT_COEX_CMD_API_S_VER_3 */ |
| 186 | 206 | ||
| 207 | /** | ||
| 208 | * struct iwl_bt_coex_ci_cmd - bt coex channel inhibition command | ||
| 209 | * @bt_primary_ci: | ||
| 210 | * @bt_secondary_ci: | ||
| 211 | * @co_run_bw_primary: | ||
| 212 | * @co_run_bw_secondary: | ||
| 213 | * @primary_ch_phy_id: | ||
| 214 | * @secondary_ch_phy_id: | ||
| 215 | * | ||
| 216 | * Used for BT_COEX_CI command | ||
| 217 | */ | ||
| 218 | struct iwl_bt_coex_ci_cmd { | ||
| 219 | __le64 bt_primary_ci; | ||
| 220 | __le64 bt_secondary_ci; | ||
| 221 | |||
| 222 | u8 co_run_bw_primary; | ||
| 223 | u8 co_run_bw_secondary; | ||
| 224 | u8 primary_ch_phy_id; | ||
| 225 | u8 secondary_ch_phy_id; | ||
| 226 | } __packed; /* BT_CI_MSG_API_S_VER_1 */ | ||
| 227 | |||
| 187 | #define BT_MBOX(n_dw, _msg, _pos, _nbits) \ | 228 | #define BT_MBOX(n_dw, _msg, _pos, _nbits) \ |
| 188 | BT_MBOX##n_dw##_##_msg##_POS = (_pos), \ | 229 | BT_MBOX##n_dw##_##_msg##_POS = (_pos), \ |
| 189 | BT_MBOX##n_dw##_##_msg = BITS(_nbits) << BT_MBOX##n_dw##_##_msg##_POS | 230 | BT_MBOX##n_dw##_##_msg = BITS(_nbits) << BT_MBOX##n_dw##_##_msg##_POS |
| @@ -244,23 +285,39 @@ enum iwl_bt_mxbox_dw3 { | |||
| 244 | ((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\ | 285 | ((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\ |
| 245 | >> BT_MBOX##_num##_##_field##_POS) | 286 | >> BT_MBOX##_num##_##_field##_POS) |
| 246 | 287 | ||
| 288 | enum iwl_bt_activity_grading { | ||
| 289 | BT_OFF = 0, | ||
| 290 | BT_ON_NO_CONNECTION = 1, | ||
| 291 | BT_LOW_TRAFFIC = 2, | ||
| 292 | BT_HIGH_TRAFFIC = 3, | ||
| 293 | }; | ||
| 294 | |||
| 247 | /** | 295 | /** |
| 248 | * struct iwl_bt_coex_profile_notif - notification about BT coex | 296 | * struct iwl_bt_coex_profile_notif - notification about BT coex |
| 249 | * @mbox_msg: message from BT to WiFi | 297 | * @mbox_msg: message from BT to WiFi |
| 250 | * @:bt_status: 0 - off, 1 - on | 298 | * @msg_idx: the index of the message |
| 251 | * @:bt_open_conn: number of BT connections open | 299 | * @bt_status: 0 - off, 1 - on |
| 252 | * @:bt_traffic_load: load of BT traffic | 300 | * @bt_open_conn: number of BT connections open |
| 253 | * @:bt_agg_traffic_load: aggregated load of BT traffic | 301 | * @bt_traffic_load: load of BT traffic |
| 254 | * @:bt_ci_compliance: 0 - no CI compliance, 1 - CI compliant | 302 | * @bt_agg_traffic_load: aggregated load of BT traffic |
| 303 | * @bt_ci_compliance: 0 - no CI compliance, 1 - CI compliant | ||
| 304 | * @primary_ch_lut: LUT used for primary channel | ||
| 305 | * @secondary_ch_lut: LUT used for secondary channel | ||
| 306 | * @bt_activity_grading: the activity of BT enum %iwl_bt_activity_grading | ||
| 255 | */ | 307 | */ |
| 256 | struct iwl_bt_coex_profile_notif { | 308 | struct iwl_bt_coex_profile_notif { |
| 257 | __le32 mbox_msg[4]; | 309 | __le32 mbox_msg[4]; |
| 310 | __le32 msg_idx; | ||
| 258 | u8 bt_status; | 311 | u8 bt_status; |
| 259 | u8 bt_open_conn; | 312 | u8 bt_open_conn; |
| 260 | u8 bt_traffic_load; | 313 | u8 bt_traffic_load; |
| 261 | u8 bt_agg_traffic_load; | 314 | u8 bt_agg_traffic_load; |
| 262 | u8 bt_ci_compliance; | 315 | u8 bt_ci_compliance; |
| 263 | u8 reserved[3]; | 316 | u8 reserved[3]; |
| 317 | |||
| 318 | __le32 primary_ch_lut; | ||
| 319 | __le32 secondary_ch_lut; | ||
| 320 | __le32 bt_activity_grading; | ||
| 264 | } __packed; /* BT_COEX_PROFILE_NTFY_API_S_VER_2 */ | 321 | } __packed; /* BT_COEX_PROFILE_NTFY_API_S_VER_2 */ |
| 265 | 322 | ||
| 266 | enum iwl_bt_coex_prio_table_event { | 323 | enum iwl_bt_coex_prio_table_event { |
| @@ -300,20 +357,4 @@ struct iwl_bt_coex_prio_tbl_cmd { | |||
| 300 | u8 prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX]; | 357 | u8 prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX]; |
| 301 | } __packed; | 358 | } __packed; |
| 302 | 359 | ||
| 303 | enum iwl_bt_coex_env_action { | ||
| 304 | BT_COEX_ENV_CLOSE = 0, | ||
| 305 | BT_COEX_ENV_OPEN = 1, | ||
| 306 | }; /* BT_COEX_PROT_ENV_ACTION_API_E_VER_1 */ | ||
| 307 | |||
| 308 | /** | ||
| 309 | * struct iwl_bt_coex_prot_env_cmd - BT Protection Envelope | ||
| 310 | * @action: enum %iwl_bt_coex_env_action | ||
| 311 | * @type: enum %iwl_bt_coex_prio_table_event | ||
| 312 | */ | ||
| 313 | struct iwl_bt_coex_prot_env_cmd { | ||
| 314 | u8 action; /* 0 = closed, 1 = open */ | ||
| 315 | u8 type; /* 0 .. 15 */ | ||
| 316 | u8 reserved[2]; | ||
| 317 | } __packed; | ||
| 318 | |||
| 319 | #endif /* __fw_api_bt_coex_h__ */ | 360 | #endif /* __fw_api_bt_coex_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h index df72fcdf8170..4e7dd8cf87dc 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h | |||
| @@ -100,7 +100,12 @@ enum iwl_proto_offloads { | |||
| 100 | 100 | ||
| 101 | #define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1 2 | 101 | #define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1 2 |
| 102 | #define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2 6 | 102 | #define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2 6 |
| 103 | #define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX 6 | 103 | #define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3L 12 |
| 104 | #define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3S 4 | ||
| 105 | #define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX 12 | ||
| 106 | |||
| 107 | #define IWL_PROTO_OFFLOAD_NUM_NS_CONFIG_V3L 4 | ||
| 108 | #define IWL_PROTO_OFFLOAD_NUM_NS_CONFIG_V3S 2 | ||
| 104 | 109 | ||
| 105 | /** | 110 | /** |
| 106 | * struct iwl_proto_offload_cmd_common - ARP/NS offload common part | 111 | * struct iwl_proto_offload_cmd_common - ARP/NS offload common part |
| @@ -155,6 +160,43 @@ struct iwl_proto_offload_cmd_v2 { | |||
| 155 | u8 reserved2[3]; | 160 | u8 reserved2[3]; |
| 156 | } __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_2 */ | 161 | } __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_2 */ |
| 157 | 162 | ||
| 163 | struct iwl_ns_config { | ||
| 164 | struct in6_addr source_ipv6_addr; | ||
| 165 | struct in6_addr dest_ipv6_addr; | ||
| 166 | u8 target_mac_addr[ETH_ALEN]; | ||
| 167 | __le16 reserved; | ||
| 168 | } __packed; /* NS_OFFLOAD_CONFIG */ | ||
| 169 | |||
| 170 | struct iwl_targ_addr { | ||
| 171 | struct in6_addr addr; | ||
| 172 | __le32 config_num; | ||
| 173 | } __packed; /* TARGET_IPV6_ADDRESS */ | ||
| 174 | |||
| 175 | /** | ||
| 176 | * struct iwl_proto_offload_cmd_v3_small - ARP/NS offload configuration | ||
| 177 | * @common: common/IPv4 configuration | ||
| 178 | * @target_ipv6_addr: target IPv6 addresses | ||
| 179 | * @ns_config: NS offload configurations | ||
| 180 | */ | ||
| 181 | struct iwl_proto_offload_cmd_v3_small { | ||
| 182 | struct iwl_proto_offload_cmd_common common; | ||
| 183 | __le32 num_valid_ipv6_addrs; | ||
| 184 | struct iwl_targ_addr targ_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3S]; | ||
| 185 | struct iwl_ns_config ns_config[IWL_PROTO_OFFLOAD_NUM_NS_CONFIG_V3S]; | ||
| 186 | } __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_3 */ | ||
| 187 | |||
| 188 | /** | ||
| 189 | * struct iwl_proto_offload_cmd_v3_large - ARP/NS offload configuration | ||
| 190 | * @common: common/IPv4 configuration | ||
| 191 | * @target_ipv6_addr: target IPv6 addresses | ||
| 192 | * @ns_config: NS offload configurations | ||
| 193 | */ | ||
| 194 | struct iwl_proto_offload_cmd_v3_large { | ||
| 195 | struct iwl_proto_offload_cmd_common common; | ||
| 196 | __le32 num_valid_ipv6_addrs; | ||
| 197 | struct iwl_targ_addr targ_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3L]; | ||
| 198 | struct iwl_ns_config ns_config[IWL_PROTO_OFFLOAD_NUM_NS_CONFIG_V3L]; | ||
| 199 | } __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_3 */ | ||
| 158 | 200 | ||
| 159 | /* | 201 | /* |
| 160 | * WOWLAN_PATTERNS | 202 | * WOWLAN_PATTERNS |
| @@ -293,7 +335,7 @@ enum iwl_wowlan_wakeup_reason { | |||
| 293 | IWL_WOWLAN_WAKEUP_BY_REM_WAKE_WAKEUP_PACKET = BIT(12), | 335 | IWL_WOWLAN_WAKEUP_BY_REM_WAKE_WAKEUP_PACKET = BIT(12), |
| 294 | }; /* WOWLAN_WAKE_UP_REASON_API_E_VER_2 */ | 336 | }; /* WOWLAN_WAKE_UP_REASON_API_E_VER_2 */ |
| 295 | 337 | ||
| 296 | struct iwl_wowlan_status { | 338 | struct iwl_wowlan_status_v4 { |
| 297 | __le64 replay_ctr; | 339 | __le64 replay_ctr; |
| 298 | __le16 pattern_number; | 340 | __le16 pattern_number; |
| 299 | __le16 non_qos_seq_ctr; | 341 | __le16 non_qos_seq_ctr; |
| @@ -308,6 +350,29 @@ struct iwl_wowlan_status { | |||
| 308 | u8 wake_packet[]; /* can be truncated from _length to _bufsize */ | 350 | u8 wake_packet[]; /* can be truncated from _length to _bufsize */ |
| 309 | } __packed; /* WOWLAN_STATUSES_API_S_VER_4 */ | 351 | } __packed; /* WOWLAN_STATUSES_API_S_VER_4 */ |
| 310 | 352 | ||
| 353 | struct iwl_wowlan_gtk_status { | ||
| 354 | u8 key_index; | ||
| 355 | u8 reserved[3]; | ||
| 356 | u8 decrypt_key[16]; | ||
| 357 | u8 tkip_mic_key[8]; | ||
| 358 | struct iwl_wowlan_rsc_tsc_params_cmd rsc; | ||
| 359 | } __packed; | ||
| 360 | |||
| 361 | struct iwl_wowlan_status_v6 { | ||
| 362 | struct iwl_wowlan_gtk_status gtk; | ||
| 363 | __le64 replay_ctr; | ||
| 364 | __le16 pattern_number; | ||
| 365 | __le16 non_qos_seq_ctr; | ||
| 366 | __le16 qos_seq_ctr[8]; | ||
| 367 | __le32 wakeup_reasons; | ||
| 368 | __le32 num_of_gtk_rekeys; | ||
| 369 | __le32 transmitted_ndps; | ||
| 370 | __le32 received_beacons; | ||
| 371 | __le32 wake_packet_length; | ||
| 372 | __le32 wake_packet_bufsize; | ||
| 373 | u8 wake_packet[]; /* can be truncated from _length to _bufsize */ | ||
| 374 | } __packed; /* WOWLAN_STATUSES_API_S_VER_6 */ | ||
| 375 | |||
| 311 | #define IWL_WOWLAN_TCP_MAX_PACKET_LEN 64 | 376 | #define IWL_WOWLAN_TCP_MAX_PACKET_LEN 64 |
| 312 | #define IWL_WOWLAN_REMOTE_WAKE_MAX_PACKET_LEN 128 | 377 | #define IWL_WOWLAN_REMOTE_WAKE_MAX_PACKET_LEN 128 |
| 313 | #define IWL_WOWLAN_REMOTE_WAKE_MAX_TOKENS 2048 | 378 | #define IWL_WOWLAN_REMOTE_WAKE_MAX_TOKENS 2048 |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h index 98b1feb43d38..39c3148bdfa8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h | |||
| @@ -170,12 +170,14 @@ struct iwl_mac_data_ap { | |||
| 170 | * @beacon_tsf: beacon transmit time in TSF | 170 | * @beacon_tsf: beacon transmit time in TSF |
| 171 | * @bi: beacon interval in TU | 171 | * @bi: beacon interval in TU |
| 172 | * @bi_reciprocal: 2^32 / bi | 172 | * @bi_reciprocal: 2^32 / bi |
| 173 | * @beacon_template: beacon template ID | ||
| 173 | */ | 174 | */ |
| 174 | struct iwl_mac_data_ibss { | 175 | struct iwl_mac_data_ibss { |
| 175 | __le32 beacon_time; | 176 | __le32 beacon_time; |
| 176 | __le64 beacon_tsf; | 177 | __le64 beacon_tsf; |
| 177 | __le32 bi; | 178 | __le32 bi; |
| 178 | __le32 bi_reciprocal; | 179 | __le32 bi_reciprocal; |
| 180 | __le32 beacon_template; | ||
| 179 | } __packed; /* IBSS_MAC_DATA_API_S_VER_1 */ | 181 | } __packed; /* IBSS_MAC_DATA_API_S_VER_1 */ |
| 180 | 182 | ||
| 181 | /** | 183 | /** |
| @@ -372,4 +374,13 @@ static inline u32 iwl_mvm_reciprocal(u32 v) | |||
| 372 | return 0xFFFFFFFF / v; | 374 | return 0xFFFFFFFF / v; |
| 373 | } | 375 | } |
| 374 | 376 | ||
| 377 | #define IWL_NONQOS_SEQ_GET 0x1 | ||
| 378 | #define IWL_NONQOS_SEQ_SET 0x2 | ||
| 379 | struct iwl_nonqos_seq_query_cmd { | ||
| 380 | __le32 get_set_flag; | ||
| 381 | __le32 mac_id_n_color; | ||
| 382 | __le16 value; | ||
| 383 | __le16 reserved; | ||
| 384 | } __packed; /* NON_QOS_TX_COUNTER_GET_SET_API_S_VER_1 */ | ||
| 385 | |||
| 375 | #endif /* __fw_api_mac_h__ */ | 386 | #endif /* __fw_api_mac_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h index 8e7ab41079ca..5cb93ae5cd2f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h | |||
| @@ -132,6 +132,33 @@ struct iwl_powertable_cmd { | |||
| 132 | } __packed; | 132 | } __packed; |
| 133 | 133 | ||
| 134 | /** | 134 | /** |
| 135 | * enum iwl_device_power_flags - masks for device power command flags | ||
| 136 | * @DEVIC_POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off | ||
| 137 | * receiver and transmitter. '0' - does not allow. This flag should be | ||
| 138 | * always set to '1' unless one need to disable actual power down for debug | ||
| 139 | * purposes. | ||
| 140 | * @DEVICE_POWER_FLAGS_CAM_MSK: '1' CAM (Continuous Active Mode) is set, meaning | ||
| 141 | * that power management is disabled. '0' Power management is enabled, one | ||
| 142 | * of power schemes is applied. | ||
| 143 | */ | ||
| 144 | enum iwl_device_power_flags { | ||
| 145 | DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0), | ||
| 146 | DEVICE_POWER_FLAGS_CAM_MSK = BIT(13), | ||
| 147 | }; | ||
| 148 | |||
| 149 | /** | ||
| 150 | * struct iwl_device_power_cmd - device wide power command. | ||
| 151 | * DEVICE_POWER_CMD = 0x77 (command, has simple generic response) | ||
| 152 | * | ||
| 153 | * @flags: Power table command flags from DEVICE_POWER_FLAGS_* | ||
| 154 | */ | ||
| 155 | struct iwl_device_power_cmd { | ||
| 156 | /* PM_POWER_TABLE_CMD_API_S_VER_6 */ | ||
| 157 | __le16 flags; | ||
| 158 | __le16 reserved; | ||
| 159 | } __packed; | ||
| 160 | |||
| 161 | /** | ||
| 135 | * struct iwl_mac_power_cmd - New power command containing uAPSD support | 162 | * struct iwl_mac_power_cmd - New power command containing uAPSD support |
| 136 | * MAC_PM_POWER_TABLE = 0xA9 (command, has simple generic response) | 163 | * MAC_PM_POWER_TABLE = 0xA9 (command, has simple generic response) |
| 137 | * @id_and_color: MAC contex identifier | 164 | * @id_and_color: MAC contex identifier |
| @@ -290,7 +317,7 @@ struct iwl_beacon_filter_cmd { | |||
| 290 | #define IWL_BF_ESCAPE_TIMER_MIN 0 | 317 | #define IWL_BF_ESCAPE_TIMER_MIN 0 |
| 291 | 318 | ||
| 292 | #define IWL_BA_ESCAPE_TIMER_DEFAULT 6 | 319 | #define IWL_BA_ESCAPE_TIMER_DEFAULT 6 |
| 293 | #define IWL_BA_ESCAPE_TIMER_D3 6 | 320 | #define IWL_BA_ESCAPE_TIMER_D3 9 |
| 294 | #define IWL_BA_ESCAPE_TIMER_MAX 1024 | 321 | #define IWL_BA_ESCAPE_TIMER_MAX 1024 |
| 295 | #define IWL_BA_ESCAPE_TIMER_MIN 0 | 322 | #define IWL_BA_ESCAPE_TIMER_MIN 0 |
| 296 | 323 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h index fdd33bc0a594..538f1c7a5966 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h | |||
| @@ -68,6 +68,7 @@ | |||
| 68 | /* | 68 | /* |
| 69 | * These serve as indexes into | 69 | * These serve as indexes into |
| 70 | * struct iwl_rate_info fw_rate_idx_to_plcp[IWL_RATE_COUNT]; | 70 | * struct iwl_rate_info fw_rate_idx_to_plcp[IWL_RATE_COUNT]; |
| 71 | * TODO: avoid overlap between legacy and HT rates | ||
| 71 | */ | 72 | */ |
| 72 | enum { | 73 | enum { |
| 73 | IWL_RATE_1M_INDEX = 0, | 74 | IWL_RATE_1M_INDEX = 0, |
| @@ -78,18 +79,31 @@ enum { | |||
| 78 | IWL_LAST_CCK_RATE = IWL_RATE_11M_INDEX, | 79 | IWL_LAST_CCK_RATE = IWL_RATE_11M_INDEX, |
| 79 | IWL_RATE_6M_INDEX, | 80 | IWL_RATE_6M_INDEX, |
| 80 | IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX, | 81 | IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX, |
| 82 | IWL_RATE_MCS_0_INDEX = IWL_RATE_6M_INDEX, | ||
| 83 | IWL_FIRST_HT_RATE = IWL_RATE_MCS_0_INDEX, | ||
| 84 | IWL_FIRST_VHT_RATE = IWL_RATE_MCS_0_INDEX, | ||
| 81 | IWL_RATE_9M_INDEX, | 85 | IWL_RATE_9M_INDEX, |
| 82 | IWL_RATE_12M_INDEX, | 86 | IWL_RATE_12M_INDEX, |
| 87 | IWL_RATE_MCS_1_INDEX = IWL_RATE_12M_INDEX, | ||
| 83 | IWL_RATE_18M_INDEX, | 88 | IWL_RATE_18M_INDEX, |
| 89 | IWL_RATE_MCS_2_INDEX = IWL_RATE_18M_INDEX, | ||
| 84 | IWL_RATE_24M_INDEX, | 90 | IWL_RATE_24M_INDEX, |
| 91 | IWL_RATE_MCS_3_INDEX = IWL_RATE_24M_INDEX, | ||
| 85 | IWL_RATE_36M_INDEX, | 92 | IWL_RATE_36M_INDEX, |
| 93 | IWL_RATE_MCS_4_INDEX = IWL_RATE_36M_INDEX, | ||
| 86 | IWL_RATE_48M_INDEX, | 94 | IWL_RATE_48M_INDEX, |
| 95 | IWL_RATE_MCS_5_INDEX = IWL_RATE_48M_INDEX, | ||
| 87 | IWL_RATE_54M_INDEX, | 96 | IWL_RATE_54M_INDEX, |
| 97 | IWL_RATE_MCS_6_INDEX = IWL_RATE_54M_INDEX, | ||
| 88 | IWL_LAST_NON_HT_RATE = IWL_RATE_54M_INDEX, | 98 | IWL_LAST_NON_HT_RATE = IWL_RATE_54M_INDEX, |
| 89 | IWL_RATE_60M_INDEX, | 99 | IWL_RATE_60M_INDEX, |
| 90 | IWL_LAST_OFDM_RATE = IWL_RATE_60M_INDEX, | 100 | IWL_RATE_MCS_7_INDEX = IWL_RATE_60M_INDEX, |
| 101 | IWL_LAST_HT_RATE = IWL_RATE_MCS_7_INDEX, | ||
| 102 | IWL_RATE_MCS_8_INDEX, | ||
| 103 | IWL_RATE_MCS_9_INDEX, | ||
| 104 | IWL_LAST_VHT_RATE = IWL_RATE_MCS_9_INDEX, | ||
| 91 | IWL_RATE_COUNT_LEGACY = IWL_LAST_NON_HT_RATE + 1, | 105 | IWL_RATE_COUNT_LEGACY = IWL_LAST_NON_HT_RATE + 1, |
| 92 | IWL_RATE_COUNT, | 106 | IWL_RATE_COUNT = IWL_LAST_VHT_RATE + 1, |
| 93 | }; | 107 | }; |
| 94 | 108 | ||
| 95 | #define IWL_RATE_BIT_MSK(r) BIT(IWL_RATE_##r##M_INDEX) | 109 | #define IWL_RATE_BIT_MSK(r) BIT(IWL_RATE_##r##M_INDEX) |
| @@ -108,6 +122,7 @@ enum { | |||
| 108 | IWL_RATE_2M_PLCP = 20, | 122 | IWL_RATE_2M_PLCP = 20, |
| 109 | IWL_RATE_5M_PLCP = 55, | 123 | IWL_RATE_5M_PLCP = 55, |
| 110 | IWL_RATE_11M_PLCP = 110, | 124 | IWL_RATE_11M_PLCP = 110, |
| 125 | IWL_RATE_INVM_PLCP = -1, | ||
| 111 | }; | 126 | }; |
| 112 | 127 | ||
| 113 | /* | 128 | /* |
| @@ -164,6 +179,8 @@ enum { | |||
| 164 | * which is the duplicate 20 MHz MCS (bit 5 set, all others zero.) | 179 | * which is the duplicate 20 MHz MCS (bit 5 set, all others zero.) |
| 165 | */ | 180 | */ |
| 166 | #define RATE_HT_MCS_RATE_CODE_MSK 0x7 | 181 | #define RATE_HT_MCS_RATE_CODE_MSK 0x7 |
| 182 | #define RATE_HT_MCS_NSS_POS 3 | ||
| 183 | #define RATE_HT_MCS_NSS_MSK (3 << RATE_HT_MCS_NSS_POS) | ||
| 167 | 184 | ||
| 168 | /* Bit 10: (1) Use Green Field preamble */ | 185 | /* Bit 10: (1) Use Green Field preamble */ |
| 169 | #define RATE_HT_MCS_GF_POS 10 | 186 | #define RATE_HT_MCS_GF_POS 10 |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h index 83cb9b992ea4..c3782b48ded1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h | |||
| @@ -356,6 +356,7 @@ struct iwl_scan_complete_notif { | |||
| 356 | /* scan offload */ | 356 | /* scan offload */ |
| 357 | #define IWL_MAX_SCAN_CHANNELS 40 | 357 | #define IWL_MAX_SCAN_CHANNELS 40 |
| 358 | #define IWL_SCAN_MAX_BLACKLIST_LEN 64 | 358 | #define IWL_SCAN_MAX_BLACKLIST_LEN 64 |
| 359 | #define IWL_SCAN_SHORT_BLACKLIST_LEN 16 | ||
| 359 | #define IWL_SCAN_MAX_PROFILES 11 | 360 | #define IWL_SCAN_MAX_PROFILES 11 |
| 360 | #define SCAN_OFFLOAD_PROBE_REQ_SIZE 512 | 361 | #define SCAN_OFFLOAD_PROBE_REQ_SIZE 512 |
| 361 | 362 | ||
| @@ -368,6 +369,12 @@ struct iwl_scan_complete_notif { | |||
| 368 | #define IWL_FULL_SCAN_MULTIPLIER 5 | 369 | #define IWL_FULL_SCAN_MULTIPLIER 5 |
| 369 | #define IWL_FAST_SCHED_SCAN_ITERATIONS 3 | 370 | #define IWL_FAST_SCHED_SCAN_ITERATIONS 3 |
| 370 | 371 | ||
| 372 | enum scan_framework_client { | ||
| 373 | SCAN_CLIENT_SCHED_SCAN = BIT(0), | ||
| 374 | SCAN_CLIENT_NETDETECT = BIT(1), | ||
| 375 | SCAN_CLIENT_ASSET_TRACKING = BIT(2), | ||
| 376 | }; | ||
| 377 | |||
| 371 | /** | 378 | /** |
| 372 | * struct iwl_scan_offload_cmd - SCAN_REQUEST_FIXED_PART_API_S_VER_6 | 379 | * struct iwl_scan_offload_cmd - SCAN_REQUEST_FIXED_PART_API_S_VER_6 |
| 373 | * @scan_flags: see enum iwl_scan_flags | 380 | * @scan_flags: see enum iwl_scan_flags |
| @@ -449,11 +456,12 @@ struct iwl_scan_offload_cfg { | |||
| 449 | * iwl_scan_offload_blacklist - SCAN_OFFLOAD_BLACKLIST_S | 456 | * iwl_scan_offload_blacklist - SCAN_OFFLOAD_BLACKLIST_S |
| 450 | * @ssid: MAC address to filter out | 457 | * @ssid: MAC address to filter out |
| 451 | * @reported_rssi: AP rssi reported to the host | 458 | * @reported_rssi: AP rssi reported to the host |
| 459 | * @client_bitmap: clients ignore this entry - enum scan_framework_client | ||
| 452 | */ | 460 | */ |
| 453 | struct iwl_scan_offload_blacklist { | 461 | struct iwl_scan_offload_blacklist { |
| 454 | u8 ssid[ETH_ALEN]; | 462 | u8 ssid[ETH_ALEN]; |
| 455 | u8 reported_rssi; | 463 | u8 reported_rssi; |
| 456 | u8 reserved; | 464 | u8 client_bitmap; |
| 457 | } __packed; | 465 | } __packed; |
| 458 | 466 | ||
| 459 | enum iwl_scan_offload_network_type { | 467 | enum iwl_scan_offload_network_type { |
| @@ -475,6 +483,7 @@ enum iwl_scan_offload_band_selection { | |||
| 475 | * @aut_alg: authentication olgorithm to match - bitmap | 483 | * @aut_alg: authentication olgorithm to match - bitmap |
| 476 | * @network_type: enum iwl_scan_offload_network_type | 484 | * @network_type: enum iwl_scan_offload_network_type |
| 477 | * @band_selection: enum iwl_scan_offload_band_selection | 485 | * @band_selection: enum iwl_scan_offload_band_selection |
| 486 | * @client_bitmap: clients waiting for match - enum scan_framework_client | ||
| 478 | */ | 487 | */ |
| 479 | struct iwl_scan_offload_profile { | 488 | struct iwl_scan_offload_profile { |
| 480 | u8 ssid_index; | 489 | u8 ssid_index; |
| @@ -482,7 +491,8 @@ struct iwl_scan_offload_profile { | |||
| 482 | u8 auth_alg; | 491 | u8 auth_alg; |
| 483 | u8 network_type; | 492 | u8 network_type; |
| 484 | u8 band_selection; | 493 | u8 band_selection; |
| 485 | u8 reserved[3]; | 494 | u8 client_bitmap; |
| 495 | u8 reserved[2]; | ||
| 486 | } __packed; | 496 | } __packed; |
| 487 | 497 | ||
| 488 | /** | 498 | /** |
| @@ -491,13 +501,18 @@ struct iwl_scan_offload_profile { | |||
| 491 | * @profiles: profiles to search for match | 501 | * @profiles: profiles to search for match |
| 492 | * @blacklist_len: length of blacklist | 502 | * @blacklist_len: length of blacklist |
| 493 | * @num_profiles: num of profiles in the list | 503 | * @num_profiles: num of profiles in the list |
| 504 | * @match_notify: clients waiting for match found notification | ||
| 505 | * @pass_match: clients waiting for the results | ||
| 506 | * @active_clients: active clients bitmap - enum scan_framework_client | ||
| 494 | */ | 507 | */ |
| 495 | struct iwl_scan_offload_profile_cfg { | 508 | struct iwl_scan_offload_profile_cfg { |
| 496 | struct iwl_scan_offload_blacklist blacklist[IWL_SCAN_MAX_BLACKLIST_LEN]; | ||
| 497 | struct iwl_scan_offload_profile profiles[IWL_SCAN_MAX_PROFILES]; | 509 | struct iwl_scan_offload_profile profiles[IWL_SCAN_MAX_PROFILES]; |
| 498 | u8 blacklist_len; | 510 | u8 blacklist_len; |
| 499 | u8 num_profiles; | 511 | u8 num_profiles; |
| 500 | u8 reserved[2]; | 512 | u8 match_notify; |
| 513 | u8 pass_match; | ||
| 514 | u8 active_clients; | ||
| 515 | u8 reserved[3]; | ||
| 501 | } __packed; | 516 | } __packed; |
| 502 | 517 | ||
| 503 | /** | 518 | /** |
| @@ -560,4 +575,15 @@ struct iwl_scan_offload_complete { | |||
| 560 | u8 reserved; | 575 | u8 reserved; |
| 561 | } __packed; | 576 | } __packed; |
| 562 | 577 | ||
| 578 | /** | ||
| 579 | * iwl_sched_scan_results - SCAN_OFFLOAD_MATCH_FOUND_NTF_API_S_VER_1 | ||
| 580 | * @ssid_bitmap: SSIDs indexes found in this iteration | ||
| 581 | * @client_bitmap: clients that are active and wait for this notification | ||
| 582 | */ | ||
| 583 | struct iwl_sched_scan_results { | ||
| 584 | __le16 ssid_bitmap; | ||
| 585 | u8 client_bitmap; | ||
| 586 | u8 reserved; | ||
| 587 | }; | ||
| 588 | |||
| 563 | #endif | 589 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h index a30691a8a85b..4aca5933a65d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h | |||
| @@ -247,7 +247,7 @@ struct iwl_mvm_keyinfo { | |||
| 247 | } __packed; | 247 | } __packed; |
| 248 | 248 | ||
| 249 | /** | 249 | /** |
| 250 | * struct iwl_mvm_add_sta_cmd - Add / modify a station in the fw's station table | 250 | * struct iwl_mvm_add_sta_cmd_v5 - Add/modify a station in the fw's sta table. |
| 251 | * ( REPLY_ADD_STA = 0x18 ) | 251 | * ( REPLY_ADD_STA = 0x18 ) |
| 252 | * @add_modify: 1: modify existing, 0: add new station | 252 | * @add_modify: 1: modify existing, 0: add new station |
| 253 | * @unicast_tx_key_id: unicast tx key id. Relevant only when unicast key sent | 253 | * @unicast_tx_key_id: unicast tx key id. Relevant only when unicast key sent |
| @@ -286,7 +286,7 @@ struct iwl_mvm_keyinfo { | |||
| 286 | * ADD_STA sets up the table entry for one station, either creating a new | 286 | * ADD_STA sets up the table entry for one station, either creating a new |
| 287 | * entry, or modifying a pre-existing one. | 287 | * entry, or modifying a pre-existing one. |
| 288 | */ | 288 | */ |
| 289 | struct iwl_mvm_add_sta_cmd { | 289 | struct iwl_mvm_add_sta_cmd_v5 { |
| 290 | u8 add_modify; | 290 | u8 add_modify; |
| 291 | u8 unicast_tx_key_id; | 291 | u8 unicast_tx_key_id; |
| 292 | u8 multicast_tx_key_id; | 292 | u8 multicast_tx_key_id; |
| @@ -313,6 +313,57 @@ struct iwl_mvm_add_sta_cmd { | |||
| 313 | } __packed; /* ADD_STA_CMD_API_S_VER_5 */ | 313 | } __packed; /* ADD_STA_CMD_API_S_VER_5 */ |
| 314 | 314 | ||
| 315 | /** | 315 | /** |
| 316 | * struct iwl_mvm_add_sta_cmd_v6 - Add / modify a station | ||
| 317 | * VER_6 of this command is quite similar to VER_5 except | ||
| 318 | * exclusion of all fields related to the security key installation. | ||
| 319 | */ | ||
| 320 | struct iwl_mvm_add_sta_cmd_v6 { | ||
| 321 | u8 add_modify; | ||
| 322 | u8 reserved1; | ||
| 323 | __le16 tid_disable_tx; | ||
| 324 | __le32 mac_id_n_color; | ||
| 325 | u8 addr[ETH_ALEN]; /* _STA_ID_MODIFY_INFO_API_S_VER_1 */ | ||
| 326 | __le16 reserved2; | ||
| 327 | u8 sta_id; | ||
| 328 | u8 modify_mask; | ||
| 329 | __le16 reserved3; | ||
| 330 | __le32 station_flags; | ||
| 331 | __le32 station_flags_msk; | ||
| 332 | u8 add_immediate_ba_tid; | ||
| 333 | u8 remove_immediate_ba_tid; | ||
| 334 | __le16 add_immediate_ba_ssn; | ||
| 335 | __le16 sleep_tx_count; | ||
| 336 | __le16 sleep_state_flags; | ||
| 337 | __le16 assoc_id; | ||
| 338 | __le16 beamform_flags; | ||
| 339 | __le32 tfd_queue_msk; | ||
| 340 | } __packed; /* ADD_STA_CMD_API_S_VER_6 */ | ||
| 341 | |||
| 342 | /** | ||
| 343 | * struct iwl_mvm_add_sta_key_cmd - add/modify sta key | ||
| 344 | * ( REPLY_ADD_STA_KEY = 0x17 ) | ||
| 345 | * @sta_id: index of station in uCode's station table | ||
| 346 | * @key_offset: key offset in key storage | ||
| 347 | * @key_flags: type %iwl_sta_key_flag | ||
| 348 | * @key: key material data | ||
| 349 | * @key2: key material data | ||
| 350 | * @rx_secur_seq_cnt: RX security sequence counter for the key | ||
| 351 | * @tkip_rx_tsc_byte2: TSC[2] for key mix ph1 detection | ||
| 352 | * @tkip_rx_ttak: 10-byte unicast TKIP TTAK for Rx | ||
| 353 | */ | ||
| 354 | struct iwl_mvm_add_sta_key_cmd { | ||
| 355 | u8 sta_id; | ||
| 356 | u8 key_offset; | ||
| 357 | __le16 key_flags; | ||
| 358 | u8 key[16]; | ||
| 359 | u8 key2[16]; | ||
| 360 | u8 rx_secur_seq_cnt[16]; | ||
| 361 | u8 tkip_rx_tsc_byte2; | ||
| 362 | u8 reserved; | ||
| 363 | __le16 tkip_rx_ttak[5]; | ||
| 364 | } __packed; /* ADD_MODIFY_STA_KEY_API_S_VER_1 */ | ||
| 365 | |||
| 366 | /** | ||
| 316 | * enum iwl_mvm_add_sta_rsp_status - status in the response to ADD_STA command | 367 | * enum iwl_mvm_add_sta_rsp_status - status in the response to ADD_STA command |
| 317 | * @ADD_STA_SUCCESS: operation was executed successfully | 368 | * @ADD_STA_SUCCESS: operation was executed successfully |
| 318 | * @ADD_STA_STATIONS_OVERLOAD: no room left in the fw's station table | 369 | * @ADD_STA_STATIONS_OVERLOAD: no room left in the fw's station table |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 66264cc5a016..bad5a552dd8d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h | |||
| @@ -72,17 +72,17 @@ | |||
| 72 | #include "fw-api-d3.h" | 72 | #include "fw-api-d3.h" |
| 73 | #include "fw-api-bt-coex.h" | 73 | #include "fw-api-bt-coex.h" |
| 74 | 74 | ||
| 75 | /* queue and FIFO numbers by usage */ | 75 | /* maximal number of Tx queues in any platform */ |
| 76 | #define IWL_MVM_MAX_QUEUES 20 | ||
| 77 | |||
| 78 | /* Tx queue numbers */ | ||
| 76 | enum { | 79 | enum { |
| 77 | IWL_MVM_OFFCHANNEL_QUEUE = 8, | 80 | IWL_MVM_OFFCHANNEL_QUEUE = 8, |
| 78 | IWL_MVM_CMD_QUEUE = 9, | 81 | IWL_MVM_CMD_QUEUE = 9, |
| 79 | IWL_MVM_AUX_QUEUE = 15, | ||
| 80 | IWL_MVM_FIRST_AGG_QUEUE = 16, | ||
| 81 | IWL_MVM_NUM_QUEUES = 20, | ||
| 82 | IWL_MVM_LAST_AGG_QUEUE = IWL_MVM_NUM_QUEUES - 1, | ||
| 83 | IWL_MVM_CMD_FIFO = 7 | ||
| 84 | }; | 82 | }; |
| 85 | 83 | ||
| 84 | #define IWL_MVM_CMD_FIFO 7 | ||
| 85 | |||
| 86 | #define IWL_MVM_STATION_COUNT 16 | 86 | #define IWL_MVM_STATION_COUNT 16 |
| 87 | 87 | ||
| 88 | /* commands */ | 88 | /* commands */ |
| @@ -97,6 +97,7 @@ enum { | |||
| 97 | DBG_CFG = 0x9, | 97 | DBG_CFG = 0x9, |
| 98 | 98 | ||
| 99 | /* station table */ | 99 | /* station table */ |
| 100 | ADD_STA_KEY = 0x17, | ||
| 100 | ADD_STA = 0x18, | 101 | ADD_STA = 0x18, |
| 101 | REMOVE_STA = 0x19, | 102 | REMOVE_STA = 0x19, |
| 102 | 103 | ||
| @@ -114,6 +115,7 @@ enum { | |||
| 114 | TIME_EVENT_NOTIFICATION = 0x2a, | 115 | TIME_EVENT_NOTIFICATION = 0x2a, |
| 115 | BINDING_CONTEXT_CMD = 0x2b, | 116 | BINDING_CONTEXT_CMD = 0x2b, |
| 116 | TIME_QUOTA_CMD = 0x2c, | 117 | TIME_QUOTA_CMD = 0x2c, |
| 118 | NON_QOS_TX_COUNTER_CMD = 0x2d, | ||
| 117 | 119 | ||
| 118 | LQ_CMD = 0x4e, | 120 | LQ_CMD = 0x4e, |
| 119 | 121 | ||
| @@ -130,6 +132,7 @@ enum { | |||
| 130 | SCAN_OFFLOAD_COMPLETE = 0x6D, | 132 | SCAN_OFFLOAD_COMPLETE = 0x6D, |
| 131 | SCAN_OFFLOAD_UPDATE_PROFILES_CMD = 0x6E, | 133 | SCAN_OFFLOAD_UPDATE_PROFILES_CMD = 0x6E, |
| 132 | SCAN_OFFLOAD_CONFIG_CMD = 0x6f, | 134 | SCAN_OFFLOAD_CONFIG_CMD = 0x6f, |
| 135 | MATCH_FOUND_NOTIFICATION = 0xd9, | ||
| 133 | 136 | ||
| 134 | /* Phy */ | 137 | /* Phy */ |
| 135 | PHY_CONFIGURATION_CMD = 0x6a, | 138 | PHY_CONFIGURATION_CMD = 0x6a, |
| @@ -178,6 +181,7 @@ enum { | |||
| 178 | BT_COEX_PRIO_TABLE = 0xcc, | 181 | BT_COEX_PRIO_TABLE = 0xcc, |
| 179 | BT_COEX_PROT_ENV = 0xcd, | 182 | BT_COEX_PROT_ENV = 0xcd, |
| 180 | BT_PROFILE_NOTIFICATION = 0xce, | 183 | BT_PROFILE_NOTIFICATION = 0xce, |
| 184 | BT_COEX_CI = 0x5d, | ||
| 181 | 185 | ||
| 182 | REPLY_BEACON_FILTERING_CMD = 0xd2, | 186 | REPLY_BEACON_FILTERING_CMD = 0xd2, |
| 183 | 187 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index c76299a3a1e0..70e5297646b2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c | |||
| @@ -151,13 +151,11 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, | |||
| 151 | enum iwl_ucode_type old_type = mvm->cur_ucode; | 151 | enum iwl_ucode_type old_type = mvm->cur_ucode; |
| 152 | static const u8 alive_cmd[] = { MVM_ALIVE }; | 152 | static const u8 alive_cmd[] = { MVM_ALIVE }; |
| 153 | 153 | ||
| 154 | mvm->cur_ucode = ucode_type; | ||
| 155 | fw = iwl_get_ucode_image(mvm, ucode_type); | 154 | fw = iwl_get_ucode_image(mvm, ucode_type); |
| 156 | 155 | if (WARN_ON(!fw)) | |
| 157 | mvm->ucode_loaded = false; | ||
| 158 | |||
| 159 | if (!fw) | ||
| 160 | return -EINVAL; | 156 | return -EINVAL; |
| 157 | mvm->cur_ucode = ucode_type; | ||
| 158 | mvm->ucode_loaded = false; | ||
| 161 | 159 | ||
| 162 | iwl_init_notification_wait(&mvm->notif_wait, &alive_wait, | 160 | iwl_init_notification_wait(&mvm->notif_wait, &alive_wait, |
| 163 | alive_cmd, ARRAY_SIZE(alive_cmd), | 161 | alive_cmd, ARRAY_SIZE(alive_cmd), |
| @@ -199,7 +197,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, | |||
| 199 | */ | 197 | */ |
| 200 | 198 | ||
| 201 | for (i = 0; i < IWL_MAX_HW_QUEUES; i++) { | 199 | for (i = 0; i < IWL_MAX_HW_QUEUES; i++) { |
| 202 | if (i < IWL_MVM_FIRST_AGG_QUEUE && i != IWL_MVM_CMD_QUEUE) | 200 | if (i < mvm->first_agg_queue && i != IWL_MVM_CMD_QUEUE) |
| 203 | mvm->queue_to_mac80211[i] = i; | 201 | mvm->queue_to_mac80211[i] = i; |
| 204 | else | 202 | else |
| 205 | mvm->queue_to_mac80211[i] = IWL_INVALID_MAC80211_QUEUE; | 203 | mvm->queue_to_mac80211[i] = IWL_INVALID_MAC80211_QUEUE; |
| @@ -243,7 +241,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
| 243 | 241 | ||
| 244 | lockdep_assert_held(&mvm->mutex); | 242 | lockdep_assert_held(&mvm->mutex); |
| 245 | 243 | ||
| 246 | if (mvm->init_ucode_run) | 244 | if (mvm->init_ucode_complete) |
| 247 | return 0; | 245 | return 0; |
| 248 | 246 | ||
| 249 | iwl_init_notification_wait(&mvm->notif_wait, | 247 | iwl_init_notification_wait(&mvm->notif_wait, |
| @@ -264,6 +262,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
| 264 | if (ret) | 262 | if (ret) |
| 265 | goto error; | 263 | goto error; |
| 266 | 264 | ||
| 265 | /* Read the NVM only at driver load time, no need to do this twice */ | ||
| 267 | if (read_nvm) { | 266 | if (read_nvm) { |
| 268 | /* Read nvm */ | 267 | /* Read nvm */ |
| 269 | ret = iwl_nvm_init(mvm); | 268 | ret = iwl_nvm_init(mvm); |
| @@ -273,6 +272,10 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
| 273 | } | 272 | } |
| 274 | } | 273 | } |
| 275 | 274 | ||
| 275 | /* In case we read the NVM from external file, load it to the NIC */ | ||
| 276 | if (iwlwifi_mod_params.nvm_file) | ||
| 277 | iwl_mvm_load_nvm_to_nic(mvm); | ||
| 278 | |||
| 276 | ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans); | 279 | ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans); |
| 277 | WARN_ON(ret); | 280 | WARN_ON(ret); |
| 278 | 281 | ||
| @@ -310,7 +313,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
| 310 | ret = iwl_wait_notification(&mvm->notif_wait, &calib_wait, | 313 | ret = iwl_wait_notification(&mvm->notif_wait, &calib_wait, |
| 311 | MVM_UCODE_CALIB_TIMEOUT); | 314 | MVM_UCODE_CALIB_TIMEOUT); |
| 312 | if (!ret) | 315 | if (!ret) |
| 313 | mvm->init_ucode_run = true; | 316 | mvm->init_ucode_complete = true; |
| 314 | goto out; | 317 | goto out; |
| 315 | 318 | ||
| 316 | error: | 319 | error: |
| @@ -353,8 +356,12 @@ int iwl_mvm_up(struct iwl_mvm *mvm) | |||
| 353 | if (ret) | 356 | if (ret) |
| 354 | return ret; | 357 | return ret; |
| 355 | 358 | ||
| 356 | /* If we were in RFKILL during module loading, load init ucode now */ | 359 | /* |
| 357 | if (!mvm->init_ucode_run) { | 360 | * If we haven't completed the run of the init ucode during |
| 361 | * module loading, load init ucode now | ||
| 362 | * (for example, if we were in RFKILL) | ||
| 363 | */ | ||
| 364 | if (!mvm->init_ucode_complete) { | ||
| 358 | ret = iwl_run_init_mvm_ucode(mvm, false); | 365 | ret = iwl_run_init_mvm_ucode(mvm, false); |
| 359 | if (ret && !iwlmvm_mod_params.init_dbg) { | 366 | if (ret && !iwlmvm_mod_params.init_dbg) { |
| 360 | IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", ret); | 367 | IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", ret); |
| @@ -424,6 +431,10 @@ int iwl_mvm_up(struct iwl_mvm *mvm) | |||
| 424 | goto error; | 431 | goto error; |
| 425 | } | 432 | } |
| 426 | 433 | ||
| 434 | ret = iwl_mvm_power_update_device_mode(mvm); | ||
| 435 | if (ret) | ||
| 436 | goto error; | ||
| 437 | |||
| 427 | IWL_DEBUG_INFO(mvm, "RT uCode started.\n"); | 438 | IWL_DEBUG_INFO(mvm, "RT uCode started.\n"); |
| 428 | return 0; | 439 | return 0; |
| 429 | error: | 440 | error: |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 5fe23a5ea9b6..f41f9b079831 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | |||
| @@ -80,7 +80,7 @@ struct iwl_mvm_mac_iface_iterator_data { | |||
| 80 | struct ieee80211_vif *vif; | 80 | struct ieee80211_vif *vif; |
| 81 | unsigned long available_mac_ids[BITS_TO_LONGS(NUM_MAC_INDEX_DRIVER)]; | 81 | unsigned long available_mac_ids[BITS_TO_LONGS(NUM_MAC_INDEX_DRIVER)]; |
| 82 | unsigned long available_tsf_ids[BITS_TO_LONGS(NUM_TSF_IDS)]; | 82 | unsigned long available_tsf_ids[BITS_TO_LONGS(NUM_TSF_IDS)]; |
| 83 | unsigned long used_hw_queues[BITS_TO_LONGS(IWL_MVM_FIRST_AGG_QUEUE)]; | 83 | unsigned long used_hw_queues[BITS_TO_LONGS(IWL_MVM_MAX_QUEUES)]; |
| 84 | enum iwl_tsf_id preferred_tsf; | 84 | enum iwl_tsf_id preferred_tsf; |
| 85 | bool found_vif; | 85 | bool found_vif; |
| 86 | }; | 86 | }; |
| @@ -218,7 +218,7 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm, | |||
| 218 | .preferred_tsf = NUM_TSF_IDS, | 218 | .preferred_tsf = NUM_TSF_IDS, |
| 219 | .used_hw_queues = { | 219 | .used_hw_queues = { |
| 220 | BIT(IWL_MVM_OFFCHANNEL_QUEUE) | | 220 | BIT(IWL_MVM_OFFCHANNEL_QUEUE) | |
| 221 | BIT(IWL_MVM_AUX_QUEUE) | | 221 | BIT(mvm->aux_queue) | |
| 222 | BIT(IWL_MVM_CMD_QUEUE) | 222 | BIT(IWL_MVM_CMD_QUEUE) |
| 223 | }, | 223 | }, |
| 224 | .found_vif = false, | 224 | .found_vif = false, |
| @@ -242,9 +242,17 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm, | |||
| 242 | * that we should share it with another interface. | 242 | * that we should share it with another interface. |
| 243 | */ | 243 | */ |
| 244 | 244 | ||
| 245 | /* Currently, MAC ID 0 should be used only for the managed vif */ | 245 | /* Currently, MAC ID 0 should be used only for the managed/IBSS vif */ |
| 246 | if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) | 246 | switch (vif->type) { |
| 247 | case NL80211_IFTYPE_ADHOC: | ||
| 248 | break; | ||
| 249 | case NL80211_IFTYPE_STATION: | ||
| 250 | if (!vif->p2p) | ||
| 251 | break; | ||
| 252 | /* fall through */ | ||
| 253 | default: | ||
| 247 | __clear_bit(0, data.available_mac_ids); | 254 | __clear_bit(0, data.available_mac_ids); |
| 255 | } | ||
| 248 | 256 | ||
| 249 | ieee80211_iterate_active_interfaces_atomic( | 257 | ieee80211_iterate_active_interfaces_atomic( |
| 250 | mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL, | 258 | mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL, |
| @@ -302,9 +310,9 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm, | |||
| 302 | /* Find available queues, and allocate them to the ACs */ | 310 | /* Find available queues, and allocate them to the ACs */ |
| 303 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | 311 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
| 304 | u8 queue = find_first_zero_bit(data.used_hw_queues, | 312 | u8 queue = find_first_zero_bit(data.used_hw_queues, |
| 305 | IWL_MVM_FIRST_AGG_QUEUE); | 313 | mvm->first_agg_queue); |
| 306 | 314 | ||
| 307 | if (queue >= IWL_MVM_FIRST_AGG_QUEUE) { | 315 | if (queue >= mvm->first_agg_queue) { |
| 308 | IWL_ERR(mvm, "Failed to allocate queue\n"); | 316 | IWL_ERR(mvm, "Failed to allocate queue\n"); |
| 309 | ret = -EIO; | 317 | ret = -EIO; |
| 310 | goto exit_fail; | 318 | goto exit_fail; |
| @@ -317,9 +325,9 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm, | |||
| 317 | /* Allocate the CAB queue for softAP and GO interfaces */ | 325 | /* Allocate the CAB queue for softAP and GO interfaces */ |
| 318 | if (vif->type == NL80211_IFTYPE_AP) { | 326 | if (vif->type == NL80211_IFTYPE_AP) { |
| 319 | u8 queue = find_first_zero_bit(data.used_hw_queues, | 327 | u8 queue = find_first_zero_bit(data.used_hw_queues, |
| 320 | IWL_MVM_FIRST_AGG_QUEUE); | 328 | mvm->first_agg_queue); |
| 321 | 329 | ||
| 322 | if (queue >= IWL_MVM_FIRST_AGG_QUEUE) { | 330 | if (queue >= mvm->first_agg_queue) { |
| 323 | IWL_ERR(mvm, "Failed to allocate cab queue\n"); | 331 | IWL_ERR(mvm, "Failed to allocate cab queue\n"); |
| 324 | ret = -EIO; | 332 | ret = -EIO; |
| 325 | goto exit_fail; | 333 | goto exit_fail; |
| @@ -559,8 +567,12 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm, | |||
| 559 | cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA); | 567 | cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA); |
| 560 | 568 | ||
| 561 | /* Don't use cts to self as the fw doesn't support it currently. */ | 569 | /* Don't use cts to self as the fw doesn't support it currently. */ |
| 562 | if (vif->bss_conf.use_cts_prot) | 570 | if (vif->bss_conf.use_cts_prot) { |
| 563 | cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT); | 571 | cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT); |
| 572 | if (IWL_UCODE_API(mvm->fw->ucode_ver) >= 8) | ||
| 573 | cmd->protection_flags |= | ||
| 574 | cpu_to_le32(MAC_PROT_FLG_SELF_CTS_EN); | ||
| 575 | } | ||
| 564 | 576 | ||
| 565 | /* | 577 | /* |
| 566 | * I think that we should enable these 2 flags regardless the HT PROT | 578 | * I think that we should enable these 2 flags regardless the HT PROT |
| @@ -707,8 +719,35 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm, | |||
| 707 | cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROMISC | | 719 | cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROMISC | |
| 708 | MAC_FILTER_IN_CONTROL_AND_MGMT | | 720 | MAC_FILTER_IN_CONTROL_AND_MGMT | |
| 709 | MAC_FILTER_IN_BEACON | | 721 | MAC_FILTER_IN_BEACON | |
| 722 | MAC_FILTER_IN_PROBE_REQUEST | | ||
| 723 | MAC_FILTER_IN_CRC32); | ||
| 724 | mvm->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS; | ||
| 725 | |||
| 726 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); | ||
| 727 | } | ||
| 728 | |||
| 729 | static int iwl_mvm_mac_ctxt_cmd_ibss(struct iwl_mvm *mvm, | ||
| 730 | struct ieee80211_vif *vif, | ||
| 731 | u32 action) | ||
| 732 | { | ||
| 733 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
| 734 | struct iwl_mac_ctx_cmd cmd = {}; | ||
| 735 | |||
| 736 | WARN_ON(vif->type != NL80211_IFTYPE_ADHOC); | ||
| 737 | |||
| 738 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); | ||
| 739 | |||
| 740 | cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_BEACON | | ||
| 710 | MAC_FILTER_IN_PROBE_REQUEST); | 741 | MAC_FILTER_IN_PROBE_REQUEST); |
| 711 | 742 | ||
| 743 | /* cmd.ibss.beacon_time/cmd.ibss.beacon_tsf are curently ignored */ | ||
| 744 | cmd.ibss.bi = cpu_to_le32(vif->bss_conf.beacon_int); | ||
| 745 | cmd.ibss.bi_reciprocal = | ||
| 746 | cpu_to_le32(iwl_mvm_reciprocal(vif->bss_conf.beacon_int)); | ||
| 747 | |||
| 748 | /* TODO: Assumes that the beacon id == mac context id */ | ||
| 749 | cmd.ibss.beacon_template = cpu_to_le32(mvmvif->id); | ||
| 750 | |||
| 712 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); | 751 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); |
| 713 | } | 752 | } |
| 714 | 753 | ||
| @@ -721,7 +760,8 @@ static void iwl_mvm_go_iterator(void *_data, u8 *mac, struct ieee80211_vif *vif) | |||
| 721 | struct iwl_mvm_go_iterator_data *data = _data; | 760 | struct iwl_mvm_go_iterator_data *data = _data; |
| 722 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 761 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
| 723 | 762 | ||
| 724 | if (vif->type == NL80211_IFTYPE_AP && vif->p2p && mvmvif->ap_active) | 763 | if (vif->type == NL80211_IFTYPE_AP && vif->p2p && |
| 764 | mvmvif->ap_ibss_active) | ||
| 725 | data->go_active = true; | 765 | data->go_active = true; |
| 726 | } | 766 | } |
| 727 | 767 | ||
| @@ -833,9 +873,10 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, | |||
| 833 | cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(rate)); | 873 | cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(rate)); |
| 834 | 874 | ||
| 835 | /* Set up TX beacon command fields */ | 875 | /* Set up TX beacon command fields */ |
| 836 | iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd, | 876 | if (vif->type == NL80211_IFTYPE_AP) |
| 837 | beacon->data, | 877 | iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd, |
| 838 | beacon_skb_len); | 878 | beacon->data, |
| 879 | beacon_skb_len); | ||
| 839 | 880 | ||
| 840 | /* Submit command */ | 881 | /* Submit command */ |
| 841 | cmd.len[0] = sizeof(beacon_cmd); | 882 | cmd.len[0] = sizeof(beacon_cmd); |
| @@ -848,14 +889,15 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, | |||
| 848 | return iwl_mvm_send_cmd(mvm, &cmd); | 889 | return iwl_mvm_send_cmd(mvm, &cmd); |
| 849 | } | 890 | } |
| 850 | 891 | ||
| 851 | /* The beacon template for the AP/GO context has changed and needs update */ | 892 | /* The beacon template for the AP/GO/IBSS has changed and needs update */ |
| 852 | int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm, | 893 | int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm, |
| 853 | struct ieee80211_vif *vif) | 894 | struct ieee80211_vif *vif) |
| 854 | { | 895 | { |
| 855 | struct sk_buff *beacon; | 896 | struct sk_buff *beacon; |
| 856 | int ret; | 897 | int ret; |
| 857 | 898 | ||
| 858 | WARN_ON(vif->type != NL80211_IFTYPE_AP); | 899 | WARN_ON(vif->type != NL80211_IFTYPE_AP && |
| 900 | vif->type != NL80211_IFTYPE_ADHOC); | ||
| 859 | 901 | ||
| 860 | beacon = ieee80211_beacon_get(mvm->hw, vif); | 902 | beacon = ieee80211_beacon_get(mvm->hw, vif); |
| 861 | if (!beacon) | 903 | if (!beacon) |
| @@ -1018,6 +1060,8 @@ static int iwl_mvm_mac_ctx_send(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 1018 | return iwl_mvm_mac_ctxt_cmd_listener(mvm, vif, action); | 1060 | return iwl_mvm_mac_ctxt_cmd_listener(mvm, vif, action); |
| 1019 | case NL80211_IFTYPE_P2P_DEVICE: | 1061 | case NL80211_IFTYPE_P2P_DEVICE: |
| 1020 | return iwl_mvm_mac_ctxt_cmd_p2p_device(mvm, vif, action); | 1062 | return iwl_mvm_mac_ctxt_cmd_p2p_device(mvm, vif, action); |
| 1063 | case NL80211_IFTYPE_ADHOC: | ||
| 1064 | return iwl_mvm_mac_ctxt_cmd_ibss(mvm, vif, action); | ||
| 1021 | default: | 1065 | default: |
| 1022 | break; | 1066 | break; |
| 1023 | } | 1067 | } |
| @@ -1038,6 +1082,9 @@ int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
| 1038 | if (ret) | 1082 | if (ret) |
| 1039 | return ret; | 1083 | return ret; |
| 1040 | 1084 | ||
| 1085 | /* will only do anything at resume from D3 time */ | ||
| 1086 | iwl_mvm_set_last_nonqos_seq(mvm, vif); | ||
| 1087 | |||
| 1041 | mvmvif->uploaded = true; | 1088 | mvmvif->uploaded = true; |
| 1042 | return 0; | 1089 | return 0; |
| 1043 | } | 1090 | } |
| @@ -1077,6 +1124,10 @@ int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
| 1077 | } | 1124 | } |
| 1078 | 1125 | ||
| 1079 | mvmvif->uploaded = false; | 1126 | mvmvif->uploaded = false; |
| 1127 | |||
| 1128 | if (vif->type == NL80211_IFTYPE_MONITOR) | ||
| 1129 | mvm->hw->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS; | ||
| 1130 | |||
| 1080 | return 0; | 1131 | return 0; |
| 1081 | } | 1132 | } |
| 1082 | 1133 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 9833cdf6177c..74bc2c8af06d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
| @@ -77,6 +77,7 @@ | |||
| 77 | #include "iwl-eeprom-parse.h" | 77 | #include "iwl-eeprom-parse.h" |
| 78 | #include "fw-api-scan.h" | 78 | #include "fw-api-scan.h" |
| 79 | #include "iwl-phy-db.h" | 79 | #include "iwl-phy-db.h" |
| 80 | #include "testmode.h" | ||
| 80 | 81 | ||
| 81 | static const struct ieee80211_iface_limit iwl_mvm_limits[] = { | 82 | static const struct ieee80211_iface_limit iwl_mvm_limits[] = { |
| 82 | { | 83 | { |
| @@ -138,6 +139,14 @@ static void iwl_mvm_reset_phy_ctxts(struct iwl_mvm *mvm) | |||
| 138 | } | 139 | } |
| 139 | } | 140 | } |
| 140 | 141 | ||
| 142 | static int iwl_mvm_max_scan_ie_len(struct iwl_mvm *mvm) | ||
| 143 | { | ||
| 144 | /* we create the 802.11 header and SSID element */ | ||
| 145 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID) | ||
| 146 | return mvm->fw->ucode_capa.max_probe_length - 24 - 2; | ||
| 147 | return mvm->fw->ucode_capa.max_probe_length - 24 - 34; | ||
| 148 | } | ||
| 149 | |||
| 141 | int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | 150 | int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) |
| 142 | { | 151 | { |
| 143 | struct ieee80211_hw *hw = mvm->hw; | 152 | struct ieee80211_hw *hw = mvm->hw; |
| @@ -155,10 +164,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
| 155 | IEEE80211_HW_TIMING_BEACON_ONLY | | 164 | IEEE80211_HW_TIMING_BEACON_ONLY | |
| 156 | IEEE80211_HW_CONNECTION_MONITOR | | 165 | IEEE80211_HW_CONNECTION_MONITOR | |
| 157 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | 166 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | |
| 158 | IEEE80211_HW_SUPPORTS_STATIC_SMPS | | 167 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; |
| 159 | IEEE80211_HW_SUPPORTS_UAPSD; | ||
| 160 | 168 | ||
| 161 | hw->queues = IWL_MVM_FIRST_AGG_QUEUE; | 169 | hw->queues = mvm->first_agg_queue; |
| 162 | hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE; | 170 | hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE; |
| 163 | hw->rate_control_algorithm = "iwl-mvm-rs"; | 171 | hw->rate_control_algorithm = "iwl-mvm-rs"; |
| 164 | 172 | ||
| @@ -171,6 +179,12 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
| 171 | !iwlwifi_mod_params.sw_crypto) | 179 | !iwlwifi_mod_params.sw_crypto) |
| 172 | hw->flags |= IEEE80211_HW_MFP_CAPABLE; | 180 | hw->flags |= IEEE80211_HW_MFP_CAPABLE; |
| 173 | 181 | ||
| 182 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT) { | ||
| 183 | hw->flags |= IEEE80211_HW_SUPPORTS_UAPSD; | ||
| 184 | hw->uapsd_queues = IWL_UAPSD_AC_INFO; | ||
| 185 | hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; | ||
| 186 | } | ||
| 187 | |||
| 174 | hw->sta_data_size = sizeof(struct iwl_mvm_sta); | 188 | hw->sta_data_size = sizeof(struct iwl_mvm_sta); |
| 175 | hw->vif_data_size = sizeof(struct iwl_mvm_vif); | 189 | hw->vif_data_size = sizeof(struct iwl_mvm_vif); |
| 176 | hw->chanctx_data_size = sizeof(u16); | 190 | hw->chanctx_data_size = sizeof(u16); |
| @@ -181,6 +195,10 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
| 181 | BIT(NL80211_IFTYPE_P2P_GO) | | 195 | BIT(NL80211_IFTYPE_P2P_GO) | |
| 182 | BIT(NL80211_IFTYPE_P2P_DEVICE); | 196 | BIT(NL80211_IFTYPE_P2P_DEVICE); |
| 183 | 197 | ||
| 198 | /* IBSS has bugs in older versions */ | ||
| 199 | if (IWL_UCODE_API(mvm->fw->ucode_ver) >= 8) | ||
| 200 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC); | ||
| 201 | |||
| 184 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | | 202 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | |
| 185 | WIPHY_FLAG_DISABLE_BEACON_HINTS | | 203 | WIPHY_FLAG_DISABLE_BEACON_HINTS | |
| 186 | WIPHY_FLAG_IBSS_RSN; | 204 | WIPHY_FLAG_IBSS_RSN; |
| @@ -191,8 +209,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
| 191 | 209 | ||
| 192 | hw->wiphy->max_remain_on_channel_duration = 10000; | 210 | hw->wiphy->max_remain_on_channel_duration = 10000; |
| 193 | hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; | 211 | hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; |
| 194 | hw->uapsd_queues = IWL_UAPSD_AC_INFO; | ||
| 195 | hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; | ||
| 196 | 212 | ||
| 197 | /* Extract MAC address */ | 213 | /* Extract MAC address */ |
| 198 | memcpy(mvm->addresses[0].addr, mvm->nvm_data->hw_addr, ETH_ALEN); | 214 | memcpy(mvm->addresses[0].addr, mvm->nvm_data->hw_addr, ETH_ALEN); |
| @@ -212,9 +228,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
| 212 | 228 | ||
| 213 | iwl_mvm_reset_phy_ctxts(mvm); | 229 | iwl_mvm_reset_phy_ctxts(mvm); |
| 214 | 230 | ||
| 215 | /* we create the 802.11 header and a max-length SSID element */ | 231 | hw->wiphy->max_scan_ie_len = iwl_mvm_max_scan_ie_len(mvm); |
| 216 | hw->wiphy->max_scan_ie_len = | 232 | |
| 217 | mvm->fw->ucode_capa.max_probe_length - 24 - 34; | ||
| 218 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; | 233 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; |
| 219 | 234 | ||
| 220 | if (mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels) | 235 | if (mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels) |
| @@ -231,6 +246,15 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
| 231 | else | 246 | else |
| 232 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 247 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
| 233 | 248 | ||
| 249 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SCHED_SCAN) { | ||
| 250 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; | ||
| 251 | hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX; | ||
| 252 | hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES; | ||
| 253 | /* we create the 802.11 header and zero length SSID IE. */ | ||
| 254 | hw->wiphy->max_sched_scan_ie_len = | ||
| 255 | SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2; | ||
| 256 | } | ||
| 257 | |||
| 234 | hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN | | 258 | hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN | |
| 235 | NL80211_FEATURE_P2P_GO_OPPPS; | 259 | NL80211_FEATURE_P2P_GO_OPPPS; |
| 236 | 260 | ||
| @@ -548,7 +572,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | |||
| 548 | * In short: there's not much we can do at this point, other than | 572 | * In short: there's not much we can do at this point, other than |
| 549 | * allocating resources :) | 573 | * allocating resources :) |
| 550 | */ | 574 | */ |
| 551 | if (vif->type == NL80211_IFTYPE_AP) { | 575 | if (vif->type == NL80211_IFTYPE_AP || |
| 576 | vif->type == NL80211_IFTYPE_ADHOC) { | ||
| 552 | u32 qmask = iwl_mvm_mac_get_queues_mask(mvm, vif); | 577 | u32 qmask = iwl_mvm_mac_get_queues_mask(mvm, vif); |
| 553 | ret = iwl_mvm_allocate_int_sta(mvm, &mvmvif->bcast_sta, | 578 | ret = iwl_mvm_allocate_int_sta(mvm, &mvmvif->bcast_sta, |
| 554 | qmask); | 579 | qmask); |
| @@ -698,7 +723,14 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, | |||
| 698 | * For AP/GO interface, the tear down of the resources allocated to the | 723 | * For AP/GO interface, the tear down of the resources allocated to the |
| 699 | * interface is be handled as part of the stop_ap flow. | 724 | * interface is be handled as part of the stop_ap flow. |
| 700 | */ | 725 | */ |
| 701 | if (vif->type == NL80211_IFTYPE_AP) { | 726 | if (vif->type == NL80211_IFTYPE_AP || |
| 727 | vif->type == NL80211_IFTYPE_ADHOC) { | ||
| 728 | #ifdef CONFIG_NL80211_TESTMODE | ||
| 729 | if (vif == mvm->noa_vif) { | ||
| 730 | mvm->noa_vif = NULL; | ||
| 731 | mvm->noa_duration = 0; | ||
| 732 | } | ||
| 733 | #endif | ||
| 702 | iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta); | 734 | iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta); |
| 703 | goto out_release; | 735 | goto out_release; |
| 704 | } | 736 | } |
| @@ -796,6 +828,27 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
| 796 | return; | 828 | return; |
| 797 | } | 829 | } |
| 798 | iwl_mvm_configure_mcast_filter(mvm, vif); | 830 | iwl_mvm_configure_mcast_filter(mvm, vif); |
| 831 | |||
| 832 | if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, | ||
| 833 | &mvm->status)) { | ||
| 834 | /* | ||
| 835 | * If we're restarting then the firmware will | ||
| 836 | * obviously have lost synchronisation with | ||
| 837 | * the AP. It will attempt to synchronise by | ||
| 838 | * itself, but we can make it more reliable by | ||
| 839 | * scheduling a session protection time event. | ||
| 840 | * | ||
| 841 | * The firmware needs to receive a beacon to | ||
| 842 | * catch up with synchronisation, use 110% of | ||
| 843 | * the beacon interval. | ||
| 844 | * | ||
| 845 | * Set a large maximum delay to allow for more | ||
| 846 | * than a single interface. | ||
| 847 | */ | ||
| 848 | u32 dur = (11 * vif->bss_conf.beacon_int) / 10; | ||
| 849 | iwl_mvm_protect_session(mvm, vif, dur, dur, | ||
| 850 | 5 * dur); | ||
| 851 | } | ||
| 799 | } else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) { | 852 | } else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) { |
| 800 | /* remove AP station now that the MAC is unassoc */ | 853 | /* remove AP station now that the MAC is unassoc */ |
| 801 | ret = iwl_mvm_rm_sta_id(mvm, vif, mvmvif->ap_sta_id); | 854 | ret = iwl_mvm_rm_sta_id(mvm, vif, mvmvif->ap_sta_id); |
| @@ -811,7 +864,8 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
| 811 | /* reset rssi values */ | 864 | /* reset rssi values */ |
| 812 | mvmvif->bf_data.ave_beacon_signal = 0; | 865 | mvmvif->bf_data.ave_beacon_signal = 0; |
| 813 | 866 | ||
| 814 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD)) { | 867 | if (!(mvm->fw->ucode_capa.flags & |
| 868 | IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT)) { | ||
| 815 | /* Workaround for FW bug, otherwise FW disables device | 869 | /* Workaround for FW bug, otherwise FW disables device |
| 816 | * power save upon disassociation | 870 | * power save upon disassociation |
| 817 | */ | 871 | */ |
| @@ -819,7 +873,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
| 819 | if (ret) | 873 | if (ret) |
| 820 | IWL_ERR(mvm, "failed to update power mode\n"); | 874 | IWL_ERR(mvm, "failed to update power mode\n"); |
| 821 | } | 875 | } |
| 822 | iwl_mvm_bt_coex_vif_assoc(mvm, vif); | 876 | iwl_mvm_bt_coex_vif_change(mvm); |
| 823 | } else if (changes & BSS_CHANGED_BEACON_INFO) { | 877 | } else if (changes & BSS_CHANGED_BEACON_INFO) { |
| 824 | /* | 878 | /* |
| 825 | * We received a beacon _after_ association so | 879 | * We received a beacon _after_ association so |
| @@ -848,7 +902,8 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
| 848 | } | 902 | } |
| 849 | } | 903 | } |
| 850 | 904 | ||
| 851 | static int iwl_mvm_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | 905 | static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, |
| 906 | struct ieee80211_vif *vif) | ||
| 852 | { | 907 | { |
| 853 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 908 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
| 854 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 909 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
| @@ -871,7 +926,7 @@ static int iwl_mvm_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
| 871 | if (ret) | 926 | if (ret) |
| 872 | goto out_remove; | 927 | goto out_remove; |
| 873 | 928 | ||
| 874 | mvmvif->ap_active = true; | 929 | mvmvif->ap_ibss_active = true; |
| 875 | 930 | ||
| 876 | /* Send the bcast station. At this stage the TBTT and DTIM time events | 931 | /* Send the bcast station. At this stage the TBTT and DTIM time events |
| 877 | * are added and applied to the scheduler */ | 932 | * are added and applied to the scheduler */ |
| @@ -883,10 +938,12 @@ static int iwl_mvm_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
| 883 | if (ret) | 938 | if (ret) |
| 884 | goto out_rm_bcast; | 939 | goto out_rm_bcast; |
| 885 | 940 | ||
| 886 | /* Need to update the P2P Device MAC */ | 941 | /* Need to update the P2P Device MAC (only GO, IBSS is single vif) */ |
| 887 | if (vif->p2p && mvm->p2p_device_vif) | 942 | if (vif->p2p && mvm->p2p_device_vif) |
| 888 | iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif); | 943 | iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif); |
| 889 | 944 | ||
| 945 | iwl_mvm_bt_coex_vif_change(mvm); | ||
| 946 | |||
| 890 | mutex_unlock(&mvm->mutex); | 947 | mutex_unlock(&mvm->mutex); |
| 891 | return 0; | 948 | return 0; |
| 892 | 949 | ||
| @@ -901,7 +958,8 @@ out_unlock: | |||
| 901 | return ret; | 958 | return ret; |
| 902 | } | 959 | } |
| 903 | 960 | ||
| 904 | static void iwl_mvm_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | 961 | static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw, |
| 962 | struct ieee80211_vif *vif) | ||
| 905 | { | 963 | { |
| 906 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 964 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
| 907 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 965 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
| @@ -910,9 +968,11 @@ static void iwl_mvm_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
| 910 | 968 | ||
| 911 | mutex_lock(&mvm->mutex); | 969 | mutex_lock(&mvm->mutex); |
| 912 | 970 | ||
| 913 | mvmvif->ap_active = false; | 971 | mvmvif->ap_ibss_active = false; |
| 972 | |||
| 973 | iwl_mvm_bt_coex_vif_change(mvm); | ||
| 914 | 974 | ||
| 915 | /* Need to update the P2P Device MAC */ | 975 | /* Need to update the P2P Device MAC (only GO, IBSS is single vif) */ |
| 916 | if (vif->p2p && mvm->p2p_device_vif) | 976 | if (vif->p2p && mvm->p2p_device_vif) |
| 917 | iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif); | 977 | iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif); |
| 918 | 978 | ||
| @@ -924,10 +984,11 @@ static void iwl_mvm_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
| 924 | mutex_unlock(&mvm->mutex); | 984 | mutex_unlock(&mvm->mutex); |
| 925 | } | 985 | } |
| 926 | 986 | ||
| 927 | static void iwl_mvm_bss_info_changed_ap(struct iwl_mvm *mvm, | 987 | static void |
| 928 | struct ieee80211_vif *vif, | 988 | iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm, |
| 929 | struct ieee80211_bss_conf *bss_conf, | 989 | struct ieee80211_vif *vif, |
| 930 | u32 changes) | 990 | struct ieee80211_bss_conf *bss_conf, |
| 991 | u32 changes) | ||
| 931 | { | 992 | { |
| 932 | /* Need to send a new beacon template to the FW */ | 993 | /* Need to send a new beacon template to the FW */ |
| 933 | if (changes & BSS_CHANGED_BEACON) { | 994 | if (changes & BSS_CHANGED_BEACON) { |
| @@ -950,7 +1011,8 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw, | |||
| 950 | iwl_mvm_bss_info_changed_station(mvm, vif, bss_conf, changes); | 1011 | iwl_mvm_bss_info_changed_station(mvm, vif, bss_conf, changes); |
| 951 | break; | 1012 | break; |
| 952 | case NL80211_IFTYPE_AP: | 1013 | case NL80211_IFTYPE_AP: |
| 953 | iwl_mvm_bss_info_changed_ap(mvm, vif, bss_conf, changes); | 1014 | case NL80211_IFTYPE_ADHOC: |
| 1015 | iwl_mvm_bss_info_changed_ap_ibss(mvm, vif, bss_conf, changes); | ||
| 954 | break; | 1016 | break; |
| 955 | default: | 1017 | default: |
| 956 | /* shouldn't happen */ | 1018 | /* shouldn't happen */ |
| @@ -1163,7 +1225,54 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw, | |||
| 1163 | 1225 | ||
| 1164 | mutex_lock(&mvm->mutex); | 1226 | mutex_lock(&mvm->mutex); |
| 1165 | /* Try really hard to protect the session and hear a beacon */ | 1227 | /* Try really hard to protect the session and hear a beacon */ |
| 1166 | iwl_mvm_protect_session(mvm, vif, duration, min_duration); | 1228 | iwl_mvm_protect_session(mvm, vif, duration, min_duration, 500); |
| 1229 | mutex_unlock(&mvm->mutex); | ||
| 1230 | } | ||
| 1231 | |||
| 1232 | static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw, | ||
| 1233 | struct ieee80211_vif *vif, | ||
| 1234 | struct cfg80211_sched_scan_request *req, | ||
| 1235 | struct ieee80211_sched_scan_ies *ies) | ||
| 1236 | { | ||
| 1237 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
| 1238 | int ret; | ||
| 1239 | |||
| 1240 | mutex_lock(&mvm->mutex); | ||
| 1241 | |||
| 1242 | if (mvm->scan_status != IWL_MVM_SCAN_NONE) { | ||
| 1243 | IWL_DEBUG_SCAN(mvm, | ||
| 1244 | "SCHED SCAN request during internal scan - abort\n"); | ||
| 1245 | ret = -EBUSY; | ||
| 1246 | goto out; | ||
| 1247 | } | ||
| 1248 | |||
| 1249 | mvm->scan_status = IWL_MVM_SCAN_SCHED; | ||
| 1250 | |||
| 1251 | ret = iwl_mvm_config_sched_scan(mvm, vif, req, ies); | ||
| 1252 | if (ret) | ||
| 1253 | goto err; | ||
| 1254 | |||
| 1255 | ret = iwl_mvm_config_sched_scan_profiles(mvm, req); | ||
| 1256 | if (ret) | ||
| 1257 | goto err; | ||
| 1258 | |||
| 1259 | ret = iwl_mvm_sched_scan_start(mvm, req); | ||
| 1260 | if (!ret) | ||
| 1261 | goto out; | ||
| 1262 | err: | ||
| 1263 | mvm->scan_status = IWL_MVM_SCAN_NONE; | ||
| 1264 | out: | ||
| 1265 | mutex_unlock(&mvm->mutex); | ||
| 1266 | return ret; | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | static void iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw, | ||
| 1270 | struct ieee80211_vif *vif) | ||
| 1271 | { | ||
| 1272 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
| 1273 | |||
| 1274 | mutex_lock(&mvm->mutex); | ||
| 1275 | iwl_mvm_sched_scan_stop(mvm); | ||
| 1167 | mutex_unlock(&mvm->mutex); | 1276 | mutex_unlock(&mvm->mutex); |
| 1168 | } | 1277 | } |
| 1169 | 1278 | ||
| @@ -1207,8 +1316,13 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, | |||
| 1207 | 1316 | ||
| 1208 | switch (cmd) { | 1317 | switch (cmd) { |
| 1209 | case SET_KEY: | 1318 | case SET_KEY: |
| 1210 | if (vif->type == NL80211_IFTYPE_AP && !sta) { | 1319 | if ((vif->type == NL80211_IFTYPE_ADHOC || |
| 1211 | /* GTK on AP interface is a TX-only key, return 0 */ | 1320 | vif->type == NL80211_IFTYPE_AP) && !sta) { |
| 1321 | /* | ||
| 1322 | * GTK on AP interface is a TX-only key, return 0; | ||
| 1323 | * on IBSS they're per-station and because we're lazy | ||
| 1324 | * we don't support them for RX, so do the same. | ||
| 1325 | */ | ||
| 1212 | ret = 0; | 1326 | ret = 0; |
| 1213 | key->hw_key_idx = STA_KEY_IDX_INVALID; | 1327 | key->hw_key_idx = STA_KEY_IDX_INVALID; |
| 1214 | break; | 1328 | break; |
| @@ -1252,6 +1366,9 @@ static void iwl_mvm_mac_update_tkip_key(struct ieee80211_hw *hw, | |||
| 1252 | { | 1366 | { |
| 1253 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 1367 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
| 1254 | 1368 | ||
| 1369 | if (keyconf->hw_key_idx == STA_KEY_IDX_INVALID) | ||
| 1370 | return; | ||
| 1371 | |||
| 1255 | iwl_mvm_update_tkip_key(mvm, vif, keyconf, sta, iv32, phase1key); | 1372 | iwl_mvm_update_tkip_key(mvm, vif, keyconf, sta, iv32, phase1key); |
| 1256 | } | 1373 | } |
| 1257 | 1374 | ||
| @@ -1445,6 +1562,7 @@ static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw, | |||
| 1445 | iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->def, | 1562 | iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->def, |
| 1446 | ctx->rx_chains_static, | 1563 | ctx->rx_chains_static, |
| 1447 | ctx->rx_chains_dynamic); | 1564 | ctx->rx_chains_dynamic); |
| 1565 | iwl_mvm_bt_coex_vif_change(mvm); | ||
| 1448 | mutex_unlock(&mvm->mutex); | 1566 | mutex_unlock(&mvm->mutex); |
| 1449 | } | 1567 | } |
| 1450 | 1568 | ||
| @@ -1464,14 +1582,14 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw, | |||
| 1464 | 1582 | ||
| 1465 | switch (vif->type) { | 1583 | switch (vif->type) { |
| 1466 | case NL80211_IFTYPE_AP: | 1584 | case NL80211_IFTYPE_AP: |
| 1585 | case NL80211_IFTYPE_ADHOC: | ||
| 1467 | /* | 1586 | /* |
| 1468 | * The AP binding flow is handled as part of the start_ap flow | 1587 | * The AP binding flow is handled as part of the start_ap flow |
| 1469 | * (in bss_info_changed). | 1588 | * (in bss_info_changed), similarly for IBSS. |
| 1470 | */ | 1589 | */ |
| 1471 | ret = 0; | 1590 | ret = 0; |
| 1472 | goto out_unlock; | 1591 | goto out_unlock; |
| 1473 | case NL80211_IFTYPE_STATION: | 1592 | case NL80211_IFTYPE_STATION: |
| 1474 | case NL80211_IFTYPE_ADHOC: | ||
| 1475 | case NL80211_IFTYPE_MONITOR: | 1593 | case NL80211_IFTYPE_MONITOR: |
| 1476 | break; | 1594 | break; |
| 1477 | default: | 1595 | default: |
| @@ -1517,10 +1635,10 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw, | |||
| 1517 | 1635 | ||
| 1518 | iwl_mvm_remove_time_event(mvm, mvmvif, &mvmvif->time_event_data); | 1636 | iwl_mvm_remove_time_event(mvm, mvmvif, &mvmvif->time_event_data); |
| 1519 | 1637 | ||
| 1520 | if (vif->type == NL80211_IFTYPE_AP) | ||
| 1521 | goto out_unlock; | ||
| 1522 | |||
| 1523 | switch (vif->type) { | 1638 | switch (vif->type) { |
| 1639 | case NL80211_IFTYPE_AP: | ||
| 1640 | case NL80211_IFTYPE_ADHOC: | ||
| 1641 | goto out_unlock; | ||
| 1524 | case NL80211_IFTYPE_MONITOR: | 1642 | case NL80211_IFTYPE_MONITOR: |
| 1525 | mvmvif->monitor_active = false; | 1643 | mvmvif->monitor_active = false; |
| 1526 | iwl_mvm_update_quotas(mvm, NULL); | 1644 | iwl_mvm_update_quotas(mvm, NULL); |
| @@ -1550,14 +1668,72 @@ static int iwl_mvm_set_tim(struct ieee80211_hw *hw, | |||
| 1550 | return iwl_mvm_mac_ctxt_beacon_changed(mvm, mvm_sta->vif); | 1668 | return iwl_mvm_mac_ctxt_beacon_changed(mvm, mvm_sta->vif); |
| 1551 | } | 1669 | } |
| 1552 | 1670 | ||
| 1553 | static void iwl_mvm_mac_rssi_callback(struct ieee80211_hw *hw, | 1671 | #ifdef CONFIG_NL80211_TESTMODE |
| 1672 | static const struct nla_policy iwl_mvm_tm_policy[IWL_MVM_TM_ATTR_MAX + 1] = { | ||
| 1673 | [IWL_MVM_TM_ATTR_CMD] = { .type = NLA_U32 }, | ||
| 1674 | [IWL_MVM_TM_ATTR_NOA_DURATION] = { .type = NLA_U32 }, | ||
| 1675 | [IWL_MVM_TM_ATTR_BEACON_FILTER_STATE] = { .type = NLA_U32 }, | ||
| 1676 | }; | ||
| 1677 | |||
| 1678 | static int __iwl_mvm_mac_testmode_cmd(struct iwl_mvm *mvm, | ||
| 1554 | struct ieee80211_vif *vif, | 1679 | struct ieee80211_vif *vif, |
| 1555 | enum ieee80211_rssi_event rssi_event) | 1680 | void *data, int len) |
| 1681 | { | ||
| 1682 | struct nlattr *tb[IWL_MVM_TM_ATTR_MAX + 1]; | ||
| 1683 | int err; | ||
| 1684 | u32 noa_duration; | ||
| 1685 | |||
| 1686 | err = nla_parse(tb, IWL_MVM_TM_ATTR_MAX, data, len, iwl_mvm_tm_policy); | ||
| 1687 | if (err) | ||
| 1688 | return err; | ||
| 1689 | |||
| 1690 | if (!tb[IWL_MVM_TM_ATTR_CMD]) | ||
| 1691 | return -EINVAL; | ||
| 1692 | |||
| 1693 | switch (nla_get_u32(tb[IWL_MVM_TM_ATTR_CMD])) { | ||
| 1694 | case IWL_MVM_TM_CMD_SET_NOA: | ||
| 1695 | if (!vif || vif->type != NL80211_IFTYPE_AP || !vif->p2p || | ||
| 1696 | !vif->bss_conf.enable_beacon || | ||
| 1697 | !tb[IWL_MVM_TM_ATTR_NOA_DURATION]) | ||
| 1698 | return -EINVAL; | ||
| 1699 | |||
| 1700 | noa_duration = nla_get_u32(tb[IWL_MVM_TM_ATTR_NOA_DURATION]); | ||
| 1701 | if (noa_duration >= vif->bss_conf.beacon_int) | ||
| 1702 | return -EINVAL; | ||
| 1703 | |||
| 1704 | mvm->noa_duration = noa_duration; | ||
| 1705 | mvm->noa_vif = vif; | ||
| 1706 | |||
| 1707 | return iwl_mvm_update_quotas(mvm, NULL); | ||
| 1708 | case IWL_MVM_TM_CMD_SET_BEACON_FILTER: | ||
| 1709 | /* must be associated client vif - ignore authorized */ | ||
| 1710 | if (!vif || vif->type != NL80211_IFTYPE_STATION || | ||
| 1711 | !vif->bss_conf.assoc || !vif->bss_conf.dtim_period || | ||
| 1712 | !tb[IWL_MVM_TM_ATTR_BEACON_FILTER_STATE]) | ||
| 1713 | return -EINVAL; | ||
| 1714 | |||
| 1715 | if (nla_get_u32(tb[IWL_MVM_TM_ATTR_BEACON_FILTER_STATE])) | ||
| 1716 | return iwl_mvm_enable_beacon_filter(mvm, vif); | ||
| 1717 | return iwl_mvm_disable_beacon_filter(mvm, vif); | ||
| 1718 | } | ||
| 1719 | |||
| 1720 | return -EOPNOTSUPP; | ||
| 1721 | } | ||
| 1722 | |||
| 1723 | static int iwl_mvm_mac_testmode_cmd(struct ieee80211_hw *hw, | ||
| 1724 | struct ieee80211_vif *vif, | ||
| 1725 | void *data, int len) | ||
| 1556 | { | 1726 | { |
| 1557 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 1727 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
| 1728 | int err; | ||
| 1558 | 1729 | ||
| 1559 | iwl_mvm_bt_rssi_event(mvm, vif, rssi_event); | 1730 | mutex_lock(&mvm->mutex); |
| 1731 | err = __iwl_mvm_mac_testmode_cmd(mvm, vif, data, len); | ||
| 1732 | mutex_unlock(&mvm->mutex); | ||
| 1733 | |||
| 1734 | return err; | ||
| 1560 | } | 1735 | } |
| 1736 | #endif | ||
| 1561 | 1737 | ||
| 1562 | struct ieee80211_ops iwl_mvm_hw_ops = { | 1738 | struct ieee80211_ops iwl_mvm_hw_ops = { |
| 1563 | .tx = iwl_mvm_mac_tx, | 1739 | .tx = iwl_mvm_mac_tx, |
| @@ -1578,23 +1754,27 @@ struct ieee80211_ops iwl_mvm_hw_ops = { | |||
| 1578 | .set_rts_threshold = iwl_mvm_mac_set_rts_threshold, | 1754 | .set_rts_threshold = iwl_mvm_mac_set_rts_threshold, |
| 1579 | .conf_tx = iwl_mvm_mac_conf_tx, | 1755 | .conf_tx = iwl_mvm_mac_conf_tx, |
| 1580 | .mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx, | 1756 | .mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx, |
| 1757 | .sched_scan_start = iwl_mvm_mac_sched_scan_start, | ||
| 1758 | .sched_scan_stop = iwl_mvm_mac_sched_scan_stop, | ||
| 1581 | .set_key = iwl_mvm_mac_set_key, | 1759 | .set_key = iwl_mvm_mac_set_key, |
| 1582 | .update_tkip_key = iwl_mvm_mac_update_tkip_key, | 1760 | .update_tkip_key = iwl_mvm_mac_update_tkip_key, |
| 1583 | .remain_on_channel = iwl_mvm_roc, | 1761 | .remain_on_channel = iwl_mvm_roc, |
| 1584 | .cancel_remain_on_channel = iwl_mvm_cancel_roc, | 1762 | .cancel_remain_on_channel = iwl_mvm_cancel_roc, |
| 1585 | .rssi_callback = iwl_mvm_mac_rssi_callback, | ||
| 1586 | |||
| 1587 | .add_chanctx = iwl_mvm_add_chanctx, | 1763 | .add_chanctx = iwl_mvm_add_chanctx, |
| 1588 | .remove_chanctx = iwl_mvm_remove_chanctx, | 1764 | .remove_chanctx = iwl_mvm_remove_chanctx, |
| 1589 | .change_chanctx = iwl_mvm_change_chanctx, | 1765 | .change_chanctx = iwl_mvm_change_chanctx, |
| 1590 | .assign_vif_chanctx = iwl_mvm_assign_vif_chanctx, | 1766 | .assign_vif_chanctx = iwl_mvm_assign_vif_chanctx, |
| 1591 | .unassign_vif_chanctx = iwl_mvm_unassign_vif_chanctx, | 1767 | .unassign_vif_chanctx = iwl_mvm_unassign_vif_chanctx, |
| 1592 | 1768 | ||
| 1593 | .start_ap = iwl_mvm_start_ap, | 1769 | .start_ap = iwl_mvm_start_ap_ibss, |
| 1594 | .stop_ap = iwl_mvm_stop_ap, | 1770 | .stop_ap = iwl_mvm_stop_ap_ibss, |
| 1771 | .join_ibss = iwl_mvm_start_ap_ibss, | ||
| 1772 | .leave_ibss = iwl_mvm_stop_ap_ibss, | ||
| 1595 | 1773 | ||
| 1596 | .set_tim = iwl_mvm_set_tim, | 1774 | .set_tim = iwl_mvm_set_tim, |
| 1597 | 1775 | ||
| 1776 | CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd) | ||
| 1777 | |||
| 1598 | #ifdef CONFIG_PM_SLEEP | 1778 | #ifdef CONFIG_PM_SLEEP |
| 1599 | /* look at d3.c */ | 1779 | /* look at d3.c */ |
| 1600 | .suspend = iwl_mvm_suspend, | 1780 | .suspend = iwl_mvm_suspend, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index b0389279cc1e..fed21ef4162d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
| @@ -73,7 +73,6 @@ | |||
| 73 | #include "iwl-trans.h" | 73 | #include "iwl-trans.h" |
| 74 | #include "iwl-notif-wait.h" | 74 | #include "iwl-notif-wait.h" |
| 75 | #include "iwl-eeprom-parse.h" | 75 | #include "iwl-eeprom-parse.h" |
| 76 | #include "iwl-trans.h" | ||
| 77 | #include "sta.h" | 76 | #include "sta.h" |
| 78 | #include "fw-api.h" | 77 | #include "fw-api.h" |
| 79 | #include "constants.h" | 78 | #include "constants.h" |
| @@ -162,6 +161,7 @@ enum iwl_power_scheme { | |||
| 162 | struct iwl_mvm_power_ops { | 161 | struct iwl_mvm_power_ops { |
| 163 | int (*power_update_mode)(struct iwl_mvm *mvm, | 162 | int (*power_update_mode)(struct iwl_mvm *mvm, |
| 164 | struct ieee80211_vif *vif); | 163 | struct ieee80211_vif *vif); |
| 164 | int (*power_update_device_mode)(struct iwl_mvm *mvm); | ||
| 165 | int (*power_disable)(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 165 | int (*power_disable)(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
| 166 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 166 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 167 | int (*power_dbgfs_read)(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 167 | int (*power_dbgfs_read)(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
| @@ -241,12 +241,18 @@ enum iwl_mvm_smps_type_request { | |||
| 241 | * @last_beacon_signal: last beacon rssi signal in dbm | 241 | * @last_beacon_signal: last beacon rssi signal in dbm |
| 242 | * @ave_beacon_signal: average beacon signal | 242 | * @ave_beacon_signal: average beacon signal |
| 243 | * @last_cqm_event: rssi of the last cqm event | 243 | * @last_cqm_event: rssi of the last cqm event |
| 244 | * @bt_coex_min_thold: minimum threshold for BT coex | ||
| 245 | * @bt_coex_max_thold: maximum threshold for BT coex | ||
| 246 | * @last_bt_coex_event: rssi of the last BT coex event | ||
| 244 | */ | 247 | */ |
| 245 | struct iwl_mvm_vif_bf_data { | 248 | struct iwl_mvm_vif_bf_data { |
| 246 | bool bf_enabled; | 249 | bool bf_enabled; |
| 247 | bool ba_enabled; | 250 | bool ba_enabled; |
| 248 | s8 ave_beacon_signal; | 251 | s8 ave_beacon_signal; |
| 249 | s8 last_cqm_event; | 252 | s8 last_cqm_event; |
| 253 | s8 bt_coex_min_thold; | ||
| 254 | s8 bt_coex_max_thold; | ||
| 255 | s8 last_bt_coex_event; | ||
| 250 | }; | 256 | }; |
| 251 | 257 | ||
| 252 | /** | 258 | /** |
| @@ -255,8 +261,8 @@ struct iwl_mvm_vif_bf_data { | |||
| 255 | * @color: to solve races upon MAC addition and removal | 261 | * @color: to solve races upon MAC addition and removal |
| 256 | * @ap_sta_id: the sta_id of the AP - valid only if VIF type is STA | 262 | * @ap_sta_id: the sta_id of the AP - valid only if VIF type is STA |
| 257 | * @uploaded: indicates the MAC context has been added to the device | 263 | * @uploaded: indicates the MAC context has been added to the device |
| 258 | * @ap_active: indicates that ap context is configured, and that the interface | 264 | * @ap_ibss_active: indicates that AP/IBSS is configured and that the interface |
| 259 | * should get quota etc. | 265 | * should get quota etc. |
| 260 | * @monitor_active: indicates that monitor context is configured, and that the | 266 | * @monitor_active: indicates that monitor context is configured, and that the |
| 261 | * interface should get quota etc. | 267 | * interface should get quota etc. |
| 262 | * @queue_params: QoS params for this MAC | 268 | * @queue_params: QoS params for this MAC |
| @@ -272,7 +278,7 @@ struct iwl_mvm_vif { | |||
| 272 | u8 ap_sta_id; | 278 | u8 ap_sta_id; |
| 273 | 279 | ||
| 274 | bool uploaded; | 280 | bool uploaded; |
| 275 | bool ap_active; | 281 | bool ap_ibss_active; |
| 276 | bool monitor_active; | 282 | bool monitor_active; |
| 277 | struct iwl_mvm_vif_bf_data bf_data; | 283 | struct iwl_mvm_vif_bf_data bf_data; |
| 278 | 284 | ||
| @@ -306,6 +312,9 @@ struct iwl_mvm_vif { | |||
| 306 | 312 | ||
| 307 | int tx_key_idx; | 313 | int tx_key_idx; |
| 308 | 314 | ||
| 315 | bool seqno_valid; | ||
| 316 | u16 seqno; | ||
| 317 | |||
| 309 | #if IS_ENABLED(CONFIG_IPV6) | 318 | #if IS_ENABLED(CONFIG_IPV6) |
| 310 | /* IPv6 addresses for WoWLAN */ | 319 | /* IPv6 addresses for WoWLAN */ |
| 311 | struct in6_addr target_ipv6_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX]; | 320 | struct in6_addr target_ipv6_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX]; |
| @@ -333,6 +342,7 @@ iwl_mvm_vif_from_mac80211(struct ieee80211_vif *vif) | |||
| 333 | enum iwl_scan_status { | 342 | enum iwl_scan_status { |
| 334 | IWL_MVM_SCAN_NONE, | 343 | IWL_MVM_SCAN_NONE, |
| 335 | IWL_MVM_SCAN_OS, | 344 | IWL_MVM_SCAN_OS, |
| 345 | IWL_MVM_SCAN_SCHED, | ||
| 336 | }; | 346 | }; |
| 337 | 347 | ||
| 338 | /** | 348 | /** |
| @@ -434,7 +444,7 @@ struct iwl_mvm { | |||
| 434 | 444 | ||
| 435 | enum iwl_ucode_type cur_ucode; | 445 | enum iwl_ucode_type cur_ucode; |
| 436 | bool ucode_loaded; | 446 | bool ucode_loaded; |
| 437 | bool init_ucode_run; | 447 | bool init_ucode_complete; |
| 438 | u32 error_event_table; | 448 | u32 error_event_table; |
| 439 | u32 log_event_table; | 449 | u32 log_event_table; |
| 440 | 450 | ||
| @@ -470,6 +480,9 @@ struct iwl_mvm { | |||
| 470 | enum iwl_scan_status scan_status; | 480 | enum iwl_scan_status scan_status; |
| 471 | struct iwl_scan_cmd *scan_cmd; | 481 | struct iwl_scan_cmd *scan_cmd; |
| 472 | 482 | ||
| 483 | /* rx chain antennas set through debugfs for the scan command */ | ||
| 484 | u8 scan_rx_ant; | ||
| 485 | |||
| 473 | /* Internal station */ | 486 | /* Internal station */ |
| 474 | struct iwl_mvm_int_sta aux_sta; | 487 | struct iwl_mvm_int_sta aux_sta; |
| 475 | 488 | ||
| @@ -479,7 +492,8 @@ struct iwl_mvm { | |||
| 479 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 492 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 480 | struct dentry *debugfs_dir; | 493 | struct dentry *debugfs_dir; |
| 481 | u32 dbgfs_sram_offset, dbgfs_sram_len; | 494 | u32 dbgfs_sram_offset, dbgfs_sram_len; |
| 482 | bool prevent_power_down_d3; | 495 | bool disable_power_off; |
| 496 | bool disable_power_off_d3; | ||
| 483 | #endif | 497 | #endif |
| 484 | 498 | ||
| 485 | struct iwl_mvm_phy_ctxt phy_ctxts[NUM_PHY_CTX]; | 499 | struct iwl_mvm_phy_ctxt phy_ctxts[NUM_PHY_CTX]; |
| @@ -523,12 +537,23 @@ struct iwl_mvm { | |||
| 523 | /* BT-Coex */ | 537 | /* BT-Coex */ |
| 524 | u8 bt_kill_msk; | 538 | u8 bt_kill_msk; |
| 525 | struct iwl_bt_coex_profile_notif last_bt_notif; | 539 | struct iwl_bt_coex_profile_notif last_bt_notif; |
| 540 | struct iwl_bt_coex_ci_cmd last_bt_ci_cmd; | ||
| 526 | 541 | ||
| 527 | /* Thermal Throttling and CTkill */ | 542 | /* Thermal Throttling and CTkill */ |
| 528 | struct iwl_mvm_tt_mgmt thermal_throttle; | 543 | struct iwl_mvm_tt_mgmt thermal_throttle; |
| 529 | s32 temperature; /* Celsius */ | 544 | s32 temperature; /* Celsius */ |
| 530 | 545 | ||
| 531 | const struct iwl_mvm_power_ops *pm_ops; | 546 | const struct iwl_mvm_power_ops *pm_ops; |
| 547 | |||
| 548 | #ifdef CONFIG_NL80211_TESTMODE | ||
| 549 | u32 noa_duration; | ||
| 550 | struct ieee80211_vif *noa_vif; | ||
| 551 | #endif | ||
| 552 | |||
| 553 | /* Tx queues */ | ||
| 554 | u8 aux_queue; | ||
| 555 | u8 first_agg_queue; | ||
| 556 | u8 last_agg_queue; | ||
| 532 | }; | 557 | }; |
| 533 | 558 | ||
| 534 | /* Extract MVM priv from op_mode and _hw */ | 559 | /* Extract MVM priv from op_mode and _hw */ |
| @@ -570,6 +595,9 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm); | |||
| 570 | /* Utils */ | 595 | /* Utils */ |
| 571 | int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags, | 596 | int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags, |
| 572 | enum ieee80211_band band); | 597 | enum ieee80211_band band); |
| 598 | void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags, | ||
| 599 | enum ieee80211_band band, | ||
| 600 | struct ieee80211_tx_rate *r); | ||
| 573 | u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx); | 601 | u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx); |
| 574 | void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm); | 602 | void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm); |
| 575 | void iwl_mvm_dump_sram(struct iwl_mvm *mvm); | 603 | void iwl_mvm_dump_sram(struct iwl_mvm *mvm); |
| @@ -608,6 +636,7 @@ int iwl_mvm_rx_statistics(struct iwl_mvm *mvm, | |||
| 608 | 636 | ||
| 609 | /* NVM */ | 637 | /* NVM */ |
| 610 | int iwl_nvm_init(struct iwl_mvm *mvm); | 638 | int iwl_nvm_init(struct iwl_mvm *mvm); |
| 639 | int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm); | ||
| 611 | 640 | ||
| 612 | int iwl_mvm_up(struct iwl_mvm *mvm); | 641 | int iwl_mvm_up(struct iwl_mvm *mvm); |
| 613 | int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm); | 642 | int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm); |
| @@ -682,6 +711,23 @@ int iwl_mvm_rx_scan_complete(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
| 682 | struct iwl_device_cmd *cmd); | 711 | struct iwl_device_cmd *cmd); |
| 683 | void iwl_mvm_cancel_scan(struct iwl_mvm *mvm); | 712 | void iwl_mvm_cancel_scan(struct iwl_mvm *mvm); |
| 684 | 713 | ||
| 714 | /* Scheduled scan */ | ||
| 715 | int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, | ||
| 716 | struct iwl_rx_cmd_buffer *rxb, | ||
| 717 | struct iwl_device_cmd *cmd); | ||
| 718 | int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm, | ||
| 719 | struct ieee80211_vif *vif, | ||
| 720 | struct cfg80211_sched_scan_request *req, | ||
| 721 | struct ieee80211_sched_scan_ies *ies); | ||
| 722 | int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm, | ||
| 723 | struct cfg80211_sched_scan_request *req); | ||
| 724 | int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, | ||
| 725 | struct cfg80211_sched_scan_request *req); | ||
| 726 | void iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm); | ||
| 727 | int iwl_mvm_rx_sched_scan_results(struct iwl_mvm *mvm, | ||
| 728 | struct iwl_rx_cmd_buffer *rxb, | ||
| 729 | struct iwl_device_cmd *cmd); | ||
| 730 | |||
| 685 | /* MVM debugfs */ | 731 | /* MVM debugfs */ |
| 686 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 732 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 687 | int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir); | 733 | int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir); |
| @@ -720,6 +766,13 @@ static inline int iwl_mvm_power_disable(struct iwl_mvm *mvm, | |||
| 720 | return mvm->pm_ops->power_disable(mvm, vif); | 766 | return mvm->pm_ops->power_disable(mvm, vif); |
| 721 | } | 767 | } |
| 722 | 768 | ||
| 769 | static inline int iwl_mvm_power_update_device_mode(struct iwl_mvm *mvm) | ||
| 770 | { | ||
| 771 | if (mvm->pm_ops->power_update_device_mode) | ||
| 772 | return mvm->pm_ops->power_update_device_mode(mvm); | ||
| 773 | return 0; | ||
| 774 | } | ||
| 775 | |||
| 723 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 776 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 724 | static inline int iwl_mvm_power_dbgfs_read(struct iwl_mvm *mvm, | 777 | static inline int iwl_mvm_power_dbgfs_read(struct iwl_mvm *mvm, |
| 725 | struct ieee80211_vif *vif, | 778 | struct ieee80211_vif *vif, |
| @@ -745,6 +798,15 @@ void iwl_mvm_ipv6_addr_change(struct ieee80211_hw *hw, | |||
| 745 | void iwl_mvm_set_default_unicast_key(struct ieee80211_hw *hw, | 798 | void iwl_mvm_set_default_unicast_key(struct ieee80211_hw *hw, |
| 746 | struct ieee80211_vif *vif, int idx); | 799 | struct ieee80211_vif *vif, int idx); |
| 747 | extern const struct file_operations iwl_dbgfs_d3_test_ops; | 800 | extern const struct file_operations iwl_dbgfs_d3_test_ops; |
| 801 | #ifdef CONFIG_PM_SLEEP | ||
| 802 | void iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, | ||
| 803 | struct ieee80211_vif *vif); | ||
| 804 | #else | ||
| 805 | static inline void | ||
| 806 | iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | ||
| 807 | { | ||
| 808 | } | ||
| 809 | #endif | ||
| 748 | 810 | ||
| 749 | /* BT Coex */ | 811 | /* BT Coex */ |
| 750 | int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm); | 812 | int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm); |
| @@ -754,7 +816,20 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, | |||
| 754 | struct iwl_device_cmd *cmd); | 816 | struct iwl_device_cmd *cmd); |
| 755 | void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 817 | void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
| 756 | enum ieee80211_rssi_event rssi_event); | 818 | enum ieee80211_rssi_event rssi_event); |
| 757 | void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 819 | void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm); |
| 820 | u16 iwl_mvm_bt_coex_agg_time_limit(struct iwl_mvm *mvm, | ||
| 821 | struct ieee80211_sta *sta); | ||
| 822 | bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm, | ||
| 823 | struct ieee80211_sta *sta); | ||
| 824 | |||
| 825 | enum iwl_bt_kill_msk { | ||
| 826 | BT_KILL_MSK_DEFAULT, | ||
| 827 | BT_KILL_MSK_SCO_HID_A2DP, | ||
| 828 | BT_KILL_MSK_REDUCED_TXPOW, | ||
| 829 | BT_KILL_MSK_MAX, | ||
| 830 | }; | ||
| 831 | extern const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX]; | ||
| 832 | extern const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX]; | ||
| 758 | 833 | ||
| 759 | /* beacon filtering */ | 834 | /* beacon filtering */ |
| 760 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 835 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index edb94ea31654..2beffd028b67 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c | |||
| @@ -77,7 +77,7 @@ static const int nvm_to_read[] = { | |||
| 77 | 77 | ||
| 78 | /* Default NVM size to read */ | 78 | /* Default NVM size to read */ |
| 79 | #define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024) | 79 | #define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024) |
| 80 | #define IWL_MAX_NVM_SECTION_SIZE 6000 | 80 | #define IWL_MAX_NVM_SECTION_SIZE 7000 |
| 81 | 81 | ||
| 82 | #define NVM_WRITE_OPCODE 1 | 82 | #define NVM_WRITE_OPCODE 1 |
| 83 | #define NVM_READ_OPCODE 0 | 83 | #define NVM_READ_OPCODE 0 |
| @@ -259,6 +259,8 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) | |||
| 259 | #define MAX_NVM_FILE_LEN 16384 | 259 | #define MAX_NVM_FILE_LEN 16384 |
| 260 | 260 | ||
| 261 | /* | 261 | /* |
| 262 | * Reads external NVM from a file into mvm->nvm_sections | ||
| 263 | * | ||
| 262 | * HOW TO CREATE THE NVM FILE FORMAT: | 264 | * HOW TO CREATE THE NVM FILE FORMAT: |
| 263 | * ------------------------------ | 265 | * ------------------------------ |
| 264 | * 1. create hex file, format: | 266 | * 1. create hex file, format: |
| @@ -277,20 +279,23 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) | |||
| 277 | * | 279 | * |
| 278 | * 4. save as "iNVM_xxx.bin" under /lib/firmware | 280 | * 4. save as "iNVM_xxx.bin" under /lib/firmware |
| 279 | */ | 281 | */ |
| 280 | static int iwl_mvm_load_external_nvm(struct iwl_mvm *mvm) | 282 | static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm) |
| 281 | { | 283 | { |
| 282 | int ret, section_id, section_size; | 284 | int ret, section_size; |
| 285 | u16 section_id; | ||
| 283 | const struct firmware *fw_entry; | 286 | const struct firmware *fw_entry; |
| 284 | const struct { | 287 | const struct { |
| 285 | __le16 word1; | 288 | __le16 word1; |
| 286 | __le16 word2; | 289 | __le16 word2; |
| 287 | u8 data[]; | 290 | u8 data[]; |
| 288 | } *file_sec; | 291 | } *file_sec; |
| 289 | const u8 *eof; | 292 | const u8 *eof, *temp; |
| 290 | 293 | ||
| 291 | #define NVM_WORD1_LEN(x) (8 * (x & 0x03FF)) | 294 | #define NVM_WORD1_LEN(x) (8 * (x & 0x03FF)) |
| 292 | #define NVM_WORD2_ID(x) (x >> 12) | 295 | #define NVM_WORD2_ID(x) (x >> 12) |
| 293 | 296 | ||
| 297 | IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n"); | ||
| 298 | |||
| 294 | /* | 299 | /* |
| 295 | * Obtain NVM image via request_firmware. Since we already used | 300 | * Obtain NVM image via request_firmware. Since we already used |
| 296 | * request_firmware_nowait() for the firmware binary load and only | 301 | * request_firmware_nowait() for the firmware binary load and only |
| @@ -362,12 +367,18 @@ static int iwl_mvm_load_external_nvm(struct iwl_mvm *mvm) | |||
| 362 | break; | 367 | break; |
| 363 | } | 368 | } |
| 364 | 369 | ||
| 365 | ret = iwl_nvm_write_section(mvm, section_id, file_sec->data, | 370 | temp = kmemdup(file_sec->data, section_size, GFP_KERNEL); |
| 366 | section_size); | 371 | if (!temp) { |
| 367 | if (ret < 0) { | 372 | ret = -ENOMEM; |
| 368 | IWL_ERR(mvm, "iwl_mvm_send_cmd failed: %d\n", ret); | 373 | break; |
| 374 | } | ||
| 375 | if (WARN_ON(section_id >= NVM_NUM_OF_SECTIONS)) { | ||
| 376 | IWL_ERR(mvm, "Invalid NVM section ID\n"); | ||
| 377 | ret = -EINVAL; | ||
| 369 | break; | 378 | break; |
| 370 | } | 379 | } |
| 380 | mvm->nvm_sections[section_id].data = temp; | ||
| 381 | mvm->nvm_sections[section_id].length = section_size; | ||
| 371 | 382 | ||
| 372 | /* advance to the next section */ | 383 | /* advance to the next section */ |
| 373 | file_sec = (void *)(file_sec->data + section_size); | 384 | file_sec = (void *)(file_sec->data + section_size); |
| @@ -377,6 +388,28 @@ out: | |||
| 377 | return ret; | 388 | return ret; |
| 378 | } | 389 | } |
| 379 | 390 | ||
| 391 | /* Loads the NVM data stored in mvm->nvm_sections into the NIC */ | ||
| 392 | int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm) | ||
| 393 | { | ||
| 394 | int i, ret; | ||
| 395 | u16 section_id; | ||
| 396 | struct iwl_nvm_section *sections = mvm->nvm_sections; | ||
| 397 | |||
| 398 | IWL_DEBUG_EEPROM(mvm->trans->dev, "'Write to NVM\n"); | ||
| 399 | |||
| 400 | for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) { | ||
| 401 | section_id = nvm_to_read[i]; | ||
| 402 | ret = iwl_nvm_write_section(mvm, section_id, | ||
| 403 | sections[section_id].data, | ||
| 404 | sections[section_id].length); | ||
| 405 | if (ret < 0) { | ||
| 406 | IWL_ERR(mvm, "iwl_mvm_send_cmd failed: %d\n", ret); | ||
| 407 | break; | ||
| 408 | } | ||
| 409 | } | ||
| 410 | return ret; | ||
| 411 | } | ||
| 412 | |||
| 380 | int iwl_nvm_init(struct iwl_mvm *mvm) | 413 | int iwl_nvm_init(struct iwl_mvm *mvm) |
| 381 | { | 414 | { |
| 382 | int ret, i, section; | 415 | int ret, i, section; |
| @@ -385,36 +418,36 @@ int iwl_nvm_init(struct iwl_mvm *mvm) | |||
| 385 | /* load external NVM if configured */ | 418 | /* load external NVM if configured */ |
| 386 | if (iwlwifi_mod_params.nvm_file) { | 419 | if (iwlwifi_mod_params.nvm_file) { |
| 387 | /* move to External NVM flow */ | 420 | /* move to External NVM flow */ |
| 388 | ret = iwl_mvm_load_external_nvm(mvm); | 421 | ret = iwl_mvm_read_external_nvm(mvm); |
| 389 | if (ret) | 422 | if (ret) |
| 390 | return ret; | 423 | return ret; |
| 391 | } | 424 | } else { |
| 392 | 425 | /* Read From FW NVM */ | |
| 393 | /* Read From FW NVM */ | 426 | IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n"); |
| 394 | IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n"); | 427 | |
| 395 | 428 | /* TODO: find correct NVM max size for a section */ | |
| 396 | /* TODO: find correct NVM max size for a section */ | 429 | nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size, |
| 397 | nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size, | 430 | GFP_KERNEL); |
| 398 | GFP_KERNEL); | 431 | if (!nvm_buffer) |
| 399 | if (!nvm_buffer) | 432 | return -ENOMEM; |
| 400 | return -ENOMEM; | 433 | for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) { |
| 401 | for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) { | 434 | section = nvm_to_read[i]; |
| 402 | section = nvm_to_read[i]; | 435 | /* we override the constness for initial read */ |
| 403 | /* we override the constness for initial read */ | 436 | ret = iwl_nvm_read_section(mvm, section, nvm_buffer); |
| 404 | ret = iwl_nvm_read_section(mvm, section, nvm_buffer); | 437 | if (ret < 0) |
| 405 | if (ret < 0) | 438 | break; |
| 406 | break; | 439 | temp = kmemdup(nvm_buffer, ret, GFP_KERNEL); |
| 407 | temp = kmemdup(nvm_buffer, ret, GFP_KERNEL); | 440 | if (!temp) { |
| 408 | if (!temp) { | 441 | ret = -ENOMEM; |
| 409 | ret = -ENOMEM; | 442 | break; |
| 410 | break; | 443 | } |
| 444 | mvm->nvm_sections[section].data = temp; | ||
| 445 | mvm->nvm_sections[section].length = ret; | ||
| 411 | } | 446 | } |
| 412 | mvm->nvm_sections[section].data = temp; | 447 | kfree(nvm_buffer); |
| 413 | mvm->nvm_sections[section].length = ret; | 448 | if (ret < 0) |
| 449 | return ret; | ||
| 414 | } | 450 | } |
| 415 | kfree(nvm_buffer); | ||
| 416 | if (ret < 0) | ||
| 417 | return ret; | ||
| 418 | 451 | ||
| 419 | mvm->nvm_data = iwl_parse_nvm_sections(mvm); | 452 | mvm->nvm_data = iwl_parse_nvm_sections(mvm); |
| 420 | if (!mvm->nvm_data) | 453 | if (!mvm->nvm_data) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 2fcc8ef88a68..d86083c6f445 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
| @@ -224,6 +224,10 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { | |||
| 224 | 224 | ||
| 225 | RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false), | 225 | RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false), |
| 226 | RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false), | 226 | RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false), |
| 227 | RX_HANDLER(SCAN_OFFLOAD_COMPLETE, | ||
| 228 | iwl_mvm_rx_scan_offload_complete_notif, false), | ||
| 229 | RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_sched_scan_results, | ||
| 230 | false), | ||
| 227 | 231 | ||
| 228 | RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false), | 232 | RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false), |
| 229 | RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false), | 233 | RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false), |
| @@ -249,6 +253,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { | |||
| 249 | CMD(TIME_EVENT_NOTIFICATION), | 253 | CMD(TIME_EVENT_NOTIFICATION), |
| 250 | CMD(BINDING_CONTEXT_CMD), | 254 | CMD(BINDING_CONTEXT_CMD), |
| 251 | CMD(TIME_QUOTA_CMD), | 255 | CMD(TIME_QUOTA_CMD), |
| 256 | CMD(NON_QOS_TX_COUNTER_CMD), | ||
| 252 | CMD(RADIO_VERSION_NOTIFICATION), | 257 | CMD(RADIO_VERSION_NOTIFICATION), |
| 253 | CMD(SCAN_REQUEST_CMD), | 258 | CMD(SCAN_REQUEST_CMD), |
| 254 | CMD(SCAN_ABORT_CMD), | 259 | CMD(SCAN_ABORT_CMD), |
| @@ -260,10 +265,12 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { | |||
| 260 | CMD(CALIB_RES_NOTIF_PHY_DB), | 265 | CMD(CALIB_RES_NOTIF_PHY_DB), |
| 261 | CMD(SET_CALIB_DEFAULT_CMD), | 266 | CMD(SET_CALIB_DEFAULT_CMD), |
| 262 | CMD(CALIBRATION_COMPLETE_NOTIFICATION), | 267 | CMD(CALIBRATION_COMPLETE_NOTIFICATION), |
| 268 | CMD(ADD_STA_KEY), | ||
| 263 | CMD(ADD_STA), | 269 | CMD(ADD_STA), |
| 264 | CMD(REMOVE_STA), | 270 | CMD(REMOVE_STA), |
| 265 | CMD(LQ_CMD), | 271 | CMD(LQ_CMD), |
| 266 | CMD(SCAN_OFFLOAD_CONFIG_CMD), | 272 | CMD(SCAN_OFFLOAD_CONFIG_CMD), |
| 273 | CMD(MATCH_FOUND_NOTIFICATION), | ||
| 267 | CMD(SCAN_OFFLOAD_REQUEST_CMD), | 274 | CMD(SCAN_OFFLOAD_REQUEST_CMD), |
| 268 | CMD(SCAN_OFFLOAD_ABORT_CMD), | 275 | CMD(SCAN_OFFLOAD_ABORT_CMD), |
| 269 | CMD(SCAN_OFFLOAD_COMPLETE), | 276 | CMD(SCAN_OFFLOAD_COMPLETE), |
| @@ -303,6 +310,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { | |||
| 303 | CMD(REPLY_BEACON_FILTERING_CMD), | 310 | CMD(REPLY_BEACON_FILTERING_CMD), |
| 304 | CMD(REPLY_THERMAL_MNG_BACKOFF), | 311 | CMD(REPLY_THERMAL_MNG_BACKOFF), |
| 305 | CMD(MAC_PM_POWER_TABLE), | 312 | CMD(MAC_PM_POWER_TABLE), |
| 313 | CMD(BT_COEX_CI), | ||
| 306 | }; | 314 | }; |
| 307 | #undef CMD | 315 | #undef CMD |
| 308 | 316 | ||
| @@ -344,6 +352,14 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
| 344 | 352 | ||
| 345 | mvm->restart_fw = iwlwifi_mod_params.restart_fw ? -1 : 0; | 353 | mvm->restart_fw = iwlwifi_mod_params.restart_fw ? -1 : 0; |
| 346 | 354 | ||
| 355 | mvm->aux_queue = 15; | ||
| 356 | mvm->first_agg_queue = 16; | ||
| 357 | mvm->last_agg_queue = mvm->cfg->base_params->num_of_queues - 1; | ||
| 358 | if (mvm->cfg->base_params->num_of_queues == 16) { | ||
| 359 | mvm->aux_queue = 11; | ||
| 360 | mvm->first_agg_queue = 12; | ||
| 361 | } | ||
| 362 | |||
| 347 | mutex_init(&mvm->mutex); | 363 | mutex_init(&mvm->mutex); |
| 348 | spin_lock_init(&mvm->async_handlers_lock); | 364 | spin_lock_init(&mvm->async_handlers_lock); |
| 349 | INIT_LIST_HEAD(&mvm->time_event_list); | 365 | INIT_LIST_HEAD(&mvm->time_event_list); |
| @@ -401,24 +417,32 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
| 401 | IWL_INFO(mvm, "Detected %s, REV=0x%X\n", | 417 | IWL_INFO(mvm, "Detected %s, REV=0x%X\n", |
| 402 | mvm->cfg->name, mvm->trans->hw_rev); | 418 | mvm->cfg->name, mvm->trans->hw_rev); |
| 403 | 419 | ||
| 404 | err = iwl_trans_start_hw(mvm->trans); | ||
| 405 | if (err) | ||
| 406 | goto out_free; | ||
| 407 | |||
| 408 | iwl_mvm_tt_initialize(mvm); | 420 | iwl_mvm_tt_initialize(mvm); |
| 409 | 421 | ||
| 410 | mutex_lock(&mvm->mutex); | 422 | /* |
| 411 | err = iwl_run_init_mvm_ucode(mvm, true); | 423 | * If the NVM exists in an external file, |
| 412 | mutex_unlock(&mvm->mutex); | 424 | * there is no need to unnecessarily power up the NIC at driver load |
| 413 | /* returns 0 if successful, 1 if success but in rfkill */ | 425 | */ |
| 414 | if (err < 0 && !iwlmvm_mod_params.init_dbg) { | 426 | if (iwlwifi_mod_params.nvm_file) { |
| 415 | IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", err); | 427 | iwl_nvm_init(mvm); |
| 416 | goto out_free; | 428 | } else { |
| 417 | } | 429 | err = iwl_trans_start_hw(mvm->trans); |
| 430 | if (err) | ||
| 431 | goto out_free; | ||
| 432 | |||
| 433 | mutex_lock(&mvm->mutex); | ||
| 434 | err = iwl_run_init_mvm_ucode(mvm, true); | ||
| 435 | mutex_unlock(&mvm->mutex); | ||
| 436 | /* returns 0 if successful, 1 if success but in rfkill */ | ||
| 437 | if (err < 0 && !iwlmvm_mod_params.init_dbg) { | ||
| 438 | IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", err); | ||
| 439 | goto out_free; | ||
| 440 | } | ||
| 418 | 441 | ||
| 419 | /* Stop the hw after the ALIVE and NVM has been read */ | 442 | /* Stop the hw after the ALIVE and NVM has been read */ |
| 420 | if (!iwlmvm_mod_params.init_dbg) | 443 | if (!iwlmvm_mod_params.init_dbg) |
| 421 | iwl_trans_stop_hw(mvm->trans, false); | 444 | iwl_trans_stop_hw(mvm->trans, false); |
| 445 | } | ||
| 422 | 446 | ||
| 423 | scan_size = sizeof(struct iwl_scan_cmd) + | 447 | scan_size = sizeof(struct iwl_scan_cmd) + |
| 424 | mvm->fw->ucode_capa.max_probe_length + | 448 | mvm->fw->ucode_capa.max_probe_length + |
| @@ -435,7 +459,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
| 435 | if (err) | 459 | if (err) |
| 436 | goto out_unregister; | 460 | goto out_unregister; |
| 437 | 461 | ||
| 438 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD) | 462 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT) |
| 439 | mvm->pm_ops = &pm_mac_ops; | 463 | mvm->pm_ops = &pm_mac_ops; |
| 440 | else | 464 | else |
| 441 | mvm->pm_ops = &pm_legacy_ops; | 465 | mvm->pm_ops = &pm_legacy_ops; |
| @@ -449,7 +473,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
| 449 | out_free: | 473 | out_free: |
| 450 | iwl_phy_db_free(mvm->phy_db); | 474 | iwl_phy_db_free(mvm->phy_db); |
| 451 | kfree(mvm->scan_cmd); | 475 | kfree(mvm->scan_cmd); |
| 452 | iwl_trans_stop_hw(trans, true); | 476 | if (!iwlwifi_mod_params.nvm_file) |
| 477 | iwl_trans_stop_hw(trans, true); | ||
| 453 | ieee80211_free_hw(mvm->hw); | 478 | ieee80211_free_hw(mvm->hw); |
| 454 | return NULL; | 479 | return NULL; |
| 455 | } | 480 | } |
| @@ -715,6 +740,9 @@ static void iwl_mvm_nic_restart(struct iwl_mvm *mvm) | |||
| 715 | case IWL_MVM_SCAN_OS: | 740 | case IWL_MVM_SCAN_OS: |
| 716 | ieee80211_scan_completed(mvm->hw, true); | 741 | ieee80211_scan_completed(mvm->hw, true); |
| 717 | break; | 742 | break; |
| 743 | case IWL_MVM_SCAN_SCHED: | ||
| 744 | ieee80211_sched_scan_stopped(mvm->hw); | ||
| 745 | break; | ||
| 718 | } | 746 | } |
| 719 | 747 | ||
| 720 | if (mvm->restart_fw > 0) | 748 | if (mvm->restart_fw > 0) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index d58e393324ef..550824aa84ea 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c | |||
| @@ -300,11 +300,6 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | |||
| 300 | } | 300 | } |
| 301 | 301 | ||
| 302 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)) { | 302 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)) { |
| 303 | cmd->rx_data_timeout_uapsd = | ||
| 304 | cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT); | ||
| 305 | cmd->tx_data_timeout_uapsd = | ||
| 306 | cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT); | ||
| 307 | |||
| 308 | if (cmd->uapsd_ac_flags == (BIT(IEEE80211_AC_VO) | | 303 | if (cmd->uapsd_ac_flags == (BIT(IEEE80211_AC_VO) | |
| 309 | BIT(IEEE80211_AC_VI) | | 304 | BIT(IEEE80211_AC_VI) | |
| 310 | BIT(IEEE80211_AC_BE) | | 305 | BIT(IEEE80211_AC_BE) | |
| @@ -319,10 +314,31 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | |||
| 319 | } | 314 | } |
| 320 | 315 | ||
| 321 | cmd->uapsd_max_sp = IWL_UAPSD_MAX_SP; | 316 | cmd->uapsd_max_sp = IWL_UAPSD_MAX_SP; |
| 322 | cmd->heavy_tx_thld_packets = | 317 | |
| 323 | IWL_MVM_PS_HEAVY_TX_THLD_PACKETS; | 318 | if (mvm->cur_ucode == IWL_UCODE_WOWLAN || cmd->flags & |
| 324 | cmd->heavy_rx_thld_packets = | 319 | cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) { |
| 325 | IWL_MVM_PS_HEAVY_RX_THLD_PACKETS; | 320 | cmd->rx_data_timeout_uapsd = |
| 321 | cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT); | ||
| 322 | cmd->tx_data_timeout_uapsd = | ||
| 323 | cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT); | ||
| 324 | } else { | ||
| 325 | cmd->rx_data_timeout_uapsd = | ||
| 326 | cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT); | ||
| 327 | cmd->tx_data_timeout_uapsd = | ||
| 328 | cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT); | ||
| 329 | } | ||
| 330 | |||
| 331 | if (cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) { | ||
| 332 | cmd->heavy_tx_thld_packets = | ||
| 333 | IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS; | ||
| 334 | cmd->heavy_rx_thld_packets = | ||
| 335 | IWL_MVM_PS_SNOOZE_HEAVY_RX_THLD_PACKETS; | ||
| 336 | } else { | ||
| 337 | cmd->heavy_tx_thld_packets = | ||
| 338 | IWL_MVM_PS_HEAVY_TX_THLD_PACKETS; | ||
| 339 | cmd->heavy_rx_thld_packets = | ||
| 340 | IWL_MVM_PS_HEAVY_RX_THLD_PACKETS; | ||
| 341 | } | ||
| 326 | cmd->heavy_tx_thld_percentage = | 342 | cmd->heavy_tx_thld_percentage = |
| 327 | IWL_MVM_PS_HEAVY_TX_THLD_PERCENT; | 343 | IWL_MVM_PS_HEAVY_TX_THLD_PERCENT; |
| 328 | cmd->heavy_rx_thld_percentage = | 344 | cmd->heavy_rx_thld_percentage = |
| @@ -430,6 +446,32 @@ static int iwl_mvm_power_mac_disable(struct iwl_mvm *mvm, | |||
| 430 | sizeof(cmd), &cmd); | 446 | sizeof(cmd), &cmd); |
| 431 | } | 447 | } |
| 432 | 448 | ||
| 449 | static int iwl_mvm_power_update_device(struct iwl_mvm *mvm) | ||
| 450 | { | ||
| 451 | struct iwl_device_power_cmd cmd = { | ||
| 452 | .flags = cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK), | ||
| 453 | }; | ||
| 454 | |||
| 455 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)) | ||
| 456 | return 0; | ||
| 457 | |||
| 458 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) | ||
| 459 | cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_CAM_MSK); | ||
| 460 | |||
| 461 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
| 462 | if ((mvm->cur_ucode == IWL_UCODE_WOWLAN) ? mvm->disable_power_off_d3 : | ||
| 463 | mvm->disable_power_off) | ||
| 464 | cmd.flags &= | ||
| 465 | cpu_to_le16(~DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK); | ||
| 466 | #endif | ||
| 467 | IWL_DEBUG_POWER(mvm, | ||
| 468 | "Sending device power command with flags = 0x%X\n", | ||
| 469 | cmd.flags); | ||
| 470 | |||
| 471 | return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC, sizeof(cmd), | ||
| 472 | &cmd); | ||
| 473 | } | ||
| 474 | |||
| 433 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 475 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 434 | static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, | 476 | static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, |
| 435 | struct ieee80211_vif *vif, char *buf, | 477 | struct ieee80211_vif *vif, char *buf, |
| @@ -440,10 +482,11 @@ static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, | |||
| 440 | 482 | ||
| 441 | iwl_mvm_power_build_cmd(mvm, vif, &cmd); | 483 | iwl_mvm_power_build_cmd(mvm, vif, &cmd); |
| 442 | 484 | ||
| 443 | pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n", | 485 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)) |
| 444 | (cmd.flags & | 486 | pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n", |
| 445 | cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ? | 487 | (cmd.flags & |
| 446 | 0 : 1); | 488 | cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ? |
| 489 | 0 : 1); | ||
| 447 | pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n", | 490 | pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n", |
| 448 | iwlmvm_mod_params.power_scheme); | 491 | iwlmvm_mod_params.power_scheme); |
| 449 | pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n", | 492 | pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n", |
| @@ -609,6 +652,7 @@ int iwl_mvm_update_beacon_filter(struct iwl_mvm *mvm, | |||
| 609 | 652 | ||
| 610 | const struct iwl_mvm_power_ops pm_mac_ops = { | 653 | const struct iwl_mvm_power_ops pm_mac_ops = { |
| 611 | .power_update_mode = iwl_mvm_power_mac_update_mode, | 654 | .power_update_mode = iwl_mvm_power_mac_update_mode, |
| 655 | .power_update_device_mode = iwl_mvm_power_update_device, | ||
| 612 | .power_disable = iwl_mvm_power_mac_disable, | 656 | .power_disable = iwl_mvm_power_mac_disable, |
| 613 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 657 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 614 | .power_dbgfs_read = iwl_mvm_power_mac_dbgfs_read, | 658 | .power_dbgfs_read = iwl_mvm_power_mac_dbgfs_read, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/quota.c b/drivers/net/wireless/iwlwifi/mvm/quota.c index 5c6ae16ec52b..17e2bc827f9a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/quota.c +++ b/drivers/net/wireless/iwlwifi/mvm/quota.c | |||
| @@ -110,7 +110,8 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac, | |||
| 110 | data->n_interfaces[id]++; | 110 | data->n_interfaces[id]++; |
| 111 | break; | 111 | break; |
| 112 | case NL80211_IFTYPE_AP: | 112 | case NL80211_IFTYPE_AP: |
| 113 | if (mvmvif->ap_active) | 113 | case NL80211_IFTYPE_ADHOC: |
| 114 | if (mvmvif->ap_ibss_active) | ||
| 114 | data->n_interfaces[id]++; | 115 | data->n_interfaces[id]++; |
| 115 | break; | 116 | break; |
| 116 | case NL80211_IFTYPE_MONITOR: | 117 | case NL80211_IFTYPE_MONITOR: |
| @@ -119,16 +120,45 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac, | |||
| 119 | break; | 120 | break; |
| 120 | case NL80211_IFTYPE_P2P_DEVICE: | 121 | case NL80211_IFTYPE_P2P_DEVICE: |
| 121 | break; | 122 | break; |
| 122 | case NL80211_IFTYPE_ADHOC: | ||
| 123 | if (vif->bss_conf.ibss_joined) | ||
| 124 | data->n_interfaces[id]++; | ||
| 125 | break; | ||
| 126 | default: | 123 | default: |
| 127 | WARN_ON_ONCE(1); | 124 | WARN_ON_ONCE(1); |
| 128 | break; | 125 | break; |
| 129 | } | 126 | } |
| 130 | } | 127 | } |
| 131 | 128 | ||
| 129 | static void iwl_mvm_adjust_quota_for_noa(struct iwl_mvm *mvm, | ||
| 130 | struct iwl_time_quota_cmd *cmd) | ||
| 131 | { | ||
| 132 | #ifdef CONFIG_NL80211_TESTMODE | ||
| 133 | struct iwl_mvm_vif *mvmvif; | ||
| 134 | int i, phy_id = -1, beacon_int = 0; | ||
| 135 | |||
| 136 | if (!mvm->noa_duration || !mvm->noa_vif) | ||
| 137 | return; | ||
| 138 | |||
| 139 | mvmvif = iwl_mvm_vif_from_mac80211(mvm->noa_vif); | ||
| 140 | if (!mvmvif->ap_ibss_active) | ||
| 141 | return; | ||
| 142 | |||
| 143 | phy_id = mvmvif->phy_ctxt->id; | ||
| 144 | beacon_int = mvm->noa_vif->bss_conf.beacon_int; | ||
| 145 | |||
| 146 | for (i = 0; i < MAX_BINDINGS; i++) { | ||
| 147 | u32 id_n_c = le32_to_cpu(cmd->quotas[i].id_and_color); | ||
| 148 | u32 id = (id_n_c & FW_CTXT_ID_MSK) >> FW_CTXT_ID_POS; | ||
| 149 | u32 quota = le32_to_cpu(cmd->quotas[i].quota); | ||
| 150 | |||
| 151 | if (id != phy_id) | ||
| 152 | continue; | ||
| 153 | |||
| 154 | quota *= (beacon_int - mvm->noa_duration); | ||
| 155 | quota /= beacon_int; | ||
| 156 | |||
| 157 | cmd->quotas[i].quota = cpu_to_le32(quota); | ||
| 158 | } | ||
| 159 | #endif | ||
| 160 | } | ||
| 161 | |||
| 132 | int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) | 162 | int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) |
| 133 | { | 163 | { |
| 134 | struct iwl_time_quota_cmd cmd = {}; | 164 | struct iwl_time_quota_cmd cmd = {}; |
| @@ -196,6 +226,8 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) | |||
| 196 | /* Give the remainder of the session to the first binding */ | 226 | /* Give the remainder of the session to the first binding */ |
| 197 | le32_add_cpu(&cmd.quotas[0].quota, quota_rem); | 227 | le32_add_cpu(&cmd.quotas[0].quota, quota_rem); |
| 198 | 228 | ||
| 229 | iwl_mvm_adjust_quota_for_noa(mvm, &cmd); | ||
| 230 | |||
| 199 | ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, CMD_SYNC, | 231 | ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, CMD_SYNC, |
| 200 | sizeof(cmd), &cmd); | 232 | sizeof(cmd), &cmd); |
| 201 | if (ret) | 233 | if (ret) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 4ffaa3fa153f..a0b4cc8d9c3b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
| @@ -82,13 +82,24 @@ static const u8 ant_toggle_lookup[] = { | |||
| 82 | [ANT_ABC] = ANT_ABC, | 82 | [ANT_ABC] = ANT_ABC, |
| 83 | }; | 83 | }; |
| 84 | 84 | ||
| 85 | #define IWL_DECLARE_RATE_INFO(r, s, rp, rn) \ | 85 | #define IWL_DECLARE_RATE_INFO(r, s, rp, rn) \ |
| 86 | [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ | 86 | [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ |
| 87 | IWL_RATE_SISO_##s##M_PLCP, \ | 87 | IWL_RATE_HT_SISO_MCS_##s##_PLCP, \ |
| 88 | IWL_RATE_MIMO2_##s##M_PLCP,\ | 88 | IWL_RATE_HT_MIMO2_MCS_##s##_PLCP, \ |
| 89 | IWL_RATE_##rp##M_INDEX, \ | 89 | IWL_RATE_VHT_SISO_MCS_##s##_PLCP, \ |
| 90 | IWL_RATE_VHT_MIMO2_MCS_##s##_PLCP,\ | ||
| 91 | IWL_RATE_##rp##M_INDEX, \ | ||
| 90 | IWL_RATE_##rn##M_INDEX } | 92 | IWL_RATE_##rn##M_INDEX } |
| 91 | 93 | ||
| 94 | #define IWL_DECLARE_MCS_RATE(s) \ | ||
| 95 | [IWL_RATE_MCS_##s##_INDEX] = { IWL_RATE_INVM_PLCP, \ | ||
| 96 | IWL_RATE_HT_SISO_MCS_##s##_PLCP, \ | ||
| 97 | IWL_RATE_HT_MIMO2_MCS_##s##_PLCP, \ | ||
| 98 | IWL_RATE_VHT_SISO_MCS_##s##_PLCP, \ | ||
| 99 | IWL_RATE_VHT_MIMO2_MCS_##s##_PLCP, \ | ||
| 100 | IWL_RATE_INVM_INDEX, \ | ||
| 101 | IWL_RATE_INVM_INDEX } | ||
| 102 | |||
| 92 | /* | 103 | /* |
| 93 | * Parameter order: | 104 | * Parameter order: |
| 94 | * rate, ht rate, prev rate, next rate | 105 | * rate, ht rate, prev rate, next rate |
| @@ -102,16 +113,17 @@ static const struct iwl_rs_rate_info iwl_rates[IWL_RATE_COUNT] = { | |||
| 102 | IWL_DECLARE_RATE_INFO(2, INV, 1, 5), /* 2mbps */ | 113 | IWL_DECLARE_RATE_INFO(2, INV, 1, 5), /* 2mbps */ |
| 103 | IWL_DECLARE_RATE_INFO(5, INV, 2, 11), /*5.5mbps */ | 114 | IWL_DECLARE_RATE_INFO(5, INV, 2, 11), /*5.5mbps */ |
| 104 | IWL_DECLARE_RATE_INFO(11, INV, 9, 12), /* 11mbps */ | 115 | IWL_DECLARE_RATE_INFO(11, INV, 9, 12), /* 11mbps */ |
| 105 | IWL_DECLARE_RATE_INFO(6, 6, 5, 11), /* 6mbps */ | 116 | IWL_DECLARE_RATE_INFO(6, 0, 5, 11), /* 6mbps ; MCS 0 */ |
| 106 | IWL_DECLARE_RATE_INFO(9, 6, 6, 11), /* 9mbps */ | 117 | IWL_DECLARE_RATE_INFO(9, INV, 6, 11), /* 9mbps */ |
| 107 | IWL_DECLARE_RATE_INFO(12, 12, 11, 18), /* 12mbps */ | 118 | IWL_DECLARE_RATE_INFO(12, 1, 11, 18), /* 12mbps ; MCS 1 */ |
| 108 | IWL_DECLARE_RATE_INFO(18, 18, 12, 24), /* 18mbps */ | 119 | IWL_DECLARE_RATE_INFO(18, 2, 12, 24), /* 18mbps ; MCS 2 */ |
| 109 | IWL_DECLARE_RATE_INFO(24, 24, 18, 36), /* 24mbps */ | 120 | IWL_DECLARE_RATE_INFO(24, 3, 18, 36), /* 24mbps ; MCS 3 */ |
| 110 | IWL_DECLARE_RATE_INFO(36, 36, 24, 48), /* 36mbps */ | 121 | IWL_DECLARE_RATE_INFO(36, 4, 24, 48), /* 36mbps ; MCS 4 */ |
| 111 | IWL_DECLARE_RATE_INFO(48, 48, 36, 54), /* 48mbps */ | 122 | IWL_DECLARE_RATE_INFO(48, 5, 36, 54), /* 48mbps ; MCS 5 */ |
| 112 | IWL_DECLARE_RATE_INFO(54, 54, 48, INV), /* 54mbps */ | 123 | IWL_DECLARE_RATE_INFO(54, 6, 48, INV), /* 54mbps ; MCS 6 */ |
| 113 | IWL_DECLARE_RATE_INFO(60, 60, 48, INV), /* 60mbps */ | 124 | IWL_DECLARE_MCS_RATE(7), /* MCS 7 */ |
| 114 | /* FIXME:RS: ^^ should be INV (legacy) */ | 125 | IWL_DECLARE_MCS_RATE(8), /* MCS 8 */ |
| 126 | IWL_DECLARE_MCS_RATE(9), /* MCS 9 */ | ||
| 115 | }; | 127 | }; |
| 116 | 128 | ||
| 117 | static inline u8 rs_extract_rate(u32 rate_n_flags) | 129 | static inline u8 rs_extract_rate(u32 rate_n_flags) |
| @@ -124,26 +136,30 @@ static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) | |||
| 124 | { | 136 | { |
| 125 | int idx = 0; | 137 | int idx = 0; |
| 126 | 138 | ||
| 127 | /* HT rate format */ | ||
| 128 | if (rate_n_flags & RATE_MCS_HT_MSK) { | 139 | if (rate_n_flags & RATE_MCS_HT_MSK) { |
| 129 | idx = rs_extract_rate(rate_n_flags); | 140 | idx = rate_n_flags & RATE_HT_MCS_RATE_CODE_MSK; |
| 130 | 141 | idx += IWL_RATE_MCS_0_INDEX; | |
| 131 | WARN_ON_ONCE(idx >= IWL_RATE_MIMO3_6M_PLCP); | ||
| 132 | if (idx >= IWL_RATE_MIMO2_6M_PLCP) | ||
| 133 | idx = idx - IWL_RATE_MIMO2_6M_PLCP; | ||
| 134 | 142 | ||
| 135 | idx += IWL_FIRST_OFDM_RATE; | 143 | /* skip 9M not supported in HT*/ |
| 136 | /* skip 9M not supported in ht*/ | ||
| 137 | if (idx >= IWL_RATE_9M_INDEX) | 144 | if (idx >= IWL_RATE_9M_INDEX) |
| 138 | idx += 1; | 145 | idx += 1; |
| 139 | if ((idx >= IWL_FIRST_OFDM_RATE) && (idx <= IWL_LAST_OFDM_RATE)) | 146 | if ((idx >= IWL_FIRST_HT_RATE) && (idx <= IWL_LAST_HT_RATE)) |
| 140 | return idx; | 147 | return idx; |
| 148 | } else if (rate_n_flags & RATE_MCS_VHT_MSK) { | ||
| 149 | idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK; | ||
| 150 | idx += IWL_RATE_MCS_0_INDEX; | ||
| 141 | 151 | ||
| 142 | /* legacy rate format, search for match in table */ | 152 | /* skip 9M not supported in VHT*/ |
| 153 | if (idx >= IWL_RATE_9M_INDEX) | ||
| 154 | idx++; | ||
| 155 | if ((idx >= IWL_FIRST_VHT_RATE) && (idx <= IWL_LAST_VHT_RATE)) | ||
| 156 | return idx; | ||
| 143 | } else { | 157 | } else { |
| 158 | /* legacy rate format, search for match in table */ | ||
| 159 | |||
| 160 | u8 legacy_rate = rs_extract_rate(rate_n_flags); | ||
| 144 | for (idx = 0; idx < ARRAY_SIZE(iwl_rates); idx++) | 161 | for (idx = 0; idx < ARRAY_SIZE(iwl_rates); idx++) |
| 145 | if (iwl_rates[idx].plcp == | 162 | if (iwl_rates[idx].plcp == legacy_rate) |
| 146 | rs_extract_rate(rate_n_flags)) | ||
| 147 | return idx; | 163 | return idx; |
| 148 | } | 164 | } |
| 149 | 165 | ||
| @@ -155,6 +171,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
| 155 | struct ieee80211_sta *sta, | 171 | struct ieee80211_sta *sta, |
| 156 | struct iwl_lq_sta *lq_sta); | 172 | struct iwl_lq_sta *lq_sta); |
| 157 | static void rs_fill_link_cmd(struct iwl_mvm *mvm, | 173 | static void rs_fill_link_cmd(struct iwl_mvm *mvm, |
| 174 | struct ieee80211_sta *sta, | ||
| 158 | struct iwl_lq_sta *lq_sta, u32 rate_n_flags); | 175 | struct iwl_lq_sta *lq_sta, u32 rate_n_flags); |
| 159 | static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search); | 176 | static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search); |
| 160 | 177 | ||
| @@ -180,35 +197,52 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, | |||
| 180 | */ | 197 | */ |
| 181 | 198 | ||
| 182 | static s32 expected_tpt_legacy[IWL_RATE_COUNT] = { | 199 | static s32 expected_tpt_legacy[IWL_RATE_COUNT] = { |
| 183 | 7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 0 | 200 | 7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 0, 0, 0 |
| 184 | }; | 201 | }; |
| 185 | 202 | ||
| 186 | static s32 expected_tpt_siso20MHz[4][IWL_RATE_COUNT] = { | 203 | /* Expected TpT tables. 4 indexes: |
| 187 | {0, 0, 0, 0, 42, 0, 76, 102, 124, 159, 183, 193, 202}, /* Norm */ | 204 | * 0 - NGI, 1 - SGI, 2 - AGG+NGI, 3 - AGG+SGI |
| 188 | {0, 0, 0, 0, 46, 0, 82, 110, 132, 168, 192, 202, 210}, /* SGI */ | 205 | */ |
| 189 | {0, 0, 0, 0, 47, 0, 91, 133, 171, 242, 305, 334, 362}, /* AGG */ | 206 | static s32 expected_tpt_siso_20MHz[4][IWL_RATE_COUNT] = { |
| 190 | {0, 0, 0, 0, 52, 0, 101, 145, 187, 264, 330, 361, 390}, /* AGG+SGI */ | 207 | {0, 0, 0, 0, 42, 0, 76, 102, 124, 159, 183, 193, 202, 216, 0}, |
| 208 | {0, 0, 0, 0, 46, 0, 82, 110, 132, 168, 192, 202, 210, 225, 0}, | ||
| 209 | {0, 0, 0, 0, 49, 0, 97, 145, 192, 285, 375, 420, 464, 551, 0}, | ||
| 210 | {0, 0, 0, 0, 54, 0, 108, 160, 213, 315, 415, 465, 513, 608, 0}, | ||
| 191 | }; | 211 | }; |
| 192 | 212 | ||
| 193 | static s32 expected_tpt_siso40MHz[4][IWL_RATE_COUNT] = { | 213 | static s32 expected_tpt_siso_40MHz[4][IWL_RATE_COUNT] = { |
| 194 | {0, 0, 0, 0, 77, 0, 127, 160, 184, 220, 242, 250, 257}, /* Norm */ | 214 | {0, 0, 0, 0, 77, 0, 127, 160, 184, 220, 242, 250, 257, 269, 275}, |
| 195 | {0, 0, 0, 0, 83, 0, 135, 169, 193, 229, 250, 257, 264}, /* SGI */ | 215 | {0, 0, 0, 0, 83, 0, 135, 169, 193, 229, 250, 257, 264, 275, 280}, |
| 196 | {0, 0, 0, 0, 94, 0, 177, 249, 313, 423, 512, 550, 586}, /* AGG */ | 216 | {0, 0, 0, 0, 101, 0, 199, 295, 389, 570, 744, 828, 911, 1070, 1173}, |
| 197 | {0, 0, 0, 0, 104, 0, 193, 270, 338, 454, 545, 584, 620}, /* AGG+SGI */ | 217 | {0, 0, 0, 0, 112, 0, 220, 326, 429, 629, 819, 912, 1000, 1173, 1284}, |
| 218 | }; | ||
| 219 | |||
| 220 | static s32 expected_tpt_siso_80MHz[4][IWL_RATE_COUNT] = { | ||
| 221 | {0, 0, 0, 0, 130, 0, 191, 223, 244, 273, 288, 294, 298, 305, 308}, | ||
| 222 | {0, 0, 0, 0, 138, 0, 200, 231, 251, 279, 293, 298, 302, 308, 312}, | ||
| 223 | {0, 0, 0, 0, 217, 0, 429, 634, 834, 1220, 1585, 1760, 1931, 2258, 2466}, | ||
| 224 | {0, 0, 0, 0, 241, 0, 475, 701, 921, 1343, 1741, 1931, 2117, 2468, 2691}, | ||
| 198 | }; | 225 | }; |
| 199 | 226 | ||
| 200 | static s32 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = { | 227 | static s32 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = { |
| 201 | {0, 0, 0, 0, 74, 0, 123, 155, 179, 214, 236, 244, 251}, /* Norm */ | 228 | {0, 0, 0, 0, 74, 0, 123, 155, 179, 213, 235, 243, 250, 261, 0}, |
| 202 | {0, 0, 0, 0, 81, 0, 131, 164, 188, 223, 243, 251, 257}, /* SGI */ | 229 | {0, 0, 0, 0, 81, 0, 131, 164, 187, 221, 242, 250, 256, 267, 0}, |
| 203 | {0, 0, 0, 0, 89, 0, 167, 235, 296, 402, 488, 526, 560}, /* AGG */ | 230 | {0, 0, 0, 0, 98, 0, 193, 286, 375, 550, 718, 799, 878, 1032, 0}, |
| 204 | {0, 0, 0, 0, 97, 0, 182, 255, 320, 431, 520, 558, 593}, /* AGG+SGI*/ | 231 | {0, 0, 0, 0, 109, 0, 214, 316, 414, 607, 790, 879, 965, 1132, 0}, |
| 205 | }; | 232 | }; |
| 206 | 233 | ||
| 207 | static s32 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = { | 234 | static s32 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = { |
| 208 | {0, 0, 0, 0, 123, 0, 182, 214, 235, 264, 279, 285, 289}, /* Norm */ | 235 | {0, 0, 0, 0, 123, 0, 182, 214, 235, 264, 279, 285, 289, 296, 300}, |
| 209 | {0, 0, 0, 0, 131, 0, 191, 222, 242, 270, 284, 289, 293}, /* SGI */ | 236 | {0, 0, 0, 0, 131, 0, 191, 222, 242, 270, 284, 289, 293, 300, 303}, |
| 210 | {0, 0, 0, 0, 171, 0, 305, 410, 496, 634, 731, 771, 805}, /* AGG */ | 237 | {0, 0, 0, 0, 200, 0, 390, 571, 741, 1067, 1365, 1505, 1640, 1894, 2053}, |
| 211 | {0, 0, 0, 0, 186, 0, 329, 439, 527, 667, 764, 803, 838}, /* AGG+SGI */ | 238 | {0, 0, 0, 0, 221, 0, 430, 630, 816, 1169, 1490, 1641, 1784, 2053, 2221}, |
| 239 | }; | ||
| 240 | |||
| 241 | static s32 expected_tpt_mimo2_80MHz[4][IWL_RATE_COUNT] = { | ||
| 242 | {0, 0, 0, 0, 182, 0, 240, 264, 278, 299, 308, 311, 313, 317, 319}, | ||
| 243 | {0, 0, 0, 0, 190, 0, 247, 269, 282, 302, 310, 313, 315, 319, 320}, | ||
| 244 | {0, 0, 0, 0, 428, 0, 833, 1215, 1577, 2254, 2863, 3147, 3418, 3913, 4219}, | ||
| 245 | {0, 0, 0, 0, 474, 0, 920, 1338, 1732, 2464, 3116, 3418, 3705, 4225, 4545}, | ||
| 212 | }; | 246 | }; |
| 213 | 247 | ||
| 214 | /* mbps, mcs */ | 248 | /* mbps, mcs */ |
| @@ -263,7 +297,7 @@ static void rs_program_fix_rate(struct iwl_mvm *mvm, | |||
| 263 | lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate); | 297 | lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate); |
| 264 | 298 | ||
| 265 | if (lq_sta->dbg_fixed_rate) { | 299 | if (lq_sta->dbg_fixed_rate) { |
| 266 | rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate); | 300 | rs_fill_link_cmd(NULL, NULL, lq_sta, lq_sta->dbg_fixed_rate); |
| 267 | iwl_mvm_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC, false); | 301 | iwl_mvm_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC, false); |
| 268 | } | 302 | } |
| 269 | } | 303 | } |
| @@ -275,17 +309,6 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_mvm *mvm, | |||
| 275 | { | 309 | { |
| 276 | int ret = -EAGAIN; | 310 | int ret = -EAGAIN; |
| 277 | 311 | ||
| 278 | /* | ||
| 279 | * Don't create TX aggregation sessions when in high | ||
| 280 | * BT traffic, as they would just be disrupted by BT. | ||
| 281 | */ | ||
| 282 | if (BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD) >= 2) { | ||
| 283 | IWL_DEBUG_COEX(mvm, "BT traffic (%d), no aggregation allowed\n", | ||
| 284 | BT_MBOX_MSG(&mvm->last_bt_notif, | ||
| 285 | 3, TRAFFIC_LOAD)); | ||
| 286 | return ret; | ||
| 287 | } | ||
| 288 | |||
| 289 | IWL_DEBUG_HT(mvm, "Starting Tx agg: STA: %pM tid: %d\n", | 312 | IWL_DEBUG_HT(mvm, "Starting Tx agg: STA: %pM tid: %d\n", |
| 290 | sta->addr, tid); | 313 | sta->addr, tid); |
| 291 | ret = ieee80211_start_tx_ba_session(sta, tid, 5000); | 314 | ret = ieee80211_start_tx_ba_session(sta, tid, 5000); |
| @@ -416,49 +439,54 @@ static int rs_collect_tx_data(struct iwl_scale_tbl_info *tbl, | |||
| 416 | */ | 439 | */ |
| 417 | /* FIXME:RS:remove this function and put the flags statically in the table */ | 440 | /* FIXME:RS:remove this function and put the flags statically in the table */ |
| 418 | static u32 rate_n_flags_from_tbl(struct iwl_mvm *mvm, | 441 | static u32 rate_n_flags_from_tbl(struct iwl_mvm *mvm, |
| 419 | struct iwl_scale_tbl_info *tbl, | 442 | struct iwl_scale_tbl_info *tbl, int index) |
| 420 | int index, u8 use_green) | ||
| 421 | { | 443 | { |
| 422 | u32 rate_n_flags = 0; | 444 | u32 rate_n_flags = 0; |
| 423 | 445 | ||
| 446 | rate_n_flags |= ((tbl->ant_type << RATE_MCS_ANT_POS) & | ||
| 447 | RATE_MCS_ANT_ABC_MSK); | ||
| 448 | |||
| 424 | if (is_legacy(tbl->lq_type)) { | 449 | if (is_legacy(tbl->lq_type)) { |
| 425 | rate_n_flags = iwl_rates[index].plcp; | 450 | rate_n_flags |= iwl_rates[index].plcp; |
| 426 | if (index >= IWL_FIRST_CCK_RATE && index <= IWL_LAST_CCK_RATE) | 451 | if (index >= IWL_FIRST_CCK_RATE && index <= IWL_LAST_CCK_RATE) |
| 427 | rate_n_flags |= RATE_MCS_CCK_MSK; | 452 | rate_n_flags |= RATE_MCS_CCK_MSK; |
| 428 | } else if (is_Ht(tbl->lq_type)) { | 453 | return rate_n_flags; |
| 429 | if (index > IWL_LAST_OFDM_RATE) { | 454 | } |
| 455 | |||
| 456 | if (is_ht(tbl->lq_type)) { | ||
| 457 | if (index < IWL_FIRST_HT_RATE || index > IWL_LAST_HT_RATE) { | ||
| 430 | IWL_ERR(mvm, "Invalid HT rate index %d\n", index); | 458 | IWL_ERR(mvm, "Invalid HT rate index %d\n", index); |
| 431 | index = IWL_LAST_OFDM_RATE; | 459 | index = IWL_LAST_HT_RATE; |
| 432 | } | 460 | } |
| 433 | rate_n_flags = RATE_MCS_HT_MSK; | 461 | rate_n_flags |= RATE_MCS_HT_MSK; |
| 434 | 462 | ||
| 435 | if (is_siso(tbl->lq_type)) | 463 | if (is_ht_siso(tbl->lq_type)) |
| 436 | rate_n_flags |= iwl_rates[index].plcp_siso; | 464 | rate_n_flags |= iwl_rates[index].plcp_ht_siso; |
| 437 | else if (is_mimo2(tbl->lq_type)) | 465 | else if (is_ht_mimo2(tbl->lq_type)) |
| 438 | rate_n_flags |= iwl_rates[index].plcp_mimo2; | 466 | rate_n_flags |= iwl_rates[index].plcp_ht_mimo2; |
| 439 | else | 467 | else |
| 440 | WARN_ON_ONCE(1); | 468 | WARN_ON_ONCE(1); |
| 469 | } else if (is_vht(tbl->lq_type)) { | ||
| 470 | if (index < IWL_FIRST_VHT_RATE || index > IWL_LAST_VHT_RATE) { | ||
| 471 | IWL_ERR(mvm, "Invalid VHT rate index %d\n", index); | ||
| 472 | index = IWL_LAST_VHT_RATE; | ||
| 473 | } | ||
| 474 | rate_n_flags |= RATE_MCS_VHT_MSK; | ||
| 475 | if (is_vht_siso(tbl->lq_type)) | ||
| 476 | rate_n_flags |= iwl_rates[index].plcp_vht_siso; | ||
| 477 | else if (is_vht_mimo2(tbl->lq_type)) | ||
| 478 | rate_n_flags |= iwl_rates[index].plcp_vht_mimo2; | ||
| 479 | else | ||
| 480 | WARN_ON_ONCE(1); | ||
| 481 | |||
| 441 | } else { | 482 | } else { |
| 442 | IWL_ERR(mvm, "Invalid tbl->lq_type %d\n", tbl->lq_type); | 483 | IWL_ERR(mvm, "Invalid tbl->lq_type %d\n", tbl->lq_type); |
| 443 | } | 484 | } |
| 444 | 485 | ||
| 445 | rate_n_flags |= ((tbl->ant_type << RATE_MCS_ANT_POS) & | 486 | rate_n_flags |= tbl->bw; |
| 446 | RATE_MCS_ANT_ABC_MSK); | 487 | if (tbl->is_SGI) |
| 447 | 488 | rate_n_flags |= RATE_MCS_SGI_MSK; | |
| 448 | if (is_Ht(tbl->lq_type)) { | 489 | |
| 449 | if (tbl->is_ht40) | ||
| 450 | rate_n_flags |= RATE_MCS_CHAN_WIDTH_40; | ||
| 451 | if (tbl->is_SGI) | ||
| 452 | rate_n_flags |= RATE_MCS_SGI_MSK; | ||
| 453 | |||
| 454 | if (use_green) { | ||
| 455 | rate_n_flags |= RATE_HT_MCS_GF_MSK; | ||
| 456 | if (is_siso(tbl->lq_type) && tbl->is_SGI) { | ||
| 457 | rate_n_flags &= ~RATE_MCS_SGI_MSK; | ||
| 458 | IWL_ERR(mvm, "GF was set with SGI:SISO\n"); | ||
| 459 | } | ||
| 460 | } | ||
| 461 | } | ||
| 462 | return rate_n_flags; | 490 | return rate_n_flags; |
| 463 | } | 491 | } |
| 464 | 492 | ||
| @@ -473,7 +501,7 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, | |||
| 473 | { | 501 | { |
| 474 | u32 ant_msk = (rate_n_flags & RATE_MCS_ANT_ABC_MSK); | 502 | u32 ant_msk = (rate_n_flags & RATE_MCS_ANT_ABC_MSK); |
| 475 | u8 num_of_ant = get_num_of_ant_from_rate(rate_n_flags); | 503 | u8 num_of_ant = get_num_of_ant_from_rate(rate_n_flags); |
| 476 | u8 mcs; | 504 | u8 nss; |
| 477 | 505 | ||
| 478 | memset(tbl, 0, offsetof(struct iwl_scale_tbl_info, win)); | 506 | memset(tbl, 0, offsetof(struct iwl_scale_tbl_info, win)); |
| 479 | *rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); | 507 | *rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); |
| @@ -483,41 +511,62 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, | |||
| 483 | return -EINVAL; | 511 | return -EINVAL; |
| 484 | } | 512 | } |
| 485 | tbl->is_SGI = 0; /* default legacy setup */ | 513 | tbl->is_SGI = 0; /* default legacy setup */ |
| 486 | tbl->is_ht40 = 0; | 514 | tbl->bw = 0; |
| 487 | tbl->ant_type = (ant_msk >> RATE_MCS_ANT_POS); | 515 | tbl->ant_type = (ant_msk >> RATE_MCS_ANT_POS); |
| 488 | tbl->lq_type = LQ_NONE; | 516 | tbl->lq_type = LQ_NONE; |
| 489 | tbl->max_search = IWL_MAX_SEARCH; | 517 | tbl->max_search = IWL_MAX_SEARCH; |
| 490 | 518 | ||
| 491 | /* legacy rate format */ | 519 | /* Legacy */ |
| 492 | if (!(rate_n_flags & RATE_MCS_HT_MSK)) { | 520 | if (!(rate_n_flags & RATE_MCS_HT_MSK) && |
| 521 | !(rate_n_flags & RATE_MCS_VHT_MSK)) { | ||
| 493 | if (num_of_ant == 1) { | 522 | if (num_of_ant == 1) { |
| 494 | if (band == IEEE80211_BAND_5GHZ) | 523 | if (band == IEEE80211_BAND_5GHZ) |
| 495 | tbl->lq_type = LQ_A; | 524 | tbl->lq_type = LQ_LEGACY_A; |
| 496 | else | 525 | else |
| 497 | tbl->lq_type = LQ_G; | 526 | tbl->lq_type = LQ_LEGACY_G; |
| 498 | } | 527 | } |
| 499 | /* HT rate format */ | 528 | |
| 500 | } else { | 529 | return 0; |
| 501 | if (rate_n_flags & RATE_MCS_SGI_MSK) | 530 | } |
| 502 | tbl->is_SGI = 1; | 531 | |
| 503 | 532 | /* HT or VHT */ | |
| 504 | if (rate_n_flags & RATE_MCS_CHAN_WIDTH_40) /* TODO */ | 533 | if (rate_n_flags & RATE_MCS_SGI_MSK) |
| 505 | tbl->is_ht40 = 1; | 534 | tbl->is_SGI = 1; |
| 506 | 535 | ||
| 507 | mcs = rs_extract_rate(rate_n_flags); | 536 | tbl->bw = rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK; |
| 508 | 537 | ||
| 509 | /* SISO */ | 538 | if (rate_n_flags & RATE_MCS_HT_MSK) { |
| 510 | if (mcs <= IWL_RATE_SISO_60M_PLCP) { | 539 | nss = ((rate_n_flags & RATE_HT_MCS_NSS_MSK) >> |
| 511 | if (num_of_ant == 1) | 540 | RATE_HT_MCS_NSS_POS) + 1; |
| 512 | tbl->lq_type = LQ_SISO; /*else NONE*/ | 541 | |
| 513 | /* MIMO2 */ | 542 | if (nss == 1) { |
| 514 | } else if (mcs <= IWL_RATE_MIMO2_60M_PLCP) { | 543 | tbl->lq_type = LQ_HT_SISO; |
| 515 | if (num_of_ant == 2) | 544 | WARN_ON_ONCE(num_of_ant != 1); |
| 516 | tbl->lq_type = LQ_MIMO2; | 545 | } else if (nss == 2) { |
| 546 | tbl->lq_type = LQ_HT_MIMO2; | ||
| 547 | WARN_ON_ONCE(num_of_ant != 2); | ||
| 548 | } else { | ||
| 549 | WARN_ON_ONCE(1); | ||
| 550 | } | ||
| 551 | } else if (rate_n_flags & RATE_MCS_VHT_MSK) { | ||
| 552 | nss = ((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >> | ||
| 553 | RATE_VHT_MCS_NSS_POS) + 1; | ||
| 554 | |||
| 555 | if (nss == 1) { | ||
| 556 | tbl->lq_type = LQ_VHT_SISO; | ||
| 557 | WARN_ON_ONCE(num_of_ant != 1); | ||
| 558 | } else if (nss == 2) { | ||
| 559 | tbl->lq_type = LQ_VHT_MIMO2; | ||
| 560 | WARN_ON_ONCE(num_of_ant != 2); | ||
| 517 | } else { | 561 | } else { |
| 518 | WARN_ON_ONCE(num_of_ant == 3); | 562 | WARN_ON_ONCE(1); |
| 519 | } | 563 | } |
| 520 | } | 564 | } |
| 565 | |||
| 566 | WARN_ON_ONCE(tbl->bw == RATE_MCS_CHAN_WIDTH_160); | ||
| 567 | WARN_ON_ONCE(tbl->bw == RATE_MCS_CHAN_WIDTH_80 && | ||
| 568 | !is_vht(tbl->lq_type)); | ||
| 569 | |||
| 521 | return 0; | 570 | return 0; |
| 522 | } | 571 | } |
| 523 | 572 | ||
| @@ -550,22 +599,6 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, | |||
| 550 | } | 599 | } |
| 551 | 600 | ||
| 552 | /** | 601 | /** |
| 553 | * Green-field mode is valid if the station supports it and | ||
| 554 | * there are no non-GF stations present in the BSS. | ||
| 555 | */ | ||
| 556 | static bool rs_use_green(struct ieee80211_sta *sta) | ||
| 557 | { | ||
| 558 | /* | ||
| 559 | * There's a bug somewhere in this code that causes the | ||
| 560 | * scaling to get stuck because GF+SGI can't be combined | ||
| 561 | * in SISO rates. Until we find that bug, disable GF, it | ||
| 562 | * has only limited benefit and we still interoperate with | ||
| 563 | * GF APs since we can always receive GF transmissions. | ||
| 564 | */ | ||
| 565 | return false; | ||
| 566 | } | ||
| 567 | |||
| 568 | /** | ||
| 569 | * rs_get_supported_rates - get the available rates | 602 | * rs_get_supported_rates - get the available rates |
| 570 | * | 603 | * |
| 571 | * if management frame or broadcast frame only return | 604 | * if management frame or broadcast frame only return |
| @@ -576,16 +609,15 @@ static u16 rs_get_supported_rates(struct iwl_lq_sta *lq_sta, | |||
| 576 | struct ieee80211_hdr *hdr, | 609 | struct ieee80211_hdr *hdr, |
| 577 | enum iwl_table_type rate_type) | 610 | enum iwl_table_type rate_type) |
| 578 | { | 611 | { |
| 579 | if (is_legacy(rate_type)) { | 612 | if (is_legacy(rate_type)) |
| 580 | return lq_sta->active_legacy_rate; | 613 | return lq_sta->active_legacy_rate; |
| 581 | } else { | 614 | else if (is_siso(rate_type)) |
| 582 | if (is_siso(rate_type)) | 615 | return lq_sta->active_siso_rate; |
| 583 | return lq_sta->active_siso_rate; | 616 | else if (is_mimo2(rate_type)) |
| 584 | else { | 617 | return lq_sta->active_mimo2_rate; |
| 585 | WARN_ON_ONCE(!is_mimo2(rate_type)); | 618 | |
| 586 | return lq_sta->active_mimo2_rate; | 619 | WARN_ON_ONCE(1); |
| 587 | } | 620 | return 0; |
| 588 | } | ||
| 589 | } | 621 | } |
| 590 | 622 | ||
| 591 | static u16 rs_get_adjacent_rate(struct iwl_mvm *mvm, u8 index, u16 rate_mask, | 623 | static u16 rs_get_adjacent_rate(struct iwl_mvm *mvm, u8 index, u16 rate_mask, |
| @@ -652,7 +684,6 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, | |||
| 652 | u16 rate_mask; | 684 | u16 rate_mask; |
| 653 | u16 high_low; | 685 | u16 high_low; |
| 654 | u8 switch_to_legacy = 0; | 686 | u8 switch_to_legacy = 0; |
| 655 | u8 is_green = lq_sta->is_green; | ||
| 656 | struct iwl_mvm *mvm = lq_sta->drv; | 687 | struct iwl_mvm *mvm = lq_sta->drv; |
| 657 | 688 | ||
| 658 | /* check if we need to switch from HT to legacy rates. | 689 | /* check if we need to switch from HT to legacy rates. |
| @@ -662,15 +693,15 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, | |||
| 662 | switch_to_legacy = 1; | 693 | switch_to_legacy = 1; |
| 663 | scale_index = rs_ht_to_legacy[scale_index]; | 694 | scale_index = rs_ht_to_legacy[scale_index]; |
| 664 | if (lq_sta->band == IEEE80211_BAND_5GHZ) | 695 | if (lq_sta->band == IEEE80211_BAND_5GHZ) |
| 665 | tbl->lq_type = LQ_A; | 696 | tbl->lq_type = LQ_LEGACY_A; |
| 666 | else | 697 | else |
| 667 | tbl->lq_type = LQ_G; | 698 | tbl->lq_type = LQ_LEGACY_G; |
| 668 | 699 | ||
| 669 | if (num_of_ant(tbl->ant_type) > 1) | 700 | if (num_of_ant(tbl->ant_type) > 1) |
| 670 | tbl->ant_type = | 701 | tbl->ant_type = |
| 671 | first_antenna(iwl_fw_valid_tx_ant(mvm->fw)); | 702 | first_antenna(iwl_fw_valid_tx_ant(mvm->fw)); |
| 672 | 703 | ||
| 673 | tbl->is_ht40 = 0; | 704 | tbl->bw = 0; |
| 674 | tbl->is_SGI = 0; | 705 | tbl->is_SGI = 0; |
| 675 | tbl->max_search = IWL_MAX_SEARCH; | 706 | tbl->max_search = IWL_MAX_SEARCH; |
| 676 | } | 707 | } |
| @@ -701,7 +732,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, | |||
| 701 | low = scale_index; | 732 | low = scale_index; |
| 702 | 733 | ||
| 703 | out: | 734 | out: |
| 704 | return rate_n_flags_from_tbl(lq_sta->drv, tbl, low, is_green); | 735 | return rate_n_flags_from_tbl(lq_sta->drv, tbl, low); |
| 705 | } | 736 | } |
| 706 | 737 | ||
| 707 | /* | 738 | /* |
| @@ -714,6 +745,18 @@ static bool table_type_matches(struct iwl_scale_tbl_info *a, | |||
| 714 | (a->is_SGI == b->is_SGI); | 745 | (a->is_SGI == b->is_SGI); |
| 715 | } | 746 | } |
| 716 | 747 | ||
| 748 | static u32 rs_ch_width_from_mac_flags(enum mac80211_rate_control_flags flags) | ||
| 749 | { | ||
| 750 | if (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | ||
| 751 | return RATE_MCS_CHAN_WIDTH_40; | ||
| 752 | else if (flags & IEEE80211_TX_RC_80_MHZ_WIDTH) | ||
| 753 | return RATE_MCS_CHAN_WIDTH_80; | ||
| 754 | else if (flags & IEEE80211_TX_RC_160_MHZ_WIDTH) | ||
| 755 | return RATE_MCS_CHAN_WIDTH_160; | ||
| 756 | |||
| 757 | return RATE_MCS_CHAN_WIDTH_20; | ||
| 758 | } | ||
| 759 | |||
| 717 | /* | 760 | /* |
| 718 | * mac80211 sends us Tx status | 761 | * mac80211 sends us Tx status |
| 719 | */ | 762 | */ |
| @@ -783,16 +826,23 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, | |||
| 783 | */ | 826 | */ |
| 784 | if (info->band == IEEE80211_BAND_2GHZ) | 827 | if (info->band == IEEE80211_BAND_2GHZ) |
| 785 | mac_index += IWL_FIRST_OFDM_RATE; | 828 | mac_index += IWL_FIRST_OFDM_RATE; |
| 829 | } else if (mac_flags & IEEE80211_TX_RC_VHT_MCS) { | ||
| 830 | mac_index &= RATE_VHT_MCS_RATE_CODE_MSK; | ||
| 831 | if (mac_index >= (IWL_RATE_9M_INDEX - IWL_FIRST_OFDM_RATE)) | ||
| 832 | mac_index++; | ||
| 786 | } | 833 | } |
| 834 | |||
| 787 | /* Here we actually compare this rate to the latest LQ command */ | 835 | /* Here we actually compare this rate to the latest LQ command */ |
| 788 | if ((mac_index < 0) || | 836 | if ((mac_index < 0) || |
| 789 | (tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || | 837 | (tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || |
| 790 | (tbl_type.is_ht40 != !!(mac_flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) || | 838 | (tbl_type.bw != rs_ch_width_from_mac_flags(mac_flags)) || |
| 791 | (tbl_type.ant_type != info->status.antenna) || | 839 | (tbl_type.ant_type != info->status.antenna) || |
| 792 | (!!(tx_rate & RATE_MCS_HT_MSK) != | 840 | (!!(tx_rate & RATE_MCS_HT_MSK) != |
| 793 | !!(mac_flags & IEEE80211_TX_RC_MCS)) || | 841 | !!(mac_flags & IEEE80211_TX_RC_MCS)) || |
| 842 | (!!(tx_rate & RATE_MCS_VHT_MSK) != | ||
| 843 | !!(mac_flags & IEEE80211_TX_RC_VHT_MCS)) || | ||
| 794 | (!!(tx_rate & RATE_HT_MCS_GF_MSK) != | 844 | (!!(tx_rate & RATE_HT_MCS_GF_MSK) != |
| 795 | !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) || | 845 | !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) || |
| 796 | (rs_index != mac_index)) { | 846 | (rs_index != mac_index)) { |
| 797 | IWL_DEBUG_RATE(mvm, | 847 | IWL_DEBUG_RATE(mvm, |
| 798 | "initial rate %d does not match %d (0x%x)\n", | 848 | "initial rate %d does not match %d (0x%x)\n", |
| @@ -947,7 +997,8 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, | |||
| 947 | s32 (*ht_tbl_pointer)[IWL_RATE_COUNT]; | 997 | s32 (*ht_tbl_pointer)[IWL_RATE_COUNT]; |
| 948 | 998 | ||
| 949 | /* Check for invalid LQ type */ | 999 | /* Check for invalid LQ type */ |
| 950 | if (WARN_ON_ONCE(!is_legacy(tbl->lq_type) && !is_Ht(tbl->lq_type))) { | 1000 | if (WARN_ON_ONCE(!is_legacy(tbl->lq_type) && !is_ht(tbl->lq_type) && |
| 1001 | !(is_vht(tbl->lq_type)))) { | ||
| 951 | tbl->expected_tpt = expected_tpt_legacy; | 1002 | tbl->expected_tpt = expected_tpt_legacy; |
| 952 | return; | 1003 | return; |
| 953 | } | 1004 | } |
| @@ -958,18 +1009,40 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, | |||
| 958 | return; | 1009 | return; |
| 959 | } | 1010 | } |
| 960 | 1011 | ||
| 1012 | ht_tbl_pointer = expected_tpt_mimo2_20MHz; | ||
| 961 | /* Choose among many HT tables depending on number of streams | 1013 | /* Choose among many HT tables depending on number of streams |
| 962 | * (SISO/MIMO2), channel width (20/40), SGI, and aggregation | 1014 | * (SISO/MIMO2), channel width (20/40/80), SGI, and aggregation |
| 963 | * status */ | 1015 | * status */ |
| 964 | if (is_siso(tbl->lq_type) && !tbl->is_ht40) | 1016 | if (is_siso(tbl->lq_type)) { |
| 965 | ht_tbl_pointer = expected_tpt_siso20MHz; | 1017 | switch (tbl->bw) { |
| 966 | else if (is_siso(tbl->lq_type)) | 1018 | case RATE_MCS_CHAN_WIDTH_20: |
| 967 | ht_tbl_pointer = expected_tpt_siso40MHz; | 1019 | ht_tbl_pointer = expected_tpt_siso_20MHz; |
| 968 | else if (is_mimo2(tbl->lq_type) && !tbl->is_ht40) | 1020 | break; |
| 969 | ht_tbl_pointer = expected_tpt_mimo2_20MHz; | 1021 | case RATE_MCS_CHAN_WIDTH_40: |
| 970 | else { | 1022 | ht_tbl_pointer = expected_tpt_siso_40MHz; |
| 971 | WARN_ON_ONCE(!is_mimo2(tbl->lq_type)); | 1023 | break; |
| 972 | ht_tbl_pointer = expected_tpt_mimo2_40MHz; | 1024 | case RATE_MCS_CHAN_WIDTH_80: |
| 1025 | ht_tbl_pointer = expected_tpt_siso_80MHz; | ||
| 1026 | break; | ||
| 1027 | default: | ||
| 1028 | WARN_ON_ONCE(1); | ||
| 1029 | } | ||
| 1030 | } else if (is_mimo2(tbl->lq_type)) { | ||
| 1031 | switch (tbl->bw) { | ||
| 1032 | case RATE_MCS_CHAN_WIDTH_20: | ||
| 1033 | ht_tbl_pointer = expected_tpt_mimo2_20MHz; | ||
| 1034 | break; | ||
| 1035 | case RATE_MCS_CHAN_WIDTH_40: | ||
| 1036 | ht_tbl_pointer = expected_tpt_mimo2_40MHz; | ||
| 1037 | break; | ||
| 1038 | case RATE_MCS_CHAN_WIDTH_80: | ||
| 1039 | ht_tbl_pointer = expected_tpt_mimo2_80MHz; | ||
| 1040 | break; | ||
| 1041 | default: | ||
| 1042 | WARN_ON_ONCE(1); | ||
| 1043 | } | ||
| 1044 | } else { | ||
| 1045 | WARN_ON_ONCE(1); | ||
| 973 | } | 1046 | } |
| 974 | 1047 | ||
| 975 | if (!tbl->is_SGI && !lq_sta->is_agg) /* Normal */ | 1048 | if (!tbl->is_SGI && !lq_sta->is_agg) /* Normal */ |
| @@ -1084,9 +1157,47 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm, | |||
| 1084 | return new_rate; | 1157 | return new_rate; |
| 1085 | } | 1158 | } |
| 1086 | 1159 | ||
| 1087 | static bool iwl_is_ht40_tx_allowed(struct ieee80211_sta *sta) | 1160 | /* Move to the next action and wrap around to the first action in case |
| 1161 | * we're at the last action. Assumes actions start at 0. | ||
| 1162 | */ | ||
| 1163 | static inline void rs_move_next_action(struct iwl_scale_tbl_info *tbl, | ||
| 1164 | u8 last_action) | ||
| 1165 | { | ||
| 1166 | BUILD_BUG_ON(IWL_LEGACY_FIRST_ACTION != 0); | ||
| 1167 | BUILD_BUG_ON(IWL_SISO_FIRST_ACTION != 0); | ||
| 1168 | BUILD_BUG_ON(IWL_MIMO2_FIRST_ACTION != 0); | ||
| 1169 | |||
| 1170 | tbl->action = (tbl->action + 1) % (last_action + 1); | ||
| 1171 | } | ||
| 1172 | |||
| 1173 | static void rs_set_bw_from_sta(struct iwl_scale_tbl_info *tbl, | ||
| 1174 | struct ieee80211_sta *sta) | ||
| 1175 | { | ||
| 1176 | if (sta->bandwidth >= IEEE80211_STA_RX_BW_80) | ||
| 1177 | tbl->bw = RATE_MCS_CHAN_WIDTH_80; | ||
| 1178 | else if (sta->bandwidth >= IEEE80211_STA_RX_BW_40) | ||
| 1179 | tbl->bw = RATE_MCS_CHAN_WIDTH_40; | ||
| 1180 | else | ||
| 1181 | tbl->bw = RATE_MCS_CHAN_WIDTH_20; | ||
| 1182 | } | ||
| 1183 | |||
| 1184 | static bool rs_sgi_allowed(struct iwl_scale_tbl_info *tbl, | ||
| 1185 | struct ieee80211_sta *sta) | ||
| 1088 | { | 1186 | { |
| 1089 | return sta->bandwidth >= IEEE80211_STA_RX_BW_40; | 1187 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; |
| 1188 | struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; | ||
| 1189 | |||
| 1190 | if (is_ht20(tbl) && (ht_cap->cap & | ||
| 1191 | IEEE80211_HT_CAP_SGI_20)) | ||
| 1192 | return true; | ||
| 1193 | if (is_ht40(tbl) && (ht_cap->cap & | ||
| 1194 | IEEE80211_HT_CAP_SGI_40)) | ||
| 1195 | return true; | ||
| 1196 | if (is_ht80(tbl) && (vht_cap->cap & | ||
| 1197 | IEEE80211_VHT_CAP_SHORT_GI_80)) | ||
| 1198 | return true; | ||
| 1199 | |||
| 1200 | return false; | ||
| 1090 | } | 1201 | } |
| 1091 | 1202 | ||
| 1092 | /* | 1203 | /* |
| @@ -1099,7 +1210,6 @@ static int rs_switch_to_mimo2(struct iwl_mvm *mvm, | |||
| 1099 | { | 1210 | { |
| 1100 | u16 rate_mask; | 1211 | u16 rate_mask; |
| 1101 | s32 rate; | 1212 | s32 rate; |
| 1102 | s8 is_green = lq_sta->is_green; | ||
| 1103 | 1213 | ||
| 1104 | if (!sta->ht_cap.ht_supported) | 1214 | if (!sta->ht_cap.ht_supported) |
| 1105 | return -1; | 1215 | return -1; |
| @@ -1113,16 +1223,12 @@ static int rs_switch_to_mimo2(struct iwl_mvm *mvm, | |||
| 1113 | 1223 | ||
| 1114 | IWL_DEBUG_RATE(mvm, "LQ: try to switch to MIMO2\n"); | 1224 | IWL_DEBUG_RATE(mvm, "LQ: try to switch to MIMO2\n"); |
| 1115 | 1225 | ||
| 1116 | tbl->lq_type = LQ_MIMO2; | 1226 | tbl->lq_type = lq_sta->is_vht ? LQ_VHT_MIMO2 : LQ_HT_MIMO2; |
| 1117 | tbl->action = 0; | 1227 | tbl->action = 0; |
| 1118 | tbl->max_search = IWL_MAX_SEARCH; | 1228 | tbl->max_search = IWL_MAX_SEARCH; |
| 1119 | rate_mask = lq_sta->active_mimo2_rate; | 1229 | rate_mask = lq_sta->active_mimo2_rate; |
| 1120 | 1230 | ||
| 1121 | if (iwl_is_ht40_tx_allowed(sta)) | 1231 | rs_set_bw_from_sta(tbl, sta); |
| 1122 | tbl->is_ht40 = 1; | ||
| 1123 | else | ||
| 1124 | tbl->is_ht40 = 0; | ||
| 1125 | |||
| 1126 | rs_set_expected_tpt_table(lq_sta, tbl); | 1232 | rs_set_expected_tpt_table(lq_sta, tbl); |
| 1127 | 1233 | ||
| 1128 | rate = rs_get_best_rate(mvm, lq_sta, tbl, rate_mask, index); | 1234 | rate = rs_get_best_rate(mvm, lq_sta, tbl, rate_mask, index); |
| @@ -1134,10 +1240,10 @@ static int rs_switch_to_mimo2(struct iwl_mvm *mvm, | |||
| 1134 | rate, rate_mask); | 1240 | rate, rate_mask); |
| 1135 | return -1; | 1241 | return -1; |
| 1136 | } | 1242 | } |
| 1137 | tbl->current_rate = rate_n_flags_from_tbl(mvm, tbl, rate, is_green); | 1243 | tbl->current_rate = rate_n_flags_from_tbl(mvm, tbl, rate); |
| 1138 | 1244 | ||
| 1139 | IWL_DEBUG_RATE(mvm, "LQ: Switch to new mcs %X index is green %X\n", | 1245 | IWL_DEBUG_RATE(mvm, "LQ: Switch to new mcs %X index\n", |
| 1140 | tbl->current_rate, is_green); | 1246 | tbl->current_rate); |
| 1141 | return 0; | 1247 | return 0; |
| 1142 | } | 1248 | } |
| 1143 | 1249 | ||
| @@ -1150,7 +1256,6 @@ static int rs_switch_to_siso(struct iwl_mvm *mvm, | |||
| 1150 | struct iwl_scale_tbl_info *tbl, int index) | 1256 | struct iwl_scale_tbl_info *tbl, int index) |
| 1151 | { | 1257 | { |
| 1152 | u16 rate_mask; | 1258 | u16 rate_mask; |
| 1153 | u8 is_green = lq_sta->is_green; | ||
| 1154 | s32 rate; | 1259 | s32 rate; |
| 1155 | 1260 | ||
| 1156 | if (!sta->ht_cap.ht_supported) | 1261 | if (!sta->ht_cap.ht_supported) |
| @@ -1158,19 +1263,12 @@ static int rs_switch_to_siso(struct iwl_mvm *mvm, | |||
| 1158 | 1263 | ||
| 1159 | IWL_DEBUG_RATE(mvm, "LQ: try to switch to SISO\n"); | 1264 | IWL_DEBUG_RATE(mvm, "LQ: try to switch to SISO\n"); |
| 1160 | 1265 | ||
| 1161 | tbl->lq_type = LQ_SISO; | 1266 | tbl->lq_type = lq_sta->is_vht ? LQ_VHT_SISO : LQ_HT_SISO; |
| 1162 | tbl->action = 0; | 1267 | tbl->action = 0; |
| 1163 | tbl->max_search = IWL_MAX_SEARCH; | 1268 | tbl->max_search = IWL_MAX_SEARCH; |
| 1164 | rate_mask = lq_sta->active_siso_rate; | 1269 | rate_mask = lq_sta->active_siso_rate; |
| 1165 | 1270 | ||
| 1166 | if (iwl_is_ht40_tx_allowed(sta)) | 1271 | rs_set_bw_from_sta(tbl, sta); |
| 1167 | tbl->is_ht40 = 1; | ||
| 1168 | else | ||
| 1169 | tbl->is_ht40 = 0; | ||
| 1170 | |||
| 1171 | if (is_green) | ||
| 1172 | tbl->is_SGI = 0; /*11n spec: no SGI in SISO+Greenfield*/ | ||
| 1173 | |||
| 1174 | rs_set_expected_tpt_table(lq_sta, tbl); | 1272 | rs_set_expected_tpt_table(lq_sta, tbl); |
| 1175 | rate = rs_get_best_rate(mvm, lq_sta, tbl, rate_mask, index); | 1273 | rate = rs_get_best_rate(mvm, lq_sta, tbl, rate_mask, index); |
| 1176 | 1274 | ||
| @@ -1181,9 +1279,9 @@ static int rs_switch_to_siso(struct iwl_mvm *mvm, | |||
| 1181 | rate, rate_mask); | 1279 | rate, rate_mask); |
| 1182 | return -1; | 1280 | return -1; |
| 1183 | } | 1281 | } |
| 1184 | tbl->current_rate = rate_n_flags_from_tbl(mvm, tbl, rate, is_green); | 1282 | tbl->current_rate = rate_n_flags_from_tbl(mvm, tbl, rate); |
| 1185 | IWL_DEBUG_RATE(mvm, "LQ: Switch to new mcs %X index is green %X\n", | 1283 | IWL_DEBUG_RATE(mvm, "LQ: Switch to new mcs %X index\n", |
| 1186 | tbl->current_rate, is_green); | 1284 | tbl->current_rate); |
| 1187 | return 0; | 1285 | return 0; |
| 1188 | } | 1286 | } |
| 1189 | 1287 | ||
| @@ -1211,14 +1309,10 @@ static int rs_move_legacy_other(struct iwl_mvm *mvm, | |||
| 1211 | while (1) { | 1309 | while (1) { |
| 1212 | lq_sta->action_counter++; | 1310 | lq_sta->action_counter++; |
| 1213 | switch (tbl->action) { | 1311 | switch (tbl->action) { |
| 1214 | case IWL_LEGACY_SWITCH_ANTENNA1: | 1312 | case IWL_LEGACY_SWITCH_ANTENNA: |
| 1215 | case IWL_LEGACY_SWITCH_ANTENNA2: | ||
| 1216 | IWL_DEBUG_RATE(mvm, "LQ: Legacy toggle Antenna\n"); | 1313 | IWL_DEBUG_RATE(mvm, "LQ: Legacy toggle Antenna\n"); |
| 1217 | 1314 | ||
| 1218 | if ((tbl->action == IWL_LEGACY_SWITCH_ANTENNA1 && | 1315 | if (tx_chains_num <= 1) |
| 1219 | tx_chains_num <= 1) || | ||
| 1220 | (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2 && | ||
| 1221 | tx_chains_num <= 2)) | ||
| 1222 | break; | 1316 | break; |
| 1223 | 1317 | ||
| 1224 | /* Don't change antenna if success has been great */ | 1318 | /* Don't change antenna if success has been great */ |
| @@ -1273,9 +1367,7 @@ static int rs_move_legacy_other(struct iwl_mvm *mvm, | |||
| 1273 | default: | 1367 | default: |
| 1274 | WARN_ON_ONCE(1); | 1368 | WARN_ON_ONCE(1); |
| 1275 | } | 1369 | } |
| 1276 | tbl->action++; | 1370 | rs_move_next_action(tbl, IWL_LEGACY_LAST_ACTION); |
| 1277 | if (tbl->action > IWL_LEGACY_SWITCH_MIMO2) | ||
| 1278 | tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; | ||
| 1279 | 1371 | ||
| 1280 | if (tbl->action == start_action) | 1372 | if (tbl->action == start_action) |
| 1281 | break; | 1373 | break; |
| @@ -1285,9 +1377,7 @@ static int rs_move_legacy_other(struct iwl_mvm *mvm, | |||
| 1285 | 1377 | ||
| 1286 | out: | 1378 | out: |
| 1287 | lq_sta->search_better_tbl = 1; | 1379 | lq_sta->search_better_tbl = 1; |
| 1288 | tbl->action++; | 1380 | rs_move_next_action(tbl, IWL_LEGACY_LAST_ACTION); |
| 1289 | if (tbl->action > IWL_LEGACY_SWITCH_MIMO2) | ||
| 1290 | tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; | ||
| 1291 | if (update_search_tbl_counter) | 1381 | if (update_search_tbl_counter) |
| 1292 | search_tbl->action = tbl->action; | 1382 | search_tbl->action = tbl->action; |
| 1293 | return 0; | 1383 | return 0; |
| @@ -1300,12 +1390,10 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm, | |||
| 1300 | struct iwl_lq_sta *lq_sta, | 1390 | struct iwl_lq_sta *lq_sta, |
| 1301 | struct ieee80211_sta *sta, int index) | 1391 | struct ieee80211_sta *sta, int index) |
| 1302 | { | 1392 | { |
| 1303 | u8 is_green = lq_sta->is_green; | ||
| 1304 | struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | 1393 | struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
| 1305 | struct iwl_scale_tbl_info *search_tbl = | 1394 | struct iwl_scale_tbl_info *search_tbl = |
| 1306 | &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); | 1395 | &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); |
| 1307 | struct iwl_rate_scale_data *window = &(tbl->win[index]); | 1396 | struct iwl_rate_scale_data *window = &(tbl->win[index]); |
| 1308 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | ||
| 1309 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1397 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
| 1310 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1398 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
| 1311 | u8 start_action; | 1399 | u8 start_action; |
| @@ -1314,40 +1402,17 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm, | |||
| 1314 | u8 update_search_tbl_counter = 0; | 1402 | u8 update_search_tbl_counter = 0; |
| 1315 | int ret; | 1403 | int ret; |
| 1316 | 1404 | ||
| 1317 | switch (BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)) { | 1405 | if (tbl->action == IWL_SISO_SWITCH_MIMO2 && |
| 1318 | case IWL_BT_COEX_TRAFFIC_LOAD_NONE: | 1406 | !iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) |
| 1319 | /* nothing */ | 1407 | tbl->action = IWL_SISO_SWITCH_ANTENNA; |
| 1320 | break; | ||
| 1321 | case IWL_BT_COEX_TRAFFIC_LOAD_LOW: | ||
| 1322 | /* avoid antenna B unless MIMO */ | ||
| 1323 | if (tbl->action == IWL_SISO_SWITCH_ANTENNA2) | ||
| 1324 | tbl->action = IWL_SISO_SWITCH_MIMO2; | ||
| 1325 | break; | ||
| 1326 | case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: | ||
| 1327 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: | ||
| 1328 | /* avoid antenna B and MIMO */ | ||
| 1329 | valid_tx_ant = | ||
| 1330 | first_antenna(iwl_fw_valid_tx_ant(mvm->fw)); | ||
| 1331 | if (tbl->action != IWL_SISO_SWITCH_ANTENNA1) | ||
| 1332 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | ||
| 1333 | break; | ||
| 1334 | default: | ||
| 1335 | IWL_ERR(mvm, "Invalid BT load %d", | ||
| 1336 | BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)); | ||
| 1337 | break; | ||
| 1338 | } | ||
| 1339 | 1408 | ||
| 1340 | start_action = tbl->action; | 1409 | start_action = tbl->action; |
| 1341 | while (1) { | 1410 | while (1) { |
| 1342 | lq_sta->action_counter++; | 1411 | lq_sta->action_counter++; |
| 1343 | switch (tbl->action) { | 1412 | switch (tbl->action) { |
| 1344 | case IWL_SISO_SWITCH_ANTENNA1: | 1413 | case IWL_SISO_SWITCH_ANTENNA: |
| 1345 | case IWL_SISO_SWITCH_ANTENNA2: | ||
| 1346 | IWL_DEBUG_RATE(mvm, "LQ: SISO toggle Antenna\n"); | 1414 | IWL_DEBUG_RATE(mvm, "LQ: SISO toggle Antenna\n"); |
| 1347 | if ((tbl->action == IWL_SISO_SWITCH_ANTENNA1 && | 1415 | if (tx_chains_num <= 1) |
| 1348 | tx_chains_num <= 1) || | ||
| 1349 | (tbl->action == IWL_SISO_SWITCH_ANTENNA2 && | ||
| 1350 | tx_chains_num <= 2)) | ||
| 1351 | break; | 1416 | break; |
| 1352 | 1417 | ||
| 1353 | if (window->success_ratio >= IWL_RS_GOOD_RATIO && | 1418 | if (window->success_ratio >= IWL_RS_GOOD_RATIO && |
| @@ -1380,23 +1445,12 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm, | |||
| 1380 | goto out; | 1445 | goto out; |
| 1381 | break; | 1446 | break; |
| 1382 | case IWL_SISO_SWITCH_GI: | 1447 | case IWL_SISO_SWITCH_GI: |
| 1383 | if (!tbl->is_ht40 && !(ht_cap->cap & | 1448 | if (!rs_sgi_allowed(tbl, sta)) |
| 1384 | IEEE80211_HT_CAP_SGI_20)) | ||
| 1385 | break; | ||
| 1386 | if (tbl->is_ht40 && !(ht_cap->cap & | ||
| 1387 | IEEE80211_HT_CAP_SGI_40)) | ||
| 1388 | break; | 1449 | break; |
| 1389 | 1450 | ||
| 1390 | IWL_DEBUG_RATE(mvm, "LQ: SISO toggle SGI/NGI\n"); | 1451 | IWL_DEBUG_RATE(mvm, "LQ: SISO toggle SGI/NGI\n"); |
| 1391 | 1452 | ||
| 1392 | memcpy(search_tbl, tbl, sz); | 1453 | memcpy(search_tbl, tbl, sz); |
| 1393 | if (is_green) { | ||
| 1394 | if (!tbl->is_SGI) | ||
| 1395 | break; | ||
| 1396 | else | ||
| 1397 | IWL_ERR(mvm, | ||
| 1398 | "SGI was set in GF+SISO\n"); | ||
| 1399 | } | ||
| 1400 | search_tbl->is_SGI = !tbl->is_SGI; | 1454 | search_tbl->is_SGI = !tbl->is_SGI; |
| 1401 | rs_set_expected_tpt_table(lq_sta, search_tbl); | 1455 | rs_set_expected_tpt_table(lq_sta, search_tbl); |
| 1402 | if (tbl->is_SGI) { | 1456 | if (tbl->is_SGI) { |
| @@ -1405,16 +1459,13 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm, | |||
| 1405 | break; | 1459 | break; |
| 1406 | } | 1460 | } |
| 1407 | search_tbl->current_rate = | 1461 | search_tbl->current_rate = |
| 1408 | rate_n_flags_from_tbl(mvm, search_tbl, | 1462 | rate_n_flags_from_tbl(mvm, search_tbl, index); |
| 1409 | index, is_green); | ||
| 1410 | update_search_tbl_counter = 1; | 1463 | update_search_tbl_counter = 1; |
| 1411 | goto out; | 1464 | goto out; |
| 1412 | default: | 1465 | default: |
| 1413 | WARN_ON_ONCE(1); | 1466 | WARN_ON_ONCE(1); |
| 1414 | } | 1467 | } |
| 1415 | tbl->action++; | 1468 | rs_move_next_action(tbl, IWL_SISO_LAST_ACTION); |
| 1416 | if (tbl->action > IWL_SISO_SWITCH_GI) | ||
| 1417 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | ||
| 1418 | 1469 | ||
| 1419 | if (tbl->action == start_action) | 1470 | if (tbl->action == start_action) |
| 1420 | break; | 1471 | break; |
| @@ -1424,9 +1475,7 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm, | |||
| 1424 | 1475 | ||
| 1425 | out: | 1476 | out: |
| 1426 | lq_sta->search_better_tbl = 1; | 1477 | lq_sta->search_better_tbl = 1; |
| 1427 | tbl->action++; | 1478 | rs_move_next_action(tbl, IWL_SISO_LAST_ACTION); |
| 1428 | if (tbl->action > IWL_SISO_SWITCH_GI) | ||
| 1429 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | ||
| 1430 | if (update_search_tbl_counter) | 1479 | if (update_search_tbl_counter) |
| 1431 | search_tbl->action = tbl->action; | 1480 | search_tbl->action = tbl->action; |
| 1432 | 1481 | ||
| @@ -1440,63 +1489,20 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm, | |||
| 1440 | struct iwl_lq_sta *lq_sta, | 1489 | struct iwl_lq_sta *lq_sta, |
| 1441 | struct ieee80211_sta *sta, int index) | 1490 | struct ieee80211_sta *sta, int index) |
| 1442 | { | 1491 | { |
| 1443 | s8 is_green = lq_sta->is_green; | ||
| 1444 | struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | 1492 | struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
| 1445 | struct iwl_scale_tbl_info *search_tbl = | 1493 | struct iwl_scale_tbl_info *search_tbl = |
| 1446 | &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); | 1494 | &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); |
| 1447 | struct iwl_rate_scale_data *window = &(tbl->win[index]); | ||
| 1448 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | ||
| 1449 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1495 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
| 1450 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1496 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
| 1451 | u8 start_action; | 1497 | u8 start_action; |
| 1452 | u8 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw); | 1498 | u8 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw); |
| 1453 | u8 tx_chains_num = num_of_ant(valid_tx_ant); | ||
| 1454 | u8 update_search_tbl_counter = 0; | 1499 | u8 update_search_tbl_counter = 0; |
| 1455 | int ret; | 1500 | int ret; |
| 1456 | 1501 | ||
| 1457 | switch (BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)) { | ||
| 1458 | case IWL_BT_COEX_TRAFFIC_LOAD_NONE: | ||
| 1459 | /* nothing */ | ||
| 1460 | break; | ||
| 1461 | case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: | ||
| 1462 | case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: | ||
| 1463 | /* avoid antenna B and MIMO */ | ||
| 1464 | if (tbl->action != IWL_MIMO2_SWITCH_SISO_A) | ||
| 1465 | tbl->action = IWL_MIMO2_SWITCH_SISO_A; | ||
| 1466 | break; | ||
| 1467 | case IWL_BT_COEX_TRAFFIC_LOAD_LOW: | ||
| 1468 | /* avoid antenna B unless MIMO */ | ||
| 1469 | if (tbl->action == IWL_MIMO2_SWITCH_SISO_B) | ||
| 1470 | tbl->action = IWL_MIMO2_SWITCH_SISO_A; | ||
| 1471 | break; | ||
| 1472 | default: | ||
| 1473 | IWL_ERR(mvm, "Invalid BT load %d", | ||
| 1474 | BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)); | ||
| 1475 | break; | ||
| 1476 | } | ||
| 1477 | |||
| 1478 | start_action = tbl->action; | 1502 | start_action = tbl->action; |
| 1479 | while (1) { | 1503 | while (1) { |
| 1480 | lq_sta->action_counter++; | 1504 | lq_sta->action_counter++; |
| 1481 | switch (tbl->action) { | 1505 | switch (tbl->action) { |
| 1482 | case IWL_MIMO2_SWITCH_ANTENNA1: | ||
| 1483 | case IWL_MIMO2_SWITCH_ANTENNA2: | ||
| 1484 | IWL_DEBUG_RATE(mvm, "LQ: MIMO2 toggle Antennas\n"); | ||
| 1485 | |||
| 1486 | if (tx_chains_num <= 2) | ||
| 1487 | break; | ||
| 1488 | |||
| 1489 | if (window->success_ratio >= IWL_RS_GOOD_RATIO) | ||
| 1490 | break; | ||
| 1491 | |||
| 1492 | memcpy(search_tbl, tbl, sz); | ||
| 1493 | if (rs_toggle_antenna(valid_tx_ant, | ||
| 1494 | &search_tbl->current_rate, | ||
| 1495 | search_tbl)) { | ||
| 1496 | update_search_tbl_counter = 1; | ||
| 1497 | goto out; | ||
| 1498 | } | ||
| 1499 | break; | ||
| 1500 | case IWL_MIMO2_SWITCH_SISO_A: | 1506 | case IWL_MIMO2_SWITCH_SISO_A: |
| 1501 | case IWL_MIMO2_SWITCH_SISO_B: | 1507 | case IWL_MIMO2_SWITCH_SISO_B: |
| 1502 | IWL_DEBUG_RATE(mvm, "LQ: MIMO2 switch to SISO\n"); | 1508 | IWL_DEBUG_RATE(mvm, "LQ: MIMO2 switch to SISO\n"); |
| @@ -1521,11 +1527,7 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm, | |||
| 1521 | break; | 1527 | break; |
| 1522 | 1528 | ||
| 1523 | case IWL_MIMO2_SWITCH_GI: | 1529 | case IWL_MIMO2_SWITCH_GI: |
| 1524 | if (!tbl->is_ht40 && !(ht_cap->cap & | 1530 | if (!rs_sgi_allowed(tbl, sta)) |
| 1525 | IEEE80211_HT_CAP_SGI_20)) | ||
| 1526 | break; | ||
| 1527 | if (tbl->is_ht40 && !(ht_cap->cap & | ||
| 1528 | IEEE80211_HT_CAP_SGI_40)) | ||
| 1529 | break; | 1531 | break; |
| 1530 | 1532 | ||
| 1531 | IWL_DEBUG_RATE(mvm, "LQ: MIMO2 toggle SGI/NGI\n"); | 1533 | IWL_DEBUG_RATE(mvm, "LQ: MIMO2 toggle SGI/NGI\n"); |
| @@ -1546,16 +1548,13 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm, | |||
| 1546 | break; | 1548 | break; |
| 1547 | } | 1549 | } |
| 1548 | search_tbl->current_rate = | 1550 | search_tbl->current_rate = |
| 1549 | rate_n_flags_from_tbl(mvm, search_tbl, | 1551 | rate_n_flags_from_tbl(mvm, search_tbl, index); |
| 1550 | index, is_green); | ||
| 1551 | update_search_tbl_counter = 1; | 1552 | update_search_tbl_counter = 1; |
| 1552 | goto out; | 1553 | goto out; |
| 1553 | default: | 1554 | default: |
| 1554 | WARN_ON_ONCE(1); | 1555 | WARN_ON_ONCE(1); |
| 1555 | } | 1556 | } |
| 1556 | tbl->action++; | 1557 | rs_move_next_action(tbl, IWL_MIMO2_LAST_ACTION); |
| 1557 | if (tbl->action > IWL_MIMO2_SWITCH_GI) | ||
| 1558 | tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; | ||
| 1559 | 1558 | ||
| 1560 | if (tbl->action == start_action) | 1559 | if (tbl->action == start_action) |
| 1561 | break; | 1560 | break; |
| @@ -1564,9 +1563,7 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm, | |||
| 1564 | return 0; | 1563 | return 0; |
| 1565 | out: | 1564 | out: |
| 1566 | lq_sta->search_better_tbl = 1; | 1565 | lq_sta->search_better_tbl = 1; |
| 1567 | tbl->action++; | 1566 | rs_move_next_action(tbl, IWL_MIMO2_LAST_ACTION); |
| 1568 | if (tbl->action > IWL_MIMO2_SWITCH_GI) | ||
| 1569 | tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; | ||
| 1570 | if (update_search_tbl_counter) | 1567 | if (update_search_tbl_counter) |
| 1571 | search_tbl->action = tbl->action; | 1568 | search_tbl->action = tbl->action; |
| 1572 | 1569 | ||
| @@ -1660,15 +1657,16 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) | |||
| 1660 | * setup rate table in uCode | 1657 | * setup rate table in uCode |
| 1661 | */ | 1658 | */ |
| 1662 | static void rs_update_rate_tbl(struct iwl_mvm *mvm, | 1659 | static void rs_update_rate_tbl(struct iwl_mvm *mvm, |
| 1660 | struct ieee80211_sta *sta, | ||
| 1663 | struct iwl_lq_sta *lq_sta, | 1661 | struct iwl_lq_sta *lq_sta, |
| 1664 | struct iwl_scale_tbl_info *tbl, | 1662 | struct iwl_scale_tbl_info *tbl, |
| 1665 | int index, u8 is_green) | 1663 | int index) |
| 1666 | { | 1664 | { |
| 1667 | u32 rate; | 1665 | u32 rate; |
| 1668 | 1666 | ||
| 1669 | /* Update uCode's rate table. */ | 1667 | /* Update uCode's rate table. */ |
| 1670 | rate = rate_n_flags_from_tbl(mvm, tbl, index, is_green); | 1668 | rate = rate_n_flags_from_tbl(mvm, tbl, index); |
| 1671 | rs_fill_link_cmd(mvm, lq_sta, rate); | 1669 | rs_fill_link_cmd(mvm, sta, lq_sta, rate); |
| 1672 | iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, CMD_ASYNC, false); | 1670 | iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, CMD_ASYNC, false); |
| 1673 | } | 1671 | } |
| 1674 | 1672 | ||
| @@ -1712,7 +1710,6 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
| 1712 | u8 update_lq = 0; | 1710 | u8 update_lq = 0; |
| 1713 | struct iwl_scale_tbl_info *tbl, *tbl1; | 1711 | struct iwl_scale_tbl_info *tbl, *tbl1; |
| 1714 | u16 rate_scale_index_msk = 0; | 1712 | u16 rate_scale_index_msk = 0; |
| 1715 | u8 is_green = 0; | ||
| 1716 | u8 active_tbl = 0; | 1713 | u8 active_tbl = 0; |
| 1717 | u8 done_search = 0; | 1714 | u8 done_search = 0; |
| 1718 | u16 high_low; | 1715 | u16 high_low; |
| @@ -1754,11 +1751,6 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
| 1754 | active_tbl = 1 - lq_sta->active_tbl; | 1751 | active_tbl = 1 - lq_sta->active_tbl; |
| 1755 | 1752 | ||
| 1756 | tbl = &(lq_sta->lq_info[active_tbl]); | 1753 | tbl = &(lq_sta->lq_info[active_tbl]); |
| 1757 | if (is_legacy(tbl->lq_type)) | ||
| 1758 | lq_sta->is_green = 0; | ||
| 1759 | else | ||
| 1760 | lq_sta->is_green = rs_use_green(sta); | ||
| 1761 | is_green = lq_sta->is_green; | ||
| 1762 | 1754 | ||
| 1763 | /* current tx rate */ | 1755 | /* current tx rate */ |
| 1764 | index = lq_sta->last_txrate_idx; | 1756 | index = lq_sta->last_txrate_idx; |
| @@ -1797,7 +1789,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
| 1797 | tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | 1789 | tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
| 1798 | /* get "active" rate info */ | 1790 | /* get "active" rate info */ |
| 1799 | index = iwl_hwrate_to_plcp_idx(tbl->current_rate); | 1791 | index = iwl_hwrate_to_plcp_idx(tbl->current_rate); |
| 1800 | rs_update_rate_tbl(mvm, lq_sta, tbl, index, is_green); | 1792 | rs_update_rate_tbl(mvm, sta, lq_sta, tbl, index); |
| 1801 | } | 1793 | } |
| 1802 | return; | 1794 | return; |
| 1803 | } | 1795 | } |
| @@ -1978,24 +1970,24 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
| 1978 | (current_tpt > (100 * tbl->expected_tpt[low])))) | 1970 | (current_tpt > (100 * tbl->expected_tpt[low])))) |
| 1979 | scale_action = 0; | 1971 | scale_action = 0; |
| 1980 | 1972 | ||
| 1981 | if ((BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD) >= | 1973 | if ((le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) >= |
| 1982 | IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && (is_mimo(tbl->lq_type))) { | 1974 | IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && (is_mimo(tbl->lq_type))) { |
| 1983 | if (lq_sta->last_bt_traffic > | 1975 | if (lq_sta->last_bt_traffic > |
| 1984 | BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)) { | 1976 | le32_to_cpu(mvm->last_bt_notif.bt_activity_grading)) { |
| 1985 | /* | 1977 | /* |
| 1986 | * don't set scale_action, don't want to scale up if | 1978 | * don't set scale_action, don't want to scale up if |
| 1987 | * the rate scale doesn't otherwise think that is a | 1979 | * the rate scale doesn't otherwise think that is a |
| 1988 | * good idea. | 1980 | * good idea. |
| 1989 | */ | 1981 | */ |
| 1990 | } else if (lq_sta->last_bt_traffic <= | 1982 | } else if (lq_sta->last_bt_traffic <= |
| 1991 | BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)) { | 1983 | le32_to_cpu(mvm->last_bt_notif.bt_activity_grading)) { |
| 1992 | scale_action = -1; | 1984 | scale_action = -1; |
| 1993 | } | 1985 | } |
| 1994 | } | 1986 | } |
| 1995 | lq_sta->last_bt_traffic = | 1987 | lq_sta->last_bt_traffic = |
| 1996 | BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD); | 1988 | le32_to_cpu(mvm->last_bt_notif.bt_activity_grading); |
| 1997 | 1989 | ||
| 1998 | if ((BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD) >= | 1990 | if ((le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) >= |
| 1999 | IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && is_mimo(tbl->lq_type)) { | 1991 | IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && is_mimo(tbl->lq_type)) { |
| 2000 | /* search for a new modulation */ | 1992 | /* search for a new modulation */ |
| 2001 | rs_stay_in_table(lq_sta, true); | 1993 | rs_stay_in_table(lq_sta, true); |
| @@ -2032,7 +2024,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
| 2032 | lq_update: | 2024 | lq_update: |
| 2033 | /* Replace uCode's rate table for the destination station. */ | 2025 | /* Replace uCode's rate table for the destination station. */ |
| 2034 | if (update_lq) | 2026 | if (update_lq) |
| 2035 | rs_update_rate_tbl(mvm, lq_sta, tbl, index, is_green); | 2027 | rs_update_rate_tbl(mvm, sta, lq_sta, tbl, index); |
| 2036 | 2028 | ||
| 2037 | rs_stay_in_table(lq_sta, false); | 2029 | rs_stay_in_table(lq_sta, false); |
| 2038 | 2030 | ||
| @@ -2071,7 +2063,7 @@ lq_update: | |||
| 2071 | IWL_DEBUG_RATE(mvm, | 2063 | IWL_DEBUG_RATE(mvm, |
| 2072 | "Switch current mcs: %X index: %d\n", | 2064 | "Switch current mcs: %X index: %d\n", |
| 2073 | tbl->current_rate, index); | 2065 | tbl->current_rate, index); |
| 2074 | rs_fill_link_cmd(mvm, lq_sta, tbl->current_rate); | 2066 | rs_fill_link_cmd(mvm, sta, lq_sta, tbl->current_rate); |
| 2075 | iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, CMD_ASYNC, false); | 2067 | iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, CMD_ASYNC, false); |
| 2076 | } else { | 2068 | } else { |
| 2077 | done_search = 1; | 2069 | done_search = 1; |
| @@ -2113,7 +2105,7 @@ lq_update: | |||
| 2113 | } | 2105 | } |
| 2114 | 2106 | ||
| 2115 | out: | 2107 | out: |
| 2116 | tbl->current_rate = rate_n_flags_from_tbl(mvm, tbl, index, is_green); | 2108 | tbl->current_rate = rate_n_flags_from_tbl(mvm, tbl, index); |
| 2117 | lq_sta->last_txrate_idx = index; | 2109 | lq_sta->last_txrate_idx = index; |
| 2118 | } | 2110 | } |
| 2119 | 2111 | ||
| @@ -2140,7 +2132,6 @@ static void rs_initialize_lq(struct iwl_mvm *mvm, | |||
| 2140 | int rate_idx; | 2132 | int rate_idx; |
| 2141 | int i; | 2133 | int i; |
| 2142 | u32 rate; | 2134 | u32 rate; |
| 2143 | u8 use_green = rs_use_green(sta); | ||
| 2144 | u8 active_tbl = 0; | 2135 | u8 active_tbl = 0; |
| 2145 | u8 valid_tx_ant; | 2136 | u8 valid_tx_ant; |
| 2146 | 2137 | ||
| @@ -2172,10 +2163,10 @@ static void rs_initialize_lq(struct iwl_mvm *mvm, | |||
| 2172 | if (!rs_is_valid_ant(valid_tx_ant, tbl->ant_type)) | 2163 | if (!rs_is_valid_ant(valid_tx_ant, tbl->ant_type)) |
| 2173 | rs_toggle_antenna(valid_tx_ant, &rate, tbl); | 2164 | rs_toggle_antenna(valid_tx_ant, &rate, tbl); |
| 2174 | 2165 | ||
| 2175 | rate = rate_n_flags_from_tbl(mvm, tbl, rate_idx, use_green); | 2166 | rate = rate_n_flags_from_tbl(mvm, tbl, rate_idx); |
| 2176 | tbl->current_rate = rate; | 2167 | tbl->current_rate = rate; |
| 2177 | rs_set_expected_tpt_table(lq_sta, tbl); | 2168 | rs_set_expected_tpt_table(lq_sta, tbl); |
| 2178 | rs_fill_link_cmd(NULL, lq_sta, rate); | 2169 | rs_fill_link_cmd(NULL, NULL, lq_sta, rate); |
| 2179 | /* TODO restore station should remember the lq cmd */ | 2170 | /* TODO restore station should remember the lq cmd */ |
| 2180 | iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, CMD_SYNC, true); | 2171 | iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, CMD_SYNC, true); |
| 2181 | } | 2172 | } |
| @@ -2190,7 +2181,6 @@ static void rs_get_rate(void *mvm_r, struct ieee80211_sta *sta, void *mvm_sta, | |||
| 2190 | struct iwl_mvm *mvm __maybe_unused = IWL_OP_MODE_GET_MVM(op_mode); | 2181 | struct iwl_mvm *mvm __maybe_unused = IWL_OP_MODE_GET_MVM(op_mode); |
| 2191 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 2182 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
| 2192 | struct iwl_lq_sta *lq_sta = mvm_sta; | 2183 | struct iwl_lq_sta *lq_sta = mvm_sta; |
| 2193 | int rate_idx; | ||
| 2194 | 2184 | ||
| 2195 | IWL_DEBUG_RATE_LIMIT(mvm, "rate scale calculate new rate for skb\n"); | 2185 | IWL_DEBUG_RATE_LIMIT(mvm, "rate scale calculate new rate for skb\n"); |
| 2196 | 2186 | ||
| @@ -2215,36 +2205,9 @@ static void rs_get_rate(void *mvm_r, struct ieee80211_sta *sta, void *mvm_sta, | |||
| 2215 | if (rate_control_send_low(sta, mvm_sta, txrc)) | 2205 | if (rate_control_send_low(sta, mvm_sta, txrc)) |
| 2216 | return; | 2206 | return; |
| 2217 | 2207 | ||
| 2218 | rate_idx = lq_sta->last_txrate_idx; | 2208 | iwl_mvm_hwrate_to_tx_rate(lq_sta->last_rate_n_flags, |
| 2219 | 2209 | info->band, &info->control.rates[0]); | |
| 2220 | if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) { | 2210 | |
| 2221 | rate_idx -= IWL_FIRST_OFDM_RATE; | ||
| 2222 | /* 6M and 9M shared same MCS index */ | ||
| 2223 | rate_idx = (rate_idx > 0) ? (rate_idx - 1) : 0; | ||
| 2224 | WARN_ON_ONCE(rs_extract_rate(lq_sta->last_rate_n_flags) >= | ||
| 2225 | IWL_RATE_MIMO3_6M_PLCP); | ||
| 2226 | if (rs_extract_rate(lq_sta->last_rate_n_flags) >= | ||
| 2227 | IWL_RATE_MIMO2_6M_PLCP) | ||
| 2228 | rate_idx = rate_idx + MCS_INDEX_PER_STREAM; | ||
| 2229 | info->control.rates[0].flags = IEEE80211_TX_RC_MCS; | ||
| 2230 | if (lq_sta->last_rate_n_flags & RATE_MCS_SGI_MSK) | ||
| 2231 | info->control.rates[0].flags |= IEEE80211_TX_RC_SHORT_GI; | ||
| 2232 | if (lq_sta->last_rate_n_flags & RATE_MCS_CHAN_WIDTH_40) /* TODO */ | ||
| 2233 | info->control.rates[0].flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; | ||
| 2234 | if (lq_sta->last_rate_n_flags & RATE_HT_MCS_GF_MSK) | ||
| 2235 | info->control.rates[0].flags |= IEEE80211_TX_RC_GREEN_FIELD; | ||
| 2236 | } else { | ||
| 2237 | /* Check for invalid rates */ | ||
| 2238 | if ((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT_LEGACY) || | ||
| 2239 | ((sband->band == IEEE80211_BAND_5GHZ) && | ||
| 2240 | (rate_idx < IWL_FIRST_OFDM_RATE))) | ||
| 2241 | rate_idx = rate_lowest_index(sband, sta); | ||
| 2242 | /* On valid 5 GHz rate, adjust index */ | ||
| 2243 | else if (sband->band == IEEE80211_BAND_5GHZ) | ||
| 2244 | rate_idx -= IWL_FIRST_OFDM_RATE; | ||
| 2245 | info->control.rates[0].flags = 0; | ||
| 2246 | } | ||
| 2247 | info->control.rates[0].idx = rate_idx; | ||
| 2248 | info->control.rates[0].count = 1; | 2211 | info->control.rates[0].count = 1; |
| 2249 | } | 2212 | } |
| 2250 | 2213 | ||
| @@ -2261,6 +2224,24 @@ static void *rs_alloc_sta(void *mvm_rate, struct ieee80211_sta *sta, | |||
| 2261 | return &sta_priv->lq_sta; | 2224 | return &sta_priv->lq_sta; |
| 2262 | } | 2225 | } |
| 2263 | 2226 | ||
| 2227 | static int rs_vht_highest_rx_mcs_index(struct ieee80211_sta_vht_cap *vht_cap, | ||
| 2228 | int nss) | ||
| 2229 | { | ||
| 2230 | u16 rx_mcs = le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map) & | ||
| 2231 | (0x3 << (2 * (nss - 1))); | ||
| 2232 | rx_mcs >>= (2 * (nss - 1)); | ||
| 2233 | |||
| 2234 | if (rx_mcs == IEEE80211_VHT_MCS_SUPPORT_0_7) | ||
| 2235 | return IWL_RATE_MCS_7_INDEX; | ||
| 2236 | else if (rx_mcs == IEEE80211_VHT_MCS_SUPPORT_0_8) | ||
| 2237 | return IWL_RATE_MCS_8_INDEX; | ||
| 2238 | else if (rx_mcs == IEEE80211_VHT_MCS_SUPPORT_0_9) | ||
| 2239 | return IWL_RATE_MCS_9_INDEX; | ||
| 2240 | |||
| 2241 | WARN_ON_ONCE(rx_mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED); | ||
| 2242 | return -1; | ||
| 2243 | } | ||
| 2244 | |||
| 2264 | /* | 2245 | /* |
| 2265 | * Called after adding a new station to initialize rate scaling | 2246 | * Called after adding a new station to initialize rate scaling |
| 2266 | */ | 2247 | */ |
| @@ -2270,6 +2251,7 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 2270 | int i, j; | 2251 | int i, j; |
| 2271 | struct ieee80211_hw *hw = mvm->hw; | 2252 | struct ieee80211_hw *hw = mvm->hw; |
| 2272 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | 2253 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; |
| 2254 | struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; | ||
| 2273 | struct iwl_mvm_sta *sta_priv; | 2255 | struct iwl_mvm_sta *sta_priv; |
| 2274 | struct iwl_lq_sta *lq_sta; | 2256 | struct iwl_lq_sta *lq_sta; |
| 2275 | struct ieee80211_supported_band *sband; | 2257 | struct ieee80211_supported_band *sband; |
| @@ -2298,7 +2280,6 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 2298 | 2280 | ||
| 2299 | lq_sta->max_rate_idx = -1; | 2281 | lq_sta->max_rate_idx = -1; |
| 2300 | lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; | 2282 | lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; |
| 2301 | lq_sta->is_green = rs_use_green(sta); | ||
| 2302 | lq_sta->band = sband->band; | 2283 | lq_sta->band = sband->band; |
| 2303 | /* | 2284 | /* |
| 2304 | * active legacy rates as per supported rates bitmap | 2285 | * active legacy rates as per supported rates bitmap |
| @@ -2308,25 +2289,54 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 2308 | for_each_set_bit(i, &supp, BITS_PER_LONG) | 2289 | for_each_set_bit(i, &supp, BITS_PER_LONG) |
| 2309 | lq_sta->active_legacy_rate |= BIT(sband->bitrates[i].hw_value); | 2290 | lq_sta->active_legacy_rate |= BIT(sband->bitrates[i].hw_value); |
| 2310 | 2291 | ||
| 2311 | /* | 2292 | /* TODO: should probably account for rx_highest for both HT/VHT */ |
| 2312 | * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), | 2293 | if (!vht_cap || !vht_cap->vht_supported) { |
| 2313 | * supp_rates[] does not; shift to convert format, force 9 MBits off. | 2294 | /* active_siso_rate mask includes 9 MBits (bit 5), |
| 2314 | */ | 2295 | * and CCK (bits 0-3), supp_rates[] does not; |
| 2315 | lq_sta->active_siso_rate = ht_cap->mcs.rx_mask[0] << 1; | 2296 | * shift to convert format, force 9 MBits off. |
| 2316 | lq_sta->active_siso_rate |= ht_cap->mcs.rx_mask[0] & 0x1; | 2297 | */ |
| 2317 | lq_sta->active_siso_rate &= ~((u16)0x2); | 2298 | lq_sta->active_siso_rate = ht_cap->mcs.rx_mask[0] << 1; |
| 2318 | lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE; | 2299 | lq_sta->active_siso_rate |= ht_cap->mcs.rx_mask[0] & 0x1; |
| 2300 | lq_sta->active_siso_rate &= ~((u16)0x2); | ||
| 2301 | lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE; | ||
| 2302 | |||
| 2303 | /* Same here */ | ||
| 2304 | lq_sta->active_mimo2_rate = ht_cap->mcs.rx_mask[1] << 1; | ||
| 2305 | lq_sta->active_mimo2_rate |= ht_cap->mcs.rx_mask[1] & 0x1; | ||
| 2306 | lq_sta->active_mimo2_rate &= ~((u16)0x2); | ||
| 2307 | lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE; | ||
| 2308 | |||
| 2309 | lq_sta->is_vht = false; | ||
| 2310 | } else { | ||
| 2311 | int highest_mcs = rs_vht_highest_rx_mcs_index(vht_cap, 1); | ||
| 2312 | if (highest_mcs >= IWL_RATE_MCS_0_INDEX) { | ||
| 2313 | for (i = IWL_RATE_MCS_0_INDEX; i <= highest_mcs; i++) { | ||
| 2314 | if (i == IWL_RATE_9M_INDEX) | ||
| 2315 | continue; | ||
| 2316 | |||
| 2317 | lq_sta->active_siso_rate |= BIT(i); | ||
| 2318 | } | ||
| 2319 | } | ||
| 2320 | |||
| 2321 | highest_mcs = rs_vht_highest_rx_mcs_index(vht_cap, 2); | ||
| 2322 | if (highest_mcs >= IWL_RATE_MCS_0_INDEX) { | ||
| 2323 | for (i = IWL_RATE_MCS_0_INDEX; i <= highest_mcs; i++) { | ||
| 2324 | if (i == IWL_RATE_9M_INDEX) | ||
| 2325 | continue; | ||
| 2319 | 2326 | ||
| 2320 | /* Same here */ | 2327 | lq_sta->active_mimo2_rate |= BIT(i); |
| 2321 | lq_sta->active_mimo2_rate = ht_cap->mcs.rx_mask[1] << 1; | 2328 | } |
| 2322 | lq_sta->active_mimo2_rate |= ht_cap->mcs.rx_mask[1] & 0x1; | 2329 | } |
| 2323 | lq_sta->active_mimo2_rate &= ~((u16)0x2); | 2330 | |
| 2324 | lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE; | 2331 | /* TODO: avoid MCS9 in 20Mhz which isn't valid for 11ac */ |
| 2332 | lq_sta->is_vht = true; | ||
| 2333 | } | ||
| 2325 | 2334 | ||
| 2326 | IWL_DEBUG_RATE(mvm, | 2335 | IWL_DEBUG_RATE(mvm, |
| 2327 | "SISO-RATE=%X MIMO2-RATE=%X\n", | 2336 | "SISO-RATE=%X MIMO2-RATE=%X VHT=%d\n", |
| 2328 | lq_sta->active_siso_rate, | 2337 | lq_sta->active_siso_rate, |
| 2329 | lq_sta->active_mimo2_rate); | 2338 | lq_sta->active_mimo2_rate, |
| 2339 | lq_sta->is_vht); | ||
| 2330 | 2340 | ||
| 2331 | /* These values will be overridden later */ | 2341 | /* These values will be overridden later */ |
| 2332 | lq_sta->lq.single_stream_ant_msk = | 2342 | lq_sta->lq.single_stream_ant_msk = |
| @@ -2358,6 +2368,7 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 2358 | } | 2368 | } |
| 2359 | 2369 | ||
| 2360 | static void rs_fill_link_cmd(struct iwl_mvm *mvm, | 2370 | static void rs_fill_link_cmd(struct iwl_mvm *mvm, |
| 2371 | struct ieee80211_sta *sta, | ||
| 2361 | struct iwl_lq_sta *lq_sta, u32 new_rate) | 2372 | struct iwl_lq_sta *lq_sta, u32 new_rate) |
| 2362 | { | 2373 | { |
| 2363 | struct iwl_scale_tbl_info tbl_type; | 2374 | struct iwl_scale_tbl_info tbl_type; |
| @@ -2429,7 +2440,6 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm, | |||
| 2429 | rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, &tbl_type, | 2440 | rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, &tbl_type, |
| 2430 | &rate_idx); | 2441 | &rate_idx); |
| 2431 | 2442 | ||
| 2432 | |||
| 2433 | /* Indicate to uCode which entries might be MIMO. | 2443 | /* Indicate to uCode which entries might be MIMO. |
| 2434 | * If initial rate was MIMO, this will finally end up | 2444 | * If initial rate was MIMO, this will finally end up |
| 2435 | * as (IWL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */ | 2445 | * as (IWL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */ |
| @@ -2455,7 +2465,9 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm, | |||
| 2455 | } | 2465 | } |
| 2456 | 2466 | ||
| 2457 | /* Don't allow HT rates after next pass. | 2467 | /* Don't allow HT rates after next pass. |
| 2458 | * rs_get_lower_rate() will change type to LQ_A or LQ_G. */ | 2468 | * rs_get_lower_rate() will change type to LQ_LEGACY_A |
| 2469 | * or LQ_LEGACY_G. | ||
| 2470 | */ | ||
| 2459 | use_ht_possible = 0; | 2471 | use_ht_possible = 0; |
| 2460 | 2472 | ||
| 2461 | /* Override next rate if needed for debug purposes */ | 2473 | /* Override next rate if needed for debug purposes */ |
| @@ -2474,12 +2486,9 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm, | |||
| 2474 | lq_cmd->agg_time_limit = | 2486 | lq_cmd->agg_time_limit = |
| 2475 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); | 2487 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); |
| 2476 | 2488 | ||
| 2477 | /* | 2489 | if (sta) |
| 2478 | * overwrite if needed, pass aggregation time limit | 2490 | lq_cmd->agg_time_limit = |
| 2479 | * to uCode in uSec - This is racy - but heh, at least it helps... | 2491 | cpu_to_le16(iwl_mvm_bt_coex_agg_time_limit(mvm, sta)); |
| 2480 | */ | ||
| 2481 | if (mvm && BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD) >= 2) | ||
| 2482 | lq_cmd->agg_time_limit = cpu_to_le16(1200); | ||
| 2483 | } | 2492 | } |
| 2484 | 2493 | ||
| 2485 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | 2494 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) |
| @@ -2586,16 +2595,18 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | |||
| 2586 | (iwl_fw_valid_tx_ant(mvm->fw) & ANT_B) ? "ANT_B," : "", | 2595 | (iwl_fw_valid_tx_ant(mvm->fw) & ANT_B) ? "ANT_B," : "", |
| 2587 | (iwl_fw_valid_tx_ant(mvm->fw) & ANT_C) ? "ANT_C" : ""); | 2596 | (iwl_fw_valid_tx_ant(mvm->fw) & ANT_C) ? "ANT_C" : ""); |
| 2588 | desc += sprintf(buff+desc, "lq type %s\n", | 2597 | desc += sprintf(buff+desc, "lq type %s\n", |
| 2589 | (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); | 2598 | (is_legacy(tbl->lq_type)) ? "legacy" : |
| 2590 | if (is_Ht(tbl->lq_type)) { | 2599 | is_vht(tbl->lq_type) ? "VHT" : "HT"); |
| 2600 | if (is_ht(tbl->lq_type)) { | ||
| 2591 | desc += sprintf(buff+desc, " %s", | 2601 | desc += sprintf(buff+desc, " %s", |
| 2592 | (is_siso(tbl->lq_type)) ? "SISO" : "MIMO2"); | 2602 | (is_siso(tbl->lq_type)) ? "SISO" : "MIMO2"); |
| 2593 | desc += sprintf(buff+desc, " %s", | 2603 | desc += sprintf(buff+desc, " %s", |
| 2594 | (tbl->is_ht40) ? "40MHz" : "20MHz"); | 2604 | (is_ht20(tbl)) ? "20MHz" : |
| 2595 | desc += sprintf(buff+desc, " %s %s %s\n", | 2605 | (is_ht40(tbl)) ? "40MHz" : |
| 2606 | (is_ht80(tbl)) ? "80Mhz" : "BAD BW"); | ||
| 2607 | desc += sprintf(buff+desc, " %s %s\n", | ||
| 2596 | (tbl->is_SGI) ? "SGI" : "", | 2608 | (tbl->is_SGI) ? "SGI" : "", |
| 2597 | (lq_sta->is_green) ? "GF enabled" : "", | 2609 | (lq_sta->is_agg) ? "AGG on" : ""); |
| 2598 | (lq_sta->is_agg) ? "AGG on" : ""); | ||
| 2599 | } | 2610 | } |
| 2600 | desc += sprintf(buff+desc, "last tx rate=0x%X\n", | 2611 | desc += sprintf(buff+desc, "last tx rate=0x%X\n", |
| 2601 | lq_sta->last_rate_n_flags); | 2612 | lq_sta->last_rate_n_flags); |
| @@ -2653,7 +2664,7 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file, | |||
| 2653 | int desc = 0; | 2664 | int desc = 0; |
| 2654 | int i, j; | 2665 | int i, j; |
| 2655 | ssize_t ret; | 2666 | ssize_t ret; |
| 2656 | 2667 | struct iwl_scale_tbl_info *tbl; | |
| 2657 | struct iwl_lq_sta *lq_sta = file->private_data; | 2668 | struct iwl_lq_sta *lq_sta = file->private_data; |
| 2658 | 2669 | ||
| 2659 | buff = kmalloc(1024, GFP_KERNEL); | 2670 | buff = kmalloc(1024, GFP_KERNEL); |
| @@ -2661,21 +2672,23 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file, | |||
| 2661 | return -ENOMEM; | 2672 | return -ENOMEM; |
| 2662 | 2673 | ||
| 2663 | for (i = 0; i < LQ_SIZE; i++) { | 2674 | for (i = 0; i < LQ_SIZE; i++) { |
| 2675 | tbl = &(lq_sta->lq_info[i]); | ||
| 2664 | desc += sprintf(buff+desc, | 2676 | desc += sprintf(buff+desc, |
| 2665 | "%s type=%d SGI=%d HT40=%d DUP=0 GF=%d\n" | 2677 | "%s type=%d SGI=%d BW=%s DUP=0\n" |
| 2666 | "rate=0x%X\n", | 2678 | "rate=0x%X\n", |
| 2667 | lq_sta->active_tbl == i ? "*" : "x", | 2679 | lq_sta->active_tbl == i ? "*" : "x", |
| 2668 | lq_sta->lq_info[i].lq_type, | 2680 | tbl->lq_type, |
| 2669 | lq_sta->lq_info[i].is_SGI, | 2681 | tbl->is_SGI, |
| 2670 | lq_sta->lq_info[i].is_ht40, | 2682 | is_ht20(tbl) ? "20Mhz" : |
| 2671 | lq_sta->is_green, | 2683 | is_ht40(tbl) ? "40Mhz" : |
| 2672 | lq_sta->lq_info[i].current_rate); | 2684 | is_ht80(tbl) ? "80Mhz" : "ERR", |
| 2685 | tbl->current_rate); | ||
| 2673 | for (j = 0; j < IWL_RATE_COUNT; j++) { | 2686 | for (j = 0; j < IWL_RATE_COUNT; j++) { |
| 2674 | desc += sprintf(buff+desc, | 2687 | desc += sprintf(buff+desc, |
| 2675 | "counter=%d success=%d %%=%d\n", | 2688 | "counter=%d success=%d %%=%d\n", |
| 2676 | lq_sta->lq_info[i].win[j].counter, | 2689 | tbl->win[j].counter, |
| 2677 | lq_sta->lq_info[i].win[j].success_counter, | 2690 | tbl->win[j].success_counter, |
| 2678 | lq_sta->lq_info[i].win[j].success_ratio); | 2691 | tbl->win[j].success_ratio); |
| 2679 | } | 2692 | } |
| 2680 | } | 2693 | } |
| 2681 | ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); | 2694 | ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index 335cf1682902..5d5344f7070b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h | |||
| @@ -35,9 +35,11 @@ | |||
| 35 | #include "iwl-trans.h" | 35 | #include "iwl-trans.h" |
| 36 | 36 | ||
| 37 | struct iwl_rs_rate_info { | 37 | struct iwl_rs_rate_info { |
| 38 | u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ | 38 | u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ |
| 39 | u8 plcp_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */ | 39 | u8 plcp_ht_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */ |
| 40 | u8 plcp_mimo2; /* uCode API: IWL_RATE_MIMO2_6M_PLCP, etc. */ | 40 | u8 plcp_ht_mimo2; /* uCode API: IWL_RATE_MIMO2_6M_PLCP, etc. */ |
| 41 | u8 plcp_vht_siso; | ||
| 42 | u8 plcp_vht_mimo2; | ||
| 41 | u8 prev_rs; /* previous rate used in rs algo */ | 43 | u8 prev_rs; /* previous rate used in rs algo */ |
| 42 | u8 next_rs; /* next rate used in rs algo */ | 44 | u8 next_rs; /* next rate used in rs algo */ |
| 43 | }; | 45 | }; |
| @@ -83,35 +85,52 @@ enum { | |||
| 83 | #define IWL_RATE_11M_MASK (1 << IWL_RATE_11M_INDEX) | 85 | #define IWL_RATE_11M_MASK (1 << IWL_RATE_11M_INDEX) |
| 84 | 86 | ||
| 85 | 87 | ||
| 86 | /* uCode API values for OFDM high-throughput (HT) bit rates */ | 88 | /* uCode API values for HT/VHT bit rates */ |
| 87 | enum { | 89 | enum { |
| 88 | IWL_RATE_SISO_6M_PLCP = 0, | 90 | IWL_RATE_HT_SISO_MCS_0_PLCP = 0, |
| 89 | IWL_RATE_SISO_12M_PLCP = 1, | 91 | IWL_RATE_HT_SISO_MCS_1_PLCP = 1, |
| 90 | IWL_RATE_SISO_18M_PLCP = 2, | 92 | IWL_RATE_HT_SISO_MCS_2_PLCP = 2, |
| 91 | IWL_RATE_SISO_24M_PLCP = 3, | 93 | IWL_RATE_HT_SISO_MCS_3_PLCP = 3, |
| 92 | IWL_RATE_SISO_36M_PLCP = 4, | 94 | IWL_RATE_HT_SISO_MCS_4_PLCP = 4, |
| 93 | IWL_RATE_SISO_48M_PLCP = 5, | 95 | IWL_RATE_HT_SISO_MCS_5_PLCP = 5, |
| 94 | IWL_RATE_SISO_54M_PLCP = 6, | 96 | IWL_RATE_HT_SISO_MCS_6_PLCP = 6, |
| 95 | IWL_RATE_SISO_60M_PLCP = 7, | 97 | IWL_RATE_HT_SISO_MCS_7_PLCP = 7, |
| 96 | IWL_RATE_MIMO2_6M_PLCP = 0x8, | 98 | IWL_RATE_HT_MIMO2_MCS_0_PLCP = 0x8, |
| 97 | IWL_RATE_MIMO2_12M_PLCP = 0x9, | 99 | IWL_RATE_HT_MIMO2_MCS_1_PLCP = 0x9, |
| 98 | IWL_RATE_MIMO2_18M_PLCP = 0xa, | 100 | IWL_RATE_HT_MIMO2_MCS_2_PLCP = 0xA, |
| 99 | IWL_RATE_MIMO2_24M_PLCP = 0xb, | 101 | IWL_RATE_HT_MIMO2_MCS_3_PLCP = 0xB, |
| 100 | IWL_RATE_MIMO2_36M_PLCP = 0xc, | 102 | IWL_RATE_HT_MIMO2_MCS_4_PLCP = 0xC, |
| 101 | IWL_RATE_MIMO2_48M_PLCP = 0xd, | 103 | IWL_RATE_HT_MIMO2_MCS_5_PLCP = 0xD, |
| 102 | IWL_RATE_MIMO2_54M_PLCP = 0xe, | 104 | IWL_RATE_HT_MIMO2_MCS_6_PLCP = 0xE, |
| 103 | IWL_RATE_MIMO2_60M_PLCP = 0xf, | 105 | IWL_RATE_HT_MIMO2_MCS_7_PLCP = 0xF, |
| 104 | IWL_RATE_MIMO3_6M_PLCP = 0x10, | 106 | IWL_RATE_VHT_SISO_MCS_0_PLCP = 0, |
| 105 | IWL_RATE_MIMO3_12M_PLCP = 0x11, | 107 | IWL_RATE_VHT_SISO_MCS_1_PLCP = 1, |
| 106 | IWL_RATE_MIMO3_18M_PLCP = 0x12, | 108 | IWL_RATE_VHT_SISO_MCS_2_PLCP = 2, |
| 107 | IWL_RATE_MIMO3_24M_PLCP = 0x13, | 109 | IWL_RATE_VHT_SISO_MCS_3_PLCP = 3, |
| 108 | IWL_RATE_MIMO3_36M_PLCP = 0x14, | 110 | IWL_RATE_VHT_SISO_MCS_4_PLCP = 4, |
| 109 | IWL_RATE_MIMO3_48M_PLCP = 0x15, | 111 | IWL_RATE_VHT_SISO_MCS_5_PLCP = 5, |
| 110 | IWL_RATE_MIMO3_54M_PLCP = 0x16, | 112 | IWL_RATE_VHT_SISO_MCS_6_PLCP = 6, |
| 111 | IWL_RATE_MIMO3_60M_PLCP = 0x17, | 113 | IWL_RATE_VHT_SISO_MCS_7_PLCP = 7, |
| 112 | IWL_RATE_SISO_INVM_PLCP, | 114 | IWL_RATE_VHT_SISO_MCS_8_PLCP = 8, |
| 113 | IWL_RATE_MIMO2_INVM_PLCP = IWL_RATE_SISO_INVM_PLCP, | 115 | IWL_RATE_VHT_SISO_MCS_9_PLCP = 9, |
| 114 | IWL_RATE_MIMO3_INVM_PLCP = IWL_RATE_SISO_INVM_PLCP, | 116 | IWL_RATE_VHT_MIMO2_MCS_0_PLCP = 0x10, |
| 117 | IWL_RATE_VHT_MIMO2_MCS_1_PLCP = 0x11, | ||
| 118 | IWL_RATE_VHT_MIMO2_MCS_2_PLCP = 0x12, | ||
| 119 | IWL_RATE_VHT_MIMO2_MCS_3_PLCP = 0x13, | ||
| 120 | IWL_RATE_VHT_MIMO2_MCS_4_PLCP = 0x14, | ||
| 121 | IWL_RATE_VHT_MIMO2_MCS_5_PLCP = 0x15, | ||
| 122 | IWL_RATE_VHT_MIMO2_MCS_6_PLCP = 0x16, | ||
| 123 | IWL_RATE_VHT_MIMO2_MCS_7_PLCP = 0x17, | ||
| 124 | IWL_RATE_VHT_MIMO2_MCS_8_PLCP = 0x18, | ||
| 125 | IWL_RATE_VHT_MIMO2_MCS_9_PLCP = 0x19, | ||
| 126 | IWL_RATE_HT_SISO_MCS_INV_PLCP, | ||
| 127 | IWL_RATE_HT_MIMO2_MCS_INV_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP, | ||
| 128 | IWL_RATE_VHT_SISO_MCS_INV_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP, | ||
| 129 | IWL_RATE_VHT_MIMO2_MCS_INV_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP, | ||
| 130 | IWL_RATE_HT_SISO_MCS_8_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP, | ||
| 131 | IWL_RATE_HT_SISO_MCS_9_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP, | ||
| 132 | IWL_RATE_HT_MIMO2_MCS_8_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP, | ||
| 133 | IWL_RATE_HT_MIMO2_MCS_9_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP, | ||
| 115 | }; | 134 | }; |
| 116 | 135 | ||
| 117 | #define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1) | 136 | #define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1) |
| @@ -139,25 +158,33 @@ enum { | |||
| 139 | #define IWL_RATE_DECREASE_TH 1920 /* 15% */ | 158 | #define IWL_RATE_DECREASE_TH 1920 /* 15% */ |
| 140 | 159 | ||
| 141 | /* possible actions when in legacy mode */ | 160 | /* possible actions when in legacy mode */ |
| 142 | #define IWL_LEGACY_SWITCH_ANTENNA1 0 | 161 | enum { |
| 143 | #define IWL_LEGACY_SWITCH_ANTENNA2 1 | 162 | IWL_LEGACY_SWITCH_ANTENNA, |
| 144 | #define IWL_LEGACY_SWITCH_SISO 2 | 163 | IWL_LEGACY_SWITCH_SISO, |
| 145 | #define IWL_LEGACY_SWITCH_MIMO2 3 | 164 | IWL_LEGACY_SWITCH_MIMO2, |
| 165 | IWL_LEGACY_FIRST_ACTION = IWL_LEGACY_SWITCH_ANTENNA, | ||
| 166 | IWL_LEGACY_LAST_ACTION = IWL_LEGACY_SWITCH_MIMO2, | ||
| 167 | }; | ||
| 146 | 168 | ||
| 147 | /* possible actions when in siso mode */ | 169 | /* possible actions when in siso mode */ |
| 148 | #define IWL_SISO_SWITCH_ANTENNA1 0 | 170 | enum { |
| 149 | #define IWL_SISO_SWITCH_ANTENNA2 1 | 171 | IWL_SISO_SWITCH_ANTENNA, |
| 150 | #define IWL_SISO_SWITCH_MIMO2 2 | 172 | IWL_SISO_SWITCH_MIMO2, |
| 151 | #define IWL_SISO_SWITCH_GI 3 | 173 | IWL_SISO_SWITCH_GI, |
| 174 | IWL_SISO_FIRST_ACTION = IWL_SISO_SWITCH_ANTENNA, | ||
| 175 | IWL_SISO_LAST_ACTION = IWL_SISO_SWITCH_GI, | ||
| 176 | }; | ||
| 152 | 177 | ||
| 153 | /* possible actions when in mimo mode */ | 178 | /* possible actions when in mimo mode */ |
| 154 | #define IWL_MIMO2_SWITCH_ANTENNA1 0 | 179 | enum { |
| 155 | #define IWL_MIMO2_SWITCH_ANTENNA2 1 | 180 | IWL_MIMO2_SWITCH_SISO_A, |
| 156 | #define IWL_MIMO2_SWITCH_SISO_A 2 | 181 | IWL_MIMO2_SWITCH_SISO_B, |
| 157 | #define IWL_MIMO2_SWITCH_SISO_B 3 | 182 | IWL_MIMO2_SWITCH_GI, |
| 158 | #define IWL_MIMO2_SWITCH_GI 4 | 183 | IWL_MIMO2_FIRST_ACTION = IWL_MIMO2_SWITCH_SISO_A, |
| 184 | IWL_MIMO2_LAST_ACTION = IWL_MIMO2_SWITCH_GI, | ||
| 185 | }; | ||
| 159 | 186 | ||
| 160 | #define IWL_MAX_SEARCH IWL_MIMO2_SWITCH_GI | 187 | #define IWL_MAX_SEARCH IWL_MIMO2_LAST_ACTION |
| 161 | 188 | ||
| 162 | #define IWL_ACTION_LIMIT 3 /* # possible actions */ | 189 | #define IWL_ACTION_LIMIT 3 /* # possible actions */ |
| 163 | 190 | ||
| @@ -188,20 +215,31 @@ enum { | |||
| 188 | 215 | ||
| 189 | enum iwl_table_type { | 216 | enum iwl_table_type { |
| 190 | LQ_NONE, | 217 | LQ_NONE, |
| 191 | LQ_G, /* legacy types */ | 218 | LQ_LEGACY_G, /* legacy types */ |
| 192 | LQ_A, | 219 | LQ_LEGACY_A, |
| 193 | LQ_SISO, /* high-throughput types */ | 220 | LQ_HT_SISO, /* HT types */ |
| 194 | LQ_MIMO2, | 221 | LQ_HT_MIMO2, |
| 222 | LQ_VHT_SISO, /* VHT types */ | ||
| 223 | LQ_VHT_MIMO2, | ||
| 195 | LQ_MAX, | 224 | LQ_MAX, |
| 196 | }; | 225 | }; |
| 197 | 226 | ||
| 198 | #define is_legacy(tbl) (((tbl) == LQ_G) || ((tbl) == LQ_A)) | 227 | #define is_legacy(tbl) (((tbl) == LQ_LEGACY_G) || ((tbl) == LQ_LEGACY_A)) |
| 199 | #define is_siso(tbl) ((tbl) == LQ_SISO) | 228 | #define is_ht_siso(tbl) ((tbl) == LQ_HT_SISO) |
| 200 | #define is_mimo2(tbl) ((tbl) == LQ_MIMO2) | 229 | #define is_ht_mimo2(tbl) ((tbl) == LQ_HT_MIMO2) |
| 201 | #define is_mimo(tbl) is_mimo2(tbl) | 230 | #define is_vht_siso(tbl) ((tbl) == LQ_VHT_SISO) |
| 202 | #define is_Ht(tbl) (is_siso(tbl) || is_mimo(tbl)) | 231 | #define is_vht_mimo2(tbl) ((tbl) == LQ_VHT_MIMO2) |
| 203 | #define is_a_band(tbl) ((tbl) == LQ_A) | 232 | #define is_siso(tbl) (is_ht_siso(tbl) || is_vht_siso(tbl)) |
| 204 | #define is_g_and(tbl) ((tbl) == LQ_G) | 233 | #define is_mimo2(tbl) (is_ht_mimo2(tbl) || is_vht_mimo2(tbl)) |
| 234 | #define is_mimo(tbl) (is_mimo2(tbl)) | ||
| 235 | #define is_ht(tbl) (is_ht_siso(tbl) || is_ht_mimo2(tbl)) | ||
| 236 | #define is_vht(tbl) (is_vht_siso(tbl) || is_vht_mimo2(tbl)) | ||
| 237 | #define is_a_band(tbl) ((tbl) == LQ_LEGACY_A) | ||
| 238 | #define is_g_band(tbl) ((tbl) == LQ_LEGACY_G) | ||
| 239 | |||
| 240 | #define is_ht20(tbl) (tbl->bw == RATE_MCS_CHAN_WIDTH_20) | ||
| 241 | #define is_ht40(tbl) (tbl->bw == RATE_MCS_CHAN_WIDTH_40) | ||
| 242 | #define is_ht80(tbl) (tbl->bw == RATE_MCS_CHAN_WIDTH_80) | ||
| 205 | 243 | ||
| 206 | #define IWL_MAX_MCS_DISPLAY_SIZE 12 | 244 | #define IWL_MAX_MCS_DISPLAY_SIZE 12 |
| 207 | 245 | ||
| @@ -232,7 +270,7 @@ struct iwl_scale_tbl_info { | |||
| 232 | enum iwl_table_type lq_type; | 270 | enum iwl_table_type lq_type; |
| 233 | u8 ant_type; | 271 | u8 ant_type; |
| 234 | u8 is_SGI; /* 1 = short guard interval */ | 272 | u8 is_SGI; /* 1 = short guard interval */ |
| 235 | u8 is_ht40; /* 1 = 40 MHz channel width */ | 273 | u32 bw; /* channel bandwidth; RATE_MCS_CHAN_WIDTH_XX */ |
| 236 | u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */ | 274 | u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */ |
| 237 | u8 max_search; /* maximun number of tables we can search */ | 275 | u8 max_search; /* maximun number of tables we can search */ |
| 238 | s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ | 276 | s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ |
| @@ -262,7 +300,7 @@ struct iwl_lq_sta { | |||
| 262 | u64 flush_timer; /* time staying in mode before new search */ | 300 | u64 flush_timer; /* time staying in mode before new search */ |
| 263 | 301 | ||
| 264 | u8 action_counter; /* # mode-switch actions tried */ | 302 | u8 action_counter; /* # mode-switch actions tried */ |
| 265 | u8 is_green; | 303 | bool is_vht; |
| 266 | enum ieee80211_band band; | 304 | enum ieee80211_band band; |
| 267 | 305 | ||
| 268 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ | 306 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ |
| @@ -314,9 +352,8 @@ static inline u8 num_of_ant(u8 mask) | |||
| 314 | } | 352 | } |
| 315 | 353 | ||
| 316 | /* Initialize station's rate scaling information after adding station */ | 354 | /* Initialize station's rate scaling information after adding station */ |
| 317 | extern void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, | 355 | void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, |
| 318 | struct ieee80211_sta *sta, | 356 | enum ieee80211_band band); |
| 319 | enum ieee80211_band band); | ||
| 320 | 357 | ||
| 321 | /** | 358 | /** |
| 322 | * iwl_rate_control_register - Register the rate control algorithm callbacks | 359 | * iwl_rate_control_register - Register the rate control algorithm callbacks |
| @@ -328,7 +365,7 @@ extern void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, | |||
| 328 | * ieee80211_register_hw | 365 | * ieee80211_register_hw |
| 329 | * | 366 | * |
| 330 | */ | 367 | */ |
| 331 | extern int iwl_mvm_rate_control_register(void); | 368 | int iwl_mvm_rate_control_register(void); |
| 332 | 369 | ||
| 333 | /** | 370 | /** |
| 334 | * iwl_rate_control_unregister - Unregister the rate control callbacks | 371 | * iwl_rate_control_unregister - Unregister the rate control callbacks |
| @@ -336,7 +373,7 @@ extern int iwl_mvm_rate_control_register(void); | |||
| 336 | * This should be called after calling ieee80211_unregister_hw, but before | 373 | * This should be called after calling ieee80211_unregister_hw, but before |
| 337 | * the driver is unloaded. | 374 | * the driver is unloaded. |
| 338 | */ | 375 | */ |
| 339 | extern void iwl_mvm_rate_control_unregister(void); | 376 | void iwl_mvm_rate_control_unregister(void); |
| 340 | 377 | ||
| 341 | struct iwl_mvm_sta; | 378 | struct iwl_mvm_sta; |
| 342 | 379 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index 2a8cb5a60535..3a1f3982109d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c | |||
| @@ -300,10 +300,14 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
| 300 | return 0; | 300 | return 0; |
| 301 | } | 301 | } |
| 302 | 302 | ||
| 303 | /* | ||
| 304 | * Keep packets with CRC errors (and with overrun) for monitor mode | ||
| 305 | * (otherwise the firmware discards them) but mark them as bad. | ||
| 306 | */ | ||
| 303 | if (!(rx_pkt_status & RX_MPDU_RES_STATUS_CRC_OK) || | 307 | if (!(rx_pkt_status & RX_MPDU_RES_STATUS_CRC_OK) || |
| 304 | !(rx_pkt_status & RX_MPDU_RES_STATUS_OVERRUN_OK)) { | 308 | !(rx_pkt_status & RX_MPDU_RES_STATUS_OVERRUN_OK)) { |
| 305 | IWL_DEBUG_RX(mvm, "Bad CRC or FIFO: 0x%08X.\n", rx_pkt_status); | 309 | IWL_DEBUG_RX(mvm, "Bad CRC or FIFO: 0x%08X.\n", rx_pkt_status); |
| 306 | return 0; | 310 | rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; |
| 307 | } | 311 | } |
| 308 | 312 | ||
| 309 | /* This will be used in several places later */ | 313 | /* This will be used in several places later */ |
| @@ -422,6 +426,27 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac, | |||
| 422 | 426 | ||
| 423 | mvmvif->bf_data.ave_beacon_signal = sig; | 427 | mvmvif->bf_data.ave_beacon_signal = sig; |
| 424 | 428 | ||
| 429 | /* BT Coex */ | ||
| 430 | if (mvmvif->bf_data.bt_coex_min_thold != | ||
| 431 | mvmvif->bf_data.bt_coex_max_thold) { | ||
| 432 | last_event = mvmvif->bf_data.last_bt_coex_event; | ||
| 433 | if (sig > mvmvif->bf_data.bt_coex_max_thold && | ||
| 434 | (last_event <= mvmvif->bf_data.bt_coex_min_thold || | ||
| 435 | last_event == 0)) { | ||
| 436 | mvmvif->bf_data.last_bt_coex_event = sig; | ||
| 437 | IWL_DEBUG_RX(mvm, "cqm_iterator bt coex high %d\n", | ||
| 438 | sig); | ||
| 439 | iwl_mvm_bt_rssi_event(mvm, vif, RSSI_EVENT_HIGH); | ||
| 440 | } else if (sig < mvmvif->bf_data.bt_coex_min_thold && | ||
| 441 | (last_event >= mvmvif->bf_data.bt_coex_max_thold || | ||
| 442 | last_event == 0)) { | ||
| 443 | mvmvif->bf_data.last_bt_coex_event = sig; | ||
| 444 | IWL_DEBUG_RX(mvm, "cqm_iterator bt coex low %d\n", | ||
| 445 | sig); | ||
| 446 | iwl_mvm_bt_rssi_event(mvm, vif, RSSI_EVENT_LOW); | ||
| 447 | } | ||
| 448 | } | ||
| 449 | |||
| 425 | if (!(vif->driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)) | 450 | if (!(vif->driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)) |
| 426 | return; | 451 | return; |
| 427 | 452 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 621fb71f282a..dff7592e1ff8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
| @@ -74,8 +74,12 @@ | |||
| 74 | static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm) | 74 | static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm) |
| 75 | { | 75 | { |
| 76 | u16 rx_chain; | 76 | u16 rx_chain; |
| 77 | u8 rx_ant = iwl_fw_valid_rx_ant(mvm->fw); | 77 | u8 rx_ant; |
| 78 | 78 | ||
| 79 | if (mvm->scan_rx_ant != ANT_NONE) | ||
| 80 | rx_ant = mvm->scan_rx_ant; | ||
| 81 | else | ||
| 82 | rx_ant = iwl_fw_valid_rx_ant(mvm->fw); | ||
| 79 | rx_chain = rx_ant << PHY_RX_CHAIN_VALID_POS; | 83 | rx_chain = rx_ant << PHY_RX_CHAIN_VALID_POS; |
| 80 | rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_MIMO_SEL_POS; | 84 | rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_MIMO_SEL_POS; |
| 81 | rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_SEL_POS; | 85 | rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_SEL_POS; |
| @@ -93,10 +97,10 @@ static inline __le32 iwl_mvm_scan_max_out_time(struct ieee80211_vif *vif) | |||
| 93 | 97 | ||
| 94 | static inline __le32 iwl_mvm_scan_suspend_time(struct ieee80211_vif *vif) | 98 | static inline __le32 iwl_mvm_scan_suspend_time(struct ieee80211_vif *vif) |
| 95 | { | 99 | { |
| 96 | if (vif->bss_conf.assoc) | 100 | if (!vif->bss_conf.assoc) |
| 97 | return cpu_to_le32(vif->bss_conf.beacon_int); | ||
| 98 | else | ||
| 99 | return 0; | 101 | return 0; |
| 102 | |||
| 103 | return cpu_to_le32(ieee80211_tu_to_usec(vif->bss_conf.beacon_int)); | ||
| 100 | } | 104 | } |
| 101 | 105 | ||
| 102 | static inline __le32 | 106 | static inline __le32 |
| @@ -133,11 +137,12 @@ iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum ieee80211_band band, | |||
| 133 | * request. | 137 | * request. |
| 134 | */ | 138 | */ |
| 135 | static void iwl_mvm_scan_fill_ssids(struct iwl_scan_cmd *cmd, | 139 | static void iwl_mvm_scan_fill_ssids(struct iwl_scan_cmd *cmd, |
| 136 | struct cfg80211_scan_request *req) | 140 | struct cfg80211_scan_request *req, |
| 141 | int first) | ||
| 137 | { | 142 | { |
| 138 | int fw_idx, req_idx; | 143 | int fw_idx, req_idx; |
| 139 | 144 | ||
| 140 | for (req_idx = req->n_ssids - 1, fw_idx = 0; req_idx > 0; | 145 | for (req_idx = req->n_ssids - 1, fw_idx = 0; req_idx >= first; |
| 141 | req_idx--, fw_idx++) { | 146 | req_idx--, fw_idx++) { |
| 142 | cmd->direct_scan[fw_idx].id = WLAN_EID_SSID; | 147 | cmd->direct_scan[fw_idx].id = WLAN_EID_SSID; |
| 143 | cmd->direct_scan[fw_idx].len = req->ssids[req_idx].ssid_len; | 148 | cmd->direct_scan[fw_idx].len = req->ssids[req_idx].ssid_len; |
| @@ -153,9 +158,9 @@ static void iwl_mvm_scan_fill_ssids(struct iwl_scan_cmd *cmd, | |||
| 153 | * just to notify that this scan is active and not passive. | 158 | * just to notify that this scan is active and not passive. |
| 154 | * In order to notify the FW of the number of SSIDs we wish to scan (including | 159 | * In order to notify the FW of the number of SSIDs we wish to scan (including |
| 155 | * the zero-length one), we need to set the corresponding bits in chan->type, | 160 | * the zero-length one), we need to set the corresponding bits in chan->type, |
| 156 | * one for each SSID, and set the active bit (first). The first SSID is already | 161 | * one for each SSID, and set the active bit (first). If the first SSID is |
| 157 | * included in the probe template, so we need to set only req->n_ssids - 1 bits | 162 | * already included in the probe template, so we need to set only |
| 158 | * in addition to the first bit. | 163 | * req->n_ssids - 1 bits in addition to the first bit. |
| 159 | */ | 164 | */ |
| 160 | static u16 iwl_mvm_get_active_dwell(enum ieee80211_band band, int n_ssids) | 165 | static u16 iwl_mvm_get_active_dwell(enum ieee80211_band band, int n_ssids) |
| 161 | { | 166 | { |
| @@ -170,7 +175,8 @@ static u16 iwl_mvm_get_passive_dwell(enum ieee80211_band band) | |||
| 170 | } | 175 | } |
| 171 | 176 | ||
| 172 | static void iwl_mvm_scan_fill_channels(struct iwl_scan_cmd *cmd, | 177 | static void iwl_mvm_scan_fill_channels(struct iwl_scan_cmd *cmd, |
| 173 | struct cfg80211_scan_request *req) | 178 | struct cfg80211_scan_request *req, |
| 179 | bool basic_ssid) | ||
| 174 | { | 180 | { |
| 175 | u16 passive_dwell = iwl_mvm_get_passive_dwell(req->channels[0]->band); | 181 | u16 passive_dwell = iwl_mvm_get_passive_dwell(req->channels[0]->band); |
| 176 | u16 active_dwell = iwl_mvm_get_active_dwell(req->channels[0]->band, | 182 | u16 active_dwell = iwl_mvm_get_active_dwell(req->channels[0]->band, |
| @@ -178,10 +184,14 @@ static void iwl_mvm_scan_fill_channels(struct iwl_scan_cmd *cmd, | |||
| 178 | struct iwl_scan_channel *chan = (struct iwl_scan_channel *) | 184 | struct iwl_scan_channel *chan = (struct iwl_scan_channel *) |
| 179 | (cmd->data + le16_to_cpu(cmd->tx_cmd.len)); | 185 | (cmd->data + le16_to_cpu(cmd->tx_cmd.len)); |
| 180 | int i; | 186 | int i; |
| 187 | int type = BIT(req->n_ssids) - 1; | ||
| 188 | |||
| 189 | if (!basic_ssid) | ||
| 190 | type |= BIT(req->n_ssids); | ||
| 181 | 191 | ||
| 182 | for (i = 0; i < cmd->channel_count; i++) { | 192 | for (i = 0; i < cmd->channel_count; i++) { |
| 183 | chan->channel = cpu_to_le16(req->channels[i]->hw_value); | 193 | chan->channel = cpu_to_le16(req->channels[i]->hw_value); |
| 184 | chan->type = cpu_to_le32(BIT(req->n_ssids) - 1); | 194 | chan->type = cpu_to_le32(type); |
| 185 | if (req->channels[i]->flags & IEEE80211_CHAN_PASSIVE_SCAN) | 195 | if (req->channels[i]->flags & IEEE80211_CHAN_PASSIVE_SCAN) |
| 186 | chan->type &= cpu_to_le32(~SCAN_CHANNEL_TYPE_ACTIVE); | 196 | chan->type &= cpu_to_le32(~SCAN_CHANNEL_TYPE_ACTIVE); |
| 187 | chan->active_dwell = cpu_to_le16(active_dwell); | 197 | chan->active_dwell = cpu_to_le16(active_dwell); |
| @@ -268,6 +278,8 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm, | |||
| 268 | u32 status; | 278 | u32 status; |
| 269 | int ssid_len = 0; | 279 | int ssid_len = 0; |
| 270 | u8 *ssid = NULL; | 280 | u8 *ssid = NULL; |
| 281 | bool basic_ssid = !(mvm->fw->ucode_capa.flags & | ||
| 282 | IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID); | ||
| 271 | 283 | ||
| 272 | lockdep_assert_held(&mvm->mutex); | 284 | lockdep_assert_held(&mvm->mutex); |
| 273 | BUG_ON(mvm->scan_cmd == NULL); | 285 | BUG_ON(mvm->scan_cmd == NULL); |
| @@ -302,14 +314,16 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm, | |||
| 302 | if (req->n_ssids > 0) { | 314 | if (req->n_ssids > 0) { |
| 303 | cmd->passive2active = cpu_to_le16(1); | 315 | cmd->passive2active = cpu_to_le16(1); |
| 304 | cmd->scan_flags |= SCAN_FLAGS_PASSIVE2ACTIVE; | 316 | cmd->scan_flags |= SCAN_FLAGS_PASSIVE2ACTIVE; |
| 305 | ssid = req->ssids[0].ssid; | 317 | if (basic_ssid) { |
| 306 | ssid_len = req->ssids[0].ssid_len; | 318 | ssid = req->ssids[0].ssid; |
| 319 | ssid_len = req->ssids[0].ssid_len; | ||
| 320 | } | ||
| 307 | } else { | 321 | } else { |
| 308 | cmd->passive2active = 0; | 322 | cmd->passive2active = 0; |
| 309 | cmd->scan_flags &= ~SCAN_FLAGS_PASSIVE2ACTIVE; | 323 | cmd->scan_flags &= ~SCAN_FLAGS_PASSIVE2ACTIVE; |
| 310 | } | 324 | } |
| 311 | 325 | ||
| 312 | iwl_mvm_scan_fill_ssids(cmd, req); | 326 | iwl_mvm_scan_fill_ssids(cmd, req, basic_ssid ? 1 : 0); |
| 313 | 327 | ||
| 314 | cmd->tx_cmd.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL); | 328 | cmd->tx_cmd.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL); |
| 315 | cmd->tx_cmd.sta_id = mvm->aux_sta.sta_id; | 329 | cmd->tx_cmd.sta_id = mvm->aux_sta.sta_id; |
| @@ -326,7 +340,7 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm, | |||
| 326 | req->ie, req->ie_len, | 340 | req->ie, req->ie_len, |
| 327 | mvm->fw->ucode_capa.max_probe_length)); | 341 | mvm->fw->ucode_capa.max_probe_length)); |
| 328 | 342 | ||
| 329 | iwl_mvm_scan_fill_channels(cmd, req); | 343 | iwl_mvm_scan_fill_channels(cmd, req, basic_ssid); |
| 330 | 344 | ||
| 331 | cmd->len = cpu_to_le16(sizeof(struct iwl_scan_cmd) + | 345 | cmd->len = cpu_to_le16(sizeof(struct iwl_scan_cmd) + |
| 332 | le16_to_cpu(cmd->tx_cmd.len) + | 346 | le16_to_cpu(cmd->tx_cmd.len) + |
| @@ -377,6 +391,21 @@ int iwl_mvm_rx_scan_complete(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
| 377 | return 0; | 391 | return 0; |
| 378 | } | 392 | } |
| 379 | 393 | ||
| 394 | int iwl_mvm_rx_sched_scan_results(struct iwl_mvm *mvm, | ||
| 395 | struct iwl_rx_cmd_buffer *rxb, | ||
| 396 | struct iwl_device_cmd *cmd) | ||
| 397 | { | ||
| 398 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
| 399 | struct iwl_sched_scan_results *notif = (void *)pkt->data; | ||
| 400 | |||
| 401 | if (notif->client_bitmap & SCAN_CLIENT_SCHED_SCAN) { | ||
| 402 | IWL_DEBUG_SCAN(mvm, "Scheduled scan results\n"); | ||
| 403 | ieee80211_sched_scan_results(mvm->hw); | ||
| 404 | } | ||
| 405 | |||
| 406 | return 0; | ||
| 407 | } | ||
| 408 | |||
| 380 | static bool iwl_mvm_scan_abort_notif(struct iwl_notif_wait_data *notif_wait, | 409 | static bool iwl_mvm_scan_abort_notif(struct iwl_notif_wait_data *notif_wait, |
| 381 | struct iwl_rx_packet *pkt, void *data) | 410 | struct iwl_rx_packet *pkt, void *data) |
| 382 | { | 411 | { |
| @@ -447,3 +476,406 @@ void iwl_mvm_cancel_scan(struct iwl_mvm *mvm) | |||
| 447 | out_remove_notif: | 476 | out_remove_notif: |
| 448 | iwl_remove_notification(&mvm->notif_wait, &wait_scan_abort); | 477 | iwl_remove_notification(&mvm->notif_wait, &wait_scan_abort); |
| 449 | } | 478 | } |
| 479 | |||
| 480 | int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, | ||
| 481 | struct iwl_rx_cmd_buffer *rxb, | ||
| 482 | struct iwl_device_cmd *cmd) | ||
| 483 | { | ||
| 484 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
| 485 | struct iwl_scan_offload_complete *scan_notif = (void *)pkt->data; | ||
| 486 | |||
| 487 | IWL_DEBUG_SCAN(mvm, "Scheduled scan completed, status %s\n", | ||
| 488 | scan_notif->status == IWL_SCAN_OFFLOAD_COMPLETED ? | ||
| 489 | "completed" : "aborted"); | ||
| 490 | |||
| 491 | mvm->scan_status = IWL_MVM_SCAN_NONE; | ||
| 492 | ieee80211_sched_scan_stopped(mvm->hw); | ||
| 493 | |||
| 494 | return 0; | ||
| 495 | } | ||
| 496 | |||
| 497 | static void iwl_scan_offload_build_tx_cmd(struct iwl_mvm *mvm, | ||
| 498 | struct ieee80211_vif *vif, | ||
| 499 | struct ieee80211_sched_scan_ies *ies, | ||
| 500 | enum ieee80211_band band, | ||
| 501 | struct iwl_tx_cmd *cmd, | ||
| 502 | u8 *data) | ||
| 503 | { | ||
| 504 | u16 cmd_len; | ||
| 505 | |||
| 506 | cmd->tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL); | ||
| 507 | cmd->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE); | ||
| 508 | cmd->sta_id = mvm->aux_sta.sta_id; | ||
| 509 | |||
| 510 | cmd->rate_n_flags = iwl_mvm_scan_rate_n_flags(mvm, band, false); | ||
| 511 | |||
| 512 | cmd_len = iwl_mvm_fill_probe_req((struct ieee80211_mgmt *)data, | ||
| 513 | vif->addr, | ||
| 514 | 1, NULL, 0, | ||
| 515 | ies->ie[band], ies->len[band], | ||
| 516 | SCAN_OFFLOAD_PROBE_REQ_SIZE); | ||
| 517 | cmd->len = cpu_to_le16(cmd_len); | ||
| 518 | } | ||
| 519 | |||
| 520 | static void iwl_build_scan_cmd(struct iwl_mvm *mvm, | ||
| 521 | struct ieee80211_vif *vif, | ||
| 522 | struct cfg80211_sched_scan_request *req, | ||
| 523 | struct iwl_scan_offload_cmd *scan) | ||
| 524 | { | ||
| 525 | scan->channel_count = | ||
| 526 | mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels + | ||
| 527 | mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels; | ||
| 528 | scan->quiet_time = cpu_to_le16(IWL_ACTIVE_QUIET_TIME); | ||
| 529 | scan->quiet_plcp_th = cpu_to_le16(IWL_PLCP_QUIET_THRESH); | ||
| 530 | scan->good_CRC_th = IWL_GOOD_CRC_TH_DEFAULT; | ||
| 531 | scan->rx_chain = iwl_mvm_scan_rx_chain(mvm); | ||
| 532 | scan->max_out_time = cpu_to_le32(200 * 1024); | ||
| 533 | scan->suspend_time = iwl_mvm_scan_suspend_time(vif); | ||
| 534 | scan->filter_flags |= cpu_to_le32(MAC_FILTER_ACCEPT_GRP | | ||
| 535 | MAC_FILTER_IN_BEACON); | ||
| 536 | scan->scan_type = cpu_to_le32(SCAN_TYPE_BACKGROUND); | ||
| 537 | scan->rep_count = cpu_to_le32(1); | ||
| 538 | } | ||
| 539 | |||
| 540 | static int iwl_ssid_exist(u8 *ssid, u8 ssid_len, struct iwl_ssid_ie *ssid_list) | ||
| 541 | { | ||
| 542 | int i; | ||
| 543 | |||
| 544 | for (i = 0; i < PROBE_OPTION_MAX; i++) { | ||
| 545 | if (!ssid_list[i].len) | ||
| 546 | break; | ||
| 547 | if (ssid_list[i].len == ssid_len && | ||
| 548 | !memcmp(ssid_list->ssid, ssid, ssid_len)) | ||
| 549 | return i; | ||
| 550 | } | ||
| 551 | return -1; | ||
| 552 | } | ||
| 553 | |||
| 554 | static void iwl_scan_offload_build_ssid(struct cfg80211_sched_scan_request *req, | ||
| 555 | struct iwl_scan_offload_cmd *scan, | ||
| 556 | u32 *ssid_bitmap) | ||
| 557 | { | ||
| 558 | int i, j; | ||
| 559 | int index; | ||
| 560 | |||
| 561 | /* | ||
| 562 | * copy SSIDs from match list. | ||
| 563 | * iwl_config_sched_scan_profiles() uses the order of these ssids to | ||
| 564 | * config match list. | ||
| 565 | */ | ||
| 566 | for (i = 0; i < req->n_match_sets && i < PROBE_OPTION_MAX; i++) { | ||
| 567 | scan->direct_scan[i].id = WLAN_EID_SSID; | ||
| 568 | scan->direct_scan[i].len = req->match_sets[i].ssid.ssid_len; | ||
| 569 | memcpy(scan->direct_scan[i].ssid, req->match_sets[i].ssid.ssid, | ||
| 570 | scan->direct_scan[i].len); | ||
| 571 | } | ||
| 572 | |||
| 573 | /* add SSIDs from scan SSID list */ | ||
| 574 | *ssid_bitmap = 0; | ||
| 575 | for (j = 0; j < req->n_ssids && i < PROBE_OPTION_MAX; j++) { | ||
| 576 | index = iwl_ssid_exist(req->ssids[j].ssid, | ||
| 577 | req->ssids[j].ssid_len, | ||
| 578 | scan->direct_scan); | ||
| 579 | if (index < 0) { | ||
| 580 | if (!req->ssids[j].ssid_len) | ||
| 581 | continue; | ||
| 582 | scan->direct_scan[i].id = WLAN_EID_SSID; | ||
| 583 | scan->direct_scan[i].len = req->ssids[j].ssid_len; | ||
| 584 | memcpy(scan->direct_scan[i].ssid, req->ssids[j].ssid, | ||
| 585 | scan->direct_scan[i].len); | ||
| 586 | *ssid_bitmap |= BIT(i + 1); | ||
| 587 | i++; | ||
| 588 | } else { | ||
| 589 | *ssid_bitmap |= BIT(index + 1); | ||
| 590 | } | ||
| 591 | } | ||
| 592 | } | ||
| 593 | |||
| 594 | static void iwl_build_channel_cfg(struct iwl_mvm *mvm, | ||
| 595 | struct cfg80211_sched_scan_request *req, | ||
| 596 | struct iwl_scan_channel_cfg *channels, | ||
| 597 | enum ieee80211_band band, | ||
| 598 | int *head, int *tail, | ||
| 599 | u32 ssid_bitmap) | ||
| 600 | { | ||
| 601 | struct ieee80211_supported_band *s_band; | ||
| 602 | int n_probes = req->n_ssids; | ||
| 603 | int n_channels = req->n_channels; | ||
| 604 | u8 active_dwell, passive_dwell; | ||
| 605 | int i, j, index = 0; | ||
| 606 | bool partial; | ||
| 607 | |||
| 608 | /* | ||
| 609 | * We have to configure all supported channels, even if we don't want to | ||
| 610 | * scan on them, but we have to send channels in the order that we want | ||
| 611 | * to scan. So add requested channels to head of the list and others to | ||
| 612 | * the end. | ||
| 613 | */ | ||
| 614 | active_dwell = iwl_mvm_get_active_dwell(band, n_probes); | ||
| 615 | passive_dwell = iwl_mvm_get_passive_dwell(band); | ||
| 616 | s_band = &mvm->nvm_data->bands[band]; | ||
| 617 | |||
| 618 | for (i = 0; i < s_band->n_channels && *head <= *tail; i++) { | ||
| 619 | partial = false; | ||
| 620 | for (j = 0; j < n_channels; j++) | ||
| 621 | if (s_band->channels[i].center_freq == | ||
| 622 | req->channels[j]->center_freq) { | ||
| 623 | index = *head; | ||
| 624 | (*head)++; | ||
| 625 | /* | ||
| 626 | * Channels that came with the request will be | ||
| 627 | * in partial scan . | ||
| 628 | */ | ||
| 629 | partial = true; | ||
| 630 | break; | ||
| 631 | } | ||
| 632 | if (!partial) { | ||
| 633 | index = *tail; | ||
| 634 | (*tail)--; | ||
| 635 | } | ||
| 636 | channels->channel_number[index] = | ||
| 637 | cpu_to_le16(ieee80211_frequency_to_channel( | ||
| 638 | s_band->channels[i].center_freq)); | ||
| 639 | channels->dwell_time[index][0] = active_dwell; | ||
| 640 | channels->dwell_time[index][1] = passive_dwell; | ||
| 641 | |||
| 642 | channels->iter_count[index] = cpu_to_le16(1); | ||
| 643 | channels->iter_interval[index] = 0; | ||
| 644 | |||
| 645 | if (!(s_band->channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN)) | ||
| 646 | channels->type[index] |= | ||
| 647 | cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_ACTIVE); | ||
| 648 | |||
| 649 | channels->type[index] |= | ||
| 650 | cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_FULL); | ||
| 651 | if (partial) | ||
| 652 | channels->type[index] |= | ||
| 653 | cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_PARTIAL); | ||
| 654 | |||
| 655 | if (s_band->channels[i].flags & IEEE80211_CHAN_NO_HT40) | ||
| 656 | channels->type[index] |= | ||
| 657 | cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_NARROW); | ||
| 658 | |||
| 659 | /* scan for all SSIDs from req->ssids */ | ||
| 660 | channels->type[index] |= cpu_to_le32(ssid_bitmap); | ||
| 661 | } | ||
| 662 | } | ||
| 663 | |||
| 664 | int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm, | ||
| 665 | struct ieee80211_vif *vif, | ||
| 666 | struct cfg80211_sched_scan_request *req, | ||
| 667 | struct ieee80211_sched_scan_ies *ies) | ||
| 668 | { | ||
| 669 | int supported_bands = 0; | ||
| 670 | int band_2ghz = mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels; | ||
| 671 | int band_5ghz = mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels; | ||
| 672 | int head = 0; | ||
| 673 | int tail = band_2ghz + band_5ghz; | ||
| 674 | u32 ssid_bitmap; | ||
| 675 | int cmd_len; | ||
| 676 | int ret; | ||
| 677 | |||
| 678 | struct iwl_scan_offload_cfg *scan_cfg; | ||
| 679 | struct iwl_host_cmd cmd = { | ||
| 680 | .id = SCAN_OFFLOAD_CONFIG_CMD, | ||
| 681 | .flags = CMD_SYNC, | ||
| 682 | }; | ||
| 683 | |||
| 684 | lockdep_assert_held(&mvm->mutex); | ||
| 685 | |||
| 686 | if (band_2ghz) | ||
| 687 | supported_bands++; | ||
| 688 | if (band_5ghz) | ||
| 689 | supported_bands++; | ||
| 690 | |||
| 691 | cmd_len = sizeof(struct iwl_scan_offload_cfg) + | ||
| 692 | supported_bands * SCAN_OFFLOAD_PROBE_REQ_SIZE; | ||
| 693 | |||
| 694 | scan_cfg = kzalloc(cmd_len, GFP_KERNEL); | ||
| 695 | if (!scan_cfg) | ||
| 696 | return -ENOMEM; | ||
| 697 | |||
| 698 | iwl_build_scan_cmd(mvm, vif, req, &scan_cfg->scan_cmd); | ||
| 699 | scan_cfg->scan_cmd.len = cpu_to_le16(cmd_len); | ||
| 700 | |||
| 701 | iwl_scan_offload_build_ssid(req, &scan_cfg->scan_cmd, &ssid_bitmap); | ||
| 702 | /* build tx frames for supported bands */ | ||
| 703 | if (band_2ghz) { | ||
| 704 | iwl_scan_offload_build_tx_cmd(mvm, vif, ies, | ||
| 705 | IEEE80211_BAND_2GHZ, | ||
| 706 | &scan_cfg->scan_cmd.tx_cmd[0], | ||
| 707 | scan_cfg->data); | ||
| 708 | iwl_build_channel_cfg(mvm, req, &scan_cfg->channel_cfg, | ||
| 709 | IEEE80211_BAND_2GHZ, &head, &tail, | ||
| 710 | ssid_bitmap); | ||
| 711 | } | ||
| 712 | if (band_5ghz) { | ||
| 713 | iwl_scan_offload_build_tx_cmd(mvm, vif, ies, | ||
| 714 | IEEE80211_BAND_5GHZ, | ||
| 715 | &scan_cfg->scan_cmd.tx_cmd[1], | ||
| 716 | scan_cfg->data + | ||
| 717 | SCAN_OFFLOAD_PROBE_REQ_SIZE); | ||
| 718 | iwl_build_channel_cfg(mvm, req, &scan_cfg->channel_cfg, | ||
| 719 | IEEE80211_BAND_5GHZ, &head, &tail, | ||
| 720 | ssid_bitmap); | ||
| 721 | } | ||
| 722 | |||
| 723 | cmd.data[0] = scan_cfg; | ||
| 724 | cmd.len[0] = cmd_len; | ||
| 725 | cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; | ||
| 726 | |||
| 727 | IWL_DEBUG_SCAN(mvm, "Sending scheduled scan config\n"); | ||
| 728 | |||
| 729 | ret = iwl_mvm_send_cmd(mvm, &cmd); | ||
| 730 | kfree(scan_cfg); | ||
| 731 | return ret; | ||
| 732 | } | ||
| 733 | |||
| 734 | int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm, | ||
| 735 | struct cfg80211_sched_scan_request *req) | ||
| 736 | { | ||
| 737 | struct iwl_scan_offload_profile *profile; | ||
| 738 | struct iwl_scan_offload_profile_cfg *profile_cfg; | ||
| 739 | struct iwl_scan_offload_blacklist *blacklist; | ||
| 740 | struct iwl_host_cmd cmd = { | ||
| 741 | .id = SCAN_OFFLOAD_UPDATE_PROFILES_CMD, | ||
| 742 | .flags = CMD_SYNC, | ||
| 743 | .len[1] = sizeof(*profile_cfg), | ||
| 744 | .dataflags[0] = IWL_HCMD_DFL_NOCOPY, | ||
| 745 | .dataflags[1] = IWL_HCMD_DFL_NOCOPY, | ||
| 746 | }; | ||
| 747 | int blacklist_len; | ||
| 748 | int i; | ||
| 749 | int ret; | ||
| 750 | |||
| 751 | if (WARN_ON(req->n_match_sets > IWL_SCAN_MAX_PROFILES)) | ||
| 752 | return -EIO; | ||
| 753 | |||
| 754 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SHORT_BL) | ||
| 755 | blacklist_len = IWL_SCAN_SHORT_BLACKLIST_LEN; | ||
| 756 | else | ||
| 757 | blacklist_len = IWL_SCAN_MAX_BLACKLIST_LEN; | ||
| 758 | |||
| 759 | blacklist = kzalloc(sizeof(*blacklist) * blacklist_len, GFP_KERNEL); | ||
| 760 | if (!blacklist) | ||
| 761 | return -ENOMEM; | ||
| 762 | |||
| 763 | profile_cfg = kzalloc(sizeof(*profile_cfg), GFP_KERNEL); | ||
| 764 | if (!profile_cfg) { | ||
| 765 | ret = -ENOMEM; | ||
| 766 | goto free_blacklist; | ||
| 767 | } | ||
| 768 | |||
| 769 | cmd.data[0] = blacklist; | ||
| 770 | cmd.len[0] = sizeof(*blacklist) * blacklist_len; | ||
| 771 | cmd.data[1] = profile_cfg; | ||
| 772 | |||
| 773 | /* No blacklist configuration */ | ||
| 774 | |||
| 775 | profile_cfg->num_profiles = req->n_match_sets; | ||
| 776 | profile_cfg->active_clients = SCAN_CLIENT_SCHED_SCAN; | ||
| 777 | profile_cfg->pass_match = SCAN_CLIENT_SCHED_SCAN; | ||
| 778 | profile_cfg->match_notify = SCAN_CLIENT_SCHED_SCAN; | ||
| 779 | |||
| 780 | for (i = 0; i < req->n_match_sets; i++) { | ||
| 781 | profile = &profile_cfg->profiles[i]; | ||
| 782 | profile->ssid_index = i; | ||
| 783 | /* Support any cipher and auth algorithm */ | ||
| 784 | profile->unicast_cipher = 0xff; | ||
| 785 | profile->auth_alg = 0xff; | ||
| 786 | profile->network_type = IWL_NETWORK_TYPE_ANY; | ||
| 787 | profile->band_selection = IWL_SCAN_OFFLOAD_SELECT_ANY; | ||
| 788 | profile->client_bitmap = SCAN_CLIENT_SCHED_SCAN; | ||
| 789 | } | ||
| 790 | |||
| 791 | IWL_DEBUG_SCAN(mvm, "Sending scheduled scan profile config\n"); | ||
| 792 | |||
| 793 | ret = iwl_mvm_send_cmd(mvm, &cmd); | ||
| 794 | kfree(profile_cfg); | ||
| 795 | free_blacklist: | ||
| 796 | kfree(blacklist); | ||
| 797 | |||
| 798 | return ret; | ||
| 799 | } | ||
| 800 | |||
| 801 | int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, | ||
| 802 | struct cfg80211_sched_scan_request *req) | ||
| 803 | { | ||
| 804 | struct iwl_scan_offload_req scan_req = { | ||
| 805 | .watchdog = IWL_SCHED_SCAN_WATCHDOG, | ||
| 806 | |||
| 807 | .schedule_line[0].iterations = IWL_FAST_SCHED_SCAN_ITERATIONS, | ||
| 808 | .schedule_line[0].delay = req->interval / 1000, | ||
| 809 | .schedule_line[0].full_scan_mul = 1, | ||
| 810 | |||
| 811 | .schedule_line[1].iterations = 0xff, | ||
| 812 | .schedule_line[1].delay = req->interval / 1000, | ||
| 813 | .schedule_line[1].full_scan_mul = IWL_FULL_SCAN_MULTIPLIER, | ||
| 814 | }; | ||
| 815 | |||
| 816 | if (req->n_match_sets && req->match_sets[0].ssid.ssid_len) { | ||
| 817 | IWL_DEBUG_SCAN(mvm, | ||
| 818 | "Sending scheduled scan with filtering, filter len %d\n", | ||
| 819 | req->n_match_sets); | ||
| 820 | scan_req.flags |= | ||
| 821 | cpu_to_le16(IWL_SCAN_OFFLOAD_FLAG_FILTER_SSID); | ||
| 822 | } else { | ||
| 823 | IWL_DEBUG_SCAN(mvm, | ||
| 824 | "Sending Scheduled scan without filtering\n"); | ||
| 825 | } | ||
| 826 | |||
| 827 | return iwl_mvm_send_cmd_pdu(mvm, SCAN_OFFLOAD_REQUEST_CMD, CMD_SYNC, | ||
| 828 | sizeof(scan_req), &scan_req); | ||
| 829 | } | ||
| 830 | |||
| 831 | static int iwl_mvm_send_sched_scan_abort(struct iwl_mvm *mvm) | ||
| 832 | { | ||
| 833 | int ret; | ||
| 834 | struct iwl_host_cmd cmd = { | ||
| 835 | .id = SCAN_OFFLOAD_ABORT_CMD, | ||
| 836 | .flags = CMD_SYNC, | ||
| 837 | }; | ||
| 838 | u32 status; | ||
| 839 | |||
| 840 | /* Exit instantly with error when device is not ready | ||
| 841 | * to receive scan abort command or it does not perform | ||
| 842 | * scheduled scan currently */ | ||
| 843 | if (mvm->scan_status != IWL_MVM_SCAN_SCHED) | ||
| 844 | return -EIO; | ||
| 845 | |||
| 846 | ret = iwl_mvm_send_cmd_status(mvm, &cmd, &status); | ||
| 847 | if (ret) | ||
| 848 | return ret; | ||
| 849 | |||
| 850 | if (status != CAN_ABORT_STATUS) { | ||
| 851 | /* | ||
| 852 | * The scan abort will return 1 for success or | ||
| 853 | * 2 for "failure". A failure condition can be | ||
| 854 | * due to simply not being in an active scan which | ||
| 855 | * can occur if we send the scan abort before the | ||
| 856 | * microcode has notified us that a scan is completed. | ||
| 857 | */ | ||
| 858 | IWL_DEBUG_SCAN(mvm, "SCAN OFFLOAD ABORT ret %d.\n", status); | ||
| 859 | ret = -EIO; | ||
| 860 | } | ||
| 861 | |||
| 862 | return ret; | ||
| 863 | } | ||
| 864 | |||
| 865 | void iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm) | ||
| 866 | { | ||
| 867 | int ret; | ||
| 868 | |||
| 869 | lockdep_assert_held(&mvm->mutex); | ||
| 870 | |||
| 871 | if (mvm->scan_status != IWL_MVM_SCAN_SCHED) { | ||
| 872 | IWL_DEBUG_SCAN(mvm, "No offloaded scan to stop\n"); | ||
| 873 | return; | ||
| 874 | } | ||
| 875 | |||
| 876 | ret = iwl_mvm_send_sched_scan_abort(mvm); | ||
| 877 | if (ret) | ||
| 878 | IWL_DEBUG_SCAN(mvm, "Send stop offload scan failed %d\n", ret); | ||
| 879 | else | ||
| 880 | IWL_DEBUG_SCAN(mvm, "Successfully sent stop offload scan\n"); | ||
| 881 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 44add291531b..329952363a54 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
| @@ -66,6 +66,115 @@ | |||
| 66 | #include "sta.h" | 66 | #include "sta.h" |
| 67 | #include "rs.h" | 67 | #include "rs.h" |
| 68 | 68 | ||
| 69 | static void iwl_mvm_add_sta_cmd_v6_to_v5(struct iwl_mvm_add_sta_cmd_v6 *cmd_v6, | ||
| 70 | struct iwl_mvm_add_sta_cmd_v5 *cmd_v5) | ||
| 71 | { | ||
| 72 | memset(cmd_v5, 0, sizeof(*cmd_v5)); | ||
| 73 | |||
| 74 | cmd_v5->add_modify = cmd_v6->add_modify; | ||
| 75 | cmd_v5->tid_disable_tx = cmd_v6->tid_disable_tx; | ||
| 76 | cmd_v5->mac_id_n_color = cmd_v6->mac_id_n_color; | ||
| 77 | memcpy(cmd_v5->addr, cmd_v6->addr, ETH_ALEN); | ||
| 78 | cmd_v5->sta_id = cmd_v6->sta_id; | ||
| 79 | cmd_v5->modify_mask = cmd_v6->modify_mask; | ||
| 80 | cmd_v5->station_flags = cmd_v6->station_flags; | ||
| 81 | cmd_v5->station_flags_msk = cmd_v6->station_flags_msk; | ||
| 82 | cmd_v5->add_immediate_ba_tid = cmd_v6->add_immediate_ba_tid; | ||
| 83 | cmd_v5->remove_immediate_ba_tid = cmd_v6->remove_immediate_ba_tid; | ||
| 84 | cmd_v5->add_immediate_ba_ssn = cmd_v6->add_immediate_ba_ssn; | ||
| 85 | cmd_v5->sleep_tx_count = cmd_v6->sleep_tx_count; | ||
| 86 | cmd_v5->sleep_state_flags = cmd_v6->sleep_state_flags; | ||
| 87 | cmd_v5->assoc_id = cmd_v6->assoc_id; | ||
| 88 | cmd_v5->beamform_flags = cmd_v6->beamform_flags; | ||
| 89 | cmd_v5->tfd_queue_msk = cmd_v6->tfd_queue_msk; | ||
| 90 | } | ||
| 91 | |||
| 92 | static void | ||
| 93 | iwl_mvm_add_sta_key_to_add_sta_cmd_v5(struct iwl_mvm_add_sta_key_cmd *key_cmd, | ||
| 94 | struct iwl_mvm_add_sta_cmd_v5 *sta_cmd, | ||
| 95 | u32 mac_id_n_color) | ||
| 96 | { | ||
| 97 | memset(sta_cmd, 0, sizeof(*sta_cmd)); | ||
| 98 | |||
| 99 | sta_cmd->sta_id = key_cmd->sta_id; | ||
| 100 | sta_cmd->add_modify = STA_MODE_MODIFY; | ||
| 101 | sta_cmd->modify_mask = STA_MODIFY_KEY; | ||
| 102 | sta_cmd->mac_id_n_color = cpu_to_le32(mac_id_n_color); | ||
| 103 | |||
| 104 | sta_cmd->key.key_offset = key_cmd->key_offset; | ||
| 105 | sta_cmd->key.key_flags = key_cmd->key_flags; | ||
| 106 | memcpy(sta_cmd->key.key, key_cmd->key, sizeof(sta_cmd->key.key)); | ||
| 107 | sta_cmd->key.tkip_rx_tsc_byte2 = key_cmd->tkip_rx_tsc_byte2; | ||
| 108 | memcpy(sta_cmd->key.tkip_rx_ttak, key_cmd->tkip_rx_ttak, | ||
| 109 | sizeof(sta_cmd->key.tkip_rx_ttak)); | ||
| 110 | } | ||
| 111 | |||
| 112 | static int iwl_mvm_send_add_sta_cmd_status(struct iwl_mvm *mvm, | ||
| 113 | struct iwl_mvm_add_sta_cmd_v6 *cmd, | ||
| 114 | int *status) | ||
| 115 | { | ||
| 116 | struct iwl_mvm_add_sta_cmd_v5 cmd_v5; | ||
| 117 | |||
| 118 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_STA_KEY_CMD) | ||
| 119 | return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(*cmd), | ||
| 120 | cmd, status); | ||
| 121 | |||
| 122 | iwl_mvm_add_sta_cmd_v6_to_v5(cmd, &cmd_v5); | ||
| 123 | |||
| 124 | return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd_v5), | ||
| 125 | &cmd_v5, status); | ||
| 126 | } | ||
| 127 | |||
| 128 | static int iwl_mvm_send_add_sta_cmd(struct iwl_mvm *mvm, u32 flags, | ||
| 129 | struct iwl_mvm_add_sta_cmd_v6 *cmd) | ||
| 130 | { | ||
| 131 | struct iwl_mvm_add_sta_cmd_v5 cmd_v5; | ||
| 132 | |||
| 133 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_STA_KEY_CMD) | ||
| 134 | return iwl_mvm_send_cmd_pdu(mvm, ADD_STA, flags, | ||
| 135 | sizeof(*cmd), cmd); | ||
| 136 | |||
| 137 | iwl_mvm_add_sta_cmd_v6_to_v5(cmd, &cmd_v5); | ||
| 138 | |||
| 139 | return iwl_mvm_send_cmd_pdu(mvm, ADD_STA, flags, sizeof(cmd_v5), | ||
| 140 | &cmd_v5); | ||
| 141 | } | ||
| 142 | |||
| 143 | static int | ||
| 144 | iwl_mvm_send_add_sta_key_cmd_status(struct iwl_mvm *mvm, | ||
| 145 | struct iwl_mvm_add_sta_key_cmd *cmd, | ||
| 146 | u32 mac_id_n_color, | ||
| 147 | int *status) | ||
| 148 | { | ||
| 149 | struct iwl_mvm_add_sta_cmd_v5 sta_cmd; | ||
| 150 | |||
| 151 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_STA_KEY_CMD) | ||
| 152 | return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, | ||
| 153 | sizeof(*cmd), cmd, status); | ||
| 154 | |||
| 155 | iwl_mvm_add_sta_key_to_add_sta_cmd_v5(cmd, &sta_cmd, mac_id_n_color); | ||
| 156 | |||
| 157 | return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(sta_cmd), | ||
| 158 | &sta_cmd, status); | ||
| 159 | } | ||
| 160 | |||
| 161 | static int iwl_mvm_send_add_sta_key_cmd(struct iwl_mvm *mvm, | ||
| 162 | u32 flags, | ||
| 163 | struct iwl_mvm_add_sta_key_cmd *cmd, | ||
| 164 | u32 mac_id_n_color) | ||
| 165 | { | ||
| 166 | struct iwl_mvm_add_sta_cmd_v5 sta_cmd; | ||
| 167 | |||
| 168 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_STA_KEY_CMD) | ||
| 169 | return iwl_mvm_send_cmd_pdu(mvm, ADD_STA_KEY, flags, | ||
| 170 | sizeof(*cmd), cmd); | ||
| 171 | |||
| 172 | iwl_mvm_add_sta_key_to_add_sta_cmd_v5(cmd, &sta_cmd, mac_id_n_color); | ||
| 173 | |||
| 174 | return iwl_mvm_send_cmd_pdu(mvm, ADD_STA, flags, sizeof(sta_cmd), | ||
| 175 | &sta_cmd); | ||
| 176 | } | ||
| 177 | |||
| 69 | static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm) | 178 | static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm) |
| 70 | { | 179 | { |
| 71 | int sta_id; | 180 | int sta_id; |
| @@ -87,7 +196,7 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 87 | bool update) | 196 | bool update) |
| 88 | { | 197 | { |
| 89 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; | 198 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; |
| 90 | struct iwl_mvm_add_sta_cmd add_sta_cmd; | 199 | struct iwl_mvm_add_sta_cmd_v6 add_sta_cmd; |
| 91 | int ret; | 200 | int ret; |
| 92 | u32 status; | 201 | u32 status; |
| 93 | u32 agg_size = 0, mpdu_dens = 0; | 202 | u32 agg_size = 0, mpdu_dens = 0; |
| @@ -175,8 +284,7 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 175 | cpu_to_le32(mpdu_dens << STA_FLG_AGG_MPDU_DENS_SHIFT); | 284 | cpu_to_le32(mpdu_dens << STA_FLG_AGG_MPDU_DENS_SHIFT); |
| 176 | 285 | ||
| 177 | status = ADD_STA_SUCCESS; | 286 | status = ADD_STA_SUCCESS; |
| 178 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(add_sta_cmd), | 287 | ret = iwl_mvm_send_add_sta_cmd_status(mvm, &add_sta_cmd, &status); |
| 179 | &add_sta_cmd, &status); | ||
| 180 | if (ret) | 288 | if (ret) |
| 181 | return ret; | 289 | return ret; |
| 182 | 290 | ||
| @@ -229,8 +337,12 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, | |||
| 229 | if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE) | 337 | if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE) |
| 230 | mvm_sta->tfd_queue_msk |= BIT(vif->hw_queue[i]); | 338 | mvm_sta->tfd_queue_msk |= BIT(vif->hw_queue[i]); |
| 231 | 339 | ||
| 232 | /* for HW restart - need to reset the seq_number etc... */ | 340 | /* for HW restart - reset everything but the sequence number */ |
| 233 | memset(mvm_sta->tid_data, 0, sizeof(mvm_sta->tid_data)); | 341 | for (i = 0; i < IWL_MAX_TID_COUNT; i++) { |
| 342 | u16 seq = mvm_sta->tid_data[i].seq_number; | ||
| 343 | memset(&mvm_sta->tid_data[i], 0, sizeof(mvm_sta->tid_data[i])); | ||
| 344 | mvm_sta->tid_data[i].seq_number = seq; | ||
| 345 | } | ||
| 234 | 346 | ||
| 235 | ret = iwl_mvm_sta_send_to_fw(mvm, sta, false); | 347 | ret = iwl_mvm_sta_send_to_fw(mvm, sta, false); |
| 236 | if (ret) | 348 | if (ret) |
| @@ -256,7 +368,7 @@ int iwl_mvm_update_sta(struct iwl_mvm *mvm, | |||
| 256 | int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, | 368 | int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, |
| 257 | bool drain) | 369 | bool drain) |
| 258 | { | 370 | { |
| 259 | struct iwl_mvm_add_sta_cmd cmd = {}; | 371 | struct iwl_mvm_add_sta_cmd_v6 cmd = {}; |
| 260 | int ret; | 372 | int ret; |
| 261 | u32 status; | 373 | u32 status; |
| 262 | 374 | ||
| @@ -269,8 +381,7 @@ int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, | |||
| 269 | cmd.station_flags_msk = cpu_to_le32(STA_FLG_DRAIN_FLOW); | 381 | cmd.station_flags_msk = cpu_to_le32(STA_FLG_DRAIN_FLOW); |
| 270 | 382 | ||
| 271 | status = ADD_STA_SUCCESS; | 383 | status = ADD_STA_SUCCESS; |
| 272 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd), | 384 | ret = iwl_mvm_send_add_sta_cmd_status(mvm, &cmd, &status); |
| 273 | &cmd, &status); | ||
| 274 | if (ret) | 385 | if (ret) |
| 275 | return ret; | 386 | return ret; |
| 276 | 387 | ||
| @@ -469,13 +580,13 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm, | |||
| 469 | const u8 *addr, | 580 | const u8 *addr, |
| 470 | u16 mac_id, u16 color) | 581 | u16 mac_id, u16 color) |
| 471 | { | 582 | { |
| 472 | struct iwl_mvm_add_sta_cmd cmd; | 583 | struct iwl_mvm_add_sta_cmd_v6 cmd; |
| 473 | int ret; | 584 | int ret; |
| 474 | u32 status; | 585 | u32 status; |
| 475 | 586 | ||
| 476 | lockdep_assert_held(&mvm->mutex); | 587 | lockdep_assert_held(&mvm->mutex); |
| 477 | 588 | ||
| 478 | memset(&cmd, 0, sizeof(struct iwl_mvm_add_sta_cmd)); | 589 | memset(&cmd, 0, sizeof(struct iwl_mvm_add_sta_cmd_v6)); |
| 479 | cmd.sta_id = sta->sta_id; | 590 | cmd.sta_id = sta->sta_id; |
| 480 | cmd.mac_id_n_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mac_id, | 591 | cmd.mac_id_n_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mac_id, |
| 481 | color)); | 592 | color)); |
| @@ -485,8 +596,7 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm, | |||
| 485 | if (addr) | 596 | if (addr) |
| 486 | memcpy(cmd.addr, addr, ETH_ALEN); | 597 | memcpy(cmd.addr, addr, ETH_ALEN); |
| 487 | 598 | ||
| 488 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd), | 599 | ret = iwl_mvm_send_add_sta_cmd_status(mvm, &cmd, &status); |
| 489 | &cmd, &status); | ||
| 490 | if (ret) | 600 | if (ret) |
| 491 | return ret; | 601 | return ret; |
| 492 | 602 | ||
| @@ -534,10 +644,14 @@ int iwl_mvm_send_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 534 | struct iwl_mvm_int_sta *bsta) | 644 | struct iwl_mvm_int_sta *bsta) |
| 535 | { | 645 | { |
| 536 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 646 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
| 537 | static const u8 baddr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; | 647 | static const u8 _baddr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; |
| 648 | static const u8 *baddr = _baddr; | ||
| 538 | 649 | ||
| 539 | lockdep_assert_held(&mvm->mutex); | 650 | lockdep_assert_held(&mvm->mutex); |
| 540 | 651 | ||
| 652 | if (vif->type == NL80211_IFTYPE_ADHOC) | ||
| 653 | baddr = vif->bss_conf.bssid; | ||
| 654 | |||
| 541 | if (WARN_ON_ONCE(bsta->sta_id == IWL_MVM_STATION_COUNT)) | 655 | if (WARN_ON_ONCE(bsta->sta_id == IWL_MVM_STATION_COUNT)) |
| 542 | return -ENOSPC; | 656 | return -ENOSPC; |
| 543 | 657 | ||
| @@ -614,7 +728,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 614 | int tid, u16 ssn, bool start) | 728 | int tid, u16 ssn, bool start) |
| 615 | { | 729 | { |
| 616 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; | 730 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; |
| 617 | struct iwl_mvm_add_sta_cmd cmd = {}; | 731 | struct iwl_mvm_add_sta_cmd_v6 cmd = {}; |
| 618 | int ret; | 732 | int ret; |
| 619 | u32 status; | 733 | u32 status; |
| 620 | 734 | ||
| @@ -638,8 +752,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 638 | STA_MODIFY_REMOVE_BA_TID; | 752 | STA_MODIFY_REMOVE_BA_TID; |
| 639 | 753 | ||
| 640 | status = ADD_STA_SUCCESS; | 754 | status = ADD_STA_SUCCESS; |
| 641 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd), | 755 | ret = iwl_mvm_send_add_sta_cmd_status(mvm, &cmd, &status); |
| 642 | &cmd, &status); | ||
| 643 | if (ret) | 756 | if (ret) |
| 644 | return ret; | 757 | return ret; |
| 645 | 758 | ||
| @@ -674,7 +787,7 @@ static int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 674 | int tid, u8 queue, bool start) | 787 | int tid, u8 queue, bool start) |
| 675 | { | 788 | { |
| 676 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; | 789 | struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; |
| 677 | struct iwl_mvm_add_sta_cmd cmd = {}; | 790 | struct iwl_mvm_add_sta_cmd_v6 cmd = {}; |
| 678 | int ret; | 791 | int ret; |
| 679 | u32 status; | 792 | u32 status; |
| 680 | 793 | ||
| @@ -696,8 +809,7 @@ static int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
| 696 | cmd.tid_disable_tx = cpu_to_le16(mvm_sta->tid_disable_agg); | 809 | cmd.tid_disable_tx = cpu_to_le16(mvm_sta->tid_disable_agg); |
| 697 | 810 | ||
| 698 | status = ADD_STA_SUCCESS; | 811 | status = ADD_STA_SUCCESS; |
| 699 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd), | 812 | ret = iwl_mvm_send_add_sta_cmd_status(mvm, &cmd, &status); |
| 700 | &cmd, &status); | ||
| 701 | if (ret) | 813 | if (ret) |
| 702 | return ret; | 814 | return ret; |
| 703 | 815 | ||
| @@ -743,13 +855,13 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
| 743 | 855 | ||
| 744 | lockdep_assert_held(&mvm->mutex); | 856 | lockdep_assert_held(&mvm->mutex); |
| 745 | 857 | ||
| 746 | for (txq_id = IWL_MVM_FIRST_AGG_QUEUE; | 858 | for (txq_id = mvm->first_agg_queue; |
| 747 | txq_id <= IWL_MVM_LAST_AGG_QUEUE; txq_id++) | 859 | txq_id <= mvm->last_agg_queue; txq_id++) |
| 748 | if (mvm->queue_to_mac80211[txq_id] == | 860 | if (mvm->queue_to_mac80211[txq_id] == |
| 749 | IWL_INVALID_MAC80211_QUEUE) | 861 | IWL_INVALID_MAC80211_QUEUE) |
| 750 | break; | 862 | break; |
| 751 | 863 | ||
| 752 | if (txq_id > IWL_MVM_LAST_AGG_QUEUE) { | 864 | if (txq_id > mvm->last_agg_queue) { |
| 753 | IWL_ERR(mvm, "Failed to allocate agg queue\n"); | 865 | IWL_ERR(mvm, "Failed to allocate agg queue\n"); |
| 754 | return -EIO; | 866 | return -EIO; |
| 755 | } | 867 | } |
| @@ -987,10 +1099,11 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, | |||
| 987 | u32 cmd_flags) | 1099 | u32 cmd_flags) |
| 988 | { | 1100 | { |
| 989 | __le16 key_flags; | 1101 | __le16 key_flags; |
| 990 | struct iwl_mvm_add_sta_cmd cmd = {}; | 1102 | struct iwl_mvm_add_sta_key_cmd cmd = {}; |
| 991 | int ret, status; | 1103 | int ret, status; |
| 992 | u16 keyidx; | 1104 | u16 keyidx; |
| 993 | int i; | 1105 | int i; |
| 1106 | u32 mac_id_n_color = mvm_sta->mac_id_n_color; | ||
| 994 | 1107 | ||
| 995 | keyidx = (keyconf->keyidx << STA_KEY_FLG_KEYID_POS) & | 1108 | keyidx = (keyconf->keyidx << STA_KEY_FLG_KEYID_POS) & |
| 996 | STA_KEY_FLG_KEYID_MSK; | 1109 | STA_KEY_FLG_KEYID_MSK; |
| @@ -1000,14 +1113,14 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, | |||
| 1000 | switch (keyconf->cipher) { | 1113 | switch (keyconf->cipher) { |
| 1001 | case WLAN_CIPHER_SUITE_TKIP: | 1114 | case WLAN_CIPHER_SUITE_TKIP: |
| 1002 | key_flags |= cpu_to_le16(STA_KEY_FLG_TKIP); | 1115 | key_flags |= cpu_to_le16(STA_KEY_FLG_TKIP); |
| 1003 | cmd.key.tkip_rx_tsc_byte2 = tkip_iv32; | 1116 | cmd.tkip_rx_tsc_byte2 = tkip_iv32; |
| 1004 | for (i = 0; i < 5; i++) | 1117 | for (i = 0; i < 5; i++) |
| 1005 | cmd.key.tkip_rx_ttak[i] = cpu_to_le16(tkip_p1k[i]); | 1118 | cmd.tkip_rx_ttak[i] = cpu_to_le16(tkip_p1k[i]); |
| 1006 | memcpy(cmd.key.key, keyconf->key, keyconf->keylen); | 1119 | memcpy(cmd.key, keyconf->key, keyconf->keylen); |
| 1007 | break; | 1120 | break; |
| 1008 | case WLAN_CIPHER_SUITE_CCMP: | 1121 | case WLAN_CIPHER_SUITE_CCMP: |
| 1009 | key_flags |= cpu_to_le16(STA_KEY_FLG_CCM); | 1122 | key_flags |= cpu_to_le16(STA_KEY_FLG_CCM); |
| 1010 | memcpy(cmd.key.key, keyconf->key, keyconf->keylen); | 1123 | memcpy(cmd.key, keyconf->key, keyconf->keylen); |
| 1011 | break; | 1124 | break; |
| 1012 | default: | 1125 | default: |
| 1013 | WARN_ON(1); | 1126 | WARN_ON(1); |
| @@ -1017,20 +1130,18 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, | |||
| 1017 | if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) | 1130 | if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) |
| 1018 | key_flags |= cpu_to_le16(STA_KEY_MULTICAST); | 1131 | key_flags |= cpu_to_le16(STA_KEY_MULTICAST); |
| 1019 | 1132 | ||
| 1020 | cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color); | 1133 | cmd.key_offset = keyconf->hw_key_idx; |
| 1021 | cmd.key.key_offset = keyconf->hw_key_idx; | 1134 | cmd.key_flags = key_flags; |
| 1022 | cmd.key.key_flags = key_flags; | ||
| 1023 | cmd.add_modify = STA_MODE_MODIFY; | ||
| 1024 | cmd.modify_mask = STA_MODIFY_KEY; | ||
| 1025 | cmd.sta_id = sta_id; | 1135 | cmd.sta_id = sta_id; |
| 1026 | 1136 | ||
| 1027 | status = ADD_STA_SUCCESS; | 1137 | status = ADD_STA_SUCCESS; |
| 1028 | if (cmd_flags == CMD_SYNC) | 1138 | if (cmd_flags == CMD_SYNC) |
| 1029 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd), | 1139 | ret = iwl_mvm_send_add_sta_key_cmd_status(mvm, &cmd, |
| 1030 | &cmd, &status); | 1140 | mac_id_n_color, |
| 1141 | &status); | ||
| 1031 | else | 1142 | else |
| 1032 | ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, | 1143 | ret = iwl_mvm_send_add_sta_key_cmd(mvm, CMD_ASYNC, &cmd, |
| 1033 | sizeof(cmd), &cmd); | 1144 | mac_id_n_color); |
| 1034 | 1145 | ||
| 1035 | switch (status) { | 1146 | switch (status) { |
| 1036 | case ADD_STA_SUCCESS: | 1147 | case ADD_STA_SUCCESS: |
| @@ -1197,7 +1308,7 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, | |||
| 1197 | struct ieee80211_key_conf *keyconf) | 1308 | struct ieee80211_key_conf *keyconf) |
| 1198 | { | 1309 | { |
| 1199 | struct iwl_mvm_sta *mvm_sta; | 1310 | struct iwl_mvm_sta *mvm_sta; |
| 1200 | struct iwl_mvm_add_sta_cmd cmd = {}; | 1311 | struct iwl_mvm_add_sta_key_cmd cmd = {}; |
| 1201 | __le16 key_flags; | 1312 | __le16 key_flags; |
| 1202 | int ret, status; | 1313 | int ret, status; |
| 1203 | u8 sta_id; | 1314 | u8 sta_id; |
| @@ -1252,17 +1363,14 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, | |||
| 1252 | if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) | 1363 | if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) |
| 1253 | key_flags |= cpu_to_le16(STA_KEY_MULTICAST); | 1364 | key_flags |= cpu_to_le16(STA_KEY_MULTICAST); |
| 1254 | 1365 | ||
| 1255 | cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color); | 1366 | cmd.key_flags = key_flags; |
| 1256 | cmd.key.key_flags = key_flags; | 1367 | cmd.key_offset = keyconf->hw_key_idx; |
| 1257 | cmd.key.key_offset = keyconf->hw_key_idx; | ||
| 1258 | cmd.sta_id = sta_id; | 1368 | cmd.sta_id = sta_id; |
| 1259 | 1369 | ||
| 1260 | cmd.modify_mask = STA_MODIFY_KEY; | ||
| 1261 | cmd.add_modify = STA_MODE_MODIFY; | ||
| 1262 | |||
| 1263 | status = ADD_STA_SUCCESS; | 1370 | status = ADD_STA_SUCCESS; |
| 1264 | ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd), | 1371 | ret = iwl_mvm_send_add_sta_key_cmd_status(mvm, &cmd, |
| 1265 | &cmd, &status); | 1372 | mvm_sta->mac_id_n_color, |
| 1373 | &status); | ||
| 1266 | 1374 | ||
| 1267 | switch (status) { | 1375 | switch (status) { |
| 1268 | case ADD_STA_SUCCESS: | 1376 | case ADD_STA_SUCCESS: |
| @@ -1309,7 +1417,7 @@ void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm, | |||
| 1309 | struct ieee80211_sta *sta) | 1417 | struct ieee80211_sta *sta) |
| 1310 | { | 1418 | { |
| 1311 | struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; | 1419 | struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; |
| 1312 | struct iwl_mvm_add_sta_cmd cmd = { | 1420 | struct iwl_mvm_add_sta_cmd_v6 cmd = { |
| 1313 | .add_modify = STA_MODE_MODIFY, | 1421 | .add_modify = STA_MODE_MODIFY, |
| 1314 | .sta_id = mvmsta->sta_id, | 1422 | .sta_id = mvmsta->sta_id, |
| 1315 | .station_flags_msk = cpu_to_le32(STA_FLG_PS), | 1423 | .station_flags_msk = cpu_to_le32(STA_FLG_PS), |
| @@ -1317,7 +1425,7 @@ void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm, | |||
| 1317 | }; | 1425 | }; |
| 1318 | int ret; | 1426 | int ret; |
| 1319 | 1427 | ||
| 1320 | ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd); | 1428 | ret = iwl_mvm_send_add_sta_cmd(mvm, CMD_ASYNC, &cmd); |
| 1321 | if (ret) | 1429 | if (ret) |
| 1322 | IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); | 1430 | IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); |
| 1323 | } | 1431 | } |
| @@ -1331,7 +1439,7 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm, | |||
| 1331 | (reason == IEEE80211_FRAME_RELEASE_UAPSD) ? | 1439 | (reason == IEEE80211_FRAME_RELEASE_UAPSD) ? |
| 1332 | STA_SLEEP_STATE_UAPSD : STA_SLEEP_STATE_PS_POLL; | 1440 | STA_SLEEP_STATE_UAPSD : STA_SLEEP_STATE_PS_POLL; |
| 1333 | struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; | 1441 | struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; |
| 1334 | struct iwl_mvm_add_sta_cmd cmd = { | 1442 | struct iwl_mvm_add_sta_cmd_v6 cmd = { |
| 1335 | .add_modify = STA_MODE_MODIFY, | 1443 | .add_modify = STA_MODE_MODIFY, |
| 1336 | .sta_id = mvmsta->sta_id, | 1444 | .sta_id = mvmsta->sta_id, |
| 1337 | .modify_mask = STA_MODIFY_SLEEPING_STA_TX_COUNT, | 1445 | .modify_mask = STA_MODIFY_SLEEPING_STA_TX_COUNT, |
| @@ -1346,7 +1454,7 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm, | |||
| 1346 | int ret; | 1454 | int ret; |
| 1347 | 1455 | ||
| 1348 | /* TODO: somehow the fw doesn't seem to take PS_POLL into account */ | 1456 | /* TODO: somehow the fw doesn't seem to take PS_POLL into account */ |
| 1349 | ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd); | 1457 | ret = iwl_mvm_send_add_sta_cmd(mvm, CMD_ASYNC, &cmd); |
| 1350 | if (ret) | 1458 | if (ret) |
| 1351 | IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); | 1459 | IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); |
| 1352 | } | 1460 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h index 94b265eb32b8..4dfc359a4bdd 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/iwlwifi/mvm/sta.h | |||
| @@ -293,10 +293,6 @@ struct iwl_mvm_sta { | |||
| 293 | struct iwl_lq_sta lq_sta; | 293 | struct iwl_lq_sta lq_sta; |
| 294 | struct ieee80211_vif *vif; | 294 | struct ieee80211_vif *vif; |
| 295 | 295 | ||
| 296 | #ifdef CONFIG_PM_SLEEP | ||
| 297 | u16 last_seq_ctl; | ||
| 298 | #endif | ||
| 299 | |||
| 300 | /* Temporary, until the new TLC will control the Tx protection */ | 296 | /* Temporary, until the new TLC will control the Tx protection */ |
| 301 | s8 tx_protection; | 297 | s8 tx_protection; |
| 302 | bool tt_tx_protection; | 298 | bool tt_tx_protection; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/testmode.h b/drivers/net/wireless/iwlwifi/mvm/testmode.h new file mode 100644 index 000000000000..eb74391d91ca --- /dev/null +++ b/drivers/net/wireless/iwlwifi/mvm/testmode.h | |||
| @@ -0,0 +1,95 @@ | |||
| 1 | /****************************************************************************** | ||
| 2 | * | ||
| 3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
| 4 | * redistributing this file, you may do so under either license. | ||
| 5 | * | ||
| 6 | * GPL LICENSE SUMMARY | ||
| 7 | * | ||
| 8 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of version 2 of the GNU General Public License as | ||
| 12 | * published by the Free Software Foundation. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, but | ||
| 15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 17 | * General Public License for more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License | ||
| 20 | * along with this program; if not, write to the Free Software | ||
| 21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
| 22 | * USA | ||
| 23 | * | ||
| 24 | * The full GNU General Public License is included in this distribution | ||
| 25 | * in the file called COPYING. | ||
| 26 | * | ||
| 27 | * Contact Information: | ||
| 28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
| 29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
| 30 | * | ||
| 31 | * BSD LICENSE | ||
| 32 | * | ||
| 33 | * Copyright(c) 2013 Intel Corporation. All rights reserved. | ||
| 34 | * All rights reserved. | ||
| 35 | * | ||
| 36 | * Redistribution and use in source and binary forms, with or without | ||
| 37 | * modification, are permitted provided that the following conditions | ||
| 38 | * are met: | ||
| 39 | * | ||
| 40 | * * Redistributions of source code must retain the above copyright | ||
| 41 | * notice, this list of conditions and the following disclaimer. | ||
| 42 | * * Redistributions in binary form must reproduce the above copyright | ||
| 43 | * notice, this list of conditions and the following disclaimer in | ||
| 44 | * the documentation and/or other materials provided with the | ||
| 45 | * distribution. | ||
| 46 | * * Neither the name Intel Corporation nor the names of its | ||
| 47 | * contributors may be used to endorse or promote products derived | ||
| 48 | * from this software without specific prior written permission. | ||
| 49 | * | ||
| 50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| 51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| 52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| 53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| 54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| 55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
| 56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
| 57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
| 58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| 60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 61 | * | ||
| 62 | *****************************************************************************/ | ||
| 63 | |||
| 64 | #ifndef __IWL_MVM_TESTMODE_H__ | ||
| 65 | #define __IWL_MVM_TESTMODE_H__ | ||
| 66 | |||
| 67 | /** | ||
| 68 | * enum iwl_mvm_testmode_attrs - testmode attributes inside NL80211_ATTR_TESTDATA | ||
| 69 | * @IWL_MVM_TM_ATTR_UNSPEC: (invalid attribute) | ||
| 70 | * @IWL_MVM_TM_ATTR_CMD: sub command, see &enum iwl_mvm_testmode_commands (u32) | ||
| 71 | * @IWL_MVM_TM_ATTR_NOA_DURATION: requested NoA duration (u32) | ||
| 72 | * @IWL_MVM_TM_ATTR_BEACON_FILTER_STATE: beacon filter state (0 or 1, u32) | ||
| 73 | */ | ||
| 74 | enum iwl_mvm_testmode_attrs { | ||
| 75 | IWL_MVM_TM_ATTR_UNSPEC, | ||
| 76 | IWL_MVM_TM_ATTR_CMD, | ||
| 77 | IWL_MVM_TM_ATTR_NOA_DURATION, | ||
| 78 | IWL_MVM_TM_ATTR_BEACON_FILTER_STATE, | ||
| 79 | |||
| 80 | /* keep last */ | ||
| 81 | NUM_IWL_MVM_TM_ATTRS, | ||
| 82 | IWL_MVM_TM_ATTR_MAX = NUM_IWL_MVM_TM_ATTRS - 1, | ||
| 83 | }; | ||
| 84 | |||
| 85 | /** | ||
| 86 | * enum iwl_mvm_testmode_commands - MVM testmode commands | ||
| 87 | * @IWL_MVM_TM_CMD_SET_NOA: set NoA on GO vif for testing | ||
| 88 | * @IWL_MVM_TM_CMD_SET_BEACON_FILTER: turn beacon filtering off/on | ||
| 89 | */ | ||
| 90 | enum iwl_mvm_testmode_commands { | ||
| 91 | IWL_MVM_TM_CMD_SET_NOA, | ||
| 92 | IWL_MVM_TM_CMD_SET_BEACON_FILTER, | ||
| 93 | }; | ||
| 94 | |||
| 95 | #endif /* __IWL_MVM_TESTMODE_H__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index 76a3c177e100..33cf56fdfc41 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c | |||
| @@ -387,7 +387,8 @@ static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm, | |||
| 387 | 387 | ||
| 388 | void iwl_mvm_protect_session(struct iwl_mvm *mvm, | 388 | void iwl_mvm_protect_session(struct iwl_mvm *mvm, |
| 389 | struct ieee80211_vif *vif, | 389 | struct ieee80211_vif *vif, |
| 390 | u32 duration, u32 min_duration) | 390 | u32 duration, u32 min_duration, |
| 391 | u32 max_delay) | ||
| 391 | { | 392 | { |
| 392 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 393 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
| 393 | struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; | 394 | struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; |
| @@ -426,7 +427,7 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm, | |||
| 426 | cpu_to_le32(iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG)); | 427 | cpu_to_le32(iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG)); |
| 427 | 428 | ||
| 428 | time_cmd.max_frags = TE_V2_FRAG_NONE; | 429 | time_cmd.max_frags = TE_V2_FRAG_NONE; |
| 429 | time_cmd.max_delay = cpu_to_le32(500); | 430 | time_cmd.max_delay = cpu_to_le32(max_delay); |
| 430 | /* TODO: why do we need to interval = bi if it is not periodic? */ | 431 | /* TODO: why do we need to interval = bi if it is not periodic? */ |
| 431 | time_cmd.interval = cpu_to_le32(1); | 432 | time_cmd.interval = cpu_to_le32(1); |
| 432 | time_cmd.duration = cpu_to_le32(duration); | 433 | time_cmd.duration = cpu_to_le32(duration); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.h b/drivers/net/wireless/iwlwifi/mvm/time-event.h index f86c51065ed3..d9c8d6cfa2db 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.h +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.h | |||
| @@ -123,6 +123,7 @@ | |||
| 123 | * @duration: the duration of the session in TU. | 123 | * @duration: the duration of the session in TU. |
| 124 | * @min_duration: will start a new session if the current session will end | 124 | * @min_duration: will start a new session if the current session will end |
| 125 | * in less than min_duration. | 125 | * in less than min_duration. |
| 126 | * @max_delay: maximum delay before starting the time event (in TU) | ||
| 126 | * | 127 | * |
| 127 | * This function can be used to start a session protection which means that the | 128 | * This function can be used to start a session protection which means that the |
| 128 | * fw will stay on the channel for %duration_ms milliseconds. This function | 129 | * fw will stay on the channel for %duration_ms milliseconds. This function |
| @@ -133,7 +134,8 @@ | |||
| 133 | */ | 134 | */ |
| 134 | void iwl_mvm_protect_session(struct iwl_mvm *mvm, | 135 | void iwl_mvm_protect_session(struct iwl_mvm *mvm, |
| 135 | struct ieee80211_vif *vif, | 136 | struct ieee80211_vif *vif, |
| 136 | u32 duration, u32 min_duration); | 137 | u32 duration, u32 min_duration, |
| 138 | u32 max_delay); | ||
| 137 | 139 | ||
| 138 | /** | 140 | /** |
| 139 | * iwl_mvm_stop_session_protection - cancel the session protection. | 141 | * iwl_mvm_stop_session_protection - cancel the session protection. |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index e05440d90319..43d97c33a75a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
| @@ -417,7 +417,7 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
| 417 | 417 | ||
| 418 | spin_unlock(&mvmsta->lock); | 418 | spin_unlock(&mvmsta->lock); |
| 419 | 419 | ||
| 420 | if (txq_id < IWL_MVM_FIRST_AGG_QUEUE) | 420 | if (txq_id < mvm->first_agg_queue) |
| 421 | atomic_inc(&mvm->pending_frames[mvmsta->sta_id]); | 421 | atomic_inc(&mvm->pending_frames[mvmsta->sta_id]); |
| 422 | 422 | ||
| 423 | return 0; | 423 | return 0; |
| @@ -511,16 +511,10 @@ const char *iwl_mvm_get_tx_fail_reason(u32 status) | |||
| 511 | } | 511 | } |
| 512 | #endif /* CONFIG_IWLWIFI_DEBUG */ | 512 | #endif /* CONFIG_IWLWIFI_DEBUG */ |
| 513 | 513 | ||
| 514 | /** | 514 | void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags, |
| 515 | * translate ucode response to mac80211 tx status control values | 515 | enum ieee80211_band band, |
| 516 | */ | 516 | struct ieee80211_tx_rate *r) |
| 517 | static void iwl_mvm_hwrate_to_tx_control(u32 rate_n_flags, | ||
| 518 | struct ieee80211_tx_info *info) | ||
| 519 | { | 517 | { |
| 520 | struct ieee80211_tx_rate *r = &info->status.rates[0]; | ||
| 521 | |||
| 522 | info->status.antenna = | ||
| 523 | ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); | ||
| 524 | if (rate_n_flags & RATE_HT_MCS_GF_MSK) | 518 | if (rate_n_flags & RATE_HT_MCS_GF_MSK) |
| 525 | r->flags |= IEEE80211_TX_RC_GREEN_FIELD; | 519 | r->flags |= IEEE80211_TX_RC_GREEN_FIELD; |
| 526 | switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) { | 520 | switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) { |
| @@ -549,10 +543,23 @@ static void iwl_mvm_hwrate_to_tx_control(u32 rate_n_flags, | |||
| 549 | r->flags |= IEEE80211_TX_RC_VHT_MCS; | 543 | r->flags |= IEEE80211_TX_RC_VHT_MCS; |
| 550 | } else { | 544 | } else { |
| 551 | r->idx = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags, | 545 | r->idx = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags, |
| 552 | info->band); | 546 | band); |
| 553 | } | 547 | } |
| 554 | } | 548 | } |
| 555 | 549 | ||
| 550 | /** | ||
| 551 | * translate ucode response to mac80211 tx status control values | ||
| 552 | */ | ||
| 553 | static void iwl_mvm_hwrate_to_tx_status(u32 rate_n_flags, | ||
| 554 | struct ieee80211_tx_info *info) | ||
| 555 | { | ||
| 556 | struct ieee80211_tx_rate *r = &info->status.rates[0]; | ||
| 557 | |||
| 558 | info->status.antenna = | ||
| 559 | ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); | ||
| 560 | iwl_mvm_hwrate_to_tx_rate(rate_n_flags, info->band, r); | ||
| 561 | } | ||
| 562 | |||
| 556 | static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | 563 | static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, |
| 557 | struct iwl_rx_packet *pkt) | 564 | struct iwl_rx_packet *pkt) |
| 558 | { | 565 | { |
| @@ -602,11 +609,11 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
| 602 | } | 609 | } |
| 603 | 610 | ||
| 604 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 611 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
| 605 | iwl_mvm_hwrate_to_tx_control(le32_to_cpu(tx_resp->initial_rate), | 612 | iwl_mvm_hwrate_to_tx_status(le32_to_cpu(tx_resp->initial_rate), |
| 606 | info); | 613 | info); |
| 607 | 614 | ||
| 608 | /* Single frame failure in an AMPDU queue => send BAR */ | 615 | /* Single frame failure in an AMPDU queue => send BAR */ |
| 609 | if (txq_id >= IWL_MVM_FIRST_AGG_QUEUE && | 616 | if (txq_id >= mvm->first_agg_queue && |
| 610 | !(info->flags & IEEE80211_TX_STAT_ACK)) | 617 | !(info->flags & IEEE80211_TX_STAT_ACK)) |
| 611 | info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | 618 | info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; |
| 612 | 619 | ||
| @@ -619,7 +626,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
| 619 | ieee80211_tx_status_ni(mvm->hw, skb); | 626 | ieee80211_tx_status_ni(mvm->hw, skb); |
| 620 | } | 627 | } |
| 621 | 628 | ||
| 622 | if (txq_id >= IWL_MVM_FIRST_AGG_QUEUE) { | 629 | if (txq_id >= mvm->first_agg_queue) { |
| 623 | /* If this is an aggregation queue, we use the ssn since: | 630 | /* If this is an aggregation queue, we use the ssn since: |
| 624 | * ssn = wifi seq_num % 256. | 631 | * ssn = wifi seq_num % 256. |
| 625 | * The seq_ctl is the sequence control of the packet to which | 632 | * The seq_ctl is the sequence control of the packet to which |
| @@ -668,10 +675,6 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
| 668 | iwl_mvm_check_ratid_empty(mvm, sta, tid); | 675 | iwl_mvm_check_ratid_empty(mvm, sta, tid); |
| 669 | spin_unlock_bh(&mvmsta->lock); | 676 | spin_unlock_bh(&mvmsta->lock); |
| 670 | } | 677 | } |
| 671 | |||
| 672 | #ifdef CONFIG_PM_SLEEP | ||
| 673 | mvmsta->last_seq_ctl = seq_ctl; | ||
| 674 | #endif | ||
| 675 | } else { | 678 | } else { |
| 676 | sta = NULL; | 679 | sta = NULL; |
| 677 | mvmsta = NULL; | 680 | mvmsta = NULL; |
| @@ -681,7 +684,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
| 681 | * If the txq is not an AMPDU queue, there is no chance we freed | 684 | * If the txq is not an AMPDU queue, there is no chance we freed |
| 682 | * several skbs. Check that out... | 685 | * several skbs. Check that out... |
| 683 | */ | 686 | */ |
| 684 | if (txq_id < IWL_MVM_FIRST_AGG_QUEUE && !WARN_ON(skb_freed > 1) && | 687 | if (txq_id < mvm->first_agg_queue && !WARN_ON(skb_freed > 1) && |
| 685 | atomic_sub_and_test(skb_freed, &mvm->pending_frames[sta_id])) { | 688 | atomic_sub_and_test(skb_freed, &mvm->pending_frames[sta_id])) { |
| 686 | if (mvmsta) { | 689 | if (mvmsta) { |
| 687 | /* | 690 | /* |
| @@ -777,7 +780,7 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm, | |||
| 777 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | 780 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); |
| 778 | struct ieee80211_sta *sta; | 781 | struct ieee80211_sta *sta; |
| 779 | 782 | ||
| 780 | if (WARN_ON_ONCE(SEQ_TO_QUEUE(sequence) < IWL_MVM_FIRST_AGG_QUEUE)) | 783 | if (WARN_ON_ONCE(SEQ_TO_QUEUE(sequence) < mvm->first_agg_queue)) |
| 781 | return; | 784 | return; |
| 782 | 785 | ||
| 783 | if (WARN_ON_ONCE(tid == IWL_TID_NON_QOS)) | 786 | if (WARN_ON_ONCE(tid == IWL_TID_NON_QOS)) |
| @@ -904,8 +907,8 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
| 904 | info->flags |= IEEE80211_TX_STAT_AMPDU; | 907 | info->flags |= IEEE80211_TX_STAT_AMPDU; |
| 905 | info->status.ampdu_ack_len = ba_notif->txed_2_done; | 908 | info->status.ampdu_ack_len = ba_notif->txed_2_done; |
| 906 | info->status.ampdu_len = ba_notif->txed; | 909 | info->status.ampdu_len = ba_notif->txed; |
| 907 | iwl_mvm_hwrate_to_tx_control(tid_data->rate_n_flags, | 910 | iwl_mvm_hwrate_to_tx_status(tid_data->rate_n_flags, |
| 908 | info); | 911 | info); |
| 909 | } | 912 | } |
| 910 | } | 913 | } |
| 911 | 914 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index a9c357491434..ed69e9b78e82 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c | |||
| @@ -466,7 +466,7 @@ void iwl_mvm_dump_sram(struct iwl_mvm *mvm) | |||
| 466 | ofs = img->sec[IWL_UCODE_SECTION_DATA].offset; | 466 | ofs = img->sec[IWL_UCODE_SECTION_DATA].offset; |
| 467 | len = img->sec[IWL_UCODE_SECTION_DATA].len; | 467 | len = img->sec[IWL_UCODE_SECTION_DATA].len; |
| 468 | 468 | ||
| 469 | buf = kzalloc(len, GFP_KERNEL); | 469 | buf = kzalloc(len, GFP_ATOMIC); |
| 470 | if (!buf) | 470 | if (!buf) |
| 471 | return; | 471 | return; |
| 472 | 472 | ||
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 26108a1a29fa..941c0c88f982 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c | |||
| @@ -268,7 +268,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { | |||
| 268 | #endif /* CONFIG_IWLDVM */ | 268 | #endif /* CONFIG_IWLDVM */ |
| 269 | 269 | ||
| 270 | #if IS_ENABLED(CONFIG_IWLMVM) | 270 | #if IS_ENABLED(CONFIG_IWLMVM) |
| 271 | /* 7000 Series */ | 271 | /* 7260 Series */ |
| 272 | {IWL_PCI_DEVICE(0x08B1, 0x4070, iwl7260_2ac_cfg)}, | 272 | {IWL_PCI_DEVICE(0x08B1, 0x4070, iwl7260_2ac_cfg)}, |
| 273 | {IWL_PCI_DEVICE(0x08B1, 0x4072, iwl7260_2ac_cfg)}, | 273 | {IWL_PCI_DEVICE(0x08B1, 0x4072, iwl7260_2ac_cfg)}, |
| 274 | {IWL_PCI_DEVICE(0x08B1, 0x4170, iwl7260_2ac_cfg)}, | 274 | {IWL_PCI_DEVICE(0x08B1, 0x4170, iwl7260_2ac_cfg)}, |
| @@ -350,6 +350,9 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { | |||
| 350 | {IWL_PCI_DEVICE(0x08B4, 0x8270, iwl3160_2ac_cfg)}, | 350 | {IWL_PCI_DEVICE(0x08B4, 0x8270, iwl3160_2ac_cfg)}, |
| 351 | {IWL_PCI_DEVICE(0x08B3, 0x8470, iwl3160_2ac_cfg)}, | 351 | {IWL_PCI_DEVICE(0x08B3, 0x8470, iwl3160_2ac_cfg)}, |
| 352 | {IWL_PCI_DEVICE(0x08B3, 0x8570, iwl3160_2ac_cfg)}, | 352 | {IWL_PCI_DEVICE(0x08B3, 0x8570, iwl3160_2ac_cfg)}, |
| 353 | |||
| 354 | /* 7265 Series */ | ||
| 355 | {IWL_PCI_DEVICE(0x095A, 0x5010, iwl7265_2ac_cfg)}, | ||
| 353 | #endif /* CONFIG_IWLMVM */ | 356 | #endif /* CONFIG_IWLMVM */ |
| 354 | 357 | ||
| 355 | {0} | 358 | {0} |
| @@ -391,7 +394,6 @@ out_free_drv: | |||
| 391 | iwl_drv_stop(trans_pcie->drv); | 394 | iwl_drv_stop(trans_pcie->drv); |
| 392 | out_free_trans: | 395 | out_free_trans: |
| 393 | iwl_trans_pcie_free(iwl_trans); | 396 | iwl_trans_pcie_free(iwl_trans); |
| 394 | pci_set_drvdata(pdev, NULL); | ||
| 395 | return ret; | 397 | return ret; |
| 396 | } | 398 | } |
| 397 | 399 | ||
| @@ -402,8 +404,6 @@ static void iwl_pci_remove(struct pci_dev *pdev) | |||
| 402 | 404 | ||
| 403 | iwl_drv_stop(trans_pcie->drv); | 405 | iwl_drv_stop(trans_pcie->drv); |
| 404 | iwl_trans_pcie_free(trans); | 406 | iwl_trans_pcie_free(trans); |
| 405 | |||
| 406 | pci_set_drvdata(pdev, NULL); | ||
| 407 | } | 407 | } |
| 408 | 408 | ||
| 409 | #ifdef CONFIG_PM_SLEEP | 409 | #ifdef CONFIG_PM_SLEEP |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index c3f904d422b0..5d9337bec67a 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
| @@ -220,6 +220,9 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans) | |||
| 220 | iwl_set_bits_prph(trans, APMG_PCIDEV_STT_REG, | 220 | iwl_set_bits_prph(trans, APMG_PCIDEV_STT_REG, |
| 221 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | 221 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); |
| 222 | 222 | ||
| 223 | /* Clear the interrupt in APMG if the NIC is in RFKILL */ | ||
| 224 | iwl_write_prph(trans, APMG_RTC_INT_STT_REG, APMG_RTC_INT_STT_RFKILL); | ||
| 225 | |||
| 223 | set_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status); | 226 | set_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status); |
| 224 | 227 | ||
| 225 | out: | 228 | out: |
| @@ -443,22 +446,138 @@ static int iwl_pcie_load_section(struct iwl_trans *trans, u8 section_num, | |||
| 443 | return ret; | 446 | return ret; |
| 444 | } | 447 | } |
| 445 | 448 | ||
| 449 | static int iwl_pcie_secure_set(struct iwl_trans *trans, int cpu) | ||
| 450 | { | ||
| 451 | int shift_param; | ||
| 452 | u32 address; | ||
| 453 | int ret = 0; | ||
| 454 | |||
| 455 | if (cpu == 1) { | ||
| 456 | shift_param = 0; | ||
| 457 | address = CSR_SECURE_BOOT_CPU1_STATUS_ADDR; | ||
| 458 | } else { | ||
| 459 | shift_param = 16; | ||
| 460 | address = CSR_SECURE_BOOT_CPU2_STATUS_ADDR; | ||
| 461 | } | ||
| 462 | |||
| 463 | /* set CPU to started */ | ||
| 464 | iwl_trans_set_bits_mask(trans, | ||
| 465 | CSR_UCODE_LOAD_STATUS_ADDR, | ||
| 466 | CSR_CPU_STATUS_LOADING_STARTED << shift_param, | ||
| 467 | 1); | ||
| 468 | |||
| 469 | /* set last complete descriptor number */ | ||
| 470 | iwl_trans_set_bits_mask(trans, | ||
| 471 | CSR_UCODE_LOAD_STATUS_ADDR, | ||
| 472 | CSR_CPU_STATUS_NUM_OF_LAST_COMPLETED | ||
| 473 | << shift_param, | ||
| 474 | 1); | ||
| 475 | |||
| 476 | /* set last loaded block */ | ||
| 477 | iwl_trans_set_bits_mask(trans, | ||
| 478 | CSR_UCODE_LOAD_STATUS_ADDR, | ||
| 479 | CSR_CPU_STATUS_NUM_OF_LAST_LOADED_BLOCK | ||
| 480 | << shift_param, | ||
| 481 | 1); | ||
| 482 | |||
| 483 | /* image loading complete */ | ||
| 484 | iwl_trans_set_bits_mask(trans, | ||
| 485 | CSR_UCODE_LOAD_STATUS_ADDR, | ||
| 486 | CSR_CPU_STATUS_LOADING_COMPLETED | ||
| 487 | << shift_param, | ||
| 488 | 1); | ||
| 489 | |||
| 490 | /* set FH_TCSR_0_REG */ | ||
| 491 | iwl_trans_set_bits_mask(trans, FH_TCSR_0_REG0, 0x00400000, 1); | ||
| 492 | |||
| 493 | /* verify image verification started */ | ||
| 494 | ret = iwl_poll_bit(trans, address, | ||
| 495 | CSR_SECURE_BOOT_CPU_STATUS_VERF_STATUS, | ||
| 496 | CSR_SECURE_BOOT_CPU_STATUS_VERF_STATUS, | ||
| 497 | CSR_SECURE_TIME_OUT); | ||
| 498 | if (ret < 0) { | ||
| 499 | IWL_ERR(trans, "secure boot process didn't start\n"); | ||
| 500 | return ret; | ||
| 501 | } | ||
| 502 | |||
| 503 | /* wait for image verification to complete */ | ||
| 504 | ret = iwl_poll_bit(trans, address, | ||
| 505 | CSR_SECURE_BOOT_CPU_STATUS_VERF_COMPLETED, | ||
| 506 | CSR_SECURE_BOOT_CPU_STATUS_VERF_COMPLETED, | ||
| 507 | CSR_SECURE_TIME_OUT); | ||
| 508 | |||
| 509 | if (ret < 0) { | ||
| 510 | IWL_ERR(trans, "Time out on secure boot process\n"); | ||
| 511 | return ret; | ||
| 512 | } | ||
| 513 | |||
| 514 | return 0; | ||
| 515 | } | ||
| 516 | |||
| 446 | static int iwl_pcie_load_given_ucode(struct iwl_trans *trans, | 517 | static int iwl_pcie_load_given_ucode(struct iwl_trans *trans, |
| 447 | const struct fw_img *image) | 518 | const struct fw_img *image) |
| 448 | { | 519 | { |
| 449 | int i, ret = 0; | 520 | int i, ret = 0; |
| 450 | 521 | ||
| 451 | for (i = 0; i < IWL_UCODE_SECTION_MAX; i++) { | 522 | IWL_DEBUG_FW(trans, |
| 523 | "working with %s image\n", | ||
| 524 | image->is_secure ? "Secured" : "Non Secured"); | ||
| 525 | IWL_DEBUG_FW(trans, | ||
| 526 | "working with %s CPU\n", | ||
| 527 | image->is_dual_cpus ? "Dual" : "Single"); | ||
| 528 | |||
| 529 | /* configure the ucode to be ready to get the secured image */ | ||
| 530 | if (image->is_secure) { | ||
| 531 | /* set secure boot inspector addresses */ | ||
| 532 | iwl_write32(trans, CSR_SECURE_INSPECTOR_CODE_ADDR, 0); | ||
| 533 | iwl_write32(trans, CSR_SECURE_INSPECTOR_DATA_ADDR, 0); | ||
| 534 | |||
| 535 | /* release CPU1 reset if secure inspector image burned in OTP */ | ||
| 536 | iwl_write32(trans, CSR_RESET, 0); | ||
| 537 | } | ||
| 538 | |||
| 539 | /* load to FW the binary sections of CPU1 */ | ||
| 540 | IWL_DEBUG_INFO(trans, "Loading CPU1\n"); | ||
| 541 | for (i = 0; | ||
| 542 | i < IWL_UCODE_FIRST_SECTION_OF_SECOND_CPU; | ||
| 543 | i++) { | ||
| 452 | if (!image->sec[i].data) | 544 | if (!image->sec[i].data) |
| 453 | break; | 545 | break; |
| 454 | |||
| 455 | ret = iwl_pcie_load_section(trans, i, &image->sec[i]); | 546 | ret = iwl_pcie_load_section(trans, i, &image->sec[i]); |
| 456 | if (ret) | 547 | if (ret) |
| 457 | return ret; | 548 | return ret; |
| 458 | } | 549 | } |
| 459 | 550 | ||
| 460 | /* Remove all resets to allow NIC to operate */ | 551 | /* configure the ucode to start secure process on CPU1 */ |
| 461 | iwl_write32(trans, CSR_RESET, 0); | 552 | if (image->is_secure) { |
| 553 | /* config CPU1 to start secure protocol */ | ||
| 554 | ret = iwl_pcie_secure_set(trans, 1); | ||
| 555 | if (ret) | ||
| 556 | return ret; | ||
| 557 | } else { | ||
| 558 | /* Remove all resets to allow NIC to operate */ | ||
| 559 | iwl_write32(trans, CSR_RESET, 0); | ||
| 560 | } | ||
| 561 | |||
| 562 | if (image->is_dual_cpus) { | ||
| 563 | /* load to FW the binary sections of CPU2 */ | ||
| 564 | IWL_DEBUG_INFO(trans, "working w/ DUAL CPUs - Loading CPU2\n"); | ||
| 565 | for (i = IWL_UCODE_FIRST_SECTION_OF_SECOND_CPU; | ||
| 566 | i < IWL_UCODE_SECTION_MAX; i++) { | ||
| 567 | if (!image->sec[i].data) | ||
| 568 | break; | ||
| 569 | ret = iwl_pcie_load_section(trans, i, &image->sec[i]); | ||
| 570 | if (ret) | ||
| 571 | return ret; | ||
| 572 | } | ||
| 573 | |||
| 574 | if (image->is_secure) { | ||
| 575 | /* set CPU2 for secure protocol */ | ||
| 576 | ret = iwl_pcie_secure_set(trans, 2); | ||
| 577 | if (ret) | ||
| 578 | return ret; | ||
| 579 | } | ||
| 580 | } | ||
| 462 | 581 | ||
| 463 | return 0; | 582 | return 0; |
| 464 | } | 583 | } |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 1424335163b9..059c5acad3a0 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
| @@ -1465,7 +1465,8 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans, | |||
| 1465 | spin_unlock_bh(&txq->lock); | 1465 | spin_unlock_bh(&txq->lock); |
| 1466 | } | 1466 | } |
| 1467 | 1467 | ||
| 1468 | #define HOST_COMPLETE_TIMEOUT (2 * HZ) | 1468 | #define HOST_COMPLETE_TIMEOUT (2 * HZ) |
| 1469 | #define COMMAND_POKE_TIMEOUT (HZ / 10) | ||
| 1469 | 1470 | ||
| 1470 | static int iwl_pcie_send_hcmd_async(struct iwl_trans *trans, | 1471 | static int iwl_pcie_send_hcmd_async(struct iwl_trans *trans, |
| 1471 | struct iwl_host_cmd *cmd) | 1472 | struct iwl_host_cmd *cmd) |
| @@ -1493,16 +1494,16 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, | |||
| 1493 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1494 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 1494 | int cmd_idx; | 1495 | int cmd_idx; |
| 1495 | int ret; | 1496 | int ret; |
| 1497 | int timeout = HOST_COMPLETE_TIMEOUT; | ||
| 1496 | 1498 | ||
| 1497 | IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", | 1499 | IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", |
| 1498 | get_cmd_string(trans_pcie, cmd->id)); | 1500 | get_cmd_string(trans_pcie, cmd->id)); |
| 1499 | 1501 | ||
| 1500 | if (WARN_ON(test_and_set_bit(STATUS_HCMD_ACTIVE, | 1502 | if (WARN(test_and_set_bit(STATUS_HCMD_ACTIVE, |
| 1501 | &trans_pcie->status))) { | 1503 | &trans_pcie->status), |
| 1502 | IWL_ERR(trans, "Command %s: a command is already active!\n", | 1504 | "Command %s: a command is already active!\n", |
| 1503 | get_cmd_string(trans_pcie, cmd->id)); | 1505 | get_cmd_string(trans_pcie, cmd->id))) |
| 1504 | return -EIO; | 1506 | return -EIO; |
| 1505 | } | ||
| 1506 | 1507 | ||
| 1507 | IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n", | 1508 | IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n", |
| 1508 | get_cmd_string(trans_pcie, cmd->id)); | 1509 | get_cmd_string(trans_pcie, cmd->id)); |
| @@ -1517,10 +1518,29 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, | |||
| 1517 | return ret; | 1518 | return ret; |
| 1518 | } | 1519 | } |
| 1519 | 1520 | ||
| 1520 | ret = wait_event_timeout(trans_pcie->wait_command_queue, | 1521 | while (timeout > 0) { |
| 1521 | !test_bit(STATUS_HCMD_ACTIVE, | 1522 | unsigned long flags; |
| 1522 | &trans_pcie->status), | 1523 | |
| 1523 | HOST_COMPLETE_TIMEOUT); | 1524 | timeout -= COMMAND_POKE_TIMEOUT; |
| 1525 | ret = wait_event_timeout(trans_pcie->wait_command_queue, | ||
| 1526 | !test_bit(STATUS_HCMD_ACTIVE, | ||
| 1527 | &trans_pcie->status), | ||
| 1528 | COMMAND_POKE_TIMEOUT); | ||
| 1529 | if (ret) | ||
| 1530 | break; | ||
| 1531 | /* poke the device - it may have lost the command */ | ||
| 1532 | if (iwl_trans_grab_nic_access(trans, true, &flags)) { | ||
| 1533 | iwl_trans_release_nic_access(trans, &flags); | ||
| 1534 | IWL_DEBUG_INFO(trans, | ||
| 1535 | "Tried to wake NIC for command %s\n", | ||
| 1536 | get_cmd_string(trans_pcie, cmd->id)); | ||
| 1537 | } else { | ||
| 1538 | IWL_ERR(trans, "Failed to poke NIC for command %s\n", | ||
| 1539 | get_cmd_string(trans_pcie, cmd->id)); | ||
| 1540 | break; | ||
| 1541 | } | ||
| 1542 | } | ||
| 1543 | |||
| 1524 | if (!ret) { | 1544 | if (!ret) { |
| 1525 | if (test_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status)) { | 1545 | if (test_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status)) { |
| 1526 | struct iwl_txq *txq = | 1546 | struct iwl_txq *txq = |
| @@ -1541,6 +1561,9 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, | |||
| 1541 | "Clearing HCMD_ACTIVE for command %s\n", | 1561 | "Clearing HCMD_ACTIVE for command %s\n", |
| 1542 | get_cmd_string(trans_pcie, cmd->id)); | 1562 | get_cmd_string(trans_pcie, cmd->id)); |
| 1543 | ret = -ETIMEDOUT; | 1563 | ret = -ETIMEDOUT; |
| 1564 | |||
| 1565 | iwl_op_mode_nic_error(trans->op_mode); | ||
| 1566 | |||
| 1544 | goto cancel; | 1567 | goto cancel; |
| 1545 | } | 1568 | } |
| 1546 | } | 1569 | } |
diff --git a/drivers/net/wireless/libertas/firmware.c b/drivers/net/wireless/libertas/firmware.c index c0f9e7e862f6..51b92b5df119 100644 --- a/drivers/net/wireless/libertas/firmware.c +++ b/drivers/net/wireless/libertas/firmware.c | |||
| @@ -53,6 +53,11 @@ static void main_firmware_cb(const struct firmware *firmware, void *context) | |||
| 53 | 53 | ||
| 54 | /* Firmware found! */ | 54 | /* Firmware found! */ |
| 55 | lbs_fw_loaded(priv, 0, priv->helper_fw, firmware); | 55 | lbs_fw_loaded(priv, 0, priv->helper_fw, firmware); |
| 56 | if (priv->helper_fw) { | ||
| 57 | release_firmware (priv->helper_fw); | ||
| 58 | priv->helper_fw = NULL; | ||
| 59 | } | ||
| 60 | release_firmware (firmware); | ||
| 56 | } | 61 | } |
| 57 | 62 | ||
| 58 | static void helper_firmware_cb(const struct firmware *firmware, void *context) | 63 | static void helper_firmware_cb(const struct firmware *firmware, void *context) |
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index c94dd6802672..ef8c98e21098 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c | |||
| @@ -754,14 +754,14 @@ static void if_cs_prog_firmware(struct lbs_private *priv, int ret, | |||
| 754 | if (ret == 0 && (card->model != MODEL_8305)) | 754 | if (ret == 0 && (card->model != MODEL_8305)) |
| 755 | ret = if_cs_prog_real(card, mainfw); | 755 | ret = if_cs_prog_real(card, mainfw); |
| 756 | if (ret) | 756 | if (ret) |
| 757 | goto out; | 757 | return; |
| 758 | 758 | ||
| 759 | /* Now actually get the IRQ */ | 759 | /* Now actually get the IRQ */ |
| 760 | ret = request_irq(card->p_dev->irq, if_cs_interrupt, | 760 | ret = request_irq(card->p_dev->irq, if_cs_interrupt, |
| 761 | IRQF_SHARED, DRV_NAME, card); | 761 | IRQF_SHARED, DRV_NAME, card); |
| 762 | if (ret) { | 762 | if (ret) { |
| 763 | pr_err("error in request_irq\n"); | 763 | pr_err("error in request_irq\n"); |
| 764 | goto out; | 764 | return; |
| 765 | } | 765 | } |
| 766 | 766 | ||
| 767 | /* | 767 | /* |
| @@ -777,10 +777,6 @@ static void if_cs_prog_firmware(struct lbs_private *priv, int ret, | |||
| 777 | pr_err("could not activate card\n"); | 777 | pr_err("could not activate card\n"); |
| 778 | free_irq(card->p_dev->irq, card); | 778 | free_irq(card->p_dev->irq, card); |
| 779 | } | 779 | } |
| 780 | |||
| 781 | out: | ||
| 782 | release_firmware(helper); | ||
| 783 | release_firmware(mainfw); | ||
| 784 | } | 780 | } |
| 785 | 781 | ||
| 786 | 782 | ||
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 45578335e420..991238afd1b6 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
| @@ -708,20 +708,16 @@ static void if_sdio_do_prog_firmware(struct lbs_private *priv, int ret, | |||
| 708 | 708 | ||
| 709 | ret = if_sdio_prog_helper(card, helper); | 709 | ret = if_sdio_prog_helper(card, helper); |
| 710 | if (ret) | 710 | if (ret) |
| 711 | goto out; | 711 | return; |
| 712 | 712 | ||
| 713 | lbs_deb_sdio("Helper firmware loaded\n"); | 713 | lbs_deb_sdio("Helper firmware loaded\n"); |
| 714 | 714 | ||
| 715 | ret = if_sdio_prog_real(card, mainfw); | 715 | ret = if_sdio_prog_real(card, mainfw); |
| 716 | if (ret) | 716 | if (ret) |
| 717 | goto out; | 717 | return; |
| 718 | 718 | ||
| 719 | lbs_deb_sdio("Firmware loaded\n"); | 719 | lbs_deb_sdio("Firmware loaded\n"); |
| 720 | if_sdio_finish_power_on(card); | 720 | if_sdio_finish_power_on(card); |
| 721 | |||
| 722 | out: | ||
| 723 | release_firmware(helper); | ||
| 724 | release_firmware(mainfw); | ||
| 725 | } | 721 | } |
| 726 | 722 | ||
| 727 | static int if_sdio_prog_firmware(struct if_sdio_card *card) | 723 | static int if_sdio_prog_firmware(struct if_sdio_card *card) |
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 4bb6574f4073..83669151bb82 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c | |||
| @@ -1094,11 +1094,7 @@ static int if_spi_init_card(struct if_spi_card *card) | |||
| 1094 | goto out; | 1094 | goto out; |
| 1095 | 1095 | ||
| 1096 | out: | 1096 | out: |
| 1097 | release_firmware(helper); | ||
| 1098 | release_firmware(mainfw); | ||
| 1099 | |||
| 1100 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); | 1097 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); |
| 1101 | |||
| 1102 | return err; | 1098 | return err; |
| 1103 | } | 1099 | } |
| 1104 | 1100 | ||
| @@ -1128,7 +1124,7 @@ static int if_spi_probe(struct spi_device *spi) | |||
| 1128 | { | 1124 | { |
| 1129 | struct if_spi_card *card; | 1125 | struct if_spi_card *card; |
| 1130 | struct lbs_private *priv = NULL; | 1126 | struct lbs_private *priv = NULL; |
| 1131 | struct libertas_spi_platform_data *pdata = spi->dev.platform_data; | 1127 | struct libertas_spi_platform_data *pdata = dev_get_platdata(&spi->dev); |
| 1132 | int err = 0; | 1128 | int err = 0; |
| 1133 | 1129 | ||
| 1134 | lbs_deb_enter(LBS_DEB_SPI); | 1130 | lbs_deb_enter(LBS_DEB_SPI); |
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 27980778d992..dff08a2896a3 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c | |||
| @@ -844,7 +844,7 @@ static void if_usb_prog_firmware(struct lbs_private *priv, int ret, | |||
| 844 | cardp->fw = fw; | 844 | cardp->fw = fw; |
| 845 | if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) { | 845 | if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) { |
| 846 | ret = -EINVAL; | 846 | ret = -EINVAL; |
| 847 | goto release_fw; | 847 | goto done; |
| 848 | } | 848 | } |
| 849 | 849 | ||
| 850 | /* Cancel any pending usb business */ | 850 | /* Cancel any pending usb business */ |
| @@ -861,7 +861,7 @@ restart: | |||
| 861 | if (if_usb_submit_rx_urb_fwload(cardp) < 0) { | 861 | if (if_usb_submit_rx_urb_fwload(cardp) < 0) { |
| 862 | lbs_deb_usbd(&cardp->udev->dev, "URB submission is failed\n"); | 862 | lbs_deb_usbd(&cardp->udev->dev, "URB submission is failed\n"); |
| 863 | ret = -EIO; | 863 | ret = -EIO; |
| 864 | goto release_fw; | 864 | goto done; |
| 865 | } | 865 | } |
| 866 | 866 | ||
| 867 | cardp->bootcmdresp = 0; | 867 | cardp->bootcmdresp = 0; |
| @@ -883,14 +883,14 @@ restart: | |||
| 883 | usb_kill_urb(cardp->tx_urb); | 883 | usb_kill_urb(cardp->tx_urb); |
| 884 | if (if_usb_submit_rx_urb(cardp) < 0) | 884 | if (if_usb_submit_rx_urb(cardp) < 0) |
| 885 | ret = -EIO; | 885 | ret = -EIO; |
| 886 | goto release_fw; | 886 | goto done; |
| 887 | } else if (cardp->bootcmdresp <= 0) { | 887 | } else if (cardp->bootcmdresp <= 0) { |
| 888 | if (--reset_count >= 0) { | 888 | if (--reset_count >= 0) { |
| 889 | if_usb_reset_device(cardp); | 889 | if_usb_reset_device(cardp); |
| 890 | goto restart; | 890 | goto restart; |
| 891 | } | 891 | } |
| 892 | ret = -EIO; | 892 | ret = -EIO; |
| 893 | goto release_fw; | 893 | goto done; |
| 894 | } | 894 | } |
| 895 | 895 | ||
| 896 | i = 0; | 896 | i = 0; |
| @@ -921,14 +921,14 @@ restart: | |||
| 921 | 921 | ||
| 922 | pr_info("FW download failure, time = %d ms\n", i * 100); | 922 | pr_info("FW download failure, time = %d ms\n", i * 100); |
| 923 | ret = -EIO; | 923 | ret = -EIO; |
| 924 | goto release_fw; | 924 | goto done; |
| 925 | } | 925 | } |
| 926 | 926 | ||
| 927 | cardp->priv->fw_ready = 1; | 927 | cardp->priv->fw_ready = 1; |
| 928 | if_usb_submit_rx_urb(cardp); | 928 | if_usb_submit_rx_urb(cardp); |
| 929 | 929 | ||
| 930 | if (lbs_start_card(priv)) | 930 | if (lbs_start_card(priv)) |
| 931 | goto release_fw; | 931 | goto done; |
| 932 | 932 | ||
| 933 | if_usb_setup_firmware(priv); | 933 | if_usb_setup_firmware(priv); |
| 934 | 934 | ||
| @@ -939,11 +939,8 @@ restart: | |||
| 939 | if (lbs_host_sleep_cfg(priv, priv->wol_criteria, NULL)) | 939 | if (lbs_host_sleep_cfg(priv, priv->wol_criteria, NULL)) |
| 940 | priv->ehs_remove_supported = false; | 940 | priv->ehs_remove_supported = false; |
| 941 | 941 | ||
| 942 | release_fw: | ||
| 943 | release_firmware(cardp->fw); | ||
| 944 | cardp->fw = NULL; | ||
| 945 | |||
| 946 | done: | 942 | done: |
| 943 | cardp->fw = NULL; | ||
| 947 | lbs_deb_leave(LBS_DEB_USB); | 944 | lbs_deb_leave(LBS_DEB_USB); |
| 948 | } | 945 | } |
| 949 | 946 | ||
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 2cd3f54e1efa..de0df86704e7 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
| @@ -167,6 +167,7 @@ struct hwsim_vif_priv { | |||
| 167 | u32 magic; | 167 | u32 magic; |
| 168 | u8 bssid[ETH_ALEN]; | 168 | u8 bssid[ETH_ALEN]; |
| 169 | bool assoc; | 169 | bool assoc; |
| 170 | bool bcn_en; | ||
| 170 | u16 aid; | 171 | u16 aid; |
| 171 | }; | 172 | }; |
| 172 | 173 | ||
| @@ -1170,6 +1171,16 @@ static void mac80211_hwsim_configure_filter(struct ieee80211_hw *hw, | |||
| 1170 | *total_flags = data->rx_filter; | 1171 | *total_flags = data->rx_filter; |
| 1171 | } | 1172 | } |
| 1172 | 1173 | ||
| 1174 | static void mac80211_hwsim_bcn_en_iter(void *data, u8 *mac, | ||
| 1175 | struct ieee80211_vif *vif) | ||
| 1176 | { | ||
| 1177 | unsigned int *count = data; | ||
| 1178 | struct hwsim_vif_priv *vp = (void *)vif->drv_priv; | ||
| 1179 | |||
| 1180 | if (vp->bcn_en) | ||
| 1181 | (*count)++; | ||
| 1182 | } | ||
| 1183 | |||
| 1173 | static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, | 1184 | static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, |
| 1174 | struct ieee80211_vif *vif, | 1185 | struct ieee80211_vif *vif, |
| 1175 | struct ieee80211_bss_conf *info, | 1186 | struct ieee80211_bss_conf *info, |
| @@ -1180,7 +1191,8 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, | |||
| 1180 | 1191 | ||
| 1181 | hwsim_check_magic(vif); | 1192 | hwsim_check_magic(vif); |
| 1182 | 1193 | ||
| 1183 | wiphy_debug(hw->wiphy, "%s(changed=0x%x)\n", __func__, changed); | 1194 | wiphy_debug(hw->wiphy, "%s(changed=0x%x vif->addr=%pM)\n", |
| 1195 | __func__, changed, vif->addr); | ||
| 1184 | 1196 | ||
| 1185 | if (changed & BSS_CHANGED_BSSID) { | 1197 | if (changed & BSS_CHANGED_BSSID) { |
| 1186 | wiphy_debug(hw->wiphy, "%s: BSSID changed: %pM\n", | 1198 | wiphy_debug(hw->wiphy, "%s: BSSID changed: %pM\n", |
| @@ -1202,6 +1214,7 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, | |||
| 1202 | 1214 | ||
| 1203 | if (changed & BSS_CHANGED_BEACON_ENABLED) { | 1215 | if (changed & BSS_CHANGED_BEACON_ENABLED) { |
| 1204 | wiphy_debug(hw->wiphy, " BCN EN: %d\n", info->enable_beacon); | 1216 | wiphy_debug(hw->wiphy, " BCN EN: %d\n", info->enable_beacon); |
| 1217 | vp->bcn_en = info->enable_beacon; | ||
| 1205 | if (data->started && | 1218 | if (data->started && |
| 1206 | !hrtimer_is_queued(&data->beacon_timer.timer) && | 1219 | !hrtimer_is_queued(&data->beacon_timer.timer) && |
| 1207 | info->enable_beacon) { | 1220 | info->enable_beacon) { |
| @@ -1215,8 +1228,16 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, | |||
| 1215 | tasklet_hrtimer_start(&data->beacon_timer, | 1228 | tasklet_hrtimer_start(&data->beacon_timer, |
| 1216 | ns_to_ktime(until_tbtt * 1000), | 1229 | ns_to_ktime(until_tbtt * 1000), |
| 1217 | HRTIMER_MODE_REL); | 1230 | HRTIMER_MODE_REL); |
| 1218 | } else if (!info->enable_beacon) | 1231 | } else if (!info->enable_beacon) { |
| 1219 | tasklet_hrtimer_cancel(&data->beacon_timer); | 1232 | unsigned int count = 0; |
| 1233 | ieee80211_iterate_active_interfaces( | ||
| 1234 | data->hw, IEEE80211_IFACE_ITER_NORMAL, | ||
| 1235 | mac80211_hwsim_bcn_en_iter, &count); | ||
| 1236 | wiphy_debug(hw->wiphy, " beaconing vifs remaining: %u", | ||
| 1237 | count); | ||
| 1238 | if (count == 0) | ||
| 1239 | tasklet_hrtimer_cancel(&data->beacon_timer); | ||
| 1240 | } | ||
| 1220 | } | 1241 | } |
| 1221 | 1242 | ||
| 1222 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { | 1243 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { |
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index a6c46f3b6e3a..e47f4e3012b8 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c | |||
| @@ -1048,7 +1048,7 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) | |||
| 1048 | struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; | 1048 | struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; |
| 1049 | unsigned long cmd_flags; | 1049 | unsigned long cmd_flags; |
| 1050 | unsigned long scan_pending_q_flags; | 1050 | unsigned long scan_pending_q_flags; |
| 1051 | uint16_t cancel_scan_cmd = false; | 1051 | bool cancel_scan_cmd = false; |
| 1052 | 1052 | ||
| 1053 | if ((adapter->curr_cmd) && | 1053 | if ((adapter->curr_cmd) && |
| 1054 | (adapter->curr_cmd->wait_q_enabled)) { | 1054 | (adapter->curr_cmd->wait_q_enabled)) { |
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 37f873bb342f..4e4686e6ac09 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c | |||
| @@ -621,7 +621,7 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, | |||
| 621 | int ret = 0; | 621 | int ret = 0; |
| 622 | struct ieee_types_assoc_rsp *assoc_rsp; | 622 | struct ieee_types_assoc_rsp *assoc_rsp; |
| 623 | struct mwifiex_bssdescriptor *bss_desc; | 623 | struct mwifiex_bssdescriptor *bss_desc; |
| 624 | u8 enable_data = true; | 624 | bool enable_data = true; |
| 625 | u16 cap_info, status_code; | 625 | u16 cap_info, status_code; |
| 626 | 626 | ||
| 627 | assoc_rsp = (struct ieee_types_assoc_rsp *) &resp->params; | 627 | assoc_rsp = (struct ieee_types_assoc_rsp *) &resp->params; |
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index c2b91f566e05..9d7c9d354d34 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
| @@ -882,7 +882,9 @@ mwifiex_add_card(void *card, struct semaphore *sem, | |||
| 882 | adapter->cmd_wait_q.status = 0; | 882 | adapter->cmd_wait_q.status = 0; |
| 883 | adapter->scan_wait_q_woken = false; | 883 | adapter->scan_wait_q_woken = false; |
| 884 | 884 | ||
| 885 | adapter->workqueue = create_workqueue("MWIFIEX_WORK_QUEUE"); | 885 | adapter->workqueue = |
| 886 | alloc_workqueue("MWIFIEX_WORK_QUEUE", | ||
| 887 | WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1); | ||
| 886 | if (!adapter->workqueue) | 888 | if (!adapter->workqueue) |
| 887 | goto err_kmalloc; | 889 | goto err_kmalloc; |
| 888 | 890 | ||
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 52da8ee7599a..33fa9432b241 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c | |||
| @@ -93,7 +93,7 @@ static int mwifiex_pcie_suspend(struct device *dev) | |||
| 93 | struct pci_dev *pdev = to_pci_dev(dev); | 93 | struct pci_dev *pdev = to_pci_dev(dev); |
| 94 | 94 | ||
| 95 | if (pdev) { | 95 | if (pdev) { |
| 96 | card = (struct pcie_service_card *) pci_get_drvdata(pdev); | 96 | card = pci_get_drvdata(pdev); |
| 97 | if (!card || !card->adapter) { | 97 | if (!card || !card->adapter) { |
| 98 | pr_err("Card or adapter structure is not valid\n"); | 98 | pr_err("Card or adapter structure is not valid\n"); |
| 99 | return 0; | 99 | return 0; |
| @@ -128,7 +128,7 @@ static int mwifiex_pcie_resume(struct device *dev) | |||
| 128 | struct pci_dev *pdev = to_pci_dev(dev); | 128 | struct pci_dev *pdev = to_pci_dev(dev); |
| 129 | 129 | ||
| 130 | if (pdev) { | 130 | if (pdev) { |
| 131 | card = (struct pcie_service_card *) pci_get_drvdata(pdev); | 131 | card = pci_get_drvdata(pdev); |
| 132 | if (!card || !card->adapter) { | 132 | if (!card || !card->adapter) { |
| 133 | pr_err("Card or adapter structure is not valid\n"); | 133 | pr_err("Card or adapter structure is not valid\n"); |
| 134 | return 0; | 134 | return 0; |
| @@ -2037,7 +2037,7 @@ static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context) | |||
| 2037 | goto exit; | 2037 | goto exit; |
| 2038 | } | 2038 | } |
| 2039 | 2039 | ||
| 2040 | card = (struct pcie_service_card *) pci_get_drvdata(pdev); | 2040 | card = pci_get_drvdata(pdev); |
| 2041 | if (!card || !card->adapter) { | 2041 | if (!card || !card->adapter) { |
| 2042 | pr_debug("info: %s: card=%p adapter=%p\n", __func__, card, | 2042 | pr_debug("info: %s: card=%p adapter=%p\n", __func__, card, |
| 2043 | card ? card->adapter : NULL); | 2043 | card ? card->adapter : NULL); |
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index c0268b597748..7d66018a2e33 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
| @@ -327,7 +327,7 @@ mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv, | |||
| 327 | { | 327 | { |
| 328 | struct mwifiex_adapter *adapter = priv->adapter; | 328 | struct mwifiex_adapter *adapter = priv->adapter; |
| 329 | struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = &cmd->params.opt_hs_cfg; | 329 | struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = &cmd->params.opt_hs_cfg; |
| 330 | u16 hs_activate = false; | 330 | bool hs_activate = false; |
| 331 | 331 | ||
| 332 | if (!hscfg_param) | 332 | if (!hscfg_param) |
| 333 | /* New Activate command */ | 333 | /* New Activate command */ |
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 95fa3599b407..5dd0ccc70b86 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c | |||
| @@ -708,7 +708,7 @@ int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv, | |||
| 708 | { | 708 | { |
| 709 | u8 *curr = (u8 *) &resp->params.get_wmm_status; | 709 | u8 *curr = (u8 *) &resp->params.get_wmm_status; |
| 710 | uint16_t resp_len = le16_to_cpu(resp->size), tlv_len; | 710 | uint16_t resp_len = le16_to_cpu(resp->size), tlv_len; |
| 711 | int valid = true; | 711 | bool valid = true; |
| 712 | 712 | ||
| 713 | struct mwifiex_ie_types_data *tlv_hdr; | 713 | struct mwifiex_ie_types_data *tlv_hdr; |
| 714 | struct mwifiex_ie_types_wmm_queue_status *tlv_wmm_qstatus; | 714 | struct mwifiex_ie_types_wmm_queue_status *tlv_wmm_qstatus; |
diff --git a/drivers/net/wireless/mwifiex/wmm.h b/drivers/net/wireless/mwifiex/wmm.h index 644d6e0c51cc..0f129d498fb1 100644 --- a/drivers/net/wireless/mwifiex/wmm.h +++ b/drivers/net/wireless/mwifiex/wmm.h | |||
| @@ -83,11 +83,10 @@ mwifiex_wmm_is_ra_list_empty(struct list_head *ra_list_hhead) | |||
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | void mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, | 85 | void mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, |
| 86 | struct sk_buff *skb); | 86 | struct sk_buff *skb); |
| 87 | void mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra); | 87 | void mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra); |
| 88 | void mwifiex_rotate_priolists(struct mwifiex_private *priv, | 88 | void mwifiex_rotate_priolists(struct mwifiex_private *priv, |
| 89 | struct mwifiex_ra_list_tbl *ra, | 89 | struct mwifiex_ra_list_tbl *ra, int tid); |
| 90 | int tid); | ||
| 91 | 90 | ||
| 92 | int mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter); | 91 | int mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter); |
| 93 | void mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter); | 92 | void mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter); |
| @@ -95,21 +94,18 @@ int mwifiex_is_ralist_valid(struct mwifiex_private *priv, | |||
| 95 | struct mwifiex_ra_list_tbl *ra_list, int tid); | 94 | struct mwifiex_ra_list_tbl *ra_list, int tid); |
| 96 | 95 | ||
| 97 | u8 mwifiex_wmm_compute_drv_pkt_delay(struct mwifiex_private *priv, | 96 | u8 mwifiex_wmm_compute_drv_pkt_delay(struct mwifiex_private *priv, |
| 98 | const struct sk_buff *skb); | 97 | const struct sk_buff *skb); |
| 99 | void mwifiex_wmm_init(struct mwifiex_adapter *adapter); | 98 | void mwifiex_wmm_init(struct mwifiex_adapter *adapter); |
| 100 | 99 | ||
| 101 | extern u32 mwifiex_wmm_process_association_req(struct mwifiex_private *priv, | 100 | u32 mwifiex_wmm_process_association_req(struct mwifiex_private *priv, |
| 102 | u8 **assoc_buf, | 101 | u8 **assoc_buf, |
| 103 | struct ieee_types_wmm_parameter | 102 | struct ieee_types_wmm_parameter *wmmie, |
| 104 | *wmmie, | 103 | struct ieee80211_ht_cap *htcap); |
| 105 | struct ieee80211_ht_cap | ||
| 106 | *htcap); | ||
| 107 | 104 | ||
| 108 | void mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv, | 105 | void mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv, |
| 109 | struct ieee_types_wmm_parameter | 106 | struct ieee_types_wmm_parameter *wmm_ie); |
| 110 | *wmm_ie); | ||
| 111 | void mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv); | 107 | void mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv); |
| 112 | extern int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv, | 108 | int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv, |
| 113 | const struct host_cmd_ds_command *resp); | 109 | const struct host_cmd_ds_command *resp); |
| 114 | 110 | ||
| 115 | #endif /* !_MWIFIEX_WMM_H_ */ | 111 | #endif /* !_MWIFIEX_WMM_H_ */ |
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index a3707fd4ef62..b953ad621e0b 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
| @@ -6093,7 +6093,6 @@ err_iounmap: | |||
| 6093 | if (priv->sram != NULL) | 6093 | if (priv->sram != NULL) |
| 6094 | pci_iounmap(pdev, priv->sram); | 6094 | pci_iounmap(pdev, priv->sram); |
| 6095 | 6095 | ||
| 6096 | pci_set_drvdata(pdev, NULL); | ||
| 6097 | ieee80211_free_hw(hw); | 6096 | ieee80211_free_hw(hw); |
| 6098 | 6097 | ||
| 6099 | err_free_reg: | 6098 | err_free_reg: |
| @@ -6147,7 +6146,6 @@ static void mwl8k_remove(struct pci_dev *pdev) | |||
| 6147 | unmap: | 6146 | unmap: |
| 6148 | pci_iounmap(pdev, priv->regs); | 6147 | pci_iounmap(pdev, priv->regs); |
| 6149 | pci_iounmap(pdev, priv->sram); | 6148 | pci_iounmap(pdev, priv->sram); |
| 6150 | pci_set_drvdata(pdev, NULL); | ||
| 6151 | ieee80211_free_hw(hw); | 6149 | ieee80211_free_hw(hw); |
| 6152 | pci_release_regions(pdev); | 6150 | pci_release_regions(pdev); |
| 6153 | pci_disable_device(pdev); | 6151 | pci_disable_device(pdev); |
diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h index 3bb936b9558c..eebd2be21ee9 100644 --- a/drivers/net/wireless/orinoco/orinoco.h +++ b/drivers/net/wireless/orinoco/orinoco.h | |||
| @@ -182,23 +182,20 @@ extern int orinoco_debug; | |||
| 182 | /* Exported prototypes */ | 182 | /* Exported prototypes */ |
| 183 | /********************************************************************/ | 183 | /********************************************************************/ |
| 184 | 184 | ||
| 185 | extern struct orinoco_private *alloc_orinocodev( | 185 | struct orinoco_private *alloc_orinocodev(int sizeof_card, struct device *device, |
| 186 | int sizeof_card, struct device *device, | 186 | int (*hard_reset)(struct orinoco_private *), |
| 187 | int (*hard_reset)(struct orinoco_private *), | 187 | int (*stop_fw)(struct orinoco_private *, int)); |
| 188 | int (*stop_fw)(struct orinoco_private *, int)); | 188 | void free_orinocodev(struct orinoco_private *priv); |
| 189 | extern void free_orinocodev(struct orinoco_private *priv); | 189 | int orinoco_init(struct orinoco_private *priv); |
| 190 | extern int orinoco_init(struct orinoco_private *priv); | 190 | int orinoco_if_add(struct orinoco_private *priv, unsigned long base_addr, |
| 191 | extern int orinoco_if_add(struct orinoco_private *priv, | 191 | unsigned int irq, const struct net_device_ops *ops); |
| 192 | unsigned long base_addr, | 192 | void orinoco_if_del(struct orinoco_private *priv); |
| 193 | unsigned int irq, | 193 | int orinoco_up(struct orinoco_private *priv); |
| 194 | const struct net_device_ops *ops); | 194 | void orinoco_down(struct orinoco_private *priv); |
| 195 | extern void orinoco_if_del(struct orinoco_private *priv); | 195 | irqreturn_t orinoco_interrupt(int irq, void *dev_id); |
| 196 | extern int orinoco_up(struct orinoco_private *priv); | 196 | |
| 197 | extern void orinoco_down(struct orinoco_private *priv); | 197 | void __orinoco_ev_info(struct net_device *dev, struct hermes *hw); |
| 198 | extern irqreturn_t orinoco_interrupt(int irq, void *dev_id); | 198 | void __orinoco_ev_rx(struct net_device *dev, struct hermes *hw); |
| 199 | |||
| 200 | extern void __orinoco_ev_info(struct net_device *dev, struct hermes *hw); | ||
| 201 | extern void __orinoco_ev_rx(struct net_device *dev, struct hermes *hw); | ||
| 202 | 199 | ||
| 203 | int orinoco_process_xmit_skb(struct sk_buff *skb, | 200 | int orinoco_process_xmit_skb(struct sk_buff *skb, |
| 204 | struct net_device *dev, | 201 | struct net_device *dev, |
diff --git a/drivers/net/wireless/orinoco/orinoco_nortel.c b/drivers/net/wireless/orinoco/orinoco_nortel.c index d73fdf6185a2..ffb2469eb679 100644 --- a/drivers/net/wireless/orinoco/orinoco_nortel.c +++ b/drivers/net/wireless/orinoco/orinoco_nortel.c | |||
| @@ -234,7 +234,6 @@ static int orinoco_nortel_init_one(struct pci_dev *pdev, | |||
| 234 | free_irq(pdev->irq, priv); | 234 | free_irq(pdev->irq, priv); |
| 235 | 235 | ||
| 236 | fail_irq: | 236 | fail_irq: |
| 237 | pci_set_drvdata(pdev, NULL); | ||
| 238 | free_orinocodev(priv); | 237 | free_orinocodev(priv); |
| 239 | 238 | ||
| 240 | fail_alloc: | 239 | fail_alloc: |
| @@ -265,7 +264,6 @@ static void orinoco_nortel_remove_one(struct pci_dev *pdev) | |||
| 265 | 264 | ||
| 266 | orinoco_if_del(priv); | 265 | orinoco_if_del(priv); |
| 267 | free_irq(pdev->irq, priv); | 266 | free_irq(pdev->irq, priv); |
| 268 | pci_set_drvdata(pdev, NULL); | ||
| 269 | free_orinocodev(priv); | 267 | free_orinocodev(priv); |
| 270 | pci_iounmap(pdev, priv->hw.iobase); | 268 | pci_iounmap(pdev, priv->hw.iobase); |
| 271 | pci_iounmap(pdev, card->attr_io); | 269 | pci_iounmap(pdev, card->attr_io); |
diff --git a/drivers/net/wireless/orinoco/orinoco_pci.c b/drivers/net/wireless/orinoco/orinoco_pci.c index 677bf14eca84..5ae1191d2532 100644 --- a/drivers/net/wireless/orinoco/orinoco_pci.c +++ b/drivers/net/wireless/orinoco/orinoco_pci.c | |||
| @@ -184,7 +184,6 @@ static int orinoco_pci_init_one(struct pci_dev *pdev, | |||
| 184 | free_irq(pdev->irq, priv); | 184 | free_irq(pdev->irq, priv); |
| 185 | 185 | ||
| 186 | fail_irq: | 186 | fail_irq: |
| 187 | pci_set_drvdata(pdev, NULL); | ||
| 188 | free_orinocodev(priv); | 187 | free_orinocodev(priv); |
| 189 | 188 | ||
| 190 | fail_alloc: | 189 | fail_alloc: |
| @@ -205,7 +204,6 @@ static void orinoco_pci_remove_one(struct pci_dev *pdev) | |||
| 205 | 204 | ||
| 206 | orinoco_if_del(priv); | 205 | orinoco_if_del(priv); |
| 207 | free_irq(pdev->irq, priv); | 206 | free_irq(pdev->irq, priv); |
| 208 | pci_set_drvdata(pdev, NULL); | ||
| 209 | free_orinocodev(priv); | 207 | free_orinocodev(priv); |
| 210 | pci_iounmap(pdev, priv->hw.iobase); | 208 | pci_iounmap(pdev, priv->hw.iobase); |
| 211 | pci_release_regions(pdev); | 209 | pci_release_regions(pdev); |
diff --git a/drivers/net/wireless/orinoco/orinoco_plx.c b/drivers/net/wireless/orinoco/orinoco_plx.c index 2559dbd6184b..bbd36d1676ff 100644 --- a/drivers/net/wireless/orinoco/orinoco_plx.c +++ b/drivers/net/wireless/orinoco/orinoco_plx.c | |||
| @@ -273,7 +273,6 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, | |||
| 273 | free_irq(pdev->irq, priv); | 273 | free_irq(pdev->irq, priv); |
| 274 | 274 | ||
| 275 | fail_irq: | 275 | fail_irq: |
| 276 | pci_set_drvdata(pdev, NULL); | ||
| 277 | free_orinocodev(priv); | 276 | free_orinocodev(priv); |
| 278 | 277 | ||
| 279 | fail_alloc: | 278 | fail_alloc: |
| @@ -301,7 +300,6 @@ static void orinoco_plx_remove_one(struct pci_dev *pdev) | |||
| 301 | 300 | ||
| 302 | orinoco_if_del(priv); | 301 | orinoco_if_del(priv); |
| 303 | free_irq(pdev->irq, priv); | 302 | free_irq(pdev->irq, priv); |
| 304 | pci_set_drvdata(pdev, NULL); | ||
| 305 | free_orinocodev(priv); | 303 | free_orinocodev(priv); |
| 306 | pci_iounmap(pdev, priv->hw.iobase); | 304 | pci_iounmap(pdev, priv->hw.iobase); |
| 307 | pci_iounmap(pdev, card->attr_io); | 305 | pci_iounmap(pdev, card->attr_io); |
diff --git a/drivers/net/wireless/orinoco/orinoco_tmd.c b/drivers/net/wireless/orinoco/orinoco_tmd.c index 42afeeea2c40..04b08de5fd5d 100644 --- a/drivers/net/wireless/orinoco/orinoco_tmd.c +++ b/drivers/net/wireless/orinoco/orinoco_tmd.c | |||
| @@ -170,7 +170,6 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev, | |||
| 170 | free_irq(pdev->irq, priv); | 170 | free_irq(pdev->irq, priv); |
| 171 | 171 | ||
| 172 | fail_irq: | 172 | fail_irq: |
| 173 | pci_set_drvdata(pdev, NULL); | ||
| 174 | free_orinocodev(priv); | 173 | free_orinocodev(priv); |
| 175 | 174 | ||
| 176 | fail_alloc: | 175 | fail_alloc: |
| @@ -195,7 +194,6 @@ static void orinoco_tmd_remove_one(struct pci_dev *pdev) | |||
| 195 | 194 | ||
| 196 | orinoco_if_del(priv); | 195 | orinoco_if_del(priv); |
| 197 | free_irq(pdev->irq, priv); | 196 | free_irq(pdev->irq, priv); |
| 198 | pci_set_drvdata(pdev, NULL); | ||
| 199 | free_orinocodev(priv); | 197 | free_orinocodev(priv); |
| 200 | pci_iounmap(pdev, priv->hw.iobase); | 198 | pci_iounmap(pdev, priv->hw.iobase); |
| 201 | pci_iounmap(pdev, card->bridge_io); | 199 | pci_iounmap(pdev, card->bridge_io); |
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 57e3af8ebb4b..f9a07b0d83ac 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c | |||
| @@ -631,7 +631,6 @@ static int p54p_probe(struct pci_dev *pdev, | |||
| 631 | iounmap(priv->map); | 631 | iounmap(priv->map); |
| 632 | 632 | ||
| 633 | err_free_dev: | 633 | err_free_dev: |
| 634 | pci_set_drvdata(pdev, NULL); | ||
| 635 | p54_free_common(dev); | 634 | p54_free_common(dev); |
| 636 | 635 | ||
| 637 | err_free_reg: | 636 | err_free_reg: |
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index 7fc46f26cf2b..de15171e2cd8 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c | |||
| @@ -636,7 +636,7 @@ static int p54spi_probe(struct spi_device *spi) | |||
| 636 | gpio_direction_input(p54spi_gpio_irq); | 636 | gpio_direction_input(p54spi_gpio_irq); |
| 637 | 637 | ||
| 638 | ret = request_irq(gpio_to_irq(p54spi_gpio_irq), | 638 | ret = request_irq(gpio_to_irq(p54spi_gpio_irq), |
| 639 | p54spi_interrupt, IRQF_DISABLED, "p54spi", | 639 | p54spi_interrupt, 0, "p54spi", |
| 640 | priv->spi); | 640 | priv->spi); |
| 641 | if (ret < 0) { | 641 | if (ret < 0) { |
| 642 | dev_err(&priv->spi->dev, "request_irq() failed"); | 642 | dev_err(&priv->spi->dev, "request_irq() failed"); |
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 1c22b81e6ef3..8863a6cb2388 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c | |||
| @@ -183,7 +183,7 @@ prism54_update_stats(struct work_struct *work) | |||
| 183 | data = r.ptr; | 183 | data = r.ptr; |
| 184 | 184 | ||
| 185 | /* copy this MAC to the bss */ | 185 | /* copy this MAC to the bss */ |
| 186 | memcpy(bss.address, data, 6); | 186 | memcpy(bss.address, data, ETH_ALEN); |
| 187 | kfree(data); | 187 | kfree(data); |
| 188 | 188 | ||
| 189 | /* now ask for the corresponding bss */ | 189 | /* now ask for the corresponding bss */ |
| @@ -531,7 +531,7 @@ prism54_set_wap(struct net_device *ndev, struct iw_request_info *info, | |||
| 531 | return -EINVAL; | 531 | return -EINVAL; |
| 532 | 532 | ||
| 533 | /* prepare the structure for the set object */ | 533 | /* prepare the structure for the set object */ |
| 534 | memcpy(&bssid[0], awrq->sa_data, 6); | 534 | memcpy(&bssid[0], awrq->sa_data, ETH_ALEN); |
| 535 | 535 | ||
| 536 | /* set the bssid -- does this make sense when in AP mode? */ | 536 | /* set the bssid -- does this make sense when in AP mode? */ |
| 537 | rvalue = mgt_set_request(priv, DOT11_OID_BSSID, 0, &bssid); | 537 | rvalue = mgt_set_request(priv, DOT11_OID_BSSID, 0, &bssid); |
| @@ -550,7 +550,7 @@ prism54_get_wap(struct net_device *ndev, struct iw_request_info *info, | |||
| 550 | int rvalue; | 550 | int rvalue; |
| 551 | 551 | ||
| 552 | rvalue = mgt_get_request(priv, DOT11_OID_BSSID, 0, NULL, &r); | 552 | rvalue = mgt_get_request(priv, DOT11_OID_BSSID, 0, NULL, &r); |
| 553 | memcpy(awrq->sa_data, r.ptr, 6); | 553 | memcpy(awrq->sa_data, r.ptr, ETH_ALEN); |
| 554 | awrq->sa_family = ARPHRD_ETHER; | 554 | awrq->sa_family = ARPHRD_ETHER; |
| 555 | kfree(r.ptr); | 555 | kfree(r.ptr); |
| 556 | 556 | ||
| @@ -582,7 +582,7 @@ prism54_translate_bss(struct net_device *ndev, struct iw_request_info *info, | |||
| 582 | size_t wpa_ie_len; | 582 | size_t wpa_ie_len; |
| 583 | 583 | ||
| 584 | /* The first entry must be the MAC address */ | 584 | /* The first entry must be the MAC address */ |
| 585 | memcpy(iwe.u.ap_addr.sa_data, bss->address, 6); | 585 | memcpy(iwe.u.ap_addr.sa_data, bss->address, ETH_ALEN); |
| 586 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | 586 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; |
| 587 | iwe.cmd = SIOCGIWAP; | 587 | iwe.cmd = SIOCGIWAP; |
| 588 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, | 588 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, |
| @@ -2489,7 +2489,7 @@ prism54_set_mac_address(struct net_device *ndev, void *addr) | |||
| 2489 | &((struct sockaddr *) addr)->sa_data); | 2489 | &((struct sockaddr *) addr)->sa_data); |
| 2490 | if (!ret) | 2490 | if (!ret) |
| 2491 | memcpy(priv->ndev->dev_addr, | 2491 | memcpy(priv->ndev->dev_addr, |
| 2492 | &((struct sockaddr *) addr)->sa_data, 6); | 2492 | &((struct sockaddr *) addr)->sa_data, ETH_ALEN); |
| 2493 | 2493 | ||
| 2494 | return ret; | 2494 | return ret; |
| 2495 | } | 2495 | } |
diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index 5970ff6f40cc..41a16d30c79c 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c | |||
| @@ -837,7 +837,7 @@ islpci_setup(struct pci_dev *pdev) | |||
| 837 | /* ndev->set_multicast_list = &islpci_set_multicast_list; */ | 837 | /* ndev->set_multicast_list = &islpci_set_multicast_list; */ |
| 838 | ndev->addr_len = ETH_ALEN; | 838 | ndev->addr_len = ETH_ALEN; |
| 839 | /* Get a non-zero dummy MAC address for nameif. Jean II */ | 839 | /* Get a non-zero dummy MAC address for nameif. Jean II */ |
| 840 | memcpy(ndev->dev_addr, dummy_mac, 6); | 840 | memcpy(ndev->dev_addr, dummy_mac, ETH_ALEN); |
| 841 | 841 | ||
| 842 | ndev->watchdog_timeo = ISLPCI_TX_TIMEOUT; | 842 | ndev->watchdog_timeo = ISLPCI_TX_TIMEOUT; |
| 843 | 843 | ||
diff --git a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c index a01606b36e03..056af38e72e3 100644 --- a/drivers/net/wireless/prism54/oid_mgt.c +++ b/drivers/net/wireless/prism54/oid_mgt.c | |||
| @@ -682,7 +682,7 @@ mgt_update_addr(islpci_private *priv) | |||
| 682 | isl_oid[GEN_OID_MACADDRESS].size, &res); | 682 | isl_oid[GEN_OID_MACADDRESS].size, &res); |
| 683 | 683 | ||
| 684 | if ((ret == 0) && res && (res->header->operation != PIMFOR_OP_ERROR)) | 684 | if ((ret == 0) && res && (res->header->operation != PIMFOR_OP_ERROR)) |
| 685 | memcpy(priv->ndev->dev_addr, res->data, 6); | 685 | memcpy(priv->ndev->dev_addr, res->data, ETH_ALEN); |
| 686 | else | 686 | else |
| 687 | ret = -EIO; | 687 | ret = -EIO; |
| 688 | if (res) | 688 | if (res) |
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 68dbbb9c6d12..006b8bcb2e31 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig | |||
| @@ -58,11 +58,11 @@ config RT61PCI | |||
| 58 | 58 | ||
| 59 | config RT2800PCI | 59 | config RT2800PCI |
| 60 | tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support" | 60 | tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support" |
| 61 | depends on PCI || SOC_RT288X || SOC_RT305X | 61 | depends on PCI |
| 62 | select RT2800_LIB | 62 | select RT2800_LIB |
| 63 | select RT2800_LIB_MMIO | ||
| 63 | select RT2X00_LIB_MMIO | 64 | select RT2X00_LIB_MMIO |
| 64 | select RT2X00_LIB_PCI if PCI | 65 | select RT2X00_LIB_PCI |
| 65 | select RT2X00_LIB_SOC if SOC_RT288X || SOC_RT305X | ||
| 66 | select RT2X00_LIB_FIRMWARE | 66 | select RT2X00_LIB_FIRMWARE |
| 67 | select RT2X00_LIB_CRYPTO | 67 | select RT2X00_LIB_CRYPTO |
| 68 | select CRC_CCITT | 68 | select CRC_CCITT |
| @@ -199,9 +199,30 @@ config RT2800USB_UNKNOWN | |||
| 199 | 199 | ||
| 200 | endif | 200 | endif |
| 201 | 201 | ||
| 202 | config RT2800SOC | ||
| 203 | tristate "Ralink WiSoC support" | ||
| 204 | depends on SOC_RT288X || SOC_RT305X | ||
| 205 | select RT2X00_LIB_SOC | ||
| 206 | select RT2X00_LIB_MMIO | ||
| 207 | select RT2X00_LIB_CRYPTO | ||
| 208 | select RT2X00_LIB_FIRMWARE | ||
| 209 | select RT2800_LIB | ||
| 210 | select RT2800_LIB_MMIO | ||
| 211 | ---help--- | ||
| 212 | This adds support for Ralink WiSoC devices. | ||
| 213 | Supported chips: RT2880, RT3050, RT3052, RT3350, RT3352. | ||
| 214 | |||
| 215 | When compiled as a module, this driver will be called rt2800soc. | ||
| 216 | |||
| 217 | |||
| 202 | config RT2800_LIB | 218 | config RT2800_LIB |
| 203 | tristate | 219 | tristate |
| 204 | 220 | ||
| 221 | config RT2800_LIB_MMIO | ||
| 222 | tristate | ||
| 223 | select RT2X00_LIB_MMIO | ||
| 224 | select RT2800_LIB | ||
| 225 | |||
| 205 | config RT2X00_LIB_MMIO | 226 | config RT2X00_LIB_MMIO |
| 206 | tristate | 227 | tristate |
| 207 | 228 | ||
| @@ -219,6 +240,7 @@ config RT2X00_LIB_USB | |||
| 219 | 240 | ||
| 220 | config RT2X00_LIB | 241 | config RT2X00_LIB |
| 221 | tristate | 242 | tristate |
| 243 | select AVERAGE | ||
| 222 | 244 | ||
| 223 | config RT2X00_LIB_FIRMWARE | 245 | config RT2X00_LIB_FIRMWARE |
| 224 | boolean | 246 | boolean |
diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile index f069d8bc5b67..24a66015a495 100644 --- a/drivers/net/wireless/rt2x00/Makefile +++ b/drivers/net/wireless/rt2x00/Makefile | |||
| @@ -14,6 +14,7 @@ obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o | |||
| 14 | obj-$(CONFIG_RT2X00_LIB_SOC) += rt2x00soc.o | 14 | obj-$(CONFIG_RT2X00_LIB_SOC) += rt2x00soc.o |
| 15 | obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o | 15 | obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o |
| 16 | obj-$(CONFIG_RT2800_LIB) += rt2800lib.o | 16 | obj-$(CONFIG_RT2800_LIB) += rt2800lib.o |
| 17 | obj-$(CONFIG_RT2800_LIB_MMIO) += rt2800mmio.o | ||
| 17 | obj-$(CONFIG_RT2400PCI) += rt2400pci.o | 18 | obj-$(CONFIG_RT2400PCI) += rt2400pci.o |
| 18 | obj-$(CONFIG_RT2500PCI) += rt2500pci.o | 19 | obj-$(CONFIG_RT2500PCI) += rt2500pci.o |
| 19 | obj-$(CONFIG_RT61PCI) += rt61pci.o | 20 | obj-$(CONFIG_RT61PCI) += rt61pci.o |
| @@ -21,3 +22,4 @@ obj-$(CONFIG_RT2800PCI) += rt2800pci.o | |||
| 21 | obj-$(CONFIG_RT2500USB) += rt2500usb.o | 22 | obj-$(CONFIG_RT2500USB) += rt2500usb.o |
| 22 | obj-$(CONFIG_RT73USB) += rt73usb.o | 23 | obj-$(CONFIG_RT73USB) += rt73usb.o |
| 23 | obj-$(CONFIG_RT2800USB) += rt2800usb.o | 24 | obj-$(CONFIG_RT2800USB) += rt2800usb.o |
| 25 | obj-$(CONFIG_RT2800SOC) += rt2800soc.o | ||
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 3d53a09da5a1..38ed9a3e44c8 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
| @@ -1261,7 +1261,7 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry, | |||
| 1261 | */ | 1261 | */ |
| 1262 | rxdesc->timestamp = ((u64)rx_high << 32) | rx_low; | 1262 | rxdesc->timestamp = ((u64)rx_high << 32) | rx_low; |
| 1263 | rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL) & ~0x08; | 1263 | rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL) & ~0x08; |
| 1264 | rxdesc->rssi = rt2x00_get_field32(word2, RXD_W3_RSSI) - | 1264 | rxdesc->rssi = rt2x00_get_field32(word3, RXD_W3_RSSI) - |
| 1265 | entry->queue->rt2x00dev->rssi_offset; | 1265 | entry->queue->rt2x00dev->rssi_offset; |
| 1266 | rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); | 1266 | rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); |
| 1267 | 1267 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index fa33b5edf931..aab6b5e4f5dd 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
| @@ -52,6 +52,7 @@ | |||
| 52 | * RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392) | 52 | * RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392) |
| 53 | * RF3053 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662) | 53 | * RF3053 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662) |
| 54 | * RF5592 2.4G/5G 2T2R | 54 | * RF5592 2.4G/5G 2T2R |
| 55 | * RF3070 2.4G 1T1R | ||
| 55 | * RF5360 2.4G 1T1R | 56 | * RF5360 2.4G 1T1R |
| 56 | * RF5370 2.4G 1T1R | 57 | * RF5370 2.4G 1T1R |
| 57 | * RF5390 2.4G 1T1R | 58 | * RF5390 2.4G 1T1R |
| @@ -70,6 +71,7 @@ | |||
| 70 | #define RF3322 0x000c | 71 | #define RF3322 0x000c |
| 71 | #define RF3053 0x000d | 72 | #define RF3053 0x000d |
| 72 | #define RF5592 0x000f | 73 | #define RF5592 0x000f |
| 74 | #define RF3070 0x3070 | ||
| 73 | #define RF3290 0x3290 | 75 | #define RF3290 0x3290 |
| 74 | #define RF5360 0x5360 | 76 | #define RF5360 0x5360 |
| 75 | #define RF5370 0x5370 | 77 | #define RF5370 0x5370 |
| @@ -122,7 +124,7 @@ | |||
| 122 | /* | 124 | /* |
| 123 | * MAC_CSR0_3290: MAC_CSR0 for RT3290 to identity MAC version number. | 125 | * MAC_CSR0_3290: MAC_CSR0 for RT3290 to identity MAC version number. |
| 124 | */ | 126 | */ |
| 125 | #define MAC_CSR0_3290 0x0000 | 127 | #define MAC_CSR0_3290 0x0000 |
| 126 | 128 | ||
| 127 | /* | 129 | /* |
| 128 | * E2PROM_CSR: PCI EEPROM control register. | 130 | * E2PROM_CSR: PCI EEPROM control register. |
| @@ -211,17 +213,17 @@ | |||
| 211 | /* | 213 | /* |
| 212 | * COEX_CFG_0 | 214 | * COEX_CFG_0 |
| 213 | */ | 215 | */ |
| 214 | #define COEX_CFG0 0x0040 | 216 | #define COEX_CFG0 0x0040 |
| 215 | #define COEX_CFG_ANT FIELD32(0xff000000) | 217 | #define COEX_CFG_ANT FIELD32(0xff000000) |
| 216 | /* | 218 | /* |
| 217 | * COEX_CFG_1 | 219 | * COEX_CFG_1 |
| 218 | */ | 220 | */ |
| 219 | #define COEX_CFG1 0x0044 | 221 | #define COEX_CFG1 0x0044 |
| 220 | 222 | ||
| 221 | /* | 223 | /* |
| 222 | * COEX_CFG_2 | 224 | * COEX_CFG_2 |
| 223 | */ | 225 | */ |
| 224 | #define COEX_CFG2 0x0048 | 226 | #define COEX_CFG2 0x0048 |
| 225 | #define BT_COEX_CFG1 FIELD32(0xff000000) | 227 | #define BT_COEX_CFG1 FIELD32(0xff000000) |
| 226 | #define BT_COEX_CFG0 FIELD32(0x00ff0000) | 228 | #define BT_COEX_CFG0 FIELD32(0x00ff0000) |
| 227 | #define WL_COEX_CFG1 FIELD32(0x0000ff00) | 229 | #define WL_COEX_CFG1 FIELD32(0x0000ff00) |
| @@ -235,8 +237,8 @@ | |||
| 235 | #define PLL_RESERVED_INPUT2 FIELD32(0x0000ff00) | 237 | #define PLL_RESERVED_INPUT2 FIELD32(0x0000ff00) |
| 236 | #define PLL_CONTROL FIELD32(0x00070000) | 238 | #define PLL_CONTROL FIELD32(0x00070000) |
| 237 | #define PLL_LPF_R1 FIELD32(0x00080000) | 239 | #define PLL_LPF_R1 FIELD32(0x00080000) |
| 238 | #define PLL_LPF_C1_CTRL FIELD32(0x00300000) | 240 | #define PLL_LPF_C1_CTRL FIELD32(0x00300000) |
| 239 | #define PLL_LPF_C2_CTRL FIELD32(0x00c00000) | 241 | #define PLL_LPF_C2_CTRL FIELD32(0x00c00000) |
| 240 | #define PLL_CP_CURRENT_CTRL FIELD32(0x03000000) | 242 | #define PLL_CP_CURRENT_CTRL FIELD32(0x03000000) |
| 241 | #define PLL_PFD_DELAY_CTRL FIELD32(0x0c000000) | 243 | #define PLL_PFD_DELAY_CTRL FIELD32(0x0c000000) |
| 242 | #define PLL_LOCK_CTRL FIELD32(0x70000000) | 244 | #define PLL_LOCK_CTRL FIELD32(0x70000000) |
| @@ -2164,7 +2166,7 @@ struct mac_iveiv_entry { | |||
| 2164 | */ | 2166 | */ |
| 2165 | #define RFCSR6_R1 FIELD8(0x03) | 2167 | #define RFCSR6_R1 FIELD8(0x03) |
| 2166 | #define RFCSR6_R2 FIELD8(0x40) | 2168 | #define RFCSR6_R2 FIELD8(0x40) |
| 2167 | #define RFCSR6_TXDIV FIELD8(0x0c) | 2169 | #define RFCSR6_TXDIV FIELD8(0x0c) |
| 2168 | /* bits for RF3053 */ | 2170 | /* bits for RF3053 */ |
| 2169 | #define RFCSR6_VCO_IC FIELD8(0xc0) | 2171 | #define RFCSR6_VCO_IC FIELD8(0xc0) |
| 2170 | 2172 | ||
| @@ -2202,13 +2204,13 @@ struct mac_iveiv_entry { | |||
| 2202 | * RFCSR 12: | 2204 | * RFCSR 12: |
| 2203 | */ | 2205 | */ |
| 2204 | #define RFCSR12_TX_POWER FIELD8(0x1f) | 2206 | #define RFCSR12_TX_POWER FIELD8(0x1f) |
| 2205 | #define RFCSR12_DR0 FIELD8(0xe0) | 2207 | #define RFCSR12_DR0 FIELD8(0xe0) |
| 2206 | 2208 | ||
| 2207 | /* | 2209 | /* |
| 2208 | * RFCSR 13: | 2210 | * RFCSR 13: |
| 2209 | */ | 2211 | */ |
| 2210 | #define RFCSR13_TX_POWER FIELD8(0x1f) | 2212 | #define RFCSR13_TX_POWER FIELD8(0x1f) |
| 2211 | #define RFCSR13_DR0 FIELD8(0xe0) | 2213 | #define RFCSR13_DR0 FIELD8(0xe0) |
| 2212 | 2214 | ||
| 2213 | /* | 2215 | /* |
| 2214 | * RFCSR 15: | 2216 | * RFCSR 15: |
| @@ -2226,7 +2228,7 @@ struct mac_iveiv_entry { | |||
| 2226 | #define RFCSR17_TXMIXER_GAIN FIELD8(0x07) | 2228 | #define RFCSR17_TXMIXER_GAIN FIELD8(0x07) |
| 2227 | #define RFCSR17_TX_LO1_EN FIELD8(0x08) | 2229 | #define RFCSR17_TX_LO1_EN FIELD8(0x08) |
| 2228 | #define RFCSR17_R FIELD8(0x20) | 2230 | #define RFCSR17_R FIELD8(0x20) |
| 2229 | #define RFCSR17_CODE FIELD8(0x7f) | 2231 | #define RFCSR17_CODE FIELD8(0x7f) |
| 2230 | 2232 | ||
| 2231 | /* RFCSR 18 */ | 2233 | /* RFCSR 18 */ |
| 2232 | #define RFCSR18_XO_TUNE_BYPASS FIELD8(0x40) | 2234 | #define RFCSR18_XO_TUNE_BYPASS FIELD8(0x40) |
| @@ -2449,7 +2451,7 @@ enum rt2800_eeprom_word { | |||
| 2449 | */ | 2451 | */ |
| 2450 | #define EEPROM_NIC_CONF0_RXPATH FIELD16(0x000f) | 2452 | #define EEPROM_NIC_CONF0_RXPATH FIELD16(0x000f) |
| 2451 | #define EEPROM_NIC_CONF0_TXPATH FIELD16(0x00f0) | 2453 | #define EEPROM_NIC_CONF0_TXPATH FIELD16(0x00f0) |
| 2452 | #define EEPROM_NIC_CONF0_RF_TYPE FIELD16(0x0f00) | 2454 | #define EEPROM_NIC_CONF0_RF_TYPE FIELD16(0x0f00) |
| 2453 | 2455 | ||
| 2454 | /* | 2456 | /* |
| 2455 | * EEPROM NIC Configuration 1 | 2457 | * EEPROM NIC Configuration 1 |
| @@ -2471,18 +2473,18 @@ enum rt2800_eeprom_word { | |||
| 2471 | * DAC_TEST: 0: disable, 1: enable | 2473 | * DAC_TEST: 0: disable, 1: enable |
| 2472 | */ | 2474 | */ |
| 2473 | #define EEPROM_NIC_CONF1_HW_RADIO FIELD16(0x0001) | 2475 | #define EEPROM_NIC_CONF1_HW_RADIO FIELD16(0x0001) |
| 2474 | #define EEPROM_NIC_CONF1_EXTERNAL_TX_ALC FIELD16(0x0002) | 2476 | #define EEPROM_NIC_CONF1_EXTERNAL_TX_ALC FIELD16(0x0002) |
| 2475 | #define EEPROM_NIC_CONF1_EXTERNAL_LNA_2G FIELD16(0x0004) | 2477 | #define EEPROM_NIC_CONF1_EXTERNAL_LNA_2G FIELD16(0x0004) |
| 2476 | #define EEPROM_NIC_CONF1_EXTERNAL_LNA_5G FIELD16(0x0008) | 2478 | #define EEPROM_NIC_CONF1_EXTERNAL_LNA_5G FIELD16(0x0008) |
| 2477 | #define EEPROM_NIC_CONF1_CARDBUS_ACCEL FIELD16(0x0010) | 2479 | #define EEPROM_NIC_CONF1_CARDBUS_ACCEL FIELD16(0x0010) |
| 2478 | #define EEPROM_NIC_CONF1_BW40M_SB_2G FIELD16(0x0020) | 2480 | #define EEPROM_NIC_CONF1_BW40M_SB_2G FIELD16(0x0020) |
| 2479 | #define EEPROM_NIC_CONF1_BW40M_SB_5G FIELD16(0x0040) | 2481 | #define EEPROM_NIC_CONF1_BW40M_SB_5G FIELD16(0x0040) |
| 2480 | #define EEPROM_NIC_CONF1_WPS_PBC FIELD16(0x0080) | 2482 | #define EEPROM_NIC_CONF1_WPS_PBC FIELD16(0x0080) |
| 2481 | #define EEPROM_NIC_CONF1_BW40M_2G FIELD16(0x0100) | 2483 | #define EEPROM_NIC_CONF1_BW40M_2G FIELD16(0x0100) |
| 2482 | #define EEPROM_NIC_CONF1_BW40M_5G FIELD16(0x0200) | 2484 | #define EEPROM_NIC_CONF1_BW40M_5G FIELD16(0x0200) |
| 2483 | #define EEPROM_NIC_CONF1_BROADBAND_EXT_LNA FIELD16(0x400) | 2485 | #define EEPROM_NIC_CONF1_BROADBAND_EXT_LNA FIELD16(0x400) |
| 2484 | #define EEPROM_NIC_CONF1_ANT_DIVERSITY FIELD16(0x1800) | 2486 | #define EEPROM_NIC_CONF1_ANT_DIVERSITY FIELD16(0x1800) |
| 2485 | #define EEPROM_NIC_CONF1_INTERNAL_TX_ALC FIELD16(0x2000) | 2487 | #define EEPROM_NIC_CONF1_INTERNAL_TX_ALC FIELD16(0x2000) |
| 2486 | #define EEPROM_NIC_CONF1_BT_COEXIST FIELD16(0x4000) | 2488 | #define EEPROM_NIC_CONF1_BT_COEXIST FIELD16(0x4000) |
| 2487 | #define EEPROM_NIC_CONF1_DAC_TEST FIELD16(0x8000) | 2489 | #define EEPROM_NIC_CONF1_DAC_TEST FIELD16(0x8000) |
| 2488 | 2490 | ||
| @@ -2521,9 +2523,9 @@ enum rt2800_eeprom_word { | |||
| 2521 | * TX_STREAM: 0: Reserved, 1: 1 Stream, 2: 2 Stream | 2523 | * TX_STREAM: 0: Reserved, 1: 1 Stream, 2: 2 Stream |
| 2522 | * CRYSTAL: 00: Reserved, 01: One crystal, 10: Two crystal, 11: Reserved | 2524 | * CRYSTAL: 00: Reserved, 01: One crystal, 10: Two crystal, 11: Reserved |
| 2523 | */ | 2525 | */ |
| 2524 | #define EEPROM_NIC_CONF2_RX_STREAM FIELD16(0x000f) | 2526 | #define EEPROM_NIC_CONF2_RX_STREAM FIELD16(0x000f) |
| 2525 | #define EEPROM_NIC_CONF2_TX_STREAM FIELD16(0x00f0) | 2527 | #define EEPROM_NIC_CONF2_TX_STREAM FIELD16(0x00f0) |
| 2526 | #define EEPROM_NIC_CONF2_CRYSTAL FIELD16(0x0600) | 2528 | #define EEPROM_NIC_CONF2_CRYSTAL FIELD16(0x0600) |
| 2527 | 2529 | ||
| 2528 | /* | 2530 | /* |
| 2529 | * EEPROM LNA | 2531 | * EEPROM LNA |
| @@ -2790,7 +2792,7 @@ enum rt2800_eeprom_word { | |||
| 2790 | #define MCU_CURRENT 0x36 | 2792 | #define MCU_CURRENT 0x36 |
| 2791 | #define MCU_LED 0x50 | 2793 | #define MCU_LED 0x50 |
| 2792 | #define MCU_LED_STRENGTH 0x51 | 2794 | #define MCU_LED_STRENGTH 0x51 |
| 2793 | #define MCU_LED_AG_CONF 0x52 | 2795 | #define MCU_LED_AG_CONF 0x52 |
| 2794 | #define MCU_LED_ACT_CONF 0x53 | 2796 | #define MCU_LED_ACT_CONF 0x53 |
| 2795 | #define MCU_LED_LED_POLARITY 0x54 | 2797 | #define MCU_LED_LED_POLARITY 0x54 |
| 2796 | #define MCU_RADAR 0x60 | 2798 | #define MCU_RADAR 0x60 |
| @@ -2799,7 +2801,7 @@ enum rt2800_eeprom_word { | |||
| 2799 | #define MCU_FREQ_OFFSET 0x74 | 2801 | #define MCU_FREQ_OFFSET 0x74 |
| 2800 | #define MCU_BBP_SIGNAL 0x80 | 2802 | #define MCU_BBP_SIGNAL 0x80 |
| 2801 | #define MCU_POWER_SAVE 0x83 | 2803 | #define MCU_POWER_SAVE 0x83 |
| 2802 | #define MCU_BAND_SELECT 0x91 | 2804 | #define MCU_BAND_SELECT 0x91 |
| 2803 | 2805 | ||
| 2804 | /* | 2806 | /* |
| 2805 | * MCU mailbox tokens | 2807 | * MCU mailbox tokens |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 88ce656f96cd..c5738f14c4ba 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
| @@ -278,12 +278,9 @@ static const unsigned int rt2800_eeprom_map_ext[EEPROM_WORD_COUNT] = { | |||
| 278 | [EEPROM_LNA] = 0x0026, | 278 | [EEPROM_LNA] = 0x0026, |
| 279 | [EEPROM_EXT_LNA2] = 0x0027, | 279 | [EEPROM_EXT_LNA2] = 0x0027, |
| 280 | [EEPROM_RSSI_BG] = 0x0028, | 280 | [EEPROM_RSSI_BG] = 0x0028, |
| 281 | [EEPROM_TXPOWER_DELTA] = 0x0028, /* Overlaps with RSSI_BG */ | ||
| 282 | [EEPROM_RSSI_BG2] = 0x0029, | 281 | [EEPROM_RSSI_BG2] = 0x0029, |
| 283 | [EEPROM_TXMIXER_GAIN_BG] = 0x0029, /* Overlaps with RSSI_BG2 */ | ||
| 284 | [EEPROM_RSSI_A] = 0x002a, | 282 | [EEPROM_RSSI_A] = 0x002a, |
| 285 | [EEPROM_RSSI_A2] = 0x002b, | 283 | [EEPROM_RSSI_A2] = 0x002b, |
| 286 | [EEPROM_TXMIXER_GAIN_A] = 0x002b, /* Overlaps with RSSI_A2 */ | ||
| 287 | [EEPROM_TXPOWER_BG1] = 0x0030, | 284 | [EEPROM_TXPOWER_BG1] = 0x0030, |
| 288 | [EEPROM_TXPOWER_BG2] = 0x0037, | 285 | [EEPROM_TXPOWER_BG2] = 0x0037, |
| 289 | [EEPROM_EXT_TXPOWER_BG3] = 0x003e, | 286 | [EEPROM_EXT_TXPOWER_BG3] = 0x003e, |
| @@ -1783,7 +1780,7 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant) | |||
| 1783 | rt2800_bbp_read(rt2x00dev, 3, &r3); | 1780 | rt2800_bbp_read(rt2x00dev, 3, &r3); |
| 1784 | 1781 | ||
| 1785 | if (rt2x00_rt(rt2x00dev, RT3572) && | 1782 | if (rt2x00_rt(rt2x00dev, RT3572) && |
| 1786 | test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) | 1783 | rt2x00_has_cap_bt_coexist(rt2x00dev)) |
| 1787 | rt2800_config_3572bt_ant(rt2x00dev); | 1784 | rt2800_config_3572bt_ant(rt2x00dev); |
| 1788 | 1785 | ||
| 1789 | /* | 1786 | /* |
| @@ -1795,7 +1792,7 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant) | |||
| 1795 | break; | 1792 | break; |
| 1796 | case 2: | 1793 | case 2: |
| 1797 | if (rt2x00_rt(rt2x00dev, RT3572) && | 1794 | if (rt2x00_rt(rt2x00dev, RT3572) && |
| 1798 | test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) | 1795 | rt2x00_has_cap_bt_coexist(rt2x00dev)) |
| 1799 | rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 1); | 1796 | rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 1); |
| 1800 | else | 1797 | else |
| 1801 | rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); | 1798 | rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); |
| @@ -1825,7 +1822,7 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant) | |||
| 1825 | break; | 1822 | break; |
| 1826 | case 2: | 1823 | case 2: |
| 1827 | if (rt2x00_rt(rt2x00dev, RT3572) && | 1824 | if (rt2x00_rt(rt2x00dev, RT3572) && |
| 1828 | test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { | 1825 | rt2x00_has_cap_bt_coexist(rt2x00dev)) { |
| 1829 | rt2x00_set_field8(&r3, BBP3_RX_ADC, 1); | 1826 | rt2x00_set_field8(&r3, BBP3_RX_ADC, 1); |
| 1830 | rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, | 1827 | rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, |
| 1831 | rt2x00dev->curr_band == IEEE80211_BAND_5GHZ); | 1828 | rt2x00dev->curr_band == IEEE80211_BAND_5GHZ); |
| @@ -2029,13 +2026,6 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev, | |||
| 2029 | rt2x00dev->default_ant.tx_chain_num <= 2); | 2026 | rt2x00dev->default_ant.tx_chain_num <= 2); |
| 2030 | rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); | 2027 | rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); |
| 2031 | 2028 | ||
| 2032 | rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); | ||
| 2033 | rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1); | ||
| 2034 | rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); | ||
| 2035 | msleep(1); | ||
| 2036 | rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); | ||
| 2037 | rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); | ||
| 2038 | |||
| 2039 | rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); | 2029 | rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); |
| 2040 | rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); | 2030 | rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); |
| 2041 | rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); | 2031 | rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); |
| @@ -2141,7 +2131,7 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, | |||
| 2141 | rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); | 2131 | rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); |
| 2142 | rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); | 2132 | rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); |
| 2143 | rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); | 2133 | rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); |
| 2144 | if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { | 2134 | if (rt2x00_has_cap_bt_coexist(rt2x00dev)) { |
| 2145 | if (rf->channel <= 14) { | 2135 | if (rf->channel <= 14) { |
| 2146 | rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); | 2136 | rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); |
| 2147 | rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); | 2137 | rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); |
| @@ -2674,7 +2664,7 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, | |||
| 2674 | if (rf->channel <= 14) { | 2664 | if (rf->channel <= 14) { |
| 2675 | int idx = rf->channel-1; | 2665 | int idx = rf->channel-1; |
| 2676 | 2666 | ||
| 2677 | if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { | 2667 | if (rt2x00_has_cap_bt_coexist(rt2x00dev)) { |
| 2678 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) { | 2668 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) { |
| 2679 | /* r55/r59 value array of channel 1~14 */ | 2669 | /* r55/r59 value array of channel 1~14 */ |
| 2680 | static const char r55_bt_rev[] = {0x83, 0x83, | 2670 | static const char r55_bt_rev[] = {0x83, 0x83, |
| @@ -3152,6 +3142,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
| 3152 | case RF3322: | 3142 | case RF3322: |
| 3153 | rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info); | 3143 | rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info); |
| 3154 | break; | 3144 | break; |
| 3145 | case RF3070: | ||
| 3155 | case RF5360: | 3146 | case RF5360: |
| 3156 | case RF5370: | 3147 | case RF5370: |
| 3157 | case RF5372: | 3148 | case RF5372: |
| @@ -3166,7 +3157,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
| 3166 | rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); | 3157 | rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); |
| 3167 | } | 3158 | } |
| 3168 | 3159 | ||
| 3169 | if (rt2x00_rf(rt2x00dev, RF3290) || | 3160 | if (rt2x00_rf(rt2x00dev, RF3070) || |
| 3161 | rt2x00_rf(rt2x00dev, RF3290) || | ||
| 3170 | rt2x00_rf(rt2x00dev, RF3322) || | 3162 | rt2x00_rf(rt2x00dev, RF3322) || |
| 3171 | rt2x00_rf(rt2x00dev, RF5360) || | 3163 | rt2x00_rf(rt2x00dev, RF5360) || |
| 3172 | rt2x00_rf(rt2x00dev, RF5370) || | 3164 | rt2x00_rf(rt2x00dev, RF5370) || |
| @@ -3218,8 +3210,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
| 3218 | if (rf->channel <= 14) { | 3210 | if (rf->channel <= 14) { |
| 3219 | if (!rt2x00_rt(rt2x00dev, RT5390) && | 3211 | if (!rt2x00_rt(rt2x00dev, RT5390) && |
| 3220 | !rt2x00_rt(rt2x00dev, RT5392)) { | 3212 | !rt2x00_rt(rt2x00dev, RT5392)) { |
| 3221 | if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, | 3213 | if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { |
| 3222 | &rt2x00dev->cap_flags)) { | ||
| 3223 | rt2800_bbp_write(rt2x00dev, 82, 0x62); | 3214 | rt2800_bbp_write(rt2x00dev, 82, 0x62); |
| 3224 | rt2800_bbp_write(rt2x00dev, 75, 0x46); | 3215 | rt2800_bbp_write(rt2x00dev, 75, 0x46); |
| 3225 | } else { | 3216 | } else { |
| @@ -3244,7 +3235,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
| 3244 | if (rt2x00_rt(rt2x00dev, RT3593)) | 3235 | if (rt2x00_rt(rt2x00dev, RT3593)) |
| 3245 | rt2800_bbp_write(rt2x00dev, 83, 0x9a); | 3236 | rt2800_bbp_write(rt2x00dev, 83, 0x9a); |
| 3246 | 3237 | ||
| 3247 | if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) | 3238 | if (rt2x00_has_cap_external_lna_a(rt2x00dev)) |
| 3248 | rt2800_bbp_write(rt2x00dev, 75, 0x46); | 3239 | rt2800_bbp_write(rt2x00dev, 75, 0x46); |
| 3249 | else | 3240 | else |
| 3250 | rt2800_bbp_write(rt2x00dev, 75, 0x50); | 3241 | rt2800_bbp_write(rt2x00dev, 75, 0x50); |
| @@ -3280,7 +3271,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
| 3280 | /* Turn on primary PAs */ | 3271 | /* Turn on primary PAs */ |
| 3281 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, | 3272 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, |
| 3282 | rf->channel > 14); | 3273 | rf->channel > 14); |
| 3283 | if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) | 3274 | if (rt2x00_has_cap_bt_coexist(rt2x00dev)) |
| 3284 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1); | 3275 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1); |
| 3285 | else | 3276 | else |
| 3286 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, | 3277 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, |
| @@ -3311,33 +3302,50 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
| 3311 | 3302 | ||
| 3312 | rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); | 3303 | rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); |
| 3313 | 3304 | ||
| 3314 | if (rt2x00_rt(rt2x00dev, RT3572)) | 3305 | if (rt2x00_rt(rt2x00dev, RT3572)) { |
| 3315 | rt2800_rfcsr_write(rt2x00dev, 8, 0x80); | 3306 | rt2800_rfcsr_write(rt2x00dev, 8, 0x80); |
| 3316 | 3307 | ||
| 3308 | /* AGC init */ | ||
| 3309 | if (rf->channel <= 14) | ||
| 3310 | reg = 0x1c + (2 * rt2x00dev->lna_gain); | ||
| 3311 | else | ||
| 3312 | reg = 0x22 + ((rt2x00dev->lna_gain * 5) / 3); | ||
| 3313 | |||
| 3314 | rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg); | ||
| 3315 | } | ||
| 3316 | |||
| 3317 | if (rt2x00_rt(rt2x00dev, RT3593)) { | 3317 | if (rt2x00_rt(rt2x00dev, RT3593)) { |
| 3318 | if (rt2x00_is_usb(rt2x00dev)) { | 3318 | rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); |
| 3319 | rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); | ||
| 3320 | 3319 | ||
| 3321 | /* Band selection. GPIO #8 controls all paths */ | 3320 | /* Band selection */ |
| 3321 | if (rt2x00_is_usb(rt2x00dev) || | ||
| 3322 | rt2x00_is_pcie(rt2x00dev)) { | ||
| 3323 | /* GPIO #8 controls all paths */ | ||
| 3322 | rt2x00_set_field32(®, GPIO_CTRL_DIR8, 0); | 3324 | rt2x00_set_field32(®, GPIO_CTRL_DIR8, 0); |
| 3323 | if (rf->channel <= 14) | 3325 | if (rf->channel <= 14) |
| 3324 | rt2x00_set_field32(®, GPIO_CTRL_VAL8, 1); | 3326 | rt2x00_set_field32(®, GPIO_CTRL_VAL8, 1); |
| 3325 | else | 3327 | else |
| 3326 | rt2x00_set_field32(®, GPIO_CTRL_VAL8, 0); | 3328 | rt2x00_set_field32(®, GPIO_CTRL_VAL8, 0); |
| 3329 | } | ||
| 3327 | 3330 | ||
| 3331 | /* LNA PE control. */ | ||
| 3332 | if (rt2x00_is_usb(rt2x00dev)) { | ||
| 3333 | /* GPIO #4 controls PE0 and PE1, | ||
| 3334 | * GPIO #7 controls PE2 | ||
| 3335 | */ | ||
| 3328 | rt2x00_set_field32(®, GPIO_CTRL_DIR4, 0); | 3336 | rt2x00_set_field32(®, GPIO_CTRL_DIR4, 0); |
| 3329 | rt2x00_set_field32(®, GPIO_CTRL_DIR7, 0); | 3337 | rt2x00_set_field32(®, GPIO_CTRL_DIR7, 0); |
| 3330 | 3338 | ||
| 3331 | /* LNA PE control. | ||
| 3332 | * GPIO #4 controls PE0 and PE1, | ||
| 3333 | * GPIO #7 controls PE2 | ||
| 3334 | */ | ||
| 3335 | rt2x00_set_field32(®, GPIO_CTRL_VAL4, 1); | 3339 | rt2x00_set_field32(®, GPIO_CTRL_VAL4, 1); |
| 3336 | rt2x00_set_field32(®, GPIO_CTRL_VAL7, 1); | 3340 | rt2x00_set_field32(®, GPIO_CTRL_VAL7, 1); |
| 3337 | 3341 | } else if (rt2x00_is_pcie(rt2x00dev)) { | |
| 3338 | rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); | 3342 | /* GPIO #4 controls PE0, PE1 and PE2 */ |
| 3343 | rt2x00_set_field32(®, GPIO_CTRL_DIR4, 0); | ||
| 3344 | rt2x00_set_field32(®, GPIO_CTRL_VAL4, 1); | ||
| 3339 | } | 3345 | } |
| 3340 | 3346 | ||
| 3347 | rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); | ||
| 3348 | |||
| 3341 | /* AGC init */ | 3349 | /* AGC init */ |
| 3342 | if (rf->channel <= 14) | 3350 | if (rf->channel <= 14) |
| 3343 | reg = 0x1c + 2 * rt2x00dev->lna_gain; | 3351 | reg = 0x1c + 2 * rt2x00dev->lna_gain; |
| @@ -3565,7 +3573,7 @@ static int rt2800_get_txpower_reg_delta(struct rt2x00_dev *rt2x00dev, | |||
| 3565 | { | 3573 | { |
| 3566 | int delta; | 3574 | int delta; |
| 3567 | 3575 | ||
| 3568 | if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) | 3576 | if (rt2x00_has_cap_power_limit(rt2x00dev)) |
| 3569 | return 0; | 3577 | return 0; |
| 3570 | 3578 | ||
| 3571 | /* | 3579 | /* |
| @@ -3594,7 +3602,7 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, | |||
| 3594 | if (rt2x00_rt(rt2x00dev, RT3593)) | 3602 | if (rt2x00_rt(rt2x00dev, RT3593)) |
| 3595 | return min_t(u8, txpower, 0xc); | 3603 | return min_t(u8, txpower, 0xc); |
| 3596 | 3604 | ||
| 3597 | if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) { | 3605 | if (rt2x00_has_cap_power_limit(rt2x00dev)) { |
| 3598 | /* | 3606 | /* |
| 3599 | * Check if eirp txpower exceed txpower_limit. | 3607 | * Check if eirp txpower exceed txpower_limit. |
| 3600 | * We use OFDM 6M as criterion and its eirp txpower | 3608 | * We use OFDM 6M as criterion and its eirp txpower |
| @@ -4264,6 +4272,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev) | |||
| 4264 | rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); | 4272 | rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); |
| 4265 | break; | 4273 | break; |
| 4266 | case RF3053: | 4274 | case RF3053: |
| 4275 | case RF3070: | ||
| 4267 | case RF3290: | 4276 | case RF3290: |
| 4268 | case RF5360: | 4277 | case RF5360: |
| 4269 | case RF5370: | 4278 | case RF5370: |
| @@ -4405,6 +4414,7 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) | |||
| 4405 | rt2x00_rt(rt2x00dev, RT3290) || | 4414 | rt2x00_rt(rt2x00dev, RT3290) || |
| 4406 | rt2x00_rt(rt2x00dev, RT3390) || | 4415 | rt2x00_rt(rt2x00dev, RT3390) || |
| 4407 | rt2x00_rt(rt2x00dev, RT3572) || | 4416 | rt2x00_rt(rt2x00dev, RT3572) || |
| 4417 | rt2x00_rt(rt2x00dev, RT3593) || | ||
| 4408 | rt2x00_rt(rt2x00dev, RT5390) || | 4418 | rt2x00_rt(rt2x00dev, RT5390) || |
| 4409 | rt2x00_rt(rt2x00dev, RT5392) || | 4419 | rt2x00_rt(rt2x00dev, RT5392) || |
| 4410 | rt2x00_rt(rt2x00dev, RT5592)) | 4420 | rt2x00_rt(rt2x00dev, RT5592)) |
| @@ -4412,8 +4422,8 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) | |||
| 4412 | else | 4422 | else |
| 4413 | vgc = 0x2e + rt2x00dev->lna_gain; | 4423 | vgc = 0x2e + rt2x00dev->lna_gain; |
| 4414 | } else { /* 5GHZ band */ | 4424 | } else { /* 5GHZ band */ |
| 4415 | if (rt2x00_rt(rt2x00dev, RT3572)) | 4425 | if (rt2x00_rt(rt2x00dev, RT3593)) |
| 4416 | vgc = 0x22 + (rt2x00dev->lna_gain * 5) / 3; | 4426 | vgc = 0x20 + (rt2x00dev->lna_gain * 5) / 3; |
| 4417 | else if (rt2x00_rt(rt2x00dev, RT5592)) | 4427 | else if (rt2x00_rt(rt2x00dev, RT5592)) |
| 4418 | vgc = 0x24 + (2 * rt2x00dev->lna_gain); | 4428 | vgc = 0x24 + (2 * rt2x00dev->lna_gain); |
| 4419 | else { | 4429 | else { |
| @@ -4431,11 +4441,17 @@ static inline void rt2800_set_vgc(struct rt2x00_dev *rt2x00dev, | |||
| 4431 | struct link_qual *qual, u8 vgc_level) | 4441 | struct link_qual *qual, u8 vgc_level) |
| 4432 | { | 4442 | { |
| 4433 | if (qual->vgc_level != vgc_level) { | 4443 | if (qual->vgc_level != vgc_level) { |
| 4434 | if (rt2x00_rt(rt2x00dev, RT5592)) { | 4444 | if (rt2x00_rt(rt2x00dev, RT3572) || |
| 4445 | rt2x00_rt(rt2x00dev, RT3593)) { | ||
| 4446 | rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, | ||
| 4447 | vgc_level); | ||
| 4448 | } else if (rt2x00_rt(rt2x00dev, RT5592)) { | ||
| 4435 | rt2800_bbp_write(rt2x00dev, 83, qual->rssi > -65 ? 0x4a : 0x7a); | 4449 | rt2800_bbp_write(rt2x00dev, 83, qual->rssi > -65 ? 0x4a : 0x7a); |
| 4436 | rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, vgc_level); | 4450 | rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, vgc_level); |
| 4437 | } else | 4451 | } else { |
| 4438 | rt2800_bbp_write(rt2x00dev, 66, vgc_level); | 4452 | rt2800_bbp_write(rt2x00dev, 66, vgc_level); |
| 4453 | } | ||
| 4454 | |||
| 4439 | qual->vgc_level = vgc_level; | 4455 | qual->vgc_level = vgc_level; |
| 4440 | qual->vgc_level_reg = vgc_level; | 4456 | qual->vgc_level_reg = vgc_level; |
| 4441 | } | 4457 | } |
| @@ -4454,17 +4470,35 @@ void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, | |||
| 4454 | 4470 | ||
| 4455 | if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) | 4471 | if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) |
| 4456 | return; | 4472 | return; |
| 4457 | /* | 4473 | |
| 4458 | * When RSSI is better then -80 increase VGC level with 0x10, except | 4474 | /* When RSSI is better than a certain threshold, increase VGC |
| 4459 | * for rt5592 chip. | 4475 | * with a chip specific value in order to improve the balance |
| 4476 | * between sensibility and noise isolation. | ||
| 4460 | */ | 4477 | */ |
| 4461 | 4478 | ||
| 4462 | vgc = rt2800_get_default_vgc(rt2x00dev); | 4479 | vgc = rt2800_get_default_vgc(rt2x00dev); |
| 4463 | 4480 | ||
| 4464 | if (rt2x00_rt(rt2x00dev, RT5592) && qual->rssi > -65) | 4481 | switch (rt2x00dev->chip.rt) { |
| 4465 | vgc += 0x20; | 4482 | case RT3572: |
| 4466 | else if (qual->rssi > -80) | 4483 | case RT3593: |
| 4467 | vgc += 0x10; | 4484 | if (qual->rssi > -65) { |
| 4485 | if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) | ||
| 4486 | vgc += 0x20; | ||
| 4487 | else | ||
| 4488 | vgc += 0x10; | ||
| 4489 | } | ||
| 4490 | break; | ||
| 4491 | |||
| 4492 | case RT5592: | ||
| 4493 | if (qual->rssi > -65) | ||
| 4494 | vgc += 0x20; | ||
| 4495 | break; | ||
| 4496 | |||
| 4497 | default: | ||
| 4498 | if (qual->rssi > -80) | ||
| 4499 | vgc += 0x10; | ||
| 4500 | break; | ||
| 4501 | } | ||
| 4468 | 4502 | ||
| 4469 | rt2800_set_vgc(rt2x00dev, qual, vgc); | 4503 | rt2800_set_vgc(rt2x00dev, qual, vgc); |
| 4470 | } | 4504 | } |
| @@ -5489,7 +5523,7 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) | |||
| 5489 | ant = (div_mode == 3) ? 1 : 0; | 5523 | ant = (div_mode == 3) ? 1 : 0; |
| 5490 | 5524 | ||
| 5491 | /* check if this is a Bluetooth combo card */ | 5525 | /* check if this is a Bluetooth combo card */ |
| 5492 | if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { | 5526 | if (rt2x00_has_cap_bt_coexist(rt2x00dev)) { |
| 5493 | u32 reg; | 5527 | u32 reg; |
| 5494 | 5528 | ||
| 5495 | rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); | 5529 | rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); |
| @@ -5798,7 +5832,7 @@ static void rt2800_normal_mode_setup_3xxx(struct rt2x00_dev *rt2x00dev) | |||
| 5798 | rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || | 5832 | rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || |
| 5799 | rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || | 5833 | rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || |
| 5800 | rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { | 5834 | rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { |
| 5801 | if (!test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) | 5835 | if (!rt2x00_has_cap_external_lna_bg(rt2x00dev)) |
| 5802 | rt2x00_set_field8(&rfcsr, RFCSR17_R, 1); | 5836 | rt2x00_set_field8(&rfcsr, RFCSR17_R, 1); |
| 5803 | } | 5837 | } |
| 5804 | 5838 | ||
| @@ -5985,7 +6019,7 @@ static void rt2800_init_rfcsr_30xx(struct rt2x00_dev *rt2x00dev) | |||
| 5985 | rt2800_rfcsr_write(rt2x00dev, 20, 0xba); | 6019 | rt2800_rfcsr_write(rt2x00dev, 20, 0xba); |
| 5986 | rt2800_rfcsr_write(rt2x00dev, 21, 0xdb); | 6020 | rt2800_rfcsr_write(rt2x00dev, 21, 0xdb); |
| 5987 | rt2800_rfcsr_write(rt2x00dev, 24, 0x16); | 6021 | rt2800_rfcsr_write(rt2x00dev, 24, 0x16); |
| 5988 | rt2800_rfcsr_write(rt2x00dev, 25, 0x01); | 6022 | rt2800_rfcsr_write(rt2x00dev, 25, 0x03); |
| 5989 | rt2800_rfcsr_write(rt2x00dev, 29, 0x1f); | 6023 | rt2800_rfcsr_write(rt2x00dev, 29, 0x1f); |
| 5990 | 6024 | ||
| 5991 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) { | 6025 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) { |
| @@ -6441,7 +6475,7 @@ static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) | |||
| 6441 | rt2800_rfcsr_write(rt2x00dev, 28, 0x00); | 6475 | rt2800_rfcsr_write(rt2x00dev, 28, 0x00); |
| 6442 | rt2800_rfcsr_write(rt2x00dev, 29, 0x10); | 6476 | rt2800_rfcsr_write(rt2x00dev, 29, 0x10); |
| 6443 | 6477 | ||
| 6444 | rt2800_rfcsr_write(rt2x00dev, 30, 0x00); | 6478 | rt2800_rfcsr_write(rt2x00dev, 30, 0x10); |
| 6445 | rt2800_rfcsr_write(rt2x00dev, 31, 0x80); | 6479 | rt2800_rfcsr_write(rt2x00dev, 31, 0x80); |
| 6446 | rt2800_rfcsr_write(rt2x00dev, 32, 0x80); | 6480 | rt2800_rfcsr_write(rt2x00dev, 32, 0x80); |
| 6447 | rt2800_rfcsr_write(rt2x00dev, 33, 0x00); | 6481 | rt2800_rfcsr_write(rt2x00dev, 33, 0x00); |
| @@ -6479,7 +6513,7 @@ static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) | |||
| 6479 | rt2800_rfcsr_write(rt2x00dev, 56, 0x22); | 6513 | rt2800_rfcsr_write(rt2x00dev, 56, 0x22); |
| 6480 | rt2800_rfcsr_write(rt2x00dev, 57, 0x80); | 6514 | rt2800_rfcsr_write(rt2x00dev, 57, 0x80); |
| 6481 | rt2800_rfcsr_write(rt2x00dev, 58, 0x7f); | 6515 | rt2800_rfcsr_write(rt2x00dev, 58, 0x7f); |
| 6482 | rt2800_rfcsr_write(rt2x00dev, 59, 0x63); | 6516 | rt2800_rfcsr_write(rt2x00dev, 59, 0x8f); |
| 6483 | 6517 | ||
| 6484 | rt2800_rfcsr_write(rt2x00dev, 60, 0x45); | 6518 | rt2800_rfcsr_write(rt2x00dev, 60, 0x45); |
| 6485 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) | 6519 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) |
| @@ -6499,7 +6533,6 @@ static void rt2800_init_rfcsr_5392(struct rt2x00_dev *rt2x00dev) | |||
| 6499 | rt2800_rf_init_calibration(rt2x00dev, 2); | 6533 | rt2800_rf_init_calibration(rt2x00dev, 2); |
| 6500 | 6534 | ||
| 6501 | rt2800_rfcsr_write(rt2x00dev, 1, 0x17); | 6535 | rt2800_rfcsr_write(rt2x00dev, 1, 0x17); |
| 6502 | rt2800_rfcsr_write(rt2x00dev, 2, 0x80); | ||
| 6503 | rt2800_rfcsr_write(rt2x00dev, 3, 0x88); | 6536 | rt2800_rfcsr_write(rt2x00dev, 3, 0x88); |
| 6504 | rt2800_rfcsr_write(rt2x00dev, 5, 0x10); | 6537 | rt2800_rfcsr_write(rt2x00dev, 5, 0x10); |
| 6505 | rt2800_rfcsr_write(rt2x00dev, 6, 0xe0); | 6538 | rt2800_rfcsr_write(rt2x00dev, 6, 0xe0); |
| @@ -6653,17 +6686,20 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
| 6653 | u16 word; | 6686 | u16 word; |
| 6654 | 6687 | ||
| 6655 | /* | 6688 | /* |
| 6656 | * Initialize all registers. | 6689 | * Initialize MAC registers. |
| 6657 | */ | 6690 | */ |
| 6658 | if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) || | 6691 | if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) || |
| 6659 | rt2800_init_registers(rt2x00dev))) | 6692 | rt2800_init_registers(rt2x00dev))) |
| 6660 | return -EIO; | 6693 | return -EIO; |
| 6661 | 6694 | ||
| 6695 | /* | ||
| 6696 | * Wait BBP/RF to wake up. | ||
| 6697 | */ | ||
| 6662 | if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev))) | 6698 | if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev))) |
| 6663 | return -EIO; | 6699 | return -EIO; |
| 6664 | 6700 | ||
| 6665 | /* | 6701 | /* |
| 6666 | * Send signal to firmware during boot time. | 6702 | * Send signal during boot time to initialize firmware. |
| 6667 | */ | 6703 | */ |
| 6668 | rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); | 6704 | rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); |
| 6669 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); | 6705 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); |
| @@ -6672,9 +6708,15 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
| 6672 | rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); | 6708 | rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); |
| 6673 | msleep(1); | 6709 | msleep(1); |
| 6674 | 6710 | ||
| 6711 | /* | ||
| 6712 | * Make sure BBP is up and running. | ||
| 6713 | */ | ||
| 6675 | if (unlikely(rt2800_wait_bbp_ready(rt2x00dev))) | 6714 | if (unlikely(rt2800_wait_bbp_ready(rt2x00dev))) |
| 6676 | return -EIO; | 6715 | return -EIO; |
| 6677 | 6716 | ||
| 6717 | /* | ||
| 6718 | * Initialize BBP/RF registers. | ||
| 6719 | */ | ||
| 6678 | rt2800_init_bbp(rt2x00dev); | 6720 | rt2800_init_bbp(rt2x00dev); |
| 6679 | rt2800_init_rfcsr(rt2x00dev); | 6721 | rt2800_init_rfcsr(rt2x00dev); |
| 6680 | 6722 | ||
| @@ -7021,6 +7063,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
| 7021 | case RF3022: | 7063 | case RF3022: |
| 7022 | case RF3052: | 7064 | case RF3052: |
| 7023 | case RF3053: | 7065 | case RF3053: |
| 7066 | case RF3070: | ||
| 7024 | case RF3290: | 7067 | case RF3290: |
| 7025 | case RF3320: | 7068 | case RF3320: |
| 7026 | case RF3322: | 7069 | case RF3322: |
| @@ -7203,7 +7246,7 @@ static const struct rf_channel rf_vals[] = { | |||
| 7203 | 7246 | ||
| 7204 | /* | 7247 | /* |
| 7205 | * RF value list for rt3xxx | 7248 | * RF value list for rt3xxx |
| 7206 | * Supports: 2.4 GHz (all) & 5.2 GHz (RF3052) | 7249 | * Supports: 2.4 GHz (all) & 5.2 GHz (RF3052 & RF3053) |
| 7207 | */ | 7250 | */ |
| 7208 | static const struct rf_channel rf_vals_3x[] = { | 7251 | static const struct rf_channel rf_vals_3x[] = { |
| 7209 | {1, 241, 2, 2 }, | 7252 | {1, 241, 2, 2 }, |
| @@ -7399,72 +7442,6 @@ static const struct rf_channel rf_vals_5592_xtal40[] = { | |||
| 7399 | {196, 83, 0, 12, 1}, | 7442 | {196, 83, 0, 12, 1}, |
| 7400 | }; | 7443 | }; |
| 7401 | 7444 | ||
| 7402 | static const struct rf_channel rf_vals_3053[] = { | ||
| 7403 | /* Channel, N, R, K */ | ||
| 7404 | {1, 241, 2, 2}, | ||
| 7405 | {2, 241, 2, 7}, | ||
| 7406 | {3, 242, 2, 2}, | ||
| 7407 | {4, 242, 2, 7}, | ||
| 7408 | {5, 243, 2, 2}, | ||
| 7409 | {6, 243, 2, 7}, | ||
| 7410 | {7, 244, 2, 2}, | ||
| 7411 | {8, 244, 2, 7}, | ||
| 7412 | {9, 245, 2, 2}, | ||
| 7413 | {10, 245, 2, 7}, | ||
| 7414 | {11, 246, 2, 2}, | ||
| 7415 | {12, 246, 2, 7}, | ||
| 7416 | {13, 247, 2, 2}, | ||
| 7417 | {14, 248, 2, 4}, | ||
| 7418 | |||
| 7419 | {36, 0x56, 0, 4}, | ||
| 7420 | {38, 0x56, 0, 6}, | ||
| 7421 | {40, 0x56, 0, 8}, | ||
| 7422 | {44, 0x57, 0, 0}, | ||
| 7423 | {46, 0x57, 0, 2}, | ||
| 7424 | {48, 0x57, 0, 4}, | ||
| 7425 | {52, 0x57, 0, 8}, | ||
| 7426 | {54, 0x57, 0, 10}, | ||
| 7427 | {56, 0x58, 0, 0}, | ||
| 7428 | {60, 0x58, 0, 4}, | ||
| 7429 | {62, 0x58, 0, 6}, | ||
| 7430 | {64, 0x58, 0, 8}, | ||
| 7431 | |||
| 7432 | {100, 0x5B, 0, 8}, | ||
| 7433 | {102, 0x5B, 0, 10}, | ||
| 7434 | {104, 0x5C, 0, 0}, | ||
| 7435 | {108, 0x5C, 0, 4}, | ||
| 7436 | {110, 0x5C, 0, 6}, | ||
| 7437 | {112, 0x5C, 0, 8}, | ||
| 7438 | |||
| 7439 | /* NOTE: Channel 114 has been removed intentionally. | ||
| 7440 | * The EEPROM contains no TX power values for that, | ||
| 7441 | * and it is disabled in the vendor driver as well. | ||
| 7442 | */ | ||
| 7443 | |||
| 7444 | {116, 0x5D, 0, 0}, | ||
| 7445 | {118, 0x5D, 0, 2}, | ||
| 7446 | {120, 0x5D, 0, 4}, | ||
| 7447 | {124, 0x5D, 0, 8}, | ||
| 7448 | {126, 0x5D, 0, 10}, | ||
| 7449 | {128, 0x5E, 0, 0}, | ||
| 7450 | {132, 0x5E, 0, 4}, | ||
| 7451 | {134, 0x5E, 0, 6}, | ||
| 7452 | {136, 0x5E, 0, 8}, | ||
| 7453 | {140, 0x5F, 0, 0}, | ||
| 7454 | |||
| 7455 | {149, 0x5F, 0, 9}, | ||
| 7456 | {151, 0x5F, 0, 11}, | ||
| 7457 | {153, 0x60, 0, 1}, | ||
| 7458 | {157, 0x60, 0, 5}, | ||
| 7459 | {159, 0x60, 0, 7}, | ||
| 7460 | {161, 0x60, 0, 9}, | ||
| 7461 | {165, 0x61, 0, 1}, | ||
| 7462 | {167, 0x61, 0, 3}, | ||
| 7463 | {169, 0x61, 0, 5}, | ||
| 7464 | {171, 0x61, 0, 7}, | ||
| 7465 | {173, 0x61, 0, 9}, | ||
| 7466 | }; | ||
| 7467 | |||
| 7468 | static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | 7445 | static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) |
| 7469 | { | 7446 | { |
| 7470 | struct hw_mode_spec *spec = &rt2x00dev->spec; | 7447 | struct hw_mode_spec *spec = &rt2x00dev->spec; |
| @@ -7473,7 +7450,6 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
| 7473 | char *default_power2; | 7450 | char *default_power2; |
| 7474 | char *default_power3; | 7451 | char *default_power3; |
| 7475 | unsigned int i; | 7452 | unsigned int i; |
| 7476 | u16 eeprom; | ||
| 7477 | u32 reg; | 7453 | u32 reg; |
| 7478 | 7454 | ||
| 7479 | /* | 7455 | /* |
| @@ -7522,48 +7498,48 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
| 7522 | rt2x00dev->hw->max_report_rates = 7; | 7498 | rt2x00dev->hw->max_report_rates = 7; |
| 7523 | rt2x00dev->hw->max_rate_tries = 1; | 7499 | rt2x00dev->hw->max_rate_tries = 1; |
| 7524 | 7500 | ||
| 7525 | rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); | ||
| 7526 | |||
| 7527 | /* | 7501 | /* |
| 7528 | * Initialize hw_mode information. | 7502 | * Initialize hw_mode information. |
| 7529 | */ | 7503 | */ |
| 7530 | spec->supported_bands = SUPPORT_BAND_2GHZ; | ||
| 7531 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; | 7504 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; |
| 7532 | 7505 | ||
| 7533 | if (rt2x00_rf(rt2x00dev, RF2820) || | 7506 | switch (rt2x00dev->chip.rf) { |
| 7534 | rt2x00_rf(rt2x00dev, RF2720)) { | 7507 | case RF2720: |
| 7508 | case RF2820: | ||
| 7535 | spec->num_channels = 14; | 7509 | spec->num_channels = 14; |
| 7536 | spec->channels = rf_vals; | 7510 | spec->channels = rf_vals; |
| 7537 | } else if (rt2x00_rf(rt2x00dev, RF2850) || | 7511 | break; |
| 7538 | rt2x00_rf(rt2x00dev, RF2750)) { | 7512 | |
| 7539 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 7513 | case RF2750: |
| 7514 | case RF2850: | ||
| 7540 | spec->num_channels = ARRAY_SIZE(rf_vals); | 7515 | spec->num_channels = ARRAY_SIZE(rf_vals); |
| 7541 | spec->channels = rf_vals; | 7516 | spec->channels = rf_vals; |
| 7542 | } else if (rt2x00_rf(rt2x00dev, RF3020) || | 7517 | break; |
| 7543 | rt2x00_rf(rt2x00dev, RF2020) || | 7518 | |
| 7544 | rt2x00_rf(rt2x00dev, RF3021) || | 7519 | case RF2020: |
| 7545 | rt2x00_rf(rt2x00dev, RF3022) || | 7520 | case RF3020: |
| 7546 | rt2x00_rf(rt2x00dev, RF3290) || | 7521 | case RF3021: |
| 7547 | rt2x00_rf(rt2x00dev, RF3320) || | 7522 | case RF3022: |
| 7548 | rt2x00_rf(rt2x00dev, RF3322) || | 7523 | case RF3070: |
| 7549 | rt2x00_rf(rt2x00dev, RF5360) || | 7524 | case RF3290: |
| 7550 | rt2x00_rf(rt2x00dev, RF5370) || | 7525 | case RF3320: |
| 7551 | rt2x00_rf(rt2x00dev, RF5372) || | 7526 | case RF3322: |
| 7552 | rt2x00_rf(rt2x00dev, RF5390) || | 7527 | case RF5360: |
| 7553 | rt2x00_rf(rt2x00dev, RF5392)) { | 7528 | case RF5370: |
| 7529 | case RF5372: | ||
| 7530 | case RF5390: | ||
| 7531 | case RF5392: | ||
| 7554 | spec->num_channels = 14; | 7532 | spec->num_channels = 14; |
| 7555 | spec->channels = rf_vals_3x; | 7533 | spec->channels = rf_vals_3x; |
| 7556 | } else if (rt2x00_rf(rt2x00dev, RF3052)) { | 7534 | break; |
| 7557 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 7535 | |
| 7536 | case RF3052: | ||
| 7537 | case RF3053: | ||
| 7558 | spec->num_channels = ARRAY_SIZE(rf_vals_3x); | 7538 | spec->num_channels = ARRAY_SIZE(rf_vals_3x); |
| 7559 | spec->channels = rf_vals_3x; | 7539 | spec->channels = rf_vals_3x; |
| 7560 | } else if (rt2x00_rf(rt2x00dev, RF3053)) { | 7540 | break; |
| 7561 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | ||
| 7562 | spec->num_channels = ARRAY_SIZE(rf_vals_3053); | ||
| 7563 | spec->channels = rf_vals_3053; | ||
| 7564 | } else if (rt2x00_rf(rt2x00dev, RF5592)) { | ||
| 7565 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | ||
| 7566 | 7541 | ||
| 7542 | case RF5592: | ||
| 7567 | rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX, ®); | 7543 | rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX, ®); |
| 7568 | if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) { | 7544 | if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) { |
| 7569 | spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal40); | 7545 | spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal40); |
| @@ -7572,11 +7548,16 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
| 7572 | spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal20); | 7548 | spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal20); |
| 7573 | spec->channels = rf_vals_5592_xtal20; | 7549 | spec->channels = rf_vals_5592_xtal20; |
| 7574 | } | 7550 | } |
| 7551 | break; | ||
| 7575 | } | 7552 | } |
| 7576 | 7553 | ||
| 7577 | if (WARN_ON_ONCE(!spec->channels)) | 7554 | if (WARN_ON_ONCE(!spec->channels)) |
| 7578 | return -ENODEV; | 7555 | return -ENODEV; |
| 7579 | 7556 | ||
| 7557 | spec->supported_bands = SUPPORT_BAND_2GHZ; | ||
| 7558 | if (spec->num_channels > 14) | ||
| 7559 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | ||
| 7560 | |||
| 7580 | /* | 7561 | /* |
| 7581 | * Initialize HT information. | 7562 | * Initialize HT information. |
| 7582 | */ | 7563 | */ |
| @@ -7591,22 +7572,21 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
| 7591 | IEEE80211_HT_CAP_SGI_20 | | 7572 | IEEE80211_HT_CAP_SGI_20 | |
| 7592 | IEEE80211_HT_CAP_SGI_40; | 7573 | IEEE80211_HT_CAP_SGI_40; |
| 7593 | 7574 | ||
| 7594 | if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) >= 2) | 7575 | if (rt2x00dev->default_ant.tx_chain_num >= 2) |
| 7595 | spec->ht.cap |= IEEE80211_HT_CAP_TX_STBC; | 7576 | spec->ht.cap |= IEEE80211_HT_CAP_TX_STBC; |
| 7596 | 7577 | ||
| 7597 | spec->ht.cap |= | 7578 | spec->ht.cap |= rt2x00dev->default_ant.rx_chain_num << |
| 7598 | rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) << | 7579 | IEEE80211_HT_CAP_RX_STBC_SHIFT; |
| 7599 | IEEE80211_HT_CAP_RX_STBC_SHIFT; | ||
| 7600 | 7580 | ||
| 7601 | spec->ht.ampdu_factor = 3; | 7581 | spec->ht.ampdu_factor = 3; |
| 7602 | spec->ht.ampdu_density = 4; | 7582 | spec->ht.ampdu_density = 4; |
| 7603 | spec->ht.mcs.tx_params = | 7583 | spec->ht.mcs.tx_params = |
| 7604 | IEEE80211_HT_MCS_TX_DEFINED | | 7584 | IEEE80211_HT_MCS_TX_DEFINED | |
| 7605 | IEEE80211_HT_MCS_TX_RX_DIFF | | 7585 | IEEE80211_HT_MCS_TX_RX_DIFF | |
| 7606 | ((rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) - 1) << | 7586 | ((rt2x00dev->default_ant.tx_chain_num - 1) << |
| 7607 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); | 7587 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); |
| 7608 | 7588 | ||
| 7609 | switch (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH)) { | 7589 | switch (rt2x00dev->default_ant.rx_chain_num) { |
| 7610 | case 3: | 7590 | case 3: |
| 7611 | spec->ht.mcs.rx_mask[2] = 0xff; | 7591 | spec->ht.mcs.rx_mask[2] = 0xff; |
| 7612 | case 2: | 7592 | case 2: |
| @@ -7671,6 +7651,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
| 7671 | case RF3320: | 7651 | case RF3320: |
| 7672 | case RF3052: | 7652 | case RF3052: |
| 7673 | case RF3053: | 7653 | case RF3053: |
| 7654 | case RF3070: | ||
| 7674 | case RF3290: | 7655 | case RF3290: |
| 7675 | case RF5360: | 7656 | case RF5360: |
| 7676 | case RF5370: | 7657 | case RF5370: |
diff --git a/drivers/net/wireless/rt2x00/rt2800mmio.c b/drivers/net/wireless/rt2x00/rt2800mmio.c new file mode 100644 index 000000000000..ae152280e071 --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2800mmio.c | |||
| @@ -0,0 +1,873 @@ | |||
| 1 | /* Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
| 2 | * Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com> | ||
| 3 | * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> | ||
| 4 | * Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com> | ||
| 5 | * Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de> | ||
| 6 | * Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com> | ||
| 7 | * Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com> | ||
| 8 | * Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com> | ||
| 9 | * <http://rt2x00.serialmonkey.com> | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License as published by | ||
| 13 | * the Free Software Foundation; either version 2 of the License, or | ||
| 14 | * (at your option) any later version. | ||
| 15 | * | ||
| 16 | * This program is distributed in the hope that it will be useful, | ||
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | * GNU General Public License for more details. | ||
| 20 | * | ||
| 21 | * You should have received a copy of the GNU General Public License | ||
| 22 | * along with this program; if not, write to the | ||
| 23 | * Free Software Foundation, Inc., | ||
| 24 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 25 | */ | ||
| 26 | |||
| 27 | /* Module: rt2800mmio | ||
| 28 | * Abstract: rt2800 MMIO device routines. | ||
| 29 | */ | ||
| 30 | |||
| 31 | #include <linux/kernel.h> | ||
| 32 | #include <linux/module.h> | ||
| 33 | #include <linux/export.h> | ||
| 34 | |||
| 35 | #include "rt2x00.h" | ||
| 36 | #include "rt2x00mmio.h" | ||
| 37 | #include "rt2800.h" | ||
| 38 | #include "rt2800lib.h" | ||
| 39 | #include "rt2800mmio.h" | ||
| 40 | |||
| 41 | /* | ||
| 42 | * TX descriptor initialization | ||
| 43 | */ | ||
| 44 | __le32 *rt2800mmio_get_txwi(struct queue_entry *entry) | ||
| 45 | { | ||
| 46 | return (__le32 *) entry->skb->data; | ||
| 47 | } | ||
| 48 | EXPORT_SYMBOL_GPL(rt2800mmio_get_txwi); | ||
| 49 | |||
| 50 | void rt2800mmio_write_tx_desc(struct queue_entry *entry, | ||
| 51 | struct txentry_desc *txdesc) | ||
| 52 | { | ||
| 53 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
| 54 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; | ||
| 55 | __le32 *txd = entry_priv->desc; | ||
| 56 | u32 word; | ||
| 57 | const unsigned int txwi_size = entry->queue->winfo_size; | ||
| 58 | |||
| 59 | /* | ||
| 60 | * The buffers pointed by SD_PTR0/SD_LEN0 and SD_PTR1/SD_LEN1 | ||
| 61 | * must contains a TXWI structure + 802.11 header + padding + 802.11 | ||
| 62 | * data. We choose to have SD_PTR0/SD_LEN0 only contains TXWI and | ||
| 63 | * SD_PTR1/SD_LEN1 contains 802.11 header + padding + 802.11 | ||
| 64 | * data. It means that LAST_SEC0 is always 0. | ||
| 65 | */ | ||
| 66 | |||
| 67 | /* | ||
| 68 | * Initialize TX descriptor | ||
| 69 | */ | ||
| 70 | word = 0; | ||
| 71 | rt2x00_set_field32(&word, TXD_W0_SD_PTR0, skbdesc->skb_dma); | ||
| 72 | rt2x00_desc_write(txd, 0, word); | ||
| 73 | |||
| 74 | word = 0; | ||
| 75 | rt2x00_set_field32(&word, TXD_W1_SD_LEN1, entry->skb->len); | ||
| 76 | rt2x00_set_field32(&word, TXD_W1_LAST_SEC1, | ||
| 77 | !test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); | ||
| 78 | rt2x00_set_field32(&word, TXD_W1_BURST, | ||
| 79 | test_bit(ENTRY_TXD_BURST, &txdesc->flags)); | ||
| 80 | rt2x00_set_field32(&word, TXD_W1_SD_LEN0, txwi_size); | ||
| 81 | rt2x00_set_field32(&word, TXD_W1_LAST_SEC0, 0); | ||
| 82 | rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0); | ||
| 83 | rt2x00_desc_write(txd, 1, word); | ||
| 84 | |||
| 85 | word = 0; | ||
| 86 | rt2x00_set_field32(&word, TXD_W2_SD_PTR1, | ||
| 87 | skbdesc->skb_dma + txwi_size); | ||
| 88 | rt2x00_desc_write(txd, 2, word); | ||
| 89 | |||
| 90 | word = 0; | ||
| 91 | rt2x00_set_field32(&word, TXD_W3_WIV, | ||
| 92 | !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); | ||
| 93 | rt2x00_set_field32(&word, TXD_W3_QSEL, 2); | ||
| 94 | rt2x00_desc_write(txd, 3, word); | ||
| 95 | |||
| 96 | /* | ||
| 97 | * Register descriptor details in skb frame descriptor. | ||
| 98 | */ | ||
| 99 | skbdesc->desc = txd; | ||
| 100 | skbdesc->desc_len = TXD_DESC_SIZE; | ||
| 101 | } | ||
| 102 | EXPORT_SYMBOL_GPL(rt2800mmio_write_tx_desc); | ||
| 103 | |||
| 104 | /* | ||
| 105 | * RX control handlers | ||
| 106 | */ | ||
| 107 | void rt2800mmio_fill_rxdone(struct queue_entry *entry, | ||
| 108 | struct rxdone_entry_desc *rxdesc) | ||
| 109 | { | ||
| 110 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; | ||
| 111 | __le32 *rxd = entry_priv->desc; | ||
| 112 | u32 word; | ||
| 113 | |||
| 114 | rt2x00_desc_read(rxd, 3, &word); | ||
| 115 | |||
| 116 | if (rt2x00_get_field32(word, RXD_W3_CRC_ERROR)) | ||
| 117 | rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; | ||
| 118 | |||
| 119 | /* | ||
| 120 | * Unfortunately we don't know the cipher type used during | ||
| 121 | * decryption. This prevents us from correct providing | ||
| 122 | * correct statistics through debugfs. | ||
| 123 | */ | ||
| 124 | rxdesc->cipher_status = rt2x00_get_field32(word, RXD_W3_CIPHER_ERROR); | ||
| 125 | |||
| 126 | if (rt2x00_get_field32(word, RXD_W3_DECRYPTED)) { | ||
| 127 | /* | ||
| 128 | * Hardware has stripped IV/EIV data from 802.11 frame during | ||
| 129 | * decryption. Unfortunately the descriptor doesn't contain | ||
| 130 | * any fields with the EIV/IV data either, so they can't | ||
| 131 | * be restored by rt2x00lib. | ||
| 132 | */ | ||
| 133 | rxdesc->flags |= RX_FLAG_IV_STRIPPED; | ||
| 134 | |||
| 135 | /* | ||
| 136 | * The hardware has already checked the Michael Mic and has | ||
| 137 | * stripped it from the frame. Signal this to mac80211. | ||
| 138 | */ | ||
| 139 | rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; | ||
| 140 | |||
| 141 | if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) | ||
| 142 | rxdesc->flags |= RX_FLAG_DECRYPTED; | ||
| 143 | else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) | ||
| 144 | rxdesc->flags |= RX_FLAG_MMIC_ERROR; | ||
| 145 | } | ||
| 146 | |||
| 147 | if (rt2x00_get_field32(word, RXD_W3_MY_BSS)) | ||
| 148 | rxdesc->dev_flags |= RXDONE_MY_BSS; | ||
| 149 | |||
| 150 | if (rt2x00_get_field32(word, RXD_W3_L2PAD)) | ||
| 151 | rxdesc->dev_flags |= RXDONE_L2PAD; | ||
| 152 | |||
| 153 | /* | ||
| 154 | * Process the RXWI structure that is at the start of the buffer. | ||
| 155 | */ | ||
| 156 | rt2800_process_rxwi(entry, rxdesc); | ||
| 157 | } | ||
| 158 | EXPORT_SYMBOL_GPL(rt2800mmio_fill_rxdone); | ||
| 159 | |||
| 160 | /* | ||
| 161 | * Interrupt functions. | ||
| 162 | */ | ||
| 163 | static void rt2800mmio_wakeup(struct rt2x00_dev *rt2x00dev) | ||
| 164 | { | ||
| 165 | struct ieee80211_conf conf = { .flags = 0 }; | ||
| 166 | struct rt2x00lib_conf libconf = { .conf = &conf }; | ||
| 167 | |||
| 168 | rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); | ||
| 169 | } | ||
| 170 | |||
| 171 | static bool rt2800mmio_txdone_entry_check(struct queue_entry *entry, u32 status) | ||
| 172 | { | ||
| 173 | __le32 *txwi; | ||
| 174 | u32 word; | ||
| 175 | int wcid, tx_wcid; | ||
| 176 | |||
| 177 | wcid = rt2x00_get_field32(status, TX_STA_FIFO_WCID); | ||
| 178 | |||
| 179 | txwi = rt2800_drv_get_txwi(entry); | ||
| 180 | rt2x00_desc_read(txwi, 1, &word); | ||
| 181 | tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); | ||
| 182 | |||
| 183 | return (tx_wcid == wcid); | ||
| 184 | } | ||
| 185 | |||
| 186 | static bool rt2800mmio_txdone_find_entry(struct queue_entry *entry, void *data) | ||
| 187 | { | ||
| 188 | u32 status = *(u32 *)data; | ||
| 189 | |||
| 190 | /* | ||
| 191 | * rt2800pci hardware might reorder frames when exchanging traffic | ||
| 192 | * with multiple BA enabled STAs. | ||
| 193 | * | ||
| 194 | * For example, a tx queue | ||
| 195 | * [ STA1 | STA2 | STA1 | STA2 ] | ||
| 196 | * can result in tx status reports | ||
| 197 | * [ STA1 | STA1 | STA2 | STA2 ] | ||
| 198 | * when the hw decides to aggregate the frames for STA1 into one AMPDU. | ||
| 199 | * | ||
| 200 | * To mitigate this effect, associate the tx status to the first frame | ||
| 201 | * in the tx queue with a matching wcid. | ||
| 202 | */ | ||
| 203 | if (rt2800mmio_txdone_entry_check(entry, status) && | ||
| 204 | !test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { | ||
| 205 | /* | ||
| 206 | * Got a matching frame, associate the tx status with | ||
| 207 | * the frame | ||
| 208 | */ | ||
| 209 | entry->status = status; | ||
| 210 | set_bit(ENTRY_DATA_STATUS_SET, &entry->flags); | ||
| 211 | return true; | ||
| 212 | } | ||
| 213 | |||
| 214 | /* Check the next frame */ | ||
| 215 | return false; | ||
| 216 | } | ||
| 217 | |||
| 218 | static bool rt2800mmio_txdone_match_first(struct queue_entry *entry, void *data) | ||
| 219 | { | ||
| 220 | u32 status = *(u32 *)data; | ||
| 221 | |||
| 222 | /* | ||
| 223 | * Find the first frame without tx status and assign this status to it | ||
| 224 | * regardless if it matches or not. | ||
| 225 | */ | ||
| 226 | if (!test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { | ||
| 227 | /* | ||
| 228 | * Got a matching frame, associate the tx status with | ||
| 229 | * the frame | ||
| 230 | */ | ||
| 231 | entry->status = status; | ||
| 232 | set_bit(ENTRY_DATA_STATUS_SET, &entry->flags); | ||
| 233 | return true; | ||
| 234 | } | ||
| 235 | |||
| 236 | /* Check the next frame */ | ||
| 237 | return false; | ||
| 238 | } | ||
| 239 | static bool rt2800mmio_txdone_release_entries(struct queue_entry *entry, | ||
| 240 | void *data) | ||
| 241 | { | ||
| 242 | if (test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { | ||
| 243 | rt2800_txdone_entry(entry, entry->status, | ||
| 244 | rt2800mmio_get_txwi(entry)); | ||
| 245 | return false; | ||
| 246 | } | ||
| 247 | |||
| 248 | /* No more frames to release */ | ||
| 249 | return true; | ||
| 250 | } | ||
| 251 | |||
| 252 | static bool rt2800mmio_txdone(struct rt2x00_dev *rt2x00dev) | ||
| 253 | { | ||
| 254 | struct data_queue *queue; | ||
| 255 | u32 status; | ||
| 256 | u8 qid; | ||
| 257 | int max_tx_done = 16; | ||
| 258 | |||
| 259 | while (kfifo_get(&rt2x00dev->txstatus_fifo, &status)) { | ||
| 260 | qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE); | ||
| 261 | if (unlikely(qid >= QID_RX)) { | ||
| 262 | /* | ||
| 263 | * Unknown queue, this shouldn't happen. Just drop | ||
| 264 | * this tx status. | ||
| 265 | */ | ||
| 266 | rt2x00_warn(rt2x00dev, "Got TX status report with unexpected pid %u, dropping\n", | ||
| 267 | qid); | ||
| 268 | break; | ||
| 269 | } | ||
| 270 | |||
| 271 | queue = rt2x00queue_get_tx_queue(rt2x00dev, qid); | ||
| 272 | if (unlikely(queue == NULL)) { | ||
| 273 | /* | ||
| 274 | * The queue is NULL, this shouldn't happen. Stop | ||
| 275 | * processing here and drop the tx status | ||
| 276 | */ | ||
| 277 | rt2x00_warn(rt2x00dev, "Got TX status for an unavailable queue %u, dropping\n", | ||
| 278 | qid); | ||
| 279 | break; | ||
| 280 | } | ||
| 281 | |||
| 282 | if (unlikely(rt2x00queue_empty(queue))) { | ||
| 283 | /* | ||
| 284 | * The queue is empty. Stop processing here | ||
| 285 | * and drop the tx status. | ||
| 286 | */ | ||
| 287 | rt2x00_warn(rt2x00dev, "Got TX status for an empty queue %u, dropping\n", | ||
| 288 | qid); | ||
| 289 | break; | ||
| 290 | } | ||
| 291 | |||
| 292 | /* | ||
| 293 | * Let's associate this tx status with the first | ||
| 294 | * matching frame. | ||
| 295 | */ | ||
| 296 | if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, | ||
| 297 | Q_INDEX, &status, | ||
| 298 | rt2800mmio_txdone_find_entry)) { | ||
| 299 | /* | ||
| 300 | * We cannot match the tx status to any frame, so just | ||
| 301 | * use the first one. | ||
| 302 | */ | ||
| 303 | if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, | ||
| 304 | Q_INDEX, &status, | ||
| 305 | rt2800mmio_txdone_match_first)) { | ||
| 306 | rt2x00_warn(rt2x00dev, "No frame found for TX status on queue %u, dropping\n", | ||
| 307 | qid); | ||
| 308 | break; | ||
| 309 | } | ||
| 310 | } | ||
| 311 | |||
| 312 | /* | ||
| 313 | * Release all frames with a valid tx status. | ||
| 314 | */ | ||
| 315 | rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, | ||
| 316 | Q_INDEX, NULL, | ||
| 317 | rt2800mmio_txdone_release_entries); | ||
| 318 | |||
| 319 | if (--max_tx_done == 0) | ||
| 320 | break; | ||
| 321 | } | ||
| 322 | |||
| 323 | return !max_tx_done; | ||
| 324 | } | ||
| 325 | |||
| 326 | static inline void rt2800mmio_enable_interrupt(struct rt2x00_dev *rt2x00dev, | ||
| 327 | struct rt2x00_field32 irq_field) | ||
| 328 | { | ||
| 329 | u32 reg; | ||
| 330 | |||
| 331 | /* | ||
| 332 | * Enable a single interrupt. The interrupt mask register | ||
| 333 | * access needs locking. | ||
| 334 | */ | ||
| 335 | spin_lock_irq(&rt2x00dev->irqmask_lock); | ||
| 336 | rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, ®); | ||
| 337 | rt2x00_set_field32(®, irq_field, 1); | ||
| 338 | rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg); | ||
| 339 | spin_unlock_irq(&rt2x00dev->irqmask_lock); | ||
| 340 | } | ||
| 341 | |||
| 342 | void rt2800mmio_txstatus_tasklet(unsigned long data) | ||
| 343 | { | ||
| 344 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
| 345 | if (rt2800mmio_txdone(rt2x00dev)) | ||
| 346 | tasklet_schedule(&rt2x00dev->txstatus_tasklet); | ||
| 347 | |||
| 348 | /* | ||
| 349 | * No need to enable the tx status interrupt here as we always | ||
| 350 | * leave it enabled to minimize the possibility of a tx status | ||
| 351 | * register overflow. See comment in interrupt handler. | ||
| 352 | */ | ||
| 353 | } | ||
| 354 | EXPORT_SYMBOL_GPL(rt2800mmio_txstatus_tasklet); | ||
| 355 | |||
| 356 | void rt2800mmio_pretbtt_tasklet(unsigned long data) | ||
| 357 | { | ||
| 358 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
| 359 | rt2x00lib_pretbtt(rt2x00dev); | ||
| 360 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
| 361 | rt2800mmio_enable_interrupt(rt2x00dev, INT_MASK_CSR_PRE_TBTT); | ||
| 362 | } | ||
| 363 | EXPORT_SYMBOL_GPL(rt2800mmio_pretbtt_tasklet); | ||
| 364 | |||
| 365 | void rt2800mmio_tbtt_tasklet(unsigned long data) | ||
| 366 | { | ||
| 367 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
| 368 | struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; | ||
| 369 | u32 reg; | ||
| 370 | |||
| 371 | rt2x00lib_beacondone(rt2x00dev); | ||
| 372 | |||
| 373 | if (rt2x00dev->intf_ap_count) { | ||
| 374 | /* | ||
| 375 | * The rt2800pci hardware tbtt timer is off by 1us per tbtt | ||
| 376 | * causing beacon skew and as a result causing problems with | ||
| 377 | * some powersaving clients over time. Shorten the beacon | ||
| 378 | * interval every 64 beacons by 64us to mitigate this effect. | ||
| 379 | */ | ||
| 380 | if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 2)) { | ||
| 381 | rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
| 382 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, | ||
| 383 | (rt2x00dev->beacon_int * 16) - 1); | ||
| 384 | rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
| 385 | } else if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 1)) { | ||
| 386 | rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
| 387 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, | ||
| 388 | (rt2x00dev->beacon_int * 16)); | ||
| 389 | rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
| 390 | } | ||
| 391 | drv_data->tbtt_tick++; | ||
| 392 | drv_data->tbtt_tick %= BCN_TBTT_OFFSET; | ||
| 393 | } | ||
| 394 | |||
| 395 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
| 396 | rt2800mmio_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT); | ||
| 397 | } | ||
| 398 | EXPORT_SYMBOL_GPL(rt2800mmio_tbtt_tasklet); | ||
| 399 | |||
| 400 | void rt2800mmio_rxdone_tasklet(unsigned long data) | ||
| 401 | { | ||
| 402 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
| 403 | if (rt2x00mmio_rxdone(rt2x00dev)) | ||
| 404 | tasklet_schedule(&rt2x00dev->rxdone_tasklet); | ||
| 405 | else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
| 406 | rt2800mmio_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE); | ||
| 407 | } | ||
| 408 | EXPORT_SYMBOL_GPL(rt2800mmio_rxdone_tasklet); | ||
| 409 | |||
| 410 | void rt2800mmio_autowake_tasklet(unsigned long data) | ||
| 411 | { | ||
| 412 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
| 413 | rt2800mmio_wakeup(rt2x00dev); | ||
| 414 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
| 415 | rt2800mmio_enable_interrupt(rt2x00dev, | ||
| 416 | INT_MASK_CSR_AUTO_WAKEUP); | ||
| 417 | } | ||
| 418 | EXPORT_SYMBOL_GPL(rt2800mmio_autowake_tasklet); | ||
| 419 | |||
| 420 | static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) | ||
| 421 | { | ||
| 422 | u32 status; | ||
| 423 | int i; | ||
| 424 | |||
| 425 | /* | ||
| 426 | * The TX_FIFO_STATUS interrupt needs special care. We should | ||
| 427 | * read TX_STA_FIFO but we should do it immediately as otherwise | ||
| 428 | * the register can overflow and we would lose status reports. | ||
| 429 | * | ||
| 430 | * Hence, read the TX_STA_FIFO register and copy all tx status | ||
| 431 | * reports into a kernel FIFO which is handled in the txstatus | ||
| 432 | * tasklet. We use a tasklet to process the tx status reports | ||
| 433 | * because we can schedule the tasklet multiple times (when the | ||
| 434 | * interrupt fires again during tx status processing). | ||
| 435 | * | ||
| 436 | * Furthermore we don't disable the TX_FIFO_STATUS | ||
| 437 | * interrupt here but leave it enabled so that the TX_STA_FIFO | ||
| 438 | * can also be read while the tx status tasklet gets executed. | ||
| 439 | * | ||
| 440 | * Since we have only one producer and one consumer we don't | ||
| 441 | * need to lock the kfifo. | ||
| 442 | */ | ||
| 443 | for (i = 0; i < rt2x00dev->tx->limit; i++) { | ||
| 444 | rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &status); | ||
| 445 | |||
| 446 | if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID)) | ||
| 447 | break; | ||
| 448 | |||
| 449 | if (!kfifo_put(&rt2x00dev->txstatus_fifo, &status)) { | ||
| 450 | rt2x00_warn(rt2x00dev, "TX status FIFO overrun, drop tx status report\n"); | ||
| 451 | break; | ||
| 452 | } | ||
| 453 | } | ||
| 454 | |||
| 455 | /* Schedule the tasklet for processing the tx status. */ | ||
| 456 | tasklet_schedule(&rt2x00dev->txstatus_tasklet); | ||
| 457 | } | ||
| 458 | |||
| 459 | irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance) | ||
| 460 | { | ||
| 461 | struct rt2x00_dev *rt2x00dev = dev_instance; | ||
| 462 | u32 reg, mask; | ||
| 463 | |||
| 464 | /* Read status and ACK all interrupts */ | ||
| 465 | rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, ®); | ||
| 466 | rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg); | ||
| 467 | |||
| 468 | if (!reg) | ||
| 469 | return IRQ_NONE; | ||
| 470 | |||
| 471 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
| 472 | return IRQ_HANDLED; | ||
| 473 | |||
| 474 | /* | ||
| 475 | * Since INT_MASK_CSR and INT_SOURCE_CSR use the same bits | ||
| 476 | * for interrupts and interrupt masks we can just use the value of | ||
| 477 | * INT_SOURCE_CSR to create the interrupt mask. | ||
| 478 | */ | ||
| 479 | mask = ~reg; | ||
| 480 | |||
| 481 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) { | ||
| 482 | rt2800mmio_txstatus_interrupt(rt2x00dev); | ||
| 483 | /* | ||
| 484 | * Never disable the TX_FIFO_STATUS interrupt. | ||
| 485 | */ | ||
| 486 | rt2x00_set_field32(&mask, INT_MASK_CSR_TX_FIFO_STATUS, 1); | ||
| 487 | } | ||
| 488 | |||
| 489 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT)) | ||
| 490 | tasklet_hi_schedule(&rt2x00dev->pretbtt_tasklet); | ||
| 491 | |||
| 492 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT)) | ||
| 493 | tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet); | ||
| 494 | |||
| 495 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE)) | ||
| 496 | tasklet_schedule(&rt2x00dev->rxdone_tasklet); | ||
| 497 | |||
| 498 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) | ||
| 499 | tasklet_schedule(&rt2x00dev->autowake_tasklet); | ||
| 500 | |||
| 501 | /* | ||
| 502 | * Disable all interrupts for which a tasklet was scheduled right now, | ||
| 503 | * the tasklet will reenable the appropriate interrupts. | ||
| 504 | */ | ||
| 505 | spin_lock(&rt2x00dev->irqmask_lock); | ||
| 506 | rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, ®); | ||
| 507 | reg &= mask; | ||
| 508 | rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg); | ||
| 509 | spin_unlock(&rt2x00dev->irqmask_lock); | ||
| 510 | |||
| 511 | return IRQ_HANDLED; | ||
| 512 | } | ||
| 513 | EXPORT_SYMBOL_GPL(rt2800mmio_interrupt); | ||
| 514 | |||
| 515 | void rt2800mmio_toggle_irq(struct rt2x00_dev *rt2x00dev, | ||
| 516 | enum dev_state state) | ||
| 517 | { | ||
| 518 | u32 reg; | ||
| 519 | unsigned long flags; | ||
| 520 | |||
| 521 | /* | ||
| 522 | * When interrupts are being enabled, the interrupt registers | ||
| 523 | * should clear the register to assure a clean state. | ||
| 524 | */ | ||
| 525 | if (state == STATE_RADIO_IRQ_ON) { | ||
| 526 | rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, ®); | ||
| 527 | rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg); | ||
| 528 | } | ||
| 529 | |||
| 530 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
| 531 | reg = 0; | ||
| 532 | if (state == STATE_RADIO_IRQ_ON) { | ||
| 533 | rt2x00_set_field32(®, INT_MASK_CSR_RX_DONE, 1); | ||
| 534 | rt2x00_set_field32(®, INT_MASK_CSR_TBTT, 1); | ||
| 535 | rt2x00_set_field32(®, INT_MASK_CSR_PRE_TBTT, 1); | ||
| 536 | rt2x00_set_field32(®, INT_MASK_CSR_TX_FIFO_STATUS, 1); | ||
| 537 | rt2x00_set_field32(®, INT_MASK_CSR_AUTO_WAKEUP, 1); | ||
| 538 | } | ||
| 539 | rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg); | ||
| 540 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | ||
| 541 | |||
| 542 | if (state == STATE_RADIO_IRQ_OFF) { | ||
| 543 | /* | ||
| 544 | * Wait for possibly running tasklets to finish. | ||
| 545 | */ | ||
| 546 | tasklet_kill(&rt2x00dev->txstatus_tasklet); | ||
| 547 | tasklet_kill(&rt2x00dev->rxdone_tasklet); | ||
| 548 | tasklet_kill(&rt2x00dev->autowake_tasklet); | ||
| 549 | tasklet_kill(&rt2x00dev->tbtt_tasklet); | ||
| 550 | tasklet_kill(&rt2x00dev->pretbtt_tasklet); | ||
| 551 | } | ||
| 552 | } | ||
| 553 | EXPORT_SYMBOL_GPL(rt2800mmio_toggle_irq); | ||
| 554 | |||
| 555 | /* | ||
| 556 | * Queue handlers. | ||
| 557 | */ | ||
| 558 | void rt2800mmio_start_queue(struct data_queue *queue) | ||
| 559 | { | ||
| 560 | struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; | ||
| 561 | u32 reg; | ||
| 562 | |||
| 563 | switch (queue->qid) { | ||
| 564 | case QID_RX: | ||
| 565 | rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL, ®); | ||
| 566 | rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); | ||
| 567 | rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | ||
| 568 | break; | ||
| 569 | case QID_BEACON: | ||
| 570 | rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
| 571 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); | ||
| 572 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); | ||
| 573 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); | ||
| 574 | rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
| 575 | |||
| 576 | rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN, ®); | ||
| 577 | rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, 1); | ||
| 578 | rt2x00mmio_register_write(rt2x00dev, INT_TIMER_EN, reg); | ||
| 579 | break; | ||
| 580 | default: | ||
| 581 | break; | ||
| 582 | } | ||
| 583 | } | ||
| 584 | EXPORT_SYMBOL_GPL(rt2800mmio_start_queue); | ||
| 585 | |||
| 586 | void rt2800mmio_kick_queue(struct data_queue *queue) | ||
| 587 | { | ||
| 588 | struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; | ||
| 589 | struct queue_entry *entry; | ||
| 590 | |||
| 591 | switch (queue->qid) { | ||
| 592 | case QID_AC_VO: | ||
| 593 | case QID_AC_VI: | ||
| 594 | case QID_AC_BE: | ||
| 595 | case QID_AC_BK: | ||
| 596 | entry = rt2x00queue_get_entry(queue, Q_INDEX); | ||
| 597 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(queue->qid), | ||
| 598 | entry->entry_idx); | ||
| 599 | break; | ||
| 600 | case QID_MGMT: | ||
| 601 | entry = rt2x00queue_get_entry(queue, Q_INDEX); | ||
| 602 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(5), | ||
| 603 | entry->entry_idx); | ||
| 604 | break; | ||
| 605 | default: | ||
| 606 | break; | ||
| 607 | } | ||
| 608 | } | ||
| 609 | EXPORT_SYMBOL_GPL(rt2800mmio_kick_queue); | ||
| 610 | |||
| 611 | void rt2800mmio_stop_queue(struct data_queue *queue) | ||
| 612 | { | ||
| 613 | struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; | ||
| 614 | u32 reg; | ||
| 615 | |||
| 616 | switch (queue->qid) { | ||
| 617 | case QID_RX: | ||
| 618 | rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL, ®); | ||
| 619 | rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); | ||
| 620 | rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | ||
| 621 | break; | ||
| 622 | case QID_BEACON: | ||
| 623 | rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
| 624 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); | ||
| 625 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); | ||
| 626 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); | ||
| 627 | rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
| 628 | |||
| 629 | rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN, ®); | ||
| 630 | rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, 0); | ||
| 631 | rt2x00mmio_register_write(rt2x00dev, INT_TIMER_EN, reg); | ||
| 632 | |||
| 633 | /* | ||
| 634 | * Wait for current invocation to finish. The tasklet | ||
| 635 | * won't be scheduled anymore afterwards since we disabled | ||
| 636 | * the TBTT and PRE TBTT timer. | ||
| 637 | */ | ||
| 638 | tasklet_kill(&rt2x00dev->tbtt_tasklet); | ||
| 639 | tasklet_kill(&rt2x00dev->pretbtt_tasklet); | ||
| 640 | |||
| 641 | break; | ||
| 642 | default: | ||
| 643 | break; | ||
| 644 | } | ||
| 645 | } | ||
| 646 | EXPORT_SYMBOL_GPL(rt2800mmio_stop_queue); | ||
| 647 | |||
| 648 | void rt2800mmio_queue_init(struct data_queue *queue) | ||
| 649 | { | ||
| 650 | struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; | ||
| 651 | unsigned short txwi_size, rxwi_size; | ||
| 652 | |||
| 653 | rt2800_get_txwi_rxwi_size(rt2x00dev, &txwi_size, &rxwi_size); | ||
| 654 | |||
| 655 | switch (queue->qid) { | ||
| 656 | case QID_RX: | ||
| 657 | queue->limit = 128; | ||
| 658 | queue->data_size = AGGREGATION_SIZE; | ||
| 659 | queue->desc_size = RXD_DESC_SIZE; | ||
| 660 | queue->winfo_size = rxwi_size; | ||
| 661 | queue->priv_size = sizeof(struct queue_entry_priv_mmio); | ||
| 662 | break; | ||
| 663 | |||
| 664 | case QID_AC_VO: | ||
| 665 | case QID_AC_VI: | ||
| 666 | case QID_AC_BE: | ||
| 667 | case QID_AC_BK: | ||
| 668 | queue->limit = 64; | ||
| 669 | queue->data_size = AGGREGATION_SIZE; | ||
| 670 | queue->desc_size = TXD_DESC_SIZE; | ||
| 671 | queue->winfo_size = txwi_size; | ||
| 672 | queue->priv_size = sizeof(struct queue_entry_priv_mmio); | ||
| 673 | break; | ||
| 674 | |||
| 675 | case QID_BEACON: | ||
| 676 | queue->limit = 8; | ||
| 677 | queue->data_size = 0; /* No DMA required for beacons */ | ||
| 678 | queue->desc_size = TXD_DESC_SIZE; | ||
| 679 | queue->winfo_size = txwi_size; | ||
| 680 | queue->priv_size = sizeof(struct queue_entry_priv_mmio); | ||
| 681 | break; | ||
| 682 | |||
| 683 | case QID_ATIM: | ||
| 684 | /* fallthrough */ | ||
| 685 | default: | ||
| 686 | BUG(); | ||
| 687 | break; | ||
| 688 | } | ||
| 689 | } | ||
| 690 | EXPORT_SYMBOL_GPL(rt2800mmio_queue_init); | ||
| 691 | |||
| 692 | /* | ||
| 693 | * Initialization functions. | ||
| 694 | */ | ||
| 695 | bool rt2800mmio_get_entry_state(struct queue_entry *entry) | ||
| 696 | { | ||
| 697 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; | ||
| 698 | u32 word; | ||
| 699 | |||
| 700 | if (entry->queue->qid == QID_RX) { | ||
| 701 | rt2x00_desc_read(entry_priv->desc, 1, &word); | ||
| 702 | |||
| 703 | return (!rt2x00_get_field32(word, RXD_W1_DMA_DONE)); | ||
| 704 | } else { | ||
| 705 | rt2x00_desc_read(entry_priv->desc, 1, &word); | ||
| 706 | |||
| 707 | return (!rt2x00_get_field32(word, TXD_W1_DMA_DONE)); | ||
| 708 | } | ||
| 709 | } | ||
| 710 | EXPORT_SYMBOL_GPL(rt2800mmio_get_entry_state); | ||
| 711 | |||
| 712 | void rt2800mmio_clear_entry(struct queue_entry *entry) | ||
| 713 | { | ||
| 714 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; | ||
| 715 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
| 716 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
| 717 | u32 word; | ||
| 718 | |||
| 719 | if (entry->queue->qid == QID_RX) { | ||
| 720 | rt2x00_desc_read(entry_priv->desc, 0, &word); | ||
| 721 | rt2x00_set_field32(&word, RXD_W0_SDP0, skbdesc->skb_dma); | ||
| 722 | rt2x00_desc_write(entry_priv->desc, 0, word); | ||
| 723 | |||
| 724 | rt2x00_desc_read(entry_priv->desc, 1, &word); | ||
| 725 | rt2x00_set_field32(&word, RXD_W1_DMA_DONE, 0); | ||
| 726 | rt2x00_desc_write(entry_priv->desc, 1, word); | ||
| 727 | |||
| 728 | /* | ||
| 729 | * Set RX IDX in register to inform hardware that we have | ||
| 730 | * handled this entry and it is available for reuse again. | ||
| 731 | */ | ||
| 732 | rt2x00mmio_register_write(rt2x00dev, RX_CRX_IDX, | ||
| 733 | entry->entry_idx); | ||
| 734 | } else { | ||
| 735 | rt2x00_desc_read(entry_priv->desc, 1, &word); | ||
| 736 | rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1); | ||
| 737 | rt2x00_desc_write(entry_priv->desc, 1, word); | ||
| 738 | } | ||
| 739 | } | ||
| 740 | EXPORT_SYMBOL_GPL(rt2800mmio_clear_entry); | ||
| 741 | |||
| 742 | int rt2800mmio_init_queues(struct rt2x00_dev *rt2x00dev) | ||
| 743 | { | ||
| 744 | struct queue_entry_priv_mmio *entry_priv; | ||
| 745 | |||
| 746 | /* | ||
| 747 | * Initialize registers. | ||
| 748 | */ | ||
| 749 | entry_priv = rt2x00dev->tx[0].entries[0].priv_data; | ||
| 750 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR0, | ||
| 751 | entry_priv->desc_dma); | ||
| 752 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT0, | ||
| 753 | rt2x00dev->tx[0].limit); | ||
| 754 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX0, 0); | ||
| 755 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX0, 0); | ||
| 756 | |||
| 757 | entry_priv = rt2x00dev->tx[1].entries[0].priv_data; | ||
| 758 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR1, | ||
| 759 | entry_priv->desc_dma); | ||
| 760 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT1, | ||
| 761 | rt2x00dev->tx[1].limit); | ||
| 762 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX1, 0); | ||
| 763 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX1, 0); | ||
| 764 | |||
| 765 | entry_priv = rt2x00dev->tx[2].entries[0].priv_data; | ||
| 766 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR2, | ||
| 767 | entry_priv->desc_dma); | ||
| 768 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT2, | ||
| 769 | rt2x00dev->tx[2].limit); | ||
| 770 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX2, 0); | ||
| 771 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX2, 0); | ||
| 772 | |||
| 773 | entry_priv = rt2x00dev->tx[3].entries[0].priv_data; | ||
| 774 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR3, | ||
| 775 | entry_priv->desc_dma); | ||
| 776 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT3, | ||
| 777 | rt2x00dev->tx[3].limit); | ||
| 778 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX3, 0); | ||
| 779 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX3, 0); | ||
| 780 | |||
| 781 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR4, 0); | ||
| 782 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT4, 0); | ||
| 783 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX4, 0); | ||
| 784 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX4, 0); | ||
| 785 | |||
| 786 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR5, 0); | ||
| 787 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT5, 0); | ||
| 788 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX5, 0); | ||
| 789 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX5, 0); | ||
| 790 | |||
| 791 | entry_priv = rt2x00dev->rx->entries[0].priv_data; | ||
| 792 | rt2x00mmio_register_write(rt2x00dev, RX_BASE_PTR, | ||
| 793 | entry_priv->desc_dma); | ||
| 794 | rt2x00mmio_register_write(rt2x00dev, RX_MAX_CNT, | ||
| 795 | rt2x00dev->rx[0].limit); | ||
| 796 | rt2x00mmio_register_write(rt2x00dev, RX_CRX_IDX, | ||
| 797 | rt2x00dev->rx[0].limit - 1); | ||
| 798 | rt2x00mmio_register_write(rt2x00dev, RX_DRX_IDX, 0); | ||
| 799 | |||
| 800 | rt2800_disable_wpdma(rt2x00dev); | ||
| 801 | |||
| 802 | rt2x00mmio_register_write(rt2x00dev, DELAY_INT_CFG, 0); | ||
| 803 | |||
| 804 | return 0; | ||
| 805 | } | ||
| 806 | EXPORT_SYMBOL_GPL(rt2800mmio_init_queues); | ||
| 807 | |||
| 808 | int rt2800mmio_init_registers(struct rt2x00_dev *rt2x00dev) | ||
| 809 | { | ||
| 810 | u32 reg; | ||
| 811 | |||
| 812 | /* | ||
| 813 | * Reset DMA indexes | ||
| 814 | */ | ||
| 815 | rt2x00mmio_register_read(rt2x00dev, WPDMA_RST_IDX, ®); | ||
| 816 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); | ||
| 817 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); | ||
| 818 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); | ||
| 819 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, 1); | ||
| 820 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); | ||
| 821 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); | ||
| 822 | rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); | ||
| 823 | rt2x00mmio_register_write(rt2x00dev, WPDMA_RST_IDX, reg); | ||
| 824 | |||
| 825 | rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); | ||
| 826 | rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); | ||
| 827 | |||
| 828 | if (rt2x00_is_pcie(rt2x00dev) && | ||
| 829 | (rt2x00_rt(rt2x00dev, RT3090) || | ||
| 830 | rt2x00_rt(rt2x00dev, RT3390) || | ||
| 831 | rt2x00_rt(rt2x00dev, RT3572) || | ||
| 832 | rt2x00_rt(rt2x00dev, RT3593) || | ||
| 833 | rt2x00_rt(rt2x00dev, RT5390) || | ||
| 834 | rt2x00_rt(rt2x00dev, RT5392) || | ||
| 835 | rt2x00_rt(rt2x00dev, RT5592))) { | ||
| 836 | rt2x00mmio_register_read(rt2x00dev, AUX_CTRL, ®); | ||
| 837 | rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1); | ||
| 838 | rt2x00_set_field32(®, AUX_CTRL_WAKE_PCIE_EN, 1); | ||
| 839 | rt2x00mmio_register_write(rt2x00dev, AUX_CTRL, reg); | ||
| 840 | } | ||
| 841 | |||
| 842 | rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); | ||
| 843 | |||
| 844 | reg = 0; | ||
| 845 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); | ||
| 846 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); | ||
| 847 | rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | ||
| 848 | |||
| 849 | rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); | ||
| 850 | |||
| 851 | return 0; | ||
| 852 | } | ||
| 853 | EXPORT_SYMBOL_GPL(rt2800mmio_init_registers); | ||
| 854 | |||
| 855 | /* | ||
| 856 | * Device state switch handlers. | ||
| 857 | */ | ||
| 858 | int rt2800mmio_enable_radio(struct rt2x00_dev *rt2x00dev) | ||
| 859 | { | ||
| 860 | /* Wait for DMA, ignore error until we initialize queues. */ | ||
| 861 | rt2800_wait_wpdma_ready(rt2x00dev); | ||
| 862 | |||
| 863 | if (unlikely(rt2800mmio_init_queues(rt2x00dev))) | ||
| 864 | return -EIO; | ||
| 865 | |||
| 866 | return rt2800_enable_radio(rt2x00dev); | ||
| 867 | } | ||
| 868 | EXPORT_SYMBOL_GPL(rt2800mmio_enable_radio); | ||
| 869 | |||
| 870 | MODULE_AUTHOR(DRV_PROJECT); | ||
| 871 | MODULE_VERSION(DRV_VERSION); | ||
| 872 | MODULE_DESCRIPTION("rt2800 MMIO library"); | ||
| 873 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800mmio.h b/drivers/net/wireless/rt2x00/rt2800mmio.h new file mode 100644 index 000000000000..6a10de3eee3e --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2800mmio.h | |||
| @@ -0,0 +1,165 @@ | |||
| 1 | /* Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
| 2 | * Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com> | ||
| 3 | * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> | ||
| 4 | * Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com> | ||
| 5 | * Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de> | ||
| 6 | * Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com> | ||
| 7 | * Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com> | ||
| 8 | * Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com> | ||
| 9 | * <http://rt2x00.serialmonkey.com> | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License as published by | ||
| 13 | * the Free Software Foundation; either version 2 of the License, or | ||
| 14 | * (at your option) any later version. | ||
| 15 | * | ||
| 16 | * This program is distributed in the hope that it will be useful, | ||
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | * GNU General Public License for more details. | ||
| 20 | * | ||
| 21 | * You should have received a copy of the GNU General Public License | ||
| 22 | * along with this program; if not, write to the | ||
| 23 | * Free Software Foundation, Inc., | ||
| 24 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 25 | */ | ||
| 26 | |||
| 27 | /* Module: rt2800mmio | ||
| 28 | * Abstract: forward declarations for the rt2800mmio module. | ||
| 29 | */ | ||
| 30 | |||
| 31 | #ifndef RT2800MMIO_H | ||
| 32 | #define RT2800MMIO_H | ||
| 33 | |||
| 34 | /* | ||
| 35 | * Queue register offset macros | ||
| 36 | */ | ||
| 37 | #define TX_QUEUE_REG_OFFSET 0x10 | ||
| 38 | #define TX_BASE_PTR(__x) (TX_BASE_PTR0 + ((__x) * TX_QUEUE_REG_OFFSET)) | ||
| 39 | #define TX_MAX_CNT(__x) (TX_MAX_CNT0 + ((__x) * TX_QUEUE_REG_OFFSET)) | ||
| 40 | #define TX_CTX_IDX(__x) (TX_CTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)) | ||
| 41 | #define TX_DTX_IDX(__x) (TX_DTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)) | ||
| 42 | |||
| 43 | /* | ||
| 44 | * DMA descriptor defines. | ||
| 45 | */ | ||
| 46 | #define TXD_DESC_SIZE (4 * sizeof(__le32)) | ||
| 47 | #define RXD_DESC_SIZE (4 * sizeof(__le32)) | ||
| 48 | |||
| 49 | /* | ||
| 50 | * TX descriptor format for TX, PRIO and Beacon Ring. | ||
| 51 | */ | ||
| 52 | |||
| 53 | /* | ||
| 54 | * Word0 | ||
| 55 | */ | ||
| 56 | #define TXD_W0_SD_PTR0 FIELD32(0xffffffff) | ||
| 57 | |||
| 58 | /* | ||
| 59 | * Word1 | ||
| 60 | */ | ||
| 61 | #define TXD_W1_SD_LEN1 FIELD32(0x00003fff) | ||
| 62 | #define TXD_W1_LAST_SEC1 FIELD32(0x00004000) | ||
| 63 | #define TXD_W1_BURST FIELD32(0x00008000) | ||
| 64 | #define TXD_W1_SD_LEN0 FIELD32(0x3fff0000) | ||
| 65 | #define TXD_W1_LAST_SEC0 FIELD32(0x40000000) | ||
| 66 | #define TXD_W1_DMA_DONE FIELD32(0x80000000) | ||
| 67 | |||
| 68 | /* | ||
| 69 | * Word2 | ||
| 70 | */ | ||
| 71 | #define TXD_W2_SD_PTR1 FIELD32(0xffffffff) | ||
| 72 | |||
| 73 | /* | ||
| 74 | * Word3 | ||
| 75 | * WIV: Wireless Info Valid. 1: Driver filled WI, 0: DMA needs to copy WI | ||
| 76 | * QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler. | ||
| 77 | * 0:MGMT, 1:HCCA 2:EDCA | ||
| 78 | */ | ||
| 79 | #define TXD_W3_WIV FIELD32(0x01000000) | ||
| 80 | #define TXD_W3_QSEL FIELD32(0x06000000) | ||
| 81 | #define TXD_W3_TCO FIELD32(0x20000000) | ||
| 82 | #define TXD_W3_UCO FIELD32(0x40000000) | ||
| 83 | #define TXD_W3_ICO FIELD32(0x80000000) | ||
| 84 | |||
| 85 | /* | ||
| 86 | * RX descriptor format for RX Ring. | ||
| 87 | */ | ||
| 88 | |||
| 89 | /* | ||
| 90 | * Word0 | ||
| 91 | */ | ||
| 92 | #define RXD_W0_SDP0 FIELD32(0xffffffff) | ||
| 93 | |||
| 94 | /* | ||
| 95 | * Word1 | ||
| 96 | */ | ||
| 97 | #define RXD_W1_SDL1 FIELD32(0x00003fff) | ||
| 98 | #define RXD_W1_SDL0 FIELD32(0x3fff0000) | ||
| 99 | #define RXD_W1_LS0 FIELD32(0x40000000) | ||
| 100 | #define RXD_W1_DMA_DONE FIELD32(0x80000000) | ||
| 101 | |||
| 102 | /* | ||
| 103 | * Word2 | ||
| 104 | */ | ||
| 105 | #define RXD_W2_SDP1 FIELD32(0xffffffff) | ||
| 106 | |||
| 107 | /* | ||
| 108 | * Word3 | ||
| 109 | * AMSDU: RX with 802.3 header, not 802.11 header. | ||
| 110 | * DECRYPTED: This frame is being decrypted. | ||
| 111 | */ | ||
| 112 | #define RXD_W3_BA FIELD32(0x00000001) | ||
| 113 | #define RXD_W3_DATA FIELD32(0x00000002) | ||
| 114 | #define RXD_W3_NULLDATA FIELD32(0x00000004) | ||
| 115 | #define RXD_W3_FRAG FIELD32(0x00000008) | ||
| 116 | #define RXD_W3_UNICAST_TO_ME FIELD32(0x00000010) | ||
| 117 | #define RXD_W3_MULTICAST FIELD32(0x00000020) | ||
| 118 | #define RXD_W3_BROADCAST FIELD32(0x00000040) | ||
| 119 | #define RXD_W3_MY_BSS FIELD32(0x00000080) | ||
| 120 | #define RXD_W3_CRC_ERROR FIELD32(0x00000100) | ||
| 121 | #define RXD_W3_CIPHER_ERROR FIELD32(0x00000600) | ||
| 122 | #define RXD_W3_AMSDU FIELD32(0x00000800) | ||
| 123 | #define RXD_W3_HTC FIELD32(0x00001000) | ||
| 124 | #define RXD_W3_RSSI FIELD32(0x00002000) | ||
| 125 | #define RXD_W3_L2PAD FIELD32(0x00004000) | ||
| 126 | #define RXD_W3_AMPDU FIELD32(0x00008000) | ||
| 127 | #define RXD_W3_DECRYPTED FIELD32(0x00010000) | ||
| 128 | #define RXD_W3_PLCP_SIGNAL FIELD32(0x00020000) | ||
| 129 | #define RXD_W3_PLCP_RSSI FIELD32(0x00040000) | ||
| 130 | |||
| 131 | /* TX descriptor initialization */ | ||
| 132 | __le32 *rt2800mmio_get_txwi(struct queue_entry *entry); | ||
| 133 | void rt2800mmio_write_tx_desc(struct queue_entry *entry, | ||
| 134 | struct txentry_desc *txdesc); | ||
| 135 | |||
| 136 | /* RX control handlers */ | ||
| 137 | void rt2800mmio_fill_rxdone(struct queue_entry *entry, | ||
| 138 | struct rxdone_entry_desc *rxdesc); | ||
| 139 | |||
| 140 | /* Interrupt functions */ | ||
| 141 | void rt2800mmio_txstatus_tasklet(unsigned long data); | ||
| 142 | void rt2800mmio_pretbtt_tasklet(unsigned long data); | ||
| 143 | void rt2800mmio_tbtt_tasklet(unsigned long data); | ||
| 144 | void rt2800mmio_rxdone_tasklet(unsigned long data); | ||
| 145 | void rt2800mmio_autowake_tasklet(unsigned long data); | ||
| 146 | irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance); | ||
| 147 | void rt2800mmio_toggle_irq(struct rt2x00_dev *rt2x00dev, | ||
| 148 | enum dev_state state); | ||
| 149 | |||
| 150 | /* Queue handlers */ | ||
| 151 | void rt2800mmio_start_queue(struct data_queue *queue); | ||
| 152 | void rt2800mmio_kick_queue(struct data_queue *queue); | ||
| 153 | void rt2800mmio_stop_queue(struct data_queue *queue); | ||
| 154 | void rt2800mmio_queue_init(struct data_queue *queue); | ||
| 155 | |||
| 156 | /* Initialization functions */ | ||
| 157 | bool rt2800mmio_get_entry_state(struct queue_entry *entry); | ||
| 158 | void rt2800mmio_clear_entry(struct queue_entry *entry); | ||
| 159 | int rt2800mmio_init_queues(struct rt2x00_dev *rt2x00dev); | ||
| 160 | int rt2800mmio_init_registers(struct rt2x00_dev *rt2x00dev); | ||
| 161 | |||
| 162 | /* Device state switch handlers. */ | ||
| 163 | int rt2800mmio_enable_radio(struct rt2x00_dev *rt2x00dev); | ||
| 164 | |||
| 165 | #endif /* RT2800MMIO_H */ | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index f8f2abbfbb65..b504455b4fec 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
| @@ -37,14 +37,13 @@ | |||
| 37 | #include <linux/kernel.h> | 37 | #include <linux/kernel.h> |
| 38 | #include <linux/module.h> | 38 | #include <linux/module.h> |
| 39 | #include <linux/pci.h> | 39 | #include <linux/pci.h> |
| 40 | #include <linux/platform_device.h> | ||
| 41 | #include <linux/eeprom_93cx6.h> | 40 | #include <linux/eeprom_93cx6.h> |
| 42 | 41 | ||
| 43 | #include "rt2x00.h" | 42 | #include "rt2x00.h" |
| 44 | #include "rt2x00mmio.h" | 43 | #include "rt2x00mmio.h" |
| 45 | #include "rt2x00pci.h" | 44 | #include "rt2x00pci.h" |
| 46 | #include "rt2x00soc.h" | ||
| 47 | #include "rt2800lib.h" | 45 | #include "rt2800lib.h" |
| 46 | #include "rt2800mmio.h" | ||
| 48 | #include "rt2800.h" | 47 | #include "rt2800.h" |
| 49 | #include "rt2800pci.h" | 48 | #include "rt2800pci.h" |
| 50 | 49 | ||
| @@ -90,27 +89,6 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) | |||
| 90 | rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); | 89 | rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); |
| 91 | } | 90 | } |
| 92 | 91 | ||
| 93 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) | ||
| 94 | static int rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) | ||
| 95 | { | ||
| 96 | void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE); | ||
| 97 | |||
| 98 | if (!base_addr) | ||
| 99 | return -ENOMEM; | ||
| 100 | |||
| 101 | memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE); | ||
| 102 | |||
| 103 | iounmap(base_addr); | ||
| 104 | return 0; | ||
| 105 | } | ||
| 106 | #else | ||
| 107 | static inline int rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) | ||
| 108 | { | ||
| 109 | return -ENOMEM; | ||
| 110 | } | ||
| 111 | #endif /* CONFIG_SOC_RT288X || CONFIG_SOC_RT305X */ | ||
| 112 | |||
| 113 | #ifdef CONFIG_PCI | ||
| 114 | static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) | 92 | static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) |
| 115 | { | 93 | { |
| 116 | struct rt2x00_dev *rt2x00dev = eeprom->data; | 94 | struct rt2x00_dev *rt2x00dev = eeprom->data; |
| @@ -183,112 +161,6 @@ static inline int rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev) | |||
| 183 | { | 161 | { |
| 184 | return rt2800_read_eeprom_efuse(rt2x00dev); | 162 | return rt2800_read_eeprom_efuse(rt2x00dev); |
| 185 | } | 163 | } |
| 186 | #else | ||
| 187 | static inline int rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) | ||
| 188 | { | ||
| 189 | return -EOPNOTSUPP; | ||
| 190 | } | ||
| 191 | |||
| 192 | static inline int rt2800pci_efuse_detect(struct rt2x00_dev *rt2x00dev) | ||
| 193 | { | ||
| 194 | return 0; | ||
| 195 | } | ||
| 196 | |||
| 197 | static inline int rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev) | ||
| 198 | { | ||
| 199 | return -EOPNOTSUPP; | ||
| 200 | } | ||
| 201 | #endif /* CONFIG_PCI */ | ||
| 202 | |||
| 203 | /* | ||
| 204 | * Queue handlers. | ||
| 205 | */ | ||
| 206 | static void rt2800pci_start_queue(struct data_queue *queue) | ||
| 207 | { | ||
| 208 | struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; | ||
| 209 | u32 reg; | ||
| 210 | |||
| 211 | switch (queue->qid) { | ||
| 212 | case QID_RX: | ||
| 213 | rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL, ®); | ||
| 214 | rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); | ||
| 215 | rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | ||
| 216 | break; | ||
| 217 | case QID_BEACON: | ||
| 218 | rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
| 219 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); | ||
| 220 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); | ||
| 221 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); | ||
| 222 | rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
| 223 | |||
| 224 | rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN, ®); | ||
| 225 | rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, 1); | ||
| 226 | rt2x00mmio_register_write(rt2x00dev, INT_TIMER_EN, reg); | ||
| 227 | break; | ||
| 228 | default: | ||
| 229 | break; | ||
| 230 | } | ||
| 231 | } | ||
| 232 | |||
| 233 | static void rt2800pci_kick_queue(struct data_queue *queue) | ||
| 234 | { | ||
| 235 | struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; | ||
| 236 | struct queue_entry *entry; | ||
| 237 | |||
| 238 | switch (queue->qid) { | ||
| 239 | case QID_AC_VO: | ||
| 240 | case QID_AC_VI: | ||
| 241 | case QID_AC_BE: | ||
| 242 | case QID_AC_BK: | ||
| 243 | entry = rt2x00queue_get_entry(queue, Q_INDEX); | ||
| 244 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(queue->qid), | ||
| 245 | entry->entry_idx); | ||
| 246 | break; | ||
| 247 | case QID_MGMT: | ||
| 248 | entry = rt2x00queue_get_entry(queue, Q_INDEX); | ||
| 249 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(5), | ||
| 250 | entry->entry_idx); | ||
| 251 | break; | ||
| 252 | default: | ||
| 253 | break; | ||
| 254 | } | ||
| 255 | } | ||
| 256 | |||
| 257 | static void rt2800pci_stop_queue(struct data_queue *queue) | ||
| 258 | { | ||
| 259 | struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; | ||
| 260 | u32 reg; | ||
| 261 | |||
| 262 | switch (queue->qid) { | ||
| 263 | case QID_RX: | ||
| 264 | rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL, ®); | ||
| 265 | rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); | ||
| 266 | rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | ||
| 267 | break; | ||
| 268 | case QID_BEACON: | ||
| 269 | rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
| 270 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); | ||
| 271 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); | ||
| 272 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); | ||
| 273 | rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
| 274 | |||
| 275 | rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN, ®); | ||
| 276 | rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, 0); | ||
| 277 | rt2x00mmio_register_write(rt2x00dev, INT_TIMER_EN, reg); | ||
| 278 | |||
| 279 | /* | ||
| 280 | * Wait for current invocation to finish. The tasklet | ||
| 281 | * won't be scheduled anymore afterwards since we disabled | ||
| 282 | * the TBTT and PRE TBTT timer. | ||
| 283 | */ | ||
| 284 | tasklet_kill(&rt2x00dev->tbtt_tasklet); | ||
| 285 | tasklet_kill(&rt2x00dev->pretbtt_tasklet); | ||
| 286 | |||
| 287 | break; | ||
| 288 | default: | ||
| 289 | break; | ||
| 290 | } | ||
| 291 | } | ||
| 292 | 164 | ||
| 293 | /* | 165 | /* |
| 294 | * Firmware functions | 166 | * Firmware functions |
| @@ -332,217 +204,13 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev, | |||
| 332 | } | 204 | } |
| 333 | 205 | ||
| 334 | /* | 206 | /* |
| 335 | * Initialization functions. | ||
| 336 | */ | ||
| 337 | static bool rt2800pci_get_entry_state(struct queue_entry *entry) | ||
| 338 | { | ||
| 339 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; | ||
| 340 | u32 word; | ||
| 341 | |||
| 342 | if (entry->queue->qid == QID_RX) { | ||
| 343 | rt2x00_desc_read(entry_priv->desc, 1, &word); | ||
| 344 | |||
| 345 | return (!rt2x00_get_field32(word, RXD_W1_DMA_DONE)); | ||
| 346 | } else { | ||
| 347 | rt2x00_desc_read(entry_priv->desc, 1, &word); | ||
| 348 | |||
| 349 | return (!rt2x00_get_field32(word, TXD_W1_DMA_DONE)); | ||
| 350 | } | ||
| 351 | } | ||
| 352 | |||
| 353 | static void rt2800pci_clear_entry(struct queue_entry *entry) | ||
| 354 | { | ||
| 355 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; | ||
| 356 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
| 357 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
| 358 | u32 word; | ||
| 359 | |||
| 360 | if (entry->queue->qid == QID_RX) { | ||
| 361 | rt2x00_desc_read(entry_priv->desc, 0, &word); | ||
| 362 | rt2x00_set_field32(&word, RXD_W0_SDP0, skbdesc->skb_dma); | ||
| 363 | rt2x00_desc_write(entry_priv->desc, 0, word); | ||
| 364 | |||
| 365 | rt2x00_desc_read(entry_priv->desc, 1, &word); | ||
| 366 | rt2x00_set_field32(&word, RXD_W1_DMA_DONE, 0); | ||
| 367 | rt2x00_desc_write(entry_priv->desc, 1, word); | ||
| 368 | |||
| 369 | /* | ||
| 370 | * Set RX IDX in register to inform hardware that we have | ||
| 371 | * handled this entry and it is available for reuse again. | ||
| 372 | */ | ||
| 373 | rt2x00mmio_register_write(rt2x00dev, RX_CRX_IDX, | ||
| 374 | entry->entry_idx); | ||
| 375 | } else { | ||
| 376 | rt2x00_desc_read(entry_priv->desc, 1, &word); | ||
| 377 | rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1); | ||
| 378 | rt2x00_desc_write(entry_priv->desc, 1, word); | ||
| 379 | } | ||
| 380 | } | ||
| 381 | |||
| 382 | static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev) | ||
| 383 | { | ||
| 384 | struct queue_entry_priv_mmio *entry_priv; | ||
| 385 | |||
| 386 | /* | ||
| 387 | * Initialize registers. | ||
| 388 | */ | ||
| 389 | entry_priv = rt2x00dev->tx[0].entries[0].priv_data; | ||
| 390 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR0, | ||
| 391 | entry_priv->desc_dma); | ||
| 392 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT0, | ||
| 393 | rt2x00dev->tx[0].limit); | ||
| 394 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX0, 0); | ||
| 395 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX0, 0); | ||
| 396 | |||
| 397 | entry_priv = rt2x00dev->tx[1].entries[0].priv_data; | ||
| 398 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR1, | ||
| 399 | entry_priv->desc_dma); | ||
| 400 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT1, | ||
| 401 | rt2x00dev->tx[1].limit); | ||
| 402 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX1, 0); | ||
| 403 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX1, 0); | ||
| 404 | |||
| 405 | entry_priv = rt2x00dev->tx[2].entries[0].priv_data; | ||
| 406 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR2, | ||
| 407 | entry_priv->desc_dma); | ||
| 408 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT2, | ||
| 409 | rt2x00dev->tx[2].limit); | ||
| 410 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX2, 0); | ||
| 411 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX2, 0); | ||
| 412 | |||
| 413 | entry_priv = rt2x00dev->tx[3].entries[0].priv_data; | ||
| 414 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR3, | ||
| 415 | entry_priv->desc_dma); | ||
| 416 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT3, | ||
| 417 | rt2x00dev->tx[3].limit); | ||
| 418 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX3, 0); | ||
| 419 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX3, 0); | ||
| 420 | |||
| 421 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR4, 0); | ||
| 422 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT4, 0); | ||
| 423 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX4, 0); | ||
| 424 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX4, 0); | ||
| 425 | |||
| 426 | rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR5, 0); | ||
| 427 | rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT5, 0); | ||
| 428 | rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX5, 0); | ||
| 429 | rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX5, 0); | ||
| 430 | |||
| 431 | entry_priv = rt2x00dev->rx->entries[0].priv_data; | ||
| 432 | rt2x00mmio_register_write(rt2x00dev, RX_BASE_PTR, | ||
| 433 | entry_priv->desc_dma); | ||
| 434 | rt2x00mmio_register_write(rt2x00dev, RX_MAX_CNT, | ||
| 435 | rt2x00dev->rx[0].limit); | ||
| 436 | rt2x00mmio_register_write(rt2x00dev, RX_CRX_IDX, | ||
| 437 | rt2x00dev->rx[0].limit - 1); | ||
| 438 | rt2x00mmio_register_write(rt2x00dev, RX_DRX_IDX, 0); | ||
| 439 | |||
| 440 | rt2800_disable_wpdma(rt2x00dev); | ||
| 441 | |||
| 442 | rt2x00mmio_register_write(rt2x00dev, DELAY_INT_CFG, 0); | ||
| 443 | |||
| 444 | return 0; | ||
| 445 | } | ||
| 446 | |||
| 447 | /* | ||
| 448 | * Device state switch handlers. | 207 | * Device state switch handlers. |
| 449 | */ | 208 | */ |
| 450 | static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | ||
| 451 | enum dev_state state) | ||
| 452 | { | ||
| 453 | u32 reg; | ||
| 454 | unsigned long flags; | ||
| 455 | |||
| 456 | /* | ||
| 457 | * When interrupts are being enabled, the interrupt registers | ||
| 458 | * should clear the register to assure a clean state. | ||
| 459 | */ | ||
| 460 | if (state == STATE_RADIO_IRQ_ON) { | ||
| 461 | rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, ®); | ||
| 462 | rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg); | ||
| 463 | } | ||
| 464 | |||
| 465 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
| 466 | reg = 0; | ||
| 467 | if (state == STATE_RADIO_IRQ_ON) { | ||
| 468 | rt2x00_set_field32(®, INT_MASK_CSR_RX_DONE, 1); | ||
| 469 | rt2x00_set_field32(®, INT_MASK_CSR_TBTT, 1); | ||
| 470 | rt2x00_set_field32(®, INT_MASK_CSR_PRE_TBTT, 1); | ||
| 471 | rt2x00_set_field32(®, INT_MASK_CSR_TX_FIFO_STATUS, 1); | ||
| 472 | rt2x00_set_field32(®, INT_MASK_CSR_AUTO_WAKEUP, 1); | ||
| 473 | } | ||
| 474 | rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg); | ||
| 475 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | ||
| 476 | |||
| 477 | if (state == STATE_RADIO_IRQ_OFF) { | ||
| 478 | /* | ||
| 479 | * Wait for possibly running tasklets to finish. | ||
| 480 | */ | ||
| 481 | tasklet_kill(&rt2x00dev->txstatus_tasklet); | ||
| 482 | tasklet_kill(&rt2x00dev->rxdone_tasklet); | ||
| 483 | tasklet_kill(&rt2x00dev->autowake_tasklet); | ||
| 484 | tasklet_kill(&rt2x00dev->tbtt_tasklet); | ||
| 485 | tasklet_kill(&rt2x00dev->pretbtt_tasklet); | ||
| 486 | } | ||
| 487 | } | ||
| 488 | |||
| 489 | static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev) | ||
| 490 | { | ||
| 491 | u32 reg; | ||
| 492 | |||
| 493 | /* | ||
| 494 | * Reset DMA indexes | ||
| 495 | */ | ||
| 496 | rt2x00mmio_register_read(rt2x00dev, WPDMA_RST_IDX, ®); | ||
| 497 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); | ||
| 498 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); | ||
| 499 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); | ||
| 500 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, 1); | ||
| 501 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); | ||
| 502 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); | ||
| 503 | rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); | ||
| 504 | rt2x00mmio_register_write(rt2x00dev, WPDMA_RST_IDX, reg); | ||
| 505 | |||
| 506 | rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); | ||
| 507 | rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); | ||
| 508 | |||
| 509 | if (rt2x00_is_pcie(rt2x00dev) && | ||
| 510 | (rt2x00_rt(rt2x00dev, RT3090) || | ||
| 511 | rt2x00_rt(rt2x00dev, RT3390) || | ||
| 512 | rt2x00_rt(rt2x00dev, RT3572) || | ||
| 513 | rt2x00_rt(rt2x00dev, RT3593) || | ||
| 514 | rt2x00_rt(rt2x00dev, RT5390) || | ||
| 515 | rt2x00_rt(rt2x00dev, RT5392) || | ||
| 516 | rt2x00_rt(rt2x00dev, RT5592))) { | ||
| 517 | rt2x00mmio_register_read(rt2x00dev, AUX_CTRL, ®); | ||
| 518 | rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1); | ||
| 519 | rt2x00_set_field32(®, AUX_CTRL_WAKE_PCIE_EN, 1); | ||
| 520 | rt2x00mmio_register_write(rt2x00dev, AUX_CTRL, reg); | ||
| 521 | } | ||
| 522 | |||
| 523 | rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); | ||
| 524 | |||
| 525 | reg = 0; | ||
| 526 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); | ||
| 527 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); | ||
| 528 | rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | ||
| 529 | |||
| 530 | rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); | ||
| 531 | |||
| 532 | return 0; | ||
| 533 | } | ||
| 534 | |||
| 535 | static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev) | 209 | static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev) |
| 536 | { | 210 | { |
| 537 | int retval; | 211 | int retval; |
| 538 | 212 | ||
| 539 | /* Wait for DMA, ignore error until we initialize queues. */ | 213 | retval = rt2800mmio_enable_radio(rt2x00dev); |
| 540 | rt2800_wait_wpdma_ready(rt2x00dev); | ||
| 541 | |||
| 542 | if (unlikely(rt2800pci_init_queues(rt2x00dev))) | ||
| 543 | return -EIO; | ||
| 544 | |||
| 545 | retval = rt2800_enable_radio(rt2x00dev); | ||
| 546 | if (retval) | 214 | if (retval) |
| 547 | return retval; | 215 | return retval; |
| 548 | 216 | ||
| @@ -559,15 +227,6 @@ static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
| 559 | return retval; | 227 | return retval; |
| 560 | } | 228 | } |
| 561 | 229 | ||
| 562 | static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev) | ||
| 563 | { | ||
| 564 | if (rt2x00_is_soc(rt2x00dev)) { | ||
| 565 | rt2800_disable_radio(rt2x00dev); | ||
| 566 | rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0); | ||
| 567 | rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, 0); | ||
| 568 | } | ||
| 569 | } | ||
| 570 | |||
| 571 | static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev, | 230 | static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev, |
| 572 | enum dev_state state) | 231 | enum dev_state state) |
| 573 | { | 232 | { |
| @@ -601,12 +260,11 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
| 601 | * After the radio has been disabled, the device should | 260 | * After the radio has been disabled, the device should |
| 602 | * be put to sleep for powersaving. | 261 | * be put to sleep for powersaving. |
| 603 | */ | 262 | */ |
| 604 | rt2800pci_disable_radio(rt2x00dev); | ||
| 605 | rt2800pci_set_state(rt2x00dev, STATE_SLEEP); | 263 | rt2800pci_set_state(rt2x00dev, STATE_SLEEP); |
| 606 | break; | 264 | break; |
| 607 | case STATE_RADIO_IRQ_ON: | 265 | case STATE_RADIO_IRQ_ON: |
| 608 | case STATE_RADIO_IRQ_OFF: | 266 | case STATE_RADIO_IRQ_OFF: |
| 609 | rt2800pci_toggle_irq(rt2x00dev, state); | 267 | rt2800mmio_toggle_irq(rt2x00dev, state); |
| 610 | break; | 268 | break; |
| 611 | case STATE_DEEP_SLEEP: | 269 | case STATE_DEEP_SLEEP: |
| 612 | case STATE_SLEEP: | 270 | case STATE_SLEEP: |
| @@ -627,479 +285,13 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
| 627 | } | 285 | } |
| 628 | 286 | ||
| 629 | /* | 287 | /* |
| 630 | * TX descriptor initialization | ||
| 631 | */ | ||
| 632 | static __le32 *rt2800pci_get_txwi(struct queue_entry *entry) | ||
| 633 | { | ||
| 634 | return (__le32 *) entry->skb->data; | ||
| 635 | } | ||
| 636 | |||
| 637 | static void rt2800pci_write_tx_desc(struct queue_entry *entry, | ||
| 638 | struct txentry_desc *txdesc) | ||
| 639 | { | ||
| 640 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
| 641 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; | ||
| 642 | __le32 *txd = entry_priv->desc; | ||
| 643 | u32 word; | ||
| 644 | const unsigned int txwi_size = entry->queue->winfo_size; | ||
| 645 | |||
| 646 | /* | ||
| 647 | * The buffers pointed by SD_PTR0/SD_LEN0 and SD_PTR1/SD_LEN1 | ||
| 648 | * must contains a TXWI structure + 802.11 header + padding + 802.11 | ||
| 649 | * data. We choose to have SD_PTR0/SD_LEN0 only contains TXWI and | ||
| 650 | * SD_PTR1/SD_LEN1 contains 802.11 header + padding + 802.11 | ||
| 651 | * data. It means that LAST_SEC0 is always 0. | ||
| 652 | */ | ||
| 653 | |||
| 654 | /* | ||
| 655 | * Initialize TX descriptor | ||
| 656 | */ | ||
| 657 | word = 0; | ||
| 658 | rt2x00_set_field32(&word, TXD_W0_SD_PTR0, skbdesc->skb_dma); | ||
| 659 | rt2x00_desc_write(txd, 0, word); | ||
| 660 | |||
| 661 | word = 0; | ||
| 662 | rt2x00_set_field32(&word, TXD_W1_SD_LEN1, entry->skb->len); | ||
| 663 | rt2x00_set_field32(&word, TXD_W1_LAST_SEC1, | ||
| 664 | !test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); | ||
| 665 | rt2x00_set_field32(&word, TXD_W1_BURST, | ||
| 666 | test_bit(ENTRY_TXD_BURST, &txdesc->flags)); | ||
| 667 | rt2x00_set_field32(&word, TXD_W1_SD_LEN0, txwi_size); | ||
| 668 | rt2x00_set_field32(&word, TXD_W1_LAST_SEC0, 0); | ||
| 669 | rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0); | ||
| 670 | rt2x00_desc_write(txd, 1, word); | ||
| 671 | |||
| 672 | word = 0; | ||
| 673 | rt2x00_set_field32(&word, TXD_W2_SD_PTR1, | ||
| 674 | skbdesc->skb_dma + txwi_size); | ||
| 675 | rt2x00_desc_write(txd, 2, word); | ||
| 676 | |||
| 677 | word = 0; | ||
| 678 | rt2x00_set_field32(&word, TXD_W3_WIV, | ||
| 679 | !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); | ||
| 680 | rt2x00_set_field32(&word, TXD_W3_QSEL, 2); | ||
| 681 | rt2x00_desc_write(txd, 3, word); | ||
| 682 | |||
| 683 | /* | ||
| 684 | * Register descriptor details in skb frame descriptor. | ||
| 685 | */ | ||
| 686 | skbdesc->desc = txd; | ||
| 687 | skbdesc->desc_len = TXD_DESC_SIZE; | ||
| 688 | } | ||
| 689 | |||
| 690 | /* | ||
| 691 | * RX control handlers | ||
| 692 | */ | ||
| 693 | static void rt2800pci_fill_rxdone(struct queue_entry *entry, | ||
| 694 | struct rxdone_entry_desc *rxdesc) | ||
| 695 | { | ||
| 696 | struct queue_entry_priv_mmio *entry_priv = entry->priv_data; | ||
| 697 | __le32 *rxd = entry_priv->desc; | ||
| 698 | u32 word; | ||
| 699 | |||
| 700 | rt2x00_desc_read(rxd, 3, &word); | ||
| 701 | |||
| 702 | if (rt2x00_get_field32(word, RXD_W3_CRC_ERROR)) | ||
| 703 | rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; | ||
| 704 | |||
| 705 | /* | ||
| 706 | * Unfortunately we don't know the cipher type used during | ||
| 707 | * decryption. This prevents us from correct providing | ||
| 708 | * correct statistics through debugfs. | ||
| 709 | */ | ||
| 710 | rxdesc->cipher_status = rt2x00_get_field32(word, RXD_W3_CIPHER_ERROR); | ||
| 711 | |||
| 712 | if (rt2x00_get_field32(word, RXD_W3_DECRYPTED)) { | ||
| 713 | /* | ||
| 714 | * Hardware has stripped IV/EIV data from 802.11 frame during | ||
| 715 | * decryption. Unfortunately the descriptor doesn't contain | ||
| 716 | * any fields with the EIV/IV data either, so they can't | ||
| 717 | * be restored by rt2x00lib. | ||
| 718 | */ | ||
| 719 | rxdesc->flags |= RX_FLAG_IV_STRIPPED; | ||
| 720 | |||
| 721 | /* | ||
| 722 | * The hardware has already checked the Michael Mic and has | ||
| 723 | * stripped it from the frame. Signal this to mac80211. | ||
| 724 | */ | ||
| 725 | rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; | ||
| 726 | |||
| 727 | if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) | ||
| 728 | rxdesc->flags |= RX_FLAG_DECRYPTED; | ||
| 729 | else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) | ||
| 730 | rxdesc->flags |= RX_FLAG_MMIC_ERROR; | ||
| 731 | } | ||
| 732 | |||
| 733 | if (rt2x00_get_field32(word, RXD_W3_MY_BSS)) | ||
| 734 | rxdesc->dev_flags |= RXDONE_MY_BSS; | ||
| 735 | |||
| 736 | if (rt2x00_get_field32(word, RXD_W3_L2PAD)) | ||
| 737 | rxdesc->dev_flags |= RXDONE_L2PAD; | ||
| 738 | |||
| 739 | /* | ||
| 740 | * Process the RXWI structure that is at the start of the buffer. | ||
| 741 | */ | ||
| 742 | rt2800_process_rxwi(entry, rxdesc); | ||
| 743 | } | ||
| 744 | |||
| 745 | /* | ||
| 746 | * Interrupt functions. | ||
| 747 | */ | ||
| 748 | static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev) | ||
| 749 | { | ||
| 750 | struct ieee80211_conf conf = { .flags = 0 }; | ||
| 751 | struct rt2x00lib_conf libconf = { .conf = &conf }; | ||
| 752 | |||
| 753 | rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); | ||
| 754 | } | ||
| 755 | |||
| 756 | static bool rt2800pci_txdone_entry_check(struct queue_entry *entry, u32 status) | ||
| 757 | { | ||
| 758 | __le32 *txwi; | ||
| 759 | u32 word; | ||
| 760 | int wcid, tx_wcid; | ||
| 761 | |||
| 762 | wcid = rt2x00_get_field32(status, TX_STA_FIFO_WCID); | ||
| 763 | |||
| 764 | txwi = rt2800_drv_get_txwi(entry); | ||
| 765 | rt2x00_desc_read(txwi, 1, &word); | ||
| 766 | tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); | ||
| 767 | |||
| 768 | return (tx_wcid == wcid); | ||
| 769 | } | ||
| 770 | |||
| 771 | static bool rt2800pci_txdone_find_entry(struct queue_entry *entry, void *data) | ||
| 772 | { | ||
| 773 | u32 status = *(u32 *)data; | ||
| 774 | |||
| 775 | /* | ||
| 776 | * rt2800pci hardware might reorder frames when exchanging traffic | ||
| 777 | * with multiple BA enabled STAs. | ||
| 778 | * | ||
| 779 | * For example, a tx queue | ||
| 780 | * [ STA1 | STA2 | STA1 | STA2 ] | ||
| 781 | * can result in tx status reports | ||
| 782 | * [ STA1 | STA1 | STA2 | STA2 ] | ||
| 783 | * when the hw decides to aggregate the frames for STA1 into one AMPDU. | ||
| 784 | * | ||
| 785 | * To mitigate this effect, associate the tx status to the first frame | ||
| 786 | * in the tx queue with a matching wcid. | ||
| 787 | */ | ||
| 788 | if (rt2800pci_txdone_entry_check(entry, status) && | ||
| 789 | !test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { | ||
| 790 | /* | ||
| 791 | * Got a matching frame, associate the tx status with | ||
| 792 | * the frame | ||
| 793 | */ | ||
| 794 | entry->status = status; | ||
| 795 | set_bit(ENTRY_DATA_STATUS_SET, &entry->flags); | ||
| 796 | return true; | ||
| 797 | } | ||
| 798 | |||
| 799 | /* Check the next frame */ | ||
| 800 | return false; | ||
| 801 | } | ||
| 802 | |||
| 803 | static bool rt2800pci_txdone_match_first(struct queue_entry *entry, void *data) | ||
| 804 | { | ||
| 805 | u32 status = *(u32 *)data; | ||
| 806 | |||
| 807 | /* | ||
| 808 | * Find the first frame without tx status and assign this status to it | ||
| 809 | * regardless if it matches or not. | ||
| 810 | */ | ||
| 811 | if (!test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { | ||
| 812 | /* | ||
| 813 | * Got a matching frame, associate the tx status with | ||
| 814 | * the frame | ||
| 815 | */ | ||
| 816 | entry->status = status; | ||
| 817 | set_bit(ENTRY_DATA_STATUS_SET, &entry->flags); | ||
| 818 | return true; | ||
| 819 | } | ||
| 820 | |||
| 821 | /* Check the next frame */ | ||
| 822 | return false; | ||
| 823 | } | ||
| 824 | static bool rt2800pci_txdone_release_entries(struct queue_entry *entry, | ||
| 825 | void *data) | ||
| 826 | { | ||
| 827 | if (test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { | ||
| 828 | rt2800_txdone_entry(entry, entry->status, | ||
| 829 | rt2800pci_get_txwi(entry)); | ||
| 830 | return false; | ||
| 831 | } | ||
| 832 | |||
| 833 | /* No more frames to release */ | ||
| 834 | return true; | ||
| 835 | } | ||
| 836 | |||
| 837 | static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) | ||
| 838 | { | ||
| 839 | struct data_queue *queue; | ||
| 840 | u32 status; | ||
| 841 | u8 qid; | ||
| 842 | int max_tx_done = 16; | ||
| 843 | |||
| 844 | while (kfifo_get(&rt2x00dev->txstatus_fifo, &status)) { | ||
| 845 | qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE); | ||
| 846 | if (unlikely(qid >= QID_RX)) { | ||
| 847 | /* | ||
| 848 | * Unknown queue, this shouldn't happen. Just drop | ||
| 849 | * this tx status. | ||
| 850 | */ | ||
| 851 | rt2x00_warn(rt2x00dev, "Got TX status report with unexpected pid %u, dropping\n", | ||
| 852 | qid); | ||
| 853 | break; | ||
| 854 | } | ||
| 855 | |||
| 856 | queue = rt2x00queue_get_tx_queue(rt2x00dev, qid); | ||
| 857 | if (unlikely(queue == NULL)) { | ||
| 858 | /* | ||
| 859 | * The queue is NULL, this shouldn't happen. Stop | ||
| 860 | * processing here and drop the tx status | ||
| 861 | */ | ||
| 862 | rt2x00_warn(rt2x00dev, "Got TX status for an unavailable queue %u, dropping\n", | ||
| 863 | qid); | ||
| 864 | break; | ||
| 865 | } | ||
| 866 | |||
| 867 | if (unlikely(rt2x00queue_empty(queue))) { | ||
| 868 | /* | ||
| 869 | * The queue is empty. Stop processing here | ||
| 870 | * and drop the tx status. | ||
| 871 | */ | ||
| 872 | rt2x00_warn(rt2x00dev, "Got TX status for an empty queue %u, dropping\n", | ||
| 873 | qid); | ||
| 874 | break; | ||
| 875 | } | ||
| 876 | |||
| 877 | /* | ||
| 878 | * Let's associate this tx status with the first | ||
| 879 | * matching frame. | ||
| 880 | */ | ||
| 881 | if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, | ||
| 882 | Q_INDEX, &status, | ||
| 883 | rt2800pci_txdone_find_entry)) { | ||
| 884 | /* | ||
| 885 | * We cannot match the tx status to any frame, so just | ||
| 886 | * use the first one. | ||
| 887 | */ | ||
| 888 | if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, | ||
| 889 | Q_INDEX, &status, | ||
| 890 | rt2800pci_txdone_match_first)) { | ||
| 891 | rt2x00_warn(rt2x00dev, "No frame found for TX status on queue %u, dropping\n", | ||
| 892 | qid); | ||
| 893 | break; | ||
| 894 | } | ||
| 895 | } | ||
| 896 | |||
| 897 | /* | ||
| 898 | * Release all frames with a valid tx status. | ||
| 899 | */ | ||
| 900 | rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, | ||
| 901 | Q_INDEX, NULL, | ||
| 902 | rt2800pci_txdone_release_entries); | ||
| 903 | |||
| 904 | if (--max_tx_done == 0) | ||
| 905 | break; | ||
| 906 | } | ||
| 907 | |||
| 908 | return !max_tx_done; | ||
| 909 | } | ||
| 910 | |||
| 911 | static inline void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, | ||
| 912 | struct rt2x00_field32 irq_field) | ||
| 913 | { | ||
| 914 | u32 reg; | ||
| 915 | |||
| 916 | /* | ||
| 917 | * Enable a single interrupt. The interrupt mask register | ||
| 918 | * access needs locking. | ||
| 919 | */ | ||
| 920 | spin_lock_irq(&rt2x00dev->irqmask_lock); | ||
| 921 | rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, ®); | ||
| 922 | rt2x00_set_field32(®, irq_field, 1); | ||
| 923 | rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg); | ||
| 924 | spin_unlock_irq(&rt2x00dev->irqmask_lock); | ||
| 925 | } | ||
| 926 | |||
| 927 | static void rt2800pci_txstatus_tasklet(unsigned long data) | ||
| 928 | { | ||
| 929 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
| 930 | if (rt2800pci_txdone(rt2x00dev)) | ||
| 931 | tasklet_schedule(&rt2x00dev->txstatus_tasklet); | ||
| 932 | |||
| 933 | /* | ||
| 934 | * No need to enable the tx status interrupt here as we always | ||
| 935 | * leave it enabled to minimize the possibility of a tx status | ||
| 936 | * register overflow. See comment in interrupt handler. | ||
| 937 | */ | ||
| 938 | } | ||
| 939 | |||
| 940 | static void rt2800pci_pretbtt_tasklet(unsigned long data) | ||
| 941 | { | ||
| 942 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
| 943 | rt2x00lib_pretbtt(rt2x00dev); | ||
| 944 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
| 945 | rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_PRE_TBTT); | ||
| 946 | } | ||
| 947 | |||
| 948 | static void rt2800pci_tbtt_tasklet(unsigned long data) | ||
| 949 | { | ||
| 950 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
| 951 | struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; | ||
| 952 | u32 reg; | ||
| 953 | |||
| 954 | rt2x00lib_beacondone(rt2x00dev); | ||
| 955 | |||
| 956 | if (rt2x00dev->intf_ap_count) { | ||
| 957 | /* | ||
| 958 | * The rt2800pci hardware tbtt timer is off by 1us per tbtt | ||
| 959 | * causing beacon skew and as a result causing problems with | ||
| 960 | * some powersaving clients over time. Shorten the beacon | ||
| 961 | * interval every 64 beacons by 64us to mitigate this effect. | ||
| 962 | */ | ||
| 963 | if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 2)) { | ||
| 964 | rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
| 965 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, | ||
| 966 | (rt2x00dev->beacon_int * 16) - 1); | ||
| 967 | rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
| 968 | } else if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 1)) { | ||
| 969 | rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
| 970 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, | ||
| 971 | (rt2x00dev->beacon_int * 16)); | ||
| 972 | rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
| 973 | } | ||
| 974 | drv_data->tbtt_tick++; | ||
| 975 | drv_data->tbtt_tick %= BCN_TBTT_OFFSET; | ||
| 976 | } | ||
| 977 | |||
| 978 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
| 979 | rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT); | ||
| 980 | } | ||
| 981 | |||
| 982 | static void rt2800pci_rxdone_tasklet(unsigned long data) | ||
| 983 | { | ||
| 984 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
| 985 | if (rt2x00mmio_rxdone(rt2x00dev)) | ||
| 986 | tasklet_schedule(&rt2x00dev->rxdone_tasklet); | ||
| 987 | else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
| 988 | rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE); | ||
| 989 | } | ||
| 990 | |||
| 991 | static void rt2800pci_autowake_tasklet(unsigned long data) | ||
| 992 | { | ||
| 993 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
| 994 | rt2800pci_wakeup(rt2x00dev); | ||
| 995 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
| 996 | rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_AUTO_WAKEUP); | ||
| 997 | } | ||
| 998 | |||
| 999 | static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) | ||
| 1000 | { | ||
| 1001 | u32 status; | ||
| 1002 | int i; | ||
| 1003 | |||
| 1004 | /* | ||
| 1005 | * The TX_FIFO_STATUS interrupt needs special care. We should | ||
| 1006 | * read TX_STA_FIFO but we should do it immediately as otherwise | ||
| 1007 | * the register can overflow and we would lose status reports. | ||
| 1008 | * | ||
| 1009 | * Hence, read the TX_STA_FIFO register and copy all tx status | ||
| 1010 | * reports into a kernel FIFO which is handled in the txstatus | ||
| 1011 | * tasklet. We use a tasklet to process the tx status reports | ||
| 1012 | * because we can schedule the tasklet multiple times (when the | ||
| 1013 | * interrupt fires again during tx status processing). | ||
| 1014 | * | ||
| 1015 | * Furthermore we don't disable the TX_FIFO_STATUS | ||
| 1016 | * interrupt here but leave it enabled so that the TX_STA_FIFO | ||
| 1017 | * can also be read while the tx status tasklet gets executed. | ||
| 1018 | * | ||
| 1019 | * Since we have only one producer and one consumer we don't | ||
| 1020 | * need to lock the kfifo. | ||
| 1021 | */ | ||
| 1022 | for (i = 0; i < rt2x00dev->tx->limit; i++) { | ||
| 1023 | rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &status); | ||
| 1024 | |||
| 1025 | if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID)) | ||
| 1026 | break; | ||
| 1027 | |||
| 1028 | if (!kfifo_put(&rt2x00dev->txstatus_fifo, &status)) { | ||
| 1029 | rt2x00_warn(rt2x00dev, "TX status FIFO overrun, drop tx status report\n"); | ||
| 1030 | break; | ||
| 1031 | } | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | /* Schedule the tasklet for processing the tx status. */ | ||
| 1035 | tasklet_schedule(&rt2x00dev->txstatus_tasklet); | ||
| 1036 | } | ||
| 1037 | |||
| 1038 | static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) | ||
| 1039 | { | ||
| 1040 | struct rt2x00_dev *rt2x00dev = dev_instance; | ||
| 1041 | u32 reg, mask; | ||
| 1042 | |||
| 1043 | /* Read status and ACK all interrupts */ | ||
| 1044 | rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, ®); | ||
| 1045 | rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg); | ||
| 1046 | |||
| 1047 | if (!reg) | ||
| 1048 | return IRQ_NONE; | ||
| 1049 | |||
| 1050 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
| 1051 | return IRQ_HANDLED; | ||
| 1052 | |||
| 1053 | /* | ||
| 1054 | * Since INT_MASK_CSR and INT_SOURCE_CSR use the same bits | ||
| 1055 | * for interrupts and interrupt masks we can just use the value of | ||
| 1056 | * INT_SOURCE_CSR to create the interrupt mask. | ||
| 1057 | */ | ||
| 1058 | mask = ~reg; | ||
| 1059 | |||
| 1060 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) { | ||
| 1061 | rt2800pci_txstatus_interrupt(rt2x00dev); | ||
| 1062 | /* | ||
| 1063 | * Never disable the TX_FIFO_STATUS interrupt. | ||
| 1064 | */ | ||
| 1065 | rt2x00_set_field32(&mask, INT_MASK_CSR_TX_FIFO_STATUS, 1); | ||
| 1066 | } | ||
| 1067 | |||
| 1068 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT)) | ||
| 1069 | tasklet_hi_schedule(&rt2x00dev->pretbtt_tasklet); | ||
| 1070 | |||
| 1071 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT)) | ||
| 1072 | tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet); | ||
| 1073 | |||
| 1074 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE)) | ||
| 1075 | tasklet_schedule(&rt2x00dev->rxdone_tasklet); | ||
| 1076 | |||
| 1077 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) | ||
| 1078 | tasklet_schedule(&rt2x00dev->autowake_tasklet); | ||
| 1079 | |||
| 1080 | /* | ||
| 1081 | * Disable all interrupts for which a tasklet was scheduled right now, | ||
| 1082 | * the tasklet will reenable the appropriate interrupts. | ||
| 1083 | */ | ||
| 1084 | spin_lock(&rt2x00dev->irqmask_lock); | ||
| 1085 | rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, ®); | ||
| 1086 | reg &= mask; | ||
| 1087 | rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg); | ||
| 1088 | spin_unlock(&rt2x00dev->irqmask_lock); | ||
| 1089 | |||
| 1090 | return IRQ_HANDLED; | ||
| 1091 | } | ||
| 1092 | |||
| 1093 | /* | ||
| 1094 | * Device probe functions. | 288 | * Device probe functions. |
| 1095 | */ | 289 | */ |
| 1096 | static int rt2800pci_read_eeprom(struct rt2x00_dev *rt2x00dev) | 290 | static int rt2800pci_read_eeprom(struct rt2x00_dev *rt2x00dev) |
| 1097 | { | 291 | { |
| 1098 | int retval; | 292 | int retval; |
| 1099 | 293 | ||
| 1100 | if (rt2x00_is_soc(rt2x00dev)) | 294 | if (rt2800pci_efuse_detect(rt2x00dev)) |
| 1101 | retval = rt2800pci_read_eeprom_soc(rt2x00dev); | ||
| 1102 | else if (rt2800pci_efuse_detect(rt2x00dev)) | ||
| 1103 | retval = rt2800pci_read_eeprom_efuse(rt2x00dev); | 295 | retval = rt2800pci_read_eeprom_efuse(rt2x00dev); |
| 1104 | else | 296 | else |
| 1105 | retval = rt2800pci_read_eeprom_pci(rt2x00dev); | 297 | retval = rt2800pci_read_eeprom_pci(rt2x00dev); |
| @@ -1145,25 +337,25 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = { | |||
| 1145 | .read_eeprom = rt2800pci_read_eeprom, | 337 | .read_eeprom = rt2800pci_read_eeprom, |
| 1146 | .hwcrypt_disabled = rt2800pci_hwcrypt_disabled, | 338 | .hwcrypt_disabled = rt2800pci_hwcrypt_disabled, |
| 1147 | .drv_write_firmware = rt2800pci_write_firmware, | 339 | .drv_write_firmware = rt2800pci_write_firmware, |
| 1148 | .drv_init_registers = rt2800pci_init_registers, | 340 | .drv_init_registers = rt2800mmio_init_registers, |
| 1149 | .drv_get_txwi = rt2800pci_get_txwi, | 341 | .drv_get_txwi = rt2800mmio_get_txwi, |
| 1150 | }; | 342 | }; |
| 1151 | 343 | ||
| 1152 | static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | 344 | static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { |
| 1153 | .irq_handler = rt2800pci_interrupt, | 345 | .irq_handler = rt2800mmio_interrupt, |
| 1154 | .txstatus_tasklet = rt2800pci_txstatus_tasklet, | 346 | .txstatus_tasklet = rt2800mmio_txstatus_tasklet, |
| 1155 | .pretbtt_tasklet = rt2800pci_pretbtt_tasklet, | 347 | .pretbtt_tasklet = rt2800mmio_pretbtt_tasklet, |
| 1156 | .tbtt_tasklet = rt2800pci_tbtt_tasklet, | 348 | .tbtt_tasklet = rt2800mmio_tbtt_tasklet, |
| 1157 | .rxdone_tasklet = rt2800pci_rxdone_tasklet, | 349 | .rxdone_tasklet = rt2800mmio_rxdone_tasklet, |
| 1158 | .autowake_tasklet = rt2800pci_autowake_tasklet, | 350 | .autowake_tasklet = rt2800mmio_autowake_tasklet, |
| 1159 | .probe_hw = rt2800_probe_hw, | 351 | .probe_hw = rt2800_probe_hw, |
| 1160 | .get_firmware_name = rt2800pci_get_firmware_name, | 352 | .get_firmware_name = rt2800pci_get_firmware_name, |
| 1161 | .check_firmware = rt2800_check_firmware, | 353 | .check_firmware = rt2800_check_firmware, |
| 1162 | .load_firmware = rt2800_load_firmware, | 354 | .load_firmware = rt2800_load_firmware, |
| 1163 | .initialize = rt2x00mmio_initialize, | 355 | .initialize = rt2x00mmio_initialize, |
| 1164 | .uninitialize = rt2x00mmio_uninitialize, | 356 | .uninitialize = rt2x00mmio_uninitialize, |
| 1165 | .get_entry_state = rt2800pci_get_entry_state, | 357 | .get_entry_state = rt2800mmio_get_entry_state, |
| 1166 | .clear_entry = rt2800pci_clear_entry, | 358 | .clear_entry = rt2800mmio_clear_entry, |
| 1167 | .set_device_state = rt2800pci_set_device_state, | 359 | .set_device_state = rt2800pci_set_device_state, |
| 1168 | .rfkill_poll = rt2800_rfkill_poll, | 360 | .rfkill_poll = rt2800_rfkill_poll, |
| 1169 | .link_stats = rt2800_link_stats, | 361 | .link_stats = rt2800_link_stats, |
| @@ -1171,15 +363,15 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | |||
| 1171 | .link_tuner = rt2800_link_tuner, | 363 | .link_tuner = rt2800_link_tuner, |
| 1172 | .gain_calibration = rt2800_gain_calibration, | 364 | .gain_calibration = rt2800_gain_calibration, |
| 1173 | .vco_calibration = rt2800_vco_calibration, | 365 | .vco_calibration = rt2800_vco_calibration, |
| 1174 | .start_queue = rt2800pci_start_queue, | 366 | .start_queue = rt2800mmio_start_queue, |
| 1175 | .kick_queue = rt2800pci_kick_queue, | 367 | .kick_queue = rt2800mmio_kick_queue, |
| 1176 | .stop_queue = rt2800pci_stop_queue, | 368 | .stop_queue = rt2800mmio_stop_queue, |
| 1177 | .flush_queue = rt2x00mmio_flush_queue, | 369 | .flush_queue = rt2x00mmio_flush_queue, |
| 1178 | .write_tx_desc = rt2800pci_write_tx_desc, | 370 | .write_tx_desc = rt2800mmio_write_tx_desc, |
| 1179 | .write_tx_data = rt2800_write_tx_data, | 371 | .write_tx_data = rt2800_write_tx_data, |
| 1180 | .write_beacon = rt2800_write_beacon, | 372 | .write_beacon = rt2800_write_beacon, |
| 1181 | .clear_beacon = rt2800_clear_beacon, | 373 | .clear_beacon = rt2800_clear_beacon, |
| 1182 | .fill_rxdone = rt2800pci_fill_rxdone, | 374 | .fill_rxdone = rt2800mmio_fill_rxdone, |
| 1183 | .config_shared_key = rt2800_config_shared_key, | 375 | .config_shared_key = rt2800_config_shared_key, |
| 1184 | .config_pairwise_key = rt2800_config_pairwise_key, | 376 | .config_pairwise_key = rt2800_config_pairwise_key, |
| 1185 | .config_filter = rt2800_config_filter, | 377 | .config_filter = rt2800_config_filter, |
| @@ -1191,49 +383,6 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | |||
| 1191 | .sta_remove = rt2800_sta_remove, | 383 | .sta_remove = rt2800_sta_remove, |
| 1192 | }; | 384 | }; |
| 1193 | 385 | ||
| 1194 | static void rt2800pci_queue_init(struct data_queue *queue) | ||
| 1195 | { | ||
| 1196 | struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; | ||
| 1197 | unsigned short txwi_size, rxwi_size; | ||
| 1198 | |||
| 1199 | rt2800_get_txwi_rxwi_size(rt2x00dev, &txwi_size, &rxwi_size); | ||
| 1200 | |||
| 1201 | switch (queue->qid) { | ||
| 1202 | case QID_RX: | ||
| 1203 | queue->limit = 128; | ||
| 1204 | queue->data_size = AGGREGATION_SIZE; | ||
| 1205 | queue->desc_size = RXD_DESC_SIZE; | ||
| 1206 | queue->winfo_size = rxwi_size; | ||
| 1207 | queue->priv_size = sizeof(struct queue_entry_priv_mmio); | ||
| 1208 | break; | ||
| 1209 | |||
| 1210 | case QID_AC_VO: | ||
| 1211 | case QID_AC_VI: | ||
| 1212 | case QID_AC_BE: | ||
| 1213 | case QID_AC_BK: | ||
| 1214 | queue->limit = 64; | ||
| 1215 | queue->data_size = AGGREGATION_SIZE; | ||
| 1216 | queue->desc_size = TXD_DESC_SIZE; | ||
| 1217 | queue->winfo_size = txwi_size; | ||
| 1218 | queue->priv_size = sizeof(struct queue_entry_priv_mmio); | ||
| 1219 | break; | ||
| 1220 | |||
| 1221 | case QID_BEACON: | ||
| 1222 | queue->limit = 8; | ||
| 1223 | queue->data_size = 0; /* No DMA required for beacons */ | ||
| 1224 | queue->desc_size = TXD_DESC_SIZE; | ||
| 1225 | queue->winfo_size = txwi_size; | ||
| 1226 | queue->priv_size = sizeof(struct queue_entry_priv_mmio); | ||
| 1227 | break; | ||
| 1228 | |||
| 1229 | case QID_ATIM: | ||
| 1230 | /* fallthrough */ | ||
| 1231 | default: | ||
| 1232 | BUG(); | ||
| 1233 | break; | ||
| 1234 | } | ||
| 1235 | } | ||
| 1236 | |||
| 1237 | static const struct rt2x00_ops rt2800pci_ops = { | 386 | static const struct rt2x00_ops rt2800pci_ops = { |
| 1238 | .name = KBUILD_MODNAME, | 387 | .name = KBUILD_MODNAME, |
| 1239 | .drv_data_size = sizeof(struct rt2800_drv_data), | 388 | .drv_data_size = sizeof(struct rt2800_drv_data), |
| @@ -1241,7 +390,7 @@ static const struct rt2x00_ops rt2800pci_ops = { | |||
| 1241 | .eeprom_size = EEPROM_SIZE, | 390 | .eeprom_size = EEPROM_SIZE, |
| 1242 | .rf_size = RF_SIZE, | 391 | .rf_size = RF_SIZE, |
| 1243 | .tx_queues = NUM_TX_QUEUES, | 392 | .tx_queues = NUM_TX_QUEUES, |
| 1244 | .queue_init = rt2800pci_queue_init, | 393 | .queue_init = rt2800mmio_queue_init, |
| 1245 | .lib = &rt2800pci_rt2x00_ops, | 394 | .lib = &rt2800pci_rt2x00_ops, |
| 1246 | .drv = &rt2800pci_rt2800_ops, | 395 | .drv = &rt2800pci_rt2800_ops, |
| 1247 | .hw = &rt2800pci_mac80211_ops, | 396 | .hw = &rt2800pci_mac80211_ops, |
| @@ -1253,7 +402,6 @@ static const struct rt2x00_ops rt2800pci_ops = { | |||
| 1253 | /* | 402 | /* |
| 1254 | * RT2800pci module information. | 403 | * RT2800pci module information. |
| 1255 | */ | 404 | */ |
| 1256 | #ifdef CONFIG_PCI | ||
| 1257 | static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { | 405 | static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { |
| 1258 | { PCI_DEVICE(0x1814, 0x0601) }, | 406 | { PCI_DEVICE(0x1814, 0x0601) }, |
| 1259 | { PCI_DEVICE(0x1814, 0x0681) }, | 407 | { PCI_DEVICE(0x1814, 0x0681) }, |
| @@ -1298,38 +446,15 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { | |||
| 1298 | #endif | 446 | #endif |
| 1299 | { 0, } | 447 | { 0, } |
| 1300 | }; | 448 | }; |
| 1301 | #endif /* CONFIG_PCI */ | ||
| 1302 | 449 | ||
| 1303 | MODULE_AUTHOR(DRV_PROJECT); | 450 | MODULE_AUTHOR(DRV_PROJECT); |
| 1304 | MODULE_VERSION(DRV_VERSION); | 451 | MODULE_VERSION(DRV_VERSION); |
| 1305 | MODULE_DESCRIPTION("Ralink RT2800 PCI & PCMCIA Wireless LAN driver."); | 452 | MODULE_DESCRIPTION("Ralink RT2800 PCI & PCMCIA Wireless LAN driver."); |
| 1306 | MODULE_SUPPORTED_DEVICE("Ralink RT2860 PCI & PCMCIA chipset based cards"); | 453 | MODULE_SUPPORTED_DEVICE("Ralink RT2860 PCI & PCMCIA chipset based cards"); |
| 1307 | #ifdef CONFIG_PCI | ||
| 1308 | MODULE_FIRMWARE(FIRMWARE_RT2860); | 454 | MODULE_FIRMWARE(FIRMWARE_RT2860); |
| 1309 | MODULE_DEVICE_TABLE(pci, rt2800pci_device_table); | 455 | MODULE_DEVICE_TABLE(pci, rt2800pci_device_table); |
| 1310 | #endif /* CONFIG_PCI */ | ||
| 1311 | MODULE_LICENSE("GPL"); | 456 | MODULE_LICENSE("GPL"); |
| 1312 | 457 | ||
| 1313 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) | ||
| 1314 | static int rt2800soc_probe(struct platform_device *pdev) | ||
| 1315 | { | ||
| 1316 | return rt2x00soc_probe(pdev, &rt2800pci_ops); | ||
| 1317 | } | ||
| 1318 | |||
| 1319 | static struct platform_driver rt2800soc_driver = { | ||
| 1320 | .driver = { | ||
| 1321 | .name = "rt2800_wmac", | ||
| 1322 | .owner = THIS_MODULE, | ||
| 1323 | .mod_name = KBUILD_MODNAME, | ||
| 1324 | }, | ||
| 1325 | .probe = rt2800soc_probe, | ||
| 1326 | .remove = rt2x00soc_remove, | ||
| 1327 | .suspend = rt2x00soc_suspend, | ||
| 1328 | .resume = rt2x00soc_resume, | ||
| 1329 | }; | ||
| 1330 | #endif /* CONFIG_SOC_RT288X || CONFIG_SOC_RT305X */ | ||
| 1331 | |||
| 1332 | #ifdef CONFIG_PCI | ||
| 1333 | static int rt2800pci_probe(struct pci_dev *pci_dev, | 458 | static int rt2800pci_probe(struct pci_dev *pci_dev, |
| 1334 | const struct pci_device_id *id) | 459 | const struct pci_device_id *id) |
| 1335 | { | 460 | { |
| @@ -1344,39 +469,5 @@ static struct pci_driver rt2800pci_driver = { | |||
| 1344 | .suspend = rt2x00pci_suspend, | 469 | .suspend = rt2x00pci_suspend, |
| 1345 | .resume = rt2x00pci_resume, | 470 | .resume = rt2x00pci_resume, |
| 1346 | }; | 471 | }; |
| 1347 | #endif /* CONFIG_PCI */ | ||
| 1348 | |||
| 1349 | static int __init rt2800pci_init(void) | ||
| 1350 | { | ||
| 1351 | int ret = 0; | ||
| 1352 | |||
| 1353 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) | ||
| 1354 | ret = platform_driver_register(&rt2800soc_driver); | ||
| 1355 | if (ret) | ||
| 1356 | return ret; | ||
| 1357 | #endif | ||
| 1358 | #ifdef CONFIG_PCI | ||
| 1359 | ret = pci_register_driver(&rt2800pci_driver); | ||
| 1360 | if (ret) { | ||
| 1361 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) | ||
| 1362 | platform_driver_unregister(&rt2800soc_driver); | ||
| 1363 | #endif | ||
| 1364 | return ret; | ||
| 1365 | } | ||
| 1366 | #endif | ||
| 1367 | |||
| 1368 | return ret; | ||
| 1369 | } | ||
| 1370 | |||
| 1371 | static void __exit rt2800pci_exit(void) | ||
| 1372 | { | ||
| 1373 | #ifdef CONFIG_PCI | ||
| 1374 | pci_unregister_driver(&rt2800pci_driver); | ||
| 1375 | #endif | ||
| 1376 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) | ||
| 1377 | platform_driver_unregister(&rt2800soc_driver); | ||
| 1378 | #endif | ||
| 1379 | } | ||
| 1380 | 472 | ||
| 1381 | module_init(rt2800pci_init); | 473 | module_pci_driver(rt2800pci_driver); |
| 1382 | module_exit(rt2800pci_exit); | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h index ab22a087c50d..a81c9ee281c0 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.h +++ b/drivers/net/wireless/rt2x00/rt2800pci.h | |||
| @@ -35,107 +35,10 @@ | |||
| 35 | #define RT2800PCI_H | 35 | #define RT2800PCI_H |
| 36 | 36 | ||
| 37 | /* | 37 | /* |
| 38 | * Queue register offset macros | ||
| 39 | */ | ||
| 40 | #define TX_QUEUE_REG_OFFSET 0x10 | ||
| 41 | #define TX_BASE_PTR(__x) (TX_BASE_PTR0 + ((__x) * TX_QUEUE_REG_OFFSET)) | ||
| 42 | #define TX_MAX_CNT(__x) (TX_MAX_CNT0 + ((__x) * TX_QUEUE_REG_OFFSET)) | ||
| 43 | #define TX_CTX_IDX(__x) (TX_CTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)) | ||
| 44 | #define TX_DTX_IDX(__x) (TX_DTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)) | ||
| 45 | |||
| 46 | /* | ||
| 47 | * 8051 firmware image. | 38 | * 8051 firmware image. |
| 48 | */ | 39 | */ |
| 49 | #define FIRMWARE_RT2860 "rt2860.bin" | 40 | #define FIRMWARE_RT2860 "rt2860.bin" |
| 50 | #define FIRMWARE_RT3290 "rt3290.bin" | 41 | #define FIRMWARE_RT3290 "rt3290.bin" |
| 51 | #define FIRMWARE_IMAGE_BASE 0x2000 | 42 | #define FIRMWARE_IMAGE_BASE 0x2000 |
| 52 | 43 | ||
| 53 | /* | ||
| 54 | * DMA descriptor defines. | ||
| 55 | */ | ||
| 56 | #define TXD_DESC_SIZE (4 * sizeof(__le32)) | ||
| 57 | #define RXD_DESC_SIZE (4 * sizeof(__le32)) | ||
| 58 | |||
| 59 | /* | ||
| 60 | * TX descriptor format for TX, PRIO and Beacon Ring. | ||
| 61 | */ | ||
| 62 | |||
| 63 | /* | ||
| 64 | * Word0 | ||
| 65 | */ | ||
| 66 | #define TXD_W0_SD_PTR0 FIELD32(0xffffffff) | ||
| 67 | |||
| 68 | /* | ||
| 69 | * Word1 | ||
| 70 | */ | ||
| 71 | #define TXD_W1_SD_LEN1 FIELD32(0x00003fff) | ||
| 72 | #define TXD_W1_LAST_SEC1 FIELD32(0x00004000) | ||
| 73 | #define TXD_W1_BURST FIELD32(0x00008000) | ||
| 74 | #define TXD_W1_SD_LEN0 FIELD32(0x3fff0000) | ||
| 75 | #define TXD_W1_LAST_SEC0 FIELD32(0x40000000) | ||
| 76 | #define TXD_W1_DMA_DONE FIELD32(0x80000000) | ||
| 77 | |||
| 78 | /* | ||
| 79 | * Word2 | ||
| 80 | */ | ||
| 81 | #define TXD_W2_SD_PTR1 FIELD32(0xffffffff) | ||
| 82 | |||
| 83 | /* | ||
| 84 | * Word3 | ||
| 85 | * WIV: Wireless Info Valid. 1: Driver filled WI, 0: DMA needs to copy WI | ||
| 86 | * QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler. | ||
| 87 | * 0:MGMT, 1:HCCA 2:EDCA | ||
| 88 | */ | ||
| 89 | #define TXD_W3_WIV FIELD32(0x01000000) | ||
| 90 | #define TXD_W3_QSEL FIELD32(0x06000000) | ||
| 91 | #define TXD_W3_TCO FIELD32(0x20000000) | ||
| 92 | #define TXD_W3_UCO FIELD32(0x40000000) | ||
| 93 | #define TXD_W3_ICO FIELD32(0x80000000) | ||
| 94 | |||
| 95 | /* | ||
| 96 | * RX descriptor format for RX Ring. | ||
| 97 | */ | ||
| 98 | |||
| 99 | /* | ||
| 100 | * Word0 | ||
| 101 | */ | ||
| 102 | #define RXD_W0_SDP0 FIELD32(0xffffffff) | ||
| 103 | |||
| 104 | /* | ||
| 105 | * Word1 | ||
| 106 | */ | ||
| 107 | #define RXD_W1_SDL1 FIELD32(0x00003fff) | ||
| 108 | #define RXD_W1_SDL0 FIELD32(0x3fff0000) | ||
| 109 | #define RXD_W1_LS0 FIELD32(0x40000000) | ||
| 110 | #define RXD_W1_DMA_DONE FIELD32(0x80000000) | ||
| 111 | |||
| 112 | /* | ||
| 113 | * Word2 | ||
| 114 | */ | ||
| 115 | #define RXD_W2_SDP1 FIELD32(0xffffffff) | ||
| 116 | |||
| 117 | /* | ||
| 118 | * Word3 | ||
| 119 | * AMSDU: RX with 802.3 header, not 802.11 header. | ||
| 120 | * DECRYPTED: This frame is being decrypted. | ||
| 121 | */ | ||
| 122 | #define RXD_W3_BA FIELD32(0x00000001) | ||
| 123 | #define RXD_W3_DATA FIELD32(0x00000002) | ||
| 124 | #define RXD_W3_NULLDATA FIELD32(0x00000004) | ||
| 125 | #define RXD_W3_FRAG FIELD32(0x00000008) | ||
| 126 | #define RXD_W3_UNICAST_TO_ME FIELD32(0x00000010) | ||
| 127 | #define RXD_W3_MULTICAST FIELD32(0x00000020) | ||
| 128 | #define RXD_W3_BROADCAST FIELD32(0x00000040) | ||
| 129 | #define RXD_W3_MY_BSS FIELD32(0x00000080) | ||
| 130 | #define RXD_W3_CRC_ERROR FIELD32(0x00000100) | ||
| 131 | #define RXD_W3_CIPHER_ERROR FIELD32(0x00000600) | ||
| 132 | #define RXD_W3_AMSDU FIELD32(0x00000800) | ||
| 133 | #define RXD_W3_HTC FIELD32(0x00001000) | ||
| 134 | #define RXD_W3_RSSI FIELD32(0x00002000) | ||
| 135 | #define RXD_W3_L2PAD FIELD32(0x00004000) | ||
| 136 | #define RXD_W3_AMPDU FIELD32(0x00008000) | ||
| 137 | #define RXD_W3_DECRYPTED FIELD32(0x00010000) | ||
| 138 | #define RXD_W3_PLCP_SIGNAL FIELD32(0x00020000) | ||
| 139 | #define RXD_W3_PLCP_RSSI FIELD32(0x00040000) | ||
| 140 | |||
| 141 | #endif /* RT2800PCI_H */ | 44 | #endif /* RT2800PCI_H */ |
diff --git a/drivers/net/wireless/rt2x00/rt2800soc.c b/drivers/net/wireless/rt2x00/rt2800soc.c new file mode 100644 index 000000000000..1359227ca411 --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2800soc.c | |||
| @@ -0,0 +1,263 @@ | |||
| 1 | /* Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
| 2 | * Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com> | ||
| 3 | * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> | ||
| 4 | * Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com> | ||
| 5 | * Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de> | ||
| 6 | * Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com> | ||
| 7 | * Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com> | ||
| 8 | * Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com> | ||
| 9 | * <http://rt2x00.serialmonkey.com> | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License as published by | ||
| 13 | * the Free Software Foundation; either version 2 of the License, or | ||
| 14 | * (at your option) any later version. | ||
| 15 | * | ||
| 16 | * This program is distributed in the hope that it will be useful, | ||
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | * GNU General Public License for more details. | ||
| 20 | * | ||
| 21 | * You should have received a copy of the GNU General Public License | ||
| 22 | * along with this program; if not, write to the | ||
| 23 | * Free Software Foundation, Inc., | ||
| 24 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 25 | */ | ||
| 26 | |||
| 27 | /* Module: rt2800soc | ||
| 28 | * Abstract: rt2800 WiSoC specific routines. | ||
| 29 | */ | ||
| 30 | |||
| 31 | #include <linux/etherdevice.h> | ||
| 32 | #include <linux/init.h> | ||
| 33 | #include <linux/kernel.h> | ||
| 34 | #include <linux/module.h> | ||
| 35 | #include <linux/platform_device.h> | ||
| 36 | |||
| 37 | #include "rt2x00.h" | ||
| 38 | #include "rt2x00mmio.h" | ||
| 39 | #include "rt2x00soc.h" | ||
| 40 | #include "rt2800.h" | ||
| 41 | #include "rt2800lib.h" | ||
| 42 | #include "rt2800mmio.h" | ||
| 43 | |||
| 44 | /* Allow hardware encryption to be disabled. */ | ||
| 45 | static bool modparam_nohwcrypt; | ||
| 46 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); | ||
| 47 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | ||
| 48 | |||
| 49 | static bool rt2800soc_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev) | ||
| 50 | { | ||
| 51 | return modparam_nohwcrypt; | ||
| 52 | } | ||
| 53 | |||
| 54 | static void rt2800soc_disable_radio(struct rt2x00_dev *rt2x00dev) | ||
| 55 | { | ||
| 56 | rt2800_disable_radio(rt2x00dev); | ||
| 57 | rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0); | ||
| 58 | rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, 0); | ||
| 59 | } | ||
| 60 | |||
| 61 | static int rt2800soc_set_device_state(struct rt2x00_dev *rt2x00dev, | ||
| 62 | enum dev_state state) | ||
| 63 | { | ||
| 64 | int retval = 0; | ||
| 65 | |||
| 66 | switch (state) { | ||
| 67 | case STATE_RADIO_ON: | ||
| 68 | retval = rt2800mmio_enable_radio(rt2x00dev); | ||
| 69 | break; | ||
| 70 | |||
| 71 | case STATE_RADIO_OFF: | ||
| 72 | rt2800soc_disable_radio(rt2x00dev); | ||
| 73 | break; | ||
| 74 | |||
| 75 | case STATE_RADIO_IRQ_ON: | ||
| 76 | case STATE_RADIO_IRQ_OFF: | ||
| 77 | rt2800mmio_toggle_irq(rt2x00dev, state); | ||
| 78 | break; | ||
| 79 | |||
| 80 | case STATE_DEEP_SLEEP: | ||
| 81 | case STATE_SLEEP: | ||
| 82 | case STATE_STANDBY: | ||
| 83 | case STATE_AWAKE: | ||
| 84 | /* These states are not supported, but don't report an error */ | ||
| 85 | retval = 0; | ||
| 86 | break; | ||
| 87 | |||
| 88 | default: | ||
| 89 | retval = -ENOTSUPP; | ||
| 90 | break; | ||
| 91 | } | ||
| 92 | |||
| 93 | if (unlikely(retval)) | ||
| 94 | rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n", | ||
| 95 | state, retval); | ||
| 96 | |||
| 97 | return retval; | ||
| 98 | } | ||
| 99 | |||
| 100 | static int rt2800soc_read_eeprom(struct rt2x00_dev *rt2x00dev) | ||
| 101 | { | ||
| 102 | void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE); | ||
| 103 | |||
| 104 | if (!base_addr) | ||
| 105 | return -ENOMEM; | ||
| 106 | |||
| 107 | memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE); | ||
| 108 | |||
| 109 | iounmap(base_addr); | ||
| 110 | return 0; | ||
| 111 | } | ||
| 112 | |||
| 113 | /* Firmware functions */ | ||
| 114 | static char *rt2800soc_get_firmware_name(struct rt2x00_dev *rt2x00dev) | ||
| 115 | { | ||
| 116 | WARN_ON_ONCE(1); | ||
| 117 | return NULL; | ||
| 118 | } | ||
| 119 | |||
| 120 | static int rt2800soc_load_firmware(struct rt2x00_dev *rt2x00dev, | ||
| 121 | const u8 *data, const size_t len) | ||
| 122 | { | ||
| 123 | WARN_ON_ONCE(1); | ||
| 124 | return 0; | ||
| 125 | } | ||
| 126 | |||
| 127 | static int rt2800soc_check_firmware(struct rt2x00_dev *rt2x00dev, | ||
| 128 | const u8 *data, const size_t len) | ||
| 129 | { | ||
| 130 | WARN_ON_ONCE(1); | ||
| 131 | return 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | static int rt2800soc_write_firmware(struct rt2x00_dev *rt2x00dev, | ||
| 135 | const u8 *data, const size_t len) | ||
| 136 | { | ||
| 137 | WARN_ON_ONCE(1); | ||
| 138 | return 0; | ||
| 139 | } | ||
| 140 | |||
| 141 | static const struct ieee80211_ops rt2800soc_mac80211_ops = { | ||
| 142 | .tx = rt2x00mac_tx, | ||
| 143 | .start = rt2x00mac_start, | ||
| 144 | .stop = rt2x00mac_stop, | ||
| 145 | .add_interface = rt2x00mac_add_interface, | ||
| 146 | .remove_interface = rt2x00mac_remove_interface, | ||
| 147 | .config = rt2x00mac_config, | ||
| 148 | .configure_filter = rt2x00mac_configure_filter, | ||
| 149 | .set_key = rt2x00mac_set_key, | ||
| 150 | .sw_scan_start = rt2x00mac_sw_scan_start, | ||
| 151 | .sw_scan_complete = rt2x00mac_sw_scan_complete, | ||
| 152 | .get_stats = rt2x00mac_get_stats, | ||
| 153 | .get_tkip_seq = rt2800_get_tkip_seq, | ||
| 154 | .set_rts_threshold = rt2800_set_rts_threshold, | ||
| 155 | .sta_add = rt2x00mac_sta_add, | ||
| 156 | .sta_remove = rt2x00mac_sta_remove, | ||
| 157 | .bss_info_changed = rt2x00mac_bss_info_changed, | ||
| 158 | .conf_tx = rt2800_conf_tx, | ||
| 159 | .get_tsf = rt2800_get_tsf, | ||
| 160 | .rfkill_poll = rt2x00mac_rfkill_poll, | ||
| 161 | .ampdu_action = rt2800_ampdu_action, | ||
| 162 | .flush = rt2x00mac_flush, | ||
| 163 | .get_survey = rt2800_get_survey, | ||
| 164 | .get_ringparam = rt2x00mac_get_ringparam, | ||
| 165 | .tx_frames_pending = rt2x00mac_tx_frames_pending, | ||
| 166 | }; | ||
| 167 | |||
| 168 | static const struct rt2800_ops rt2800soc_rt2800_ops = { | ||
| 169 | .register_read = rt2x00mmio_register_read, | ||
| 170 | .register_read_lock = rt2x00mmio_register_read, /* same for SoCs */ | ||
| 171 | .register_write = rt2x00mmio_register_write, | ||
| 172 | .register_write_lock = rt2x00mmio_register_write, /* same for SoCs */ | ||
| 173 | .register_multiread = rt2x00mmio_register_multiread, | ||
| 174 | .register_multiwrite = rt2x00mmio_register_multiwrite, | ||
| 175 | .regbusy_read = rt2x00mmio_regbusy_read, | ||
| 176 | .read_eeprom = rt2800soc_read_eeprom, | ||
| 177 | .hwcrypt_disabled = rt2800soc_hwcrypt_disabled, | ||
| 178 | .drv_write_firmware = rt2800soc_write_firmware, | ||
| 179 | .drv_init_registers = rt2800mmio_init_registers, | ||
| 180 | .drv_get_txwi = rt2800mmio_get_txwi, | ||
| 181 | }; | ||
| 182 | |||
| 183 | static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = { | ||
| 184 | .irq_handler = rt2800mmio_interrupt, | ||
| 185 | .txstatus_tasklet = rt2800mmio_txstatus_tasklet, | ||
| 186 | .pretbtt_tasklet = rt2800mmio_pretbtt_tasklet, | ||
| 187 | .tbtt_tasklet = rt2800mmio_tbtt_tasklet, | ||
| 188 | .rxdone_tasklet = rt2800mmio_rxdone_tasklet, | ||
| 189 | .autowake_tasklet = rt2800mmio_autowake_tasklet, | ||
| 190 | .probe_hw = rt2800_probe_hw, | ||
| 191 | .get_firmware_name = rt2800soc_get_firmware_name, | ||
| 192 | .check_firmware = rt2800soc_check_firmware, | ||
| 193 | .load_firmware = rt2800soc_load_firmware, | ||
| 194 | .initialize = rt2x00mmio_initialize, | ||
| 195 | .uninitialize = rt2x00mmio_uninitialize, | ||
| 196 | .get_entry_state = rt2800mmio_get_entry_state, | ||
| 197 | .clear_entry = rt2800mmio_clear_entry, | ||
| 198 | .set_device_state = rt2800soc_set_device_state, | ||
| 199 | .rfkill_poll = rt2800_rfkill_poll, | ||
| 200 | .link_stats = rt2800_link_stats, | ||
| 201 | .reset_tuner = rt2800_reset_tuner, | ||
| 202 | .link_tuner = rt2800_link_tuner, | ||
| 203 | .gain_calibration = rt2800_gain_calibration, | ||
| 204 | .vco_calibration = rt2800_vco_calibration, | ||
| 205 | .start_queue = rt2800mmio_start_queue, | ||
| 206 | .kick_queue = rt2800mmio_kick_queue, | ||
| 207 | .stop_queue = rt2800mmio_stop_queue, | ||
| 208 | .flush_queue = rt2x00mmio_flush_queue, | ||
| 209 | .write_tx_desc = rt2800mmio_write_tx_desc, | ||
| 210 | .write_tx_data = rt2800_write_tx_data, | ||
| 211 | .write_beacon = rt2800_write_beacon, | ||
| 212 | .clear_beacon = rt2800_clear_beacon, | ||
| 213 | .fill_rxdone = rt2800mmio_fill_rxdone, | ||
| 214 | .config_shared_key = rt2800_config_shared_key, | ||
| 215 | .config_pairwise_key = rt2800_config_pairwise_key, | ||
| 216 | .config_filter = rt2800_config_filter, | ||
| 217 | .config_intf = rt2800_config_intf, | ||
| 218 | .config_erp = rt2800_config_erp, | ||
| 219 | .config_ant = rt2800_config_ant, | ||
| 220 | .config = rt2800_config, | ||
| 221 | .sta_add = rt2800_sta_add, | ||
| 222 | .sta_remove = rt2800_sta_remove, | ||
| 223 | }; | ||
| 224 | |||
| 225 | static const struct rt2x00_ops rt2800soc_ops = { | ||
| 226 | .name = KBUILD_MODNAME, | ||
| 227 | .drv_data_size = sizeof(struct rt2800_drv_data), | ||
| 228 | .max_ap_intf = 8, | ||
| 229 | .eeprom_size = EEPROM_SIZE, | ||
| 230 | .rf_size = RF_SIZE, | ||
| 231 | .tx_queues = NUM_TX_QUEUES, | ||
| 232 | .queue_init = rt2800mmio_queue_init, | ||
| 233 | .lib = &rt2800soc_rt2x00_ops, | ||
| 234 | .drv = &rt2800soc_rt2800_ops, | ||
| 235 | .hw = &rt2800soc_mac80211_ops, | ||
| 236 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | ||
| 237 | .debugfs = &rt2800_rt2x00debug, | ||
| 238 | #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ | ||
| 239 | }; | ||
| 240 | |||
| 241 | static int rt2800soc_probe(struct platform_device *pdev) | ||
| 242 | { | ||
| 243 | return rt2x00soc_probe(pdev, &rt2800soc_ops); | ||
| 244 | } | ||
| 245 | |||
| 246 | static struct platform_driver rt2800soc_driver = { | ||
| 247 | .driver = { | ||
| 248 | .name = "rt2800_wmac", | ||
| 249 | .owner = THIS_MODULE, | ||
| 250 | .mod_name = KBUILD_MODNAME, | ||
| 251 | }, | ||
| 252 | .probe = rt2800soc_probe, | ||
| 253 | .remove = rt2x00soc_remove, | ||
| 254 | .suspend = rt2x00soc_suspend, | ||
| 255 | .resume = rt2x00soc_resume, | ||
| 256 | }; | ||
| 257 | |||
| 258 | module_platform_driver(rt2800soc_driver); | ||
| 259 | |||
| 260 | MODULE_AUTHOR(DRV_PROJECT); | ||
| 261 | MODULE_VERSION(DRV_VERSION); | ||
| 262 | MODULE_DESCRIPTION("Ralink WiSoC Wireless LAN driver."); | ||
| 263 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 96961b9a395c..997df03a0c2e 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
| @@ -148,6 +148,8 @@ static bool rt2800usb_txstatus_timeout(struct rt2x00_dev *rt2x00dev) | |||
| 148 | return false; | 148 | return false; |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | #define TXSTATUS_READ_INTERVAL 1000000 | ||
| 152 | |||
| 151 | static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, | 153 | static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, |
| 152 | int urb_status, u32 tx_status) | 154 | int urb_status, u32 tx_status) |
| 153 | { | 155 | { |
| @@ -176,8 +178,9 @@ static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, | |||
| 176 | queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); | 178 | queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); |
| 177 | 179 | ||
| 178 | if (rt2800usb_txstatus_pending(rt2x00dev)) { | 180 | if (rt2800usb_txstatus_pending(rt2x00dev)) { |
| 179 | /* Read register after 250 us */ | 181 | /* Read register after 1 ms */ |
| 180 | hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 250000), | 182 | hrtimer_start(&rt2x00dev->txstatus_timer, |
| 183 | ktime_set(0, TXSTATUS_READ_INTERVAL), | ||
| 181 | HRTIMER_MODE_REL); | 184 | HRTIMER_MODE_REL); |
| 182 | return false; | 185 | return false; |
| 183 | } | 186 | } |
| @@ -202,8 +205,9 @@ static void rt2800usb_async_read_tx_status(struct rt2x00_dev *rt2x00dev) | |||
| 202 | if (test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags)) | 205 | if (test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags)) |
| 203 | return; | 206 | return; |
| 204 | 207 | ||
| 205 | /* Read TX_STA_FIFO register after 500 us */ | 208 | /* Read TX_STA_FIFO register after 2 ms */ |
| 206 | hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 500000), | 209 | hrtimer_start(&rt2x00dev->txstatus_timer, |
| 210 | ktime_set(0, 2*TXSTATUS_READ_INTERVAL), | ||
| 207 | HRTIMER_MODE_REL); | 211 | HRTIMER_MODE_REL); |
| 208 | } | 212 | } |
| 209 | 213 | ||
| @@ -1176,6 +1180,8 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
| 1176 | /* Linksys */ | 1180 | /* Linksys */ |
| 1177 | { USB_DEVICE(0x13b1, 0x002f) }, | 1181 | { USB_DEVICE(0x13b1, 0x002f) }, |
| 1178 | { USB_DEVICE(0x1737, 0x0079) }, | 1182 | { USB_DEVICE(0x1737, 0x0079) }, |
| 1183 | /* Logitec */ | ||
| 1184 | { USB_DEVICE(0x0789, 0x0170) }, | ||
| 1179 | /* Ralink */ | 1185 | /* Ralink */ |
| 1180 | { USB_DEVICE(0x148f, 0x3572) }, | 1186 | { USB_DEVICE(0x148f, 0x3572) }, |
| 1181 | /* Sitecom */ | 1187 | /* Sitecom */ |
| @@ -1199,6 +1205,8 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
| 1199 | { USB_DEVICE(0x050d, 0x1103) }, | 1205 | { USB_DEVICE(0x050d, 0x1103) }, |
| 1200 | /* Cameo */ | 1206 | /* Cameo */ |
| 1201 | { USB_DEVICE(0x148f, 0xf301) }, | 1207 | { USB_DEVICE(0x148f, 0xf301) }, |
| 1208 | /* D-Link */ | ||
| 1209 | { USB_DEVICE(0x2001, 0x3c1f) }, | ||
| 1202 | /* Edimax */ | 1210 | /* Edimax */ |
| 1203 | { USB_DEVICE(0x7392, 0x7733) }, | 1211 | { USB_DEVICE(0x7392, 0x7733) }, |
| 1204 | /* Hawking */ | 1212 | /* Hawking */ |
| @@ -1212,6 +1220,7 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
| 1212 | { USB_DEVICE(0x0789, 0x016b) }, | 1220 | { USB_DEVICE(0x0789, 0x016b) }, |
| 1213 | /* NETGEAR */ | 1221 | /* NETGEAR */ |
| 1214 | { USB_DEVICE(0x0846, 0x9012) }, | 1222 | { USB_DEVICE(0x0846, 0x9012) }, |
| 1223 | { USB_DEVICE(0x0846, 0x9013) }, | ||
| 1215 | { USB_DEVICE(0x0846, 0x9019) }, | 1224 | { USB_DEVICE(0x0846, 0x9019) }, |
| 1216 | /* Planex */ | 1225 | /* Planex */ |
| 1217 | { USB_DEVICE(0x2019, 0xed19) }, | 1226 | { USB_DEVICE(0x2019, 0xed19) }, |
| @@ -1220,6 +1229,7 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
| 1220 | /* Sitecom */ | 1229 | /* Sitecom */ |
| 1221 | { USB_DEVICE(0x0df6, 0x0067) }, | 1230 | { USB_DEVICE(0x0df6, 0x0067) }, |
| 1222 | { USB_DEVICE(0x0df6, 0x006a) }, | 1231 | { USB_DEVICE(0x0df6, 0x006a) }, |
| 1232 | { USB_DEVICE(0x0df6, 0x006e) }, | ||
| 1223 | /* ZyXEL */ | 1233 | /* ZyXEL */ |
| 1224 | { USB_DEVICE(0x0586, 0x3421) }, | 1234 | { USB_DEVICE(0x0586, 0x3421) }, |
| 1225 | #endif | 1235 | #endif |
| @@ -1236,6 +1246,9 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
| 1236 | { USB_DEVICE(0x2001, 0x3c1c) }, | 1246 | { USB_DEVICE(0x2001, 0x3c1c) }, |
| 1237 | { USB_DEVICE(0x2001, 0x3c1d) }, | 1247 | { USB_DEVICE(0x2001, 0x3c1d) }, |
| 1238 | { USB_DEVICE(0x2001, 0x3c1e) }, | 1248 | { USB_DEVICE(0x2001, 0x3c1e) }, |
| 1249 | { USB_DEVICE(0x2001, 0x3c20) }, | ||
| 1250 | { USB_DEVICE(0x2001, 0x3c22) }, | ||
| 1251 | { USB_DEVICE(0x2001, 0x3c23) }, | ||
| 1239 | /* LG innotek */ | 1252 | /* LG innotek */ |
| 1240 | { USB_DEVICE(0x043e, 0x7a22) }, | 1253 | { USB_DEVICE(0x043e, 0x7a22) }, |
| 1241 | { USB_DEVICE(0x043e, 0x7a42) }, | 1254 | { USB_DEVICE(0x043e, 0x7a42) }, |
| @@ -1258,12 +1271,17 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
| 1258 | { USB_DEVICE(0x043e, 0x7a32) }, | 1271 | { USB_DEVICE(0x043e, 0x7a32) }, |
| 1259 | /* AVM GmbH */ | 1272 | /* AVM GmbH */ |
| 1260 | { USB_DEVICE(0x057c, 0x8501) }, | 1273 | { USB_DEVICE(0x057c, 0x8501) }, |
| 1261 | /* D-Link DWA-160-B2 */ | 1274 | /* Buffalo */ |
| 1275 | { USB_DEVICE(0x0411, 0x0241) }, | ||
| 1276 | /* D-Link */ | ||
| 1262 | { USB_DEVICE(0x2001, 0x3c1a) }, | 1277 | { USB_DEVICE(0x2001, 0x3c1a) }, |
| 1278 | { USB_DEVICE(0x2001, 0x3c21) }, | ||
| 1263 | /* Proware */ | 1279 | /* Proware */ |
| 1264 | { USB_DEVICE(0x043e, 0x7a13) }, | 1280 | { USB_DEVICE(0x043e, 0x7a13) }, |
| 1265 | /* Ralink */ | 1281 | /* Ralink */ |
| 1266 | { USB_DEVICE(0x148f, 0x5572) }, | 1282 | { USB_DEVICE(0x148f, 0x5572) }, |
| 1283 | /* TRENDnet */ | ||
| 1284 | { USB_DEVICE(0x20f4, 0x724a) }, | ||
| 1267 | #endif | 1285 | #endif |
| 1268 | #ifdef CONFIG_RT2800USB_UNKNOWN | 1286 | #ifdef CONFIG_RT2800USB_UNKNOWN |
| 1269 | /* | 1287 | /* |
| @@ -1333,6 +1351,7 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
| 1333 | { USB_DEVICE(0x1d4d, 0x0010) }, | 1351 | { USB_DEVICE(0x1d4d, 0x0010) }, |
| 1334 | /* Planex */ | 1352 | /* Planex */ |
| 1335 | { USB_DEVICE(0x2019, 0xab24) }, | 1353 | { USB_DEVICE(0x2019, 0xab24) }, |
| 1354 | { USB_DEVICE(0x2019, 0xab29) }, | ||
| 1336 | /* Qcom */ | 1355 | /* Qcom */ |
| 1337 | { USB_DEVICE(0x18e8, 0x6259) }, | 1356 | { USB_DEVICE(0x18e8, 0x6259) }, |
| 1338 | /* RadioShack */ | 1357 | /* RadioShack */ |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index fe4c572db52c..e4ba2ce0f212 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #include <linux/input-polldev.h> | 39 | #include <linux/input-polldev.h> |
| 40 | #include <linux/kfifo.h> | 40 | #include <linux/kfifo.h> |
| 41 | #include <linux/hrtimer.h> | 41 | #include <linux/hrtimer.h> |
| 42 | #include <linux/average.h> | ||
| 42 | 43 | ||
| 43 | #include <net/mac80211.h> | 44 | #include <net/mac80211.h> |
| 44 | 45 | ||
| @@ -138,17 +139,6 @@ | |||
| 138 | #define SHORT_EIFS ( SIFS + SHORT_DIFS + \ | 139 | #define SHORT_EIFS ( SIFS + SHORT_DIFS + \ |
| 139 | GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) ) | 140 | GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) ) |
| 140 | 141 | ||
| 141 | /* | ||
| 142 | * Structure for average calculation | ||
| 143 | * The avg field contains the actual average value, | ||
| 144 | * but avg_weight is internally used during calculations | ||
| 145 | * to prevent rounding errors. | ||
| 146 | */ | ||
| 147 | struct avg_val { | ||
| 148 | int avg; | ||
| 149 | int avg_weight; | ||
| 150 | }; | ||
| 151 | |||
| 152 | enum rt2x00_chip_intf { | 142 | enum rt2x00_chip_intf { |
| 153 | RT2X00_CHIP_INTF_PCI, | 143 | RT2X00_CHIP_INTF_PCI, |
| 154 | RT2X00_CHIP_INTF_PCIE, | 144 | RT2X00_CHIP_INTF_PCIE, |
| @@ -297,7 +287,7 @@ struct link_ant { | |||
| 297 | * Similar to the avg_rssi in the link_qual structure | 287 | * Similar to the avg_rssi in the link_qual structure |
| 298 | * this value is updated by using the walking average. | 288 | * this value is updated by using the walking average. |
| 299 | */ | 289 | */ |
| 300 | struct avg_val rssi_ant; | 290 | struct ewma rssi_ant; |
| 301 | }; | 291 | }; |
| 302 | 292 | ||
| 303 | /* | 293 | /* |
| @@ -326,7 +316,7 @@ struct link { | |||
| 326 | /* | 316 | /* |
| 327 | * Currently active average RSSI value | 317 | * Currently active average RSSI value |
| 328 | */ | 318 | */ |
| 329 | struct avg_val avg_rssi; | 319 | struct ewma avg_rssi; |
| 330 | 320 | ||
| 331 | /* | 321 | /* |
| 332 | * Work structure for scheduling periodic link tuning. | 322 | * Work structure for scheduling periodic link tuning. |
| @@ -1179,6 +1169,93 @@ static inline bool rt2x00_is_soc(struct rt2x00_dev *rt2x00dev) | |||
| 1179 | return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC); | 1169 | return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC); |
| 1180 | } | 1170 | } |
| 1181 | 1171 | ||
| 1172 | /* Helpers for capability flags */ | ||
| 1173 | |||
| 1174 | static inline bool | ||
| 1175 | rt2x00_has_cap_flag(struct rt2x00_dev *rt2x00dev, | ||
| 1176 | enum rt2x00_capability_flags cap_flag) | ||
| 1177 | { | ||
| 1178 | return test_bit(cap_flag, &rt2x00dev->cap_flags); | ||
| 1179 | } | ||
| 1180 | |||
| 1181 | static inline bool | ||
| 1182 | rt2x00_has_cap_hw_crypto(struct rt2x00_dev *rt2x00dev) | ||
| 1183 | { | ||
| 1184 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_HW_CRYPTO); | ||
| 1185 | } | ||
| 1186 | |||
| 1187 | static inline bool | ||
| 1188 | rt2x00_has_cap_power_limit(struct rt2x00_dev *rt2x00dev) | ||
| 1189 | { | ||
| 1190 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_POWER_LIMIT); | ||
| 1191 | } | ||
| 1192 | |||
| 1193 | static inline bool | ||
| 1194 | rt2x00_has_cap_control_filters(struct rt2x00_dev *rt2x00dev) | ||
| 1195 | { | ||
| 1196 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_CONTROL_FILTERS); | ||
| 1197 | } | ||
| 1198 | |||
| 1199 | static inline bool | ||
| 1200 | rt2x00_has_cap_control_filter_pspoll(struct rt2x00_dev *rt2x00dev) | ||
| 1201 | { | ||
| 1202 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_CONTROL_FILTER_PSPOLL); | ||
| 1203 | } | ||
| 1204 | |||
| 1205 | static inline bool | ||
| 1206 | rt2x00_has_cap_pre_tbtt_interrupt(struct rt2x00_dev *rt2x00dev) | ||
| 1207 | { | ||
| 1208 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_PRE_TBTT_INTERRUPT); | ||
| 1209 | } | ||
| 1210 | |||
| 1211 | static inline bool | ||
| 1212 | rt2x00_has_cap_link_tuning(struct rt2x00_dev *rt2x00dev) | ||
| 1213 | { | ||
| 1214 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_LINK_TUNING); | ||
| 1215 | } | ||
| 1216 | |||
| 1217 | static inline bool | ||
| 1218 | rt2x00_has_cap_frame_type(struct rt2x00_dev *rt2x00dev) | ||
| 1219 | { | ||
| 1220 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_FRAME_TYPE); | ||
| 1221 | } | ||
| 1222 | |||
| 1223 | static inline bool | ||
| 1224 | rt2x00_has_cap_rf_sequence(struct rt2x00_dev *rt2x00dev) | ||
| 1225 | { | ||
| 1226 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_RF_SEQUENCE); | ||
| 1227 | } | ||
| 1228 | |||
| 1229 | static inline bool | ||
| 1230 | rt2x00_has_cap_external_lna_a(struct rt2x00_dev *rt2x00dev) | ||
| 1231 | { | ||
| 1232 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_EXTERNAL_LNA_A); | ||
| 1233 | } | ||
| 1234 | |||
| 1235 | static inline bool | ||
| 1236 | rt2x00_has_cap_external_lna_bg(struct rt2x00_dev *rt2x00dev) | ||
| 1237 | { | ||
| 1238 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_EXTERNAL_LNA_BG); | ||
| 1239 | } | ||
| 1240 | |||
| 1241 | static inline bool | ||
| 1242 | rt2x00_has_cap_double_antenna(struct rt2x00_dev *rt2x00dev) | ||
| 1243 | { | ||
| 1244 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_DOUBLE_ANTENNA); | ||
| 1245 | } | ||
| 1246 | |||
| 1247 | static inline bool | ||
| 1248 | rt2x00_has_cap_bt_coexist(struct rt2x00_dev *rt2x00dev) | ||
| 1249 | { | ||
| 1250 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_BT_COEXIST); | ||
| 1251 | } | ||
| 1252 | |||
| 1253 | static inline bool | ||
| 1254 | rt2x00_has_cap_vco_recalibration(struct rt2x00_dev *rt2x00dev) | ||
| 1255 | { | ||
| 1256 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_VCO_RECALIBRATION); | ||
| 1257 | } | ||
| 1258 | |||
| 1182 | /** | 1259 | /** |
| 1183 | * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes. | 1260 | * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes. |
| 1184 | * @entry: Pointer to &struct queue_entry | 1261 | * @entry: Pointer to &struct queue_entry |
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c index 1ca4c7ffc189..3db0d99d9da7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c | |||
| @@ -52,7 +52,7 @@ void rt2x00crypto_create_tx_descriptor(struct rt2x00_dev *rt2x00dev, | |||
| 52 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 52 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
| 53 | struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; | 53 | struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; |
| 54 | 54 | ||
| 55 | if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !hw_key) | 55 | if (!rt2x00_has_cap_hw_crypto(rt2x00dev) || !hw_key) |
| 56 | return; | 56 | return; |
| 57 | 57 | ||
| 58 | __set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags); | 58 | __set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags); |
| @@ -80,7 +80,7 @@ unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev, | |||
| 80 | struct ieee80211_key_conf *key = tx_info->control.hw_key; | 80 | struct ieee80211_key_conf *key = tx_info->control.hw_key; |
| 81 | unsigned int overhead = 0; | 81 | unsigned int overhead = 0; |
| 82 | 82 | ||
| 83 | if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !key) | 83 | if (!rt2x00_has_cap_hw_crypto(rt2x00dev) || !key) |
| 84 | return overhead; | 84 | return overhead; |
| 85 | 85 | ||
| 86 | /* | 86 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index fe7a7f63a9ed..7f7baae5ae02 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c | |||
| @@ -750,7 +750,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) | |||
| 750 | intf, &rt2x00debug_fop_queue_stats); | 750 | intf, &rt2x00debug_fop_queue_stats); |
| 751 | 751 | ||
| 752 | #ifdef CONFIG_RT2X00_LIB_CRYPTO | 752 | #ifdef CONFIG_RT2X00_LIB_CRYPTO |
| 753 | if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) | 753 | if (rt2x00_has_cap_hw_crypto(rt2x00dev)) |
| 754 | intf->crypto_stats_entry = | 754 | intf->crypto_stats_entry = |
| 755 | debugfs_create_file("crypto", S_IRUGO, intf->queue_folder, | 755 | debugfs_create_file("crypto", S_IRUGO, intf->queue_folder, |
| 756 | intf, &rt2x00debug_fop_crypto_stats); | 756 | intf, &rt2x00debug_fop_crypto_stats); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 712eea9d398f..080b1fcae5fa 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
| @@ -88,7 +88,7 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
| 88 | rt2x00queue_start_queues(rt2x00dev); | 88 | rt2x00queue_start_queues(rt2x00dev); |
| 89 | rt2x00link_start_tuner(rt2x00dev); | 89 | rt2x00link_start_tuner(rt2x00dev); |
| 90 | rt2x00link_start_agc(rt2x00dev); | 90 | rt2x00link_start_agc(rt2x00dev); |
| 91 | if (test_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags)) | 91 | if (rt2x00_has_cap_vco_recalibration(rt2x00dev)) |
| 92 | rt2x00link_start_vcocal(rt2x00dev); | 92 | rt2x00link_start_vcocal(rt2x00dev); |
| 93 | 93 | ||
| 94 | /* | 94 | /* |
| @@ -113,7 +113,7 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) | |||
| 113 | * Stop all queues | 113 | * Stop all queues |
| 114 | */ | 114 | */ |
| 115 | rt2x00link_stop_agc(rt2x00dev); | 115 | rt2x00link_stop_agc(rt2x00dev); |
| 116 | if (test_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags)) | 116 | if (rt2x00_has_cap_vco_recalibration(rt2x00dev)) |
| 117 | rt2x00link_stop_vcocal(rt2x00dev); | 117 | rt2x00link_stop_vcocal(rt2x00dev); |
| 118 | rt2x00link_stop_tuner(rt2x00dev); | 118 | rt2x00link_stop_tuner(rt2x00dev); |
| 119 | rt2x00queue_stop_queues(rt2x00dev); | 119 | rt2x00queue_stop_queues(rt2x00dev); |
| @@ -234,7 +234,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) | |||
| 234 | * here as they will fetch the next beacon directly prior to | 234 | * here as they will fetch the next beacon directly prior to |
| 235 | * transmission. | 235 | * transmission. |
| 236 | */ | 236 | */ |
| 237 | if (test_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags)) | 237 | if (rt2x00_has_cap_pre_tbtt_interrupt(rt2x00dev)) |
| 238 | return; | 238 | return; |
| 239 | 239 | ||
| 240 | /* fetch next beacon */ | 240 | /* fetch next beacon */ |
| @@ -358,7 +358,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
| 358 | * mac80211 will expect the same data to be present it the | 358 | * mac80211 will expect the same data to be present it the |
| 359 | * frame as it was passed to us. | 359 | * frame as it was passed to us. |
| 360 | */ | 360 | */ |
| 361 | if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) | 361 | if (rt2x00_has_cap_hw_crypto(rt2x00dev)) |
| 362 | rt2x00crypto_tx_insert_iv(entry->skb, header_length); | 362 | rt2x00crypto_tx_insert_iv(entry->skb, header_length); |
| 363 | 363 | ||
| 364 | /* | 364 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index 8368aab86f28..c2b3b6629188 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c | |||
| @@ -35,50 +35,28 @@ | |||
| 35 | */ | 35 | */ |
| 36 | #define DEFAULT_RSSI -128 | 36 | #define DEFAULT_RSSI -128 |
| 37 | 37 | ||
| 38 | /* | 38 | /* Constants for EWMA calculations. */ |
| 39 | * Helper struct and macro to work with moving/walking averages. | 39 | #define RT2X00_EWMA_FACTOR 1024 |
| 40 | * When adding a value to the average value the following calculation | 40 | #define RT2X00_EWMA_WEIGHT 8 |
| 41 | * is needed: | 41 | |
| 42 | * | 42 | static inline int rt2x00link_get_avg_rssi(struct ewma *ewma) |
| 43 | * avg_rssi = ((avg_rssi * 7) + rssi) / 8; | 43 | { |
| 44 | * | 44 | unsigned long avg; |
| 45 | * The advantage of this approach is that we only need 1 variable | 45 | |
| 46 | * to store the average in (No need for a count and a total). | 46 | avg = ewma_read(ewma); |
| 47 | * But more importantly, normal average values will over time | 47 | if (avg) |
| 48 | * move less and less towards newly added values this results | 48 | return -avg; |
| 49 | * that with link tuning, the device can have a very good RSSI | 49 | |
| 50 | * for a few minutes but when the device is moved away from the AP | 50 | return DEFAULT_RSSI; |
| 51 | * the average will not decrease fast enough to compensate. | 51 | } |
| 52 | * The walking average compensates this and will move towards | ||
| 53 | * the new values correctly allowing a effective link tuning, | ||
| 54 | * the speed of the average moving towards other values depends | ||
| 55 | * on the value for the number of samples. The higher the number | ||
| 56 | * of samples, the slower the average will move. | ||
| 57 | * We use two variables to keep track of the average value to | ||
| 58 | * compensate for the rounding errors. This can be a significant | ||
| 59 | * error (>5dBm) if the factor is too low. | ||
| 60 | */ | ||
| 61 | #define AVG_SAMPLES 8 | ||
| 62 | #define AVG_FACTOR 1000 | ||
| 63 | #define MOVING_AVERAGE(__avg, __val) \ | ||
| 64 | ({ \ | ||
| 65 | struct avg_val __new; \ | ||
| 66 | __new.avg_weight = \ | ||
| 67 | (__avg).avg_weight ? \ | ||
| 68 | ((((__avg).avg_weight * ((AVG_SAMPLES) - 1)) + \ | ||
| 69 | ((__val) * (AVG_FACTOR))) / \ | ||
| 70 | (AVG_SAMPLES)) : \ | ||
| 71 | ((__val) * (AVG_FACTOR)); \ | ||
| 72 | __new.avg = __new.avg_weight / (AVG_FACTOR); \ | ||
| 73 | __new; \ | ||
| 74 | }) | ||
| 75 | 52 | ||
| 76 | static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev) | 53 | static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev) |
| 77 | { | 54 | { |
| 78 | struct link_ant *ant = &rt2x00dev->link.ant; | 55 | struct link_ant *ant = &rt2x00dev->link.ant; |
| 79 | 56 | ||
| 80 | if (ant->rssi_ant.avg && rt2x00dev->link.qual.rx_success) | 57 | if (rt2x00dev->link.qual.rx_success) |
| 81 | return ant->rssi_ant.avg; | 58 | return rt2x00link_get_avg_rssi(&ant->rssi_ant); |
| 59 | |||
| 82 | return DEFAULT_RSSI; | 60 | return DEFAULT_RSSI; |
| 83 | } | 61 | } |
| 84 | 62 | ||
| @@ -100,8 +78,8 @@ static void rt2x00link_antenna_update_rssi_history(struct rt2x00_dev *rt2x00dev, | |||
| 100 | 78 | ||
| 101 | static void rt2x00link_antenna_reset(struct rt2x00_dev *rt2x00dev) | 79 | static void rt2x00link_antenna_reset(struct rt2x00_dev *rt2x00dev) |
| 102 | { | 80 | { |
| 103 | rt2x00dev->link.ant.rssi_ant.avg = 0; | 81 | ewma_init(&rt2x00dev->link.ant.rssi_ant, RT2X00_EWMA_FACTOR, |
| 104 | rt2x00dev->link.ant.rssi_ant.avg_weight = 0; | 82 | RT2X00_EWMA_WEIGHT); |
| 105 | } | 83 | } |
| 106 | 84 | ||
| 107 | static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev) | 85 | static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev) |
| @@ -249,12 +227,12 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev, | |||
| 249 | /* | 227 | /* |
| 250 | * Update global RSSI | 228 | * Update global RSSI |
| 251 | */ | 229 | */ |
| 252 | link->avg_rssi = MOVING_AVERAGE(link->avg_rssi, rxdesc->rssi); | 230 | ewma_add(&link->avg_rssi, -rxdesc->rssi); |
| 253 | 231 | ||
| 254 | /* | 232 | /* |
| 255 | * Update antenna RSSI | 233 | * Update antenna RSSI |
| 256 | */ | 234 | */ |
| 257 | ant->rssi_ant = MOVING_AVERAGE(ant->rssi_ant, rxdesc->rssi); | 235 | ewma_add(&ant->rssi_ant, -rxdesc->rssi); |
| 258 | } | 236 | } |
| 259 | 237 | ||
| 260 | void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev) | 238 | void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev) |
| @@ -309,6 +287,8 @@ void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna) | |||
| 309 | */ | 287 | */ |
| 310 | rt2x00dev->link.count = 0; | 288 | rt2x00dev->link.count = 0; |
| 311 | memset(qual, 0, sizeof(*qual)); | 289 | memset(qual, 0, sizeof(*qual)); |
| 290 | ewma_init(&rt2x00dev->link.avg_rssi, RT2X00_EWMA_FACTOR, | ||
| 291 | RT2X00_EWMA_WEIGHT); | ||
| 312 | 292 | ||
| 313 | /* | 293 | /* |
| 314 | * Restore the VGC level as stored in the registers, | 294 | * Restore the VGC level as stored in the registers, |
| @@ -363,17 +343,17 @@ static void rt2x00link_tuner(struct work_struct *work) | |||
| 363 | * collect the RSSI data we could use this. Otherwise we | 343 | * collect the RSSI data we could use this. Otherwise we |
| 364 | * must fallback to the default RSSI value. | 344 | * must fallback to the default RSSI value. |
| 365 | */ | 345 | */ |
| 366 | if (!link->avg_rssi.avg || !qual->rx_success) | 346 | if (!qual->rx_success) |
| 367 | qual->rssi = DEFAULT_RSSI; | 347 | qual->rssi = DEFAULT_RSSI; |
| 368 | else | 348 | else |
| 369 | qual->rssi = link->avg_rssi.avg; | 349 | qual->rssi = rt2x00link_get_avg_rssi(&link->avg_rssi); |
| 370 | 350 | ||
| 371 | /* | 351 | /* |
| 372 | * Check if link tuning is supported by the hardware, some hardware | 352 | * Check if link tuning is supported by the hardware, some hardware |
| 373 | * do not support link tuning at all, while other devices can disable | 353 | * do not support link tuning at all, while other devices can disable |
| 374 | * the feature from the EEPROM. | 354 | * the feature from the EEPROM. |
| 375 | */ | 355 | */ |
| 376 | if (test_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags)) | 356 | if (rt2x00_has_cap_link_tuning(rt2x00dev)) |
| 377 | rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count); | 357 | rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count); |
| 378 | 358 | ||
| 379 | /* | 359 | /* |
| @@ -513,7 +493,7 @@ static void rt2x00link_vcocal(struct work_struct *work) | |||
| 513 | void rt2x00link_register(struct rt2x00_dev *rt2x00dev) | 493 | void rt2x00link_register(struct rt2x00_dev *rt2x00dev) |
| 514 | { | 494 | { |
| 515 | INIT_DELAYED_WORK(&rt2x00dev->link.agc_work, rt2x00link_agc); | 495 | INIT_DELAYED_WORK(&rt2x00dev->link.agc_work, rt2x00link_agc); |
| 516 | if (test_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags)) | 496 | if (rt2x00_has_cap_vco_recalibration(rt2x00dev)) |
| 517 | INIT_DELAYED_WORK(&rt2x00dev->link.vco_work, rt2x00link_vcocal); | 497 | INIT_DELAYED_WORK(&rt2x00dev->link.vco_work, rt2x00link_vcocal); |
| 518 | INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog); | 498 | INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog); |
| 519 | INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner); | 499 | INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index f883802f3505..7c157857f5ce 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
| @@ -382,11 +382,11 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw, | |||
| 382 | * of different types, but has no a separate filter for PS Poll frames, | 382 | * of different types, but has no a separate filter for PS Poll frames, |
| 383 | * FIF_CONTROL flag implies FIF_PSPOLL. | 383 | * FIF_CONTROL flag implies FIF_PSPOLL. |
| 384 | */ | 384 | */ |
| 385 | if (!test_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags)) { | 385 | if (!rt2x00_has_cap_control_filters(rt2x00dev)) { |
| 386 | if (*total_flags & FIF_CONTROL || *total_flags & FIF_PSPOLL) | 386 | if (*total_flags & FIF_CONTROL || *total_flags & FIF_PSPOLL) |
| 387 | *total_flags |= FIF_CONTROL | FIF_PSPOLL; | 387 | *total_flags |= FIF_CONTROL | FIF_PSPOLL; |
| 388 | } | 388 | } |
| 389 | if (!test_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags)) { | 389 | if (!rt2x00_has_cap_control_filter_pspoll(rt2x00dev)) { |
| 390 | if (*total_flags & FIF_CONTROL) | 390 | if (*total_flags & FIF_CONTROL) |
| 391 | *total_flags |= FIF_PSPOLL; | 391 | *total_flags |= FIF_PSPOLL; |
| 392 | } | 392 | } |
| @@ -469,7 +469,7 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
| 469 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) | 469 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) |
| 470 | return 0; | 470 | return 0; |
| 471 | 471 | ||
| 472 | if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) | 472 | if (!rt2x00_has_cap_hw_crypto(rt2x00dev)) |
| 473 | return -EOPNOTSUPP; | 473 | return -EOPNOTSUPP; |
| 474 | 474 | ||
| 475 | /* | 475 | /* |
| @@ -754,6 +754,9 @@ void rt2x00mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop) | |||
| 754 | struct rt2x00_dev *rt2x00dev = hw->priv; | 754 | struct rt2x00_dev *rt2x00dev = hw->priv; |
| 755 | struct data_queue *queue; | 755 | struct data_queue *queue; |
| 756 | 756 | ||
| 757 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) | ||
| 758 | return; | ||
| 759 | |||
| 757 | tx_queue_for_each(rt2x00dev, queue) | 760 | tx_queue_for_each(rt2x00dev, queue) |
| 758 | rt2x00queue_flush_queue(queue, drop); | 761 | rt2x00queue_flush_queue(queue, drop); |
| 759 | } | 762 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index dc49e525ae5e..25da20e7e1f3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c | |||
| @@ -119,7 +119,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops) | |||
| 119 | rt2x00dev->ops = ops; | 119 | rt2x00dev->ops = ops; |
| 120 | rt2x00dev->hw = hw; | 120 | rt2x00dev->hw = hw; |
| 121 | rt2x00dev->irq = pci_dev->irq; | 121 | rt2x00dev->irq = pci_dev->irq; |
| 122 | rt2x00dev->name = pci_name(pci_dev); | 122 | rt2x00dev->name = ops->name; |
| 123 | 123 | ||
| 124 | if (pci_is_pcie(pci_dev)) | 124 | if (pci_is_pcie(pci_dev)) |
| 125 | rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE); | 125 | rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 6c8a33b6ee22..50590b1420a5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
| @@ -61,7 +61,7 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry, gfp_t gfp) | |||
| 61 | * at least 8 bytes bytes available in headroom for IV/EIV | 61 | * at least 8 bytes bytes available in headroom for IV/EIV |
| 62 | * and 8 bytes for ICV data as tailroon. | 62 | * and 8 bytes for ICV data as tailroon. |
| 63 | */ | 63 | */ |
| 64 | if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) { | 64 | if (rt2x00_has_cap_hw_crypto(rt2x00dev)) { |
| 65 | head_size += 8; | 65 | head_size += 8; |
| 66 | tail_size += 8; | 66 | tail_size += 8; |
| 67 | } | 67 | } |
| @@ -1033,38 +1033,21 @@ EXPORT_SYMBOL_GPL(rt2x00queue_stop_queue); | |||
| 1033 | 1033 | ||
| 1034 | void rt2x00queue_flush_queue(struct data_queue *queue, bool drop) | 1034 | void rt2x00queue_flush_queue(struct data_queue *queue, bool drop) |
| 1035 | { | 1035 | { |
| 1036 | bool started; | ||
| 1037 | bool tx_queue = | 1036 | bool tx_queue = |
| 1038 | (queue->qid == QID_AC_VO) || | 1037 | (queue->qid == QID_AC_VO) || |
| 1039 | (queue->qid == QID_AC_VI) || | 1038 | (queue->qid == QID_AC_VI) || |
| 1040 | (queue->qid == QID_AC_BE) || | 1039 | (queue->qid == QID_AC_BE) || |
| 1041 | (queue->qid == QID_AC_BK); | 1040 | (queue->qid == QID_AC_BK); |
| 1042 | 1041 | ||
| 1043 | mutex_lock(&queue->status_lock); | ||
| 1044 | 1042 | ||
| 1045 | /* | 1043 | /* |
| 1046 | * If the queue has been started, we must stop it temporarily | 1044 | * If we are not supposed to drop any pending |
| 1047 | * to prevent any new frames to be queued on the device. If | 1045 | * frames, this means we must force a start (=kick) |
| 1048 | * we are not dropping the pending frames, the queue must | 1046 | * to the queue to make sure the hardware will |
| 1049 | * only be stopped in the software and not the hardware, | 1047 | * start transmitting. |
| 1050 | * otherwise the queue will never become empty on its own. | ||
| 1051 | */ | 1048 | */ |
| 1052 | started = test_bit(QUEUE_STARTED, &queue->flags); | 1049 | if (!drop && tx_queue) |
| 1053 | if (started) { | 1050 | queue->rt2x00dev->ops->lib->kick_queue(queue); |
| 1054 | /* | ||
| 1055 | * Pause the queue | ||
| 1056 | */ | ||
| 1057 | rt2x00queue_pause_queue(queue); | ||
| 1058 | |||
| 1059 | /* | ||
| 1060 | * If we are not supposed to drop any pending | ||
| 1061 | * frames, this means we must force a start (=kick) | ||
| 1062 | * to the queue to make sure the hardware will | ||
| 1063 | * start transmitting. | ||
| 1064 | */ | ||
| 1065 | if (!drop && tx_queue) | ||
| 1066 | queue->rt2x00dev->ops->lib->kick_queue(queue); | ||
| 1067 | } | ||
| 1068 | 1051 | ||
| 1069 | /* | 1052 | /* |
| 1070 | * Check if driver supports flushing, if that is the case we can | 1053 | * Check if driver supports flushing, if that is the case we can |
| @@ -1080,14 +1063,6 @@ void rt2x00queue_flush_queue(struct data_queue *queue, bool drop) | |||
| 1080 | if (unlikely(!rt2x00queue_empty(queue))) | 1063 | if (unlikely(!rt2x00queue_empty(queue))) |
| 1081 | rt2x00_warn(queue->rt2x00dev, "Queue %d failed to flush\n", | 1064 | rt2x00_warn(queue->rt2x00dev, "Queue %d failed to flush\n", |
| 1082 | queue->qid); | 1065 | queue->qid); |
| 1083 | |||
| 1084 | /* | ||
| 1085 | * Restore the queue to the previous status | ||
| 1086 | */ | ||
| 1087 | if (started) | ||
| 1088 | rt2x00queue_unpause_queue(queue); | ||
| 1089 | |||
| 1090 | mutex_unlock(&queue->status_lock); | ||
| 1091 | } | 1066 | } |
| 1092 | EXPORT_SYMBOL_GPL(rt2x00queue_flush_queue); | 1067 | EXPORT_SYMBOL_GPL(rt2x00queue_flush_queue); |
| 1093 | 1068 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 88289873c0cf..4e121627925d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
| @@ -523,7 +523,9 @@ static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue) | |||
| 523 | rt2x00_warn(queue->rt2x00dev, "TX queue %d DMA timed out, invoke forced forced reset\n", | 523 | rt2x00_warn(queue->rt2x00dev, "TX queue %d DMA timed out, invoke forced forced reset\n", |
| 524 | queue->qid); | 524 | queue->qid); |
| 525 | 525 | ||
| 526 | rt2x00queue_stop_queue(queue); | ||
| 526 | rt2x00queue_flush_queue(queue, true); | 527 | rt2x00queue_flush_queue(queue, true); |
| 528 | rt2x00queue_start_queue(queue); | ||
| 527 | } | 529 | } |
| 528 | 530 | ||
| 529 | static int rt2x00usb_dma_timeout(struct data_queue *queue) | 531 | static int rt2x00usb_dma_timeout(struct data_queue *queue) |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 54d3ddfc9888..a5b69cb49012 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
| @@ -685,7 +685,7 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev, | |||
| 685 | 685 | ||
| 686 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529)); | 686 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529)); |
| 687 | rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, | 687 | rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, |
| 688 | !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags)); | 688 | !rt2x00_has_cap_frame_type(rt2x00dev)); |
| 689 | 689 | ||
| 690 | /* | 690 | /* |
| 691 | * Configure the RX antenna. | 691 | * Configure the RX antenna. |
| @@ -813,10 +813,10 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev, | |||
| 813 | 813 | ||
| 814 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { | 814 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { |
| 815 | sel = antenna_sel_a; | 815 | sel = antenna_sel_a; |
| 816 | lna = test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags); | 816 | lna = rt2x00_has_cap_external_lna_a(rt2x00dev); |
| 817 | } else { | 817 | } else { |
| 818 | sel = antenna_sel_bg; | 818 | sel = antenna_sel_bg; |
| 819 | lna = test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags); | 819 | lna = rt2x00_has_cap_external_lna_bg(rt2x00dev); |
| 820 | } | 820 | } |
| 821 | 821 | ||
| 822 | for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) | 822 | for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) |
| @@ -836,7 +836,7 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev, | |||
| 836 | else if (rt2x00_rf(rt2x00dev, RF2527)) | 836 | else if (rt2x00_rf(rt2x00dev, RF2527)) |
| 837 | rt61pci_config_antenna_2x(rt2x00dev, ant); | 837 | rt61pci_config_antenna_2x(rt2x00dev, ant); |
| 838 | else if (rt2x00_rf(rt2x00dev, RF2529)) { | 838 | else if (rt2x00_rf(rt2x00dev, RF2529)) { |
| 839 | if (test_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags)) | 839 | if (rt2x00_has_cap_double_antenna(rt2x00dev)) |
| 840 | rt61pci_config_antenna_2x(rt2x00dev, ant); | 840 | rt61pci_config_antenna_2x(rt2x00dev, ant); |
| 841 | else | 841 | else |
| 842 | rt61pci_config_antenna_2529(rt2x00dev, ant); | 842 | rt61pci_config_antenna_2529(rt2x00dev, ant); |
| @@ -850,13 +850,13 @@ static void rt61pci_config_lna_gain(struct rt2x00_dev *rt2x00dev, | |||
| 850 | short lna_gain = 0; | 850 | short lna_gain = 0; |
| 851 | 851 | ||
| 852 | if (libconf->conf->chandef.chan->band == IEEE80211_BAND_2GHZ) { | 852 | if (libconf->conf->chandef.chan->band == IEEE80211_BAND_2GHZ) { |
| 853 | if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) | 853 | if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) |
| 854 | lna_gain += 14; | 854 | lna_gain += 14; |
| 855 | 855 | ||
| 856 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom); | 856 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom); |
| 857 | lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1); | 857 | lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1); |
| 858 | } else { | 858 | } else { |
| 859 | if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) | 859 | if (rt2x00_has_cap_external_lna_a(rt2x00dev)) |
| 860 | lna_gain += 14; | 860 | lna_gain += 14; |
| 861 | 861 | ||
| 862 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom); | 862 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom); |
| @@ -1054,14 +1054,14 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev, | |||
| 1054 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { | 1054 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { |
| 1055 | low_bound = 0x28; | 1055 | low_bound = 0x28; |
| 1056 | up_bound = 0x48; | 1056 | up_bound = 0x48; |
| 1057 | if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) { | 1057 | if (rt2x00_has_cap_external_lna_a(rt2x00dev)) { |
| 1058 | low_bound += 0x10; | 1058 | low_bound += 0x10; |
| 1059 | up_bound += 0x10; | 1059 | up_bound += 0x10; |
| 1060 | } | 1060 | } |
| 1061 | } else { | 1061 | } else { |
| 1062 | low_bound = 0x20; | 1062 | low_bound = 0x20; |
| 1063 | up_bound = 0x40; | 1063 | up_bound = 0x40; |
| 1064 | if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) { | 1064 | if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { |
| 1065 | low_bound += 0x10; | 1065 | low_bound += 0x10; |
| 1066 | up_bound += 0x10; | 1066 | up_bound += 0x10; |
| 1067 | } | 1067 | } |
| @@ -2578,7 +2578,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
| 2578 | * eeprom word. | 2578 | * eeprom word. |
| 2579 | */ | 2579 | */ |
| 2580 | if (rt2x00_rf(rt2x00dev, RF2529) && | 2580 | if (rt2x00_rf(rt2x00dev, RF2529) && |
| 2581 | !test_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags)) { | 2581 | !rt2x00_has_cap_double_antenna(rt2x00dev)) { |
| 2582 | rt2x00dev->default_ant.rx = | 2582 | rt2x00dev->default_ant.rx = |
| 2583 | ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED); | 2583 | ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED); |
| 2584 | rt2x00dev->default_ant.tx = | 2584 | rt2x00dev->default_ant.tx = |
| @@ -2793,7 +2793,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
| 2793 | spec->supported_bands = SUPPORT_BAND_2GHZ; | 2793 | spec->supported_bands = SUPPORT_BAND_2GHZ; |
| 2794 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; | 2794 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; |
| 2795 | 2795 | ||
| 2796 | if (!test_bit(CAPABILITY_RF_SEQUENCE, &rt2x00dev->cap_flags)) { | 2796 | if (!rt2x00_has_cap_rf_sequence(rt2x00dev)) { |
| 2797 | spec->num_channels = 14; | 2797 | spec->num_channels = 14; |
| 2798 | spec->channels = rf_vals_noseq; | 2798 | spec->channels = rf_vals_noseq; |
| 2799 | } else { | 2799 | } else { |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 1d3880e09a13..1baf9c896dcd 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
| @@ -595,8 +595,8 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev, | |||
| 595 | switch (ant->rx) { | 595 | switch (ant->rx) { |
| 596 | case ANTENNA_HW_DIVERSITY: | 596 | case ANTENNA_HW_DIVERSITY: |
| 597 | rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2); | 597 | rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2); |
| 598 | temp = !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags) | 598 | temp = !rt2x00_has_cap_frame_type(rt2x00dev) && |
| 599 | && (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ); | 599 | (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ); |
| 600 | rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp); | 600 | rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp); |
| 601 | break; | 601 | break; |
| 602 | case ANTENNA_A: | 602 | case ANTENNA_A: |
| @@ -636,7 +636,7 @@ static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev, | |||
| 636 | 636 | ||
| 637 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0); | 637 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0); |
| 638 | rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, | 638 | rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, |
| 639 | !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags)); | 639 | !rt2x00_has_cap_frame_type(rt2x00dev)); |
| 640 | 640 | ||
| 641 | /* | 641 | /* |
| 642 | * Configure the RX antenna. | 642 | * Configure the RX antenna. |
| @@ -709,10 +709,10 @@ static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev, | |||
| 709 | 709 | ||
| 710 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { | 710 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { |
| 711 | sel = antenna_sel_a; | 711 | sel = antenna_sel_a; |
| 712 | lna = test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags); | 712 | lna = rt2x00_has_cap_external_lna_a(rt2x00dev); |
| 713 | } else { | 713 | } else { |
| 714 | sel = antenna_sel_bg; | 714 | sel = antenna_sel_bg; |
| 715 | lna = test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags); | 715 | lna = rt2x00_has_cap_external_lna_bg(rt2x00dev); |
| 716 | } | 716 | } |
| 717 | 717 | ||
| 718 | for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) | 718 | for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) |
| @@ -740,7 +740,7 @@ static void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev, | |||
| 740 | short lna_gain = 0; | 740 | short lna_gain = 0; |
| 741 | 741 | ||
| 742 | if (libconf->conf->chandef.chan->band == IEEE80211_BAND_2GHZ) { | 742 | if (libconf->conf->chandef.chan->band == IEEE80211_BAND_2GHZ) { |
| 743 | if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) | 743 | if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) |
| 744 | lna_gain += 14; | 744 | lna_gain += 14; |
| 745 | 745 | ||
| 746 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom); | 746 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom); |
| @@ -930,7 +930,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev, | |||
| 930 | low_bound = 0x28; | 930 | low_bound = 0x28; |
| 931 | up_bound = 0x48; | 931 | up_bound = 0x48; |
| 932 | 932 | ||
| 933 | if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) { | 933 | if (rt2x00_has_cap_external_lna_a(rt2x00dev)) { |
| 934 | low_bound += 0x10; | 934 | low_bound += 0x10; |
| 935 | up_bound += 0x10; | 935 | up_bound += 0x10; |
| 936 | } | 936 | } |
| @@ -946,7 +946,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev, | |||
| 946 | up_bound = 0x1c; | 946 | up_bound = 0x1c; |
| 947 | } | 947 | } |
| 948 | 948 | ||
| 949 | if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) { | 949 | if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { |
| 950 | low_bound += 0x14; | 950 | low_bound += 0x14; |
| 951 | up_bound += 0x10; | 951 | up_bound += 0x10; |
| 952 | } | 952 | } |
| @@ -1661,7 +1661,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) | |||
| 1661 | } | 1661 | } |
| 1662 | 1662 | ||
| 1663 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { | 1663 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { |
| 1664 | if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) { | 1664 | if (rt2x00_has_cap_external_lna_a(rt2x00dev)) { |
| 1665 | if (lna == 3 || lna == 2) | 1665 | if (lna == 3 || lna == 2) |
| 1666 | offset += 10; | 1666 | offset += 10; |
| 1667 | } else { | 1667 | } else { |
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c index fc207b268e4f..a91506b12a62 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c | |||
| @@ -1122,7 +1122,6 @@ static int rtl8180_probe(struct pci_dev *pdev, | |||
| 1122 | iounmap(priv->map); | 1122 | iounmap(priv->map); |
| 1123 | 1123 | ||
| 1124 | err_free_dev: | 1124 | err_free_dev: |
| 1125 | pci_set_drvdata(pdev, NULL); | ||
| 1126 | ieee80211_free_hw(dev); | 1125 | ieee80211_free_hw(dev); |
| 1127 | 1126 | ||
| 1128 | err_free_reg: | 1127 | err_free_reg: |
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index 8bb4a9a01a18..9a78e3daf742 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c | |||
| @@ -1613,6 +1613,35 @@ err_free: | |||
| 1613 | } | 1613 | } |
| 1614 | EXPORT_SYMBOL(rtl_send_smps_action); | 1614 | EXPORT_SYMBOL(rtl_send_smps_action); |
| 1615 | 1615 | ||
| 1616 | void rtl_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) | ||
| 1617 | { | ||
| 1618 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
| 1619 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
| 1620 | enum io_type iotype; | ||
| 1621 | |||
| 1622 | if (!is_hal_stop(rtlhal)) { | ||
| 1623 | switch (operation) { | ||
| 1624 | case SCAN_OPT_BACKUP: | ||
| 1625 | iotype = IO_CMD_PAUSE_DM_BY_SCAN; | ||
| 1626 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
| 1627 | HW_VAR_IO_CMD, | ||
| 1628 | (u8 *)&iotype); | ||
| 1629 | break; | ||
| 1630 | case SCAN_OPT_RESTORE: | ||
| 1631 | iotype = IO_CMD_RESUME_DM_BY_SCAN; | ||
| 1632 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
| 1633 | HW_VAR_IO_CMD, | ||
| 1634 | (u8 *)&iotype); | ||
| 1635 | break; | ||
| 1636 | default: | ||
| 1637 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
| 1638 | "Unknown Scan Backup operation.\n"); | ||
| 1639 | break; | ||
| 1640 | } | ||
| 1641 | } | ||
| 1642 | } | ||
| 1643 | EXPORT_SYMBOL(rtl_phy_scan_operation_backup); | ||
| 1644 | |||
| 1616 | /* There seem to be issues in mac80211 regarding when del ba frames can be | 1645 | /* There seem to be issues in mac80211 regarding when del ba frames can be |
| 1617 | * received. As a work around, we make a fake del_ba if we receive a ba_req; | 1646 | * received. As a work around, we make a fake del_ba if we receive a ba_req; |
| 1618 | * however, rx_agg was opened to let mac80211 release some ba related | 1647 | * however, rx_agg was opened to let mac80211 release some ba related |
diff --git a/drivers/net/wireless/rtlwifi/base.h b/drivers/net/wireless/rtlwifi/base.h index 0e5fe0902daf..0cd07420777a 100644 --- a/drivers/net/wireless/rtlwifi/base.h +++ b/drivers/net/wireless/rtlwifi/base.h | |||
| @@ -114,7 +114,6 @@ void rtl_init_rfkill(struct ieee80211_hw *hw); | |||
| 114 | void rtl_deinit_rfkill(struct ieee80211_hw *hw); | 114 | void rtl_deinit_rfkill(struct ieee80211_hw *hw); |
| 115 | 115 | ||
| 116 | void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb); | 116 | void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb); |
| 117 | void rtl_watch_dog_timer_callback(unsigned long data); | ||
| 118 | void rtl_deinit_deferred_work(struct ieee80211_hw *hw); | 117 | void rtl_deinit_deferred_work(struct ieee80211_hw *hw); |
| 119 | 118 | ||
| 120 | bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx); | 119 | bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx); |
| @@ -153,5 +152,6 @@ int rtlwifi_rate_mapping(struct ieee80211_hw *hw, | |||
| 153 | bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb); | 152 | bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb); |
| 154 | struct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw, | 153 | struct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw, |
| 155 | u8 *sa, u8 *bssid, u16 tid); | 154 | u8 *sa, u8 *bssid, u16 tid); |
| 155 | void rtl_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation); | ||
| 156 | 156 | ||
| 157 | #endif | 157 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/cam.h b/drivers/net/wireless/rtlwifi/cam.h index 35e00086a520..0105e6c1901e 100644 --- a/drivers/net/wireless/rtlwifi/cam.h +++ b/drivers/net/wireless/rtlwifi/cam.h | |||
| @@ -41,12 +41,12 @@ | |||
| 41 | #define CAM_CONFIG_USEDK 1 | 41 | #define CAM_CONFIG_USEDK 1 |
| 42 | #define CAM_CONFIG_NO_USEDK 0 | 42 | #define CAM_CONFIG_NO_USEDK 0 |
| 43 | 43 | ||
| 44 | extern void rtl_cam_reset_all_entry(struct ieee80211_hw *hw); | 44 | void rtl_cam_reset_all_entry(struct ieee80211_hw *hw); |
| 45 | extern u8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, u8 *mac_addr, | 45 | u8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, u8 *mac_addr, |
| 46 | u32 ul_key_id, u32 ul_entry_idx, u32 ul_enc_alg, | 46 | u32 ul_key_id, u32 ul_entry_idx, u32 ul_enc_alg, |
| 47 | u32 ul_default_key, u8 *key_content); | 47 | u32 ul_default_key, u8 *key_content); |
| 48 | int rtl_cam_delete_one_entry(struct ieee80211_hw *hw, u8 *mac_addr, | 48 | int rtl_cam_delete_one_entry(struct ieee80211_hw *hw, u8 *mac_addr, |
| 49 | u32 ul_key_id); | 49 | u32 ul_key_id); |
| 50 | void rtl_cam_mark_invalid(struct ieee80211_hw *hw, u8 uc_index); | 50 | void rtl_cam_mark_invalid(struct ieee80211_hw *hw, u8 uc_index); |
| 51 | void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index); | 51 | void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index); |
| 52 | void rtl_cam_reset_sec_info(struct ieee80211_hw *hw); | 52 | void rtl_cam_reset_sec_info(struct ieee80211_hw *hw); |
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index 733b7ce7f0e2..210ce7cd94d8 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c | |||
| @@ -115,7 +115,7 @@ static void rtl_op_stop(struct ieee80211_hw *hw) | |||
| 115 | mutex_lock(&rtlpriv->locks.conf_mutex); | 115 | mutex_lock(&rtlpriv->locks.conf_mutex); |
| 116 | 116 | ||
| 117 | mac->link_state = MAC80211_NOLINK; | 117 | mac->link_state = MAC80211_NOLINK; |
| 118 | memset(mac->bssid, 0, 6); | 118 | memset(mac->bssid, 0, ETH_ALEN); |
| 119 | mac->vendor = PEER_UNKNOWN; | 119 | mac->vendor = PEER_UNKNOWN; |
| 120 | 120 | ||
| 121 | /*reset sec info */ | 121 | /*reset sec info */ |
| @@ -280,7 +280,7 @@ static void rtl_op_remove_interface(struct ieee80211_hw *hw, | |||
| 280 | mac->p2p = 0; | 280 | mac->p2p = 0; |
| 281 | mac->vif = NULL; | 281 | mac->vif = NULL; |
| 282 | mac->link_state = MAC80211_NOLINK; | 282 | mac->link_state = MAC80211_NOLINK; |
| 283 | memset(mac->bssid, 0, 6); | 283 | memset(mac->bssid, 0, ETH_ALEN); |
| 284 | mac->vendor = PEER_UNKNOWN; | 284 | mac->vendor = PEER_UNKNOWN; |
| 285 | mac->opmode = NL80211_IFTYPE_UNSPECIFIED; | 285 | mac->opmode = NL80211_IFTYPE_UNSPECIFIED; |
| 286 | rtlpriv->cfg->ops->set_network_type(hw, mac->opmode); | 286 | rtlpriv->cfg->ops->set_network_type(hw, mac->opmode); |
| @@ -721,7 +721,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, | |||
| 721 | mac->link_state = MAC80211_LINKED; | 721 | mac->link_state = MAC80211_LINKED; |
| 722 | mac->cnt_after_linked = 0; | 722 | mac->cnt_after_linked = 0; |
| 723 | mac->assoc_id = bss_conf->aid; | 723 | mac->assoc_id = bss_conf->aid; |
| 724 | memcpy(mac->bssid, bss_conf->bssid, 6); | 724 | memcpy(mac->bssid, bss_conf->bssid, ETH_ALEN); |
| 725 | 725 | ||
| 726 | if (rtlpriv->cfg->ops->linked_set_reg) | 726 | if (rtlpriv->cfg->ops->linked_set_reg) |
| 727 | rtlpriv->cfg->ops->linked_set_reg(hw); | 727 | rtlpriv->cfg->ops->linked_set_reg(hw); |
| @@ -750,7 +750,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, | |||
| 750 | if (ppsc->p2p_ps_info.p2p_ps_mode > P2P_PS_NONE) | 750 | if (ppsc->p2p_ps_info.p2p_ps_mode > P2P_PS_NONE) |
| 751 | rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); | 751 | rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); |
| 752 | mac->link_state = MAC80211_NOLINK; | 752 | mac->link_state = MAC80211_NOLINK; |
| 753 | memset(mac->bssid, 0, 6); | 753 | memset(mac->bssid, 0, ETH_ALEN); |
| 754 | mac->vendor = PEER_UNKNOWN; | 754 | mac->vendor = PEER_UNKNOWN; |
| 755 | 755 | ||
| 756 | if (rtlpriv->dm.supp_phymode_switch) { | 756 | if (rtlpriv->dm.supp_phymode_switch) { |
| @@ -826,7 +826,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, | |||
| 826 | bss_conf->bssid); | 826 | bss_conf->bssid); |
| 827 | 827 | ||
| 828 | mac->vendor = PEER_UNKNOWN; | 828 | mac->vendor = PEER_UNKNOWN; |
| 829 | memcpy(mac->bssid, bss_conf->bssid, 6); | 829 | memcpy(mac->bssid, bss_conf->bssid, ETH_ALEN); |
| 830 | rtlpriv->cfg->ops->set_network_type(hw, vif->type); | 830 | rtlpriv->cfg->ops->set_network_type(hw, vif->type); |
| 831 | 831 | ||
| 832 | rcu_read_lock(); | 832 | rcu_read_lock(); |
diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c index 838a1ed3f194..ae13fb94b2e8 100644 --- a/drivers/net/wireless/rtlwifi/efuse.c +++ b/drivers/net/wireless/rtlwifi/efuse.c | |||
| @@ -1203,20 +1203,18 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) | |||
| 1203 | 1203 | ||
| 1204 | static u16 efuse_get_current_size(struct ieee80211_hw *hw) | 1204 | static u16 efuse_get_current_size(struct ieee80211_hw *hw) |
| 1205 | { | 1205 | { |
| 1206 | int continual = true; | ||
| 1207 | u16 efuse_addr = 0; | 1206 | u16 efuse_addr = 0; |
| 1208 | u8 hworden; | 1207 | u8 hworden; |
| 1209 | u8 efuse_data, word_cnts; | 1208 | u8 efuse_data, word_cnts; |
| 1210 | 1209 | ||
| 1211 | while (continual && efuse_one_byte_read(hw, efuse_addr, &efuse_data) | 1210 | while (efuse_one_byte_read(hw, efuse_addr, &efuse_data) && |
| 1212 | && (efuse_addr < EFUSE_MAX_SIZE)) { | 1211 | efuse_addr < EFUSE_MAX_SIZE) { |
| 1213 | if (efuse_data != 0xFF) { | 1212 | if (efuse_data == 0xFF) |
| 1214 | hworden = efuse_data & 0x0F; | 1213 | break; |
| 1215 | word_cnts = efuse_calculate_word_cnts(hworden); | 1214 | |
| 1216 | efuse_addr = efuse_addr + (word_cnts * 2) + 1; | 1215 | hworden = efuse_data & 0x0F; |
| 1217 | } else { | 1216 | word_cnts = efuse_calculate_word_cnts(hworden); |
| 1218 | continual = false; | 1217 | efuse_addr = efuse_addr + (word_cnts * 2) + 1; |
| 1219 | } | ||
| 1220 | } | 1218 | } |
| 1221 | 1219 | ||
| 1222 | return efuse_addr; | 1220 | return efuse_addr; |
diff --git a/drivers/net/wireless/rtlwifi/efuse.h b/drivers/net/wireless/rtlwifi/efuse.h index 395a326acfb4..1663b3afd41e 100644 --- a/drivers/net/wireless/rtlwifi/efuse.h +++ b/drivers/net/wireless/rtlwifi/efuse.h | |||
| @@ -104,20 +104,19 @@ struct efuse_priv { | |||
| 104 | u8 tx_power_g[14]; | 104 | u8 tx_power_g[14]; |
| 105 | }; | 105 | }; |
| 106 | 106 | ||
| 107 | extern void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf); | 107 | void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf); |
| 108 | extern void efuse_initialize(struct ieee80211_hw *hw); | 108 | void efuse_initialize(struct ieee80211_hw *hw); |
| 109 | extern u8 efuse_read_1byte(struct ieee80211_hw *hw, u16 address); | 109 | u8 efuse_read_1byte(struct ieee80211_hw *hw, u16 address); |
| 110 | extern void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value); | 110 | void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value); |
| 111 | extern void read_efuse(struct ieee80211_hw *hw, u16 _offset, | 111 | void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf); |
| 112 | u16 _size_byte, u8 *pbuf); | 112 | void efuse_shadow_read(struct ieee80211_hw *hw, u8 type, u16 offset, |
| 113 | extern void efuse_shadow_read(struct ieee80211_hw *hw, u8 type, | 113 | u32 *value); |
| 114 | u16 offset, u32 *value); | 114 | void efuse_shadow_write(struct ieee80211_hw *hw, u8 type, u16 offset, |
| 115 | extern void efuse_shadow_write(struct ieee80211_hw *hw, u8 type, | 115 | u32 value); |
| 116 | u16 offset, u32 value); | 116 | bool efuse_shadow_update(struct ieee80211_hw *hw); |
| 117 | extern bool efuse_shadow_update(struct ieee80211_hw *hw); | 117 | bool efuse_shadow_update_chk(struct ieee80211_hw *hw); |
| 118 | extern bool efuse_shadow_update_chk(struct ieee80211_hw *hw); | 118 | void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw); |
| 119 | extern void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw); | 119 | void efuse_force_write_vendor_Id(struct ieee80211_hw *hw); |
| 120 | extern void efuse_force_write_vendor_Id(struct ieee80211_hw *hw); | 120 | void efuse_re_pg_section(struct ieee80211_hw *hw, u8 section_idx); |
| 121 | extern void efuse_re_pg_section(struct ieee80211_hw *hw, u8 section_idx); | ||
| 122 | 121 | ||
| 123 | #endif | 122 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 703f839af6ca..0f494444bcd1 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c | |||
| @@ -736,7 +736,6 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) | |||
| 736 | 736 | ||
| 737 | struct rtl_stats stats = { | 737 | struct rtl_stats stats = { |
| 738 | .signal = 0, | 738 | .signal = 0, |
| 739 | .noise = -98, | ||
| 740 | .rate = 0, | 739 | .rate = 0, |
| 741 | }; | 740 | }; |
| 742 | int index = rtlpci->rx_ring[rx_queue_idx].idx; | 741 | int index = rtlpci->rx_ring[rx_queue_idx].idx; |
| @@ -2009,7 +2008,6 @@ fail2: | |||
| 2009 | fail1: | 2008 | fail1: |
| 2010 | if (hw) | 2009 | if (hw) |
| 2011 | ieee80211_free_hw(hw); | 2010 | ieee80211_free_hw(hw); |
| 2012 | pci_set_drvdata(pdev, NULL); | ||
| 2013 | pci_disable_device(pdev); | 2011 | pci_disable_device(pdev); |
| 2014 | 2012 | ||
| 2015 | return err; | 2013 | return err; |
| @@ -2064,8 +2062,6 @@ void rtl_pci_disconnect(struct pci_dev *pdev) | |||
| 2064 | 2062 | ||
| 2065 | rtl_pci_disable_aspm(hw); | 2063 | rtl_pci_disable_aspm(hw); |
| 2066 | 2064 | ||
| 2067 | pci_set_drvdata(pdev, NULL); | ||
| 2068 | |||
| 2069 | ieee80211_free_hw(hw); | 2065 | ieee80211_free_hw(hw); |
| 2070 | } | 2066 | } |
| 2071 | EXPORT_SYMBOL(rtl_pci_disconnect); | 2067 | EXPORT_SYMBOL(rtl_pci_disconnect); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c index b68cae3024fc..e06971be7df7 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c | |||
| @@ -143,6 +143,7 @@ static void _rtl88ee_set_fw_clock_on(struct ieee80211_hw *hw, | |||
| 143 | } else { | 143 | } else { |
| 144 | rtlhal->fw_clk_change_in_progress = false; | 144 | rtlhal->fw_clk_change_in_progress = false; |
| 145 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | 145 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); |
| 146 | break; | ||
| 146 | } | 147 | } |
| 147 | } | 148 | } |
| 148 | 149 | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.c b/drivers/net/wireless/rtlwifi/rtl8188ee/phy.c index e655c0473225..d67f9c731cc4 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/phy.c | |||
| @@ -1136,34 +1136,6 @@ void rtl88e_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) | |||
| 1136 | &bw40_pwr[0], channel); | 1136 | &bw40_pwr[0], channel); |
| 1137 | } | 1137 | } |
| 1138 | 1138 | ||
| 1139 | void rtl88e_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) | ||
| 1140 | { | ||
| 1141 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
| 1142 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
| 1143 | enum io_type iotype; | ||
| 1144 | |||
| 1145 | if (!is_hal_stop(rtlhal)) { | ||
| 1146 | switch (operation) { | ||
| 1147 | case SCAN_OPT_BACKUP: | ||
| 1148 | iotype = IO_CMD_PAUSE_DM_BY_SCAN; | ||
| 1149 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
| 1150 | HW_VAR_IO_CMD, | ||
| 1151 | (u8 *)&iotype); | ||
| 1152 | break; | ||
| 1153 | case SCAN_OPT_RESTORE: | ||
| 1154 | iotype = IO_CMD_RESUME_DM_BY_SCAN; | ||
| 1155 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
| 1156 | HW_VAR_IO_CMD, | ||
| 1157 | (u8 *)&iotype); | ||
| 1158 | break; | ||
| 1159 | default: | ||
| 1160 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
| 1161 | "Unknown Scan Backup operation.\n"); | ||
| 1162 | break; | ||
| 1163 | } | ||
| 1164 | } | ||
| 1165 | } | ||
| 1166 | |||
| 1167 | void rtl88e_phy_set_bw_mode_callback(struct ieee80211_hw *hw) | 1139 | void rtl88e_phy_set_bw_mode_callback(struct ieee80211_hw *hw) |
| 1168 | { | 1140 | { |
| 1169 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1141 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h b/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h index f1acd6d27e44..89f0f1ef1465 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h | |||
| @@ -200,37 +200,35 @@ enum _ANT_DIV_TYPE { | |||
| 200 | CGCS_RX_SW_ANTDIV = 0x05, | 200 | CGCS_RX_SW_ANTDIV = 0x05, |
| 201 | }; | 201 | }; |
| 202 | 202 | ||
| 203 | extern u32 rtl88e_phy_query_bb_reg(struct ieee80211_hw *hw, | 203 | u32 rtl88e_phy_query_bb_reg(struct ieee80211_hw *hw, |
| 204 | u32 regaddr, u32 bitmask); | 204 | u32 regaddr, u32 bitmask); |
| 205 | extern void rtl88e_phy_set_bb_reg(struct ieee80211_hw *hw, | 205 | void rtl88e_phy_set_bb_reg(struct ieee80211_hw *hw, |
| 206 | u32 regaddr, u32 bitmask, u32 data); | 206 | u32 regaddr, u32 bitmask, u32 data); |
| 207 | extern u32 rtl88e_phy_query_rf_reg(struct ieee80211_hw *hw, | 207 | u32 rtl88e_phy_query_rf_reg(struct ieee80211_hw *hw, |
| 208 | enum radio_path rfpath, u32 regaddr, | 208 | enum radio_path rfpath, u32 regaddr, |
| 209 | u32 bitmask); | 209 | u32 bitmask); |
| 210 | extern void rtl88e_phy_set_rf_reg(struct ieee80211_hw *hw, | 210 | void rtl88e_phy_set_rf_reg(struct ieee80211_hw *hw, |
| 211 | enum radio_path rfpath, u32 regaddr, | 211 | enum radio_path rfpath, u32 regaddr, |
| 212 | u32 bitmask, u32 data); | 212 | u32 bitmask, u32 data); |
| 213 | extern bool rtl88e_phy_mac_config(struct ieee80211_hw *hw); | 213 | bool rtl88e_phy_mac_config(struct ieee80211_hw *hw); |
| 214 | extern bool rtl88e_phy_bb_config(struct ieee80211_hw *hw); | 214 | bool rtl88e_phy_bb_config(struct ieee80211_hw *hw); |
| 215 | extern bool rtl88e_phy_rf_config(struct ieee80211_hw *hw); | 215 | bool rtl88e_phy_rf_config(struct ieee80211_hw *hw); |
| 216 | extern void rtl88e_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); | 216 | void rtl88e_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); |
| 217 | extern void rtl88e_phy_get_txpower_level(struct ieee80211_hw *hw, | 217 | void rtl88e_phy_get_txpower_level(struct ieee80211_hw *hw, |
| 218 | long *powerlevel); | 218 | long *powerlevel); |
| 219 | extern void rtl88e_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); | 219 | void rtl88e_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); |
| 220 | extern void rtl88e_phy_scan_operation_backup(struct ieee80211_hw *hw, | 220 | void rtl88e_phy_set_bw_mode_callback(struct ieee80211_hw *hw); |
| 221 | u8 operation); | 221 | void rtl88e_phy_set_bw_mode(struct ieee80211_hw *hw, |
| 222 | extern void rtl88e_phy_set_bw_mode_callback(struct ieee80211_hw *hw); | 222 | enum nl80211_channel_type ch_type); |
| 223 | extern void rtl88e_phy_set_bw_mode(struct ieee80211_hw *hw, | 223 | void rtl88e_phy_sw_chnl_callback(struct ieee80211_hw *hw); |
| 224 | enum nl80211_channel_type ch_type); | 224 | u8 rtl88e_phy_sw_chnl(struct ieee80211_hw *hw); |
| 225 | extern void rtl88e_phy_sw_chnl_callback(struct ieee80211_hw *hw); | 225 | void rtl88e_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); |
| 226 | extern u8 rtl88e_phy_sw_chnl(struct ieee80211_hw *hw); | ||
| 227 | extern void rtl88e_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); | ||
| 228 | void rtl88e_phy_lc_calibrate(struct ieee80211_hw *hw); | 226 | void rtl88e_phy_lc_calibrate(struct ieee80211_hw *hw); |
| 229 | void rtl88e_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); | 227 | void rtl88e_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); |
| 230 | bool rtl88e_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, | 228 | bool rtl88e_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, |
| 231 | enum radio_path rfpath); | 229 | enum radio_path rfpath); |
| 232 | bool rtl88e_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); | 230 | bool rtl88e_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); |
| 233 | extern bool rtl88e_phy_set_rf_power_state(struct ieee80211_hw *hw, | 231 | bool rtl88e_phy_set_rf_power_state(struct ieee80211_hw *hw, |
| 234 | enum rf_pwrstate rfpwr_state); | 232 | enum rf_pwrstate rfpwr_state); |
| 235 | 233 | ||
| 236 | #endif | 234 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c index c254693a1e6a..347af1e4f438 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include "../wifi.h" | 30 | #include "../wifi.h" |
| 31 | #include "../core.h" | 31 | #include "../core.h" |
| 32 | #include "../pci.h" | 32 | #include "../pci.h" |
| 33 | #include "../base.h" | ||
| 33 | #include "reg.h" | 34 | #include "reg.h" |
| 34 | #include "def.h" | 35 | #include "def.h" |
| 35 | #include "phy.h" | 36 | #include "phy.h" |
| @@ -244,7 +245,7 @@ static struct rtl_hal_ops rtl8188ee_hal_ops = { | |||
| 244 | .set_bw_mode = rtl88e_phy_set_bw_mode, | 245 | .set_bw_mode = rtl88e_phy_set_bw_mode, |
| 245 | .switch_channel = rtl88e_phy_sw_chnl, | 246 | .switch_channel = rtl88e_phy_sw_chnl, |
| 246 | .dm_watchdog = rtl88e_dm_watchdog, | 247 | .dm_watchdog = rtl88e_dm_watchdog, |
| 247 | .scan_operation_backup = rtl88e_phy_scan_operation_backup, | 248 | .scan_operation_backup = rtl_phy_scan_operation_backup, |
| 248 | .set_rf_power_state = rtl88e_phy_set_rf_power_state, | 249 | .set_rf_power_state = rtl88e_phy_set_rf_power_state, |
| 249 | .led_control = rtl88ee_led_control, | 250 | .led_control = rtl88ee_led_control, |
| 250 | .set_desc = rtl88ee_set_desc, | 251 | .set_desc = rtl88ee_set_desc, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c index 68685a898257..aece6c9cccf1 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c | |||
| @@ -478,7 +478,6 @@ bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw, | |||
| 478 | 478 | ||
| 479 | /*rx_status->qual = status->signal; */ | 479 | /*rx_status->qual = status->signal; */ |
| 480 | rx_status->signal = status->recvsignalpower + 10; | 480 | rx_status->signal = status->recvsignalpower + 10; |
| 481 | /*rx_status->noise = -status->noise; */ | ||
| 482 | if (status->packet_report_type == TX_REPORT2) { | 481 | if (status->packet_report_type == TX_REPORT2) { |
| 483 | status->macid_valid_entry[0] = | 482 | status->macid_valid_entry[0] = |
| 484 | GET_RX_RPT2_DESC_MACID_VALID_1(pdesc); | 483 | GET_RX_RPT2_DESC_MACID_VALID_1(pdesc); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c index d2d57a27a7c1..e9caa5d4cff0 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c | |||
| @@ -541,29 +541,6 @@ EXPORT_SYMBOL(rtl92c_dm_write_dig); | |||
| 541 | 541 | ||
| 542 | static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw) | 542 | static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw) |
| 543 | { | 543 | { |
| 544 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
| 545 | long tmpentry_max_pwdb = 0, tmpentry_min_pwdb = 0xff; | ||
| 546 | |||
| 547 | u8 h2c_parameter[3] = { 0 }; | ||
| 548 | |||
| 549 | return; | ||
| 550 | |||
| 551 | if (tmpentry_max_pwdb != 0) { | ||
| 552 | rtlpriv->dm.entry_max_undec_sm_pwdb = tmpentry_max_pwdb; | ||
| 553 | } else { | ||
| 554 | rtlpriv->dm.entry_max_undec_sm_pwdb = 0; | ||
| 555 | } | ||
| 556 | |||
| 557 | if (tmpentry_min_pwdb != 0xff) { | ||
| 558 | rtlpriv->dm.entry_min_undec_sm_pwdb = tmpentry_min_pwdb; | ||
| 559 | } else { | ||
| 560 | rtlpriv->dm.entry_min_undec_sm_pwdb = 0; | ||
| 561 | } | ||
| 562 | |||
| 563 | h2c_parameter[2] = (u8) (rtlpriv->dm.undec_sm_pwdb & 0xFF); | ||
| 564 | h2c_parameter[0] = 0; | ||
| 565 | |||
| 566 | rtl92c_fill_h2c_cmd(hw, H2C_RSSI_REPORT, 3, h2c_parameter); | ||
| 567 | } | 544 | } |
| 568 | 545 | ||
| 569 | void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw) | 546 | void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw) |
| @@ -673,7 +650,7 @@ static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw | |||
| 673 | s8 cck_index = 0; | 650 | s8 cck_index = 0; |
| 674 | int i; | 651 | int i; |
| 675 | bool is2t = IS_92C_SERIAL(rtlhal->version); | 652 | bool is2t = IS_92C_SERIAL(rtlhal->version); |
| 676 | s8 txpwr_level[2] = {0, 0}; | 653 | s8 txpwr_level[3] = {0, 0, 0}; |
| 677 | u8 ofdm_min_index = 6, rf; | 654 | u8 ofdm_min_index = 6, rf; |
| 678 | 655 | ||
| 679 | rtlpriv->dm.txpower_trackinginit = true; | 656 | rtlpriv->dm.txpower_trackinginit = true; |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c index 246e5352f2e1..0c0e78263a66 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c | |||
| @@ -592,36 +592,6 @@ long _rtl92c_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw, | |||
| 592 | } | 592 | } |
| 593 | EXPORT_SYMBOL(_rtl92c_phy_txpwr_idx_to_dbm); | 593 | EXPORT_SYMBOL(_rtl92c_phy_txpwr_idx_to_dbm); |
| 594 | 594 | ||
| 595 | void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) | ||
| 596 | { | ||
| 597 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
| 598 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
| 599 | enum io_type iotype; | ||
| 600 | |||
| 601 | if (!is_hal_stop(rtlhal)) { | ||
| 602 | switch (operation) { | ||
| 603 | case SCAN_OPT_BACKUP: | ||
| 604 | iotype = IO_CMD_PAUSE_DM_BY_SCAN; | ||
| 605 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
| 606 | HW_VAR_IO_CMD, | ||
| 607 | (u8 *)&iotype); | ||
| 608 | |||
| 609 | break; | ||
| 610 | case SCAN_OPT_RESTORE: | ||
| 611 | iotype = IO_CMD_RESUME_DM_BY_SCAN; | ||
| 612 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
| 613 | HW_VAR_IO_CMD, | ||
| 614 | (u8 *)&iotype); | ||
| 615 | break; | ||
| 616 | default: | ||
| 617 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
| 618 | "Unknown Scan Backup operation\n"); | ||
| 619 | break; | ||
| 620 | } | ||
| 621 | } | ||
| 622 | } | ||
| 623 | EXPORT_SYMBOL(rtl92c_phy_scan_operation_backup); | ||
| 624 | |||
| 625 | void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, | 595 | void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, |
| 626 | enum nl80211_channel_type ch_type) | 596 | enum nl80211_channel_type ch_type) |
| 627 | { | 597 | { |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h index cec10d696492..e79dabe9ba1d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h +++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h | |||
| @@ -39,9 +39,7 @@ | |||
| 39 | #define RT_CANNOT_IO(hw) false | 39 | #define RT_CANNOT_IO(hw) false |
| 40 | #define HIGHPOWER_RADIOA_ARRAYLEN 22 | 40 | #define HIGHPOWER_RADIOA_ARRAYLEN 22 |
| 41 | 41 | ||
| 42 | #define IQK_ADDA_REG_NUM 16 | ||
| 43 | #define MAX_TOLERANCE 5 | 42 | #define MAX_TOLERANCE 5 |
| 44 | #define IQK_DELAY_TIME 1 | ||
| 45 | 43 | ||
| 46 | #define APK_BB_REG_NUM 5 | 44 | #define APK_BB_REG_NUM 5 |
| 47 | #define APK_AFE_REG_NUM 16 | 45 | #define APK_AFE_REG_NUM 16 |
| @@ -205,8 +203,6 @@ void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, | |||
| 205 | void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); | 203 | void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); |
| 206 | bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, | 204 | bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, |
| 207 | long power_indbm); | 205 | long power_indbm); |
| 208 | void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw, | ||
| 209 | u8 operation); | ||
| 210 | void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, | 206 | void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, |
| 211 | enum nl80211_channel_type ch_type); | 207 | enum nl80211_channel_type ch_type); |
| 212 | void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); | 208 | void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h index 3cfa1bb0f476..fa24de43ce79 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h | |||
| @@ -152,8 +152,6 @@ enum version_8192c { | |||
| 152 | #define IS_VENDOR_UMC_A_CUT(version) ((IS_CHIP_VENDOR_UMC(version)) ? \ | 152 | #define IS_VENDOR_UMC_A_CUT(version) ((IS_CHIP_VENDOR_UMC(version)) ? \ |
| 153 | ((GET_CVID_CUT_VERSION(version)) ? false : true) : false) | 153 | ((GET_CVID_CUT_VERSION(version)) ? false : true) : false) |
| 154 | #define IS_CHIP_VER_B(version) ((version & CHIP_VER_B) ? true : false) | 154 | #define IS_CHIP_VER_B(version) ((version & CHIP_VER_B) ? true : false) |
| 155 | #define IS_VENDOR_UMC_A_CUT(version) ((IS_CHIP_VENDOR_UMC(version)) ? \ | ||
| 156 | ((GET_CVID_CUT_VERSION(version)) ? false : true) : false) | ||
| 157 | #define IS_92C_SERIAL(version) ((version & CHIP_92C_BITMASK) ? true : false) | 155 | #define IS_92C_SERIAL(version) ((version & CHIP_92C_BITMASK) ? true : false) |
| 158 | #define IS_CHIP_VENDOR_UMC(version) \ | 156 | #define IS_CHIP_VENDOR_UMC(version) \ |
| 159 | ((version & CHIP_VENDOR_UMC) ? true : false) | 157 | ((version & CHIP_VENDOR_UMC) ? true : false) |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h index d5e3b704f930..94486cca4000 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h | |||
| @@ -39,9 +39,7 @@ | |||
| 39 | #define RT_CANNOT_IO(hw) false | 39 | #define RT_CANNOT_IO(hw) false |
| 40 | #define HIGHPOWER_RADIOA_ARRAYLEN 22 | 40 | #define HIGHPOWER_RADIOA_ARRAYLEN 22 |
| 41 | 41 | ||
| 42 | #define IQK_ADDA_REG_NUM 16 | ||
| 43 | #define MAX_TOLERANCE 5 | 42 | #define MAX_TOLERANCE 5 |
| 44 | #define IQK_DELAY_TIME 1 | ||
| 45 | 43 | ||
| 46 | #define APK_BB_REG_NUM 5 | 44 | #define APK_BB_REG_NUM 5 |
| 47 | #define APK_AFE_REG_NUM 16 | 45 | #define APK_AFE_REG_NUM 16 |
| @@ -188,36 +186,29 @@ struct tx_power_struct { | |||
| 188 | }; | 186 | }; |
| 189 | 187 | ||
| 190 | bool rtl92c_phy_bb_config(struct ieee80211_hw *hw); | 188 | bool rtl92c_phy_bb_config(struct ieee80211_hw *hw); |
| 191 | u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, | 189 | u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask); |
| 192 | u32 regaddr, u32 bitmask); | 190 | void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, |
| 193 | void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, | 191 | u32 data); |
| 194 | u32 regaddr, u32 bitmask, u32 data); | 192 | u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, |
| 195 | u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, | 193 | u32 regaddr, u32 bitmask); |
| 196 | enum radio_path rfpath, u32 regaddr, | 194 | void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, |
| 197 | u32 bitmask); | 195 | u32 regaddr, u32 bitmask, u32 data); |
| 198 | extern void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw, | ||
| 199 | enum radio_path rfpath, u32 regaddr, | ||
| 200 | u32 bitmask, u32 data); | ||
| 201 | bool rtl92c_phy_mac_config(struct ieee80211_hw *hw); | 196 | bool rtl92c_phy_mac_config(struct ieee80211_hw *hw); |
| 202 | bool rtl92ce_phy_bb_config(struct ieee80211_hw *hw); | 197 | bool rtl92ce_phy_bb_config(struct ieee80211_hw *hw); |
| 203 | bool rtl92c_phy_rf_config(struct ieee80211_hw *hw); | 198 | bool rtl92c_phy_rf_config(struct ieee80211_hw *hw); |
| 204 | bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, | 199 | bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, |
| 205 | enum radio_path rfpath); | 200 | enum radio_path rfpath); |
| 206 | void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); | 201 | void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); |
| 207 | void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, | 202 | void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel); |
| 208 | long *powerlevel); | ||
| 209 | void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); | 203 | void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); |
| 210 | bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, | 204 | bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, |
| 211 | long power_indbm); | 205 | long power_indbm); |
| 212 | void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw, | ||
| 213 | u8 operation); | ||
| 214 | void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, | 206 | void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, |
| 215 | enum nl80211_channel_type ch_type); | 207 | enum nl80211_channel_type ch_type); |
| 216 | void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); | 208 | void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); |
| 217 | u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw); | 209 | u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw); |
| 218 | void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); | 210 | void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); |
| 219 | void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, | 211 | void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, u16 beaconinterval); |
| 220 | u16 beaconinterval); | ||
| 221 | void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); | 212 | void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); |
| 222 | void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw); | 213 | void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw); |
| 223 | void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t); | 214 | void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t); |
| @@ -225,28 +216,25 @@ void rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); | |||
| 225 | bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, | 216 | bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, |
| 226 | enum radio_path rfpath); | 217 | enum radio_path rfpath); |
| 227 | bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, | 218 | bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, |
| 228 | u32 rfpath); | 219 | u32 rfpath); |
| 229 | bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); | ||
| 230 | bool rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, | 220 | bool rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, |
| 231 | enum rf_pwrstate rfpwr_state); | 221 | enum rf_pwrstate rfpwr_state); |
| 232 | void rtl92ce_phy_set_rf_on(struct ieee80211_hw *hw); | 222 | void rtl92ce_phy_set_rf_on(struct ieee80211_hw *hw); |
| 233 | bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); | 223 | bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); |
| 234 | void rtl92c_phy_set_io(struct ieee80211_hw *hw); | 224 | void rtl92c_phy_set_io(struct ieee80211_hw *hw); |
| 235 | void rtl92c_bb_block_on(struct ieee80211_hw *hw); | 225 | void rtl92c_bb_block_on(struct ieee80211_hw *hw); |
| 236 | u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, | 226 | u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, enum radio_path rfpath, |
| 237 | enum radio_path rfpath, u32 offset); | 227 | u32 offset); |
| 238 | u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw, | 228 | u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw, |
| 239 | enum radio_path rfpath, u32 offset); | 229 | enum radio_path rfpath, u32 offset); |
| 240 | u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask); | 230 | u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask); |
| 241 | void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, | 231 | void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, |
| 242 | enum radio_path rfpath, u32 offset, | 232 | enum radio_path rfpath, u32 offset, u32 data); |
| 243 | u32 data); | ||
| 244 | void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, | 233 | void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, |
| 245 | enum radio_path rfpath, u32 offset, | 234 | enum radio_path rfpath, u32 offset, |
| 246 | u32 data); | 235 | u32 data); |
| 247 | void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, | 236 | void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, |
| 248 | u32 regaddr, u32 bitmask, | 237 | u32 regaddr, u32 bitmask, u32 data); |
| 249 | u32 data); | ||
| 250 | bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); | 238 | bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); |
| 251 | void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw); | 239 | void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw); |
| 252 | bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw); | 240 | bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h index bd4aef74c056..8922ecb47ad2 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h | |||
| @@ -560,7 +560,6 @@ | |||
| 560 | #define EEPROM_DEFAULT_TXPOWERLEVEL 0x22 | 560 | #define EEPROM_DEFAULT_TXPOWERLEVEL 0x22 |
| 561 | #define EEPROM_DEFAULT_HT40_2SDIFF 0x0 | 561 | #define EEPROM_DEFAULT_HT40_2SDIFF 0x0 |
| 562 | #define EEPROM_DEFAULT_HT20_DIFF 2 | 562 | #define EEPROM_DEFAULT_HT20_DIFF 2 |
| 563 | #define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 | ||
| 564 | #define EEPROM_DEFAULT_HT40_PWRMAXOFFSET 0 | 563 | #define EEPROM_DEFAULT_HT40_PWRMAXOFFSET 0 |
| 565 | #define EEPROM_DEFAULT_HT20_PWRMAXOFFSET 0 | 564 | #define EEPROM_DEFAULT_HT20_PWRMAXOFFSET 0 |
| 566 | 565 | ||
| @@ -639,17 +638,8 @@ | |||
| 639 | 638 | ||
| 640 | #define EEPROM_TXPWR_GROUP 0x6F | 639 | #define EEPROM_TXPWR_GROUP 0x6F |
| 641 | 640 | ||
| 642 | #define EEPROM_TSSI_A 0x76 | ||
| 643 | #define EEPROM_TSSI_B 0x77 | ||
| 644 | #define EEPROM_THERMAL_METER 0x78 | ||
| 645 | |||
| 646 | #define EEPROM_CHANNELPLAN 0x75 | 641 | #define EEPROM_CHANNELPLAN 0x75 |
| 647 | 642 | ||
| 648 | #define RF_OPTION1 0x79 | ||
| 649 | #define RF_OPTION2 0x7A | ||
| 650 | #define RF_OPTION3 0x7B | ||
| 651 | #define RF_OPTION4 0x7C | ||
| 652 | |||
| 653 | #define STOPBECON BIT(6) | 643 | #define STOPBECON BIT(6) |
| 654 | #define STOPHIGHT BIT(5) | 644 | #define STOPHIGHT BIT(5) |
| 655 | #define STOPMGT BIT(4) | 645 | #define STOPMGT BIT(4) |
| @@ -689,13 +679,6 @@ | |||
| 689 | #define RSV_CTRL 0x001C | 679 | #define RSV_CTRL 0x001C |
| 690 | #define RD_CTRL 0x0524 | 680 | #define RD_CTRL 0x0524 |
| 691 | 681 | ||
| 692 | #define REG_USB_INFO 0xFE17 | ||
| 693 | #define REG_USB_SPECIAL_OPTION 0xFE55 | ||
| 694 | |||
| 695 | #define REG_USB_DMA_AGG_TO 0xFE5B | ||
| 696 | #define REG_USB_AGG_TO 0xFE5C | ||
| 697 | #define REG_USB_AGG_TH 0xFE5D | ||
| 698 | |||
| 699 | #define REG_USB_VID 0xFE60 | 682 | #define REG_USB_VID 0xFE60 |
| 700 | #define REG_USB_PID 0xFE62 | 683 | #define REG_USB_PID 0xFE62 |
| 701 | #define REG_USB_OPTIONAL 0xFE64 | 684 | #define REG_USB_OPTIONAL 0xFE64 |
| @@ -1196,9 +1179,6 @@ | |||
| 1196 | #define POLLING_LLT_THRESHOLD 20 | 1179 | #define POLLING_LLT_THRESHOLD 20 |
| 1197 | #define POLLING_READY_TIMEOUT_COUNT 1000 | 1180 | #define POLLING_READY_TIMEOUT_COUNT 1000 |
| 1198 | 1181 | ||
| 1199 | #define MAX_MSS_DENSITY_2T 0x13 | ||
| 1200 | #define MAX_MSS_DENSITY_1T 0x0A | ||
| 1201 | |||
| 1202 | #define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6)) | 1182 | #define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6)) |
| 1203 | #define EPROM_CMD_CONFIG 0x3 | 1183 | #define EPROM_CMD_CONFIG 0x3 |
| 1204 | #define EPROM_CMD_LOAD 1 | 1184 | #define EPROM_CMD_LOAD 1 |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h index 6c8d56efceae..d8fe68b389d2 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h | |||
| @@ -34,11 +34,10 @@ | |||
| 34 | #define RF6052_MAX_REG 0x3F | 34 | #define RF6052_MAX_REG 0x3F |
| 35 | #define RF6052_MAX_PATH 2 | 35 | #define RF6052_MAX_PATH 2 |
| 36 | 36 | ||
| 37 | extern void rtl92ce_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, | 37 | void rtl92ce_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth); |
| 38 | u8 bandwidth); | 38 | void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, |
| 39 | extern void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, | 39 | u8 *ppowerlevel); |
| 40 | u8 *ppowerlevel); | 40 | void rtl92ce_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, |
| 41 | extern void rtl92ce_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, | 41 | u8 *ppowerlevel, u8 channel); |
| 42 | u8 *ppowerlevel, u8 channel); | 42 | bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw); |
| 43 | extern bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw); | ||
| 44 | #endif | 43 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 14203561b6ee..b790320d2030 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include "../wifi.h" | 30 | #include "../wifi.h" |
| 31 | #include "../core.h" | 31 | #include "../core.h" |
| 32 | #include "../pci.h" | 32 | #include "../pci.h" |
| 33 | #include "../base.h" | ||
| 33 | #include "reg.h" | 34 | #include "reg.h" |
| 34 | #include "def.h" | 35 | #include "def.h" |
| 35 | #include "phy.h" | 36 | #include "phy.h" |
| @@ -219,7 +220,7 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = { | |||
| 219 | .set_bw_mode = rtl92c_phy_set_bw_mode, | 220 | .set_bw_mode = rtl92c_phy_set_bw_mode, |
| 220 | .switch_channel = rtl92c_phy_sw_chnl, | 221 | .switch_channel = rtl92c_phy_sw_chnl, |
| 221 | .dm_watchdog = rtl92c_dm_watchdog, | 222 | .dm_watchdog = rtl92c_dm_watchdog, |
| 222 | .scan_operation_backup = rtl92c_phy_scan_operation_backup, | 223 | .scan_operation_backup = rtl_phy_scan_operation_backup, |
| 223 | .set_rf_power_state = rtl92c_phy_set_rf_power_state, | 224 | .set_rf_power_state = rtl92c_phy_set_rf_power_state, |
| 224 | .led_control = rtl92ce_led_control, | 225 | .led_control = rtl92ce_led_control, |
| 225 | .set_desc = rtl92ce_set_desc, | 226 | .set_desc = rtl92ce_set_desc, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c index 6ad23b413eb3..52abf0a862fa 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c | |||
| @@ -420,7 +420,6 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, | |||
| 420 | 420 | ||
| 421 | /*rx_status->qual = stats->signal; */ | 421 | /*rx_status->qual = stats->signal; */ |
| 422 | rx_status->signal = stats->recvsignalpower + 10; | 422 | rx_status->signal = stats->recvsignalpower + 10; |
| 423 | /*rx_status->noise = -stats->noise; */ | ||
| 424 | 423 | ||
| 425 | return true; | 424 | return true; |
| 426 | } | 425 | } |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c index da4f587199ee..393685390f3e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include "../usb.h" | 32 | #include "../usb.h" |
| 33 | #include "../ps.h" | 33 | #include "../ps.h" |
| 34 | #include "../cam.h" | 34 | #include "../cam.h" |
| 35 | #include "../stats.h" | ||
| 35 | #include "reg.h" | 36 | #include "reg.h" |
| 36 | #include "def.h" | 37 | #include "def.h" |
| 37 | #include "phy.h" | 38 | #include "phy.h" |
| @@ -738,16 +739,6 @@ static u8 _rtl92c_evm_db_to_percentage(char value) | |||
| 738 | return ret_val; | 739 | return ret_val; |
| 739 | } | 740 | } |
| 740 | 741 | ||
| 741 | static long _rtl92c_translate_todbm(struct ieee80211_hw *hw, | ||
| 742 | u8 signal_strength_index) | ||
| 743 | { | ||
| 744 | long signal_power; | ||
| 745 | |||
| 746 | signal_power = (long)((signal_strength_index + 1) >> 1); | ||
| 747 | signal_power -= 95; | ||
| 748 | return signal_power; | ||
| 749 | } | ||
| 750 | |||
| 751 | static long _rtl92c_signal_scale_mapping(struct ieee80211_hw *hw, | 742 | static long _rtl92c_signal_scale_mapping(struct ieee80211_hw *hw, |
| 752 | long currsig) | 743 | long currsig) |
| 753 | { | 744 | { |
| @@ -913,180 +904,6 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw, | |||
| 913 | (hw, total_rssi /= rf_rx_num)); | 904 | (hw, total_rssi /= rf_rx_num)); |
| 914 | } | 905 | } |
| 915 | 906 | ||
| 916 | static void _rtl92c_process_ui_rssi(struct ieee80211_hw *hw, | ||
| 917 | struct rtl_stats *pstats) | ||
| 918 | { | ||
| 919 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
| 920 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
| 921 | u8 rfpath; | ||
| 922 | u32 last_rssi, tmpval; | ||
| 923 | |||
| 924 | if (pstats->packet_toself || pstats->packet_beacon) { | ||
| 925 | rtlpriv->stats.rssi_calculate_cnt++; | ||
| 926 | if (rtlpriv->stats.ui_rssi.total_num++ >= | ||
| 927 | PHY_RSSI_SLID_WIN_MAX) { | ||
| 928 | rtlpriv->stats.ui_rssi.total_num = | ||
| 929 | PHY_RSSI_SLID_WIN_MAX; | ||
| 930 | last_rssi = | ||
| 931 | rtlpriv->stats.ui_rssi.elements[rtlpriv-> | ||
| 932 | stats.ui_rssi.index]; | ||
| 933 | rtlpriv->stats.ui_rssi.total_val -= last_rssi; | ||
| 934 | } | ||
| 935 | rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength; | ||
| 936 | rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi. | ||
| 937 | index++] = pstats->signalstrength; | ||
| 938 | if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX) | ||
| 939 | rtlpriv->stats.ui_rssi.index = 0; | ||
| 940 | tmpval = rtlpriv->stats.ui_rssi.total_val / | ||
| 941 | rtlpriv->stats.ui_rssi.total_num; | ||
| 942 | rtlpriv->stats.signal_strength = | ||
| 943 | _rtl92c_translate_todbm(hw, (u8) tmpval); | ||
| 944 | pstats->rssi = rtlpriv->stats.signal_strength; | ||
| 945 | } | ||
| 946 | if (!pstats->is_cck && pstats->packet_toself) { | ||
| 947 | for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; | ||
| 948 | rfpath++) { | ||
| 949 | if (!rtl8192_phy_check_is_legal_rfpath(hw, rfpath)) | ||
| 950 | continue; | ||
| 951 | if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) { | ||
| 952 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
| 953 | pstats->rx_mimo_signalstrength[rfpath]; | ||
| 954 | } | ||
| 955 | if (pstats->rx_mimo_signalstrength[rfpath] > | ||
| 956 | rtlpriv->stats.rx_rssi_percentage[rfpath]) { | ||
| 957 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
| 958 | ((rtlpriv->stats. | ||
| 959 | rx_rssi_percentage[rfpath] * | ||
| 960 | (RX_SMOOTH_FACTOR - 1)) + | ||
| 961 | (pstats->rx_mimo_signalstrength[rfpath])) / | ||
| 962 | (RX_SMOOTH_FACTOR); | ||
| 963 | |||
| 964 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
| 965 | rtlpriv->stats.rx_rssi_percentage[rfpath] + | ||
| 966 | 1; | ||
| 967 | } else { | ||
| 968 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
| 969 | ((rtlpriv->stats. | ||
| 970 | rx_rssi_percentage[rfpath] * | ||
| 971 | (RX_SMOOTH_FACTOR - 1)) + | ||
| 972 | (pstats->rx_mimo_signalstrength[rfpath])) / | ||
| 973 | (RX_SMOOTH_FACTOR); | ||
| 974 | } | ||
| 975 | } | ||
| 976 | } | ||
| 977 | } | ||
| 978 | |||
| 979 | static void _rtl92c_update_rxsignalstatistics(struct ieee80211_hw *hw, | ||
| 980 | struct rtl_stats *pstats) | ||
| 981 | { | ||
| 982 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
| 983 | int weighting = 0; | ||
| 984 | |||
| 985 | if (rtlpriv->stats.recv_signal_power == 0) | ||
| 986 | rtlpriv->stats.recv_signal_power = pstats->recvsignalpower; | ||
| 987 | if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power) | ||
| 988 | weighting = 5; | ||
| 989 | else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power) | ||
| 990 | weighting = (-5); | ||
| 991 | rtlpriv->stats.recv_signal_power = | ||
| 992 | (rtlpriv->stats.recv_signal_power * 5 + | ||
| 993 | pstats->recvsignalpower + weighting) / 6; | ||
| 994 | } | ||
| 995 | |||
| 996 | static void _rtl92c_process_pwdb(struct ieee80211_hw *hw, | ||
| 997 | struct rtl_stats *pstats) | ||
| 998 | { | ||
| 999 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
| 1000 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
| 1001 | long undec_sm_pwdb = 0; | ||
| 1002 | |||
| 1003 | if (mac->opmode == NL80211_IFTYPE_ADHOC) { | ||
| 1004 | return; | ||
| 1005 | } else { | ||
| 1006 | undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; | ||
| 1007 | } | ||
| 1008 | if (pstats->packet_toself || pstats->packet_beacon) { | ||
| 1009 | if (undec_sm_pwdb < 0) | ||
| 1010 | undec_sm_pwdb = pstats->rx_pwdb_all; | ||
| 1011 | if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) { | ||
| 1012 | undec_sm_pwdb = (((undec_sm_pwdb) * | ||
| 1013 | (RX_SMOOTH_FACTOR - 1)) + | ||
| 1014 | (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); | ||
| 1015 | undec_sm_pwdb += 1; | ||
| 1016 | } else { | ||
| 1017 | undec_sm_pwdb = (((undec_sm_pwdb) * | ||
| 1018 | (RX_SMOOTH_FACTOR - 1)) + | ||
| 1019 | (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); | ||
| 1020 | } | ||
| 1021 | rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb; | ||
| 1022 | _rtl92c_update_rxsignalstatistics(hw, pstats); | ||
| 1023 | } | ||
| 1024 | } | ||
| 1025 | |||
| 1026 | static void _rtl92c_process_LINK_Q(struct ieee80211_hw *hw, | ||
| 1027 | struct rtl_stats *pstats) | ||
| 1028 | { | ||
| 1029 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
| 1030 | u32 last_evm = 0, n_stream, tmpval; | ||
| 1031 | |||
| 1032 | if (pstats->signalquality != 0) { | ||
| 1033 | if (pstats->packet_toself || pstats->packet_beacon) { | ||
| 1034 | if (rtlpriv->stats.LINK_Q.total_num++ >= | ||
| 1035 | PHY_LINKQUALITY_SLID_WIN_MAX) { | ||
| 1036 | rtlpriv->stats.LINK_Q.total_num = | ||
| 1037 | PHY_LINKQUALITY_SLID_WIN_MAX; | ||
| 1038 | last_evm = | ||
| 1039 | rtlpriv->stats.LINK_Q.elements | ||
| 1040 | [rtlpriv->stats.LINK_Q.index]; | ||
| 1041 | rtlpriv->stats.LINK_Q.total_val -= | ||
| 1042 | last_evm; | ||
| 1043 | } | ||
| 1044 | rtlpriv->stats.LINK_Q.total_val += | ||
| 1045 | pstats->signalquality; | ||
| 1046 | rtlpriv->stats.LINK_Q.elements | ||
| 1047 | [rtlpriv->stats.LINK_Q.index++] = | ||
| 1048 | pstats->signalquality; | ||
| 1049 | if (rtlpriv->stats.LINK_Q.index >= | ||
| 1050 | PHY_LINKQUALITY_SLID_WIN_MAX) | ||
| 1051 | rtlpriv->stats.LINK_Q.index = 0; | ||
| 1052 | tmpval = rtlpriv->stats.LINK_Q.total_val / | ||
| 1053 | rtlpriv->stats.LINK_Q.total_num; | ||
| 1054 | rtlpriv->stats.signal_quality = tmpval; | ||
| 1055 | rtlpriv->stats.last_sigstrength_inpercent = tmpval; | ||
| 1056 | for (n_stream = 0; n_stream < 2; | ||
| 1057 | n_stream++) { | ||
| 1058 | if (pstats->RX_SIGQ[n_stream] != -1) { | ||
| 1059 | if (!rtlpriv->stats.RX_EVM[n_stream]) { | ||
| 1060 | rtlpriv->stats.RX_EVM[n_stream] | ||
| 1061 | = pstats->RX_SIGQ[n_stream]; | ||
| 1062 | } | ||
| 1063 | rtlpriv->stats.RX_EVM[n_stream] = | ||
| 1064 | ((rtlpriv->stats.RX_EVM | ||
| 1065 | [n_stream] * | ||
| 1066 | (RX_SMOOTH_FACTOR - 1)) + | ||
| 1067 | (pstats->RX_SIGQ | ||
| 1068 | [n_stream] * 1)) / | ||
| 1069 | (RX_SMOOTH_FACTOR); | ||
| 1070 | } | ||
| 1071 | } | ||
| 1072 | } | ||
| 1073 | } else { | ||
| 1074 | ; | ||
| 1075 | } | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | static void _rtl92c_process_phyinfo(struct ieee80211_hw *hw, | ||
| 1079 | u8 *buffer, | ||
| 1080 | struct rtl_stats *pcurrent_stats) | ||
| 1081 | { | ||
| 1082 | if (!pcurrent_stats->packet_matchbssid && | ||
| 1083 | !pcurrent_stats->packet_beacon) | ||
| 1084 | return; | ||
| 1085 | _rtl92c_process_ui_rssi(hw, pcurrent_stats); | ||
| 1086 | _rtl92c_process_pwdb(hw, pcurrent_stats); | ||
| 1087 | _rtl92c_process_LINK_Q(hw, pcurrent_stats); | ||
| 1088 | } | ||
| 1089 | |||
| 1090 | void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw, | 907 | void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw, |
| 1091 | struct sk_buff *skb, | 908 | struct sk_buff *skb, |
| 1092 | struct rtl_stats *pstats, | 909 | struct rtl_stats *pstats, |
| @@ -1123,5 +940,5 @@ void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw, | |||
| 1123 | _rtl92c_query_rxphystatus(hw, pstats, pdesc, p_drvinfo, | 940 | _rtl92c_query_rxphystatus(hw, pstats, pdesc, p_drvinfo, |
| 1124 | packet_matchbssid, packet_toself, | 941 | packet_matchbssid, packet_toself, |
| 1125 | packet_beacon); | 942 | packet_beacon); |
| 1126 | _rtl92c_process_phyinfo(hw, tmp_buf, pstats); | 943 | rtl_process_phyinfo(hw, tmp_buf, pstats); |
| 1127 | } | 944 | } |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h index 090fd33a158d..11b439d6b671 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h | |||
| @@ -34,15 +34,14 @@ | |||
| 34 | #define RF6052_MAX_REG 0x3F | 34 | #define RF6052_MAX_REG 0x3F |
| 35 | #define RF6052_MAX_PATH 2 | 35 | #define RF6052_MAX_PATH 2 |
| 36 | 36 | ||
| 37 | extern void rtl92cu_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, | 37 | void rtl92cu_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth); |
| 38 | u8 bandwidth); | 38 | void rtl92c_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, |
| 39 | extern void rtl92c_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, | 39 | u8 *ppowerlevel); |
| 40 | u8 *ppowerlevel); | 40 | void rtl92c_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, |
| 41 | extern void rtl92c_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, | 41 | u8 *ppowerlevel, u8 channel); |
| 42 | u8 *ppowerlevel, u8 channel); | ||
| 43 | bool rtl92cu_phy_rf6052_config(struct ieee80211_hw *hw); | 42 | bool rtl92cu_phy_rf6052_config(struct ieee80211_hw *hw); |
| 44 | bool rtl92cu_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, | 43 | bool rtl92cu_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, |
| 45 | enum radio_path rfpath); | 44 | enum radio_path rfpath); |
| 46 | void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, | 45 | void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, |
| 47 | u8 *ppowerlevel); | 46 | u8 *ppowerlevel); |
| 48 | void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, | 47 | void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 2bd598526217..9936de716ad5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include "../core.h" | 31 | #include "../core.h" |
| 32 | #include "../usb.h" | 32 | #include "../usb.h" |
| 33 | #include "../efuse.h" | 33 | #include "../efuse.h" |
| 34 | #include "../base.h" | ||
| 34 | #include "reg.h" | 35 | #include "reg.h" |
| 35 | #include "def.h" | 36 | #include "def.h" |
| 36 | #include "phy.h" | 37 | #include "phy.h" |
| @@ -117,7 +118,7 @@ static struct rtl_hal_ops rtl8192cu_hal_ops = { | |||
| 117 | .set_bw_mode = rtl92c_phy_set_bw_mode, | 118 | .set_bw_mode = rtl92c_phy_set_bw_mode, |
| 118 | .switch_channel = rtl92c_phy_sw_chnl, | 119 | .switch_channel = rtl92c_phy_sw_chnl, |
| 119 | .dm_watchdog = rtl92c_dm_watchdog, | 120 | .dm_watchdog = rtl92c_dm_watchdog, |
| 120 | .scan_operation_backup = rtl92c_phy_scan_operation_backup, | 121 | .scan_operation_backup = rtl_phy_scan_operation_backup, |
| 121 | .set_rf_power_state = rtl92cu_phy_set_rf_power_state, | 122 | .set_rf_power_state = rtl92cu_phy_set_rf_power_state, |
| 122 | .led_control = rtl92cu_led_control, | 123 | .led_control = rtl92cu_led_control, |
| 123 | .enable_hw_sec = rtl92cu_enable_hw_security_config, | 124 | .enable_hw_sec = rtl92cu_enable_hw_security_config, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index 5a060e537fbe..25e50ffc44ec 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c | |||
| @@ -350,7 +350,6 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, | |||
| 350 | } | 350 | } |
| 351 | /*rx_status->qual = stats->signal; */ | 351 | /*rx_status->qual = stats->signal; */ |
| 352 | rx_status->signal = stats->rssi + 10; | 352 | rx_status->signal = stats->rssi + 10; |
| 353 | /*rx_status->noise = -stats->noise; */ | ||
| 354 | return true; | 353 | return true; |
| 355 | } | 354 | } |
| 356 | 355 | ||
| @@ -365,7 +364,6 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
| 365 | u8 *rxdesc; | 364 | u8 *rxdesc; |
| 366 | struct rtl_stats stats = { | 365 | struct rtl_stats stats = { |
| 367 | .signal = 0, | 366 | .signal = 0, |
| 368 | .noise = -98, | ||
| 369 | .rate = 0, | 367 | .rate = 0, |
| 370 | }; | 368 | }; |
| 371 | struct rx_fwinfo_92c *p_drvinfo; | 369 | struct rx_fwinfo_92c *p_drvinfo; |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c index f700f7a614b2..7908e1c85819 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c | |||
| @@ -840,9 +840,9 @@ static void rtl92d_dm_txpower_tracking_callback_thermalmeter( | |||
| 840 | bool internal_pa = false; | 840 | bool internal_pa = false; |
| 841 | long ele_a = 0, ele_d, temp_cck, val_x, value32; | 841 | long ele_a = 0, ele_d, temp_cck, val_x, value32; |
| 842 | long val_y, ele_c = 0; | 842 | long val_y, ele_c = 0; |
| 843 | u8 ofdm_index[2]; | 843 | u8 ofdm_index[3]; |
| 844 | s8 cck_index = 0; | 844 | s8 cck_index = 0; |
| 845 | u8 ofdm_index_old[2] = {0, 0}; | 845 | u8 ofdm_index_old[3] = {0, 0, 0}; |
| 846 | s8 cck_index_old = 0; | 846 | s8 cck_index_old = 0; |
| 847 | u8 index; | 847 | u8 index; |
| 848 | int i; | 848 | int i; |
| @@ -1118,6 +1118,10 @@ static void rtl92d_dm_txpower_tracking_callback_thermalmeter( | |||
| 1118 | val_x, val_y, ele_a, ele_c, ele_d, | 1118 | val_x, val_y, ele_a, ele_c, ele_d, |
| 1119 | val_x, val_y); | 1119 | val_x, val_y); |
| 1120 | 1120 | ||
| 1121 | if (cck_index >= CCK_TABLE_SIZE) | ||
| 1122 | cck_index = CCK_TABLE_SIZE - 1; | ||
| 1123 | if (cck_index < 0) | ||
| 1124 | cck_index = 0; | ||
| 1121 | if (rtlhal->current_bandtype == BAND_ON_2_4G) { | 1125 | if (rtlhal->current_bandtype == BAND_ON_2_4G) { |
| 1122 | /* Adjust CCK according to IQK result */ | 1126 | /* Adjust CCK according to IQK result */ |
| 1123 | if (!rtlpriv->dm.cck_inch14) { | 1127 | if (!rtlpriv->dm.cck_inch14) { |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c index 7dd8f6de0550..c4a7db9135d6 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c | |||
| @@ -1194,25 +1194,7 @@ void rtl92d_linked_set_reg(struct ieee80211_hw *hw) | |||
| 1194 | * mac80211 will send pkt when scan */ | 1194 | * mac80211 will send pkt when scan */ |
| 1195 | void rtl92de_set_qos(struct ieee80211_hw *hw, int aci) | 1195 | void rtl92de_set_qos(struct ieee80211_hw *hw, int aci) |
| 1196 | { | 1196 | { |
| 1197 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
| 1198 | rtl92d_dm_init_edca_turbo(hw); | 1197 | rtl92d_dm_init_edca_turbo(hw); |
| 1199 | return; | ||
| 1200 | switch (aci) { | ||
| 1201 | case AC1_BK: | ||
| 1202 | rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f); | ||
| 1203 | break; | ||
| 1204 | case AC0_BE: | ||
| 1205 | break; | ||
| 1206 | case AC2_VI: | ||
| 1207 | rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322); | ||
| 1208 | break; | ||
| 1209 | case AC3_VO: | ||
| 1210 | rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222); | ||
| 1211 | break; | ||
| 1212 | default: | ||
| 1213 | RT_ASSERT(false, "invalid aci: %d !\n", aci); | ||
| 1214 | break; | ||
| 1215 | } | ||
| 1216 | } | 1198 | } |
| 1217 | 1199 | ||
| 1218 | void rtl92de_enable_interrupt(struct ieee80211_hw *hw) | 1200 | void rtl92de_enable_interrupt(struct ieee80211_hw *hw) |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.h b/drivers/net/wireless/rtlwifi/rtl8192de/hw.h index 7c9f7a2f1e42..1bc7b1a96d4a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/hw.h +++ b/drivers/net/wireless/rtlwifi/rtl8192de/hw.h | |||
| @@ -55,10 +55,9 @@ void rtl92de_set_key(struct ieee80211_hw *hw, u32 key_index, | |||
| 55 | u8 *p_macaddr, bool is_group, u8 enc_algo, | 55 | u8 *p_macaddr, bool is_group, u8 enc_algo, |
| 56 | bool is_wepkey, bool clear_all); | 56 | bool is_wepkey, bool clear_all); |
| 57 | 57 | ||
| 58 | extern void rtl92de_write_dword_dbi(struct ieee80211_hw *hw, u16 offset, | 58 | void rtl92de_write_dword_dbi(struct ieee80211_hw *hw, u16 offset, u32 value, |
| 59 | u32 value, u8 direct); | 59 | u8 direct); |
| 60 | extern u32 rtl92de_read_dword_dbi(struct ieee80211_hw *hw, u16 offset, | 60 | u32 rtl92de_read_dword_dbi(struct ieee80211_hw *hw, u16 offset, u8 direct); |
| 61 | u8 direct); | ||
| 62 | void rtl92de_suspend(struct ieee80211_hw *hw); | 61 | void rtl92de_suspend(struct ieee80211_hw *hw); |
| 63 | void rtl92de_resume(struct ieee80211_hw *hw); | 62 | void rtl92de_resume(struct ieee80211_hw *hw); |
| 64 | void rtl92d_linked_set_reg(struct ieee80211_hw *hw); | 63 | void rtl92d_linked_set_reg(struct ieee80211_hw *hw); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c index 840bac5fa2f8..13196cc4b1d3 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c | |||
| @@ -1022,34 +1022,6 @@ void rtl92d_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) | |||
| 1022 | rtl92d_phy_rf6052_set_ofdm_txpower(hw, &ofdmpowerlevel[0], channel); | 1022 | rtl92d_phy_rf6052_set_ofdm_txpower(hw, &ofdmpowerlevel[0], channel); |
| 1023 | } | 1023 | } |
| 1024 | 1024 | ||
| 1025 | void rtl92d_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) | ||
| 1026 | { | ||
| 1027 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
| 1028 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
| 1029 | enum io_type iotype; | ||
| 1030 | |||
| 1031 | if (!is_hal_stop(rtlhal)) { | ||
| 1032 | switch (operation) { | ||
| 1033 | case SCAN_OPT_BACKUP: | ||
| 1034 | rtlhal->current_bandtypebackup = | ||
| 1035 | rtlhal->current_bandtype; | ||
| 1036 | iotype = IO_CMD_PAUSE_DM_BY_SCAN; | ||
| 1037 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD, | ||
| 1038 | (u8 *)&iotype); | ||
| 1039 | break; | ||
| 1040 | case SCAN_OPT_RESTORE: | ||
| 1041 | iotype = IO_CMD_RESUME_DM_BY_SCAN; | ||
| 1042 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD, | ||
| 1043 | (u8 *)&iotype); | ||
| 1044 | break; | ||
| 1045 | default: | ||
| 1046 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
| 1047 | "Unknown Scan Backup operation\n"); | ||
| 1048 | break; | ||
| 1049 | } | ||
| 1050 | } | ||
| 1051 | } | ||
| 1052 | |||
| 1053 | void rtl92d_phy_set_bw_mode(struct ieee80211_hw *hw, | 1025 | void rtl92d_phy_set_bw_mode(struct ieee80211_hw *hw, |
| 1054 | enum nl80211_channel_type ch_type) | 1026 | enum nl80211_channel_type ch_type) |
| 1055 | { | 1027 | { |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.h b/drivers/net/wireless/rtlwifi/rtl8192de/phy.h index f074952bf25c..48d5c6835b6a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/phy.h +++ b/drivers/net/wireless/rtlwifi/rtl8192de/phy.h | |||
| @@ -39,9 +39,7 @@ | |||
| 39 | #define RT_CANNOT_IO(hw) false | 39 | #define RT_CANNOT_IO(hw) false |
| 40 | #define HIGHPOWER_RADIOA_ARRAYLEN 22 | 40 | #define HIGHPOWER_RADIOA_ARRAYLEN 22 |
| 41 | 41 | ||
| 42 | #define IQK_ADDA_REG_NUM 16 | ||
| 43 | #define MAX_TOLERANCE 5 | 42 | #define MAX_TOLERANCE 5 |
| 44 | #define IQK_DELAY_TIME 1 | ||
| 45 | 43 | ||
| 46 | #define APK_BB_REG_NUM 5 | 44 | #define APK_BB_REG_NUM 5 |
| 47 | #define APK_AFE_REG_NUM 16 | 45 | #define APK_AFE_REG_NUM 16 |
| @@ -127,34 +125,32 @@ static inline void rtl92d_release_cckandrw_pagea_ctl(struct ieee80211_hw *hw, | |||
| 127 | *flag); | 125 | *flag); |
| 128 | } | 126 | } |
| 129 | 127 | ||
| 130 | extern u32 rtl92d_phy_query_bb_reg(struct ieee80211_hw *hw, | 128 | u32 rtl92d_phy_query_bb_reg(struct ieee80211_hw *hw, |
| 131 | u32 regaddr, u32 bitmask); | 129 | u32 regaddr, u32 bitmask); |
| 132 | extern void rtl92d_phy_set_bb_reg(struct ieee80211_hw *hw, | 130 | void rtl92d_phy_set_bb_reg(struct ieee80211_hw *hw, |
| 133 | u32 regaddr, u32 bitmask, u32 data); | 131 | u32 regaddr, u32 bitmask, u32 data); |
| 134 | extern u32 rtl92d_phy_query_rf_reg(struct ieee80211_hw *hw, | 132 | u32 rtl92d_phy_query_rf_reg(struct ieee80211_hw *hw, |
| 135 | enum radio_path rfpath, u32 regaddr, | 133 | enum radio_path rfpath, u32 regaddr, |
| 136 | u32 bitmask); | 134 | u32 bitmask); |
| 137 | extern void rtl92d_phy_set_rf_reg(struct ieee80211_hw *hw, | 135 | void rtl92d_phy_set_rf_reg(struct ieee80211_hw *hw, |
| 138 | enum radio_path rfpath, u32 regaddr, | 136 | enum radio_path rfpath, u32 regaddr, |
| 139 | u32 bitmask, u32 data); | 137 | u32 bitmask, u32 data); |
| 140 | extern bool rtl92d_phy_mac_config(struct ieee80211_hw *hw); | 138 | bool rtl92d_phy_mac_config(struct ieee80211_hw *hw); |
| 141 | extern bool rtl92d_phy_bb_config(struct ieee80211_hw *hw); | 139 | bool rtl92d_phy_bb_config(struct ieee80211_hw *hw); |
| 142 | extern bool rtl92d_phy_rf_config(struct ieee80211_hw *hw); | 140 | bool rtl92d_phy_rf_config(struct ieee80211_hw *hw); |
| 143 | extern bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, | 141 | bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, |
| 144 | enum radio_path rfpath); | 142 | enum radio_path rfpath); |
| 145 | extern void rtl92d_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); | 143 | void rtl92d_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); |
| 146 | extern void rtl92d_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); | 144 | void rtl92d_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); |
| 147 | extern void rtl92d_phy_scan_operation_backup(struct ieee80211_hw *hw, | 145 | void rtl92d_phy_set_bw_mode(struct ieee80211_hw *hw, |
| 148 | u8 operation); | 146 | enum nl80211_channel_type ch_type); |
| 149 | extern void rtl92d_phy_set_bw_mode(struct ieee80211_hw *hw, | 147 | u8 rtl92d_phy_sw_chnl(struct ieee80211_hw *hw); |
| 150 | enum nl80211_channel_type ch_type); | ||
| 151 | extern u8 rtl92d_phy_sw_chnl(struct ieee80211_hw *hw); | ||
| 152 | bool rtl92d_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, | 148 | bool rtl92d_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, |
| 153 | enum rf_content content, | 149 | enum rf_content content, |
| 154 | enum radio_path rfpath); | 150 | enum radio_path rfpath); |
| 155 | bool rtl92d_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); | 151 | bool rtl92d_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); |
| 156 | extern bool rtl92d_phy_set_rf_power_state(struct ieee80211_hw *hw, | 152 | bool rtl92d_phy_set_rf_power_state(struct ieee80211_hw *hw, |
| 157 | enum rf_pwrstate rfpwr_state); | 153 | enum rf_pwrstate rfpwr_state); |
| 158 | 154 | ||
| 159 | void rtl92d_phy_config_macphymode(struct ieee80211_hw *hw); | 155 | void rtl92d_phy_config_macphymode(struct ieee80211_hw *hw); |
| 160 | void rtl92d_phy_config_macphymode_info(struct ieee80211_hw *hw); | 156 | void rtl92d_phy_config_macphymode_info(struct ieee80211_hw *hw); |
| @@ -173,6 +169,5 @@ void rtl92d_acquire_cckandrw_pagea_ctl(struct ieee80211_hw *hw, | |||
| 173 | unsigned long *flag); | 169 | unsigned long *flag); |
| 174 | u8 rtl92d_get_rightchnlplace_for_iqk(u8 chnl); | 170 | u8 rtl92d_get_rightchnlplace_for_iqk(u8 chnl); |
| 175 | void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel); | 171 | void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel); |
| 176 | void rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw); | ||
| 177 | 172 | ||
| 178 | #endif | 173 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/rf.h b/drivers/net/wireless/rtlwifi/rtl8192de/rf.h index 0fe1a48593e8..7303d12c266f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/rf.h +++ b/drivers/net/wireless/rtlwifi/rtl8192de/rf.h | |||
| @@ -30,15 +30,13 @@ | |||
| 30 | #ifndef __RTL92D_RF_H__ | 30 | #ifndef __RTL92D_RF_H__ |
| 31 | #define __RTL92D_RF_H__ | 31 | #define __RTL92D_RF_H__ |
| 32 | 32 | ||
| 33 | extern void rtl92d_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, | 33 | void rtl92d_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth); |
| 34 | u8 bandwidth); | 34 | void rtl92d_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, |
| 35 | extern void rtl92d_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, | 35 | u8 *ppowerlevel); |
| 36 | u8 *ppowerlevel); | 36 | void rtl92d_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, |
| 37 | extern void rtl92d_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, | 37 | u8 *ppowerlevel, u8 channel); |
| 38 | u8 *ppowerlevel, u8 channel); | 38 | bool rtl92d_phy_rf6052_config(struct ieee80211_hw *hw); |
| 39 | extern bool rtl92d_phy_rf6052_config(struct ieee80211_hw *hw); | 39 | bool rtl92d_phy_enable_anotherphy(struct ieee80211_hw *hw, bool bmac0); |
| 40 | extern bool rtl92d_phy_enable_anotherphy(struct ieee80211_hw *hw, bool bmac0); | 40 | void rtl92d_phy_powerdown_anotherphy(struct ieee80211_hw *hw, bool bmac0); |
| 41 | extern void rtl92d_phy_powerdown_anotherphy(struct ieee80211_hw *hw, | ||
| 42 | bool bmac0); | ||
| 43 | 41 | ||
| 44 | #endif | 42 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c index c18c04bf0c13..edab5a5351b5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include "../wifi.h" | 30 | #include "../wifi.h" |
| 31 | #include "../core.h" | 31 | #include "../core.h" |
| 32 | #include "../pci.h" | 32 | #include "../pci.h" |
| 33 | #include "../base.h" | ||
| 33 | #include "reg.h" | 34 | #include "reg.h" |
| 34 | #include "def.h" | 35 | #include "def.h" |
| 35 | #include "phy.h" | 36 | #include "phy.h" |
| @@ -236,7 +237,7 @@ static struct rtl_hal_ops rtl8192de_hal_ops = { | |||
| 236 | .set_bw_mode = rtl92d_phy_set_bw_mode, | 237 | .set_bw_mode = rtl92d_phy_set_bw_mode, |
| 237 | .switch_channel = rtl92d_phy_sw_chnl, | 238 | .switch_channel = rtl92d_phy_sw_chnl, |
| 238 | .dm_watchdog = rtl92d_dm_watchdog, | 239 | .dm_watchdog = rtl92d_dm_watchdog, |
| 239 | .scan_operation_backup = rtl92d_phy_scan_operation_backup, | 240 | .scan_operation_backup = rtl_phy_scan_operation_backup, |
| 240 | .set_rf_power_state = rtl92d_phy_set_rf_power_state, | 241 | .set_rf_power_state = rtl92d_phy_set_rf_power_state, |
| 241 | .led_control = rtl92de_led_control, | 242 | .led_control = rtl92de_led_control, |
| 242 | .set_desc = rtl92de_set_desc, | 243 | .set_desc = rtl92de_set_desc, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c index b8ec718a0fab..945ddecf90c9 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c | |||
| @@ -526,7 +526,6 @@ bool rtl92de_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, | |||
| 526 | } | 526 | } |
| 527 | /*rx_status->qual = stats->signal; */ | 527 | /*rx_status->qual = stats->signal; */ |
| 528 | rx_status->signal = stats->rssi + 10; | 528 | rx_status->signal = stats->rssi + 10; |
| 529 | /*rx_status->noise = -stats->noise; */ | ||
| 530 | return true; | 529 | return true; |
| 531 | } | 530 | } |
| 532 | 531 | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/reg.h b/drivers/net/wireless/rtlwifi/rtl8192se/reg.h index 84d1181795b8..c81c83591940 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/reg.h +++ b/drivers/net/wireless/rtlwifi/rtl8192se/reg.h | |||
| @@ -425,14 +425,9 @@ | |||
| 425 | #define EXT_IMEM_CODE_DONE BIT(2) | 425 | #define EXT_IMEM_CODE_DONE BIT(2) |
| 426 | #define IMEM_CHK_RPT BIT(1) | 426 | #define IMEM_CHK_RPT BIT(1) |
| 427 | #define IMEM_CODE_DONE BIT(0) | 427 | #define IMEM_CODE_DONE BIT(0) |
| 428 | #define IMEM_CODE_DONE BIT(0) | ||
| 429 | #define IMEM_CHK_RPT BIT(1) | ||
| 430 | #define EMEM_CODE_DONE BIT(2) | 428 | #define EMEM_CODE_DONE BIT(2) |
| 431 | #define EMEM_CHK_RPT BIT(3) | 429 | #define EMEM_CHK_RPT BIT(3) |
| 432 | #define DMEM_CODE_DONE BIT(4) | ||
| 433 | #define IMEM_RDY BIT(5) | 430 | #define IMEM_RDY BIT(5) |
| 434 | #define BASECHG BIT(6) | ||
| 435 | #define FWRDY BIT(7) | ||
| 436 | #define LOAD_FW_READY (IMEM_CODE_DONE | \ | 431 | #define LOAD_FW_READY (IMEM_CODE_DONE | \ |
| 437 | IMEM_CHK_RPT | \ | 432 | IMEM_CHK_RPT | \ |
| 438 | EMEM_CODE_DONE | \ | 433 | EMEM_CODE_DONE | \ |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c index c7095118de6e..222d2e792ca6 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c | |||
| @@ -330,7 +330,6 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, | |||
| 330 | 330 | ||
| 331 | /*rx_status->qual = stats->signal; */ | 331 | /*rx_status->qual = stats->signal; */ |
| 332 | rx_status->signal = stats->rssi + 10; | 332 | rx_status->signal = stats->rssi + 10; |
| 333 | /*rx_status->noise = -stats->noise; */ | ||
| 334 | 333 | ||
| 335 | return true; | 334 | return true; |
| 336 | } | 335 | } |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c b/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c index eafbb18dd48e..5d318a85eda4 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c | |||
| @@ -934,35 +934,6 @@ static long _phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw, | |||
| 934 | return pwrout_dbm; | 934 | return pwrout_dbm; |
| 935 | } | 935 | } |
| 936 | 936 | ||
| 937 | void rtl8723ae_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) | ||
| 938 | { | ||
| 939 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
| 940 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
| 941 | enum io_type iotype; | ||
| 942 | |||
| 943 | if (!is_hal_stop(rtlhal)) { | ||
| 944 | switch (operation) { | ||
| 945 | case SCAN_OPT_BACKUP: | ||
| 946 | iotype = IO_CMD_PAUSE_DM_BY_SCAN; | ||
| 947 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
| 948 | HW_VAR_IO_CMD, | ||
| 949 | (u8 *)&iotype); | ||
| 950 | |||
| 951 | break; | ||
| 952 | case SCAN_OPT_RESTORE: | ||
| 953 | iotype = IO_CMD_RESUME_DM_BY_SCAN; | ||
| 954 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
| 955 | HW_VAR_IO_CMD, | ||
| 956 | (u8 *)&iotype); | ||
| 957 | break; | ||
| 958 | default: | ||
| 959 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
| 960 | "Unknown Scan Backup operation.\n"); | ||
| 961 | break; | ||
| 962 | } | ||
| 963 | } | ||
| 964 | } | ||
| 965 | |||
| 966 | void rtl8723ae_phy_set_bw_mode_callback(struct ieee80211_hw *hw) | 937 | void rtl8723ae_phy_set_bw_mode_callback(struct ieee80211_hw *hw) |
| 967 | { | 938 | { |
| 968 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 939 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.h b/drivers/net/wireless/rtlwifi/rtl8723ae/phy.h index e7a59eba351a..007ebdbbe108 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.h +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/phy.h | |||
| @@ -183,42 +183,40 @@ struct tx_power_struct { | |||
| 183 | u32 mcs_original_offset[4][16]; | 183 | u32 mcs_original_offset[4][16]; |
| 184 | }; | 184 | }; |
| 185 | 185 | ||
| 186 | extern u32 rtl8723ae_phy_query_bb_reg(struct ieee80211_hw *hw, | 186 | u32 rtl8723ae_phy_query_bb_reg(struct ieee80211_hw *hw, |
| 187 | u32 regaddr, u32 bitmask); | 187 | u32 regaddr, u32 bitmask); |
| 188 | extern void rtl8723ae_phy_set_bb_reg(struct ieee80211_hw *hw, | 188 | void rtl8723ae_phy_set_bb_reg(struct ieee80211_hw *hw, |
| 189 | u32 regaddr, u32 bitmask, u32 data); | 189 | u32 regaddr, u32 bitmask, u32 data); |
| 190 | extern u32 rtl8723ae_phy_query_rf_reg(struct ieee80211_hw *hw, | 190 | u32 rtl8723ae_phy_query_rf_reg(struct ieee80211_hw *hw, |
| 191 | enum radio_path rfpath, u32 regaddr, | 191 | enum radio_path rfpath, u32 regaddr, |
| 192 | u32 bitmask); | 192 | u32 bitmask); |
| 193 | extern void rtl8723ae_phy_set_rf_reg(struct ieee80211_hw *hw, | 193 | void rtl8723ae_phy_set_rf_reg(struct ieee80211_hw *hw, |
| 194 | enum radio_path rfpath, u32 regaddr, | 194 | enum radio_path rfpath, u32 regaddr, |
| 195 | u32 bitmask, u32 data); | 195 | u32 bitmask, u32 data); |
| 196 | extern bool rtl8723ae_phy_mac_config(struct ieee80211_hw *hw); | 196 | bool rtl8723ae_phy_mac_config(struct ieee80211_hw *hw); |
| 197 | extern bool rtl8723ae_phy_bb_config(struct ieee80211_hw *hw); | 197 | bool rtl8723ae_phy_bb_config(struct ieee80211_hw *hw); |
| 198 | extern bool rtl8723ae_phy_rf_config(struct ieee80211_hw *hw); | 198 | bool rtl8723ae_phy_rf_config(struct ieee80211_hw *hw); |
| 199 | extern bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, | 199 | bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, |
| 200 | enum radio_path rfpath); | 200 | enum radio_path rfpath); |
| 201 | extern void rtl8723ae_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); | 201 | void rtl8723ae_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); |
| 202 | extern void rtl8723ae_phy_get_txpower_level(struct ieee80211_hw *hw, | 202 | void rtl8723ae_phy_get_txpower_level(struct ieee80211_hw *hw, |
| 203 | long *powerlevel); | 203 | long *powerlevel); |
| 204 | extern void rtl8723ae_phy_set_txpower_level(struct ieee80211_hw *hw, | 204 | void rtl8723ae_phy_set_txpower_level(struct ieee80211_hw *hw, |
| 205 | u8 channel); | 205 | u8 channel); |
| 206 | extern bool rtl8723ae_phy_update_txpower_dbm(struct ieee80211_hw *hw, | 206 | bool rtl8723ae_phy_update_txpower_dbm(struct ieee80211_hw *hw, |
| 207 | long power_indbm); | 207 | long power_indbm); |
| 208 | extern void rtl8723ae_phy_scan_operation_backup(struct ieee80211_hw *hw, | 208 | void rtl8723ae_phy_set_bw_mode_callback(struct ieee80211_hw *hw); |
| 209 | u8 operation); | 209 | void rtl8723ae_phy_set_bw_mode(struct ieee80211_hw *hw, |
| 210 | extern void rtl8723ae_phy_set_bw_mode_callback(struct ieee80211_hw *hw); | 210 | enum nl80211_channel_type ch_type); |
| 211 | extern void rtl8723ae_phy_set_bw_mode(struct ieee80211_hw *hw, | 211 | void rtl8723ae_phy_sw_chnl_callback(struct ieee80211_hw *hw); |
| 212 | enum nl80211_channel_type ch_type); | 212 | u8 rtl8723ae_phy_sw_chnl(struct ieee80211_hw *hw); |
| 213 | extern void rtl8723ae_phy_sw_chnl_callback(struct ieee80211_hw *hw); | 213 | void rtl8723ae_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery); |
| 214 | extern u8 rtl8723ae_phy_sw_chnl(struct ieee80211_hw *hw); | ||
| 215 | extern void rtl8723ae_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery); | ||
| 216 | void rtl8723ae_phy_lc_calibrate(struct ieee80211_hw *hw); | 214 | void rtl8723ae_phy_lc_calibrate(struct ieee80211_hw *hw); |
| 217 | void rtl8723ae_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); | 215 | void rtl8723ae_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); |
| 218 | bool rtl8723ae_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, | 216 | bool rtl8723ae_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, |
| 219 | enum radio_path rfpath); | 217 | enum radio_path rfpath); |
| 220 | bool rtl8723ae_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); | 218 | bool rtl8723ae_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); |
| 221 | extern bool rtl8723ae_phy_set_rf_power_state(struct ieee80211_hw *hw, | 219 | bool rtl8723ae_phy_set_rf_power_state(struct ieee80211_hw *hw, |
| 222 | enum rf_pwrstate rfpwr_state); | 220 | enum rf_pwrstate rfpwr_state); |
| 223 | 221 | ||
| 224 | #endif | 222 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/rf.h b/drivers/net/wireless/rtlwifi/rtl8723ae/rf.h index d0f9dd79abea..57f1933ee663 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/rf.h +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/rf.h | |||
| @@ -32,12 +32,11 @@ | |||
| 32 | 32 | ||
| 33 | #define RF6052_MAX_TX_PWR 0x3F | 33 | #define RF6052_MAX_TX_PWR 0x3F |
| 34 | 34 | ||
| 35 | extern void rtl8723ae_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, | 35 | void rtl8723ae_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth); |
| 36 | u8 bandwidth); | 36 | void rtl8723ae_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, |
| 37 | extern void rtl8723ae_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, | 37 | u8 *ppowerlevel); |
| 38 | u8 *ppowerlevel); | 38 | void rtl8723ae_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, |
| 39 | extern void rtl8723ae_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, | 39 | u8 *ppowerlevel, u8 channel); |
| 40 | u8 *ppowerlevel, u8 channel); | 40 | bool rtl8723ae_phy_rf6052_config(struct ieee80211_hw *hw); |
| 41 | extern bool rtl8723ae_phy_rf6052_config(struct ieee80211_hw *hw); | ||
| 42 | 41 | ||
| 43 | #endif | 42 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c index d9ee2efffe5f..62b204faf773 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | 33 | ||
| 34 | #include "../core.h" | 34 | #include "../core.h" |
| 35 | #include "../pci.h" | 35 | #include "../pci.h" |
| 36 | #include "../base.h" | ||
| 36 | #include "reg.h" | 37 | #include "reg.h" |
| 37 | #include "def.h" | 38 | #include "def.h" |
| 38 | #include "phy.h" | 39 | #include "phy.h" |
| @@ -220,7 +221,7 @@ static struct rtl_hal_ops rtl8723ae_hal_ops = { | |||
| 220 | .set_bw_mode = rtl8723ae_phy_set_bw_mode, | 221 | .set_bw_mode = rtl8723ae_phy_set_bw_mode, |
| 221 | .switch_channel = rtl8723ae_phy_sw_chnl, | 222 | .switch_channel = rtl8723ae_phy_sw_chnl, |
| 222 | .dm_watchdog = rtl8723ae_dm_watchdog, | 223 | .dm_watchdog = rtl8723ae_dm_watchdog, |
| 223 | .scan_operation_backup = rtl8723ae_phy_scan_operation_backup, | 224 | .scan_operation_backup = rtl_phy_scan_operation_backup, |
| 224 | .set_rf_power_state = rtl8723ae_phy_set_rf_power_state, | 225 | .set_rf_power_state = rtl8723ae_phy_set_rf_power_state, |
| 225 | .led_control = rtl8723ae_led_control, | 226 | .led_control = rtl8723ae_led_control, |
| 226 | .set_desc = rtl8723ae_set_desc, | 227 | .set_desc = rtl8723ae_set_desc, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c index bcd82a1020a5..50b7be3f3a60 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c | |||
| @@ -359,7 +359,6 @@ bool rtl8723ae_rx_query_desc(struct ieee80211_hw *hw, | |||
| 359 | 359 | ||
| 360 | /*rx_status->qual = status->signal; */ | 360 | /*rx_status->qual = status->signal; */ |
| 361 | rx_status->signal = status->recvsignalpower + 10; | 361 | rx_status->signal = status->recvsignalpower + 10; |
| 362 | /*rx_status->noise = -status->noise; */ | ||
| 363 | 362 | ||
| 364 | return true; | 363 | return true; |
| 365 | } | 364 | } |
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index e56778cac9bf..6e2b5c5c83c8 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c | |||
| @@ -455,7 +455,6 @@ static void _rtl_usb_rx_process_agg(struct ieee80211_hw *hw, | |||
| 455 | struct ieee80211_rx_status rx_status = {0}; | 455 | struct ieee80211_rx_status rx_status = {0}; |
| 456 | struct rtl_stats stats = { | 456 | struct rtl_stats stats = { |
| 457 | .signal = 0, | 457 | .signal = 0, |
| 458 | .noise = -98, | ||
| 459 | .rate = 0, | 458 | .rate = 0, |
| 460 | }; | 459 | }; |
| 461 | 460 | ||
| @@ -498,7 +497,6 @@ static void _rtl_usb_rx_process_noagg(struct ieee80211_hw *hw, | |||
| 498 | struct ieee80211_rx_status rx_status = {0}; | 497 | struct ieee80211_rx_status rx_status = {0}; |
| 499 | struct rtl_stats stats = { | 498 | struct rtl_stats stats = { |
| 500 | .signal = 0, | 499 | .signal = 0, |
| 501 | .noise = -98, | ||
| 502 | .rate = 0, | 500 | .rate = 0, |
| 503 | }; | 501 | }; |
| 504 | 502 | ||
| @@ -582,12 +580,15 @@ static void _rtl_rx_work(unsigned long param) | |||
| 582 | static unsigned int _rtl_rx_get_padding(struct ieee80211_hdr *hdr, | 580 | static unsigned int _rtl_rx_get_padding(struct ieee80211_hdr *hdr, |
| 583 | unsigned int len) | 581 | unsigned int len) |
| 584 | { | 582 | { |
| 583 | #if NET_IP_ALIGN != 0 | ||
| 585 | unsigned int padding = 0; | 584 | unsigned int padding = 0; |
| 585 | #endif | ||
| 586 | 586 | ||
| 587 | /* make function no-op when possible */ | 587 | /* make function no-op when possible */ |
| 588 | if (NET_IP_ALIGN == 0 || len < sizeof(*hdr)) | 588 | if (NET_IP_ALIGN == 0 || len < sizeof(*hdr)) |
| 589 | return 0; | 589 | return 0; |
| 590 | 590 | ||
| 591 | #if NET_IP_ALIGN != 0 | ||
| 591 | /* alignment calculation as in lbtf_rx() / carl9170_rx_copy_data() */ | 592 | /* alignment calculation as in lbtf_rx() / carl9170_rx_copy_data() */ |
| 592 | /* TODO: deduplicate common code, define helper function instead? */ | 593 | /* TODO: deduplicate common code, define helper function instead? */ |
| 593 | 594 | ||
| @@ -608,6 +609,7 @@ static unsigned int _rtl_rx_get_padding(struct ieee80211_hdr *hdr, | |||
| 608 | padding ^= NET_IP_ALIGN; | 609 | padding ^= NET_IP_ALIGN; |
| 609 | 610 | ||
| 610 | return padding; | 611 | return padding; |
| 612 | #endif | ||
| 611 | } | 613 | } |
| 612 | 614 | ||
| 613 | #define __RADIO_TAP_SIZE_RSV 32 | 615 | #define __RADIO_TAP_SIZE_RSV 32 |
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 703258742d28..d224dc3bb092 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h | |||
| @@ -192,8 +192,6 @@ enum hardware_type { | |||
| 192 | (IS_HARDWARE_TYPE_8192DE(rtlhal) || IS_HARDWARE_TYPE_8192DU(rtlhal)) | 192 | (IS_HARDWARE_TYPE_8192DE(rtlhal) || IS_HARDWARE_TYPE_8192DU(rtlhal)) |
| 193 | #define IS_HARDWARE_TYPE_8723(rtlhal) \ | 193 | #define IS_HARDWARE_TYPE_8723(rtlhal) \ |
| 194 | (IS_HARDWARE_TYPE_8723E(rtlhal) || IS_HARDWARE_TYPE_8723U(rtlhal)) | 194 | (IS_HARDWARE_TYPE_8723E(rtlhal) || IS_HARDWARE_TYPE_8723U(rtlhal)) |
| 195 | #define IS_HARDWARE_TYPE_8723U(rtlhal) \ | ||
| 196 | (rtlhal->hw_type == HARDWARE_TYPE_RTL8723U) | ||
| 197 | 195 | ||
| 198 | #define RX_HAL_IS_CCK_RATE(_pdesc)\ | 196 | #define RX_HAL_IS_CCK_RATE(_pdesc)\ |
| 199 | (_pdesc->rxmcs == DESC92_RATE1M || \ | 197 | (_pdesc->rxmcs == DESC92_RATE1M || \ |
diff --git a/drivers/net/wireless/ti/wl1251/spi.c b/drivers/net/wireless/ti/wl1251/spi.c index c7dc6feab2ff..1342f81e683d 100644 --- a/drivers/net/wireless/ti/wl1251/spi.c +++ b/drivers/net/wireless/ti/wl1251/spi.c | |||
| @@ -243,7 +243,7 @@ static int wl1251_spi_probe(struct spi_device *spi) | |||
| 243 | struct wl1251 *wl; | 243 | struct wl1251 *wl; |
| 244 | int ret; | 244 | int ret; |
| 245 | 245 | ||
| 246 | pdata = spi->dev.platform_data; | 246 | pdata = dev_get_platdata(&spi->dev); |
| 247 | if (!pdata) { | 247 | if (!pdata) { |
| 248 | wl1251_error("no platform data"); | 248 | wl1251_error("no platform data"); |
| 249 | return -ENODEV; | 249 | return -ENODEV; |
diff --git a/drivers/net/wireless/ti/wl1251/wl1251.h b/drivers/net/wireless/ti/wl1251/wl1251.h index fd02060038de..2c3bd1bff3f6 100644 --- a/drivers/net/wireless/ti/wl1251/wl1251.h +++ b/drivers/net/wireless/ti/wl1251/wl1251.h | |||
| @@ -424,8 +424,8 @@ void wl1251_disable_interrupts(struct wl1251 *wl); | |||
| 424 | #define CHIP_ID_1271_PG10 (0x4030101) | 424 | #define CHIP_ID_1271_PG10 (0x4030101) |
| 425 | #define CHIP_ID_1271_PG20 (0x4030111) | 425 | #define CHIP_ID_1271_PG20 (0x4030111) |
| 426 | 426 | ||
| 427 | #define WL1251_FW_NAME "wl1251-fw.bin" | 427 | #define WL1251_FW_NAME "ti-connectivity/wl1251-fw.bin" |
| 428 | #define WL1251_NVS_NAME "wl1251-nvs.bin" | 428 | #define WL1251_NVS_NAME "ti-connectivity/wl1251-nvs.bin" |
| 429 | 429 | ||
| 430 | #define WL1251_POWER_ON_SLEEP 10 /* in milliseconds */ | 430 | #define WL1251_POWER_ON_SLEEP 10 /* in milliseconds */ |
| 431 | 431 | ||
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index 1c627da85083..be7129ba16ad 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c | |||
| @@ -333,11 +333,11 @@ static struct wlcore_conf wl12xx_conf = { | |||
| 333 | .always = 0, | 333 | .always = 0, |
| 334 | }, | 334 | }, |
| 335 | .fwlog = { | 335 | .fwlog = { |
| 336 | .mode = WL12XX_FWLOG_ON_DEMAND, | 336 | .mode = WL12XX_FWLOG_CONTINUOUS, |
| 337 | .mem_blocks = 2, | 337 | .mem_blocks = 2, |
| 338 | .severity = 0, | 338 | .severity = 0, |
| 339 | .timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED, | 339 | .timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED, |
| 340 | .output = WL12XX_FWLOG_OUTPUT_HOST, | 340 | .output = WL12XX_FWLOG_OUTPUT_DBG_PINS, |
| 341 | .threshold = 0, | 341 | .threshold = 0, |
| 342 | }, | 342 | }, |
| 343 | .rate = { | 343 | .rate = { |
| @@ -717,6 +717,9 @@ static int wl12xx_identify_chip(struct wl1271 *wl) | |||
| 717 | goto out; | 717 | goto out; |
| 718 | } | 718 | } |
| 719 | 719 | ||
| 720 | wl->fw_mem_block_size = 256; | ||
| 721 | wl->fwlog_end = 0x2000000; | ||
| 722 | |||
| 720 | /* common settings */ | 723 | /* common settings */ |
| 721 | wl->scan_templ_id_2_4 = CMD_TEMPL_APP_PROBE_REQ_2_4_LEGACY; | 724 | wl->scan_templ_id_2_4 = CMD_TEMPL_APP_PROBE_REQ_2_4_LEGACY; |
| 722 | wl->scan_templ_id_5 = CMD_TEMPL_APP_PROBE_REQ_5_LEGACY; | 725 | wl->scan_templ_id_5 = CMD_TEMPL_APP_PROBE_REQ_5_LEGACY; |
| @@ -1262,9 +1265,10 @@ static int wl12xx_boot(struct wl1271 *wl) | |||
| 1262 | BA_SESSION_RX_CONSTRAINT_EVENT_ID | | 1265 | BA_SESSION_RX_CONSTRAINT_EVENT_ID | |
| 1263 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID | | 1266 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID | |
| 1264 | INACTIVE_STA_EVENT_ID | | 1267 | INACTIVE_STA_EVENT_ID | |
| 1265 | MAX_TX_RETRY_EVENT_ID | | ||
| 1266 | CHANNEL_SWITCH_COMPLETE_EVENT_ID; | 1268 | CHANNEL_SWITCH_COMPLETE_EVENT_ID; |
| 1267 | 1269 | ||
| 1270 | wl->ap_event_mask = MAX_TX_RETRY_EVENT_ID; | ||
| 1271 | |||
| 1268 | ret = wlcore_boot_run_firmware(wl); | 1272 | ret = wlcore_boot_run_firmware(wl); |
| 1269 | if (ret < 0) | 1273 | if (ret < 0) |
| 1270 | goto out; | 1274 | goto out; |
| @@ -1648,6 +1652,11 @@ static bool wl12xx_lnk_low_prio(struct wl1271 *wl, u8 hlid, | |||
| 1648 | return true; | 1652 | return true; |
| 1649 | } | 1653 | } |
| 1650 | 1654 | ||
| 1655 | static u32 wl12xx_convert_hwaddr(struct wl1271 *wl, u32 hwaddr) | ||
| 1656 | { | ||
| 1657 | return hwaddr << 5; | ||
| 1658 | } | ||
| 1659 | |||
| 1651 | static int wl12xx_setup(struct wl1271 *wl); | 1660 | static int wl12xx_setup(struct wl1271 *wl); |
| 1652 | 1661 | ||
| 1653 | static struct wlcore_ops wl12xx_ops = { | 1662 | static struct wlcore_ops wl12xx_ops = { |
| @@ -1684,6 +1693,7 @@ static struct wlcore_ops wl12xx_ops = { | |||
| 1684 | .channel_switch = wl12xx_cmd_channel_switch, | 1693 | .channel_switch = wl12xx_cmd_channel_switch, |
| 1685 | .pre_pkt_send = NULL, | 1694 | .pre_pkt_send = NULL, |
| 1686 | .set_peer_cap = wl12xx_set_peer_cap, | 1695 | .set_peer_cap = wl12xx_set_peer_cap, |
| 1696 | .convert_hwaddr = wl12xx_convert_hwaddr, | ||
| 1687 | .lnk_high_prio = wl12xx_lnk_high_prio, | 1697 | .lnk_high_prio = wl12xx_lnk_high_prio, |
| 1688 | .lnk_low_prio = wl12xx_lnk_low_prio, | 1698 | .lnk_low_prio = wl12xx_lnk_low_prio, |
| 1689 | }; | 1699 | }; |
| @@ -1704,7 +1714,7 @@ static struct ieee80211_sta_ht_cap wl12xx_ht_cap = { | |||
| 1704 | static int wl12xx_setup(struct wl1271 *wl) | 1714 | static int wl12xx_setup(struct wl1271 *wl) |
| 1705 | { | 1715 | { |
| 1706 | struct wl12xx_priv *priv = wl->priv; | 1716 | struct wl12xx_priv *priv = wl->priv; |
| 1707 | struct wlcore_platdev_data *pdev_data = wl->pdev->dev.platform_data; | 1717 | struct wlcore_platdev_data *pdev_data = dev_get_platdata(&wl->pdev->dev); |
| 1708 | struct wl12xx_platform_data *pdata = pdev_data->pdata; | 1718 | struct wl12xx_platform_data *pdata = pdev_data->pdata; |
| 1709 | 1719 | ||
| 1710 | wl->rtable = wl12xx_rtable; | 1720 | wl->rtable = wl12xx_rtable; |
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index 7aa0eb848c5a..ec37b16585df 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c | |||
| @@ -456,11 +456,11 @@ static struct wlcore_conf wl18xx_conf = { | |||
| 456 | .always = 0, | 456 | .always = 0, |
| 457 | }, | 457 | }, |
| 458 | .fwlog = { | 458 | .fwlog = { |
| 459 | .mode = WL12XX_FWLOG_ON_DEMAND, | 459 | .mode = WL12XX_FWLOG_CONTINUOUS, |
| 460 | .mem_blocks = 2, | 460 | .mem_blocks = 2, |
| 461 | .severity = 0, | 461 | .severity = 0, |
| 462 | .timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED, | 462 | .timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED, |
| 463 | .output = WL12XX_FWLOG_OUTPUT_HOST, | 463 | .output = WL12XX_FWLOG_OUTPUT_DBG_PINS, |
| 464 | .threshold = 0, | 464 | .threshold = 0, |
| 465 | }, | 465 | }, |
| 466 | .rate = { | 466 | .rate = { |
| @@ -505,7 +505,7 @@ static struct wlcore_conf wl18xx_conf = { | |||
| 505 | 505 | ||
| 506 | static struct wl18xx_priv_conf wl18xx_default_priv_conf = { | 506 | static struct wl18xx_priv_conf wl18xx_default_priv_conf = { |
| 507 | .ht = { | 507 | .ht = { |
| 508 | .mode = HT_MODE_DEFAULT, | 508 | .mode = HT_MODE_WIDE, |
| 509 | }, | 509 | }, |
| 510 | .phy = { | 510 | .phy = { |
| 511 | .phy_standalone = 0x00, | 511 | .phy_standalone = 0x00, |
| @@ -516,7 +516,7 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = { | |||
| 516 | .auto_detect = 0x00, | 516 | .auto_detect = 0x00, |
| 517 | .dedicated_fem = FEM_NONE, | 517 | .dedicated_fem = FEM_NONE, |
| 518 | .low_band_component = COMPONENT_3_WAY_SWITCH, | 518 | .low_band_component = COMPONENT_3_WAY_SWITCH, |
| 519 | .low_band_component_type = 0x04, | 519 | .low_band_component_type = 0x05, |
| 520 | .high_band_component = COMPONENT_2_WAY_SWITCH, | 520 | .high_band_component = COMPONENT_2_WAY_SWITCH, |
| 521 | .high_band_component_type = 0x09, | 521 | .high_band_component_type = 0x09, |
| 522 | .tcxo_ldo_voltage = 0x00, | 522 | .tcxo_ldo_voltage = 0x00, |
| @@ -556,15 +556,15 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = { | |||
| 556 | .per_chan_pwr_limit_arr_11p = { 0xff, 0xff, 0xff, 0xff, | 556 | .per_chan_pwr_limit_arr_11p = { 0xff, 0xff, 0xff, 0xff, |
| 557 | 0xff, 0xff, 0xff }, | 557 | 0xff, 0xff, 0xff }, |
| 558 | .psat = 0, | 558 | .psat = 0, |
| 559 | .low_power_val = 0x08, | ||
| 560 | .med_power_val = 0x12, | ||
| 561 | .high_power_val = 0x18, | ||
| 562 | .low_power_val_2nd = 0x05, | ||
| 563 | .med_power_val_2nd = 0x0a, | ||
| 564 | .high_power_val_2nd = 0x14, | ||
| 565 | .external_pa_dc2dc = 0, | 559 | .external_pa_dc2dc = 0, |
| 566 | .number_of_assembled_ant2_4 = 2, | 560 | .number_of_assembled_ant2_4 = 2, |
| 567 | .number_of_assembled_ant5 = 1, | 561 | .number_of_assembled_ant5 = 1, |
| 562 | .low_power_val = 0xff, | ||
| 563 | .med_power_val = 0xff, | ||
| 564 | .high_power_val = 0xff, | ||
| 565 | .low_power_val_2nd = 0xff, | ||
| 566 | .med_power_val_2nd = 0xff, | ||
| 567 | .high_power_val_2nd = 0xff, | ||
| 568 | .tx_rf_margin = 1, | 568 | .tx_rf_margin = 1, |
| 569 | }, | 569 | }, |
| 570 | }; | 570 | }; |
| @@ -623,6 +623,18 @@ static const int wl18xx_rtable[REG_TABLE_LEN] = { | |||
| 623 | [REG_RAW_FW_STATUS_ADDR] = WL18XX_FW_STATUS_ADDR, | 623 | [REG_RAW_FW_STATUS_ADDR] = WL18XX_FW_STATUS_ADDR, |
| 624 | }; | 624 | }; |
| 625 | 625 | ||
| 626 | static const struct wl18xx_clk_cfg wl18xx_clk_table_coex[NUM_CLOCK_CONFIGS] = { | ||
| 627 | [CLOCK_CONFIG_16_2_M] = { 8, 121, 0, 0, false }, | ||
| 628 | [CLOCK_CONFIG_16_368_M] = { 8, 120, 0, 0, false }, | ||
| 629 | [CLOCK_CONFIG_16_8_M] = { 8, 117, 0, 0, false }, | ||
| 630 | [CLOCK_CONFIG_19_2_M] = { 10, 128, 0, 0, false }, | ||
| 631 | [CLOCK_CONFIG_26_M] = { 11, 104, 0, 0, false }, | ||
| 632 | [CLOCK_CONFIG_32_736_M] = { 8, 120, 0, 0, false }, | ||
| 633 | [CLOCK_CONFIG_33_6_M] = { 8, 117, 0, 0, false }, | ||
| 634 | [CLOCK_CONFIG_38_468_M] = { 10, 128, 0, 0, false }, | ||
| 635 | [CLOCK_CONFIG_52_M] = { 11, 104, 0, 0, false }, | ||
| 636 | }; | ||
| 637 | |||
| 626 | static const struct wl18xx_clk_cfg wl18xx_clk_table[NUM_CLOCK_CONFIGS] = { | 638 | static const struct wl18xx_clk_cfg wl18xx_clk_table[NUM_CLOCK_CONFIGS] = { |
| 627 | [CLOCK_CONFIG_16_2_M] = { 7, 104, 801, 4, true }, | 639 | [CLOCK_CONFIG_16_2_M] = { 7, 104, 801, 4, true }, |
| 628 | [CLOCK_CONFIG_16_368_M] = { 9, 132, 3751, 4, true }, | 640 | [CLOCK_CONFIG_16_368_M] = { 9, 132, 3751, 4, true }, |
| @@ -674,6 +686,9 @@ static int wl18xx_identify_chip(struct wl1271 *wl) | |||
| 674 | goto out; | 686 | goto out; |
| 675 | } | 687 | } |
| 676 | 688 | ||
| 689 | wl->fw_mem_block_size = 272; | ||
| 690 | wl->fwlog_end = 0x40000000; | ||
| 691 | |||
| 677 | wl->scan_templ_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4; | 692 | wl->scan_templ_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4; |
| 678 | wl->scan_templ_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5; | 693 | wl->scan_templ_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5; |
| 679 | wl->sched_scan_templ_id_2_4 = CMD_TEMPL_PROBE_REQ_2_4_PERIODIC; | 694 | wl->sched_scan_templ_id_2_4 = CMD_TEMPL_PROBE_REQ_2_4_PERIODIC; |
| @@ -704,6 +719,23 @@ static int wl18xx_set_clk(struct wl1271 *wl) | |||
| 704 | wl18xx_clk_table[clk_freq].p, wl18xx_clk_table[clk_freq].q, | 719 | wl18xx_clk_table[clk_freq].p, wl18xx_clk_table[clk_freq].q, |
| 705 | wl18xx_clk_table[clk_freq].swallow ? "swallow" : "spit"); | 720 | wl18xx_clk_table[clk_freq].swallow ? "swallow" : "spit"); |
| 706 | 721 | ||
| 722 | /* coex PLL configuration */ | ||
| 723 | ret = wl18xx_top_reg_write(wl, PLLSH_COEX_PLL_N, | ||
| 724 | wl18xx_clk_table_coex[clk_freq].n); | ||
| 725 | if (ret < 0) | ||
| 726 | goto out; | ||
| 727 | |||
| 728 | ret = wl18xx_top_reg_write(wl, PLLSH_COEX_PLL_M, | ||
| 729 | wl18xx_clk_table_coex[clk_freq].m); | ||
| 730 | if (ret < 0) | ||
| 731 | goto out; | ||
| 732 | |||
| 733 | /* bypass the swallowing logic */ | ||
| 734 | ret = wl18xx_top_reg_write(wl, PLLSH_COEX_PLL_SWALLOW_EN, | ||
| 735 | PLLSH_COEX_PLL_SWALLOW_EN_VAL1); | ||
| 736 | if (ret < 0) | ||
| 737 | goto out; | ||
| 738 | |||
| 707 | ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_N, | 739 | ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_N, |
| 708 | wl18xx_clk_table[clk_freq].n); | 740 | wl18xx_clk_table[clk_freq].n); |
| 709 | if (ret < 0) | 741 | if (ret < 0) |
| @@ -745,6 +777,30 @@ static int wl18xx_set_clk(struct wl1271 *wl) | |||
| 745 | PLLSH_WCS_PLL_SWALLOW_EN_VAL2); | 777 | PLLSH_WCS_PLL_SWALLOW_EN_VAL2); |
| 746 | } | 778 | } |
| 747 | 779 | ||
| 780 | /* choose WCS PLL */ | ||
| 781 | ret = wl18xx_top_reg_write(wl, PLLSH_WL_PLL_SEL, | ||
| 782 | PLLSH_WL_PLL_SEL_WCS_PLL); | ||
| 783 | if (ret < 0) | ||
| 784 | goto out; | ||
| 785 | |||
| 786 | /* enable both PLLs */ | ||
| 787 | ret = wl18xx_top_reg_write(wl, PLLSH_WL_PLL_EN, PLLSH_WL_PLL_EN_VAL1); | ||
| 788 | if (ret < 0) | ||
| 789 | goto out; | ||
| 790 | |||
| 791 | udelay(1000); | ||
| 792 | |||
| 793 | /* disable coex PLL */ | ||
| 794 | ret = wl18xx_top_reg_write(wl, PLLSH_WL_PLL_EN, PLLSH_WL_PLL_EN_VAL2); | ||
| 795 | if (ret < 0) | ||
| 796 | goto out; | ||
| 797 | |||
| 798 | /* reset the swallowing logic */ | ||
| 799 | ret = wl18xx_top_reg_write(wl, PLLSH_COEX_PLL_SWALLOW_EN, | ||
| 800 | PLLSH_COEX_PLL_SWALLOW_EN_VAL2); | ||
| 801 | if (ret < 0) | ||
| 802 | goto out; | ||
| 803 | |||
| 748 | out: | 804 | out: |
| 749 | return ret; | 805 | return ret; |
| 750 | } | 806 | } |
| @@ -935,10 +991,11 @@ static int wl18xx_boot(struct wl1271 *wl) | |||
| 935 | BA_SESSION_RX_CONSTRAINT_EVENT_ID | | 991 | BA_SESSION_RX_CONSTRAINT_EVENT_ID | |
| 936 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID | | 992 | REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID | |
| 937 | INACTIVE_STA_EVENT_ID | | 993 | INACTIVE_STA_EVENT_ID | |
| 938 | MAX_TX_FAILURE_EVENT_ID | | ||
| 939 | CHANNEL_SWITCH_COMPLETE_EVENT_ID | | 994 | CHANNEL_SWITCH_COMPLETE_EVENT_ID | |
| 940 | DFS_CHANNELS_CONFIG_COMPLETE_EVENT; | 995 | DFS_CHANNELS_CONFIG_COMPLETE_EVENT; |
| 941 | 996 | ||
| 997 | wl->ap_event_mask = MAX_TX_FAILURE_EVENT_ID; | ||
| 998 | |||
| 942 | ret = wlcore_boot_run_firmware(wl); | 999 | ret = wlcore_boot_run_firmware(wl); |
| 943 | if (ret < 0) | 1000 | if (ret < 0) |
| 944 | goto out; | 1001 | goto out; |
| @@ -1175,16 +1232,48 @@ static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl, | |||
| 1175 | } | 1232 | } |
| 1176 | } | 1233 | } |
| 1177 | 1234 | ||
| 1235 | static const char *wl18xx_rdl_name(enum wl18xx_rdl_num rdl_num) | ||
| 1236 | { | ||
| 1237 | switch (rdl_num) { | ||
| 1238 | case RDL_1_HP: | ||
| 1239 | return "183xH"; | ||
| 1240 | case RDL_2_SP: | ||
| 1241 | return "183x or 180x"; | ||
| 1242 | case RDL_3_HP: | ||
| 1243 | return "187xH"; | ||
| 1244 | case RDL_4_SP: | ||
| 1245 | return "187x"; | ||
| 1246 | case RDL_5_SP: | ||
| 1247 | return "RDL11 - Not Supported"; | ||
| 1248 | case RDL_6_SP: | ||
| 1249 | return "180xD"; | ||
| 1250 | case RDL_7_SP: | ||
| 1251 | return "RDL13 - Not Supported (1893Q)"; | ||
| 1252 | case RDL_8_SP: | ||
| 1253 | return "18xxQ"; | ||
| 1254 | case RDL_NONE: | ||
| 1255 | return "UNTRIMMED"; | ||
| 1256 | default: | ||
| 1257 | return "UNKNOWN"; | ||
| 1258 | } | ||
| 1259 | } | ||
| 1260 | |||
| 1178 | static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver) | 1261 | static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver) |
| 1179 | { | 1262 | { |
| 1180 | u32 fuse; | 1263 | u32 fuse; |
| 1181 | s8 rom = 0, metal = 0, pg_ver = 0, rdl_ver = 0; | 1264 | s8 rom = 0, metal = 0, pg_ver = 0, rdl_ver = 0, package_type = 0; |
| 1182 | int ret; | 1265 | int ret; |
| 1183 | 1266 | ||
| 1184 | ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); | 1267 | ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); |
| 1185 | if (ret < 0) | 1268 | if (ret < 0) |
| 1186 | goto out; | 1269 | goto out; |
| 1187 | 1270 | ||
| 1271 | ret = wlcore_read32(wl, WL18XX_REG_FUSE_DATA_2_3, &fuse); | ||
| 1272 | if (ret < 0) | ||
| 1273 | goto out; | ||
| 1274 | |||
| 1275 | package_type = (fuse >> WL18XX_PACKAGE_TYPE_OFFSET) & 1; | ||
| 1276 | |||
| 1188 | ret = wlcore_read32(wl, WL18XX_REG_FUSE_DATA_1_3, &fuse); | 1277 | ret = wlcore_read32(wl, WL18XX_REG_FUSE_DATA_1_3, &fuse); |
| 1189 | if (ret < 0) | 1278 | if (ret < 0) |
| 1190 | goto out; | 1279 | goto out; |
| @@ -1192,7 +1281,7 @@ static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver) | |||
| 1192 | pg_ver = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET; | 1281 | pg_ver = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET; |
| 1193 | rom = (fuse & WL18XX_ROM_VER_MASK) >> WL18XX_ROM_VER_OFFSET; | 1282 | rom = (fuse & WL18XX_ROM_VER_MASK) >> WL18XX_ROM_VER_OFFSET; |
| 1194 | 1283 | ||
| 1195 | if (rom <= 0xE) | 1284 | if ((rom <= 0xE) && (package_type == WL18XX_PACKAGE_TYPE_WSP)) |
| 1196 | metal = (fuse & WL18XX_METAL_VER_MASK) >> | 1285 | metal = (fuse & WL18XX_METAL_VER_MASK) >> |
| 1197 | WL18XX_METAL_VER_OFFSET; | 1286 | WL18XX_METAL_VER_OFFSET; |
| 1198 | else | 1287 | else |
| @@ -1204,11 +1293,9 @@ static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver) | |||
| 1204 | goto out; | 1293 | goto out; |
| 1205 | 1294 | ||
| 1206 | rdl_ver = (fuse & WL18XX_RDL_VER_MASK) >> WL18XX_RDL_VER_OFFSET; | 1295 | rdl_ver = (fuse & WL18XX_RDL_VER_MASK) >> WL18XX_RDL_VER_OFFSET; |
| 1207 | if (rdl_ver > RDL_MAX) | ||
| 1208 | rdl_ver = RDL_NONE; | ||
| 1209 | 1296 | ||
| 1210 | wl1271_info("wl18xx HW: RDL %d, %s, PG %x.%x (ROM %x)", | 1297 | wl1271_info("wl18xx HW: %s, PG %d.%d (ROM 0x%x)", |
| 1211 | rdl_ver, rdl_names[rdl_ver], pg_ver, metal, rom); | 1298 | wl18xx_rdl_name(rdl_ver), pg_ver, metal, rom); |
| 1212 | 1299 | ||
| 1213 | if (ver) | 1300 | if (ver) |
| 1214 | *ver = pg_ver; | 1301 | *ver = pg_ver; |
| @@ -1521,6 +1608,11 @@ static bool wl18xx_lnk_low_prio(struct wl1271 *wl, u8 hlid, | |||
| 1521 | return lnk->allocated_pkts < thold; | 1608 | return lnk->allocated_pkts < thold; |
| 1522 | } | 1609 | } |
| 1523 | 1610 | ||
| 1611 | static u32 wl18xx_convert_hwaddr(struct wl1271 *wl, u32 hwaddr) | ||
| 1612 | { | ||
| 1613 | return hwaddr & ~0x80000000; | ||
| 1614 | } | ||
| 1615 | |||
| 1524 | static int wl18xx_setup(struct wl1271 *wl); | 1616 | static int wl18xx_setup(struct wl1271 *wl); |
| 1525 | 1617 | ||
| 1526 | static struct wlcore_ops wl18xx_ops = { | 1618 | static struct wlcore_ops wl18xx_ops = { |
| @@ -1558,6 +1650,7 @@ static struct wlcore_ops wl18xx_ops = { | |||
| 1558 | .pre_pkt_send = wl18xx_pre_pkt_send, | 1650 | .pre_pkt_send = wl18xx_pre_pkt_send, |
| 1559 | .sta_rc_update = wl18xx_sta_rc_update, | 1651 | .sta_rc_update = wl18xx_sta_rc_update, |
| 1560 | .set_peer_cap = wl18xx_set_peer_cap, | 1652 | .set_peer_cap = wl18xx_set_peer_cap, |
| 1653 | .convert_hwaddr = wl18xx_convert_hwaddr, | ||
| 1561 | .lnk_high_prio = wl18xx_lnk_high_prio, | 1654 | .lnk_high_prio = wl18xx_lnk_high_prio, |
| 1562 | .lnk_low_prio = wl18xx_lnk_low_prio, | 1655 | .lnk_low_prio = wl18xx_lnk_low_prio, |
| 1563 | }; | 1656 | }; |
diff --git a/drivers/net/wireless/ti/wl18xx/reg.h b/drivers/net/wireless/ti/wl18xx/reg.h index 05dd8bad2746..a433a75f3cd7 100644 --- a/drivers/net/wireless/ti/wl18xx/reg.h +++ b/drivers/net/wireless/ti/wl18xx/reg.h | |||
| @@ -114,6 +114,11 @@ | |||
| 114 | #define PLATFORM_DETECTION 0xA0E3E0 | 114 | #define PLATFORM_DETECTION 0xA0E3E0 |
| 115 | #define OCS_EN 0xA02080 | 115 | #define OCS_EN 0xA02080 |
| 116 | #define PRIMARY_CLK_DETECT 0xA020A6 | 116 | #define PRIMARY_CLK_DETECT 0xA020A6 |
| 117 | #define PLLSH_COEX_PLL_N 0xA02384 | ||
| 118 | #define PLLSH_COEX_PLL_M 0xA02382 | ||
| 119 | #define PLLSH_COEX_PLL_SWALLOW_EN 0xA0238E | ||
| 120 | #define PLLSH_WL_PLL_SEL 0xA02398 | ||
| 121 | |||
| 117 | #define PLLSH_WCS_PLL_N 0xA02362 | 122 | #define PLLSH_WCS_PLL_N 0xA02362 |
| 118 | #define PLLSH_WCS_PLL_M 0xA02360 | 123 | #define PLLSH_WCS_PLL_M 0xA02360 |
| 119 | #define PLLSH_WCS_PLL_Q_FACTOR_CFG_1 0xA02364 | 124 | #define PLLSH_WCS_PLL_Q_FACTOR_CFG_1 0xA02364 |
| @@ -128,19 +133,30 @@ | |||
| 128 | #define PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK 0xFFFF | 133 | #define PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK 0xFFFF |
| 129 | #define PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK 0x000F | 134 | #define PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK 0x000F |
| 130 | 135 | ||
| 136 | #define PLLSH_WL_PLL_EN_VAL1 0x7 | ||
| 137 | #define PLLSH_WL_PLL_EN_VAL2 0x2 | ||
| 138 | #define PLLSH_COEX_PLL_SWALLOW_EN_VAL1 0x2 | ||
| 139 | #define PLLSH_COEX_PLL_SWALLOW_EN_VAL2 0x11 | ||
| 140 | |||
| 131 | #define PLLSH_WCS_PLL_SWALLOW_EN_VAL1 0x1 | 141 | #define PLLSH_WCS_PLL_SWALLOW_EN_VAL1 0x1 |
| 132 | #define PLLSH_WCS_PLL_SWALLOW_EN_VAL2 0x12 | 142 | #define PLLSH_WCS_PLL_SWALLOW_EN_VAL2 0x12 |
| 133 | 143 | ||
| 144 | #define PLLSH_WL_PLL_SEL_WCS_PLL 0x0 | ||
| 145 | #define PLLSH_WL_PLL_SEL_COEX_PLL 0x1 | ||
| 146 | |||
| 134 | #define WL18XX_REG_FUSE_DATA_1_3 0xA0260C | 147 | #define WL18XX_REG_FUSE_DATA_1_3 0xA0260C |
| 135 | #define WL18XX_PG_VER_MASK 0x70 | 148 | #define WL18XX_PG_VER_MASK 0x70 |
| 136 | #define WL18XX_PG_VER_OFFSET 4 | 149 | #define WL18XX_PG_VER_OFFSET 4 |
| 137 | #define WL18XX_ROM_VER_MASK 0x3 | 150 | #define WL18XX_ROM_VER_MASK 0x3e00 |
| 138 | #define WL18XX_ROM_VER_OFFSET 0 | 151 | #define WL18XX_ROM_VER_OFFSET 9 |
| 139 | #define WL18XX_METAL_VER_MASK 0xC | 152 | #define WL18XX_METAL_VER_MASK 0xC |
| 140 | #define WL18XX_METAL_VER_OFFSET 2 | 153 | #define WL18XX_METAL_VER_OFFSET 2 |
| 141 | #define WL18XX_NEW_METAL_VER_MASK 0x180 | 154 | #define WL18XX_NEW_METAL_VER_MASK 0x180 |
| 142 | #define WL18XX_NEW_METAL_VER_OFFSET 7 | 155 | #define WL18XX_NEW_METAL_VER_OFFSET 7 |
| 143 | 156 | ||
| 157 | #define WL18XX_PACKAGE_TYPE_OFFSET 13 | ||
| 158 | #define WL18XX_PACKAGE_TYPE_WSP 0 | ||
| 159 | |||
| 144 | #define WL18XX_REG_FUSE_DATA_2_3 0xA02614 | 160 | #define WL18XX_REG_FUSE_DATA_2_3 0xA02614 |
| 145 | #define WL18XX_RDL_VER_MASK 0x1f00 | 161 | #define WL18XX_RDL_VER_MASK 0x1f00 |
| 146 | #define WL18XX_RDL_VER_OFFSET 8 | 162 | #define WL18XX_RDL_VER_OFFSET 8 |
| @@ -201,24 +217,21 @@ enum { | |||
| 201 | NUM_BOARD_TYPES, | 217 | NUM_BOARD_TYPES, |
| 202 | }; | 218 | }; |
| 203 | 219 | ||
| 204 | enum { | 220 | enum wl18xx_rdl_num { |
| 205 | RDL_NONE = 0, | 221 | RDL_NONE = 0, |
| 206 | RDL_1_HP = 1, | 222 | RDL_1_HP = 1, |
| 207 | RDL_2_SP = 2, | 223 | RDL_2_SP = 2, |
| 208 | RDL_3_HP = 3, | 224 | RDL_3_HP = 3, |
| 209 | RDL_4_SP = 4, | 225 | RDL_4_SP = 4, |
| 226 | RDL_5_SP = 0x11, | ||
| 227 | RDL_6_SP = 0x12, | ||
| 228 | RDL_7_SP = 0x13, | ||
| 229 | RDL_8_SP = 0x14, | ||
| 210 | 230 | ||
| 211 | _RDL_LAST, | 231 | _RDL_LAST, |
| 212 | RDL_MAX = _RDL_LAST - 1, | 232 | RDL_MAX = _RDL_LAST - 1, |
| 213 | }; | 233 | }; |
| 214 | 234 | ||
| 215 | static const char * const rdl_names[] = { | ||
| 216 | [RDL_NONE] = "", | ||
| 217 | [RDL_1_HP] = "1853 SISO", | ||
| 218 | [RDL_2_SP] = "1857 MIMO", | ||
| 219 | [RDL_3_HP] = "1893 SISO", | ||
| 220 | [RDL_4_SP] = "1897 MIMO", | ||
| 221 | }; | ||
| 222 | 235 | ||
| 223 | /* FPGA_SPARE_1 register - used to change the PHY ATPG clock at boot time */ | 236 | /* FPGA_SPARE_1 register - used to change the PHY ATPG clock at boot time */ |
| 224 | #define WL18XX_PHY_FPGA_SPARE_1 0x8093CA40 | 237 | #define WL18XX_PHY_FPGA_SPARE_1 0x8093CA40 |
diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c index 7a970cd9c555..ec83675a2446 100644 --- a/drivers/net/wireless/ti/wlcore/acx.c +++ b/drivers/net/wireless/ti/wlcore/acx.c | |||
| @@ -162,7 +162,8 @@ int wl1271_acx_mem_map(struct wl1271 *wl, struct acx_header *mem_map, | |||
| 162 | 162 | ||
| 163 | wl1271_debug(DEBUG_ACX, "acx mem map"); | 163 | wl1271_debug(DEBUG_ACX, "acx mem map"); |
| 164 | 164 | ||
| 165 | ret = wl1271_cmd_interrogate(wl, ACX_MEM_MAP, mem_map, len); | 165 | ret = wl1271_cmd_interrogate(wl, ACX_MEM_MAP, mem_map, |
| 166 | sizeof(struct acx_header), len); | ||
| 166 | if (ret < 0) | 167 | if (ret < 0) |
| 167 | return ret; | 168 | return ret; |
| 168 | 169 | ||
| @@ -722,6 +723,7 @@ int wl1271_acx_statistics(struct wl1271 *wl, void *stats) | |||
| 722 | wl1271_debug(DEBUG_ACX, "acx statistics"); | 723 | wl1271_debug(DEBUG_ACX, "acx statistics"); |
| 723 | 724 | ||
| 724 | ret = wl1271_cmd_interrogate(wl, ACX_STATISTICS, stats, | 725 | ret = wl1271_cmd_interrogate(wl, ACX_STATISTICS, stats, |
| 726 | sizeof(struct acx_header), | ||
| 725 | wl->stats.fw_stats_len); | 727 | wl->stats.fw_stats_len); |
| 726 | if (ret < 0) { | 728 | if (ret < 0) { |
| 727 | wl1271_warning("acx statistics failed: %d", ret); | 729 | wl1271_warning("acx statistics failed: %d", ret); |
| @@ -1470,8 +1472,8 @@ int wl12xx_acx_tsf_info(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
| 1470 | 1472 | ||
| 1471 | tsf_info->role_id = wlvif->role_id; | 1473 | tsf_info->role_id = wlvif->role_id; |
| 1472 | 1474 | ||
| 1473 | ret = wl1271_cmd_interrogate(wl, ACX_TSF_INFO, | 1475 | ret = wl1271_cmd_interrogate(wl, ACX_TSF_INFO, tsf_info, |
| 1474 | tsf_info, sizeof(*tsf_info)); | 1476 | sizeof(struct acx_header), sizeof(*tsf_info)); |
| 1475 | if (ret < 0) { | 1477 | if (ret < 0) { |
| 1476 | wl1271_warning("acx tsf info interrogate failed"); | 1478 | wl1271_warning("acx tsf info interrogate failed"); |
| 1477 | goto out; | 1479 | goto out; |
| @@ -1752,7 +1754,7 @@ int wlcore_acx_average_rssi(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
| 1752 | 1754 | ||
| 1753 | acx->role_id = wlvif->role_id; | 1755 | acx->role_id = wlvif->role_id; |
| 1754 | ret = wl1271_cmd_interrogate(wl, ACX_ROAMING_STATISTICS_TBL, | 1756 | ret = wl1271_cmd_interrogate(wl, ACX_ROAMING_STATISTICS_TBL, |
| 1755 | acx, sizeof(*acx)); | 1757 | acx, sizeof(*acx), sizeof(*acx)); |
| 1756 | if (ret < 0) { | 1758 | if (ret < 0) { |
| 1757 | wl1271_warning("acx roaming statistics failed: %d", ret); | 1759 | wl1271_warning("acx roaming statistics failed: %d", ret); |
| 1758 | ret = -ENOMEM; | 1760 | ret = -ENOMEM; |
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index c9e060795d13..34d9dfff2ad3 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c | |||
| @@ -60,7 +60,8 @@ static int __wlcore_cmd_send(struct wl1271 *wl, u16 id, void *buf, | |||
| 60 | u16 status; | 60 | u16 status; |
| 61 | u16 poll_count = 0; | 61 | u16 poll_count = 0; |
| 62 | 62 | ||
| 63 | if (WARN_ON(unlikely(wl->state == WLCORE_STATE_RESTARTING))) | 63 | if (WARN_ON(wl->state == WLCORE_STATE_RESTARTING && |
| 64 | id != CMD_STOP_FWLOGGER)) | ||
| 64 | return -EIO; | 65 | return -EIO; |
| 65 | 66 | ||
| 66 | cmd = buf; | 67 | cmd = buf; |
| @@ -845,7 +846,8 @@ EXPORT_SYMBOL_GPL(wl1271_cmd_test); | |||
| 845 | * @buf: buffer for the response, including all headers, must work with dma | 846 | * @buf: buffer for the response, including all headers, must work with dma |
| 846 | * @len: length of buf | 847 | * @len: length of buf |
| 847 | */ | 848 | */ |
| 848 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len) | 849 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, |
| 850 | size_t cmd_len, size_t res_len) | ||
| 849 | { | 851 | { |
| 850 | struct acx_header *acx = buf; | 852 | struct acx_header *acx = buf; |
| 851 | int ret; | 853 | int ret; |
| @@ -854,10 +856,10 @@ int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len) | |||
| 854 | 856 | ||
| 855 | acx->id = cpu_to_le16(id); | 857 | acx->id = cpu_to_le16(id); |
| 856 | 858 | ||
| 857 | /* payload length, does not include any headers */ | 859 | /* response payload length, does not include any headers */ |
| 858 | acx->len = cpu_to_le16(len - sizeof(*acx)); | 860 | acx->len = cpu_to_le16(res_len - sizeof(*acx)); |
| 859 | 861 | ||
| 860 | ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx), len); | 862 | ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, cmd_len, res_len); |
| 861 | if (ret < 0) | 863 | if (ret < 0) |
| 862 | wl1271_error("INTERROGATE command failed"); | 864 | wl1271_error("INTERROGATE command failed"); |
| 863 | 865 | ||
| @@ -1126,6 +1128,8 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
| 1126 | u16 template_id_2_4 = wl->scan_templ_id_2_4; | 1128 | u16 template_id_2_4 = wl->scan_templ_id_2_4; |
| 1127 | u16 template_id_5 = wl->scan_templ_id_5; | 1129 | u16 template_id_5 = wl->scan_templ_id_5; |
| 1128 | 1130 | ||
| 1131 | wl1271_debug(DEBUG_SCAN, "build probe request band %d", band); | ||
| 1132 | |||
| 1129 | skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len, | 1133 | skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len, |
| 1130 | ie_len); | 1134 | ie_len); |
| 1131 | if (!skb) { | 1135 | if (!skb) { |
| @@ -1135,8 +1139,6 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
| 1135 | if (ie_len) | 1139 | if (ie_len) |
| 1136 | memcpy(skb_put(skb, ie_len), ie, ie_len); | 1140 | memcpy(skb_put(skb, ie_len), ie, ie_len); |
| 1137 | 1141 | ||
| 1138 | wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len); | ||
| 1139 | |||
| 1140 | if (sched_scan && | 1142 | if (sched_scan && |
| 1141 | (wl->quirks & WLCORE_QUIRK_DUAL_PROBE_TMPL)) { | 1143 | (wl->quirks & WLCORE_QUIRK_DUAL_PROBE_TMPL)) { |
| 1142 | template_id_2_4 = wl->sched_scan_templ_id_2_4; | 1144 | template_id_2_4 = wl->sched_scan_templ_id_2_4; |
| @@ -1172,7 +1174,7 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, | |||
| 1172 | if (!skb) | 1174 | if (!skb) |
| 1173 | goto out; | 1175 | goto out; |
| 1174 | 1176 | ||
| 1175 | wl1271_dump(DEBUG_SCAN, "AP PROBE REQ: ", skb->data, skb->len); | 1177 | wl1271_debug(DEBUG_SCAN, "set ap probe request template"); |
| 1176 | 1178 | ||
| 1177 | rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[wlvif->band]); | 1179 | rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[wlvif->band]); |
| 1178 | if (wlvif->band == IEEE80211_BAND_2GHZ) | 1180 | if (wlvif->band == IEEE80211_BAND_2GHZ) |
| @@ -1607,33 +1609,43 @@ out: | |||
| 1607 | 1609 | ||
| 1608 | static int wlcore_get_reg_conf_ch_idx(enum ieee80211_band band, u16 ch) | 1610 | static int wlcore_get_reg_conf_ch_idx(enum ieee80211_band band, u16 ch) |
| 1609 | { | 1611 | { |
| 1610 | int idx = -1; | 1612 | /* |
| 1611 | 1613 | * map the given band/channel to the respective predefined | |
| 1614 | * bit expected by the fw | ||
| 1615 | */ | ||
| 1612 | switch (band) { | 1616 | switch (band) { |
| 1613 | case IEEE80211_BAND_5GHZ: | ||
| 1614 | if (ch >= 8 && ch <= 16) | ||
| 1615 | idx = ((ch-8)/4 + 18); | ||
| 1616 | else if (ch >= 34 && ch <= 64) | ||
| 1617 | idx = ((ch-34)/2 + 3 + 18); | ||
| 1618 | else if (ch >= 100 && ch <= 140) | ||
| 1619 | idx = ((ch-100)/4 + 15 + 18); | ||
| 1620 | else if (ch >= 149 && ch <= 165) | ||
| 1621 | idx = ((ch-149)/4 + 26 + 18); | ||
| 1622 | else | ||
| 1623 | idx = -1; | ||
| 1624 | break; | ||
| 1625 | case IEEE80211_BAND_2GHZ: | 1617 | case IEEE80211_BAND_2GHZ: |
| 1618 | /* channels 1..14 are mapped to 0..13 */ | ||
| 1626 | if (ch >= 1 && ch <= 14) | 1619 | if (ch >= 1 && ch <= 14) |
| 1627 | idx = ch - 1; | 1620 | return ch - 1; |
| 1628 | else | 1621 | break; |
| 1629 | idx = -1; | 1622 | case IEEE80211_BAND_5GHZ: |
| 1623 | switch (ch) { | ||
| 1624 | case 8 ... 16: | ||
| 1625 | /* channels 8,12,16 are mapped to 18,19,20 */ | ||
| 1626 | return 18 + (ch-8)/4; | ||
| 1627 | case 34 ... 48: | ||
| 1628 | /* channels 34,36..48 are mapped to 21..28 */ | ||
| 1629 | return 21 + (ch-34)/2; | ||
| 1630 | case 52 ... 64: | ||
| 1631 | /* channels 52,56..64 are mapped to 29..32 */ | ||
| 1632 | return 29 + (ch-52)/4; | ||
| 1633 | case 100 ... 140: | ||
| 1634 | /* channels 100,104..140 are mapped to 33..43 */ | ||
| 1635 | return 33 + (ch-100)/4; | ||
| 1636 | case 149 ... 165: | ||
| 1637 | /* channels 149,153..165 are mapped to 44..48 */ | ||
| 1638 | return 44 + (ch-149)/4; | ||
| 1639 | default: | ||
| 1640 | break; | ||
| 1641 | } | ||
| 1630 | break; | 1642 | break; |
| 1631 | default: | 1643 | default: |
| 1632 | wl1271_error("get reg conf ch idx - unknown band: %d", | 1644 | break; |
| 1633 | (int)band); | ||
| 1634 | } | 1645 | } |
| 1635 | 1646 | ||
| 1636 | return idx; | 1647 | wl1271_error("%s: unknown band/channel: %d/%d", __func__, band, ch); |
| 1648 | return -1; | ||
| 1637 | } | 1649 | } |
| 1638 | 1650 | ||
| 1639 | void wlcore_set_pending_regdomain_ch(struct wl1271 *wl, u16 channel, | 1651 | void wlcore_set_pending_regdomain_ch(struct wl1271 *wl, u16 channel, |
| @@ -1646,7 +1658,7 @@ void wlcore_set_pending_regdomain_ch(struct wl1271 *wl, u16 channel, | |||
| 1646 | 1658 | ||
| 1647 | ch_bit_idx = wlcore_get_reg_conf_ch_idx(band, channel); | 1659 | ch_bit_idx = wlcore_get_reg_conf_ch_idx(band, channel); |
| 1648 | 1660 | ||
| 1649 | if (ch_bit_idx > 0 && ch_bit_idx <= WL1271_MAX_CHANNELS) | 1661 | if (ch_bit_idx >= 0 && ch_bit_idx <= WL1271_MAX_CHANNELS) |
| 1650 | set_bit(ch_bit_idx, (long *)wl->reg_ch_conf_pending); | 1662 | set_bit(ch_bit_idx, (long *)wl->reg_ch_conf_pending); |
| 1651 | } | 1663 | } |
| 1652 | 1664 | ||
diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h index fd34123047cd..323d4a856e4b 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.h +++ b/drivers/net/wireless/ti/wlcore/cmd.h | |||
| @@ -45,7 +45,8 @@ int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
| 45 | enum ieee80211_band band, int channel); | 45 | enum ieee80211_band band, int channel); |
| 46 | int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 46 | int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
| 47 | int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); | 47 | int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); |
| 48 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); | 48 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, |
| 49 | size_t cmd_len, size_t res_len); | ||
| 49 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); | 50 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); |
| 50 | int wlcore_cmd_configure_failsafe(struct wl1271 *wl, u16 id, void *buf, | 51 | int wlcore_cmd_configure_failsafe(struct wl1271 *wl, u16 id, void *buf, |
| 51 | size_t len, unsigned long valid_rets); | 52 | size_t len, unsigned long valid_rets); |
diff --git a/drivers/net/wireless/ti/wlcore/conf.h b/drivers/net/wireless/ti/wlcore/conf.h index 2b96ff821341..40995c42bef8 100644 --- a/drivers/net/wireless/ti/wlcore/conf.h +++ b/drivers/net/wireless/ti/wlcore/conf.h | |||
| @@ -1274,6 +1274,9 @@ struct conf_rx_streaming_settings { | |||
| 1274 | u8 always; | 1274 | u8 always; |
| 1275 | } __packed; | 1275 | } __packed; |
| 1276 | 1276 | ||
| 1277 | #define CONF_FWLOG_MIN_MEM_BLOCKS 2 | ||
| 1278 | #define CONF_FWLOG_MAX_MEM_BLOCKS 16 | ||
| 1279 | |||
| 1277 | struct conf_fwlog { | 1280 | struct conf_fwlog { |
| 1278 | /* Continuous or on-demand */ | 1281 | /* Continuous or on-demand */ |
| 1279 | u8 mode; | 1282 | u8 mode; |
| @@ -1281,7 +1284,7 @@ struct conf_fwlog { | |||
| 1281 | /* | 1284 | /* |
| 1282 | * Number of memory blocks dedicated for the FW logger | 1285 | * Number of memory blocks dedicated for the FW logger |
| 1283 | * | 1286 | * |
| 1284 | * Range: 1-3, or 0 to disable the FW logger | 1287 | * Range: 2-16, or 0 to disable the FW logger |
| 1285 | */ | 1288 | */ |
| 1286 | u8 mem_blocks; | 1289 | u8 mem_blocks; |
| 1287 | 1290 | ||
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c index e17630c2a849..89893c717025 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.c +++ b/drivers/net/wireless/ti/wlcore/debugfs.c | |||
| @@ -437,6 +437,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, | |||
| 437 | int res = 0; | 437 | int res = 0; |
| 438 | ssize_t ret; | 438 | ssize_t ret; |
| 439 | char *buf; | 439 | char *buf; |
| 440 | struct wl12xx_vif *wlvif; | ||
| 440 | 441 | ||
| 441 | #define DRIVER_STATE_BUF_LEN 1024 | 442 | #define DRIVER_STATE_BUF_LEN 1024 |
| 442 | 443 | ||
| @@ -450,12 +451,28 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, | |||
| 450 | (res += scnprintf(buf + res, DRIVER_STATE_BUF_LEN - res,\ | 451 | (res += scnprintf(buf + res, DRIVER_STATE_BUF_LEN - res,\ |
| 451 | #x " = " fmt "\n", wl->x)) | 452 | #x " = " fmt "\n", wl->x)) |
| 452 | 453 | ||
| 454 | #define DRIVER_STATE_PRINT_GENERIC(x, fmt, args...) \ | ||
| 455 | (res += scnprintf(buf + res, DRIVER_STATE_BUF_LEN - res,\ | ||
| 456 | #x " = " fmt "\n", args)) | ||
| 457 | |||
| 453 | #define DRIVER_STATE_PRINT_LONG(x) DRIVER_STATE_PRINT(x, "%ld") | 458 | #define DRIVER_STATE_PRINT_LONG(x) DRIVER_STATE_PRINT(x, "%ld") |
| 454 | #define DRIVER_STATE_PRINT_INT(x) DRIVER_STATE_PRINT(x, "%d") | 459 | #define DRIVER_STATE_PRINT_INT(x) DRIVER_STATE_PRINT(x, "%d") |
| 455 | #define DRIVER_STATE_PRINT_STR(x) DRIVER_STATE_PRINT(x, "%s") | 460 | #define DRIVER_STATE_PRINT_STR(x) DRIVER_STATE_PRINT(x, "%s") |
| 456 | #define DRIVER_STATE_PRINT_LHEX(x) DRIVER_STATE_PRINT(x, "0x%lx") | 461 | #define DRIVER_STATE_PRINT_LHEX(x) DRIVER_STATE_PRINT(x, "0x%lx") |
| 457 | #define DRIVER_STATE_PRINT_HEX(x) DRIVER_STATE_PRINT(x, "0x%x") | 462 | #define DRIVER_STATE_PRINT_HEX(x) DRIVER_STATE_PRINT(x, "0x%x") |
| 458 | 463 | ||
| 464 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | ||
| 465 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) | ||
| 466 | continue; | ||
| 467 | |||
| 468 | DRIVER_STATE_PRINT_GENERIC(channel, "%d (%s)", wlvif->channel, | ||
| 469 | wlvif->p2p ? "P2P-CL" : "STA"); | ||
| 470 | } | ||
| 471 | |||
| 472 | wl12xx_for_each_wlvif_ap(wl, wlvif) | ||
| 473 | DRIVER_STATE_PRINT_GENERIC(channel, "%d (%s)", wlvif->channel, | ||
| 474 | wlvif->p2p ? "P2P-GO" : "AP"); | ||
| 475 | |||
| 459 | DRIVER_STATE_PRINT_INT(tx_blocks_available); | 476 | DRIVER_STATE_PRINT_INT(tx_blocks_available); |
| 460 | DRIVER_STATE_PRINT_INT(tx_allocated_blocks); | 477 | DRIVER_STATE_PRINT_INT(tx_allocated_blocks); |
| 461 | DRIVER_STATE_PRINT_INT(tx_allocated_pkts[0]); | 478 | DRIVER_STATE_PRINT_INT(tx_allocated_pkts[0]); |
| @@ -474,7 +491,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, | |||
| 474 | DRIVER_STATE_PRINT_INT(tx_blocks_freed); | 491 | DRIVER_STATE_PRINT_INT(tx_blocks_freed); |
| 475 | DRIVER_STATE_PRINT_INT(rx_counter); | 492 | DRIVER_STATE_PRINT_INT(rx_counter); |
| 476 | DRIVER_STATE_PRINT_INT(state); | 493 | DRIVER_STATE_PRINT_INT(state); |
| 477 | DRIVER_STATE_PRINT_INT(channel); | ||
| 478 | DRIVER_STATE_PRINT_INT(band); | 494 | DRIVER_STATE_PRINT_INT(band); |
| 479 | DRIVER_STATE_PRINT_INT(power_level); | 495 | DRIVER_STATE_PRINT_INT(power_level); |
| 480 | DRIVER_STATE_PRINT_INT(sg_enabled); | 496 | DRIVER_STATE_PRINT_INT(sg_enabled); |
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c index 67f61689b49e..8d3b34965db3 100644 --- a/drivers/net/wireless/ti/wlcore/event.c +++ b/drivers/net/wireless/ti/wlcore/event.c | |||
| @@ -266,6 +266,7 @@ int wl1271_event_unmask(struct wl1271 *wl) | |||
| 266 | { | 266 | { |
| 267 | int ret; | 267 | int ret; |
| 268 | 268 | ||
| 269 | wl1271_debug(DEBUG_EVENT, "unmasking event_mask 0x%x", wl->event_mask); | ||
| 269 | ret = wl1271_acx_event_mbox_mask(wl, ~(wl->event_mask)); | 270 | ret = wl1271_acx_event_mbox_mask(wl, ~(wl->event_mask)); |
| 270 | if (ret < 0) | 271 | if (ret < 0) |
| 271 | return ret; | 272 | return ret; |
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h index 7fd260c02a0a..51f8d634d32f 100644 --- a/drivers/net/wireless/ti/wlcore/hw_ops.h +++ b/drivers/net/wireless/ti/wlcore/hw_ops.h | |||
| @@ -222,6 +222,15 @@ wlcore_hw_set_peer_cap(struct wl1271 *wl, | |||
| 222 | return 0; | 222 | return 0; |
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | static inline u32 | ||
| 226 | wlcore_hw_convert_hwaddr(struct wl1271 *wl, u32 hwaddr) | ||
| 227 | { | ||
| 228 | if (!wl->ops->convert_hwaddr) | ||
| 229 | BUG_ON(1); | ||
| 230 | |||
| 231 | return wl->ops->convert_hwaddr(wl, hwaddr); | ||
| 232 | } | ||
| 233 | |||
| 225 | static inline bool | 234 | static inline bool |
| 226 | wlcore_hw_lnk_high_prio(struct wl1271 *wl, u8 hlid, | 235 | wlcore_hw_lnk_high_prio(struct wl1271 *wl, u8 hlid, |
| 227 | struct wl1271_link *lnk) | 236 | struct wl1271_link *lnk) |
diff --git a/drivers/net/wireless/ti/wlcore/init.c b/drivers/net/wireless/ti/wlcore/init.c index 5c6f11e157d9..7699f9d07e26 100644 --- a/drivers/net/wireless/ti/wlcore/init.c +++ b/drivers/net/wireless/ti/wlcore/init.c | |||
| @@ -571,6 +571,12 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif) | |||
| 571 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | 571 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); |
| 572 | if (ret < 0) | 572 | if (ret < 0) |
| 573 | return ret; | 573 | return ret; |
| 574 | |||
| 575 | /* unmask ap events */ | ||
| 576 | wl->event_mask |= wl->ap_event_mask; | ||
| 577 | ret = wl1271_event_unmask(wl); | ||
| 578 | if (ret < 0) | ||
| 579 | return ret; | ||
| 574 | /* first STA, no APs */ | 580 | /* first STA, no APs */ |
| 575 | } else if (wl->sta_count == 0 && wl->ap_count == 0 && !is_ap) { | 581 | } else if (wl->sta_count == 0 && wl->ap_count == 0 && !is_ap) { |
| 576 | u8 sta_auth = wl->conf.conn.sta_sleep_auth; | 582 | u8 sta_auth = wl->conf.conn.sta_sleep_auth; |
diff --git a/drivers/net/wireless/ti/wlcore/io.h b/drivers/net/wireless/ti/wlcore/io.h index af7d9f9b3b4d..07e3d6a049ad 100644 --- a/drivers/net/wireless/ti/wlcore/io.h +++ b/drivers/net/wireless/ti/wlcore/io.h | |||
| @@ -165,8 +165,8 @@ static inline int __must_check wlcore_read_hwaddr(struct wl1271 *wl, int hwaddr, | |||
| 165 | int physical; | 165 | int physical; |
| 166 | int addr; | 166 | int addr; |
| 167 | 167 | ||
| 168 | /* Addresses are stored internally as addresses to 32 bytes blocks */ | 168 | /* Convert from FW internal address which is chip arch dependent */ |
| 169 | addr = hwaddr << 5; | 169 | addr = wl->ops->convert_hwaddr(wl, hwaddr); |
| 170 | 170 | ||
| 171 | physical = wlcore_translate_addr(wl, addr); | 171 | physical = wlcore_translate_addr(wl, addr); |
| 172 | 172 | ||
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 38995f90040d..0368b9cbfb89 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
| @@ -44,6 +44,7 @@ | |||
| 44 | #define WL1271_BOOT_RETRIES 3 | 44 | #define WL1271_BOOT_RETRIES 3 |
| 45 | 45 | ||
| 46 | static char *fwlog_param; | 46 | static char *fwlog_param; |
| 47 | static int fwlog_mem_blocks = -1; | ||
| 47 | static int bug_on_recovery = -1; | 48 | static int bug_on_recovery = -1; |
| 48 | static int no_recovery = -1; | 49 | static int no_recovery = -1; |
| 49 | 50 | ||
| @@ -291,6 +292,18 @@ static void wlcore_adjust_conf(struct wl1271 *wl) | |||
| 291 | { | 292 | { |
| 292 | /* Adjust settings according to optional module parameters */ | 293 | /* Adjust settings according to optional module parameters */ |
| 293 | 294 | ||
| 295 | /* Firmware Logger params */ | ||
| 296 | if (fwlog_mem_blocks != -1) { | ||
| 297 | if (fwlog_mem_blocks >= CONF_FWLOG_MIN_MEM_BLOCKS && | ||
| 298 | fwlog_mem_blocks <= CONF_FWLOG_MAX_MEM_BLOCKS) { | ||
| 299 | wl->conf.fwlog.mem_blocks = fwlog_mem_blocks; | ||
| 300 | } else { | ||
| 301 | wl1271_error( | ||
| 302 | "Illegal fwlog_mem_blocks=%d using default %d", | ||
| 303 | fwlog_mem_blocks, wl->conf.fwlog.mem_blocks); | ||
| 304 | } | ||
| 305 | } | ||
| 306 | |||
| 294 | if (fwlog_param) { | 307 | if (fwlog_param) { |
| 295 | if (!strcmp(fwlog_param, "continuous")) { | 308 | if (!strcmp(fwlog_param, "continuous")) { |
| 296 | wl->conf.fwlog.mode = WL12XX_FWLOG_CONTINUOUS; | 309 | wl->conf.fwlog.mode = WL12XX_FWLOG_CONTINUOUS; |
| @@ -780,6 +793,7 @@ void wl12xx_queue_recovery_work(struct wl1271 *wl) | |||
| 780 | if (wl->state == WLCORE_STATE_ON) { | 793 | if (wl->state == WLCORE_STATE_ON) { |
| 781 | wl->state = WLCORE_STATE_RESTARTING; | 794 | wl->state = WLCORE_STATE_RESTARTING; |
| 782 | set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); | 795 | set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); |
| 796 | wl1271_ps_elp_wakeup(wl); | ||
| 783 | wlcore_disable_interrupts_nosync(wl); | 797 | wlcore_disable_interrupts_nosync(wl); |
| 784 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | 798 | ieee80211_queue_work(wl->hw, &wl->recovery_work); |
| 785 | } | 799 | } |
| @@ -787,19 +801,10 @@ void wl12xx_queue_recovery_work(struct wl1271 *wl) | |||
| 787 | 801 | ||
| 788 | size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen) | 802 | size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen) |
| 789 | { | 803 | { |
| 790 | size_t len = 0; | 804 | size_t len; |
| 791 | |||
| 792 | /* The FW log is a length-value list, find where the log end */ | ||
| 793 | while (len < maxlen) { | ||
| 794 | if (memblock[len] == 0) | ||
| 795 | break; | ||
| 796 | if (len + memblock[len] + 1 > maxlen) | ||
| 797 | break; | ||
| 798 | len += memblock[len] + 1; | ||
| 799 | } | ||
| 800 | 805 | ||
| 801 | /* Make sure we have enough room */ | 806 | /* Make sure we have enough room */ |
| 802 | len = min(len, (size_t)(PAGE_SIZE - wl->fwlog_size)); | 807 | len = min(maxlen, (size_t)(PAGE_SIZE - wl->fwlog_size)); |
| 803 | 808 | ||
| 804 | /* Fill the FW log file, consumed by the sysfs fwlog entry */ | 809 | /* Fill the FW log file, consumed by the sysfs fwlog entry */ |
| 805 | memcpy(wl->fwlog + wl->fwlog_size, memblock, len); | 810 | memcpy(wl->fwlog + wl->fwlog_size, memblock, len); |
| @@ -808,10 +813,9 @@ size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen) | |||
| 808 | return len; | 813 | return len; |
| 809 | } | 814 | } |
| 810 | 815 | ||
| 811 | #define WLCORE_FW_LOG_END 0x2000000 | ||
| 812 | |||
| 813 | static void wl12xx_read_fwlog_panic(struct wl1271 *wl) | 816 | static void wl12xx_read_fwlog_panic(struct wl1271 *wl) |
| 814 | { | 817 | { |
| 818 | struct wlcore_partition_set part, old_part; | ||
| 815 | u32 addr; | 819 | u32 addr; |
| 816 | u32 offset; | 820 | u32 offset; |
| 817 | u32 end_of_log; | 821 | u32 end_of_log; |
| @@ -824,7 +828,7 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) | |||
| 824 | 828 | ||
| 825 | wl1271_info("Reading FW panic log"); | 829 | wl1271_info("Reading FW panic log"); |
| 826 | 830 | ||
| 827 | block = kmalloc(WL12XX_HW_BLOCK_SIZE, GFP_KERNEL); | 831 | block = kmalloc(wl->fw_mem_block_size, GFP_KERNEL); |
| 828 | if (!block) | 832 | if (!block) |
| 829 | return; | 833 | return; |
| 830 | 834 | ||
| @@ -850,17 +854,31 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) | |||
| 850 | 854 | ||
| 851 | if (wl->conf.fwlog.mode == WL12XX_FWLOG_CONTINUOUS) { | 855 | if (wl->conf.fwlog.mode == WL12XX_FWLOG_CONTINUOUS) { |
| 852 | offset = sizeof(addr) + sizeof(struct wl1271_rx_descriptor); | 856 | offset = sizeof(addr) + sizeof(struct wl1271_rx_descriptor); |
| 853 | end_of_log = WLCORE_FW_LOG_END; | 857 | end_of_log = wl->fwlog_end; |
| 854 | } else { | 858 | } else { |
| 855 | offset = sizeof(addr); | 859 | offset = sizeof(addr); |
| 856 | end_of_log = addr; | 860 | end_of_log = addr; |
| 857 | } | 861 | } |
| 858 | 862 | ||
| 863 | old_part = wl->curr_part; | ||
| 864 | memset(&part, 0, sizeof(part)); | ||
| 865 | |||
| 859 | /* Traverse the memory blocks linked list */ | 866 | /* Traverse the memory blocks linked list */ |
| 860 | do { | 867 | do { |
| 861 | memset(block, 0, WL12XX_HW_BLOCK_SIZE); | 868 | part.mem.start = wlcore_hw_convert_hwaddr(wl, addr); |
| 862 | ret = wlcore_read_hwaddr(wl, addr, block, WL12XX_HW_BLOCK_SIZE, | 869 | part.mem.size = PAGE_SIZE; |
| 863 | false); | 870 | |
| 871 | ret = wlcore_set_partition(wl, &part); | ||
| 872 | if (ret < 0) { | ||
| 873 | wl1271_error("%s: set_partition start=0x%X size=%d", | ||
| 874 | __func__, part.mem.start, part.mem.size); | ||
| 875 | goto out; | ||
| 876 | } | ||
| 877 | |||
| 878 | memset(block, 0, wl->fw_mem_block_size); | ||
| 879 | ret = wlcore_read_hwaddr(wl, addr, block, | ||
| 880 | wl->fw_mem_block_size, false); | ||
| 881 | |||
| 864 | if (ret < 0) | 882 | if (ret < 0) |
| 865 | goto out; | 883 | goto out; |
| 866 | 884 | ||
| @@ -871,8 +889,9 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) | |||
| 871 | * on demand mode and is equal to 0x2000000 in continuous mode. | 889 | * on demand mode and is equal to 0x2000000 in continuous mode. |
| 872 | */ | 890 | */ |
| 873 | addr = le32_to_cpup((__le32 *)block); | 891 | addr = le32_to_cpup((__le32 *)block); |
| 892 | |||
| 874 | if (!wl12xx_copy_fwlog(wl, block + offset, | 893 | if (!wl12xx_copy_fwlog(wl, block + offset, |
| 875 | WL12XX_HW_BLOCK_SIZE - offset)) | 894 | wl->fw_mem_block_size - offset)) |
| 876 | break; | 895 | break; |
| 877 | } while (addr && (addr != end_of_log)); | 896 | } while (addr && (addr != end_of_log)); |
| 878 | 897 | ||
| @@ -880,6 +899,7 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) | |||
| 880 | 899 | ||
| 881 | out: | 900 | out: |
| 882 | kfree(block); | 901 | kfree(block); |
| 902 | wlcore_set_partition(wl, &old_part); | ||
| 883 | } | 903 | } |
| 884 | 904 | ||
| 885 | static void wlcore_print_recovery(struct wl1271 *wl) | 905 | static void wlcore_print_recovery(struct wl1271 *wl) |
| @@ -924,7 +944,8 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
| 924 | goto out_unlock; | 944 | goto out_unlock; |
| 925 | 945 | ||
| 926 | if (!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)) { | 946 | if (!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)) { |
| 927 | wl12xx_read_fwlog_panic(wl); | 947 | if (wl->conf.fwlog.output == WL12XX_FWLOG_OUTPUT_HOST) |
| 948 | wl12xx_read_fwlog_panic(wl); | ||
| 928 | wlcore_print_recovery(wl); | 949 | wlcore_print_recovery(wl); |
| 929 | } | 950 | } |
| 930 | 951 | ||
| @@ -1062,7 +1083,8 @@ int wl1271_plt_start(struct wl1271 *wl, const enum plt_mode plt_mode) | |||
| 1062 | static const char* const PLT_MODE[] = { | 1083 | static const char* const PLT_MODE[] = { |
| 1063 | "PLT_OFF", | 1084 | "PLT_OFF", |
| 1064 | "PLT_ON", | 1085 | "PLT_ON", |
| 1065 | "PLT_FEM_DETECT" | 1086 | "PLT_FEM_DETECT", |
| 1087 | "PLT_CHIP_AWAKE" | ||
| 1066 | }; | 1088 | }; |
| 1067 | 1089 | ||
| 1068 | int ret; | 1090 | int ret; |
| @@ -1088,9 +1110,11 @@ int wl1271_plt_start(struct wl1271 *wl, const enum plt_mode plt_mode) | |||
| 1088 | if (ret < 0) | 1110 | if (ret < 0) |
| 1089 | goto power_off; | 1111 | goto power_off; |
| 1090 | 1112 | ||
| 1091 | ret = wl->ops->plt_init(wl); | 1113 | if (plt_mode != PLT_CHIP_AWAKE) { |
| 1092 | if (ret < 0) | 1114 | ret = wl->ops->plt_init(wl); |
| 1093 | goto power_off; | 1115 | if (ret < 0) |
| 1116 | goto power_off; | ||
| 1117 | } | ||
| 1094 | 1118 | ||
| 1095 | wl->state = WLCORE_STATE_ON; | 1119 | wl->state = WLCORE_STATE_ON; |
| 1096 | wl1271_notice("firmware booted in PLT mode %s (%s)", | 1120 | wl1271_notice("firmware booted in PLT mode %s (%s)", |
| @@ -1925,8 +1949,10 @@ static void wlcore_op_stop_locked(struct wl1271 *wl) | |||
| 1925 | 1949 | ||
| 1926 | /* | 1950 | /* |
| 1927 | * FW channels must be re-calibrated after recovery, | 1951 | * FW channels must be re-calibrated after recovery, |
| 1928 | * clear the last Reg-Domain channel configuration. | 1952 | * save current Reg-Domain channel configuration and clear it. |
| 1929 | */ | 1953 | */ |
| 1954 | memcpy(wl->reg_ch_conf_pending, wl->reg_ch_conf_last, | ||
| 1955 | sizeof(wl->reg_ch_conf_pending)); | ||
| 1930 | memset(wl->reg_ch_conf_last, 0, sizeof(wl->reg_ch_conf_last)); | 1956 | memset(wl->reg_ch_conf_last, 0, sizeof(wl->reg_ch_conf_last)); |
| 1931 | } | 1957 | } |
| 1932 | 1958 | ||
| @@ -2008,6 +2034,47 @@ out: | |||
| 2008 | mutex_unlock(&wl->mutex); | 2034 | mutex_unlock(&wl->mutex); |
| 2009 | } | 2035 | } |
| 2010 | 2036 | ||
| 2037 | static void wlcore_pending_auth_complete_work(struct work_struct *work) | ||
| 2038 | { | ||
| 2039 | struct delayed_work *dwork; | ||
| 2040 | struct wl1271 *wl; | ||
| 2041 | struct wl12xx_vif *wlvif; | ||
| 2042 | unsigned long time_spare; | ||
| 2043 | int ret; | ||
| 2044 | |||
| 2045 | dwork = container_of(work, struct delayed_work, work); | ||
| 2046 | wlvif = container_of(dwork, struct wl12xx_vif, | ||
| 2047 | pending_auth_complete_work); | ||
| 2048 | wl = wlvif->wl; | ||
| 2049 | |||
| 2050 | mutex_lock(&wl->mutex); | ||
| 2051 | |||
| 2052 | if (unlikely(wl->state != WLCORE_STATE_ON)) | ||
| 2053 | goto out; | ||
| 2054 | |||
| 2055 | /* | ||
| 2056 | * Make sure a second really passed since the last auth reply. Maybe | ||
| 2057 | * a second auth reply arrived while we were stuck on the mutex. | ||
| 2058 | * Check for a little less than the timeout to protect from scheduler | ||
| 2059 | * irregularities. | ||
| 2060 | */ | ||
| 2061 | time_spare = jiffies + | ||
| 2062 | msecs_to_jiffies(WLCORE_PEND_AUTH_ROC_TIMEOUT - 50); | ||
| 2063 | if (!time_after(time_spare, wlvif->pending_auth_reply_time)) | ||
| 2064 | goto out; | ||
| 2065 | |||
| 2066 | ret = wl1271_ps_elp_wakeup(wl); | ||
| 2067 | if (ret < 0) | ||
| 2068 | goto out; | ||
| 2069 | |||
| 2070 | /* cancel the ROC if active */ | ||
| 2071 | wlcore_update_inconn_sta(wl, wlvif, NULL, false); | ||
| 2072 | |||
| 2073 | wl1271_ps_elp_sleep(wl); | ||
| 2074 | out: | ||
| 2075 | mutex_unlock(&wl->mutex); | ||
| 2076 | } | ||
| 2077 | |||
| 2011 | static int wl12xx_allocate_rate_policy(struct wl1271 *wl, u8 *idx) | 2078 | static int wl12xx_allocate_rate_policy(struct wl1271 *wl, u8 *idx) |
| 2012 | { | 2079 | { |
| 2013 | u8 policy = find_first_zero_bit(wl->rate_policies_map, | 2080 | u8 policy = find_first_zero_bit(wl->rate_policies_map, |
| @@ -2159,6 +2226,8 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) | |||
| 2159 | wlcore_channel_switch_work); | 2226 | wlcore_channel_switch_work); |
| 2160 | INIT_DELAYED_WORK(&wlvif->connection_loss_work, | 2227 | INIT_DELAYED_WORK(&wlvif->connection_loss_work, |
| 2161 | wlcore_connection_loss_work); | 2228 | wlcore_connection_loss_work); |
| 2229 | INIT_DELAYED_WORK(&wlvif->pending_auth_complete_work, | ||
| 2230 | wlcore_pending_auth_complete_work); | ||
| 2162 | INIT_LIST_HEAD(&wlvif->list); | 2231 | INIT_LIST_HEAD(&wlvif->list); |
| 2163 | 2232 | ||
| 2164 | setup_timer(&wlvif->rx_streaming_timer, wl1271_rx_streaming_timer, | 2233 | setup_timer(&wlvif->rx_streaming_timer, wl1271_rx_streaming_timer, |
| @@ -2376,6 +2445,11 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
| 2376 | int ret = 0; | 2445 | int ret = 0; |
| 2377 | u8 role_type; | 2446 | u8 role_type; |
| 2378 | 2447 | ||
| 2448 | if (wl->plt) { | ||
| 2449 | wl1271_error("Adding Interface not allowed while in PLT mode"); | ||
| 2450 | return -EBUSY; | ||
| 2451 | } | ||
| 2452 | |||
| 2379 | vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER | | 2453 | vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER | |
| 2380 | IEEE80211_VIF_SUPPORTS_CQM_RSSI; | 2454 | IEEE80211_VIF_SUPPORTS_CQM_RSSI; |
| 2381 | 2455 | ||
| @@ -2572,6 +2646,12 @@ deinit: | |||
| 2572 | !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)) | 2646 | !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)) |
| 2573 | goto unlock; | 2647 | goto unlock; |
| 2574 | 2648 | ||
| 2649 | if (wl->ap_count == 0 && is_ap) { | ||
| 2650 | /* mask ap events */ | ||
| 2651 | wl->event_mask &= ~wl->ap_event_mask; | ||
| 2652 | wl1271_event_unmask(wl); | ||
| 2653 | } | ||
| 2654 | |||
| 2575 | if (wl->ap_count == 0 && is_ap && wl->sta_count) { | 2655 | if (wl->ap_count == 0 && is_ap && wl->sta_count) { |
| 2576 | u8 sta_auth = wl->conf.conn.sta_sleep_auth; | 2656 | u8 sta_auth = wl->conf.conn.sta_sleep_auth; |
| 2577 | /* Configure for power according to debugfs */ | 2657 | /* Configure for power according to debugfs */ |
| @@ -2590,6 +2670,7 @@ unlock: | |||
| 2590 | cancel_work_sync(&wlvif->rx_streaming_disable_work); | 2670 | cancel_work_sync(&wlvif->rx_streaming_disable_work); |
| 2591 | cancel_delayed_work_sync(&wlvif->connection_loss_work); | 2671 | cancel_delayed_work_sync(&wlvif->connection_loss_work); |
| 2592 | cancel_delayed_work_sync(&wlvif->channel_switch_work); | 2672 | cancel_delayed_work_sync(&wlvif->channel_switch_work); |
| 2673 | cancel_delayed_work_sync(&wlvif->pending_auth_complete_work); | ||
| 2593 | 2674 | ||
| 2594 | mutex_lock(&wl->mutex); | 2675 | mutex_lock(&wl->mutex); |
| 2595 | } | 2676 | } |
| @@ -2875,6 +2956,25 @@ static void wl1271_set_band_rate(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
| 2875 | wlvif->rate_set = wlvif->basic_rate_set; | 2956 | wlvif->rate_set = wlvif->basic_rate_set; |
| 2876 | } | 2957 | } |
| 2877 | 2958 | ||
| 2959 | static void wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
| 2960 | bool idle) | ||
| 2961 | { | ||
| 2962 | bool cur_idle = !test_bit(WLVIF_FLAG_ACTIVE, &wlvif->flags); | ||
| 2963 | |||
| 2964 | if (idle == cur_idle) | ||
| 2965 | return; | ||
| 2966 | |||
| 2967 | if (idle) { | ||
| 2968 | clear_bit(WLVIF_FLAG_ACTIVE, &wlvif->flags); | ||
| 2969 | } else { | ||
| 2970 | /* The current firmware only supports sched_scan in idle */ | ||
| 2971 | if (wl->sched_vif == wlvif) | ||
| 2972 | wl->ops->sched_scan_stop(wl, wlvif); | ||
| 2973 | |||
| 2974 | set_bit(WLVIF_FLAG_ACTIVE, &wlvif->flags); | ||
| 2975 | } | ||
| 2976 | } | ||
| 2977 | |||
| 2878 | static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 2978 | static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
| 2879 | struct ieee80211_conf *conf, u32 changed) | 2979 | struct ieee80211_conf *conf, u32 changed) |
| 2880 | { | 2980 | { |
| @@ -3969,6 +4069,13 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, | |||
| 3969 | } | 4069 | } |
| 3970 | } else { | 4070 | } else { |
| 3971 | if (test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) { | 4071 | if (test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) { |
| 4072 | /* | ||
| 4073 | * AP might be in ROC in case we have just | ||
| 4074 | * sent auth reply. handle it. | ||
| 4075 | */ | ||
| 4076 | if (test_bit(wlvif->role_id, wl->roc_map)) | ||
| 4077 | wl12xx_croc(wl, wlvif->role_id); | ||
| 4078 | |||
| 3972 | ret = wl12xx_cmd_role_stop_ap(wl, wlvif); | 4079 | ret = wl12xx_cmd_role_stop_ap(wl, wlvif); |
| 3973 | if (ret < 0) | 4080 | if (ret < 0) |
| 3974 | goto out; | 4081 | goto out; |
| @@ -4120,6 +4227,9 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
| 4120 | do_join = true; | 4227 | do_join = true; |
| 4121 | } | 4228 | } |
| 4122 | 4229 | ||
| 4230 | if (changed & BSS_CHANGED_IDLE && !is_ibss) | ||
| 4231 | wl1271_sta_handle_idle(wl, wlvif, bss_conf->idle); | ||
| 4232 | |||
| 4123 | if (changed & BSS_CHANGED_CQM) { | 4233 | if (changed & BSS_CHANGED_CQM) { |
| 4124 | bool enable = false; | 4234 | bool enable = false; |
| 4125 | if (bss_conf->cqm_rssi_thold) | 4235 | if (bss_conf->cqm_rssi_thold) |
| @@ -4656,29 +4766,49 @@ static void wlcore_roc_if_possible(struct wl1271 *wl, | |||
| 4656 | wl12xx_roc(wl, wlvif, wlvif->role_id, wlvif->band, wlvif->channel); | 4766 | wl12xx_roc(wl, wlvif, wlvif->role_id, wlvif->band, wlvif->channel); |
| 4657 | } | 4767 | } |
| 4658 | 4768 | ||
| 4659 | static void wlcore_update_inconn_sta(struct wl1271 *wl, | 4769 | /* |
| 4660 | struct wl12xx_vif *wlvif, | 4770 | * when wl_sta is NULL, we treat this call as if coming from a |
| 4661 | struct wl1271_station *wl_sta, | 4771 | * pending auth reply. |
| 4662 | bool in_connection) | 4772 | * wl->mutex must be taken and the FW must be awake when the call |
| 4773 | * takes place. | ||
| 4774 | */ | ||
| 4775 | void wlcore_update_inconn_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
| 4776 | struct wl1271_station *wl_sta, bool in_conn) | ||
| 4663 | { | 4777 | { |
| 4664 | if (in_connection) { | 4778 | if (in_conn) { |
| 4665 | if (WARN_ON(wl_sta->in_connection)) | 4779 | if (WARN_ON(wl_sta && wl_sta->in_connection)) |
| 4666 | return; | 4780 | return; |
| 4667 | wl_sta->in_connection = true; | 4781 | |
| 4668 | if (!wlvif->inconn_count++) | 4782 | if (!wlvif->ap_pending_auth_reply && |
| 4783 | !wlvif->inconn_count) | ||
| 4669 | wlcore_roc_if_possible(wl, wlvif); | 4784 | wlcore_roc_if_possible(wl, wlvif); |
| 4785 | |||
| 4786 | if (wl_sta) { | ||
| 4787 | wl_sta->in_connection = true; | ||
| 4788 | wlvif->inconn_count++; | ||
| 4789 | } else { | ||
| 4790 | wlvif->ap_pending_auth_reply = true; | ||
| 4791 | } | ||
| 4670 | } else { | 4792 | } else { |
| 4671 | if (!wl_sta->in_connection) | 4793 | if (wl_sta && !wl_sta->in_connection) |
| 4672 | return; | 4794 | return; |
| 4673 | 4795 | ||
| 4674 | wl_sta->in_connection = false; | 4796 | if (WARN_ON(!wl_sta && !wlvif->ap_pending_auth_reply)) |
| 4675 | wlvif->inconn_count--; | ||
| 4676 | if (WARN_ON(wlvif->inconn_count < 0)) | ||
| 4677 | return; | 4797 | return; |
| 4678 | 4798 | ||
| 4679 | if (!wlvif->inconn_count) | 4799 | if (WARN_ON(wl_sta && !wlvif->inconn_count)) |
| 4680 | if (test_bit(wlvif->role_id, wl->roc_map)) | 4800 | return; |
| 4681 | wl12xx_croc(wl, wlvif->role_id); | 4801 | |
| 4802 | if (wl_sta) { | ||
| 4803 | wl_sta->in_connection = false; | ||
| 4804 | wlvif->inconn_count--; | ||
| 4805 | } else { | ||
| 4806 | wlvif->ap_pending_auth_reply = false; | ||
| 4807 | } | ||
| 4808 | |||
| 4809 | if (!wlvif->inconn_count && !wlvif->ap_pending_auth_reply && | ||
| 4810 | test_bit(wlvif->role_id, wl->roc_map)) | ||
| 4811 | wl12xx_croc(wl, wlvif->role_id); | ||
| 4682 | } | 4812 | } |
| 4683 | } | 4813 | } |
| 4684 | 4814 | ||
| @@ -5313,10 +5443,7 @@ static struct ieee80211_rate wl1271_rates_5ghz[] = { | |||
| 5313 | 5443 | ||
| 5314 | /* 5 GHz band channels for WL1273 */ | 5444 | /* 5 GHz band channels for WL1273 */ |
| 5315 | static struct ieee80211_channel wl1271_channels_5ghz[] = { | 5445 | static struct ieee80211_channel wl1271_channels_5ghz[] = { |
| 5316 | { .hw_value = 7, .center_freq = 5035, .max_power = WLCORE_MAX_TXPWR }, | ||
| 5317 | { .hw_value = 8, .center_freq = 5040, .max_power = WLCORE_MAX_TXPWR }, | 5446 | { .hw_value = 8, .center_freq = 5040, .max_power = WLCORE_MAX_TXPWR }, |
| 5318 | { .hw_value = 9, .center_freq = 5045, .max_power = WLCORE_MAX_TXPWR }, | ||
| 5319 | { .hw_value = 11, .center_freq = 5055, .max_power = WLCORE_MAX_TXPWR }, | ||
| 5320 | { .hw_value = 12, .center_freq = 5060, .max_power = WLCORE_MAX_TXPWR }, | 5447 | { .hw_value = 12, .center_freq = 5060, .max_power = WLCORE_MAX_TXPWR }, |
| 5321 | { .hw_value = 16, .center_freq = 5080, .max_power = WLCORE_MAX_TXPWR }, | 5448 | { .hw_value = 16, .center_freq = 5080, .max_power = WLCORE_MAX_TXPWR }, |
| 5322 | { .hw_value = 34, .center_freq = 5170, .max_power = WLCORE_MAX_TXPWR }, | 5449 | { .hw_value = 34, .center_freq = 5170, .max_power = WLCORE_MAX_TXPWR }, |
| @@ -5896,14 +6023,20 @@ static const struct wiphy_wowlan_support wlcore_wowlan_support = { | |||
| 5896 | }; | 6023 | }; |
| 5897 | #endif | 6024 | #endif |
| 5898 | 6025 | ||
| 6026 | static irqreturn_t wlcore_hardirq(int irq, void *cookie) | ||
| 6027 | { | ||
| 6028 | return IRQ_WAKE_THREAD; | ||
| 6029 | } | ||
| 6030 | |||
| 5899 | static void wlcore_nvs_cb(const struct firmware *fw, void *context) | 6031 | static void wlcore_nvs_cb(const struct firmware *fw, void *context) |
| 5900 | { | 6032 | { |
| 5901 | struct wl1271 *wl = context; | 6033 | struct wl1271 *wl = context; |
| 5902 | struct platform_device *pdev = wl->pdev; | 6034 | struct platform_device *pdev = wl->pdev; |
| 5903 | struct wlcore_platdev_data *pdev_data = pdev->dev.platform_data; | 6035 | struct wlcore_platdev_data *pdev_data = dev_get_platdata(&pdev->dev); |
| 5904 | struct wl12xx_platform_data *pdata = pdev_data->pdata; | 6036 | struct wl12xx_platform_data *pdata = pdev_data->pdata; |
| 5905 | unsigned long irqflags; | 6037 | unsigned long irqflags; |
| 5906 | int ret; | 6038 | int ret; |
| 6039 | irq_handler_t hardirq_fn = NULL; | ||
| 5907 | 6040 | ||
| 5908 | if (fw) { | 6041 | if (fw) { |
| 5909 | wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL); | 6042 | wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL); |
| @@ -5932,12 +6065,14 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context) | |||
| 5932 | wl->platform_quirks = pdata->platform_quirks; | 6065 | wl->platform_quirks = pdata->platform_quirks; |
| 5933 | wl->if_ops = pdev_data->if_ops; | 6066 | wl->if_ops = pdev_data->if_ops; |
| 5934 | 6067 | ||
| 5935 | if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) | 6068 | if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) { |
| 5936 | irqflags = IRQF_TRIGGER_RISING; | 6069 | irqflags = IRQF_TRIGGER_RISING; |
| 5937 | else | 6070 | hardirq_fn = wlcore_hardirq; |
| 6071 | } else { | ||
| 5938 | irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; | 6072 | irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; |
| 6073 | } | ||
| 5939 | 6074 | ||
| 5940 | ret = request_threaded_irq(wl->irq, NULL, wlcore_irq, | 6075 | ret = request_threaded_irq(wl->irq, hardirq_fn, wlcore_irq, |
| 5941 | irqflags, pdev->name, wl); | 6076 | irqflags, pdev->name, wl); |
| 5942 | if (ret < 0) { | 6077 | if (ret < 0) { |
| 5943 | wl1271_error("request_irq() failed: %d", ret); | 6078 | wl1271_error("request_irq() failed: %d", ret); |
| @@ -6046,6 +6181,9 @@ module_param_named(fwlog, fwlog_param, charp, 0); | |||
| 6046 | MODULE_PARM_DESC(fwlog, | 6181 | MODULE_PARM_DESC(fwlog, |
| 6047 | "FW logger options: continuous, ondemand, dbgpins or disable"); | 6182 | "FW logger options: continuous, ondemand, dbgpins or disable"); |
| 6048 | 6183 | ||
| 6184 | module_param(fwlog_mem_blocks, int, S_IRUSR | S_IWUSR); | ||
| 6185 | MODULE_PARM_DESC(fwlog_mem_blocks, "fwlog mem_blocks"); | ||
| 6186 | |||
| 6049 | module_param(bug_on_recovery, int, S_IRUSR | S_IWUSR); | 6187 | module_param(bug_on_recovery, int, S_IRUSR | S_IWUSR); |
| 6050 | MODULE_PARM_DESC(bug_on_recovery, "BUG() on fw recovery"); | 6188 | MODULE_PARM_DESC(bug_on_recovery, "BUG() on fw recovery"); |
| 6051 | 6189 | ||
diff --git a/drivers/net/wireless/ti/wlcore/ps.c b/drivers/net/wireless/ti/wlcore/ps.c index 98066d40c2ad..26bfc365ba70 100644 --- a/drivers/net/wireless/ti/wlcore/ps.c +++ b/drivers/net/wireless/ti/wlcore/ps.c | |||
| @@ -83,6 +83,10 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl) | |||
| 83 | struct wl12xx_vif *wlvif; | 83 | struct wl12xx_vif *wlvif; |
| 84 | u32 timeout; | 84 | u32 timeout; |
| 85 | 85 | ||
| 86 | /* We do not enter elp sleep in PLT mode */ | ||
| 87 | if (wl->plt) | ||
| 88 | return; | ||
| 89 | |||
| 86 | if (wl->sleep_auth != WL1271_PSM_ELP) | 90 | if (wl->sleep_auth != WL1271_PSM_ELP) |
| 87 | return; | 91 | return; |
| 88 | 92 | ||
diff --git a/drivers/net/wireless/ti/wlcore/scan.c b/drivers/net/wireless/ti/wlcore/scan.c index f407101e525b..7ed86203304b 100644 --- a/drivers/net/wireless/ti/wlcore/scan.c +++ b/drivers/net/wireless/ti/wlcore/scan.c | |||
| @@ -92,9 +92,31 @@ out: | |||
| 92 | static void wlcore_started_vifs_iter(void *data, u8 *mac, | 92 | static void wlcore_started_vifs_iter(void *data, u8 *mac, |
| 93 | struct ieee80211_vif *vif) | 93 | struct ieee80211_vif *vif) |
| 94 | { | 94 | { |
| 95 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
| 96 | bool active = false; | ||
| 95 | int *count = (int *)data; | 97 | int *count = (int *)data; |
| 96 | 98 | ||
| 97 | if (!vif->bss_conf.idle) | 99 | /* |
| 100 | * count active interfaces according to interface type. | ||
| 101 | * checking only bss_conf.idle is bad for some cases, e.g. | ||
| 102 | * we don't want to count sta in p2p_find as active interface. | ||
| 103 | */ | ||
| 104 | switch (wlvif->bss_type) { | ||
| 105 | case BSS_TYPE_STA_BSS: | ||
| 106 | if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) | ||
| 107 | active = true; | ||
| 108 | break; | ||
| 109 | |||
| 110 | case BSS_TYPE_AP_BSS: | ||
| 111 | if (wlvif->wl->active_sta_count > 0) | ||
| 112 | active = true; | ||
| 113 | break; | ||
| 114 | |||
| 115 | default: | ||
| 116 | break; | ||
| 117 | } | ||
| 118 | |||
| 119 | if (active) | ||
| 98 | (*count)++; | 120 | (*count)++; |
| 99 | } | 121 | } |
| 100 | 122 | ||
| @@ -174,17 +196,7 @@ wlcore_scan_get_channels(struct wl1271 *wl, | |||
| 174 | /* if radar is set, we ignore the passive flag */ | 196 | /* if radar is set, we ignore the passive flag */ |
| 175 | (radar || | 197 | (radar || |
| 176 | !!(flags & IEEE80211_CHAN_PASSIVE_SCAN) == passive)) { | 198 | !!(flags & IEEE80211_CHAN_PASSIVE_SCAN) == passive)) { |
| 177 | wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ", | 199 | |
| 178 | req_channels[i]->band, | ||
| 179 | req_channels[i]->center_freq); | ||
| 180 | wl1271_debug(DEBUG_SCAN, "hw_value %d, flags %X", | ||
| 181 | req_channels[i]->hw_value, | ||
| 182 | req_channels[i]->flags); | ||
| 183 | wl1271_debug(DEBUG_SCAN, "max_power %d", | ||
| 184 | req_channels[i]->max_power); | ||
| 185 | wl1271_debug(DEBUG_SCAN, "min_dwell_time %d max dwell time %d", | ||
| 186 | min_dwell_time_active, | ||
| 187 | max_dwell_time_active); | ||
| 188 | 200 | ||
| 189 | if (flags & IEEE80211_CHAN_RADAR) { | 201 | if (flags & IEEE80211_CHAN_RADAR) { |
| 190 | channels[j].flags |= SCAN_CHANNEL_FLAGS_DFS; | 202 | channels[j].flags |= SCAN_CHANNEL_FLAGS_DFS; |
| @@ -222,6 +234,17 @@ wlcore_scan_get_channels(struct wl1271 *wl, | |||
| 222 | *n_pactive_ch); | 234 | *n_pactive_ch); |
| 223 | } | 235 | } |
| 224 | 236 | ||
| 237 | wl1271_debug(DEBUG_SCAN, "freq %d, ch. %d, flags 0x%x, power %d, min/max_dwell %d/%d%s%s", | ||
| 238 | req_channels[i]->center_freq, | ||
| 239 | req_channels[i]->hw_value, | ||
| 240 | req_channels[i]->flags, | ||
| 241 | req_channels[i]->max_power, | ||
| 242 | min_dwell_time_active, | ||
| 243 | max_dwell_time_active, | ||
| 244 | flags & IEEE80211_CHAN_RADAR ? | ||
| 245 | ", DFS" : "", | ||
| 246 | flags & IEEE80211_CHAN_PASSIVE_SCAN ? | ||
| 247 | ", PASSIVE" : ""); | ||
| 225 | j++; | 248 | j++; |
| 226 | } | 249 | } |
| 227 | } | 250 | } |
| @@ -364,7 +387,7 @@ wlcore_scan_sched_scan_ssid_list(struct wl1271 *wl, | |||
| 364 | struct cfg80211_ssid *ssids = req->ssids; | 387 | struct cfg80211_ssid *ssids = req->ssids; |
| 365 | int ret = 0, type, i, j, n_match_ssids = 0; | 388 | int ret = 0, type, i, j, n_match_ssids = 0; |
| 366 | 389 | ||
| 367 | wl1271_debug(DEBUG_CMD, "cmd sched scan ssid list"); | 390 | wl1271_debug((DEBUG_CMD | DEBUG_SCAN), "cmd sched scan ssid list"); |
| 368 | 391 | ||
| 369 | /* count the match sets that contain SSIDs */ | 392 | /* count the match sets that contain SSIDs */ |
| 370 | for (i = 0; i < req->n_match_sets; i++) | 393 | for (i = 0; i < req->n_match_sets; i++) |
| @@ -442,8 +465,6 @@ wlcore_scan_sched_scan_ssid_list(struct wl1271 *wl, | |||
| 442 | } | 465 | } |
| 443 | } | 466 | } |
| 444 | 467 | ||
| 445 | wl1271_dump(DEBUG_SCAN, "SSID_LIST: ", cmd, sizeof(*cmd)); | ||
| 446 | |||
| 447 | ret = wl1271_cmd_send(wl, CMD_CONNECTION_SCAN_SSID_CFG, cmd, | 468 | ret = wl1271_cmd_send(wl, CMD_CONNECTION_SCAN_SSID_CFG, cmd, |
| 448 | sizeof(*cmd), 0); | 469 | sizeof(*cmd), 0); |
| 449 | if (ret < 0) { | 470 | if (ret < 0) { |
diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index 1b0cd98e35f1..b2c018dccf18 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c | |||
| @@ -335,7 +335,7 @@ static int wl1271_probe(struct spi_device *spi) | |||
| 335 | if (!pdev_data) | 335 | if (!pdev_data) |
| 336 | goto out; | 336 | goto out; |
| 337 | 337 | ||
| 338 | pdev_data->pdata = spi->dev.platform_data; | 338 | pdev_data->pdata = dev_get_platdata(&spi->dev); |
| 339 | if (!pdev_data->pdata) { | 339 | if (!pdev_data->pdata) { |
| 340 | dev_err(&spi->dev, "no platform data\n"); | 340 | dev_err(&spi->dev, "no platform data\n"); |
| 341 | ret = -ENODEV; | 341 | ret = -ENODEV; |
diff --git a/drivers/net/wireless/ti/wlcore/testmode.c b/drivers/net/wireless/ti/wlcore/testmode.c index 527590f2adfb..ddad58f614da 100644 --- a/drivers/net/wireless/ti/wlcore/testmode.c +++ b/drivers/net/wireless/ti/wlcore/testmode.c | |||
| @@ -179,7 +179,8 @@ static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[]) | |||
| 179 | goto out_sleep; | 179 | goto out_sleep; |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | ret = wl1271_cmd_interrogate(wl, ie_id, cmd, sizeof(*cmd)); | 182 | ret = wl1271_cmd_interrogate(wl, ie_id, cmd, |
| 183 | sizeof(struct acx_header), sizeof(*cmd)); | ||
| 183 | if (ret < 0) { | 184 | if (ret < 0) { |
| 184 | wl1271_warning("testmode cmd interrogate failed: %d", ret); | 185 | wl1271_warning("testmode cmd interrogate failed: %d", ret); |
| 185 | goto out_free; | 186 | goto out_free; |
| @@ -297,7 +298,8 @@ static int wl1271_tm_cmd_set_plt_mode(struct wl1271 *wl, struct nlattr *tb[]) | |||
| 297 | ret = wl1271_plt_stop(wl); | 298 | ret = wl1271_plt_stop(wl); |
| 298 | break; | 299 | break; |
| 299 | case PLT_ON: | 300 | case PLT_ON: |
| 300 | ret = wl1271_plt_start(wl, PLT_ON); | 301 | case PLT_CHIP_AWAKE: |
| 302 | ret = wl1271_plt_start(wl, val); | ||
| 301 | break; | 303 | break; |
| 302 | case PLT_FEM_DETECT: | 304 | case PLT_FEM_DETECT: |
| 303 | ret = wl1271_tm_detect_fem(wl, tb); | 305 | ret = wl1271_tm_detect_fem(wl, tb); |
| @@ -361,6 +363,7 @@ int wl1271_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
| 361 | { | 363 | { |
| 362 | struct wl1271 *wl = hw->priv; | 364 | struct wl1271 *wl = hw->priv; |
| 363 | struct nlattr *tb[WL1271_TM_ATTR_MAX + 1]; | 365 | struct nlattr *tb[WL1271_TM_ATTR_MAX + 1]; |
| 366 | u32 nla_cmd; | ||
| 364 | int err; | 367 | int err; |
| 365 | 368 | ||
| 366 | err = nla_parse(tb, WL1271_TM_ATTR_MAX, data, len, wl1271_tm_policy); | 369 | err = nla_parse(tb, WL1271_TM_ATTR_MAX, data, len, wl1271_tm_policy); |
| @@ -370,7 +373,14 @@ int wl1271_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
| 370 | if (!tb[WL1271_TM_ATTR_CMD_ID]) | 373 | if (!tb[WL1271_TM_ATTR_CMD_ID]) |
| 371 | return -EINVAL; | 374 | return -EINVAL; |
| 372 | 375 | ||
| 373 | switch (nla_get_u32(tb[WL1271_TM_ATTR_CMD_ID])) { | 376 | nla_cmd = nla_get_u32(tb[WL1271_TM_ATTR_CMD_ID]); |
| 377 | |||
| 378 | /* Only SET_PLT_MODE is allowed in case of mode PLT_CHIP_AWAKE */ | ||
| 379 | if (wl->plt_mode == PLT_CHIP_AWAKE && | ||
| 380 | nla_cmd != WL1271_TM_CMD_SET_PLT_MODE) | ||
| 381 | return -EOPNOTSUPP; | ||
| 382 | |||
| 383 | switch (nla_cmd) { | ||
| 374 | case WL1271_TM_CMD_TEST: | 384 | case WL1271_TM_CMD_TEST: |
| 375 | return wl1271_tm_cmd_test(wl, tb); | 385 | return wl1271_tm_cmd_test(wl, tb); |
| 376 | case WL1271_TM_CMD_INTERROGATE: | 386 | case WL1271_TM_CMD_INTERROGATE: |
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index 7e93fe63a2c7..87cd707affa2 100644 --- a/drivers/net/wireless/ti/wlcore/tx.c +++ b/drivers/net/wireless/ti/wlcore/tx.c | |||
| @@ -86,19 +86,34 @@ void wl1271_free_tx_id(struct wl1271 *wl, int id) | |||
| 86 | EXPORT_SYMBOL(wl1271_free_tx_id); | 86 | EXPORT_SYMBOL(wl1271_free_tx_id); |
| 87 | 87 | ||
| 88 | static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl, | 88 | static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl, |
| 89 | struct wl12xx_vif *wlvif, | ||
| 89 | struct sk_buff *skb) | 90 | struct sk_buff *skb) |
| 90 | { | 91 | { |
| 91 | struct ieee80211_hdr *hdr; | 92 | struct ieee80211_hdr *hdr; |
| 92 | 93 | ||
| 94 | hdr = (struct ieee80211_hdr *)(skb->data + | ||
| 95 | sizeof(struct wl1271_tx_hw_descr)); | ||
| 96 | if (!ieee80211_is_auth(hdr->frame_control)) | ||
| 97 | return; | ||
| 98 | |||
| 93 | /* | 99 | /* |
| 94 | * add the station to the known list before transmitting the | 100 | * add the station to the known list before transmitting the |
| 95 | * authentication response. this way it won't get de-authed by FW | 101 | * authentication response. this way it won't get de-authed by FW |
| 96 | * when transmitting too soon. | 102 | * when transmitting too soon. |
| 97 | */ | 103 | */ |
| 98 | hdr = (struct ieee80211_hdr *)(skb->data + | 104 | wl1271_acx_set_inconnection_sta(wl, hdr->addr1); |
| 99 | sizeof(struct wl1271_tx_hw_descr)); | 105 | |
| 100 | if (ieee80211_is_auth(hdr->frame_control)) | 106 | /* |
| 101 | wl1271_acx_set_inconnection_sta(wl, hdr->addr1); | 107 | * ROC for 1 second on the AP channel for completing the connection. |
| 108 | * Note the ROC will be continued by the update_sta_state callbacks | ||
| 109 | * once the station reaches the associated state. | ||
| 110 | */ | ||
| 111 | wlcore_update_inconn_sta(wl, wlvif, NULL, true); | ||
| 112 | wlvif->pending_auth_reply_time = jiffies; | ||
| 113 | cancel_delayed_work(&wlvif->pending_auth_complete_work); | ||
| 114 | ieee80211_queue_delayed_work(wl->hw, | ||
| 115 | &wlvif->pending_auth_complete_work, | ||
| 116 | msecs_to_jiffies(WLCORE_PEND_AUTH_ROC_TIMEOUT)); | ||
| 102 | } | 117 | } |
| 103 | 118 | ||
| 104 | static void wl1271_tx_regulate_link(struct wl1271 *wl, | 119 | static void wl1271_tx_regulate_link(struct wl1271 *wl, |
| @@ -386,7 +401,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
| 386 | is_wep = (cipher == WLAN_CIPHER_SUITE_WEP40) || | 401 | is_wep = (cipher == WLAN_CIPHER_SUITE_WEP40) || |
| 387 | (cipher == WLAN_CIPHER_SUITE_WEP104); | 402 | (cipher == WLAN_CIPHER_SUITE_WEP104); |
| 388 | 403 | ||
| 389 | if (WARN_ON(is_wep && wlvif->default_key != idx)) { | 404 | if (WARN_ON(is_wep && wlvif && wlvif->default_key != idx)) { |
| 390 | ret = wl1271_set_default_wep_key(wl, wlvif, idx); | 405 | ret = wl1271_set_default_wep_key(wl, wlvif, idx); |
| 391 | if (ret < 0) | 406 | if (ret < 0) |
| 392 | return ret; | 407 | return ret; |
| @@ -404,7 +419,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
| 404 | wl1271_tx_fill_hdr(wl, wlvif, skb, extra, info, hlid); | 419 | wl1271_tx_fill_hdr(wl, wlvif, skb, extra, info, hlid); |
| 405 | 420 | ||
| 406 | if (!is_dummy && wlvif && wlvif->bss_type == BSS_TYPE_AP_BSS) { | 421 | if (!is_dummy && wlvif && wlvif->bss_type == BSS_TYPE_AP_BSS) { |
| 407 | wl1271_tx_ap_update_inconnection_sta(wl, skb); | 422 | wl1271_tx_ap_update_inconnection_sta(wl, wlvif, skb); |
| 408 | wl1271_tx_regulate_link(wl, wlvif, hlid); | 423 | wl1271_tx_regulate_link(wl, wlvif, hlid); |
| 409 | } | 424 | } |
| 410 | 425 | ||
diff --git a/drivers/net/wireless/ti/wlcore/tx.h b/drivers/net/wireless/ti/wlcore/tx.h index 55aa4acf9105..35489c300da1 100644 --- a/drivers/net/wireless/ti/wlcore/tx.h +++ b/drivers/net/wireless/ti/wlcore/tx.h | |||
| @@ -56,6 +56,9 @@ | |||
| 56 | /* Used for management frames and dummy packets */ | 56 | /* Used for management frames and dummy packets */ |
| 57 | #define WL1271_TID_MGMT 7 | 57 | #define WL1271_TID_MGMT 7 |
| 58 | 58 | ||
| 59 | /* stop a ROC for pending authentication reply after this time (ms) */ | ||
| 60 | #define WLCORE_PEND_AUTH_ROC_TIMEOUT 1000 | ||
| 61 | |||
| 59 | struct wl127x_tx_mem { | 62 | struct wl127x_tx_mem { |
| 60 | /* | 63 | /* |
| 61 | * Number of extra memory blocks to allocate for this packet | 64 | * Number of extra memory blocks to allocate for this packet |
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index 0034979e97cb..06efc12a39e5 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h | |||
| @@ -110,6 +110,7 @@ struct wlcore_ops { | |||
| 110 | struct ieee80211_sta_ht_cap *ht_cap, | 110 | struct ieee80211_sta_ht_cap *ht_cap, |
| 111 | bool allow_ht_operation, | 111 | bool allow_ht_operation, |
| 112 | u32 rate_set, u8 hlid); | 112 | u32 rate_set, u8 hlid); |
| 113 | u32 (*convert_hwaddr)(struct wl1271 *wl, u32 hwaddr); | ||
| 113 | bool (*lnk_high_prio)(struct wl1271 *wl, u8 hlid, | 114 | bool (*lnk_high_prio)(struct wl1271 *wl, u8 hlid, |
| 114 | struct wl1271_link *lnk); | 115 | struct wl1271_link *lnk); |
| 115 | bool (*lnk_low_prio)(struct wl1271 *wl, u8 hlid, | 116 | bool (*lnk_low_prio)(struct wl1271 *wl, u8 hlid, |
| @@ -290,6 +291,12 @@ struct wl1271 { | |||
| 290 | /* Number of valid bytes in the FW log buffer */ | 291 | /* Number of valid bytes in the FW log buffer */ |
| 291 | ssize_t fwlog_size; | 292 | ssize_t fwlog_size; |
| 292 | 293 | ||
| 294 | /* FW log end marker */ | ||
| 295 | u32 fwlog_end; | ||
| 296 | |||
| 297 | /* FW memory block size */ | ||
| 298 | u32 fw_mem_block_size; | ||
| 299 | |||
| 293 | /* Sysfs FW log entry readers wait queue */ | 300 | /* Sysfs FW log entry readers wait queue */ |
| 294 | wait_queue_head_t fwlog_waitq; | 301 | wait_queue_head_t fwlog_waitq; |
| 295 | 302 | ||
| @@ -307,6 +314,8 @@ struct wl1271 { | |||
| 307 | 314 | ||
| 308 | /* The mbox event mask */ | 315 | /* The mbox event mask */ |
| 309 | u32 event_mask; | 316 | u32 event_mask; |
| 317 | /* events to unmask only when ap interface is up */ | ||
| 318 | u32 ap_event_mask; | ||
| 310 | 319 | ||
| 311 | /* Mailbox pointers */ | 320 | /* Mailbox pointers */ |
| 312 | u32 mbox_size; | 321 | u32 mbox_size; |
| @@ -481,6 +490,8 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, | |||
| 481 | struct ieee80211_sta *sta, | 490 | struct ieee80211_sta *sta, |
| 482 | struct ieee80211_key_conf *key_conf); | 491 | struct ieee80211_key_conf *key_conf); |
| 483 | void wlcore_regdomain_config(struct wl1271 *wl); | 492 | void wlcore_regdomain_config(struct wl1271 *wl); |
| 493 | void wlcore_update_inconn_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
| 494 | struct wl1271_station *wl_sta, bool in_conn); | ||
| 484 | 495 | ||
| 485 | static inline void | 496 | static inline void |
| 486 | wlcore_set_ht_cap(struct wl1271 *wl, enum ieee80211_band band, | 497 | wlcore_set_ht_cap(struct wl1271 *wl, enum ieee80211_band band, |
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h index e5e146435fe7..ce7261ce8b59 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h | |||
| @@ -255,6 +255,7 @@ enum wl12xx_vif_flags { | |||
| 255 | WLVIF_FLAG_CS_PROGRESS, | 255 | WLVIF_FLAG_CS_PROGRESS, |
| 256 | WLVIF_FLAG_AP_PROBE_RESP_SET, | 256 | WLVIF_FLAG_AP_PROBE_RESP_SET, |
| 257 | WLVIF_FLAG_IN_USE, | 257 | WLVIF_FLAG_IN_USE, |
| 258 | WLVIF_FLAG_ACTIVE, | ||
| 258 | }; | 259 | }; |
| 259 | 260 | ||
| 260 | struct wl12xx_vif; | 261 | struct wl12xx_vif; |
| @@ -307,6 +308,7 @@ enum plt_mode { | |||
| 307 | PLT_OFF = 0, | 308 | PLT_OFF = 0, |
| 308 | PLT_ON = 1, | 309 | PLT_ON = 1, |
| 309 | PLT_FEM_DETECT = 2, | 310 | PLT_FEM_DETECT = 2, |
| 311 | PLT_CHIP_AWAKE = 3 | ||
| 310 | }; | 312 | }; |
| 311 | 313 | ||
| 312 | struct wl12xx_rx_filter_field { | 314 | struct wl12xx_rx_filter_field { |
| @@ -456,6 +458,15 @@ struct wl12xx_vif { | |||
| 456 | */ | 458 | */ |
| 457 | int hw_queue_base; | 459 | int hw_queue_base; |
| 458 | 460 | ||
| 461 | /* do we have a pending auth reply? (and ROC) */ | ||
| 462 | bool ap_pending_auth_reply; | ||
| 463 | |||
| 464 | /* time when we sent the pending auth reply */ | ||
| 465 | unsigned long pending_auth_reply_time; | ||
| 466 | |||
| 467 | /* work for canceling ROC after pending auth reply */ | ||
| 468 | struct delayed_work pending_auth_complete_work; | ||
| 469 | |||
| 459 | /* | 470 | /* |
| 460 | * This struct must be last! | 471 | * This struct must be last! |
| 461 | * data that has to be saved acrossed reconfigs (e.g. recovery) | 472 | * data that has to be saved acrossed reconfigs (e.g. recovery) |
| @@ -539,6 +550,4 @@ void wl1271_rx_filter_flatten_fields(struct wl12xx_rx_filter *filter, | |||
| 539 | #define HW_HT_RATES_OFFSET 16 | 550 | #define HW_HT_RATES_OFFSET 16 |
| 540 | #define HW_MIMO_RATES_OFFSET 24 | 551 | #define HW_MIMO_RATES_OFFSET 24 |
| 541 | 552 | ||
| 542 | #define WL12XX_HW_BLOCK_SIZE 256 | ||
| 543 | |||
| 544 | #endif /* __WLCORE_I_H__ */ | 553 | #endif /* __WLCORE_I_H__ */ |
