Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless

Conflicts:
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/iwlwifi/dvm/tx.c

+6497 -217
+8
MAINTAINERS
··· 1353 1353 S: Supported 1354 1354 F: drivers/net/wireless/ath/ath9k/ 1355 1355 1356 + WILOCITY WIL6210 WIRELESS DRIVER 1357 + M: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com> 1358 + L: linux-wireless@vger.kernel.org 1359 + L: wil6210@qca.qualcomm.com 1360 + S: Supported 1361 + W: http://wireless.kernel.org/en/users/Drivers/wil6210 1362 + F: drivers/net/wireless/ath/wil6210/ 1363 + 1356 1364 CARL9170 LINUX COMMUNITY WIRELESS DRIVER 1357 1365 M: Christian Lamparter <chunkeey@googlemail.com> 1358 1366 L: linux-wireless@vger.kernel.org
+1 -2
drivers/bcma/Kconfig
··· 67 67 68 68 config BCMA_DRIVER_GPIO 69 69 bool "BCMA GPIO driver" 70 - depends on BCMA 71 - select GPIOLIB 70 + depends on BCMA && GPIOLIB 72 71 help 73 72 Driver to provide access to the GPIO pins of the bcma bus. 74 73
+1 -1
drivers/bcma/driver_chipcommon_sflash.c
··· 35 35 { "M25P40", 0x12, 0x10000, 8, }, 36 36 37 37 { "M25P16", 0x14, 0x10000, 32, }, 38 - { "M25P32", 0x14, 0x10000, 64, }, 38 + { "M25P32", 0x15, 0x10000, 64, }, 39 39 { "M25P64", 0x16, 0x10000, 128, }, 40 40 { "M25FL128", 0x17, 0x10000, 256, }, 41 41 { 0 },
+10
drivers/bluetooth/ath3k.c
··· 77 77 { USB_DEVICE(0x0CF3, 0x311D) }, 78 78 { USB_DEVICE(0x13d3, 0x3375) }, 79 79 { USB_DEVICE(0x04CA, 0x3005) }, 80 + { USB_DEVICE(0x04CA, 0x3006) }, 81 + { USB_DEVICE(0x04CA, 0x3008) }, 80 82 { USB_DEVICE(0x13d3, 0x3362) }, 81 83 { USB_DEVICE(0x0CF3, 0xE004) }, 82 84 { USB_DEVICE(0x0930, 0x0219) }, 83 85 { USB_DEVICE(0x0489, 0xe057) }, 86 + { USB_DEVICE(0x13d3, 0x3393) }, 87 + { USB_DEVICE(0x0489, 0xe04e) }, 88 + { USB_DEVICE(0x0489, 0xe056) }, 84 89 85 90 /* Atheros AR5BBU12 with sflash firmware */ 86 91 { USB_DEVICE(0x0489, 0xE02C) }, ··· 109 104 { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, 110 105 { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, 111 106 { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, 107 + { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, 108 + { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, 112 109 { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, 113 110 { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, 114 111 { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, 115 112 { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, 113 + { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, 114 + { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, 115 + { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, 116 116 117 117 /* Atheros AR5BBU22 with sflash firmware */ 118 118 { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
+5
drivers/bluetooth/btusb.c
··· 135 135 { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, 136 136 { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, 137 137 { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, 138 + { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, 139 + { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, 138 140 { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, 139 141 { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, 140 142 { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, 141 143 { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, 144 + { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, 145 + { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, 146 + { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, 142 147 143 148 /* Atheros AR5BBU12 with sflash firmware */ 144 149 { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
+1
drivers/net/wireless/ath/Kconfig
··· 30 30 source "drivers/net/wireless/ath/carl9170/Kconfig" 31 31 source "drivers/net/wireless/ath/ath6kl/Kconfig" 32 32 source "drivers/net/wireless/ath/ar5523/Kconfig" 33 + source "drivers/net/wireless/ath/wil6210/Kconfig" 33 34 34 35 endif
+1
drivers/net/wireless/ath/Makefile
··· 3 3 obj-$(CONFIG_CARL9170) += carl9170/ 4 4 obj-$(CONFIG_ATH6KL) += ath6kl/ 5 5 obj-$(CONFIG_AR5523) += ar5523/ 6 + obj-$(CONFIG_WIL6210) += wil6210/ 6 7 7 8 obj-$(CONFIG_ATH_COMMON) += ath.o 8 9
+3 -2
drivers/net/wireless/ath/ath9k/Kconfig
··· 2 2 tristate 3 3 config ATH9K_COMMON 4 4 tristate 5 + select ATH_COMMON 5 6 config ATH9K_DFS_DEBUGFS 6 7 def_bool y 7 8 depends on ATH9K_DEBUGFS && ATH9K_DFS_CERTIFIED ··· 18 17 config ATH9K 19 18 tristate "Atheros 802.11n wireless cards support" 20 19 depends on MAC80211 21 - select ATH_COMMON 22 20 select ATH9K_HW 23 21 select MAC80211_LEDS 24 22 select LEDS_CLASS ··· 56 56 57 57 config ATH9K_DEBUGFS 58 58 bool "Atheros ath9k debugging" 59 - depends on ATH9K && DEBUG_FS 59 + depends on ATH9K 60 + select MAC80211_DEBUGFS 60 61 ---help--- 61 62 Say Y, if you need access to ath9k's statistics for 62 63 interrupts, rate control, etc.
+2
drivers/net/wireless/ath/ath9k/ar9003_calib.c
··· 1023 1023 AR_PHY_AGC_CONTROL_FLTR_CAL | 1024 1024 AR_PHY_AGC_CONTROL_PKDET_CAL; 1025 1025 1026 + ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask); 1027 + 1026 1028 if (rtt) { 1027 1029 if (!ar9003_hw_rtt_restore(ah, chan)) 1028 1030 run_rtt_cal = true;
+1 -1
drivers/net/wireless/ath/ath9k/ar9003_hw.c
··· 575 575 ar9340Common_rx_gain_table_1p0); 576 576 else if (AR_SREV_9485_11(ah)) 577 577 INIT_INI_ARRAY(&ah->iniModesRxGain, 578 - ar9485Common_wo_xlna_rx_gain_1_1); 578 + ar9485_common_rx_gain_1_1); 579 579 else if (AR_SREV_9550(ah)) { 580 580 INIT_INI_ARRAY(&ah->iniModesRxGain, 581 581 ar955x_1p0_common_rx_gain_table);
+7 -20
drivers/net/wireless/ath/ath9k/ar9003_phy.c
··· 589 589 ath9k_hw_synth_delay(ah, chan, synthDelay); 590 590 } 591 591 592 - static void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) 592 + void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) 593 593 { 594 - switch (rx) { 595 - case 0x5: 594 + if (ah->caps.tx_chainmask == 5 || ah->caps.rx_chainmask == 5) 596 595 REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, 597 596 AR_PHY_SWAP_ALT_CHAIN); 598 - case 0x3: 599 - case 0x1: 600 - case 0x2: 601 - case 0x7: 602 - REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx); 603 - REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx); 604 - break; 605 - default: 606 - break; 607 - } 597 + 598 + REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx); 599 + REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx); 608 600 609 601 if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7)) 610 - REG_WRITE(ah, AR_SELFGEN_MASK, 0x3); 611 - else 612 - REG_WRITE(ah, AR_SELFGEN_MASK, tx); 602 + tx = 3; 613 603 614 - if (tx == 0x5) { 615 - REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, 616 - AR_PHY_SWAP_ALT_CHAIN); 617 - } 604 + REG_WRITE(ah, AR_SELFGEN_MASK, tx); 618 605 } 619 606 620 607 /*
-3
drivers/net/wireless/ath/ath9k/ath9k.h
··· 314 314 u32 *rxlink; 315 315 u32 num_pkts; 316 316 unsigned int rxfilter; 317 - spinlock_t rxbuflock; 318 317 struct list_head rxbuf; 319 318 struct ath_descdma rxdma; 320 319 struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX]; ··· 323 324 324 325 int ath_startrecv(struct ath_softc *sc); 325 326 bool ath_stoprecv(struct ath_softc *sc); 326 - void ath_flushrecv(struct ath_softc *sc); 327 327 u32 ath_calcrxfilter(struct ath_softc *sc); 328 328 int ath_rx_init(struct ath_softc *sc, int nbufs); 329 329 void ath_rx_cleanup(struct ath_softc *sc); ··· 638 640 enum sc_op_flags { 639 641 SC_OP_INVALID, 640 642 SC_OP_BEACONS, 641 - SC_OP_RXFLUSH, 642 643 SC_OP_ANI_RUN, 643 644 SC_OP_PRIM_STA_VIF, 644 645 SC_OP_HW_RESET,
+1 -1
drivers/net/wireless/ath/ath9k/beacon.c
··· 147 147 skb->len, DMA_TO_DEVICE); 148 148 dev_kfree_skb_any(skb); 149 149 bf->bf_buf_addr = 0; 150 + bf->bf_mpdu = NULL; 150 151 } 151 152 152 153 skb = ieee80211_beacon_get(hw, vif); ··· 360 359 return; 361 360 362 361 bf = ath9k_beacon_generate(sc->hw, vif); 363 - WARN_ON(!bf); 364 362 365 363 if (sc->beacon.bmisscnt != 0) { 366 364 ath_dbg(common, BSTUCK, "resume beacon xmit after %u misses\n",
-1
drivers/net/wireless/ath/ath9k/debug.c
··· 862 862 RXS_ERR("RX-LENGTH-ERR", rx_len_err); 863 863 RXS_ERR("RX-OOM-ERR", rx_oom_err); 864 864 RXS_ERR("RX-RATE-ERR", rx_rate_err); 865 - RXS_ERR("RX-DROP-RXFLUSH", rx_drop_rxflush); 866 865 RXS_ERR("RX-TOO-MANY-FRAGS", rx_too_many_frags_err); 867 866 868 867 PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN);
-2
drivers/net/wireless/ath/ath9k/debug.h
··· 217 217 * @rx_oom_err: No. of frames dropped due to OOM issues. 218 218 * @rx_rate_err: No. of frames dropped due to rate errors. 219 219 * @rx_too_many_frags_err: Frames dropped due to too-many-frags received. 220 - * @rx_drop_rxflush: No. of frames dropped due to RX-FLUSH. 221 220 * @rx_beacons: No. of beacons received. 222 221 * @rx_frags: No. of rx-fragements received. 223 222 */ ··· 235 236 u32 rx_oom_err; 236 237 u32 rx_rate_err; 237 238 u32 rx_too_many_frags_err; 238 - u32 rx_drop_rxflush; 239 239 u32 rx_beacons; 240 240 u32 rx_frags; 241 241 };
+2
drivers/net/wireless/ath/ath9k/htc_hst.c
··· 344 344 endpoint->ep_callbacks.tx(endpoint->ep_callbacks.priv, 345 345 skb, htc_hdr->endpoint_id, 346 346 txok); 347 + } else { 348 + kfree_skb(skb); 347 349 } 348 350 } 349 351
+1
drivers/net/wireless/ath/ath9k/hw.h
··· 1096 1096 int ar9003_paprd_init_table(struct ath_hw *ah); 1097 1097 bool ar9003_paprd_is_done(struct ath_hw *ah); 1098 1098 bool ar9003_is_paprd_enabled(struct ath_hw *ah); 1099 + void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx); 1099 1100 1100 1101 /* Hardware family op attach helpers */ 1101 1102 int ar5008_hw_attach_phy_ops(struct ath_hw *ah);
+9 -13
drivers/net/wireless/ath/ath9k/main.c
··· 182 182 ath_start_ani(sc); 183 183 } 184 184 185 - static bool ath_prepare_reset(struct ath_softc *sc, bool flush) 185 + static bool ath_prepare_reset(struct ath_softc *sc) 186 186 { 187 187 struct ath_hw *ah = sc->sc_ah; 188 188 bool ret = true; ··· 201 201 202 202 if (!ath_stoprecv(sc)) 203 203 ret = false; 204 - 205 - if (!flush) { 206 - if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) 207 - ath_rx_tasklet(sc, 1, true); 208 - ath_rx_tasklet(sc, 1, false); 209 - } else { 210 - ath_flushrecv(sc); 211 - } 212 204 213 205 return ret; 214 206 } ··· 253 261 struct ath_common *common = ath9k_hw_common(ah); 254 262 struct ath9k_hw_cal_data *caldata = NULL; 255 263 bool fastcc = true; 256 - bool flush = false; 257 264 int r; 258 265 259 266 __ath_cancel_work(sc); 260 267 268 + tasklet_disable(&sc->intr_tq); 261 269 spin_lock_bh(&sc->sc_pcu_lock); 262 270 263 271 if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) { ··· 267 275 268 276 if (!hchan) { 269 277 fastcc = false; 270 - flush = true; 271 278 hchan = ah->curchan; 272 279 } 273 280 274 - if (!ath_prepare_reset(sc, flush)) 281 + if (!ath_prepare_reset(sc)) 275 282 fastcc = false; 276 283 277 284 ath_dbg(common, CONFIG, "Reset to %u MHz, HT40: %d fastcc: %d\n", ··· 292 301 293 302 out: 294 303 spin_unlock_bh(&sc->sc_pcu_lock); 304 + tasklet_enable(&sc->intr_tq); 305 + 295 306 return r; 296 307 } 297 308 ··· 794 801 ath9k_hw_cfg_gpio_input(ah, ah->led_pin); 795 802 } 796 803 797 - ath_prepare_reset(sc, true); 804 + ath_prepare_reset(sc); 798 805 799 806 if (sc->rx.frag) { 800 807 dev_kfree_skb_any(sc->rx.frag); ··· 1910 1917 1911 1918 static bool validate_antenna_mask(struct ath_hw *ah, u32 val) 1912 1919 { 1920 + if (AR_SREV_9300_20_OR_LATER(ah)) 1921 + return true; 1922 + 1913 1923 switch (val & 0x7) { 1914 1924 case 0x1: 1915 1925 case 0x3:
+15 -39
drivers/net/wireless/ath/ath9k/recv.c
··· 249 249 250 250 static void ath_edma_start_recv(struct ath_softc *sc) 251 251 { 252 - spin_lock_bh(&sc->rx.rxbuflock); 253 - 254 252 ath9k_hw_rxena(sc->sc_ah); 255 253 256 254 ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP, ··· 260 262 ath_opmode_init(sc); 261 263 262 264 ath9k_hw_startpcureceive(sc->sc_ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)); 263 - 264 - spin_unlock_bh(&sc->rx.rxbuflock); 265 265 } 266 266 267 267 static void ath_edma_stop_recv(struct ath_softc *sc) ··· 276 280 int error = 0; 277 281 278 282 spin_lock_init(&sc->sc_pcu_lock); 279 - spin_lock_init(&sc->rx.rxbuflock); 280 - clear_bit(SC_OP_RXFLUSH, &sc->sc_flags); 281 283 282 284 common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 + 283 285 sc->sc_ah->caps.rx_status_len; ··· 433 439 return 0; 434 440 } 435 441 436 - spin_lock_bh(&sc->rx.rxbuflock); 437 442 if (list_empty(&sc->rx.rxbuf)) 438 443 goto start_recv; 439 444 ··· 453 460 ath_opmode_init(sc); 454 461 ath9k_hw_startpcureceive(ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)); 455 462 456 - spin_unlock_bh(&sc->rx.rxbuflock); 457 - 458 463 return 0; 464 + } 465 + 466 + static void ath_flushrecv(struct ath_softc *sc) 467 + { 468 + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) 469 + ath_rx_tasklet(sc, 1, true); 470 + ath_rx_tasklet(sc, 1, false); 459 471 } 460 472 461 473 bool ath_stoprecv(struct ath_softc *sc) ··· 468 470 struct ath_hw *ah = sc->sc_ah; 469 471 bool stopped, reset = false; 470 472 471 - spin_lock_bh(&sc->rx.rxbuflock); 472 473 ath9k_hw_abortpcurecv(ah); 473 474 ath9k_hw_setrxfilter(ah, 0); 474 475 stopped = ath9k_hw_stopdmarecv(ah, &reset); 476 + 477 + ath_flushrecv(sc); 475 478 476 479 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) 477 480 ath_edma_stop_recv(sc); 478 481 else 479 482 sc->rx.rxlink = NULL; 480 - spin_unlock_bh(&sc->rx.rxbuflock); 481 483 482 484 if (!(ah->ah_flags & AH_UNPLUGGED) && 483 485 unlikely(!stopped)) { ··· 487 489 ATH_DBG_WARN_ON_ONCE(!stopped); 488 490 } 489 491 return stopped && !reset; 490 - } 491 - 492 - void ath_flushrecv(struct ath_softc *sc) 493 - { 494 - set_bit(SC_OP_RXFLUSH, &sc->sc_flags); 495 - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) 496 - ath_rx_tasklet(sc, 1, true); 497 - ath_rx_tasklet(sc, 1, false); 498 - clear_bit(SC_OP_RXFLUSH, &sc->sc_flags); 499 492 } 500 493 501 494 static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb) ··· 725 736 return NULL; 726 737 } 727 738 739 + list_del(&bf->list); 728 740 if (!bf->bf_mpdu) 729 741 return bf; 730 742 ··· 1143 1153 dma_type = DMA_FROM_DEVICE; 1144 1154 1145 1155 qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP; 1146 - spin_lock_bh(&sc->rx.rxbuflock); 1147 1156 1148 1157 tsf = ath9k_hw_gettsf64(ah); 1149 1158 tsf_lower = tsf & 0xffffffff; 1150 1159 1151 1160 do { 1152 1161 bool decrypt_error = false; 1153 - /* If handling rx interrupt and flush is in progress => exit */ 1154 - if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags) && (flush == 0)) 1155 - break; 1156 1162 1157 1163 memset(&rs, 0, sizeof(rs)); 1158 1164 if (edma) ··· 1190 1204 sc->rx.num_pkts++; 1191 1205 1192 1206 ath_debug_stat_rx(sc, &rs); 1193 - 1194 - /* 1195 - * If we're asked to flush receive queue, directly 1196 - * chain it back at the queue without processing it. 1197 - */ 1198 - if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags)) { 1199 - RX_STAT_INC(rx_drop_rxflush); 1200 - goto requeue_drop_frag; 1201 - } 1202 1207 1203 1208 memset(rxs, 0, sizeof(struct ieee80211_rx_status)); 1204 1209 ··· 1328 1351 sc->rx.frag = NULL; 1329 1352 } 1330 1353 requeue: 1354 + list_add_tail(&bf->list, &sc->rx.rxbuf); 1355 + if (flush) 1356 + continue; 1357 + 1331 1358 if (edma) { 1332 - list_add_tail(&bf->list, &sc->rx.rxbuf); 1333 1359 ath_rx_edma_buf_link(sc, qtype); 1334 1360 } else { 1335 - list_move_tail(&bf->list, &sc->rx.rxbuf); 1336 1361 ath_rx_buf_link(sc, bf); 1337 - if (!flush) 1338 - ath9k_hw_rxena(ah); 1362 + ath9k_hw_rxena(ah); 1339 1363 } 1340 1364 } while (1); 1341 - 1342 - spin_unlock_bh(&sc->rx.rxbuflock); 1343 1365 1344 1366 if (!(ah->imask & ATH9K_INT_RXEOL)) { 1345 1367 ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
+5 -1
drivers/net/wireless/ath/carl9170/fw.c
··· 354 354 if (SUPP(CARL9170FW_WLANTX_CAB)) { 355 355 if_comb_types |= 356 356 BIT(NL80211_IFTYPE_AP) | 357 - BIT(NL80211_IFTYPE_MESH_POINT) | 358 357 BIT(NL80211_IFTYPE_P2P_GO); 358 + 359 + #ifdef CONFIG_MAC80211_MESH 360 + if_comb_types |= 361 + BIT(NL80211_IFTYPE_MESH_POINT); 362 + #endif /* CONFIG_MAC80211_MESH */ 359 363 } 360 364 } 361 365
+29
drivers/net/wireless/ath/wil6210/Kconfig
··· 1 + config WIL6210 2 + tristate "Wilocity 60g WiFi card wil6210 support" 3 + depends on CFG80211 4 + depends on PCI 5 + default n 6 + ---help--- 7 + This module adds support for wireless adapter based on 8 + wil6210 chip by Wilocity. It supports operation on the 9 + 60 GHz band, covered by the IEEE802.11ad standard. 10 + 11 + http://wireless.kernel.org/en/users/Drivers/wil6210 12 + 13 + If you choose to build it as a module, it will be called 14 + wil6210 15 + 16 + config WIL6210_ISR_COR 17 + bool "Use Clear-On-Read mode for ISR registers for wil6210" 18 + depends on WIL6210 19 + default y 20 + ---help--- 21 + ISR registers on wil6210 chip may operate in either 22 + COR (Clear-On-Read) or W1C (Write-1-to-Clear) mode. 23 + For production code, use COR (say y); is default since 24 + it saves extra target transaction; 25 + For ISR debug, use W1C (say n); is allows to monitor ISR 26 + registers with debugfs. If COR were used, ISR would 27 + self-clear when accessed for debug purposes, it makes 28 + such monitoring impossible. 29 + Say y unless you debug interrupts
+13
drivers/net/wireless/ath/wil6210/Makefile
··· 1 + obj-$(CONFIG_WIL6210) += wil6210.o 2 + 3 + wil6210-objs := main.o 4 + wil6210-objs += netdev.o 5 + wil6210-objs += cfg80211.o 6 + wil6210-objs += pcie_bus.o 7 + wil6210-objs += debugfs.o 8 + wil6210-objs += wmi.o 9 + wil6210-objs += interrupt.o 10 + wil6210-objs += txrx.o 11 + 12 + subdir-ccflags-y += -Werror 13 + subdir-ccflags-y += -D__CHECK_ENDIAN__
+573
drivers/net/wireless/ath/wil6210/cfg80211.c
··· 1 + /* 2 + * Copyright (c) 2012 Qualcomm Atheros, Inc. 3 + * 4 + * Permission to use, copy, modify, and/or distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + 17 + #include <linux/kernel.h> 18 + #include <linux/netdevice.h> 19 + #include <linux/sched.h> 20 + #include <linux/etherdevice.h> 21 + #include <linux/wireless.h> 22 + #include <linux/ieee80211.h> 23 + #include <linux/slab.h> 24 + #include <linux/version.h> 25 + #include <net/cfg80211.h> 26 + 27 + #include "wil6210.h" 28 + #include "wmi.h" 29 + 30 + #define CHAN60G(_channel, _flags) { \ 31 + .band = IEEE80211_BAND_60GHZ, \ 32 + .center_freq = 56160 + (2160 * (_channel)), \ 33 + .hw_value = (_channel), \ 34 + .flags = (_flags), \ 35 + .max_antenna_gain = 0, \ 36 + .max_power = 40, \ 37 + } 38 + 39 + static struct ieee80211_channel wil_60ghz_channels[] = { 40 + CHAN60G(1, 0), 41 + CHAN60G(2, 0), 42 + CHAN60G(3, 0), 43 + /* channel 4 not supported yet */ 44 + }; 45 + 46 + static struct ieee80211_supported_band wil_band_60ghz = { 47 + .channels = wil_60ghz_channels, 48 + .n_channels = ARRAY_SIZE(wil_60ghz_channels), 49 + .ht_cap = { 50 + .ht_supported = true, 51 + .cap = 0, /* TODO */ 52 + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, /* TODO */ 53 + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, /* TODO */ 54 + .mcs = { 55 + /* MCS 1..12 - SC PHY */ 56 + .rx_mask = {0xfe, 0x1f}, /* 1..12 */ 57 + .tx_params = IEEE80211_HT_MCS_TX_DEFINED, /* TODO */ 58 + }, 59 + }, 60 + }; 61 + 62 + static const struct ieee80211_txrx_stypes 63 + wil_mgmt_stypes[NUM_NL80211_IFTYPES] = { 64 + [NL80211_IFTYPE_STATION] = { 65 + .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | 66 + BIT(IEEE80211_STYPE_PROBE_RESP >> 4), 67 + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | 68 + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) 69 + }, 70 + [NL80211_IFTYPE_AP] = { 71 + .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | 72 + BIT(IEEE80211_STYPE_PROBE_RESP >> 4), 73 + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | 74 + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) 75 + }, 76 + [NL80211_IFTYPE_P2P_CLIENT] = { 77 + .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | 78 + BIT(IEEE80211_STYPE_PROBE_RESP >> 4), 79 + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | 80 + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) 81 + }, 82 + [NL80211_IFTYPE_P2P_GO] = { 83 + .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | 84 + BIT(IEEE80211_STYPE_PROBE_RESP >> 4), 85 + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | 86 + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) 87 + }, 88 + }; 89 + 90 + static const u32 wil_cipher_suites[] = { 91 + WLAN_CIPHER_SUITE_GCMP, 92 + }; 93 + 94 + int wil_iftype_nl2wmi(enum nl80211_iftype type) 95 + { 96 + static const struct { 97 + enum nl80211_iftype nl; 98 + enum wmi_network_type wmi; 99 + } __nl2wmi[] = { 100 + {NL80211_IFTYPE_ADHOC, WMI_NETTYPE_ADHOC}, 101 + {NL80211_IFTYPE_STATION, WMI_NETTYPE_INFRA}, 102 + {NL80211_IFTYPE_AP, WMI_NETTYPE_AP}, 103 + {NL80211_IFTYPE_P2P_CLIENT, WMI_NETTYPE_P2P}, 104 + {NL80211_IFTYPE_P2P_GO, WMI_NETTYPE_P2P}, 105 + {NL80211_IFTYPE_MONITOR, WMI_NETTYPE_ADHOC}, /* FIXME */ 106 + }; 107 + uint i; 108 + 109 + for (i = 0; i < ARRAY_SIZE(__nl2wmi); i++) { 110 + if (__nl2wmi[i].nl == type) 111 + return __nl2wmi[i].wmi; 112 + } 113 + 114 + return -EOPNOTSUPP; 115 + } 116 + 117 + static int wil_cfg80211_get_station(struct wiphy *wiphy, 118 + struct net_device *ndev, 119 + u8 *mac, struct station_info *sinfo) 120 + { 121 + struct wil6210_priv *wil = wiphy_to_wil(wiphy); 122 + int rc; 123 + struct wmi_notify_req_cmd cmd = { 124 + .cid = 0, 125 + .interval_usec = 0, 126 + }; 127 + 128 + if (memcmp(mac, wil->dst_addr[0], ETH_ALEN)) 129 + return -ENOENT; 130 + 131 + /* WMI_NOTIFY_REQ_DONE_EVENTID handler fills wil->stats.bf_mcs */ 132 + rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, &cmd, sizeof(cmd), 133 + WMI_NOTIFY_REQ_DONE_EVENTID, NULL, 0, 20); 134 + if (rc) 135 + return rc; 136 + 137 + sinfo->generation = wil->sinfo_gen; 138 + 139 + sinfo->filled |= STATION_INFO_TX_BITRATE; 140 + sinfo->txrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G; 141 + sinfo->txrate.mcs = wil->stats.bf_mcs; 142 + sinfo->filled |= STATION_INFO_RX_BITRATE; 143 + sinfo->rxrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G; 144 + sinfo->rxrate.mcs = wil->stats.last_mcs_rx; 145 + 146 + if (test_bit(wil_status_fwconnected, &wil->status)) { 147 + sinfo->filled |= STATION_INFO_SIGNAL; 148 + sinfo->signal = 12; /* TODO: provide real value */ 149 + } 150 + 151 + return 0; 152 + } 153 + 154 + static int wil_cfg80211_change_iface(struct wiphy *wiphy, 155 + struct net_device *ndev, 156 + enum nl80211_iftype type, u32 *flags, 157 + struct vif_params *params) 158 + { 159 + struct wil6210_priv *wil = wiphy_to_wil(wiphy); 160 + struct wireless_dev *wdev = wil->wdev; 161 + 162 + switch (type) { 163 + case NL80211_IFTYPE_STATION: 164 + case NL80211_IFTYPE_AP: 165 + case NL80211_IFTYPE_P2P_CLIENT: 166 + case NL80211_IFTYPE_P2P_GO: 167 + break; 168 + case NL80211_IFTYPE_MONITOR: 169 + if (flags) 170 + wil->monitor_flags = *flags; 171 + else 172 + wil->monitor_flags = 0; 173 + 174 + break; 175 + default: 176 + return -EOPNOTSUPP; 177 + } 178 + 179 + wdev->iftype = type; 180 + 181 + return 0; 182 + } 183 + 184 + static int wil_cfg80211_scan(struct wiphy *wiphy, 185 + struct cfg80211_scan_request *request) 186 + { 187 + struct wil6210_priv *wil = wiphy_to_wil(wiphy); 188 + struct wireless_dev *wdev = wil->wdev; 189 + struct { 190 + struct wmi_start_scan_cmd cmd; 191 + u16 chnl[4]; 192 + } __packed cmd; 193 + uint i, n; 194 + 195 + if (wil->scan_request) { 196 + wil_err(wil, "Already scanning\n"); 197 + return -EAGAIN; 198 + } 199 + 200 + /* check we are client side */ 201 + switch (wdev->iftype) { 202 + case NL80211_IFTYPE_STATION: 203 + case NL80211_IFTYPE_P2P_CLIENT: 204 + break; 205 + default: 206 + return -EOPNOTSUPP; 207 + 208 + } 209 + 210 + /* FW don't support scan after connection attempt */ 211 + if (test_bit(wil_status_dontscan, &wil->status)) { 212 + wil_err(wil, "Scan after connect attempt not supported\n"); 213 + return -EBUSY; 214 + } 215 + 216 + wil->scan_request = request; 217 + 218 + memset(&cmd, 0, sizeof(cmd)); 219 + cmd.cmd.num_channels = 0; 220 + n = min(request->n_channels, 4U); 221 + for (i = 0; i < n; i++) { 222 + int ch = request->channels[i]->hw_value; 223 + if (ch == 0) { 224 + wil_err(wil, 225 + "Scan requested for unknown frequency %dMhz\n", 226 + request->channels[i]->center_freq); 227 + continue; 228 + } 229 + /* 0-based channel indexes */ 230 + cmd.cmd.channel_list[cmd.cmd.num_channels++].channel = ch - 1; 231 + wil_dbg(wil, "Scan for ch %d : %d MHz\n", ch, 232 + request->channels[i]->center_freq); 233 + } 234 + 235 + return wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) + 236 + cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0])); 237 + } 238 + 239 + static int wil_cfg80211_connect(struct wiphy *wiphy, 240 + struct net_device *ndev, 241 + struct cfg80211_connect_params *sme) 242 + { 243 + struct wil6210_priv *wil = wiphy_to_wil(wiphy); 244 + struct cfg80211_bss *bss; 245 + struct wmi_connect_cmd conn; 246 + const u8 *ssid_eid; 247 + const u8 *rsn_eid; 248 + int ch; 249 + int rc = 0; 250 + 251 + bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, 252 + sme->ssid, sme->ssid_len, 253 + WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); 254 + if (!bss) { 255 + wil_err(wil, "Unable to find BSS\n"); 256 + return -ENOENT; 257 + } 258 + 259 + ssid_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SSID); 260 + if (!ssid_eid) { 261 + wil_err(wil, "No SSID\n"); 262 + rc = -ENOENT; 263 + goto out; 264 + } 265 + 266 + rsn_eid = sme->ie ? 267 + cfg80211_find_ie(WLAN_EID_RSN, sme->ie, sme->ie_len) : 268 + NULL; 269 + if (rsn_eid) { 270 + if (sme->ie_len > WMI_MAX_IE_LEN) { 271 + rc = -ERANGE; 272 + wil_err(wil, "IE too large (%td bytes)\n", 273 + sme->ie_len); 274 + goto out; 275 + } 276 + /* 277 + * For secure assoc, send: 278 + * (1) WMI_DELETE_CIPHER_KEY_CMD 279 + * (2) WMI_SET_APPIE_CMD 280 + */ 281 + rc = wmi_del_cipher_key(wil, 0, bss->bssid); 282 + if (rc) { 283 + wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD failed\n"); 284 + goto out; 285 + } 286 + /* WMI_SET_APPIE_CMD */ 287 + rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie); 288 + if (rc) { 289 + wil_err(wil, "WMI_SET_APPIE_CMD failed\n"); 290 + goto out; 291 + } 292 + } 293 + 294 + /* WMI_CONNECT_CMD */ 295 + memset(&conn, 0, sizeof(conn)); 296 + switch (bss->capability & 0x03) { 297 + case WLAN_CAPABILITY_DMG_TYPE_AP: 298 + conn.network_type = WMI_NETTYPE_INFRA; 299 + break; 300 + case WLAN_CAPABILITY_DMG_TYPE_PBSS: 301 + conn.network_type = WMI_NETTYPE_P2P; 302 + break; 303 + default: 304 + wil_err(wil, "Unsupported BSS type, capability= 0x%04x\n", 305 + bss->capability); 306 + goto out; 307 + } 308 + if (rsn_eid) { 309 + conn.dot11_auth_mode = WMI_AUTH11_SHARED; 310 + conn.auth_mode = WMI_AUTH_WPA2_PSK; 311 + conn.pairwise_crypto_type = WMI_CRYPT_AES_GCMP; 312 + conn.pairwise_crypto_len = 16; 313 + } else { 314 + conn.dot11_auth_mode = WMI_AUTH11_OPEN; 315 + conn.auth_mode = WMI_AUTH_NONE; 316 + } 317 + 318 + conn.ssid_len = min_t(u8, ssid_eid[1], 32); 319 + memcpy(conn.ssid, ssid_eid+2, conn.ssid_len); 320 + 321 + ch = bss->channel->hw_value; 322 + if (ch == 0) { 323 + wil_err(wil, "BSS at unknown frequency %dMhz\n", 324 + bss->channel->center_freq); 325 + rc = -EOPNOTSUPP; 326 + goto out; 327 + } 328 + conn.channel = ch - 1; 329 + 330 + memcpy(conn.bssid, bss->bssid, 6); 331 + memcpy(conn.dst_mac, bss->bssid, 6); 332 + /* 333 + * FW don't support scan after connection attempt 334 + */ 335 + set_bit(wil_status_dontscan, &wil->status); 336 + 337 + rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn)); 338 + if (rc == 0) { 339 + /* Connect can take lots of time */ 340 + mod_timer(&wil->connect_timer, 341 + jiffies + msecs_to_jiffies(2000)); 342 + } 343 + 344 + out: 345 + cfg80211_put_bss(bss); 346 + 347 + return rc; 348 + } 349 + 350 + static int wil_cfg80211_disconnect(struct wiphy *wiphy, 351 + struct net_device *ndev, 352 + u16 reason_code) 353 + { 354 + int rc; 355 + struct wil6210_priv *wil = wiphy_to_wil(wiphy); 356 + 357 + rc = wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0); 358 + 359 + return rc; 360 + } 361 + 362 + static int wil_cfg80211_set_channel(struct wiphy *wiphy, 363 + struct cfg80211_chan_def *chandef) 364 + { 365 + struct wil6210_priv *wil = wiphy_to_wil(wiphy); 366 + struct wireless_dev *wdev = wil->wdev; 367 + 368 + wdev->preset_chandef = *chandef; 369 + 370 + return 0; 371 + } 372 + 373 + static int wil_cfg80211_add_key(struct wiphy *wiphy, 374 + struct net_device *ndev, 375 + u8 key_index, bool pairwise, 376 + const u8 *mac_addr, 377 + struct key_params *params) 378 + { 379 + struct wil6210_priv *wil = wiphy_to_wil(wiphy); 380 + 381 + /* group key is not used */ 382 + if (!pairwise) 383 + return 0; 384 + 385 + return wmi_add_cipher_key(wil, key_index, mac_addr, 386 + params->key_len, params->key); 387 + } 388 + 389 + static int wil_cfg80211_del_key(struct wiphy *wiphy, 390 + struct net_device *ndev, 391 + u8 key_index, bool pairwise, 392 + const u8 *mac_addr) 393 + { 394 + struct wil6210_priv *wil = wiphy_to_wil(wiphy); 395 + 396 + /* group key is not used */ 397 + if (!pairwise) 398 + return 0; 399 + 400 + return wmi_del_cipher_key(wil, key_index, mac_addr); 401 + } 402 + 403 + /* Need to be present or wiphy_new() will WARN */ 404 + static int wil_cfg80211_set_default_key(struct wiphy *wiphy, 405 + struct net_device *ndev, 406 + u8 key_index, bool unicast, 407 + bool multicast) 408 + { 409 + return 0; 410 + } 411 + 412 + static int wil_cfg80211_start_ap(struct wiphy *wiphy, 413 + struct net_device *ndev, 414 + struct cfg80211_ap_settings *info) 415 + { 416 + int rc = 0; 417 + struct wil6210_priv *wil = wiphy_to_wil(wiphy); 418 + struct wireless_dev *wdev = ndev->ieee80211_ptr; 419 + struct ieee80211_channel *channel = info->chandef.chan; 420 + struct cfg80211_beacon_data *bcon = &info->beacon; 421 + u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); 422 + 423 + if (!channel) { 424 + wil_err(wil, "AP: No channel???\n"); 425 + return -EINVAL; 426 + } 427 + 428 + wil_dbg(wil, "AP on Channel %d %d MHz, %s\n", channel->hw_value, 429 + channel->center_freq, info->privacy ? "secure" : "open"); 430 + print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET, 431 + info->ssid, info->ssid_len); 432 + 433 + rc = wil_reset(wil); 434 + if (rc) 435 + return rc; 436 + 437 + rc = wmi_set_ssid(wil, info->ssid_len, info->ssid); 438 + if (rc) 439 + return rc; 440 + 441 + rc = wmi_set_channel(wil, channel->hw_value); 442 + if (rc) 443 + return rc; 444 + 445 + /* MAC address - pre-requisite for other commands */ 446 + wmi_set_mac_address(wil, ndev->dev_addr); 447 + 448 + /* IE's */ 449 + /* bcon 'head IE's are not relevant for 60g band */ 450 + wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->beacon_ies_len, 451 + bcon->beacon_ies); 452 + wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, bcon->proberesp_ies_len, 453 + bcon->proberesp_ies); 454 + wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, bcon->assocresp_ies_len, 455 + bcon->assocresp_ies); 456 + 457 + wil->secure_pcp = info->privacy; 458 + 459 + rc = wmi_set_bcon(wil, info->beacon_interval, wmi_nettype); 460 + if (rc) 461 + return rc; 462 + 463 + /* Rx VRING. After MAC and beacon */ 464 + rc = wil_rx_init(wil); 465 + 466 + netif_carrier_on(ndev); 467 + 468 + return rc; 469 + } 470 + 471 + static int wil_cfg80211_stop_ap(struct wiphy *wiphy, 472 + struct net_device *ndev) 473 + { 474 + int rc = 0; 475 + struct wil6210_priv *wil = wiphy_to_wil(wiphy); 476 + struct wireless_dev *wdev = ndev->ieee80211_ptr; 477 + u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); 478 + 479 + /* To stop beaconing, set BI to 0 */ 480 + rc = wmi_set_bcon(wil, 0, wmi_nettype); 481 + 482 + return rc; 483 + } 484 + 485 + static struct cfg80211_ops wil_cfg80211_ops = { 486 + .scan = wil_cfg80211_scan, 487 + .connect = wil_cfg80211_connect, 488 + .disconnect = wil_cfg80211_disconnect, 489 + .change_virtual_intf = wil_cfg80211_change_iface, 490 + .get_station = wil_cfg80211_get_station, 491 + .set_monitor_channel = wil_cfg80211_set_channel, 492 + .add_key = wil_cfg80211_add_key, 493 + .del_key = wil_cfg80211_del_key, 494 + .set_default_key = wil_cfg80211_set_default_key, 495 + /* AP mode */ 496 + .start_ap = wil_cfg80211_start_ap, 497 + .stop_ap = wil_cfg80211_stop_ap, 498 + }; 499 + 500 + static void wil_wiphy_init(struct wiphy *wiphy) 501 + { 502 + /* TODO: set real value */ 503 + wiphy->max_scan_ssids = 10; 504 + wiphy->max_num_pmkids = 0 /* TODO: */; 505 + wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | 506 + BIT(NL80211_IFTYPE_AP) | 507 + BIT(NL80211_IFTYPE_MONITOR); 508 + /* TODO: enable P2P when integrated with supplicant: 509 + * BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) 510 + */ 511 + wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | 512 + WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; 513 + dev_warn(wiphy_dev(wiphy), "%s : flags = 0x%08x\n", 514 + __func__, wiphy->flags); 515 + wiphy->probe_resp_offload = 516 + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | 517 + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | 518 + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; 519 + 520 + wiphy->bands[IEEE80211_BAND_60GHZ] = &wil_band_60ghz; 521 + 522 + /* TODO: figure this out */ 523 + wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; 524 + 525 + wiphy->cipher_suites = wil_cipher_suites; 526 + wiphy->n_cipher_suites = ARRAY_SIZE(wil_cipher_suites); 527 + wiphy->mgmt_stypes = wil_mgmt_stypes; 528 + } 529 + 530 + struct wireless_dev *wil_cfg80211_init(struct device *dev) 531 + { 532 + int rc = 0; 533 + struct wireless_dev *wdev; 534 + 535 + wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); 536 + if (!wdev) 537 + return ERR_PTR(-ENOMEM); 538 + 539 + wdev->wiphy = wiphy_new(&wil_cfg80211_ops, 540 + sizeof(struct wil6210_priv)); 541 + if (!wdev->wiphy) { 542 + rc = -ENOMEM; 543 + goto out; 544 + } 545 + 546 + set_wiphy_dev(wdev->wiphy, dev); 547 + wil_wiphy_init(wdev->wiphy); 548 + 549 + rc = wiphy_register(wdev->wiphy); 550 + if (rc < 0) 551 + goto out_failed_reg; 552 + 553 + return wdev; 554 + 555 + out_failed_reg: 556 + wiphy_free(wdev->wiphy); 557 + out: 558 + kfree(wdev); 559 + 560 + return ERR_PTR(rc); 561 + } 562 + 563 + void wil_wdev_free(struct wil6210_priv *wil) 564 + { 565 + struct wireless_dev *wdev = wil_to_wdev(wil); 566 + 567 + if (!wdev) 568 + return; 569 + 570 + wiphy_unregister(wdev->wiphy); 571 + wiphy_free(wdev->wiphy); 572 + kfree(wdev); 573 + }
+30
drivers/net/wireless/ath/wil6210/dbg_hexdump.h
··· 1 + #ifndef WIL_DBG_HEXDUMP_H_ 2 + #define WIL_DBG_HEXDUMP_H_ 3 + 4 + #if defined(CONFIG_DYNAMIC_DEBUG) 5 + #define wil_dynamic_hex_dump(prefix_str, prefix_type, rowsize, \ 6 + groupsize, buf, len, ascii) \ 7 + do { \ 8 + DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, \ 9 + __builtin_constant_p(prefix_str) ? prefix_str : "hexdump");\ 10 + if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \ 11 + print_hex_dump(KERN_DEBUG, prefix_str, \ 12 + prefix_type, rowsize, groupsize, \ 13 + buf, len, ascii); \ 14 + } while (0) 15 + 16 + #define wil_print_hex_dump_debug(prefix_str, prefix_type, rowsize, \ 17 + groupsize, buf, len, ascii) \ 18 + wil_dynamic_hex_dump(prefix_str, prefix_type, rowsize, \ 19 + groupsize, buf, len, ascii) 20 + 21 + #define print_hex_dump_bytes(prefix_str, prefix_type, buf, len) \ 22 + wil_dynamic_hex_dump(prefix_str, prefix_type, 16, 1, buf, len, true) 23 + #else /* defined(CONFIG_DYNAMIC_DEBUG) */ 24 + #define wil_print_hex_dump_debug(prefix_str, prefix_type, rowsize, \ 25 + groupsize, buf, len, ascii) \ 26 + print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, rowsize, \ 27 + groupsize, buf, len, ascii) 28 + #endif /* defined(CONFIG_DYNAMIC_DEBUG) */ 29 + 30 + #endif /* WIL_DBG_HEXDUMP_H_ */
+603
drivers/net/wireless/ath/wil6210/debugfs.c
··· 1 + /* 2 + * Copyright (c) 2012 Qualcomm Atheros, Inc. 3 + * 4 + * Permission to use, copy, modify, and/or distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + 17 + #include <linux/module.h> 18 + #include <linux/debugfs.h> 19 + #include <linux/seq_file.h> 20 + #include <linux/pci.h> 21 + #include <linux/rtnetlink.h> 22 + 23 + #include "wil6210.h" 24 + #include "txrx.h" 25 + 26 + /* Nasty hack. Better have per device instances */ 27 + static u32 mem_addr; 28 + static u32 dbg_txdesc_index; 29 + 30 + static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil, 31 + const char *name, struct vring *vring) 32 + { 33 + void __iomem *x = wmi_addr(wil, vring->hwtail); 34 + 35 + seq_printf(s, "VRING %s = {\n", name); 36 + seq_printf(s, " pa = 0x%016llx\n", (unsigned long long)vring->pa); 37 + seq_printf(s, " va = 0x%p\n", vring->va); 38 + seq_printf(s, " size = %d\n", vring->size); 39 + seq_printf(s, " swtail = %d\n", vring->swtail); 40 + seq_printf(s, " swhead = %d\n", vring->swhead); 41 + seq_printf(s, " hwtail = [0x%08x] -> ", vring->hwtail); 42 + if (x) 43 + seq_printf(s, "0x%08x\n", ioread32(x)); 44 + else 45 + seq_printf(s, "???\n"); 46 + 47 + if (vring->va && (vring->size < 1025)) { 48 + uint i; 49 + for (i = 0; i < vring->size; i++) { 50 + volatile struct vring_tx_desc *d = &vring->va[i].tx; 51 + if ((i % 64) == 0 && (i != 0)) 52 + seq_printf(s, "\n"); 53 + seq_printf(s, "%s", (d->dma.status & BIT(0)) ? 54 + "S" : (vring->ctx[i] ? "H" : "h")); 55 + } 56 + seq_printf(s, "\n"); 57 + } 58 + seq_printf(s, "}\n"); 59 + } 60 + 61 + static int wil_vring_debugfs_show(struct seq_file *s, void *data) 62 + { 63 + uint i; 64 + struct wil6210_priv *wil = s->private; 65 + 66 + wil_print_vring(s, wil, "rx", &wil->vring_rx); 67 + 68 + for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) { 69 + struct vring *vring = &(wil->vring_tx[i]); 70 + if (vring->va) { 71 + char name[10]; 72 + snprintf(name, sizeof(name), "tx_%2d", i); 73 + wil_print_vring(s, wil, name, vring); 74 + } 75 + } 76 + 77 + return 0; 78 + } 79 + 80 + static int wil_vring_seq_open(struct inode *inode, struct file *file) 81 + { 82 + return single_open(file, wil_vring_debugfs_show, inode->i_private); 83 + } 84 + 85 + static const struct file_operations fops_vring = { 86 + .open = wil_vring_seq_open, 87 + .release = single_release, 88 + .read = seq_read, 89 + .llseek = seq_lseek, 90 + }; 91 + 92 + static void wil_print_ring(struct seq_file *s, const char *prefix, 93 + void __iomem *off) 94 + { 95 + struct wil6210_priv *wil = s->private; 96 + struct wil6210_mbox_ring r; 97 + int rsize; 98 + uint i; 99 + 100 + wil_memcpy_fromio_32(&r, off, sizeof(r)); 101 + wil_mbox_ring_le2cpus(&r); 102 + /* 103 + * we just read memory block from NIC. This memory may be 104 + * garbage. Check validity before using it. 105 + */ 106 + rsize = r.size / sizeof(struct wil6210_mbox_ring_desc); 107 + 108 + seq_printf(s, "ring %s = {\n", prefix); 109 + seq_printf(s, " base = 0x%08x\n", r.base); 110 + seq_printf(s, " size = 0x%04x bytes -> %d entries\n", r.size, rsize); 111 + seq_printf(s, " tail = 0x%08x\n", r.tail); 112 + seq_printf(s, " head = 0x%08x\n", r.head); 113 + seq_printf(s, " entry size = %d\n", r.entry_size); 114 + 115 + if (r.size % sizeof(struct wil6210_mbox_ring_desc)) { 116 + seq_printf(s, " ??? size is not multiple of %zd, garbage?\n", 117 + sizeof(struct wil6210_mbox_ring_desc)); 118 + goto out; 119 + } 120 + 121 + if (!wmi_addr(wil, r.base) || 122 + !wmi_addr(wil, r.tail) || 123 + !wmi_addr(wil, r.head)) { 124 + seq_printf(s, " ??? pointers are garbage?\n"); 125 + goto out; 126 + } 127 + 128 + for (i = 0; i < rsize; i++) { 129 + struct wil6210_mbox_ring_desc d; 130 + struct wil6210_mbox_hdr hdr; 131 + size_t delta = i * sizeof(d); 132 + void __iomem *x = wil->csr + HOSTADDR(r.base) + delta; 133 + 134 + wil_memcpy_fromio_32(&d, x, sizeof(d)); 135 + 136 + seq_printf(s, " [%2x] %s %s%s 0x%08x", i, 137 + d.sync ? "F" : "E", 138 + (r.tail - r.base == delta) ? "t" : " ", 139 + (r.head - r.base == delta) ? "h" : " ", 140 + le32_to_cpu(d.addr)); 141 + if (0 == wmi_read_hdr(wil, d.addr, &hdr)) { 142 + u16 len = le16_to_cpu(hdr.len); 143 + seq_printf(s, " -> %04x %04x %04x %02x\n", 144 + le16_to_cpu(hdr.seq), len, 145 + le16_to_cpu(hdr.type), hdr.flags); 146 + if (len <= MAX_MBOXITEM_SIZE) { 147 + int n = 0; 148 + unsigned char printbuf[16 * 3 + 2]; 149 + unsigned char databuf[MAX_MBOXITEM_SIZE]; 150 + void __iomem *src = wmi_buffer(wil, d.addr) + 151 + sizeof(struct wil6210_mbox_hdr); 152 + /* 153 + * No need to check @src for validity - 154 + * we already validated @d.addr while 155 + * reading header 156 + */ 157 + wil_memcpy_fromio_32(databuf, src, len); 158 + while (n < len) { 159 + int l = min(len - n, 16); 160 + hex_dump_to_buffer(databuf + n, l, 161 + 16, 1, printbuf, 162 + sizeof(printbuf), 163 + false); 164 + seq_printf(s, " : %s\n", printbuf); 165 + n += l; 166 + } 167 + } 168 + } else { 169 + seq_printf(s, "\n"); 170 + } 171 + } 172 + out: 173 + seq_printf(s, "}\n"); 174 + } 175 + 176 + static int wil_mbox_debugfs_show(struct seq_file *s, void *data) 177 + { 178 + struct wil6210_priv *wil = s->private; 179 + 180 + wil_print_ring(s, "tx", wil->csr + HOST_MBOX + 181 + offsetof(struct wil6210_mbox_ctl, tx)); 182 + wil_print_ring(s, "rx", wil->csr + HOST_MBOX + 183 + offsetof(struct wil6210_mbox_ctl, rx)); 184 + 185 + return 0; 186 + } 187 + 188 + static int wil_mbox_seq_open(struct inode *inode, struct file *file) 189 + { 190 + return single_open(file, wil_mbox_debugfs_show, inode->i_private); 191 + } 192 + 193 + static const struct file_operations fops_mbox = { 194 + .open = wil_mbox_seq_open, 195 + .release = single_release, 196 + .read = seq_read, 197 + .llseek = seq_lseek, 198 + }; 199 + 200 + static int wil_debugfs_iomem_x32_set(void *data, u64 val) 201 + { 202 + iowrite32(val, (void __iomem *)data); 203 + wmb(); /* make sure write propagated to HW */ 204 + 205 + return 0; 206 + } 207 + 208 + static int wil_debugfs_iomem_x32_get(void *data, u64 *val) 209 + { 210 + *val = ioread32((void __iomem *)data); 211 + 212 + return 0; 213 + } 214 + 215 + DEFINE_SIMPLE_ATTRIBUTE(fops_iomem_x32, wil_debugfs_iomem_x32_get, 216 + wil_debugfs_iomem_x32_set, "0x%08llx\n"); 217 + 218 + static struct dentry *wil_debugfs_create_iomem_x32(const char *name, 219 + mode_t mode, 220 + struct dentry *parent, 221 + void __iomem *value) 222 + { 223 + return debugfs_create_file(name, mode, parent, (void * __force)value, 224 + &fops_iomem_x32); 225 + } 226 + 227 + static int wil6210_debugfs_create_ISR(struct wil6210_priv *wil, 228 + const char *name, 229 + struct dentry *parent, u32 off) 230 + { 231 + struct dentry *d = debugfs_create_dir(name, parent); 232 + 233 + if (IS_ERR_OR_NULL(d)) 234 + return -ENODEV; 235 + 236 + wil_debugfs_create_iomem_x32("ICC", S_IRUGO | S_IWUSR, d, 237 + wil->csr + off); 238 + wil_debugfs_create_iomem_x32("ICR", S_IRUGO | S_IWUSR, d, 239 + wil->csr + off + 4); 240 + wil_debugfs_create_iomem_x32("ICM", S_IRUGO | S_IWUSR, d, 241 + wil->csr + off + 8); 242 + wil_debugfs_create_iomem_x32("ICS", S_IWUSR, d, 243 + wil->csr + off + 12); 244 + wil_debugfs_create_iomem_x32("IMV", S_IRUGO | S_IWUSR, d, 245 + wil->csr + off + 16); 246 + wil_debugfs_create_iomem_x32("IMS", S_IWUSR, d, 247 + wil->csr + off + 20); 248 + wil_debugfs_create_iomem_x32("IMC", S_IWUSR, d, 249 + wil->csr + off + 24); 250 + 251 + return 0; 252 + } 253 + 254 + static int wil6210_debugfs_create_pseudo_ISR(struct wil6210_priv *wil, 255 + struct dentry *parent) 256 + { 257 + struct dentry *d = debugfs_create_dir("PSEUDO_ISR", parent); 258 + 259 + if (IS_ERR_OR_NULL(d)) 260 + return -ENODEV; 261 + 262 + wil_debugfs_create_iomem_x32("CAUSE", S_IRUGO, d, wil->csr + 263 + HOSTADDR(RGF_DMA_PSEUDO_CAUSE)); 264 + wil_debugfs_create_iomem_x32("MASK_SW", S_IRUGO, d, wil->csr + 265 + HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); 266 + wil_debugfs_create_iomem_x32("MASK_FW", S_IRUGO, d, wil->csr + 267 + HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_FW)); 268 + 269 + return 0; 270 + } 271 + 272 + static int wil6210_debugfs_create_ITR_CNT(struct wil6210_priv *wil, 273 + struct dentry *parent) 274 + { 275 + struct dentry *d = debugfs_create_dir("ITR_CNT", parent); 276 + 277 + if (IS_ERR_OR_NULL(d)) 278 + return -ENODEV; 279 + 280 + wil_debugfs_create_iomem_x32("TRSH", S_IRUGO, d, wil->csr + 281 + HOSTADDR(RGF_DMA_ITR_CNT_TRSH)); 282 + wil_debugfs_create_iomem_x32("DATA", S_IRUGO, d, wil->csr + 283 + HOSTADDR(RGF_DMA_ITR_CNT_DATA)); 284 + wil_debugfs_create_iomem_x32("CTL", S_IRUGO, d, wil->csr + 285 + HOSTADDR(RGF_DMA_ITR_CNT_CRL)); 286 + 287 + return 0; 288 + } 289 + 290 + static int wil_memread_debugfs_show(struct seq_file *s, void *data) 291 + { 292 + struct wil6210_priv *wil = s->private; 293 + void __iomem *a = wmi_buffer(wil, cpu_to_le32(mem_addr)); 294 + 295 + if (a) 296 + seq_printf(s, "[0x%08x] = 0x%08x\n", mem_addr, ioread32(a)); 297 + else 298 + seq_printf(s, "[0x%08x] = INVALID\n", mem_addr); 299 + 300 + return 0; 301 + } 302 + 303 + static int wil_memread_seq_open(struct inode *inode, struct file *file) 304 + { 305 + return single_open(file, wil_memread_debugfs_show, inode->i_private); 306 + } 307 + 308 + static const struct file_operations fops_memread = { 309 + .open = wil_memread_seq_open, 310 + .release = single_release, 311 + .read = seq_read, 312 + .llseek = seq_lseek, 313 + }; 314 + 315 + static int wil_default_open(struct inode *inode, struct file *file) 316 + { 317 + if (inode->i_private) 318 + file->private_data = inode->i_private; 319 + 320 + return 0; 321 + } 322 + 323 + static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, 324 + size_t count, loff_t *ppos) 325 + { 326 + enum { max_count = 4096 }; 327 + struct debugfs_blob_wrapper *blob = file->private_data; 328 + loff_t pos = *ppos; 329 + size_t available = blob->size; 330 + void *buf; 331 + size_t ret; 332 + 333 + if (pos < 0) 334 + return -EINVAL; 335 + 336 + if (pos >= available || !count) 337 + return 0; 338 + 339 + if (count > available - pos) 340 + count = available - pos; 341 + if (count > max_count) 342 + count = max_count; 343 + 344 + buf = kmalloc(count, GFP_KERNEL); 345 + if (!buf) 346 + return -ENOMEM; 347 + 348 + wil_memcpy_fromio_32(buf, (const volatile void __iomem *)blob->data + 349 + pos, count); 350 + 351 + ret = copy_to_user(user_buf, buf, count); 352 + kfree(buf); 353 + if (ret == count) 354 + return -EFAULT; 355 + 356 + count -= ret; 357 + *ppos = pos + count; 358 + 359 + return count; 360 + } 361 + 362 + static const struct file_operations fops_ioblob = { 363 + .read = wil_read_file_ioblob, 364 + .open = wil_default_open, 365 + .llseek = default_llseek, 366 + }; 367 + 368 + static 369 + struct dentry *wil_debugfs_create_ioblob(const char *name, 370 + mode_t mode, 371 + struct dentry *parent, 372 + struct debugfs_blob_wrapper *blob) 373 + { 374 + return debugfs_create_file(name, mode, parent, blob, &fops_ioblob); 375 + } 376 + /*---reset---*/ 377 + static ssize_t wil_write_file_reset(struct file *file, const char __user *buf, 378 + size_t len, loff_t *ppos) 379 + { 380 + struct wil6210_priv *wil = file->private_data; 381 + struct net_device *ndev = wil_to_ndev(wil); 382 + 383 + /** 384 + * BUG: 385 + * this code does NOT sync device state with the rest of system 386 + * use with care, debug only!!! 387 + */ 388 + rtnl_lock(); 389 + dev_close(ndev); 390 + ndev->flags &= ~IFF_UP; 391 + rtnl_unlock(); 392 + wil_reset(wil); 393 + 394 + return len; 395 + } 396 + 397 + static const struct file_operations fops_reset = { 398 + .write = wil_write_file_reset, 399 + .open = wil_default_open, 400 + }; 401 + /*---------Tx descriptor------------*/ 402 + 403 + static int wil_txdesc_debugfs_show(struct seq_file *s, void *data) 404 + { 405 + struct wil6210_priv *wil = s->private; 406 + struct vring *vring = &(wil->vring_tx[0]); 407 + 408 + if (!vring->va) { 409 + seq_printf(s, "No Tx VRING\n"); 410 + return 0; 411 + } 412 + 413 + if (dbg_txdesc_index < vring->size) { 414 + volatile struct vring_tx_desc *d = 415 + &(vring->va[dbg_txdesc_index].tx); 416 + volatile u32 *u = (volatile u32 *)d; 417 + struct sk_buff *skb = vring->ctx[dbg_txdesc_index]; 418 + 419 + seq_printf(s, "Tx[%3d] = {\n", dbg_txdesc_index); 420 + seq_printf(s, " MAC = 0x%08x 0x%08x 0x%08x 0x%08x\n", 421 + u[0], u[1], u[2], u[3]); 422 + seq_printf(s, " DMA = 0x%08x 0x%08x 0x%08x 0x%08x\n", 423 + u[4], u[5], u[6], u[7]); 424 + seq_printf(s, " SKB = %p\n", skb); 425 + 426 + if (skb) { 427 + unsigned char printbuf[16 * 3 + 2]; 428 + int i = 0; 429 + int len = skb_headlen(skb); 430 + void *p = skb->data; 431 + 432 + seq_printf(s, " len = %d\n", len); 433 + 434 + while (i < len) { 435 + int l = min(len - i, 16); 436 + hex_dump_to_buffer(p + i, l, 16, 1, printbuf, 437 + sizeof(printbuf), false); 438 + seq_printf(s, " : %s\n", printbuf); 439 + i += l; 440 + } 441 + } 442 + seq_printf(s, "}\n"); 443 + } else { 444 + seq_printf(s, "TxDesc index (%d) >= size (%d)\n", 445 + dbg_txdesc_index, vring->size); 446 + } 447 + 448 + return 0; 449 + } 450 + 451 + static int wil_txdesc_seq_open(struct inode *inode, struct file *file) 452 + { 453 + return single_open(file, wil_txdesc_debugfs_show, inode->i_private); 454 + } 455 + 456 + static const struct file_operations fops_txdesc = { 457 + .open = wil_txdesc_seq_open, 458 + .release = single_release, 459 + .read = seq_read, 460 + .llseek = seq_lseek, 461 + }; 462 + 463 + /*---------beamforming------------*/ 464 + static int wil_bf_debugfs_show(struct seq_file *s, void *data) 465 + { 466 + struct wil6210_priv *wil = s->private; 467 + seq_printf(s, 468 + "TSF : 0x%016llx\n" 469 + "TxMCS : %d\n" 470 + "Sectors(rx:tx) my %2d:%2d peer %2d:%2d\n", 471 + wil->stats.tsf, wil->stats.bf_mcs, 472 + wil->stats.my_rx_sector, wil->stats.my_tx_sector, 473 + wil->stats.peer_rx_sector, wil->stats.peer_tx_sector); 474 + return 0; 475 + } 476 + 477 + static int wil_bf_seq_open(struct inode *inode, struct file *file) 478 + { 479 + return single_open(file, wil_bf_debugfs_show, inode->i_private); 480 + } 481 + 482 + static const struct file_operations fops_bf = { 483 + .open = wil_bf_seq_open, 484 + .release = single_release, 485 + .read = seq_read, 486 + .llseek = seq_lseek, 487 + }; 488 + /*---------SSID------------*/ 489 + static ssize_t wil_read_file_ssid(struct file *file, char __user *user_buf, 490 + size_t count, loff_t *ppos) 491 + { 492 + struct wil6210_priv *wil = file->private_data; 493 + struct wireless_dev *wdev = wil_to_wdev(wil); 494 + 495 + return simple_read_from_buffer(user_buf, count, ppos, 496 + wdev->ssid, wdev->ssid_len); 497 + } 498 + 499 + static ssize_t wil_write_file_ssid(struct file *file, const char __user *buf, 500 + size_t count, loff_t *ppos) 501 + { 502 + struct wil6210_priv *wil = file->private_data; 503 + struct wireless_dev *wdev = wil_to_wdev(wil); 504 + struct net_device *ndev = wil_to_ndev(wil); 505 + 506 + if (*ppos != 0) { 507 + wil_err(wil, "Unable to set SSID substring from [%d]\n", 508 + (int)*ppos); 509 + return -EINVAL; 510 + } 511 + 512 + if (count > sizeof(wdev->ssid)) { 513 + wil_err(wil, "SSID too long, len = %d\n", (int)count); 514 + return -EINVAL; 515 + } 516 + if (netif_running(ndev)) { 517 + wil_err(wil, "Unable to change SSID on running interface\n"); 518 + return -EINVAL; 519 + } 520 + 521 + wdev->ssid_len = count; 522 + return simple_write_to_buffer(wdev->ssid, wdev->ssid_len, ppos, 523 + buf, count); 524 + } 525 + 526 + static const struct file_operations fops_ssid = { 527 + .read = wil_read_file_ssid, 528 + .write = wil_write_file_ssid, 529 + .open = wil_default_open, 530 + }; 531 + 532 + /*----------------*/ 533 + int wil6210_debugfs_init(struct wil6210_priv *wil) 534 + { 535 + struct dentry *dbg = wil->debug = debugfs_create_dir(WIL_NAME, 536 + wil_to_wiphy(wil)->debugfsdir); 537 + 538 + if (IS_ERR_OR_NULL(dbg)) 539 + return -ENODEV; 540 + 541 + debugfs_create_file("mbox", S_IRUGO, dbg, wil, &fops_mbox); 542 + debugfs_create_file("vrings", S_IRUGO, dbg, wil, &fops_vring); 543 + debugfs_create_file("txdesc", S_IRUGO, dbg, wil, &fops_txdesc); 544 + debugfs_create_u32("txdesc_index", S_IRUGO | S_IWUSR, dbg, 545 + &dbg_txdesc_index); 546 + debugfs_create_file("bf", S_IRUGO, dbg, wil, &fops_bf); 547 + debugfs_create_file("ssid", S_IRUGO | S_IWUSR, dbg, wil, &fops_ssid); 548 + debugfs_create_u32("secure_pcp", S_IRUGO | S_IWUSR, dbg, 549 + &wil->secure_pcp); 550 + 551 + wil6210_debugfs_create_ISR(wil, "USER_ICR", dbg, 552 + HOSTADDR(RGF_USER_USER_ICR)); 553 + wil6210_debugfs_create_ISR(wil, "DMA_EP_TX_ICR", dbg, 554 + HOSTADDR(RGF_DMA_EP_TX_ICR)); 555 + wil6210_debugfs_create_ISR(wil, "DMA_EP_RX_ICR", dbg, 556 + HOSTADDR(RGF_DMA_EP_RX_ICR)); 557 + wil6210_debugfs_create_ISR(wil, "DMA_EP_MISC_ICR", dbg, 558 + HOSTADDR(RGF_DMA_EP_MISC_ICR)); 559 + wil6210_debugfs_create_pseudo_ISR(wil, dbg); 560 + wil6210_debugfs_create_ITR_CNT(wil, dbg); 561 + 562 + debugfs_create_u32("mem_addr", S_IRUGO | S_IWUSR, dbg, &mem_addr); 563 + debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread); 564 + 565 + debugfs_create_file("reset", S_IWUSR, dbg, wil, &fops_reset); 566 + 567 + wil->rgf_blob.data = (void * __force)wil->csr + 0; 568 + wil->rgf_blob.size = 0xa000; 569 + wil_debugfs_create_ioblob("blob_rgf", S_IRUGO, dbg, &wil->rgf_blob); 570 + 571 + wil->fw_code_blob.data = (void * __force)wil->csr + 0x40000; 572 + wil->fw_code_blob.size = 0x40000; 573 + wil_debugfs_create_ioblob("blob_fw_code", S_IRUGO, dbg, 574 + &wil->fw_code_blob); 575 + 576 + wil->fw_data_blob.data = (void * __force)wil->csr + 0x80000; 577 + wil->fw_data_blob.size = 0x8000; 578 + wil_debugfs_create_ioblob("blob_fw_data", S_IRUGO, dbg, 579 + &wil->fw_data_blob); 580 + 581 + wil->fw_peri_blob.data = (void * __force)wil->csr + 0x88000; 582 + wil->fw_peri_blob.size = 0x18000; 583 + wil_debugfs_create_ioblob("blob_fw_peri", S_IRUGO, dbg, 584 + &wil->fw_peri_blob); 585 + 586 + wil->uc_code_blob.data = (void * __force)wil->csr + 0xa0000; 587 + wil->uc_code_blob.size = 0x10000; 588 + wil_debugfs_create_ioblob("blob_uc_code", S_IRUGO, dbg, 589 + &wil->uc_code_blob); 590 + 591 + wil->uc_data_blob.data = (void * __force)wil->csr + 0xb0000; 592 + wil->uc_data_blob.size = 0x4000; 593 + wil_debugfs_create_ioblob("blob_uc_data", S_IRUGO, dbg, 594 + &wil->uc_data_blob); 595 + 596 + return 0; 597 + } 598 + 599 + void wil6210_debugfs_remove(struct wil6210_priv *wil) 600 + { 601 + debugfs_remove_recursive(wil->debug); 602 + wil->debug = NULL; 603 + }
+471
drivers/net/wireless/ath/wil6210/interrupt.c
··· 1 + /* 2 + * Copyright (c) 2012 Qualcomm Atheros, Inc. 3 + * 4 + * Permission to use, copy, modify, and/or distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + 17 + #include <linux/interrupt.h> 18 + 19 + #include "wil6210.h" 20 + 21 + /** 22 + * Theory of operation: 23 + * 24 + * There is ISR pseudo-cause register, 25 + * dma_rgf->DMA_RGF.PSEUDO_CAUSE.PSEUDO_CAUSE 26 + * Its bits represents OR'ed bits from 3 real ISR registers: 27 + * TX, RX, and MISC. 28 + * 29 + * Registers may be configured to either "write 1 to clear" or 30 + * "clear on read" mode 31 + * 32 + * When handling interrupt, one have to mask/unmask interrupts for the 33 + * real ISR registers, or hardware may malfunction. 34 + * 35 + */ 36 + 37 + #define WIL6210_IRQ_DISABLE (0xFFFFFFFFUL) 38 + #define WIL6210_IMC_RX BIT_DMA_EP_RX_ICR_RX_DONE 39 + #define WIL6210_IMC_TX (BIT_DMA_EP_TX_ICR_TX_DONE | \ 40 + BIT_DMA_EP_TX_ICR_TX_DONE_N(0)) 41 + #define WIL6210_IMC_MISC (ISR_MISC_FW_READY | ISR_MISC_MBOX_EVT) 42 + 43 + #define WIL6210_IRQ_PSEUDO_MASK (u32)(~(BIT_DMA_PSEUDO_CAUSE_RX | \ 44 + BIT_DMA_PSEUDO_CAUSE_TX | \ 45 + BIT_DMA_PSEUDO_CAUSE_MISC)) 46 + 47 + #if defined(CONFIG_WIL6210_ISR_COR) 48 + /* configure to Clear-On-Read mode */ 49 + #define WIL_ICR_ICC_VALUE (0xFFFFFFFFUL) 50 + 51 + static inline void wil_icr_clear(u32 x, void __iomem *addr) 52 + { 53 + 54 + } 55 + #else /* defined(CONFIG_WIL6210_ISR_COR) */ 56 + /* configure to Write-1-to-Clear mode */ 57 + #define WIL_ICR_ICC_VALUE (0UL) 58 + 59 + static inline void wil_icr_clear(u32 x, void __iomem *addr) 60 + { 61 + iowrite32(x, addr); 62 + } 63 + #endif /* defined(CONFIG_WIL6210_ISR_COR) */ 64 + 65 + static inline u32 wil_ioread32_and_clear(void __iomem *addr) 66 + { 67 + u32 x = ioread32(addr); 68 + 69 + wil_icr_clear(x, addr); 70 + 71 + return x; 72 + } 73 + 74 + static void wil6210_mask_irq_tx(struct wil6210_priv *wil) 75 + { 76 + iowrite32(WIL6210_IRQ_DISABLE, wil->csr + 77 + HOSTADDR(RGF_DMA_EP_TX_ICR) + 78 + offsetof(struct RGF_ICR, IMS)); 79 + } 80 + 81 + static void wil6210_mask_irq_rx(struct wil6210_priv *wil) 82 + { 83 + iowrite32(WIL6210_IRQ_DISABLE, wil->csr + 84 + HOSTADDR(RGF_DMA_EP_RX_ICR) + 85 + offsetof(struct RGF_ICR, IMS)); 86 + } 87 + 88 + static void wil6210_mask_irq_misc(struct wil6210_priv *wil) 89 + { 90 + iowrite32(WIL6210_IRQ_DISABLE, wil->csr + 91 + HOSTADDR(RGF_DMA_EP_MISC_ICR) + 92 + offsetof(struct RGF_ICR, IMS)); 93 + } 94 + 95 + static void wil6210_mask_irq_pseudo(struct wil6210_priv *wil) 96 + { 97 + wil_dbg_IRQ(wil, "%s()\n", __func__); 98 + 99 + iowrite32(WIL6210_IRQ_DISABLE, wil->csr + 100 + HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); 101 + 102 + clear_bit(wil_status_irqen, &wil->status); 103 + } 104 + 105 + static void wil6210_unmask_irq_tx(struct wil6210_priv *wil) 106 + { 107 + iowrite32(WIL6210_IMC_TX, wil->csr + 108 + HOSTADDR(RGF_DMA_EP_TX_ICR) + 109 + offsetof(struct RGF_ICR, IMC)); 110 + } 111 + 112 + static void wil6210_unmask_irq_rx(struct wil6210_priv *wil) 113 + { 114 + iowrite32(WIL6210_IMC_RX, wil->csr + 115 + HOSTADDR(RGF_DMA_EP_RX_ICR) + 116 + offsetof(struct RGF_ICR, IMC)); 117 + } 118 + 119 + static void wil6210_unmask_irq_misc(struct wil6210_priv *wil) 120 + { 121 + iowrite32(WIL6210_IMC_MISC, wil->csr + 122 + HOSTADDR(RGF_DMA_EP_MISC_ICR) + 123 + offsetof(struct RGF_ICR, IMC)); 124 + } 125 + 126 + static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil) 127 + { 128 + wil_dbg_IRQ(wil, "%s()\n", __func__); 129 + 130 + set_bit(wil_status_irqen, &wil->status); 131 + 132 + iowrite32(WIL6210_IRQ_PSEUDO_MASK, wil->csr + 133 + HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); 134 + } 135 + 136 + void wil6210_disable_irq(struct wil6210_priv *wil) 137 + { 138 + wil_dbg_IRQ(wil, "%s()\n", __func__); 139 + 140 + wil6210_mask_irq_tx(wil); 141 + wil6210_mask_irq_rx(wil); 142 + wil6210_mask_irq_misc(wil); 143 + wil6210_mask_irq_pseudo(wil); 144 + } 145 + 146 + void wil6210_enable_irq(struct wil6210_priv *wil) 147 + { 148 + wil_dbg_IRQ(wil, "%s()\n", __func__); 149 + 150 + iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_RX_ICR) + 151 + offsetof(struct RGF_ICR, ICC)); 152 + iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_TX_ICR) + 153 + offsetof(struct RGF_ICR, ICC)); 154 + iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) + 155 + offsetof(struct RGF_ICR, ICC)); 156 + 157 + wil6210_unmask_irq_pseudo(wil); 158 + wil6210_unmask_irq_tx(wil); 159 + wil6210_unmask_irq_rx(wil); 160 + wil6210_unmask_irq_misc(wil); 161 + } 162 + 163 + static irqreturn_t wil6210_irq_rx(int irq, void *cookie) 164 + { 165 + struct wil6210_priv *wil = cookie; 166 + u32 isr = wil_ioread32_and_clear(wil->csr + 167 + HOSTADDR(RGF_DMA_EP_RX_ICR) + 168 + offsetof(struct RGF_ICR, ICR)); 169 + 170 + wil_dbg_IRQ(wil, "ISR RX 0x%08x\n", isr); 171 + 172 + if (!isr) { 173 + wil_err(wil, "spurious IRQ: RX\n"); 174 + return IRQ_NONE; 175 + } 176 + 177 + wil6210_mask_irq_rx(wil); 178 + 179 + if (isr & BIT_DMA_EP_RX_ICR_RX_DONE) { 180 + wil_dbg_IRQ(wil, "RX done\n"); 181 + isr &= ~BIT_DMA_EP_RX_ICR_RX_DONE; 182 + wil_rx_handle(wil); 183 + } 184 + 185 + if (isr) 186 + wil_err(wil, "un-handled RX ISR bits 0x%08x\n", isr); 187 + 188 + wil6210_unmask_irq_rx(wil); 189 + 190 + return IRQ_HANDLED; 191 + } 192 + 193 + static irqreturn_t wil6210_irq_tx(int irq, void *cookie) 194 + { 195 + struct wil6210_priv *wil = cookie; 196 + u32 isr = wil_ioread32_and_clear(wil->csr + 197 + HOSTADDR(RGF_DMA_EP_TX_ICR) + 198 + offsetof(struct RGF_ICR, ICR)); 199 + 200 + wil_dbg_IRQ(wil, "ISR TX 0x%08x\n", isr); 201 + 202 + if (!isr) { 203 + wil_err(wil, "spurious IRQ: TX\n"); 204 + return IRQ_NONE; 205 + } 206 + 207 + wil6210_mask_irq_tx(wil); 208 + 209 + if (isr & BIT_DMA_EP_TX_ICR_TX_DONE) { 210 + uint i; 211 + wil_dbg_IRQ(wil, "TX done\n"); 212 + isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE; 213 + for (i = 0; i < 24; i++) { 214 + u32 mask = BIT_DMA_EP_TX_ICR_TX_DONE_N(i); 215 + if (isr & mask) { 216 + isr &= ~mask; 217 + wil_dbg_IRQ(wil, "TX done(%i)\n", i); 218 + wil_tx_complete(wil, i); 219 + } 220 + } 221 + } 222 + 223 + if (isr) 224 + wil_err(wil, "un-handled TX ISR bits 0x%08x\n", isr); 225 + 226 + wil6210_unmask_irq_tx(wil); 227 + 228 + return IRQ_HANDLED; 229 + } 230 + 231 + static irqreturn_t wil6210_irq_misc(int irq, void *cookie) 232 + { 233 + struct wil6210_priv *wil = cookie; 234 + u32 isr = wil_ioread32_and_clear(wil->csr + 235 + HOSTADDR(RGF_DMA_EP_MISC_ICR) + 236 + offsetof(struct RGF_ICR, ICR)); 237 + 238 + wil_dbg_IRQ(wil, "ISR MISC 0x%08x\n", isr); 239 + 240 + if (!isr) { 241 + wil_err(wil, "spurious IRQ: MISC\n"); 242 + return IRQ_NONE; 243 + } 244 + 245 + wil6210_mask_irq_misc(wil); 246 + 247 + if (isr & ISR_MISC_FW_READY) { 248 + wil_dbg_IRQ(wil, "IRQ: FW ready\n"); 249 + /** 250 + * Actual FW ready indicated by the 251 + * WMI_FW_READY_EVENTID 252 + */ 253 + isr &= ~ISR_MISC_FW_READY; 254 + } 255 + 256 + wil->isr_misc = isr; 257 + 258 + if (isr) { 259 + return IRQ_WAKE_THREAD; 260 + } else { 261 + wil6210_unmask_irq_misc(wil); 262 + return IRQ_HANDLED; 263 + } 264 + } 265 + 266 + static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie) 267 + { 268 + struct wil6210_priv *wil = cookie; 269 + u32 isr = wil->isr_misc; 270 + 271 + wil_dbg_IRQ(wil, "Thread ISR MISC 0x%08x\n", isr); 272 + 273 + if (isr & ISR_MISC_MBOX_EVT) { 274 + wil_dbg_IRQ(wil, "MBOX event\n"); 275 + wmi_recv_cmd(wil); 276 + isr &= ~ISR_MISC_MBOX_EVT; 277 + } 278 + 279 + if (isr) 280 + wil_err(wil, "un-handled MISC ISR bits 0x%08x\n", isr); 281 + 282 + wil->isr_misc = 0; 283 + 284 + wil6210_unmask_irq_misc(wil); 285 + 286 + return IRQ_HANDLED; 287 + } 288 + 289 + /** 290 + * thread IRQ handler 291 + */ 292 + static irqreturn_t wil6210_thread_irq(int irq, void *cookie) 293 + { 294 + struct wil6210_priv *wil = cookie; 295 + 296 + wil_dbg_IRQ(wil, "Thread IRQ\n"); 297 + /* Discover real IRQ cause */ 298 + if (wil->isr_misc) 299 + wil6210_irq_misc_thread(irq, cookie); 300 + 301 + wil6210_unmask_irq_pseudo(wil); 302 + 303 + return IRQ_HANDLED; 304 + } 305 + 306 + /* DEBUG 307 + * There is subtle bug in hardware that causes IRQ to raise when it should be 308 + * masked. It is quite rare and hard to debug. 309 + * 310 + * Catch irq issue if it happens and print all I can. 311 + */ 312 + static int wil6210_debug_irq_mask(struct wil6210_priv *wil, u32 pseudo_cause) 313 + { 314 + if (!test_bit(wil_status_irqen, &wil->status)) { 315 + u32 icm_rx = wil_ioread32_and_clear(wil->csr + 316 + HOSTADDR(RGF_DMA_EP_RX_ICR) + 317 + offsetof(struct RGF_ICR, ICM)); 318 + u32 icr_rx = wil_ioread32_and_clear(wil->csr + 319 + HOSTADDR(RGF_DMA_EP_RX_ICR) + 320 + offsetof(struct RGF_ICR, ICR)); 321 + u32 imv_rx = ioread32(wil->csr + 322 + HOSTADDR(RGF_DMA_EP_RX_ICR) + 323 + offsetof(struct RGF_ICR, IMV)); 324 + u32 icm_tx = wil_ioread32_and_clear(wil->csr + 325 + HOSTADDR(RGF_DMA_EP_TX_ICR) + 326 + offsetof(struct RGF_ICR, ICM)); 327 + u32 icr_tx = wil_ioread32_and_clear(wil->csr + 328 + HOSTADDR(RGF_DMA_EP_TX_ICR) + 329 + offsetof(struct RGF_ICR, ICR)); 330 + u32 imv_tx = ioread32(wil->csr + 331 + HOSTADDR(RGF_DMA_EP_TX_ICR) + 332 + offsetof(struct RGF_ICR, IMV)); 333 + u32 icm_misc = wil_ioread32_and_clear(wil->csr + 334 + HOSTADDR(RGF_DMA_EP_MISC_ICR) + 335 + offsetof(struct RGF_ICR, ICM)); 336 + u32 icr_misc = wil_ioread32_and_clear(wil->csr + 337 + HOSTADDR(RGF_DMA_EP_MISC_ICR) + 338 + offsetof(struct RGF_ICR, ICR)); 339 + u32 imv_misc = ioread32(wil->csr + 340 + HOSTADDR(RGF_DMA_EP_MISC_ICR) + 341 + offsetof(struct RGF_ICR, IMV)); 342 + wil_err(wil, "IRQ when it should be masked: pseudo 0x%08x\n" 343 + "Rx icm:icr:imv 0x%08x 0x%08x 0x%08x\n" 344 + "Tx icm:icr:imv 0x%08x 0x%08x 0x%08x\n" 345 + "Misc icm:icr:imv 0x%08x 0x%08x 0x%08x\n", 346 + pseudo_cause, 347 + icm_rx, icr_rx, imv_rx, 348 + icm_tx, icr_tx, imv_tx, 349 + icm_misc, icr_misc, imv_misc); 350 + 351 + return -EINVAL; 352 + } 353 + 354 + return 0; 355 + } 356 + 357 + static irqreturn_t wil6210_hardirq(int irq, void *cookie) 358 + { 359 + irqreturn_t rc = IRQ_HANDLED; 360 + struct wil6210_priv *wil = cookie; 361 + u32 pseudo_cause = ioread32(wil->csr + HOSTADDR(RGF_DMA_PSEUDO_CAUSE)); 362 + 363 + /** 364 + * pseudo_cause is Clear-On-Read, no need to ACK 365 + */ 366 + if ((pseudo_cause == 0) || ((pseudo_cause & 0xff) == 0xff)) 367 + return IRQ_NONE; 368 + 369 + /* FIXME: IRQ mask debug */ 370 + if (wil6210_debug_irq_mask(wil, pseudo_cause)) 371 + return IRQ_NONE; 372 + 373 + wil6210_mask_irq_pseudo(wil); 374 + 375 + /* Discover real IRQ cause 376 + * There are 2 possible phases for every IRQ: 377 + * - hard IRQ handler called right here 378 + * - threaded handler called later 379 + * 380 + * Hard IRQ handler reads and clears ISR. 381 + * 382 + * If threaded handler requested, hard IRQ handler 383 + * returns IRQ_WAKE_THREAD and saves ISR register value 384 + * for the threaded handler use. 385 + * 386 + * voting for wake thread - need at least 1 vote 387 + */ 388 + if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_RX) && 389 + (wil6210_irq_rx(irq, cookie) == IRQ_WAKE_THREAD)) 390 + rc = IRQ_WAKE_THREAD; 391 + 392 + if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_TX) && 393 + (wil6210_irq_tx(irq, cookie) == IRQ_WAKE_THREAD)) 394 + rc = IRQ_WAKE_THREAD; 395 + 396 + if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_MISC) && 397 + (wil6210_irq_misc(irq, cookie) == IRQ_WAKE_THREAD)) 398 + rc = IRQ_WAKE_THREAD; 399 + 400 + /* if thread is requested, it will unmask IRQ */ 401 + if (rc != IRQ_WAKE_THREAD) 402 + wil6210_unmask_irq_pseudo(wil); 403 + 404 + wil_dbg_IRQ(wil, "Hard IRQ 0x%08x\n", pseudo_cause); 405 + 406 + return rc; 407 + } 408 + 409 + static int wil6210_request_3msi(struct wil6210_priv *wil, int irq) 410 + { 411 + int rc; 412 + /* 413 + * IRQ's are in the following order: 414 + * - Tx 415 + * - Rx 416 + * - Misc 417 + */ 418 + 419 + rc = request_irq(irq, wil6210_irq_tx, IRQF_SHARED, 420 + WIL_NAME"_tx", wil); 421 + if (rc) 422 + return rc; 423 + 424 + rc = request_irq(irq + 1, wil6210_irq_rx, IRQF_SHARED, 425 + WIL_NAME"_rx", wil); 426 + if (rc) 427 + goto free0; 428 + 429 + rc = request_threaded_irq(irq + 2, wil6210_irq_misc, 430 + wil6210_irq_misc_thread, 431 + IRQF_SHARED, WIL_NAME"_misc", wil); 432 + if (rc) 433 + goto free1; 434 + 435 + return 0; 436 + /* error branch */ 437 + free1: 438 + free_irq(irq + 1, wil); 439 + free0: 440 + free_irq(irq, wil); 441 + 442 + return rc; 443 + } 444 + 445 + int wil6210_init_irq(struct wil6210_priv *wil, int irq) 446 + { 447 + int rc; 448 + if (wil->n_msi == 3) 449 + rc = wil6210_request_3msi(wil, irq); 450 + else 451 + rc = request_threaded_irq(irq, wil6210_hardirq, 452 + wil6210_thread_irq, 453 + wil->n_msi ? 0 : IRQF_SHARED, 454 + WIL_NAME, wil); 455 + if (rc) 456 + return rc; 457 + 458 + wil6210_enable_irq(wil); 459 + 460 + return 0; 461 + } 462 + 463 + void wil6210_fini_irq(struct wil6210_priv *wil, int irq) 464 + { 465 + wil6210_disable_irq(wil); 466 + free_irq(irq, wil); 467 + if (wil->n_msi == 3) { 468 + free_irq(irq + 1, wil); 469 + free_irq(irq + 2, wil); 470 + } 471 + }
+407
drivers/net/wireless/ath/wil6210/main.c
··· 1 + /* 2 + * Copyright (c) 2012 Qualcomm Atheros, Inc. 3 + * 4 + * Permission to use, copy, modify, and/or distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + 17 + #include <linux/kernel.h> 18 + #include <linux/netdevice.h> 19 + #include <linux/sched.h> 20 + #include <linux/ieee80211.h> 21 + #include <linux/wireless.h> 22 + #include <linux/slab.h> 23 + #include <linux/moduleparam.h> 24 + #include <linux/if_arp.h> 25 + 26 + #include "wil6210.h" 27 + 28 + /* 29 + * Due to a hardware issue, 30 + * one has to read/write to/from NIC in 32-bit chunks; 31 + * regular memcpy_fromio and siblings will 32 + * not work on 64-bit platform - it uses 64-bit transactions 33 + * 34 + * Force 32-bit transactions to enable NIC on 64-bit platforms 35 + * 36 + * To avoid byte swap on big endian host, __raw_{read|write}l 37 + * should be used - {read|write}l would swap bytes to provide 38 + * little endian on PCI value in host endianness. 39 + */ 40 + void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src, 41 + size_t count) 42 + { 43 + u32 *d = dst; 44 + const volatile u32 __iomem *s = src; 45 + 46 + /* size_t is unsigned, if (count%4 != 0) it will wrap */ 47 + for (count += 4; count > 4; count -= 4) 48 + *d++ = __raw_readl(s++); 49 + } 50 + 51 + void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, 52 + size_t count) 53 + { 54 + volatile u32 __iomem *d = dst; 55 + const u32 *s = src; 56 + 57 + for (count += 4; count > 4; count -= 4) 58 + __raw_writel(*s++, d++); 59 + } 60 + 61 + static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid) 62 + { 63 + uint i; 64 + struct net_device *ndev = wil_to_ndev(wil); 65 + struct wireless_dev *wdev = wil->wdev; 66 + 67 + wil_dbg(wil, "%s()\n", __func__); 68 + 69 + wil_link_off(wil); 70 + clear_bit(wil_status_fwconnected, &wil->status); 71 + 72 + switch (wdev->sme_state) { 73 + case CFG80211_SME_CONNECTED: 74 + cfg80211_disconnected(ndev, WLAN_STATUS_UNSPECIFIED_FAILURE, 75 + NULL, 0, GFP_KERNEL); 76 + break; 77 + case CFG80211_SME_CONNECTING: 78 + cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0, 79 + WLAN_STATUS_UNSPECIFIED_FAILURE, 80 + GFP_KERNEL); 81 + break; 82 + default: 83 + ; 84 + } 85 + 86 + for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) 87 + wil_vring_fini_tx(wil, i); 88 + } 89 + 90 + static void wil_disconnect_worker(struct work_struct *work) 91 + { 92 + struct wil6210_priv *wil = container_of(work, 93 + struct wil6210_priv, disconnect_worker); 94 + 95 + _wil6210_disconnect(wil, NULL); 96 + } 97 + 98 + static void wil_connect_timer_fn(ulong x) 99 + { 100 + struct wil6210_priv *wil = (void *)x; 101 + 102 + wil_dbg(wil, "Connect timeout\n"); 103 + 104 + /* reschedule to thread context - disconnect won't 105 + * run from atomic context 106 + */ 107 + schedule_work(&wil->disconnect_worker); 108 + } 109 + 110 + int wil_priv_init(struct wil6210_priv *wil) 111 + { 112 + wil_dbg(wil, "%s()\n", __func__); 113 + 114 + mutex_init(&wil->mutex); 115 + mutex_init(&wil->wmi_mutex); 116 + 117 + init_completion(&wil->wmi_ready); 118 + 119 + wil->pending_connect_cid = -1; 120 + setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil); 121 + 122 + INIT_WORK(&wil->wmi_connect_worker, wmi_connect_worker); 123 + INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker); 124 + INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); 125 + 126 + INIT_LIST_HEAD(&wil->pending_wmi_ev); 127 + spin_lock_init(&wil->wmi_ev_lock); 128 + 129 + wil->wmi_wq = create_singlethread_workqueue(WIL_NAME"_wmi"); 130 + if (!wil->wmi_wq) 131 + return -EAGAIN; 132 + 133 + wil->wmi_wq_conn = create_singlethread_workqueue(WIL_NAME"_connect"); 134 + if (!wil->wmi_wq_conn) { 135 + destroy_workqueue(wil->wmi_wq); 136 + return -EAGAIN; 137 + } 138 + 139 + /* make shadow copy of registers that should not change on run time */ 140 + wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX, 141 + sizeof(struct wil6210_mbox_ctl)); 142 + wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx); 143 + wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx); 144 + 145 + return 0; 146 + } 147 + 148 + void wil6210_disconnect(struct wil6210_priv *wil, void *bssid) 149 + { 150 + del_timer_sync(&wil->connect_timer); 151 + _wil6210_disconnect(wil, bssid); 152 + } 153 + 154 + void wil_priv_deinit(struct wil6210_priv *wil) 155 + { 156 + cancel_work_sync(&wil->disconnect_worker); 157 + wil6210_disconnect(wil, NULL); 158 + wmi_event_flush(wil); 159 + destroy_workqueue(wil->wmi_wq_conn); 160 + destroy_workqueue(wil->wmi_wq); 161 + } 162 + 163 + static void wil_target_reset(struct wil6210_priv *wil) 164 + { 165 + wil_dbg(wil, "Resetting...\n"); 166 + 167 + /* register write */ 168 + #define W(a, v) iowrite32(v, wil->csr + HOSTADDR(a)) 169 + /* register set = read, OR, write */ 170 + #define S(a, v) iowrite32(ioread32(wil->csr + HOSTADDR(a)) | v, \ 171 + wil->csr + HOSTADDR(a)) 172 + 173 + /* hpal_perst_from_pad_src_n_mask */ 174 + S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(6)); 175 + /* car_perst_rst_src_n_mask */ 176 + S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(7)); 177 + 178 + W(RGF_USER_MAC_CPU_0, BIT(1)); /* mac_cpu_man_rst */ 179 + W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */ 180 + 181 + msleep(100); 182 + 183 + W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000); 184 + W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F); 185 + W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000170); 186 + W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00); 187 + 188 + msleep(100); 189 + 190 + W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0); 191 + W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0); 192 + W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0); 193 + W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); 194 + 195 + W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001); 196 + W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080); 197 + W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); 198 + 199 + msleep(2000); 200 + 201 + W(RGF_USER_USER_CPU_0, BIT(0)); /* user_cpu_man_de_rst */ 202 + 203 + msleep(2000); 204 + 205 + wil_dbg(wil, "Reset completed\n"); 206 + 207 + #undef W 208 + #undef S 209 + } 210 + 211 + void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r) 212 + { 213 + le32_to_cpus(&r->base); 214 + le16_to_cpus(&r->entry_size); 215 + le16_to_cpus(&r->size); 216 + le32_to_cpus(&r->tail); 217 + le32_to_cpus(&r->head); 218 + } 219 + 220 + static int wil_wait_for_fw_ready(struct wil6210_priv *wil) 221 + { 222 + ulong to = msecs_to_jiffies(1000); 223 + ulong left = wait_for_completion_timeout(&wil->wmi_ready, to); 224 + if (0 == left) { 225 + wil_err(wil, "Firmware not ready\n"); 226 + return -ETIME; 227 + } else { 228 + wil_dbg(wil, "FW ready after %d ms\n", 229 + jiffies_to_msecs(to-left)); 230 + } 231 + return 0; 232 + } 233 + 234 + /* 235 + * We reset all the structures, and we reset the UMAC. 236 + * After calling this routine, you're expected to reload 237 + * the firmware. 238 + */ 239 + int wil_reset(struct wil6210_priv *wil) 240 + { 241 + int rc; 242 + 243 + cancel_work_sync(&wil->disconnect_worker); 244 + wil6210_disconnect(wil, NULL); 245 + 246 + wmi_event_flush(wil); 247 + 248 + flush_workqueue(wil->wmi_wq); 249 + flush_workqueue(wil->wmi_wq_conn); 250 + 251 + wil6210_disable_irq(wil); 252 + wil->status = 0; 253 + 254 + /* TODO: put MAC in reset */ 255 + wil_target_reset(wil); 256 + 257 + /* init after reset */ 258 + wil->pending_connect_cid = -1; 259 + INIT_COMPLETION(wil->wmi_ready); 260 + 261 + /* make shadow copy of registers that should not change on run time */ 262 + wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX, 263 + sizeof(struct wil6210_mbox_ctl)); 264 + wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx); 265 + wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx); 266 + 267 + /* TODO: release MAC reset */ 268 + wil6210_enable_irq(wil); 269 + 270 + /* we just started MAC, wait for FW ready */ 271 + rc = wil_wait_for_fw_ready(wil); 272 + 273 + return rc; 274 + } 275 + 276 + 277 + void wil_link_on(struct wil6210_priv *wil) 278 + { 279 + struct net_device *ndev = wil_to_ndev(wil); 280 + 281 + wil_dbg(wil, "%s()\n", __func__); 282 + 283 + netif_carrier_on(ndev); 284 + netif_tx_wake_all_queues(ndev); 285 + } 286 + 287 + void wil_link_off(struct wil6210_priv *wil) 288 + { 289 + struct net_device *ndev = wil_to_ndev(wil); 290 + 291 + wil_dbg(wil, "%s()\n", __func__); 292 + 293 + netif_tx_stop_all_queues(ndev); 294 + netif_carrier_off(ndev); 295 + } 296 + 297 + static int __wil_up(struct wil6210_priv *wil) 298 + { 299 + struct net_device *ndev = wil_to_ndev(wil); 300 + struct wireless_dev *wdev = wil->wdev; 301 + struct ieee80211_channel *channel = wdev->preset_chandef.chan; 302 + int rc; 303 + int bi; 304 + u16 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); 305 + 306 + rc = wil_reset(wil); 307 + if (rc) 308 + return rc; 309 + 310 + /* FIXME Firmware works now in PBSS mode(ToDS=0, FromDS=0) */ 311 + wmi_nettype = wil_iftype_nl2wmi(NL80211_IFTYPE_ADHOC); 312 + switch (wdev->iftype) { 313 + case NL80211_IFTYPE_STATION: 314 + wil_dbg(wil, "type: STATION\n"); 315 + bi = 0; 316 + ndev->type = ARPHRD_ETHER; 317 + break; 318 + case NL80211_IFTYPE_AP: 319 + wil_dbg(wil, "type: AP\n"); 320 + bi = 100; 321 + ndev->type = ARPHRD_ETHER; 322 + break; 323 + case NL80211_IFTYPE_P2P_CLIENT: 324 + wil_dbg(wil, "type: P2P_CLIENT\n"); 325 + bi = 0; 326 + ndev->type = ARPHRD_ETHER; 327 + break; 328 + case NL80211_IFTYPE_P2P_GO: 329 + wil_dbg(wil, "type: P2P_GO\n"); 330 + bi = 100; 331 + ndev->type = ARPHRD_ETHER; 332 + break; 333 + case NL80211_IFTYPE_MONITOR: 334 + wil_dbg(wil, "type: Monitor\n"); 335 + bi = 0; 336 + ndev->type = ARPHRD_IEEE80211_RADIOTAP; 337 + /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_RADIOTAP ? */ 338 + break; 339 + default: 340 + return -EOPNOTSUPP; 341 + } 342 + 343 + /* Apply profile in the following order: */ 344 + /* SSID and channel for the AP */ 345 + switch (wdev->iftype) { 346 + case NL80211_IFTYPE_AP: 347 + case NL80211_IFTYPE_P2P_GO: 348 + if (wdev->ssid_len == 0) { 349 + wil_err(wil, "SSID not set\n"); 350 + return -EINVAL; 351 + } 352 + wmi_set_ssid(wil, wdev->ssid_len, wdev->ssid); 353 + if (channel) 354 + wmi_set_channel(wil, channel->hw_value); 355 + break; 356 + default: 357 + ; 358 + } 359 + 360 + /* MAC address - pre-requisite for other commands */ 361 + wmi_set_mac_address(wil, ndev->dev_addr); 362 + 363 + /* Set up beaconing if required. */ 364 + rc = wmi_set_bcon(wil, bi, wmi_nettype); 365 + if (rc) 366 + return rc; 367 + 368 + /* Rx VRING. After MAC and beacon */ 369 + wil_rx_init(wil); 370 + 371 + return 0; 372 + } 373 + 374 + int wil_up(struct wil6210_priv *wil) 375 + { 376 + int rc; 377 + 378 + mutex_lock(&wil->mutex); 379 + rc = __wil_up(wil); 380 + mutex_unlock(&wil->mutex); 381 + 382 + return rc; 383 + } 384 + 385 + static int __wil_down(struct wil6210_priv *wil) 386 + { 387 + if (wil->scan_request) { 388 + cfg80211_scan_done(wil->scan_request, true); 389 + wil->scan_request = NULL; 390 + } 391 + 392 + wil6210_disconnect(wil, NULL); 393 + wil_rx_fini(wil); 394 + 395 + return 0; 396 + } 397 + 398 + int wil_down(struct wil6210_priv *wil) 399 + { 400 + int rc; 401 + 402 + mutex_lock(&wil->mutex); 403 + rc = __wil_down(wil); 404 + mutex_unlock(&wil->mutex); 405 + 406 + return rc; 407 + }
+157
drivers/net/wireless/ath/wil6210/netdev.c
··· 1 + /* 2 + * Copyright (c) 2012 Qualcomm Atheros, Inc. 3 + * 4 + * Permission to use, copy, modify, and/or distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + 17 + #include <linux/module.h> 18 + #include <linux/netdevice.h> 19 + #include <linux/etherdevice.h> 20 + #include <linux/slab.h> 21 + 22 + #include "wil6210.h" 23 + 24 + static int wil_open(struct net_device *ndev) 25 + { 26 + struct wil6210_priv *wil = ndev_to_wil(ndev); 27 + 28 + return wil_up(wil); 29 + } 30 + 31 + static int wil_stop(struct net_device *ndev) 32 + { 33 + struct wil6210_priv *wil = ndev_to_wil(ndev); 34 + 35 + return wil_down(wil); 36 + } 37 + 38 + /* 39 + * AC to queue mapping 40 + * 41 + * AC_VO -> queue 3 42 + * AC_VI -> queue 2 43 + * AC_BE -> queue 1 44 + * AC_BK -> queue 0 45 + */ 46 + static u16 wil_select_queue(struct net_device *ndev, struct sk_buff *skb) 47 + { 48 + static const u16 wil_1d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; 49 + struct wil6210_priv *wil = ndev_to_wil(ndev); 50 + u16 rc; 51 + 52 + skb->priority = cfg80211_classify8021d(skb); 53 + 54 + rc = wil_1d_to_queue[skb->priority]; 55 + 56 + wil_dbg_TXRX(wil, "%s() %d -> %d\n", __func__, (int)skb->priority, 57 + (int)rc); 58 + 59 + return rc; 60 + } 61 + 62 + static const struct net_device_ops wil_netdev_ops = { 63 + .ndo_open = wil_open, 64 + .ndo_stop = wil_stop, 65 + .ndo_start_xmit = wil_start_xmit, 66 + .ndo_select_queue = wil_select_queue, 67 + .ndo_set_mac_address = eth_mac_addr, 68 + .ndo_validate_addr = eth_validate_addr, 69 + }; 70 + 71 + void *wil_if_alloc(struct device *dev, void __iomem *csr) 72 + { 73 + struct net_device *ndev; 74 + struct wireless_dev *wdev; 75 + struct wil6210_priv *wil; 76 + struct ieee80211_channel *ch; 77 + int rc = 0; 78 + 79 + wdev = wil_cfg80211_init(dev); 80 + if (IS_ERR(wdev)) { 81 + dev_err(dev, "wil_cfg80211_init failed\n"); 82 + return wdev; 83 + } 84 + 85 + wil = wdev_to_wil(wdev); 86 + wil->csr = csr; 87 + wil->wdev = wdev; 88 + 89 + rc = wil_priv_init(wil); 90 + if (rc) { 91 + dev_err(dev, "wil_priv_init failed\n"); 92 + goto out_wdev; 93 + } 94 + 95 + wdev->iftype = NL80211_IFTYPE_STATION; /* TODO */ 96 + /* default monitor channel */ 97 + ch = wdev->wiphy->bands[IEEE80211_BAND_60GHZ]->channels; 98 + cfg80211_chandef_create(&wdev->preset_chandef, ch, NL80211_CHAN_NO_HT); 99 + 100 + ndev = alloc_netdev_mqs(0, "wlan%d", ether_setup, WIL6210_TX_QUEUES, 1); 101 + if (!ndev) { 102 + dev_err(dev, "alloc_netdev_mqs failed\n"); 103 + rc = -ENOMEM; 104 + goto out_priv; 105 + } 106 + 107 + ndev->netdev_ops = &wil_netdev_ops; 108 + ndev->ieee80211_ptr = wdev; 109 + SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); 110 + wdev->netdev = ndev; 111 + 112 + wil_link_off(wil); 113 + 114 + return wil; 115 + 116 + out_priv: 117 + wil_priv_deinit(wil); 118 + 119 + out_wdev: 120 + wil_wdev_free(wil); 121 + 122 + return ERR_PTR(rc); 123 + } 124 + 125 + void wil_if_free(struct wil6210_priv *wil) 126 + { 127 + struct net_device *ndev = wil_to_ndev(wil); 128 + if (!ndev) 129 + return; 130 + 131 + free_netdev(ndev); 132 + wil_priv_deinit(wil); 133 + wil_wdev_free(wil); 134 + } 135 + 136 + int wil_if_add(struct wil6210_priv *wil) 137 + { 138 + struct net_device *ndev = wil_to_ndev(wil); 139 + int rc; 140 + 141 + rc = register_netdev(ndev); 142 + if (rc < 0) { 143 + dev_err(&ndev->dev, "Failed to register netdev: %d\n", rc); 144 + return rc; 145 + } 146 + 147 + wil_link_off(wil); 148 + 149 + return 0; 150 + } 151 + 152 + void wil_if_remove(struct wil6210_priv *wil) 153 + { 154 + struct net_device *ndev = wil_to_ndev(wil); 155 + 156 + unregister_netdev(ndev); 157 + }
+223
drivers/net/wireless/ath/wil6210/pcie_bus.c
··· 1 + /* 2 + * Copyright (c) 2012 Qualcomm Atheros, Inc. 3 + * 4 + * Permission to use, copy, modify, and/or distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + 17 + #include <linux/kernel.h> 18 + #include <linux/module.h> 19 + #include <linux/slab.h> 20 + #include <linux/netdevice.h> 21 + #include <linux/debugfs.h> 22 + #include <linux/pci.h> 23 + #include <linux/moduleparam.h> 24 + 25 + #include "wil6210.h" 26 + 27 + static int use_msi = 1; 28 + module_param(use_msi, int, S_IRUGO); 29 + MODULE_PARM_DESC(use_msi, 30 + " Use MSI interrupt: " 31 + "0 - don't, 1 - (default) - single, or 3"); 32 + 33 + /* Bus ops */ 34 + static int wil_if_pcie_enable(struct wil6210_priv *wil) 35 + { 36 + struct pci_dev *pdev = wil->pdev; 37 + int rc; 38 + 39 + pci_set_master(pdev); 40 + 41 + /* 42 + * how many MSI interrupts to request? 43 + */ 44 + switch (use_msi) { 45 + case 3: 46 + case 1: 47 + case 0: 48 + break; 49 + default: 50 + wil_err(wil, "Invalid use_msi=%d, default to 1\n", 51 + use_msi); 52 + use_msi = 1; 53 + } 54 + wil->n_msi = use_msi; 55 + if (wil->n_msi) { 56 + wil_dbg(wil, "Setup %d MSI interrupts\n", use_msi); 57 + rc = pci_enable_msi_block(pdev, wil->n_msi); 58 + if (rc && (wil->n_msi == 3)) { 59 + wil_err(wil, "3 MSI mode failed, try 1 MSI\n"); 60 + wil->n_msi = 1; 61 + rc = pci_enable_msi_block(pdev, wil->n_msi); 62 + } 63 + if (rc) { 64 + wil_err(wil, "pci_enable_msi failed, use INTx\n"); 65 + wil->n_msi = 0; 66 + } 67 + } else { 68 + wil_dbg(wil, "MSI interrupts disabled, use INTx\n"); 69 + } 70 + 71 + rc = wil6210_init_irq(wil, pdev->irq); 72 + if (rc) 73 + goto stop_master; 74 + 75 + /* need reset here to obtain MAC */ 76 + rc = wil_reset(wil); 77 + if (rc) 78 + goto release_irq; 79 + 80 + return 0; 81 + 82 + release_irq: 83 + wil6210_fini_irq(wil, pdev->irq); 84 + /* safe to call if no MSI */ 85 + pci_disable_msi(pdev); 86 + stop_master: 87 + pci_clear_master(pdev); 88 + return rc; 89 + } 90 + 91 + static int wil_if_pcie_disable(struct wil6210_priv *wil) 92 + { 93 + struct pci_dev *pdev = wil->pdev; 94 + 95 + pci_clear_master(pdev); 96 + /* disable and release IRQ */ 97 + wil6210_fini_irq(wil, pdev->irq); 98 + /* safe to call if no MSI */ 99 + pci_disable_msi(pdev); 100 + /* TODO: disable HW */ 101 + 102 + return 0; 103 + } 104 + 105 + static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) 106 + { 107 + struct wil6210_priv *wil; 108 + struct device *dev = &pdev->dev; 109 + void __iomem *csr; 110 + int rc; 111 + 112 + /* check HW */ 113 + dev_info(&pdev->dev, WIL_NAME " device found [%04x:%04x] (rev %x)\n", 114 + (int)pdev->vendor, (int)pdev->device, (int)pdev->revision); 115 + 116 + if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) { 117 + dev_err(&pdev->dev, "Not " WIL_NAME "? " 118 + "BAR0 size is %lu while expecting %lu\n", 119 + (ulong)pci_resource_len(pdev, 0), WIL6210_MEM_SIZE); 120 + return -ENODEV; 121 + } 122 + 123 + rc = pci_enable_device(pdev); 124 + if (rc) { 125 + dev_err(&pdev->dev, "pci_enable_device failed\n"); 126 + return -ENODEV; 127 + } 128 + /* rollback to err_disable_pdev */ 129 + 130 + rc = pci_request_region(pdev, 0, WIL_NAME); 131 + if (rc) { 132 + dev_err(&pdev->dev, "pci_request_region failed\n"); 133 + goto err_disable_pdev; 134 + } 135 + /* rollback to err_release_reg */ 136 + 137 + csr = pci_ioremap_bar(pdev, 0); 138 + if (!csr) { 139 + dev_err(&pdev->dev, "pci_ioremap_bar failed\n"); 140 + rc = -ENODEV; 141 + goto err_release_reg; 142 + } 143 + /* rollback to err_iounmap */ 144 + dev_info(&pdev->dev, "CSR at %pR -> %p\n", &pdev->resource[0], csr); 145 + 146 + wil = wil_if_alloc(dev, csr); 147 + if (IS_ERR(wil)) { 148 + rc = (int)PTR_ERR(wil); 149 + dev_err(dev, "wil_if_alloc failed: %d\n", rc); 150 + goto err_iounmap; 151 + } 152 + /* rollback to if_free */ 153 + 154 + pci_set_drvdata(pdev, wil); 155 + wil->pdev = pdev; 156 + 157 + /* FW should raise IRQ when ready */ 158 + rc = wil_if_pcie_enable(wil); 159 + if (rc) { 160 + wil_err(wil, "Enable device failed\n"); 161 + goto if_free; 162 + } 163 + /* rollback to bus_disable */ 164 + 165 + rc = wil_if_add(wil); 166 + if (rc) { 167 + wil_err(wil, "wil_if_add failed: %d\n", rc); 168 + goto bus_disable; 169 + } 170 + 171 + wil6210_debugfs_init(wil); 172 + 173 + /* check FW is alive */ 174 + wmi_echo(wil); 175 + 176 + return 0; 177 + 178 + bus_disable: 179 + wil_if_pcie_disable(wil); 180 + if_free: 181 + wil_if_free(wil); 182 + err_iounmap: 183 + pci_iounmap(pdev, csr); 184 + err_release_reg: 185 + pci_release_region(pdev, 0); 186 + err_disable_pdev: 187 + pci_disable_device(pdev); 188 + 189 + return rc; 190 + } 191 + 192 + static void wil_pcie_remove(struct pci_dev *pdev) 193 + { 194 + struct wil6210_priv *wil = pci_get_drvdata(pdev); 195 + 196 + wil6210_debugfs_remove(wil); 197 + wil_if_pcie_disable(wil); 198 + wil_if_remove(wil); 199 + wil_if_free(wil); 200 + pci_iounmap(pdev, wil->csr); 201 + pci_release_region(pdev, 0); 202 + pci_disable_device(pdev); 203 + pci_set_drvdata(pdev, NULL); 204 + } 205 + 206 + static DEFINE_PCI_DEVICE_TABLE(wil6210_pcie_ids) = { 207 + { PCI_DEVICE(0x1ae9, 0x0301) }, 208 + { /* end: all zeroes */ }, 209 + }; 210 + MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids); 211 + 212 + static struct pci_driver wil6210_driver = { 213 + .probe = wil_pcie_probe, 214 + .remove = wil_pcie_remove, 215 + .id_table = wil6210_pcie_ids, 216 + .name = WIL_NAME, 217 + }; 218 + 219 + module_pci_driver(wil6210_driver); 220 + 221 + MODULE_LICENSE("Dual BSD/GPL"); 222 + MODULE_AUTHOR("Qualcomm Atheros <wil6210@qca.qualcomm.com>"); 223 + MODULE_DESCRIPTION("Driver for 60g WiFi WIL6210 card");
+871
drivers/net/wireless/ath/wil6210/txrx.c
··· 1 + /* 2 + * Copyright (c) 2012 Qualcomm Atheros, Inc. 3 + * 4 + * Permission to use, copy, modify, and/or distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + 17 + #include <linux/kernel.h> 18 + #include <linux/netdevice.h> 19 + #include <linux/etherdevice.h> 20 + #include <linux/hardirq.h> 21 + #include <net/ieee80211_radiotap.h> 22 + #include <linux/if_arp.h> 23 + #include <linux/moduleparam.h> 24 + 25 + #include "wil6210.h" 26 + #include "wmi.h" 27 + #include "txrx.h" 28 + 29 + static bool rtap_include_phy_info; 30 + module_param(rtap_include_phy_info, bool, S_IRUGO); 31 + MODULE_PARM_DESC(rtap_include_phy_info, 32 + " Include PHY info in the radiotap header, default - no"); 33 + 34 + static inline int wil_vring_is_empty(struct vring *vring) 35 + { 36 + return vring->swhead == vring->swtail; 37 + } 38 + 39 + static inline u32 wil_vring_next_tail(struct vring *vring) 40 + { 41 + return (vring->swtail + 1) % vring->size; 42 + } 43 + 44 + static inline void wil_vring_advance_head(struct vring *vring, int n) 45 + { 46 + vring->swhead = (vring->swhead + n) % vring->size; 47 + } 48 + 49 + static inline int wil_vring_is_full(struct vring *vring) 50 + { 51 + return wil_vring_next_tail(vring) == vring->swhead; 52 + } 53 + /* 54 + * Available space in Tx Vring 55 + */ 56 + static inline int wil_vring_avail_tx(struct vring *vring) 57 + { 58 + u32 swhead = vring->swhead; 59 + u32 swtail = vring->swtail; 60 + int used = (vring->size + swhead - swtail) % vring->size; 61 + 62 + return vring->size - used - 1; 63 + } 64 + 65 + static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring) 66 + { 67 + struct device *dev = wil_to_dev(wil); 68 + size_t sz = vring->size * sizeof(vring->va[0]); 69 + uint i; 70 + 71 + BUILD_BUG_ON(sizeof(vring->va[0]) != 32); 72 + 73 + vring->swhead = 0; 74 + vring->swtail = 0; 75 + vring->ctx = kzalloc(vring->size * sizeof(vring->ctx[0]), GFP_KERNEL); 76 + if (!vring->ctx) { 77 + wil_err(wil, "vring_alloc [%d] failed to alloc ctx mem\n", 78 + vring->size); 79 + vring->va = NULL; 80 + return -ENOMEM; 81 + } 82 + /* 83 + * vring->va should be aligned on its size rounded up to power of 2 84 + * This is granted by the dma_alloc_coherent 85 + */ 86 + vring->va = dma_alloc_coherent(dev, sz, &vring->pa, GFP_KERNEL); 87 + if (!vring->va) { 88 + wil_err(wil, "vring_alloc [%d] failed to alloc DMA mem\n", 89 + vring->size); 90 + kfree(vring->ctx); 91 + vring->ctx = NULL; 92 + return -ENOMEM; 93 + } 94 + /* initially, all descriptors are SW owned 95 + * For Tx and Rx, ownership bit is at the same location, thus 96 + * we can use any 97 + */ 98 + for (i = 0; i < vring->size; i++) { 99 + volatile struct vring_tx_desc *d = &(vring->va[i].tx); 100 + d->dma.status = TX_DMA_STATUS_DU; 101 + } 102 + 103 + wil_dbg(wil, "vring[%d] 0x%p:0x%016llx 0x%p\n", vring->size, 104 + vring->va, (unsigned long long)vring->pa, vring->ctx); 105 + 106 + return 0; 107 + } 108 + 109 + static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring, 110 + int tx) 111 + { 112 + struct device *dev = wil_to_dev(wil); 113 + size_t sz = vring->size * sizeof(vring->va[0]); 114 + 115 + while (!wil_vring_is_empty(vring)) { 116 + if (tx) { 117 + volatile struct vring_tx_desc *d = 118 + &vring->va[vring->swtail].tx; 119 + dma_addr_t pa = d->dma.addr_low | 120 + ((u64)d->dma.addr_high << 32); 121 + struct sk_buff *skb = vring->ctx[vring->swtail]; 122 + if (skb) { 123 + dma_unmap_single(dev, pa, d->dma.length, 124 + DMA_TO_DEVICE); 125 + dev_kfree_skb_any(skb); 126 + vring->ctx[vring->swtail] = NULL; 127 + } else { 128 + dma_unmap_page(dev, pa, d->dma.length, 129 + DMA_TO_DEVICE); 130 + } 131 + vring->swtail = wil_vring_next_tail(vring); 132 + } else { /* rx */ 133 + volatile struct vring_rx_desc *d = 134 + &vring->va[vring->swtail].rx; 135 + dma_addr_t pa = d->dma.addr_low | 136 + ((u64)d->dma.addr_high << 32); 137 + struct sk_buff *skb = vring->ctx[vring->swhead]; 138 + dma_unmap_single(dev, pa, d->dma.length, 139 + DMA_FROM_DEVICE); 140 + kfree_skb(skb); 141 + wil_vring_advance_head(vring, 1); 142 + } 143 + } 144 + dma_free_coherent(dev, sz, (void *)vring->va, vring->pa); 145 + kfree(vring->ctx); 146 + vring->pa = 0; 147 + vring->va = NULL; 148 + vring->ctx = NULL; 149 + } 150 + 151 + /** 152 + * Allocate one skb for Rx VRING 153 + * 154 + * Safe to call from IRQ 155 + */ 156 + static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring, 157 + u32 i, int headroom) 158 + { 159 + struct device *dev = wil_to_dev(wil); 160 + unsigned int sz = RX_BUF_LEN; 161 + volatile struct vring_rx_desc *d = &(vring->va[i].rx); 162 + dma_addr_t pa; 163 + 164 + /* TODO align */ 165 + struct sk_buff *skb = dev_alloc_skb(sz + headroom); 166 + if (unlikely(!skb)) 167 + return -ENOMEM; 168 + 169 + skb_reserve(skb, headroom); 170 + skb_put(skb, sz); 171 + 172 + pa = dma_map_single(dev, skb->data, skb->len, DMA_FROM_DEVICE); 173 + if (unlikely(dma_mapping_error(dev, pa))) { 174 + kfree_skb(skb); 175 + return -ENOMEM; 176 + } 177 + 178 + d->dma.d0 = BIT(9) | RX_DMA_D0_CMD_DMA_IT; 179 + d->dma.addr_low = lower_32_bits(pa); 180 + d->dma.addr_high = (u16)upper_32_bits(pa); 181 + /* ip_length don't care */ 182 + /* b11 don't care */ 183 + /* error don't care */ 184 + d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */ 185 + d->dma.length = sz; 186 + vring->ctx[i] = skb; 187 + 188 + return 0; 189 + } 190 + 191 + /** 192 + * Adds radiotap header 193 + * 194 + * Any error indicated as "Bad FCS" 195 + * 196 + * Vendor data for 04:ce:14-1 (Wilocity-1) consists of: 197 + * - Rx descriptor: 32 bytes 198 + * - Phy info 199 + */ 200 + static void wil_rx_add_radiotap_header(struct wil6210_priv *wil, 201 + struct sk_buff *skb, 202 + volatile struct vring_rx_desc *d) 203 + { 204 + struct wireless_dev *wdev = wil->wdev; 205 + struct wil6210_rtap { 206 + struct ieee80211_radiotap_header rthdr; 207 + /* fields should be in the order of bits in rthdr.it_present */ 208 + /* flags */ 209 + u8 flags; 210 + /* channel */ 211 + __le16 chnl_freq __aligned(2); 212 + __le16 chnl_flags; 213 + /* MCS */ 214 + u8 mcs_present; 215 + u8 mcs_flags; 216 + u8 mcs_index; 217 + } __packed; 218 + struct wil6210_rtap_vendor { 219 + struct wil6210_rtap rtap; 220 + /* vendor */ 221 + u8 vendor_oui[3] __aligned(2); 222 + u8 vendor_ns; 223 + __le16 vendor_skip; 224 + u8 vendor_data[0]; 225 + } __packed; 226 + struct wil6210_rtap_vendor *rtap_vendor; 227 + int rtap_len = sizeof(struct wil6210_rtap); 228 + int phy_length = 0; /* phy info header size, bytes */ 229 + static char phy_data[128]; 230 + struct ieee80211_channel *ch = wdev->preset_chandef.chan; 231 + 232 + if (rtap_include_phy_info) { 233 + rtap_len = sizeof(*rtap_vendor) + sizeof(*d); 234 + /* calculate additional length */ 235 + if (d->dma.status & RX_DMA_STATUS_PHY_INFO) { 236 + /** 237 + * PHY info starts from 8-byte boundary 238 + * there are 8-byte lines, last line may be partially 239 + * written (HW bug), thus FW configures for last line 240 + * to be excessive. Driver skips this last line. 241 + */ 242 + int len = min_t(int, 8 + sizeof(phy_data), 243 + wil_rxdesc_phy_length(d)); 244 + if (len > 8) { 245 + void *p = skb_tail_pointer(skb); 246 + void *pa = PTR_ALIGN(p, 8); 247 + if (skb_tailroom(skb) >= len + (pa - p)) { 248 + phy_length = len - 8; 249 + memcpy(phy_data, pa, phy_length); 250 + } 251 + } 252 + } 253 + rtap_len += phy_length; 254 + } 255 + 256 + if (skb_headroom(skb) < rtap_len && 257 + pskb_expand_head(skb, rtap_len, 0, GFP_ATOMIC)) { 258 + wil_err(wil, "Unable to expand headrom to %d\n", rtap_len); 259 + return; 260 + } 261 + 262 + rtap_vendor = (void *)skb_push(skb, rtap_len); 263 + memset(rtap_vendor, 0, rtap_len); 264 + 265 + rtap_vendor->rtap.rthdr.it_version = PKTHDR_RADIOTAP_VERSION; 266 + rtap_vendor->rtap.rthdr.it_len = cpu_to_le16(rtap_len); 267 + rtap_vendor->rtap.rthdr.it_present = cpu_to_le32( 268 + (1 << IEEE80211_RADIOTAP_FLAGS) | 269 + (1 << IEEE80211_RADIOTAP_CHANNEL) | 270 + (1 << IEEE80211_RADIOTAP_MCS)); 271 + if (d->dma.status & RX_DMA_STATUS_ERROR) 272 + rtap_vendor->rtap.flags |= IEEE80211_RADIOTAP_F_BADFCS; 273 + 274 + rtap_vendor->rtap.chnl_freq = cpu_to_le16(ch ? ch->center_freq : 58320); 275 + rtap_vendor->rtap.chnl_flags = cpu_to_le16(0); 276 + 277 + rtap_vendor->rtap.mcs_present = IEEE80211_RADIOTAP_MCS_HAVE_MCS; 278 + rtap_vendor->rtap.mcs_flags = 0; 279 + rtap_vendor->rtap.mcs_index = wil_rxdesc_mcs(d); 280 + 281 + if (rtap_include_phy_info) { 282 + rtap_vendor->rtap.rthdr.it_present |= cpu_to_le32(1 << 283 + IEEE80211_RADIOTAP_VENDOR_NAMESPACE); 284 + /* OUI for Wilocity 04:ce:14 */ 285 + rtap_vendor->vendor_oui[0] = 0x04; 286 + rtap_vendor->vendor_oui[1] = 0xce; 287 + rtap_vendor->vendor_oui[2] = 0x14; 288 + rtap_vendor->vendor_ns = 1; 289 + /* Rx descriptor + PHY data */ 290 + rtap_vendor->vendor_skip = cpu_to_le16(sizeof(*d) + 291 + phy_length); 292 + memcpy(rtap_vendor->vendor_data, (void *)d, sizeof(*d)); 293 + memcpy(rtap_vendor->vendor_data + sizeof(*d), phy_data, 294 + phy_length); 295 + } 296 + } 297 + 298 + /* 299 + * Fast swap in place between 2 registers 300 + */ 301 + static void wil_swap_u16(u16 *a, u16 *b) 302 + { 303 + *a ^= *b; 304 + *b ^= *a; 305 + *a ^= *b; 306 + } 307 + 308 + static void wil_swap_ethaddr(void *data) 309 + { 310 + struct ethhdr *eth = data; 311 + u16 *s = (u16 *)eth->h_source; 312 + u16 *d = (u16 *)eth->h_dest; 313 + 314 + wil_swap_u16(s++, d++); 315 + wil_swap_u16(s++, d++); 316 + wil_swap_u16(s, d); 317 + } 318 + 319 + /** 320 + * reap 1 frame from @swhead 321 + * 322 + * Safe to call from IRQ 323 + */ 324 + static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, 325 + struct vring *vring) 326 + { 327 + struct device *dev = wil_to_dev(wil); 328 + struct net_device *ndev = wil_to_ndev(wil); 329 + volatile struct vring_rx_desc *d; 330 + struct sk_buff *skb; 331 + dma_addr_t pa; 332 + unsigned int sz = RX_BUF_LEN; 333 + u8 ftype; 334 + u8 ds_bits; 335 + 336 + if (wil_vring_is_empty(vring)) 337 + return NULL; 338 + 339 + d = &(vring->va[vring->swhead].rx); 340 + if (!(d->dma.status & RX_DMA_STATUS_DU)) { 341 + /* it is not error, we just reached end of Rx done area */ 342 + return NULL; 343 + } 344 + 345 + pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); 346 + skb = vring->ctx[vring->swhead]; 347 + dma_unmap_single(dev, pa, sz, DMA_FROM_DEVICE); 348 + skb_trim(skb, d->dma.length); 349 + 350 + wil->stats.last_mcs_rx = wil_rxdesc_mcs(d); 351 + 352 + /* use radiotap header only if required */ 353 + if (ndev->type == ARPHRD_IEEE80211_RADIOTAP) 354 + wil_rx_add_radiotap_header(wil, skb, d); 355 + 356 + wil_dbg_TXRX(wil, "Rx[%3d] : %d bytes\n", vring->swhead, d->dma.length); 357 + wil_hex_dump_TXRX("Rx ", DUMP_PREFIX_NONE, 32, 4, 358 + (const void *)d, sizeof(*d), false); 359 + 360 + wil_vring_advance_head(vring, 1); 361 + 362 + /* no extra checks if in sniffer mode */ 363 + if (ndev->type != ARPHRD_ETHER) 364 + return skb; 365 + /* 366 + * Non-data frames may be delivered through Rx DMA channel (ex: BAR) 367 + * Driver should recognize it by frame type, that is found 368 + * in Rx descriptor. If type is not data, it is 802.11 frame as is 369 + */ 370 + ftype = wil_rxdesc_ftype(d) << 2; 371 + if (ftype != IEEE80211_FTYPE_DATA) { 372 + wil_dbg_TXRX(wil, "Non-data frame ftype 0x%08x\n", ftype); 373 + /* TODO: process it */ 374 + kfree_skb(skb); 375 + return NULL; 376 + } 377 + 378 + if (skb->len < ETH_HLEN) { 379 + wil_err(wil, "Short frame, len = %d\n", skb->len); 380 + /* TODO: process it (i.e. BAR) */ 381 + kfree_skb(skb); 382 + return NULL; 383 + } 384 + 385 + ds_bits = wil_rxdesc_ds_bits(d); 386 + if (ds_bits == 1) { 387 + /* 388 + * HW bug - in ToDS mode, i.e. Rx on AP side, 389 + * addresses get swapped 390 + */ 391 + wil_swap_ethaddr(skb->data); 392 + } 393 + 394 + return skb; 395 + } 396 + 397 + /** 398 + * allocate and fill up to @count buffers in rx ring 399 + * buffers posted at @swtail 400 + */ 401 + static int wil_rx_refill(struct wil6210_priv *wil, int count) 402 + { 403 + struct net_device *ndev = wil_to_ndev(wil); 404 + struct vring *v = &wil->vring_rx; 405 + u32 next_tail; 406 + int rc = 0; 407 + int headroom = ndev->type == ARPHRD_IEEE80211_RADIOTAP ? 408 + WIL6210_RTAP_SIZE : 0; 409 + 410 + for (; next_tail = wil_vring_next_tail(v), 411 + (next_tail != v->swhead) && (count-- > 0); 412 + v->swtail = next_tail) { 413 + rc = wil_vring_alloc_skb(wil, v, v->swtail, headroom); 414 + if (rc) { 415 + wil_err(wil, "Error %d in wil_rx_refill[%d]\n", 416 + rc, v->swtail); 417 + break; 418 + } 419 + } 420 + iowrite32(v->swtail, wil->csr + HOSTADDR(v->hwtail)); 421 + 422 + return rc; 423 + } 424 + 425 + /* 426 + * Pass Rx packet to the netif. Update statistics. 427 + */ 428 + static void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) 429 + { 430 + int rc; 431 + unsigned int len = skb->len; 432 + 433 + if (in_interrupt()) 434 + rc = netif_rx(skb); 435 + else 436 + rc = netif_rx_ni(skb); 437 + 438 + if (likely(rc == NET_RX_SUCCESS)) { 439 + ndev->stats.rx_packets++; 440 + ndev->stats.rx_bytes += len; 441 + 442 + } else { 443 + ndev->stats.rx_dropped++; 444 + } 445 + } 446 + 447 + /** 448 + * Proceed all completed skb's from Rx VRING 449 + * 450 + * Safe to call from IRQ 451 + */ 452 + void wil_rx_handle(struct wil6210_priv *wil) 453 + { 454 + struct net_device *ndev = wil_to_ndev(wil); 455 + struct vring *v = &wil->vring_rx; 456 + struct sk_buff *skb; 457 + 458 + if (!v->va) { 459 + wil_err(wil, "Rx IRQ while Rx not yet initialized\n"); 460 + return; 461 + } 462 + wil_dbg_TXRX(wil, "%s()\n", __func__); 463 + while (NULL != (skb = wil_vring_reap_rx(wil, v))) { 464 + wil_hex_dump_TXRX("Rx ", DUMP_PREFIX_OFFSET, 16, 1, 465 + skb->data, skb_headlen(skb), false); 466 + 467 + skb_orphan(skb); 468 + 469 + if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { 470 + skb->dev = ndev; 471 + skb_reset_mac_header(skb); 472 + skb->ip_summed = CHECKSUM_UNNECESSARY; 473 + skb->pkt_type = PACKET_OTHERHOST; 474 + skb->protocol = htons(ETH_P_802_2); 475 + 476 + } else { 477 + skb->protocol = eth_type_trans(skb, ndev); 478 + } 479 + 480 + wil_netif_rx_any(skb, ndev); 481 + } 482 + wil_rx_refill(wil, v->size); 483 + } 484 + 485 + int wil_rx_init(struct wil6210_priv *wil) 486 + { 487 + struct net_device *ndev = wil_to_ndev(wil); 488 + struct wireless_dev *wdev = wil->wdev; 489 + struct vring *vring = &wil->vring_rx; 490 + int rc; 491 + struct wmi_cfg_rx_chain_cmd cmd = { 492 + .action = WMI_RX_CHAIN_ADD, 493 + .rx_sw_ring = { 494 + .max_mpdu_size = cpu_to_le16(RX_BUF_LEN), 495 + }, 496 + .mid = 0, /* TODO - what is it? */ 497 + .decap_trans_type = WMI_DECAP_TYPE_802_3, 498 + }; 499 + struct { 500 + struct wil6210_mbox_hdr_wmi wmi; 501 + struct wmi_cfg_rx_chain_done_event evt; 502 + } __packed evt; 503 + 504 + vring->size = WIL6210_RX_RING_SIZE; 505 + rc = wil_vring_alloc(wil, vring); 506 + if (rc) 507 + return rc; 508 + 509 + cmd.rx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); 510 + cmd.rx_sw_ring.ring_size = cpu_to_le16(vring->size); 511 + if (wdev->iftype == NL80211_IFTYPE_MONITOR) { 512 + struct ieee80211_channel *ch = wdev->preset_chandef.chan; 513 + 514 + cmd.sniffer_cfg.mode = cpu_to_le32(WMI_SNIFFER_ON); 515 + if (ch) 516 + cmd.sniffer_cfg.channel = ch->hw_value - 1; 517 + cmd.sniffer_cfg.phy_info_mode = 518 + cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP); 519 + cmd.sniffer_cfg.phy_support = 520 + cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL) 521 + ? WMI_SNIFFER_CP : WMI_SNIFFER_DP); 522 + } 523 + /* typical time for secure PCP is 840ms */ 524 + rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd), 525 + WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000); 526 + if (rc) 527 + goto err_free; 528 + 529 + vring->hwtail = le32_to_cpu(evt.evt.rx_ring_tail_ptr); 530 + 531 + wil_dbg(wil, "Rx init: status %d tail 0x%08x\n", 532 + le32_to_cpu(evt.evt.status), vring->hwtail); 533 + 534 + rc = wil_rx_refill(wil, vring->size); 535 + if (rc) 536 + goto err_free; 537 + 538 + return 0; 539 + err_free: 540 + wil_vring_free(wil, vring, 0); 541 + 542 + return rc; 543 + } 544 + 545 + void wil_rx_fini(struct wil6210_priv *wil) 546 + { 547 + struct vring *vring = &wil->vring_rx; 548 + 549 + if (vring->va) { 550 + int rc; 551 + struct wmi_cfg_rx_chain_cmd cmd = { 552 + .action = cpu_to_le32(WMI_RX_CHAIN_DEL), 553 + .rx_sw_ring = { 554 + .max_mpdu_size = cpu_to_le16(RX_BUF_LEN), 555 + }, 556 + }; 557 + struct { 558 + struct wil6210_mbox_hdr_wmi wmi; 559 + struct wmi_cfg_rx_chain_done_event cfg; 560 + } __packed wmi_rx_cfg_reply; 561 + 562 + rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd), 563 + WMI_CFG_RX_CHAIN_DONE_EVENTID, 564 + &wmi_rx_cfg_reply, sizeof(wmi_rx_cfg_reply), 565 + 100); 566 + wil_vring_free(wil, vring, 0); 567 + } 568 + } 569 + 570 + int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, 571 + int cid, int tid) 572 + { 573 + int rc; 574 + struct wmi_vring_cfg_cmd cmd = { 575 + .action = cpu_to_le32(WMI_VRING_CMD_ADD), 576 + .vring_cfg = { 577 + .tx_sw_ring = { 578 + .max_mpdu_size = cpu_to_le16(TX_BUF_LEN), 579 + }, 580 + .ringid = id, 581 + .cidxtid = (cid & 0xf) | ((tid & 0xf) << 4), 582 + .encap_trans_type = WMI_VRING_ENC_TYPE_802_3, 583 + .mac_ctrl = 0, 584 + .to_resolution = 0, 585 + .agg_max_wsize = 16, 586 + .schd_params = { 587 + .priority = cpu_to_le16(0), 588 + .timeslot_us = cpu_to_le16(0xfff), 589 + }, 590 + }, 591 + }; 592 + struct { 593 + struct wil6210_mbox_hdr_wmi wmi; 594 + struct wmi_vring_cfg_done_event cmd; 595 + } __packed reply; 596 + struct vring *vring = &wil->vring_tx[id]; 597 + 598 + if (vring->va) { 599 + wil_err(wil, "Tx ring [%d] already allocated\n", id); 600 + rc = -EINVAL; 601 + goto out; 602 + } 603 + 604 + vring->size = size; 605 + rc = wil_vring_alloc(wil, vring); 606 + if (rc) 607 + goto out; 608 + 609 + cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); 610 + cmd.vring_cfg.tx_sw_ring.ring_size = cpu_to_le16(vring->size); 611 + 612 + rc = wmi_call(wil, WMI_VRING_CFG_CMDID, &cmd, sizeof(cmd), 613 + WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100); 614 + if (rc) 615 + goto out_free; 616 + 617 + if (reply.cmd.status != WMI_VRING_CFG_SUCCESS) { 618 + wil_err(wil, "Tx config failed, status 0x%02x\n", 619 + reply.cmd.status); 620 + goto out_free; 621 + } 622 + vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr); 623 + 624 + return 0; 625 + out_free: 626 + wil_vring_free(wil, vring, 1); 627 + out: 628 + 629 + return rc; 630 + } 631 + 632 + void wil_vring_fini_tx(struct wil6210_priv *wil, int id) 633 + { 634 + struct vring *vring = &wil->vring_tx[id]; 635 + 636 + if (!vring->va) 637 + return; 638 + 639 + wil_vring_free(wil, vring, 1); 640 + } 641 + 642 + static struct vring *wil_find_tx_vring(struct wil6210_priv *wil, 643 + struct sk_buff *skb) 644 + { 645 + struct vring *v = &wil->vring_tx[0]; 646 + 647 + if (v->va) 648 + return v; 649 + 650 + return NULL; 651 + } 652 + 653 + static int wil_tx_desc_map(volatile struct vring_tx_desc *d, 654 + dma_addr_t pa, u32 len) 655 + { 656 + d->dma.addr_low = lower_32_bits(pa); 657 + d->dma.addr_high = (u16)upper_32_bits(pa); 658 + d->dma.ip_length = 0; 659 + /* 0..6: mac_length; 7:ip_version 0-IP6 1-IP4*/ 660 + d->dma.b11 = 0/*14 | BIT(7)*/; 661 + d->dma.error = 0; 662 + d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */ 663 + d->dma.length = len; 664 + d->dma.d0 = 0; 665 + d->mac.d[0] = 0; 666 + d->mac.d[1] = 0; 667 + d->mac.d[2] = 0; 668 + d->mac.ucode_cmd = 0; 669 + /* use dst index 0 */ 670 + d->mac.d[1] |= BIT(MAC_CFG_DESC_TX_1_DST_INDEX_EN_POS) | 671 + (0 << MAC_CFG_DESC_TX_1_DST_INDEX_POS); 672 + /* translation type: 0 - bypass; 1 - 802.3; 2 - native wifi */ 673 + d->mac.d[2] = BIT(MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_POS) | 674 + (1 << MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_POS); 675 + 676 + return 0; 677 + } 678 + 679 + static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, 680 + struct sk_buff *skb) 681 + { 682 + struct device *dev = wil_to_dev(wil); 683 + volatile struct vring_tx_desc *d; 684 + u32 swhead = vring->swhead; 685 + int avail = wil_vring_avail_tx(vring); 686 + int nr_frags = skb_shinfo(skb)->nr_frags; 687 + uint f; 688 + int vring_index = vring - wil->vring_tx; 689 + uint i = swhead; 690 + dma_addr_t pa; 691 + 692 + wil_dbg_TXRX(wil, "%s()\n", __func__); 693 + 694 + if (avail < vring->size/8) 695 + netif_tx_stop_all_queues(wil_to_ndev(wil)); 696 + if (avail < 1 + nr_frags) { 697 + wil_err(wil, "Tx ring full. No space for %d fragments\n", 698 + 1 + nr_frags); 699 + return -ENOMEM; 700 + } 701 + d = &(vring->va[i].tx); 702 + 703 + /* FIXME FW can accept only unicast frames for the peer */ 704 + memcpy(skb->data, wil->dst_addr[vring_index], ETH_ALEN); 705 + 706 + pa = dma_map_single(dev, skb->data, 707 + skb_headlen(skb), DMA_TO_DEVICE); 708 + 709 + wil_dbg_TXRX(wil, "Tx skb %d bytes %p -> %#08llx\n", skb_headlen(skb), 710 + skb->data, (unsigned long long)pa); 711 + wil_hex_dump_TXRX("Tx ", DUMP_PREFIX_OFFSET, 16, 1, 712 + skb->data, skb_headlen(skb), false); 713 + 714 + if (unlikely(dma_mapping_error(dev, pa))) 715 + return -EINVAL; 716 + /* 1-st segment */ 717 + wil_tx_desc_map(d, pa, skb_headlen(skb)); 718 + d->mac.d[2] |= ((nr_frags + 1) << 719 + MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS); 720 + /* middle segments */ 721 + for (f = 0; f < nr_frags; f++) { 722 + const struct skb_frag_struct *frag = 723 + &skb_shinfo(skb)->frags[f]; 724 + int len = skb_frag_size(frag); 725 + i = (swhead + f + 1) % vring->size; 726 + d = &(vring->va[i].tx); 727 + pa = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), 728 + DMA_TO_DEVICE); 729 + if (unlikely(dma_mapping_error(dev, pa))) 730 + goto dma_error; 731 + wil_tx_desc_map(d, pa, len); 732 + vring->ctx[i] = NULL; 733 + } 734 + /* for the last seg only */ 735 + d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_EOP_POS); 736 + d->dma.d0 |= BIT(9); /* BUG: undocumented bit */ 737 + d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS); 738 + d->dma.d0 |= (vring_index << DMA_CFG_DESC_TX_0_QID_POS); 739 + 740 + wil_hex_dump_TXRX("Tx ", DUMP_PREFIX_NONE, 32, 4, 741 + (const void *)d, sizeof(*d), false); 742 + 743 + /* advance swhead */ 744 + wil_vring_advance_head(vring, nr_frags + 1); 745 + wil_dbg_TXRX(wil, "Tx swhead %d -> %d\n", swhead, vring->swhead); 746 + iowrite32(vring->swhead, wil->csr + HOSTADDR(vring->hwtail)); 747 + /* hold reference to skb 748 + * to prevent skb release before accounting 749 + * in case of immediate "tx done" 750 + */ 751 + vring->ctx[i] = skb_get(skb); 752 + 753 + return 0; 754 + dma_error: 755 + /* unmap what we have mapped */ 756 + /* Note: increment @f to operate with positive index */ 757 + for (f++; f > 0; f--) { 758 + i = (swhead + f) % vring->size; 759 + d = &(vring->va[i].tx); 760 + d->dma.status = TX_DMA_STATUS_DU; 761 + pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); 762 + if (vring->ctx[i]) 763 + dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE); 764 + else 765 + dma_unmap_page(dev, pa, d->dma.length, DMA_TO_DEVICE); 766 + } 767 + 768 + return -EINVAL; 769 + } 770 + 771 + 772 + netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) 773 + { 774 + struct wil6210_priv *wil = ndev_to_wil(ndev); 775 + struct vring *vring; 776 + int rc; 777 + 778 + wil_dbg_TXRX(wil, "%s()\n", __func__); 779 + if (!test_bit(wil_status_fwready, &wil->status)) { 780 + wil_err(wil, "FW not ready\n"); 781 + goto drop; 782 + } 783 + if (!test_bit(wil_status_fwconnected, &wil->status)) { 784 + wil_err(wil, "FW not connected\n"); 785 + goto drop; 786 + } 787 + if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { 788 + wil_err(wil, "Xmit in monitor mode not supported\n"); 789 + goto drop; 790 + } 791 + if (skb->protocol == cpu_to_be16(ETH_P_PAE)) { 792 + rc = wmi_tx_eapol(wil, skb); 793 + } else { 794 + /* find vring */ 795 + vring = wil_find_tx_vring(wil, skb); 796 + if (!vring) { 797 + wil_err(wil, "No Tx VRING available\n"); 798 + goto drop; 799 + } 800 + /* set up vring entry */ 801 + rc = wil_tx_vring(wil, vring, skb); 802 + } 803 + switch (rc) { 804 + case 0: 805 + ndev->stats.tx_packets++; 806 + ndev->stats.tx_bytes += skb->len; 807 + dev_kfree_skb_any(skb); 808 + return NETDEV_TX_OK; 809 + case -ENOMEM: 810 + return NETDEV_TX_BUSY; 811 + default: 812 + ; /* goto drop; */ 813 + break; 814 + } 815 + drop: 816 + netif_tx_stop_all_queues(ndev); 817 + ndev->stats.tx_dropped++; 818 + dev_kfree_skb_any(skb); 819 + 820 + return NET_XMIT_DROP; 821 + } 822 + 823 + /** 824 + * Clean up transmitted skb's from the Tx VRING 825 + * 826 + * Safe to call from IRQ 827 + */ 828 + void wil_tx_complete(struct wil6210_priv *wil, int ringid) 829 + { 830 + struct device *dev = wil_to_dev(wil); 831 + struct vring *vring = &wil->vring_tx[ringid]; 832 + 833 + if (!vring->va) { 834 + wil_err(wil, "Tx irq[%d]: vring not initialized\n", ringid); 835 + return; 836 + } 837 + 838 + wil_dbg_TXRX(wil, "%s(%d)\n", __func__, ringid); 839 + 840 + while (!wil_vring_is_empty(vring)) { 841 + volatile struct vring_tx_desc *d = &vring->va[vring->swtail].tx; 842 + dma_addr_t pa; 843 + struct sk_buff *skb; 844 + if (!(d->dma.status & TX_DMA_STATUS_DU)) 845 + break; 846 + 847 + wil_dbg_TXRX(wil, 848 + "Tx[%3d] : %d bytes, status 0x%02x err 0x%02x\n", 849 + vring->swtail, d->dma.length, d->dma.status, 850 + d->dma.error); 851 + wil_hex_dump_TXRX("TxC ", DUMP_PREFIX_NONE, 32, 4, 852 + (const void *)d, sizeof(*d), false); 853 + 854 + pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); 855 + skb = vring->ctx[vring->swtail]; 856 + if (skb) { 857 + dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE); 858 + dev_kfree_skb_any(skb); 859 + vring->ctx[vring->swtail] = NULL; 860 + } else { 861 + dma_unmap_page(dev, pa, d->dma.length, DMA_TO_DEVICE); 862 + } 863 + d->dma.addr_low = 0; 864 + d->dma.addr_high = 0; 865 + d->dma.length = 0; 866 + d->dma.status = TX_DMA_STATUS_DU; 867 + vring->swtail = wil_vring_next_tail(vring); 868 + } 869 + if (wil_vring_avail_tx(vring) > vring->size/4) 870 + netif_tx_wake_all_queues(wil_to_ndev(wil)); 871 + }
+362
drivers/net/wireless/ath/wil6210/txrx.h
··· 1 + /* 2 + * Copyright (c) 2012 Qualcomm Atheros, Inc. 3 + * 4 + * Permission to use, copy, modify, and/or distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + 17 + #ifndef WIL6210_TXRX_H 18 + #define WIL6210_TXRX_H 19 + 20 + #define BUF_SW_OWNED (1) 21 + #define BUF_HW_OWNED (0) 22 + 23 + /* size of max. Rx packet */ 24 + #define RX_BUF_LEN (2048) 25 + #define TX_BUF_LEN (2048) 26 + /* how many bytes to reserve for rtap header? */ 27 + #define WIL6210_RTAP_SIZE (128) 28 + 29 + /* Tx/Rx path */ 30 + /* 31 + * Tx descriptor - MAC part 32 + * [dword 0] 33 + * bit 0.. 9 : lifetime_expiry_value:10 34 + * bit 10 : interrup_en:1 35 + * bit 11 : status_en:1 36 + * bit 12..13 : txss_override:2 37 + * bit 14 : timestamp_insertion:1 38 + * bit 15 : duration_preserve:1 39 + * bit 16..21 : reserved0:6 40 + * bit 22..26 : mcs_index:5 41 + * bit 27 : mcs_en:1 42 + * bit 28..29 : reserved1:2 43 + * bit 30 : reserved2:1 44 + * bit 31 : sn_preserved:1 45 + * [dword 1] 46 + * bit 0.. 3 : pkt_mode:4 47 + * bit 4 : pkt_mode_en:1 48 + * bit 5.. 7 : reserved0:3 49 + * bit 8..13 : reserved1:6 50 + * bit 14 : reserved2:1 51 + * bit 15 : ack_policy_en:1 52 + * bit 16..19 : dst_index:4 53 + * bit 20 : dst_index_en:1 54 + * bit 21..22 : ack_policy:2 55 + * bit 23 : lifetime_en:1 56 + * bit 24..30 : max_retry:7 57 + * bit 31 : max_retry_en:1 58 + * [dword 2] 59 + * bit 0.. 7 : num_of_descriptors:8 60 + * bit 8..17 : reserved:10 61 + * bit 18..19 : l2_translation_type:2 62 + * bit 20 : snap_hdr_insertion_en:1 63 + * bit 21 : vlan_removal_en:1 64 + * bit 22..31 : reserved0:10 65 + * [dword 3] 66 + * bit 0.. 31: ucode_cmd:32 67 + */ 68 + struct vring_tx_mac { 69 + u32 d[3]; 70 + u32 ucode_cmd; 71 + } __packed; 72 + 73 + /* TX MAC Dword 0 */ 74 + #define MAC_CFG_DESC_TX_0_LIFETIME_EXPIRY_VALUE_POS 0 75 + #define MAC_CFG_DESC_TX_0_LIFETIME_EXPIRY_VALUE_LEN 10 76 + #define MAC_CFG_DESC_TX_0_LIFETIME_EXPIRY_VALUE_MSK 0x3FF 77 + 78 + #define MAC_CFG_DESC_TX_0_INTERRUP_EN_POS 10 79 + #define MAC_CFG_DESC_TX_0_INTERRUP_EN_LEN 1 80 + #define MAC_CFG_DESC_TX_0_INTERRUP_EN_MSK 0x400 81 + 82 + #define MAC_CFG_DESC_TX_0_STATUS_EN_POS 11 83 + #define MAC_CFG_DESC_TX_0_STATUS_EN_LEN 1 84 + #define MAC_CFG_DESC_TX_0_STATUS_EN_MSK 0x800 85 + 86 + #define MAC_CFG_DESC_TX_0_TXSS_OVERRIDE_POS 12 87 + #define MAC_CFG_DESC_TX_0_TXSS_OVERRIDE_LEN 2 88 + #define MAC_CFG_DESC_TX_0_TXSS_OVERRIDE_MSK 0x3000 89 + 90 + #define MAC_CFG_DESC_TX_0_TIMESTAMP_INSERTION_POS 14 91 + #define MAC_CFG_DESC_TX_0_TIMESTAMP_INSERTION_LEN 1 92 + #define MAC_CFG_DESC_TX_0_TIMESTAMP_INSERTION_MSK 0x4000 93 + 94 + #define MAC_CFG_DESC_TX_0_DURATION_PRESERVE_POS 15 95 + #define MAC_CFG_DESC_TX_0_DURATION_PRESERVE_LEN 1 96 + #define MAC_CFG_DESC_TX_0_DURATION_PRESERVE_MSK 0x8000 97 + 98 + #define MAC_CFG_DESC_TX_0_MCS_INDEX_POS 22 99 + #define MAC_CFG_DESC_TX_0_MCS_INDEX_LEN 5 100 + #define MAC_CFG_DESC_TX_0_MCS_INDEX_MSK 0x7C00000 101 + 102 + #define MAC_CFG_DESC_TX_0_MCS_EN_POS 27 103 + #define MAC_CFG_DESC_TX_0_MCS_EN_LEN 1 104 + #define MAC_CFG_DESC_TX_0_MCS_EN_MSK 0x8000000 105 + 106 + #define MAC_CFG_DESC_TX_0_SN_PRESERVED_POS 31 107 + #define MAC_CFG_DESC_TX_0_SN_PRESERVED_LEN 1 108 + #define MAC_CFG_DESC_TX_0_SN_PRESERVED_MSK 0x80000000 109 + 110 + /* TX MAC Dword 1 */ 111 + #define MAC_CFG_DESC_TX_1_PKT_MODE_POS 0 112 + #define MAC_CFG_DESC_TX_1_PKT_MODE_LEN 4 113 + #define MAC_CFG_DESC_TX_1_PKT_MODE_MSK 0xF 114 + 115 + #define MAC_CFG_DESC_TX_1_PKT_MODE_EN_POS 4 116 + #define MAC_CFG_DESC_TX_1_PKT_MODE_EN_LEN 1 117 + #define MAC_CFG_DESC_TX_1_PKT_MODE_EN_MSK 0x10 118 + 119 + #define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_POS 15 120 + #define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_LEN 1 121 + #define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_MSK 0x8000 122 + 123 + #define MAC_CFG_DESC_TX_1_DST_INDEX_POS 16 124 + #define MAC_CFG_DESC_TX_1_DST_INDEX_LEN 4 125 + #define MAC_CFG_DESC_TX_1_DST_INDEX_MSK 0xF0000 126 + 127 + #define MAC_CFG_DESC_TX_1_DST_INDEX_EN_POS 20 128 + #define MAC_CFG_DESC_TX_1_DST_INDEX_EN_LEN 1 129 + #define MAC_CFG_DESC_TX_1_DST_INDEX_EN_MSK 0x100000 130 + 131 + #define MAC_CFG_DESC_TX_1_ACK_POLICY_POS 21 132 + #define MAC_CFG_DESC_TX_1_ACK_POLICY_LEN 2 133 + #define MAC_CFG_DESC_TX_1_ACK_POLICY_MSK 0x600000 134 + 135 + #define MAC_CFG_DESC_TX_1_LIFETIME_EN_POS 23 136 + #define MAC_CFG_DESC_TX_1_LIFETIME_EN_LEN 1 137 + #define MAC_CFG_DESC_TX_1_LIFETIME_EN_MSK 0x800000 138 + 139 + #define MAC_CFG_DESC_TX_1_MAX_RETRY_POS 24 140 + #define MAC_CFG_DESC_TX_1_MAX_RETRY_LEN 7 141 + #define MAC_CFG_DESC_TX_1_MAX_RETRY_MSK 0x7F000000 142 + 143 + #define MAC_CFG_DESC_TX_1_MAX_RETRY_EN_POS 31 144 + #define MAC_CFG_DESC_TX_1_MAX_RETRY_EN_LEN 1 145 + #define MAC_CFG_DESC_TX_1_MAX_RETRY_EN_MSK 0x80000000 146 + 147 + /* TX MAC Dword 2 */ 148 + #define MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS 0 149 + #define MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_LEN 8 150 + #define MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_MSK 0xFF 151 + 152 + #define MAC_CFG_DESC_TX_2_RESERVED_POS 8 153 + #define MAC_CFG_DESC_TX_2_RESERVED_LEN 10 154 + #define MAC_CFG_DESC_TX_2_RESERVED_MSK 0x3FF00 155 + 156 + #define MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_POS 18 157 + #define MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_LEN 2 158 + #define MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_MSK 0xC0000 159 + 160 + #define MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_POS 20 161 + #define MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_LEN 1 162 + #define MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_MSK 0x100000 163 + 164 + #define MAC_CFG_DESC_TX_2_VLAN_REMOVAL_EN_POS 21 165 + #define MAC_CFG_DESC_TX_2_VLAN_REMOVAL_EN_LEN 1 166 + #define MAC_CFG_DESC_TX_2_VLAN_REMOVAL_EN_MSK 0x200000 167 + 168 + /* TX MAC Dword 3 */ 169 + #define MAC_CFG_DESC_TX_3_UCODE_CMD_POS 0 170 + #define MAC_CFG_DESC_TX_3_UCODE_CMD_LEN 32 171 + #define MAC_CFG_DESC_TX_3_UCODE_CMD_MSK 0xFFFFFFFF 172 + 173 + /* TX DMA Dword 0 */ 174 + #define DMA_CFG_DESC_TX_0_L4_LENGTH_POS 0 175 + #define DMA_CFG_DESC_TX_0_L4_LENGTH_LEN 8 176 + #define DMA_CFG_DESC_TX_0_L4_LENGTH_MSK 0xFF 177 + 178 + #define DMA_CFG_DESC_TX_0_CMD_EOP_POS 8 179 + #define DMA_CFG_DESC_TX_0_CMD_EOP_LEN 1 180 + #define DMA_CFG_DESC_TX_0_CMD_EOP_MSK 0x100 181 + 182 + #define DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS 10 183 + #define DMA_CFG_DESC_TX_0_CMD_DMA_IT_LEN 1 184 + #define DMA_CFG_DESC_TX_0_CMD_DMA_IT_MSK 0x400 185 + 186 + #define DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_POS 11 187 + #define DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_LEN 2 188 + #define DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_MSK 0x1800 189 + 190 + #define DMA_CFG_DESC_TX_0_TCP_SEG_EN_POS 13 191 + #define DMA_CFG_DESC_TX_0_TCP_SEG_EN_LEN 1 192 + #define DMA_CFG_DESC_TX_0_TCP_SEG_EN_MSK 0x2000 193 + 194 + #define DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_POS 14 195 + #define DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_LEN 1 196 + #define DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_MSK 0x4000 197 + 198 + #define DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_POS 15 199 + #define DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_LEN 1 200 + #define DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_MSK 0x8000 201 + 202 + #define DMA_CFG_DESC_TX_0_QID_POS 16 203 + #define DMA_CFG_DESC_TX_0_QID_LEN 5 204 + #define DMA_CFG_DESC_TX_0_QID_MSK 0x1F0000 205 + 206 + #define DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_POS 21 207 + #define DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_LEN 1 208 + #define DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_MSK 0x200000 209 + 210 + #define DMA_CFG_DESC_TX_0_L4_TYPE_POS 30 211 + #define DMA_CFG_DESC_TX_0_L4_TYPE_LEN 2 212 + #define DMA_CFG_DESC_TX_0_L4_TYPE_MSK 0xC0000000 213 + 214 + 215 + #define TX_DMA_STATUS_DU BIT(0) 216 + 217 + struct vring_tx_dma { 218 + u32 d0; 219 + u32 addr_low; 220 + u16 addr_high; 221 + u8 ip_length; 222 + u8 b11; /* 0..6: mac_length; 7:ip_version */ 223 + u8 error; /* 0..2: err; 3..7: reserved; */ 224 + u8 status; /* 0: used; 1..7; reserved */ 225 + u16 length; 226 + } __packed; 227 + 228 + /* 229 + * Rx descriptor - MAC part 230 + * [dword 0] 231 + * bit 0.. 3 : tid:4 The QoS (b3-0) TID Field 232 + * bit 4.. 6 : connection_id:3 :The Source index that was found during 233 + * Parsing the TA. This field is used to define the source of the packet 234 + * bit 7 : reserved:1 235 + * bit 8.. 9 : mac_id:2 : The MAC virtual Ring number (always zero) 236 + * bit 10..11 : frame_type:2 : The FC Control (b3-2) - MPDU Type 237 + * (management, data, control and extension) 238 + * bit 12..15 : frame_subtype:4 : The FC Control (b7-4) - Frame Subtype 239 + * bit 16..27 : seq_number:12 The received Sequence number field 240 + * bit 28..31 : extended:4 extended subtype 241 + * [dword 1] 242 + * bit 0.. 3 : reserved 243 + * bit 4.. 5 : key_id:2 244 + * bit 6 : decrypt_bypass:1 245 + * bit 7 : security:1 246 + * bit 8.. 9 : ds_bits:2 247 + * bit 10 : a_msdu_present:1 from qos header 248 + * bit 11 : a_msdu_type:1 from qos header 249 + * bit 12 : a_mpdu:1 part of AMPDU aggregation 250 + * bit 13 : broadcast:1 251 + * bit 14 : mutlicast:1 252 + * bit 15 : reserved:1 253 + * bit 16..20 : rx_mac_qid:5 The Queue Identifier that the packet 254 + * is received from 255 + * bit 21..24 : mcs:4 256 + * bit 25..28 : mic_icr:4 257 + * bit 29..31 : reserved:3 258 + * [dword 2] 259 + * bit 0.. 2 : time_slot:3 The timeslot that the MPDU is received 260 + * bit 3 : fc_protocol_ver:1 The FC Control (b0) - Protocol Version 261 + * bit 4 : fc_order:1 The FC Control (b15) -Order 262 + * bit 5.. 7 : qos_ack_policy:3 The QoS (b6-5) ack policy Field 263 + * bit 8 : esop:1 The QoS (b4) ESOP field 264 + * bit 9 : qos_rdg_more_ppdu:1 The QoS (b9) RDG field 265 + * bit 10..14 : qos_reserved:5 The QoS (b14-10) Reserved field 266 + * bit 15 : qos_ac_constraint:1 267 + * bit 16..31 : pn_15_0:16 low 2 bytes of PN 268 + * [dword 3] 269 + * bit 0..31 : pn_47_16:32 high 4 bytes of PN 270 + */ 271 + struct vring_rx_mac { 272 + u32 d0; 273 + u32 d1; 274 + u16 w4; 275 + u16 pn_15_0; 276 + u32 pn_47_16; 277 + } __packed; 278 + 279 + /* 280 + * Rx descriptor - DMA part 281 + * [dword 0] 282 + * bit 0.. 7 : l4_length:8 layer 4 length 283 + * bit 8.. 9 : reserved:2 284 + * bit 10 : cmd_dma_it:1 285 + * bit 11..15 : reserved:5 286 + * bit 16..29 : phy_info_length:14 287 + * bit 30..31 : l4_type:2 valid if the L4I bit is set in the status field 288 + * [dword 1] 289 + * bit 0..31 : addr_low:32 The payload buffer low address 290 + * [dword 2] 291 + * bit 0..15 : addr_high:16 The payload buffer high address 292 + * bit 16..23 : ip_length:8 293 + * bit 24..30 : mac_length:7 294 + * bit 31 : ip_version:1 295 + * [dword 3] 296 + * [byte 12] error 297 + * [byte 13] status 298 + * bit 0 : du:1 299 + * bit 1 : eop:1 300 + * bit 2 : error:1 301 + * bit 3 : mi:1 302 + * bit 4 : l3_identified:1 303 + * bit 5 : l4_identified:1 304 + * bit 6 : phy_info_included:1 305 + * bit 7 : reserved:1 306 + * [word 7] length 307 + * 308 + */ 309 + 310 + #define RX_DMA_D0_CMD_DMA_IT BIT(10) 311 + 312 + #define RX_DMA_STATUS_DU BIT(0) 313 + #define RX_DMA_STATUS_ERROR BIT(2) 314 + #define RX_DMA_STATUS_PHY_INFO BIT(6) 315 + 316 + struct vring_rx_dma { 317 + u32 d0; 318 + u32 addr_low; 319 + u16 addr_high; 320 + u8 ip_length; 321 + u8 b11; 322 + u8 error; 323 + u8 status; 324 + u16 length; 325 + } __packed; 326 + 327 + struct vring_tx_desc { 328 + struct vring_tx_mac mac; 329 + struct vring_tx_dma dma; 330 + } __packed; 331 + 332 + struct vring_rx_desc { 333 + struct vring_rx_mac mac; 334 + struct vring_rx_dma dma; 335 + } __packed; 336 + 337 + union vring_desc { 338 + struct vring_tx_desc tx; 339 + struct vring_rx_desc rx; 340 + } __packed; 341 + 342 + static inline int wil_rxdesc_phy_length(volatile struct vring_rx_desc *d) 343 + { 344 + return WIL_GET_BITS(d->dma.d0, 16, 29); 345 + } 346 + 347 + static inline int wil_rxdesc_mcs(volatile struct vring_rx_desc *d) 348 + { 349 + return WIL_GET_BITS(d->mac.d1, 21, 24); 350 + } 351 + 352 + static inline int wil_rxdesc_ds_bits(volatile struct vring_rx_desc *d) 353 + { 354 + return WIL_GET_BITS(d->mac.d1, 8, 9); 355 + } 356 + 357 + static inline int wil_rxdesc_ftype(volatile struct vring_rx_desc *d) 358 + { 359 + return WIL_GET_BITS(d->mac.d0, 10, 11); 360 + } 361 + 362 + #endif /* WIL6210_TXRX_H */
+363
drivers/net/wireless/ath/wil6210/wil6210.h
··· 1 + /* 2 + * Copyright (c) 2012 Qualcomm Atheros, Inc. 3 + * 4 + * Permission to use, copy, modify, and/or distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + 17 + #ifndef __WIL6210_H__ 18 + #define __WIL6210_H__ 19 + 20 + #include <linux/netdevice.h> 21 + #include <linux/wireless.h> 22 + #include <net/cfg80211.h> 23 + 24 + #include "dbg_hexdump.h" 25 + 26 + #define WIL_NAME "wil6210" 27 + 28 + /** 29 + * extract bits [@b0:@b1] (inclusive) from the value @x 30 + * it should be @b0 <= @b1, or result is incorrect 31 + */ 32 + static inline u32 WIL_GET_BITS(u32 x, int b0, int b1) 33 + { 34 + return (x >> b0) & ((1 << (b1 - b0 + 1)) - 1); 35 + } 36 + 37 + #define WIL6210_MEM_SIZE (2*1024*1024UL) 38 + 39 + #define WIL6210_TX_QUEUES (4) 40 + 41 + #define WIL6210_RX_RING_SIZE (128) 42 + #define WIL6210_TX_RING_SIZE (128) 43 + #define WIL6210_MAX_TX_RINGS (24) 44 + 45 + /* Hardware definitions begin */ 46 + 47 + /* 48 + * Mapping 49 + * RGF File | Host addr | FW addr 50 + * | | 51 + * user_rgf | 0x000000 | 0x880000 52 + * dma_rgf | 0x001000 | 0x881000 53 + * pcie_rgf | 0x002000 | 0x882000 54 + * | | 55 + */ 56 + 57 + /* Where various structures placed in host address space */ 58 + #define WIL6210_FW_HOST_OFF (0x880000UL) 59 + 60 + #define HOSTADDR(fwaddr) (fwaddr - WIL6210_FW_HOST_OFF) 61 + 62 + /* 63 + * Interrupt control registers block 64 + * 65 + * each interrupt controlled by the same bit in all registers 66 + */ 67 + struct RGF_ICR { 68 + u32 ICC; /* Cause Control, RW: 0 - W1C, 1 - COR */ 69 + u32 ICR; /* Cause, W1C/COR depending on ICC */ 70 + u32 ICM; /* Cause masked (ICR & ~IMV), W1C/COR depending on ICC */ 71 + u32 ICS; /* Cause Set, WO */ 72 + u32 IMV; /* Mask, RW+S/C */ 73 + u32 IMS; /* Mask Set, write 1 to set */ 74 + u32 IMC; /* Mask Clear, write 1 to clear */ 75 + } __packed; 76 + 77 + /* registers - FW addresses */ 78 + #define RGF_USER_USER_SCRATCH_PAD (0x8802bc) 79 + #define RGF_USER_USER_ICR (0x880b4c) /* struct RGF_ICR */ 80 + #define BIT_USER_USER_ICR_SW_INT_2 BIT(18) 81 + #define RGF_USER_CLKS_CTL_SW_RST_MASK_0 (0x880b14) 82 + #define RGF_USER_MAC_CPU_0 (0x8801fc) 83 + #define RGF_USER_USER_CPU_0 (0x8801e0) 84 + #define RGF_USER_CLKS_CTL_SW_RST_VEC_0 (0x880b04) 85 + #define RGF_USER_CLKS_CTL_SW_RST_VEC_1 (0x880b08) 86 + #define RGF_USER_CLKS_CTL_SW_RST_VEC_2 (0x880b0c) 87 + #define RGF_USER_CLKS_CTL_SW_RST_VEC_3 (0x880b10) 88 + 89 + #define RGF_DMA_PSEUDO_CAUSE (0x881c68) 90 + #define RGF_DMA_PSEUDO_CAUSE_MASK_SW (0x881c6c) 91 + #define RGF_DMA_PSEUDO_CAUSE_MASK_FW (0x881c70) 92 + #define BIT_DMA_PSEUDO_CAUSE_RX BIT(0) 93 + #define BIT_DMA_PSEUDO_CAUSE_TX BIT(1) 94 + #define BIT_DMA_PSEUDO_CAUSE_MISC BIT(2) 95 + 96 + #define RGF_DMA_EP_TX_ICR (0x881bb4) /* struct RGF_ICR */ 97 + #define BIT_DMA_EP_TX_ICR_TX_DONE BIT(0) 98 + #define BIT_DMA_EP_TX_ICR_TX_DONE_N(n) BIT(n+1) /* n = [0..23] */ 99 + #define RGF_DMA_EP_RX_ICR (0x881bd0) /* struct RGF_ICR */ 100 + #define BIT_DMA_EP_RX_ICR_RX_DONE BIT(0) 101 + #define RGF_DMA_EP_MISC_ICR (0x881bec) /* struct RGF_ICR */ 102 + #define BIT_DMA_EP_MISC_ICR_RX_HTRSH BIT(0) 103 + #define BIT_DMA_EP_MISC_ICR_TX_NO_ACT BIT(1) 104 + #define BIT_DMA_EP_MISC_ICR_FW_INT0 BIT(28) 105 + #define BIT_DMA_EP_MISC_ICR_FW_INT1 BIT(29) 106 + 107 + /* Interrupt moderation control */ 108 + #define RGF_DMA_ITR_CNT_TRSH (0x881c5c) 109 + #define RGF_DMA_ITR_CNT_DATA (0x881c60) 110 + #define RGF_DMA_ITR_CNT_CRL (0x881C64) 111 + #define BIT_DMA_ITR_CNT_CRL_EN BIT(0) 112 + #define BIT_DMA_ITR_CNT_CRL_EXT_TICK BIT(1) 113 + #define BIT_DMA_ITR_CNT_CRL_FOREVER BIT(2) 114 + #define BIT_DMA_ITR_CNT_CRL_CLR BIT(3) 115 + #define BIT_DMA_ITR_CNT_CRL_REACH_TRSH BIT(4) 116 + 117 + /* popular locations */ 118 + #define HOST_MBOX HOSTADDR(RGF_USER_USER_SCRATCH_PAD) 119 + #define HOST_SW_INT (HOSTADDR(RGF_USER_USER_ICR) + \ 120 + offsetof(struct RGF_ICR, ICS)) 121 + #define SW_INT_MBOX BIT_USER_USER_ICR_SW_INT_2 122 + 123 + /* ISR register bits */ 124 + #define ISR_MISC_FW_READY BIT_DMA_EP_MISC_ICR_FW_INT0 125 + #define ISR_MISC_MBOX_EVT BIT_DMA_EP_MISC_ICR_FW_INT1 126 + 127 + /* Hardware definitions end */ 128 + 129 + struct wil6210_mbox_ring { 130 + u32 base; 131 + u16 entry_size; /* max. size of mbox entry, incl. all headers */ 132 + u16 size; 133 + u32 tail; 134 + u32 head; 135 + } __packed; 136 + 137 + struct wil6210_mbox_ring_desc { 138 + __le32 sync; 139 + __le32 addr; 140 + } __packed; 141 + 142 + /* at HOST_OFF_WIL6210_MBOX_CTL */ 143 + struct wil6210_mbox_ctl { 144 + struct wil6210_mbox_ring tx; 145 + struct wil6210_mbox_ring rx; 146 + } __packed; 147 + 148 + struct wil6210_mbox_hdr { 149 + __le16 seq; 150 + __le16 len; /* payload, bytes after this header */ 151 + __le16 type; 152 + u8 flags; 153 + u8 reserved; 154 + } __packed; 155 + 156 + #define WIL_MBOX_HDR_TYPE_WMI (0) 157 + 158 + /* max. value for wil6210_mbox_hdr.len */ 159 + #define MAX_MBOXITEM_SIZE (240) 160 + 161 + struct wil6210_mbox_hdr_wmi { 162 + u8 reserved0[2]; 163 + __le16 id; 164 + __le16 info1; /* bits [0..3] - device_id, rest - unused */ 165 + u8 reserved1[2]; 166 + } __packed; 167 + 168 + struct pending_wmi_event { 169 + struct list_head list; 170 + struct { 171 + struct wil6210_mbox_hdr hdr; 172 + struct wil6210_mbox_hdr_wmi wmi; 173 + u8 data[0]; 174 + } __packed event; 175 + }; 176 + 177 + union vring_desc; 178 + 179 + struct vring { 180 + dma_addr_t pa; 181 + volatile union vring_desc *va; /* vring_desc[size], WriteBack by DMA */ 182 + u16 size; /* number of vring_desc elements */ 183 + u32 swtail; 184 + u32 swhead; 185 + u32 hwtail; /* write here to inform hw */ 186 + void **ctx; /* void *ctx[size] - software context */ 187 + }; 188 + 189 + enum { /* for wil6210_priv.status */ 190 + wil_status_fwready = 0, 191 + wil_status_fwconnected, 192 + wil_status_dontscan, 193 + wil_status_irqen, /* FIXME: interrupts enabled - for debug */ 194 + }; 195 + 196 + struct pci_dev; 197 + 198 + struct wil6210_stats { 199 + u64 tsf; 200 + u32 snr; 201 + u16 last_mcs_rx; 202 + u16 bf_mcs; /* last BF, used for Tx */ 203 + u16 my_rx_sector; 204 + u16 my_tx_sector; 205 + u16 peer_rx_sector; 206 + u16 peer_tx_sector; 207 + }; 208 + 209 + struct wil6210_priv { 210 + struct pci_dev *pdev; 211 + int n_msi; 212 + struct wireless_dev *wdev; 213 + void __iomem *csr; 214 + ulong status; 215 + /* profile */ 216 + u32 monitor_flags; 217 + u32 secure_pcp; /* create secure PCP? */ 218 + int sinfo_gen; 219 + /* cached ISR registers */ 220 + u32 isr_misc; 221 + /* mailbox related */ 222 + struct mutex wmi_mutex; 223 + struct wil6210_mbox_ctl mbox_ctl; 224 + struct completion wmi_ready; 225 + u16 wmi_seq; 226 + u16 reply_id; /**< wait for this WMI event */ 227 + void *reply_buf; 228 + u16 reply_size; 229 + struct workqueue_struct *wmi_wq; /* for deferred calls */ 230 + struct work_struct wmi_event_worker; 231 + struct workqueue_struct *wmi_wq_conn; /* for connect worker */ 232 + struct work_struct wmi_connect_worker; 233 + struct work_struct disconnect_worker; 234 + struct timer_list connect_timer; 235 + int pending_connect_cid; 236 + struct list_head pending_wmi_ev; 237 + /* 238 + * protect pending_wmi_ev 239 + * - fill in IRQ from wil6210_irq_misc, 240 + * - consumed in thread by wmi_event_worker 241 + */ 242 + spinlock_t wmi_ev_lock; 243 + /* DMA related */ 244 + struct vring vring_rx; 245 + struct vring vring_tx[WIL6210_MAX_TX_RINGS]; 246 + u8 dst_addr[WIL6210_MAX_TX_RINGS][ETH_ALEN]; 247 + /* scan */ 248 + struct cfg80211_scan_request *scan_request; 249 + 250 + struct mutex mutex; /* for wil6210_priv access in wil_{up|down} */ 251 + /* statistics */ 252 + struct wil6210_stats stats; 253 + /* debugfs */ 254 + struct dentry *debug; 255 + struct debugfs_blob_wrapper fw_code_blob; 256 + struct debugfs_blob_wrapper fw_data_blob; 257 + struct debugfs_blob_wrapper fw_peri_blob; 258 + struct debugfs_blob_wrapper uc_code_blob; 259 + struct debugfs_blob_wrapper uc_data_blob; 260 + struct debugfs_blob_wrapper rgf_blob; 261 + }; 262 + 263 + #define wil_to_wiphy(i) (i->wdev->wiphy) 264 + #define wil_to_dev(i) (wiphy_dev(wil_to_wiphy(i))) 265 + #define wiphy_to_wil(w) (struct wil6210_priv *)(wiphy_priv(w)) 266 + #define wil_to_wdev(i) (i->wdev) 267 + #define wdev_to_wil(w) (struct wil6210_priv *)(wdev_priv(w)) 268 + #define wil_to_ndev(i) (wil_to_wdev(i)->netdev) 269 + #define ndev_to_wil(n) (wdev_to_wil(n->ieee80211_ptr)) 270 + 271 + #define wil_dbg(wil, fmt, arg...) netdev_dbg(wil_to_ndev(wil), fmt, ##arg) 272 + #define wil_info(wil, fmt, arg...) netdev_info(wil_to_ndev(wil), fmt, ##arg) 273 + #define wil_err(wil, fmt, arg...) netdev_err(wil_to_ndev(wil), fmt, ##arg) 274 + 275 + #define wil_dbg_IRQ(wil, fmt, arg...) wil_dbg(wil, "DBG[ IRQ]" fmt, ##arg) 276 + #define wil_dbg_TXRX(wil, fmt, arg...) wil_dbg(wil, "DBG[TXRX]" fmt, ##arg) 277 + #define wil_dbg_WMI(wil, fmt, arg...) wil_dbg(wil, "DBG[ WMI]" fmt, ##arg) 278 + 279 + #define wil_hex_dump_TXRX(prefix_str, prefix_type, rowsize, \ 280 + groupsize, buf, len, ascii) \ 281 + wil_print_hex_dump_debug("DBG[TXRX]" prefix_str,\ 282 + prefix_type, rowsize, \ 283 + groupsize, buf, len, ascii) 284 + 285 + #define wil_hex_dump_WMI(prefix_str, prefix_type, rowsize, \ 286 + groupsize, buf, len, ascii) \ 287 + wil_print_hex_dump_debug("DBG[ WMI]" prefix_str,\ 288 + prefix_type, rowsize, \ 289 + groupsize, buf, len, ascii) 290 + 291 + void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src, 292 + size_t count); 293 + void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, 294 + size_t count); 295 + 296 + void *wil_if_alloc(struct device *dev, void __iomem *csr); 297 + void wil_if_free(struct wil6210_priv *wil); 298 + int wil_if_add(struct wil6210_priv *wil); 299 + void wil_if_remove(struct wil6210_priv *wil); 300 + int wil_priv_init(struct wil6210_priv *wil); 301 + void wil_priv_deinit(struct wil6210_priv *wil); 302 + int wil_reset(struct wil6210_priv *wil); 303 + void wil_link_on(struct wil6210_priv *wil); 304 + void wil_link_off(struct wil6210_priv *wil); 305 + int wil_up(struct wil6210_priv *wil); 306 + int wil_down(struct wil6210_priv *wil); 307 + void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r); 308 + 309 + void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr); 310 + void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr); 311 + int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr, 312 + struct wil6210_mbox_hdr *hdr); 313 + int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len); 314 + void wmi_recv_cmd(struct wil6210_priv *wil); 315 + int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, 316 + u16 reply_id, void *reply, u8 reply_size, int to_msec); 317 + void wmi_connect_worker(struct work_struct *work); 318 + void wmi_event_worker(struct work_struct *work); 319 + void wmi_event_flush(struct wil6210_priv *wil); 320 + int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid); 321 + int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid); 322 + int wmi_set_channel(struct wil6210_priv *wil, int channel); 323 + int wmi_get_channel(struct wil6210_priv *wil, int *channel); 324 + int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb); 325 + int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index, 326 + const void *mac_addr); 327 + int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index, 328 + const void *mac_addr, int key_len, const void *key); 329 + int wmi_echo(struct wil6210_priv *wil); 330 + int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie); 331 + 332 + int wil6210_init_irq(struct wil6210_priv *wil, int irq); 333 + void wil6210_fini_irq(struct wil6210_priv *wil, int irq); 334 + void wil6210_disable_irq(struct wil6210_priv *wil); 335 + void wil6210_enable_irq(struct wil6210_priv *wil); 336 + 337 + int wil6210_debugfs_init(struct wil6210_priv *wil); 338 + void wil6210_debugfs_remove(struct wil6210_priv *wil); 339 + 340 + struct wireless_dev *wil_cfg80211_init(struct device *dev); 341 + void wil_wdev_free(struct wil6210_priv *wil); 342 + 343 + int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); 344 + int wmi_set_bcon(struct wil6210_priv *wil, int bi, u8 wmi_nettype); 345 + void wil6210_disconnect(struct wil6210_priv *wil, void *bssid); 346 + 347 + int wil_rx_init(struct wil6210_priv *wil); 348 + void wil_rx_fini(struct wil6210_priv *wil); 349 + 350 + /* TX API */ 351 + int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, 352 + int cid, int tid); 353 + void wil_vring_fini_tx(struct wil6210_priv *wil, int id); 354 + 355 + netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev); 356 + void wil_tx_complete(struct wil6210_priv *wil, int ringid); 357 + 358 + /* RX API */ 359 + void wil_rx_handle(struct wil6210_priv *wil); 360 + 361 + int wil_iftype_nl2wmi(enum nl80211_iftype type); 362 + 363 + #endif /* __WIL6210_H__ */
+975
drivers/net/wireless/ath/wil6210/wmi.c
··· 1 + /* 2 + * Copyright (c) 2012 Qualcomm Atheros, Inc. 3 + * 4 + * Permission to use, copy, modify, and/or distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + 17 + #include <linux/pci.h> 18 + #include <linux/io.h> 19 + #include <linux/list.h> 20 + #include <linux/etherdevice.h> 21 + 22 + #include "wil6210.h" 23 + #include "wmi.h" 24 + 25 + /** 26 + * WMI event receiving - theory of operations 27 + * 28 + * When firmware about to report WMI event, it fills memory area 29 + * in the mailbox and raises misc. IRQ. Thread interrupt handler invoked for 30 + * the misc IRQ, function @wmi_recv_cmd called by thread IRQ handler. 31 + * 32 + * @wmi_recv_cmd reads event, allocates memory chunk and attaches it to the 33 + * event list @wil->pending_wmi_ev. Then, work queue @wil->wmi_wq wakes up 34 + * and handles events within the @wmi_event_worker. Every event get detached 35 + * from list, processed and deleted. 36 + * 37 + * Purpose for this mechanism is to release IRQ thread; otherwise, 38 + * if WMI event handling involves another WMI command flow, this 2-nd flow 39 + * won't be completed because of blocked IRQ thread. 40 + */ 41 + 42 + /** 43 + * Addressing - theory of operations 44 + * 45 + * There are several buses present on the WIL6210 card. 46 + * Same memory areas are visible at different address on 47 + * the different busses. There are 3 main bus masters: 48 + * - MAC CPU (ucode) 49 + * - User CPU (firmware) 50 + * - AHB (host) 51 + * 52 + * On the PCI bus, there is one BAR (BAR0) of 2Mb size, exposing 53 + * AHB addresses starting from 0x880000 54 + * 55 + * Internally, firmware uses addresses that allows faster access but 56 + * are invisible from the host. To read from these addresses, alternative 57 + * AHB address must be used. 58 + * 59 + * Memory mapping 60 + * Linker address PCI/Host address 61 + * 0x880000 .. 0xa80000 2Mb BAR0 62 + * 0x800000 .. 0x807000 0x900000 .. 0x907000 28k DCCM 63 + * 0x840000 .. 0x857000 0x908000 .. 0x91f000 92k PERIPH 64 + */ 65 + 66 + /** 67 + * @fw_mapping provides memory remapping table 68 + */ 69 + static const struct { 70 + u32 from; /* linker address - from, inclusive */ 71 + u32 to; /* linker address - to, exclusive */ 72 + u32 host; /* PCI/Host address - BAR0 + 0x880000 */ 73 + } fw_mapping[] = { 74 + {0x000000, 0x040000, 0x8c0000}, /* FW code RAM 256k */ 75 + {0x800000, 0x808000, 0x900000}, /* FW data RAM 32k */ 76 + {0x840000, 0x860000, 0x908000}, /* peripheral data RAM 128k/96k used */ 77 + {0x880000, 0x88a000, 0x880000}, /* various RGF */ 78 + {0x8c0000, 0x932000, 0x8c0000}, /* trivial mapping for upper area */ 79 + /* 80 + * 920000..930000 ucode code RAM 81 + * 930000..932000 ucode data RAM 82 + */ 83 + }; 84 + 85 + /** 86 + * return AHB address for given firmware/ucode internal (linker) address 87 + * @x - internal address 88 + * If address have no valid AHB mapping, return 0 89 + */ 90 + static u32 wmi_addr_remap(u32 x) 91 + { 92 + uint i; 93 + 94 + for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) { 95 + if ((x >= fw_mapping[i].from) && (x < fw_mapping[i].to)) 96 + return x + fw_mapping[i].host - fw_mapping[i].from; 97 + } 98 + 99 + return 0; 100 + } 101 + 102 + /** 103 + * Check address validity for WMI buffer; remap if needed 104 + * @ptr - internal (linker) fw/ucode address 105 + * 106 + * Valid buffer should be DWORD aligned 107 + * 108 + * return address for accessing buffer from the host; 109 + * if buffer is not valid, return NULL. 110 + */ 111 + void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_) 112 + { 113 + u32 off; 114 + u32 ptr = le32_to_cpu(ptr_); 115 + 116 + if (ptr % 4) 117 + return NULL; 118 + 119 + ptr = wmi_addr_remap(ptr); 120 + if (ptr < WIL6210_FW_HOST_OFF) 121 + return NULL; 122 + 123 + off = HOSTADDR(ptr); 124 + if (off > WIL6210_MEM_SIZE - 4) 125 + return NULL; 126 + 127 + return wil->csr + off; 128 + } 129 + 130 + /** 131 + * Check address validity 132 + */ 133 + void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr) 134 + { 135 + u32 off; 136 + 137 + if (ptr % 4) 138 + return NULL; 139 + 140 + if (ptr < WIL6210_FW_HOST_OFF) 141 + return NULL; 142 + 143 + off = HOSTADDR(ptr); 144 + if (off > WIL6210_MEM_SIZE - 4) 145 + return NULL; 146 + 147 + return wil->csr + off; 148 + } 149 + 150 + int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr, 151 + struct wil6210_mbox_hdr *hdr) 152 + { 153 + void __iomem *src = wmi_buffer(wil, ptr); 154 + if (!src) 155 + return -EINVAL; 156 + 157 + wil_memcpy_fromio_32(hdr, src, sizeof(*hdr)); 158 + 159 + return 0; 160 + } 161 + 162 + static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) 163 + { 164 + struct { 165 + struct wil6210_mbox_hdr hdr; 166 + struct wil6210_mbox_hdr_wmi wmi; 167 + } __packed cmd = { 168 + .hdr = { 169 + .type = WIL_MBOX_HDR_TYPE_WMI, 170 + .flags = 0, 171 + .len = cpu_to_le16(sizeof(cmd.wmi) + len), 172 + }, 173 + .wmi = { 174 + .id = cpu_to_le16(cmdid), 175 + .info1 = 0, 176 + }, 177 + }; 178 + struct wil6210_mbox_ring *r = &wil->mbox_ctl.tx; 179 + struct wil6210_mbox_ring_desc d_head; 180 + u32 next_head; 181 + void __iomem *dst; 182 + void __iomem *head = wmi_addr(wil, r->head); 183 + uint retry; 184 + 185 + if (sizeof(cmd) + len > r->entry_size) { 186 + wil_err(wil, "WMI size too large: %d bytes, max is %d\n", 187 + (int)(sizeof(cmd) + len), r->entry_size); 188 + return -ERANGE; 189 + 190 + } 191 + 192 + might_sleep(); 193 + 194 + if (!test_bit(wil_status_fwready, &wil->status)) { 195 + wil_err(wil, "FW not ready\n"); 196 + return -EAGAIN; 197 + } 198 + 199 + if (!head) { 200 + wil_err(wil, "WMI head is garbage: 0x%08x\n", r->head); 201 + return -EINVAL; 202 + } 203 + /* read Tx head till it is not busy */ 204 + for (retry = 5; retry > 0; retry--) { 205 + wil_memcpy_fromio_32(&d_head, head, sizeof(d_head)); 206 + if (d_head.sync == 0) 207 + break; 208 + msleep(20); 209 + } 210 + if (d_head.sync != 0) { 211 + wil_err(wil, "WMI head busy\n"); 212 + return -EBUSY; 213 + } 214 + /* next head */ 215 + next_head = r->base + ((r->head - r->base + sizeof(d_head)) % r->size); 216 + wil_dbg_WMI(wil, "Head 0x%08x -> 0x%08x\n", r->head, next_head); 217 + /* wait till FW finish with previous command */ 218 + for (retry = 5; retry > 0; retry--) { 219 + r->tail = ioread32(wil->csr + HOST_MBOX + 220 + offsetof(struct wil6210_mbox_ctl, tx.tail)); 221 + if (next_head != r->tail) 222 + break; 223 + msleep(20); 224 + } 225 + if (next_head == r->tail) { 226 + wil_err(wil, "WMI ring full\n"); 227 + return -EBUSY; 228 + } 229 + dst = wmi_buffer(wil, d_head.addr); 230 + if (!dst) { 231 + wil_err(wil, "invalid WMI buffer: 0x%08x\n", 232 + le32_to_cpu(d_head.addr)); 233 + return -EINVAL; 234 + } 235 + cmd.hdr.seq = cpu_to_le16(++wil->wmi_seq); 236 + /* set command */ 237 + wil_dbg_WMI(wil, "WMI command 0x%04x [%d]\n", cmdid, len); 238 + wil_hex_dump_WMI("Cmd ", DUMP_PREFIX_OFFSET, 16, 1, &cmd, 239 + sizeof(cmd), true); 240 + wil_hex_dump_WMI("cmd ", DUMP_PREFIX_OFFSET, 16, 1, buf, 241 + len, true); 242 + wil_memcpy_toio_32(dst, &cmd, sizeof(cmd)); 243 + wil_memcpy_toio_32(dst + sizeof(cmd), buf, len); 244 + /* mark entry as full */ 245 + iowrite32(1, wil->csr + HOSTADDR(r->head) + 246 + offsetof(struct wil6210_mbox_ring_desc, sync)); 247 + /* advance next ptr */ 248 + iowrite32(r->head = next_head, wil->csr + HOST_MBOX + 249 + offsetof(struct wil6210_mbox_ctl, tx.head)); 250 + 251 + /* interrupt to FW */ 252 + iowrite32(SW_INT_MBOX, wil->csr + HOST_SW_INT); 253 + 254 + return 0; 255 + } 256 + 257 + int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) 258 + { 259 + int rc; 260 + 261 + mutex_lock(&wil->wmi_mutex); 262 + rc = __wmi_send(wil, cmdid, buf, len); 263 + mutex_unlock(&wil->wmi_mutex); 264 + 265 + return rc; 266 + } 267 + 268 + /*=== Event handlers ===*/ 269 + static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len) 270 + { 271 + struct net_device *ndev = wil_to_ndev(wil); 272 + struct wireless_dev *wdev = wil->wdev; 273 + struct wmi_ready_event *evt = d; 274 + u32 ver = le32_to_cpu(evt->sw_version); 275 + 276 + wil_dbg_WMI(wil, "FW ver. %d; MAC %pM\n", ver, evt->mac); 277 + 278 + if (!is_valid_ether_addr(ndev->dev_addr)) { 279 + memcpy(ndev->dev_addr, evt->mac, ETH_ALEN); 280 + memcpy(ndev->perm_addr, evt->mac, ETH_ALEN); 281 + } 282 + snprintf(wdev->wiphy->fw_version, sizeof(wdev->wiphy->fw_version), 283 + "%d", ver); 284 + } 285 + 286 + static void wmi_evt_fw_ready(struct wil6210_priv *wil, int id, void *d, 287 + int len) 288 + { 289 + wil_dbg_WMI(wil, "WMI: FW ready\n"); 290 + 291 + set_bit(wil_status_fwready, &wil->status); 292 + /* reuse wmi_ready for the firmware ready indication */ 293 + complete(&wil->wmi_ready); 294 + } 295 + 296 + static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) 297 + { 298 + struct wmi_rx_mgmt_packet_event *data = d; 299 + struct wiphy *wiphy = wil_to_wiphy(wil); 300 + struct ieee80211_mgmt *rx_mgmt_frame = 301 + (struct ieee80211_mgmt *)data->payload; 302 + int ch_no = data->info.channel+1; 303 + u32 freq = ieee80211_channel_to_frequency(ch_no, 304 + IEEE80211_BAND_60GHZ); 305 + struct ieee80211_channel *channel = ieee80211_get_channel(wiphy, freq); 306 + /* TODO convert LE to CPU */ 307 + s32 signal = 0; /* TODO */ 308 + __le16 fc = rx_mgmt_frame->frame_control; 309 + u32 d_len = le32_to_cpu(data->info.len); 310 + u16 d_status = le16_to_cpu(data->info.status); 311 + 312 + wil_dbg_WMI(wil, "MGMT: channel %d MCS %d SNR %d\n", 313 + data->info.channel, data->info.mcs, data->info.snr); 314 + wil_dbg_WMI(wil, "status 0x%04x len %d stype %04x\n", d_status, d_len, 315 + le16_to_cpu(data->info.stype)); 316 + wil_dbg_WMI(wil, "qid %d mid %d cid %d\n", 317 + data->info.qid, data->info.mid, data->info.cid); 318 + 319 + if (!channel) { 320 + wil_err(wil, "Frame on unsupported channel\n"); 321 + return; 322 + } 323 + 324 + if (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)) { 325 + struct cfg80211_bss *bss; 326 + u64 tsf = le64_to_cpu(rx_mgmt_frame->u.beacon.timestamp); 327 + u16 cap = le16_to_cpu(rx_mgmt_frame->u.beacon.capab_info); 328 + u16 bi = le16_to_cpu(rx_mgmt_frame->u.beacon.beacon_int); 329 + const u8 *ie_buf = rx_mgmt_frame->u.beacon.variable; 330 + size_t ie_len = d_len - offsetof(struct ieee80211_mgmt, 331 + u.beacon.variable); 332 + wil_dbg_WMI(wil, "Capability info : 0x%04x\n", cap); 333 + 334 + bss = cfg80211_inform_bss(wiphy, channel, rx_mgmt_frame->bssid, 335 + tsf, cap, bi, ie_buf, ie_len, 336 + signal, GFP_KERNEL); 337 + if (bss) { 338 + wil_dbg_WMI(wil, "Added BSS %pM\n", 339 + rx_mgmt_frame->bssid); 340 + cfg80211_put_bss(bss); 341 + } else { 342 + wil_err(wil, "cfg80211_inform_bss() failed\n"); 343 + } 344 + } 345 + } 346 + 347 + static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id, 348 + void *d, int len) 349 + { 350 + if (wil->scan_request) { 351 + struct wmi_scan_complete_event *data = d; 352 + bool aborted = (data->status != 0); 353 + 354 + wil_dbg_WMI(wil, "SCAN_COMPLETE(0x%08x)\n", data->status); 355 + cfg80211_scan_done(wil->scan_request, aborted); 356 + wil->scan_request = NULL; 357 + } else { 358 + wil_err(wil, "SCAN_COMPLETE while not scanning\n"); 359 + } 360 + } 361 + 362 + static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) 363 + { 364 + struct net_device *ndev = wil_to_ndev(wil); 365 + struct wireless_dev *wdev = wil->wdev; 366 + struct wmi_connect_event *evt = d; 367 + int ch; /* channel number */ 368 + struct station_info sinfo; 369 + u8 *assoc_req_ie, *assoc_resp_ie; 370 + size_t assoc_req_ielen, assoc_resp_ielen; 371 + /* capinfo(u16) + listen_interval(u16) + IEs */ 372 + const size_t assoc_req_ie_offset = sizeof(u16) * 2; 373 + /* capinfo(u16) + status_code(u16) + associd(u16) + IEs */ 374 + const size_t assoc_resp_ie_offset = sizeof(u16) * 3; 375 + 376 + if (len < sizeof(*evt)) { 377 + wil_err(wil, "Connect event too short : %d bytes\n", len); 378 + return; 379 + } 380 + if (len != sizeof(*evt) + evt->beacon_ie_len + evt->assoc_req_len + 381 + evt->assoc_resp_len) { 382 + wil_err(wil, 383 + "Connect event corrupted : %d != %d + %d + %d + %d\n", 384 + len, (int)sizeof(*evt), evt->beacon_ie_len, 385 + evt->assoc_req_len, evt->assoc_resp_len); 386 + return; 387 + } 388 + ch = evt->channel + 1; 389 + wil_dbg_WMI(wil, "Connect %pM channel [%d] cid %d\n", 390 + evt->bssid, ch, evt->cid); 391 + wil_hex_dump_WMI("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1, 392 + evt->assoc_info, len - sizeof(*evt), true); 393 + 394 + /* figure out IE's */ 395 + assoc_req_ie = &evt->assoc_info[evt->beacon_ie_len + 396 + assoc_req_ie_offset]; 397 + assoc_req_ielen = evt->assoc_req_len - assoc_req_ie_offset; 398 + if (evt->assoc_req_len <= assoc_req_ie_offset) { 399 + assoc_req_ie = NULL; 400 + assoc_req_ielen = 0; 401 + } 402 + 403 + assoc_resp_ie = &evt->assoc_info[evt->beacon_ie_len + 404 + evt->assoc_req_len + 405 + assoc_resp_ie_offset]; 406 + assoc_resp_ielen = evt->assoc_resp_len - assoc_resp_ie_offset; 407 + if (evt->assoc_resp_len <= assoc_resp_ie_offset) { 408 + assoc_resp_ie = NULL; 409 + assoc_resp_ielen = 0; 410 + } 411 + 412 + if ((wdev->iftype == NL80211_IFTYPE_STATION) || 413 + (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { 414 + if (wdev->sme_state != CFG80211_SME_CONNECTING) { 415 + wil_err(wil, "Not in connecting state\n"); 416 + return; 417 + } 418 + del_timer_sync(&wil->connect_timer); 419 + cfg80211_connect_result(ndev, evt->bssid, 420 + assoc_req_ie, assoc_req_ielen, 421 + assoc_resp_ie, assoc_resp_ielen, 422 + WLAN_STATUS_SUCCESS, GFP_KERNEL); 423 + 424 + } else if ((wdev->iftype == NL80211_IFTYPE_AP) || 425 + (wdev->iftype == NL80211_IFTYPE_P2P_GO)) { 426 + memset(&sinfo, 0, sizeof(sinfo)); 427 + 428 + sinfo.generation = wil->sinfo_gen++; 429 + 430 + if (assoc_req_ie) { 431 + sinfo.assoc_req_ies = assoc_req_ie; 432 + sinfo.assoc_req_ies_len = assoc_req_ielen; 433 + sinfo.filled |= STATION_INFO_ASSOC_REQ_IES; 434 + } 435 + 436 + cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL); 437 + } 438 + set_bit(wil_status_fwconnected, &wil->status); 439 + 440 + /* FIXME FW can transmit only ucast frames to peer */ 441 + /* FIXME real ring_id instead of hard coded 0 */ 442 + memcpy(wil->dst_addr[0], evt->bssid, ETH_ALEN); 443 + 444 + wil->pending_connect_cid = evt->cid; 445 + queue_work(wil->wmi_wq_conn, &wil->wmi_connect_worker); 446 + } 447 + 448 + static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, 449 + void *d, int len) 450 + { 451 + struct wmi_disconnect_event *evt = d; 452 + 453 + wil_dbg_WMI(wil, "Disconnect %pM reason %d proto %d wmi\n", 454 + evt->bssid, 455 + evt->protocol_reason_status, evt->disconnect_reason); 456 + 457 + wil->sinfo_gen++; 458 + 459 + wil6210_disconnect(wil, evt->bssid); 460 + clear_bit(wil_status_dontscan, &wil->status); 461 + } 462 + 463 + static void wmi_evt_notify(struct wil6210_priv *wil, int id, void *d, int len) 464 + { 465 + struct wmi_notify_req_done_event *evt = d; 466 + 467 + if (len < sizeof(*evt)) { 468 + wil_err(wil, "Short NOTIFY event\n"); 469 + return; 470 + } 471 + 472 + wil->stats.tsf = le64_to_cpu(evt->tsf); 473 + wil->stats.snr = le32_to_cpu(evt->snr_val); 474 + wil->stats.bf_mcs = le16_to_cpu(evt->bf_mcs); 475 + wil->stats.my_rx_sector = le16_to_cpu(evt->my_rx_sector); 476 + wil->stats.my_tx_sector = le16_to_cpu(evt->my_tx_sector); 477 + wil->stats.peer_rx_sector = le16_to_cpu(evt->other_rx_sector); 478 + wil->stats.peer_tx_sector = le16_to_cpu(evt->other_tx_sector); 479 + wil_dbg_WMI(wil, "Link status, MCS %d TSF 0x%016llx\n" 480 + "BF status 0x%08x SNR 0x%08x\n" 481 + "Tx Tpt %d goodput %d Rx goodput %d\n" 482 + "Sectors(rx:tx) my %d:%d peer %d:%d\n", 483 + wil->stats.bf_mcs, wil->stats.tsf, evt->status, 484 + wil->stats.snr, le32_to_cpu(evt->tx_tpt), 485 + le32_to_cpu(evt->tx_goodput), le32_to_cpu(evt->rx_goodput), 486 + wil->stats.my_rx_sector, wil->stats.my_tx_sector, 487 + wil->stats.peer_rx_sector, wil->stats.peer_tx_sector); 488 + } 489 + 490 + /* 491 + * Firmware reports EAPOL frame using WME event. 492 + * Reconstruct Ethernet frame and deliver it via normal Rx 493 + */ 494 + static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id, 495 + void *d, int len) 496 + { 497 + struct net_device *ndev = wil_to_ndev(wil); 498 + struct wmi_eapol_rx_event *evt = d; 499 + u16 eapol_len = le16_to_cpu(evt->eapol_len); 500 + int sz = eapol_len + ETH_HLEN; 501 + struct sk_buff *skb; 502 + struct ethhdr *eth; 503 + 504 + wil_dbg_WMI(wil, "EAPOL len %d from %pM\n", eapol_len, 505 + evt->src_mac); 506 + 507 + if (eapol_len > 196) { /* TODO: revisit size limit */ 508 + wil_err(wil, "EAPOL too large\n"); 509 + return; 510 + } 511 + 512 + skb = alloc_skb(sz, GFP_KERNEL); 513 + if (!skb) { 514 + wil_err(wil, "Failed to allocate skb\n"); 515 + return; 516 + } 517 + eth = (struct ethhdr *)skb_put(skb, ETH_HLEN); 518 + memcpy(eth->h_dest, ndev->dev_addr, ETH_ALEN); 519 + memcpy(eth->h_source, evt->src_mac, ETH_ALEN); 520 + eth->h_proto = cpu_to_be16(ETH_P_PAE); 521 + memcpy(skb_put(skb, eapol_len), evt->eapol, eapol_len); 522 + skb->protocol = eth_type_trans(skb, ndev); 523 + if (likely(netif_rx_ni(skb) == NET_RX_SUCCESS)) { 524 + ndev->stats.rx_packets++; 525 + ndev->stats.rx_bytes += skb->len; 526 + } else { 527 + ndev->stats.rx_dropped++; 528 + } 529 + } 530 + 531 + static const struct { 532 + int eventid; 533 + void (*handler)(struct wil6210_priv *wil, int eventid, 534 + void *data, int data_len); 535 + } wmi_evt_handlers[] = { 536 + {WMI_READY_EVENTID, wmi_evt_ready}, 537 + {WMI_FW_READY_EVENTID, wmi_evt_fw_ready}, 538 + {WMI_RX_MGMT_PACKET_EVENTID, wmi_evt_rx_mgmt}, 539 + {WMI_SCAN_COMPLETE_EVENTID, wmi_evt_scan_complete}, 540 + {WMI_CONNECT_EVENTID, wmi_evt_connect}, 541 + {WMI_DISCONNECT_EVENTID, wmi_evt_disconnect}, 542 + {WMI_NOTIFY_REQ_DONE_EVENTID, wmi_evt_notify}, 543 + {WMI_EAPOL_RX_EVENTID, wmi_evt_eapol_rx}, 544 + }; 545 + 546 + /* 547 + * Run in IRQ context 548 + * Extract WMI command from mailbox. Queue it to the @wil->pending_wmi_ev 549 + * that will be eventually handled by the @wmi_event_worker in the thread 550 + * context of thread "wil6210_wmi" 551 + */ 552 + void wmi_recv_cmd(struct wil6210_priv *wil) 553 + { 554 + struct wil6210_mbox_ring_desc d_tail; 555 + struct wil6210_mbox_hdr hdr; 556 + struct wil6210_mbox_ring *r = &wil->mbox_ctl.rx; 557 + struct pending_wmi_event *evt; 558 + u8 *cmd; 559 + void __iomem *src; 560 + ulong flags; 561 + 562 + for (;;) { 563 + u16 len; 564 + 565 + r->head = ioread32(wil->csr + HOST_MBOX + 566 + offsetof(struct wil6210_mbox_ctl, rx.head)); 567 + if (r->tail == r->head) 568 + return; 569 + 570 + /* read cmd from tail */ 571 + wil_memcpy_fromio_32(&d_tail, wil->csr + HOSTADDR(r->tail), 572 + sizeof(struct wil6210_mbox_ring_desc)); 573 + if (d_tail.sync == 0) { 574 + wil_err(wil, "Mbox evt not owned by FW?\n"); 575 + return; 576 + } 577 + 578 + if (0 != wmi_read_hdr(wil, d_tail.addr, &hdr)) { 579 + wil_err(wil, "Mbox evt at 0x%08x?\n", 580 + le32_to_cpu(d_tail.addr)); 581 + return; 582 + } 583 + 584 + len = le16_to_cpu(hdr.len); 585 + src = wmi_buffer(wil, d_tail.addr) + 586 + sizeof(struct wil6210_mbox_hdr); 587 + evt = kmalloc(ALIGN(offsetof(struct pending_wmi_event, 588 + event.wmi) + len, 4), 589 + GFP_KERNEL); 590 + if (!evt) { 591 + wil_err(wil, "kmalloc for WMI event (%d) failed\n", 592 + len); 593 + return; 594 + } 595 + evt->event.hdr = hdr; 596 + cmd = (void *)&evt->event.wmi; 597 + wil_memcpy_fromio_32(cmd, src, len); 598 + /* mark entry as empty */ 599 + iowrite32(0, wil->csr + HOSTADDR(r->tail) + 600 + offsetof(struct wil6210_mbox_ring_desc, sync)); 601 + /* indicate */ 602 + wil_dbg_WMI(wil, "Mbox evt %04x %04x %04x %02x\n", 603 + le16_to_cpu(hdr.seq), len, le16_to_cpu(hdr.type), 604 + hdr.flags); 605 + if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) && 606 + (len >= sizeof(struct wil6210_mbox_hdr_wmi))) { 607 + wil_dbg_WMI(wil, "WMI event 0x%04x\n", 608 + evt->event.wmi.id); 609 + } 610 + wil_hex_dump_WMI("evt ", DUMP_PREFIX_OFFSET, 16, 1, 611 + &evt->event.hdr, sizeof(hdr) + len, true); 612 + 613 + /* advance tail */ 614 + r->tail = r->base + ((r->tail - r->base + 615 + sizeof(struct wil6210_mbox_ring_desc)) % r->size); 616 + iowrite32(r->tail, wil->csr + HOST_MBOX + 617 + offsetof(struct wil6210_mbox_ctl, rx.tail)); 618 + 619 + /* add to the pending list */ 620 + spin_lock_irqsave(&wil->wmi_ev_lock, flags); 621 + list_add_tail(&evt->list, &wil->pending_wmi_ev); 622 + spin_unlock_irqrestore(&wil->wmi_ev_lock, flags); 623 + { 624 + int q = queue_work(wil->wmi_wq, 625 + &wil->wmi_event_worker); 626 + wil_dbg_WMI(wil, "queue_work -> %d\n", q); 627 + } 628 + } 629 + } 630 + 631 + int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, 632 + u16 reply_id, void *reply, u8 reply_size, int to_msec) 633 + { 634 + int rc; 635 + int remain; 636 + 637 + mutex_lock(&wil->wmi_mutex); 638 + 639 + rc = __wmi_send(wil, cmdid, buf, len); 640 + if (rc) 641 + goto out; 642 + 643 + wil->reply_id = reply_id; 644 + wil->reply_buf = reply; 645 + wil->reply_size = reply_size; 646 + remain = wait_for_completion_timeout(&wil->wmi_ready, 647 + msecs_to_jiffies(to_msec)); 648 + if (0 == remain) { 649 + wil_err(wil, "wmi_call(0x%04x->0x%04x) timeout %d msec\n", 650 + cmdid, reply_id, to_msec); 651 + rc = -ETIME; 652 + } else { 653 + wil_dbg_WMI(wil, 654 + "wmi_call(0x%04x->0x%04x) completed in %d msec\n", 655 + cmdid, reply_id, 656 + to_msec - jiffies_to_msecs(remain)); 657 + } 658 + wil->reply_id = 0; 659 + wil->reply_buf = NULL; 660 + wil->reply_size = 0; 661 + out: 662 + mutex_unlock(&wil->wmi_mutex); 663 + 664 + return rc; 665 + } 666 + 667 + int wmi_echo(struct wil6210_priv *wil) 668 + { 669 + struct wmi_echo_cmd cmd = { 670 + .value = cpu_to_le32(0x12345678), 671 + }; 672 + 673 + return wmi_call(wil, WMI_ECHO_CMDID, &cmd, sizeof(cmd), 674 + WMI_ECHO_RSP_EVENTID, NULL, 0, 20); 675 + } 676 + 677 + int wmi_set_mac_address(struct wil6210_priv *wil, void *addr) 678 + { 679 + struct wmi_set_mac_address_cmd cmd; 680 + 681 + memcpy(cmd.mac, addr, ETH_ALEN); 682 + 683 + wil_dbg_WMI(wil, "Set MAC %pM\n", addr); 684 + 685 + return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd)); 686 + } 687 + 688 + int wmi_set_bcon(struct wil6210_priv *wil, int bi, u8 wmi_nettype) 689 + { 690 + struct wmi_bcon_ctrl_cmd cmd = { 691 + .bcon_interval = cpu_to_le16(bi), 692 + .network_type = wmi_nettype, 693 + .disable_sec_offload = 1, 694 + }; 695 + 696 + if (!wil->secure_pcp) 697 + cmd.disable_sec = 1; 698 + 699 + return wmi_send(wil, WMI_BCON_CTRL_CMDID, &cmd, sizeof(cmd)); 700 + } 701 + 702 + int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid) 703 + { 704 + struct wmi_set_ssid_cmd cmd = { 705 + .ssid_len = cpu_to_le32(ssid_len), 706 + }; 707 + 708 + if (ssid_len > sizeof(cmd.ssid)) 709 + return -EINVAL; 710 + 711 + memcpy(cmd.ssid, ssid, ssid_len); 712 + 713 + return wmi_send(wil, WMI_SET_SSID_CMDID, &cmd, sizeof(cmd)); 714 + } 715 + 716 + int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid) 717 + { 718 + int rc; 719 + struct { 720 + struct wil6210_mbox_hdr_wmi wmi; 721 + struct wmi_set_ssid_cmd cmd; 722 + } __packed reply; 723 + int len; /* reply.cmd.ssid_len in CPU order */ 724 + 725 + rc = wmi_call(wil, WMI_GET_SSID_CMDID, NULL, 0, WMI_GET_SSID_EVENTID, 726 + &reply, sizeof(reply), 20); 727 + if (rc) 728 + return rc; 729 + 730 + len = le32_to_cpu(reply.cmd.ssid_len); 731 + if (len > sizeof(reply.cmd.ssid)) 732 + return -EINVAL; 733 + 734 + *ssid_len = len; 735 + memcpy(ssid, reply.cmd.ssid, len); 736 + 737 + return 0; 738 + } 739 + 740 + int wmi_set_channel(struct wil6210_priv *wil, int channel) 741 + { 742 + struct wmi_set_pcp_channel_cmd cmd = { 743 + .channel = channel - 1, 744 + }; 745 + 746 + return wmi_send(wil, WMI_SET_PCP_CHANNEL_CMDID, &cmd, sizeof(cmd)); 747 + } 748 + 749 + int wmi_get_channel(struct wil6210_priv *wil, int *channel) 750 + { 751 + int rc; 752 + struct { 753 + struct wil6210_mbox_hdr_wmi wmi; 754 + struct wmi_set_pcp_channel_cmd cmd; 755 + } __packed reply; 756 + 757 + rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, NULL, 0, 758 + WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply), 20); 759 + if (rc) 760 + return rc; 761 + 762 + if (reply.cmd.channel > 3) 763 + return -EINVAL; 764 + 765 + *channel = reply.cmd.channel + 1; 766 + 767 + return 0; 768 + } 769 + 770 + int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb) 771 + { 772 + struct wmi_eapol_tx_cmd *cmd; 773 + struct ethhdr *eth; 774 + u16 eapol_len = skb->len - ETH_HLEN; 775 + void *eapol = skb->data + ETH_HLEN; 776 + uint i; 777 + int rc; 778 + 779 + skb_set_mac_header(skb, 0); 780 + eth = eth_hdr(skb); 781 + wil_dbg_WMI(wil, "EAPOL %d bytes to %pM\n", eapol_len, eth->h_dest); 782 + for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) { 783 + if (memcmp(wil->dst_addr[i], eth->h_dest, ETH_ALEN) == 0) 784 + goto found_dest; 785 + } 786 + 787 + return -EINVAL; 788 + 789 + found_dest: 790 + /* find out eapol data & len */ 791 + cmd = kzalloc(sizeof(*cmd) + eapol_len, GFP_KERNEL); 792 + if (!cmd) 793 + return -EINVAL; 794 + 795 + memcpy(cmd->dst_mac, eth->h_dest, ETH_ALEN); 796 + cmd->eapol_len = cpu_to_le16(eapol_len); 797 + memcpy(cmd->eapol, eapol, eapol_len); 798 + rc = wmi_send(wil, WMI_EAPOL_TX_CMDID, cmd, sizeof(*cmd) + eapol_len); 799 + kfree(cmd); 800 + 801 + return rc; 802 + } 803 + 804 + int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index, 805 + const void *mac_addr) 806 + { 807 + struct wmi_delete_cipher_key_cmd cmd = { 808 + .key_index = key_index, 809 + }; 810 + 811 + if (mac_addr) 812 + memcpy(cmd.mac, mac_addr, WMI_MAC_LEN); 813 + 814 + return wmi_send(wil, WMI_DELETE_CIPHER_KEY_CMDID, &cmd, sizeof(cmd)); 815 + } 816 + 817 + int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index, 818 + const void *mac_addr, int key_len, const void *key) 819 + { 820 + struct wmi_add_cipher_key_cmd cmd = { 821 + .key_index = key_index, 822 + .key_usage = WMI_KEY_USE_PAIRWISE, 823 + .key_len = key_len, 824 + }; 825 + 826 + if (!key || (key_len > sizeof(cmd.key))) 827 + return -EINVAL; 828 + 829 + memcpy(cmd.key, key, key_len); 830 + if (mac_addr) 831 + memcpy(cmd.mac, mac_addr, WMI_MAC_LEN); 832 + 833 + return wmi_send(wil, WMI_ADD_CIPHER_KEY_CMDID, &cmd, sizeof(cmd)); 834 + } 835 + 836 + int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie) 837 + { 838 + int rc; 839 + u16 len = sizeof(struct wmi_set_appie_cmd) + ie_len; 840 + struct wmi_set_appie_cmd *cmd = kzalloc(len, GFP_KERNEL); 841 + if (!cmd) { 842 + wil_err(wil, "kmalloc(%d) failed\n", len); 843 + return -ENOMEM; 844 + } 845 + 846 + cmd->mgmt_frm_type = type; 847 + /* BUG: FW API define ieLen as u8. Will fix FW */ 848 + cmd->ie_len = cpu_to_le16(ie_len); 849 + memcpy(cmd->ie_info, ie, ie_len); 850 + rc = wmi_send(wil, WMI_SET_APPIE_CMDID, &cmd, len); 851 + kfree(cmd); 852 + 853 + return rc; 854 + } 855 + 856 + void wmi_event_flush(struct wil6210_priv *wil) 857 + { 858 + struct pending_wmi_event *evt, *t; 859 + 860 + wil_dbg_WMI(wil, "%s()\n", __func__); 861 + 862 + list_for_each_entry_safe(evt, t, &wil->pending_wmi_ev, list) { 863 + list_del(&evt->list); 864 + kfree(evt); 865 + } 866 + } 867 + 868 + static bool wmi_evt_call_handler(struct wil6210_priv *wil, int id, 869 + void *d, int len) 870 + { 871 + uint i; 872 + 873 + for (i = 0; i < ARRAY_SIZE(wmi_evt_handlers); i++) { 874 + if (wmi_evt_handlers[i].eventid == id) { 875 + wmi_evt_handlers[i].handler(wil, id, d, len); 876 + return true; 877 + } 878 + } 879 + 880 + return false; 881 + } 882 + 883 + static void wmi_event_handle(struct wil6210_priv *wil, 884 + struct wil6210_mbox_hdr *hdr) 885 + { 886 + u16 len = le16_to_cpu(hdr->len); 887 + 888 + if ((hdr->type == WIL_MBOX_HDR_TYPE_WMI) && 889 + (len >= sizeof(struct wil6210_mbox_hdr_wmi))) { 890 + struct wil6210_mbox_hdr_wmi *wmi = (void *)(&hdr[1]); 891 + void *evt_data = (void *)(&wmi[1]); 892 + u16 id = le16_to_cpu(wmi->id); 893 + /* check if someone waits for this event */ 894 + if (wil->reply_id && wil->reply_id == id) { 895 + if (wil->reply_buf) { 896 + memcpy(wil->reply_buf, wmi, 897 + min(len, wil->reply_size)); 898 + } else { 899 + wmi_evt_call_handler(wil, id, evt_data, 900 + len - sizeof(*wmi)); 901 + } 902 + wil_dbg_WMI(wil, "Complete WMI 0x%04x\n", id); 903 + complete(&wil->wmi_ready); 904 + return; 905 + } 906 + /* unsolicited event */ 907 + /* search for handler */ 908 + if (!wmi_evt_call_handler(wil, id, evt_data, 909 + len - sizeof(*wmi))) { 910 + wil_err(wil, "Unhandled event 0x%04x\n", id); 911 + } 912 + } else { 913 + wil_err(wil, "Unknown event type\n"); 914 + print_hex_dump(KERN_ERR, "evt?? ", DUMP_PREFIX_OFFSET, 16, 1, 915 + hdr, sizeof(*hdr) + len, true); 916 + } 917 + } 918 + 919 + /* 920 + * Retrieve next WMI event from the pending list 921 + */ 922 + static struct list_head *next_wmi_ev(struct wil6210_priv *wil) 923 + { 924 + ulong flags; 925 + struct list_head *ret = NULL; 926 + 927 + spin_lock_irqsave(&wil->wmi_ev_lock, flags); 928 + 929 + if (!list_empty(&wil->pending_wmi_ev)) { 930 + ret = wil->pending_wmi_ev.next; 931 + list_del(ret); 932 + } 933 + 934 + spin_unlock_irqrestore(&wil->wmi_ev_lock, flags); 935 + 936 + return ret; 937 + } 938 + 939 + /* 940 + * Handler for the WMI events 941 + */ 942 + void wmi_event_worker(struct work_struct *work) 943 + { 944 + struct wil6210_priv *wil = container_of(work, struct wil6210_priv, 945 + wmi_event_worker); 946 + struct pending_wmi_event *evt; 947 + struct list_head *lh; 948 + 949 + while ((lh = next_wmi_ev(wil)) != NULL) { 950 + evt = list_entry(lh, struct pending_wmi_event, list); 951 + wmi_event_handle(wil, &evt->event.hdr); 952 + kfree(evt); 953 + } 954 + } 955 + 956 + void wmi_connect_worker(struct work_struct *work) 957 + { 958 + int rc; 959 + struct wil6210_priv *wil = container_of(work, struct wil6210_priv, 960 + wmi_connect_worker); 961 + 962 + if (wil->pending_connect_cid < 0) { 963 + wil_err(wil, "No connection pending\n"); 964 + return; 965 + } 966 + 967 + wil_dbg_WMI(wil, "Configure for connection CID %d\n", 968 + wil->pending_connect_cid); 969 + 970 + rc = wil_vring_init_tx(wil, 0, WIL6210_TX_RING_SIZE, 971 + wil->pending_connect_cid, 0); 972 + wil->pending_connect_cid = -1; 973 + if (rc == 0) 974 + wil_link_on(wil); 975 + }
+1116
drivers/net/wireless/ath/wil6210/wmi.h
··· 1 + /* 2 + * Copyright (c) 2012 Qualcomm Atheros, Inc. 3 + * Copyright (c) 2006-2012 Wilocity . 4 + * 5 + * Permission to use, copy, modify, and/or distribute this software for any 6 + * purpose with or without fee is hereby granted, provided that the above 7 + * copyright notice and this permission notice appear in all copies. 8 + * 9 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 + */ 17 + 18 + /* 19 + * This file contains the definitions of the WMI protocol specified in the 20 + * Wireless Module Interface (WMI) for the Wilocity 21 + * MARLON 60 Gigabit wireless solution. 22 + * It includes definitions of all the commands and events. 23 + * Commands are messages from the host to the WM. 24 + * Events are messages from the WM to the host. 25 + */ 26 + 27 + #ifndef __WILOCITY_WMI_H__ 28 + #define __WILOCITY_WMI_H__ 29 + 30 + /* General */ 31 + 32 + #define WMI_MAC_LEN (6) 33 + #define WMI_PROX_RANGE_NUM (3) 34 + 35 + /* List of Commands */ 36 + enum wmi_command_id { 37 + WMI_CONNECT_CMDID = 0x0001, 38 + WMI_DISCONNECT_CMDID = 0x0003, 39 + WMI_START_SCAN_CMDID = 0x0007, 40 + WMI_SET_BSS_FILTER_CMDID = 0x0009, 41 + WMI_SET_PROBED_SSID_CMDID = 0x000a, 42 + WMI_SET_LISTEN_INT_CMDID = 0x000b, 43 + WMI_BCON_CTRL_CMDID = 0x000f, 44 + WMI_ADD_CIPHER_KEY_CMDID = 0x0016, 45 + WMI_DELETE_CIPHER_KEY_CMDID = 0x0017, 46 + WMI_SET_APPIE_CMDID = 0x003f, 47 + WMI_GET_APPIE_CMDID = 0x0040, 48 + WMI_SET_WSC_STATUS_CMDID = 0x0041, 49 + WMI_PXMT_RANGE_CFG_CMDID = 0x0042, 50 + WMI_PXMT_SNR2_RANGE_CFG_CMDID = 0x0043, 51 + WMI_FAST_MEM_ACC_MODE_CMDID = 0x0300, 52 + WMI_MEM_READ_CMDID = 0x0800, 53 + WMI_MEM_WR_CMDID = 0x0801, 54 + WMI_ECHO_CMDID = 0x0803, 55 + WMI_DEEP_ECHO_CMDID = 0x0804, 56 + WMI_CONFIG_MAC_CMDID = 0x0805, 57 + WMI_CONFIG_PHY_DEBUG_CMDID = 0x0806, 58 + WMI_ADD_STATION_CMDID = 0x0807, 59 + WMI_ADD_DEBUG_TX_PCKT_CMDID = 0x0808, 60 + WMI_PHY_GET_STATISTICS_CMDID = 0x0809, 61 + WMI_FS_TUNE_CMDID = 0x080a, 62 + WMI_CORR_MEASURE_CMDID = 0x080b, 63 + WMI_TEMP_SENSE_CMDID = 0x080e, 64 + WMI_DC_CALIB_CMDID = 0x080f, 65 + WMI_SEND_TONE_CMDID = 0x0810, 66 + WMI_IQ_TX_CALIB_CMDID = 0x0811, 67 + WMI_IQ_RX_CALIB_CMDID = 0x0812, 68 + WMI_SET_UCODE_IDLE_CMDID = 0x0813, 69 + WMI_SET_WORK_MODE_CMDID = 0x0815, 70 + WMI_LO_LEAKAGE_CALIB_CMDID = 0x0816, 71 + WMI_MARLON_R_ACTIVATE_CMDID = 0x0817, 72 + WMI_MARLON_R_READ_CMDID = 0x0818, 73 + WMI_MARLON_R_WRITE_CMDID = 0x0819, 74 + WMI_MARLON_R_TXRX_SEL_CMDID = 0x081a, 75 + MAC_IO_STATIC_PARAMS_CMDID = 0x081b, 76 + MAC_IO_DYNAMIC_PARAMS_CMDID = 0x081c, 77 + WMI_SILENT_RSSI_CALIB_CMDID = 0x081d, 78 + WMI_CFG_RX_CHAIN_CMDID = 0x0820, 79 + WMI_VRING_CFG_CMDID = 0x0821, 80 + WMI_RX_ON_CMDID = 0x0822, 81 + WMI_VRING_BA_EN_CMDID = 0x0823, 82 + WMI_VRING_BA_DIS_CMDID = 0x0824, 83 + WMI_RCP_ADDBA_RESP_CMDID = 0x0825, 84 + WMI_RCP_DELBA_CMDID = 0x0826, 85 + WMI_SET_SSID_CMDID = 0x0827, 86 + WMI_GET_SSID_CMDID = 0x0828, 87 + WMI_SET_PCP_CHANNEL_CMDID = 0x0829, 88 + WMI_GET_PCP_CHANNEL_CMDID = 0x082a, 89 + WMI_SW_TX_REQ_CMDID = 0x082b, 90 + WMI_RX_OFF_CMDID = 0x082c, 91 + WMI_READ_MAC_RXQ_CMDID = 0x0830, 92 + WMI_READ_MAC_TXQ_CMDID = 0x0831, 93 + WMI_WRITE_MAC_RXQ_CMDID = 0x0832, 94 + WMI_WRITE_MAC_TXQ_CMDID = 0x0833, 95 + WMI_WRITE_MAC_XQ_FIELD_CMDID = 0x0834, 96 + WMI_MLME_PUSH_CMDID = 0x0835, 97 + WMI_BEAMFORMING_MGMT_CMDID = 0x0836, 98 + WMI_BF_TXSS_MGMT_CMDID = 0x0837, 99 + WMI_BF_SM_MGMT_CMDID = 0x0838, 100 + WMI_BF_RXSS_MGMT_CMDID = 0x0839, 101 + WMI_SET_SECTORS_CMDID = 0x0849, 102 + WMI_MAINTAIN_PAUSE_CMDID = 0x0850, 103 + WMI_MAINTAIN_RESUME_CMDID = 0x0851, 104 + WMI_RS_MGMT_CMDID = 0x0852, 105 + WMI_RF_MGMT_CMDID = 0x0853, 106 + /* Performance monitoring commands */ 107 + WMI_BF_CTRL_CMDID = 0x0862, 108 + WMI_NOTIFY_REQ_CMDID = 0x0863, 109 + WMI_GET_STATUS_CMDID = 0x0864, 110 + WMI_UNIT_TEST_CMDID = 0x0900, 111 + WMI_HICCUP_CMDID = 0x0901, 112 + WMI_FLASH_READ_CMDID = 0x0902, 113 + WMI_FLASH_WRITE_CMDID = 0x0903, 114 + WMI_SECURITY_UNIT_TEST_CMDID = 0x0904, 115 + 116 + WMI_SET_MAC_ADDRESS_CMDID = 0xf003, 117 + WMI_ABORT_SCAN_CMDID = 0xf007, 118 + WMI_SET_PMK_CMDID = 0xf028, 119 + 120 + WMI_SET_PROMISCUOUS_MODE_CMDID = 0xf041, 121 + WMI_GET_PMK_CMDID = 0xf048, 122 + WMI_SET_PASSPHRASE_CMDID = 0xf049, 123 + WMI_SEND_ASSOC_RES_CMDID = 0xf04a, 124 + WMI_SET_ASSOC_REQ_RELAY_CMDID = 0xf04b, 125 + WMI_EAPOL_TX_CMDID = 0xf04c, 126 + WMI_MAC_ADDR_REQ_CMDID = 0xf04d, 127 + WMI_FW_VER_CMDID = 0xf04e, 128 + }; 129 + 130 + /* 131 + * Commands data structures 132 + */ 133 + 134 + /* 135 + * Frame Types 136 + */ 137 + enum wmi_mgmt_frame_type { 138 + WMI_FRAME_BEACON = 0, 139 + WMI_FRAME_PROBE_REQ = 1, 140 + WMI_FRAME_PROBE_RESP = 2, 141 + WMI_FRAME_ASSOC_REQ = 3, 142 + WMI_FRAME_ASSOC_RESP = 4, 143 + WMI_NUM_MGMT_FRAME, 144 + }; 145 + 146 + /* 147 + * WMI_CONNECT_CMDID 148 + */ 149 + enum wmi_network_type { 150 + WMI_NETTYPE_INFRA = 0x01, 151 + WMI_NETTYPE_ADHOC = 0x02, 152 + WMI_NETTYPE_ADHOC_CREATOR = 0x04, 153 + WMI_NETTYPE_AP = 0x10, 154 + WMI_NETTYPE_P2P = 0x20, 155 + WMI_NETTYPE_WBE = 0x40, /* PCIE over 60g */ 156 + }; 157 + 158 + enum wmi_dot11_auth_mode { 159 + WMI_AUTH11_OPEN = 0x01, 160 + WMI_AUTH11_SHARED = 0x02, 161 + WMI_AUTH11_LEAP = 0x04, 162 + WMI_AUTH11_WSC = 0x08, 163 + }; 164 + 165 + enum wmi_auth_mode { 166 + WMI_AUTH_NONE = 0x01, 167 + WMI_AUTH_WPA = 0x02, 168 + WMI_AUTH_WPA2 = 0x04, 169 + WMI_AUTH_WPA_PSK = 0x08, 170 + WMI_AUTH_WPA2_PSK = 0x10, 171 + WMI_AUTH_WPA_CCKM = 0x20, 172 + WMI_AUTH_WPA2_CCKM = 0x40, 173 + }; 174 + 175 + enum wmi_crypto_type { 176 + WMI_CRYPT_NONE = 0x01, 177 + WMI_CRYPT_WEP = 0x02, 178 + WMI_CRYPT_TKIP = 0x04, 179 + WMI_CRYPT_AES = 0x08, 180 + WMI_CRYPT_AES_GCMP = 0x20, 181 + }; 182 + 183 + 184 + enum wmi_connect_ctrl_flag_bits { 185 + WMI_CONNECT_ASSOC_POLICY_USER = 0x0001, 186 + WMI_CONNECT_SEND_REASSOC = 0x0002, 187 + WMI_CONNECT_IGNORE_WPAx_GROUP_CIPHER = 0x0004, 188 + WMI_CONNECT_PROFILE_MATCH_DONE = 0x0008, 189 + WMI_CONNECT_IGNORE_AAC_BEACON = 0x0010, 190 + WMI_CONNECT_CSA_FOLLOW_BSS = 0x0020, 191 + WMI_CONNECT_DO_WPA_OFFLOAD = 0x0040, 192 + WMI_CONNECT_DO_NOT_DEAUTH = 0x0080, 193 + }; 194 + 195 + #define WMI_MAX_SSID_LEN (32) 196 + 197 + struct wmi_connect_cmd { 198 + u8 network_type; 199 + u8 dot11_auth_mode; 200 + u8 auth_mode; 201 + u8 pairwise_crypto_type; 202 + u8 pairwise_crypto_len; 203 + u8 group_crypto_type; 204 + u8 group_crypto_len; 205 + u8 ssid_len; 206 + u8 ssid[WMI_MAX_SSID_LEN]; 207 + u8 channel; 208 + u8 reserved0; 209 + u8 bssid[WMI_MAC_LEN]; 210 + __le32 ctrl_flags; 211 + u8 dst_mac[WMI_MAC_LEN]; 212 + u8 reserved1[2]; 213 + } __packed; 214 + 215 + 216 + /* 217 + * WMI_RECONNECT_CMDID 218 + */ 219 + struct wmi_reconnect_cmd { 220 + u8 channel; /* hint */ 221 + u8 reserved; 222 + u8 bssid[WMI_MAC_LEN]; /* mandatory if set */ 223 + } __packed; 224 + 225 + 226 + /* 227 + * WMI_SET_PMK_CMDID 228 + */ 229 + 230 + #define WMI_MIN_KEY_INDEX (0) 231 + #define WMI_MAX_KEY_INDEX (3) 232 + #define WMI_MAX_KEY_LEN (32) 233 + #define WMI_PASSPHRASE_LEN (64) 234 + #define WMI_PMK_LEN (32) 235 + 236 + struct wmi_set_pmk_cmd { 237 + u8 pmk[WMI_PMK_LEN]; 238 + } __packed; 239 + 240 + 241 + /* 242 + * WMI_SET_PASSPHRASE_CMDID 243 + */ 244 + struct wmi_set_passphrase_cmd { 245 + u8 ssid[WMI_MAX_SSID_LEN]; 246 + u8 passphrase[WMI_PASSPHRASE_LEN]; 247 + u8 ssid_len; 248 + u8 passphrase_len; 249 + } __packed; 250 + 251 + /* 252 + * WMI_ADD_CIPHER_KEY_CMDID 253 + */ 254 + enum wmi_key_usage { 255 + WMI_KEY_USE_PAIRWISE = 0, 256 + WMI_KEY_USE_GROUP = 1, 257 + WMI_KEY_USE_TX = 2, /* default Tx Key - Static WEP only */ 258 + }; 259 + 260 + struct wmi_add_cipher_key_cmd { 261 + u8 key_index; 262 + u8 key_type; 263 + u8 key_usage; /* enum wmi_key_usage */ 264 + u8 key_len; 265 + u8 key_rsc[8]; /* key replay sequence counter */ 266 + u8 key[WMI_MAX_KEY_LEN]; 267 + u8 key_op_ctrl; /* Additional Key Control information */ 268 + u8 mac[WMI_MAC_LEN]; 269 + } __packed; 270 + 271 + /* 272 + * WMI_DELETE_CIPHER_KEY_CMDID 273 + */ 274 + struct wmi_delete_cipher_key_cmd { 275 + u8 key_index; 276 + u8 mac[WMI_MAC_LEN]; 277 + } __packed; 278 + 279 + 280 + /* 281 + * WMI_START_SCAN_CMDID 282 + * 283 + * Start L1 scan operation 284 + * 285 + * Returned events: 286 + * - WMI_RX_MGMT_PACKET_EVENTID - for every probe resp. 287 + * - WMI_SCAN_COMPLETE_EVENTID 288 + */ 289 + enum wmi_scan_type { 290 + WMI_LONG_SCAN = 0, 291 + WMI_SHORT_SCAN = 1, 292 + }; 293 + 294 + struct wmi_start_scan_cmd { 295 + u8 reserved[8]; 296 + __le32 home_dwell_time; /* Max duration in the home channel(ms) */ 297 + __le32 force_scan_interval; /* Time interval between scans (ms)*/ 298 + u8 scan_type; /* wmi_scan_type */ 299 + u8 num_channels; /* how many channels follow */ 300 + struct { 301 + u8 channel; 302 + u8 reserved; 303 + } channel_list[0]; /* channels ID's */ 304 + /* 0 - 58320 MHz */ 305 + /* 1 - 60480 MHz */ 306 + /* 2 - 62640 MHz */ 307 + } __packed; 308 + 309 + /* 310 + * WMI_SET_PROBED_SSID_CMDID 311 + */ 312 + #define MAX_PROBED_SSID_INDEX (15) 313 + 314 + enum wmi_ssid_flag { 315 + WMI_SSID_FLAG_DISABLE = 0, /* disables entry */ 316 + WMI_SSID_FLAG_SPECIFIC = 1, /* probes specified ssid */ 317 + WMI_SSID_FLAG_ANY = 2, /* probes for any ssid */ 318 + }; 319 + 320 + struct wmi_probed_ssid_cmd { 321 + u8 entry_index; /* 0 to MAX_PROBED_SSID_INDEX */ 322 + u8 flag; /* enum wmi_ssid_flag */ 323 + u8 ssid_len; 324 + u8 ssid[WMI_MAX_SSID_LEN]; 325 + } __packed; 326 + 327 + /* 328 + * WMI_SET_APPIE_CMDID 329 + * Add Application specified IE to a management frame 330 + */ 331 + struct wmi_set_appie_cmd { 332 + u8 mgmt_frm_type; /* enum wmi_mgmt_frame_type */ 333 + u8 reserved; 334 + __le16 ie_len; /* Length of the IE to be added to MGMT frame */ 335 + u8 ie_info[0]; 336 + } __packed; 337 + 338 + #define WMI_MAX_IE_LEN (1024) 339 + 340 + struct wmi_pxmt_range_cfg_cmd { 341 + u8 dst_mac[WMI_MAC_LEN]; 342 + __le16 range; 343 + } __packed; 344 + 345 + struct wmi_pxmt_snr2_range_cfg_cmd { 346 + s8 snr2range_arr[WMI_PROX_RANGE_NUM-1]; 347 + } __packed; 348 + 349 + /* 350 + * WMI_RF_MGMT_CMDID 351 + */ 352 + enum wmi_rf_mgmt_type { 353 + WMI_RF_MGMT_W_DISABLE = 0, 354 + WMI_RF_MGMT_W_ENABLE = 1, 355 + WMI_RF_MGMT_GET_STATUS = 2, 356 + }; 357 + 358 + struct wmi_rf_mgmt_cmd { 359 + __le32 rf_mgmt_type; 360 + } __packed; 361 + 362 + /* 363 + * WMI_SET_SSID_CMDID 364 + */ 365 + struct wmi_set_ssid_cmd { 366 + __le32 ssid_len; 367 + u8 ssid[WMI_MAX_SSID_LEN]; 368 + } __packed; 369 + 370 + /* 371 + * WMI_SET_PCP_CHANNEL_CMDID 372 + */ 373 + struct wmi_set_pcp_channel_cmd { 374 + u8 channel; 375 + u8 reserved[3]; 376 + } __packed; 377 + 378 + /* 379 + * WMI_BCON_CTRL_CMDID 380 + */ 381 + struct wmi_bcon_ctrl_cmd { 382 + __le16 bcon_interval; 383 + __le16 frag_num; 384 + __le64 ss_mask; 385 + u8 network_type; 386 + u8 reserved; 387 + u8 disable_sec_offload; 388 + u8 disable_sec; 389 + } __packed; 390 + 391 + /* 392 + * WMI_SW_TX_REQ_CMDID 393 + */ 394 + struct wmi_sw_tx_req_cmd { 395 + u8 dst_mac[WMI_MAC_LEN]; 396 + __le16 len; 397 + u8 payload[0]; 398 + } __packed; 399 + 400 + /* 401 + * WMI_VRING_CFG_CMDID 402 + */ 403 + 404 + struct wmi_sw_ring_cfg { 405 + __le64 ring_mem_base; 406 + __le16 ring_size; 407 + __le16 max_mpdu_size; 408 + } __packed; 409 + 410 + struct wmi_vring_cfg_schd { 411 + __le16 priority; 412 + __le16 timeslot_us; 413 + } __packed; 414 + 415 + enum wmi_vring_cfg_encap_trans_type { 416 + WMI_VRING_ENC_TYPE_802_3 = 0, 417 + WMI_VRING_ENC_TYPE_NATIVE_WIFI = 1, 418 + }; 419 + 420 + enum wmi_vring_cfg_ds_cfg { 421 + WMI_VRING_DS_PBSS = 0, 422 + WMI_VRING_DS_STATION = 1, 423 + WMI_VRING_DS_AP = 2, 424 + WMI_VRING_DS_ADDR4 = 3, 425 + }; 426 + 427 + enum wmi_vring_cfg_nwifi_ds_trans_type { 428 + WMI_NWIFI_TX_TRANS_MODE_NO = 0, 429 + WMI_NWIFI_TX_TRANS_MODE_AP2PBSS = 1, 430 + WMI_NWIFI_TX_TRANS_MODE_STA2PBSS = 2, 431 + }; 432 + 433 + enum wmi_vring_cfg_schd_params_priority { 434 + WMI_SCH_PRIO_REGULAR = 0, 435 + WMI_SCH_PRIO_HIGH = 1, 436 + }; 437 + 438 + struct wmi_vring_cfg { 439 + struct wmi_sw_ring_cfg tx_sw_ring; 440 + u8 ringid; /* 0-23 vrings */ 441 + 442 + #define CIDXTID_CID_POS (0) 443 + #define CIDXTID_CID_LEN (4) 444 + #define CIDXTID_CID_MSK (0xF) 445 + #define CIDXTID_TID_POS (4) 446 + #define CIDXTID_TID_LEN (4) 447 + #define CIDXTID_TID_MSK (0xF0) 448 + u8 cidxtid; 449 + 450 + u8 encap_trans_type; 451 + u8 ds_cfg; /* 802.3 DS cfg */ 452 + u8 nwifi_ds_trans_type; 453 + 454 + #define VRING_CFG_MAC_CTRL_LIFETIME_EN_POS (0) 455 + #define VRING_CFG_MAC_CTRL_LIFETIME_EN_LEN (1) 456 + #define VRING_CFG_MAC_CTRL_LIFETIME_EN_MSK (0x1) 457 + #define VRING_CFG_MAC_CTRL_AGGR_EN_POS (1) 458 + #define VRING_CFG_MAC_CTRL_AGGR_EN_LEN (1) 459 + #define VRING_CFG_MAC_CTRL_AGGR_EN_MSK (0x2) 460 + u8 mac_ctrl; 461 + 462 + #define VRING_CFG_TO_RESOLUTION_VALUE_POS (0) 463 + #define VRING_CFG_TO_RESOLUTION_VALUE_LEN (6) 464 + #define VRING_CFG_TO_RESOLUTION_VALUE_MSK (0x3F) 465 + u8 to_resolution; 466 + u8 agg_max_wsize; 467 + struct wmi_vring_cfg_schd schd_params; 468 + } __packed; 469 + 470 + enum wmi_vring_cfg_cmd_action { 471 + WMI_VRING_CMD_ADD = 0, 472 + WMI_VRING_CMD_MODIFY = 1, 473 + WMI_VRING_CMD_DELETE = 2, 474 + }; 475 + 476 + struct wmi_vring_cfg_cmd { 477 + __le32 action; 478 + struct wmi_vring_cfg vring_cfg; 479 + } __packed; 480 + 481 + /* 482 + * WMI_VRING_BA_EN_CMDID 483 + */ 484 + struct wmi_vring_ba_en_cmd { 485 + u8 ringid; 486 + u8 agg_max_wsize; 487 + __le16 ba_timeout; 488 + } __packed; 489 + 490 + /* 491 + * WMI_VRING_BA_DIS_CMDID 492 + */ 493 + struct wmi_vring_ba_dis_cmd { 494 + u8 ringid; 495 + u8 reserved; 496 + __le16 reason; 497 + } __packed; 498 + 499 + /* 500 + * WMI_NOTIFY_REQ_CMDID 501 + */ 502 + struct wmi_notify_req_cmd { 503 + u8 cid; 504 + u8 reserved[3]; 505 + __le32 interval_usec; 506 + } __packed; 507 + 508 + /* 509 + * WMI_CFG_RX_CHAIN_CMDID 510 + */ 511 + enum wmi_sniffer_cfg_mode { 512 + WMI_SNIFFER_OFF = 0, 513 + WMI_SNIFFER_ON = 1, 514 + }; 515 + 516 + enum wmi_sniffer_cfg_phy_info_mode { 517 + WMI_SNIFFER_PHY_INFO_DISABLED = 0, 518 + WMI_SNIFFER_PHY_INFO_ENABLED = 1, 519 + }; 520 + 521 + enum wmi_sniffer_cfg_phy_support { 522 + WMI_SNIFFER_CP = 0, 523 + WMI_SNIFFER_DP = 1, 524 + WMI_SNIFFER_BOTH_PHYS = 2, 525 + }; 526 + 527 + struct wmi_sniffer_cfg { 528 + __le32 mode; /* enum wmi_sniffer_cfg_mode */ 529 + __le32 phy_info_mode; /* enum wmi_sniffer_cfg_phy_info_mode */ 530 + __le32 phy_support; /* enum wmi_sniffer_cfg_phy_support */ 531 + u8 channel; 532 + u8 reserved[3]; 533 + } __packed; 534 + 535 + enum wmi_cfg_rx_chain_cmd_action { 536 + WMI_RX_CHAIN_ADD = 0, 537 + WMI_RX_CHAIN_DEL = 1, 538 + }; 539 + 540 + enum wmi_cfg_rx_chain_cmd_decap_trans_type { 541 + WMI_DECAP_TYPE_802_3 = 0, 542 + WMI_DECAP_TYPE_NATIVE_WIFI = 1, 543 + }; 544 + 545 + enum wmi_cfg_rx_chain_cmd_nwifi_ds_trans_type { 546 + WMI_NWIFI_RX_TRANS_MODE_NO = 0, 547 + WMI_NWIFI_RX_TRANS_MODE_PBSS2AP = 1, 548 + WMI_NWIFI_RX_TRANS_MODE_PBSS2STA = 2, 549 + }; 550 + 551 + struct wmi_cfg_rx_chain_cmd { 552 + __le32 action; 553 + struct wmi_sw_ring_cfg rx_sw_ring; 554 + u8 mid; 555 + u8 decap_trans_type; 556 + 557 + #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_POS (0) 558 + #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_LEN (1) 559 + #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_MSK (0x1) 560 + u8 l2_802_3_offload_ctrl; 561 + 562 + #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_POS (0) 563 + #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_LEN (1) 564 + #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_MSK (0x1) 565 + #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_POS (1) 566 + #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_LEN (1) 567 + #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_MSK (0x2) 568 + u8 l2_nwifi_offload_ctrl; 569 + 570 + u8 vlan_id; 571 + u8 nwifi_ds_trans_type; 572 + 573 + #define L3_L4_CTRL_IPV4_CHECKSUM_EN_POS (0) 574 + #define L3_L4_CTRL_IPV4_CHECKSUM_EN_LEN (1) 575 + #define L3_L4_CTRL_IPV4_CHECKSUM_EN_MSK (0x1) 576 + #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS (1) 577 + #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_LEN (1) 578 + #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_MSK (0x2) 579 + u8 l3_l4_ctrl; 580 + 581 + #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_POS (0) 582 + #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_LEN (1) 583 + #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_MSK (0x1) 584 + #define RING_CTRL_OVERRIDE_WB_THRSH_POS (1) 585 + #define RING_CTRL_OVERRIDE_WB_THRSH_LEN (1) 586 + #define RING_CTRL_OVERRIDE_WB_THRSH_MSK (0x2) 587 + #define RING_CTRL_OVERRIDE_ITR_THRSH_POS (2) 588 + #define RING_CTRL_OVERRIDE_ITR_THRSH_LEN (1) 589 + #define RING_CTRL_OVERRIDE_ITR_THRSH_MSK (0x4) 590 + #define RING_CTRL_OVERRIDE_HOST_THRSH_POS (3) 591 + #define RING_CTRL_OVERRIDE_HOST_THRSH_LEN (1) 592 + #define RING_CTRL_OVERRIDE_HOST_THRSH_MSK (0x8) 593 + u8 ring_ctrl; 594 + 595 + __le16 prefetch_thrsh; 596 + __le16 wb_thrsh; 597 + __le32 itr_value; 598 + __le16 host_thrsh; 599 + u8 reserved[2]; 600 + struct wmi_sniffer_cfg sniffer_cfg; 601 + } __packed; 602 + 603 + /* 604 + * WMI_RCP_ADDBA_RESP_CMDID 605 + */ 606 + struct wmi_rcp_addba_resp_cmd { 607 + 608 + #define CIDXTID_CID_POS (0) 609 + #define CIDXTID_CID_LEN (4) 610 + #define CIDXTID_CID_MSK (0xF) 611 + #define CIDXTID_TID_POS (4) 612 + #define CIDXTID_TID_LEN (4) 613 + #define CIDXTID_TID_MSK (0xF0) 614 + u8 cidxtid; 615 + 616 + u8 dialog_token; 617 + __le16 status_code; 618 + __le16 ba_param_set; /* ieee80211_ba_parameterset field to send */ 619 + __le16 ba_timeout; 620 + } __packed; 621 + 622 + /* 623 + * WMI_RCP_DELBA_CMDID 624 + */ 625 + struct wmi_rcp_delba_cmd { 626 + 627 + #define CIDXTID_CID_POS (0) 628 + #define CIDXTID_CID_LEN (4) 629 + #define CIDXTID_CID_MSK (0xF) 630 + #define CIDXTID_TID_POS (4) 631 + #define CIDXTID_TID_LEN (4) 632 + #define CIDXTID_TID_MSK (0xF0) 633 + u8 cidxtid; 634 + 635 + u8 reserved; 636 + __le16 reason; 637 + } __packed; 638 + 639 + /* 640 + * WMI_RCP_ADDBA_REQ_CMDID 641 + */ 642 + struct wmi_rcp_addba_req_cmd { 643 + 644 + #define CIDXTID_CID_POS (0) 645 + #define CIDXTID_CID_LEN (4) 646 + #define CIDXTID_CID_MSK (0xF) 647 + #define CIDXTID_TID_POS (4) 648 + #define CIDXTID_TID_LEN (4) 649 + #define CIDXTID_TID_MSK (0xF0) 650 + u8 cidxtid; 651 + 652 + u8 dialog_token; 653 + /* ieee80211_ba_parameterset field as it received */ 654 + __le16 ba_param_set; 655 + __le16 ba_timeout; 656 + /* ieee80211_ba_seqstrl field as it received */ 657 + __le16 ba_seq_ctrl; 658 + } __packed; 659 + 660 + /* 661 + * WMI_SET_MAC_ADDRESS_CMDID 662 + */ 663 + struct wmi_set_mac_address_cmd { 664 + u8 mac[WMI_MAC_LEN]; 665 + u8 reserved[2]; 666 + } __packed; 667 + 668 + 669 + /* 670 + * WMI_EAPOL_TX_CMDID 671 + */ 672 + struct wmi_eapol_tx_cmd { 673 + u8 dst_mac[WMI_MAC_LEN]; 674 + __le16 eapol_len; 675 + u8 eapol[0]; 676 + } __packed; 677 + 678 + /* 679 + * WMI_ECHO_CMDID 680 + * 681 + * Check FW is alive 682 + * 683 + * WMI_DEEP_ECHO_CMDID 684 + * 685 + * Check FW and ucode are alive 686 + * 687 + * Returned event: WMI_ECHO_RSP_EVENTID 688 + * same event for both commands 689 + */ 690 + struct wmi_echo_cmd { 691 + __le32 value; 692 + } __packed; 693 + 694 + /* 695 + * WMI Events 696 + */ 697 + 698 + /* 699 + * List of Events (target to host) 700 + */ 701 + enum wmi_event_id { 702 + WMI_IMM_RSP_EVENTID = 0x0000, 703 + WMI_READY_EVENTID = 0x1001, 704 + WMI_CONNECT_EVENTID = 0x1002, 705 + WMI_DISCONNECT_EVENTID = 0x1003, 706 + WMI_SCAN_COMPLETE_EVENTID = 0x100a, 707 + WMI_REPORT_STATISTICS_EVENTID = 0x100b, 708 + WMI_RD_MEM_RSP_EVENTID = 0x1800, 709 + WMI_FW_READY_EVENTID = 0x1801, 710 + WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID = 0x0200, 711 + WMI_ECHO_RSP_EVENTID = 0x1803, 712 + WMI_CONFIG_MAC_DONE_EVENTID = 0x1805, 713 + WMI_CONFIG_PHY_DEBUG_DONE_EVENTID = 0x1806, 714 + WMI_ADD_STATION_DONE_EVENTID = 0x1807, 715 + WMI_ADD_DEBUG_TX_PCKT_DONE_EVENTID = 0x1808, 716 + WMI_PHY_GET_STATISTICS_EVENTID = 0x1809, 717 + WMI_FS_TUNE_DONE_EVENTID = 0x180a, 718 + WMI_CORR_MEASURE_DONE_EVENTID = 0x180b, 719 + WMI_TEMP_SENSE_DONE_EVENTID = 0x180e, 720 + WMI_DC_CALIB_DONE_EVENTID = 0x180f, 721 + WMI_IQ_TX_CALIB_DONE_EVENTID = 0x1811, 722 + WMI_IQ_RX_CALIB_DONE_EVENTID = 0x1812, 723 + WMI_SET_WORK_MODE_DONE_EVENTID = 0x1815, 724 + WMI_LO_LEAKAGE_CALIB_DONE_EVENTID = 0x1816, 725 + WMI_MARLON_R_ACTIVATE_DONE_EVENTID = 0x1817, 726 + WMI_MARLON_R_READ_DONE_EVENTID = 0x1818, 727 + WMI_MARLON_R_WRITE_DONE_EVENTID = 0x1819, 728 + WMI_MARLON_R_TXRX_SEL_DONE_EVENTID = 0x181a, 729 + WMI_SILENT_RSSI_CALIB_DONE_EVENTID = 0x181d, 730 + 731 + WMI_CFG_RX_CHAIN_DONE_EVENTID = 0x1820, 732 + WMI_VRING_CFG_DONE_EVENTID = 0x1821, 733 + WMI_RX_ON_DONE_EVENTID = 0x1822, 734 + WMI_BA_STATUS_EVENTID = 0x1823, 735 + WMI_RCP_ADDBA_REQ_EVENTID = 0x1824, 736 + WMI_ADDBA_RESP_SENT_EVENTID = 0x1825, 737 + WMI_DELBA_EVENTID = 0x1826, 738 + WMI_GET_SSID_EVENTID = 0x1828, 739 + WMI_GET_PCP_CHANNEL_EVENTID = 0x182a, 740 + WMI_SW_TX_COMPLETE_EVENTID = 0x182b, 741 + WMI_RX_OFF_DONE_EVENTID = 0x182c, 742 + 743 + WMI_READ_MAC_RXQ_EVENTID = 0x1830, 744 + WMI_READ_MAC_TXQ_EVENTID = 0x1831, 745 + WMI_WRITE_MAC_RXQ_EVENTID = 0x1832, 746 + WMI_WRITE_MAC_TXQ_EVENTID = 0x1833, 747 + WMI_WRITE_MAC_XQ_FIELD_EVENTID = 0x1834, 748 + 749 + WMI_BEAFORMING_MGMT_DONE_EVENTID = 0x1836, 750 + WMI_BF_TXSS_MGMT_DONE_EVENTID = 0x1837, 751 + WMI_BF_RXSS_MGMT_DONE_EVENTID = 0x1839, 752 + WMI_RS_MGMT_DONE_EVENTID = 0x1852, 753 + WMI_RF_MGMT_STATUS_EVENTID = 0x1853, 754 + WMI_BF_SM_MGMT_DONE_EVENTID = 0x1838, 755 + WMI_RX_MGMT_PACKET_EVENTID = 0x1840, 756 + 757 + /* Performance monitoring events */ 758 + WMI_DATA_PORT_OPEN_EVENTID = 0x1860, 759 + WMI_WBE_LINKDOWN_EVENTID = 0x1861, 760 + 761 + WMI_BF_CTRL_DONE_EVENTID = 0x1862, 762 + WMI_NOTIFY_REQ_DONE_EVENTID = 0x1863, 763 + WMI_GET_STATUS_DONE_EVENTID = 0x1864, 764 + 765 + WMI_UNIT_TEST_EVENTID = 0x1900, 766 + WMI_FLASH_READ_DONE_EVENTID = 0x1902, 767 + WMI_FLASH_WRITE_DONE_EVENTID = 0x1903, 768 + 769 + WMI_SET_CHANNEL_EVENTID = 0x9000, 770 + WMI_ASSOC_REQ_EVENTID = 0x9001, 771 + WMI_EAPOL_RX_EVENTID = 0x9002, 772 + WMI_MAC_ADDR_RESP_EVENTID = 0x9003, 773 + WMI_FW_VER_EVENTID = 0x9004, 774 + }; 775 + 776 + /* 777 + * Events data structures 778 + */ 779 + 780 + /* 781 + * WMI_RF_MGMT_STATUS_EVENTID 782 + */ 783 + enum wmi_rf_status { 784 + WMI_RF_ENABLED = 0, 785 + WMI_RF_DISABLED_HW = 1, 786 + WMI_RF_DISABLED_SW = 2, 787 + WMI_RF_DISABLED_HW_SW = 3, 788 + }; 789 + 790 + struct wmi_rf_mgmt_status_event { 791 + __le32 rf_status; 792 + } __packed; 793 + 794 + /* 795 + * WMI_GET_STATUS_DONE_EVENTID 796 + */ 797 + struct wmi_get_status_done_event { 798 + __le32 is_associated; 799 + u8 cid; 800 + u8 reserved0[3]; 801 + u8 bssid[WMI_MAC_LEN]; 802 + u8 channel; 803 + u8 reserved1; 804 + u8 network_type; 805 + u8 reserved2[3]; 806 + __le32 ssid_len; 807 + u8 ssid[WMI_MAX_SSID_LEN]; 808 + __le32 rf_status; 809 + __le32 is_secured; 810 + } __packed; 811 + 812 + /* 813 + * WMI_FW_VER_EVENTID 814 + */ 815 + struct wmi_fw_ver_event { 816 + u8 major; 817 + u8 minor; 818 + __le16 subminor; 819 + __le16 build; 820 + } __packed; 821 + 822 + /* 823 + * WMI_MAC_ADDR_RESP_EVENTID 824 + */ 825 + struct wmi_mac_addr_resp_event { 826 + u8 mac[WMI_MAC_LEN]; 827 + u8 auth_mode; 828 + u8 crypt_mode; 829 + __le32 offload_mode; 830 + } __packed; 831 + 832 + /* 833 + * WMI_EAPOL_RX_EVENTID 834 + */ 835 + struct wmi_eapol_rx_event { 836 + u8 src_mac[WMI_MAC_LEN]; 837 + __le16 eapol_len; 838 + u8 eapol[0]; 839 + } __packed; 840 + 841 + /* 842 + * WMI_READY_EVENTID 843 + */ 844 + enum wmi_phy_capability { 845 + WMI_11A_CAPABILITY = 1, 846 + WMI_11G_CAPABILITY = 2, 847 + WMI_11AG_CAPABILITY = 3, 848 + WMI_11NA_CAPABILITY = 4, 849 + WMI_11NG_CAPABILITY = 5, 850 + WMI_11NAG_CAPABILITY = 6, 851 + WMI_11AD_CAPABILITY = 7, 852 + WMI_11N_CAPABILITY_OFFSET = WMI_11NA_CAPABILITY - WMI_11A_CAPABILITY, 853 + }; 854 + 855 + struct wmi_ready_event { 856 + __le32 sw_version; 857 + __le32 abi_version; 858 + u8 mac[WMI_MAC_LEN]; 859 + u8 phy_capability; /* enum wmi_phy_capability */ 860 + u8 reserved; 861 + } __packed; 862 + 863 + /* 864 + * WMI_NOTIFY_REQ_DONE_EVENTID 865 + */ 866 + struct wmi_notify_req_done_event { 867 + __le32 status; 868 + __le64 tsf; 869 + __le32 snr_val; 870 + __le32 tx_tpt; 871 + __le32 tx_goodput; 872 + __le32 rx_goodput; 873 + __le16 bf_mcs; 874 + __le16 my_rx_sector; 875 + __le16 my_tx_sector; 876 + __le16 other_rx_sector; 877 + __le16 other_tx_sector; 878 + __le16 range; 879 + } __packed; 880 + 881 + /* 882 + * WMI_CONNECT_EVENTID 883 + */ 884 + struct wmi_connect_event { 885 + u8 channel; 886 + u8 reserved0; 887 + u8 bssid[WMI_MAC_LEN]; 888 + __le16 listen_interval; 889 + __le16 beacon_interval; 890 + u8 network_type; 891 + u8 reserved1[3]; 892 + u8 beacon_ie_len; 893 + u8 assoc_req_len; 894 + u8 assoc_resp_len; 895 + u8 cid; 896 + u8 reserved2[3]; 897 + u8 assoc_info[0]; 898 + } __packed; 899 + 900 + /* 901 + * WMI_DISCONNECT_EVENTID 902 + */ 903 + enum wmi_disconnect_reason { 904 + WMI_DIS_REASON_NO_NETWORK_AVAIL = 1, 905 + WMI_DIS_REASON_LOST_LINK = 2, /* bmiss */ 906 + WMI_DIS_REASON_DISCONNECT_CMD = 3, 907 + WMI_DIS_REASON_BSS_DISCONNECTED = 4, 908 + WMI_DIS_REASON_AUTH_FAILED = 5, 909 + WMI_DIS_REASON_ASSOC_FAILED = 6, 910 + WMI_DIS_REASON_NO_RESOURCES_AVAIL = 7, 911 + WMI_DIS_REASON_CSERV_DISCONNECT = 8, 912 + WMI_DIS_REASON_INVALID_PROFILE = 10, 913 + WMI_DIS_REASON_DOT11H_CHANNEL_SWITCH = 11, 914 + WMI_DIS_REASON_PROFILE_MISMATCH = 12, 915 + WMI_DIS_REASON_CONNECTION_EVICTED = 13, 916 + WMI_DIS_REASON_IBSS_MERGE = 14, 917 + }; 918 + 919 + struct wmi_disconnect_event { 920 + __le16 protocol_reason_status; /* reason code, see 802.11 spec. */ 921 + u8 bssid[WMI_MAC_LEN]; /* set if known */ 922 + u8 disconnect_reason; /* see wmi_disconnect_reason_e */ 923 + u8 assoc_resp_len; 924 + u8 assoc_info[0]; 925 + } __packed; 926 + 927 + /* 928 + * WMI_SCAN_COMPLETE_EVENTID 929 + */ 930 + struct wmi_scan_complete_event { 931 + __le32 status; 932 + } __packed; 933 + 934 + /* 935 + * WMI_BA_STATUS_EVENTID 936 + */ 937 + enum wmi_vring_ba_status { 938 + WMI_BA_AGREED = 0, 939 + WMI_BA_NON_AGREED = 1, 940 + }; 941 + 942 + struct wmi_vring_ba_status_event { 943 + __le16 status; 944 + u8 reserved[2]; 945 + u8 ringid; 946 + u8 agg_wsize; 947 + __le16 ba_timeout; 948 + } __packed; 949 + 950 + /* 951 + * WMI_DELBA_EVENTID 952 + */ 953 + struct wmi_delba_event { 954 + 955 + #define CIDXTID_CID_POS (0) 956 + #define CIDXTID_CID_LEN (4) 957 + #define CIDXTID_CID_MSK (0xF) 958 + #define CIDXTID_TID_POS (4) 959 + #define CIDXTID_TID_LEN (4) 960 + #define CIDXTID_TID_MSK (0xF0) 961 + u8 cidxtid; 962 + 963 + u8 from_initiator; 964 + __le16 reason; 965 + } __packed; 966 + 967 + /* 968 + * WMI_VRING_CFG_DONE_EVENTID 969 + */ 970 + enum wmi_vring_cfg_done_event_status { 971 + WMI_VRING_CFG_SUCCESS = 0, 972 + WMI_VRING_CFG_FAILURE = 1, 973 + }; 974 + 975 + struct wmi_vring_cfg_done_event { 976 + u8 ringid; 977 + u8 status; 978 + u8 reserved[2]; 979 + __le32 tx_vring_tail_ptr; 980 + } __packed; 981 + 982 + /* 983 + * WMI_ADDBA_RESP_SENT_EVENTID 984 + */ 985 + enum wmi_rcp_addba_resp_sent_event_status { 986 + WMI_ADDBA_SUCCESS = 0, 987 + WMI_ADDBA_FAIL = 1, 988 + }; 989 + 990 + struct wmi_rcp_addba_resp_sent_event { 991 + 992 + #define CIDXTID_CID_POS (0) 993 + #define CIDXTID_CID_LEN (4) 994 + #define CIDXTID_CID_MSK (0xF) 995 + #define CIDXTID_TID_POS (4) 996 + #define CIDXTID_TID_LEN (4) 997 + #define CIDXTID_TID_MSK (0xF0) 998 + u8 cidxtid; 999 + 1000 + u8 reserved; 1001 + __le16 status; 1002 + } __packed; 1003 + 1004 + /* 1005 + * WMI_RCP_ADDBA_REQ_EVENTID 1006 + */ 1007 + struct wmi_rcp_addba_req_event { 1008 + 1009 + #define CIDXTID_CID_POS (0) 1010 + #define CIDXTID_CID_LEN (4) 1011 + #define CIDXTID_CID_MSK (0xF) 1012 + #define CIDXTID_TID_POS (4) 1013 + #define CIDXTID_TID_LEN (4) 1014 + #define CIDXTID_TID_MSK (0xF0) 1015 + u8 cidxtid; 1016 + 1017 + u8 dialog_token; 1018 + __le16 ba_param_set; /* ieee80211_ba_parameterset as it received */ 1019 + __le16 ba_timeout; 1020 + __le16 ba_seq_ctrl; /* ieee80211_ba_seqstrl field as it received */ 1021 + } __packed; 1022 + 1023 + /* 1024 + * WMI_CFG_RX_CHAIN_DONE_EVENTID 1025 + */ 1026 + enum wmi_cfg_rx_chain_done_event_status { 1027 + WMI_CFG_RX_CHAIN_SUCCESS = 1, 1028 + }; 1029 + 1030 + struct wmi_cfg_rx_chain_done_event { 1031 + __le32 rx_ring_tail_ptr; /* Rx V-Ring Tail pointer */ 1032 + __le32 status; 1033 + } __packed; 1034 + 1035 + /* 1036 + * WMI_WBE_LINKDOWN_EVENTID 1037 + */ 1038 + enum wmi_wbe_link_down_event_reason { 1039 + WMI_WBE_REASON_USER_REQUEST = 0, 1040 + WMI_WBE_REASON_RX_DISASSOC = 1, 1041 + WMI_WBE_REASON_BAD_PHY_LINK = 2, 1042 + }; 1043 + 1044 + struct wmi_wbe_link_down_event { 1045 + u8 cid; 1046 + u8 reserved[3]; 1047 + __le32 reason; 1048 + } __packed; 1049 + 1050 + /* 1051 + * WMI_DATA_PORT_OPEN_EVENTID 1052 + */ 1053 + struct wmi_data_port_open_event { 1054 + u8 cid; 1055 + u8 reserved[3]; 1056 + } __packed; 1057 + 1058 + /* 1059 + * WMI_GET_PCP_CHANNEL_EVENTID 1060 + */ 1061 + struct wmi_get_pcp_channel_event { 1062 + u8 channel; 1063 + u8 reserved[3]; 1064 + } __packed; 1065 + 1066 + /* 1067 + * WMI_SW_TX_COMPLETE_EVENTID 1068 + */ 1069 + enum wmi_sw_tx_status { 1070 + WMI_TX_SW_STATUS_SUCCESS = 0, 1071 + WMI_TX_SW_STATUS_FAILED_NO_RESOURCES = 1, 1072 + WMI_TX_SW_STATUS_FAILED_TX = 2, 1073 + }; 1074 + 1075 + struct wmi_sw_tx_complete_event { 1076 + u8 status; /* enum wmi_sw_tx_status */ 1077 + u8 reserved[3]; 1078 + } __packed; 1079 + 1080 + /* 1081 + * WMI_GET_SSID_EVENTID 1082 + */ 1083 + struct wmi_get_ssid_event { 1084 + __le32 ssid_len; 1085 + u8 ssid[WMI_MAX_SSID_LEN]; 1086 + } __packed; 1087 + 1088 + /* 1089 + * WMI_RX_MGMT_PACKET_EVENTID 1090 + */ 1091 + struct wmi_rx_mgmt_info { 1092 + u8 mcs; 1093 + s8 snr; 1094 + __le16 range; 1095 + __le16 stype; 1096 + __le16 status; 1097 + __le32 len; 1098 + u8 qid; 1099 + u8 mid; 1100 + u8 cid; 1101 + u8 channel; /* From Radio MNGR */ 1102 + } __packed; 1103 + 1104 + struct wmi_rx_mgmt_packet_event { 1105 + struct wmi_rx_mgmt_info info; 1106 + u8 payload[0]; 1107 + } __packed; 1108 + 1109 + /* 1110 + * WMI_ECHO_RSP_EVENTID 1111 + */ 1112 + struct wmi_echo_event { 1113 + __le32 echoed_value; 1114 + } __packed; 1115 + 1116 + #endif /* __WILOCITY_WMI_H__ */
+5
drivers/net/wireless/b43/b43.h
··· 7 7 #include <linux/hw_random.h> 8 8 #include <linux/bcma/bcma.h> 9 9 #include <linux/ssb/ssb.h> 10 + #include <linux/completion.h> 10 11 #include <net/mac80211.h> 11 12 12 13 #include "debugfs.h" ··· 723 722 struct b43_request_fw_context { 724 723 /* The device we are requesting the fw for. */ 725 724 struct b43_wldev *dev; 725 + /* a completion event structure needed if this call is asynchronous */ 726 + struct completion fw_load_complete; 727 + /* a pointer to the firmware object */ 728 + const struct firmware *blob; 726 729 /* The type of firmware to request. */ 727 730 enum b43_firmware_file_type req_type; 728 731 /* Error messages for each firmware type. */
+41 -13
drivers/net/wireless/b43/main.c
··· 2088 2088 b43warn(wl, text); 2089 2089 } 2090 2090 2091 + static void b43_fw_cb(const struct firmware *firmware, void *context) 2092 + { 2093 + struct b43_request_fw_context *ctx = context; 2094 + 2095 + ctx->blob = firmware; 2096 + complete(&ctx->fw_load_complete); 2097 + } 2098 + 2091 2099 int b43_do_request_fw(struct b43_request_fw_context *ctx, 2092 2100 const char *name, 2093 - struct b43_firmware_file *fw) 2101 + struct b43_firmware_file *fw, bool async) 2094 2102 { 2095 - const struct firmware *blob; 2096 2103 struct b43_fw_header *hdr; 2097 2104 u32 size; 2098 2105 int err; ··· 2138 2131 B43_WARN_ON(1); 2139 2132 return -ENOSYS; 2140 2133 } 2141 - err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev); 2134 + if (async) { 2135 + /* do this part asynchronously */ 2136 + init_completion(&ctx->fw_load_complete); 2137 + err = request_firmware_nowait(THIS_MODULE, 1, ctx->fwname, 2138 + ctx->dev->dev->dev, GFP_KERNEL, 2139 + ctx, b43_fw_cb); 2140 + if (err < 0) { 2141 + pr_err("Unable to load firmware\n"); 2142 + return err; 2143 + } 2144 + /* stall here until fw ready */ 2145 + wait_for_completion(&ctx->fw_load_complete); 2146 + if (ctx->blob) 2147 + goto fw_ready; 2148 + /* On some ARM systems, the async request will fail, but the next sync 2149 + * request works. For this reason, we dall through here 2150 + */ 2151 + } 2152 + err = request_firmware(&ctx->blob, ctx->fwname, 2153 + ctx->dev->dev->dev); 2142 2154 if (err == -ENOENT) { 2143 2155 snprintf(ctx->errors[ctx->req_type], 2144 2156 sizeof(ctx->errors[ctx->req_type]), 2145 - "Firmware file \"%s\" not found\n", ctx->fwname); 2157 + "Firmware file \"%s\" not found\n", 2158 + ctx->fwname); 2146 2159 return err; 2147 2160 } else if (err) { 2148 2161 snprintf(ctx->errors[ctx->req_type], ··· 2171 2144 ctx->fwname, err); 2172 2145 return err; 2173 2146 } 2174 - if (blob->size < sizeof(struct b43_fw_header)) 2147 + fw_ready: 2148 + if (ctx->blob->size < sizeof(struct b43_fw_header)) 2175 2149 goto err_format; 2176 - hdr = (struct b43_fw_header *)(blob->data); 2150 + hdr = (struct b43_fw_header *)(ctx->blob->data); 2177 2151 switch (hdr->type) { 2178 2152 case B43_FW_TYPE_UCODE: 2179 2153 case B43_FW_TYPE_PCM: 2180 2154 size = be32_to_cpu(hdr->size); 2181 - if (size != blob->size - sizeof(struct b43_fw_header)) 2155 + if (size != ctx->blob->size - sizeof(struct b43_fw_header)) 2182 2156 goto err_format; 2183 2157 /* fallthrough */ 2184 2158 case B43_FW_TYPE_IV: ··· 2190 2162 goto err_format; 2191 2163 } 2192 2164 2193 - fw->data = blob; 2165 + fw->data = ctx->blob; 2194 2166 fw->filename = name; 2195 2167 fw->type = ctx->req_type; 2196 2168 ··· 2200 2172 snprintf(ctx->errors[ctx->req_type], 2201 2173 sizeof(ctx->errors[ctx->req_type]), 2202 2174 "Firmware file \"%s\" format error.\n", ctx->fwname); 2203 - release_firmware(blob); 2175 + release_firmware(ctx->blob); 2204 2176 2205 2177 return -EPROTO; 2206 2178 } ··· 2251 2223 goto err_no_ucode; 2252 2224 } 2253 2225 } 2254 - err = b43_do_request_fw(ctx, filename, &fw->ucode); 2226 + err = b43_do_request_fw(ctx, filename, &fw->ucode, true); 2255 2227 if (err) 2256 2228 goto err_load; 2257 2229 ··· 2263 2235 else 2264 2236 goto err_no_pcm; 2265 2237 fw->pcm_request_failed = false; 2266 - err = b43_do_request_fw(ctx, filename, &fw->pcm); 2238 + err = b43_do_request_fw(ctx, filename, &fw->pcm, false); 2267 2239 if (err == -ENOENT) { 2268 2240 /* We did not find a PCM file? Not fatal, but 2269 2241 * core rev <= 10 must do without hwcrypto then. */ ··· 2324 2296 default: 2325 2297 goto err_no_initvals; 2326 2298 } 2327 - err = b43_do_request_fw(ctx, filename, &fw->initvals); 2299 + err = b43_do_request_fw(ctx, filename, &fw->initvals, false); 2328 2300 if (err) 2329 2301 goto err_load; 2330 2302 ··· 2383 2355 default: 2384 2356 goto err_no_initvals; 2385 2357 } 2386 - err = b43_do_request_fw(ctx, filename, &fw->initvals_band); 2358 + err = b43_do_request_fw(ctx, filename, &fw->initvals_band, false); 2387 2359 if (err) 2388 2360 goto err_load; 2389 2361
+2 -3
drivers/net/wireless/b43/main.h
··· 137 137 138 138 139 139 struct b43_request_fw_context; 140 - int b43_do_request_fw(struct b43_request_fw_context *ctx, 141 - const char *name, 142 - struct b43_firmware_file *fw); 140 + int b43_do_request_fw(struct b43_request_fw_context *ctx, const char *name, 141 + struct b43_firmware_file *fw, bool async); 143 142 void b43_do_release_fw(struct b43_firmware_file *fw); 144 143 145 144 #endif /* B43_MAIN_H_ */
+3 -2
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
··· 3028 3028 3029 3029 len = wpa_ie->len + TLV_HDR_LEN; 3030 3030 data = (u8 *)wpa_ie; 3031 - offset = 0; 3031 + offset = TLV_HDR_LEN; 3032 3032 if (!is_rsn_ie) 3033 3033 offset += VS_IE_FIXED_HDR_LEN; 3034 - offset += WPA_IE_VERSION_LEN; 3034 + else 3035 + offset += WPA_IE_VERSION_LEN; 3035 3036 3036 3037 /* check for multicast cipher suite */ 3037 3038 if (offset + WPA_IE_MIN_OUI_LEN > len) {
+1
drivers/net/wireless/brcm80211/brcmsmac/debug.h
··· 1 1 /* 2 2 * Copyright (c) 2012 Broadcom Corporation 3 + * Copyright (c) 2012 Canonical Ltd. 3 4 * 4 5 * Permission to use, copy, modify, and/or distribute this software for any 5 6 * purpose with or without fee is hereby granted, provided that the above
+2 -2
drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
··· 1343 1343 1344 1344 wlc_lcnphy_rx_gain_override_enable(pi, true); 1345 1345 wlc_lcnphy_start_tx_tone(pi, 2000, (40 >> 1), 0); 1346 - usleep_range(500, 500); 1346 + udelay(500); 1347 1347 write_radio_reg(pi, RADIO_2064_REG112, 0); 1348 1348 if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_l)) 1349 1349 return false; 1350 1350 1351 1351 wlc_lcnphy_start_tx_tone(pi, 2000, 40, 0); 1352 - usleep_range(500, 500); 1352 + udelay(500); 1353 1353 write_radio_reg(pi, RADIO_2064_REG112, 0); 1354 1354 if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_h)) 1355 1355 return false;
+1 -1
drivers/net/wireless/iwlegacy/3945-mac.c
··· 3273 3273 3274 3274 if (count) { 3275 3275 char *p = buffer; 3276 - strncpy(buffer, buf, min(sizeof(buffer), count)); 3276 + strlcpy(buffer, buf, sizeof(buffer)); 3277 3277 channel = simple_strtoul(p, NULL, 0); 3278 3278 if (channel) 3279 3279 params.channel = channel;
+14 -21
drivers/net/wireless/iwlegacy/common.c
··· 3958 3958 3959 3959 memset(&il->staging, 0, sizeof(il->staging)); 3960 3960 3961 - if (!il->vif) { 3961 + switch (il->iw_mode) { 3962 + case NL80211_IFTYPE_UNSPECIFIED: 3962 3963 il->staging.dev_type = RXON_DEV_TYPE_ESS; 3963 - } else if (il->vif->type == NL80211_IFTYPE_STATION) { 3964 + break; 3965 + case NL80211_IFTYPE_STATION: 3964 3966 il->staging.dev_type = RXON_DEV_TYPE_ESS; 3965 3967 il->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; 3966 - } else if (il->vif->type == NL80211_IFTYPE_ADHOC) { 3968 + break; 3969 + case NL80211_IFTYPE_ADHOC: 3967 3970 il->staging.dev_type = RXON_DEV_TYPE_IBSS; 3968 3971 il->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; 3969 3972 il->staging.filter_flags = 3970 3973 RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK; 3971 - } else { 3974 + break; 3975 + default: 3972 3976 IL_ERR("Unsupported interface type %d\n", il->vif->type); 3973 3977 return; 3974 3978 } ··· 4554 4550 EXPORT_SYMBOL(il_mac_add_interface); 4555 4551 4556 4552 static void 4557 - il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, 4558 - bool mode_change) 4553 + il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif) 4559 4554 { 4560 4555 lockdep_assert_held(&il->mutex); 4561 4556 ··· 4563 4560 il_force_scan_end(il); 4564 4561 } 4565 4562 4566 - if (!mode_change) 4567 - il_set_mode(il); 4568 - 4563 + il_set_mode(il); 4569 4564 } 4570 4565 4571 4566 void ··· 4576 4575 4577 4576 WARN_ON(il->vif != vif); 4578 4577 il->vif = NULL; 4579 - 4580 - il_teardown_interface(il, vif, false); 4578 + il->iw_mode = NL80211_IFTYPE_UNSPECIFIED; 4579 + il_teardown_interface(il, vif); 4581 4580 memset(il->bssid, 0, ETH_ALEN); 4582 4581 4583 4582 D_MAC80211("leave\n"); ··· 4686 4685 } 4687 4686 4688 4687 /* success */ 4689 - il_teardown_interface(il, vif, true); 4690 4688 vif->type = newtype; 4691 4689 vif->p2p = false; 4692 - err = il_set_mode(il); 4693 - WARN_ON(err); 4694 - /* 4695 - * We've switched internally, but submitting to the 4696 - * device may have failed for some reason. Mask this 4697 - * error, because otherwise mac80211 will not switch 4698 - * (and set the interface type back) and we'll be 4699 - * out of sync with it. 4700 - */ 4690 + il->iw_mode = newtype; 4691 + il_teardown_interface(il, vif); 4701 4692 err = 0; 4702 4693 4703 4694 out:
+19 -7
drivers/net/wireless/iwlwifi/dvm/tx.c
··· 1071 1071 { 1072 1072 u16 status = le16_to_cpu(tx_resp->status.status); 1073 1073 1074 + info->flags &= ~IEEE80211_TX_CTL_AMPDU; 1075 + 1074 1076 info->status.rates[0].count = tx_resp->failure_frame + 1; 1075 1077 info->flags |= iwl_tx_status_to_mac80211(status); 1076 1078 iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags), ··· 1145 1143 next_reclaimed = ssn; 1146 1144 } 1147 1145 1148 - if (tid != IWL_TID_NON_QOS) { 1149 - priv->tid_data[sta_id][tid].next_reclaimed = 1150 - next_reclaimed; 1151 - IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n", 1152 - next_reclaimed); 1153 - } 1154 - 1155 1146 iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs); 1156 1147 1157 1148 iwlagn_check_ratid_empty(priv, sta_id, tid); ··· 1195 1200 if (!is_agg) 1196 1201 iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); 1197 1202 1203 + /* 1204 + * W/A for FW bug - the seq_ctl isn't updated when the 1205 + * queues are flushed. Fetch it from the packet itself 1206 + */ 1207 + if (!is_agg && status == TX_STATUS_FAIL_FIFO_FLUSHED) { 1208 + next_reclaimed = le16_to_cpu(hdr->seq_ctrl); 1209 + next_reclaimed = 1210 + SEQ_TO_SN(next_reclaimed + 0x10); 1211 + } 1212 + 1198 1213 is_offchannel_skb = 1199 1214 (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN); 1200 1215 freed++; 1216 + } 1217 + 1218 + if (tid != IWL_TID_NON_QOS) { 1219 + priv->tid_data[sta_id][tid].next_reclaimed = 1220 + next_reclaimed; 1221 + IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n", 1222 + next_reclaimed); 1201 1223 } 1202 1224 1203 1225 if (!is_agg && freed != 1)
+1
drivers/net/wireless/iwlwifi/pcie/rx.c
··· 1172 1172 else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && 1173 1173 !trans_pcie->inta) 1174 1174 iwl_enable_interrupts(trans); 1175 + return IRQ_HANDLED; 1175 1176 1176 1177 none: 1177 1178 /* re-enable interrupts here since we don't have anything to service. */
+3 -16
drivers/net/wireless/mwifiex/cfg80211.c
··· 1458 1458 struct cfg80211_ssid req_ssid; 1459 1459 int ret, auth_type = 0; 1460 1460 struct cfg80211_bss *bss = NULL; 1461 - u8 is_scanning_required = 0, config_bands = 0; 1461 + u8 is_scanning_required = 0; 1462 1462 1463 1463 memset(&req_ssid, 0, sizeof(struct cfg80211_ssid)); 1464 1464 ··· 1476 1476 1477 1477 /* disconnect before try to associate */ 1478 1478 mwifiex_deauthenticate(priv, NULL); 1479 - 1480 - if (channel) { 1481 - if (mode == NL80211_IFTYPE_STATION) { 1482 - if (channel->band == IEEE80211_BAND_2GHZ) 1483 - config_bands = BAND_B | BAND_G | BAND_GN; 1484 - else 1485 - config_bands = BAND_A | BAND_AN; 1486 - 1487 - if (!((config_bands | priv->adapter->fw_bands) & 1488 - ~priv->adapter->fw_bands)) 1489 - priv->adapter->config_bands = config_bands; 1490 - } 1491 - } 1492 1479 1493 1480 /* As this is new association, clear locally stored 1494 1481 * keys and security related flags */ ··· 1693 1706 1694 1707 if (cfg80211_get_chandef_type(&params->chandef) != 1695 1708 NL80211_CHAN_NO_HT) 1696 - config_bands |= BAND_GN; 1709 + config_bands |= BAND_G | BAND_GN; 1697 1710 } else { 1698 - if (cfg80211_get_chandef_type(&params->chandef) != 1711 + if (cfg80211_get_chandef_type(&params->chandef) == 1699 1712 NL80211_CHAN_NO_HT) 1700 1713 config_bands = BAND_A; 1701 1714 else
+1 -1
drivers/net/wireless/mwifiex/pcie.c
··· 164 164 165 165 if (pdev) { 166 166 card = (struct pcie_service_card *) pci_get_drvdata(pdev); 167 - if (!card || card->adapter) { 167 + if (!card || !card->adapter) { 168 168 pr_err("Card or adapter structure is not valid\n"); 169 169 return 0; 170 170 }
+24 -11
drivers/net/wireless/mwifiex/sta_ioctl.c
··· 56 56 */ 57 57 int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) 58 58 { 59 - bool cancel_flag = false; 60 59 int status; 61 60 struct cmd_ctrl_node *cmd_queued; 62 61 ··· 69 70 atomic_inc(&adapter->cmd_pending); 70 71 71 72 /* Wait for completion */ 72 - wait_event_interruptible(adapter->cmd_wait_q.wait, 73 - *(cmd_queued->condition)); 74 - if (!*(cmd_queued->condition)) 75 - cancel_flag = true; 76 - 77 - if (cancel_flag) { 78 - mwifiex_cancel_pending_ioctl(adapter); 79 - dev_dbg(adapter->dev, "cmd cancel\n"); 73 + status = wait_event_interruptible(adapter->cmd_wait_q.wait, 74 + *(cmd_queued->condition)); 75 + if (status) { 76 + dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status); 77 + return status; 80 78 } 81 79 82 80 status = adapter->cmd_wait_q.status; ··· 282 286 ret = mwifiex_deauthenticate(priv, NULL); 283 287 if (ret) 284 288 goto done; 289 + 290 + if (bss_desc) { 291 + u8 config_bands = 0; 292 + 293 + if (mwifiex_band_to_radio_type((u8) bss_desc->bss_band) 294 + == HostCmd_SCAN_RADIO_TYPE_BG) 295 + config_bands = BAND_B | BAND_G | BAND_GN; 296 + else 297 + config_bands = BAND_A | BAND_AN; 298 + 299 + if (!((config_bands | adapter->fw_bands) & 300 + ~adapter->fw_bands)) 301 + adapter->config_bands = config_bands; 302 + } 285 303 286 304 ret = mwifiex_check_network_compatibility(priv, bss_desc); 287 305 if (ret) ··· 506 496 return false; 507 497 } 508 498 509 - wait_event_interruptible(adapter->hs_activate_wait_q, 510 - adapter->hs_activate_wait_q_woken); 499 + if (wait_event_interruptible(adapter->hs_activate_wait_q, 500 + adapter->hs_activate_wait_q_woken)) { 501 + dev_err(adapter->dev, "hs_activate_wait_q terminated\n"); 502 + return false; 503 + } 511 504 512 505 return true; 513 506 }
+3 -1
drivers/net/wireless/mwl8k.c
··· 4333 4333 p->amsdu_enabled = 0; 4334 4334 4335 4335 rc = mwl8k_post_cmd(hw, &cmd->header); 4336 + if (!rc) 4337 + rc = p->station_id; 4336 4338 kfree(cmd); 4337 4339 4338 - return rc ? rc : p->station_id; 4340 + return rc; 4339 4341 } 4340 4342 4341 4343 static int mwl8k_cmd_update_stadb_del(struct ieee80211_hw *hw,
+4
drivers/net/wireless/p54/p54usb.c
··· 47 47 {USB_DEVICE(0x0411, 0x0050)}, /* Buffalo WLI2-USB2-G54 */ 48 48 {USB_DEVICE(0x045e, 0x00c2)}, /* Microsoft MN-710 */ 49 49 {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */ 50 + {USB_DEVICE(0x0675, 0x0530)}, /* DrayTek Vigor 530 */ 50 51 {USB_DEVICE(0x06b9, 0x0120)}, /* Thomson SpeedTouch 120g */ 51 52 {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */ 52 53 {USB_DEVICE(0x07aa, 0x001c)}, /* Corega CG-WLUSB2GT */ ··· 83 82 {USB_DEVICE(0x06a9, 0x000e)}, /* Westell 802.11g USB (A90-211WG-01) */ 84 83 {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */ 85 84 {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ 85 + {USB_DEVICE(0x0803, 0x4310)}, /* Zoom 4410a */ 86 + {USB_DEVICE(0x083a, 0x4503)}, /* T-Com Sinus 154 data II */ 86 87 {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ 87 88 {USB_DEVICE(0x083a, 0xc501)}, /* Zoom Wireless-G 4410 */ 88 89 {USB_DEVICE(0x083a, 0xf503)}, /* Accton FD7050E ver 1010ec */ ··· 104 101 {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */ 105 102 {USB_DEVICE(0x1413, 0x5400)}, /* Telsey 802.11g USB2.0 Adapter */ 106 103 {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */ 104 + /* {USB_DEVICE(0x15a9, 0x0002)}, * Also SparkLAN WL-682 with 3887 */ 107 105 {USB_DEVICE(0x1668, 0x1050)}, /* Actiontec 802UIG-1 */ 108 106 {USB_DEVICE(0x1740, 0x1000)}, /* Senao NUB-350 */ 109 107 {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */
+2 -2
drivers/net/wireless/rtlwifi/Kconfig
··· 57 57 58 58 config RTLWIFI 59 59 tristate 60 - depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE 60 + depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE || RTL8723AE 61 61 default m 62 62 63 63 config RTLWIFI_DEBUG 64 64 bool "Additional debugging output" 65 - depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE 65 + depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE || RTL8723AE 66 66 default y 67 67 68 68 config RTL8192C_COMMON
+6
drivers/net/wireless/rtlwifi/pci.c
··· 743 743 744 744 done: 745 745 bufferaddress = (*((dma_addr_t *)skb->cb)); 746 + if (pci_dma_mapping_error(rtlpci->pdev, bufferaddress)) 747 + return; 746 748 tmp_one = 1; 747 749 rtlpriv->cfg->ops->set_desc((u8 *) pdesc, false, 748 750 HW_DESC_RXBUFF_ADDR, ··· 1117 1115 PCI_DMA_FROMDEVICE); 1118 1116 1119 1117 bufferaddress = (*((dma_addr_t *)skb->cb)); 1118 + if (pci_dma_mapping_error(rtlpci->pdev, bufferaddress)) { 1119 + dev_kfree_skb_any(skb); 1120 + return 1; 1121 + } 1120 1122 rtlpriv->cfg->ops->set_desc((u8 *)entry, false, 1121 1123 HW_DESC_RXBUFF_ADDR, 1122 1124 (u8 *)&bufferaddress);
+1 -1
drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
··· 692 692 if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { 693 693 rtl92c_phy_sw_chnl_callback(hw); 694 694 RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, 695 - "sw_chnl_inprogress false schdule workitem\n"); 695 + "sw_chnl_inprogress false schedule workitem\n"); 696 696 rtlphy->sw_chnl_inprogress = false; 697 697 } else { 698 698 RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
+11
drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
··· 611 611 dma_addr_t mapping = pci_map_single(rtlpci->pdev, 612 612 skb->data, skb->len, 613 613 PCI_DMA_TODEVICE); 614 + 614 615 u8 bw_40 = 0; 615 616 617 + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { 618 + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, 619 + "DMA mapping error"); 620 + return; 621 + } 616 622 rcu_read_lock(); 617 623 sta = get_sta(hw, mac->vif, mac->bssid); 618 624 if (mac->opmode == NL80211_IFTYPE_STATION) { ··· 780 774 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); 781 775 __le16 fc = hdr->frame_control; 782 776 777 + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { 778 + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, 779 + "DMA mapping error"); 780 + return; 781 + } 783 782 CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); 784 783 785 784 if (firstseg)
+10
drivers/net/wireless/rtlwifi/rtl8192de/trx.c
··· 587 587 buf_len = skb->len; 588 588 mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, 589 589 PCI_DMA_TODEVICE); 590 + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { 591 + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, 592 + "DMA mapping error"); 593 + return; 594 + } 590 595 CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92d)); 591 596 if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { 592 597 firstseg = true; ··· 745 740 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); 746 741 __le16 fc = hdr->frame_control; 747 742 743 + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { 744 + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, 745 + "DMA mapping error"); 746 + return; 747 + } 748 748 CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); 749 749 if (firstseg) 750 750 SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
+12 -1
drivers/net/wireless/rtlwifi/rtl8192se/trx.c
··· 611 611 PCI_DMA_TODEVICE); 612 612 u8 bw_40 = 0; 613 613 614 + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { 615 + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, 616 + "DMA mapping error"); 617 + return; 618 + } 614 619 if (mac->opmode == NL80211_IFTYPE_STATION) { 615 620 bw_40 = mac->bw_40; 616 621 } else if (mac->opmode == NL80211_IFTYPE_AP || ··· 768 763 void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, 769 764 bool firstseg, bool lastseg, struct sk_buff *skb) 770 765 { 766 + struct rtl_priv *rtlpriv = rtl_priv(hw); 771 767 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 772 768 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 773 769 struct rtl_tcb_desc *tcb_desc = (struct rtl_tcb_desc *)(skb->cb); ··· 776 770 dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, 777 771 PCI_DMA_TODEVICE); 778 772 779 - /* Clear all status */ 773 + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { 774 + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, 775 + "DMA mapping error"); 776 + return; 777 + } 778 + /* Clear all status */ 780 779 CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_CMDDESC_SIZE_RTL8192S); 781 780 782 781 /* This bit indicate this packet is used for FW download. */
+1 -1
drivers/net/wireless/rtlwifi/rtl8723ae/phy.c
··· 1106 1106 if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { 1107 1107 rtl8723ae_phy_sw_chnl_callback(hw); 1108 1108 RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, 1109 - "sw_chnl_inprogress false schdule workitem\n"); 1109 + "sw_chnl_inprogress false schedule workitem\n"); 1110 1110 rtlphy->sw_chnl_inprogress = false; 1111 1111 } else { 1112 1112 RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
+10
drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
··· 387 387 PCI_DMA_TODEVICE); 388 388 u8 bw_40 = 0; 389 389 390 + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { 391 + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, 392 + "DMA mapping error"); 393 + return; 394 + } 390 395 if (mac->opmode == NL80211_IFTYPE_STATION) { 391 396 bw_40 = mac->bw_40; 392 397 } else if (mac->opmode == NL80211_IFTYPE_AP || ··· 547 542 PCI_DMA_TODEVICE); 548 543 __le16 fc = hdr->frame_control; 549 544 545 + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { 546 + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, 547 + "DMA mapping error"); 548 + return; 549 + } 550 550 CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); 551 551 552 552 if (firstseg)
+4 -4
drivers/net/wireless/rtlwifi/usb.c
··· 210 210 u16 index = REALTEK_USB_VENQT_CMD_IDX; 211 211 int pipe = usb_sndctrlpipe(udev, 0); /* write_out */ 212 212 u8 *buffer; 213 - dma_addr_t dma_addr; 214 213 215 - wvalue = (u16)(addr&0x0000ffff); 216 - buffer = usb_alloc_coherent(udev, (size_t)len, GFP_ATOMIC, &dma_addr); 214 + wvalue = (u16)(addr & 0x0000ffff); 215 + buffer = kmalloc(len, GFP_ATOMIC); 217 216 if (!buffer) 218 217 return; 219 218 memcpy(buffer, data, len); 220 219 usb_control_msg(udev, pipe, request, reqtype, wvalue, 221 220 index, buffer, len, 50); 222 221 223 - usb_free_coherent(udev, (size_t)len, buffer, dma_addr); 222 + kfree(buffer); 224 223 } 225 224 226 225 static void _rtl_usb_io_handler_init(struct device *dev, ··· 639 640 RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, 640 641 "Failed to prep_rx_urb!!\n"); 641 642 err = PTR_ERR(skb); 643 + usb_free_urb(urb); 642 644 goto err_out; 643 645 } 644 646
+1 -2
drivers/ssb/Kconfig
··· 167 167 168 168 config SSB_DRIVER_GPIO 169 169 bool "SSB GPIO driver" 170 - depends on SSB 171 - select GPIOLIB 170 + depends on SSB && GPIOLIB 172 171 help 173 172 Driver to provide access to the GPIO pins on the bus. 174 173
-8
net/bluetooth/hci_core.c
··· 2810 2810 if (conn) { 2811 2811 hci_conn_enter_active_mode(conn, BT_POWER_FORCE_ACTIVE_OFF); 2812 2812 2813 - hci_dev_lock(hdev); 2814 - if (test_bit(HCI_MGMT, &hdev->dev_flags) && 2815 - !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2816 - mgmt_device_connected(hdev, &conn->dst, conn->type, 2817 - conn->dst_type, 0, NULL, 0, 2818 - conn->dev_class); 2819 - hci_dev_unlock(hdev); 2820 - 2821 2813 /* Send to upper protocol */ 2822 2814 l2cap_recv_acldata(conn, skb, flags); 2823 2815 return;
+1 -1
net/bluetooth/hci_event.c
··· 2688 2688 if (ev->opcode != HCI_OP_NOP) 2689 2689 del_timer(&hdev->cmd_timer); 2690 2690 2691 - if (ev->ncmd) { 2691 + if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2692 2692 atomic_set(&hdev->cmd_cnt, 1); 2693 2693 if (!skb_queue_empty(&hdev->cmd_q)) 2694 2694 queue_work(hdev->workqueue, &hdev->cmd_work);
+1 -1
net/bluetooth/hidp/core.c
··· 931 931 hid->version = req->version; 932 932 hid->country = req->country; 933 933 934 - strncpy(hid->name, req->name, 128); 934 + strncpy(hid->name, req->name, sizeof(req->name) - 1); 935 935 936 936 snprintf(hid->phys, sizeof(hid->phys), "%pMR", 937 937 &bt_sk(session->ctrl_sock->sk)->src);
+11
net/bluetooth/l2cap_core.c
··· 3727 3727 static int l2cap_connect_req(struct l2cap_conn *conn, 3728 3728 struct l2cap_cmd_hdr *cmd, u8 *data) 3729 3729 { 3730 + struct hci_dev *hdev = conn->hcon->hdev; 3731 + struct hci_conn *hcon = conn->hcon; 3732 + 3733 + hci_dev_lock(hdev); 3734 + if (test_bit(HCI_MGMT, &hdev->dev_flags) && 3735 + !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags)) 3736 + mgmt_device_connected(hdev, &hcon->dst, hcon->type, 3737 + hcon->dst_type, 0, NULL, 0, 3738 + hcon->dev_class); 3739 + hci_dev_unlock(hdev); 3740 + 3730 3741 l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0); 3731 3742 return 0; 3732 3743 }
+1 -1
net/bluetooth/sco.c
··· 352 352 353 353 case BT_CONNECTED: 354 354 case BT_CONFIG: 355 - if (sco_pi(sk)->conn) { 355 + if (sco_pi(sk)->conn->hcon) { 356 356 sk->sk_state = BT_DISCONN; 357 357 sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT); 358 358 hci_conn_put(sco_pi(sk)->conn->hcon);
+11 -1
net/mac80211/cfg.c
··· 164 164 sta = sta_info_get(sdata, mac_addr); 165 165 else 166 166 sta = sta_info_get_bss(sdata, mac_addr); 167 - if (!sta) { 167 + /* 168 + * The ASSOC test makes sure the driver is ready to 169 + * receive the key. When wpa_supplicant has roamed 170 + * using FT, it attempts to set the key before 171 + * association has completed, this rejects that attempt 172 + * so it will set the key again after assocation. 173 + * 174 + * TODO: accept the key if we have a station entry and 175 + * add it to the device after the station. 176 + */ 177 + if (!sta || !test_sta_flag(sta, WLAN_STA_ASSOC)) { 168 178 ieee80211_key_free(sdata->local, key); 169 179 err = -ENOENT; 170 180 goto out_unlock;
+2 -4
net/mac80211/ieee80211_i.h
··· 1368 1368 void ieee80211_sched_scan_stopped_work(struct work_struct *work); 1369 1369 1370 1370 /* off-channel helpers */ 1371 - void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, 1372 - bool offchannel_ps_enable); 1373 - void ieee80211_offchannel_return(struct ieee80211_local *local, 1374 - bool offchannel_ps_disable); 1371 + void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local); 1372 + void ieee80211_offchannel_return(struct ieee80211_local *local); 1375 1373 void ieee80211_roc_setup(struct ieee80211_local *local); 1376 1374 void ieee80211_start_next_roc(struct ieee80211_local *local); 1377 1375 void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata);
+4 -1
net/mac80211/mesh_hwmp.c
··· 215 215 skb->priority = 7; 216 216 217 217 info->control.vif = &sdata->vif; 218 + info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; 218 219 ieee80211_set_qos_hdr(sdata, skb); 219 220 } 220 221 ··· 249 248 return -EAGAIN; 250 249 251 250 skb = dev_alloc_skb(local->tx_headroom + 251 + IEEE80211_ENCRYPT_HEADROOM + 252 + IEEE80211_ENCRYPT_TAILROOM + 252 253 hdr_len + 253 254 2 + 15 /* PERR IE */); 254 255 if (!skb) 255 256 return -1; 256 - skb_reserve(skb, local->tx_headroom); 257 + skb_reserve(skb, local->tx_headroom + IEEE80211_ENCRYPT_HEADROOM); 257 258 mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); 258 259 memset(mgmt, 0, hdr_len); 259 260 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+7 -12
net/mac80211/offchannel.c
··· 102 102 ieee80211_sta_reset_conn_monitor(sdata); 103 103 } 104 104 105 - void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, 106 - bool offchannel_ps_enable) 105 + void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local) 107 106 { 108 107 struct ieee80211_sub_if_data *sdata; 109 108 ··· 135 136 136 137 if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { 137 138 netif_tx_stop_all_queues(sdata->dev); 138 - if (offchannel_ps_enable && 139 - (sdata->vif.type == NL80211_IFTYPE_STATION) && 139 + if (sdata->vif.type == NL80211_IFTYPE_STATION && 140 140 sdata->u.mgd.associated) 141 141 ieee80211_offchannel_ps_enable(sdata); 142 142 } ··· 143 145 mutex_unlock(&local->iflist_mtx); 144 146 } 145 147 146 - void ieee80211_offchannel_return(struct ieee80211_local *local, 147 - bool offchannel_ps_disable) 148 + void ieee80211_offchannel_return(struct ieee80211_local *local) 148 149 { 149 150 struct ieee80211_sub_if_data *sdata; 150 151 ··· 162 165 continue; 163 166 164 167 /* Tell AP we're back */ 165 - if (offchannel_ps_disable && 166 - sdata->vif.type == NL80211_IFTYPE_STATION) { 167 - if (sdata->u.mgd.associated) 168 - ieee80211_offchannel_ps_disable(sdata); 169 - } 168 + if (sdata->vif.type == NL80211_IFTYPE_STATION && 169 + sdata->u.mgd.associated) 170 + ieee80211_offchannel_ps_disable(sdata); 170 171 171 172 if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { 172 173 /* ··· 383 388 local->tmp_channel = NULL; 384 389 ieee80211_hw_config(local, 0); 385 390 386 - ieee80211_offchannel_return(local, true); 391 + ieee80211_offchannel_return(local); 387 392 } 388 393 389 394 ieee80211_recalc_idle(local);
+5 -10
net/mac80211/scan.c
··· 291 291 if (!was_hw_scan) { 292 292 ieee80211_configure_filter(local); 293 293 drv_sw_scan_complete(local); 294 - ieee80211_offchannel_return(local, true); 294 + ieee80211_offchannel_return(local); 295 295 } 296 296 297 297 ieee80211_recalc_idle(local); ··· 340 340 local->next_scan_state = SCAN_DECISION; 341 341 local->scan_channel_idx = 0; 342 342 343 - ieee80211_offchannel_stop_vifs(local, true); 343 + ieee80211_offchannel_stop_vifs(local); 344 344 345 345 ieee80211_configure_filter(local); 346 346 ··· 677 677 local->scan_channel = NULL; 678 678 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); 679 679 680 - /* 681 - * Re-enable vifs and beaconing. Leave PS 682 - * in off-channel state..will put that back 683 - * on-channel at the end of scanning. 684 - */ 685 - ieee80211_offchannel_return(local, false); 680 + /* disable PS */ 681 + ieee80211_offchannel_return(local); 686 682 687 683 *next_delay = HZ / 5; 688 684 /* afterwards, resume scan & go to next channel */ ··· 688 692 static void ieee80211_scan_state_resume(struct ieee80211_local *local, 689 693 unsigned long *next_delay) 690 694 { 691 - /* PS already is in off-channel mode */ 692 - ieee80211_offchannel_stop_vifs(local, false); 695 + ieee80211_offchannel_stop_vifs(local); 693 696 694 697 if (local->ops->flush) { 695 698 drv_flush(local, false);
+6 -3
net/mac80211/tx.c
··· 1673 1673 chanctx_conf = 1674 1674 rcu_dereference(tmp_sdata->vif.chanctx_conf); 1675 1675 } 1676 - if (!chanctx_conf) 1677 - goto fail_rcu; 1678 1676 1679 - chan = chanctx_conf->def.chan; 1677 + if (chanctx_conf) 1678 + chan = chanctx_conf->def.chan; 1679 + else if (!local->use_chanctx) 1680 + chan = local->_oper_channel; 1681 + else 1682 + goto fail_rcu; 1680 1683 1681 1684 /* 1682 1685 * Frame injection is not allowed if beaconing is not allowed