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

Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next

John W. Linville says:

====================
This is a batch of updates intended for the 3.13 stream...

The biggest item of interest in here is wcn36xx, the new mac80211
driver for Qualcomm WCN3660/WCN3680 hardware.

Regarding the mac80211 bits, Johannes says:

"We have an assortment of cleanups and new features, of which the
biggest one is probably the channel-switch support in IBSS. Nothing
else really stands out much."

On top of that, the ath9k and rt2x00 get a lot of update action from
Felix Fietkau and Gabor Juhos, respectively. There are a handful of
updates to other drivers here and there as well.

Please let me know if there are problems!
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+11952 -1324
+8
MAINTAINERS
··· 6830 6830 S: Supported 6831 6831 F: arch/hexagon/ 6832 6832 6833 + QUALCOMM WCN36XX WIRELESS DRIVER 6834 + M: Eugene Krasnikov <k.eugene.e@gmail.com> 6835 + L: wcn36xx@lists.infradead.org 6836 + W: http://wireless.kernel.org/en/users/Drivers/wcn36xx 6837 + T: git git://github.com/KrasnikovEugene/wcn36xx.git 6838 + S: Supported 6839 + F: drivers/net/wireless/ath/wcn36xx/ 6840 + 6833 6841 QUICKCAM PARALLEL PORT WEBCAMS 6834 6842 M: Hans Verkuil <hverkuil@xs4all.nl> 6835 6843 L: linux-media@vger.kernel.org
+6 -2
drivers/bcma/host_pci.c
··· 188 188 pci_write_config_dword(dev, 0x40, val & 0xffff00ff); 189 189 190 190 /* SSB needed additional powering up, do we have any AMBA PCI cards? */ 191 - if (!pci_is_pcie(dev)) 192 - bcma_err(bus, "PCI card detected, report problems.\n"); 191 + if (!pci_is_pcie(dev)) { 192 + bcma_err(bus, "PCI card detected, they are not supported.\n"); 193 + err = -ENXIO; 194 + goto err_pci_release_regions; 195 + } 193 196 194 197 /* Map MMIO */ 195 198 err = -ENOMEM; ··· 272 269 273 270 static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { 274 271 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, 272 + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4313) }, 275 273 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) }, 276 274 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, 277 275 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
+1
drivers/net/wireless/ath/Kconfig
··· 32 32 source "drivers/net/wireless/ath/ar5523/Kconfig" 33 33 source "drivers/net/wireless/ath/wil6210/Kconfig" 34 34 source "drivers/net/wireless/ath/ath10k/Kconfig" 35 + source "drivers/net/wireless/ath/wcn36xx/Kconfig" 35 36 36 37 endif
+1
drivers/net/wireless/ath/Makefile
··· 5 5 obj-$(CONFIG_AR5523) += ar5523/ 6 6 obj-$(CONFIG_WIL6210) += wil6210/ 7 7 obj-$(CONFIG_ATH10K) += ath10k/ 8 + obj-$(CONFIG_WCN36XX) += wcn36xx/ 8 9 9 10 obj-$(CONFIG_ATH_COMMON) += ath.o 10 11
+2 -4
drivers/net/wireless/ath/ath9k/ani.c
··· 338 338 aniState->cckNoiseImmunityLevel != 339 339 ATH9K_ANI_CCK_DEF_LEVEL) { 340 340 ath_dbg(common, ANI, 341 - "Restore defaults: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n", 341 + "Restore defaults: opmode %u chan %d Mhz is_scanning=%d ofdm:%d cck:%d\n", 342 342 ah->opmode, 343 343 chan->channel, 344 - chan->channelFlags, 345 344 is_scanning, 346 345 aniState->ofdmNoiseImmunityLevel, 347 346 aniState->cckNoiseImmunityLevel); ··· 353 354 * restore historical levels for this channel 354 355 */ 355 356 ath_dbg(common, ANI, 356 - "Restore history: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n", 357 + "Restore history: opmode %u chan %d Mhz is_scanning=%d ofdm:%d cck:%d\n", 357 358 ah->opmode, 358 359 chan->channel, 359 - chan->channelFlags, 360 360 is_scanning, 361 361 aniState->ofdmNoiseImmunityLevel, 362 362 aniState->cckNoiseImmunityLevel);
+12 -31
drivers/net/wireless/ath/ath9k/ar5008_phy.c
··· 666 666 if (IS_CHAN_HT40(chan)) { 667 667 phymode |= AR_PHY_FC_DYN2040_EN; 668 668 669 - if ((chan->chanmode == CHANNEL_A_HT40PLUS) || 670 - (chan->chanmode == CHANNEL_G_HT40PLUS)) 669 + if (IS_CHAN_HT40PLUS(chan)) 671 670 phymode |= AR_PHY_FC_DYN2040_PRI_CH; 672 671 673 672 } 674 673 REG_WRITE(ah, AR_PHY_TURBO, phymode); 675 674 676 - ath9k_hw_set11nmac2040(ah); 675 + ath9k_hw_set11nmac2040(ah, chan); 677 676 678 677 ENABLE_REGWRITE_BUFFER(ah); 679 678 ··· 690 691 int i, regWrites = 0; 691 692 u32 modesIndex, freqIndex; 692 693 693 - switch (chan->chanmode) { 694 - case CHANNEL_A: 695 - case CHANNEL_A_HT20: 696 - modesIndex = 1; 694 + if (IS_CHAN_5GHZ(chan)) { 697 695 freqIndex = 1; 698 - break; 699 - case CHANNEL_A_HT40PLUS: 700 - case CHANNEL_A_HT40MINUS: 701 - modesIndex = 2; 702 - freqIndex = 1; 703 - break; 704 - case CHANNEL_G: 705 - case CHANNEL_G_HT20: 706 - case CHANNEL_B: 707 - modesIndex = 4; 696 + modesIndex = IS_CHAN_HT40(chan) ? 2 : 1; 697 + } else { 708 698 freqIndex = 2; 709 - break; 710 - case CHANNEL_G_HT40PLUS: 711 - case CHANNEL_G_HT40MINUS: 712 - modesIndex = 3; 713 - freqIndex = 2; 714 - break; 715 - 716 - default: 717 - return -EINVAL; 699 + modesIndex = IS_CHAN_HT40(chan) ? 3 : 4; 718 700 } 719 701 720 702 /* ··· 794 814 if (chan == NULL) 795 815 return; 796 816 797 - rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan)) 798 - ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; 817 + if (IS_CHAN_2GHZ(chan)) 818 + rfMode |= AR_PHY_MODE_DYNAMIC; 819 + else 820 + rfMode |= AR_PHY_MODE_OFDM; 799 821 800 822 if (!AR_SREV_9280_20_OR_LATER(ah)) 801 823 rfMode |= (IS_CHAN_5GHZ(chan)) ? ··· 1200 1218 1201 1219 iniDef = &aniState->iniDef; 1202 1220 1203 - ath_dbg(common, ANI, "ver %d.%d opmode %u chan %d Mhz/0x%x\n", 1221 + ath_dbg(common, ANI, "ver %d.%d opmode %u chan %d Mhz\n", 1204 1222 ah->hw_version.macVersion, 1205 1223 ah->hw_version.macRev, 1206 1224 ah->opmode, 1207 - chan->channel, 1208 - chan->channelFlags); 1225 + chan->channel); 1209 1226 1210 1227 val = REG_READ(ah, AR_PHY_SFCORR); 1211 1228 iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH);
+2 -5
drivers/net/wireless/ath/ath9k/ar9002_calib.c
··· 33 33 bool supported = false; 34 34 switch (ah->supp_cals & cal_type) { 35 35 case IQ_MISMATCH_CAL: 36 - /* Run IQ Mismatch for non-CCK only */ 37 - if (!IS_CHAN_B(chan)) 38 - supported = true; 36 + supported = true; 39 37 break; 40 38 case ADC_GAIN_CAL: 41 39 case ADC_DC_CAL: 42 40 /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */ 43 - if (!IS_CHAN_B(chan) && 44 - !((IS_CHAN_2GHZ(chan) || IS_CHAN_A_FAST_CLOCK(ah, chan)) && 41 + if (!((IS_CHAN_2GHZ(chan) || IS_CHAN_A_FAST_CLOCK(ah, chan)) && 45 42 IS_CHAN_HT20(chan))) 46 43 supported = true; 47 44 break;
+4 -22
drivers/net/wireless/ath/ath9k/ar9002_hw.c
··· 419 419 u32 modesIndex; 420 420 int i; 421 421 422 - switch (chan->chanmode) { 423 - case CHANNEL_A: 424 - case CHANNEL_A_HT20: 425 - modesIndex = 1; 426 - break; 427 - case CHANNEL_A_HT40PLUS: 428 - case CHANNEL_A_HT40MINUS: 429 - modesIndex = 2; 430 - break; 431 - case CHANNEL_G: 432 - case CHANNEL_G_HT20: 433 - case CHANNEL_B: 434 - modesIndex = 4; 435 - break; 436 - case CHANNEL_G_HT40PLUS: 437 - case CHANNEL_G_HT40MINUS: 438 - modesIndex = 3; 439 - break; 440 - 441 - default: 442 - return; 443 - } 422 + if (IS_CHAN_5GHZ(chan)) 423 + modesIndex = IS_CHAN_HT40(chan) ? 2 : 1; 424 + else 425 + modesIndex = IS_CHAN_HT40(chan) ? 3 : 4; 444 426 445 427 ENABLE_REGWRITE_BUFFER(ah); 446 428
+30 -85
drivers/net/wireless/ath/ath9k/ar9003_phy.c
··· 551 551 if (IS_CHAN_HT40(chan)) { 552 552 phymode |= AR_PHY_GC_DYN2040_EN; 553 553 /* Configure control (primary) channel at +-10MHz */ 554 - if ((chan->chanmode == CHANNEL_A_HT40PLUS) || 555 - (chan->chanmode == CHANNEL_G_HT40PLUS)) 554 + if (IS_CHAN_HT40PLUS(chan)) 556 555 phymode |= AR_PHY_GC_DYN2040_PRI_CH; 557 556 558 557 } ··· 564 565 REG_WRITE(ah, AR_PHY_GEN_CTRL, phymode); 565 566 566 567 /* Configure MAC for 20/40 operation */ 567 - ath9k_hw_set11nmac2040(ah); 568 + ath9k_hw_set11nmac2040(ah, chan); 568 569 569 570 /* global transmit timeout (25 TUs default)*/ 570 571 REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S); ··· 681 682 { 682 683 int ret; 683 684 684 - switch (chan->chanmode) { 685 - case CHANNEL_A: 686 - case CHANNEL_A_HT20: 687 - if (chan->channel <= 5350) 688 - ret = 1; 689 - else if ((chan->channel > 5350) && (chan->channel <= 5600)) 690 - ret = 3; 685 + if (IS_CHAN_2GHZ(chan)) { 686 + if (IS_CHAN_HT40(chan)) 687 + return 7; 691 688 else 692 - ret = 5; 693 - break; 694 - 695 - case CHANNEL_A_HT40PLUS: 696 - case CHANNEL_A_HT40MINUS: 697 - if (chan->channel <= 5350) 698 - ret = 2; 699 - else if ((chan->channel > 5350) && (chan->channel <= 5600)) 700 - ret = 4; 701 - else 702 - ret = 6; 703 - break; 704 - 705 - case CHANNEL_G: 706 - case CHANNEL_G_HT20: 707 - case CHANNEL_B: 708 - ret = 8; 709 - break; 710 - 711 - case CHANNEL_G_HT40PLUS: 712 - case CHANNEL_G_HT40MINUS: 713 - ret = 7; 714 - break; 715 - 716 - default: 717 - ret = -EINVAL; 689 + return 8; 718 690 } 691 + 692 + if (chan->channel <= 5350) 693 + ret = 1; 694 + else if ((chan->channel > 5350) && (chan->channel <= 5600)) 695 + ret = 3; 696 + else 697 + ret = 5; 698 + 699 + if (IS_CHAN_HT40(chan)) 700 + ret++; 719 701 720 702 return ret; 721 703 } ··· 707 727 unsigned int regWrites = 0, i; 708 728 u32 modesIndex; 709 729 710 - switch (chan->chanmode) { 711 - case CHANNEL_A: 712 - case CHANNEL_A_HT20: 713 - modesIndex = 1; 714 - break; 715 - case CHANNEL_A_HT40PLUS: 716 - case CHANNEL_A_HT40MINUS: 717 - modesIndex = 2; 718 - break; 719 - case CHANNEL_G: 720 - case CHANNEL_G_HT20: 721 - case CHANNEL_B: 722 - modesIndex = 4; 723 - break; 724 - case CHANNEL_G_HT40PLUS: 725 - case CHANNEL_G_HT40MINUS: 726 - modesIndex = 3; 727 - break; 728 - 729 - default: 730 - return -EINVAL; 731 - } 730 + if (IS_CHAN_5GHZ(chan)) 731 + modesIndex = IS_CHAN_HT40(chan) ? 2 : 1; 732 + else 733 + modesIndex = IS_CHAN_HT40(chan) ? 3 : 4; 732 734 733 735 /* 734 736 * SOC, MAC, BB, RADIO initvals. ··· 808 846 if (chan == NULL) 809 847 return; 810 848 811 - rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan)) 812 - ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; 849 + if (IS_CHAN_2GHZ(chan)) 850 + rfMode |= AR_PHY_MODE_DYNAMIC; 851 + else 852 + rfMode |= AR_PHY_MODE_OFDM; 813 853 814 854 if (IS_CHAN_A_FAST_CLOCK(ah, chan)) 815 855 rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE); ··· 1237 1273 aniState = &ah->ani; 1238 1274 iniDef = &aniState->iniDef; 1239 1275 1240 - ath_dbg(common, ANI, "ver %d.%d opmode %u chan %d Mhz/0x%x\n", 1276 + ath_dbg(common, ANI, "ver %d.%d opmode %u chan %d Mhz\n", 1241 1277 ah->hw_version.macVersion, 1242 1278 ah->hw_version.macRev, 1243 1279 ah->opmode, 1244 - chan->channel, 1245 - chan->channelFlags); 1280 + chan->channel); 1246 1281 1247 1282 val = REG_READ(ah, AR_PHY_SFCORR); 1248 1283 iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH); ··· 1499 1536 unsigned int regWrites = 0; 1500 1537 u32 modesIndex; 1501 1538 1502 - switch (chan->chanmode) { 1503 - case CHANNEL_A: 1504 - case CHANNEL_A_HT20: 1505 - modesIndex = 1; 1506 - break; 1507 - case CHANNEL_A_HT40PLUS: 1508 - case CHANNEL_A_HT40MINUS: 1509 - modesIndex = 2; 1510 - break; 1511 - case CHANNEL_G: 1512 - case CHANNEL_G_HT20: 1513 - case CHANNEL_B: 1514 - modesIndex = 4; 1515 - break; 1516 - case CHANNEL_G_HT40PLUS: 1517 - case CHANNEL_G_HT40MINUS: 1518 - modesIndex = 3; 1519 - break; 1520 - 1521 - default: 1522 - return -EINVAL; 1523 - } 1539 + if (IS_CHAN_5GHZ(chan)) 1540 + modesIndex = IS_CHAN_HT40(chan) ? 2 : 1; 1541 + else 1542 + modesIndex = IS_CHAN_HT40(chan) ? 3 : 4; 1524 1543 1525 1544 if (modesIndex == ah->modes_index) { 1526 1545 *ini_reloaded = false;
+9 -3
drivers/net/wireless/ath/ath9k/ath9k.h
··· 64 64 65 65 struct ath_config { 66 66 u16 txpowlimit; 67 - u8 cabqReadytime; 68 67 }; 69 68 70 69 /*************************/ ··· 206 207 u8 baw_tracked : 1; 207 208 }; 208 209 210 + struct ath_rxbuf { 211 + struct list_head list; 212 + struct sk_buff *bf_mpdu; 213 + void *bf_desc; 214 + dma_addr_t bf_daddr; 215 + dma_addr_t bf_buf_addr; 216 + }; 217 + 209 218 struct ath_buf_state { 210 219 u8 bf_type; 211 220 u8 bfs_paprd; ··· 314 307 struct ath_descdma rxdma; 315 308 struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX]; 316 309 317 - struct ath_buf *buf_hold; 310 + struct ath_rxbuf *buf_hold; 318 311 struct sk_buff *frag; 319 312 320 313 u32 ampdu_ref; ··· 933 926 void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); 934 927 void ath9k_reload_chainmask_settings(struct ath_softc *sc); 935 928 936 - bool ath9k_uses_beacons(int type); 937 929 void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw); 938 930 int ath9k_spectral_scan_config(struct ieee80211_hw *hw, 939 931 enum spectral_mode spectral_mode);
+3 -6
drivers/net/wireless/ath/ath9k/calib.c
··· 186 186 bool ath9k_hw_reset_calvalid(struct ath_hw *ah) 187 187 { 188 188 struct ath_common *common = ath9k_hw_common(ah); 189 - struct ieee80211_conf *conf = &common->hw->conf; 190 189 struct ath9k_cal_list *currCal = ah->cal_list_curr; 191 190 192 191 if (!ah->caldata) ··· 207 208 return true; 208 209 209 210 ath_dbg(common, CALIBRATE, "Resetting Cal %d state for channel %u\n", 210 - currCal->calData->calType, conf->chandef.chan->center_freq); 211 + currCal->calData->calType, ah->curchan->chan->center_freq); 211 212 212 213 ah->caldata->CalValid &= ~currCal->calData->calType; 213 214 currCal->calState = CAL_WAITING; ··· 241 242 int32_t val; 242 243 u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; 243 244 struct ath_common *common = ath9k_hw_common(ah); 244 - struct ieee80211_conf *conf = &common->hw->conf; 245 245 s16 default_nf = ath9k_hw_get_default_nf(ah, chan); 246 246 247 247 if (ah->caldata) ··· 250 252 if (chainmask & (1 << i)) { 251 253 s16 nfval; 252 254 253 - if ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)) 255 + if ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(chan)) 254 256 continue; 255 257 256 258 if (h) ··· 312 314 ENABLE_REGWRITE_BUFFER(ah); 313 315 for (i = 0; i < NUM_NF_READINGS; i++) { 314 316 if (chainmask & (1 << i)) { 315 - if ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)) 317 + if ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(chan)) 316 318 continue; 317 319 318 320 val = REG_READ(ah, ah->nf_regs[i]); ··· 406 408 407 409 ah->caldata->channel = chan->channel; 408 410 ah->caldata->channelFlags = chan->channelFlags; 409 - ah->caldata->chanmode = chan->chanmode; 410 411 h = ah->caldata->nfCalHist; 411 412 default_nf = ath9k_hw_get_default_nf(ah, chan); 412 413 for (i = 0; i < NUM_NF_READINGS; i++) {
+25 -64
drivers/net/wireless/ath/ath9k/common.c
··· 49 49 } 50 50 EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype); 51 51 52 - static u32 ath9k_get_extchanmode(struct cfg80211_chan_def *chandef) 53 - { 54 - u32 chanmode = 0; 55 - 56 - switch (chandef->chan->band) { 57 - case IEEE80211_BAND_2GHZ: 58 - switch (chandef->width) { 59 - case NL80211_CHAN_WIDTH_20_NOHT: 60 - case NL80211_CHAN_WIDTH_20: 61 - chanmode = CHANNEL_G_HT20; 62 - break; 63 - case NL80211_CHAN_WIDTH_40: 64 - if (chandef->center_freq1 > chandef->chan->center_freq) 65 - chanmode = CHANNEL_G_HT40PLUS; 66 - else 67 - chanmode = CHANNEL_G_HT40MINUS; 68 - break; 69 - default: 70 - break; 71 - } 72 - break; 73 - case IEEE80211_BAND_5GHZ: 74 - switch (chandef->width) { 75 - case NL80211_CHAN_WIDTH_20_NOHT: 76 - case NL80211_CHAN_WIDTH_20: 77 - chanmode = CHANNEL_A_HT20; 78 - break; 79 - case NL80211_CHAN_WIDTH_40: 80 - if (chandef->center_freq1 > chandef->chan->center_freq) 81 - chanmode = CHANNEL_A_HT40PLUS; 82 - else 83 - chanmode = CHANNEL_A_HT40MINUS; 84 - break; 85 - default: 86 - break; 87 - } 88 - break; 89 - default: 90 - break; 91 - } 92 - 93 - return chanmode; 94 - } 95 - 96 52 /* 97 53 * Update internal channel flags. 98 54 */ 99 - void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, 100 - struct cfg80211_chan_def *chandef) 55 + static void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, 56 + struct cfg80211_chan_def *chandef) 101 57 { 102 - ichan->channel = chandef->chan->center_freq; 103 - ichan->chan = chandef->chan; 58 + struct ieee80211_channel *chan = chandef->chan; 59 + u16 flags = 0; 104 60 105 - if (chandef->chan->band == IEEE80211_BAND_2GHZ) { 106 - ichan->chanmode = CHANNEL_G; 107 - ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM; 108 - } else { 109 - ichan->chanmode = CHANNEL_A; 110 - ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; 111 - } 61 + ichan->channel = chan->center_freq; 62 + ichan->chan = chan; 63 + 64 + if (chan->band == IEEE80211_BAND_5GHZ) 65 + flags |= CHANNEL_5GHZ; 112 66 113 67 switch (chandef->width) { 114 68 case NL80211_CHAN_WIDTH_5: 115 - ichan->channelFlags |= CHANNEL_QUARTER; 69 + flags |= CHANNEL_QUARTER; 116 70 break; 117 71 case NL80211_CHAN_WIDTH_10: 118 - ichan->channelFlags |= CHANNEL_HALF; 72 + flags |= CHANNEL_HALF; 119 73 break; 120 74 case NL80211_CHAN_WIDTH_20_NOHT: 121 75 break; 122 76 case NL80211_CHAN_WIDTH_20: 77 + flags |= CHANNEL_HT; 78 + break; 123 79 case NL80211_CHAN_WIDTH_40: 124 - ichan->chanmode = ath9k_get_extchanmode(chandef); 80 + if (chandef->center_freq1 > chandef->chan->center_freq) 81 + flags |= CHANNEL_HT40PLUS | CHANNEL_HT; 82 + else 83 + flags |= CHANNEL_HT40MINUS | CHANNEL_HT; 125 84 break; 126 85 default: 127 86 WARN_ON(1); 128 87 } 88 + 89 + ichan->channelFlags = flags; 129 90 } 130 - EXPORT_SYMBOL(ath9k_cmn_update_ichannel); 131 91 132 92 /* 133 93 * Get the internal channel reference. 134 94 */ 135 - struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, 136 - struct ath_hw *ah) 95 + struct ath9k_channel *ath9k_cmn_get_channel(struct ieee80211_hw *hw, 96 + struct ath_hw *ah, 97 + struct cfg80211_chan_def *chandef) 137 98 { 138 - struct ieee80211_channel *curchan = hw->conf.chandef.chan; 99 + struct ieee80211_channel *curchan = chandef->chan; 139 100 struct ath9k_channel *channel; 140 101 u8 chan_idx; 141 102 142 103 chan_idx = curchan->hw_value; 143 104 channel = &ah->channels[chan_idx]; 144 - ath9k_cmn_update_ichannel(channel, &hw->conf.chandef); 105 + ath9k_cmn_update_ichannel(channel, chandef); 145 106 146 107 return channel; 147 108 } 148 - EXPORT_SYMBOL(ath9k_cmn_get_curchannel); 109 + EXPORT_SYMBOL(ath9k_cmn_get_channel); 149 110 150 111 int ath9k_cmn_count_streams(unsigned int chainmask, int max) 151 112 {
+3 -4
drivers/net/wireless/ath/ath9k/common.h
··· 43 43 (((x) + ((mul)/2)) / (mul)) 44 44 45 45 int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); 46 - void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, 47 - struct cfg80211_chan_def *chandef); 48 - struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, 49 - struct ath_hw *ah); 46 + struct ath9k_channel *ath9k_cmn_get_channel(struct ieee80211_hw *hw, 47 + struct ath_hw *ah, 48 + struct cfg80211_chan_def *chandef); 50 49 int ath9k_cmn_count_streams(unsigned int chainmask, int max); 51 50 void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, 52 51 enum ath_stomp_type stomp_type);
+5 -27
drivers/net/wireless/ath/ath9k/htc_drv_main.c
··· 24 24 static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv, 25 25 struct ath9k_channel *ichan) 26 26 { 27 - enum htc_phymode mode; 27 + if (IS_CHAN_5GHZ(ichan)) 28 + return HTC_MODE_11NA; 28 29 29 - mode = -EINVAL; 30 - 31 - switch (ichan->chanmode) { 32 - case CHANNEL_G: 33 - case CHANNEL_G_HT20: 34 - case CHANNEL_G_HT40PLUS: 35 - case CHANNEL_G_HT40MINUS: 36 - mode = HTC_MODE_11NG; 37 - break; 38 - case CHANNEL_A: 39 - case CHANNEL_A_HT20: 40 - case CHANNEL_A_HT40PLUS: 41 - case CHANNEL_A_HT40MINUS: 42 - mode = HTC_MODE_11NA; 43 - break; 44 - default: 45 - break; 46 - } 47 - 48 - WARN_ON(mode < 0); 49 - 50 - return mode; 30 + return HTC_MODE_11NG; 51 31 } 52 32 53 33 bool ath9k_htc_setpower(struct ath9k_htc_priv *priv, ··· 906 926 WMI_CMD(WMI_FLUSH_RECV_CMDID); 907 927 908 928 /* setup initial channel */ 909 - init_channel = ath9k_cmn_get_curchannel(hw, ah); 929 + init_channel = ath9k_cmn_get_channel(hw, ah, &hw->conf.chandef); 910 930 911 931 ret = ath9k_hw_reset(ah, init_channel, ah->caldata, false); 912 932 if (ret) { ··· 1188 1208 ath_dbg(common, CONFIG, "Set channel: %d MHz\n", 1189 1209 curchan->center_freq); 1190 1210 1191 - ath9k_cmn_update_ichannel(&priv->ah->channels[pos], 1192 - &hw->conf.chandef); 1193 - 1211 + ath9k_cmn_get_channel(hw, priv->ah, &hw->conf.chandef); 1194 1212 if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) { 1195 1213 ath_err(common, "Unable to set channel\n"); 1196 1214 ret = -EINVAL;
+21 -46
drivers/net/wireless/ath/ath9k/hw.c
··· 130 130 131 131 static void ath9k_hw_set_clockrate(struct ath_hw *ah) 132 132 { 133 - struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; 134 133 struct ath_common *common = ath9k_hw_common(ah); 134 + struct ath9k_channel *chan = ah->curchan; 135 135 unsigned int clockrate; 136 136 137 137 /* AR9287 v1.3+ uses async FIFO and runs the MAC at 117 MHz */ 138 138 if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) 139 139 clockrate = 117; 140 - else if (!ah->curchan) /* should really check for CCK instead */ 140 + else if (!chan) /* should really check for CCK instead */ 141 141 clockrate = ATH9K_CLOCK_RATE_CCK; 142 - else if (conf->chandef.chan->band == IEEE80211_BAND_2GHZ) 142 + else if (IS_CHAN_2GHZ(chan)) 143 143 clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM; 144 144 else if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK) 145 145 clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM; 146 146 else 147 147 clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM; 148 148 149 - if (conf_is_ht40(conf)) 149 + if (IS_CHAN_HT40(chan)) 150 150 clockrate *= 2; 151 151 152 152 if (ah->curchan) { 153 - if (IS_CHAN_HALF_RATE(ah->curchan)) 153 + if (IS_CHAN_HALF_RATE(chan)) 154 154 clockrate /= 2; 155 - if (IS_CHAN_QUARTER_RATE(ah->curchan)) 155 + if (IS_CHAN_QUARTER_RATE(chan)) 156 156 clockrate /= 4; 157 157 } 158 158 ··· 190 190 void ath9k_hw_synth_delay(struct ath_hw *ah, struct ath9k_channel *chan, 191 191 int hw_delay) 192 192 { 193 - if (IS_CHAN_B(chan)) 194 - hw_delay = (4 * hw_delay) / 22; 195 - else 196 - hw_delay /= 10; 193 + hw_delay /= 10; 197 194 198 195 if (IS_CHAN_HALF_RATE(chan)) 199 196 hw_delay *= 2; ··· 291 294 return; 292 295 } 293 296 294 - if ((chan->chanmode == CHANNEL_A_HT40PLUS) || 295 - (chan->chanmode == CHANNEL_G_HT40PLUS)) { 297 + if (IS_CHAN_HT40PLUS(chan)) { 296 298 centers->synth_center = 297 299 chan->channel + HT40_CHANNEL_CENTER_SHIFT; 298 300 extoff = 1; ··· 1038 1042 void ath9k_hw_init_global_settings(struct ath_hw *ah) 1039 1043 { 1040 1044 struct ath_common *common = ath9k_hw_common(ah); 1041 - struct ieee80211_conf *conf = &common->hw->conf; 1042 1045 const struct ath9k_channel *chan = ah->curchan; 1043 1046 int acktimeout, ctstimeout, ack_offset = 0; 1044 1047 int slottime; ··· 1112 1117 * BA frames in some implementations, but it has been found to fix ACK 1113 1118 * timeout issues in other cases as well. 1114 1119 */ 1115 - if (conf->chandef.chan && 1116 - conf->chandef.chan->band == IEEE80211_BAND_2GHZ && 1120 + if (IS_CHAN_2GHZ(chan) && 1117 1121 !IS_CHAN_HALF_RATE(chan) && !IS_CHAN_QUARTER_RATE(chan)) { 1118 1122 acktimeout += 64 - sifstime - ah->slottime; 1119 1123 ctstimeout += 48 - sifstime - ah->slottime; ··· 1154 1160 { 1155 1161 u32 ctl = ath_regd_get_band_ctl(reg, chan->chan->band); 1156 1162 1157 - if (IS_CHAN_B(chan)) 1158 - ctl |= CTL_11B; 1159 - else if (IS_CHAN_G(chan)) 1163 + if (IS_CHAN_2GHZ(chan)) 1160 1164 ctl |= CTL_11G; 1161 1165 else 1162 1166 ctl |= CTL_11A; ··· 1502 1510 int r; 1503 1511 1504 1512 if (pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) { 1505 - u32 cur = ah->curchan->channelFlags & (CHANNEL_2GHZ | CHANNEL_5GHZ); 1506 - u32 new = chan->channelFlags & (CHANNEL_2GHZ | CHANNEL_5GHZ); 1507 - band_switch = (cur != new); 1508 - mode_diff = (chan->chanmode != ah->curchan->chanmode); 1513 + band_switch = IS_CHAN_5GHZ(ah->curchan) != IS_CHAN_5GHZ(chan); 1514 + mode_diff = (chan->channelFlags != ah->curchan->channelFlags); 1509 1515 } 1510 1516 1511 1517 for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { ··· 1542 1552 ath9k_hw_set_clockrate(ah); 1543 1553 ath9k_hw_apply_txpower(ah, chan, false); 1544 1554 1545 - if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) 1546 - ath9k_hw_set_delta_slope(ah, chan); 1547 - 1555 + ath9k_hw_set_delta_slope(ah, chan); 1548 1556 ath9k_hw_spur_mitigate_freq(ah, chan); 1549 1557 1550 1558 if (band_switch || ini_reloaded) ··· 1812 1824 goto fail; 1813 1825 1814 1826 /* 1815 - * If cross-band fcc is not supoprted, bail out if 1816 - * either channelFlags or chanmode differ. 1817 - * 1818 - * chanmode will be different if the HT operating mode 1819 - * changes because of CSA. 1827 + * If cross-band fcc is not supoprted, bail out if channelFlags differ. 1820 1828 */ 1821 - if (!(pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH)) { 1822 - if ((chan->channelFlags & CHANNEL_ALL) != 1823 - (ah->curchan->channelFlags & CHANNEL_ALL)) 1824 - goto fail; 1825 - 1826 - if (chan->chanmode != ah->curchan->chanmode) 1827 - goto fail; 1828 - } 1829 + if (!(pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) && 1830 + chan->channelFlags != ah->curchan->channelFlags) 1831 + goto fail; 1829 1832 1830 1833 if (!ath9k_hw_check_alive(ah)) 1831 1834 goto fail; ··· 1878 1899 1879 1900 ah->caldata = caldata; 1880 1901 if (caldata && (chan->channel != caldata->channel || 1881 - chan->channelFlags != caldata->channelFlags || 1882 - chan->chanmode != caldata->chanmode)) { 1902 + chan->channelFlags != caldata->channelFlags)) { 1883 1903 /* Operating channel changed, reset channel calibration data */ 1884 1904 memset(caldata, 0, sizeof(*caldata)); 1885 1905 ath9k_init_nfcal_hist_buffer(ah, chan); ··· 1967 1989 1968 1990 ath9k_hw_init_mfp(ah); 1969 1991 1970 - if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) 1971 - ath9k_hw_set_delta_slope(ah, chan); 1972 - 1992 + ath9k_hw_set_delta_slope(ah, chan); 1973 1993 ath9k_hw_spur_mitigate_freq(ah, chan); 1974 1994 ah->eep_ops->set_board_values(ah, chan); 1975 1995 ··· 2944 2968 } 2945 2969 EXPORT_SYMBOL(ath9k_hw_set_tsfadjust); 2946 2970 2947 - void ath9k_hw_set11nmac2040(struct ath_hw *ah) 2971 + void ath9k_hw_set11nmac2040(struct ath_hw *ah, struct ath9k_channel *chan) 2948 2972 { 2949 - struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; 2950 2973 u32 macmode; 2951 2974 2952 - if (conf_is_ht40(conf) && !ah->config.cwm_ignore_extcca) 2975 + if (IS_CHAN_HT40(chan) && !ah->config.cwm_ignore_extcca) 2953 2976 macmode = AR_2040_JOINED_RX_CLEAR; 2954 2977 else 2955 2978 macmode = 0;
+26 -56
drivers/net/wireless/ath/ath9k/hw.h
··· 369 369 ATH9K_INT_NOCARD = 0xffffffff 370 370 }; 371 371 372 - #define CHANNEL_CCK 0x00020 373 - #define CHANNEL_OFDM 0x00040 374 - #define CHANNEL_2GHZ 0x00080 375 - #define CHANNEL_5GHZ 0x00100 376 - #define CHANNEL_PASSIVE 0x00200 377 - #define CHANNEL_DYN 0x00400 378 - #define CHANNEL_HALF 0x04000 379 - #define CHANNEL_QUARTER 0x08000 380 - #define CHANNEL_HT20 0x10000 381 - #define CHANNEL_HT40PLUS 0x20000 382 - #define CHANNEL_HT40MINUS 0x40000 383 - 384 - #define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM) 385 - #define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK) 386 - #define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM) 387 - #define CHANNEL_G_HT20 (CHANNEL_2GHZ|CHANNEL_HT20) 388 - #define CHANNEL_A_HT20 (CHANNEL_5GHZ|CHANNEL_HT20) 389 - #define CHANNEL_G_HT40PLUS (CHANNEL_2GHZ|CHANNEL_HT40PLUS) 390 - #define CHANNEL_G_HT40MINUS (CHANNEL_2GHZ|CHANNEL_HT40MINUS) 391 - #define CHANNEL_A_HT40PLUS (CHANNEL_5GHZ|CHANNEL_HT40PLUS) 392 - #define CHANNEL_A_HT40MINUS (CHANNEL_5GHZ|CHANNEL_HT40MINUS) 393 - #define CHANNEL_ALL \ 394 - (CHANNEL_OFDM| \ 395 - CHANNEL_CCK| \ 396 - CHANNEL_2GHZ | \ 397 - CHANNEL_5GHZ | \ 398 - CHANNEL_HT20 | \ 399 - CHANNEL_HT40PLUS | \ 400 - CHANNEL_HT40MINUS) 401 - 402 372 #define MAX_RTT_TABLE_ENTRY 6 403 373 #define MAX_IQCAL_MEASUREMENT 8 404 374 #define MAX_CL_TAB_ENTRY 16 ··· 387 417 388 418 struct ath9k_hw_cal_data { 389 419 u16 channel; 390 - u32 channelFlags; 391 - u32 chanmode; 420 + u16 channelFlags; 392 421 unsigned long cal_flags; 393 422 int32_t CalValid; 394 423 int8_t iCoff; ··· 405 436 struct ath9k_channel { 406 437 struct ieee80211_channel *chan; 407 438 u16 channel; 408 - u32 channelFlags; 409 - u32 chanmode; 439 + u16 channelFlags; 410 440 s16 noisefloor; 411 441 }; 412 442 413 - #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ 414 - (((_c)->channelFlags & CHANNEL_G_HT20) == CHANNEL_G_HT20) || \ 415 - (((_c)->channelFlags & CHANNEL_G_HT40PLUS) == CHANNEL_G_HT40PLUS) || \ 416 - (((_c)->channelFlags & CHANNEL_G_HT40MINUS) == CHANNEL_G_HT40MINUS)) 417 - #define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0) 418 - #define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0) 419 - #define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0) 420 - #define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0) 421 - #define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0) 422 - #define IS_CHAN_A_FAST_CLOCK(_ah, _c) \ 423 - ((((_c)->channelFlags & CHANNEL_5GHZ) != 0) && \ 424 - ((_ah)->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)) 443 + #define CHANNEL_5GHZ BIT(0) 444 + #define CHANNEL_HALF BIT(1) 445 + #define CHANNEL_QUARTER BIT(2) 446 + #define CHANNEL_HT BIT(3) 447 + #define CHANNEL_HT40PLUS BIT(4) 448 + #define CHANNEL_HT40MINUS BIT(5) 425 449 426 - /* These macros check chanmode and not channelFlags */ 427 - #define IS_CHAN_B(_c) ((_c)->chanmode == CHANNEL_B) 428 - #define IS_CHAN_HT20(_c) (((_c)->chanmode == CHANNEL_A_HT20) || \ 429 - ((_c)->chanmode == CHANNEL_G_HT20)) 430 - #define IS_CHAN_HT40(_c) (((_c)->chanmode == CHANNEL_A_HT40PLUS) || \ 431 - ((_c)->chanmode == CHANNEL_A_HT40MINUS) || \ 432 - ((_c)->chanmode == CHANNEL_G_HT40PLUS) || \ 433 - ((_c)->chanmode == CHANNEL_G_HT40MINUS)) 434 - #define IS_CHAN_HT(_c) (IS_CHAN_HT20((_c)) || IS_CHAN_HT40((_c))) 450 + #define IS_CHAN_5GHZ(_c) (!!((_c)->channelFlags & CHANNEL_5GHZ)) 451 + #define IS_CHAN_2GHZ(_c) (!IS_CHAN_5GHZ(_c)) 452 + 453 + #define IS_CHAN_HALF_RATE(_c) (!!((_c)->channelFlags & CHANNEL_HALF)) 454 + #define IS_CHAN_QUARTER_RATE(_c) (!!((_c)->channelFlags & CHANNEL_QUARTER)) 455 + #define IS_CHAN_A_FAST_CLOCK(_ah, _c) \ 456 + (IS_CHAN_5GHZ(_c) && ((_ah)->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)) 457 + 458 + #define IS_CHAN_HT(_c) ((_c)->channelFlags & CHANNEL_HT) 459 + 460 + #define IS_CHAN_HT20(_c) (IS_CHAN_HT(_c) && !IS_CHAN_HT40(_c)) 461 + 462 + #define IS_CHAN_HT40(_c) \ 463 + (!!((_c)->channelFlags & (CHANNEL_HT40PLUS | CHANNEL_HT40MINUS))) 464 + 465 + #define IS_CHAN_HT40PLUS(_c) ((_c)->channelFlags & CHANNEL_HT40PLUS) 466 + #define IS_CHAN_HT40MINUS(_c) ((_c)->channelFlags & CHANNEL_HT40MINUS) 435 467 436 468 enum ath9k_power_mode { 437 469 ATH9K_PM_AWAKE = 0, ··· 1003 1033 void ath9k_hw_set_tsfadjust(struct ath_hw *ah, bool set); 1004 1034 void ath9k_hw_init_global_settings(struct ath_hw *ah); 1005 1035 u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah); 1006 - void ath9k_hw_set11nmac2040(struct ath_hw *ah); 1036 + void ath9k_hw_set11nmac2040(struct ath_hw *ah, struct ath9k_channel *chan); 1007 1037 void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); 1008 1038 void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, 1009 1039 const struct ath9k_beacon_state *bs);
+58 -25
drivers/net/wireless/ath/ath9k/init.c
··· 347 347 { 348 348 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 349 349 u8 *ds; 350 - struct ath_buf *bf; 351 350 int i, bsize, desc_len; 352 351 353 352 ath_dbg(common, CONFIG, "%s DMA: %u buffers %u desc/buf\n", ··· 398 399 ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); 399 400 400 401 /* allocate buffers */ 401 - bsize = sizeof(struct ath_buf) * nbuf; 402 - bf = devm_kzalloc(sc->dev, bsize, GFP_KERNEL); 403 - if (!bf) 404 - return -ENOMEM; 402 + if (is_tx) { 403 + struct ath_buf *bf; 405 404 406 - for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) { 407 - bf->bf_desc = ds; 408 - bf->bf_daddr = DS2PHYS(dd, ds); 405 + bsize = sizeof(struct ath_buf) * nbuf; 406 + bf = devm_kzalloc(sc->dev, bsize, GFP_KERNEL); 407 + if (!bf) 408 + return -ENOMEM; 409 409 410 - if (!(sc->sc_ah->caps.hw_caps & 411 - ATH9K_HW_CAP_4KB_SPLITTRANS)) { 412 - /* 413 - * Skip descriptor addresses which can cause 4KB 414 - * boundary crossing (addr + length) with a 32 dword 415 - * descriptor fetch. 416 - */ 417 - while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { 418 - BUG_ON((caddr_t) bf->bf_desc >= 419 - ((caddr_t) dd->dd_desc + 420 - dd->dd_desc_len)); 410 + for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) { 411 + bf->bf_desc = ds; 412 + bf->bf_daddr = DS2PHYS(dd, ds); 421 413 422 - ds += (desc_len * ndesc); 423 - bf->bf_desc = ds; 424 - bf->bf_daddr = DS2PHYS(dd, ds); 414 + if (!(sc->sc_ah->caps.hw_caps & 415 + ATH9K_HW_CAP_4KB_SPLITTRANS)) { 416 + /* 417 + * Skip descriptor addresses which can cause 4KB 418 + * boundary crossing (addr + length) with a 32 dword 419 + * descriptor fetch. 420 + */ 421 + while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { 422 + BUG_ON((caddr_t) bf->bf_desc >= 423 + ((caddr_t) dd->dd_desc + 424 + dd->dd_desc_len)); 425 + 426 + ds += (desc_len * ndesc); 427 + bf->bf_desc = ds; 428 + bf->bf_daddr = DS2PHYS(dd, ds); 429 + } 425 430 } 431 + list_add_tail(&bf->list, head); 426 432 } 427 - list_add_tail(&bf->list, head); 433 + } else { 434 + struct ath_rxbuf *bf; 435 + 436 + bsize = sizeof(struct ath_rxbuf) * nbuf; 437 + bf = devm_kzalloc(sc->dev, bsize, GFP_KERNEL); 438 + if (!bf) 439 + return -ENOMEM; 440 + 441 + for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) { 442 + bf->bf_desc = ds; 443 + bf->bf_daddr = DS2PHYS(dd, ds); 444 + 445 + if (!(sc->sc_ah->caps.hw_caps & 446 + ATH9K_HW_CAP_4KB_SPLITTRANS)) { 447 + /* 448 + * Skip descriptor addresses which can cause 4KB 449 + * boundary crossing (addr + length) with a 32 dword 450 + * descriptor fetch. 451 + */ 452 + while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { 453 + BUG_ON((caddr_t) bf->bf_desc >= 454 + ((caddr_t) dd->dd_desc + 455 + dd->dd_desc_len)); 456 + 457 + ds += (desc_len * ndesc); 458 + bf->bf_desc = ds; 459 + bf->bf_daddr = DS2PHYS(dd, ds); 460 + } 461 + } 462 + list_add_tail(&bf->list, head); 463 + } 428 464 } 429 465 return 0; 430 466 } ··· 471 437 sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah); 472 438 sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); 473 439 474 - sc->config.cabqReadytime = ATH_CABQ_READY_TIME; 475 440 ath_cabq_update(sc); 476 441 477 442 sc->tx.uapsdq = ath_txq_setup(sc, ATH9K_TX_QUEUE_UAPSD, 0); ··· 801 768 chan = &sband->channels[i]; 802 769 ah->curchan = &ah->channels[chan->hw_value]; 803 770 cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_HT20); 804 - ath9k_cmn_update_ichannel(ah->curchan, &chandef); 771 + ath9k_cmn_get_channel(sc->hw, ah, &chandef); 805 772 ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true); 806 773 } 807 774 }
+1 -5
drivers/net/wireless/ath/ath9k/mac.c
··· 374 374 bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) 375 375 { 376 376 struct ath_common *common = ath9k_hw_common(ah); 377 - struct ath9k_channel *chan = ah->curchan; 378 377 struct ath9k_tx_queue_info *qi; 379 378 u32 cwMin, chanCwMin, value; 380 379 ··· 386 387 ath_dbg(common, QUEUE, "Reset TX queue: %u\n", q); 387 388 388 389 if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) { 389 - if (chan && IS_CHAN_B(chan)) 390 - chanCwMin = INIT_CWMIN_11B; 391 - else 392 - chanCwMin = INIT_CWMIN; 390 + chanCwMin = INIT_CWMIN; 393 391 394 392 for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1); 395 393 } else
-2
drivers/net/wireless/ath/ath9k/mac.h
··· 603 603 #define ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS 0x00000001 604 604 605 605 #define ATH9K_DECOMP_MASK_SIZE 128 606 - #define ATH9K_READY_TIME_LO_BOUND 50 607 - #define ATH9K_READY_TIME_HI_BOUND 96 608 606 609 607 enum ath9k_pkt_type { 610 608 ATH9K_PKT_TYPE_NORMAL = 0,
+82 -77
drivers/net/wireless/ath/ath9k/main.c
··· 302 302 * by reseting the chip. To accomplish this we must first cleanup any pending 303 303 * DMA, then restart stuff. 304 304 */ 305 - static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, 306 - struct ath9k_channel *hchan) 305 + static int ath_set_channel(struct ath_softc *sc, struct cfg80211_chan_def *chandef) 307 306 { 307 + struct ath_hw *ah = sc->sc_ah; 308 + struct ath_common *common = ath9k_hw_common(ah); 309 + struct ieee80211_hw *hw = sc->hw; 310 + struct ath9k_channel *hchan; 311 + struct ieee80211_channel *chan = chandef->chan; 312 + unsigned long flags; 313 + bool offchannel; 314 + int pos = chan->hw_value; 315 + int old_pos = -1; 308 316 int r; 309 317 310 318 if (test_bit(SC_OP_INVALID, &sc->sc_flags)) 311 319 return -EIO; 312 320 313 - r = ath_reset_internal(sc, hchan); 321 + offchannel = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL); 314 322 315 - return r; 323 + if (ah->curchan) 324 + old_pos = ah->curchan - &ah->channels[0]; 325 + 326 + ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n", 327 + chan->center_freq, chandef->width); 328 + 329 + /* update survey stats for the old channel before switching */ 330 + spin_lock_irqsave(&common->cc_lock, flags); 331 + ath_update_survey_stats(sc); 332 + spin_unlock_irqrestore(&common->cc_lock, flags); 333 + 334 + ath9k_cmn_get_channel(hw, ah, chandef); 335 + 336 + /* 337 + * If the operating channel changes, change the survey in-use flags 338 + * along with it. 339 + * Reset the survey data for the new channel, unless we're switching 340 + * back to the operating channel from an off-channel operation. 341 + */ 342 + if (!offchannel && sc->cur_survey != &sc->survey[pos]) { 343 + if (sc->cur_survey) 344 + sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE; 345 + 346 + sc->cur_survey = &sc->survey[pos]; 347 + 348 + memset(sc->cur_survey, 0, sizeof(struct survey_info)); 349 + sc->cur_survey->filled |= SURVEY_INFO_IN_USE; 350 + } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) { 351 + memset(&sc->survey[pos], 0, sizeof(struct survey_info)); 352 + } 353 + 354 + hchan = &sc->sc_ah->channels[pos]; 355 + r = ath_reset_internal(sc, hchan); 356 + if (r) 357 + return r; 358 + 359 + /* 360 + * The most recent snapshot of channel->noisefloor for the old 361 + * channel is only available after the hardware reset. Copy it to 362 + * the survey stats now. 363 + */ 364 + if (old_pos >= 0) 365 + ath_update_survey_nf(sc, old_pos); 366 + 367 + /* 368 + * Enable radar pulse detection if on a DFS channel. Spectral 369 + * scanning and radar detection can not be used concurrently. 370 + */ 371 + if (hw->conf.radar_enabled) { 372 + u32 rxfilter; 373 + 374 + /* set HW specific DFS configuration */ 375 + ath9k_hw_set_radar_params(ah); 376 + rxfilter = ath9k_hw_getrxfilter(ah); 377 + rxfilter |= ATH9K_RX_FILTER_PHYRADAR | 378 + ATH9K_RX_FILTER_PHYERR; 379 + ath9k_hw_setrxfilter(ah, rxfilter); 380 + ath_dbg(common, DFS, "DFS enabled at freq %d\n", 381 + chan->center_freq); 382 + } else { 383 + /* perform spectral scan if requested. */ 384 + if (test_bit(SC_OP_SCANNING, &sc->sc_flags) && 385 + sc->spectral_mode == SPECTRAL_CHANSCAN) 386 + ath9k_spectral_scan_trigger(hw); 387 + } 388 + 389 + return 0; 316 390 } 317 391 318 392 static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, ··· 675 601 ath9k_ps_wakeup(sc); 676 602 mutex_lock(&sc->mutex); 677 603 678 - init_channel = ath9k_cmn_get_curchannel(hw, ah); 604 + init_channel = ath9k_cmn_get_channel(hw, ah, &hw->conf.chandef); 679 605 680 606 /* Reset SERDES registers */ 681 607 ath9k_hw_configpcipowersave(ah, false); ··· 878 804 } 879 805 880 806 if (!ah->curchan) 881 - ah->curchan = ath9k_cmn_get_curchannel(hw, ah); 807 + ah->curchan = ath9k_cmn_get_channel(hw, ah, &hw->conf.chandef); 882 808 883 809 ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); 884 810 ath9k_hw_phy_disable(ah); ··· 897 823 ath_dbg(common, CONFIG, "Driver halt\n"); 898 824 } 899 825 900 - bool ath9k_uses_beacons(int type) 826 + static bool ath9k_uses_beacons(int type) 901 827 { 902 828 switch (type) { 903 829 case NL80211_IFTYPE_AP: ··· 1282 1208 } 1283 1209 1284 1210 if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) { 1285 - struct ieee80211_channel *curchan = hw->conf.chandef.chan; 1286 - int pos = curchan->hw_value; 1287 - int old_pos = -1; 1288 - unsigned long flags; 1289 - 1290 - if (ah->curchan) 1291 - old_pos = ah->curchan - &ah->channels[0]; 1292 - 1293 - ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n", 1294 - curchan->center_freq, hw->conf.chandef.width); 1295 - 1296 - /* update survey stats for the old channel before switching */ 1297 - spin_lock_irqsave(&common->cc_lock, flags); 1298 - ath_update_survey_stats(sc); 1299 - spin_unlock_irqrestore(&common->cc_lock, flags); 1300 - 1301 - ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos], 1302 - &conf->chandef); 1303 - 1304 - /* 1305 - * If the operating channel changes, change the survey in-use flags 1306 - * along with it. 1307 - * Reset the survey data for the new channel, unless we're switching 1308 - * back to the operating channel from an off-channel operation. 1309 - */ 1310 - if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) && 1311 - sc->cur_survey != &sc->survey[pos]) { 1312 - 1313 - if (sc->cur_survey) 1314 - sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE; 1315 - 1316 - sc->cur_survey = &sc->survey[pos]; 1317 - 1318 - memset(sc->cur_survey, 0, sizeof(struct survey_info)); 1319 - sc->cur_survey->filled |= SURVEY_INFO_IN_USE; 1320 - } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) { 1321 - memset(&sc->survey[pos], 0, sizeof(struct survey_info)); 1322 - } 1323 - 1324 - if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) { 1211 + if (ath_set_channel(sc, &hw->conf.chandef) < 0) { 1325 1212 ath_err(common, "Unable to set channel\n"); 1326 1213 mutex_unlock(&sc->mutex); 1327 1214 ath9k_ps_restore(sc); 1328 1215 return -EINVAL; 1329 - } 1330 - 1331 - /* 1332 - * The most recent snapshot of channel->noisefloor for the old 1333 - * channel is only available after the hardware reset. Copy it to 1334 - * the survey stats now. 1335 - */ 1336 - if (old_pos >= 0) 1337 - ath_update_survey_nf(sc, old_pos); 1338 - 1339 - /* 1340 - * Enable radar pulse detection if on a DFS channel. Spectral 1341 - * scanning and radar detection can not be used concurrently. 1342 - */ 1343 - if (hw->conf.radar_enabled) { 1344 - u32 rxfilter; 1345 - 1346 - /* set HW specific DFS configuration */ 1347 - ath9k_hw_set_radar_params(ah); 1348 - rxfilter = ath9k_hw_getrxfilter(ah); 1349 - rxfilter |= ATH9K_RX_FILTER_PHYRADAR | 1350 - ATH9K_RX_FILTER_PHYERR; 1351 - ath9k_hw_setrxfilter(ah, rxfilter); 1352 - ath_dbg(common, DFS, "DFS enabled at freq %d\n", 1353 - curchan->center_freq); 1354 - } else { 1355 - /* perform spectral scan if requested. */ 1356 - if (test_bit(SC_OP_SCANNING, &sc->sc_flags) && 1357 - sc->spectral_mode == SPECTRAL_CHANSCAN) 1358 - ath9k_spectral_scan_trigger(hw); 1359 1216 } 1360 1217 } 1361 1218
+4 -4
drivers/net/wireless/ath/ath9k/mci.c
··· 661 661 chan_start = wlan_chan - 10; 662 662 chan_end = wlan_chan + 10; 663 663 664 - if (chan->chanmode == CHANNEL_G_HT40PLUS) 664 + if (IS_CHAN_HT40PLUS(chan)) 665 665 chan_end += 20; 666 - else if (chan->chanmode == CHANNEL_G_HT40MINUS) 666 + else if (IS_CHAN_HT40MINUS(chan)) 667 667 chan_start -= 20; 668 668 669 669 /* adjust side band */ ··· 707 707 708 708 if (setchannel) { 709 709 struct ath9k_hw_cal_data *caldata = &sc->caldata; 710 - if ((caldata->chanmode == CHANNEL_G_HT40PLUS) && 710 + if (IS_CHAN_HT40PLUS(ah->curchan) && 711 711 (ah->curchan->channel > caldata->channel) && 712 712 (ah->curchan->channel <= caldata->channel + 20)) 713 713 return; 714 - if ((caldata->chanmode == CHANNEL_G_HT40MINUS) && 714 + if (IS_CHAN_HT40MINUS(ah->curchan) && 715 715 (ah->curchan->channel < caldata->channel) && 716 716 (ah->curchan->channel >= caldata->channel - 20)) 717 717 return;
+24 -24
drivers/net/wireless/ath/ath9k/recv.c
··· 19 19 #include "ath9k.h" 20 20 #include "ar9003_mac.h" 21 21 22 - #define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb)) 22 + #define SKB_CB_ATHBUF(__skb) (*((struct ath_rxbuf **)__skb->cb)) 23 23 24 24 static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) 25 25 { ··· 35 35 * buffer (or rx fifo). This can incorrectly acknowledge packets 36 36 * to a sender if last desc is self-linked. 37 37 */ 38 - static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) 38 + static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf) 39 39 { 40 40 struct ath_hw *ah = sc->sc_ah; 41 41 struct ath_common *common = ath9k_hw_common(ah); ··· 68 68 sc->rx.rxlink = &ds->ds_link; 69 69 } 70 70 71 - static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_buf *bf) 71 + static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf) 72 72 { 73 73 if (sc->rx.buf_hold) 74 74 ath_rx_buf_link(sc, sc->rx.buf_hold); ··· 112 112 struct ath_hw *ah = sc->sc_ah; 113 113 struct ath_rx_edma *rx_edma; 114 114 struct sk_buff *skb; 115 - struct ath_buf *bf; 115 + struct ath_rxbuf *bf; 116 116 117 117 rx_edma = &sc->rx.rx_edma[qtype]; 118 118 if (skb_queue_len(&rx_edma->rx_fifo) >= rx_edma->rx_fifo_hwsize) 119 119 return false; 120 120 121 - bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); 121 + bf = list_first_entry(&sc->rx.rxbuf, struct ath_rxbuf, list); 122 122 list_del_init(&bf->list); 123 123 124 124 skb = bf->bf_mpdu; ··· 138 138 enum ath9k_rx_qtype qtype) 139 139 { 140 140 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 141 - struct ath_buf *bf, *tbf; 141 + struct ath_rxbuf *bf, *tbf; 142 142 143 143 if (list_empty(&sc->rx.rxbuf)) { 144 144 ath_dbg(common, QUEUE, "No free rx buf available\n"); ··· 154 154 static void ath_rx_remove_buffer(struct ath_softc *sc, 155 155 enum ath9k_rx_qtype qtype) 156 156 { 157 - struct ath_buf *bf; 157 + struct ath_rxbuf *bf; 158 158 struct ath_rx_edma *rx_edma; 159 159 struct sk_buff *skb; 160 160 ··· 171 171 { 172 172 struct ath_hw *ah = sc->sc_ah; 173 173 struct ath_common *common = ath9k_hw_common(ah); 174 - struct ath_buf *bf; 174 + struct ath_rxbuf *bf; 175 175 176 176 ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP); 177 177 ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP); ··· 199 199 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 200 200 struct ath_hw *ah = sc->sc_ah; 201 201 struct sk_buff *skb; 202 - struct ath_buf *bf; 202 + struct ath_rxbuf *bf; 203 203 int error = 0, i; 204 204 u32 size; 205 205 ··· 211 211 ath_rx_edma_init_queue(&sc->rx.rx_edma[ATH9K_RX_QUEUE_HP], 212 212 ah->caps.rx_hp_qdepth); 213 213 214 - size = sizeof(struct ath_buf) * nbufs; 214 + size = sizeof(struct ath_rxbuf) * nbufs; 215 215 bf = devm_kzalloc(sc->dev, size, GFP_KERNEL); 216 216 if (!bf) 217 217 return -ENOMEM; ··· 271 271 { 272 272 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 273 273 struct sk_buff *skb; 274 - struct ath_buf *bf; 274 + struct ath_rxbuf *bf; 275 275 int error = 0; 276 276 277 277 spin_lock_init(&sc->sc_pcu_lock); ··· 332 332 struct ath_hw *ah = sc->sc_ah; 333 333 struct ath_common *common = ath9k_hw_common(ah); 334 334 struct sk_buff *skb; 335 - struct ath_buf *bf; 335 + struct ath_rxbuf *bf; 336 336 337 337 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { 338 338 ath_rx_edma_cleanup(sc); ··· 427 427 int ath_startrecv(struct ath_softc *sc) 428 428 { 429 429 struct ath_hw *ah = sc->sc_ah; 430 - struct ath_buf *bf, *tbf; 430 + struct ath_rxbuf *bf, *tbf; 431 431 432 432 if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { 433 433 ath_edma_start_recv(sc); ··· 447 447 if (list_empty(&sc->rx.rxbuf)) 448 448 goto start_recv; 449 449 450 - bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); 450 + bf = list_first_entry(&sc->rx.rxbuf, struct ath_rxbuf, list); 451 451 ath9k_hw_putrxbuf(ah, bf->bf_daddr); 452 452 ath9k_hw_rxena(ah); 453 453 ··· 603 603 static bool ath_edma_get_buffers(struct ath_softc *sc, 604 604 enum ath9k_rx_qtype qtype, 605 605 struct ath_rx_status *rs, 606 - struct ath_buf **dest) 606 + struct ath_rxbuf **dest) 607 607 { 608 608 struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype]; 609 609 struct ath_hw *ah = sc->sc_ah; 610 610 struct ath_common *common = ath9k_hw_common(ah); 611 611 struct sk_buff *skb; 612 - struct ath_buf *bf; 612 + struct ath_rxbuf *bf; 613 613 int ret; 614 614 615 615 skb = skb_peek(&rx_edma->rx_fifo); ··· 653 653 return true; 654 654 } 655 655 656 - static struct ath_buf *ath_edma_get_next_rx_buf(struct ath_softc *sc, 656 + static struct ath_rxbuf *ath_edma_get_next_rx_buf(struct ath_softc *sc, 657 657 struct ath_rx_status *rs, 658 658 enum ath9k_rx_qtype qtype) 659 659 { 660 - struct ath_buf *bf = NULL; 660 + struct ath_rxbuf *bf = NULL; 661 661 662 662 while (ath_edma_get_buffers(sc, qtype, rs, &bf)) { 663 663 if (!bf) ··· 668 668 return NULL; 669 669 } 670 670 671 - static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, 671 + static struct ath_rxbuf *ath_get_next_rx_buf(struct ath_softc *sc, 672 672 struct ath_rx_status *rs) 673 673 { 674 674 struct ath_hw *ah = sc->sc_ah; 675 675 struct ath_common *common = ath9k_hw_common(ah); 676 676 struct ath_desc *ds; 677 - struct ath_buf *bf; 677 + struct ath_rxbuf *bf; 678 678 int ret; 679 679 680 680 if (list_empty(&sc->rx.rxbuf)) { ··· 682 682 return NULL; 683 683 } 684 684 685 - bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); 685 + bf = list_first_entry(&sc->rx.rxbuf, struct ath_rxbuf, list); 686 686 if (bf == sc->rx.buf_hold) 687 687 return NULL; 688 688 ··· 702 702 ret = ath9k_hw_rxprocdesc(ah, ds, rs); 703 703 if (ret == -EINPROGRESS) { 704 704 struct ath_rx_status trs; 705 - struct ath_buf *tbf; 705 + struct ath_rxbuf *tbf; 706 706 struct ath_desc *tds; 707 707 708 708 memset(&trs, 0, sizeof(trs)); ··· 711 711 return NULL; 712 712 } 713 713 714 - tbf = list_entry(bf->list.next, struct ath_buf, list); 714 + tbf = list_entry(bf->list.next, struct ath_rxbuf, list); 715 715 716 716 /* 717 717 * On some hardware the descriptor status words could ··· 1308 1308 1309 1309 int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) 1310 1310 { 1311 - struct ath_buf *bf; 1311 + struct ath_rxbuf *bf; 1312 1312 struct sk_buff *skb = NULL, *requeue_skb, *hdr_skb; 1313 1313 struct ieee80211_rx_status *rxs; 1314 1314 struct ath_hw *ah = sc->sc_ah;
+2 -10
drivers/net/wireless/ath/ath9k/xmit.c
··· 1704 1704 int qnum = sc->beacon.cabq->axq_qnum; 1705 1705 1706 1706 ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi); 1707 - /* 1708 - * Ensure the readytime % is within the bounds. 1709 - */ 1710 - if (sc->config.cabqReadytime < ATH9K_READY_TIME_LO_BOUND) 1711 - sc->config.cabqReadytime = ATH9K_READY_TIME_LO_BOUND; 1712 - else if (sc->config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND) 1713 - sc->config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND; 1714 1707 1715 1708 qi.tqi_readyTime = (cur_conf->beacon_interval * 1716 - sc->config.cabqReadytime) / 100; 1709 + ATH_CABQ_READY_TIME) / 100; 1717 1710 ath_txq_update(sc, qnum, &qi); 1718 1711 1719 1712 return 0; ··· 2030 2037 struct ath_hw *ah = sc->sc_ah; 2031 2038 struct ath9k_channel *curchan = ah->curchan; 2032 2039 2033 - if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && 2034 - (curchan->channelFlags & CHANNEL_5GHZ) && 2040 + if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && IS_CHAN_5GHZ(curchan) && 2035 2041 (chainmask == 0x7) && (rate < 0x90)) 2036 2042 return 0x3; 2037 2043 else if (AR_SREV_9462(ah) && ath9k_hw_btcoex_is_enabled(ah) &&
+16
drivers/net/wireless/ath/wcn36xx/Kconfig
··· 1 + config WCN36XX 2 + tristate "Qualcomm Atheros WCN3660/3680 support" 3 + depends on MAC80211 && HAS_DMA 4 + ---help--- 5 + This module adds support for wireless adapters based on 6 + Qualcomm Atheros WCN3660 and WCN3680 mobile chipsets. 7 + 8 + If you choose to build a module, it'll be called wcn36xx. 9 + 10 + config WCN36XX_DEBUGFS 11 + bool "WCN36XX debugfs support" 12 + depends on WCN36XX 13 + ---help--- 14 + Enabled debugfs support 15 + 16 + If unsure, say Y to make it easier to debug problems.
+7
drivers/net/wireless/ath/wcn36xx/Makefile
··· 1 + obj-$(CONFIG_WCN36XX) := wcn36xx.o 2 + wcn36xx-y += main.o \ 3 + dxe.o \ 4 + txrx.o \ 5 + smd.o \ 6 + pmc.o \ 7 + debug.o
+181
drivers/net/wireless/ath/wcn36xx/debug.c
··· 1 + /* 2 + * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> 3 + * 4 + * Permission to use, copy, modify, and/or distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 11 + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 13 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 14 + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + 17 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 18 + 19 + #include <linux/debugfs.h> 20 + #include <linux/uaccess.h> 21 + #include "wcn36xx.h" 22 + #include "debug.h" 23 + #include "pmc.h" 24 + 25 + #ifdef CONFIG_WCN36XX_DEBUGFS 26 + 27 + static ssize_t read_file_bool_bmps(struct file *file, char __user *user_buf, 28 + size_t count, loff_t *ppos) 29 + { 30 + struct wcn36xx *wcn = file->private_data; 31 + struct wcn36xx_vif *vif_priv = NULL; 32 + struct ieee80211_vif *vif = NULL; 33 + char buf[3]; 34 + 35 + list_for_each_entry(vif_priv, &wcn->vif_list, list) { 36 + vif = container_of((void *)vif_priv, 37 + struct ieee80211_vif, 38 + drv_priv); 39 + if (NL80211_IFTYPE_STATION == vif->type) { 40 + if (vif_priv->pw_state == WCN36XX_BMPS) 41 + buf[0] = '1'; 42 + else 43 + buf[0] = '0'; 44 + break; 45 + } 46 + } 47 + buf[1] = '\n'; 48 + buf[2] = 0x00; 49 + 50 + return simple_read_from_buffer(user_buf, count, ppos, buf, 2); 51 + } 52 + 53 + static ssize_t write_file_bool_bmps(struct file *file, 54 + const char __user *user_buf, 55 + size_t count, loff_t *ppos) 56 + { 57 + struct wcn36xx *wcn = file->private_data; 58 + struct wcn36xx_vif *vif_priv = NULL; 59 + struct ieee80211_vif *vif = NULL; 60 + 61 + char buf[32]; 62 + int buf_size; 63 + 64 + buf_size = min(count, (sizeof(buf)-1)); 65 + if (copy_from_user(buf, user_buf, buf_size)) 66 + return -EFAULT; 67 + 68 + switch (buf[0]) { 69 + case 'y': 70 + case 'Y': 71 + case '1': 72 + list_for_each_entry(vif_priv, &wcn->vif_list, list) { 73 + vif = container_of((void *)vif_priv, 74 + struct ieee80211_vif, 75 + drv_priv); 76 + if (NL80211_IFTYPE_STATION == vif->type) { 77 + wcn36xx_enable_keep_alive_null_packet(wcn, vif); 78 + wcn36xx_pmc_enter_bmps_state(wcn, vif); 79 + } 80 + } 81 + break; 82 + case 'n': 83 + case 'N': 84 + case '0': 85 + list_for_each_entry(vif_priv, &wcn->vif_list, list) { 86 + vif = container_of((void *)vif_priv, 87 + struct ieee80211_vif, 88 + drv_priv); 89 + if (NL80211_IFTYPE_STATION == vif->type) 90 + wcn36xx_pmc_exit_bmps_state(wcn, vif); 91 + } 92 + break; 93 + } 94 + 95 + return count; 96 + } 97 + 98 + static const struct file_operations fops_wcn36xx_bmps = { 99 + .open = simple_open, 100 + .read = read_file_bool_bmps, 101 + .write = write_file_bool_bmps, 102 + }; 103 + 104 + static ssize_t write_file_dump(struct file *file, 105 + const char __user *user_buf, 106 + size_t count, loff_t *ppos) 107 + { 108 + struct wcn36xx *wcn = file->private_data; 109 + char buf[255], *tmp; 110 + int buf_size; 111 + u32 arg[WCN36xx_MAX_DUMP_ARGS]; 112 + int i; 113 + 114 + memset(buf, 0, sizeof(buf)); 115 + memset(arg, 0, sizeof(arg)); 116 + 117 + buf_size = min(count, (sizeof(buf) - 1)); 118 + if (copy_from_user(buf, user_buf, buf_size)) 119 + return -EFAULT; 120 + 121 + tmp = buf; 122 + 123 + for (i = 0; i < WCN36xx_MAX_DUMP_ARGS; i++) { 124 + char *begin; 125 + begin = strsep(&tmp, " "); 126 + if (begin == NULL) 127 + break; 128 + 129 + if (kstrtoul(begin, 0, (unsigned long *)(arg + i)) != 0) 130 + break; 131 + } 132 + 133 + wcn36xx_info("DUMP args is %d %d %d %d %d\n", arg[0], arg[1], arg[2], 134 + arg[3], arg[4]); 135 + wcn36xx_smd_dump_cmd_req(wcn, arg[0], arg[1], arg[2], arg[3], arg[4]); 136 + 137 + return count; 138 + } 139 + 140 + static const struct file_operations fops_wcn36xx_dump = { 141 + .open = simple_open, 142 + .write = write_file_dump, 143 + }; 144 + 145 + #define ADD_FILE(name, mode, fop, priv_data) \ 146 + do { \ 147 + struct dentry *d; \ 148 + d = debugfs_create_file(__stringify(name), \ 149 + mode, dfs->rootdir, \ 150 + priv_data, fop); \ 151 + dfs->file_##name.dentry = d; \ 152 + if (IS_ERR(d)) { \ 153 + wcn36xx_warn("Create the debugfs entry failed");\ 154 + dfs->file_##name.dentry = NULL; \ 155 + } \ 156 + } while (0) 157 + 158 + 159 + void wcn36xx_debugfs_init(struct wcn36xx *wcn) 160 + { 161 + struct wcn36xx_dfs_entry *dfs = &wcn->dfs; 162 + 163 + dfs->rootdir = debugfs_create_dir(KBUILD_MODNAME, 164 + wcn->hw->wiphy->debugfsdir); 165 + if (IS_ERR(dfs->rootdir)) { 166 + wcn36xx_warn("Create the debugfs failed\n"); 167 + dfs->rootdir = NULL; 168 + } 169 + 170 + ADD_FILE(bmps_switcher, S_IRUSR | S_IWUSR, 171 + &fops_wcn36xx_bmps, wcn); 172 + ADD_FILE(dump, S_IWUSR, &fops_wcn36xx_dump, wcn); 173 + } 174 + 175 + void wcn36xx_debugfs_exit(struct wcn36xx *wcn) 176 + { 177 + struct wcn36xx_dfs_entry *dfs = &wcn->dfs; 178 + debugfs_remove_recursive(dfs->rootdir); 179 + } 180 + 181 + #endif /* CONFIG_WCN36XX_DEBUGFS */
+49
drivers/net/wireless/ath/wcn36xx/debug.h
··· 1 + /* 2 + * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> 3 + * 4 + * Permission to use, copy, modify, and/or distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 11 + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 13 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 14 + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + 17 + #ifndef _WCN36XX_DEBUG_H_ 18 + #define _WCN36XX_DEBUG_H_ 19 + 20 + #include <linux/kernel.h> 21 + 22 + #define WCN36xx_MAX_DUMP_ARGS 5 23 + 24 + #ifdef CONFIG_WCN36XX_DEBUGFS 25 + struct wcn36xx_dfs_file { 26 + struct dentry *dentry; 27 + u32 value; 28 + }; 29 + 30 + struct wcn36xx_dfs_entry { 31 + struct dentry *rootdir; 32 + struct wcn36xx_dfs_file file_bmps_switcher; 33 + struct wcn36xx_dfs_file file_dump; 34 + }; 35 + 36 + void wcn36xx_debugfs_init(struct wcn36xx *wcn); 37 + void wcn36xx_debugfs_exit(struct wcn36xx *wcn); 38 + 39 + #else 40 + static inline void wcn36xx_debugfs_init(struct wcn36xx *wcn) 41 + { 42 + } 43 + static inline void wcn36xx_debugfs_exit(struct wcn36xx *wcn) 44 + { 45 + } 46 + 47 + #endif /* CONFIG_WCN36XX_DEBUGFS */ 48 + 49 + #endif /* _WCN36XX_DEBUG_H_ */
+805
drivers/net/wireless/ath/wcn36xx/dxe.c
··· 1 + /* 2 + * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> 3 + * 4 + * Permission to use, copy, modify, and/or distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 11 + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 13 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 14 + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + 17 + /* DXE - DMA transfer engine 18 + * we have 2 channels(High prio and Low prio) for TX and 2 channels for RX. 19 + * through low channels data packets are transfered 20 + * through high channels managment packets are transfered 21 + */ 22 + 23 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 24 + 25 + #include <linux/interrupt.h> 26 + #include "wcn36xx.h" 27 + #include "txrx.h" 28 + 29 + void *wcn36xx_dxe_get_next_bd(struct wcn36xx *wcn, bool is_low) 30 + { 31 + struct wcn36xx_dxe_ch *ch = is_low ? 32 + &wcn->dxe_tx_l_ch : 33 + &wcn->dxe_tx_h_ch; 34 + 35 + return ch->head_blk_ctl->bd_cpu_addr; 36 + } 37 + 38 + static void wcn36xx_dxe_write_register(struct wcn36xx *wcn, int addr, int data) 39 + { 40 + wcn36xx_dbg(WCN36XX_DBG_DXE, 41 + "wcn36xx_dxe_write_register: addr=%x, data=%x\n", 42 + addr, data); 43 + 44 + writel(data, wcn->mmio + addr); 45 + } 46 + 47 + static void wcn36xx_dxe_read_register(struct wcn36xx *wcn, int addr, int *data) 48 + { 49 + *data = readl(wcn->mmio + addr); 50 + 51 + wcn36xx_dbg(WCN36XX_DBG_DXE, 52 + "wcn36xx_dxe_read_register: addr=%x, data=%x\n", 53 + addr, *data); 54 + } 55 + 56 + static void wcn36xx_dxe_free_ctl_block(struct wcn36xx_dxe_ch *ch) 57 + { 58 + struct wcn36xx_dxe_ctl *ctl = ch->head_blk_ctl, *next; 59 + int i; 60 + 61 + for (i = 0; i < ch->desc_num && ctl; i++) { 62 + next = ctl->next; 63 + kfree(ctl); 64 + ctl = next; 65 + } 66 + } 67 + 68 + static int wcn36xx_dxe_allocate_ctl_block(struct wcn36xx_dxe_ch *ch) 69 + { 70 + struct wcn36xx_dxe_ctl *prev_ctl = NULL; 71 + struct wcn36xx_dxe_ctl *cur_ctl = NULL; 72 + int i; 73 + 74 + for (i = 0; i < ch->desc_num; i++) { 75 + cur_ctl = kzalloc(sizeof(*cur_ctl), GFP_KERNEL); 76 + if (!cur_ctl) 77 + goto out_fail; 78 + 79 + cur_ctl->ctl_blk_order = i; 80 + if (i == 0) { 81 + ch->head_blk_ctl = cur_ctl; 82 + ch->tail_blk_ctl = cur_ctl; 83 + } else if (ch->desc_num - 1 == i) { 84 + prev_ctl->next = cur_ctl; 85 + cur_ctl->next = ch->head_blk_ctl; 86 + } else { 87 + prev_ctl->next = cur_ctl; 88 + } 89 + prev_ctl = cur_ctl; 90 + } 91 + 92 + return 0; 93 + 94 + out_fail: 95 + wcn36xx_dxe_free_ctl_block(ch); 96 + return -ENOMEM; 97 + } 98 + 99 + int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn) 100 + { 101 + int ret; 102 + 103 + wcn->dxe_tx_l_ch.ch_type = WCN36XX_DXE_CH_TX_L; 104 + wcn->dxe_tx_h_ch.ch_type = WCN36XX_DXE_CH_TX_H; 105 + wcn->dxe_rx_l_ch.ch_type = WCN36XX_DXE_CH_RX_L; 106 + wcn->dxe_rx_h_ch.ch_type = WCN36XX_DXE_CH_RX_H; 107 + 108 + wcn->dxe_tx_l_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_TX_L; 109 + wcn->dxe_tx_h_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_TX_H; 110 + wcn->dxe_rx_l_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_RX_L; 111 + wcn->dxe_rx_h_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_RX_H; 112 + 113 + wcn->dxe_tx_l_ch.dxe_wq = WCN36XX_DXE_WQ_TX_L; 114 + wcn->dxe_tx_h_ch.dxe_wq = WCN36XX_DXE_WQ_TX_H; 115 + 116 + wcn->dxe_tx_l_ch.ctrl_bd = WCN36XX_DXE_CTRL_TX_L_BD; 117 + wcn->dxe_tx_h_ch.ctrl_bd = WCN36XX_DXE_CTRL_TX_H_BD; 118 + 119 + wcn->dxe_tx_l_ch.ctrl_skb = WCN36XX_DXE_CTRL_TX_L_SKB; 120 + wcn->dxe_tx_h_ch.ctrl_skb = WCN36XX_DXE_CTRL_TX_H_SKB; 121 + 122 + wcn->dxe_tx_l_ch.reg_ctrl = WCN36XX_DXE_REG_CTL_TX_L; 123 + wcn->dxe_tx_h_ch.reg_ctrl = WCN36XX_DXE_REG_CTL_TX_H; 124 + 125 + wcn->dxe_tx_l_ch.def_ctrl = WCN36XX_DXE_CH_DEFAULT_CTL_TX_L; 126 + wcn->dxe_tx_h_ch.def_ctrl = WCN36XX_DXE_CH_DEFAULT_CTL_TX_H; 127 + 128 + /* DXE control block allocation */ 129 + ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_tx_l_ch); 130 + if (ret) 131 + goto out_err; 132 + ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_tx_h_ch); 133 + if (ret) 134 + goto out_err; 135 + ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_rx_l_ch); 136 + if (ret) 137 + goto out_err; 138 + ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_rx_h_ch); 139 + if (ret) 140 + goto out_err; 141 + 142 + /* Initialize SMSM state Clear TX Enable RING EMPTY STATE */ 143 + ret = wcn->ctrl_ops->smsm_change_state( 144 + WCN36XX_SMSM_WLAN_TX_ENABLE, 145 + WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY); 146 + 147 + return 0; 148 + 149 + out_err: 150 + wcn36xx_err("Failed to allocate DXE control blocks\n"); 151 + wcn36xx_dxe_free_ctl_blks(wcn); 152 + return -ENOMEM; 153 + } 154 + 155 + void wcn36xx_dxe_free_ctl_blks(struct wcn36xx *wcn) 156 + { 157 + wcn36xx_dxe_free_ctl_block(&wcn->dxe_tx_l_ch); 158 + wcn36xx_dxe_free_ctl_block(&wcn->dxe_tx_h_ch); 159 + wcn36xx_dxe_free_ctl_block(&wcn->dxe_rx_l_ch); 160 + wcn36xx_dxe_free_ctl_block(&wcn->dxe_rx_h_ch); 161 + } 162 + 163 + static int wcn36xx_dxe_init_descs(struct wcn36xx_dxe_ch *wcn_ch) 164 + { 165 + struct wcn36xx_dxe_desc *cur_dxe = NULL; 166 + struct wcn36xx_dxe_desc *prev_dxe = NULL; 167 + struct wcn36xx_dxe_ctl *cur_ctl = NULL; 168 + size_t size; 169 + int i; 170 + 171 + size = wcn_ch->desc_num * sizeof(struct wcn36xx_dxe_desc); 172 + wcn_ch->cpu_addr = dma_alloc_coherent(NULL, size, &wcn_ch->dma_addr, 173 + GFP_KERNEL); 174 + if (!wcn_ch->cpu_addr) 175 + return -ENOMEM; 176 + 177 + memset(wcn_ch->cpu_addr, 0, size); 178 + 179 + cur_dxe = (struct wcn36xx_dxe_desc *)wcn_ch->cpu_addr; 180 + cur_ctl = wcn_ch->head_blk_ctl; 181 + 182 + for (i = 0; i < wcn_ch->desc_num; i++) { 183 + cur_ctl->desc = cur_dxe; 184 + cur_ctl->desc_phy_addr = wcn_ch->dma_addr + 185 + i * sizeof(struct wcn36xx_dxe_desc); 186 + 187 + switch (wcn_ch->ch_type) { 188 + case WCN36XX_DXE_CH_TX_L: 189 + cur_dxe->ctrl = WCN36XX_DXE_CTRL_TX_L; 190 + cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_L; 191 + break; 192 + case WCN36XX_DXE_CH_TX_H: 193 + cur_dxe->ctrl = WCN36XX_DXE_CTRL_TX_H; 194 + cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_H; 195 + break; 196 + case WCN36XX_DXE_CH_RX_L: 197 + cur_dxe->ctrl = WCN36XX_DXE_CTRL_RX_L; 198 + cur_dxe->src_addr_l = WCN36XX_DXE_WQ_RX_L; 199 + break; 200 + case WCN36XX_DXE_CH_RX_H: 201 + cur_dxe->ctrl = WCN36XX_DXE_CTRL_RX_H; 202 + cur_dxe->src_addr_l = WCN36XX_DXE_WQ_RX_H; 203 + break; 204 + } 205 + if (0 == i) { 206 + cur_dxe->phy_next_l = 0; 207 + } else if ((0 < i) && (i < wcn_ch->desc_num - 1)) { 208 + prev_dxe->phy_next_l = 209 + cur_ctl->desc_phy_addr; 210 + } else if (i == (wcn_ch->desc_num - 1)) { 211 + prev_dxe->phy_next_l = 212 + cur_ctl->desc_phy_addr; 213 + cur_dxe->phy_next_l = 214 + wcn_ch->head_blk_ctl->desc_phy_addr; 215 + } 216 + cur_ctl = cur_ctl->next; 217 + prev_dxe = cur_dxe; 218 + cur_dxe++; 219 + } 220 + 221 + return 0; 222 + } 223 + 224 + static void wcn36xx_dxe_init_tx_bd(struct wcn36xx_dxe_ch *ch, 225 + struct wcn36xx_dxe_mem_pool *pool) 226 + { 227 + int i, chunk_size = pool->chunk_size; 228 + dma_addr_t bd_phy_addr = pool->phy_addr; 229 + void *bd_cpu_addr = pool->virt_addr; 230 + struct wcn36xx_dxe_ctl *cur = ch->head_blk_ctl; 231 + 232 + for (i = 0; i < ch->desc_num; i++) { 233 + /* Only every second dxe needs a bd pointer, 234 + the other will point to the skb data */ 235 + if (!(i & 1)) { 236 + cur->bd_phy_addr = bd_phy_addr; 237 + cur->bd_cpu_addr = bd_cpu_addr; 238 + bd_phy_addr += chunk_size; 239 + bd_cpu_addr += chunk_size; 240 + } else { 241 + cur->bd_phy_addr = 0; 242 + cur->bd_cpu_addr = NULL; 243 + } 244 + cur = cur->next; 245 + } 246 + } 247 + 248 + static int wcn36xx_dxe_enable_ch_int(struct wcn36xx *wcn, u16 wcn_ch) 249 + { 250 + int reg_data = 0; 251 + 252 + wcn36xx_dxe_read_register(wcn, 253 + WCN36XX_DXE_INT_MASK_REG, 254 + &reg_data); 255 + 256 + reg_data |= wcn_ch; 257 + 258 + wcn36xx_dxe_write_register(wcn, 259 + WCN36XX_DXE_INT_MASK_REG, 260 + (int)reg_data); 261 + return 0; 262 + } 263 + 264 + static int wcn36xx_dxe_fill_skb(struct wcn36xx_dxe_ctl *ctl) 265 + { 266 + struct wcn36xx_dxe_desc *dxe = ctl->desc; 267 + struct sk_buff *skb; 268 + 269 + skb = alloc_skb(WCN36XX_PKT_SIZE, GFP_ATOMIC); 270 + if (skb == NULL) 271 + return -ENOMEM; 272 + 273 + dxe->dst_addr_l = dma_map_single(NULL, 274 + skb_tail_pointer(skb), 275 + WCN36XX_PKT_SIZE, 276 + DMA_FROM_DEVICE); 277 + ctl->skb = skb; 278 + 279 + return 0; 280 + } 281 + 282 + static int wcn36xx_dxe_ch_alloc_skb(struct wcn36xx *wcn, 283 + struct wcn36xx_dxe_ch *wcn_ch) 284 + { 285 + int i; 286 + struct wcn36xx_dxe_ctl *cur_ctl = NULL; 287 + 288 + cur_ctl = wcn_ch->head_blk_ctl; 289 + 290 + for (i = 0; i < wcn_ch->desc_num; i++) { 291 + wcn36xx_dxe_fill_skb(cur_ctl); 292 + cur_ctl = cur_ctl->next; 293 + } 294 + 295 + return 0; 296 + } 297 + 298 + static void wcn36xx_dxe_ch_free_skbs(struct wcn36xx *wcn, 299 + struct wcn36xx_dxe_ch *wcn_ch) 300 + { 301 + struct wcn36xx_dxe_ctl *cur = wcn_ch->head_blk_ctl; 302 + int i; 303 + 304 + for (i = 0; i < wcn_ch->desc_num; i++) { 305 + kfree_skb(cur->skb); 306 + cur = cur->next; 307 + } 308 + } 309 + 310 + void wcn36xx_dxe_tx_ack_ind(struct wcn36xx *wcn, u32 status) 311 + { 312 + struct ieee80211_tx_info *info; 313 + struct sk_buff *skb; 314 + unsigned long flags; 315 + 316 + spin_lock_irqsave(&wcn->dxe_lock, flags); 317 + skb = wcn->tx_ack_skb; 318 + wcn->tx_ack_skb = NULL; 319 + spin_unlock_irqrestore(&wcn->dxe_lock, flags); 320 + 321 + if (!skb) { 322 + wcn36xx_warn("Spurious TX complete indication\n"); 323 + return; 324 + } 325 + 326 + info = IEEE80211_SKB_CB(skb); 327 + 328 + if (status == 1) 329 + info->flags |= IEEE80211_TX_STAT_ACK; 330 + 331 + wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ack status: %d\n", status); 332 + 333 + ieee80211_tx_status_irqsafe(wcn->hw, skb); 334 + ieee80211_wake_queues(wcn->hw); 335 + } 336 + 337 + static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) 338 + { 339 + struct wcn36xx_dxe_ctl *ctl = ch->tail_blk_ctl; 340 + struct ieee80211_tx_info *info; 341 + unsigned long flags; 342 + 343 + /* 344 + * Make at least one loop of do-while because in case ring is 345 + * completely full head and tail are pointing to the same element 346 + * and while-do will not make any cycles. 347 + */ 348 + do { 349 + if (ctl->skb) { 350 + dma_unmap_single(NULL, ctl->desc->src_addr_l, 351 + ctl->skb->len, DMA_TO_DEVICE); 352 + info = IEEE80211_SKB_CB(ctl->skb); 353 + if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) { 354 + /* Keep frame until TX status comes */ 355 + ieee80211_free_txskb(wcn->hw, ctl->skb); 356 + } 357 + spin_lock_irqsave(&ctl->skb_lock, flags); 358 + if (wcn->queues_stopped) { 359 + wcn->queues_stopped = false; 360 + ieee80211_wake_queues(wcn->hw); 361 + } 362 + spin_unlock_irqrestore(&ctl->skb_lock, flags); 363 + 364 + ctl->skb = NULL; 365 + } 366 + ctl = ctl->next; 367 + } while (ctl != ch->head_blk_ctl && 368 + !(ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)); 369 + 370 + ch->tail_blk_ctl = ctl; 371 + } 372 + 373 + static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) 374 + { 375 + struct wcn36xx *wcn = (struct wcn36xx *)dev; 376 + int int_src, int_reason; 377 + 378 + wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_INT_SRC_RAW_REG, &int_src); 379 + 380 + if (int_src & WCN36XX_INT_MASK_CHAN_TX_H) { 381 + wcn36xx_dxe_read_register(wcn, 382 + WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_H, 383 + &int_reason); 384 + 385 + /* TODO: Check int_reason */ 386 + 387 + wcn36xx_dxe_write_register(wcn, 388 + WCN36XX_DXE_0_INT_CLR, 389 + WCN36XX_INT_MASK_CHAN_TX_H); 390 + 391 + wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_ED_CLR, 392 + WCN36XX_INT_MASK_CHAN_TX_H); 393 + wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready high\n"); 394 + reap_tx_dxes(wcn, &wcn->dxe_tx_h_ch); 395 + } 396 + 397 + if (int_src & WCN36XX_INT_MASK_CHAN_TX_L) { 398 + wcn36xx_dxe_read_register(wcn, 399 + WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_L, 400 + &int_reason); 401 + /* TODO: Check int_reason */ 402 + 403 + wcn36xx_dxe_write_register(wcn, 404 + WCN36XX_DXE_0_INT_CLR, 405 + WCN36XX_INT_MASK_CHAN_TX_L); 406 + 407 + wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_ED_CLR, 408 + WCN36XX_INT_MASK_CHAN_TX_L); 409 + wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready low\n"); 410 + reap_tx_dxes(wcn, &wcn->dxe_tx_l_ch); 411 + } 412 + 413 + return IRQ_HANDLED; 414 + } 415 + 416 + static irqreturn_t wcn36xx_irq_rx_ready(int irq, void *dev) 417 + { 418 + struct wcn36xx *wcn = (struct wcn36xx *)dev; 419 + 420 + disable_irq_nosync(wcn->rx_irq); 421 + wcn36xx_dxe_rx_frame(wcn); 422 + enable_irq(wcn->rx_irq); 423 + return IRQ_HANDLED; 424 + } 425 + 426 + static int wcn36xx_dxe_request_irqs(struct wcn36xx *wcn) 427 + { 428 + int ret; 429 + 430 + ret = request_irq(wcn->tx_irq, wcn36xx_irq_tx_complete, 431 + IRQF_TRIGGER_HIGH, "wcn36xx_tx", wcn); 432 + if (ret) { 433 + wcn36xx_err("failed to alloc tx irq\n"); 434 + goto out_err; 435 + } 436 + 437 + ret = request_irq(wcn->rx_irq, wcn36xx_irq_rx_ready, IRQF_TRIGGER_HIGH, 438 + "wcn36xx_rx", wcn); 439 + if (ret) { 440 + wcn36xx_err("failed to alloc rx irq\n"); 441 + goto out_txirq; 442 + } 443 + 444 + enable_irq_wake(wcn->rx_irq); 445 + 446 + return 0; 447 + 448 + out_txirq: 449 + free_irq(wcn->tx_irq, wcn); 450 + out_err: 451 + return ret; 452 + 453 + } 454 + 455 + static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn, 456 + struct wcn36xx_dxe_ch *ch) 457 + { 458 + struct wcn36xx_dxe_ctl *ctl = ch->head_blk_ctl; 459 + struct wcn36xx_dxe_desc *dxe = ctl->desc; 460 + dma_addr_t dma_addr; 461 + struct sk_buff *skb; 462 + 463 + while (!(dxe->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)) { 464 + skb = ctl->skb; 465 + dma_addr = dxe->dst_addr_l; 466 + wcn36xx_dxe_fill_skb(ctl); 467 + 468 + switch (ch->ch_type) { 469 + case WCN36XX_DXE_CH_RX_L: 470 + dxe->ctrl = WCN36XX_DXE_CTRL_RX_L; 471 + wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_ENCH_ADDR, 472 + WCN36XX_DXE_INT_CH1_MASK); 473 + break; 474 + case WCN36XX_DXE_CH_RX_H: 475 + dxe->ctrl = WCN36XX_DXE_CTRL_RX_H; 476 + wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_ENCH_ADDR, 477 + WCN36XX_DXE_INT_CH3_MASK); 478 + break; 479 + default: 480 + wcn36xx_warn("Unknown channel\n"); 481 + } 482 + 483 + dma_unmap_single(NULL, dma_addr, WCN36XX_PKT_SIZE, 484 + DMA_FROM_DEVICE); 485 + wcn36xx_rx_skb(wcn, skb); 486 + ctl = ctl->next; 487 + dxe = ctl->desc; 488 + } 489 + 490 + ch->head_blk_ctl = ctl; 491 + 492 + return 0; 493 + } 494 + 495 + void wcn36xx_dxe_rx_frame(struct wcn36xx *wcn) 496 + { 497 + int int_src; 498 + 499 + wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_INT_SRC_RAW_REG, &int_src); 500 + 501 + /* RX_LOW_PRI */ 502 + if (int_src & WCN36XX_DXE_INT_CH1_MASK) { 503 + wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_CLR, 504 + WCN36XX_DXE_INT_CH1_MASK); 505 + wcn36xx_rx_handle_packets(wcn, &(wcn->dxe_rx_l_ch)); 506 + } 507 + 508 + /* RX_HIGH_PRI */ 509 + if (int_src & WCN36XX_DXE_INT_CH3_MASK) { 510 + /* Clean up all the INT within this channel */ 511 + wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_CLR, 512 + WCN36XX_DXE_INT_CH3_MASK); 513 + wcn36xx_rx_handle_packets(wcn, &(wcn->dxe_rx_h_ch)); 514 + } 515 + 516 + if (!int_src) 517 + wcn36xx_warn("No DXE interrupt pending\n"); 518 + } 519 + 520 + int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn) 521 + { 522 + size_t s; 523 + void *cpu_addr; 524 + 525 + /* Allocate BD headers for MGMT frames */ 526 + 527 + /* Where this come from ask QC */ 528 + wcn->mgmt_mem_pool.chunk_size = WCN36XX_BD_CHUNK_SIZE + 529 + 16 - (WCN36XX_BD_CHUNK_SIZE % 8); 530 + 531 + s = wcn->mgmt_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_H; 532 + cpu_addr = dma_alloc_coherent(NULL, s, &wcn->mgmt_mem_pool.phy_addr, 533 + GFP_KERNEL); 534 + if (!cpu_addr) 535 + goto out_err; 536 + 537 + wcn->mgmt_mem_pool.virt_addr = cpu_addr; 538 + memset(cpu_addr, 0, s); 539 + 540 + /* Allocate BD headers for DATA frames */ 541 + 542 + /* Where this come from ask QC */ 543 + wcn->data_mem_pool.chunk_size = WCN36XX_BD_CHUNK_SIZE + 544 + 16 - (WCN36XX_BD_CHUNK_SIZE % 8); 545 + 546 + s = wcn->data_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_L; 547 + cpu_addr = dma_alloc_coherent(NULL, s, &wcn->data_mem_pool.phy_addr, 548 + GFP_KERNEL); 549 + if (!cpu_addr) 550 + goto out_err; 551 + 552 + wcn->data_mem_pool.virt_addr = cpu_addr; 553 + memset(cpu_addr, 0, s); 554 + 555 + return 0; 556 + 557 + out_err: 558 + wcn36xx_dxe_free_mem_pools(wcn); 559 + wcn36xx_err("Failed to allocate BD mempool\n"); 560 + return -ENOMEM; 561 + } 562 + 563 + void wcn36xx_dxe_free_mem_pools(struct wcn36xx *wcn) 564 + { 565 + if (wcn->mgmt_mem_pool.virt_addr) 566 + dma_free_coherent(NULL, wcn->mgmt_mem_pool.chunk_size * 567 + WCN36XX_DXE_CH_DESC_NUMB_TX_H, 568 + wcn->mgmt_mem_pool.virt_addr, 569 + wcn->mgmt_mem_pool.phy_addr); 570 + 571 + if (wcn->data_mem_pool.virt_addr) { 572 + dma_free_coherent(NULL, wcn->data_mem_pool.chunk_size * 573 + WCN36XX_DXE_CH_DESC_NUMB_TX_L, 574 + wcn->data_mem_pool.virt_addr, 575 + wcn->data_mem_pool.phy_addr); 576 + } 577 + } 578 + 579 + int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, 580 + struct wcn36xx_vif *vif_priv, 581 + struct sk_buff *skb, 582 + bool is_low) 583 + { 584 + struct wcn36xx_dxe_ctl *ctl = NULL; 585 + struct wcn36xx_dxe_desc *desc = NULL; 586 + struct wcn36xx_dxe_ch *ch = NULL; 587 + unsigned long flags; 588 + 589 + ch = is_low ? &wcn->dxe_tx_l_ch : &wcn->dxe_tx_h_ch; 590 + 591 + ctl = ch->head_blk_ctl; 592 + 593 + spin_lock_irqsave(&ctl->next->skb_lock, flags); 594 + 595 + /* 596 + * If skb is not null that means that we reached the tail of the ring 597 + * hence ring is full. Stop queues to let mac80211 back off until ring 598 + * has an empty slot again. 599 + */ 600 + if (NULL != ctl->next->skb) { 601 + ieee80211_stop_queues(wcn->hw); 602 + wcn->queues_stopped = true; 603 + spin_unlock_irqrestore(&ctl->next->skb_lock, flags); 604 + return -EBUSY; 605 + } 606 + spin_unlock_irqrestore(&ctl->next->skb_lock, flags); 607 + 608 + ctl->skb = NULL; 609 + desc = ctl->desc; 610 + 611 + /* Set source address of the BD we send */ 612 + desc->src_addr_l = ctl->bd_phy_addr; 613 + 614 + desc->dst_addr_l = ch->dxe_wq; 615 + desc->fr_len = sizeof(struct wcn36xx_tx_bd); 616 + desc->ctrl = ch->ctrl_bd; 617 + 618 + wcn36xx_dbg(WCN36XX_DBG_DXE, "DXE TX\n"); 619 + 620 + wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "DESC1 >>> ", 621 + (char *)desc, sizeof(*desc)); 622 + wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, 623 + "BD >>> ", (char *)ctl->bd_cpu_addr, 624 + sizeof(struct wcn36xx_tx_bd)); 625 + 626 + /* Set source address of the SKB we send */ 627 + ctl = ctl->next; 628 + ctl->skb = skb; 629 + desc = ctl->desc; 630 + if (ctl->bd_cpu_addr) { 631 + wcn36xx_err("bd_cpu_addr cannot be NULL for skb DXE\n"); 632 + return -EINVAL; 633 + } 634 + 635 + desc->src_addr_l = dma_map_single(NULL, 636 + ctl->skb->data, 637 + ctl->skb->len, 638 + DMA_TO_DEVICE); 639 + 640 + desc->dst_addr_l = ch->dxe_wq; 641 + desc->fr_len = ctl->skb->len; 642 + 643 + /* set dxe descriptor to VALID */ 644 + desc->ctrl = ch->ctrl_skb; 645 + 646 + wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "DESC2 >>> ", 647 + (char *)desc, sizeof(*desc)); 648 + wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "SKB >>> ", 649 + (char *)ctl->skb->data, ctl->skb->len); 650 + 651 + /* Move the head of the ring to the next empty descriptor */ 652 + ch->head_blk_ctl = ctl->next; 653 + 654 + /* 655 + * When connected and trying to send data frame chip can be in sleep 656 + * mode and writing to the register will not wake up the chip. Instead 657 + * notify chip about new frame through SMSM bus. 658 + */ 659 + if (is_low && vif_priv->pw_state == WCN36XX_BMPS) { 660 + wcn->ctrl_ops->smsm_change_state( 661 + 0, 662 + WCN36XX_SMSM_WLAN_TX_ENABLE); 663 + } else { 664 + /* indicate End Of Packet and generate interrupt on descriptor 665 + * done. 666 + */ 667 + wcn36xx_dxe_write_register(wcn, 668 + ch->reg_ctrl, ch->def_ctrl); 669 + } 670 + 671 + return 0; 672 + } 673 + 674 + int wcn36xx_dxe_init(struct wcn36xx *wcn) 675 + { 676 + int reg_data = 0, ret; 677 + 678 + reg_data = WCN36XX_DXE_REG_RESET; 679 + wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CSR_RESET, reg_data); 680 + 681 + /* Setting interrupt path */ 682 + reg_data = WCN36XX_DXE_CCU_INT; 683 + wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CCU_INT, reg_data); 684 + 685 + /***************************************/ 686 + /* Init descriptors for TX LOW channel */ 687 + /***************************************/ 688 + wcn36xx_dxe_init_descs(&wcn->dxe_tx_l_ch); 689 + wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_l_ch, &wcn->data_mem_pool); 690 + 691 + /* Write channel head to a NEXT register */ 692 + wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_L, 693 + wcn->dxe_tx_l_ch.head_blk_ctl->desc_phy_addr); 694 + 695 + /* Program DMA destination addr for TX LOW */ 696 + wcn36xx_dxe_write_register(wcn, 697 + WCN36XX_DXE_CH_DEST_ADDR_TX_L, 698 + WCN36XX_DXE_WQ_TX_L); 699 + 700 + wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, &reg_data); 701 + wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_L); 702 + 703 + /***************************************/ 704 + /* Init descriptors for TX HIGH channel */ 705 + /***************************************/ 706 + wcn36xx_dxe_init_descs(&wcn->dxe_tx_h_ch); 707 + wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_h_ch, &wcn->mgmt_mem_pool); 708 + 709 + /* Write channel head to a NEXT register */ 710 + wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_H, 711 + wcn->dxe_tx_h_ch.head_blk_ctl->desc_phy_addr); 712 + 713 + /* Program DMA destination addr for TX HIGH */ 714 + wcn36xx_dxe_write_register(wcn, 715 + WCN36XX_DXE_CH_DEST_ADDR_TX_H, 716 + WCN36XX_DXE_WQ_TX_H); 717 + 718 + wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, &reg_data); 719 + 720 + /* Enable channel interrupts */ 721 + wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_H); 722 + 723 + /***************************************/ 724 + /* Init descriptors for RX LOW channel */ 725 + /***************************************/ 726 + wcn36xx_dxe_init_descs(&wcn->dxe_rx_l_ch); 727 + 728 + /* For RX we need to preallocated buffers */ 729 + wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch); 730 + 731 + /* Write channel head to a NEXT register */ 732 + wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_L, 733 + wcn->dxe_rx_l_ch.head_blk_ctl->desc_phy_addr); 734 + 735 + /* Write DMA source address */ 736 + wcn36xx_dxe_write_register(wcn, 737 + WCN36XX_DXE_CH_SRC_ADDR_RX_L, 738 + WCN36XX_DXE_WQ_RX_L); 739 + 740 + /* Program preallocated destination address */ 741 + wcn36xx_dxe_write_register(wcn, 742 + WCN36XX_DXE_CH_DEST_ADDR_RX_L, 743 + wcn->dxe_rx_l_ch.head_blk_ctl->desc->phy_next_l); 744 + 745 + /* Enable default control registers */ 746 + wcn36xx_dxe_write_register(wcn, 747 + WCN36XX_DXE_REG_CTL_RX_L, 748 + WCN36XX_DXE_CH_DEFAULT_CTL_RX_L); 749 + 750 + /* Enable channel interrupts */ 751 + wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_L); 752 + 753 + /***************************************/ 754 + /* Init descriptors for RX HIGH channel */ 755 + /***************************************/ 756 + wcn36xx_dxe_init_descs(&wcn->dxe_rx_h_ch); 757 + 758 + /* For RX we need to prealocat buffers */ 759 + wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_h_ch); 760 + 761 + /* Write chanel head to a NEXT register */ 762 + wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_H, 763 + wcn->dxe_rx_h_ch.head_blk_ctl->desc_phy_addr); 764 + 765 + /* Write DMA source address */ 766 + wcn36xx_dxe_write_register(wcn, 767 + WCN36XX_DXE_CH_SRC_ADDR_RX_H, 768 + WCN36XX_DXE_WQ_RX_H); 769 + 770 + /* Program preallocated destination address */ 771 + wcn36xx_dxe_write_register(wcn, 772 + WCN36XX_DXE_CH_DEST_ADDR_RX_H, 773 + wcn->dxe_rx_h_ch.head_blk_ctl->desc->phy_next_l); 774 + 775 + /* Enable default control registers */ 776 + wcn36xx_dxe_write_register(wcn, 777 + WCN36XX_DXE_REG_CTL_RX_H, 778 + WCN36XX_DXE_CH_DEFAULT_CTL_RX_H); 779 + 780 + /* Enable channel interrupts */ 781 + wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_H); 782 + 783 + ret = wcn36xx_dxe_request_irqs(wcn); 784 + if (ret < 0) 785 + goto out_err; 786 + 787 + return 0; 788 + 789 + out_err: 790 + return ret; 791 + } 792 + 793 + void wcn36xx_dxe_deinit(struct wcn36xx *wcn) 794 + { 795 + free_irq(wcn->tx_irq, wcn); 796 + free_irq(wcn->rx_irq, wcn); 797 + 798 + if (wcn->tx_ack_skb) { 799 + ieee80211_tx_status_irqsafe(wcn->hw, wcn->tx_ack_skb); 800 + wcn->tx_ack_skb = NULL; 801 + } 802 + 803 + wcn36xx_dxe_ch_free_skbs(wcn, &wcn->dxe_rx_l_ch); 804 + wcn36xx_dxe_ch_free_skbs(wcn, &wcn->dxe_rx_h_ch); 805 + }
+284
drivers/net/wireless/ath/wcn36xx/dxe.h
··· 1 + /* 2 + * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> 3 + * 4 + * Permission to use, copy, modify, and/or distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 11 + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 13 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 14 + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + 17 + #ifndef _DXE_H_ 18 + #define _DXE_H_ 19 + 20 + #include "wcn36xx.h" 21 + 22 + /* 23 + TX_LOW = DMA0 24 + TX_HIGH = DMA4 25 + RX_LOW = DMA1 26 + RX_HIGH = DMA3 27 + H2H_TEST_RX_TX = DMA2 28 + */ 29 + 30 + /* DXE registers */ 31 + #define WCN36XX_DXE_MEM_BASE 0x03000000 32 + #define WCN36XX_DXE_MEM_REG 0x202000 33 + 34 + #define WCN36XX_DXE_CCU_INT 0xA0011 35 + #define WCN36XX_DXE_REG_CCU_INT 0x200b10 36 + 37 + /* TODO This must calculated properly but not hardcoded */ 38 + #define WCN36XX_DXE_CTRL_TX_L 0x328a44 39 + #define WCN36XX_DXE_CTRL_TX_H 0x32ce44 40 + #define WCN36XX_DXE_CTRL_RX_L 0x12ad2f 41 + #define WCN36XX_DXE_CTRL_RX_H 0x12d12f 42 + #define WCN36XX_DXE_CTRL_TX_H_BD 0x30ce45 43 + #define WCN36XX_DXE_CTRL_TX_H_SKB 0x32ce4d 44 + #define WCN36XX_DXE_CTRL_TX_L_BD 0x308a45 45 + #define WCN36XX_DXE_CTRL_TX_L_SKB 0x328a4d 46 + 47 + /* TODO This must calculated properly but not hardcoded */ 48 + #define WCN36XX_DXE_WQ_TX_L 0x17 49 + #define WCN36XX_DXE_WQ_TX_H 0x17 50 + #define WCN36XX_DXE_WQ_RX_L 0xB 51 + #define WCN36XX_DXE_WQ_RX_H 0x4 52 + 53 + /* DXE descriptor control filed */ 54 + #define WCN36XX_DXE_CTRL_VALID_MASK (0x00000001) 55 + 56 + /* TODO This must calculated properly but not hardcoded */ 57 + /* DXE default control register values */ 58 + #define WCN36XX_DXE_CH_DEFAULT_CTL_RX_L 0x847EAD2F 59 + #define WCN36XX_DXE_CH_DEFAULT_CTL_RX_H 0x84FED12F 60 + #define WCN36XX_DXE_CH_DEFAULT_CTL_TX_H 0x853ECF4D 61 + #define WCN36XX_DXE_CH_DEFAULT_CTL_TX_L 0x843e8b4d 62 + 63 + /* Common DXE registers */ 64 + #define WCN36XX_DXE_MEM_CSR (WCN36XX_DXE_MEM_REG + 0x00) 65 + #define WCN36XX_DXE_REG_CSR_RESET (WCN36XX_DXE_MEM_REG + 0x00) 66 + #define WCN36XX_DXE_ENCH_ADDR (WCN36XX_DXE_MEM_REG + 0x04) 67 + #define WCN36XX_DXE_REG_CH_EN (WCN36XX_DXE_MEM_REG + 0x08) 68 + #define WCN36XX_DXE_REG_CH_DONE (WCN36XX_DXE_MEM_REG + 0x0C) 69 + #define WCN36XX_DXE_REG_CH_ERR (WCN36XX_DXE_MEM_REG + 0x10) 70 + #define WCN36XX_DXE_INT_MASK_REG (WCN36XX_DXE_MEM_REG + 0x18) 71 + #define WCN36XX_DXE_INT_SRC_RAW_REG (WCN36XX_DXE_MEM_REG + 0x20) 72 + /* #define WCN36XX_DXE_INT_CH6_MASK 0x00000040 */ 73 + /* #define WCN36XX_DXE_INT_CH5_MASK 0x00000020 */ 74 + #define WCN36XX_DXE_INT_CH4_MASK 0x00000010 75 + #define WCN36XX_DXE_INT_CH3_MASK 0x00000008 76 + /* #define WCN36XX_DXE_INT_CH2_MASK 0x00000004 */ 77 + #define WCN36XX_DXE_INT_CH1_MASK 0x00000002 78 + #define WCN36XX_DXE_INT_CH0_MASK 0x00000001 79 + #define WCN36XX_DXE_0_INT_CLR (WCN36XX_DXE_MEM_REG + 0x30) 80 + #define WCN36XX_DXE_0_INT_ED_CLR (WCN36XX_DXE_MEM_REG + 0x34) 81 + #define WCN36XX_DXE_0_INT_DONE_CLR (WCN36XX_DXE_MEM_REG + 0x38) 82 + #define WCN36XX_DXE_0_INT_ERR_CLR (WCN36XX_DXE_MEM_REG + 0x3C) 83 + 84 + #define WCN36XX_DXE_0_CH0_STATUS (WCN36XX_DXE_MEM_REG + 0x404) 85 + #define WCN36XX_DXE_0_CH1_STATUS (WCN36XX_DXE_MEM_REG + 0x444) 86 + #define WCN36XX_DXE_0_CH2_STATUS (WCN36XX_DXE_MEM_REG + 0x484) 87 + #define WCN36XX_DXE_0_CH3_STATUS (WCN36XX_DXE_MEM_REG + 0x4C4) 88 + #define WCN36XX_DXE_0_CH4_STATUS (WCN36XX_DXE_MEM_REG + 0x504) 89 + 90 + #define WCN36XX_DXE_REG_RESET 0x5c89 91 + 92 + /* Temporary BMU Workqueue 4 */ 93 + #define WCN36XX_DXE_BMU_WQ_RX_LOW 0xB 94 + #define WCN36XX_DXE_BMU_WQ_RX_HIGH 0x4 95 + /* DMA channel offset */ 96 + #define WCN36XX_DXE_TX_LOW_OFFSET 0x400 97 + #define WCN36XX_DXE_TX_HIGH_OFFSET 0x500 98 + #define WCN36XX_DXE_RX_LOW_OFFSET 0x440 99 + #define WCN36XX_DXE_RX_HIGH_OFFSET 0x4C0 100 + 101 + /* Address of the next DXE descriptor */ 102 + #define WCN36XX_DXE_CH_NEXT_DESC_ADDR 0x001C 103 + #define WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_L (WCN36XX_DXE_MEM_REG + \ 104 + WCN36XX_DXE_TX_LOW_OFFSET + \ 105 + WCN36XX_DXE_CH_NEXT_DESC_ADDR) 106 + #define WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_H (WCN36XX_DXE_MEM_REG + \ 107 + WCN36XX_DXE_TX_HIGH_OFFSET + \ 108 + WCN36XX_DXE_CH_NEXT_DESC_ADDR) 109 + #define WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_L (WCN36XX_DXE_MEM_REG + \ 110 + WCN36XX_DXE_RX_LOW_OFFSET + \ 111 + WCN36XX_DXE_CH_NEXT_DESC_ADDR) 112 + #define WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_H (WCN36XX_DXE_MEM_REG + \ 113 + WCN36XX_DXE_RX_HIGH_OFFSET + \ 114 + WCN36XX_DXE_CH_NEXT_DESC_ADDR) 115 + 116 + /* DXE Descriptor source address */ 117 + #define WCN36XX_DXE_CH_SRC_ADDR 0x000C 118 + #define WCN36XX_DXE_CH_SRC_ADDR_RX_L (WCN36XX_DXE_MEM_REG + \ 119 + WCN36XX_DXE_RX_LOW_OFFSET + \ 120 + WCN36XX_DXE_CH_SRC_ADDR) 121 + #define WCN36XX_DXE_CH_SRC_ADDR_RX_H (WCN36XX_DXE_MEM_REG + \ 122 + WCN36XX_DXE_RX_HIGH_OFFSET + \ 123 + WCN36XX_DXE_CH_SRC_ADDR) 124 + 125 + /* DXE Descriptor address destination address */ 126 + #define WCN36XX_DXE_CH_DEST_ADDR 0x0014 127 + #define WCN36XX_DXE_CH_DEST_ADDR_TX_L (WCN36XX_DXE_MEM_REG + \ 128 + WCN36XX_DXE_TX_LOW_OFFSET + \ 129 + WCN36XX_DXE_CH_DEST_ADDR) 130 + #define WCN36XX_DXE_CH_DEST_ADDR_TX_H (WCN36XX_DXE_MEM_REG + \ 131 + WCN36XX_DXE_TX_HIGH_OFFSET + \ 132 + WCN36XX_DXE_CH_DEST_ADDR) 133 + #define WCN36XX_DXE_CH_DEST_ADDR_RX_L (WCN36XX_DXE_MEM_REG + \ 134 + WCN36XX_DXE_RX_LOW_OFFSET + \ 135 + WCN36XX_DXE_CH_DEST_ADDR) 136 + #define WCN36XX_DXE_CH_DEST_ADDR_RX_H (WCN36XX_DXE_MEM_REG + \ 137 + WCN36XX_DXE_RX_HIGH_OFFSET + \ 138 + WCN36XX_DXE_CH_DEST_ADDR) 139 + 140 + /* Interrupt status */ 141 + #define WCN36XX_DXE_CH_STATUS_REG_ADDR 0x0004 142 + #define WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_L (WCN36XX_DXE_MEM_REG + \ 143 + WCN36XX_DXE_TX_LOW_OFFSET + \ 144 + WCN36XX_DXE_CH_STATUS_REG_ADDR) 145 + #define WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_H (WCN36XX_DXE_MEM_REG + \ 146 + WCN36XX_DXE_TX_HIGH_OFFSET + \ 147 + WCN36XX_DXE_CH_STATUS_REG_ADDR) 148 + #define WCN36XX_DXE_CH_STATUS_REG_ADDR_RX_L (WCN36XX_DXE_MEM_REG + \ 149 + WCN36XX_DXE_RX_LOW_OFFSET + \ 150 + WCN36XX_DXE_CH_STATUS_REG_ADDR) 151 + #define WCN36XX_DXE_CH_STATUS_REG_ADDR_RX_H (WCN36XX_DXE_MEM_REG + \ 152 + WCN36XX_DXE_RX_HIGH_OFFSET + \ 153 + WCN36XX_DXE_CH_STATUS_REG_ADDR) 154 + 155 + 156 + /* DXE default control register */ 157 + #define WCN36XX_DXE_REG_CTL_RX_L (WCN36XX_DXE_MEM_REG + \ 158 + WCN36XX_DXE_RX_LOW_OFFSET) 159 + #define WCN36XX_DXE_REG_CTL_RX_H (WCN36XX_DXE_MEM_REG + \ 160 + WCN36XX_DXE_RX_HIGH_OFFSET) 161 + #define WCN36XX_DXE_REG_CTL_TX_H (WCN36XX_DXE_MEM_REG + \ 162 + WCN36XX_DXE_TX_HIGH_OFFSET) 163 + #define WCN36XX_DXE_REG_CTL_TX_L (WCN36XX_DXE_MEM_REG + \ 164 + WCN36XX_DXE_TX_LOW_OFFSET) 165 + 166 + #define WCN36XX_SMSM_WLAN_TX_ENABLE 0x00000400 167 + #define WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY 0x00000200 168 + 169 + 170 + /* Interrupt control channel mask */ 171 + #define WCN36XX_INT_MASK_CHAN_TX_L 0x00000001 172 + #define WCN36XX_INT_MASK_CHAN_RX_L 0x00000002 173 + #define WCN36XX_INT_MASK_CHAN_RX_H 0x00000008 174 + #define WCN36XX_INT_MASK_CHAN_TX_H 0x00000010 175 + 176 + #define WCN36XX_BD_CHUNK_SIZE 128 177 + 178 + #define WCN36XX_PKT_SIZE 0xF20 179 + enum wcn36xx_dxe_ch_type { 180 + WCN36XX_DXE_CH_TX_L, 181 + WCN36XX_DXE_CH_TX_H, 182 + WCN36XX_DXE_CH_RX_L, 183 + WCN36XX_DXE_CH_RX_H 184 + }; 185 + 186 + /* amount of descriptors per channel */ 187 + enum wcn36xx_dxe_ch_desc_num { 188 + WCN36XX_DXE_CH_DESC_NUMB_TX_L = 128, 189 + WCN36XX_DXE_CH_DESC_NUMB_TX_H = 10, 190 + WCN36XX_DXE_CH_DESC_NUMB_RX_L = 512, 191 + WCN36XX_DXE_CH_DESC_NUMB_RX_H = 40 192 + }; 193 + 194 + /** 195 + * struct wcn36xx_dxe_desc - describes descriptor of one DXE buffer 196 + * 197 + * @ctrl: is a union that consists of following bits: 198 + * union { 199 + * u32 valid :1; //0 = DMA stop, 1 = DMA continue with this 200 + * //descriptor 201 + * u32 transfer_type :2; //0 = Host to Host space 202 + * u32 eop :1; //End of Packet 203 + * u32 bd_handling :1; //if transferType = Host to BMU, then 0 204 + * // means first 128 bytes contain BD, and 1 205 + * // means create new empty BD 206 + * u32 siq :1; // SIQ 207 + * u32 diq :1; // DIQ 208 + * u32 pdu_rel :1; //0 = don't release BD and PDUs when done, 209 + * // 1 = release them 210 + * u32 bthld_sel :4; //BMU Threshold Select 211 + * u32 prio :3; //Specifies the priority level to use for 212 + * // the transfer 213 + * u32 stop_channel :1; //1 = DMA stops processing further, channel 214 + * //requires re-enabling after this 215 + * u32 intr :1; //Interrupt on Descriptor Done 216 + * u32 rsvd :1; //reserved 217 + * u32 size :14;//14 bits used - ignored for BMU transfers, 218 + * //only used for host to host transfers? 219 + * } ctrl; 220 + */ 221 + struct wcn36xx_dxe_desc { 222 + u32 ctrl; 223 + u32 fr_len; 224 + 225 + u32 src_addr_l; 226 + u32 dst_addr_l; 227 + u32 phy_next_l; 228 + u32 src_addr_h; 229 + u32 dst_addr_h; 230 + u32 phy_next_h; 231 + } __packed; 232 + 233 + /* DXE Control block */ 234 + struct wcn36xx_dxe_ctl { 235 + struct wcn36xx_dxe_ctl *next; 236 + struct wcn36xx_dxe_desc *desc; 237 + unsigned int desc_phy_addr; 238 + int ctl_blk_order; 239 + struct sk_buff *skb; 240 + spinlock_t skb_lock; 241 + void *bd_cpu_addr; 242 + dma_addr_t bd_phy_addr; 243 + }; 244 + 245 + struct wcn36xx_dxe_ch { 246 + enum wcn36xx_dxe_ch_type ch_type; 247 + void *cpu_addr; 248 + dma_addr_t dma_addr; 249 + enum wcn36xx_dxe_ch_desc_num desc_num; 250 + /* DXE control block ring */ 251 + struct wcn36xx_dxe_ctl *head_blk_ctl; 252 + struct wcn36xx_dxe_ctl *tail_blk_ctl; 253 + 254 + /* DXE channel specific configs */ 255 + u32 dxe_wq; 256 + u32 ctrl_bd; 257 + u32 ctrl_skb; 258 + u32 reg_ctrl; 259 + u32 def_ctrl; 260 + }; 261 + 262 + /* Memory Pool for BD headers */ 263 + struct wcn36xx_dxe_mem_pool { 264 + int chunk_size; 265 + void *virt_addr; 266 + dma_addr_t phy_addr; 267 + }; 268 + 269 + struct wcn36xx_vif; 270 + int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn); 271 + void wcn36xx_dxe_free_mem_pools(struct wcn36xx *wcn); 272 + void wcn36xx_dxe_rx_frame(struct wcn36xx *wcn); 273 + int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn); 274 + void wcn36xx_dxe_free_ctl_blks(struct wcn36xx *wcn); 275 + int wcn36xx_dxe_init(struct wcn36xx *wcn); 276 + void wcn36xx_dxe_deinit(struct wcn36xx *wcn); 277 + int wcn36xx_dxe_init_channels(struct wcn36xx *wcn); 278 + int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, 279 + struct wcn36xx_vif *vif_priv, 280 + struct sk_buff *skb, 281 + bool is_low); 282 + void wcn36xx_dxe_tx_ack_ind(struct wcn36xx *wcn, u32 status); 283 + void *wcn36xx_dxe_get_next_bd(struct wcn36xx *wcn, bool is_low); 284 + #endif /* _DXE_H_ */
+4657
drivers/net/wireless/ath/wcn36xx/hal.h
··· 1 + /* 2 + * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> 3 + * 4 + * Permission to use, copy, modify, and/or distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 11 + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 13 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 14 + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + 17 + #ifndef _HAL_H_ 18 + #define _HAL_H_ 19 + 20 + /*--------------------------------------------------------------------------- 21 + API VERSIONING INFORMATION 22 + 23 + The RIVA API is versioned as MAJOR.MINOR.VERSION.REVISION 24 + The MAJOR is incremented for major product/architecture changes 25 + (and then MINOR/VERSION/REVISION are zeroed) 26 + The MINOR is incremented for minor product/architecture changes 27 + (and then VERSION/REVISION are zeroed) 28 + The VERSION is incremented if a significant API change occurs 29 + (and then REVISION is zeroed) 30 + The REVISION is incremented if an insignificant API change occurs 31 + or if a new API is added 32 + All values are in the range 0..255 (ie they are 8-bit values) 33 + ---------------------------------------------------------------------------*/ 34 + #define WCN36XX_HAL_VER_MAJOR 1 35 + #define WCN36XX_HAL_VER_MINOR 4 36 + #define WCN36XX_HAL_VER_VERSION 1 37 + #define WCN36XX_HAL_VER_REVISION 2 38 + 39 + /* This is to force compiler to use the maximum of an int ( 4 bytes ) */ 40 + #define WCN36XX_HAL_MAX_ENUM_SIZE 0x7FFFFFFF 41 + #define WCN36XX_HAL_MSG_TYPE_MAX_ENUM_SIZE 0x7FFF 42 + 43 + /* Max no. of transmit categories */ 44 + #define STACFG_MAX_TC 8 45 + 46 + /* The maximum value of access category */ 47 + #define WCN36XX_HAL_MAX_AC 4 48 + 49 + #define WCN36XX_HAL_IPV4_ADDR_LEN 4 50 + 51 + #define WALN_HAL_STA_INVALID_IDX 0xFF 52 + #define WCN36XX_HAL_BSS_INVALID_IDX 0xFF 53 + 54 + /* Default Beacon template size */ 55 + #define BEACON_TEMPLATE_SIZE 0x180 56 + 57 + /* Param Change Bitmap sent to HAL */ 58 + #define PARAM_BCN_INTERVAL_CHANGED (1 << 0) 59 + #define PARAM_SHORT_PREAMBLE_CHANGED (1 << 1) 60 + #define PARAM_SHORT_SLOT_TIME_CHANGED (1 << 2) 61 + #define PARAM_llACOEXIST_CHANGED (1 << 3) 62 + #define PARAM_llBCOEXIST_CHANGED (1 << 4) 63 + #define PARAM_llGCOEXIST_CHANGED (1 << 5) 64 + #define PARAM_HT20MHZCOEXIST_CHANGED (1<<6) 65 + #define PARAM_NON_GF_DEVICES_PRESENT_CHANGED (1<<7) 66 + #define PARAM_RIFS_MODE_CHANGED (1<<8) 67 + #define PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED (1<<9) 68 + #define PARAM_OBSS_MODE_CHANGED (1<<10) 69 + #define PARAM_BEACON_UPDATE_MASK \ 70 + (PARAM_BCN_INTERVAL_CHANGED | \ 71 + PARAM_SHORT_PREAMBLE_CHANGED | \ 72 + PARAM_SHORT_SLOT_TIME_CHANGED | \ 73 + PARAM_llACOEXIST_CHANGED | \ 74 + PARAM_llBCOEXIST_CHANGED | \ 75 + PARAM_llGCOEXIST_CHANGED | \ 76 + PARAM_HT20MHZCOEXIST_CHANGED | \ 77 + PARAM_NON_GF_DEVICES_PRESENT_CHANGED | \ 78 + PARAM_RIFS_MODE_CHANGED | \ 79 + PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED | \ 80 + PARAM_OBSS_MODE_CHANGED) 81 + 82 + /* dump command response Buffer size */ 83 + #define DUMPCMD_RSP_BUFFER 100 84 + 85 + /* version string max length (including NULL) */ 86 + #define WCN36XX_HAL_VERSION_LENGTH 64 87 + 88 + /* message types for messages exchanged between WDI and HAL */ 89 + enum wcn36xx_hal_host_msg_type { 90 + /* Init/De-Init */ 91 + WCN36XX_HAL_START_REQ = 0, 92 + WCN36XX_HAL_START_RSP = 1, 93 + WCN36XX_HAL_STOP_REQ = 2, 94 + WCN36XX_HAL_STOP_RSP = 3, 95 + 96 + /* Scan */ 97 + WCN36XX_HAL_INIT_SCAN_REQ = 4, 98 + WCN36XX_HAL_INIT_SCAN_RSP = 5, 99 + WCN36XX_HAL_START_SCAN_REQ = 6, 100 + WCN36XX_HAL_START_SCAN_RSP = 7, 101 + WCN36XX_HAL_END_SCAN_REQ = 8, 102 + WCN36XX_HAL_END_SCAN_RSP = 9, 103 + WCN36XX_HAL_FINISH_SCAN_REQ = 10, 104 + WCN36XX_HAL_FINISH_SCAN_RSP = 11, 105 + 106 + /* HW STA configuration/deconfiguration */ 107 + WCN36XX_HAL_CONFIG_STA_REQ = 12, 108 + WCN36XX_HAL_CONFIG_STA_RSP = 13, 109 + WCN36XX_HAL_DELETE_STA_REQ = 14, 110 + WCN36XX_HAL_DELETE_STA_RSP = 15, 111 + WCN36XX_HAL_CONFIG_BSS_REQ = 16, 112 + WCN36XX_HAL_CONFIG_BSS_RSP = 17, 113 + WCN36XX_HAL_DELETE_BSS_REQ = 18, 114 + WCN36XX_HAL_DELETE_BSS_RSP = 19, 115 + 116 + /* Infra STA asscoiation */ 117 + WCN36XX_HAL_JOIN_REQ = 20, 118 + WCN36XX_HAL_JOIN_RSP = 21, 119 + WCN36XX_HAL_POST_ASSOC_REQ = 22, 120 + WCN36XX_HAL_POST_ASSOC_RSP = 23, 121 + 122 + /* Security */ 123 + WCN36XX_HAL_SET_BSSKEY_REQ = 24, 124 + WCN36XX_HAL_SET_BSSKEY_RSP = 25, 125 + WCN36XX_HAL_SET_STAKEY_REQ = 26, 126 + WCN36XX_HAL_SET_STAKEY_RSP = 27, 127 + WCN36XX_HAL_RMV_BSSKEY_REQ = 28, 128 + WCN36XX_HAL_RMV_BSSKEY_RSP = 29, 129 + WCN36XX_HAL_RMV_STAKEY_REQ = 30, 130 + WCN36XX_HAL_RMV_STAKEY_RSP = 31, 131 + 132 + /* Qos Related */ 133 + WCN36XX_HAL_ADD_TS_REQ = 32, 134 + WCN36XX_HAL_ADD_TS_RSP = 33, 135 + WCN36XX_HAL_DEL_TS_REQ = 34, 136 + WCN36XX_HAL_DEL_TS_RSP = 35, 137 + WCN36XX_HAL_UPD_EDCA_PARAMS_REQ = 36, 138 + WCN36XX_HAL_UPD_EDCA_PARAMS_RSP = 37, 139 + WCN36XX_HAL_ADD_BA_REQ = 38, 140 + WCN36XX_HAL_ADD_BA_RSP = 39, 141 + WCN36XX_HAL_DEL_BA_REQ = 40, 142 + WCN36XX_HAL_DEL_BA_RSP = 41, 143 + 144 + WCN36XX_HAL_CH_SWITCH_REQ = 42, 145 + WCN36XX_HAL_CH_SWITCH_RSP = 43, 146 + WCN36XX_HAL_SET_LINK_ST_REQ = 44, 147 + WCN36XX_HAL_SET_LINK_ST_RSP = 45, 148 + WCN36XX_HAL_GET_STATS_REQ = 46, 149 + WCN36XX_HAL_GET_STATS_RSP = 47, 150 + WCN36XX_HAL_UPDATE_CFG_REQ = 48, 151 + WCN36XX_HAL_UPDATE_CFG_RSP = 49, 152 + 153 + WCN36XX_HAL_MISSED_BEACON_IND = 50, 154 + WCN36XX_HAL_UNKNOWN_ADDR2_FRAME_RX_IND = 51, 155 + WCN36XX_HAL_MIC_FAILURE_IND = 52, 156 + WCN36XX_HAL_FATAL_ERROR_IND = 53, 157 + WCN36XX_HAL_SET_KEYDONE_MSG = 54, 158 + 159 + /* NV Interface */ 160 + WCN36XX_HAL_DOWNLOAD_NV_REQ = 55, 161 + WCN36XX_HAL_DOWNLOAD_NV_RSP = 56, 162 + 163 + WCN36XX_HAL_ADD_BA_SESSION_REQ = 57, 164 + WCN36XX_HAL_ADD_BA_SESSION_RSP = 58, 165 + WCN36XX_HAL_TRIGGER_BA_REQ = 59, 166 + WCN36XX_HAL_TRIGGER_BA_RSP = 60, 167 + WCN36XX_HAL_UPDATE_BEACON_REQ = 61, 168 + WCN36XX_HAL_UPDATE_BEACON_RSP = 62, 169 + WCN36XX_HAL_SEND_BEACON_REQ = 63, 170 + WCN36XX_HAL_SEND_BEACON_RSP = 64, 171 + 172 + WCN36XX_HAL_SET_BCASTKEY_REQ = 65, 173 + WCN36XX_HAL_SET_BCASTKEY_RSP = 66, 174 + WCN36XX_HAL_DELETE_STA_CONTEXT_IND = 67, 175 + WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ = 68, 176 + WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_RSP = 69, 177 + 178 + /* PTT interface support */ 179 + WCN36XX_HAL_PROCESS_PTT_REQ = 70, 180 + WCN36XX_HAL_PROCESS_PTT_RSP = 71, 181 + 182 + /* BTAMP related events */ 183 + WCN36XX_HAL_SIGNAL_BTAMP_EVENT_REQ = 72, 184 + WCN36XX_HAL_SIGNAL_BTAMP_EVENT_RSP = 73, 185 + WCN36XX_HAL_TL_HAL_FLUSH_AC_REQ = 74, 186 + WCN36XX_HAL_TL_HAL_FLUSH_AC_RSP = 75, 187 + 188 + WCN36XX_HAL_ENTER_IMPS_REQ = 76, 189 + WCN36XX_HAL_EXIT_IMPS_REQ = 77, 190 + WCN36XX_HAL_ENTER_BMPS_REQ = 78, 191 + WCN36XX_HAL_EXIT_BMPS_REQ = 79, 192 + WCN36XX_HAL_ENTER_UAPSD_REQ = 80, 193 + WCN36XX_HAL_EXIT_UAPSD_REQ = 81, 194 + WCN36XX_HAL_UPDATE_UAPSD_PARAM_REQ = 82, 195 + WCN36XX_HAL_CONFIGURE_RXP_FILTER_REQ = 83, 196 + WCN36XX_HAL_ADD_BCN_FILTER_REQ = 84, 197 + WCN36XX_HAL_REM_BCN_FILTER_REQ = 85, 198 + WCN36XX_HAL_ADD_WOWL_BCAST_PTRN = 86, 199 + WCN36XX_HAL_DEL_WOWL_BCAST_PTRN = 87, 200 + WCN36XX_HAL_ENTER_WOWL_REQ = 88, 201 + WCN36XX_HAL_EXIT_WOWL_REQ = 89, 202 + WCN36XX_HAL_HOST_OFFLOAD_REQ = 90, 203 + WCN36XX_HAL_SET_RSSI_THRESH_REQ = 91, 204 + WCN36XX_HAL_GET_RSSI_REQ = 92, 205 + WCN36XX_HAL_SET_UAPSD_AC_PARAMS_REQ = 93, 206 + WCN36XX_HAL_CONFIGURE_APPS_CPU_WAKEUP_STATE_REQ = 94, 207 + 208 + WCN36XX_HAL_ENTER_IMPS_RSP = 95, 209 + WCN36XX_HAL_EXIT_IMPS_RSP = 96, 210 + WCN36XX_HAL_ENTER_BMPS_RSP = 97, 211 + WCN36XX_HAL_EXIT_BMPS_RSP = 98, 212 + WCN36XX_HAL_ENTER_UAPSD_RSP = 99, 213 + WCN36XX_HAL_EXIT_UAPSD_RSP = 100, 214 + WCN36XX_HAL_SET_UAPSD_AC_PARAMS_RSP = 101, 215 + WCN36XX_HAL_UPDATE_UAPSD_PARAM_RSP = 102, 216 + WCN36XX_HAL_CONFIGURE_RXP_FILTER_RSP = 103, 217 + WCN36XX_HAL_ADD_BCN_FILTER_RSP = 104, 218 + WCN36XX_HAL_REM_BCN_FILTER_RSP = 105, 219 + WCN36XX_HAL_SET_RSSI_THRESH_RSP = 106, 220 + WCN36XX_HAL_HOST_OFFLOAD_RSP = 107, 221 + WCN36XX_HAL_ADD_WOWL_BCAST_PTRN_RSP = 108, 222 + WCN36XX_HAL_DEL_WOWL_BCAST_PTRN_RSP = 109, 223 + WCN36XX_HAL_ENTER_WOWL_RSP = 110, 224 + WCN36XX_HAL_EXIT_WOWL_RSP = 111, 225 + WCN36XX_HAL_RSSI_NOTIFICATION_IND = 112, 226 + WCN36XX_HAL_GET_RSSI_RSP = 113, 227 + WCN36XX_HAL_CONFIGURE_APPS_CPU_WAKEUP_STATE_RSP = 114, 228 + 229 + /* 11k related events */ 230 + WCN36XX_HAL_SET_MAX_TX_POWER_REQ = 115, 231 + WCN36XX_HAL_SET_MAX_TX_POWER_RSP = 116, 232 + 233 + /* 11R related msgs */ 234 + WCN36XX_HAL_AGGR_ADD_TS_REQ = 117, 235 + WCN36XX_HAL_AGGR_ADD_TS_RSP = 118, 236 + 237 + /* P2P WLAN_FEATURE_P2P */ 238 + WCN36XX_HAL_SET_P2P_GONOA_REQ = 119, 239 + WCN36XX_HAL_SET_P2P_GONOA_RSP = 120, 240 + 241 + /* WLAN Dump commands */ 242 + WCN36XX_HAL_DUMP_COMMAND_REQ = 121, 243 + WCN36XX_HAL_DUMP_COMMAND_RSP = 122, 244 + 245 + /* OEM_DATA FEATURE SUPPORT */ 246 + WCN36XX_HAL_START_OEM_DATA_REQ = 123, 247 + WCN36XX_HAL_START_OEM_DATA_RSP = 124, 248 + 249 + /* ADD SELF STA REQ and RSP */ 250 + WCN36XX_HAL_ADD_STA_SELF_REQ = 125, 251 + WCN36XX_HAL_ADD_STA_SELF_RSP = 126, 252 + 253 + /* DEL SELF STA SUPPORT */ 254 + WCN36XX_HAL_DEL_STA_SELF_REQ = 127, 255 + WCN36XX_HAL_DEL_STA_SELF_RSP = 128, 256 + 257 + /* Coex Indication */ 258 + WCN36XX_HAL_COEX_IND = 129, 259 + 260 + /* Tx Complete Indication */ 261 + WCN36XX_HAL_OTA_TX_COMPL_IND = 130, 262 + 263 + /* Host Suspend/resume messages */ 264 + WCN36XX_HAL_HOST_SUSPEND_IND = 131, 265 + WCN36XX_HAL_HOST_RESUME_REQ = 132, 266 + WCN36XX_HAL_HOST_RESUME_RSP = 133, 267 + 268 + WCN36XX_HAL_SET_TX_POWER_REQ = 134, 269 + WCN36XX_HAL_SET_TX_POWER_RSP = 135, 270 + WCN36XX_HAL_GET_TX_POWER_REQ = 136, 271 + WCN36XX_HAL_GET_TX_POWER_RSP = 137, 272 + 273 + WCN36XX_HAL_P2P_NOA_ATTR_IND = 138, 274 + 275 + WCN36XX_HAL_ENABLE_RADAR_DETECT_REQ = 139, 276 + WCN36XX_HAL_ENABLE_RADAR_DETECT_RSP = 140, 277 + WCN36XX_HAL_GET_TPC_REPORT_REQ = 141, 278 + WCN36XX_HAL_GET_TPC_REPORT_RSP = 142, 279 + WCN36XX_HAL_RADAR_DETECT_IND = 143, 280 + WCN36XX_HAL_RADAR_DETECT_INTR_IND = 144, 281 + WCN36XX_HAL_KEEP_ALIVE_REQ = 145, 282 + WCN36XX_HAL_KEEP_ALIVE_RSP = 146, 283 + 284 + /* PNO messages */ 285 + WCN36XX_HAL_SET_PREF_NETWORK_REQ = 147, 286 + WCN36XX_HAL_SET_PREF_NETWORK_RSP = 148, 287 + WCN36XX_HAL_SET_RSSI_FILTER_REQ = 149, 288 + WCN36XX_HAL_SET_RSSI_FILTER_RSP = 150, 289 + WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ = 151, 290 + WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP = 152, 291 + WCN36XX_HAL_PREF_NETW_FOUND_IND = 153, 292 + 293 + WCN36XX_HAL_SET_TX_PER_TRACKING_REQ = 154, 294 + WCN36XX_HAL_SET_TX_PER_TRACKING_RSP = 155, 295 + WCN36XX_HAL_TX_PER_HIT_IND = 156, 296 + 297 + WCN36XX_HAL_8023_MULTICAST_LIST_REQ = 157, 298 + WCN36XX_HAL_8023_MULTICAST_LIST_RSP = 158, 299 + 300 + WCN36XX_HAL_SET_PACKET_FILTER_REQ = 159, 301 + WCN36XX_HAL_SET_PACKET_FILTER_RSP = 160, 302 + WCN36XX_HAL_PACKET_FILTER_MATCH_COUNT_REQ = 161, 303 + WCN36XX_HAL_PACKET_FILTER_MATCH_COUNT_RSP = 162, 304 + WCN36XX_HAL_CLEAR_PACKET_FILTER_REQ = 163, 305 + WCN36XX_HAL_CLEAR_PACKET_FILTER_RSP = 164, 306 + 307 + /* 308 + * This is temp fix. Should be removed once Host and Riva code is 309 + * in sync. 310 + */ 311 + WCN36XX_HAL_INIT_SCAN_CON_REQ = 165, 312 + 313 + WCN36XX_HAL_SET_POWER_PARAMS_REQ = 166, 314 + WCN36XX_HAL_SET_POWER_PARAMS_RSP = 167, 315 + 316 + WCN36XX_HAL_TSM_STATS_REQ = 168, 317 + WCN36XX_HAL_TSM_STATS_RSP = 169, 318 + 319 + /* wake reason indication (WOW) */ 320 + WCN36XX_HAL_WAKE_REASON_IND = 170, 321 + 322 + /* GTK offload support */ 323 + WCN36XX_HAL_GTK_OFFLOAD_REQ = 171, 324 + WCN36XX_HAL_GTK_OFFLOAD_RSP = 172, 325 + WCN36XX_HAL_GTK_OFFLOAD_GETINFO_REQ = 173, 326 + WCN36XX_HAL_GTK_OFFLOAD_GETINFO_RSP = 174, 327 + 328 + WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ = 175, 329 + WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP = 176, 330 + WCN36XX_HAL_EXCLUDE_UNENCRYPTED_IND = 177, 331 + 332 + WCN36XX_HAL_SET_THERMAL_MITIGATION_REQ = 178, 333 + WCN36XX_HAL_SET_THERMAL_MITIGATION_RSP = 179, 334 + 335 + WCN36XX_HAL_UPDATE_VHT_OP_MODE_REQ = 182, 336 + WCN36XX_HAL_UPDATE_VHT_OP_MODE_RSP = 183, 337 + 338 + WCN36XX_HAL_P2P_NOA_START_IND = 184, 339 + 340 + WCN36XX_HAL_GET_ROAM_RSSI_REQ = 185, 341 + WCN36XX_HAL_GET_ROAM_RSSI_RSP = 186, 342 + 343 + WCN36XX_HAL_CLASS_B_STATS_IND = 187, 344 + WCN36XX_HAL_DEL_BA_IND = 188, 345 + WCN36XX_HAL_DHCP_START_IND = 189, 346 + WCN36XX_HAL_DHCP_STOP_IND = 190, 347 + 348 + WCN36XX_HAL_MSG_MAX = WCN36XX_HAL_MSG_TYPE_MAX_ENUM_SIZE 349 + }; 350 + 351 + /* Enumeration for Version */ 352 + enum wcn36xx_hal_host_msg_version { 353 + WCN36XX_HAL_MSG_VERSION0 = 0, 354 + WCN36XX_HAL_MSG_VERSION1 = 1, 355 + /* define as 2 bytes data */ 356 + WCN36XX_HAL_MSG_WCNSS_CTRL_VERSION = 0x7FFF, 357 + WCN36XX_HAL_MSG_VERSION_MAX_FIELD = WCN36XX_HAL_MSG_WCNSS_CTRL_VERSION 358 + }; 359 + 360 + enum driver_type { 361 + DRIVER_TYPE_PRODUCTION = 0, 362 + DRIVER_TYPE_MFG = 1, 363 + DRIVER_TYPE_DVT = 2, 364 + DRIVER_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE 365 + }; 366 + 367 + enum wcn36xx_hal_stop_type { 368 + HAL_STOP_TYPE_SYS_RESET, 369 + HAL_STOP_TYPE_SYS_DEEP_SLEEP, 370 + HAL_STOP_TYPE_RF_KILL, 371 + HAL_STOP_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE 372 + }; 373 + 374 + enum wcn36xx_hal_sys_mode { 375 + HAL_SYS_MODE_NORMAL, 376 + HAL_SYS_MODE_LEARN, 377 + HAL_SYS_MODE_SCAN, 378 + HAL_SYS_MODE_PROMISC, 379 + HAL_SYS_MODE_SUSPEND_LINK, 380 + HAL_SYS_MODE_ROAM_SCAN, 381 + HAL_SYS_MODE_ROAM_SUSPEND_LINK, 382 + HAL_SYS_MODE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE 383 + }; 384 + 385 + enum phy_chan_bond_state { 386 + /* 20MHz IF bandwidth centered on IF carrier */ 387 + PHY_SINGLE_CHANNEL_CENTERED = 0, 388 + 389 + /* 40MHz IF bandwidth with lower 20MHz supporting the primary channel */ 390 + PHY_DOUBLE_CHANNEL_LOW_PRIMARY = 1, 391 + 392 + /* 40MHz IF bandwidth centered on IF carrier */ 393 + PHY_DOUBLE_CHANNEL_CENTERED = 2, 394 + 395 + /* 40MHz IF bandwidth with higher 20MHz supporting the primary ch */ 396 + PHY_DOUBLE_CHANNEL_HIGH_PRIMARY = 3, 397 + 398 + /* 20/40MHZ offset LOW 40/80MHZ offset CENTERED */ 399 + PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED = 4, 400 + 401 + /* 20/40MHZ offset CENTERED 40/80MHZ offset CENTERED */ 402 + PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED = 5, 403 + 404 + /* 20/40MHZ offset HIGH 40/80MHZ offset CENTERED */ 405 + PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED = 6, 406 + 407 + /* 20/40MHZ offset LOW 40/80MHZ offset LOW */ 408 + PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW = 7, 409 + 410 + /* 20/40MHZ offset HIGH 40/80MHZ offset LOW */ 411 + PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW = 8, 412 + 413 + /* 20/40MHZ offset LOW 40/80MHZ offset HIGH */ 414 + PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH = 9, 415 + 416 + /* 20/40MHZ offset-HIGH 40/80MHZ offset HIGH */ 417 + PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH = 10, 418 + 419 + PHY_CHANNEL_BONDING_STATE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE 420 + }; 421 + 422 + /* Spatial Multiplexing(SM) Power Save mode */ 423 + enum wcn36xx_hal_ht_mimo_state { 424 + /* Static SM Power Save mode */ 425 + WCN36XX_HAL_HT_MIMO_PS_STATIC = 0, 426 + 427 + /* Dynamic SM Power Save mode */ 428 + WCN36XX_HAL_HT_MIMO_PS_DYNAMIC = 1, 429 + 430 + /* reserved */ 431 + WCN36XX_HAL_HT_MIMO_PS_NA = 2, 432 + 433 + /* SM Power Save disabled */ 434 + WCN36XX_HAL_HT_MIMO_PS_NO_LIMIT = 3, 435 + 436 + WCN36XX_HAL_HT_MIMO_PS_MAX = WCN36XX_HAL_MAX_ENUM_SIZE 437 + }; 438 + 439 + /* each station added has a rate mode which specifies the sta attributes */ 440 + enum sta_rate_mode { 441 + STA_TAURUS = 0, 442 + STA_TITAN, 443 + STA_POLARIS, 444 + STA_11b, 445 + STA_11bg, 446 + STA_11a, 447 + STA_11n, 448 + STA_11ac, 449 + STA_INVALID_RATE_MODE = WCN36XX_HAL_MAX_ENUM_SIZE 450 + }; 451 + 452 + /* 1,2,5.5,11 */ 453 + #define WCN36XX_HAL_NUM_DSSS_RATES 4 454 + 455 + /* 6,9,12,18,24,36,48,54 */ 456 + #define WCN36XX_HAL_NUM_OFDM_RATES 8 457 + 458 + /* 72,96,108 */ 459 + #define WCN36XX_HAL_NUM_POLARIS_RATES 3 460 + 461 + #define WCN36XX_HAL_MAC_MAX_SUPPORTED_MCS_SET 16 462 + 463 + enum wcn36xx_hal_bss_type { 464 + WCN36XX_HAL_INFRASTRUCTURE_MODE, 465 + 466 + /* Added for softAP support */ 467 + WCN36XX_HAL_INFRA_AP_MODE, 468 + 469 + WCN36XX_HAL_IBSS_MODE, 470 + 471 + /* Added for BT-AMP support */ 472 + WCN36XX_HAL_BTAMP_STA_MODE, 473 + 474 + /* Added for BT-AMP support */ 475 + WCN36XX_HAL_BTAMP_AP_MODE, 476 + 477 + WCN36XX_HAL_AUTO_MODE, 478 + 479 + WCN36XX_HAL_DONOT_USE_BSS_TYPE = WCN36XX_HAL_MAX_ENUM_SIZE 480 + }; 481 + 482 + enum wcn36xx_hal_nw_type { 483 + WCN36XX_HAL_11A_NW_TYPE, 484 + WCN36XX_HAL_11B_NW_TYPE, 485 + WCN36XX_HAL_11G_NW_TYPE, 486 + WCN36XX_HAL_11N_NW_TYPE, 487 + WCN36XX_HAL_DONOT_USE_NW_TYPE = WCN36XX_HAL_MAX_ENUM_SIZE 488 + }; 489 + 490 + #define WCN36XX_HAL_MAC_RATESET_EID_MAX 12 491 + 492 + enum wcn36xx_hal_ht_operating_mode { 493 + /* No Protection */ 494 + WCN36XX_HAL_HT_OP_MODE_PURE, 495 + 496 + /* Overlap Legacy device present, protection is optional */ 497 + WCN36XX_HAL_HT_OP_MODE_OVERLAP_LEGACY, 498 + 499 + /* No legacy device, but 20 MHz HT present */ 500 + WCN36XX_HAL_HT_OP_MODE_NO_LEGACY_20MHZ_HT, 501 + 502 + /* Protection is required */ 503 + WCN36XX_HAL_HT_OP_MODE_MIXED, 504 + 505 + WCN36XX_HAL_HT_OP_MODE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE 506 + }; 507 + 508 + /* Encryption type enum used with peer */ 509 + enum ani_ed_type { 510 + WCN36XX_HAL_ED_NONE, 511 + WCN36XX_HAL_ED_WEP40, 512 + WCN36XX_HAL_ED_WEP104, 513 + WCN36XX_HAL_ED_TKIP, 514 + WCN36XX_HAL_ED_CCMP, 515 + WCN36XX_HAL_ED_WPI, 516 + WCN36XX_HAL_ED_AES_128_CMAC, 517 + WCN36XX_HAL_ED_NOT_IMPLEMENTED = WCN36XX_HAL_MAX_ENUM_SIZE 518 + }; 519 + 520 + #define WLAN_MAX_KEY_RSC_LEN 16 521 + #define WLAN_WAPI_KEY_RSC_LEN 16 522 + 523 + /* MAX key length when ULA is used */ 524 + #define WCN36XX_HAL_MAC_MAX_KEY_LENGTH 32 525 + #define WCN36XX_HAL_MAC_MAX_NUM_OF_DEFAULT_KEYS 4 526 + 527 + /* 528 + * Enum to specify whether key is used for TX only, RX only or both. 529 + */ 530 + enum ani_key_direction { 531 + WCN36XX_HAL_TX_ONLY, 532 + WCN36XX_HAL_RX_ONLY, 533 + WCN36XX_HAL_TX_RX, 534 + WCN36XX_HAL_TX_DEFAULT, 535 + WCN36XX_HAL_DONOT_USE_KEY_DIRECTION = WCN36XX_HAL_MAX_ENUM_SIZE 536 + }; 537 + 538 + enum ani_wep_type { 539 + WCN36XX_HAL_WEP_STATIC, 540 + WCN36XX_HAL_WEP_DYNAMIC, 541 + WCN36XX_HAL_WEP_MAX = WCN36XX_HAL_MAX_ENUM_SIZE 542 + }; 543 + 544 + enum wcn36xx_hal_link_state { 545 + 546 + WCN36XX_HAL_LINK_IDLE_STATE = 0, 547 + WCN36XX_HAL_LINK_PREASSOC_STATE = 1, 548 + WCN36XX_HAL_LINK_POSTASSOC_STATE = 2, 549 + WCN36XX_HAL_LINK_AP_STATE = 3, 550 + WCN36XX_HAL_LINK_IBSS_STATE = 4, 551 + 552 + /* BT-AMP Case */ 553 + WCN36XX_HAL_LINK_BTAMP_PREASSOC_STATE = 5, 554 + WCN36XX_HAL_LINK_BTAMP_POSTASSOC_STATE = 6, 555 + WCN36XX_HAL_LINK_BTAMP_AP_STATE = 7, 556 + WCN36XX_HAL_LINK_BTAMP_STA_STATE = 8, 557 + 558 + /* Reserved for HAL Internal Use */ 559 + WCN36XX_HAL_LINK_LEARN_STATE = 9, 560 + WCN36XX_HAL_LINK_SCAN_STATE = 10, 561 + WCN36XX_HAL_LINK_FINISH_SCAN_STATE = 11, 562 + WCN36XX_HAL_LINK_INIT_CAL_STATE = 12, 563 + WCN36XX_HAL_LINK_FINISH_CAL_STATE = 13, 564 + WCN36XX_HAL_LINK_LISTEN_STATE = 14, 565 + 566 + WCN36XX_HAL_LINK_MAX = WCN36XX_HAL_MAX_ENUM_SIZE 567 + }; 568 + 569 + enum wcn36xx_hal_stats_mask { 570 + HAL_SUMMARY_STATS_INFO = 0x00000001, 571 + HAL_GLOBAL_CLASS_A_STATS_INFO = 0x00000002, 572 + HAL_GLOBAL_CLASS_B_STATS_INFO = 0x00000004, 573 + HAL_GLOBAL_CLASS_C_STATS_INFO = 0x00000008, 574 + HAL_GLOBAL_CLASS_D_STATS_INFO = 0x00000010, 575 + HAL_PER_STA_STATS_INFO = 0x00000020 576 + }; 577 + 578 + /* BT-AMP events type */ 579 + enum bt_amp_event_type { 580 + BTAMP_EVENT_CONNECTION_START, 581 + BTAMP_EVENT_CONNECTION_STOP, 582 + BTAMP_EVENT_CONNECTION_TERMINATED, 583 + 584 + /* This and beyond are invalid values */ 585 + BTAMP_EVENT_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE, 586 + }; 587 + 588 + /* PE Statistics */ 589 + enum pe_stats_mask { 590 + PE_SUMMARY_STATS_INFO = 0x00000001, 591 + PE_GLOBAL_CLASS_A_STATS_INFO = 0x00000002, 592 + PE_GLOBAL_CLASS_B_STATS_INFO = 0x00000004, 593 + PE_GLOBAL_CLASS_C_STATS_INFO = 0x00000008, 594 + PE_GLOBAL_CLASS_D_STATS_INFO = 0x00000010, 595 + PE_PER_STA_STATS_INFO = 0x00000020, 596 + 597 + /* This and beyond are invalid values */ 598 + PE_STATS_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE 599 + }; 600 + 601 + /* 602 + * Configuration Parameter IDs 603 + */ 604 + #define WCN36XX_HAL_CFG_STA_ID 0 605 + #define WCN36XX_HAL_CFG_CURRENT_TX_ANTENNA 1 606 + #define WCN36XX_HAL_CFG_CURRENT_RX_ANTENNA 2 607 + #define WCN36XX_HAL_CFG_LOW_GAIN_OVERRIDE 3 608 + #define WCN36XX_HAL_CFG_POWER_STATE_PER_CHAIN 4 609 + #define WCN36XX_HAL_CFG_CAL_PERIOD 5 610 + #define WCN36XX_HAL_CFG_CAL_CONTROL 6 611 + #define WCN36XX_HAL_CFG_PROXIMITY 7 612 + #define WCN36XX_HAL_CFG_NETWORK_DENSITY 8 613 + #define WCN36XX_HAL_CFG_MAX_MEDIUM_TIME 9 614 + #define WCN36XX_HAL_CFG_MAX_MPDUS_IN_AMPDU 10 615 + #define WCN36XX_HAL_CFG_RTS_THRESHOLD 11 616 + #define WCN36XX_HAL_CFG_SHORT_RETRY_LIMIT 12 617 + #define WCN36XX_HAL_CFG_LONG_RETRY_LIMIT 13 618 + #define WCN36XX_HAL_CFG_FRAGMENTATION_THRESHOLD 14 619 + #define WCN36XX_HAL_CFG_DYNAMIC_THRESHOLD_ZERO 15 620 + #define WCN36XX_HAL_CFG_DYNAMIC_THRESHOLD_ONE 16 621 + #define WCN36XX_HAL_CFG_DYNAMIC_THRESHOLD_TWO 17 622 + #define WCN36XX_HAL_CFG_FIXED_RATE 18 623 + #define WCN36XX_HAL_CFG_RETRYRATE_POLICY 19 624 + #define WCN36XX_HAL_CFG_RETRYRATE_SECONDARY 20 625 + #define WCN36XX_HAL_CFG_RETRYRATE_TERTIARY 21 626 + #define WCN36XX_HAL_CFG_FORCE_POLICY_PROTECTION 22 627 + #define WCN36XX_HAL_CFG_FIXED_RATE_MULTICAST_24GHZ 23 628 + #define WCN36XX_HAL_CFG_FIXED_RATE_MULTICAST_5GHZ 24 629 + #define WCN36XX_HAL_CFG_DEFAULT_RATE_INDEX_24GHZ 25 630 + #define WCN36XX_HAL_CFG_DEFAULT_RATE_INDEX_5GHZ 26 631 + #define WCN36XX_HAL_CFG_MAX_BA_SESSIONS 27 632 + #define WCN36XX_HAL_CFG_PS_DATA_INACTIVITY_TIMEOUT 28 633 + #define WCN36XX_HAL_CFG_PS_ENABLE_BCN_FILTER 29 634 + #define WCN36XX_HAL_CFG_PS_ENABLE_RSSI_MONITOR 30 635 + #define WCN36XX_HAL_CFG_NUM_BEACON_PER_RSSI_AVERAGE 31 636 + #define WCN36XX_HAL_CFG_STATS_PERIOD 32 637 + #define WCN36XX_HAL_CFG_CFP_MAX_DURATION 33 638 + #define WCN36XX_HAL_CFG_FRAME_TRANS_ENABLED 34 639 + #define WCN36XX_HAL_CFG_DTIM_PERIOD 35 640 + #define WCN36XX_HAL_CFG_EDCA_WMM_ACBK 36 641 + #define WCN36XX_HAL_CFG_EDCA_WMM_ACBE 37 642 + #define WCN36XX_HAL_CFG_EDCA_WMM_ACVO 38 643 + #define WCN36XX_HAL_CFG_EDCA_WMM_ACVI 39 644 + #define WCN36XX_HAL_CFG_BA_THRESHOLD_HIGH 40 645 + #define WCN36XX_HAL_CFG_MAX_BA_BUFFERS 41 646 + #define WCN36XX_HAL_CFG_RPE_POLLING_THRESHOLD 42 647 + #define WCN36XX_HAL_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG 43 648 + #define WCN36XX_HAL_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG 44 649 + #define WCN36XX_HAL_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG 45 650 + #define WCN36XX_HAL_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG 46 651 + #define WCN36XX_HAL_CFG_NO_OF_ONCHIP_REORDER_SESSIONS 47 652 + #define WCN36XX_HAL_CFG_PS_LISTEN_INTERVAL 48 653 + #define WCN36XX_HAL_CFG_PS_HEART_BEAT_THRESHOLD 49 654 + #define WCN36XX_HAL_CFG_PS_NTH_BEACON_FILTER 50 655 + #define WCN36XX_HAL_CFG_PS_MAX_PS_POLL 51 656 + #define WCN36XX_HAL_CFG_PS_MIN_RSSI_THRESHOLD 52 657 + #define WCN36XX_HAL_CFG_PS_RSSI_FILTER_PERIOD 53 658 + #define WCN36XX_HAL_CFG_PS_BROADCAST_FRAME_FILTER_ENABLE 54 659 + #define WCN36XX_HAL_CFG_PS_IGNORE_DTIM 55 660 + #define WCN36XX_HAL_CFG_PS_ENABLE_BCN_EARLY_TERM 56 661 + #define WCN36XX_HAL_CFG_DYNAMIC_PS_POLL_VALUE 57 662 + #define WCN36XX_HAL_CFG_PS_NULLDATA_AP_RESP_TIMEOUT 58 663 + #define WCN36XX_HAL_CFG_TELE_BCN_WAKEUP_EN 59 664 + #define WCN36XX_HAL_CFG_TELE_BCN_TRANS_LI 60 665 + #define WCN36XX_HAL_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS 61 666 + #define WCN36XX_HAL_CFG_TELE_BCN_MAX_LI 62 667 + #define WCN36XX_HAL_CFG_TELE_BCN_MAX_LI_IDLE_BCNS 63 668 + #define WCN36XX_HAL_CFG_TX_PWR_CTRL_ENABLE 64 669 + #define WCN36XX_HAL_CFG_VALID_RADAR_CHANNEL_LIST 65 670 + #define WCN36XX_HAL_CFG_TX_POWER_24_20 66 671 + #define WCN36XX_HAL_CFG_TX_POWER_24_40 67 672 + #define WCN36XX_HAL_CFG_TX_POWER_50_20 68 673 + #define WCN36XX_HAL_CFG_TX_POWER_50_40 69 674 + #define WCN36XX_HAL_CFG_MCAST_BCAST_FILTER_SETTING 70 675 + #define WCN36XX_HAL_CFG_BCN_EARLY_TERM_WAKEUP_INTERVAL 71 676 + #define WCN36XX_HAL_CFG_MAX_TX_POWER_2_4 72 677 + #define WCN36XX_HAL_CFG_MAX_TX_POWER_5 73 678 + #define WCN36XX_HAL_CFG_INFRA_STA_KEEP_ALIVE_PERIOD 74 679 + #define WCN36XX_HAL_CFG_ENABLE_CLOSE_LOOP 75 680 + #define WCN36XX_HAL_CFG_BTC_EXECUTION_MODE 76 681 + #define WCN36XX_HAL_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK 77 682 + #define WCN36XX_HAL_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS 78 683 + #define WCN36XX_HAL_CFG_PS_TX_INACTIVITY_TIMEOUT 79 684 + #define WCN36XX_HAL_CFG_WCNSS_API_VERSION 80 685 + #define WCN36XX_HAL_CFG_AP_KEEPALIVE_TIMEOUT 81 686 + #define WCN36XX_HAL_CFG_GO_KEEPALIVE_TIMEOUT 82 687 + #define WCN36XX_HAL_CFG_ENABLE_MC_ADDR_LIST 83 688 + #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_INQ_BT 84 689 + #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_PAGE_BT 85 690 + #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_CONN_BT 86 691 + #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_LE_BT 87 692 + #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_INQ_WLAN 88 693 + #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_PAGE_WLAN 89 694 + #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_CONN_WLAN 90 695 + #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_LE_WLAN 91 696 + #define WCN36XX_HAL_CFG_BTC_DYN_MAX_LEN_BT 92 697 + #define WCN36XX_HAL_CFG_BTC_DYN_MAX_LEN_WLAN 93 698 + #define WCN36XX_HAL_CFG_BTC_MAX_SCO_BLOCK_PERC 94 699 + #define WCN36XX_HAL_CFG_BTC_DHCP_PROT_ON_A2DP 95 700 + #define WCN36XX_HAL_CFG_BTC_DHCP_PROT_ON_SCO 96 701 + #define WCN36XX_HAL_CFG_ENABLE_UNICAST_FILTER 97 702 + #define WCN36XX_HAL_CFG_MAX_ASSOC_LIMIT 98 703 + #define WCN36XX_HAL_CFG_ENABLE_LPWR_IMG_TRANSITION 99 704 + #define WCN36XX_HAL_CFG_ENABLE_MCC_ADAPTIVE_SCHEDULER 100 705 + #define WCN36XX_HAL_CFG_ENABLE_DETECT_PS_SUPPORT 101 706 + #define WCN36XX_HAL_CFG_AP_LINK_MONITOR_TIMEOUT 102 707 + #define WCN36XX_HAL_CFG_BTC_DWELL_TIME_MULTIPLIER 103 708 + #define WCN36XX_HAL_CFG_ENABLE_TDLS_OXYGEN_MODE 104 709 + #define WCN36XX_HAL_CFG_MAX_PARAMS 105 710 + 711 + /* Message definitons - All the messages below need to be packed */ 712 + 713 + /* Definition for HAL API Version. */ 714 + struct wcnss_wlan_version { 715 + u8 revision; 716 + u8 version; 717 + u8 minor; 718 + u8 major; 719 + } __packed; 720 + 721 + /* Definition for Encryption Keys */ 722 + struct wcn36xx_hal_keys { 723 + u8 id; 724 + 725 + /* 0 for multicast */ 726 + u8 unicast; 727 + 728 + enum ani_key_direction direction; 729 + 730 + /* Usage is unknown */ 731 + u8 rsc[WLAN_MAX_KEY_RSC_LEN]; 732 + 733 + /* =1 for authenticator,=0 for supplicant */ 734 + u8 pae_role; 735 + 736 + u16 length; 737 + u8 key[WCN36XX_HAL_MAC_MAX_KEY_LENGTH]; 738 + } __packed; 739 + 740 + /* 741 + * set_sta_key_params Moving here since it is shared by 742 + * configbss/setstakey msgs 743 + */ 744 + struct wcn36xx_hal_set_sta_key_params { 745 + /* STA Index */ 746 + u16 sta_index; 747 + 748 + /* Encryption Type used with peer */ 749 + enum ani_ed_type enc_type; 750 + 751 + /* STATIC/DYNAMIC - valid only for WEP */ 752 + enum ani_wep_type wep_type; 753 + 754 + /* Default WEP key, valid only for static WEP, must between 0 and 3. */ 755 + u8 def_wep_idx; 756 + 757 + /* valid only for non-static WEP encyrptions */ 758 + struct wcn36xx_hal_keys key[WCN36XX_HAL_MAC_MAX_NUM_OF_DEFAULT_KEYS]; 759 + 760 + /* 761 + * Control for Replay Count, 1= Single TID based replay count on Tx 762 + * 0 = Per TID based replay count on TX 763 + */ 764 + u8 single_tid_rc; 765 + 766 + } __packed; 767 + 768 + /* 4-byte control message header used by HAL*/ 769 + struct wcn36xx_hal_msg_header { 770 + enum wcn36xx_hal_host_msg_type msg_type:16; 771 + enum wcn36xx_hal_host_msg_version msg_version:16; 772 + u32 len; 773 + } __packed; 774 + 775 + /* Config format required by HAL for each CFG item*/ 776 + struct wcn36xx_hal_cfg { 777 + /* Cfg Id. The Id required by HAL is exported by HAL 778 + * in shared header file between UMAC and HAL.*/ 779 + u16 id; 780 + 781 + /* Length of the Cfg. This parameter is used to go to next cfg 782 + * in the TLV format.*/ 783 + u16 len; 784 + 785 + /* Padding bytes for unaligned address's */ 786 + u16 pad_bytes; 787 + 788 + /* Reserve bytes for making cfgVal to align address */ 789 + u16 reserve; 790 + 791 + /* Following the uCfgLen field there should be a 'uCfgLen' bytes 792 + * containing the uCfgValue ; u8 uCfgValue[uCfgLen] */ 793 + } __packed; 794 + 795 + struct wcn36xx_hal_mac_start_parameters { 796 + /* Drive Type - Production or FTM etc */ 797 + enum driver_type type; 798 + 799 + /* Length of the config buffer */ 800 + u32 len; 801 + 802 + /* Following this there is a TLV formatted buffer of length 803 + * "len" bytes containing all config values. 804 + * The TLV is expected to be formatted like this: 805 + * 0 15 31 31+CFG_LEN-1 length-1 806 + * | CFG_ID | CFG_LEN | CFG_BODY | CFG_ID |......| 807 + */ 808 + } __packed; 809 + 810 + struct wcn36xx_hal_mac_start_req_msg { 811 + /* config buffer must start in TLV format just here */ 812 + struct wcn36xx_hal_msg_header header; 813 + struct wcn36xx_hal_mac_start_parameters params; 814 + } __packed; 815 + 816 + struct wcn36xx_hal_mac_start_rsp_params { 817 + /* success or failure */ 818 + u16 status; 819 + 820 + /* Max number of STA supported by the device */ 821 + u8 stations; 822 + 823 + /* Max number of BSS supported by the device */ 824 + u8 bssids; 825 + 826 + /* API Version */ 827 + struct wcnss_wlan_version version; 828 + 829 + /* CRM build information */ 830 + u8 crm_version[WCN36XX_HAL_VERSION_LENGTH]; 831 + 832 + /* hardware/chipset/misc version information */ 833 + u8 wlan_version[WCN36XX_HAL_VERSION_LENGTH]; 834 + 835 + } __packed; 836 + 837 + struct wcn36xx_hal_mac_start_rsp_msg { 838 + struct wcn36xx_hal_msg_header header; 839 + struct wcn36xx_hal_mac_start_rsp_params start_rsp_params; 840 + } __packed; 841 + 842 + struct wcn36xx_hal_mac_stop_req_params { 843 + /* The reason for which the device is being stopped */ 844 + enum wcn36xx_hal_stop_type reason; 845 + 846 + } __packed; 847 + 848 + struct wcn36xx_hal_mac_stop_req_msg { 849 + struct wcn36xx_hal_msg_header header; 850 + struct wcn36xx_hal_mac_stop_req_params stop_req_params; 851 + } __packed; 852 + 853 + struct wcn36xx_hal_mac_stop_rsp_msg { 854 + struct wcn36xx_hal_msg_header header; 855 + 856 + /* success or failure */ 857 + u32 status; 858 + } __packed; 859 + 860 + struct wcn36xx_hal_update_cfg_req_msg { 861 + /* 862 + * Note: The length specified in tHalUpdateCfgReqMsg messages should be 863 + * header.msgLen = sizeof(tHalUpdateCfgReqMsg) + uConfigBufferLen 864 + */ 865 + struct wcn36xx_hal_msg_header header; 866 + 867 + /* Length of the config buffer. Allows UMAC to update multiple CFGs */ 868 + u32 len; 869 + 870 + /* 871 + * Following this there is a TLV formatted buffer of length 872 + * "uConfigBufferLen" bytes containing all config values. 873 + * The TLV is expected to be formatted like this: 874 + * 0 15 31 31+CFG_LEN-1 length-1 875 + * | CFG_ID | CFG_LEN | CFG_BODY | CFG_ID |......| 876 + */ 877 + 878 + } __packed; 879 + 880 + struct wcn36xx_hal_update_cfg_rsp_msg { 881 + struct wcn36xx_hal_msg_header header; 882 + 883 + /* success or failure */ 884 + u32 status; 885 + 886 + } __packed; 887 + 888 + /* Frame control field format (2 bytes) */ 889 + struct wcn36xx_hal_mac_frame_ctl { 890 + 891 + #ifndef ANI_LITTLE_BIT_ENDIAN 892 + 893 + u8 subType:4; 894 + u8 type:2; 895 + u8 protVer:2; 896 + 897 + u8 order:1; 898 + u8 wep:1; 899 + u8 moreData:1; 900 + u8 powerMgmt:1; 901 + u8 retry:1; 902 + u8 moreFrag:1; 903 + u8 fromDS:1; 904 + u8 toDS:1; 905 + 906 + #else 907 + 908 + u8 protVer:2; 909 + u8 type:2; 910 + u8 subType:4; 911 + 912 + u8 toDS:1; 913 + u8 fromDS:1; 914 + u8 moreFrag:1; 915 + u8 retry:1; 916 + u8 powerMgmt:1; 917 + u8 moreData:1; 918 + u8 wep:1; 919 + u8 order:1; 920 + 921 + #endif 922 + 923 + }; 924 + 925 + /* Sequence control field */ 926 + struct wcn36xx_hal_mac_seq_ctl { 927 + u8 fragNum:4; 928 + u8 seqNumLo:4; 929 + u8 seqNumHi:8; 930 + }; 931 + 932 + /* Management header format */ 933 + struct wcn36xx_hal_mac_mgmt_hdr { 934 + struct wcn36xx_hal_mac_frame_ctl fc; 935 + u8 durationLo; 936 + u8 durationHi; 937 + u8 da[6]; 938 + u8 sa[6]; 939 + u8 bssId[6]; 940 + struct wcn36xx_hal_mac_seq_ctl seqControl; 941 + }; 942 + 943 + /* FIXME: pronto v1 apparently has 4 */ 944 + #define WCN36XX_HAL_NUM_BSSID 2 945 + 946 + /* Scan Entry to hold active BSS idx's */ 947 + struct wcn36xx_hal_scan_entry { 948 + u8 bss_index[WCN36XX_HAL_NUM_BSSID]; 949 + u8 active_bss_count; 950 + }; 951 + 952 + struct wcn36xx_hal_init_scan_req_msg { 953 + struct wcn36xx_hal_msg_header header; 954 + 955 + /* LEARN - AP Role 956 + SCAN - STA Role */ 957 + enum wcn36xx_hal_sys_mode mode; 958 + 959 + /* BSSID of the BSS */ 960 + u8 bssid[ETH_ALEN]; 961 + 962 + /* Whether BSS needs to be notified */ 963 + u8 notify; 964 + 965 + /* Kind of frame to be used for notifying the BSS (Data Null, QoS 966 + * Null, or CTS to Self). Must always be a valid frame type. */ 967 + u8 frame_type; 968 + 969 + /* UMAC has the option of passing the MAC frame to be used for 970 + * notifying the BSS. If non-zero, HAL will use the MAC frame 971 + * buffer pointed to by macMgmtHdr. If zero, HAL will generate the 972 + * appropriate MAC frame based on frameType. */ 973 + u8 frame_len; 974 + 975 + /* Following the framelength there is a MAC frame buffer if 976 + * frameLength is non-zero. */ 977 + struct wcn36xx_hal_mac_mgmt_hdr mac_mgmt_hdr; 978 + 979 + /* Entry to hold number of active BSS idx's */ 980 + struct wcn36xx_hal_scan_entry scan_entry; 981 + }; 982 + 983 + struct wcn36xx_hal_init_scan_con_req_msg { 984 + struct wcn36xx_hal_msg_header header; 985 + 986 + /* LEARN - AP Role 987 + SCAN - STA Role */ 988 + enum wcn36xx_hal_sys_mode mode; 989 + 990 + /* BSSID of the BSS */ 991 + u8 bssid[ETH_ALEN]; 992 + 993 + /* Whether BSS needs to be notified */ 994 + u8 notify; 995 + 996 + /* Kind of frame to be used for notifying the BSS (Data Null, QoS 997 + * Null, or CTS to Self). Must always be a valid frame type. */ 998 + u8 frame_type; 999 + 1000 + /* UMAC has the option of passing the MAC frame to be used for 1001 + * notifying the BSS. If non-zero, HAL will use the MAC frame 1002 + * buffer pointed to by macMgmtHdr. If zero, HAL will generate the 1003 + * appropriate MAC frame based on frameType. */ 1004 + u8 frame_length; 1005 + 1006 + /* Following the framelength there is a MAC frame buffer if 1007 + * frameLength is non-zero. */ 1008 + struct wcn36xx_hal_mac_mgmt_hdr mac_mgmt_hdr; 1009 + 1010 + /* Entry to hold number of active BSS idx's */ 1011 + struct wcn36xx_hal_scan_entry scan_entry; 1012 + 1013 + /* Single NoA usage in Scanning */ 1014 + u8 use_noa; 1015 + 1016 + /* Indicates the scan duration (in ms) */ 1017 + u16 scan_duration; 1018 + 1019 + }; 1020 + 1021 + struct wcn36xx_hal_init_scan_rsp_msg { 1022 + struct wcn36xx_hal_msg_header header; 1023 + 1024 + /* success or failure */ 1025 + u32 status; 1026 + 1027 + } __packed; 1028 + 1029 + struct wcn36xx_hal_start_scan_req_msg { 1030 + struct wcn36xx_hal_msg_header header; 1031 + 1032 + /* Indicates the channel to scan */ 1033 + u8 scan_channel; 1034 + } __packed; 1035 + 1036 + struct wcn36xx_hal_start_rsp_msg { 1037 + struct wcn36xx_hal_msg_header header; 1038 + 1039 + /* success or failure */ 1040 + u32 status; 1041 + 1042 + u32 start_tsf[2]; 1043 + u8 tx_mgmt_power; 1044 + 1045 + } __packed; 1046 + 1047 + struct wcn36xx_hal_end_scan_req_msg { 1048 + struct wcn36xx_hal_msg_header header; 1049 + 1050 + /* Indicates the channel to stop scanning. Not used really. But 1051 + * retained for symmetry with "start Scan" message. It can also 1052 + * help in error check if needed. */ 1053 + u8 scan_channel; 1054 + } __packed; 1055 + 1056 + struct wcn36xx_hal_end_scan_rsp_msg { 1057 + struct wcn36xx_hal_msg_header header; 1058 + 1059 + /* success or failure */ 1060 + u32 status; 1061 + } __packed; 1062 + 1063 + struct wcn36xx_hal_finish_scan_req_msg { 1064 + struct wcn36xx_hal_msg_header header; 1065 + 1066 + /* Identifies the operational state of the AP/STA 1067 + * LEARN - AP Role SCAN - STA Role */ 1068 + enum wcn36xx_hal_sys_mode mode; 1069 + 1070 + /* Operating channel to tune to. */ 1071 + u8 oper_channel; 1072 + 1073 + /* Channel Bonding state If 20/40 MHz is operational, this will 1074 + * indicate the 40 MHz extension channel in combination with the 1075 + * control channel */ 1076 + enum phy_chan_bond_state cb_state; 1077 + 1078 + /* BSSID of the BSS */ 1079 + u8 bssid[ETH_ALEN]; 1080 + 1081 + /* Whether BSS needs to be notified */ 1082 + u8 notify; 1083 + 1084 + /* Kind of frame to be used for notifying the BSS (Data Null, QoS 1085 + * Null, or CTS to Self). Must always be a valid frame type. */ 1086 + u8 frame_type; 1087 + 1088 + /* UMAC has the option of passing the MAC frame to be used for 1089 + * notifying the BSS. If non-zero, HAL will use the MAC frame 1090 + * buffer pointed to by macMgmtHdr. If zero, HAL will generate the 1091 + * appropriate MAC frame based on frameType. */ 1092 + u8 frame_length; 1093 + 1094 + /* Following the framelength there is a MAC frame buffer if 1095 + * frameLength is non-zero. */ 1096 + struct wcn36xx_hal_mac_mgmt_hdr mac_mgmt_hdr; 1097 + 1098 + /* Entry to hold number of active BSS idx's */ 1099 + struct wcn36xx_hal_scan_entry scan_entry; 1100 + 1101 + } __packed; 1102 + 1103 + struct wcn36xx_hal_finish_scan_rsp_msg { 1104 + struct wcn36xx_hal_msg_header header; 1105 + 1106 + /* success or failure */ 1107 + u32 status; 1108 + 1109 + } __packed; 1110 + 1111 + enum wcn36xx_hal_rate_index { 1112 + HW_RATE_INDEX_1MBPS = 0x82, 1113 + HW_RATE_INDEX_2MBPS = 0x84, 1114 + HW_RATE_INDEX_5_5MBPS = 0x8B, 1115 + HW_RATE_INDEX_6MBPS = 0x0C, 1116 + HW_RATE_INDEX_9MBPS = 0x12, 1117 + HW_RATE_INDEX_11MBPS = 0x96, 1118 + HW_RATE_INDEX_12MBPS = 0x18, 1119 + HW_RATE_INDEX_18MBPS = 0x24, 1120 + HW_RATE_INDEX_24MBPS = 0x30, 1121 + HW_RATE_INDEX_36MBPS = 0x48, 1122 + HW_RATE_INDEX_48MBPS = 0x60, 1123 + HW_RATE_INDEX_54MBPS = 0x6C 1124 + }; 1125 + 1126 + struct wcn36xx_hal_supported_rates { 1127 + /* 1128 + * For Self STA Entry: this represents Self Mode. 1129 + * For Peer Stations, this represents the mode of the peer. 1130 + * On Station: 1131 + * 1132 + * --this mode is updated when PE adds the Self Entry. 1133 + * 1134 + * -- OR when PE sends 'ADD_BSS' message and station context in BSS 1135 + * is used to indicate the mode of the AP. 1136 + * 1137 + * ON AP: 1138 + * 1139 + * -- this mode is updated when PE sends 'ADD_BSS' and Sta entry 1140 + * for that BSS is used to indicate the self mode of the AP. 1141 + * 1142 + * -- OR when a station is associated, PE sends 'ADD_STA' message 1143 + * with this mode updated. 1144 + */ 1145 + 1146 + enum sta_rate_mode op_rate_mode; 1147 + 1148 + /* 11b, 11a and aniLegacyRates are IE rates which gives rate in 1149 + * unit of 500Kbps */ 1150 + u16 dsss_rates[WCN36XX_HAL_NUM_DSSS_RATES]; 1151 + u16 ofdm_rates[WCN36XX_HAL_NUM_OFDM_RATES]; 1152 + u16 legacy_rates[WCN36XX_HAL_NUM_POLARIS_RATES]; 1153 + u16 reserved; 1154 + 1155 + /* Taurus only supports 26 Titan Rates(no ESF/concat Rates will be 1156 + * supported) First 26 bits are reserved for those Titan rates and 1157 + * the last 4 bits(bit28-31) for Taurus, 2(bit26-27) bits are 1158 + * reserved. */ 1159 + /* Titan and Taurus Rates */ 1160 + u32 enhanced_rate_bitmap; 1161 + 1162 + /* 1163 + * 0-76 bits used, remaining reserved 1164 + * bits 0-15 and 32 should be set. 1165 + */ 1166 + u8 supported_mcs_set[WCN36XX_HAL_MAC_MAX_SUPPORTED_MCS_SET]; 1167 + 1168 + /* 1169 + * RX Highest Supported Data Rate defines the highest data 1170 + * rate that the STA is able to receive, in unites of 1Mbps. 1171 + * This value is derived from "Supported MCS Set field" inside 1172 + * the HT capability element. 1173 + */ 1174 + u16 rx_highest_data_rate; 1175 + 1176 + } __packed; 1177 + 1178 + struct wcn36xx_hal_config_sta_params { 1179 + /* BSSID of STA */ 1180 + u8 bssid[ETH_ALEN]; 1181 + 1182 + /* ASSOC ID, as assigned by UMAC */ 1183 + u16 aid; 1184 + 1185 + /* STA entry Type: 0 - Self, 1 - Other/Peer, 2 - BSSID, 3 - BCAST */ 1186 + u8 type; 1187 + 1188 + /* Short Preamble Supported. */ 1189 + u8 short_preamble_supported; 1190 + 1191 + /* MAC Address of STA */ 1192 + u8 mac[ETH_ALEN]; 1193 + 1194 + /* Listen interval of the STA */ 1195 + u16 listen_interval; 1196 + 1197 + /* Support for 11e/WMM */ 1198 + u8 wmm_enabled; 1199 + 1200 + /* 11n HT capable STA */ 1201 + u8 ht_capable; 1202 + 1203 + /* TX Width Set: 0 - 20 MHz only, 1 - 20/40 MHz */ 1204 + u8 tx_channel_width_set; 1205 + 1206 + /* RIFS mode 0 - NA, 1 - Allowed */ 1207 + u8 rifs_mode; 1208 + 1209 + /* L-SIG TXOP Protection mechanism 1210 + 0 - No Support, 1 - Supported 1211 + SG - there is global field */ 1212 + u8 lsig_txop_protection; 1213 + 1214 + /* Max Ampdu Size supported by STA. TPE programming. 1215 + 0 : 8k , 1 : 16k, 2 : 32k, 3 : 64k */ 1216 + u8 max_ampdu_size; 1217 + 1218 + /* Max Ampdu density. Used by RA. 3 : 0~7 : 2^(11nAMPDUdensity -4) */ 1219 + u8 max_ampdu_density; 1220 + 1221 + /* Max AMSDU size 1 : 3839 bytes, 0 : 7935 bytes */ 1222 + u8 max_amsdu_size; 1223 + 1224 + /* Short GI support for 40Mhz packets */ 1225 + u8 sgi_40mhz; 1226 + 1227 + /* Short GI support for 20Mhz packets */ 1228 + u8 sgi_20Mhz; 1229 + 1230 + /* TODO move this parameter to the end for 3680 */ 1231 + /* These rates are the intersection of peer and self capabilities. */ 1232 + struct wcn36xx_hal_supported_rates supported_rates; 1233 + 1234 + /* Robust Management Frame (RMF) enabled/disabled */ 1235 + u8 rmf; 1236 + 1237 + /* The unicast encryption type in the association */ 1238 + u32 encrypt_type; 1239 + 1240 + /* HAL should update the existing STA entry, if this flag is set. UMAC 1241 + will set this flag in case of RE-ASSOC, where we want to reuse the 1242 + old STA ID. 0 = Add, 1 = Update */ 1243 + u8 action; 1244 + 1245 + /* U-APSD Flags: 1b per AC. Encoded as follows: 1246 + b7 b6 b5 b4 b3 b2 b1 b0 = 1247 + X X X X BE BK VI VO */ 1248 + u8 uapsd; 1249 + 1250 + /* Max SP Length */ 1251 + u8 max_sp_len; 1252 + 1253 + /* 11n Green Field preamble support 1254 + 0 - Not supported, 1 - Supported */ 1255 + u8 green_field_capable; 1256 + 1257 + /* MIMO Power Save mode */ 1258 + enum wcn36xx_hal_ht_mimo_state mimo_ps; 1259 + 1260 + /* Delayed BA Support */ 1261 + u8 delayed_ba_support; 1262 + 1263 + /* Max AMPDU duration in 32us */ 1264 + u8 max_ampdu_duration; 1265 + 1266 + /* HT STA should set it to 1 if it is enabled in BSS. HT STA should 1267 + * set it to 0 if AP does not support it. This indication is sent 1268 + * to HAL and HAL uses this flag to pickup up appropriate 40Mhz 1269 + * rates. */ 1270 + u8 dsss_cck_mode_40mhz; 1271 + 1272 + /* Valid STA Idx when action=Update. Set to 0xFF when invalid! 1273 + * Retained for backward compalibity with existing HAL code */ 1274 + u8 sta_index; 1275 + 1276 + /* BSSID of BSS to which station is associated. Set to 0xFF when 1277 + * invalid. Retained for backward compalibity with existing HAL 1278 + * code */ 1279 + u8 bssid_index; 1280 + 1281 + u8 p2p; 1282 + 1283 + /* TODO add this parameter for 3680. */ 1284 + /* Reserved to align next field on a dword boundary */ 1285 + /* u8 reserved; */ 1286 + } __packed; 1287 + 1288 + struct wcn36xx_hal_config_sta_req_msg { 1289 + struct wcn36xx_hal_msg_header header; 1290 + struct wcn36xx_hal_config_sta_params sta_params; 1291 + } __packed; 1292 + 1293 + struct wcn36xx_hal_config_sta_params_v1 { 1294 + /* BSSID of STA */ 1295 + u8 bssid[ETH_ALEN]; 1296 + 1297 + /* ASSOC ID, as assigned by UMAC */ 1298 + u16 aid; 1299 + 1300 + /* STA entry Type: 0 - Self, 1 - Other/Peer, 2 - BSSID, 3 - BCAST */ 1301 + u8 type; 1302 + 1303 + /* Short Preamble Supported. */ 1304 + u8 short_preamble_supported; 1305 + 1306 + /* MAC Address of STA */ 1307 + u8 mac[ETH_ALEN]; 1308 + 1309 + /* Listen interval of the STA */ 1310 + u16 listen_interval; 1311 + 1312 + /* Support for 11e/WMM */ 1313 + u8 wmm_enabled; 1314 + 1315 + /* 11n HT capable STA */ 1316 + u8 ht_capable; 1317 + 1318 + /* TX Width Set: 0 - 20 MHz only, 1 - 20/40 MHz */ 1319 + u8 tx_channel_width_set; 1320 + 1321 + /* RIFS mode 0 - NA, 1 - Allowed */ 1322 + u8 rifs_mode; 1323 + 1324 + /* L-SIG TXOP Protection mechanism 1325 + 0 - No Support, 1 - Supported 1326 + SG - there is global field */ 1327 + u8 lsig_txop_protection; 1328 + 1329 + /* Max Ampdu Size supported by STA. TPE programming. 1330 + 0 : 8k , 1 : 16k, 2 : 32k, 3 : 64k */ 1331 + u8 max_ampdu_size; 1332 + 1333 + /* Max Ampdu density. Used by RA. 3 : 0~7 : 2^(11nAMPDUdensity -4) */ 1334 + u8 max_ampdu_density; 1335 + 1336 + /* Max AMSDU size 1 : 3839 bytes, 0 : 7935 bytes */ 1337 + u8 max_amsdu_size; 1338 + 1339 + /* Short GI support for 40Mhz packets */ 1340 + u8 sgi_40mhz; 1341 + 1342 + /* Short GI support for 20Mhz packets */ 1343 + u8 sgi_20Mhz; 1344 + 1345 + /* Robust Management Frame (RMF) enabled/disabled */ 1346 + u8 rmf; 1347 + 1348 + /* The unicast encryption type in the association */ 1349 + u32 encrypt_type; 1350 + 1351 + /* HAL should update the existing STA entry, if this flag is set. UMAC 1352 + will set this flag in case of RE-ASSOC, where we want to reuse the 1353 + old STA ID. 0 = Add, 1 = Update */ 1354 + u8 action; 1355 + 1356 + /* U-APSD Flags: 1b per AC. Encoded as follows: 1357 + b7 b6 b5 b4 b3 b2 b1 b0 = 1358 + X X X X BE BK VI VO */ 1359 + u8 uapsd; 1360 + 1361 + /* Max SP Length */ 1362 + u8 max_sp_len; 1363 + 1364 + /* 11n Green Field preamble support 1365 + 0 - Not supported, 1 - Supported */ 1366 + u8 green_field_capable; 1367 + 1368 + /* MIMO Power Save mode */ 1369 + enum wcn36xx_hal_ht_mimo_state mimo_ps; 1370 + 1371 + /* Delayed BA Support */ 1372 + u8 delayed_ba_support; 1373 + 1374 + /* Max AMPDU duration in 32us */ 1375 + u8 max_ampdu_duration; 1376 + 1377 + /* HT STA should set it to 1 if it is enabled in BSS. HT STA should 1378 + * set it to 0 if AP does not support it. This indication is sent 1379 + * to HAL and HAL uses this flag to pickup up appropriate 40Mhz 1380 + * rates. */ 1381 + u8 dsss_cck_mode_40mhz; 1382 + 1383 + /* Valid STA Idx when action=Update. Set to 0xFF when invalid! 1384 + * Retained for backward compalibity with existing HAL code */ 1385 + u8 sta_index; 1386 + 1387 + /* BSSID of BSS to which station is associated. Set to 0xFF when 1388 + * invalid. Retained for backward compalibity with existing HAL 1389 + * code */ 1390 + u8 bssid_index; 1391 + 1392 + u8 p2p; 1393 + 1394 + /* Reserved to align next field on a dword boundary */ 1395 + u8 reserved; 1396 + 1397 + /* These rates are the intersection of peer and self capabilities. */ 1398 + struct wcn36xx_hal_supported_rates supported_rates; 1399 + } __packed; 1400 + 1401 + struct wcn36xx_hal_config_sta_req_msg_v1 { 1402 + struct wcn36xx_hal_msg_header header; 1403 + struct wcn36xx_hal_config_sta_params_v1 sta_params; 1404 + } __packed; 1405 + 1406 + struct config_sta_rsp_params { 1407 + /* success or failure */ 1408 + u32 status; 1409 + 1410 + /* Station index; valid only when 'status' field value SUCCESS */ 1411 + u8 sta_index; 1412 + 1413 + /* BSSID Index of BSS to which the station is associated */ 1414 + u8 bssid_index; 1415 + 1416 + /* DPU Index for PTK */ 1417 + u8 dpu_index; 1418 + 1419 + /* DPU Index for GTK */ 1420 + u8 bcast_dpu_index; 1421 + 1422 + /* DPU Index for IGTK */ 1423 + u8 bcast_mgmt_dpu_idx; 1424 + 1425 + /* PTK DPU signature */ 1426 + u8 uc_ucast_sig; 1427 + 1428 + /* GTK DPU isignature */ 1429 + u8 uc_bcast_sig; 1430 + 1431 + /* IGTK DPU signature */ 1432 + u8 uc_mgmt_sig; 1433 + 1434 + u8 p2p; 1435 + 1436 + } __packed; 1437 + 1438 + struct wcn36xx_hal_config_sta_rsp_msg { 1439 + struct wcn36xx_hal_msg_header header; 1440 + 1441 + struct config_sta_rsp_params params; 1442 + } __packed; 1443 + 1444 + /* Delete STA Request message */ 1445 + struct wcn36xx_hal_delete_sta_req_msg { 1446 + struct wcn36xx_hal_msg_header header; 1447 + 1448 + /* Index of STA to delete */ 1449 + u8 sta_index; 1450 + 1451 + } __packed; 1452 + 1453 + /* Delete STA Response message */ 1454 + struct wcn36xx_hal_delete_sta_rsp_msg { 1455 + struct wcn36xx_hal_msg_header header; 1456 + 1457 + /* success or failure */ 1458 + u32 status; 1459 + 1460 + /* Index of STA deleted */ 1461 + u8 sta_id; 1462 + } __packed; 1463 + 1464 + /* 12 Bytes long because this structure can be used to represent rate and 1465 + * extended rate set IEs. The parser assume this to be at least 12 */ 1466 + struct wcn36xx_hal_rate_set { 1467 + u8 num_rates; 1468 + u8 rate[WCN36XX_HAL_MAC_RATESET_EID_MAX]; 1469 + } __packed; 1470 + 1471 + /* access category record */ 1472 + struct wcn36xx_hal_aci_aifsn { 1473 + #ifndef ANI_LITTLE_BIT_ENDIAN 1474 + u8 rsvd:1; 1475 + u8 aci:2; 1476 + u8 acm:1; 1477 + u8 aifsn:4; 1478 + #else 1479 + u8 aifsn:4; 1480 + u8 acm:1; 1481 + u8 aci:2; 1482 + u8 rsvd:1; 1483 + #endif 1484 + } __packed; 1485 + 1486 + /* contention window size */ 1487 + struct wcn36xx_hal_mac_cw { 1488 + #ifndef ANI_LITTLE_BIT_ENDIAN 1489 + u8 max:4; 1490 + u8 min:4; 1491 + #else 1492 + u8 min:4; 1493 + u8 max:4; 1494 + #endif 1495 + } __packed; 1496 + 1497 + struct wcn36xx_hal_edca_param_record { 1498 + struct wcn36xx_hal_aci_aifsn aci; 1499 + struct wcn36xx_hal_mac_cw cw; 1500 + u16 txop_limit; 1501 + } __packed; 1502 + 1503 + struct wcn36xx_hal_mac_ssid { 1504 + u8 length; 1505 + u8 ssid[32]; 1506 + } __packed; 1507 + 1508 + /* Concurrency role. These are generic IDs that identify the various roles 1509 + * in the software system. */ 1510 + enum wcn36xx_hal_con_mode { 1511 + WCN36XX_HAL_STA_MODE = 0, 1512 + 1513 + /* to support softAp mode . This is misleading. 1514 + It means AP MODE only. */ 1515 + WCN36XX_HAL_STA_SAP_MODE = 1, 1516 + 1517 + WCN36XX_HAL_P2P_CLIENT_MODE, 1518 + WCN36XX_HAL_P2P_GO_MODE, 1519 + WCN36XX_HAL_MONITOR_MODE, 1520 + }; 1521 + 1522 + /* This is a bit pattern to be set for each mode 1523 + * bit 0 - sta mode 1524 + * bit 1 - ap mode 1525 + * bit 2 - p2p client mode 1526 + * bit 3 - p2p go mode */ 1527 + enum wcn36xx_hal_concurrency_mode { 1528 + HAL_STA = 1, 1529 + HAL_SAP = 2, 1530 + 1531 + /* to support sta, softAp mode . This means STA+AP mode */ 1532 + HAL_STA_SAP = 3, 1533 + 1534 + HAL_P2P_CLIENT = 4, 1535 + HAL_P2P_GO = 8, 1536 + HAL_MAX_CONCURRENCY_PERSONA = 4 1537 + }; 1538 + 1539 + struct wcn36xx_hal_config_bss_params { 1540 + /* BSSID */ 1541 + u8 bssid[ETH_ALEN]; 1542 + 1543 + /* Self Mac Address */ 1544 + u8 self_mac_addr[ETH_ALEN]; 1545 + 1546 + /* BSS type */ 1547 + enum wcn36xx_hal_bss_type bss_type; 1548 + 1549 + /* Operational Mode: AP =0, STA = 1 */ 1550 + u8 oper_mode; 1551 + 1552 + /* Network Type */ 1553 + enum wcn36xx_hal_nw_type nw_type; 1554 + 1555 + /* Used to classify PURE_11G/11G_MIXED to program MTU */ 1556 + u8 short_slot_time_supported; 1557 + 1558 + /* Co-exist with 11a STA */ 1559 + u8 lla_coexist; 1560 + 1561 + /* Co-exist with 11b STA */ 1562 + u8 llb_coexist; 1563 + 1564 + /* Co-exist with 11g STA */ 1565 + u8 llg_coexist; 1566 + 1567 + /* Coexistence with 11n STA */ 1568 + u8 ht20_coexist; 1569 + 1570 + /* Non GF coexist flag */ 1571 + u8 lln_non_gf_coexist; 1572 + 1573 + /* TXOP protection support */ 1574 + u8 lsig_tx_op_protection_full_support; 1575 + 1576 + /* RIFS mode */ 1577 + u8 rifs_mode; 1578 + 1579 + /* Beacon Interval in TU */ 1580 + u16 beacon_interval; 1581 + 1582 + /* DTIM period */ 1583 + u8 dtim_period; 1584 + 1585 + /* TX Width Set: 0 - 20 MHz only, 1 - 20/40 MHz */ 1586 + u8 tx_channel_width_set; 1587 + 1588 + /* Operating channel */ 1589 + u8 oper_channel; 1590 + 1591 + /* Extension channel for channel bonding */ 1592 + u8 ext_channel; 1593 + 1594 + /* Reserved to align next field on a dword boundary */ 1595 + u8 reserved; 1596 + 1597 + /* TODO move sta to the end for 3680 */ 1598 + /* Context of the station being added in HW 1599 + * Add a STA entry for "itself" - 1600 + * 1601 + * On AP - Add the AP itself in an "STA context" 1602 + * 1603 + * On STA - Add the AP to which this STA is joining in an 1604 + * "STA context" 1605 + */ 1606 + struct wcn36xx_hal_config_sta_params sta; 1607 + /* SSID of the BSS */ 1608 + struct wcn36xx_hal_mac_ssid ssid; 1609 + 1610 + /* HAL should update the existing BSS entry, if this flag is set. 1611 + * UMAC will set this flag in case of reassoc, where we want to 1612 + * resue the the old BSSID and still return success 0 = Add, 1 = 1613 + * Update */ 1614 + u8 action; 1615 + 1616 + /* MAC Rate Set */ 1617 + struct wcn36xx_hal_rate_set rateset; 1618 + 1619 + /* Enable/Disable HT capabilities of the BSS */ 1620 + u8 ht; 1621 + 1622 + /* Enable/Disable OBSS protection */ 1623 + u8 obss_prot_enabled; 1624 + 1625 + /* RMF enabled/disabled */ 1626 + u8 rmf; 1627 + 1628 + /* HT Operating Mode operating mode of the 802.11n STA */ 1629 + enum wcn36xx_hal_ht_operating_mode ht_oper_mode; 1630 + 1631 + /* Dual CTS Protection: 0 - Unused, 1 - Used */ 1632 + u8 dual_cts_protection; 1633 + 1634 + /* Probe Response Max retries */ 1635 + u8 max_probe_resp_retry_limit; 1636 + 1637 + /* To Enable Hidden ssid */ 1638 + u8 hidden_ssid; 1639 + 1640 + /* To Enable Disable FW Proxy Probe Resp */ 1641 + u8 proxy_probe_resp; 1642 + 1643 + /* Boolean to indicate if EDCA params are valid. UMAC might not 1644 + * have valid EDCA params or might not desire to apply EDCA params 1645 + * during config BSS. 0 implies Not Valid ; Non-Zero implies 1646 + * valid */ 1647 + u8 edca_params_valid; 1648 + 1649 + /* EDCA Parameters for Best Effort Access Category */ 1650 + struct wcn36xx_hal_edca_param_record acbe; 1651 + 1652 + /* EDCA Parameters forBackground Access Category */ 1653 + struct wcn36xx_hal_edca_param_record acbk; 1654 + 1655 + /* EDCA Parameters for Video Access Category */ 1656 + struct wcn36xx_hal_edca_param_record acvi; 1657 + 1658 + /* EDCA Parameters for Voice Access Category */ 1659 + struct wcn36xx_hal_edca_param_record acvo; 1660 + 1661 + /* Ext Bss Config Msg if set */ 1662 + u8 ext_set_sta_key_param_valid; 1663 + 1664 + /* SetStaKeyParams for ext bss msg */ 1665 + struct wcn36xx_hal_set_sta_key_params ext_set_sta_key_param; 1666 + 1667 + /* Persona for the BSS can be STA,AP,GO,CLIENT value same as enum 1668 + * wcn36xx_hal_con_mode */ 1669 + u8 wcn36xx_hal_persona; 1670 + 1671 + u8 spectrum_mgt_enable; 1672 + 1673 + /* HAL fills in the tx power used for mgmt frames in txMgmtPower */ 1674 + s8 tx_mgmt_power; 1675 + 1676 + /* maxTxPower has max power to be used after applying the power 1677 + * constraint if any */ 1678 + s8 max_tx_power; 1679 + } __packed; 1680 + 1681 + struct wcn36xx_hal_config_bss_req_msg { 1682 + struct wcn36xx_hal_msg_header header; 1683 + struct wcn36xx_hal_config_bss_params bss_params; 1684 + } __packed; 1685 + 1686 + struct wcn36xx_hal_config_bss_params_v1 { 1687 + /* BSSID */ 1688 + u8 bssid[ETH_ALEN]; 1689 + 1690 + /* Self Mac Address */ 1691 + u8 self_mac_addr[ETH_ALEN]; 1692 + 1693 + /* BSS type */ 1694 + enum wcn36xx_hal_bss_type bss_type; 1695 + 1696 + /* Operational Mode: AP =0, STA = 1 */ 1697 + u8 oper_mode; 1698 + 1699 + /* Network Type */ 1700 + enum wcn36xx_hal_nw_type nw_type; 1701 + 1702 + /* Used to classify PURE_11G/11G_MIXED to program MTU */ 1703 + u8 short_slot_time_supported; 1704 + 1705 + /* Co-exist with 11a STA */ 1706 + u8 lla_coexist; 1707 + 1708 + /* Co-exist with 11b STA */ 1709 + u8 llb_coexist; 1710 + 1711 + /* Co-exist with 11g STA */ 1712 + u8 llg_coexist; 1713 + 1714 + /* Coexistence with 11n STA */ 1715 + u8 ht20_coexist; 1716 + 1717 + /* Non GF coexist flag */ 1718 + u8 lln_non_gf_coexist; 1719 + 1720 + /* TXOP protection support */ 1721 + u8 lsig_tx_op_protection_full_support; 1722 + 1723 + /* RIFS mode */ 1724 + u8 rifs_mode; 1725 + 1726 + /* Beacon Interval in TU */ 1727 + u16 beacon_interval; 1728 + 1729 + /* DTIM period */ 1730 + u8 dtim_period; 1731 + 1732 + /* TX Width Set: 0 - 20 MHz only, 1 - 20/40 MHz */ 1733 + u8 tx_channel_width_set; 1734 + 1735 + /* Operating channel */ 1736 + u8 oper_channel; 1737 + 1738 + /* Extension channel for channel bonding */ 1739 + u8 ext_channel; 1740 + 1741 + /* Reserved to align next field on a dword boundary */ 1742 + u8 reserved; 1743 + 1744 + /* SSID of the BSS */ 1745 + struct wcn36xx_hal_mac_ssid ssid; 1746 + 1747 + /* HAL should update the existing BSS entry, if this flag is set. 1748 + * UMAC will set this flag in case of reassoc, where we want to 1749 + * resue the the old BSSID and still return success 0 = Add, 1 = 1750 + * Update */ 1751 + u8 action; 1752 + 1753 + /* MAC Rate Set */ 1754 + struct wcn36xx_hal_rate_set rateset; 1755 + 1756 + /* Enable/Disable HT capabilities of the BSS */ 1757 + u8 ht; 1758 + 1759 + /* Enable/Disable OBSS protection */ 1760 + u8 obss_prot_enabled; 1761 + 1762 + /* RMF enabled/disabled */ 1763 + u8 rmf; 1764 + 1765 + /* HT Operating Mode operating mode of the 802.11n STA */ 1766 + enum wcn36xx_hal_ht_operating_mode ht_oper_mode; 1767 + 1768 + /* Dual CTS Protection: 0 - Unused, 1 - Used */ 1769 + u8 dual_cts_protection; 1770 + 1771 + /* Probe Response Max retries */ 1772 + u8 max_probe_resp_retry_limit; 1773 + 1774 + /* To Enable Hidden ssid */ 1775 + u8 hidden_ssid; 1776 + 1777 + /* To Enable Disable FW Proxy Probe Resp */ 1778 + u8 proxy_probe_resp; 1779 + 1780 + /* Boolean to indicate if EDCA params are valid. UMAC might not 1781 + * have valid EDCA params or might not desire to apply EDCA params 1782 + * during config BSS. 0 implies Not Valid ; Non-Zero implies 1783 + * valid */ 1784 + u8 edca_params_valid; 1785 + 1786 + /* EDCA Parameters for Best Effort Access Category */ 1787 + struct wcn36xx_hal_edca_param_record acbe; 1788 + 1789 + /* EDCA Parameters forBackground Access Category */ 1790 + struct wcn36xx_hal_edca_param_record acbk; 1791 + 1792 + /* EDCA Parameters for Video Access Category */ 1793 + struct wcn36xx_hal_edca_param_record acvi; 1794 + 1795 + /* EDCA Parameters for Voice Access Category */ 1796 + struct wcn36xx_hal_edca_param_record acvo; 1797 + 1798 + /* Ext Bss Config Msg if set */ 1799 + u8 ext_set_sta_key_param_valid; 1800 + 1801 + /* SetStaKeyParams for ext bss msg */ 1802 + struct wcn36xx_hal_set_sta_key_params ext_set_sta_key_param; 1803 + 1804 + /* Persona for the BSS can be STA,AP,GO,CLIENT value same as enum 1805 + * wcn36xx_hal_con_mode */ 1806 + u8 wcn36xx_hal_persona; 1807 + 1808 + u8 spectrum_mgt_enable; 1809 + 1810 + /* HAL fills in the tx power used for mgmt frames in txMgmtPower */ 1811 + s8 tx_mgmt_power; 1812 + 1813 + /* maxTxPower has max power to be used after applying the power 1814 + * constraint if any */ 1815 + s8 max_tx_power; 1816 + 1817 + /* Context of the station being added in HW 1818 + * Add a STA entry for "itself" - 1819 + * 1820 + * On AP - Add the AP itself in an "STA context" 1821 + * 1822 + * On STA - Add the AP to which this STA is joining in an 1823 + * "STA context" 1824 + */ 1825 + struct wcn36xx_hal_config_sta_params_v1 sta; 1826 + } __packed; 1827 + 1828 + struct wcn36xx_hal_config_bss_req_msg_v1 { 1829 + struct wcn36xx_hal_msg_header header; 1830 + struct wcn36xx_hal_config_bss_params_v1 bss_params; 1831 + } __packed; 1832 + 1833 + struct wcn36xx_hal_config_bss_rsp_params { 1834 + /* Success or Failure */ 1835 + u32 status; 1836 + 1837 + /* BSS index allocated by HAL */ 1838 + u8 bss_index; 1839 + 1840 + /* DPU descriptor index for PTK */ 1841 + u8 dpu_desc_index; 1842 + 1843 + /* PTK DPU signature */ 1844 + u8 ucast_dpu_signature; 1845 + 1846 + /* DPU descriptor index for GTK */ 1847 + u8 bcast_dpu_desc_indx; 1848 + 1849 + /* GTK DPU signature */ 1850 + u8 bcast_dpu_signature; 1851 + 1852 + /* DPU descriptor for IGTK */ 1853 + u8 mgmt_dpu_desc_index; 1854 + 1855 + /* IGTK DPU signature */ 1856 + u8 mgmt_dpu_signature; 1857 + 1858 + /* Station Index for BSS entry */ 1859 + u8 bss_sta_index; 1860 + 1861 + /* Self station index for this BSS */ 1862 + u8 bss_self_sta_index; 1863 + 1864 + /* Bcast station for buffering bcast frames in AP role */ 1865 + u8 bss_bcast_sta_idx; 1866 + 1867 + /* MAC Address of STA(PEER/SELF) in staContext of configBSSReq */ 1868 + u8 mac[ETH_ALEN]; 1869 + 1870 + /* HAL fills in the tx power used for mgmt frames in this field. */ 1871 + s8 tx_mgmt_power; 1872 + 1873 + } __packed; 1874 + 1875 + struct wcn36xx_hal_config_bss_rsp_msg { 1876 + struct wcn36xx_hal_msg_header header; 1877 + struct wcn36xx_hal_config_bss_rsp_params bss_rsp_params; 1878 + } __packed; 1879 + 1880 + struct wcn36xx_hal_delete_bss_req_msg { 1881 + struct wcn36xx_hal_msg_header header; 1882 + 1883 + /* BSS index to be deleted */ 1884 + u8 bss_index; 1885 + 1886 + } __packed; 1887 + 1888 + struct wcn36xx_hal_delete_bss_rsp_msg { 1889 + struct wcn36xx_hal_msg_header header; 1890 + 1891 + /* Success or Failure */ 1892 + u32 status; 1893 + 1894 + /* BSS index that has been deleted */ 1895 + u8 bss_index; 1896 + 1897 + } __packed; 1898 + 1899 + struct wcn36xx_hal_join_req_msg { 1900 + struct wcn36xx_hal_msg_header header; 1901 + 1902 + /* Indicates the BSSID to which STA is going to associate */ 1903 + u8 bssid[ETH_ALEN]; 1904 + 1905 + /* Indicates the channel to switch to. */ 1906 + u8 channel; 1907 + 1908 + /* Self STA MAC */ 1909 + u8 self_sta_mac_addr[ETH_ALEN]; 1910 + 1911 + /* Local power constraint */ 1912 + u8 local_power_constraint; 1913 + 1914 + /* Secondary channel offset */ 1915 + enum phy_chan_bond_state secondary_channel_offset; 1916 + 1917 + /* link State */ 1918 + enum wcn36xx_hal_link_state link_state; 1919 + 1920 + /* Max TX power */ 1921 + s8 max_tx_power; 1922 + } __packed; 1923 + 1924 + struct wcn36xx_hal_join_rsp_msg { 1925 + struct wcn36xx_hal_msg_header header; 1926 + 1927 + /* success or failure */ 1928 + u32 status; 1929 + 1930 + /* HAL fills in the tx power used for mgmt frames in this field */ 1931 + u8 tx_mgmt_power; 1932 + } __packed; 1933 + 1934 + struct post_assoc_req_msg { 1935 + struct wcn36xx_hal_msg_header header; 1936 + 1937 + struct wcn36xx_hal_config_sta_params sta_params; 1938 + struct wcn36xx_hal_config_bss_params bss_params; 1939 + }; 1940 + 1941 + struct post_assoc_rsp_msg { 1942 + struct wcn36xx_hal_msg_header header; 1943 + struct config_sta_rsp_params sta_rsp_params; 1944 + struct wcn36xx_hal_config_bss_rsp_params bss_rsp_params; 1945 + }; 1946 + 1947 + /* This is used to create a set of WEP keys for a given BSS. */ 1948 + struct wcn36xx_hal_set_bss_key_req_msg { 1949 + struct wcn36xx_hal_msg_header header; 1950 + 1951 + /* BSS Index of the BSS */ 1952 + u8 bss_idx; 1953 + 1954 + /* Encryption Type used with peer */ 1955 + enum ani_ed_type enc_type; 1956 + 1957 + /* Number of keys */ 1958 + u8 num_keys; 1959 + 1960 + /* Array of keys. */ 1961 + struct wcn36xx_hal_keys keys[WCN36XX_HAL_MAC_MAX_NUM_OF_DEFAULT_KEYS]; 1962 + 1963 + /* Control for Replay Count, 1= Single TID based replay count on Tx 1964 + * 0 = Per TID based replay count on TX */ 1965 + u8 single_tid_rc; 1966 + } __packed; 1967 + 1968 + /* tagged version of set bss key */ 1969 + struct wcn36xx_hal_set_bss_key_req_msg_tagged { 1970 + struct wcn36xx_hal_set_bss_key_req_msg Msg; 1971 + u32 tag; 1972 + } __packed; 1973 + 1974 + struct wcn36xx_hal_set_bss_key_rsp_msg { 1975 + struct wcn36xx_hal_msg_header header; 1976 + 1977 + /* success or failure */ 1978 + u32 status; 1979 + } __packed; 1980 + 1981 + /* 1982 + * This is used configure the key information on a given station. 1983 + * When the sec_type is WEP40 or WEP104, the def_wep_idx is used to locate 1984 + * a preconfigured key from a BSS the station assoicated with; otherwise 1985 + * a new key descriptor is created based on the key field. 1986 + */ 1987 + struct wcn36xx_hal_set_sta_key_req_msg { 1988 + struct wcn36xx_hal_msg_header header; 1989 + struct wcn36xx_hal_set_sta_key_params set_sta_key_params; 1990 + } __packed; 1991 + 1992 + struct wcn36xx_hal_set_sta_key_rsp_msg { 1993 + struct wcn36xx_hal_msg_header header; 1994 + 1995 + /* success or failure */ 1996 + u32 status; 1997 + } __packed; 1998 + 1999 + struct wcn36xx_hal_remove_bss_key_req_msg { 2000 + struct wcn36xx_hal_msg_header header; 2001 + 2002 + /* BSS Index of the BSS */ 2003 + u8 bss_idx; 2004 + 2005 + /* Encryption Type used with peer */ 2006 + enum ani_ed_type enc_type; 2007 + 2008 + /* Key Id */ 2009 + u8 key_id; 2010 + 2011 + /* STATIC/DYNAMIC. Used in Nullifying in Key Descriptors for 2012 + * Static/Dynamic keys */ 2013 + enum ani_wep_type wep_type; 2014 + } __packed; 2015 + 2016 + struct wcn36xx_hal_remove_bss_key_rsp_msg { 2017 + struct wcn36xx_hal_msg_header header; 2018 + 2019 + /* success or failure */ 2020 + u32 status; 2021 + } __packed; 2022 + 2023 + /* 2024 + * This is used by PE to Remove the key information on a given station. 2025 + */ 2026 + struct wcn36xx_hal_remove_sta_key_req_msg { 2027 + struct wcn36xx_hal_msg_header header; 2028 + 2029 + /* STA Index */ 2030 + u16 sta_idx; 2031 + 2032 + /* Encryption Type used with peer */ 2033 + enum ani_ed_type enc_type; 2034 + 2035 + /* Key Id */ 2036 + u8 key_id; 2037 + 2038 + /* Whether to invalidate the Broadcast key or Unicast key. In case 2039 + * of WEP, the same key is used for both broadcast and unicast. */ 2040 + u8 unicast; 2041 + 2042 + } __packed; 2043 + 2044 + struct wcn36xx_hal_remove_sta_key_rsp_msg { 2045 + struct wcn36xx_hal_msg_header header; 2046 + 2047 + /*success or failure */ 2048 + u32 status; 2049 + 2050 + } __packed; 2051 + 2052 + #ifdef FEATURE_OEM_DATA_SUPPORT 2053 + 2054 + #ifndef OEM_DATA_REQ_SIZE 2055 + #define OEM_DATA_REQ_SIZE 134 2056 + #endif 2057 + 2058 + #ifndef OEM_DATA_RSP_SIZE 2059 + #define OEM_DATA_RSP_SIZE 1968 2060 + #endif 2061 + 2062 + struct start_oem_data_req_msg { 2063 + struct wcn36xx_hal_msg_header header; 2064 + 2065 + u32 status; 2066 + tSirMacAddr self_mac_addr; 2067 + u8 oem_data_req[OEM_DATA_REQ_SIZE]; 2068 + 2069 + }; 2070 + 2071 + struct start_oem_data_rsp_msg { 2072 + struct wcn36xx_hal_msg_header header; 2073 + 2074 + u8 oem_data_rsp[OEM_DATA_RSP_SIZE]; 2075 + }; 2076 + 2077 + #endif 2078 + 2079 + struct wcn36xx_hal_switch_channel_req_msg { 2080 + struct wcn36xx_hal_msg_header header; 2081 + 2082 + /* Channel number */ 2083 + u8 channel_number; 2084 + 2085 + /* Local power constraint */ 2086 + u8 local_power_constraint; 2087 + 2088 + /* Secondary channel offset */ 2089 + enum phy_chan_bond_state secondary_channel_offset; 2090 + 2091 + /* HAL fills in the tx power used for mgmt frames in this field. */ 2092 + u8 tx_mgmt_power; 2093 + 2094 + /* Max TX power */ 2095 + u8 max_tx_power; 2096 + 2097 + /* Self STA MAC */ 2098 + u8 self_sta_mac_addr[ETH_ALEN]; 2099 + 2100 + /* VO WIFI comment: BSSID needed to identify session. As the 2101 + * request has power constraints, this should be applied only to 2102 + * that session Since MTU timing and EDCA are sessionized, this 2103 + * struct needs to be sessionized and bssid needs to be out of the 2104 + * VOWifi feature flag V IMP: Keep bssId field at the end of this 2105 + * msg. It is used to mantain backward compatbility by way of 2106 + * ignoring if using new host/old FW or old host/new FW since it is 2107 + * at the end of this struct 2108 + */ 2109 + u8 bssid[ETH_ALEN]; 2110 + } __packed; 2111 + 2112 + struct wcn36xx_hal_switch_channel_rsp_msg { 2113 + struct wcn36xx_hal_msg_header header; 2114 + 2115 + /* Status */ 2116 + u32 status; 2117 + 2118 + /* Channel number - same as in request */ 2119 + u8 channel_number; 2120 + 2121 + /* HAL fills in the tx power used for mgmt frames in this field */ 2122 + u8 tx_mgmt_power; 2123 + 2124 + /* BSSID needed to identify session - same as in request */ 2125 + u8 bssid[ETH_ALEN]; 2126 + 2127 + } __packed; 2128 + 2129 + struct update_edca_params_req_msg { 2130 + struct wcn36xx_hal_msg_header header; 2131 + 2132 + /*BSS Index */ 2133 + u16 bss_index; 2134 + 2135 + /* Best Effort */ 2136 + struct wcn36xx_hal_edca_param_record acbe; 2137 + 2138 + /* Background */ 2139 + struct wcn36xx_hal_edca_param_record acbk; 2140 + 2141 + /* Video */ 2142 + struct wcn36xx_hal_edca_param_record acvi; 2143 + 2144 + /* Voice */ 2145 + struct wcn36xx_hal_edca_param_record acvo; 2146 + }; 2147 + 2148 + struct update_edca_params_rsp_msg { 2149 + struct wcn36xx_hal_msg_header header; 2150 + 2151 + /* success or failure */ 2152 + u32 status; 2153 + }; 2154 + 2155 + struct dpu_stats_params { 2156 + /* Index of STA to which the statistics */ 2157 + u16 sta_index; 2158 + 2159 + /* Encryption mode */ 2160 + u8 enc_mode; 2161 + 2162 + /* status */ 2163 + u32 status; 2164 + 2165 + /* Statistics */ 2166 + u32 send_blocks; 2167 + u32 recv_blocks; 2168 + u32 replays; 2169 + u8 mic_error_cnt; 2170 + u32 prot_excl_cnt; 2171 + u16 format_err_cnt; 2172 + u16 un_decryptable_cnt; 2173 + u32 decrypt_err_cnt; 2174 + u32 decrypt_ok_cnt; 2175 + }; 2176 + 2177 + struct wcn36xx_hal_stats_req_msg { 2178 + struct wcn36xx_hal_msg_header header; 2179 + 2180 + /* Valid STA Idx for per STA stats request */ 2181 + u32 sta_id; 2182 + 2183 + /* Categories of stats requested as specified in eHalStatsMask */ 2184 + u32 stats_mask; 2185 + }; 2186 + 2187 + struct ani_summary_stats_info { 2188 + /* Total number of packets(per AC) that were successfully 2189 + * transmitted with retries */ 2190 + u32 retry_cnt[4]; 2191 + 2192 + /* The number of MSDU packets and MMPDU frames per AC that the 2193 + * 802.11 station successfully transmitted after more than one 2194 + * retransmission attempt */ 2195 + u32 multiple_retry_cnt[4]; 2196 + 2197 + /* Total number of packets(per AC) that were successfully 2198 + * transmitted (with and without retries, including multi-cast, 2199 + * broadcast) */ 2200 + u32 tx_frm_cnt[4]; 2201 + 2202 + /* Total number of packets that were successfully received (after 2203 + * appropriate filter rules including multi-cast, broadcast) */ 2204 + u32 rx_frm_cnt; 2205 + 2206 + /* Total number of duplicate frames received successfully */ 2207 + u32 frm_dup_cnt; 2208 + 2209 + /* Total number packets(per AC) failed to transmit */ 2210 + u32 fail_cnt[4]; 2211 + 2212 + /* Total number of RTS/CTS sequence failures for transmission of a 2213 + * packet */ 2214 + u32 rts_fail_cnt; 2215 + 2216 + /* Total number packets failed transmit because of no ACK from the 2217 + * remote entity */ 2218 + u32 ack_fail_cnt; 2219 + 2220 + /* Total number of RTS/CTS sequence success for transmission of a 2221 + * packet */ 2222 + u32 rts_succ_cnt; 2223 + 2224 + /* The sum of the receive error count and dropped-receive-buffer 2225 + * error count. HAL will provide this as a sum of (FCS error) + 2226 + * (Fail get BD/PDU in HW) */ 2227 + u32 rx_discard_cnt; 2228 + 2229 + /* 2230 + * The receive error count. HAL will provide the RxP FCS error 2231 + * global counter. */ 2232 + u32 rx_error_cnt; 2233 + 2234 + /* The sum of the transmit-directed byte count, transmit-multicast 2235 + * byte count and transmit-broadcast byte count. HAL will sum TPE 2236 + * UC/MC/BCAST global counters to provide this. */ 2237 + u32 tx_byte_cnt; 2238 + }; 2239 + 2240 + /* defines tx_rate_flags */ 2241 + enum tx_rate_info { 2242 + /* Legacy rates */ 2243 + HAL_TX_RATE_LEGACY = 0x1, 2244 + 2245 + /* HT20 rates */ 2246 + HAL_TX_RATE_HT20 = 0x2, 2247 + 2248 + /* HT40 rates */ 2249 + HAL_TX_RATE_HT40 = 0x4, 2250 + 2251 + /* Rate with Short guard interval */ 2252 + HAL_TX_RATE_SGI = 0x8, 2253 + 2254 + /* Rate with Long guard interval */ 2255 + HAL_TX_RATE_LGI = 0x10 2256 + }; 2257 + 2258 + struct ani_global_class_a_stats_info { 2259 + /* The number of MPDU frames received by the 802.11 station for 2260 + * MSDU packets or MMPDU frames */ 2261 + u32 rx_frag_cnt; 2262 + 2263 + /* The number of MPDU frames received by the 802.11 station for 2264 + * MSDU packets or MMPDU frames when a promiscuous packet filter 2265 + * was enabled */ 2266 + u32 promiscuous_rx_frag_cnt; 2267 + 2268 + /* The receiver input sensitivity referenced to a FER of 8% at an 2269 + * MPDU length of 1024 bytes at the antenna connector. Each element 2270 + * of the array shall correspond to a supported rate and the order 2271 + * shall be the same as the supporteRates parameter. */ 2272 + u32 rx_input_sensitivity; 2273 + 2274 + /* The maximum transmit power in dBm upto one decimal. for eg: if 2275 + * it is 10.5dBm, the value would be 105 */ 2276 + u32 max_pwr; 2277 + 2278 + /* Number of times the receiver failed to synchronize with the 2279 + * incoming signal after detecting the sync in the preamble of the 2280 + * transmitted PLCP protocol data unit. */ 2281 + u32 sync_fail_cnt; 2282 + 2283 + /* Legacy transmit rate, in units of 500 kbit/sec, for the most 2284 + * recently transmitted frame */ 2285 + u32 tx_rate; 2286 + 2287 + /* mcs index for HT20 and HT40 rates */ 2288 + u32 mcs_index; 2289 + 2290 + /* to differentiate between HT20 and HT40 rates; short and long 2291 + * guard interval */ 2292 + u32 tx_rate_flags; 2293 + }; 2294 + 2295 + struct ani_global_security_stats { 2296 + /* The number of unencrypted received MPDU frames that the MAC 2297 + * layer discarded when the IEEE 802.11 dot11ExcludeUnencrypted 2298 + * management information base (MIB) object is enabled */ 2299 + u32 rx_wep_unencrypted_frm_cnt; 2300 + 2301 + /* The number of received MSDU packets that that the 802.11 station 2302 + * discarded because of MIC failures */ 2303 + u32 rx_mic_fail_cnt; 2304 + 2305 + /* The number of encrypted MPDU frames that the 802.11 station 2306 + * failed to decrypt because of a TKIP ICV error */ 2307 + u32 tkip_icv_err; 2308 + 2309 + /* The number of received MPDU frames that the 802.11 discarded 2310 + * because of an invalid AES-CCMP format */ 2311 + u32 aes_ccmp_format_err; 2312 + 2313 + /* The number of received MPDU frames that the 802.11 station 2314 + * discarded because of the AES-CCMP replay protection procedure */ 2315 + u32 aes_ccmp_replay_cnt; 2316 + 2317 + /* The number of received MPDU frames that the 802.11 station 2318 + * discarded because of errors detected by the AES-CCMP decryption 2319 + * algorithm */ 2320 + u32 aes_ccmp_decrpt_err; 2321 + 2322 + /* The number of encrypted MPDU frames received for which a WEP 2323 + * decryption key was not available on the 802.11 station */ 2324 + u32 wep_undecryptable_cnt; 2325 + 2326 + /* The number of encrypted MPDU frames that the 802.11 station 2327 + * failed to decrypt because of a WEP ICV error */ 2328 + u32 wep_icv_err; 2329 + 2330 + /* The number of received encrypted packets that the 802.11 station 2331 + * successfully decrypted */ 2332 + u32 rx_decrypt_succ_cnt; 2333 + 2334 + /* The number of encrypted packets that the 802.11 station failed 2335 + * to decrypt */ 2336 + u32 rx_decrypt_fail_cnt; 2337 + }; 2338 + 2339 + struct ani_global_class_b_stats_info { 2340 + struct ani_global_security_stats uc_stats; 2341 + struct ani_global_security_stats mc_bc_stats; 2342 + }; 2343 + 2344 + struct ani_global_class_c_stats_info { 2345 + /* This counter shall be incremented for a received A-MSDU frame 2346 + * with the stations MAC address in the address 1 field or an 2347 + * A-MSDU frame with a group address in the address 1 field */ 2348 + u32 rx_amsdu_cnt; 2349 + 2350 + /* This counter shall be incremented when the MAC receives an AMPDU 2351 + * from the PHY */ 2352 + u32 rx_ampdu_cnt; 2353 + 2354 + /* This counter shall be incremented when a Frame is transmitted 2355 + * only on the primary channel */ 2356 + u32 tx_20_frm_cnt; 2357 + 2358 + /* This counter shall be incremented when a Frame is received only 2359 + * on the primary channel */ 2360 + u32 rx_20_frm_cnt; 2361 + 2362 + /* This counter shall be incremented by the number of MPDUs 2363 + * received in the A-MPDU when an A-MPDU is received */ 2364 + u32 rx_mpdu_in_ampdu_cnt; 2365 + 2366 + /* This counter shall be incremented when an MPDU delimiter has a 2367 + * CRC error when this is the first CRC error in the received AMPDU 2368 + * or when the previous delimiter has been decoded correctly */ 2369 + u32 ampdu_delimiter_crc_err; 2370 + }; 2371 + 2372 + struct ani_per_sta_stats_info { 2373 + /* The number of MPDU frames that the 802.11 station transmitted 2374 + * and acknowledged through a received 802.11 ACK frame */ 2375 + u32 tx_frag_cnt[4]; 2376 + 2377 + /* This counter shall be incremented when an A-MPDU is transmitted */ 2378 + u32 tx_ampdu_cnt; 2379 + 2380 + /* This counter shall increment by the number of MPDUs in the AMPDU 2381 + * when an A-MPDU is transmitted */ 2382 + u32 tx_mpdu_in_ampdu_cnt; 2383 + }; 2384 + 2385 + struct wcn36xx_hal_stats_rsp_msg { 2386 + struct wcn36xx_hal_msg_header header; 2387 + 2388 + /* Success or Failure */ 2389 + u32 status; 2390 + 2391 + /* STA Idx */ 2392 + u32 sta_index; 2393 + 2394 + /* Categories of STATS being returned as per eHalStatsMask */ 2395 + u32 stats_mask; 2396 + 2397 + /* message type is same as the request type */ 2398 + u16 msg_type; 2399 + 2400 + /* length of the entire request, includes the pStatsBuf length too */ 2401 + u16 msg_len; 2402 + }; 2403 + 2404 + struct wcn36xx_hal_set_link_state_req_msg { 2405 + struct wcn36xx_hal_msg_header header; 2406 + 2407 + u8 bssid[ETH_ALEN]; 2408 + enum wcn36xx_hal_link_state state; 2409 + u8 self_mac_addr[ETH_ALEN]; 2410 + 2411 + } __packed; 2412 + 2413 + struct set_link_state_rsp_msg { 2414 + struct wcn36xx_hal_msg_header header; 2415 + 2416 + /* success or failure */ 2417 + u32 status; 2418 + }; 2419 + 2420 + /* TSPEC Params */ 2421 + struct wcn36xx_hal_ts_info_tfc { 2422 + #ifndef ANI_LITTLE_BIT_ENDIAN 2423 + u16 ackPolicy:2; 2424 + u16 userPrio:3; 2425 + u16 psb:1; 2426 + u16 aggregation:1; 2427 + u16 accessPolicy:2; 2428 + u16 direction:2; 2429 + u16 tsid:4; 2430 + u16 trafficType:1; 2431 + #else 2432 + u16 trafficType:1; 2433 + u16 tsid:4; 2434 + u16 direction:2; 2435 + u16 accessPolicy:2; 2436 + u16 aggregation:1; 2437 + u16 psb:1; 2438 + u16 userPrio:3; 2439 + u16 ackPolicy:2; 2440 + #endif 2441 + }; 2442 + 2443 + /* Flag to schedule the traffic type */ 2444 + struct wcn36xx_hal_ts_info_sch { 2445 + #ifndef ANI_LITTLE_BIT_ENDIAN 2446 + u8 rsvd:7; 2447 + u8 schedule:1; 2448 + #else 2449 + u8 schedule:1; 2450 + u8 rsvd:7; 2451 + #endif 2452 + }; 2453 + 2454 + /* Traffic and scheduling info */ 2455 + struct wcn36xx_hal_ts_info { 2456 + struct wcn36xx_hal_ts_info_tfc traffic; 2457 + struct wcn36xx_hal_ts_info_sch schedule; 2458 + }; 2459 + 2460 + /* Information elements */ 2461 + struct wcn36xx_hal_tspec_ie { 2462 + u8 type; 2463 + u8 length; 2464 + struct wcn36xx_hal_ts_info ts_info; 2465 + u16 nom_msdu_size; 2466 + u16 max_msdu_size; 2467 + u32 min_svc_interval; 2468 + u32 max_svc_interval; 2469 + u32 inact_interval; 2470 + u32 suspend_interval; 2471 + u32 svc_start_time; 2472 + u32 min_data_rate; 2473 + u32 mean_data_rate; 2474 + u32 peak_data_rate; 2475 + u32 max_burst_sz; 2476 + u32 delay_bound; 2477 + u32 min_phy_rate; 2478 + u16 surplus_bw; 2479 + u16 medium_time; 2480 + }; 2481 + 2482 + struct add_ts_req_msg { 2483 + struct wcn36xx_hal_msg_header header; 2484 + 2485 + /* Station Index */ 2486 + u16 sta_index; 2487 + 2488 + /* TSPEC handler uniquely identifying a TSPEC for a STA in a BSS */ 2489 + u16 tspec_index; 2490 + 2491 + /* To program TPE with required parameters */ 2492 + struct wcn36xx_hal_tspec_ie tspec; 2493 + 2494 + /* U-APSD Flags: 1b per AC. Encoded as follows: 2495 + b7 b6 b5 b4 b3 b2 b1 b0 = 2496 + X X X X BE BK VI VO */ 2497 + u8 uapsd; 2498 + 2499 + /* These parameters are for all the access categories */ 2500 + 2501 + /* Service Interval */ 2502 + u32 service_interval[WCN36XX_HAL_MAX_AC]; 2503 + 2504 + /* Suspend Interval */ 2505 + u32 suspend_interval[WCN36XX_HAL_MAX_AC]; 2506 + 2507 + /* Delay Interval */ 2508 + u32 delay_interval[WCN36XX_HAL_MAX_AC]; 2509 + }; 2510 + 2511 + struct add_rs_rsp_msg { 2512 + struct wcn36xx_hal_msg_header header; 2513 + 2514 + /* success or failure */ 2515 + u32 status; 2516 + }; 2517 + 2518 + struct del_ts_req_msg { 2519 + struct wcn36xx_hal_msg_header header; 2520 + 2521 + /* Station Index */ 2522 + u16 sta_index; 2523 + 2524 + /* TSPEC identifier uniquely identifying a TSPEC for a STA in a BSS */ 2525 + u16 tspec_index; 2526 + 2527 + /* To lookup station id using the mac address */ 2528 + u8 bssid[ETH_ALEN]; 2529 + }; 2530 + 2531 + struct del_ts_rsp_msg { 2532 + struct wcn36xx_hal_msg_header header; 2533 + 2534 + /* success or failure */ 2535 + u32 status; 2536 + }; 2537 + 2538 + /* End of TSpec Parameters */ 2539 + 2540 + /* Start of BLOCK ACK related Parameters */ 2541 + 2542 + struct wcn36xx_hal_add_ba_session_req_msg { 2543 + struct wcn36xx_hal_msg_header header; 2544 + 2545 + /* Station Index */ 2546 + u16 sta_index; 2547 + 2548 + /* Peer MAC Address */ 2549 + u8 mac_addr[ETH_ALEN]; 2550 + 2551 + /* ADDBA Action Frame dialog token 2552 + HAL will not interpret this object */ 2553 + u8 dialog_token; 2554 + 2555 + /* TID for which the BA is being setup 2556 + This identifies the TC or TS of interest */ 2557 + u8 tid; 2558 + 2559 + /* 0 - Delayed BA (Not supported) 2560 + 1 - Immediate BA */ 2561 + u8 policy; 2562 + 2563 + /* Indicates the number of buffers for this TID (baTID) 2564 + NOTE - This is the requested buffer size. When this 2565 + is processed by HAL and subsequently by HDD, it is 2566 + possible that HDD may change this buffer size. Any 2567 + change in the buffer size should be noted by PE and 2568 + advertized appropriately in the ADDBA response */ 2569 + u16 buffer_size; 2570 + 2571 + /* BA timeout in TU's 0 means no timeout will occur */ 2572 + u16 timeout; 2573 + 2574 + /* b0..b3 - Fragment Number - Always set to 0 2575 + b4..b15 - Starting Sequence Number of first MSDU 2576 + for which this BA is setup */ 2577 + u16 ssn; 2578 + 2579 + /* ADDBA direction 2580 + 1 - Originator 2581 + 0 - Recipient */ 2582 + u8 direction; 2583 + } __packed; 2584 + 2585 + struct wcn36xx_hal_add_ba_session_rsp_msg { 2586 + struct wcn36xx_hal_msg_header header; 2587 + 2588 + /* success or failure */ 2589 + u32 status; 2590 + 2591 + /* Dialog token */ 2592 + u8 dialog_token; 2593 + 2594 + /* TID for which the BA session has been setup */ 2595 + u8 ba_tid; 2596 + 2597 + /* BA Buffer Size allocated for the current BA session */ 2598 + u8 ba_buffer_size; 2599 + 2600 + u8 ba_session_id; 2601 + 2602 + /* Reordering Window buffer */ 2603 + u8 win_size; 2604 + 2605 + /* Station Index to id the sta */ 2606 + u8 sta_index; 2607 + 2608 + /* Starting Sequence Number */ 2609 + u16 ssn; 2610 + } __packed; 2611 + 2612 + struct wcn36xx_hal_add_ba_req_msg { 2613 + struct wcn36xx_hal_msg_header header; 2614 + 2615 + /* Session Id */ 2616 + u8 session_id; 2617 + 2618 + /* Reorder Window Size */ 2619 + u8 win_size; 2620 + /* Old FW 1.2.2.4 does not support this*/ 2621 + #ifdef FEATURE_ON_CHIP_REORDERING 2622 + u8 reordering_done_on_chip; 2623 + #endif 2624 + } __packed; 2625 + 2626 + struct wcn36xx_hal_add_ba_rsp_msg { 2627 + struct wcn36xx_hal_msg_header header; 2628 + 2629 + /* success or failure */ 2630 + u32 status; 2631 + 2632 + /* Dialog token */ 2633 + u8 dialog_token; 2634 + } __packed; 2635 + 2636 + struct add_ba_info { 2637 + u16 ba_enable:1; 2638 + u16 starting_seq_num:12; 2639 + u16 reserved:3; 2640 + }; 2641 + 2642 + struct wcn36xx_hal_trigger_ba_rsp_candidate { 2643 + u8 sta_addr[ETH_ALEN]; 2644 + struct add_ba_info ba_info[STACFG_MAX_TC]; 2645 + } __packed; 2646 + 2647 + struct wcn36xx_hal_trigget_ba_req_candidate { 2648 + u8 sta_index; 2649 + u8 tid_bitmap; 2650 + } __packed; 2651 + 2652 + struct wcn36xx_hal_trigger_ba_req_msg { 2653 + struct wcn36xx_hal_msg_header header; 2654 + 2655 + /* Session Id */ 2656 + u8 session_id; 2657 + 2658 + /* baCandidateCnt is followed by trigger BA 2659 + * Candidate List(tTriggerBaCandidate) 2660 + */ 2661 + u16 candidate_cnt; 2662 + 2663 + } __packed; 2664 + 2665 + struct wcn36xx_hal_trigger_ba_rsp_msg { 2666 + struct wcn36xx_hal_msg_header header; 2667 + 2668 + /* TO SUPPORT BT-AMP */ 2669 + u8 bssid[ETH_ALEN]; 2670 + 2671 + /* success or failure */ 2672 + u32 status; 2673 + 2674 + /* baCandidateCnt is followed by trigger BA 2675 + * Rsp Candidate List(tTriggerRspBaCandidate) 2676 + */ 2677 + u16 candidate_cnt; 2678 + } __packed; 2679 + 2680 + struct wcn36xx_hal_del_ba_req_msg { 2681 + struct wcn36xx_hal_msg_header header; 2682 + 2683 + /* Station Index */ 2684 + u16 sta_index; 2685 + 2686 + /* TID for which the BA session is being deleted */ 2687 + u8 tid; 2688 + 2689 + /* DELBA direction 2690 + 1 - Originator 2691 + 0 - Recipient */ 2692 + u8 direction; 2693 + } __packed; 2694 + 2695 + struct wcn36xx_hal_del_ba_rsp_msg { 2696 + struct wcn36xx_hal_msg_header header; 2697 + 2698 + /* success or failure */ 2699 + u32 status; 2700 + } __packed; 2701 + 2702 + struct tsm_stats_req_msg { 2703 + struct wcn36xx_hal_msg_header header; 2704 + 2705 + /* Traffic Id */ 2706 + u8 tid; 2707 + 2708 + u8 bssid[ETH_ALEN]; 2709 + }; 2710 + 2711 + struct tsm_stats_rsp_msg { 2712 + struct wcn36xx_hal_msg_header header; 2713 + 2714 + /*success or failure */ 2715 + u32 status; 2716 + 2717 + /* Uplink Packet Queue delay */ 2718 + u16 uplink_pkt_queue_delay; 2719 + 2720 + /* Uplink Packet Queue delay histogram */ 2721 + u16 uplink_pkt_queue_delay_hist[4]; 2722 + 2723 + /* Uplink Packet Transmit delay */ 2724 + u32 uplink_pkt_tx_delay; 2725 + 2726 + /* Uplink Packet loss */ 2727 + u16 uplink_pkt_loss; 2728 + 2729 + /* Uplink Packet count */ 2730 + u16 uplink_pkt_count; 2731 + 2732 + /* Roaming count */ 2733 + u8 roaming_count; 2734 + 2735 + /* Roaming Delay */ 2736 + u16 roaming_delay; 2737 + }; 2738 + 2739 + struct set_key_done_msg { 2740 + struct wcn36xx_hal_msg_header header; 2741 + 2742 + /*bssid of the keys */ 2743 + u8 bssidx; 2744 + u8 enc_type; 2745 + }; 2746 + 2747 + struct wcn36xx_hal_nv_img_download_req_msg { 2748 + /* Note: The length specified in wcn36xx_hal_nv_img_download_req_msg 2749 + * messages should be 2750 + * header.len = sizeof(wcn36xx_hal_nv_img_download_req_msg) + 2751 + * nv_img_buffer_size */ 2752 + struct wcn36xx_hal_msg_header header; 2753 + 2754 + /* Fragment sequence number of the NV Image. Note that NV Image 2755 + * might not fit into one message due to size limitation of the SMD 2756 + * channel FIFO. UMAC can hence choose to chop the NV blob into 2757 + * multiple fragments starting with seqeunce number 0, 1, 2 etc. 2758 + * The last fragment MUST be indicated by marking the 2759 + * isLastFragment field to 1. Note that all the NV blobs would be 2760 + * concatenated together by HAL without any padding bytes in 2761 + * between.*/ 2762 + u16 frag_number; 2763 + 2764 + /* Is this the last fragment? When set to 1 it indicates that no 2765 + * more fragments will be sent by UMAC and HAL can concatenate all 2766 + * the NV blobs rcvd & proceed with the parsing. HAL would generate 2767 + * a WCN36XX_HAL_DOWNLOAD_NV_RSP to the WCN36XX_HAL_DOWNLOAD_NV_REQ 2768 + * after it receives each fragment */ 2769 + u16 last_fragment; 2770 + 2771 + /* NV Image size (number of bytes) */ 2772 + u32 nv_img_buffer_size; 2773 + 2774 + /* Following the 'nv_img_buffer_size', there should be 2775 + * nv_img_buffer_size bytes of NV Image i.e. 2776 + * u8[nv_img_buffer_size] */ 2777 + } __packed; 2778 + 2779 + struct wcn36xx_hal_nv_img_download_rsp_msg { 2780 + struct wcn36xx_hal_msg_header header; 2781 + 2782 + /* Success or Failure. HAL would generate a 2783 + * WCN36XX_HAL_DOWNLOAD_NV_RSP after each fragment */ 2784 + u32 status; 2785 + } __packed; 2786 + 2787 + struct wcn36xx_hal_nv_store_ind { 2788 + /* Note: The length specified in tHalNvStoreInd messages should be 2789 + * header.msgLen = sizeof(tHalNvStoreInd) + nvBlobSize */ 2790 + struct wcn36xx_hal_msg_header header; 2791 + 2792 + /* NV Item */ 2793 + u32 table_id; 2794 + 2795 + /* Size of NV Blob */ 2796 + u32 nv_blob_size; 2797 + 2798 + /* Following the 'nvBlobSize', there should be nvBlobSize bytes of 2799 + * NV blob i.e. u8[nvBlobSize] */ 2800 + }; 2801 + 2802 + /* End of Block Ack Related Parameters */ 2803 + 2804 + #define WCN36XX_HAL_CIPHER_SEQ_CTR_SIZE 6 2805 + 2806 + /* Definition for MIC failure indication MAC reports this each time a MIC 2807 + * failure occures on Rx TKIP packet 2808 + */ 2809 + struct mic_failure_ind_msg { 2810 + struct wcn36xx_hal_msg_header header; 2811 + 2812 + u8 bssid[ETH_ALEN]; 2813 + 2814 + /* address used to compute MIC */ 2815 + u8 src_addr[ETH_ALEN]; 2816 + 2817 + /* transmitter address */ 2818 + u8 ta_addr[ETH_ALEN]; 2819 + 2820 + u8 dst_addr[ETH_ALEN]; 2821 + 2822 + u8 multicast; 2823 + 2824 + /* first byte of IV */ 2825 + u8 iv1; 2826 + 2827 + /* second byte of IV */ 2828 + u8 key_id; 2829 + 2830 + /* sequence number */ 2831 + u8 tsc[WCN36XX_HAL_CIPHER_SEQ_CTR_SIZE]; 2832 + 2833 + /* receive address */ 2834 + u8 rx_addr[ETH_ALEN]; 2835 + }; 2836 + 2837 + struct update_vht_op_mode_req_msg { 2838 + struct wcn36xx_hal_msg_header header; 2839 + 2840 + u16 op_mode; 2841 + u16 sta_id; 2842 + }; 2843 + 2844 + struct update_vht_op_mode_params_rsp_msg { 2845 + struct wcn36xx_hal_msg_header header; 2846 + 2847 + u32 status; 2848 + }; 2849 + 2850 + struct update_beacon_req_msg { 2851 + struct wcn36xx_hal_msg_header header; 2852 + 2853 + u8 bss_index; 2854 + 2855 + /* shortPreamble mode. HAL should update all the STA rates when it 2856 + * receives this message */ 2857 + u8 short_preamble; 2858 + 2859 + /* short Slot time. */ 2860 + u8 short_slot_time; 2861 + 2862 + /* Beacon Interval */ 2863 + u16 beacon_interval; 2864 + 2865 + /* Protection related */ 2866 + u8 lla_coexist; 2867 + u8 llb_coexist; 2868 + u8 llg_coexist; 2869 + u8 ht20_coexist; 2870 + u8 lln_non_gf_coexist; 2871 + u8 lsig_tx_op_protection_full_support; 2872 + u8 rifs_mode; 2873 + 2874 + u16 param_change_bitmap; 2875 + }; 2876 + 2877 + struct update_beacon_rsp_msg { 2878 + struct wcn36xx_hal_msg_header header; 2879 + u32 status; 2880 + }; 2881 + 2882 + struct wcn36xx_hal_send_beacon_req_msg { 2883 + struct wcn36xx_hal_msg_header header; 2884 + 2885 + /* length of the template. */ 2886 + u32 beacon_length; 2887 + 2888 + /* Beacon data. */ 2889 + u8 beacon[BEACON_TEMPLATE_SIZE]; 2890 + 2891 + u8 bssid[ETH_ALEN]; 2892 + 2893 + /* TIM IE offset from the beginning of the template. */ 2894 + u32 tim_ie_offset; 2895 + 2896 + /* P2P IE offset from the begining of the template */ 2897 + u16 p2p_ie_offset; 2898 + } __packed; 2899 + 2900 + struct send_beacon_rsp_msg { 2901 + struct wcn36xx_hal_msg_header header; 2902 + u32 status; 2903 + } __packed; 2904 + 2905 + struct enable_radar_req_msg { 2906 + struct wcn36xx_hal_msg_header header; 2907 + 2908 + u8 bssid[ETH_ALEN]; 2909 + u8 channel; 2910 + }; 2911 + 2912 + struct enable_radar_rsp_msg { 2913 + struct wcn36xx_hal_msg_header header; 2914 + 2915 + /* Link Parameters */ 2916 + u8 bssid[ETH_ALEN]; 2917 + 2918 + /* success or failure */ 2919 + u32 status; 2920 + }; 2921 + 2922 + struct radar_detect_intr_ind_msg { 2923 + struct wcn36xx_hal_msg_header header; 2924 + 2925 + u8 radar_det_channel; 2926 + }; 2927 + 2928 + struct radar_detect_ind_msg { 2929 + struct wcn36xx_hal_msg_header header; 2930 + 2931 + /* channel number in which the RADAR detected */ 2932 + u8 channel_number; 2933 + 2934 + /* RADAR pulse width in usecond */ 2935 + u16 radar_pulse_width; 2936 + 2937 + /* Number of RADAR pulses */ 2938 + u16 num_radar_pulse; 2939 + }; 2940 + 2941 + struct wcn36xx_hal_get_tpc_report_req_msg { 2942 + struct wcn36xx_hal_msg_header header; 2943 + 2944 + u8 sta[ETH_ALEN]; 2945 + u8 dialog_token; 2946 + u8 txpower; 2947 + }; 2948 + 2949 + struct wcn36xx_hal_get_tpc_report_rsp_msg { 2950 + struct wcn36xx_hal_msg_header header; 2951 + 2952 + /* success or failure */ 2953 + u32 status; 2954 + }; 2955 + 2956 + struct wcn36xx_hal_send_probe_resp_req_msg { 2957 + struct wcn36xx_hal_msg_header header; 2958 + 2959 + u8 probe_resp_template[BEACON_TEMPLATE_SIZE]; 2960 + u32 probe_resp_template_len; 2961 + u32 proxy_probe_req_valid_ie_bmap[8]; 2962 + u8 bssid[ETH_ALEN]; 2963 + }; 2964 + 2965 + struct send_probe_resp_rsp_msg { 2966 + struct wcn36xx_hal_msg_header header; 2967 + 2968 + /* success or failure */ 2969 + u32 status; 2970 + }; 2971 + 2972 + struct send_unknown_frame_rx_ind_msg { 2973 + struct wcn36xx_hal_msg_header header; 2974 + 2975 + /* success or failure */ 2976 + u32 status; 2977 + }; 2978 + 2979 + struct wcn36xx_hal_delete_sta_context_ind_msg { 2980 + struct wcn36xx_hal_msg_header header; 2981 + 2982 + u16 aid; 2983 + u16 sta_id; 2984 + 2985 + /* TO SUPPORT BT-AMP */ 2986 + u8 bssid[ETH_ALEN]; 2987 + 2988 + /* HAL copies bssid from the sta table. */ 2989 + u8 addr2[ETH_ALEN]; 2990 + 2991 + /* To unify the keepalive / unknown A2 / tim-based disa */ 2992 + u16 reason_code; 2993 + } __packed; 2994 + 2995 + struct indicate_del_sta { 2996 + struct wcn36xx_hal_msg_header header; 2997 + u8 aid; 2998 + u8 sta_index; 2999 + u8 bss_index; 3000 + u8 reason_code; 3001 + u32 status; 3002 + }; 3003 + 3004 + struct bt_amp_event_msg { 3005 + struct wcn36xx_hal_msg_header header; 3006 + 3007 + enum bt_amp_event_type btAmpEventType; 3008 + }; 3009 + 3010 + struct bt_amp_event_rsp { 3011 + struct wcn36xx_hal_msg_header header; 3012 + 3013 + /* success or failure */ 3014 + u32 status; 3015 + }; 3016 + 3017 + struct tl_hal_flush_ac_req_msg { 3018 + struct wcn36xx_hal_msg_header header; 3019 + 3020 + /* Station Index. originates from HAL */ 3021 + u8 sta_id; 3022 + 3023 + /* TID for which the transmit queue is being flushed */ 3024 + u8 tid; 3025 + }; 3026 + 3027 + struct tl_hal_flush_ac_rsp_msg { 3028 + struct wcn36xx_hal_msg_header header; 3029 + 3030 + /* Station Index. originates from HAL */ 3031 + u8 sta_id; 3032 + 3033 + /* TID for which the transmit queue is being flushed */ 3034 + u8 tid; 3035 + 3036 + /* success or failure */ 3037 + u32 status; 3038 + }; 3039 + 3040 + struct wcn36xx_hal_enter_imps_req_msg { 3041 + struct wcn36xx_hal_msg_header header; 3042 + }; 3043 + 3044 + struct wcn36xx_hal_exit_imps_req { 3045 + struct wcn36xx_hal_msg_header header; 3046 + }; 3047 + 3048 + struct wcn36xx_hal_enter_bmps_req_msg { 3049 + struct wcn36xx_hal_msg_header header; 3050 + 3051 + u8 bss_index; 3052 + 3053 + /* TBTT value derived from the last beacon */ 3054 + #ifndef BUILD_QWPTTSTATIC 3055 + u64 tbtt; 3056 + #endif 3057 + u8 dtim_count; 3058 + 3059 + /* DTIM period given to HAL during association may not be valid, if 3060 + * association is based on ProbeRsp instead of beacon. */ 3061 + u8 dtim_period; 3062 + 3063 + /* For CCX and 11R Roaming */ 3064 + u32 rssi_filter_period; 3065 + 3066 + u32 num_beacon_per_rssi_average; 3067 + u8 rssi_filter_enable; 3068 + } __packed; 3069 + 3070 + struct wcn36xx_hal_exit_bmps_req_msg { 3071 + struct wcn36xx_hal_msg_header header; 3072 + 3073 + u8 send_data_null; 3074 + u8 bss_index; 3075 + } __packed; 3076 + 3077 + struct wcn36xx_hal_missed_beacon_ind_msg { 3078 + struct wcn36xx_hal_msg_header header; 3079 + 3080 + u8 bss_index; 3081 + } __packed; 3082 + 3083 + /* Beacon Filtering data structures */ 3084 + 3085 + /* The above structure would be followed by multiple of below mentioned 3086 + * structure 3087 + */ 3088 + struct beacon_filter_ie { 3089 + u8 element_id; 3090 + u8 check_ie_presence; 3091 + u8 offset; 3092 + u8 value; 3093 + u8 bitmask; 3094 + u8 ref; 3095 + }; 3096 + 3097 + struct wcn36xx_hal_add_bcn_filter_req_msg { 3098 + struct wcn36xx_hal_msg_header header; 3099 + 3100 + u16 capability_info; 3101 + u16 capability_mask; 3102 + u16 beacon_interval; 3103 + u16 ie_num; 3104 + u8 bss_index; 3105 + u8 reserved; 3106 + }; 3107 + 3108 + struct wcn36xx_hal_rem_bcn_filter_req { 3109 + struct wcn36xx_hal_msg_header header; 3110 + 3111 + u8 ie_Count; 3112 + u8 rem_ie_id[1]; 3113 + }; 3114 + 3115 + #define WCN36XX_HAL_IPV4_ARP_REPLY_OFFLOAD 0 3116 + #define WCN36XX_HAL_IPV6_NEIGHBOR_DISCOVERY_OFFLOAD 1 3117 + #define WCN36XX_HAL_IPV6_NS_OFFLOAD 2 3118 + #define WCN36XX_HAL_IPV6_ADDR_LEN 16 3119 + #define WCN36XX_HAL_OFFLOAD_DISABLE 0 3120 + #define WCN36XX_HAL_OFFLOAD_ENABLE 1 3121 + #define WCN36XX_HAL_OFFLOAD_BCAST_FILTER_ENABLE 0x2 3122 + #define WCN36XX_HAL_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE \ 3123 + (HAL_OFFLOAD_ENABLE|HAL_OFFLOAD_BCAST_FILTER_ENABLE) 3124 + 3125 + struct wcn36xx_hal_ns_offload_params { 3126 + u8 src_ipv6_addr[WCN36XX_HAL_IPV6_ADDR_LEN]; 3127 + u8 self_ipv6_addr[WCN36XX_HAL_IPV6_ADDR_LEN]; 3128 + 3129 + /* Only support 2 possible Network Advertisement IPv6 address */ 3130 + u8 target_ipv6_addr1[WCN36XX_HAL_IPV6_ADDR_LEN]; 3131 + u8 target_ipv6_addr2[WCN36XX_HAL_IPV6_ADDR_LEN]; 3132 + 3133 + u8 self_addr[ETH_ALEN]; 3134 + u8 src_ipv6_addr_valid:1; 3135 + u8 target_ipv6_addr1_valid:1; 3136 + u8 target_ipv6_addr2_valid:1; 3137 + u8 reserved1:5; 3138 + 3139 + /* make it DWORD aligned */ 3140 + u8 reserved2; 3141 + 3142 + /* slot index for this offload */ 3143 + u32 slot_index; 3144 + u8 bss_index; 3145 + }; 3146 + 3147 + struct wcn36xx_hal_host_offload_req { 3148 + u8 offload_Type; 3149 + 3150 + /* enable or disable */ 3151 + u8 enable; 3152 + 3153 + union { 3154 + u8 host_ipv4_addr[4]; 3155 + u8 host_ipv6_addr[WCN36XX_HAL_IPV6_ADDR_LEN]; 3156 + } u; 3157 + }; 3158 + 3159 + struct wcn36xx_hal_host_offload_req_msg { 3160 + struct wcn36xx_hal_msg_header header; 3161 + struct wcn36xx_hal_host_offload_req host_offload_params; 3162 + struct wcn36xx_hal_ns_offload_params ns_offload_params; 3163 + }; 3164 + 3165 + /* Packet Types. */ 3166 + #define WCN36XX_HAL_KEEP_ALIVE_NULL_PKT 1 3167 + #define WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP 2 3168 + 3169 + /* Enable or disable keep alive */ 3170 + #define WCN36XX_HAL_KEEP_ALIVE_DISABLE 0 3171 + #define WCN36XX_HAL_KEEP_ALIVE_ENABLE 1 3172 + #define WCN36XX_KEEP_ALIVE_TIME_PERIOD 30 /* unit: s */ 3173 + 3174 + /* Keep Alive request. */ 3175 + struct wcn36xx_hal_keep_alive_req_msg { 3176 + struct wcn36xx_hal_msg_header header; 3177 + 3178 + u8 packet_type; 3179 + u32 time_period; 3180 + u8 host_ipv4_addr[WCN36XX_HAL_IPV4_ADDR_LEN]; 3181 + u8 dest_ipv4_addr[WCN36XX_HAL_IPV4_ADDR_LEN]; 3182 + u8 dest_addr[ETH_ALEN]; 3183 + u8 bss_index; 3184 + } __packed; 3185 + 3186 + struct wcn36xx_hal_rssi_threshold_req_msg { 3187 + struct wcn36xx_hal_msg_header header; 3188 + 3189 + s8 threshold1:8; 3190 + s8 threshold2:8; 3191 + s8 threshold3:8; 3192 + u8 thres1_pos_notify:1; 3193 + u8 thres1_neg_notify:1; 3194 + u8 thres2_pos_notify:1; 3195 + u8 thres2_neg_notify:1; 3196 + u8 thres3_pos_notify:1; 3197 + u8 thres3_neg_notify:1; 3198 + u8 reserved10:2; 3199 + }; 3200 + 3201 + struct wcn36xx_hal_enter_uapsd_req_msg { 3202 + struct wcn36xx_hal_msg_header header; 3203 + 3204 + u8 bk_delivery:1; 3205 + u8 be_delivery:1; 3206 + u8 vi_delivery:1; 3207 + u8 vo_delivery:1; 3208 + u8 bk_trigger:1; 3209 + u8 be_trigger:1; 3210 + u8 vi_trigger:1; 3211 + u8 vo_trigger:1; 3212 + u8 bss_index; 3213 + }; 3214 + 3215 + struct wcn36xx_hal_exit_uapsd_req_msg { 3216 + struct wcn36xx_hal_msg_header header; 3217 + u8 bss_index; 3218 + }; 3219 + 3220 + #define WCN36XX_HAL_WOWL_BCAST_PATTERN_MAX_SIZE 128 3221 + #define WCN36XX_HAL_WOWL_BCAST_MAX_NUM_PATTERNS 16 3222 + 3223 + struct wcn36xx_hal_wowl_add_bcast_ptrn_req_msg { 3224 + struct wcn36xx_hal_msg_header header; 3225 + 3226 + /* Pattern ID */ 3227 + u8 id; 3228 + 3229 + /* Pattern byte offset from beginning of the 802.11 packet to start 3230 + * of the wake-up pattern */ 3231 + u8 byte_Offset; 3232 + 3233 + /* Non-Zero Pattern size */ 3234 + u8 size; 3235 + 3236 + /* Pattern */ 3237 + u8 pattern[WCN36XX_HAL_WOWL_BCAST_PATTERN_MAX_SIZE]; 3238 + 3239 + /* Non-zero pattern mask size */ 3240 + u8 mask_size; 3241 + 3242 + /* Pattern mask */ 3243 + u8 mask[WCN36XX_HAL_WOWL_BCAST_PATTERN_MAX_SIZE]; 3244 + 3245 + /* Extra pattern */ 3246 + u8 extra[WCN36XX_HAL_WOWL_BCAST_PATTERN_MAX_SIZE]; 3247 + 3248 + /* Extra pattern mask */ 3249 + u8 mask_extra[WCN36XX_HAL_WOWL_BCAST_PATTERN_MAX_SIZE]; 3250 + 3251 + u8 bss_index; 3252 + }; 3253 + 3254 + struct wcn36xx_hal_wow_del_bcast_ptrn_req_msg { 3255 + struct wcn36xx_hal_msg_header header; 3256 + 3257 + /* Pattern ID of the wakeup pattern to be deleted */ 3258 + u8 id; 3259 + u8 bss_index; 3260 + }; 3261 + 3262 + struct wcn36xx_hal_wowl_enter_req_msg { 3263 + struct wcn36xx_hal_msg_header header; 3264 + 3265 + /* Enables/disables magic packet filtering */ 3266 + u8 magic_packet_enable; 3267 + 3268 + /* Magic pattern */ 3269 + u8 magic_pattern[ETH_ALEN]; 3270 + 3271 + /* Enables/disables packet pattern filtering in firmware. Enabling 3272 + * this flag enables broadcast pattern matching in Firmware. If 3273 + * unicast pattern matching is also desired, 3274 + * ucUcastPatternFilteringEnable flag must be set tot true as well 3275 + */ 3276 + u8 pattern_filtering_enable; 3277 + 3278 + /* Enables/disables unicast packet pattern filtering. This flag 3279 + * specifies whether we want to do pattern match on unicast packets 3280 + * as well and not just broadcast packets. This flag has no effect 3281 + * if the ucPatternFilteringEnable (main controlling flag) is set 3282 + * to false 3283 + */ 3284 + u8 ucast_pattern_filtering_enable; 3285 + 3286 + /* This configuration is valid only when magicPktEnable=1. It 3287 + * requests hardware to wake up when it receives the Channel Switch 3288 + * Action Frame. 3289 + */ 3290 + u8 wow_channel_switch_receive; 3291 + 3292 + /* This configuration is valid only when magicPktEnable=1. It 3293 + * requests hardware to wake up when it receives the 3294 + * Deauthentication Frame. 3295 + */ 3296 + u8 wow_deauth_receive; 3297 + 3298 + /* This configuration is valid only when magicPktEnable=1. It 3299 + * requests hardware to wake up when it receives the Disassociation 3300 + * Frame. 3301 + */ 3302 + u8 wow_disassoc_receive; 3303 + 3304 + /* This configuration is valid only when magicPktEnable=1. It 3305 + * requests hardware to wake up when it has missed consecutive 3306 + * beacons. This is a hardware register configuration (NOT a 3307 + * firmware configuration). 3308 + */ 3309 + u8 wow_max_missed_beacons; 3310 + 3311 + /* This configuration is valid only when magicPktEnable=1. This is 3312 + * a timeout value in units of microsec. It requests hardware to 3313 + * unconditionally wake up after it has stayed in WoWLAN mode for 3314 + * some time. Set 0 to disable this feature. 3315 + */ 3316 + u8 wow_max_sleep; 3317 + 3318 + /* This configuration directs the WoW packet filtering to look for 3319 + * EAP-ID requests embedded in EAPOL frames and use this as a wake 3320 + * source. 3321 + */ 3322 + u8 wow_eap_id_request_enable; 3323 + 3324 + /* This configuration directs the WoW packet filtering to look for 3325 + * EAPOL-4WAY requests and use this as a wake source. 3326 + */ 3327 + u8 wow_eapol_4way_enable; 3328 + 3329 + /* This configuration allows a host wakeup on an network scan 3330 + * offload match. 3331 + */ 3332 + u8 wow_net_scan_offload_match; 3333 + 3334 + /* This configuration allows a host wakeup on any GTK rekeying 3335 + * error. 3336 + */ 3337 + u8 wow_gtk_rekey_error; 3338 + 3339 + /* This configuration allows a host wakeup on BSS connection loss. 3340 + */ 3341 + u8 wow_bss_connection_loss; 3342 + 3343 + u8 bss_index; 3344 + }; 3345 + 3346 + struct wcn36xx_hal_wowl_exit_req_msg { 3347 + struct wcn36xx_hal_msg_header header; 3348 + 3349 + u8 bss_index; 3350 + }; 3351 + 3352 + struct wcn36xx_hal_get_rssi_req_msg { 3353 + struct wcn36xx_hal_msg_header header; 3354 + }; 3355 + 3356 + struct wcn36xx_hal_get_roam_rssi_req_msg { 3357 + struct wcn36xx_hal_msg_header header; 3358 + 3359 + /* Valid STA Idx for per STA stats request */ 3360 + u32 sta_id; 3361 + }; 3362 + 3363 + struct wcn36xx_hal_set_uapsd_ac_params_req_msg { 3364 + struct wcn36xx_hal_msg_header header; 3365 + 3366 + /* STA index */ 3367 + u8 sta_idx; 3368 + 3369 + /* Access Category */ 3370 + u8 ac; 3371 + 3372 + /* User Priority */ 3373 + u8 up; 3374 + 3375 + /* Service Interval */ 3376 + u32 service_interval; 3377 + 3378 + /* Suspend Interval */ 3379 + u32 suspend_interval; 3380 + 3381 + /* Delay Interval */ 3382 + u32 delay_interval; 3383 + }; 3384 + 3385 + struct wcn36xx_hal_configure_rxp_filter_req_msg { 3386 + struct wcn36xx_hal_msg_header header; 3387 + 3388 + u8 set_mcst_bcst_filter_setting; 3389 + u8 set_mcst_bcst_filter; 3390 + }; 3391 + 3392 + struct wcn36xx_hal_enter_imps_rsp_msg { 3393 + struct wcn36xx_hal_msg_header header; 3394 + 3395 + /* success or failure */ 3396 + u32 status; 3397 + }; 3398 + 3399 + struct wcn36xx_hal_exit_imps_rsp_msg { 3400 + struct wcn36xx_hal_msg_header header; 3401 + 3402 + /* success or failure */ 3403 + u32 status; 3404 + }; 3405 + 3406 + struct wcn36xx_hal_enter_bmps_rsp_msg { 3407 + struct wcn36xx_hal_msg_header header; 3408 + 3409 + /* success or failure */ 3410 + u32 status; 3411 + 3412 + u8 bss_index; 3413 + } __packed; 3414 + 3415 + struct wcn36xx_hal_exit_bmps_rsp_msg { 3416 + struct wcn36xx_hal_msg_header header; 3417 + 3418 + /* success or failure */ 3419 + u32 status; 3420 + 3421 + u8 bss_index; 3422 + } __packed; 3423 + 3424 + struct wcn36xx_hal_enter_uapsd_rsp_msg { 3425 + struct wcn36xx_hal_msg_header header; 3426 + 3427 + /* success or failure */ 3428 + u32 status; 3429 + 3430 + u8 bss_index; 3431 + }; 3432 + 3433 + struct wcn36xx_hal_exit_uapsd_rsp_msg { 3434 + struct wcn36xx_hal_msg_header header; 3435 + 3436 + /* success or failure */ 3437 + u32 status; 3438 + 3439 + u8 bss_index; 3440 + }; 3441 + 3442 + struct wcn36xx_hal_rssi_notification_ind_msg { 3443 + struct wcn36xx_hal_msg_header header; 3444 + 3445 + u32 rssi_thres1_pos_cross:1; 3446 + u32 rssi_thres1_neg_cross:1; 3447 + u32 rssi_thres2_pos_cross:1; 3448 + u32 rssi_thres2_neg_cross:1; 3449 + u32 rssi_thres3_pos_cross:1; 3450 + u32 rssi_thres3_neg_cross:1; 3451 + u32 avg_rssi:8; 3452 + u32 reserved:18; 3453 + 3454 + }; 3455 + 3456 + struct wcn36xx_hal_get_rssio_rsp_msg { 3457 + struct wcn36xx_hal_msg_header header; 3458 + 3459 + /* success or failure */ 3460 + u32 status; 3461 + s8 rssi; 3462 + 3463 + }; 3464 + 3465 + struct wcn36xx_hal_get_roam_rssi_rsp_msg { 3466 + struct wcn36xx_hal_msg_header header; 3467 + 3468 + /* success or failure */ 3469 + u32 status; 3470 + 3471 + u8 sta_id; 3472 + s8 rssi; 3473 + }; 3474 + 3475 + struct wcn36xx_hal_wowl_enter_rsp_msg { 3476 + struct wcn36xx_hal_msg_header header; 3477 + 3478 + /* success or failure */ 3479 + u32 status; 3480 + u8 bss_index; 3481 + }; 3482 + 3483 + struct wcn36xx_hal_wowl_exit_rsp_msg { 3484 + struct wcn36xx_hal_msg_header header; 3485 + 3486 + /* success or failure */ 3487 + u32 status; 3488 + u8 bss_index; 3489 + }; 3490 + 3491 + struct wcn36xx_hal_add_bcn_filter_rsp_msg { 3492 + struct wcn36xx_hal_msg_header header; 3493 + 3494 + /* success or failure */ 3495 + u32 status; 3496 + }; 3497 + 3498 + struct wcn36xx_hal_rem_bcn_filter_rsp_msg { 3499 + struct wcn36xx_hal_msg_header header; 3500 + 3501 + /* success or failure */ 3502 + u32 status; 3503 + }; 3504 + 3505 + struct wcn36xx_hal_add_wowl_bcast_ptrn_rsp_msg { 3506 + struct wcn36xx_hal_msg_header header; 3507 + 3508 + /* success or failure */ 3509 + u32 status; 3510 + u8 bss_index; 3511 + }; 3512 + 3513 + struct wcn36xx_hal_del_wowl_bcast_ptrn_rsp_msg { 3514 + struct wcn36xx_hal_msg_header header; 3515 + 3516 + /* success or failure */ 3517 + u32 status; 3518 + u8 bss_index; 3519 + }; 3520 + 3521 + struct wcn36xx_hal_host_offload_rsp_msg { 3522 + struct wcn36xx_hal_msg_header header; 3523 + 3524 + /* success or failure */ 3525 + u32 status; 3526 + }; 3527 + 3528 + struct wcn36xx_hal_keep_alive_rsp_msg { 3529 + struct wcn36xx_hal_msg_header header; 3530 + 3531 + /* success or failure */ 3532 + u32 status; 3533 + }; 3534 + 3535 + struct wcn36xx_hal_set_rssi_thresh_rsp_msg { 3536 + struct wcn36xx_hal_msg_header header; 3537 + 3538 + /* success or failure */ 3539 + u32 status; 3540 + }; 3541 + 3542 + struct wcn36xx_hal_set_uapsd_ac_params_rsp_msg { 3543 + struct wcn36xx_hal_msg_header header; 3544 + 3545 + /* success or failure */ 3546 + u32 status; 3547 + }; 3548 + 3549 + struct wcn36xx_hal_configure_rxp_filter_rsp_msg { 3550 + struct wcn36xx_hal_msg_header header; 3551 + 3552 + /* success or failure */ 3553 + u32 status; 3554 + }; 3555 + 3556 + struct set_max_tx_pwr_req { 3557 + struct wcn36xx_hal_msg_header header; 3558 + 3559 + /* BSSID is needed to identify which session issued this request. 3560 + * As the request has power constraints, this should be applied 3561 + * only to that session */ 3562 + u8 bssid[ETH_ALEN]; 3563 + 3564 + u8 self_addr[ETH_ALEN]; 3565 + 3566 + /* In request, power == MaxTx power to be used. */ 3567 + u8 power; 3568 + }; 3569 + 3570 + struct set_max_tx_pwr_rsp_msg { 3571 + struct wcn36xx_hal_msg_header header; 3572 + 3573 + /* power == tx power used for management frames */ 3574 + u8 power; 3575 + 3576 + /* success or failure */ 3577 + u32 status; 3578 + }; 3579 + 3580 + struct set_tx_pwr_req_msg { 3581 + struct wcn36xx_hal_msg_header header; 3582 + 3583 + /* TX Power in milli watts */ 3584 + u32 tx_power; 3585 + 3586 + u8 bss_index; 3587 + }; 3588 + 3589 + struct set_tx_pwr_rsp_msg { 3590 + struct wcn36xx_hal_msg_header header; 3591 + 3592 + /* success or failure */ 3593 + u32 status; 3594 + }; 3595 + 3596 + struct get_tx_pwr_req_msg { 3597 + struct wcn36xx_hal_msg_header header; 3598 + 3599 + u8 sta_id; 3600 + }; 3601 + 3602 + struct get_tx_pwr_rsp_msg { 3603 + struct wcn36xx_hal_msg_header header; 3604 + 3605 + /* success or failure */ 3606 + u32 status; 3607 + 3608 + /* TX Power in milli watts */ 3609 + u32 tx_power; 3610 + }; 3611 + 3612 + struct set_p2p_gonoa_req_msg { 3613 + struct wcn36xx_hal_msg_header header; 3614 + 3615 + u8 opp_ps; 3616 + u32 ct_window; 3617 + u8 count; 3618 + u32 duration; 3619 + u32 interval; 3620 + u32 single_noa_duration; 3621 + u8 ps_selection; 3622 + }; 3623 + 3624 + struct set_p2p_gonoa_rsp_msg { 3625 + struct wcn36xx_hal_msg_header header; 3626 + 3627 + /* success or failure */ 3628 + u32 status; 3629 + }; 3630 + 3631 + struct wcn36xx_hal_add_sta_self_req { 3632 + struct wcn36xx_hal_msg_header header; 3633 + 3634 + u8 self_addr[ETH_ALEN]; 3635 + u32 status; 3636 + } __packed; 3637 + 3638 + struct wcn36xx_hal_add_sta_self_rsp_msg { 3639 + struct wcn36xx_hal_msg_header header; 3640 + 3641 + /* success or failure */ 3642 + u32 status; 3643 + 3644 + /* Self STA Index */ 3645 + u8 self_sta_index; 3646 + 3647 + /* DPU Index (IGTK, PTK, GTK all same) */ 3648 + u8 dpu_index; 3649 + 3650 + /* DPU Signature */ 3651 + u8 dpu_signature; 3652 + } __packed; 3653 + 3654 + struct wcn36xx_hal_del_sta_self_req_msg { 3655 + struct wcn36xx_hal_msg_header header; 3656 + 3657 + u8 self_addr[ETH_ALEN]; 3658 + } __packed; 3659 + 3660 + struct wcn36xx_hal_del_sta_self_rsp_msg { 3661 + struct wcn36xx_hal_msg_header header; 3662 + 3663 + /*success or failure */ 3664 + u32 status; 3665 + 3666 + u8 self_addr[ETH_ALEN]; 3667 + } __packed; 3668 + 3669 + struct aggr_add_ts_req { 3670 + struct wcn36xx_hal_msg_header header; 3671 + 3672 + /* Station Index */ 3673 + u16 sta_idx; 3674 + 3675 + /* TSPEC handler uniquely identifying a TSPEC for a STA in a BSS. 3676 + * This will carry the bitmap with the bit positions representing 3677 + * different AC.s */ 3678 + u16 tspec_index; 3679 + 3680 + /* Tspec info per AC To program TPE with required parameters */ 3681 + struct wcn36xx_hal_tspec_ie tspec[WCN36XX_HAL_MAX_AC]; 3682 + 3683 + /* U-APSD Flags: 1b per AC. Encoded as follows: 3684 + b7 b6 b5 b4 b3 b2 b1 b0 = 3685 + X X X X BE BK VI VO */ 3686 + u8 uapsd; 3687 + 3688 + /* These parameters are for all the access categories */ 3689 + 3690 + /* Service Interval */ 3691 + u32 service_interval[WCN36XX_HAL_MAX_AC]; 3692 + 3693 + /* Suspend Interval */ 3694 + u32 suspend_interval[WCN36XX_HAL_MAX_AC]; 3695 + 3696 + /* Delay Interval */ 3697 + u32 delay_interval[WCN36XX_HAL_MAX_AC]; 3698 + }; 3699 + 3700 + struct aggr_add_ts_rsp_msg { 3701 + struct wcn36xx_hal_msg_header header; 3702 + 3703 + /* success or failure */ 3704 + u32 status0; 3705 + 3706 + /* FIXME PRIMA for future use for 11R */ 3707 + u32 status1; 3708 + }; 3709 + 3710 + struct wcn36xx_hal_configure_apps_cpu_wakeup_state_req_msg { 3711 + struct wcn36xx_hal_msg_header header; 3712 + 3713 + u8 is_apps_cpu_awake; 3714 + }; 3715 + 3716 + struct wcn36xx_hal_configure_apps_cpu_wakeup_state_rsp_msg { 3717 + struct wcn36xx_hal_msg_header header; 3718 + 3719 + /* success or failure */ 3720 + u32 status; 3721 + }; 3722 + 3723 + struct wcn36xx_hal_dump_cmd_req_msg { 3724 + struct wcn36xx_hal_msg_header header; 3725 + 3726 + u32 arg1; 3727 + u32 arg2; 3728 + u32 arg3; 3729 + u32 arg4; 3730 + u32 arg5; 3731 + } __packed; 3732 + 3733 + struct wcn36xx_hal_dump_cmd_rsp_msg { 3734 + struct wcn36xx_hal_msg_header header; 3735 + 3736 + /* success or failure */ 3737 + u32 status; 3738 + 3739 + /* Length of the responce message */ 3740 + u32 rsp_length; 3741 + 3742 + /* FIXME: Currently considering the the responce will be less than 3743 + * 100bytes */ 3744 + u8 rsp_buffer[DUMPCMD_RSP_BUFFER]; 3745 + } __packed; 3746 + 3747 + #define WLAN_COEX_IND_DATA_SIZE (4) 3748 + #define WLAN_COEX_IND_TYPE_DISABLE_HB_MONITOR (0) 3749 + #define WLAN_COEX_IND_TYPE_ENABLE_HB_MONITOR (1) 3750 + 3751 + struct coex_ind_msg { 3752 + struct wcn36xx_hal_msg_header header; 3753 + 3754 + /* Coex Indication Type */ 3755 + u32 type; 3756 + 3757 + /* Coex Indication Data */ 3758 + u32 data[WLAN_COEX_IND_DATA_SIZE]; 3759 + }; 3760 + 3761 + struct wcn36xx_hal_tx_compl_ind_msg { 3762 + struct wcn36xx_hal_msg_header header; 3763 + 3764 + /* Tx Complete Indication Success or Failure */ 3765 + u32 status; 3766 + }; 3767 + 3768 + struct wcn36xx_hal_wlan_host_suspend_ind_msg { 3769 + struct wcn36xx_hal_msg_header header; 3770 + 3771 + u32 configured_mcst_bcst_filter_setting; 3772 + u32 active_session_count; 3773 + }; 3774 + 3775 + struct wcn36xx_hal_wlan_exclude_unencrpted_ind_msg { 3776 + struct wcn36xx_hal_msg_header header; 3777 + 3778 + u8 dot11_exclude_unencrypted; 3779 + u8 bssid[ETH_ALEN]; 3780 + }; 3781 + 3782 + struct noa_attr_ind_msg { 3783 + struct wcn36xx_hal_msg_header header; 3784 + 3785 + u8 index; 3786 + u8 opp_ps_flag; 3787 + u16 ctwin; 3788 + 3789 + u16 noa1_interval_count; 3790 + u16 bss_index; 3791 + u32 noa1_duration; 3792 + u32 noa1_interval; 3793 + u32 noa1_starttime; 3794 + 3795 + u16 noa2_interval_count; 3796 + u16 reserved2; 3797 + u32 noa2_duration; 3798 + u32 noa2_interval; 3799 + u32 noa2_start_time; 3800 + 3801 + u32 status; 3802 + }; 3803 + 3804 + struct noa_start_ind_msg { 3805 + struct wcn36xx_hal_msg_header header; 3806 + 3807 + u32 status; 3808 + u32 bss_index; 3809 + }; 3810 + 3811 + struct wcn36xx_hal_wlan_host_resume_req_msg { 3812 + struct wcn36xx_hal_msg_header header; 3813 + 3814 + u8 configured_mcst_bcst_filter_setting; 3815 + }; 3816 + 3817 + struct wcn36xx_hal_host_resume_rsp_msg { 3818 + struct wcn36xx_hal_msg_header header; 3819 + 3820 + /* success or failure */ 3821 + u32 status; 3822 + }; 3823 + 3824 + struct wcn36xx_hal_del_ba_ind_msg { 3825 + struct wcn36xx_hal_msg_header header; 3826 + 3827 + u16 sta_idx; 3828 + 3829 + /* Peer MAC Address, whose BA session has timed out */ 3830 + u8 peer_addr[ETH_ALEN]; 3831 + 3832 + /* TID for which a BA session timeout is being triggered */ 3833 + u8 ba_tid; 3834 + 3835 + /* DELBA direction 3836 + * 1 - Originator 3837 + * 0 - Recipient 3838 + */ 3839 + u8 direction; 3840 + 3841 + u32 reason_code; 3842 + 3843 + /* TO SUPPORT BT-AMP */ 3844 + u8 bssid[ETH_ALEN]; 3845 + }; 3846 + 3847 + /* PNO Messages */ 3848 + 3849 + /* Max number of channels that a network can be found on */ 3850 + #define WCN36XX_HAL_PNO_MAX_NETW_CHANNELS 26 3851 + 3852 + /* Max number of channels that a network can be found on */ 3853 + #define WCN36XX_HAL_PNO_MAX_NETW_CHANNELS_EX 60 3854 + 3855 + /* Maximum numbers of networks supported by PNO */ 3856 + #define WCN36XX_HAL_PNO_MAX_SUPP_NETWORKS 16 3857 + 3858 + /* The number of scan time intervals that can be programmed into PNO */ 3859 + #define WCN36XX_HAL_PNO_MAX_SCAN_TIMERS 10 3860 + 3861 + /* Maximum size of the probe template */ 3862 + #define WCN36XX_HAL_PNO_MAX_PROBE_SIZE 450 3863 + 3864 + /* Type of PNO enabling: 3865 + * 3866 + * Immediate - scanning will start immediately and PNO procedure will be 3867 + * repeated based on timer 3868 + * 3869 + * Suspend - scanning will start at suspend 3870 + * 3871 + * Resume - scanning will start on system resume 3872 + */ 3873 + enum pno_mode { 3874 + PNO_MODE_IMMEDIATE, 3875 + PNO_MODE_ON_SUSPEND, 3876 + PNO_MODE_ON_RESUME, 3877 + PNO_MODE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE 3878 + }; 3879 + 3880 + /* Authentication type */ 3881 + enum auth_type { 3882 + AUTH_TYPE_ANY = 0, 3883 + AUTH_TYPE_OPEN_SYSTEM = 1, 3884 + 3885 + /* Upper layer authentication types */ 3886 + AUTH_TYPE_WPA = 2, 3887 + AUTH_TYPE_WPA_PSK = 3, 3888 + 3889 + AUTH_TYPE_RSN = 4, 3890 + AUTH_TYPE_RSN_PSK = 5, 3891 + AUTH_TYPE_FT_RSN = 6, 3892 + AUTH_TYPE_FT_RSN_PSK = 7, 3893 + AUTH_TYPE_WAPI_WAI_CERTIFICATE = 8, 3894 + AUTH_TYPE_WAPI_WAI_PSK = 9, 3895 + 3896 + AUTH_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE 3897 + }; 3898 + 3899 + /* Encryption type */ 3900 + enum ed_type { 3901 + ED_ANY = 0, 3902 + ED_NONE = 1, 3903 + ED_WEP = 2, 3904 + ED_TKIP = 3, 3905 + ED_CCMP = 4, 3906 + ED_WPI = 5, 3907 + 3908 + ED_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE 3909 + }; 3910 + 3911 + /* SSID broadcast type */ 3912 + enum ssid_bcast_type { 3913 + BCAST_UNKNOWN = 0, 3914 + BCAST_NORMAL = 1, 3915 + BCAST_HIDDEN = 2, 3916 + 3917 + BCAST_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE 3918 + }; 3919 + 3920 + /* The network description for which PNO will have to look for */ 3921 + struct network_type { 3922 + /* SSID of the BSS */ 3923 + struct wcn36xx_hal_mac_ssid ssid; 3924 + 3925 + /* Authentication type for the network */ 3926 + enum auth_type authentication; 3927 + 3928 + /* Encryption type for the network */ 3929 + enum ed_type encryption; 3930 + 3931 + /* Indicate the channel on which the Network can be found 0 - if 3932 + * all channels */ 3933 + u8 channel_count; 3934 + u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS]; 3935 + 3936 + /* Indicates the RSSI threshold for the network to be considered */ 3937 + u8 rssi_threshold; 3938 + }; 3939 + 3940 + struct scan_timer { 3941 + /* How much it should wait */ 3942 + u32 value; 3943 + 3944 + /* How many times it should repeat that wait value 0 - keep using 3945 + * this timer until PNO is disabled */ 3946 + u32 repeat; 3947 + 3948 + /* e.g: 2 3 4 0 - it will wait 2s between consecutive scans for 3 3949 + * times - after that it will wait 4s between consecutive scans 3950 + * until disabled */ 3951 + }; 3952 + 3953 + /* The network parameters to be sent to the PNO algorithm */ 3954 + struct scan_timers_type { 3955 + /* set to 0 if you wish for PNO to use its default telescopic timer */ 3956 + u8 count; 3957 + 3958 + /* A set value represents the amount of time that PNO will wait 3959 + * between two consecutive scan procedures If the desired is for a 3960 + * uniform timer that fires always at the exact same interval - one 3961 + * single value is to be set If there is a desire for a more 3962 + * complex - telescopic like timer multiple values can be set - 3963 + * once PNO reaches the end of the array it will continue scanning 3964 + * at intervals presented by the last value */ 3965 + struct scan_timer values[WCN36XX_HAL_PNO_MAX_SCAN_TIMERS]; 3966 + }; 3967 + 3968 + /* Preferred network list request */ 3969 + struct set_pref_netw_list_req { 3970 + struct wcn36xx_hal_msg_header header; 3971 + 3972 + /* Enable PNO */ 3973 + u32 enable; 3974 + 3975 + /* Immediate, On Suspend, On Resume */ 3976 + enum pno_mode mode; 3977 + 3978 + /* Number of networks sent for PNO */ 3979 + u32 networks_count; 3980 + 3981 + /* The networks that PNO needs to look for */ 3982 + struct network_type networks[WCN36XX_HAL_PNO_MAX_SUPP_NETWORKS]; 3983 + 3984 + /* The scan timers required for PNO */ 3985 + struct scan_timers_type scan_timers; 3986 + 3987 + /* Probe template for 2.4GHz band */ 3988 + u16 band_24g_probe_size; 3989 + u8 band_24g_probe_template[WCN36XX_HAL_PNO_MAX_PROBE_SIZE]; 3990 + 3991 + /* Probe template for 5GHz band */ 3992 + u16 band_5g_probe_size; 3993 + u8 band_5g_probe_template[WCN36XX_HAL_PNO_MAX_PROBE_SIZE]; 3994 + }; 3995 + 3996 + /* The network description for which PNO will have to look for */ 3997 + struct network_type_new { 3998 + /* SSID of the BSS */ 3999 + struct wcn36xx_hal_mac_ssid ssid; 4000 + 4001 + /* Authentication type for the network */ 4002 + enum auth_type authentication; 4003 + 4004 + /* Encryption type for the network */ 4005 + enum ed_type encryption; 4006 + 4007 + /* SSID broadcast type, normal, hidden or unknown */ 4008 + enum ssid_bcast_type bcast_network_type; 4009 + 4010 + /* Indicate the channel on which the Network can be found 0 - if 4011 + * all channels */ 4012 + u8 channel_count; 4013 + u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS]; 4014 + 4015 + /* Indicates the RSSI threshold for the network to be considered */ 4016 + u8 rssi_threshold; 4017 + }; 4018 + 4019 + /* Preferred network list request new */ 4020 + struct set_pref_netw_list_req_new { 4021 + struct wcn36xx_hal_msg_header header; 4022 + 4023 + /* Enable PNO */ 4024 + u32 enable; 4025 + 4026 + /* Immediate, On Suspend, On Resume */ 4027 + enum pno_mode mode; 4028 + 4029 + /* Number of networks sent for PNO */ 4030 + u32 networks_count; 4031 + 4032 + /* The networks that PNO needs to look for */ 4033 + struct network_type_new networks[WCN36XX_HAL_PNO_MAX_SUPP_NETWORKS]; 4034 + 4035 + /* The scan timers required for PNO */ 4036 + struct scan_timers_type scan_timers; 4037 + 4038 + /* Probe template for 2.4GHz band */ 4039 + u16 band_24g_probe_size; 4040 + u8 band_24g_probe_template[WCN36XX_HAL_PNO_MAX_PROBE_SIZE]; 4041 + 4042 + /* Probe template for 5GHz band */ 4043 + u16 band_5g_probe_size; 4044 + u8 band_5g_probe_template[WCN36XX_HAL_PNO_MAX_PROBE_SIZE]; 4045 + }; 4046 + 4047 + /* Preferred network list response */ 4048 + struct set_pref_netw_list_resp { 4049 + struct wcn36xx_hal_msg_header header; 4050 + 4051 + /* status of the request - just to indicate that PNO has 4052 + * acknowledged the request and will start scanning */ 4053 + u32 status; 4054 + }; 4055 + 4056 + /* Preferred network found indication */ 4057 + struct pref_netw_found_ind { 4058 + 4059 + struct wcn36xx_hal_msg_header header; 4060 + 4061 + /* Network that was found with the highest RSSI */ 4062 + struct wcn36xx_hal_mac_ssid ssid; 4063 + 4064 + /* Indicates the RSSI */ 4065 + u8 rssi; 4066 + }; 4067 + 4068 + /* RSSI Filter request */ 4069 + struct set_rssi_filter_req { 4070 + struct wcn36xx_hal_msg_header header; 4071 + 4072 + /* RSSI Threshold */ 4073 + u8 rssi_threshold; 4074 + }; 4075 + 4076 + /* Set RSSI filter resp */ 4077 + struct set_rssi_filter_resp { 4078 + struct wcn36xx_hal_msg_header header; 4079 + 4080 + /* status of the request */ 4081 + u32 status; 4082 + }; 4083 + 4084 + /* Update scan params - sent from host to PNO to be used during PNO 4085 + * scanningx */ 4086 + struct wcn36xx_hal_update_scan_params_req { 4087 + 4088 + struct wcn36xx_hal_msg_header header; 4089 + 4090 + /* Host setting for 11d */ 4091 + u8 dot11d_enabled; 4092 + 4093 + /* Lets PNO know that host has determined the regulatory domain */ 4094 + u8 dot11d_resolved; 4095 + 4096 + /* Channels on which PNO is allowed to scan */ 4097 + u8 channel_count; 4098 + u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS]; 4099 + 4100 + /* Minimum channel time */ 4101 + u16 active_min_ch_time; 4102 + 4103 + /* Maximum channel time */ 4104 + u16 active_max_ch_time; 4105 + 4106 + /* Minimum channel time */ 4107 + u16 passive_min_ch_time; 4108 + 4109 + /* Maximum channel time */ 4110 + u16 passive_max_ch_time; 4111 + 4112 + /* Cb State */ 4113 + enum phy_chan_bond_state state; 4114 + } __packed; 4115 + 4116 + /* Update scan params - sent from host to PNO to be used during PNO 4117 + * scanningx */ 4118 + struct update_scan_params_req_ex { 4119 + 4120 + struct wcn36xx_hal_msg_header header; 4121 + 4122 + /* Host setting for 11d */ 4123 + u8 dot11d_enabled; 4124 + 4125 + /* Lets PNO know that host has determined the regulatory domain */ 4126 + u8 dot11d_resolved; 4127 + 4128 + /* Channels on which PNO is allowed to scan */ 4129 + u8 channel_count; 4130 + u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS_EX]; 4131 + 4132 + /* Minimum channel time */ 4133 + u16 active_min_ch_time; 4134 + 4135 + /* Maximum channel time */ 4136 + u16 active_max_ch_time; 4137 + 4138 + /* Minimum channel time */ 4139 + u16 passive_min_ch_time; 4140 + 4141 + /* Maximum channel time */ 4142 + u16 passive_max_ch_time; 4143 + 4144 + /* Cb State */ 4145 + enum phy_chan_bond_state state; 4146 + }; 4147 + 4148 + /* Update scan params - sent from host to PNO to be used during PNO 4149 + * scanningx */ 4150 + struct wcn36xx_hal_update_scan_params_resp { 4151 + 4152 + struct wcn36xx_hal_msg_header header; 4153 + 4154 + /* status of the request */ 4155 + u32 status; 4156 + } __packed; 4157 + 4158 + struct wcn36xx_hal_set_tx_per_tracking_req_msg { 4159 + struct wcn36xx_hal_msg_header header; 4160 + 4161 + /* 0: disable, 1:enable */ 4162 + u8 tx_per_tracking_enable; 4163 + 4164 + /* Check period, unit is sec. */ 4165 + u8 tx_per_tracking_period; 4166 + 4167 + /* (Fail TX packet)/(Total TX packet) ratio, the unit is 10%. */ 4168 + u8 tx_per_tracking_ratio; 4169 + 4170 + /* A watermark of check number, once the tx packet exceed this 4171 + * number, we do the check, default is 5 */ 4172 + u32 tx_per_tracking_watermark; 4173 + }; 4174 + 4175 + struct wcn36xx_hal_set_tx_per_tracking_rsp_msg { 4176 + struct wcn36xx_hal_msg_header header; 4177 + 4178 + /* success or failure */ 4179 + u32 status; 4180 + 4181 + }; 4182 + 4183 + struct tx_per_hit_ind_msg { 4184 + struct wcn36xx_hal_msg_header header; 4185 + }; 4186 + 4187 + /* Packet Filtering Definitions Begin */ 4188 + #define WCN36XX_HAL_PROTOCOL_DATA_LEN 8 4189 + #define WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS 240 4190 + #define WCN36XX_HAL_MAX_NUM_FILTERS 20 4191 + #define WCN36XX_HAL_MAX_CMP_PER_FILTER 10 4192 + 4193 + enum wcn36xx_hal_receive_packet_filter_type { 4194 + HAL_RCV_FILTER_TYPE_INVALID, 4195 + HAL_RCV_FILTER_TYPE_FILTER_PKT, 4196 + HAL_RCV_FILTER_TYPE_BUFFER_PKT, 4197 + HAL_RCV_FILTER_TYPE_MAX_ENUM_SIZE 4198 + }; 4199 + 4200 + enum wcn36xx_hal_rcv_pkt_flt_protocol_type { 4201 + HAL_FILTER_PROTO_TYPE_INVALID, 4202 + HAL_FILTER_PROTO_TYPE_MAC, 4203 + HAL_FILTER_PROTO_TYPE_ARP, 4204 + HAL_FILTER_PROTO_TYPE_IPV4, 4205 + HAL_FILTER_PROTO_TYPE_IPV6, 4206 + HAL_FILTER_PROTO_TYPE_UDP, 4207 + HAL_FILTER_PROTO_TYPE_MAX 4208 + }; 4209 + 4210 + enum wcn36xx_hal_rcv_pkt_flt_cmp_flag_type { 4211 + HAL_FILTER_CMP_TYPE_INVALID, 4212 + HAL_FILTER_CMP_TYPE_EQUAL, 4213 + HAL_FILTER_CMP_TYPE_MASK_EQUAL, 4214 + HAL_FILTER_CMP_TYPE_NOT_EQUAL, 4215 + HAL_FILTER_CMP_TYPE_MAX 4216 + }; 4217 + 4218 + struct wcn36xx_hal_rcv_pkt_filter_params { 4219 + u8 protocol_layer; 4220 + u8 cmp_flag; 4221 + 4222 + /* Length of the data to compare */ 4223 + u16 data_length; 4224 + 4225 + /* from start of the respective frame header */ 4226 + u8 data_offset; 4227 + 4228 + /* Reserved field */ 4229 + u8 reserved; 4230 + 4231 + /* Data to compare */ 4232 + u8 compare_data[WCN36XX_HAL_PROTOCOL_DATA_LEN]; 4233 + 4234 + /* Mask to be applied on the received packet data before compare */ 4235 + u8 data_mask[WCN36XX_HAL_PROTOCOL_DATA_LEN]; 4236 + }; 4237 + 4238 + struct wcn36xx_hal_sessionized_rcv_pkt_filter_cfg_type { 4239 + u8 id; 4240 + u8 type; 4241 + u8 params_count; 4242 + u32 coleasce_time; 4243 + u8 bss_index; 4244 + struct wcn36xx_hal_rcv_pkt_filter_params params[1]; 4245 + }; 4246 + 4247 + struct wcn36xx_hal_set_rcv_pkt_filter_req_msg { 4248 + struct wcn36xx_hal_msg_header header; 4249 + 4250 + u8 id; 4251 + u8 type; 4252 + u8 params_count; 4253 + u32 coalesce_time; 4254 + struct wcn36xx_hal_rcv_pkt_filter_params params[1]; 4255 + }; 4256 + 4257 + struct wcn36xx_hal_rcv_flt_mc_addr_list_type { 4258 + /* from start of the respective frame header */ 4259 + u8 data_offset; 4260 + 4261 + u32 mc_addr_count; 4262 + u8 mc_addr[ETH_ALEN][WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS]; 4263 + u8 bss_index; 4264 + }; 4265 + 4266 + struct wcn36xx_hal_set_pkt_filter_rsp_msg { 4267 + struct wcn36xx_hal_msg_header header; 4268 + 4269 + /* success or failure */ 4270 + u32 status; 4271 + 4272 + u8 bss_index; 4273 + }; 4274 + 4275 + struct wcn36xx_hal_rcv_flt_pkt_match_cnt_req_msg { 4276 + struct wcn36xx_hal_msg_header header; 4277 + 4278 + u8 bss_index; 4279 + }; 4280 + 4281 + struct wcn36xx_hal_rcv_flt_pkt_match_cnt { 4282 + u8 id; 4283 + u32 match_cnt; 4284 + }; 4285 + 4286 + struct wcn36xx_hal_rcv_flt_pkt_match_cnt_rsp_msg { 4287 + struct wcn36xx_hal_msg_header header; 4288 + 4289 + /* Success or Failure */ 4290 + u32 status; 4291 + 4292 + u32 match_count; 4293 + struct wcn36xx_hal_rcv_flt_pkt_match_cnt 4294 + matches[WCN36XX_HAL_MAX_NUM_FILTERS]; 4295 + u8 bss_index; 4296 + }; 4297 + 4298 + struct wcn36xx_hal_rcv_flt_pkt_clear_param { 4299 + /* only valid for response message */ 4300 + u32 status; 4301 + u8 id; 4302 + u8 bss_index; 4303 + }; 4304 + 4305 + struct wcn36xx_hal_rcv_flt_pkt_clear_req_msg { 4306 + struct wcn36xx_hal_msg_header header; 4307 + struct wcn36xx_hal_rcv_flt_pkt_clear_param param; 4308 + }; 4309 + 4310 + struct wcn36xx_hal_rcv_flt_pkt_clear_rsp_msg { 4311 + struct wcn36xx_hal_msg_header header; 4312 + struct wcn36xx_hal_rcv_flt_pkt_clear_param param; 4313 + }; 4314 + 4315 + struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg { 4316 + struct wcn36xx_hal_msg_header header; 4317 + struct wcn36xx_hal_rcv_flt_mc_addr_list_type mc_addr_list; 4318 + }; 4319 + 4320 + struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_rsp_msg { 4321 + struct wcn36xx_hal_msg_header header; 4322 + u32 status; 4323 + u8 bss_index; 4324 + }; 4325 + 4326 + /* Packet Filtering Definitions End */ 4327 + 4328 + struct wcn36xx_hal_set_power_params_req_msg { 4329 + struct wcn36xx_hal_msg_header header; 4330 + 4331 + /* Ignore DTIM */ 4332 + u32 ignore_dtim; 4333 + 4334 + /* DTIM Period */ 4335 + u32 dtim_period; 4336 + 4337 + /* Listen Interval */ 4338 + u32 listen_interval; 4339 + 4340 + /* Broadcast Multicast Filter */ 4341 + u32 bcast_mcast_filter; 4342 + 4343 + /* Beacon Early Termination */ 4344 + u32 enable_bet; 4345 + 4346 + /* Beacon Early Termination Interval */ 4347 + u32 bet_interval; 4348 + } __packed; 4349 + 4350 + struct wcn36xx_hal_set_power_params_resp { 4351 + 4352 + struct wcn36xx_hal_msg_header header; 4353 + 4354 + /* status of the request */ 4355 + u32 status; 4356 + } __packed; 4357 + 4358 + /* Capability bitmap exchange definitions and macros starts */ 4359 + 4360 + enum place_holder_in_cap_bitmap { 4361 + MCC = 0, 4362 + P2P = 1, 4363 + DOT11AC = 2, 4364 + SLM_SESSIONIZATION = 3, 4365 + DOT11AC_OPMODE = 4, 4366 + SAP32STA = 5, 4367 + TDLS = 6, 4368 + P2P_GO_NOA_DECOUPLE_INIT_SCAN = 7, 4369 + WLANACTIVE_OFFLOAD = 8, 4370 + BEACON_OFFLOAD = 9, 4371 + SCAN_OFFLOAD = 10, 4372 + ROAM_OFFLOAD = 11, 4373 + BCN_MISS_OFFLOAD = 12, 4374 + STA_POWERSAVE = 13, 4375 + STA_ADVANCED_PWRSAVE = 14, 4376 + AP_UAPSD = 15, 4377 + AP_DFS = 16, 4378 + BLOCKACK = 17, 4379 + PHY_ERR = 18, 4380 + BCN_FILTER = 19, 4381 + RTT = 20, 4382 + RATECTRL = 21, 4383 + WOW = 22, 4384 + MAX_FEATURE_SUPPORTED = 128, 4385 + }; 4386 + 4387 + struct wcn36xx_hal_feat_caps_msg { 4388 + 4389 + struct wcn36xx_hal_msg_header header; 4390 + 4391 + u32 feat_caps[4]; 4392 + } __packed; 4393 + 4394 + /* status codes to help debug rekey failures */ 4395 + enum gtk_rekey_status { 4396 + WCN36XX_HAL_GTK_REKEY_STATUS_SUCCESS = 0, 4397 + 4398 + /* rekey detected, but not handled */ 4399 + WCN36XX_HAL_GTK_REKEY_STATUS_NOT_HANDLED = 1, 4400 + 4401 + /* MIC check error on M1 */ 4402 + WCN36XX_HAL_GTK_REKEY_STATUS_MIC_ERROR = 2, 4403 + 4404 + /* decryption error on M1 */ 4405 + WCN36XX_HAL_GTK_REKEY_STATUS_DECRYPT_ERROR = 3, 4406 + 4407 + /* M1 replay detected */ 4408 + WCN36XX_HAL_GTK_REKEY_STATUS_REPLAY_ERROR = 4, 4409 + 4410 + /* missing GTK key descriptor in M1 */ 4411 + WCN36XX_HAL_GTK_REKEY_STATUS_MISSING_KDE = 5, 4412 + 4413 + /* missing iGTK key descriptor in M1 */ 4414 + WCN36XX_HAL_GTK_REKEY_STATUS_MISSING_IGTK_KDE = 6, 4415 + 4416 + /* key installation error */ 4417 + WCN36XX_HAL_GTK_REKEY_STATUS_INSTALL_ERROR = 7, 4418 + 4419 + /* iGTK key installation error */ 4420 + WCN36XX_HAL_GTK_REKEY_STATUS_IGTK_INSTALL_ERROR = 8, 4421 + 4422 + /* GTK rekey M2 response TX error */ 4423 + WCN36XX_HAL_GTK_REKEY_STATUS_RESP_TX_ERROR = 9, 4424 + 4425 + /* non-specific general error */ 4426 + WCN36XX_HAL_GTK_REKEY_STATUS_GEN_ERROR = 255 4427 + }; 4428 + 4429 + /* wake reason types */ 4430 + enum wake_reason_type { 4431 + WCN36XX_HAL_WAKE_REASON_NONE = 0, 4432 + 4433 + /* magic packet match */ 4434 + WCN36XX_HAL_WAKE_REASON_MAGIC_PACKET = 1, 4435 + 4436 + /* host defined pattern match */ 4437 + WCN36XX_HAL_WAKE_REASON_PATTERN_MATCH = 2, 4438 + 4439 + /* EAP-ID frame detected */ 4440 + WCN36XX_HAL_WAKE_REASON_EAPID_PACKET = 3, 4441 + 4442 + /* start of EAPOL 4-way handshake detected */ 4443 + WCN36XX_HAL_WAKE_REASON_EAPOL4WAY_PACKET = 4, 4444 + 4445 + /* network scan offload match */ 4446 + WCN36XX_HAL_WAKE_REASON_NETSCAN_OFFL_MATCH = 5, 4447 + 4448 + /* GTK rekey status wakeup (see status) */ 4449 + WCN36XX_HAL_WAKE_REASON_GTK_REKEY_STATUS = 6, 4450 + 4451 + /* BSS connection lost */ 4452 + WCN36XX_HAL_WAKE_REASON_BSS_CONN_LOST = 7, 4453 + }; 4454 + 4455 + /* 4456 + Wake Packet which is saved at tWakeReasonParams.DataStart 4457 + This data is sent for any wake reasons that involve a packet-based wakeup : 4458 + 4459 + WCN36XX_HAL_WAKE_REASON_TYPE_MAGIC_PACKET 4460 + WCN36XX_HAL_WAKE_REASON_TYPE_PATTERN_MATCH 4461 + WCN36XX_HAL_WAKE_REASON_TYPE_EAPID_PACKET 4462 + WCN36XX_HAL_WAKE_REASON_TYPE_EAPOL4WAY_PACKET 4463 + WCN36XX_HAL_WAKE_REASON_TYPE_GTK_REKEY_STATUS 4464 + 4465 + The information is provided to the host for auditing and debug purposes 4466 + 4467 + */ 4468 + 4469 + /* Wake reason indication */ 4470 + struct wcn36xx_hal_wake_reason_ind { 4471 + struct wcn36xx_hal_msg_header header; 4472 + 4473 + /* see tWakeReasonType */ 4474 + u32 reason; 4475 + 4476 + /* argument specific to the reason type */ 4477 + u32 reason_arg; 4478 + 4479 + /* length of optional data stored in this message, in case HAL 4480 + * truncates the data (i.e. data packets) this length will be less 4481 + * than the actual length */ 4482 + u32 stored_data_len; 4483 + 4484 + /* actual length of data */ 4485 + u32 actual_data_len; 4486 + 4487 + /* variable length start of data (length == storedDataLen) see 4488 + * specific wake type */ 4489 + u8 data_start[1]; 4490 + 4491 + u32 bss_index:8; 4492 + u32 reserved:24; 4493 + }; 4494 + 4495 + #define WCN36XX_HAL_GTK_KEK_BYTES 16 4496 + #define WCN36XX_HAL_GTK_KCK_BYTES 16 4497 + 4498 + #define WCN36XX_HAL_GTK_OFFLOAD_FLAGS_DISABLE (1 << 0) 4499 + 4500 + #define GTK_SET_BSS_KEY_TAG 0x1234AA55 4501 + 4502 + struct wcn36xx_hal_gtk_offload_req_msg { 4503 + struct wcn36xx_hal_msg_header header; 4504 + 4505 + /* optional flags */ 4506 + u32 flags; 4507 + 4508 + /* Key confirmation key */ 4509 + u8 kck[WCN36XX_HAL_GTK_KCK_BYTES]; 4510 + 4511 + /* key encryption key */ 4512 + u8 kek[WCN36XX_HAL_GTK_KEK_BYTES]; 4513 + 4514 + /* replay counter */ 4515 + u64 key_replay_counter; 4516 + 4517 + u8 bss_index; 4518 + }; 4519 + 4520 + struct wcn36xx_hal_gtk_offload_rsp_msg { 4521 + struct wcn36xx_hal_msg_header header; 4522 + 4523 + /* success or failure */ 4524 + u32 status; 4525 + 4526 + u8 bss_index; 4527 + }; 4528 + 4529 + struct wcn36xx_hal_gtk_offload_get_info_req_msg { 4530 + struct wcn36xx_hal_msg_header header; 4531 + u8 bss_index; 4532 + }; 4533 + 4534 + struct wcn36xx_hal_gtk_offload_get_info_rsp_msg { 4535 + struct wcn36xx_hal_msg_header header; 4536 + 4537 + /* success or failure */ 4538 + u32 status; 4539 + 4540 + /* last rekey status when the rekey was offloaded */ 4541 + u32 last_rekey_status; 4542 + 4543 + /* current replay counter value */ 4544 + u64 key_replay_counter; 4545 + 4546 + /* total rekey attempts */ 4547 + u32 total_rekey_count; 4548 + 4549 + /* successful GTK rekeys */ 4550 + u32 gtk_rekey_count; 4551 + 4552 + /* successful iGTK rekeys */ 4553 + u32 igtk_rekey_count; 4554 + 4555 + u8 bss_index; 4556 + }; 4557 + 4558 + struct dhcp_info { 4559 + /* Indicates the device mode which indicates about the DHCP activity */ 4560 + u8 device_mode; 4561 + 4562 + u8 addr[ETH_ALEN]; 4563 + }; 4564 + 4565 + struct dhcp_ind_status { 4566 + struct wcn36xx_hal_msg_header header; 4567 + 4568 + /* success or failure */ 4569 + u32 status; 4570 + }; 4571 + 4572 + /* 4573 + * Thermal Mitigation mode of operation. 4574 + * 4575 + * WCN36XX_HAL_THERMAL_MITIGATION_MODE_0 - Based on AMPDU disabling aggregation 4576 + * 4577 + * WCN36XX_HAL_THERMAL_MITIGATION_MODE_1 - Based on AMPDU disabling aggregation 4578 + * and reducing transmit power 4579 + * 4580 + * WCN36XX_HAL_THERMAL_MITIGATION_MODE_2 - Not supported */ 4581 + enum wcn36xx_hal_thermal_mitigation_mode_type { 4582 + HAL_THERMAL_MITIGATION_MODE_INVALID = -1, 4583 + HAL_THERMAL_MITIGATION_MODE_0, 4584 + HAL_THERMAL_MITIGATION_MODE_1, 4585 + HAL_THERMAL_MITIGATION_MODE_2, 4586 + HAL_THERMAL_MITIGATION_MODE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE, 4587 + }; 4588 + 4589 + 4590 + /* 4591 + * Thermal Mitigation level. 4592 + * Note the levels are incremental i.e WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_2 = 4593 + * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_0 + 4594 + * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_1 4595 + * 4596 + * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_0 - lowest level of thermal mitigation. 4597 + * This level indicates normal mode of operation 4598 + * 4599 + * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_1 - 1st level of thermal mitigation 4600 + * 4601 + * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_2 - 2nd level of thermal mitigation 4602 + * 4603 + * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_3 - 3rd level of thermal mitigation 4604 + * 4605 + * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_4 - 4th level of thermal mitigation 4606 + */ 4607 + enum wcn36xx_hal_thermal_mitigation_level_type { 4608 + HAL_THERMAL_MITIGATION_LEVEL_INVALID = -1, 4609 + HAL_THERMAL_MITIGATION_LEVEL_0, 4610 + HAL_THERMAL_MITIGATION_LEVEL_1, 4611 + HAL_THERMAL_MITIGATION_LEVEL_2, 4612 + HAL_THERMAL_MITIGATION_LEVEL_3, 4613 + HAL_THERMAL_MITIGATION_LEVEL_4, 4614 + HAL_THERMAL_MITIGATION_LEVEL_MAX = WCN36XX_HAL_MAX_ENUM_SIZE, 4615 + }; 4616 + 4617 + 4618 + /* WCN36XX_HAL_SET_THERMAL_MITIGATION_REQ */ 4619 + struct set_thermal_mitigation_req_msg { 4620 + struct wcn36xx_hal_msg_header header; 4621 + 4622 + /* Thermal Mitigation Operation Mode */ 4623 + enum wcn36xx_hal_thermal_mitigation_mode_type mode; 4624 + 4625 + /* Thermal Mitigation Level */ 4626 + enum wcn36xx_hal_thermal_mitigation_level_type level; 4627 + }; 4628 + 4629 + struct set_thermal_mitigation_resp { 4630 + 4631 + struct wcn36xx_hal_msg_header header; 4632 + 4633 + /* status of the request */ 4634 + u32 status; 4635 + }; 4636 + 4637 + /* Per STA Class B Statistics. Class B statistics are STA TX/RX stats 4638 + * provided to FW from Host via periodic messages */ 4639 + struct stats_class_b_ind { 4640 + struct wcn36xx_hal_msg_header header; 4641 + 4642 + /* Duration over which this stats was collected */ 4643 + u32 duration; 4644 + 4645 + /* Per STA Stats */ 4646 + 4647 + /* TX stats */ 4648 + u32 tx_bytes_pushed; 4649 + u32 tx_packets_pushed; 4650 + 4651 + /* RX stats */ 4652 + u32 rx_bytes_rcvd; 4653 + u32 rx_packets_rcvd; 4654 + u32 rx_time_total; 4655 + }; 4656 + 4657 + #endif /* _HAL_H_ */
+1036
drivers/net/wireless/ath/wcn36xx/main.c
··· 1 + /* 2 + * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> 3 + * 4 + * Permission to use, copy, modify, and/or distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 11 + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 13 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 14 + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + 17 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 18 + 19 + #include <linux/module.h> 20 + #include <linux/platform_device.h> 21 + #include "wcn36xx.h" 22 + 23 + unsigned int wcn36xx_dbg_mask; 24 + module_param_named(debug_mask, wcn36xx_dbg_mask, uint, 0644); 25 + MODULE_PARM_DESC(debug_mask, "Debugging mask"); 26 + 27 + #define CHAN2G(_freq, _idx) { \ 28 + .band = IEEE80211_BAND_2GHZ, \ 29 + .center_freq = (_freq), \ 30 + .hw_value = (_idx), \ 31 + .max_power = 25, \ 32 + } 33 + 34 + #define CHAN5G(_freq, _idx) { \ 35 + .band = IEEE80211_BAND_5GHZ, \ 36 + .center_freq = (_freq), \ 37 + .hw_value = (_idx), \ 38 + .max_power = 25, \ 39 + } 40 + 41 + /* The wcn firmware expects channel values to matching 42 + * their mnemonic values. So use these for .hw_value. */ 43 + static struct ieee80211_channel wcn_2ghz_channels[] = { 44 + CHAN2G(2412, 1), /* Channel 1 */ 45 + CHAN2G(2417, 2), /* Channel 2 */ 46 + CHAN2G(2422, 3), /* Channel 3 */ 47 + CHAN2G(2427, 4), /* Channel 4 */ 48 + CHAN2G(2432, 5), /* Channel 5 */ 49 + CHAN2G(2437, 6), /* Channel 6 */ 50 + CHAN2G(2442, 7), /* Channel 7 */ 51 + CHAN2G(2447, 8), /* Channel 8 */ 52 + CHAN2G(2452, 9), /* Channel 9 */ 53 + CHAN2G(2457, 10), /* Channel 10 */ 54 + CHAN2G(2462, 11), /* Channel 11 */ 55 + CHAN2G(2467, 12), /* Channel 12 */ 56 + CHAN2G(2472, 13), /* Channel 13 */ 57 + CHAN2G(2484, 14) /* Channel 14 */ 58 + 59 + }; 60 + 61 + static struct ieee80211_channel wcn_5ghz_channels[] = { 62 + CHAN5G(5180, 36), 63 + CHAN5G(5200, 40), 64 + CHAN5G(5220, 44), 65 + CHAN5G(5240, 48), 66 + CHAN5G(5260, 52), 67 + CHAN5G(5280, 56), 68 + CHAN5G(5300, 60), 69 + CHAN5G(5320, 64), 70 + CHAN5G(5500, 100), 71 + CHAN5G(5520, 104), 72 + CHAN5G(5540, 108), 73 + CHAN5G(5560, 112), 74 + CHAN5G(5580, 116), 75 + CHAN5G(5600, 120), 76 + CHAN5G(5620, 124), 77 + CHAN5G(5640, 128), 78 + CHAN5G(5660, 132), 79 + CHAN5G(5700, 140), 80 + CHAN5G(5745, 149), 81 + CHAN5G(5765, 153), 82 + CHAN5G(5785, 157), 83 + CHAN5G(5805, 161), 84 + CHAN5G(5825, 165) 85 + }; 86 + 87 + #define RATE(_bitrate, _hw_rate, _flags) { \ 88 + .bitrate = (_bitrate), \ 89 + .flags = (_flags), \ 90 + .hw_value = (_hw_rate), \ 91 + .hw_value_short = (_hw_rate) \ 92 + } 93 + 94 + static struct ieee80211_rate wcn_2ghz_rates[] = { 95 + RATE(10, HW_RATE_INDEX_1MBPS, 0), 96 + RATE(20, HW_RATE_INDEX_2MBPS, IEEE80211_RATE_SHORT_PREAMBLE), 97 + RATE(55, HW_RATE_INDEX_5_5MBPS, IEEE80211_RATE_SHORT_PREAMBLE), 98 + RATE(110, HW_RATE_INDEX_11MBPS, IEEE80211_RATE_SHORT_PREAMBLE), 99 + RATE(60, HW_RATE_INDEX_6MBPS, 0), 100 + RATE(90, HW_RATE_INDEX_9MBPS, 0), 101 + RATE(120, HW_RATE_INDEX_12MBPS, 0), 102 + RATE(180, HW_RATE_INDEX_18MBPS, 0), 103 + RATE(240, HW_RATE_INDEX_24MBPS, 0), 104 + RATE(360, HW_RATE_INDEX_36MBPS, 0), 105 + RATE(480, HW_RATE_INDEX_48MBPS, 0), 106 + RATE(540, HW_RATE_INDEX_54MBPS, 0) 107 + }; 108 + 109 + static struct ieee80211_rate wcn_5ghz_rates[] = { 110 + RATE(60, HW_RATE_INDEX_6MBPS, 0), 111 + RATE(90, HW_RATE_INDEX_9MBPS, 0), 112 + RATE(120, HW_RATE_INDEX_12MBPS, 0), 113 + RATE(180, HW_RATE_INDEX_18MBPS, 0), 114 + RATE(240, HW_RATE_INDEX_24MBPS, 0), 115 + RATE(360, HW_RATE_INDEX_36MBPS, 0), 116 + RATE(480, HW_RATE_INDEX_48MBPS, 0), 117 + RATE(540, HW_RATE_INDEX_54MBPS, 0) 118 + }; 119 + 120 + static struct ieee80211_supported_band wcn_band_2ghz = { 121 + .channels = wcn_2ghz_channels, 122 + .n_channels = ARRAY_SIZE(wcn_2ghz_channels), 123 + .bitrates = wcn_2ghz_rates, 124 + .n_bitrates = ARRAY_SIZE(wcn_2ghz_rates), 125 + .ht_cap = { 126 + .cap = IEEE80211_HT_CAP_GRN_FLD | 127 + IEEE80211_HT_CAP_SGI_20 | 128 + IEEE80211_HT_CAP_DSSSCCK40 | 129 + IEEE80211_HT_CAP_LSIG_TXOP_PROT, 130 + .ht_supported = true, 131 + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, 132 + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, 133 + .mcs = { 134 + .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 135 + .rx_highest = cpu_to_le16(72), 136 + .tx_params = IEEE80211_HT_MCS_TX_DEFINED, 137 + } 138 + } 139 + }; 140 + 141 + static struct ieee80211_supported_band wcn_band_5ghz = { 142 + .channels = wcn_5ghz_channels, 143 + .n_channels = ARRAY_SIZE(wcn_5ghz_channels), 144 + .bitrates = wcn_5ghz_rates, 145 + .n_bitrates = ARRAY_SIZE(wcn_5ghz_rates), 146 + .ht_cap = { 147 + .cap = IEEE80211_HT_CAP_GRN_FLD | 148 + IEEE80211_HT_CAP_SGI_20 | 149 + IEEE80211_HT_CAP_DSSSCCK40 | 150 + IEEE80211_HT_CAP_LSIG_TXOP_PROT | 151 + IEEE80211_HT_CAP_SGI_40 | 152 + IEEE80211_HT_CAP_SUP_WIDTH_20_40, 153 + .ht_supported = true, 154 + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, 155 + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, 156 + .mcs = { 157 + .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, 158 + .rx_highest = cpu_to_le16(72), 159 + .tx_params = IEEE80211_HT_MCS_TX_DEFINED, 160 + } 161 + } 162 + }; 163 + 164 + #ifdef CONFIG_PM 165 + 166 + static const struct wiphy_wowlan_support wowlan_support = { 167 + .flags = WIPHY_WOWLAN_ANY 168 + }; 169 + 170 + #endif 171 + 172 + static inline u8 get_sta_index(struct ieee80211_vif *vif, 173 + struct wcn36xx_sta *sta_priv) 174 + { 175 + return NL80211_IFTYPE_STATION == vif->type ? 176 + sta_priv->bss_sta_index : 177 + sta_priv->sta_index; 178 + } 179 + 180 + static int wcn36xx_start(struct ieee80211_hw *hw) 181 + { 182 + struct wcn36xx *wcn = hw->priv; 183 + int ret; 184 + 185 + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac start\n"); 186 + 187 + /* SMD initialization */ 188 + ret = wcn36xx_smd_open(wcn); 189 + if (ret) { 190 + wcn36xx_err("Failed to open smd channel: %d\n", ret); 191 + goto out_err; 192 + } 193 + 194 + /* Allocate memory pools for Mgmt BD headers and Data BD headers */ 195 + ret = wcn36xx_dxe_allocate_mem_pools(wcn); 196 + if (ret) { 197 + wcn36xx_err("Failed to alloc DXE mempool: %d\n", ret); 198 + goto out_smd_close; 199 + } 200 + 201 + ret = wcn36xx_dxe_alloc_ctl_blks(wcn); 202 + if (ret) { 203 + wcn36xx_err("Failed to alloc DXE ctl blocks: %d\n", ret); 204 + goto out_free_dxe_pool; 205 + } 206 + 207 + wcn->hal_buf = kmalloc(WCN36XX_HAL_BUF_SIZE, GFP_KERNEL); 208 + if (!wcn->hal_buf) { 209 + wcn36xx_err("Failed to allocate smd buf\n"); 210 + ret = -ENOMEM; 211 + goto out_free_dxe_ctl; 212 + } 213 + 214 + ret = wcn36xx_smd_load_nv(wcn); 215 + if (ret) { 216 + wcn36xx_err("Failed to push NV to chip\n"); 217 + goto out_free_smd_buf; 218 + } 219 + 220 + ret = wcn36xx_smd_start(wcn); 221 + if (ret) { 222 + wcn36xx_err("Failed to start chip\n"); 223 + goto out_free_smd_buf; 224 + } 225 + 226 + /* DMA channel initialization */ 227 + ret = wcn36xx_dxe_init(wcn); 228 + if (ret) { 229 + wcn36xx_err("DXE init failed\n"); 230 + goto out_smd_stop; 231 + } 232 + 233 + wcn36xx_debugfs_init(wcn); 234 + 235 + if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { 236 + ret = wcn36xx_smd_feature_caps_exchange(wcn); 237 + if (ret) 238 + wcn36xx_warn("Exchange feature caps failed\n"); 239 + } 240 + INIT_LIST_HEAD(&wcn->vif_list); 241 + return 0; 242 + 243 + out_smd_stop: 244 + wcn36xx_smd_stop(wcn); 245 + out_free_smd_buf: 246 + kfree(wcn->hal_buf); 247 + out_free_dxe_pool: 248 + wcn36xx_dxe_free_mem_pools(wcn); 249 + out_free_dxe_ctl: 250 + wcn36xx_dxe_free_ctl_blks(wcn); 251 + out_smd_close: 252 + wcn36xx_smd_close(wcn); 253 + out_err: 254 + return ret; 255 + } 256 + 257 + static void wcn36xx_stop(struct ieee80211_hw *hw) 258 + { 259 + struct wcn36xx *wcn = hw->priv; 260 + 261 + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac stop\n"); 262 + 263 + wcn36xx_debugfs_exit(wcn); 264 + wcn36xx_smd_stop(wcn); 265 + wcn36xx_dxe_deinit(wcn); 266 + wcn36xx_smd_close(wcn); 267 + 268 + wcn36xx_dxe_free_mem_pools(wcn); 269 + wcn36xx_dxe_free_ctl_blks(wcn); 270 + 271 + kfree(wcn->hal_buf); 272 + } 273 + 274 + static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed) 275 + { 276 + struct wcn36xx *wcn = hw->priv; 277 + struct ieee80211_vif *vif = NULL; 278 + struct wcn36xx_vif *tmp; 279 + 280 + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac config changed 0x%08x\n", changed); 281 + 282 + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { 283 + int ch = WCN36XX_HW_CHANNEL(wcn); 284 + wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n", 285 + ch); 286 + list_for_each_entry(tmp, &wcn->vif_list, list) { 287 + vif = container_of((void *)tmp, 288 + struct ieee80211_vif, 289 + drv_priv); 290 + wcn36xx_smd_switch_channel(wcn, vif, ch); 291 + } 292 + } 293 + 294 + return 0; 295 + } 296 + 297 + #define WCN36XX_SUPPORTED_FILTERS (0) 298 + 299 + static void wcn36xx_configure_filter(struct ieee80211_hw *hw, 300 + unsigned int changed, 301 + unsigned int *total, u64 multicast) 302 + { 303 + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n"); 304 + 305 + *total &= WCN36XX_SUPPORTED_FILTERS; 306 + } 307 + 308 + static void wcn36xx_tx(struct ieee80211_hw *hw, 309 + struct ieee80211_tx_control *control, 310 + struct sk_buff *skb) 311 + { 312 + struct wcn36xx *wcn = hw->priv; 313 + struct wcn36xx_sta *sta_priv = NULL; 314 + 315 + if (control->sta) 316 + sta_priv = (struct wcn36xx_sta *)control->sta->drv_priv; 317 + 318 + if (wcn36xx_start_tx(wcn, sta_priv, skb)) 319 + ieee80211_free_txskb(wcn->hw, skb); 320 + } 321 + 322 + static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 323 + struct ieee80211_vif *vif, 324 + struct ieee80211_sta *sta, 325 + struct ieee80211_key_conf *key_conf) 326 + { 327 + struct wcn36xx *wcn = hw->priv; 328 + struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 329 + struct wcn36xx_sta *sta_priv = vif_priv->sta; 330 + int ret = 0; 331 + u8 key[WLAN_MAX_KEY_LEN]; 332 + 333 + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 set key\n"); 334 + wcn36xx_dbg(WCN36XX_DBG_MAC, "Key: cmd=0x%x algo:0x%x, id:%d, len:%d flags 0x%x\n", 335 + cmd, key_conf->cipher, key_conf->keyidx, 336 + key_conf->keylen, key_conf->flags); 337 + wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "KEY: ", 338 + key_conf->key, 339 + key_conf->keylen); 340 + 341 + switch (key_conf->cipher) { 342 + case WLAN_CIPHER_SUITE_WEP40: 343 + vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40; 344 + break; 345 + case WLAN_CIPHER_SUITE_WEP104: 346 + vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40; 347 + break; 348 + case WLAN_CIPHER_SUITE_CCMP: 349 + vif_priv->encrypt_type = WCN36XX_HAL_ED_CCMP; 350 + break; 351 + case WLAN_CIPHER_SUITE_TKIP: 352 + vif_priv->encrypt_type = WCN36XX_HAL_ED_TKIP; 353 + break; 354 + default: 355 + wcn36xx_err("Unsupported key type 0x%x\n", 356 + key_conf->cipher); 357 + ret = -EOPNOTSUPP; 358 + goto out; 359 + } 360 + 361 + switch (cmd) { 362 + case SET_KEY: 363 + if (WCN36XX_HAL_ED_TKIP == vif_priv->encrypt_type) { 364 + /* 365 + * Supplicant is sending key in the wrong order: 366 + * Temporal Key (16 b) - TX MIC (8 b) - RX MIC (8 b) 367 + * but HW expects it to be in the order as described in 368 + * IEEE 802.11 spec (see chapter 11.7) like this: 369 + * Temporal Key (16 b) - RX MIC (8 b) - TX MIC (8 b) 370 + */ 371 + memcpy(key, key_conf->key, 16); 372 + memcpy(key + 16, key_conf->key + 24, 8); 373 + memcpy(key + 24, key_conf->key + 16, 8); 374 + } else { 375 + memcpy(key, key_conf->key, key_conf->keylen); 376 + } 377 + 378 + if (IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags) { 379 + sta_priv->is_data_encrypted = true; 380 + /* Reconfigure bss with encrypt_type */ 381 + if (NL80211_IFTYPE_STATION == vif->type) 382 + wcn36xx_smd_config_bss(wcn, 383 + vif, 384 + sta, 385 + sta->addr, 386 + true); 387 + 388 + wcn36xx_smd_set_stakey(wcn, 389 + vif_priv->encrypt_type, 390 + key_conf->keyidx, 391 + key_conf->keylen, 392 + key, 393 + get_sta_index(vif, sta_priv)); 394 + } else { 395 + wcn36xx_smd_set_bsskey(wcn, 396 + vif_priv->encrypt_type, 397 + key_conf->keyidx, 398 + key_conf->keylen, 399 + key); 400 + if ((WLAN_CIPHER_SUITE_WEP40 == key_conf->cipher) || 401 + (WLAN_CIPHER_SUITE_WEP104 == key_conf->cipher)) { 402 + sta_priv->is_data_encrypted = true; 403 + wcn36xx_smd_set_stakey(wcn, 404 + vif_priv->encrypt_type, 405 + key_conf->keyidx, 406 + key_conf->keylen, 407 + key, 408 + get_sta_index(vif, sta_priv)); 409 + } 410 + } 411 + break; 412 + case DISABLE_KEY: 413 + if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) { 414 + wcn36xx_smd_remove_bsskey(wcn, 415 + vif_priv->encrypt_type, 416 + key_conf->keyidx); 417 + } else { 418 + sta_priv->is_data_encrypted = false; 419 + /* do not remove key if disassociated */ 420 + if (sta_priv->aid) 421 + wcn36xx_smd_remove_stakey(wcn, 422 + vif_priv->encrypt_type, 423 + key_conf->keyidx, 424 + get_sta_index(vif, sta_priv)); 425 + } 426 + break; 427 + default: 428 + wcn36xx_err("Unsupported key cmd 0x%x\n", cmd); 429 + ret = -EOPNOTSUPP; 430 + goto out; 431 + break; 432 + } 433 + 434 + out: 435 + return ret; 436 + } 437 + 438 + static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw) 439 + { 440 + struct wcn36xx *wcn = hw->priv; 441 + 442 + wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN); 443 + wcn36xx_smd_start_scan(wcn); 444 + } 445 + 446 + static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw) 447 + { 448 + struct wcn36xx *wcn = hw->priv; 449 + 450 + wcn36xx_smd_end_scan(wcn); 451 + wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN); 452 + } 453 + 454 + static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta, 455 + enum ieee80211_band band) 456 + { 457 + int i, size; 458 + u16 *rates_table; 459 + struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 460 + u32 rates = sta->supp_rates[band]; 461 + 462 + memset(&sta_priv->supported_rates, 0, 463 + sizeof(sta_priv->supported_rates)); 464 + sta_priv->supported_rates.op_rate_mode = STA_11n; 465 + 466 + size = ARRAY_SIZE(sta_priv->supported_rates.dsss_rates); 467 + rates_table = sta_priv->supported_rates.dsss_rates; 468 + if (band == IEEE80211_BAND_2GHZ) { 469 + for (i = 0; i < size; i++) { 470 + if (rates & 0x01) { 471 + rates_table[i] = wcn_2ghz_rates[i].hw_value; 472 + rates = rates >> 1; 473 + } 474 + } 475 + } 476 + 477 + size = ARRAY_SIZE(sta_priv->supported_rates.ofdm_rates); 478 + rates_table = sta_priv->supported_rates.ofdm_rates; 479 + for (i = 0; i < size; i++) { 480 + if (rates & 0x01) { 481 + rates_table[i] = wcn_5ghz_rates[i].hw_value; 482 + rates = rates >> 1; 483 + } 484 + } 485 + 486 + if (sta->ht_cap.ht_supported) { 487 + BUILD_BUG_ON(sizeof(sta->ht_cap.mcs.rx_mask) > 488 + sizeof(sta_priv->supported_rates.supported_mcs_set)); 489 + memcpy(sta_priv->supported_rates.supported_mcs_set, 490 + sta->ht_cap.mcs.rx_mask, 491 + sizeof(sta->ht_cap.mcs.rx_mask)); 492 + } 493 + } 494 + void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates) 495 + { 496 + u16 ofdm_rates[WCN36XX_HAL_NUM_OFDM_RATES] = { 497 + HW_RATE_INDEX_6MBPS, 498 + HW_RATE_INDEX_9MBPS, 499 + HW_RATE_INDEX_12MBPS, 500 + HW_RATE_INDEX_18MBPS, 501 + HW_RATE_INDEX_24MBPS, 502 + HW_RATE_INDEX_36MBPS, 503 + HW_RATE_INDEX_48MBPS, 504 + HW_RATE_INDEX_54MBPS 505 + }; 506 + u16 dsss_rates[WCN36XX_HAL_NUM_DSSS_RATES] = { 507 + HW_RATE_INDEX_1MBPS, 508 + HW_RATE_INDEX_2MBPS, 509 + HW_RATE_INDEX_5_5MBPS, 510 + HW_RATE_INDEX_11MBPS 511 + }; 512 + 513 + rates->op_rate_mode = STA_11n; 514 + memcpy(rates->dsss_rates, dsss_rates, 515 + sizeof(*dsss_rates) * WCN36XX_HAL_NUM_DSSS_RATES); 516 + memcpy(rates->ofdm_rates, ofdm_rates, 517 + sizeof(*ofdm_rates) * WCN36XX_HAL_NUM_OFDM_RATES); 518 + rates->supported_mcs_set[0] = 0xFF; 519 + } 520 + static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, 521 + struct ieee80211_vif *vif, 522 + struct ieee80211_bss_conf *bss_conf, 523 + u32 changed) 524 + { 525 + struct wcn36xx *wcn = hw->priv; 526 + struct sk_buff *skb = NULL; 527 + u16 tim_off, tim_len; 528 + enum wcn36xx_hal_link_state link_state; 529 + struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 530 + 531 + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n", 532 + vif, changed); 533 + 534 + if (changed & BSS_CHANGED_BEACON_INFO) { 535 + wcn36xx_dbg(WCN36XX_DBG_MAC, 536 + "mac bss changed dtim period %d\n", 537 + bss_conf->dtim_period); 538 + 539 + vif_priv->dtim_period = bss_conf->dtim_period; 540 + } 541 + 542 + if (changed & BSS_CHANGED_PS) { 543 + wcn36xx_dbg(WCN36XX_DBG_MAC, 544 + "mac bss PS set %d\n", 545 + bss_conf->ps); 546 + if (bss_conf->ps) { 547 + wcn36xx_pmc_enter_bmps_state(wcn, vif); 548 + } else { 549 + wcn36xx_pmc_exit_bmps_state(wcn, vif); 550 + } 551 + } 552 + 553 + if (changed & BSS_CHANGED_BSSID) { 554 + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed_bssid %pM\n", 555 + bss_conf->bssid); 556 + 557 + if (!is_zero_ether_addr(bss_conf->bssid)) { 558 + vif_priv->is_joining = true; 559 + vif_priv->bss_index = 0xff; 560 + wcn36xx_smd_join(wcn, bss_conf->bssid, 561 + vif->addr, WCN36XX_HW_CHANNEL(wcn)); 562 + wcn36xx_smd_config_bss(wcn, vif, NULL, 563 + bss_conf->bssid, false); 564 + } else { 565 + vif_priv->is_joining = false; 566 + wcn36xx_smd_delete_bss(wcn, vif); 567 + } 568 + } 569 + 570 + if (changed & BSS_CHANGED_SSID) { 571 + wcn36xx_dbg(WCN36XX_DBG_MAC, 572 + "mac bss changed ssid\n"); 573 + wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "ssid ", 574 + bss_conf->ssid, bss_conf->ssid_len); 575 + 576 + vif_priv->ssid.length = bss_conf->ssid_len; 577 + memcpy(&vif_priv->ssid.ssid, 578 + bss_conf->ssid, 579 + bss_conf->ssid_len); 580 + } 581 + 582 + if (changed & BSS_CHANGED_ASSOC) { 583 + vif_priv->is_joining = false; 584 + if (bss_conf->assoc) { 585 + struct ieee80211_sta *sta; 586 + struct wcn36xx_sta *sta_priv; 587 + 588 + wcn36xx_dbg(WCN36XX_DBG_MAC, 589 + "mac assoc bss %pM vif %pM AID=%d\n", 590 + bss_conf->bssid, 591 + vif->addr, 592 + bss_conf->aid); 593 + 594 + rcu_read_lock(); 595 + sta = ieee80211_find_sta(vif, bss_conf->bssid); 596 + if (!sta) { 597 + wcn36xx_err("sta %pM is not found\n", 598 + bss_conf->bssid); 599 + rcu_read_unlock(); 600 + goto out; 601 + } 602 + sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 603 + 604 + wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn)); 605 + 606 + wcn36xx_smd_set_link_st(wcn, bss_conf->bssid, 607 + vif->addr, 608 + WCN36XX_HAL_LINK_POSTASSOC_STATE); 609 + wcn36xx_smd_config_bss(wcn, vif, sta, 610 + bss_conf->bssid, 611 + true); 612 + sta_priv->aid = bss_conf->aid; 613 + /* 614 + * config_sta must be called from because this is the 615 + * place where AID is available. 616 + */ 617 + wcn36xx_smd_config_sta(wcn, vif, sta); 618 + rcu_read_unlock(); 619 + } else { 620 + wcn36xx_dbg(WCN36XX_DBG_MAC, 621 + "disassociated bss %pM vif %pM AID=%d\n", 622 + bss_conf->bssid, 623 + vif->addr, 624 + bss_conf->aid); 625 + wcn36xx_smd_set_link_st(wcn, 626 + bss_conf->bssid, 627 + vif->addr, 628 + WCN36XX_HAL_LINK_IDLE_STATE); 629 + } 630 + } 631 + 632 + if (changed & BSS_CHANGED_AP_PROBE_RESP) { 633 + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed ap probe resp\n"); 634 + skb = ieee80211_proberesp_get(hw, vif); 635 + if (!skb) { 636 + wcn36xx_err("failed to alloc probereq skb\n"); 637 + goto out; 638 + } 639 + 640 + wcn36xx_smd_update_proberesp_tmpl(wcn, vif, skb); 641 + dev_kfree_skb(skb); 642 + } 643 + 644 + if (changed & BSS_CHANGED_BEACON_ENABLED) { 645 + wcn36xx_dbg(WCN36XX_DBG_MAC, 646 + "mac bss changed beacon enabled %d\n", 647 + bss_conf->enable_beacon); 648 + 649 + if (bss_conf->enable_beacon) { 650 + vif_priv->bss_index = 0xff; 651 + wcn36xx_smd_config_bss(wcn, vif, NULL, 652 + vif->addr, false); 653 + skb = ieee80211_beacon_get_tim(hw, vif, &tim_off, 654 + &tim_len); 655 + if (!skb) { 656 + wcn36xx_err("failed to alloc beacon skb\n"); 657 + goto out; 658 + } 659 + wcn36xx_smd_send_beacon(wcn, vif, skb, tim_off, 0); 660 + dev_kfree_skb(skb); 661 + 662 + if (vif->type == NL80211_IFTYPE_ADHOC || 663 + vif->type == NL80211_IFTYPE_MESH_POINT) 664 + link_state = WCN36XX_HAL_LINK_IBSS_STATE; 665 + else 666 + link_state = WCN36XX_HAL_LINK_AP_STATE; 667 + 668 + wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr, 669 + link_state); 670 + } else { 671 + wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr, 672 + WCN36XX_HAL_LINK_IDLE_STATE); 673 + wcn36xx_smd_delete_bss(wcn, vif); 674 + } 675 + } 676 + out: 677 + return; 678 + } 679 + 680 + /* this is required when using IEEE80211_HW_HAS_RATE_CONTROL */ 681 + static int wcn36xx_set_rts_threshold(struct ieee80211_hw *hw, u32 value) 682 + { 683 + struct wcn36xx *wcn = hw->priv; 684 + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac set RTS threshold %d\n", value); 685 + 686 + wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_RTS_THRESHOLD, value); 687 + return 0; 688 + } 689 + 690 + static void wcn36xx_remove_interface(struct ieee80211_hw *hw, 691 + struct ieee80211_vif *vif) 692 + { 693 + struct wcn36xx *wcn = hw->priv; 694 + struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 695 + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif); 696 + 697 + list_del(&vif_priv->list); 698 + wcn36xx_smd_delete_sta_self(wcn, vif->addr); 699 + } 700 + 701 + static int wcn36xx_add_interface(struct ieee80211_hw *hw, 702 + struct ieee80211_vif *vif) 703 + { 704 + struct wcn36xx *wcn = hw->priv; 705 + struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 706 + 707 + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac add interface vif %p type %d\n", 708 + vif, vif->type); 709 + 710 + if (!(NL80211_IFTYPE_STATION == vif->type || 711 + NL80211_IFTYPE_AP == vif->type || 712 + NL80211_IFTYPE_ADHOC == vif->type || 713 + NL80211_IFTYPE_MESH_POINT == vif->type)) { 714 + wcn36xx_warn("Unsupported interface type requested: %d\n", 715 + vif->type); 716 + return -EOPNOTSUPP; 717 + } 718 + 719 + list_add(&vif_priv->list, &wcn->vif_list); 720 + wcn36xx_smd_add_sta_self(wcn, vif); 721 + 722 + return 0; 723 + } 724 + 725 + static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 726 + struct ieee80211_sta *sta) 727 + { 728 + struct wcn36xx *wcn = hw->priv; 729 + struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 730 + struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 731 + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n", 732 + vif, sta->addr); 733 + 734 + vif_priv->sta = sta_priv; 735 + sta_priv->vif = vif_priv; 736 + /* 737 + * For STA mode HW will be configured on BSS_CHANGED_ASSOC because 738 + * at this stage AID is not available yet. 739 + */ 740 + if (NL80211_IFTYPE_STATION != vif->type) { 741 + wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn)); 742 + sta_priv->aid = sta->aid; 743 + wcn36xx_smd_config_sta(wcn, vif, sta); 744 + } 745 + return 0; 746 + } 747 + 748 + static int wcn36xx_sta_remove(struct ieee80211_hw *hw, 749 + struct ieee80211_vif *vif, 750 + struct ieee80211_sta *sta) 751 + { 752 + struct wcn36xx *wcn = hw->priv; 753 + struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 754 + struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 755 + 756 + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n", 757 + vif, sta->addr, sta_priv->sta_index); 758 + 759 + wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index); 760 + vif_priv->sta = NULL; 761 + sta_priv->vif = NULL; 762 + return 0; 763 + } 764 + 765 + #ifdef CONFIG_PM 766 + 767 + static int wcn36xx_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wow) 768 + { 769 + struct wcn36xx *wcn = hw->priv; 770 + 771 + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac suspend\n"); 772 + 773 + flush_workqueue(wcn->hal_ind_wq); 774 + wcn36xx_smd_set_power_params(wcn, true); 775 + return 0; 776 + } 777 + 778 + static int wcn36xx_resume(struct ieee80211_hw *hw) 779 + { 780 + struct wcn36xx *wcn = hw->priv; 781 + 782 + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac resume\n"); 783 + 784 + flush_workqueue(wcn->hal_ind_wq); 785 + wcn36xx_smd_set_power_params(wcn, false); 786 + return 0; 787 + } 788 + 789 + #endif 790 + 791 + static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, 792 + struct ieee80211_vif *vif, 793 + enum ieee80211_ampdu_mlme_action action, 794 + struct ieee80211_sta *sta, u16 tid, u16 *ssn, 795 + u8 buf_size) 796 + { 797 + struct wcn36xx *wcn = hw->priv; 798 + struct wcn36xx_sta *sta_priv = NULL; 799 + 800 + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n", 801 + action, tid); 802 + 803 + sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 804 + 805 + switch (action) { 806 + case IEEE80211_AMPDU_RX_START: 807 + sta_priv->tid = tid; 808 + wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 0, 809 + get_sta_index(vif, sta_priv)); 810 + wcn36xx_smd_add_ba(wcn); 811 + wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv)); 812 + ieee80211_start_tx_ba_session(sta, tid, 0); 813 + break; 814 + case IEEE80211_AMPDU_RX_STOP: 815 + wcn36xx_smd_del_ba(wcn, tid, get_sta_index(vif, sta_priv)); 816 + break; 817 + case IEEE80211_AMPDU_TX_START: 818 + ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); 819 + break; 820 + case IEEE80211_AMPDU_TX_OPERATIONAL: 821 + wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 1, 822 + get_sta_index(vif, sta_priv)); 823 + break; 824 + case IEEE80211_AMPDU_TX_STOP_FLUSH: 825 + case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: 826 + case IEEE80211_AMPDU_TX_STOP_CONT: 827 + ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); 828 + break; 829 + default: 830 + wcn36xx_err("Unknown AMPDU action\n"); 831 + } 832 + 833 + return 0; 834 + } 835 + 836 + static const struct ieee80211_ops wcn36xx_ops = { 837 + .start = wcn36xx_start, 838 + .stop = wcn36xx_stop, 839 + .add_interface = wcn36xx_add_interface, 840 + .remove_interface = wcn36xx_remove_interface, 841 + #ifdef CONFIG_PM 842 + .suspend = wcn36xx_suspend, 843 + .resume = wcn36xx_resume, 844 + #endif 845 + .config = wcn36xx_config, 846 + .configure_filter = wcn36xx_configure_filter, 847 + .tx = wcn36xx_tx, 848 + .set_key = wcn36xx_set_key, 849 + .sw_scan_start = wcn36xx_sw_scan_start, 850 + .sw_scan_complete = wcn36xx_sw_scan_complete, 851 + .bss_info_changed = wcn36xx_bss_info_changed, 852 + .set_rts_threshold = wcn36xx_set_rts_threshold, 853 + .sta_add = wcn36xx_sta_add, 854 + .sta_remove = wcn36xx_sta_remove, 855 + .ampdu_action = wcn36xx_ampdu_action, 856 + }; 857 + 858 + static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) 859 + { 860 + int ret = 0; 861 + 862 + static const u32 cipher_suites[] = { 863 + WLAN_CIPHER_SUITE_WEP40, 864 + WLAN_CIPHER_SUITE_WEP104, 865 + WLAN_CIPHER_SUITE_TKIP, 866 + WLAN_CIPHER_SUITE_CCMP, 867 + }; 868 + 869 + wcn->hw->flags = IEEE80211_HW_SIGNAL_DBM | 870 + IEEE80211_HW_HAS_RATE_CONTROL | 871 + IEEE80211_HW_SUPPORTS_PS | 872 + IEEE80211_HW_CONNECTION_MONITOR | 873 + IEEE80211_HW_AMPDU_AGGREGATION | 874 + IEEE80211_HW_TIMING_BEACON_ONLY; 875 + 876 + wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | 877 + BIT(NL80211_IFTYPE_AP) | 878 + BIT(NL80211_IFTYPE_ADHOC) | 879 + BIT(NL80211_IFTYPE_MESH_POINT); 880 + 881 + wcn->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wcn_band_2ghz; 882 + wcn->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wcn_band_5ghz; 883 + 884 + wcn->hw->wiphy->cipher_suites = cipher_suites; 885 + wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); 886 + 887 + wcn->hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; 888 + 889 + #ifdef CONFIG_PM 890 + wcn->hw->wiphy->wowlan = &wowlan_support; 891 + #endif 892 + 893 + wcn->hw->max_listen_interval = 200; 894 + 895 + wcn->hw->queues = 4; 896 + 897 + SET_IEEE80211_DEV(wcn->hw, wcn->dev); 898 + 899 + wcn->hw->sta_data_size = sizeof(struct wcn36xx_sta); 900 + wcn->hw->vif_data_size = sizeof(struct wcn36xx_vif); 901 + 902 + return ret; 903 + } 904 + 905 + static int wcn36xx_platform_get_resources(struct wcn36xx *wcn, 906 + struct platform_device *pdev) 907 + { 908 + struct resource *res; 909 + /* Set TX IRQ */ 910 + res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, 911 + "wcnss_wlantx_irq"); 912 + if (!res) { 913 + wcn36xx_err("failed to get tx_irq\n"); 914 + return -ENOENT; 915 + } 916 + wcn->tx_irq = res->start; 917 + 918 + /* Set RX IRQ */ 919 + res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, 920 + "wcnss_wlanrx_irq"); 921 + if (!res) { 922 + wcn36xx_err("failed to get rx_irq\n"); 923 + return -ENOENT; 924 + } 925 + wcn->rx_irq = res->start; 926 + 927 + /* Map the memory */ 928 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 929 + "wcnss_mmio"); 930 + if (!res) { 931 + wcn36xx_err("failed to get mmio\n"); 932 + return -ENOENT; 933 + } 934 + wcn->mmio = ioremap(res->start, resource_size(res)); 935 + if (!wcn->mmio) { 936 + wcn36xx_err("failed to map io memory\n"); 937 + return -ENOMEM; 938 + } 939 + return 0; 940 + } 941 + 942 + static int wcn36xx_probe(struct platform_device *pdev) 943 + { 944 + struct ieee80211_hw *hw; 945 + struct wcn36xx *wcn; 946 + int ret; 947 + u8 addr[ETH_ALEN]; 948 + 949 + wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n"); 950 + 951 + hw = ieee80211_alloc_hw(sizeof(struct wcn36xx), &wcn36xx_ops); 952 + if (!hw) { 953 + wcn36xx_err("failed to alloc hw\n"); 954 + ret = -ENOMEM; 955 + goto out_err; 956 + } 957 + platform_set_drvdata(pdev, hw); 958 + wcn = hw->priv; 959 + wcn->hw = hw; 960 + wcn->dev = &pdev->dev; 961 + wcn->ctrl_ops = pdev->dev.platform_data; 962 + 963 + mutex_init(&wcn->hal_mutex); 964 + 965 + if (!wcn->ctrl_ops->get_hw_mac(addr)) { 966 + wcn36xx_info("mac address: %pM\n", addr); 967 + SET_IEEE80211_PERM_ADDR(wcn->hw, addr); 968 + } 969 + 970 + ret = wcn36xx_platform_get_resources(wcn, pdev); 971 + if (ret) 972 + goto out_wq; 973 + 974 + wcn36xx_init_ieee80211(wcn); 975 + ret = ieee80211_register_hw(wcn->hw); 976 + if (ret) 977 + goto out_unmap; 978 + 979 + return 0; 980 + 981 + out_unmap: 982 + iounmap(wcn->mmio); 983 + out_wq: 984 + ieee80211_free_hw(hw); 985 + out_err: 986 + return ret; 987 + } 988 + static int wcn36xx_remove(struct platform_device *pdev) 989 + { 990 + struct ieee80211_hw *hw = platform_get_drvdata(pdev); 991 + struct wcn36xx *wcn = hw->priv; 992 + wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n"); 993 + 994 + mutex_destroy(&wcn->hal_mutex); 995 + 996 + ieee80211_unregister_hw(hw); 997 + iounmap(wcn->mmio); 998 + ieee80211_free_hw(hw); 999 + 1000 + return 0; 1001 + } 1002 + static const struct platform_device_id wcn36xx_platform_id_table[] = { 1003 + { 1004 + .name = "wcn36xx", 1005 + .driver_data = 0 1006 + }, 1007 + {} 1008 + }; 1009 + MODULE_DEVICE_TABLE(platform, wcn36xx_platform_id_table); 1010 + 1011 + static struct platform_driver wcn36xx_driver = { 1012 + .probe = wcn36xx_probe, 1013 + .remove = wcn36xx_remove, 1014 + .driver = { 1015 + .name = "wcn36xx", 1016 + .owner = THIS_MODULE, 1017 + }, 1018 + .id_table = wcn36xx_platform_id_table, 1019 + }; 1020 + 1021 + static int __init wcn36xx_init(void) 1022 + { 1023 + platform_driver_register(&wcn36xx_driver); 1024 + return 0; 1025 + } 1026 + module_init(wcn36xx_init); 1027 + 1028 + static void __exit wcn36xx_exit(void) 1029 + { 1030 + platform_driver_unregister(&wcn36xx_driver); 1031 + } 1032 + module_exit(wcn36xx_exit); 1033 + 1034 + MODULE_LICENSE("Dual BSD/GPL"); 1035 + MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com"); 1036 + MODULE_FIRMWARE(WLAN_NV_FILE);
+62
drivers/net/wireless/ath/wcn36xx/pmc.c
··· 1 + /* 2 + * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> 3 + * 4 + * Permission to use, copy, modify, and/or distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 11 + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 13 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 14 + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + 17 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 18 + 19 + #include "wcn36xx.h" 20 + 21 + int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn, 22 + struct ieee80211_vif *vif) 23 + { 24 + int ret = 0; 25 + struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 26 + /* TODO: Make sure the TX chain clean */ 27 + ret = wcn36xx_smd_enter_bmps(wcn, vif); 28 + if (!ret) { 29 + wcn36xx_dbg(WCN36XX_DBG_PMC, "Entered BMPS\n"); 30 + vif_priv->pw_state = WCN36XX_BMPS; 31 + } else { 32 + /* 33 + * One of the reasons why HW will not enter BMPS is because 34 + * driver is trying to enter bmps before first beacon was 35 + * received just after auth complete 36 + */ 37 + wcn36xx_err("Can not enter BMPS!\n"); 38 + } 39 + return ret; 40 + } 41 + 42 + int wcn36xx_pmc_exit_bmps_state(struct wcn36xx *wcn, 43 + struct ieee80211_vif *vif) 44 + { 45 + struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 46 + 47 + if (WCN36XX_BMPS != vif_priv->pw_state) { 48 + wcn36xx_err("Not in BMPS mode, no need to exit from BMPS mode!\n"); 49 + return -EINVAL; 50 + } 51 + wcn36xx_smd_exit_bmps(wcn, vif); 52 + vif_priv->pw_state = WCN36XX_FULL_POWER; 53 + return 0; 54 + } 55 + 56 + int wcn36xx_enable_keep_alive_null_packet(struct wcn36xx *wcn, 57 + struct ieee80211_vif *vif) 58 + { 59 + wcn36xx_dbg(WCN36XX_DBG_PMC, "%s\n", __func__); 60 + return wcn36xx_smd_keep_alive_req(wcn, vif, 61 + WCN36XX_HAL_KEEP_ALIVE_NULL_PKT); 62 + }
+33
drivers/net/wireless/ath/wcn36xx/pmc.h
··· 1 + /* 2 + * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> 3 + * 4 + * Permission to use, copy, modify, and/or distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 11 + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 13 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 14 + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + 17 + #ifndef _WCN36XX_PMC_H_ 18 + #define _WCN36XX_PMC_H_ 19 + 20 + struct wcn36xx; 21 + 22 + enum wcn36xx_power_state { 23 + WCN36XX_FULL_POWER, 24 + WCN36XX_BMPS 25 + }; 26 + 27 + int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn, 28 + struct ieee80211_vif *vif); 29 + int wcn36xx_pmc_exit_bmps_state(struct wcn36xx *wcn, 30 + struct ieee80211_vif *vif); 31 + int wcn36xx_enable_keep_alive_null_packet(struct wcn36xx *wcn, 32 + struct ieee80211_vif *vif); 33 + #endif /* _WCN36XX_PMC_H_ */
+2126
drivers/net/wireless/ath/wcn36xx/smd.c
··· 1 + /* 2 + * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> 3 + * 4 + * Permission to use, copy, modify, and/or distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 11 + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 13 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 14 + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + 17 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 18 + 19 + #include <linux/etherdevice.h> 20 + #include <linux/firmware.h> 21 + #include <linux/bitops.h> 22 + #include "smd.h" 23 + 24 + static int put_cfg_tlv_u32(struct wcn36xx *wcn, size_t *len, u32 id, u32 value) 25 + { 26 + struct wcn36xx_hal_cfg *entry; 27 + u32 *val; 28 + 29 + if (*len + sizeof(*entry) + sizeof(u32) >= WCN36XX_HAL_BUF_SIZE) { 30 + wcn36xx_err("Not enough room for TLV entry\n"); 31 + return -ENOMEM; 32 + } 33 + 34 + entry = (struct wcn36xx_hal_cfg *) (wcn->hal_buf + *len); 35 + entry->id = id; 36 + entry->len = sizeof(u32); 37 + entry->pad_bytes = 0; 38 + entry->reserve = 0; 39 + 40 + val = (u32 *) (entry + 1); 41 + *val = value; 42 + 43 + *len += sizeof(*entry) + sizeof(u32); 44 + 45 + return 0; 46 + } 47 + 48 + static void wcn36xx_smd_set_bss_nw_type(struct wcn36xx *wcn, 49 + struct ieee80211_sta *sta, 50 + struct wcn36xx_hal_config_bss_params *bss_params) 51 + { 52 + if (IEEE80211_BAND_5GHZ == WCN36XX_BAND(wcn)) 53 + bss_params->nw_type = WCN36XX_HAL_11A_NW_TYPE; 54 + else if (sta && sta->ht_cap.ht_supported) 55 + bss_params->nw_type = WCN36XX_HAL_11N_NW_TYPE; 56 + else if (sta && (sta->supp_rates[IEEE80211_BAND_2GHZ] & 0x7f)) 57 + bss_params->nw_type = WCN36XX_HAL_11G_NW_TYPE; 58 + else 59 + bss_params->nw_type = WCN36XX_HAL_11B_NW_TYPE; 60 + } 61 + 62 + static inline u8 is_cap_supported(unsigned long caps, unsigned long flag) 63 + { 64 + return caps & flag ? 1 : 0; 65 + } 66 + static void wcn36xx_smd_set_bss_ht_params(struct ieee80211_vif *vif, 67 + struct ieee80211_sta *sta, 68 + struct wcn36xx_hal_config_bss_params *bss_params) 69 + { 70 + if (sta && sta->ht_cap.ht_supported) { 71 + unsigned long caps = sta->ht_cap.cap; 72 + bss_params->ht = sta->ht_cap.ht_supported; 73 + bss_params->tx_channel_width_set = is_cap_supported(caps, 74 + IEEE80211_HT_CAP_SUP_WIDTH_20_40); 75 + bss_params->lsig_tx_op_protection_full_support = 76 + is_cap_supported(caps, 77 + IEEE80211_HT_CAP_LSIG_TXOP_PROT); 78 + 79 + bss_params->ht_oper_mode = vif->bss_conf.ht_operation_mode; 80 + bss_params->lln_non_gf_coexist = 81 + !!(vif->bss_conf.ht_operation_mode & 82 + IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); 83 + /* IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT */ 84 + bss_params->dual_cts_protection = 0; 85 + /* IEEE80211_HT_OP_MODE_PROTECTION_20MHZ */ 86 + bss_params->ht20_coexist = 0; 87 + } 88 + } 89 + 90 + static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta *sta, 91 + struct wcn36xx_hal_config_sta_params *sta_params) 92 + { 93 + if (sta->ht_cap.ht_supported) { 94 + unsigned long caps = sta->ht_cap.cap; 95 + sta_params->ht_capable = sta->ht_cap.ht_supported; 96 + sta_params->tx_channel_width_set = is_cap_supported(caps, 97 + IEEE80211_HT_CAP_SUP_WIDTH_20_40); 98 + sta_params->lsig_txop_protection = is_cap_supported(caps, 99 + IEEE80211_HT_CAP_LSIG_TXOP_PROT); 100 + 101 + sta_params->max_ampdu_size = sta->ht_cap.ampdu_factor; 102 + sta_params->max_ampdu_density = sta->ht_cap.ampdu_density; 103 + sta_params->max_amsdu_size = is_cap_supported(caps, 104 + IEEE80211_HT_CAP_MAX_AMSDU); 105 + sta_params->sgi_20Mhz = is_cap_supported(caps, 106 + IEEE80211_HT_CAP_SGI_20); 107 + sta_params->sgi_40mhz = is_cap_supported(caps, 108 + IEEE80211_HT_CAP_SGI_40); 109 + sta_params->green_field_capable = is_cap_supported(caps, 110 + IEEE80211_HT_CAP_GRN_FLD); 111 + sta_params->delayed_ba_support = is_cap_supported(caps, 112 + IEEE80211_HT_CAP_DELAY_BA); 113 + sta_params->dsss_cck_mode_40mhz = is_cap_supported(caps, 114 + IEEE80211_HT_CAP_DSSSCCK40); 115 + } 116 + } 117 + 118 + static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, 119 + struct ieee80211_vif *vif, 120 + struct ieee80211_sta *sta, 121 + struct wcn36xx_hal_config_sta_params *sta_params) 122 + { 123 + struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; 124 + struct wcn36xx_sta *priv_sta = NULL; 125 + if (vif->type == NL80211_IFTYPE_ADHOC || 126 + vif->type == NL80211_IFTYPE_AP || 127 + vif->type == NL80211_IFTYPE_MESH_POINT) { 128 + sta_params->type = 1; 129 + sta_params->sta_index = 0xFF; 130 + } else { 131 + sta_params->type = 0; 132 + sta_params->sta_index = 1; 133 + } 134 + 135 + sta_params->listen_interval = WCN36XX_LISTEN_INTERVAL(wcn); 136 + 137 + /* 138 + * In STA mode ieee80211_sta contains bssid and ieee80211_vif 139 + * contains our mac address. In AP mode we are bssid so vif 140 + * contains bssid and ieee80211_sta contains mac. 141 + */ 142 + if (NL80211_IFTYPE_STATION == vif->type) 143 + memcpy(&sta_params->mac, vif->addr, ETH_ALEN); 144 + else 145 + memcpy(&sta_params->bssid, vif->addr, ETH_ALEN); 146 + 147 + sta_params->encrypt_type = priv_vif->encrypt_type; 148 + sta_params->short_preamble_supported = 149 + !(WCN36XX_FLAGS(wcn) & 150 + IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE); 151 + 152 + sta_params->rifs_mode = 0; 153 + sta_params->rmf = 0; 154 + sta_params->action = 0; 155 + sta_params->uapsd = 0; 156 + sta_params->mimo_ps = WCN36XX_HAL_HT_MIMO_PS_STATIC; 157 + sta_params->max_ampdu_duration = 0; 158 + sta_params->bssid_index = priv_vif->bss_index; 159 + sta_params->p2p = 0; 160 + 161 + if (sta) { 162 + priv_sta = (struct wcn36xx_sta *)sta->drv_priv; 163 + if (NL80211_IFTYPE_STATION == vif->type) 164 + memcpy(&sta_params->bssid, sta->addr, ETH_ALEN); 165 + else 166 + memcpy(&sta_params->mac, sta->addr, ETH_ALEN); 167 + sta_params->wmm_enabled = sta->wme; 168 + sta_params->max_sp_len = sta->max_sp; 169 + sta_params->aid = priv_sta->aid; 170 + wcn36xx_smd_set_sta_ht_params(sta, sta_params); 171 + memcpy(&sta_params->supported_rates, &priv_sta->supported_rates, 172 + sizeof(priv_sta->supported_rates)); 173 + } else { 174 + wcn36xx_set_default_rates(&sta_params->supported_rates); 175 + } 176 + } 177 + 178 + static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len) 179 + { 180 + int ret = 0; 181 + wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "HAL >>> ", wcn->hal_buf, len); 182 + 183 + init_completion(&wcn->hal_rsp_compl); 184 + ret = wcn->ctrl_ops->tx(wcn->hal_buf, len); 185 + if (ret) { 186 + wcn36xx_err("HAL TX failed\n"); 187 + goto out; 188 + } 189 + if (wait_for_completion_timeout(&wcn->hal_rsp_compl, 190 + msecs_to_jiffies(HAL_MSG_TIMEOUT)) <= 0) { 191 + wcn36xx_err("Timeout while waiting SMD response\n"); 192 + ret = -ETIME; 193 + goto out; 194 + } 195 + out: 196 + return ret; 197 + } 198 + 199 + #define INIT_HAL_MSG(msg_body, type) \ 200 + do { \ 201 + memset(&msg_body, 0, sizeof(msg_body)); \ 202 + msg_body.header.msg_type = type; \ 203 + msg_body.header.msg_version = WCN36XX_HAL_MSG_VERSION0; \ 204 + msg_body.header.len = sizeof(msg_body); \ 205 + } while (0) \ 206 + 207 + #define PREPARE_HAL_BUF(send_buf, msg_body) \ 208 + do { \ 209 + memset(send_buf, 0, msg_body.header.len); \ 210 + memcpy(send_buf, &msg_body, sizeof(msg_body)); \ 211 + } while (0) \ 212 + 213 + static int wcn36xx_smd_rsp_status_check(void *buf, size_t len) 214 + { 215 + struct wcn36xx_fw_msg_status_rsp *rsp; 216 + 217 + if (len < sizeof(struct wcn36xx_hal_msg_header) + 218 + sizeof(struct wcn36xx_fw_msg_status_rsp)) 219 + return -EIO; 220 + 221 + rsp = (struct wcn36xx_fw_msg_status_rsp *) 222 + (buf + sizeof(struct wcn36xx_hal_msg_header)); 223 + 224 + if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status) 225 + return rsp->status; 226 + 227 + return 0; 228 + } 229 + 230 + int wcn36xx_smd_load_nv(struct wcn36xx *wcn) 231 + { 232 + const struct firmware *nv; 233 + struct nv_data *nv_d; 234 + struct wcn36xx_hal_nv_img_download_req_msg msg_body; 235 + int fw_bytes_left; 236 + int ret; 237 + u16 fm_offset = 0; 238 + 239 + ret = request_firmware(&nv, WLAN_NV_FILE, wcn->dev); 240 + if (ret) { 241 + wcn36xx_err("Failed to load nv file %s: %d\n", 242 + WLAN_NV_FILE, ret); 243 + goto out_free_nv; 244 + } 245 + 246 + nv_d = (struct nv_data *)nv->data; 247 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_DOWNLOAD_NV_REQ); 248 + 249 + msg_body.header.len += WCN36XX_NV_FRAGMENT_SIZE; 250 + 251 + msg_body.frag_number = 0; 252 + /* hal_buf must be protected with mutex */ 253 + mutex_lock(&wcn->hal_mutex); 254 + 255 + do { 256 + fw_bytes_left = nv->size - fm_offset - 4; 257 + if (fw_bytes_left > WCN36XX_NV_FRAGMENT_SIZE) { 258 + msg_body.last_fragment = 0; 259 + msg_body.nv_img_buffer_size = WCN36XX_NV_FRAGMENT_SIZE; 260 + } else { 261 + msg_body.last_fragment = 1; 262 + msg_body.nv_img_buffer_size = fw_bytes_left; 263 + 264 + /* Do not forget update general message len */ 265 + msg_body.header.len = sizeof(msg_body) + fw_bytes_left; 266 + 267 + } 268 + 269 + /* Add load NV request message header */ 270 + memcpy(wcn->hal_buf, &msg_body, sizeof(msg_body)); 271 + 272 + /* Add NV body itself */ 273 + memcpy(wcn->hal_buf + sizeof(msg_body), 274 + &nv_d->table + fm_offset, 275 + msg_body.nv_img_buffer_size); 276 + 277 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 278 + if (ret) 279 + goto out_unlock; 280 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, 281 + wcn->hal_rsp_len); 282 + if (ret) { 283 + wcn36xx_err("hal_load_nv response failed err=%d\n", 284 + ret); 285 + goto out_unlock; 286 + } 287 + msg_body.frag_number++; 288 + fm_offset += WCN36XX_NV_FRAGMENT_SIZE; 289 + 290 + } while (msg_body.last_fragment != 1); 291 + 292 + out_unlock: 293 + mutex_unlock(&wcn->hal_mutex); 294 + out_free_nv: 295 + release_firmware(nv); 296 + 297 + return ret; 298 + } 299 + 300 + static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len) 301 + { 302 + struct wcn36xx_hal_mac_start_rsp_msg *rsp; 303 + 304 + if (len < sizeof(*rsp)) 305 + return -EIO; 306 + 307 + rsp = (struct wcn36xx_hal_mac_start_rsp_msg *)buf; 308 + 309 + if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->start_rsp_params.status) 310 + return -EIO; 311 + 312 + memcpy(wcn->crm_version, rsp->start_rsp_params.crm_version, 313 + WCN36XX_HAL_VERSION_LENGTH); 314 + memcpy(wcn->wlan_version, rsp->start_rsp_params.wlan_version, 315 + WCN36XX_HAL_VERSION_LENGTH); 316 + 317 + /* null terminate the strings, just in case */ 318 + wcn->crm_version[WCN36XX_HAL_VERSION_LENGTH] = '\0'; 319 + wcn->wlan_version[WCN36XX_HAL_VERSION_LENGTH] = '\0'; 320 + 321 + wcn->fw_revision = rsp->start_rsp_params.version.revision; 322 + wcn->fw_version = rsp->start_rsp_params.version.version; 323 + wcn->fw_minor = rsp->start_rsp_params.version.minor; 324 + wcn->fw_major = rsp->start_rsp_params.version.major; 325 + 326 + wcn36xx_info("firmware WLAN version '%s' and CRM version '%s'\n", 327 + wcn->wlan_version, wcn->crm_version); 328 + 329 + wcn36xx_info("firmware API %u.%u.%u.%u, %u stations, %u bssids\n", 330 + wcn->fw_major, wcn->fw_minor, 331 + wcn->fw_version, wcn->fw_revision, 332 + rsp->start_rsp_params.stations, 333 + rsp->start_rsp_params.bssids); 334 + 335 + return 0; 336 + } 337 + 338 + int wcn36xx_smd_start(struct wcn36xx *wcn) 339 + { 340 + struct wcn36xx_hal_mac_start_req_msg msg_body; 341 + int ret = 0; 342 + 343 + mutex_lock(&wcn->hal_mutex); 344 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_REQ); 345 + 346 + msg_body.params.type = DRIVER_TYPE_PRODUCTION; 347 + msg_body.params.len = 0; 348 + 349 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 350 + 351 + wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start type %d\n", 352 + msg_body.params.type); 353 + 354 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 355 + if (ret) { 356 + wcn36xx_err("Sending hal_start failed\n"); 357 + goto out; 358 + } 359 + 360 + ret = wcn36xx_smd_start_rsp(wcn, wcn->hal_buf, wcn->hal_rsp_len); 361 + if (ret) { 362 + wcn36xx_err("hal_start response failed err=%d\n", ret); 363 + goto out; 364 + } 365 + 366 + out: 367 + mutex_unlock(&wcn->hal_mutex); 368 + return ret; 369 + } 370 + 371 + int wcn36xx_smd_stop(struct wcn36xx *wcn) 372 + { 373 + struct wcn36xx_hal_mac_stop_req_msg msg_body; 374 + int ret = 0; 375 + 376 + mutex_lock(&wcn->hal_mutex); 377 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_STOP_REQ); 378 + 379 + msg_body.stop_req_params.reason = HAL_STOP_TYPE_RF_KILL; 380 + 381 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 382 + 383 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 384 + if (ret) { 385 + wcn36xx_err("Sending hal_stop failed\n"); 386 + goto out; 387 + } 388 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 389 + if (ret) { 390 + wcn36xx_err("hal_stop response failed err=%d\n", ret); 391 + goto out; 392 + } 393 + out: 394 + mutex_unlock(&wcn->hal_mutex); 395 + return ret; 396 + } 397 + 398 + int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode) 399 + { 400 + struct wcn36xx_hal_init_scan_req_msg msg_body; 401 + int ret = 0; 402 + 403 + mutex_lock(&wcn->hal_mutex); 404 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_INIT_SCAN_REQ); 405 + 406 + msg_body.mode = mode; 407 + 408 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 409 + 410 + wcn36xx_dbg(WCN36XX_DBG_HAL, "hal init scan mode %d\n", msg_body.mode); 411 + 412 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 413 + if (ret) { 414 + wcn36xx_err("Sending hal_init_scan failed\n"); 415 + goto out; 416 + } 417 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 418 + if (ret) { 419 + wcn36xx_err("hal_init_scan response failed err=%d\n", ret); 420 + goto out; 421 + } 422 + out: 423 + mutex_unlock(&wcn->hal_mutex); 424 + return ret; 425 + } 426 + 427 + int wcn36xx_smd_start_scan(struct wcn36xx *wcn) 428 + { 429 + struct wcn36xx_hal_start_scan_req_msg msg_body; 430 + int ret = 0; 431 + 432 + mutex_lock(&wcn->hal_mutex); 433 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_SCAN_REQ); 434 + 435 + msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn); 436 + 437 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 438 + 439 + wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start scan channel %d\n", 440 + msg_body.scan_channel); 441 + 442 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 443 + if (ret) { 444 + wcn36xx_err("Sending hal_start_scan failed\n"); 445 + goto out; 446 + } 447 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 448 + if (ret) { 449 + wcn36xx_err("hal_start_scan response failed err=%d\n", ret); 450 + goto out; 451 + } 452 + out: 453 + mutex_unlock(&wcn->hal_mutex); 454 + return ret; 455 + } 456 + 457 + int wcn36xx_smd_end_scan(struct wcn36xx *wcn) 458 + { 459 + struct wcn36xx_hal_end_scan_req_msg msg_body; 460 + int ret = 0; 461 + 462 + mutex_lock(&wcn->hal_mutex); 463 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_END_SCAN_REQ); 464 + 465 + msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn); 466 + 467 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 468 + 469 + wcn36xx_dbg(WCN36XX_DBG_HAL, "hal end scan channel %d\n", 470 + msg_body.scan_channel); 471 + 472 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 473 + if (ret) { 474 + wcn36xx_err("Sending hal_end_scan failed\n"); 475 + goto out; 476 + } 477 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 478 + if (ret) { 479 + wcn36xx_err("hal_end_scan response failed err=%d\n", ret); 480 + goto out; 481 + } 482 + out: 483 + mutex_unlock(&wcn->hal_mutex); 484 + return ret; 485 + } 486 + 487 + int wcn36xx_smd_finish_scan(struct wcn36xx *wcn, 488 + enum wcn36xx_hal_sys_mode mode) 489 + { 490 + struct wcn36xx_hal_finish_scan_req_msg msg_body; 491 + int ret = 0; 492 + 493 + mutex_lock(&wcn->hal_mutex); 494 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_FINISH_SCAN_REQ); 495 + 496 + msg_body.mode = mode; 497 + 498 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 499 + 500 + wcn36xx_dbg(WCN36XX_DBG_HAL, "hal finish scan mode %d\n", 501 + msg_body.mode); 502 + 503 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 504 + if (ret) { 505 + wcn36xx_err("Sending hal_finish_scan failed\n"); 506 + goto out; 507 + } 508 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 509 + if (ret) { 510 + wcn36xx_err("hal_finish_scan response failed err=%d\n", ret); 511 + goto out; 512 + } 513 + out: 514 + mutex_unlock(&wcn->hal_mutex); 515 + return ret; 516 + } 517 + 518 + static int wcn36xx_smd_switch_channel_rsp(void *buf, size_t len) 519 + { 520 + struct wcn36xx_hal_switch_channel_rsp_msg *rsp; 521 + int ret = 0; 522 + 523 + ret = wcn36xx_smd_rsp_status_check(buf, len); 524 + if (ret) 525 + return ret; 526 + rsp = (struct wcn36xx_hal_switch_channel_rsp_msg *)buf; 527 + wcn36xx_dbg(WCN36XX_DBG_HAL, "channel switched to: %d, status: %d\n", 528 + rsp->channel_number, rsp->status); 529 + return ret; 530 + } 531 + 532 + int wcn36xx_smd_switch_channel(struct wcn36xx *wcn, 533 + struct ieee80211_vif *vif, int ch) 534 + { 535 + struct wcn36xx_hal_switch_channel_req_msg msg_body; 536 + int ret = 0; 537 + 538 + mutex_lock(&wcn->hal_mutex); 539 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_CH_SWITCH_REQ); 540 + 541 + msg_body.channel_number = (u8)ch; 542 + msg_body.tx_mgmt_power = 0xbf; 543 + msg_body.max_tx_power = 0xbf; 544 + memcpy(msg_body.self_sta_mac_addr, vif->addr, ETH_ALEN); 545 + 546 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 547 + 548 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 549 + if (ret) { 550 + wcn36xx_err("Sending hal_switch_channel failed\n"); 551 + goto out; 552 + } 553 + ret = wcn36xx_smd_switch_channel_rsp(wcn->hal_buf, wcn->hal_rsp_len); 554 + if (ret) { 555 + wcn36xx_err("hal_switch_channel response failed err=%d\n", ret); 556 + goto out; 557 + } 558 + out: 559 + mutex_unlock(&wcn->hal_mutex); 560 + return ret; 561 + } 562 + 563 + static int wcn36xx_smd_update_scan_params_rsp(void *buf, size_t len) 564 + { 565 + struct wcn36xx_hal_update_scan_params_resp *rsp; 566 + 567 + rsp = (struct wcn36xx_hal_update_scan_params_resp *)buf; 568 + 569 + /* Remove the PNO version bit */ 570 + rsp->status &= (~(WCN36XX_FW_MSG_PNO_VERSION_MASK)); 571 + 572 + if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status) { 573 + wcn36xx_warn("error response from update scan\n"); 574 + return rsp->status; 575 + } 576 + 577 + return 0; 578 + } 579 + 580 + int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn) 581 + { 582 + struct wcn36xx_hal_update_scan_params_req msg_body; 583 + int ret = 0; 584 + 585 + mutex_lock(&wcn->hal_mutex); 586 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ); 587 + 588 + msg_body.dot11d_enabled = 0; 589 + msg_body.dot11d_resolved = 0; 590 + msg_body.channel_count = 26; 591 + msg_body.active_min_ch_time = 60; 592 + msg_body.active_max_ch_time = 120; 593 + msg_body.passive_min_ch_time = 60; 594 + msg_body.passive_max_ch_time = 110; 595 + msg_body.state = 0; 596 + 597 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 598 + 599 + wcn36xx_dbg(WCN36XX_DBG_HAL, 600 + "hal update scan params channel_count %d\n", 601 + msg_body.channel_count); 602 + 603 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 604 + if (ret) { 605 + wcn36xx_err("Sending hal_update_scan_params failed\n"); 606 + goto out; 607 + } 608 + ret = wcn36xx_smd_update_scan_params_rsp(wcn->hal_buf, 609 + wcn->hal_rsp_len); 610 + if (ret) { 611 + wcn36xx_err("hal_update_scan_params response failed err=%d\n", 612 + ret); 613 + goto out; 614 + } 615 + out: 616 + mutex_unlock(&wcn->hal_mutex); 617 + return ret; 618 + } 619 + 620 + static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn, 621 + struct ieee80211_vif *vif, 622 + void *buf, 623 + size_t len) 624 + { 625 + struct wcn36xx_hal_add_sta_self_rsp_msg *rsp; 626 + struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; 627 + 628 + if (len < sizeof(*rsp)) 629 + return -EINVAL; 630 + 631 + rsp = (struct wcn36xx_hal_add_sta_self_rsp_msg *)buf; 632 + 633 + if (rsp->status != WCN36XX_FW_MSG_RESULT_SUCCESS) { 634 + wcn36xx_warn("hal add sta self failure: %d\n", 635 + rsp->status); 636 + return rsp->status; 637 + } 638 + 639 + wcn36xx_dbg(WCN36XX_DBG_HAL, 640 + "hal add sta self status %d self_sta_index %d dpu_index %d\n", 641 + rsp->status, rsp->self_sta_index, rsp->dpu_index); 642 + 643 + priv_vif->self_sta_index = rsp->self_sta_index; 644 + priv_vif->self_dpu_desc_index = rsp->dpu_index; 645 + 646 + return 0; 647 + } 648 + 649 + int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif) 650 + { 651 + struct wcn36xx_hal_add_sta_self_req msg_body; 652 + int ret = 0; 653 + 654 + mutex_lock(&wcn->hal_mutex); 655 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_STA_SELF_REQ); 656 + 657 + memcpy(&msg_body.self_addr, vif->addr, ETH_ALEN); 658 + 659 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 660 + 661 + wcn36xx_dbg(WCN36XX_DBG_HAL, 662 + "hal add sta self self_addr %pM status %d\n", 663 + msg_body.self_addr, msg_body.status); 664 + 665 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 666 + if (ret) { 667 + wcn36xx_err("Sending hal_add_sta_self failed\n"); 668 + goto out; 669 + } 670 + ret = wcn36xx_smd_add_sta_self_rsp(wcn, 671 + vif, 672 + wcn->hal_buf, 673 + wcn->hal_rsp_len); 674 + if (ret) { 675 + wcn36xx_err("hal_add_sta_self response failed err=%d\n", ret); 676 + goto out; 677 + } 678 + out: 679 + mutex_unlock(&wcn->hal_mutex); 680 + return ret; 681 + } 682 + 683 + int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr) 684 + { 685 + struct wcn36xx_hal_del_sta_self_req_msg msg_body; 686 + int ret = 0; 687 + 688 + mutex_lock(&wcn->hal_mutex); 689 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_STA_SELF_REQ); 690 + 691 + memcpy(&msg_body.self_addr, addr, ETH_ALEN); 692 + 693 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 694 + 695 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 696 + if (ret) { 697 + wcn36xx_err("Sending hal_delete_sta_self failed\n"); 698 + goto out; 699 + } 700 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 701 + if (ret) { 702 + wcn36xx_err("hal_delete_sta_self response failed err=%d\n", 703 + ret); 704 + goto out; 705 + } 706 + out: 707 + mutex_unlock(&wcn->hal_mutex); 708 + return ret; 709 + } 710 + 711 + int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index) 712 + { 713 + struct wcn36xx_hal_delete_sta_req_msg msg_body; 714 + int ret = 0; 715 + 716 + mutex_lock(&wcn->hal_mutex); 717 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_STA_REQ); 718 + 719 + msg_body.sta_index = sta_index; 720 + 721 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 722 + 723 + wcn36xx_dbg(WCN36XX_DBG_HAL, 724 + "hal delete sta sta_index %d\n", 725 + msg_body.sta_index); 726 + 727 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 728 + if (ret) { 729 + wcn36xx_err("Sending hal_delete_sta failed\n"); 730 + goto out; 731 + } 732 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 733 + if (ret) { 734 + wcn36xx_err("hal_delete_sta response failed err=%d\n", ret); 735 + goto out; 736 + } 737 + out: 738 + mutex_unlock(&wcn->hal_mutex); 739 + return ret; 740 + } 741 + 742 + static int wcn36xx_smd_join_rsp(void *buf, size_t len) 743 + { 744 + struct wcn36xx_hal_join_rsp_msg *rsp; 745 + 746 + if (wcn36xx_smd_rsp_status_check(buf, len)) 747 + return -EIO; 748 + 749 + rsp = (struct wcn36xx_hal_join_rsp_msg *)buf; 750 + 751 + wcn36xx_dbg(WCN36XX_DBG_HAL, 752 + "hal rsp join status %d tx_mgmt_power %d\n", 753 + rsp->status, rsp->tx_mgmt_power); 754 + 755 + return 0; 756 + } 757 + 758 + int wcn36xx_smd_join(struct wcn36xx *wcn, const u8 *bssid, u8 *vif, u8 ch) 759 + { 760 + struct wcn36xx_hal_join_req_msg msg_body; 761 + int ret = 0; 762 + 763 + mutex_lock(&wcn->hal_mutex); 764 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_JOIN_REQ); 765 + 766 + memcpy(&msg_body.bssid, bssid, ETH_ALEN); 767 + memcpy(&msg_body.self_sta_mac_addr, vif, ETH_ALEN); 768 + msg_body.channel = ch; 769 + 770 + if (conf_is_ht40_minus(&wcn->hw->conf)) 771 + msg_body.secondary_channel_offset = 772 + PHY_DOUBLE_CHANNEL_HIGH_PRIMARY; 773 + else if (conf_is_ht40_plus(&wcn->hw->conf)) 774 + msg_body.secondary_channel_offset = 775 + PHY_DOUBLE_CHANNEL_LOW_PRIMARY; 776 + else 777 + msg_body.secondary_channel_offset = 778 + PHY_SINGLE_CHANNEL_CENTERED; 779 + 780 + msg_body.link_state = WCN36XX_HAL_LINK_PREASSOC_STATE; 781 + 782 + msg_body.max_tx_power = 0xbf; 783 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 784 + 785 + wcn36xx_dbg(WCN36XX_DBG_HAL, 786 + "hal join req bssid %pM self_sta_mac_addr %pM channel %d link_state %d\n", 787 + msg_body.bssid, msg_body.self_sta_mac_addr, 788 + msg_body.channel, msg_body.link_state); 789 + 790 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 791 + if (ret) { 792 + wcn36xx_err("Sending hal_join failed\n"); 793 + goto out; 794 + } 795 + ret = wcn36xx_smd_join_rsp(wcn->hal_buf, wcn->hal_rsp_len); 796 + if (ret) { 797 + wcn36xx_err("hal_join response failed err=%d\n", ret); 798 + goto out; 799 + } 800 + out: 801 + mutex_unlock(&wcn->hal_mutex); 802 + return ret; 803 + } 804 + 805 + int wcn36xx_smd_set_link_st(struct wcn36xx *wcn, const u8 *bssid, 806 + const u8 *sta_mac, 807 + enum wcn36xx_hal_link_state state) 808 + { 809 + struct wcn36xx_hal_set_link_state_req_msg msg_body; 810 + int ret = 0; 811 + 812 + mutex_lock(&wcn->hal_mutex); 813 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_LINK_ST_REQ); 814 + 815 + memcpy(&msg_body.bssid, bssid, ETH_ALEN); 816 + memcpy(&msg_body.self_mac_addr, sta_mac, ETH_ALEN); 817 + msg_body.state = state; 818 + 819 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 820 + 821 + wcn36xx_dbg(WCN36XX_DBG_HAL, 822 + "hal set link state bssid %pM self_mac_addr %pM state %d\n", 823 + msg_body.bssid, msg_body.self_mac_addr, msg_body.state); 824 + 825 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 826 + if (ret) { 827 + wcn36xx_err("Sending hal_set_link_st failed\n"); 828 + goto out; 829 + } 830 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 831 + if (ret) { 832 + wcn36xx_err("hal_set_link_st response failed err=%d\n", ret); 833 + goto out; 834 + } 835 + out: 836 + mutex_unlock(&wcn->hal_mutex); 837 + return ret; 838 + } 839 + 840 + static void wcn36xx_smd_convert_sta_to_v1(struct wcn36xx *wcn, 841 + const struct wcn36xx_hal_config_sta_params *orig, 842 + struct wcn36xx_hal_config_sta_params_v1 *v1) 843 + { 844 + /* convert orig to v1 format */ 845 + memcpy(&v1->bssid, orig->bssid, ETH_ALEN); 846 + memcpy(&v1->mac, orig->mac, ETH_ALEN); 847 + v1->aid = orig->aid; 848 + v1->type = orig->type; 849 + v1->listen_interval = orig->listen_interval; 850 + v1->ht_capable = orig->ht_capable; 851 + 852 + v1->max_ampdu_size = orig->max_ampdu_size; 853 + v1->max_ampdu_density = orig->max_ampdu_density; 854 + v1->sgi_40mhz = orig->sgi_40mhz; 855 + v1->sgi_20Mhz = orig->sgi_20Mhz; 856 + 857 + memcpy(&v1->supported_rates, &orig->supported_rates, 858 + sizeof(orig->supported_rates)); 859 + v1->sta_index = orig->sta_index; 860 + } 861 + 862 + static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn, 863 + struct ieee80211_sta *sta, 864 + void *buf, 865 + size_t len) 866 + { 867 + struct wcn36xx_hal_config_sta_rsp_msg *rsp; 868 + struct config_sta_rsp_params *params; 869 + struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; 870 + 871 + if (len < sizeof(*rsp)) 872 + return -EINVAL; 873 + 874 + rsp = (struct wcn36xx_hal_config_sta_rsp_msg *)buf; 875 + params = &rsp->params; 876 + 877 + if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) { 878 + wcn36xx_warn("hal config sta response failure: %d\n", 879 + params->status); 880 + return -EIO; 881 + } 882 + 883 + sta_priv->sta_index = params->sta_index; 884 + sta_priv->dpu_desc_index = params->dpu_index; 885 + 886 + wcn36xx_dbg(WCN36XX_DBG_HAL, 887 + "hal config sta rsp status %d sta_index %d bssid_index %d p2p %d\n", 888 + params->status, params->sta_index, params->bssid_index, 889 + params->p2p); 890 + 891 + return 0; 892 + } 893 + 894 + static int wcn36xx_smd_config_sta_v1(struct wcn36xx *wcn, 895 + const struct wcn36xx_hal_config_sta_req_msg *orig) 896 + { 897 + struct wcn36xx_hal_config_sta_req_msg_v1 msg_body; 898 + struct wcn36xx_hal_config_sta_params_v1 *sta = &msg_body.sta_params; 899 + 900 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_STA_REQ); 901 + 902 + wcn36xx_smd_convert_sta_to_v1(wcn, &orig->sta_params, 903 + &msg_body.sta_params); 904 + 905 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 906 + 907 + wcn36xx_dbg(WCN36XX_DBG_HAL, 908 + "hal config sta v1 action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n", 909 + sta->action, sta->sta_index, sta->bssid_index, 910 + sta->bssid, sta->type, sta->mac, sta->aid); 911 + 912 + return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 913 + } 914 + 915 + int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif, 916 + struct ieee80211_sta *sta) 917 + { 918 + struct wcn36xx_hal_config_sta_req_msg msg; 919 + struct wcn36xx_hal_config_sta_params *sta_params; 920 + int ret = 0; 921 + 922 + mutex_lock(&wcn->hal_mutex); 923 + INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_STA_REQ); 924 + 925 + sta_params = &msg.sta_params; 926 + 927 + wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params); 928 + 929 + if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { 930 + ret = wcn36xx_smd_config_sta_v1(wcn, &msg); 931 + } else { 932 + PREPARE_HAL_BUF(wcn->hal_buf, msg); 933 + 934 + wcn36xx_dbg(WCN36XX_DBG_HAL, 935 + "hal config sta action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n", 936 + sta_params->action, sta_params->sta_index, 937 + sta_params->bssid_index, sta_params->bssid, 938 + sta_params->type, sta_params->mac, sta_params->aid); 939 + 940 + ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len); 941 + } 942 + if (ret) { 943 + wcn36xx_err("Sending hal_config_sta failed\n"); 944 + goto out; 945 + } 946 + ret = wcn36xx_smd_config_sta_rsp(wcn, 947 + sta, 948 + wcn->hal_buf, 949 + wcn->hal_rsp_len); 950 + if (ret) { 951 + wcn36xx_err("hal_config_sta response failed err=%d\n", ret); 952 + goto out; 953 + } 954 + out: 955 + mutex_unlock(&wcn->hal_mutex); 956 + return ret; 957 + } 958 + 959 + static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn, 960 + const struct wcn36xx_hal_config_bss_req_msg *orig) 961 + { 962 + struct wcn36xx_hal_config_bss_req_msg_v1 msg_body; 963 + struct wcn36xx_hal_config_bss_params_v1 *bss = &msg_body.bss_params; 964 + struct wcn36xx_hal_config_sta_params_v1 *sta = &bss->sta; 965 + 966 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_BSS_REQ); 967 + 968 + /* convert orig to v1 */ 969 + memcpy(&msg_body.bss_params.bssid, 970 + &orig->bss_params.bssid, ETH_ALEN); 971 + memcpy(&msg_body.bss_params.self_mac_addr, 972 + &orig->bss_params.self_mac_addr, ETH_ALEN); 973 + 974 + msg_body.bss_params.bss_type = orig->bss_params.bss_type; 975 + msg_body.bss_params.oper_mode = orig->bss_params.oper_mode; 976 + msg_body.bss_params.nw_type = orig->bss_params.nw_type; 977 + 978 + msg_body.bss_params.short_slot_time_supported = 979 + orig->bss_params.short_slot_time_supported; 980 + msg_body.bss_params.lla_coexist = orig->bss_params.lla_coexist; 981 + msg_body.bss_params.llb_coexist = orig->bss_params.llb_coexist; 982 + msg_body.bss_params.llg_coexist = orig->bss_params.llg_coexist; 983 + msg_body.bss_params.ht20_coexist = orig->bss_params.ht20_coexist; 984 + msg_body.bss_params.lln_non_gf_coexist = 985 + orig->bss_params.lln_non_gf_coexist; 986 + 987 + msg_body.bss_params.lsig_tx_op_protection_full_support = 988 + orig->bss_params.lsig_tx_op_protection_full_support; 989 + msg_body.bss_params.rifs_mode = orig->bss_params.rifs_mode; 990 + msg_body.bss_params.beacon_interval = orig->bss_params.beacon_interval; 991 + msg_body.bss_params.dtim_period = orig->bss_params.dtim_period; 992 + msg_body.bss_params.tx_channel_width_set = 993 + orig->bss_params.tx_channel_width_set; 994 + msg_body.bss_params.oper_channel = orig->bss_params.oper_channel; 995 + msg_body.bss_params.ext_channel = orig->bss_params.ext_channel; 996 + 997 + msg_body.bss_params.reserved = orig->bss_params.reserved; 998 + 999 + memcpy(&msg_body.bss_params.ssid, 1000 + &orig->bss_params.ssid, 1001 + sizeof(orig->bss_params.ssid)); 1002 + 1003 + msg_body.bss_params.action = orig->bss_params.action; 1004 + msg_body.bss_params.rateset = orig->bss_params.rateset; 1005 + msg_body.bss_params.ht = orig->bss_params.ht; 1006 + msg_body.bss_params.obss_prot_enabled = 1007 + orig->bss_params.obss_prot_enabled; 1008 + msg_body.bss_params.rmf = orig->bss_params.rmf; 1009 + msg_body.bss_params.ht_oper_mode = orig->bss_params.ht_oper_mode; 1010 + msg_body.bss_params.dual_cts_protection = 1011 + orig->bss_params.dual_cts_protection; 1012 + 1013 + msg_body.bss_params.max_probe_resp_retry_limit = 1014 + orig->bss_params.max_probe_resp_retry_limit; 1015 + msg_body.bss_params.hidden_ssid = orig->bss_params.hidden_ssid; 1016 + msg_body.bss_params.proxy_probe_resp = 1017 + orig->bss_params.proxy_probe_resp; 1018 + msg_body.bss_params.edca_params_valid = 1019 + orig->bss_params.edca_params_valid; 1020 + 1021 + memcpy(&msg_body.bss_params.acbe, 1022 + &orig->bss_params.acbe, 1023 + sizeof(orig->bss_params.acbe)); 1024 + memcpy(&msg_body.bss_params.acbk, 1025 + &orig->bss_params.acbk, 1026 + sizeof(orig->bss_params.acbk)); 1027 + memcpy(&msg_body.bss_params.acvi, 1028 + &orig->bss_params.acvi, 1029 + sizeof(orig->bss_params.acvi)); 1030 + memcpy(&msg_body.bss_params.acvo, 1031 + &orig->bss_params.acvo, 1032 + sizeof(orig->bss_params.acvo)); 1033 + 1034 + msg_body.bss_params.ext_set_sta_key_param_valid = 1035 + orig->bss_params.ext_set_sta_key_param_valid; 1036 + 1037 + memcpy(&msg_body.bss_params.ext_set_sta_key_param, 1038 + &orig->bss_params.ext_set_sta_key_param, 1039 + sizeof(orig->bss_params.acvo)); 1040 + 1041 + msg_body.bss_params.wcn36xx_hal_persona = 1042 + orig->bss_params.wcn36xx_hal_persona; 1043 + msg_body.bss_params.spectrum_mgt_enable = 1044 + orig->bss_params.spectrum_mgt_enable; 1045 + msg_body.bss_params.tx_mgmt_power = orig->bss_params.tx_mgmt_power; 1046 + msg_body.bss_params.max_tx_power = orig->bss_params.max_tx_power; 1047 + 1048 + wcn36xx_smd_convert_sta_to_v1(wcn, &orig->bss_params.sta, 1049 + &msg_body.bss_params.sta); 1050 + 1051 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1052 + 1053 + wcn36xx_dbg(WCN36XX_DBG_HAL, 1054 + "hal config bss v1 bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n", 1055 + bss->bssid, bss->self_mac_addr, bss->bss_type, 1056 + bss->oper_mode, bss->nw_type); 1057 + 1058 + wcn36xx_dbg(WCN36XX_DBG_HAL, 1059 + "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n", 1060 + sta->bssid, sta->action, sta->sta_index, 1061 + sta->bssid_index, sta->aid, sta->type, sta->mac); 1062 + 1063 + return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1064 + } 1065 + 1066 + 1067 + static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn, 1068 + struct ieee80211_vif *vif, 1069 + void *buf, 1070 + size_t len) 1071 + { 1072 + struct wcn36xx_hal_config_bss_rsp_msg *rsp; 1073 + struct wcn36xx_hal_config_bss_rsp_params *params; 1074 + struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; 1075 + 1076 + if (len < sizeof(*rsp)) 1077 + return -EINVAL; 1078 + 1079 + rsp = (struct wcn36xx_hal_config_bss_rsp_msg *)buf; 1080 + params = &rsp->bss_rsp_params; 1081 + 1082 + if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) { 1083 + wcn36xx_warn("hal config bss response failure: %d\n", 1084 + params->status); 1085 + return -EIO; 1086 + } 1087 + 1088 + wcn36xx_dbg(WCN36XX_DBG_HAL, 1089 + "hal config bss rsp status %d bss_idx %d dpu_desc_index %d" 1090 + " sta_idx %d self_idx %d bcast_idx %d mac %pM" 1091 + " power %d ucast_dpu_signature %d\n", 1092 + params->status, params->bss_index, params->dpu_desc_index, 1093 + params->bss_sta_index, params->bss_self_sta_index, 1094 + params->bss_bcast_sta_idx, params->mac, 1095 + params->tx_mgmt_power, params->ucast_dpu_signature); 1096 + 1097 + priv_vif->bss_index = params->bss_index; 1098 + 1099 + if (priv_vif->sta) { 1100 + priv_vif->sta->bss_sta_index = params->bss_sta_index; 1101 + priv_vif->sta->bss_dpu_desc_index = params->dpu_desc_index; 1102 + } 1103 + 1104 + priv_vif->ucast_dpu_signature = params->ucast_dpu_signature; 1105 + 1106 + return 0; 1107 + } 1108 + 1109 + int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, 1110 + struct ieee80211_sta *sta, const u8 *bssid, 1111 + bool update) 1112 + { 1113 + struct wcn36xx_hal_config_bss_req_msg msg; 1114 + struct wcn36xx_hal_config_bss_params *bss; 1115 + struct wcn36xx_hal_config_sta_params *sta_params; 1116 + struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 1117 + int ret = 0; 1118 + 1119 + mutex_lock(&wcn->hal_mutex); 1120 + INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_BSS_REQ); 1121 + 1122 + bss = &msg.bss_params; 1123 + sta_params = &bss->sta; 1124 + 1125 + WARN_ON(is_zero_ether_addr(bssid)); 1126 + 1127 + memcpy(&bss->bssid, bssid, ETH_ALEN); 1128 + 1129 + memcpy(bss->self_mac_addr, vif->addr, ETH_ALEN); 1130 + 1131 + if (vif->type == NL80211_IFTYPE_STATION) { 1132 + bss->bss_type = WCN36XX_HAL_INFRASTRUCTURE_MODE; 1133 + 1134 + /* STA */ 1135 + bss->oper_mode = 1; 1136 + bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_MODE; 1137 + } else if (vif->type == NL80211_IFTYPE_AP) { 1138 + bss->bss_type = WCN36XX_HAL_INFRA_AP_MODE; 1139 + 1140 + /* AP */ 1141 + bss->oper_mode = 0; 1142 + bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_SAP_MODE; 1143 + } else if (vif->type == NL80211_IFTYPE_ADHOC || 1144 + vif->type == NL80211_IFTYPE_MESH_POINT) { 1145 + bss->bss_type = WCN36XX_HAL_IBSS_MODE; 1146 + 1147 + /* STA */ 1148 + bss->oper_mode = 1; 1149 + } else { 1150 + wcn36xx_warn("Unknown type for bss config: %d\n", vif->type); 1151 + } 1152 + 1153 + if (vif->type == NL80211_IFTYPE_STATION) 1154 + wcn36xx_smd_set_bss_nw_type(wcn, sta, bss); 1155 + else 1156 + bss->nw_type = WCN36XX_HAL_11N_NW_TYPE; 1157 + 1158 + bss->short_slot_time_supported = vif->bss_conf.use_short_slot; 1159 + bss->lla_coexist = 0; 1160 + bss->llb_coexist = 0; 1161 + bss->llg_coexist = 0; 1162 + bss->rifs_mode = 0; 1163 + bss->beacon_interval = vif->bss_conf.beacon_int; 1164 + bss->dtim_period = vif_priv->dtim_period; 1165 + 1166 + wcn36xx_smd_set_bss_ht_params(vif, sta, bss); 1167 + 1168 + bss->oper_channel = WCN36XX_HW_CHANNEL(wcn); 1169 + 1170 + if (conf_is_ht40_minus(&wcn->hw->conf)) 1171 + bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_BELOW; 1172 + else if (conf_is_ht40_plus(&wcn->hw->conf)) 1173 + bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; 1174 + else 1175 + bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_NONE; 1176 + 1177 + bss->reserved = 0; 1178 + wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params); 1179 + 1180 + /* wcn->ssid is only valid in AP and IBSS mode */ 1181 + bss->ssid.length = vif_priv->ssid.length; 1182 + memcpy(bss->ssid.ssid, vif_priv->ssid.ssid, vif_priv->ssid.length); 1183 + 1184 + bss->obss_prot_enabled = 0; 1185 + bss->rmf = 0; 1186 + bss->max_probe_resp_retry_limit = 0; 1187 + bss->hidden_ssid = vif->bss_conf.hidden_ssid; 1188 + bss->proxy_probe_resp = 0; 1189 + bss->edca_params_valid = 0; 1190 + 1191 + /* FIXME: set acbe, acbk, acvi and acvo */ 1192 + 1193 + bss->ext_set_sta_key_param_valid = 0; 1194 + 1195 + /* FIXME: set ext_set_sta_key_param */ 1196 + 1197 + bss->spectrum_mgt_enable = 0; 1198 + bss->tx_mgmt_power = 0; 1199 + bss->max_tx_power = WCN36XX_MAX_POWER(wcn); 1200 + 1201 + bss->action = update; 1202 + 1203 + wcn36xx_dbg(WCN36XX_DBG_HAL, 1204 + "hal config bss bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n", 1205 + bss->bssid, bss->self_mac_addr, bss->bss_type, 1206 + bss->oper_mode, bss->nw_type); 1207 + 1208 + wcn36xx_dbg(WCN36XX_DBG_HAL, 1209 + "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n", 1210 + sta_params->bssid, sta_params->action, 1211 + sta_params->sta_index, sta_params->bssid_index, 1212 + sta_params->aid, sta_params->type, 1213 + sta_params->mac); 1214 + 1215 + if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { 1216 + ret = wcn36xx_smd_config_bss_v1(wcn, &msg); 1217 + } else { 1218 + PREPARE_HAL_BUF(wcn->hal_buf, msg); 1219 + 1220 + ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len); 1221 + } 1222 + if (ret) { 1223 + wcn36xx_err("Sending hal_config_bss failed\n"); 1224 + goto out; 1225 + } 1226 + ret = wcn36xx_smd_config_bss_rsp(wcn, 1227 + vif, 1228 + wcn->hal_buf, 1229 + wcn->hal_rsp_len); 1230 + if (ret) { 1231 + wcn36xx_err("hal_config_bss response failed err=%d\n", ret); 1232 + goto out; 1233 + } 1234 + out: 1235 + mutex_unlock(&wcn->hal_mutex); 1236 + return ret; 1237 + } 1238 + 1239 + int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif) 1240 + { 1241 + struct wcn36xx_hal_delete_bss_req_msg msg_body; 1242 + struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; 1243 + int ret = 0; 1244 + 1245 + mutex_lock(&wcn->hal_mutex); 1246 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_BSS_REQ); 1247 + 1248 + msg_body.bss_index = priv_vif->bss_index; 1249 + 1250 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1251 + 1252 + wcn36xx_dbg(WCN36XX_DBG_HAL, "hal delete bss %d\n", msg_body.bss_index); 1253 + 1254 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1255 + if (ret) { 1256 + wcn36xx_err("Sending hal_delete_bss failed\n"); 1257 + goto out; 1258 + } 1259 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1260 + if (ret) { 1261 + wcn36xx_err("hal_delete_bss response failed err=%d\n", ret); 1262 + goto out; 1263 + } 1264 + out: 1265 + mutex_unlock(&wcn->hal_mutex); 1266 + return ret; 1267 + } 1268 + 1269 + int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif, 1270 + struct sk_buff *skb_beacon, u16 tim_off, 1271 + u16 p2p_off) 1272 + { 1273 + struct wcn36xx_hal_send_beacon_req_msg msg_body; 1274 + int ret = 0; 1275 + 1276 + mutex_lock(&wcn->hal_mutex); 1277 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ); 1278 + 1279 + /* TODO need to find out why this is needed? */ 1280 + msg_body.beacon_length = skb_beacon->len + 6; 1281 + 1282 + if (BEACON_TEMPLATE_SIZE > msg_body.beacon_length) { 1283 + memcpy(&msg_body.beacon, &skb_beacon->len, sizeof(u32)); 1284 + memcpy(&(msg_body.beacon[4]), skb_beacon->data, 1285 + skb_beacon->len); 1286 + } else { 1287 + wcn36xx_err("Beacon is to big: beacon size=%d\n", 1288 + msg_body.beacon_length); 1289 + return -ENOMEM; 1290 + } 1291 + memcpy(msg_body.bssid, vif->addr, ETH_ALEN); 1292 + 1293 + /* TODO need to find out why this is needed? */ 1294 + msg_body.tim_ie_offset = tim_off+4; 1295 + msg_body.p2p_ie_offset = p2p_off; 1296 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1297 + 1298 + wcn36xx_dbg(WCN36XX_DBG_HAL, 1299 + "hal send beacon beacon_length %d\n", 1300 + msg_body.beacon_length); 1301 + 1302 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1303 + if (ret) { 1304 + wcn36xx_err("Sending hal_send_beacon failed\n"); 1305 + goto out; 1306 + } 1307 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1308 + if (ret) { 1309 + wcn36xx_err("hal_send_beacon response failed err=%d\n", ret); 1310 + goto out; 1311 + } 1312 + out: 1313 + mutex_unlock(&wcn->hal_mutex); 1314 + return ret; 1315 + } 1316 + 1317 + int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn, 1318 + struct ieee80211_vif *vif, 1319 + struct sk_buff *skb) 1320 + { 1321 + struct wcn36xx_hal_send_probe_resp_req_msg msg; 1322 + int ret = 0; 1323 + 1324 + mutex_lock(&wcn->hal_mutex); 1325 + INIT_HAL_MSG(msg, WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ); 1326 + 1327 + if (skb->len > BEACON_TEMPLATE_SIZE) { 1328 + wcn36xx_warn("probe response template is too big: %d\n", 1329 + skb->len); 1330 + return -E2BIG; 1331 + } 1332 + 1333 + msg.probe_resp_template_len = skb->len; 1334 + memcpy(&msg.probe_resp_template, skb->data, skb->len); 1335 + 1336 + memcpy(msg.bssid, vif->addr, ETH_ALEN); 1337 + 1338 + PREPARE_HAL_BUF(wcn->hal_buf, msg); 1339 + 1340 + wcn36xx_dbg(WCN36XX_DBG_HAL, 1341 + "hal update probe rsp len %d bssid %pM\n", 1342 + msg.probe_resp_template_len, msg.bssid); 1343 + 1344 + ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len); 1345 + if (ret) { 1346 + wcn36xx_err("Sending hal_update_proberesp_tmpl failed\n"); 1347 + goto out; 1348 + } 1349 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1350 + if (ret) { 1351 + wcn36xx_err("hal_update_proberesp_tmpl response failed err=%d\n", 1352 + ret); 1353 + goto out; 1354 + } 1355 + out: 1356 + mutex_unlock(&wcn->hal_mutex); 1357 + return ret; 1358 + } 1359 + 1360 + int wcn36xx_smd_set_stakey(struct wcn36xx *wcn, 1361 + enum ani_ed_type enc_type, 1362 + u8 keyidx, 1363 + u8 keylen, 1364 + u8 *key, 1365 + u8 sta_index) 1366 + { 1367 + struct wcn36xx_hal_set_sta_key_req_msg msg_body; 1368 + int ret = 0; 1369 + 1370 + mutex_lock(&wcn->hal_mutex); 1371 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_STAKEY_REQ); 1372 + 1373 + msg_body.set_sta_key_params.sta_index = sta_index; 1374 + msg_body.set_sta_key_params.enc_type = enc_type; 1375 + 1376 + msg_body.set_sta_key_params.key[0].id = keyidx; 1377 + msg_body.set_sta_key_params.key[0].unicast = 1; 1378 + msg_body.set_sta_key_params.key[0].direction = WCN36XX_HAL_TX_RX; 1379 + msg_body.set_sta_key_params.key[0].pae_role = 0; 1380 + msg_body.set_sta_key_params.key[0].length = keylen; 1381 + memcpy(msg_body.set_sta_key_params.key[0].key, key, keylen); 1382 + msg_body.set_sta_key_params.single_tid_rc = 1; 1383 + 1384 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1385 + 1386 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1387 + if (ret) { 1388 + wcn36xx_err("Sending hal_set_stakey failed\n"); 1389 + goto out; 1390 + } 1391 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1392 + if (ret) { 1393 + wcn36xx_err("hal_set_stakey response failed err=%d\n", ret); 1394 + goto out; 1395 + } 1396 + out: 1397 + mutex_unlock(&wcn->hal_mutex); 1398 + return ret; 1399 + } 1400 + 1401 + int wcn36xx_smd_set_bsskey(struct wcn36xx *wcn, 1402 + enum ani_ed_type enc_type, 1403 + u8 keyidx, 1404 + u8 keylen, 1405 + u8 *key) 1406 + { 1407 + struct wcn36xx_hal_set_bss_key_req_msg msg_body; 1408 + int ret = 0; 1409 + 1410 + mutex_lock(&wcn->hal_mutex); 1411 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_BSSKEY_REQ); 1412 + msg_body.bss_idx = 0; 1413 + msg_body.enc_type = enc_type; 1414 + msg_body.num_keys = 1; 1415 + msg_body.keys[0].id = keyidx; 1416 + msg_body.keys[0].unicast = 0; 1417 + msg_body.keys[0].direction = WCN36XX_HAL_RX_ONLY; 1418 + msg_body.keys[0].pae_role = 0; 1419 + msg_body.keys[0].length = keylen; 1420 + memcpy(msg_body.keys[0].key, key, keylen); 1421 + 1422 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1423 + 1424 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1425 + if (ret) { 1426 + wcn36xx_err("Sending hal_set_bsskey failed\n"); 1427 + goto out; 1428 + } 1429 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1430 + if (ret) { 1431 + wcn36xx_err("hal_set_bsskey response failed err=%d\n", ret); 1432 + goto out; 1433 + } 1434 + out: 1435 + mutex_unlock(&wcn->hal_mutex); 1436 + return ret; 1437 + } 1438 + 1439 + int wcn36xx_smd_remove_stakey(struct wcn36xx *wcn, 1440 + enum ani_ed_type enc_type, 1441 + u8 keyidx, 1442 + u8 sta_index) 1443 + { 1444 + struct wcn36xx_hal_remove_sta_key_req_msg msg_body; 1445 + int ret = 0; 1446 + 1447 + mutex_lock(&wcn->hal_mutex); 1448 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_STAKEY_REQ); 1449 + 1450 + msg_body.sta_idx = sta_index; 1451 + msg_body.enc_type = enc_type; 1452 + msg_body.key_id = keyidx; 1453 + 1454 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1455 + 1456 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1457 + if (ret) { 1458 + wcn36xx_err("Sending hal_remove_stakey failed\n"); 1459 + goto out; 1460 + } 1461 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1462 + if (ret) { 1463 + wcn36xx_err("hal_remove_stakey response failed err=%d\n", ret); 1464 + goto out; 1465 + } 1466 + out: 1467 + mutex_unlock(&wcn->hal_mutex); 1468 + return ret; 1469 + } 1470 + 1471 + int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn, 1472 + enum ani_ed_type enc_type, 1473 + u8 keyidx) 1474 + { 1475 + struct wcn36xx_hal_remove_bss_key_req_msg msg_body; 1476 + int ret = 0; 1477 + 1478 + mutex_lock(&wcn->hal_mutex); 1479 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_BSSKEY_REQ); 1480 + msg_body.bss_idx = 0; 1481 + msg_body.enc_type = enc_type; 1482 + msg_body.key_id = keyidx; 1483 + 1484 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1485 + 1486 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1487 + if (ret) { 1488 + wcn36xx_err("Sending hal_remove_bsskey failed\n"); 1489 + goto out; 1490 + } 1491 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1492 + if (ret) { 1493 + wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret); 1494 + goto out; 1495 + } 1496 + out: 1497 + mutex_unlock(&wcn->hal_mutex); 1498 + return ret; 1499 + } 1500 + 1501 + int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) 1502 + { 1503 + struct wcn36xx_hal_enter_bmps_req_msg msg_body; 1504 + struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 1505 + int ret = 0; 1506 + 1507 + mutex_lock(&wcn->hal_mutex); 1508 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_BMPS_REQ); 1509 + 1510 + msg_body.bss_index = vif_priv->bss_index; 1511 + msg_body.tbtt = vif->bss_conf.sync_tsf; 1512 + msg_body.dtim_period = vif_priv->dtim_period; 1513 + 1514 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1515 + 1516 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1517 + if (ret) { 1518 + wcn36xx_err("Sending hal_enter_bmps failed\n"); 1519 + goto out; 1520 + } 1521 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1522 + if (ret) { 1523 + wcn36xx_err("hal_enter_bmps response failed err=%d\n", ret); 1524 + goto out; 1525 + } 1526 + out: 1527 + mutex_unlock(&wcn->hal_mutex); 1528 + return ret; 1529 + } 1530 + 1531 + int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) 1532 + { 1533 + struct wcn36xx_hal_enter_bmps_req_msg msg_body; 1534 + struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 1535 + int ret = 0; 1536 + 1537 + mutex_lock(&wcn->hal_mutex); 1538 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_BMPS_REQ); 1539 + 1540 + msg_body.bss_index = vif_priv->bss_index; 1541 + 1542 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1543 + 1544 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1545 + if (ret) { 1546 + wcn36xx_err("Sending hal_exit_bmps failed\n"); 1547 + goto out; 1548 + } 1549 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1550 + if (ret) { 1551 + wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret); 1552 + goto out; 1553 + } 1554 + out: 1555 + mutex_unlock(&wcn->hal_mutex); 1556 + return ret; 1557 + } 1558 + int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim) 1559 + { 1560 + struct wcn36xx_hal_set_power_params_req_msg msg_body; 1561 + int ret = 0; 1562 + 1563 + mutex_lock(&wcn->hal_mutex); 1564 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_POWER_PARAMS_REQ); 1565 + 1566 + /* 1567 + * When host is down ignore every second dtim 1568 + */ 1569 + if (ignore_dtim) { 1570 + msg_body.ignore_dtim = 1; 1571 + msg_body.dtim_period = 2; 1572 + } 1573 + msg_body.listen_interval = WCN36XX_LISTEN_INTERVAL(wcn); 1574 + 1575 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1576 + 1577 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1578 + if (ret) { 1579 + wcn36xx_err("Sending hal_set_power_params failed\n"); 1580 + goto out; 1581 + } 1582 + 1583 + out: 1584 + mutex_unlock(&wcn->hal_mutex); 1585 + return ret; 1586 + } 1587 + /* Notice: This function should be called after associated, or else it 1588 + * will be invalid 1589 + */ 1590 + int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn, 1591 + struct ieee80211_vif *vif, 1592 + int packet_type) 1593 + { 1594 + struct wcn36xx_hal_keep_alive_req_msg msg_body; 1595 + struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; 1596 + int ret = 0; 1597 + 1598 + mutex_lock(&wcn->hal_mutex); 1599 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_KEEP_ALIVE_REQ); 1600 + 1601 + if (packet_type == WCN36XX_HAL_KEEP_ALIVE_NULL_PKT) { 1602 + msg_body.bss_index = vif_priv->bss_index; 1603 + msg_body.packet_type = WCN36XX_HAL_KEEP_ALIVE_NULL_PKT; 1604 + msg_body.time_period = WCN36XX_KEEP_ALIVE_TIME_PERIOD; 1605 + } else if (packet_type == WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP) { 1606 + /* TODO: it also support ARP response type */ 1607 + } else { 1608 + wcn36xx_warn("unknow keep alive packet type %d\n", packet_type); 1609 + return -EINVAL; 1610 + } 1611 + 1612 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1613 + 1614 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1615 + if (ret) { 1616 + wcn36xx_err("Sending hal_exit_bmps failed\n"); 1617 + goto out; 1618 + } 1619 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1620 + if (ret) { 1621 + wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret); 1622 + goto out; 1623 + } 1624 + out: 1625 + mutex_unlock(&wcn->hal_mutex); 1626 + return ret; 1627 + } 1628 + 1629 + int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2, 1630 + u32 arg3, u32 arg4, u32 arg5) 1631 + { 1632 + struct wcn36xx_hal_dump_cmd_req_msg msg_body; 1633 + int ret = 0; 1634 + 1635 + mutex_lock(&wcn->hal_mutex); 1636 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_DUMP_COMMAND_REQ); 1637 + 1638 + msg_body.arg1 = arg1; 1639 + msg_body.arg2 = arg2; 1640 + msg_body.arg3 = arg3; 1641 + msg_body.arg4 = arg4; 1642 + msg_body.arg5 = arg5; 1643 + 1644 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1645 + 1646 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1647 + if (ret) { 1648 + wcn36xx_err("Sending hal_dump_cmd failed\n"); 1649 + goto out; 1650 + } 1651 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1652 + if (ret) { 1653 + wcn36xx_err("hal_dump_cmd response failed err=%d\n", ret); 1654 + goto out; 1655 + } 1656 + out: 1657 + mutex_unlock(&wcn->hal_mutex); 1658 + return ret; 1659 + } 1660 + 1661 + static inline void set_feat_caps(u32 *bitmap, 1662 + enum place_holder_in_cap_bitmap cap) 1663 + { 1664 + int arr_idx, bit_idx; 1665 + 1666 + if (cap < 0 || cap > 127) { 1667 + wcn36xx_warn("error cap idx %d\n", cap); 1668 + return; 1669 + } 1670 + 1671 + arr_idx = cap / 32; 1672 + bit_idx = cap % 32; 1673 + bitmap[arr_idx] |= (1 << bit_idx); 1674 + } 1675 + 1676 + static inline int get_feat_caps(u32 *bitmap, 1677 + enum place_holder_in_cap_bitmap cap) 1678 + { 1679 + int arr_idx, bit_idx; 1680 + int ret = 0; 1681 + 1682 + if (cap < 0 || cap > 127) { 1683 + wcn36xx_warn("error cap idx %d\n", cap); 1684 + return -EINVAL; 1685 + } 1686 + 1687 + arr_idx = cap / 32; 1688 + bit_idx = cap % 32; 1689 + ret = (bitmap[arr_idx] & (1 << bit_idx)) ? 1 : 0; 1690 + return ret; 1691 + } 1692 + 1693 + static inline void clear_feat_caps(u32 *bitmap, 1694 + enum place_holder_in_cap_bitmap cap) 1695 + { 1696 + int arr_idx, bit_idx; 1697 + 1698 + if (cap < 0 || cap > 127) { 1699 + wcn36xx_warn("error cap idx %d\n", cap); 1700 + return; 1701 + } 1702 + 1703 + arr_idx = cap / 32; 1704 + bit_idx = cap % 32; 1705 + bitmap[arr_idx] &= ~(1 << bit_idx); 1706 + } 1707 + 1708 + int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn) 1709 + { 1710 + struct wcn36xx_hal_feat_caps_msg msg_body; 1711 + int ret = 0; 1712 + 1713 + mutex_lock(&wcn->hal_mutex); 1714 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ); 1715 + 1716 + set_feat_caps(msg_body.feat_caps, STA_POWERSAVE); 1717 + 1718 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1719 + 1720 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1721 + if (ret) { 1722 + wcn36xx_err("Sending hal_feature_caps_exchange failed\n"); 1723 + goto out; 1724 + } 1725 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1726 + if (ret) { 1727 + wcn36xx_err("hal_feature_caps_exchange response failed err=%d\n", 1728 + ret); 1729 + goto out; 1730 + } 1731 + out: 1732 + mutex_unlock(&wcn->hal_mutex); 1733 + return ret; 1734 + } 1735 + 1736 + int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn, 1737 + struct ieee80211_sta *sta, 1738 + u16 tid, 1739 + u16 *ssn, 1740 + u8 direction, 1741 + u8 sta_index) 1742 + { 1743 + struct wcn36xx_hal_add_ba_session_req_msg msg_body; 1744 + int ret = 0; 1745 + 1746 + mutex_lock(&wcn->hal_mutex); 1747 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_SESSION_REQ); 1748 + 1749 + msg_body.sta_index = sta_index; 1750 + memcpy(&msg_body.mac_addr, sta->addr, ETH_ALEN); 1751 + msg_body.dialog_token = 0x10; 1752 + msg_body.tid = tid; 1753 + 1754 + /* Immediate BA because Delayed BA is not supported */ 1755 + msg_body.policy = 1; 1756 + msg_body.buffer_size = WCN36XX_AGGR_BUFFER_SIZE; 1757 + msg_body.timeout = 0; 1758 + if (ssn) 1759 + msg_body.ssn = *ssn; 1760 + msg_body.direction = direction; 1761 + 1762 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1763 + 1764 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1765 + if (ret) { 1766 + wcn36xx_err("Sending hal_add_ba_session failed\n"); 1767 + goto out; 1768 + } 1769 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1770 + if (ret) { 1771 + wcn36xx_err("hal_add_ba_session response failed err=%d\n", ret); 1772 + goto out; 1773 + } 1774 + out: 1775 + mutex_unlock(&wcn->hal_mutex); 1776 + return ret; 1777 + } 1778 + 1779 + int wcn36xx_smd_add_ba(struct wcn36xx *wcn) 1780 + { 1781 + struct wcn36xx_hal_add_ba_req_msg msg_body; 1782 + int ret = 0; 1783 + 1784 + mutex_lock(&wcn->hal_mutex); 1785 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_REQ); 1786 + 1787 + msg_body.session_id = 0; 1788 + msg_body.win_size = WCN36XX_AGGR_BUFFER_SIZE; 1789 + 1790 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1791 + 1792 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1793 + if (ret) { 1794 + wcn36xx_err("Sending hal_add_ba failed\n"); 1795 + goto out; 1796 + } 1797 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1798 + if (ret) { 1799 + wcn36xx_err("hal_add_ba response failed err=%d\n", ret); 1800 + goto out; 1801 + } 1802 + out: 1803 + mutex_unlock(&wcn->hal_mutex); 1804 + return ret; 1805 + } 1806 + 1807 + int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index) 1808 + { 1809 + struct wcn36xx_hal_del_ba_req_msg msg_body; 1810 + int ret = 0; 1811 + 1812 + mutex_lock(&wcn->hal_mutex); 1813 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_BA_REQ); 1814 + 1815 + msg_body.sta_index = sta_index; 1816 + msg_body.tid = tid; 1817 + msg_body.direction = 0; 1818 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1819 + 1820 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1821 + if (ret) { 1822 + wcn36xx_err("Sending hal_del_ba failed\n"); 1823 + goto out; 1824 + } 1825 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1826 + if (ret) { 1827 + wcn36xx_err("hal_del_ba response failed err=%d\n", ret); 1828 + goto out; 1829 + } 1830 + out: 1831 + mutex_unlock(&wcn->hal_mutex); 1832 + return ret; 1833 + } 1834 + 1835 + int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index) 1836 + { 1837 + struct wcn36xx_hal_trigger_ba_req_msg msg_body; 1838 + struct wcn36xx_hal_trigget_ba_req_candidate *candidate; 1839 + int ret = 0; 1840 + 1841 + mutex_lock(&wcn->hal_mutex); 1842 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_TRIGGER_BA_REQ); 1843 + 1844 + msg_body.session_id = 0; 1845 + msg_body.candidate_cnt = 1; 1846 + msg_body.header.len += sizeof(*candidate); 1847 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1848 + 1849 + candidate = (struct wcn36xx_hal_trigget_ba_req_candidate *) 1850 + (wcn->hal_buf + sizeof(msg_body)); 1851 + candidate->sta_index = sta_index; 1852 + candidate->tid_bitmap = 1; 1853 + 1854 + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); 1855 + if (ret) { 1856 + wcn36xx_err("Sending hal_trigger_ba failed\n"); 1857 + goto out; 1858 + } 1859 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1860 + if (ret) { 1861 + wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret); 1862 + goto out; 1863 + } 1864 + out: 1865 + mutex_unlock(&wcn->hal_mutex); 1866 + return ret; 1867 + } 1868 + 1869 + static int wcn36xx_smd_tx_compl_ind(struct wcn36xx *wcn, void *buf, size_t len) 1870 + { 1871 + struct wcn36xx_hal_tx_compl_ind_msg *rsp = buf; 1872 + 1873 + if (len != sizeof(*rsp)) { 1874 + wcn36xx_warn("Bad TX complete indication\n"); 1875 + return -EIO; 1876 + } 1877 + 1878 + wcn36xx_dxe_tx_ack_ind(wcn, rsp->status); 1879 + 1880 + return 0; 1881 + } 1882 + 1883 + static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn, 1884 + void *buf, 1885 + size_t len) 1886 + { 1887 + struct wcn36xx_hal_missed_beacon_ind_msg *rsp = buf; 1888 + struct ieee80211_vif *vif = NULL; 1889 + struct wcn36xx_vif *tmp; 1890 + 1891 + /* Old FW does not have bss index */ 1892 + if (wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { 1893 + list_for_each_entry(tmp, &wcn->vif_list, list) { 1894 + wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n", 1895 + tmp->bss_index); 1896 + vif = container_of((void *)tmp, 1897 + struct ieee80211_vif, 1898 + drv_priv); 1899 + ieee80211_connection_loss(vif); 1900 + } 1901 + return 0; 1902 + } 1903 + 1904 + if (len != sizeof(*rsp)) { 1905 + wcn36xx_warn("Corrupted missed beacon indication\n"); 1906 + return -EIO; 1907 + } 1908 + 1909 + list_for_each_entry(tmp, &wcn->vif_list, list) { 1910 + if (tmp->bss_index == rsp->bss_index) { 1911 + wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n", 1912 + rsp->bss_index); 1913 + vif = container_of((void *)tmp, 1914 + struct ieee80211_vif, 1915 + drv_priv); 1916 + ieee80211_connection_loss(vif); 1917 + return 0; 1918 + } 1919 + } 1920 + 1921 + wcn36xx_warn("BSS index %d not found\n", rsp->bss_index); 1922 + return -ENOENT; 1923 + } 1924 + 1925 + static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn, 1926 + void *buf, 1927 + size_t len) 1928 + { 1929 + struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf; 1930 + struct wcn36xx_vif *tmp; 1931 + struct ieee80211_sta *sta = NULL; 1932 + 1933 + if (len != sizeof(*rsp)) { 1934 + wcn36xx_warn("Corrupted delete sta indication\n"); 1935 + return -EIO; 1936 + } 1937 + 1938 + list_for_each_entry(tmp, &wcn->vif_list, list) { 1939 + if (sta && (tmp->sta->sta_index == rsp->sta_id)) { 1940 + sta = container_of((void *)tmp->sta, 1941 + struct ieee80211_sta, 1942 + drv_priv); 1943 + wcn36xx_dbg(WCN36XX_DBG_HAL, 1944 + "delete station indication %pM index %d\n", 1945 + rsp->addr2, 1946 + rsp->sta_id); 1947 + ieee80211_report_low_ack(sta, 0); 1948 + return 0; 1949 + } 1950 + } 1951 + 1952 + wcn36xx_warn("STA with addr %pM and index %d not found\n", 1953 + rsp->addr2, 1954 + rsp->sta_id); 1955 + return -ENOENT; 1956 + } 1957 + 1958 + int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value) 1959 + { 1960 + struct wcn36xx_hal_update_cfg_req_msg msg_body, *body; 1961 + size_t len; 1962 + int ret = 0; 1963 + 1964 + mutex_lock(&wcn->hal_mutex); 1965 + INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_CFG_REQ); 1966 + 1967 + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); 1968 + 1969 + body = (struct wcn36xx_hal_update_cfg_req_msg *) wcn->hal_buf; 1970 + len = msg_body.header.len; 1971 + 1972 + put_cfg_tlv_u32(wcn, &len, cfg_id, value); 1973 + body->header.len = len; 1974 + body->len = len - sizeof(*body); 1975 + 1976 + ret = wcn36xx_smd_send_and_wait(wcn, body->header.len); 1977 + if (ret) { 1978 + wcn36xx_err("Sending hal_update_cfg failed\n"); 1979 + goto out; 1980 + } 1981 + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); 1982 + if (ret) { 1983 + wcn36xx_err("hal_update_cfg response failed err=%d\n", ret); 1984 + goto out; 1985 + } 1986 + out: 1987 + mutex_unlock(&wcn->hal_mutex); 1988 + return ret; 1989 + } 1990 + static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len) 1991 + { 1992 + struct wcn36xx_hal_msg_header *msg_header = buf; 1993 + struct wcn36xx_hal_ind_msg *msg_ind; 1994 + wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len); 1995 + 1996 + switch (msg_header->msg_type) { 1997 + case WCN36XX_HAL_START_RSP: 1998 + case WCN36XX_HAL_CONFIG_STA_RSP: 1999 + case WCN36XX_HAL_CONFIG_BSS_RSP: 2000 + case WCN36XX_HAL_ADD_STA_SELF_RSP: 2001 + case WCN36XX_HAL_STOP_RSP: 2002 + case WCN36XX_HAL_DEL_STA_SELF_RSP: 2003 + case WCN36XX_HAL_DELETE_STA_RSP: 2004 + case WCN36XX_HAL_INIT_SCAN_RSP: 2005 + case WCN36XX_HAL_START_SCAN_RSP: 2006 + case WCN36XX_HAL_END_SCAN_RSP: 2007 + case WCN36XX_HAL_FINISH_SCAN_RSP: 2008 + case WCN36XX_HAL_DOWNLOAD_NV_RSP: 2009 + case WCN36XX_HAL_DELETE_BSS_RSP: 2010 + case WCN36XX_HAL_SEND_BEACON_RSP: 2011 + case WCN36XX_HAL_SET_LINK_ST_RSP: 2012 + case WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_RSP: 2013 + case WCN36XX_HAL_SET_BSSKEY_RSP: 2014 + case WCN36XX_HAL_SET_STAKEY_RSP: 2015 + case WCN36XX_HAL_RMV_STAKEY_RSP: 2016 + case WCN36XX_HAL_RMV_BSSKEY_RSP: 2017 + case WCN36XX_HAL_ENTER_BMPS_RSP: 2018 + case WCN36XX_HAL_SET_POWER_PARAMS_RSP: 2019 + case WCN36XX_HAL_EXIT_BMPS_RSP: 2020 + case WCN36XX_HAL_KEEP_ALIVE_RSP: 2021 + case WCN36XX_HAL_DUMP_COMMAND_RSP: 2022 + case WCN36XX_HAL_ADD_BA_SESSION_RSP: 2023 + case WCN36XX_HAL_ADD_BA_RSP: 2024 + case WCN36XX_HAL_DEL_BA_RSP: 2025 + case WCN36XX_HAL_TRIGGER_BA_RSP: 2026 + case WCN36XX_HAL_UPDATE_CFG_RSP: 2027 + case WCN36XX_HAL_JOIN_RSP: 2028 + case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP: 2029 + case WCN36XX_HAL_CH_SWITCH_RSP: 2030 + case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP: 2031 + memcpy(wcn->hal_buf, buf, len); 2032 + wcn->hal_rsp_len = len; 2033 + complete(&wcn->hal_rsp_compl); 2034 + break; 2035 + 2036 + case WCN36XX_HAL_OTA_TX_COMPL_IND: 2037 + case WCN36XX_HAL_MISSED_BEACON_IND: 2038 + case WCN36XX_HAL_DELETE_STA_CONTEXT_IND: 2039 + mutex_lock(&wcn->hal_ind_mutex); 2040 + msg_ind = kmalloc(sizeof(*msg_ind), GFP_KERNEL); 2041 + msg_ind->msg_len = len; 2042 + msg_ind->msg = kmalloc(len, GFP_KERNEL); 2043 + memcpy(msg_ind->msg, buf, len); 2044 + list_add_tail(&msg_ind->list, &wcn->hal_ind_queue); 2045 + queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work); 2046 + wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n"); 2047 + mutex_unlock(&wcn->hal_ind_mutex); 2048 + break; 2049 + default: 2050 + wcn36xx_err("SMD_EVENT (%d) not supported\n", 2051 + msg_header->msg_type); 2052 + } 2053 + } 2054 + static void wcn36xx_ind_smd_work(struct work_struct *work) 2055 + { 2056 + struct wcn36xx *wcn = 2057 + container_of(work, struct wcn36xx, hal_ind_work); 2058 + struct wcn36xx_hal_msg_header *msg_header; 2059 + struct wcn36xx_hal_ind_msg *hal_ind_msg; 2060 + 2061 + mutex_lock(&wcn->hal_ind_mutex); 2062 + 2063 + hal_ind_msg = list_first_entry(&wcn->hal_ind_queue, 2064 + struct wcn36xx_hal_ind_msg, 2065 + list); 2066 + 2067 + msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg; 2068 + 2069 + switch (msg_header->msg_type) { 2070 + case WCN36XX_HAL_OTA_TX_COMPL_IND: 2071 + wcn36xx_smd_tx_compl_ind(wcn, 2072 + hal_ind_msg->msg, 2073 + hal_ind_msg->msg_len); 2074 + break; 2075 + case WCN36XX_HAL_MISSED_BEACON_IND: 2076 + wcn36xx_smd_missed_beacon_ind(wcn, 2077 + hal_ind_msg->msg, 2078 + hal_ind_msg->msg_len); 2079 + break; 2080 + case WCN36XX_HAL_DELETE_STA_CONTEXT_IND: 2081 + wcn36xx_smd_delete_sta_context_ind(wcn, 2082 + hal_ind_msg->msg, 2083 + hal_ind_msg->msg_len); 2084 + break; 2085 + default: 2086 + wcn36xx_err("SMD_EVENT (%d) not supported\n", 2087 + msg_header->msg_type); 2088 + } 2089 + list_del(wcn->hal_ind_queue.next); 2090 + kfree(hal_ind_msg->msg); 2091 + kfree(hal_ind_msg); 2092 + mutex_unlock(&wcn->hal_ind_mutex); 2093 + } 2094 + int wcn36xx_smd_open(struct wcn36xx *wcn) 2095 + { 2096 + int ret = 0; 2097 + wcn->hal_ind_wq = create_freezable_workqueue("wcn36xx_smd_ind"); 2098 + if (!wcn->hal_ind_wq) { 2099 + wcn36xx_err("failed to allocate wq\n"); 2100 + ret = -ENOMEM; 2101 + goto out; 2102 + } 2103 + INIT_WORK(&wcn->hal_ind_work, wcn36xx_ind_smd_work); 2104 + INIT_LIST_HEAD(&wcn->hal_ind_queue); 2105 + mutex_init(&wcn->hal_ind_mutex); 2106 + 2107 + ret = wcn->ctrl_ops->open(wcn, wcn36xx_smd_rsp_process); 2108 + if (ret) { 2109 + wcn36xx_err("failed to open control channel\n"); 2110 + goto free_wq; 2111 + } 2112 + 2113 + return ret; 2114 + 2115 + free_wq: 2116 + destroy_workqueue(wcn->hal_ind_wq); 2117 + out: 2118 + return ret; 2119 + } 2120 + 2121 + void wcn36xx_smd_close(struct wcn36xx *wcn) 2122 + { 2123 + wcn->ctrl_ops->close(); 2124 + destroy_workqueue(wcn->hal_ind_wq); 2125 + mutex_destroy(&wcn->hal_ind_mutex); 2126 + }
+127
drivers/net/wireless/ath/wcn36xx/smd.h
··· 1 + /* 2 + * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> 3 + * 4 + * Permission to use, copy, modify, and/or distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 11 + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 13 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 14 + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + 17 + #ifndef _SMD_H_ 18 + #define _SMD_H_ 19 + 20 + #include "wcn36xx.h" 21 + 22 + /* Max shared size is 4k but we take less.*/ 23 + #define WCN36XX_NV_FRAGMENT_SIZE 3072 24 + 25 + #define WCN36XX_HAL_BUF_SIZE 4096 26 + 27 + #define HAL_MSG_TIMEOUT 200 28 + #define WCN36XX_SMSM_WLAN_TX_ENABLE 0x00000400 29 + #define WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY 0x00000200 30 + /* The PNO version info be contained in the rsp msg */ 31 + #define WCN36XX_FW_MSG_PNO_VERSION_MASK 0x8000 32 + 33 + enum wcn36xx_fw_msg_result { 34 + WCN36XX_FW_MSG_RESULT_SUCCESS = 0, 35 + WCN36XX_FW_MSG_RESULT_SUCCESS_SYNC = 1, 36 + 37 + WCN36XX_FW_MSG_RESULT_MEM_FAIL = 5, 38 + }; 39 + 40 + /******************************/ 41 + /* SMD requests and responses */ 42 + /******************************/ 43 + struct wcn36xx_fw_msg_status_rsp { 44 + u32 status; 45 + } __packed; 46 + 47 + struct wcn36xx_hal_ind_msg { 48 + struct list_head list; 49 + u8 *msg; 50 + size_t msg_len; 51 + }; 52 + 53 + struct wcn36xx; 54 + 55 + int wcn36xx_smd_open(struct wcn36xx *wcn); 56 + void wcn36xx_smd_close(struct wcn36xx *wcn); 57 + 58 + int wcn36xx_smd_load_nv(struct wcn36xx *wcn); 59 + int wcn36xx_smd_start(struct wcn36xx *wcn); 60 + int wcn36xx_smd_stop(struct wcn36xx *wcn); 61 + int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode); 62 + int wcn36xx_smd_start_scan(struct wcn36xx *wcn); 63 + int wcn36xx_smd_end_scan(struct wcn36xx *wcn); 64 + int wcn36xx_smd_finish_scan(struct wcn36xx *wcn, 65 + enum wcn36xx_hal_sys_mode mode); 66 + int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn); 67 + int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif); 68 + int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr); 69 + int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index); 70 + int wcn36xx_smd_join(struct wcn36xx *wcn, const u8 *bssid, u8 *vif, u8 ch); 71 + int wcn36xx_smd_set_link_st(struct wcn36xx *wcn, const u8 *bssid, 72 + const u8 *sta_mac, 73 + enum wcn36xx_hal_link_state state); 74 + int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, 75 + struct ieee80211_sta *sta, const u8 *bssid, 76 + bool update); 77 + int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif); 78 + int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif, 79 + struct ieee80211_sta *sta); 80 + int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif, 81 + struct sk_buff *skb_beacon, u16 tim_off, 82 + u16 p2p_off); 83 + int wcn36xx_smd_switch_channel(struct wcn36xx *wcn, 84 + struct ieee80211_vif *vif, int ch); 85 + int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn, 86 + struct ieee80211_vif *vif, 87 + struct sk_buff *skb); 88 + int wcn36xx_smd_set_stakey(struct wcn36xx *wcn, 89 + enum ani_ed_type enc_type, 90 + u8 keyidx, 91 + u8 keylen, 92 + u8 *key, 93 + u8 sta_index); 94 + int wcn36xx_smd_set_bsskey(struct wcn36xx *wcn, 95 + enum ani_ed_type enc_type, 96 + u8 keyidx, 97 + u8 keylen, 98 + u8 *key); 99 + int wcn36xx_smd_remove_stakey(struct wcn36xx *wcn, 100 + enum ani_ed_type enc_type, 101 + u8 keyidx, 102 + u8 sta_index); 103 + int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn, 104 + enum ani_ed_type enc_type, 105 + u8 keyidx); 106 + int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif); 107 + int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif); 108 + int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim); 109 + int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn, 110 + struct ieee80211_vif *vif, 111 + int packet_type); 112 + int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2, 113 + u32 arg3, u32 arg4, u32 arg5); 114 + int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn); 115 + 116 + int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn, 117 + struct ieee80211_sta *sta, 118 + u16 tid, 119 + u16 *ssn, 120 + u8 direction, 121 + u8 sta_index); 122 + int wcn36xx_smd_add_ba(struct wcn36xx *wcn); 123 + int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index); 124 + int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index); 125 + 126 + int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value); 127 + #endif /* _SMD_H_ */
+284
drivers/net/wireless/ath/wcn36xx/txrx.c
··· 1 + /* 2 + * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> 3 + * 4 + * Permission to use, copy, modify, and/or distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 11 + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 13 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 14 + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + 17 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 18 + 19 + #include "txrx.h" 20 + 21 + static inline int get_rssi0(struct wcn36xx_rx_bd *bd) 22 + { 23 + return 100 - ((bd->phy_stat0 >> 24) & 0xff); 24 + } 25 + 26 + int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb) 27 + { 28 + struct ieee80211_rx_status status; 29 + struct ieee80211_hdr *hdr; 30 + struct wcn36xx_rx_bd *bd; 31 + u16 fc, sn; 32 + 33 + /* 34 + * All fields must be 0, otherwise it can lead to 35 + * unexpected consequences. 36 + */ 37 + memset(&status, 0, sizeof(status)); 38 + 39 + bd = (struct wcn36xx_rx_bd *)skb->data; 40 + buff_to_be((u32 *)bd, sizeof(*bd)/sizeof(u32)); 41 + wcn36xx_dbg_dump(WCN36XX_DBG_RX_DUMP, 42 + "BD <<< ", (char *)bd, 43 + sizeof(struct wcn36xx_rx_bd)); 44 + 45 + skb_put(skb, bd->pdu.mpdu_header_off + bd->pdu.mpdu_len); 46 + skb_pull(skb, bd->pdu.mpdu_header_off); 47 + 48 + status.mactime = 10; 49 + status.freq = WCN36XX_CENTER_FREQ(wcn); 50 + status.band = WCN36XX_BAND(wcn); 51 + status.signal = -get_rssi0(bd); 52 + status.antenna = 1; 53 + status.rate_idx = 1; 54 + status.flag = 0; 55 + status.rx_flags = 0; 56 + status.flag |= RX_FLAG_IV_STRIPPED | 57 + RX_FLAG_MMIC_STRIPPED | 58 + RX_FLAG_DECRYPTED; 59 + 60 + wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%x status->vendor_radiotap_len=%x\n", 61 + status.flag, status.vendor_radiotap_len); 62 + 63 + memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); 64 + 65 + hdr = (struct ieee80211_hdr *) skb->data; 66 + fc = __le16_to_cpu(hdr->frame_control); 67 + sn = IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl)); 68 + 69 + if (ieee80211_is_beacon(hdr->frame_control)) { 70 + wcn36xx_dbg(WCN36XX_DBG_BEACON, "beacon skb %p len %d fc %04x sn %d\n", 71 + skb, skb->len, fc, sn); 72 + wcn36xx_dbg_dump(WCN36XX_DBG_BEACON_DUMP, "SKB <<< ", 73 + (char *)skb->data, skb->len); 74 + } else { 75 + wcn36xx_dbg(WCN36XX_DBG_RX, "rx skb %p len %d fc %04x sn %d\n", 76 + skb, skb->len, fc, sn); 77 + wcn36xx_dbg_dump(WCN36XX_DBG_RX_DUMP, "SKB <<< ", 78 + (char *)skb->data, skb->len); 79 + } 80 + 81 + ieee80211_rx_irqsafe(wcn->hw, skb); 82 + 83 + return 0; 84 + } 85 + 86 + static void wcn36xx_set_tx_pdu(struct wcn36xx_tx_bd *bd, 87 + u32 mpdu_header_len, 88 + u32 len, 89 + u16 tid) 90 + { 91 + bd->pdu.mpdu_header_len = mpdu_header_len; 92 + bd->pdu.mpdu_header_off = sizeof(*bd); 93 + bd->pdu.mpdu_data_off = bd->pdu.mpdu_header_len + 94 + bd->pdu.mpdu_header_off; 95 + bd->pdu.mpdu_len = len; 96 + bd->pdu.tid = tid; 97 + } 98 + 99 + static inline struct wcn36xx_vif *get_vif_by_addr(struct wcn36xx *wcn, 100 + u8 *addr) 101 + { 102 + struct wcn36xx_vif *vif_priv = NULL; 103 + struct ieee80211_vif *vif = NULL; 104 + list_for_each_entry(vif_priv, &wcn->vif_list, list) { 105 + vif = container_of((void *)vif_priv, 106 + struct ieee80211_vif, 107 + drv_priv); 108 + if (memcmp(vif->addr, addr, ETH_ALEN) == 0) 109 + return vif_priv; 110 + } 111 + wcn36xx_warn("vif %pM not found\n", addr); 112 + return NULL; 113 + } 114 + static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd, 115 + struct wcn36xx *wcn, 116 + struct wcn36xx_vif **vif_priv, 117 + struct wcn36xx_sta *sta_priv, 118 + struct ieee80211_hdr *hdr, 119 + bool bcast) 120 + { 121 + struct ieee80211_vif *vif = NULL; 122 + struct wcn36xx_vif *__vif_priv = NULL; 123 + bd->bd_rate = WCN36XX_BD_RATE_DATA; 124 + 125 + /* 126 + * For not unicast frames mac80211 will not set sta pointer so use 127 + * self_sta_index instead. 128 + */ 129 + if (sta_priv) { 130 + __vif_priv = sta_priv->vif; 131 + vif = container_of((void *)__vif_priv, 132 + struct ieee80211_vif, 133 + drv_priv); 134 + 135 + if (vif->type == NL80211_IFTYPE_STATION) { 136 + bd->sta_index = sta_priv->bss_sta_index; 137 + bd->dpu_desc_idx = sta_priv->bss_dpu_desc_index; 138 + } else if (vif->type == NL80211_IFTYPE_AP || 139 + vif->type == NL80211_IFTYPE_ADHOC || 140 + vif->type == NL80211_IFTYPE_MESH_POINT) { 141 + bd->sta_index = sta_priv->sta_index; 142 + bd->dpu_desc_idx = sta_priv->dpu_desc_index; 143 + } 144 + } else { 145 + __vif_priv = get_vif_by_addr(wcn, hdr->addr2); 146 + bd->sta_index = __vif_priv->self_sta_index; 147 + bd->dpu_desc_idx = __vif_priv->self_dpu_desc_index; 148 + } 149 + 150 + bd->dpu_sign = __vif_priv->ucast_dpu_signature; 151 + 152 + if (ieee80211_is_nullfunc(hdr->frame_control) || 153 + (sta_priv && !sta_priv->is_data_encrypted)) 154 + bd->dpu_ne = 1; 155 + 156 + if (bcast) { 157 + bd->ub = 1; 158 + bd->ack_policy = 1; 159 + } 160 + *vif_priv = __vif_priv; 161 + } 162 + 163 + static void wcn36xx_set_tx_mgmt(struct wcn36xx_tx_bd *bd, 164 + struct wcn36xx *wcn, 165 + struct wcn36xx_vif **vif_priv, 166 + struct ieee80211_hdr *hdr, 167 + bool bcast) 168 + { 169 + struct wcn36xx_vif *__vif_priv = 170 + get_vif_by_addr(wcn, hdr->addr2); 171 + bd->sta_index = __vif_priv->self_sta_index; 172 + bd->dpu_desc_idx = __vif_priv->self_dpu_desc_index; 173 + bd->dpu_ne = 1; 174 + 175 + /* default rate for unicast */ 176 + if (ieee80211_is_mgmt(hdr->frame_control)) 177 + bd->bd_rate = (WCN36XX_BAND(wcn) == IEEE80211_BAND_5GHZ) ? 178 + WCN36XX_BD_RATE_CTRL : 179 + WCN36XX_BD_RATE_MGMT; 180 + else if (ieee80211_is_ctl(hdr->frame_control)) 181 + bd->bd_rate = WCN36XX_BD_RATE_CTRL; 182 + else 183 + wcn36xx_warn("frame control type unknown\n"); 184 + 185 + /* 186 + * In joining state trick hardware that probe is sent as 187 + * unicast even if address is broadcast. 188 + */ 189 + if (__vif_priv->is_joining && 190 + ieee80211_is_probe_req(hdr->frame_control)) 191 + bcast = false; 192 + 193 + if (bcast) { 194 + /* broadcast */ 195 + bd->ub = 1; 196 + /* No ack needed not unicast */ 197 + bd->ack_policy = 1; 198 + bd->queue_id = WCN36XX_TX_B_WQ_ID; 199 + } else 200 + bd->queue_id = WCN36XX_TX_U_WQ_ID; 201 + *vif_priv = __vif_priv; 202 + } 203 + 204 + int wcn36xx_start_tx(struct wcn36xx *wcn, 205 + struct wcn36xx_sta *sta_priv, 206 + struct sk_buff *skb) 207 + { 208 + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 209 + struct wcn36xx_vif *vif_priv = NULL; 210 + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 211 + unsigned long flags; 212 + bool is_low = ieee80211_is_data(hdr->frame_control); 213 + bool bcast = is_broadcast_ether_addr(hdr->addr1) || 214 + is_multicast_ether_addr(hdr->addr1); 215 + struct wcn36xx_tx_bd *bd = wcn36xx_dxe_get_next_bd(wcn, is_low); 216 + 217 + if (!bd) { 218 + /* 219 + * TX DXE are used in pairs. One for the BD and one for the 220 + * actual frame. The BD DXE's has a preallocated buffer while 221 + * the skb ones does not. If this isn't true something is really 222 + * wierd. TODO: Recover from this situation 223 + */ 224 + 225 + wcn36xx_err("bd address may not be NULL for BD DXE\n"); 226 + return -EINVAL; 227 + } 228 + 229 + memset(bd, 0, sizeof(*bd)); 230 + 231 + wcn36xx_dbg(WCN36XX_DBG_TX, 232 + "tx skb %p len %d fc %04x sn %d %s %s\n", 233 + skb, skb->len, __le16_to_cpu(hdr->frame_control), 234 + IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl)), 235 + is_low ? "low" : "high", bcast ? "bcast" : "ucast"); 236 + 237 + wcn36xx_dbg_dump(WCN36XX_DBG_TX_DUMP, "", skb->data, skb->len); 238 + 239 + bd->dpu_rf = WCN36XX_BMU_WQ_TX; 240 + 241 + bd->tx_comp = info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS; 242 + if (bd->tx_comp) { 243 + wcn36xx_dbg(WCN36XX_DBG_DXE, "TX_ACK status requested\n"); 244 + spin_lock_irqsave(&wcn->dxe_lock, flags); 245 + if (wcn->tx_ack_skb) { 246 + spin_unlock_irqrestore(&wcn->dxe_lock, flags); 247 + wcn36xx_warn("tx_ack_skb already set\n"); 248 + return -EINVAL; 249 + } 250 + 251 + wcn->tx_ack_skb = skb; 252 + spin_unlock_irqrestore(&wcn->dxe_lock, flags); 253 + 254 + /* Only one at a time is supported by fw. Stop the TX queues 255 + * until the ack status gets back. 256 + * 257 + * TODO: Add watchdog in case FW does not answer 258 + */ 259 + ieee80211_stop_queues(wcn->hw); 260 + } 261 + 262 + /* Data frames served first*/ 263 + if (is_low) { 264 + wcn36xx_set_tx_data(bd, wcn, &vif_priv, sta_priv, hdr, bcast); 265 + wcn36xx_set_tx_pdu(bd, 266 + ieee80211_is_data_qos(hdr->frame_control) ? 267 + sizeof(struct ieee80211_qos_hdr) : 268 + sizeof(struct ieee80211_hdr_3addr), 269 + skb->len, sta_priv ? sta_priv->tid : 0); 270 + } else { 271 + /* MGMT and CTRL frames are handeld here*/ 272 + wcn36xx_set_tx_mgmt(bd, wcn, &vif_priv, hdr, bcast); 273 + wcn36xx_set_tx_pdu(bd, 274 + ieee80211_is_data_qos(hdr->frame_control) ? 275 + sizeof(struct ieee80211_qos_hdr) : 276 + sizeof(struct ieee80211_hdr_3addr), 277 + skb->len, WCN36XX_TID); 278 + } 279 + 280 + buff_to_be((u32 *)bd, sizeof(*bd)/sizeof(u32)); 281 + bd->tx_bd_sign = 0xbdbdbdbd; 282 + 283 + return wcn36xx_dxe_tx_frame(wcn, vif_priv, skb, is_low); 284 + }
+160
drivers/net/wireless/ath/wcn36xx/txrx.h
··· 1 + /* 2 + * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> 3 + * 4 + * Permission to use, copy, modify, and/or distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 11 + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 13 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 14 + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + 17 + #ifndef _TXRX_H_ 18 + #define _TXRX_H_ 19 + 20 + #include <linux/etherdevice.h> 21 + #include "wcn36xx.h" 22 + 23 + /* TODO describe all properties */ 24 + #define WCN36XX_802_11_HEADER_LEN 24 25 + #define WCN36XX_BMU_WQ_TX 25 26 + #define WCN36XX_TID 7 27 + /* broadcast wq ID */ 28 + #define WCN36XX_TX_B_WQ_ID 0xA 29 + #define WCN36XX_TX_U_WQ_ID 0x9 30 + /* bd_rate */ 31 + #define WCN36XX_BD_RATE_DATA 0 32 + #define WCN36XX_BD_RATE_MGMT 2 33 + #define WCN36XX_BD_RATE_CTRL 3 34 + 35 + struct wcn36xx_pdu { 36 + u32 dpu_fb:8; 37 + u32 adu_fb:8; 38 + u32 pdu_id:16; 39 + 40 + /* 0x04*/ 41 + u32 tail_pdu_idx:16; 42 + u32 head_pdu_idx:16; 43 + 44 + /* 0x08*/ 45 + u32 pdu_count:7; 46 + u32 mpdu_data_off:9; 47 + u32 mpdu_header_off:8; 48 + u32 mpdu_header_len:8; 49 + 50 + /* 0x0c*/ 51 + u32 reserved4:8; 52 + u32 tid:4; 53 + u32 reserved3:4; 54 + u32 mpdu_len:16; 55 + }; 56 + 57 + struct wcn36xx_rx_bd { 58 + u32 bdt:2; 59 + u32 ft:1; 60 + u32 dpu_ne:1; 61 + u32 rx_key_id:3; 62 + u32 ub:1; 63 + u32 rmf:1; 64 + u32 uma_bypass:1; 65 + u32 csr11:1; 66 + u32 reserved0:1; 67 + u32 scan_learn:1; 68 + u32 rx_ch:4; 69 + u32 rtsf:1; 70 + u32 bsf:1; 71 + u32 a2hf:1; 72 + u32 st_auf:1; 73 + u32 dpu_sign:3; 74 + u32 dpu_rf:8; 75 + 76 + struct wcn36xx_pdu pdu; 77 + 78 + /* 0x14*/ 79 + u32 addr3:8; 80 + u32 addr2:8; 81 + u32 addr1:8; 82 + u32 dpu_desc_idx:8; 83 + 84 + /* 0x18*/ 85 + u32 rxp_flags:23; 86 + u32 rate_id:9; 87 + 88 + u32 phy_stat0; 89 + u32 phy_stat1; 90 + 91 + /* 0x24 */ 92 + u32 rx_times; 93 + 94 + u32 pmi_cmd[6]; 95 + 96 + /* 0x40 */ 97 + u32 reserved7:4; 98 + u32 reorder_slot_id:6; 99 + u32 reorder_fwd_id:6; 100 + u32 reserved6:12; 101 + u32 reorder_code:4; 102 + 103 + /* 0x44 */ 104 + u32 exp_seq_num:12; 105 + u32 cur_seq_num:12; 106 + u32 fr_type_subtype:8; 107 + 108 + /* 0x48 */ 109 + u32 msdu_size:16; 110 + u32 sub_fr_id:4; 111 + u32 proc_order:4; 112 + u32 reserved9:4; 113 + u32 aef:1; 114 + u32 lsf:1; 115 + u32 esf:1; 116 + u32 asf:1; 117 + }; 118 + 119 + struct wcn36xx_tx_bd { 120 + u32 bdt:2; 121 + u32 ft:1; 122 + u32 dpu_ne:1; 123 + u32 fw_tx_comp:1; 124 + u32 tx_comp:1; 125 + u32 reserved1:1; 126 + u32 ub:1; 127 + u32 rmf:1; 128 + u32 reserved0:12; 129 + u32 dpu_sign:3; 130 + u32 dpu_rf:8; 131 + 132 + struct wcn36xx_pdu pdu; 133 + 134 + /* 0x14*/ 135 + u32 reserved5:7; 136 + u32 queue_id:5; 137 + u32 bd_rate:2; 138 + u32 ack_policy:2; 139 + u32 sta_index:8; 140 + u32 dpu_desc_idx:8; 141 + 142 + u32 tx_bd_sign; 143 + u32 reserved6; 144 + u32 dxe_start_time; 145 + u32 dxe_end_time; 146 + 147 + /*u32 tcp_udp_start_off:10; 148 + u32 header_cks:16; 149 + u32 reserved7:6;*/ 150 + }; 151 + 152 + struct wcn36xx_sta; 153 + struct wcn36xx; 154 + 155 + int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb); 156 + int wcn36xx_start_tx(struct wcn36xx *wcn, 157 + struct wcn36xx_sta *sta_priv, 158 + struct sk_buff *skb); 159 + 160 + #endif /* _TXRX_H_ */
+238
drivers/net/wireless/ath/wcn36xx/wcn36xx.h
··· 1 + /* 2 + * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> 3 + * 4 + * Permission to use, copy, modify, and/or distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 11 + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 13 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 14 + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + 17 + #ifndef _WCN36XX_H_ 18 + #define _WCN36XX_H_ 19 + 20 + #include <linux/completion.h> 21 + #include <linux/printk.h> 22 + #include <linux/spinlock.h> 23 + #include <net/mac80211.h> 24 + 25 + #include "hal.h" 26 + #include "smd.h" 27 + #include "txrx.h" 28 + #include "dxe.h" 29 + #include "pmc.h" 30 + #include "debug.h" 31 + 32 + #define WLAN_NV_FILE "wlan/prima/WCNSS_qcom_wlan_nv.bin" 33 + #define WCN36XX_AGGR_BUFFER_SIZE 64 34 + 35 + extern unsigned int wcn36xx_dbg_mask; 36 + 37 + enum wcn36xx_debug_mask { 38 + WCN36XX_DBG_DXE = 0x00000001, 39 + WCN36XX_DBG_DXE_DUMP = 0x00000002, 40 + WCN36XX_DBG_SMD = 0x00000004, 41 + WCN36XX_DBG_SMD_DUMP = 0x00000008, 42 + WCN36XX_DBG_RX = 0x00000010, 43 + WCN36XX_DBG_RX_DUMP = 0x00000020, 44 + WCN36XX_DBG_TX = 0x00000040, 45 + WCN36XX_DBG_TX_DUMP = 0x00000080, 46 + WCN36XX_DBG_HAL = 0x00000100, 47 + WCN36XX_DBG_HAL_DUMP = 0x00000200, 48 + WCN36XX_DBG_MAC = 0x00000400, 49 + WCN36XX_DBG_BEACON = 0x00000800, 50 + WCN36XX_DBG_BEACON_DUMP = 0x00001000, 51 + WCN36XX_DBG_PMC = 0x00002000, 52 + WCN36XX_DBG_PMC_DUMP = 0x00004000, 53 + WCN36XX_DBG_ANY = 0xffffffff, 54 + }; 55 + 56 + #define wcn36xx_err(fmt, arg...) \ 57 + printk(KERN_ERR pr_fmt("ERROR " fmt), ##arg); 58 + 59 + #define wcn36xx_warn(fmt, arg...) \ 60 + printk(KERN_WARNING pr_fmt("WARNING " fmt), ##arg) 61 + 62 + #define wcn36xx_info(fmt, arg...) \ 63 + printk(KERN_INFO pr_fmt(fmt), ##arg) 64 + 65 + #define wcn36xx_dbg(mask, fmt, arg...) do { \ 66 + if (wcn36xx_dbg_mask & mask) \ 67 + printk(KERN_DEBUG pr_fmt(fmt), ##arg); \ 68 + } while (0) 69 + 70 + #define wcn36xx_dbg_dump(mask, prefix_str, buf, len) do { \ 71 + if (wcn36xx_dbg_mask & mask) \ 72 + print_hex_dump(KERN_DEBUG, pr_fmt(prefix_str), \ 73 + DUMP_PREFIX_OFFSET, 32, 1, \ 74 + buf, len, false); \ 75 + } while (0) 76 + 77 + #define WCN36XX_HW_CHANNEL(__wcn) (__wcn->hw->conf.chandef.chan->hw_value) 78 + #define WCN36XX_BAND(__wcn) (__wcn->hw->conf.chandef.chan->band) 79 + #define WCN36XX_CENTER_FREQ(__wcn) (__wcn->hw->conf.chandef.chan->center_freq) 80 + #define WCN36XX_LISTEN_INTERVAL(__wcn) (__wcn->hw->conf.listen_interval) 81 + #define WCN36XX_FLAGS(__wcn) (__wcn->hw->flags) 82 + #define WCN36XX_MAX_POWER(__wcn) (__wcn->hw->conf.chandef.chan->max_power) 83 + 84 + static inline void buff_to_be(u32 *buf, size_t len) 85 + { 86 + int i; 87 + for (i = 0; i < len; i++) 88 + buf[i] = cpu_to_be32(buf[i]); 89 + } 90 + 91 + struct nv_data { 92 + int is_valid; 93 + u8 table; 94 + }; 95 + 96 + /* Interface for platform control path 97 + * 98 + * @open: hook must be called when wcn36xx wants to open control channel. 99 + * @tx: sends a buffer. 100 + */ 101 + struct wcn36xx_platform_ctrl_ops { 102 + int (*open)(void *drv_priv, void *rsp_cb); 103 + void (*close)(void); 104 + int (*tx)(char *buf, size_t len); 105 + int (*get_hw_mac)(u8 *addr); 106 + int (*smsm_change_state)(u32 clear_mask, u32 set_mask); 107 + }; 108 + 109 + /** 110 + * struct wcn36xx_vif - holds VIF related fields 111 + * 112 + * @bss_index: bss_index is initially set to 0xFF. bss_index is received from 113 + * HW after first config_bss call and must be used in delete_bss and 114 + * enter/exit_bmps. 115 + */ 116 + struct wcn36xx_vif { 117 + struct list_head list; 118 + struct wcn36xx_sta *sta; 119 + u8 dtim_period; 120 + enum ani_ed_type encrypt_type; 121 + bool is_joining; 122 + struct wcn36xx_hal_mac_ssid ssid; 123 + 124 + /* Power management */ 125 + enum wcn36xx_power_state pw_state; 126 + 127 + u8 bss_index; 128 + u8 ucast_dpu_signature; 129 + /* Returned from WCN36XX_HAL_ADD_STA_SELF_RSP */ 130 + u8 self_sta_index; 131 + u8 self_dpu_desc_index; 132 + }; 133 + 134 + /** 135 + * struct wcn36xx_sta - holds STA related fields 136 + * 137 + * @tid: traffic ID that is used during AMPDU and in TX BD. 138 + * @sta_index: STA index is returned from HW after config_sta call and is 139 + * used in both SMD channel and TX BD. 140 + * @dpu_desc_index: DPU descriptor index is returned from HW after config_sta 141 + * call and is used in TX BD. 142 + * @bss_sta_index: STA index is returned from HW after config_bss call and is 143 + * used in both SMD channel and TX BD. See table bellow when it is used. 144 + * @bss_dpu_desc_index: DPU descriptor index is returned from HW after 145 + * config_bss call and is used in TX BD. 146 + * ______________________________________________ 147 + * | | STA | AP | 148 + * |______________|_____________|_______________| 149 + * | TX BD |bss_sta_index| sta_index | 150 + * |______________|_____________|_______________| 151 + * |all SMD calls |bss_sta_index| sta_index | 152 + * |______________|_____________|_______________| 153 + * |smd_delete_sta| sta_index | sta_index | 154 + * |______________|_____________|_______________| 155 + */ 156 + struct wcn36xx_sta { 157 + struct wcn36xx_vif *vif; 158 + u16 aid; 159 + u16 tid; 160 + u8 sta_index; 161 + u8 dpu_desc_index; 162 + u8 bss_sta_index; 163 + u8 bss_dpu_desc_index; 164 + bool is_data_encrypted; 165 + /* Rates */ 166 + struct wcn36xx_hal_supported_rates supported_rates; 167 + }; 168 + struct wcn36xx_dxe_ch; 169 + struct wcn36xx { 170 + struct ieee80211_hw *hw; 171 + struct device *dev; 172 + struct list_head vif_list; 173 + 174 + u8 fw_revision; 175 + u8 fw_version; 176 + u8 fw_minor; 177 + u8 fw_major; 178 + 179 + /* extra byte for the NULL termination */ 180 + u8 crm_version[WCN36XX_HAL_VERSION_LENGTH + 1]; 181 + u8 wlan_version[WCN36XX_HAL_VERSION_LENGTH + 1]; 182 + 183 + /* IRQs */ 184 + int tx_irq; 185 + int rx_irq; 186 + void __iomem *mmio; 187 + 188 + struct wcn36xx_platform_ctrl_ops *ctrl_ops; 189 + /* 190 + * smd_buf must be protected with smd_mutex to garantee 191 + * that all messages are sent one after another 192 + */ 193 + u8 *hal_buf; 194 + size_t hal_rsp_len; 195 + struct mutex hal_mutex; 196 + struct completion hal_rsp_compl; 197 + struct workqueue_struct *hal_ind_wq; 198 + struct work_struct hal_ind_work; 199 + struct mutex hal_ind_mutex; 200 + struct list_head hal_ind_queue; 201 + 202 + /* DXE channels */ 203 + struct wcn36xx_dxe_ch dxe_tx_l_ch; /* TX low */ 204 + struct wcn36xx_dxe_ch dxe_tx_h_ch; /* TX high */ 205 + struct wcn36xx_dxe_ch dxe_rx_l_ch; /* RX low */ 206 + struct wcn36xx_dxe_ch dxe_rx_h_ch; /* RX high */ 207 + 208 + /* For synchronization of DXE resources from BH, IRQ and WQ contexts */ 209 + spinlock_t dxe_lock; 210 + bool queues_stopped; 211 + 212 + /* Memory pools */ 213 + struct wcn36xx_dxe_mem_pool mgmt_mem_pool; 214 + struct wcn36xx_dxe_mem_pool data_mem_pool; 215 + 216 + struct sk_buff *tx_ack_skb; 217 + 218 + #ifdef CONFIG_WCN36XX_DEBUGFS 219 + /* Debug file system entry */ 220 + struct wcn36xx_dfs_entry dfs; 221 + #endif /* CONFIG_WCN36XX_DEBUGFS */ 222 + 223 + }; 224 + 225 + static inline bool wcn36xx_is_fw_version(struct wcn36xx *wcn, 226 + u8 major, 227 + u8 minor, 228 + u8 version, 229 + u8 revision) 230 + { 231 + return (wcn->fw_major == major && 232 + wcn->fw_minor == minor && 233 + wcn->fw_version == version && 234 + wcn->fw_revision == revision); 235 + } 236 + void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates); 237 + 238 + #endif /* _WCN36XX_H_ */
+1 -1
drivers/net/wireless/brcm80211/brcmsmac/main.c
··· 5695 5695 return true; 5696 5696 if ((device == BCM43224_D11N_ID) || (device == BCM43225_D11N2G_ID)) 5697 5697 return true; 5698 - if (device == BCM4313_D11N2G_ID) 5698 + if (device == BCM4313_D11N2G_ID || device == BCM4313_CHIP_ID) 5699 5699 return true; 5700 5700 if ((device == BCM43236_D11N_ID) || (device == BCM43236_D11N2G_ID)) 5701 5701 return true;
+1 -1
drivers/net/wireless/mwifiex/cmdevt.c
··· 1048 1048 struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; 1049 1049 unsigned long cmd_flags; 1050 1050 unsigned long scan_pending_q_flags; 1051 - uint16_t cancel_scan_cmd = false; 1051 + bool cancel_scan_cmd = false; 1052 1052 1053 1053 if ((adapter->curr_cmd) && 1054 1054 (adapter->curr_cmd->wait_q_enabled)) {
+1 -1
drivers/net/wireless/mwifiex/join.c
··· 621 621 int ret = 0; 622 622 struct ieee_types_assoc_rsp *assoc_rsp; 623 623 struct mwifiex_bssdescriptor *bss_desc; 624 - u8 enable_data = true; 624 + bool enable_data = true; 625 625 u16 cap_info, status_code; 626 626 627 627 assoc_rsp = (struct ieee_types_assoc_rsp *) &resp->params;
+3 -1
drivers/net/wireless/mwifiex/main.c
··· 882 882 adapter->cmd_wait_q.status = 0; 883 883 adapter->scan_wait_q_woken = false; 884 884 885 - adapter->workqueue = create_workqueue("MWIFIEX_WORK_QUEUE"); 885 + adapter->workqueue = 886 + alloc_workqueue("MWIFIEX_WORK_QUEUE", 887 + WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1); 886 888 if (!adapter->workqueue) 887 889 goto err_kmalloc; 888 890
+1 -1
drivers/net/wireless/mwifiex/sta_cmd.c
··· 327 327 { 328 328 struct mwifiex_adapter *adapter = priv->adapter; 329 329 struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = &cmd->params.opt_hs_cfg; 330 - u16 hs_activate = false; 330 + bool hs_activate = false; 331 331 332 332 if (!hscfg_param) 333 333 /* New Activate command */
+1 -1
drivers/net/wireless/mwifiex/wmm.c
··· 708 708 { 709 709 u8 *curr = (u8 *) &resp->params.get_wmm_status; 710 710 uint16_t resp_len = le16_to_cpu(resp->size), tlv_len; 711 - int valid = true; 711 + bool valid = true; 712 712 713 713 struct mwifiex_ie_types_data *tlv_hdr; 714 714 struct mwifiex_ie_types_wmm_queue_status *tlv_wmm_qstatus;
+1 -1
drivers/net/wireless/p54/p54spi.c
··· 636 636 gpio_direction_input(p54spi_gpio_irq); 637 637 638 638 ret = request_irq(gpio_to_irq(p54spi_gpio_irq), 639 - p54spi_interrupt, IRQF_DISABLED, "p54spi", 639 + p54spi_interrupt, 0, "p54spi", 640 640 priv->spi); 641 641 if (ret < 0) { 642 642 dev_err(&priv->spi->dev, "request_irq() failed");
+1
drivers/net/wireless/rt2x00/Kconfig
··· 219 219 220 220 config RT2X00_LIB 221 221 tristate 222 + select AVERAGE 222 223 223 224 config RT2X00_LIB_FIRMWARE 224 225 boolean
+21 -21
drivers/net/wireless/rt2x00/rt2800.h
··· 124 124 /* 125 125 * MAC_CSR0_3290: MAC_CSR0 for RT3290 to identity MAC version number. 126 126 */ 127 - #define MAC_CSR0_3290 0x0000 127 + #define MAC_CSR0_3290 0x0000 128 128 129 129 /* 130 130 * E2PROM_CSR: PCI EEPROM control register. ··· 213 213 /* 214 214 * COEX_CFG_0 215 215 */ 216 - #define COEX_CFG0 0x0040 216 + #define COEX_CFG0 0x0040 217 217 #define COEX_CFG_ANT FIELD32(0xff000000) 218 218 /* 219 219 * COEX_CFG_1 220 220 */ 221 - #define COEX_CFG1 0x0044 221 + #define COEX_CFG1 0x0044 222 222 223 223 /* 224 224 * COEX_CFG_2 225 225 */ 226 - #define COEX_CFG2 0x0048 226 + #define COEX_CFG2 0x0048 227 227 #define BT_COEX_CFG1 FIELD32(0xff000000) 228 228 #define BT_COEX_CFG0 FIELD32(0x00ff0000) 229 229 #define WL_COEX_CFG1 FIELD32(0x0000ff00) ··· 237 237 #define PLL_RESERVED_INPUT2 FIELD32(0x0000ff00) 238 238 #define PLL_CONTROL FIELD32(0x00070000) 239 239 #define PLL_LPF_R1 FIELD32(0x00080000) 240 - #define PLL_LPF_C1_CTRL FIELD32(0x00300000) 241 - #define PLL_LPF_C2_CTRL FIELD32(0x00c00000) 240 + #define PLL_LPF_C1_CTRL FIELD32(0x00300000) 241 + #define PLL_LPF_C2_CTRL FIELD32(0x00c00000) 242 242 #define PLL_CP_CURRENT_CTRL FIELD32(0x03000000) 243 243 #define PLL_PFD_DELAY_CTRL FIELD32(0x0c000000) 244 244 #define PLL_LOCK_CTRL FIELD32(0x70000000) ··· 2166 2166 */ 2167 2167 #define RFCSR6_R1 FIELD8(0x03) 2168 2168 #define RFCSR6_R2 FIELD8(0x40) 2169 - #define RFCSR6_TXDIV FIELD8(0x0c) 2169 + #define RFCSR6_TXDIV FIELD8(0x0c) 2170 2170 /* bits for RF3053 */ 2171 2171 #define RFCSR6_VCO_IC FIELD8(0xc0) 2172 2172 ··· 2204 2204 * RFCSR 12: 2205 2205 */ 2206 2206 #define RFCSR12_TX_POWER FIELD8(0x1f) 2207 - #define RFCSR12_DR0 FIELD8(0xe0) 2207 + #define RFCSR12_DR0 FIELD8(0xe0) 2208 2208 2209 2209 /* 2210 2210 * RFCSR 13: 2211 2211 */ 2212 2212 #define RFCSR13_TX_POWER FIELD8(0x1f) 2213 - #define RFCSR13_DR0 FIELD8(0xe0) 2213 + #define RFCSR13_DR0 FIELD8(0xe0) 2214 2214 2215 2215 /* 2216 2216 * RFCSR 15: ··· 2228 2228 #define RFCSR17_TXMIXER_GAIN FIELD8(0x07) 2229 2229 #define RFCSR17_TX_LO1_EN FIELD8(0x08) 2230 2230 #define RFCSR17_R FIELD8(0x20) 2231 - #define RFCSR17_CODE FIELD8(0x7f) 2231 + #define RFCSR17_CODE FIELD8(0x7f) 2232 2232 2233 2233 /* RFCSR 18 */ 2234 2234 #define RFCSR18_XO_TUNE_BYPASS FIELD8(0x40) ··· 2451 2451 */ 2452 2452 #define EEPROM_NIC_CONF0_RXPATH FIELD16(0x000f) 2453 2453 #define EEPROM_NIC_CONF0_TXPATH FIELD16(0x00f0) 2454 - #define EEPROM_NIC_CONF0_RF_TYPE FIELD16(0x0f00) 2454 + #define EEPROM_NIC_CONF0_RF_TYPE FIELD16(0x0f00) 2455 2455 2456 2456 /* 2457 2457 * EEPROM NIC Configuration 1 ··· 2473 2473 * DAC_TEST: 0: disable, 1: enable 2474 2474 */ 2475 2475 #define EEPROM_NIC_CONF1_HW_RADIO FIELD16(0x0001) 2476 - #define EEPROM_NIC_CONF1_EXTERNAL_TX_ALC FIELD16(0x0002) 2477 - #define EEPROM_NIC_CONF1_EXTERNAL_LNA_2G FIELD16(0x0004) 2478 - #define EEPROM_NIC_CONF1_EXTERNAL_LNA_5G FIELD16(0x0008) 2476 + #define EEPROM_NIC_CONF1_EXTERNAL_TX_ALC FIELD16(0x0002) 2477 + #define EEPROM_NIC_CONF1_EXTERNAL_LNA_2G FIELD16(0x0004) 2478 + #define EEPROM_NIC_CONF1_EXTERNAL_LNA_5G FIELD16(0x0008) 2479 2479 #define EEPROM_NIC_CONF1_CARDBUS_ACCEL FIELD16(0x0010) 2480 2480 #define EEPROM_NIC_CONF1_BW40M_SB_2G FIELD16(0x0020) 2481 2481 #define EEPROM_NIC_CONF1_BW40M_SB_5G FIELD16(0x0040) 2482 2482 #define EEPROM_NIC_CONF1_WPS_PBC FIELD16(0x0080) 2483 2483 #define EEPROM_NIC_CONF1_BW40M_2G FIELD16(0x0100) 2484 2484 #define EEPROM_NIC_CONF1_BW40M_5G FIELD16(0x0200) 2485 - #define EEPROM_NIC_CONF1_BROADBAND_EXT_LNA FIELD16(0x400) 2485 + #define EEPROM_NIC_CONF1_BROADBAND_EXT_LNA FIELD16(0x400) 2486 2486 #define EEPROM_NIC_CONF1_ANT_DIVERSITY FIELD16(0x1800) 2487 - #define EEPROM_NIC_CONF1_INTERNAL_TX_ALC FIELD16(0x2000) 2487 + #define EEPROM_NIC_CONF1_INTERNAL_TX_ALC FIELD16(0x2000) 2488 2488 #define EEPROM_NIC_CONF1_BT_COEXIST FIELD16(0x4000) 2489 2489 #define EEPROM_NIC_CONF1_DAC_TEST FIELD16(0x8000) 2490 2490 ··· 2523 2523 * TX_STREAM: 0: Reserved, 1: 1 Stream, 2: 2 Stream 2524 2524 * CRYSTAL: 00: Reserved, 01: One crystal, 10: Two crystal, 11: Reserved 2525 2525 */ 2526 - #define EEPROM_NIC_CONF2_RX_STREAM FIELD16(0x000f) 2527 - #define EEPROM_NIC_CONF2_TX_STREAM FIELD16(0x00f0) 2528 - #define EEPROM_NIC_CONF2_CRYSTAL FIELD16(0x0600) 2526 + #define EEPROM_NIC_CONF2_RX_STREAM FIELD16(0x000f) 2527 + #define EEPROM_NIC_CONF2_TX_STREAM FIELD16(0x00f0) 2528 + #define EEPROM_NIC_CONF2_CRYSTAL FIELD16(0x0600) 2529 2529 2530 2530 /* 2531 2531 * EEPROM LNA ··· 2792 2792 #define MCU_CURRENT 0x36 2793 2793 #define MCU_LED 0x50 2794 2794 #define MCU_LED_STRENGTH 0x51 2795 - #define MCU_LED_AG_CONF 0x52 2795 + #define MCU_LED_AG_CONF 0x52 2796 2796 #define MCU_LED_ACT_CONF 0x53 2797 2797 #define MCU_LED_LED_POLARITY 0x54 2798 2798 #define MCU_RADAR 0x60 ··· 2801 2801 #define MCU_FREQ_OFFSET 0x74 2802 2802 #define MCU_BBP_SIGNAL 0x80 2803 2803 #define MCU_POWER_SAVE 0x83 2804 - #define MCU_BAND_SELECT 0x91 2804 + #define MCU_BAND_SELECT 0x91 2805 2805 2806 2806 /* 2807 2807 * MCU mailbox tokens
+63 -110
drivers/net/wireless/rt2x00/rt2800lib.c
··· 278 278 [EEPROM_LNA] = 0x0026, 279 279 [EEPROM_EXT_LNA2] = 0x0027, 280 280 [EEPROM_RSSI_BG] = 0x0028, 281 - [EEPROM_TXPOWER_DELTA] = 0x0028, /* Overlaps with RSSI_BG */ 282 281 [EEPROM_RSSI_BG2] = 0x0029, 283 - [EEPROM_TXMIXER_GAIN_BG] = 0x0029, /* Overlaps with RSSI_BG2 */ 284 282 [EEPROM_RSSI_A] = 0x002a, 285 283 [EEPROM_RSSI_A2] = 0x002b, 286 - [EEPROM_TXMIXER_GAIN_A] = 0x002b, /* Overlaps with RSSI_A2 */ 287 284 [EEPROM_TXPOWER_BG1] = 0x0030, 288 285 [EEPROM_TXPOWER_BG2] = 0x0037, 289 286 [EEPROM_EXT_TXPOWER_BG3] = 0x003e, ··· 1780 1783 rt2800_bbp_read(rt2x00dev, 3, &r3); 1781 1784 1782 1785 if (rt2x00_rt(rt2x00dev, RT3572) && 1783 - test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) 1786 + rt2x00_has_cap_bt_coexist(rt2x00dev)) 1784 1787 rt2800_config_3572bt_ant(rt2x00dev); 1785 1788 1786 1789 /* ··· 1792 1795 break; 1793 1796 case 2: 1794 1797 if (rt2x00_rt(rt2x00dev, RT3572) && 1795 - test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) 1798 + rt2x00_has_cap_bt_coexist(rt2x00dev)) 1796 1799 rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 1); 1797 1800 else 1798 1801 rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); ··· 1822 1825 break; 1823 1826 case 2: 1824 1827 if (rt2x00_rt(rt2x00dev, RT3572) && 1825 - test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { 1828 + rt2x00_has_cap_bt_coexist(rt2x00dev)) { 1826 1829 rt2x00_set_field8(&r3, BBP3_RX_ADC, 1); 1827 1830 rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1828 1831 rt2x00dev->curr_band == IEEE80211_BAND_5GHZ); ··· 2026 2029 rt2x00dev->default_ant.tx_chain_num <= 2); 2027 2030 rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); 2028 2031 2029 - rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); 2030 - rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1); 2031 - rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); 2032 - msleep(1); 2033 - rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); 2034 - rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); 2035 - 2036 2032 rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); 2037 2033 rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); 2038 2034 rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); ··· 2131 2141 rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); 2132 2142 rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); 2133 2143 rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); 2134 - if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { 2144 + if (rt2x00_has_cap_bt_coexist(rt2x00dev)) { 2135 2145 if (rf->channel <= 14) { 2136 2146 rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); 2137 2147 rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); ··· 2664 2674 if (rf->channel <= 14) { 2665 2675 int idx = rf->channel-1; 2666 2676 2667 - if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { 2677 + if (rt2x00_has_cap_bt_coexist(rt2x00dev)) { 2668 2678 if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) { 2669 2679 /* r55/r59 value array of channel 1~14 */ 2670 2680 static const char r55_bt_rev[] = {0x83, 0x83, ··· 3210 3220 if (rf->channel <= 14) { 3211 3221 if (!rt2x00_rt(rt2x00dev, RT5390) && 3212 3222 !rt2x00_rt(rt2x00dev, RT5392)) { 3213 - if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, 3214 - &rt2x00dev->cap_flags)) { 3223 + if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { 3215 3224 rt2800_bbp_write(rt2x00dev, 82, 0x62); 3216 3225 rt2800_bbp_write(rt2x00dev, 75, 0x46); 3217 3226 } else { ··· 3235 3246 if (rt2x00_rt(rt2x00dev, RT3593)) 3236 3247 rt2800_bbp_write(rt2x00dev, 83, 0x9a); 3237 3248 3238 - if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) 3249 + if (rt2x00_has_cap_external_lna_a(rt2x00dev)) 3239 3250 rt2800_bbp_write(rt2x00dev, 75, 0x46); 3240 3251 else 3241 3252 rt2800_bbp_write(rt2x00dev, 75, 0x50); ··· 3271 3282 /* Turn on primary PAs */ 3272 3283 rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, 3273 3284 rf->channel > 14); 3274 - if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) 3285 + if (rt2x00_has_cap_bt_coexist(rt2x00dev)) 3275 3286 rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1); 3276 3287 else 3277 3288 rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, ··· 3302 3313 3303 3314 rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); 3304 3315 3305 - if (rt2x00_rt(rt2x00dev, RT3572)) 3316 + if (rt2x00_rt(rt2x00dev, RT3572)) { 3306 3317 rt2800_rfcsr_write(rt2x00dev, 8, 0x80); 3318 + 3319 + /* AGC init */ 3320 + if (rf->channel <= 14) 3321 + reg = 0x1c + (2 * rt2x00dev->lna_gain); 3322 + else 3323 + reg = 0x22 + ((rt2x00dev->lna_gain * 5) / 3); 3324 + 3325 + rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg); 3326 + } 3307 3327 3308 3328 if (rt2x00_rt(rt2x00dev, RT3593)) { 3309 3329 rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg); ··· 3573 3575 { 3574 3576 int delta; 3575 3577 3576 - if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) 3578 + if (rt2x00_has_cap_power_limit(rt2x00dev)) 3577 3579 return 0; 3578 3580 3579 3581 /* ··· 3602 3604 if (rt2x00_rt(rt2x00dev, RT3593)) 3603 3605 return min_t(u8, txpower, 0xc); 3604 3606 3605 - if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) { 3607 + if (rt2x00_has_cap_power_limit(rt2x00dev)) { 3606 3608 /* 3607 3609 * Check if eirp txpower exceed txpower_limit. 3608 3610 * We use OFDM 6M as criterion and its eirp txpower ··· 4414 4416 rt2x00_rt(rt2x00dev, RT3290) || 4415 4417 rt2x00_rt(rt2x00dev, RT3390) || 4416 4418 rt2x00_rt(rt2x00dev, RT3572) || 4419 + rt2x00_rt(rt2x00dev, RT3593) || 4417 4420 rt2x00_rt(rt2x00dev, RT5390) || 4418 4421 rt2x00_rt(rt2x00dev, RT5392) || 4419 4422 rt2x00_rt(rt2x00dev, RT5592)) ··· 4422 4423 else 4423 4424 vgc = 0x2e + rt2x00dev->lna_gain; 4424 4425 } else { /* 5GHZ band */ 4425 - if (rt2x00_rt(rt2x00dev, RT3572)) 4426 - vgc = 0x22 + (rt2x00dev->lna_gain * 5) / 3; 4426 + if (rt2x00_rt(rt2x00dev, RT3593)) 4427 + vgc = 0x20 + (rt2x00dev->lna_gain * 5) / 3; 4427 4428 else if (rt2x00_rt(rt2x00dev, RT5592)) 4428 4429 vgc = 0x24 + (2 * rt2x00dev->lna_gain); 4429 4430 else { ··· 4441 4442 struct link_qual *qual, u8 vgc_level) 4442 4443 { 4443 4444 if (qual->vgc_level != vgc_level) { 4444 - if (rt2x00_rt(rt2x00dev, RT5592)) { 4445 + if (rt2x00_rt(rt2x00dev, RT3572) || 4446 + rt2x00_rt(rt2x00dev, RT3593)) { 4447 + rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, 4448 + vgc_level); 4449 + } else if (rt2x00_rt(rt2x00dev, RT5592)) { 4445 4450 rt2800_bbp_write(rt2x00dev, 83, qual->rssi > -65 ? 0x4a : 0x7a); 4446 4451 rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, vgc_level); 4447 - } else 4452 + } else { 4448 4453 rt2800_bbp_write(rt2x00dev, 66, vgc_level); 4454 + } 4455 + 4449 4456 qual->vgc_level = vgc_level; 4450 4457 qual->vgc_level_reg = vgc_level; 4451 4458 } ··· 4470 4465 4471 4466 if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) 4472 4467 return; 4473 - /* 4474 - * When RSSI is better then -80 increase VGC level with 0x10, except 4475 - * for rt5592 chip. 4468 + 4469 + /* When RSSI is better than a certain threshold, increase VGC 4470 + * with a chip specific value in order to improve the balance 4471 + * between sensibility and noise isolation. 4476 4472 */ 4477 4473 4478 4474 vgc = rt2800_get_default_vgc(rt2x00dev); 4479 4475 4480 - if (rt2x00_rt(rt2x00dev, RT5592) && qual->rssi > -65) 4481 - vgc += 0x20; 4482 - else if (qual->rssi > -80) 4483 - vgc += 0x10; 4476 + switch (rt2x00dev->chip.rt) { 4477 + case RT3572: 4478 + case RT3593: 4479 + if (qual->rssi > -65) { 4480 + if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) 4481 + vgc += 0x20; 4482 + else 4483 + vgc += 0x10; 4484 + } 4485 + break; 4486 + 4487 + case RT5592: 4488 + if (qual->rssi > -65) 4489 + vgc += 0x20; 4490 + break; 4491 + 4492 + default: 4493 + if (qual->rssi > -80) 4494 + vgc += 0x10; 4495 + break; 4496 + } 4484 4497 4485 4498 rt2800_set_vgc(rt2x00dev, qual, vgc); 4486 4499 } ··· 5523 5500 ant = (div_mode == 3) ? 1 : 0; 5524 5501 5525 5502 /* check if this is a Bluetooth combo card */ 5526 - if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { 5503 + if (rt2x00_has_cap_bt_coexist(rt2x00dev)) { 5527 5504 u32 reg; 5528 5505 5529 5506 rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg); ··· 5832 5809 rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || 5833 5810 rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || 5834 5811 rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { 5835 - if (!test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) 5812 + if (!rt2x00_has_cap_external_lna_bg(rt2x00dev)) 5836 5813 rt2x00_set_field8(&rfcsr, RFCSR17_R, 1); 5837 5814 } 5838 5815 ··· 6475 6452 rt2800_rfcsr_write(rt2x00dev, 28, 0x00); 6476 6453 rt2800_rfcsr_write(rt2x00dev, 29, 0x10); 6477 6454 6478 - rt2800_rfcsr_write(rt2x00dev, 30, 0x00); 6455 + rt2800_rfcsr_write(rt2x00dev, 30, 0x10); 6479 6456 rt2800_rfcsr_write(rt2x00dev, 31, 0x80); 6480 6457 rt2800_rfcsr_write(rt2x00dev, 32, 0x80); 6481 6458 rt2800_rfcsr_write(rt2x00dev, 33, 0x00); ··· 6513 6490 rt2800_rfcsr_write(rt2x00dev, 56, 0x22); 6514 6491 rt2800_rfcsr_write(rt2x00dev, 57, 0x80); 6515 6492 rt2800_rfcsr_write(rt2x00dev, 58, 0x7f); 6516 - rt2800_rfcsr_write(rt2x00dev, 59, 0x63); 6493 + rt2800_rfcsr_write(rt2x00dev, 59, 0x8f); 6517 6494 6518 6495 rt2800_rfcsr_write(rt2x00dev, 60, 0x45); 6519 6496 if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) ··· 6533 6510 rt2800_rf_init_calibration(rt2x00dev, 2); 6534 6511 6535 6512 rt2800_rfcsr_write(rt2x00dev, 1, 0x17); 6536 - rt2800_rfcsr_write(rt2x00dev, 2, 0x80); 6537 6513 rt2800_rfcsr_write(rt2x00dev, 3, 0x88); 6538 6514 rt2800_rfcsr_write(rt2x00dev, 5, 0x10); 6539 6515 rt2800_rfcsr_write(rt2x00dev, 6, 0xe0); ··· 7246 7224 7247 7225 /* 7248 7226 * RF value list for rt3xxx 7249 - * Supports: 2.4 GHz (all) & 5.2 GHz (RF3052) 7227 + * Supports: 2.4 GHz (all) & 5.2 GHz (RF3052 & RF3053) 7250 7228 */ 7251 7229 static const struct rf_channel rf_vals_3x[] = { 7252 7230 {1, 241, 2, 2 }, ··· 7442 7420 {196, 83, 0, 12, 1}, 7443 7421 }; 7444 7422 7445 - static const struct rf_channel rf_vals_3053[] = { 7446 - /* Channel, N, R, K */ 7447 - {1, 241, 2, 2}, 7448 - {2, 241, 2, 7}, 7449 - {3, 242, 2, 2}, 7450 - {4, 242, 2, 7}, 7451 - {5, 243, 2, 2}, 7452 - {6, 243, 2, 7}, 7453 - {7, 244, 2, 2}, 7454 - {8, 244, 2, 7}, 7455 - {9, 245, 2, 2}, 7456 - {10, 245, 2, 7}, 7457 - {11, 246, 2, 2}, 7458 - {12, 246, 2, 7}, 7459 - {13, 247, 2, 2}, 7460 - {14, 248, 2, 4}, 7461 - 7462 - {36, 0x56, 0, 4}, 7463 - {38, 0x56, 0, 6}, 7464 - {40, 0x56, 0, 8}, 7465 - {44, 0x57, 0, 0}, 7466 - {46, 0x57, 0, 2}, 7467 - {48, 0x57, 0, 4}, 7468 - {52, 0x57, 0, 8}, 7469 - {54, 0x57, 0, 10}, 7470 - {56, 0x58, 0, 0}, 7471 - {60, 0x58, 0, 4}, 7472 - {62, 0x58, 0, 6}, 7473 - {64, 0x58, 0, 8}, 7474 - 7475 - {100, 0x5B, 0, 8}, 7476 - {102, 0x5B, 0, 10}, 7477 - {104, 0x5C, 0, 0}, 7478 - {108, 0x5C, 0, 4}, 7479 - {110, 0x5C, 0, 6}, 7480 - {112, 0x5C, 0, 8}, 7481 - 7482 - /* NOTE: Channel 114 has been removed intentionally. 7483 - * The EEPROM contains no TX power values for that, 7484 - * and it is disabled in the vendor driver as well. 7485 - */ 7486 - 7487 - {116, 0x5D, 0, 0}, 7488 - {118, 0x5D, 0, 2}, 7489 - {120, 0x5D, 0, 4}, 7490 - {124, 0x5D, 0, 8}, 7491 - {126, 0x5D, 0, 10}, 7492 - {128, 0x5E, 0, 0}, 7493 - {132, 0x5E, 0, 4}, 7494 - {134, 0x5E, 0, 6}, 7495 - {136, 0x5E, 0, 8}, 7496 - {140, 0x5F, 0, 0}, 7497 - 7498 - {149, 0x5F, 0, 9}, 7499 - {151, 0x5F, 0, 11}, 7500 - {153, 0x60, 0, 1}, 7501 - {157, 0x60, 0, 5}, 7502 - {159, 0x60, 0, 7}, 7503 - {161, 0x60, 0, 9}, 7504 - {165, 0x61, 0, 1}, 7505 - {167, 0x61, 0, 3}, 7506 - {169, 0x61, 0, 5}, 7507 - {171, 0x61, 0, 7}, 7508 - {173, 0x61, 0, 9}, 7509 - }; 7510 - 7511 7423 static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) 7512 7424 { 7513 7425 struct hw_mode_spec *spec = &rt2x00dev->spec; ··· 7531 7575 rt2x00_rf(rt2x00dev, RF5392)) { 7532 7576 spec->num_channels = 14; 7533 7577 spec->channels = rf_vals_3x; 7534 - } else if (rt2x00_rf(rt2x00dev, RF3052)) { 7578 + } else if (rt2x00_rf(rt2x00dev, RF3052) || 7579 + rt2x00_rf(rt2x00dev, RF3053)) { 7535 7580 spec->supported_bands |= SUPPORT_BAND_5GHZ; 7536 7581 spec->num_channels = ARRAY_SIZE(rf_vals_3x); 7537 7582 spec->channels = rf_vals_3x; 7538 - } else if (rt2x00_rf(rt2x00dev, RF3053)) { 7539 - spec->supported_bands |= SUPPORT_BAND_5GHZ; 7540 - spec->num_channels = ARRAY_SIZE(rf_vals_3053); 7541 - spec->channels = rf_vals_3053; 7542 7583 } else if (rt2x00_rf(rt2x00dev, RF5592)) { 7543 7584 spec->supported_bands |= SUPPORT_BAND_5GHZ; 7544 7585
+90 -13
drivers/net/wireless/rt2x00/rt2x00.h
··· 39 39 #include <linux/input-polldev.h> 40 40 #include <linux/kfifo.h> 41 41 #include <linux/hrtimer.h> 42 + #include <linux/average.h> 42 43 43 44 #include <net/mac80211.h> 44 45 ··· 138 137 GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) ) 139 138 #define SHORT_EIFS ( SIFS + SHORT_DIFS + \ 140 139 GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) ) 141 - 142 - /* 143 - * Structure for average calculation 144 - * The avg field contains the actual average value, 145 - * but avg_weight is internally used during calculations 146 - * to prevent rounding errors. 147 - */ 148 - struct avg_val { 149 - int avg; 150 - int avg_weight; 151 - }; 152 140 153 141 enum rt2x00_chip_intf { 154 142 RT2X00_CHIP_INTF_PCI, ··· 287 297 * Similar to the avg_rssi in the link_qual structure 288 298 * this value is updated by using the walking average. 289 299 */ 290 - struct avg_val rssi_ant; 300 + struct ewma rssi_ant; 291 301 }; 292 302 293 303 /* ··· 316 326 /* 317 327 * Currently active average RSSI value 318 328 */ 319 - struct avg_val avg_rssi; 329 + struct ewma avg_rssi; 320 330 321 331 /* 322 332 * Work structure for scheduling periodic link tuning. ··· 1167 1177 static inline bool rt2x00_is_soc(struct rt2x00_dev *rt2x00dev) 1168 1178 { 1169 1179 return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC); 1180 + } 1181 + 1182 + /* Helpers for capability flags */ 1183 + 1184 + static inline bool 1185 + rt2x00_has_cap_flag(struct rt2x00_dev *rt2x00dev, 1186 + enum rt2x00_capability_flags cap_flag) 1187 + { 1188 + return test_bit(cap_flag, &rt2x00dev->cap_flags); 1189 + } 1190 + 1191 + static inline bool 1192 + rt2x00_has_cap_hw_crypto(struct rt2x00_dev *rt2x00dev) 1193 + { 1194 + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_HW_CRYPTO); 1195 + } 1196 + 1197 + static inline bool 1198 + rt2x00_has_cap_power_limit(struct rt2x00_dev *rt2x00dev) 1199 + { 1200 + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_POWER_LIMIT); 1201 + } 1202 + 1203 + static inline bool 1204 + rt2x00_has_cap_control_filters(struct rt2x00_dev *rt2x00dev) 1205 + { 1206 + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_CONTROL_FILTERS); 1207 + } 1208 + 1209 + static inline bool 1210 + rt2x00_has_cap_control_filter_pspoll(struct rt2x00_dev *rt2x00dev) 1211 + { 1212 + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_CONTROL_FILTER_PSPOLL); 1213 + } 1214 + 1215 + static inline bool 1216 + rt2x00_has_cap_pre_tbtt_interrupt(struct rt2x00_dev *rt2x00dev) 1217 + { 1218 + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_PRE_TBTT_INTERRUPT); 1219 + } 1220 + 1221 + static inline bool 1222 + rt2x00_has_cap_link_tuning(struct rt2x00_dev *rt2x00dev) 1223 + { 1224 + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_LINK_TUNING); 1225 + } 1226 + 1227 + static inline bool 1228 + rt2x00_has_cap_frame_type(struct rt2x00_dev *rt2x00dev) 1229 + { 1230 + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_FRAME_TYPE); 1231 + } 1232 + 1233 + static inline bool 1234 + rt2x00_has_cap_rf_sequence(struct rt2x00_dev *rt2x00dev) 1235 + { 1236 + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_RF_SEQUENCE); 1237 + } 1238 + 1239 + static inline bool 1240 + rt2x00_has_cap_external_lna_a(struct rt2x00_dev *rt2x00dev) 1241 + { 1242 + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_EXTERNAL_LNA_A); 1243 + } 1244 + 1245 + static inline bool 1246 + rt2x00_has_cap_external_lna_bg(struct rt2x00_dev *rt2x00dev) 1247 + { 1248 + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_EXTERNAL_LNA_BG); 1249 + } 1250 + 1251 + static inline bool 1252 + rt2x00_has_cap_double_antenna(struct rt2x00_dev *rt2x00dev) 1253 + { 1254 + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_DOUBLE_ANTENNA); 1255 + } 1256 + 1257 + static inline bool 1258 + rt2x00_has_cap_bt_coexist(struct rt2x00_dev *rt2x00dev) 1259 + { 1260 + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_BT_COEXIST); 1261 + } 1262 + 1263 + static inline bool 1264 + rt2x00_has_cap_vco_recalibration(struct rt2x00_dev *rt2x00dev) 1265 + { 1266 + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_VCO_RECALIBRATION); 1170 1267 } 1171 1268 1172 1269 /**
+2 -2
drivers/net/wireless/rt2x00/rt2x00crypto.c
··· 52 52 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); 53 53 struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; 54 54 55 - if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !hw_key) 55 + if (!rt2x00_has_cap_hw_crypto(rt2x00dev) || !hw_key) 56 56 return; 57 57 58 58 __set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags); ··· 80 80 struct ieee80211_key_conf *key = tx_info->control.hw_key; 81 81 unsigned int overhead = 0; 82 82 83 - if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !key) 83 + if (!rt2x00_has_cap_hw_crypto(rt2x00dev) || !key) 84 84 return overhead; 85 85 86 86 /*
+1 -1
drivers/net/wireless/rt2x00/rt2x00debug.c
··· 750 750 intf, &rt2x00debug_fop_queue_stats); 751 751 752 752 #ifdef CONFIG_RT2X00_LIB_CRYPTO 753 - if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) 753 + if (rt2x00_has_cap_hw_crypto(rt2x00dev)) 754 754 intf->crypto_stats_entry = 755 755 debugfs_create_file("crypto", S_IRUGO, intf->queue_folder, 756 756 intf, &rt2x00debug_fop_crypto_stats);
+4 -4
drivers/net/wireless/rt2x00/rt2x00dev.c
··· 88 88 rt2x00queue_start_queues(rt2x00dev); 89 89 rt2x00link_start_tuner(rt2x00dev); 90 90 rt2x00link_start_agc(rt2x00dev); 91 - if (test_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags)) 91 + if (rt2x00_has_cap_vco_recalibration(rt2x00dev)) 92 92 rt2x00link_start_vcocal(rt2x00dev); 93 93 94 94 /* ··· 113 113 * Stop all queues 114 114 */ 115 115 rt2x00link_stop_agc(rt2x00dev); 116 - if (test_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags)) 116 + if (rt2x00_has_cap_vco_recalibration(rt2x00dev)) 117 117 rt2x00link_stop_vcocal(rt2x00dev); 118 118 rt2x00link_stop_tuner(rt2x00dev); 119 119 rt2x00queue_stop_queues(rt2x00dev); ··· 234 234 * here as they will fetch the next beacon directly prior to 235 235 * transmission. 236 236 */ 237 - if (test_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags)) 237 + if (rt2x00_has_cap_pre_tbtt_interrupt(rt2x00dev)) 238 238 return; 239 239 240 240 /* fetch next beacon */ ··· 358 358 * mac80211 will expect the same data to be present it the 359 359 * frame as it was passed to us. 360 360 */ 361 - if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) 361 + if (rt2x00_has_cap_hw_crypto(rt2x00dev)) 362 362 rt2x00crypto_tx_insert_iv(entry->skb, header_length); 363 363 364 364 /*
+27 -47
drivers/net/wireless/rt2x00/rt2x00link.c
··· 35 35 */ 36 36 #define DEFAULT_RSSI -128 37 37 38 - /* 39 - * Helper struct and macro to work with moving/walking averages. 40 - * When adding a value to the average value the following calculation 41 - * is needed: 42 - * 43 - * avg_rssi = ((avg_rssi * 7) + rssi) / 8; 44 - * 45 - * The advantage of this approach is that we only need 1 variable 46 - * to store the average in (No need for a count and a total). 47 - * But more importantly, normal average values will over time 48 - * move less and less towards newly added values this results 49 - * that with link tuning, the device can have a very good RSSI 50 - * for a few minutes but when the device is moved away from the AP 51 - * the average will not decrease fast enough to compensate. 52 - * The walking average compensates this and will move towards 53 - * the new values correctly allowing a effective link tuning, 54 - * the speed of the average moving towards other values depends 55 - * on the value for the number of samples. The higher the number 56 - * of samples, the slower the average will move. 57 - * We use two variables to keep track of the average value to 58 - * compensate for the rounding errors. This can be a significant 59 - * error (>5dBm) if the factor is too low. 60 - */ 61 - #define AVG_SAMPLES 8 62 - #define AVG_FACTOR 1000 63 - #define MOVING_AVERAGE(__avg, __val) \ 64 - ({ \ 65 - struct avg_val __new; \ 66 - __new.avg_weight = \ 67 - (__avg).avg_weight ? \ 68 - ((((__avg).avg_weight * ((AVG_SAMPLES) - 1)) + \ 69 - ((__val) * (AVG_FACTOR))) / \ 70 - (AVG_SAMPLES)) : \ 71 - ((__val) * (AVG_FACTOR)); \ 72 - __new.avg = __new.avg_weight / (AVG_FACTOR); \ 73 - __new; \ 74 - }) 38 + /* Constants for EWMA calculations. */ 39 + #define RT2X00_EWMA_FACTOR 1024 40 + #define RT2X00_EWMA_WEIGHT 8 41 + 42 + static inline int rt2x00link_get_avg_rssi(struct ewma *ewma) 43 + { 44 + unsigned long avg; 45 + 46 + avg = ewma_read(ewma); 47 + if (avg) 48 + return -avg; 49 + 50 + return DEFAULT_RSSI; 51 + } 75 52 76 53 static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev) 77 54 { 78 55 struct link_ant *ant = &rt2x00dev->link.ant; 79 56 80 - if (ant->rssi_ant.avg && rt2x00dev->link.qual.rx_success) 81 - return ant->rssi_ant.avg; 57 + if (rt2x00dev->link.qual.rx_success) 58 + return rt2x00link_get_avg_rssi(&ant->rssi_ant); 59 + 82 60 return DEFAULT_RSSI; 83 61 } 84 62 ··· 78 100 79 101 static void rt2x00link_antenna_reset(struct rt2x00_dev *rt2x00dev) 80 102 { 81 - rt2x00dev->link.ant.rssi_ant.avg = 0; 82 - rt2x00dev->link.ant.rssi_ant.avg_weight = 0; 103 + ewma_init(&rt2x00dev->link.ant.rssi_ant, RT2X00_EWMA_FACTOR, 104 + RT2X00_EWMA_WEIGHT); 83 105 } 84 106 85 107 static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev) ··· 227 249 /* 228 250 * Update global RSSI 229 251 */ 230 - link->avg_rssi = MOVING_AVERAGE(link->avg_rssi, rxdesc->rssi); 252 + ewma_add(&link->avg_rssi, -rxdesc->rssi); 231 253 232 254 /* 233 255 * Update antenna RSSI 234 256 */ 235 - ant->rssi_ant = MOVING_AVERAGE(ant->rssi_ant, rxdesc->rssi); 257 + ewma_add(&ant->rssi_ant, -rxdesc->rssi); 236 258 } 237 259 238 260 void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev) ··· 287 309 */ 288 310 rt2x00dev->link.count = 0; 289 311 memset(qual, 0, sizeof(*qual)); 312 + ewma_init(&rt2x00dev->link.avg_rssi, RT2X00_EWMA_FACTOR, 313 + RT2X00_EWMA_WEIGHT); 290 314 291 315 /* 292 316 * Restore the VGC level as stored in the registers, ··· 343 363 * collect the RSSI data we could use this. Otherwise we 344 364 * must fallback to the default RSSI value. 345 365 */ 346 - if (!link->avg_rssi.avg || !qual->rx_success) 366 + if (!qual->rx_success) 347 367 qual->rssi = DEFAULT_RSSI; 348 368 else 349 - qual->rssi = link->avg_rssi.avg; 369 + qual->rssi = rt2x00link_get_avg_rssi(&link->avg_rssi); 350 370 351 371 /* 352 372 * Check if link tuning is supported by the hardware, some hardware 353 373 * do not support link tuning at all, while other devices can disable 354 374 * the feature from the EEPROM. 355 375 */ 356 - if (test_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags)) 376 + if (rt2x00_has_cap_link_tuning(rt2x00dev)) 357 377 rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count); 358 378 359 379 /* ··· 493 513 void rt2x00link_register(struct rt2x00_dev *rt2x00dev) 494 514 { 495 515 INIT_DELAYED_WORK(&rt2x00dev->link.agc_work, rt2x00link_agc); 496 - if (test_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags)) 516 + if (rt2x00_has_cap_vco_recalibration(rt2x00dev)) 497 517 INIT_DELAYED_WORK(&rt2x00dev->link.vco_work, rt2x00link_vcocal); 498 518 INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog); 499 519 INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner);
+3 -3
drivers/net/wireless/rt2x00/rt2x00mac.c
··· 382 382 * of different types, but has no a separate filter for PS Poll frames, 383 383 * FIF_CONTROL flag implies FIF_PSPOLL. 384 384 */ 385 - if (!test_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags)) { 385 + if (!rt2x00_has_cap_control_filters(rt2x00dev)) { 386 386 if (*total_flags & FIF_CONTROL || *total_flags & FIF_PSPOLL) 387 387 *total_flags |= FIF_CONTROL | FIF_PSPOLL; 388 388 } 389 - if (!test_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags)) { 389 + if (!rt2x00_has_cap_control_filter_pspoll(rt2x00dev)) { 390 390 if (*total_flags & FIF_CONTROL) 391 391 *total_flags |= FIF_PSPOLL; 392 392 } ··· 469 469 if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) 470 470 return 0; 471 471 472 - if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) 472 + if (!rt2x00_has_cap_hw_crypto(rt2x00dev)) 473 473 return -EOPNOTSUPP; 474 474 475 475 /*
+1 -1
drivers/net/wireless/rt2x00/rt2x00pci.c
··· 119 119 rt2x00dev->ops = ops; 120 120 rt2x00dev->hw = hw; 121 121 rt2x00dev->irq = pci_dev->irq; 122 - rt2x00dev->name = pci_name(pci_dev); 122 + rt2x00dev->name = ops->name; 123 123 124 124 if (pci_is_pcie(pci_dev)) 125 125 rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE);
+7 -32
drivers/net/wireless/rt2x00/rt2x00queue.c
··· 61 61 * at least 8 bytes bytes available in headroom for IV/EIV 62 62 * and 8 bytes for ICV data as tailroon. 63 63 */ 64 - if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) { 64 + if (rt2x00_has_cap_hw_crypto(rt2x00dev)) { 65 65 head_size += 8; 66 66 tail_size += 8; 67 67 } ··· 1033 1033 1034 1034 void rt2x00queue_flush_queue(struct data_queue *queue, bool drop) 1035 1035 { 1036 - bool started; 1037 1036 bool tx_queue = 1038 1037 (queue->qid == QID_AC_VO) || 1039 1038 (queue->qid == QID_AC_VI) || 1040 1039 (queue->qid == QID_AC_BE) || 1041 1040 (queue->qid == QID_AC_BK); 1042 1041 1043 - mutex_lock(&queue->status_lock); 1044 1042 1045 1043 /* 1046 - * If the queue has been started, we must stop it temporarily 1047 - * to prevent any new frames to be queued on the device. If 1048 - * we are not dropping the pending frames, the queue must 1049 - * only be stopped in the software and not the hardware, 1050 - * otherwise the queue will never become empty on its own. 1044 + * If we are not supposed to drop any pending 1045 + * frames, this means we must force a start (=kick) 1046 + * to the queue to make sure the hardware will 1047 + * start transmitting. 1051 1048 */ 1052 - started = test_bit(QUEUE_STARTED, &queue->flags); 1053 - if (started) { 1054 - /* 1055 - * Pause the queue 1056 - */ 1057 - rt2x00queue_pause_queue(queue); 1058 - 1059 - /* 1060 - * If we are not supposed to drop any pending 1061 - * frames, this means we must force a start (=kick) 1062 - * to the queue to make sure the hardware will 1063 - * start transmitting. 1064 - */ 1065 - if (!drop && tx_queue) 1066 - queue->rt2x00dev->ops->lib->kick_queue(queue); 1067 - } 1049 + if (!drop && tx_queue) 1050 + queue->rt2x00dev->ops->lib->kick_queue(queue); 1068 1051 1069 1052 /* 1070 1053 * Check if driver supports flushing, if that is the case we can ··· 1063 1080 if (unlikely(!rt2x00queue_empty(queue))) 1064 1081 rt2x00_warn(queue->rt2x00dev, "Queue %d failed to flush\n", 1065 1082 queue->qid); 1066 - 1067 - /* 1068 - * Restore the queue to the previous status 1069 - */ 1070 - if (started) 1071 - rt2x00queue_unpause_queue(queue); 1072 - 1073 - mutex_unlock(&queue->status_lock); 1074 1083 } 1075 1084 EXPORT_SYMBOL_GPL(rt2x00queue_flush_queue); 1076 1085
+2
drivers/net/wireless/rt2x00/rt2x00usb.c
··· 523 523 rt2x00_warn(queue->rt2x00dev, "TX queue %d DMA timed out, invoke forced forced reset\n", 524 524 queue->qid); 525 525 526 + rt2x00queue_stop_queue(queue); 526 527 rt2x00queue_flush_queue(queue, true); 528 + rt2x00queue_start_queue(queue); 527 529 } 528 530 529 531 static int rt2x00usb_dma_timeout(struct data_queue *queue)
+10 -10
drivers/net/wireless/rt2x00/rt61pci.c
··· 685 685 686 686 rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529)); 687 687 rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 688 - !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags)); 688 + !rt2x00_has_cap_frame_type(rt2x00dev)); 689 689 690 690 /* 691 691 * Configure the RX antenna. ··· 813 813 814 814 if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { 815 815 sel = antenna_sel_a; 816 - lna = test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags); 816 + lna = rt2x00_has_cap_external_lna_a(rt2x00dev); 817 817 } else { 818 818 sel = antenna_sel_bg; 819 - lna = test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags); 819 + lna = rt2x00_has_cap_external_lna_bg(rt2x00dev); 820 820 } 821 821 822 822 for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) ··· 836 836 else if (rt2x00_rf(rt2x00dev, RF2527)) 837 837 rt61pci_config_antenna_2x(rt2x00dev, ant); 838 838 else if (rt2x00_rf(rt2x00dev, RF2529)) { 839 - if (test_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags)) 839 + if (rt2x00_has_cap_double_antenna(rt2x00dev)) 840 840 rt61pci_config_antenna_2x(rt2x00dev, ant); 841 841 else 842 842 rt61pci_config_antenna_2529(rt2x00dev, ant); ··· 850 850 short lna_gain = 0; 851 851 852 852 if (libconf->conf->chandef.chan->band == IEEE80211_BAND_2GHZ) { 853 - if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) 853 + if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) 854 854 lna_gain += 14; 855 855 856 856 rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom); 857 857 lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1); 858 858 } else { 859 - if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) 859 + if (rt2x00_has_cap_external_lna_a(rt2x00dev)) 860 860 lna_gain += 14; 861 861 862 862 rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom); ··· 1054 1054 if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { 1055 1055 low_bound = 0x28; 1056 1056 up_bound = 0x48; 1057 - if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) { 1057 + if (rt2x00_has_cap_external_lna_a(rt2x00dev)) { 1058 1058 low_bound += 0x10; 1059 1059 up_bound += 0x10; 1060 1060 } 1061 1061 } else { 1062 1062 low_bound = 0x20; 1063 1063 up_bound = 0x40; 1064 - if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) { 1064 + if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { 1065 1065 low_bound += 0x10; 1066 1066 up_bound += 0x10; 1067 1067 } ··· 2578 2578 * eeprom word. 2579 2579 */ 2580 2580 if (rt2x00_rf(rt2x00dev, RF2529) && 2581 - !test_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags)) { 2581 + !rt2x00_has_cap_double_antenna(rt2x00dev)) { 2582 2582 rt2x00dev->default_ant.rx = 2583 2583 ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED); 2584 2584 rt2x00dev->default_ant.tx = ··· 2793 2793 spec->supported_bands = SUPPORT_BAND_2GHZ; 2794 2794 spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; 2795 2795 2796 - if (!test_bit(CAPABILITY_RF_SEQUENCE, &rt2x00dev->cap_flags)) { 2796 + if (!rt2x00_has_cap_rf_sequence(rt2x00dev)) { 2797 2797 spec->num_channels = 14; 2798 2798 spec->channels = rf_vals_noseq; 2799 2799 } else {
+9 -9
drivers/net/wireless/rt2x00/rt73usb.c
··· 595 595 switch (ant->rx) { 596 596 case ANTENNA_HW_DIVERSITY: 597 597 rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2); 598 - temp = !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags) 599 - && (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ); 598 + temp = !rt2x00_has_cap_frame_type(rt2x00dev) && 599 + (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ); 600 600 rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp); 601 601 break; 602 602 case ANTENNA_A: ··· 636 636 637 637 rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0); 638 638 rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 639 - !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags)); 639 + !rt2x00_has_cap_frame_type(rt2x00dev)); 640 640 641 641 /* 642 642 * Configure the RX antenna. ··· 709 709 710 710 if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { 711 711 sel = antenna_sel_a; 712 - lna = test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags); 712 + lna = rt2x00_has_cap_external_lna_a(rt2x00dev); 713 713 } else { 714 714 sel = antenna_sel_bg; 715 - lna = test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags); 715 + lna = rt2x00_has_cap_external_lna_bg(rt2x00dev); 716 716 } 717 717 718 718 for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) ··· 740 740 short lna_gain = 0; 741 741 742 742 if (libconf->conf->chandef.chan->band == IEEE80211_BAND_2GHZ) { 743 - if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) 743 + if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) 744 744 lna_gain += 14; 745 745 746 746 rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom); ··· 930 930 low_bound = 0x28; 931 931 up_bound = 0x48; 932 932 933 - if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) { 933 + if (rt2x00_has_cap_external_lna_a(rt2x00dev)) { 934 934 low_bound += 0x10; 935 935 up_bound += 0x10; 936 936 } ··· 946 946 up_bound = 0x1c; 947 947 } 948 948 949 - if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) { 949 + if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { 950 950 low_bound += 0x14; 951 951 up_bound += 0x10; 952 952 } ··· 1661 1661 } 1662 1662 1663 1663 if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { 1664 - if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) { 1664 + if (rt2x00_has_cap_external_lna_a(rt2x00dev)) { 1665 1665 if (lna == 3 || lna == 2) 1666 1666 offset += 10; 1667 1667 } else {
+2 -2
drivers/net/wireless/ti/wl1251/wl1251.h
··· 424 424 #define CHIP_ID_1271_PG10 (0x4030101) 425 425 #define CHIP_ID_1271_PG20 (0x4030111) 426 426 427 - #define WL1251_FW_NAME "wl1251-fw.bin" 428 - #define WL1251_NVS_NAME "wl1251-nvs.bin" 427 + #define WL1251_FW_NAME "ti-connectivity/wl1251-fw.bin" 428 + #define WL1251_NVS_NAME "ti-connectivity/wl1251-nvs.bin" 429 429 430 430 #define WL1251_POWER_ON_SLEEP 10 /* in milliseconds */ 431 431
+2 -2
include/linux/ieee80211.h
··· 1391 1391 #define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700 1392 1392 #define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 1393 1393 #define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 1394 - #define IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX 0x00006000 1395 - #define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX 0x00030000 1394 + #define IEEE80211_VHT_CAP_BEAMFORMEE_STS_MAX 0x0000e000 1395 + #define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX 0x00070000 1396 1396 #define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000 1397 1397 #define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000 1398 1398 #define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000
+9
include/net/cfg80211.h
··· 437 437 u32 prohibited_flags); 438 438 439 439 /** 440 + * cfg80211_chandef_dfs_required - checks if radar detection is required 441 + * @wiphy: the wiphy to validate against 442 + * @chandef: the channel definition to check 443 + * Return: 1 if radar detection is required, 0 if it is not, < 0 on error 444 + */ 445 + int cfg80211_chandef_dfs_required(struct wiphy *wiphy, 446 + const struct cfg80211_chan_def *chandef); 447 + 448 + /** 440 449 * ieee80211_chandef_rate_flags - returns rate flags for a channel 441 450 * 442 451 * In some channel types, not all rates may be used - for example CCK
+42
include/net/mac80211.h
··· 829 829 * @RX_FLAG_STBC_MASK: STBC 2 bit bitmask. 1 - Nss=1, 2 - Nss=2, 3 - Nss=3 830 830 * @RX_FLAG_10MHZ: 10 MHz (half channel) was used 831 831 * @RX_FLAG_5MHZ: 5 MHz (quarter channel) was used 832 + * @RX_FLAG_AMSDU_MORE: Some drivers may prefer to report separate A-MSDU 833 + * subframes instead of a one huge frame for performance reasons. 834 + * All, but the last MSDU from an A-MSDU should have this flag set. E.g. 835 + * if an A-MSDU has 3 frames, the first 2 must have the flag set, while 836 + * the 3rd (last) one must not have this flag set. The flag is used to 837 + * deal with retransmission/duplication recovery properly since A-MSDU 838 + * subframes share the same sequence number. Reported subframes can be 839 + * either regular MSDU or singly A-MSDUs. Subframes must not be 840 + * interleaved with other frames. 832 841 */ 833 842 enum mac80211_rx_flags { 834 843 RX_FLAG_MMIC_ERROR = BIT(0), ··· 868 859 RX_FLAG_STBC_MASK = BIT(26) | BIT(27), 869 860 RX_FLAG_10MHZ = BIT(28), 870 861 RX_FLAG_5MHZ = BIT(29), 862 + RX_FLAG_AMSDU_MORE = BIT(30), 871 863 }; 872 864 873 865 #define RX_FLAG_STBC_SHIFT 26 ··· 1502 1492 * 1503 1493 * @IEEE80211_HW_TIMING_BEACON_ONLY: Use sync timing from beacon frames 1504 1494 * only, to allow getting TBTT of a DTIM beacon. 1495 + * 1496 + * @IEEE80211_HW_CHANCTX_STA_CSA: Support 802.11h based channel-switch (CSA) 1497 + * for a single active channel while using channel contexts. When support 1498 + * is not enabled the default action is to disconnect when getting the 1499 + * CSA frame. 1505 1500 */ 1506 1501 enum ieee80211_hw_flags { 1507 1502 IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, ··· 1537 1522 IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF = 1<<25, 1538 1523 IEEE80211_HW_TIMING_BEACON_ONLY = 1<<26, 1539 1524 IEEE80211_HW_SUPPORTS_HT_CCK_RATES = 1<<27, 1525 + IEEE80211_HW_CHANCTX_STA_CSA = 1<<28, 1540 1526 }; 1541 1527 1542 1528 /** ··· 2682 2666 * zero using ieee80211_csa_is_complete() after the beacon has been 2683 2667 * transmitted and then call ieee80211_csa_finish(). 2684 2668 * 2669 + * @join_ibss: Join an IBSS (on an IBSS interface); this is called after all 2670 + * information in bss_conf is set up and the beacon can be retrieved. A 2671 + * channel context is bound before this is called. 2672 + * @leave_ibss: Leave the IBSS again. 2685 2673 */ 2686 2674 struct ieee80211_ops { 2687 2675 void (*tx)(struct ieee80211_hw *hw, ··· 2877 2857 void (*channel_switch_beacon)(struct ieee80211_hw *hw, 2878 2858 struct ieee80211_vif *vif, 2879 2859 struct cfg80211_chan_def *chandef); 2860 + 2861 + int (*join_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); 2862 + void (*leave_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); 2880 2863 }; 2881 2864 2882 2865 /** ··· 3941 3918 u8 *mac, 3942 3919 struct ieee80211_vif *vif), 3943 3920 void *data); 3921 + 3922 + /** 3923 + * ieee80211_iterate_active_interfaces_rtnl - iterate active interfaces 3924 + * 3925 + * This function iterates over the interfaces associated with a given 3926 + * hardware that are currently active and calls the callback for them. 3927 + * This version can only be used while holding the RTNL. 3928 + * 3929 + * @hw: the hardware struct of which the interfaces should be iterated over 3930 + * @iter_flags: iteration flags, see &enum ieee80211_interface_iteration_flags 3931 + * @iterator: the iterator function to call, cannot sleep 3932 + * @data: first argument of the iterator function 3933 + */ 3934 + void ieee80211_iterate_active_interfaces_rtnl(struct ieee80211_hw *hw, 3935 + u32 iter_flags, 3936 + void (*iterator)(void *data, 3937 + u8 *mac, 3938 + struct ieee80211_vif *vif), 3939 + void *data); 3944 3940 3945 3941 /** 3946 3942 * ieee80211_queue_work - add work onto the mac80211 workqueue
+69 -23
net/mac80211/cfg.c
··· 2865 2865 if (!ieee80211_sdata_running(sdata)) 2866 2866 return; 2867 2867 2868 - if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP)) 2869 - return; 2870 - 2871 2868 sdata->radar_required = sdata->csa_radar_required; 2872 2869 err = ieee80211_vif_change_channel(sdata, &local->csa_chandef, 2873 2870 &changed); 2874 2871 if (WARN_ON(err < 0)) 2875 2872 return; 2876 2873 2877 - err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); 2878 - if (err < 0) 2879 - return; 2874 + if (!local->use_chanctx) { 2875 + local->_oper_chandef = local->csa_chandef; 2876 + ieee80211_hw_config(local, 0); 2877 + } 2880 2878 2881 - changed |= err; 2882 - kfree(sdata->u.ap.next_beacon); 2883 - sdata->u.ap.next_beacon = NULL; 2879 + ieee80211_bss_info_change_notify(sdata, changed); 2880 + 2881 + switch (sdata->vif.type) { 2882 + case NL80211_IFTYPE_AP: 2883 + err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); 2884 + if (err < 0) 2885 + return; 2886 + changed |= err; 2887 + kfree(sdata->u.ap.next_beacon); 2888 + sdata->u.ap.next_beacon = NULL; 2889 + 2890 + ieee80211_bss_info_change_notify(sdata, err); 2891 + break; 2892 + case NL80211_IFTYPE_ADHOC: 2893 + ieee80211_ibss_finish_csa(sdata); 2894 + break; 2895 + default: 2896 + WARN_ON(1); 2897 + return; 2898 + } 2884 2899 sdata->vif.csa_active = false; 2885 2900 2886 2901 ieee80211_wake_queues_by_reason(&sdata->local->hw, 2887 2902 IEEE80211_MAX_QUEUE_MAP, 2888 2903 IEEE80211_QUEUE_STOP_REASON_CSA); 2889 - 2890 - ieee80211_bss_info_change_notify(sdata, changed); 2891 2904 2892 2905 cfg80211_ch_switch_notify(sdata->dev, &local->csa_chandef); 2893 2906 } ··· 2949 2936 if (sdata->vif.csa_active) 2950 2937 return -EBUSY; 2951 2938 2952 - /* only handle AP for now. */ 2953 2939 switch (sdata->vif.type) { 2954 2940 case NL80211_IFTYPE_AP: 2941 + sdata->csa_counter_offset_beacon = 2942 + params->counter_offset_beacon; 2943 + sdata->csa_counter_offset_presp = params->counter_offset_presp; 2944 + sdata->u.ap.next_beacon = 2945 + cfg80211_beacon_dup(&params->beacon_after); 2946 + if (!sdata->u.ap.next_beacon) 2947 + return -ENOMEM; 2948 + 2949 + err = ieee80211_assign_beacon(sdata, &params->beacon_csa); 2950 + if (err < 0) { 2951 + kfree(sdata->u.ap.next_beacon); 2952 + return err; 2953 + } 2954 + break; 2955 + case NL80211_IFTYPE_ADHOC: 2956 + if (!sdata->vif.bss_conf.ibss_joined) 2957 + return -EINVAL; 2958 + 2959 + if (params->chandef.width != sdata->u.ibss.chandef.width) 2960 + return -EINVAL; 2961 + 2962 + switch (params->chandef.width) { 2963 + case NL80211_CHAN_WIDTH_40: 2964 + if (cfg80211_get_chandef_type(&params->chandef) != 2965 + cfg80211_get_chandef_type(&sdata->u.ibss.chandef)) 2966 + return -EINVAL; 2967 + case NL80211_CHAN_WIDTH_5: 2968 + case NL80211_CHAN_WIDTH_10: 2969 + case NL80211_CHAN_WIDTH_20_NOHT: 2970 + case NL80211_CHAN_WIDTH_20: 2971 + break; 2972 + default: 2973 + return -EINVAL; 2974 + } 2975 + 2976 + /* changes into another band are not supported */ 2977 + if (sdata->u.ibss.chandef.chan->band != 2978 + params->chandef.chan->band) 2979 + return -EINVAL; 2980 + 2981 + err = ieee80211_ibss_csa_beacon(sdata, params); 2982 + if (err < 0) 2983 + return err; 2955 2984 break; 2956 2985 default: 2957 2986 return -EOPNOTSUPP; 2958 2987 } 2959 2988 2960 - sdata->u.ap.next_beacon = cfg80211_beacon_dup(&params->beacon_after); 2961 - if (!sdata->u.ap.next_beacon) 2962 - return -ENOMEM; 2963 - 2964 - sdata->csa_counter_offset_beacon = params->counter_offset_beacon; 2965 - sdata->csa_counter_offset_presp = params->counter_offset_presp; 2966 2989 sdata->csa_radar_required = params->radar_required; 2967 2990 2968 2991 if (params->block_tx) 2969 2992 ieee80211_stop_queues_by_reason(&local->hw, 2970 2993 IEEE80211_MAX_QUEUE_MAP, 2971 2994 IEEE80211_QUEUE_STOP_REASON_CSA); 2972 - 2973 - err = ieee80211_assign_beacon(sdata, &params->beacon_csa); 2974 - if (err < 0) 2975 - return err; 2976 2995 2977 2996 local->csa_chandef = params->chandef; 2978 2997 sdata->vif.csa_active = true; ··· 3059 3014 need_offchan = true; 3060 3015 if (!ieee80211_is_action(mgmt->frame_control) || 3061 3016 mgmt->u.action.category == WLAN_CATEGORY_PUBLIC || 3062 - mgmt->u.action.category == WLAN_CATEGORY_SELF_PROTECTED) 3017 + mgmt->u.action.category == WLAN_CATEGORY_SELF_PROTECTED || 3018 + mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) 3063 3019 break; 3064 3020 rcu_read_lock(); 3065 3021 sta = sta_info_get(sdata, mgmt->da);
-5
net/mac80211/chan.c
··· 453 453 chanctx_changed |= IEEE80211_CHANCTX_CHANGE_CHANNEL; 454 454 drv_change_chanctx(local, ctx, chanctx_changed); 455 455 456 - if (!local->use_chanctx) { 457 - local->_oper_chandef = *chandef; 458 - ieee80211_hw_config(local, 0); 459 - } 460 - 461 456 ieee80211_recalc_chanctx_chantype(local, ctx); 462 457 ieee80211_recalc_smps_chanctx(local, ctx); 463 458 ieee80211_recalc_radar_chanctx(local, ctx);
+29 -26
net/mac80211/debugfs.c
··· 103 103 if (!buf) 104 104 return 0; 105 105 106 - sf += snprintf(buf, mxln - sf, "0x%x\n", local->hw.flags); 106 + sf += scnprintf(buf, mxln - sf, "0x%x\n", local->hw.flags); 107 107 if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) 108 - sf += snprintf(buf + sf, mxln - sf, "HAS_RATE_CONTROL\n"); 108 + sf += scnprintf(buf + sf, mxln - sf, "HAS_RATE_CONTROL\n"); 109 109 if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) 110 - sf += snprintf(buf + sf, mxln - sf, "RX_INCLUDES_FCS\n"); 110 + sf += scnprintf(buf + sf, mxln - sf, "RX_INCLUDES_FCS\n"); 111 111 if (local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING) 112 - sf += snprintf(buf + sf, mxln - sf, 113 - "HOST_BCAST_PS_BUFFERING\n"); 112 + sf += scnprintf(buf + sf, mxln - sf, 113 + "HOST_BCAST_PS_BUFFERING\n"); 114 114 if (local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE) 115 - sf += snprintf(buf + sf, mxln - sf, 116 - "2GHZ_SHORT_SLOT_INCAPABLE\n"); 115 + sf += scnprintf(buf + sf, mxln - sf, 116 + "2GHZ_SHORT_SLOT_INCAPABLE\n"); 117 117 if (local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE) 118 - sf += snprintf(buf + sf, mxln - sf, 119 - "2GHZ_SHORT_PREAMBLE_INCAPABLE\n"); 118 + sf += scnprintf(buf + sf, mxln - sf, 119 + "2GHZ_SHORT_PREAMBLE_INCAPABLE\n"); 120 120 if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) 121 - sf += snprintf(buf + sf, mxln - sf, "SIGNAL_UNSPEC\n"); 121 + sf += scnprintf(buf + sf, mxln - sf, "SIGNAL_UNSPEC\n"); 122 122 if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) 123 - sf += snprintf(buf + sf, mxln - sf, "SIGNAL_DBM\n"); 123 + sf += scnprintf(buf + sf, mxln - sf, "SIGNAL_DBM\n"); 124 124 if (local->hw.flags & IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC) 125 - sf += snprintf(buf + sf, mxln - sf, "NEED_DTIM_BEFORE_ASSOC\n"); 125 + sf += scnprintf(buf + sf, mxln - sf, 126 + "NEED_DTIM_BEFORE_ASSOC\n"); 126 127 if (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT) 127 - sf += snprintf(buf + sf, mxln - sf, "SPECTRUM_MGMT\n"); 128 + sf += scnprintf(buf + sf, mxln - sf, "SPECTRUM_MGMT\n"); 128 129 if (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) 129 - sf += snprintf(buf + sf, mxln - sf, "AMPDU_AGGREGATION\n"); 130 + sf += scnprintf(buf + sf, mxln - sf, "AMPDU_AGGREGATION\n"); 130 131 if (local->hw.flags & IEEE80211_HW_SUPPORTS_PS) 131 - sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_PS\n"); 132 + sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_PS\n"); 132 133 if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) 133 - sf += snprintf(buf + sf, mxln - sf, "PS_NULLFUNC_STACK\n"); 134 + sf += scnprintf(buf + sf, mxln - sf, "PS_NULLFUNC_STACK\n"); 134 135 if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) 135 - sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_PS\n"); 136 + sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_PS\n"); 136 137 if (local->hw.flags & IEEE80211_HW_MFP_CAPABLE) 137 - sf += snprintf(buf + sf, mxln - sf, "MFP_CAPABLE\n"); 138 + sf += scnprintf(buf + sf, mxln - sf, "MFP_CAPABLE\n"); 138 139 if (local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS) 139 - sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_STATIC_SMPS\n"); 140 + sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_STATIC_SMPS\n"); 140 141 if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) 141 - sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_SMPS\n"); 142 + sf += scnprintf(buf + sf, mxln - sf, 143 + "SUPPORTS_DYNAMIC_SMPS\n"); 142 144 if (local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) 143 - sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_UAPSD\n"); 145 + sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_UAPSD\n"); 144 146 if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) 145 - sf += snprintf(buf + sf, mxln - sf, "REPORTS_TX_ACK_STATUS\n"); 147 + sf += scnprintf(buf + sf, mxln - sf, 148 + "REPORTS_TX_ACK_STATUS\n"); 146 149 if (local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) 147 - sf += snprintf(buf + sf, mxln - sf, "CONNECTION_MONITOR\n"); 150 + sf += scnprintf(buf + sf, mxln - sf, "CONNECTION_MONITOR\n"); 148 151 if (local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK) 149 - sf += snprintf(buf + sf, mxln - sf, "SUPPORTS_PER_STA_GTK\n"); 152 + sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_PER_STA_GTK\n"); 150 153 if (local->hw.flags & IEEE80211_HW_AP_LINK_PS) 151 - sf += snprintf(buf + sf, mxln - sf, "AP_LINK_PS\n"); 154 + sf += scnprintf(buf + sf, mxln - sf, "AP_LINK_PS\n"); 152 155 if (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW) 153 - sf += snprintf(buf + sf, mxln - sf, "TX_AMPDU_SETUP_IN_HW\n"); 156 + sf += scnprintf(buf + sf, mxln - sf, "TX_AMPDU_SETUP_IN_HW\n"); 154 157 155 158 rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); 156 159 kfree(buf);
+27
net/mac80211/driver-ops.h
··· 1085 1085 } 1086 1086 } 1087 1087 1088 + static inline int drv_join_ibss(struct ieee80211_local *local, 1089 + struct ieee80211_sub_if_data *sdata) 1090 + { 1091 + int ret = 0; 1092 + 1093 + might_sleep(); 1094 + check_sdata_in_driver(sdata); 1095 + 1096 + trace_drv_join_ibss(local, sdata, &sdata->vif.bss_conf); 1097 + if (local->ops->join_ibss) 1098 + ret = local->ops->join_ibss(&local->hw, &sdata->vif); 1099 + trace_drv_return_int(local, ret); 1100 + return ret; 1101 + } 1102 + 1103 + static inline void drv_leave_ibss(struct ieee80211_local *local, 1104 + struct ieee80211_sub_if_data *sdata) 1105 + { 1106 + might_sleep(); 1107 + check_sdata_in_driver(sdata); 1108 + 1109 + trace_drv_leave_ibss(local, sdata); 1110 + if (local->ops->leave_ibss) 1111 + local->ops->leave_ibss(&local->hw, &sdata->vif); 1112 + trace_drv_return_void(local); 1113 + } 1114 + 1088 1115 #endif /* __MAC80211_DRIVER_OPS */
+520 -88
net/mac80211/ibss.c
··· 39 39 const int beacon_int, const u32 basic_rates, 40 40 const u16 capability, u64 tsf, 41 41 struct cfg80211_chan_def *chandef, 42 - bool *have_higher_than_11mbit) 42 + bool *have_higher_than_11mbit, 43 + struct cfg80211_csa_settings *csa_settings) 43 44 { 44 45 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 45 46 struct ieee80211_local *local = sdata->local; ··· 60 59 2 + 8 /* max Supported Rates */ + 61 60 3 /* max DS params */ + 62 61 4 /* IBSS params */ + 62 + 5 /* Channel Switch Announcement */ + 63 63 2 + (IEEE80211_MAX_SUPP_RATES - 8) + 64 64 2 + sizeof(struct ieee80211_ht_cap) + 65 65 2 + sizeof(struct ieee80211_ht_operation) + ··· 136 134 /* FIX: set ATIM window based on scan results */ 137 135 *pos++ = 0; 138 136 *pos++ = 0; 137 + 138 + if (csa_settings) { 139 + *pos++ = WLAN_EID_CHANNEL_SWITCH; 140 + *pos++ = 3; 141 + *pos++ = csa_settings->block_tx ? 1 : 0; 142 + *pos++ = ieee80211_frequency_to_channel( 143 + csa_settings->chandef.chan->center_freq); 144 + sdata->csa_counter_offset_beacon = (pos - presp->head); 145 + *pos++ = csa_settings->count; 146 + } 139 147 140 148 /* put the remaining rates in WLAN_EID_EXT_SUPP_RATES */ 141 149 if (rates_n > 8) { ··· 229 217 struct beacon_data *presp; 230 218 enum nl80211_bss_scan_width scan_width; 231 219 bool have_higher_than_11mbit; 220 + int err; 232 221 233 222 sdata_assert_lock(sdata); 234 223 ··· 248 235 ieee80211_bss_info_change_notify(sdata, 249 236 BSS_CHANGED_IBSS | 250 237 BSS_CHANGED_BEACON_ENABLED); 238 + drv_leave_ibss(local, sdata); 251 239 } 252 240 253 241 presp = rcu_dereference_protected(ifibss->presp, ··· 290 276 291 277 presp = ieee80211_ibss_build_presp(sdata, beacon_int, basic_rates, 292 278 capability, tsf, &chandef, 293 - &have_higher_than_11mbit); 279 + &have_higher_than_11mbit, NULL); 294 280 if (!presp) 295 281 return; 296 282 ··· 331 317 else 332 318 sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; 333 319 320 + ieee80211_set_wmm_default(sdata, true); 321 + 334 322 sdata->vif.bss_conf.ibss_joined = true; 335 323 sdata->vif.bss_conf.ibss_creator = creator; 336 - ieee80211_bss_info_change_notify(sdata, bss_change); 337 324 338 - ieee80211_set_wmm_default(sdata, true); 325 + err = drv_join_ibss(local, sdata); 326 + if (err) { 327 + sdata->vif.bss_conf.ibss_joined = false; 328 + sdata->vif.bss_conf.ibss_creator = false; 329 + sdata->vif.bss_conf.enable_beacon = false; 330 + sdata->vif.bss_conf.ssid_len = 0; 331 + RCU_INIT_POINTER(ifibss->presp, NULL); 332 + kfree_rcu(presp, rcu_head); 333 + ieee80211_vif_release_channel(sdata); 334 + sdata_info(sdata, "Failed to join IBSS, driver failure: %d\n", 335 + err); 336 + return; 337 + } 338 + 339 + ieee80211_bss_info_change_notify(sdata, bss_change); 339 340 340 341 ifibss->state = IEEE80211_IBSS_MLME_JOINED; 341 342 mod_timer(&ifibss->timer, ··· 445 416 tsf, false); 446 417 } 447 418 419 + static int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata, 420 + struct cfg80211_csa_settings *csa_settings) 421 + { 422 + struct sk_buff *skb; 423 + struct ieee80211_mgmt *mgmt; 424 + struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 425 + struct ieee80211_local *local = sdata->local; 426 + int freq; 427 + int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.chan_switch) + 428 + sizeof(mgmt->u.action.u.chan_switch); 429 + u8 *pos; 430 + 431 + skb = dev_alloc_skb(local->tx_headroom + hdr_len + 432 + 5 + /* channel switch announcement element */ 433 + 3); /* secondary channel offset element */ 434 + if (!skb) 435 + return -1; 436 + 437 + skb_reserve(skb, local->tx_headroom); 438 + mgmt = (struct ieee80211_mgmt *)skb_put(skb, hdr_len); 439 + memset(mgmt, 0, hdr_len); 440 + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 441 + IEEE80211_STYPE_ACTION); 442 + 443 + eth_broadcast_addr(mgmt->da); 444 + memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); 445 + memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN); 446 + mgmt->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT; 447 + mgmt->u.action.u.chan_switch.action_code = WLAN_ACTION_SPCT_CHL_SWITCH; 448 + pos = skb_put(skb, 5); 449 + *pos++ = WLAN_EID_CHANNEL_SWITCH; /* EID */ 450 + *pos++ = 3; /* IE length */ 451 + *pos++ = csa_settings->block_tx ? 1 : 0; /* CSA mode */ 452 + freq = csa_settings->chandef.chan->center_freq; 453 + *pos++ = ieee80211_frequency_to_channel(freq); /* channel */ 454 + *pos++ = csa_settings->count; /* count */ 455 + 456 + if (csa_settings->chandef.width == NL80211_CHAN_WIDTH_40) { 457 + enum nl80211_channel_type ch_type; 458 + 459 + skb_put(skb, 3); 460 + *pos++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET; /* EID */ 461 + *pos++ = 1; /* IE length */ 462 + ch_type = cfg80211_get_chandef_type(&csa_settings->chandef); 463 + if (ch_type == NL80211_CHAN_HT40PLUS) 464 + *pos++ = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; 465 + else 466 + *pos++ = IEEE80211_HT_PARAM_CHA_SEC_BELOW; 467 + } 468 + 469 + ieee80211_tx_skb(sdata, skb); 470 + return 0; 471 + } 472 + 473 + int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata, 474 + struct cfg80211_csa_settings *csa_settings) 475 + { 476 + struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 477 + struct beacon_data *presp, *old_presp; 478 + struct cfg80211_bss *cbss; 479 + const struct cfg80211_bss_ies *ies; 480 + u16 capability; 481 + u64 tsf; 482 + int ret = 0; 483 + 484 + sdata_assert_lock(sdata); 485 + 486 + capability = WLAN_CAPABILITY_IBSS; 487 + 488 + if (ifibss->privacy) 489 + capability |= WLAN_CAPABILITY_PRIVACY; 490 + 491 + cbss = cfg80211_get_bss(sdata->local->hw.wiphy, ifibss->chandef.chan, 492 + ifibss->bssid, ifibss->ssid, 493 + ifibss->ssid_len, WLAN_CAPABILITY_IBSS | 494 + WLAN_CAPABILITY_PRIVACY, 495 + capability); 496 + 497 + if (WARN_ON(!cbss)) { 498 + ret = -EINVAL; 499 + goto out; 500 + } 501 + 502 + rcu_read_lock(); 503 + ies = rcu_dereference(cbss->ies); 504 + tsf = ies->tsf; 505 + rcu_read_unlock(); 506 + cfg80211_put_bss(sdata->local->hw.wiphy, cbss); 507 + 508 + old_presp = rcu_dereference_protected(ifibss->presp, 509 + lockdep_is_held(&sdata->wdev.mtx)); 510 + 511 + presp = ieee80211_ibss_build_presp(sdata, 512 + sdata->vif.bss_conf.beacon_int, 513 + sdata->vif.bss_conf.basic_rates, 514 + capability, tsf, &ifibss->chandef, 515 + NULL, csa_settings); 516 + if (!presp) { 517 + ret = -ENOMEM; 518 + goto out; 519 + } 520 + 521 + rcu_assign_pointer(ifibss->presp, presp); 522 + if (old_presp) 523 + kfree_rcu(old_presp, rcu_head); 524 + 525 + /* it might not send the beacon for a while. send an action frame 526 + * immediately to announce the channel switch. 527 + */ 528 + if (csa_settings) 529 + ieee80211_send_action_csa(sdata, csa_settings); 530 + 531 + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); 532 + out: 533 + return ret; 534 + } 535 + 536 + int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata) 537 + { 538 + struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 539 + struct cfg80211_bss *cbss; 540 + int err; 541 + u16 capability; 542 + 543 + sdata_lock(sdata); 544 + /* update cfg80211 bss information with the new channel */ 545 + if (!is_zero_ether_addr(ifibss->bssid)) { 546 + capability = WLAN_CAPABILITY_IBSS; 547 + 548 + if (ifibss->privacy) 549 + capability |= WLAN_CAPABILITY_PRIVACY; 550 + 551 + cbss = cfg80211_get_bss(sdata->local->hw.wiphy, 552 + ifibss->chandef.chan, 553 + ifibss->bssid, ifibss->ssid, 554 + ifibss->ssid_len, WLAN_CAPABILITY_IBSS | 555 + WLAN_CAPABILITY_PRIVACY, 556 + capability); 557 + /* XXX: should not really modify cfg80211 data */ 558 + if (cbss) { 559 + cbss->channel = sdata->local->csa_chandef.chan; 560 + cfg80211_put_bss(sdata->local->hw.wiphy, cbss); 561 + } 562 + } 563 + 564 + ifibss->chandef = sdata->local->csa_chandef; 565 + 566 + /* generate the beacon */ 567 + err = ieee80211_ibss_csa_beacon(sdata, NULL); 568 + sdata_unlock(sdata); 569 + if (err < 0) 570 + return err; 571 + 572 + return 0; 573 + } 574 + 575 + void ieee80211_ibss_stop(struct ieee80211_sub_if_data *sdata) 576 + { 577 + struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 578 + 579 + cancel_work_sync(&ifibss->csa_connection_drop_work); 580 + } 581 + 448 582 static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta) 449 583 __acquires(RCU) 450 584 { ··· 689 497 ieee80211_mandatory_rates(sband, scan_width); 690 498 691 499 return ieee80211_ibss_finish_sta(sta); 500 + } 501 + 502 + static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) 503 + { 504 + struct ieee80211_local *local = sdata->local; 505 + int active = 0; 506 + struct sta_info *sta; 507 + 508 + sdata_assert_lock(sdata); 509 + 510 + rcu_read_lock(); 511 + 512 + list_for_each_entry_rcu(sta, &local->sta_list, list) { 513 + if (sta->sdata == sdata && 514 + time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL, 515 + jiffies)) { 516 + active++; 517 + break; 518 + } 519 + } 520 + 521 + rcu_read_unlock(); 522 + 523 + return active; 524 + } 525 + 526 + static void ieee80211_ibss_disconnect(struct ieee80211_sub_if_data *sdata) 527 + { 528 + struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 529 + struct ieee80211_local *local = sdata->local; 530 + struct cfg80211_bss *cbss; 531 + struct beacon_data *presp; 532 + struct sta_info *sta; 533 + int active_ibss; 534 + u16 capability; 535 + 536 + active_ibss = ieee80211_sta_active_ibss(sdata); 537 + 538 + if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) { 539 + capability = WLAN_CAPABILITY_IBSS; 540 + 541 + if (ifibss->privacy) 542 + capability |= WLAN_CAPABILITY_PRIVACY; 543 + 544 + cbss = cfg80211_get_bss(local->hw.wiphy, ifibss->chandef.chan, 545 + ifibss->bssid, ifibss->ssid, 546 + ifibss->ssid_len, WLAN_CAPABILITY_IBSS | 547 + WLAN_CAPABILITY_PRIVACY, 548 + capability); 549 + 550 + if (cbss) { 551 + cfg80211_unlink_bss(local->hw.wiphy, cbss); 552 + cfg80211_put_bss(sdata->local->hw.wiphy, cbss); 553 + } 554 + } 555 + 556 + ifibss->state = IEEE80211_IBSS_MLME_SEARCH; 557 + 558 + sta_info_flush(sdata); 559 + 560 + spin_lock_bh(&ifibss->incomplete_lock); 561 + while (!list_empty(&ifibss->incomplete_stations)) { 562 + sta = list_first_entry(&ifibss->incomplete_stations, 563 + struct sta_info, list); 564 + list_del(&sta->list); 565 + spin_unlock_bh(&ifibss->incomplete_lock); 566 + 567 + sta_info_free(local, sta); 568 + spin_lock_bh(&ifibss->incomplete_lock); 569 + } 570 + spin_unlock_bh(&ifibss->incomplete_lock); 571 + 572 + netif_carrier_off(sdata->dev); 573 + 574 + sdata->vif.bss_conf.ibss_joined = false; 575 + sdata->vif.bss_conf.ibss_creator = false; 576 + sdata->vif.bss_conf.enable_beacon = false; 577 + sdata->vif.bss_conf.ssid_len = 0; 578 + 579 + /* remove beacon */ 580 + presp = rcu_dereference_protected(ifibss->presp, 581 + lockdep_is_held(&sdata->wdev.mtx)); 582 + RCU_INIT_POINTER(sdata->u.ibss.presp, NULL); 583 + if (presp) 584 + kfree_rcu(presp, rcu_head); 585 + 586 + clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); 587 + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | 588 + BSS_CHANGED_IBSS); 589 + drv_leave_ibss(local, sdata); 590 + ieee80211_vif_release_channel(sdata); 591 + } 592 + 593 + static void ieee80211_csa_connection_drop_work(struct work_struct *work) 594 + { 595 + struct ieee80211_sub_if_data *sdata = 596 + container_of(work, struct ieee80211_sub_if_data, 597 + u.ibss.csa_connection_drop_work); 598 + 599 + ieee80211_ibss_disconnect(sdata); 600 + synchronize_rcu(); 601 + skb_queue_purge(&sdata->skb_queue); 602 + 603 + /* trigger a scan to find another IBSS network to join */ 604 + ieee80211_queue_work(&sdata->local->hw, &sdata->work); 605 + } 606 + 607 + static bool 608 + ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, 609 + struct ieee802_11_elems *elems, 610 + bool beacon) 611 + { 612 + struct cfg80211_csa_settings params; 613 + struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 614 + struct ieee80211_chanctx_conf *chanctx_conf; 615 + struct ieee80211_chanctx *chanctx; 616 + enum nl80211_channel_type ch_type; 617 + int err, num_chanctx; 618 + u32 sta_flags; 619 + u8 mode; 620 + 621 + if (sdata->vif.csa_active) 622 + return true; 623 + 624 + if (!sdata->vif.bss_conf.ibss_joined) 625 + return false; 626 + 627 + sta_flags = IEEE80211_STA_DISABLE_VHT; 628 + switch (ifibss->chandef.width) { 629 + case NL80211_CHAN_WIDTH_5: 630 + case NL80211_CHAN_WIDTH_10: 631 + case NL80211_CHAN_WIDTH_20_NOHT: 632 + sta_flags |= IEEE80211_STA_DISABLE_HT; 633 + /* fall through */ 634 + case NL80211_CHAN_WIDTH_20: 635 + sta_flags |= IEEE80211_STA_DISABLE_40MHZ; 636 + break; 637 + default: 638 + break; 639 + } 640 + 641 + memset(&params, 0, sizeof(params)); 642 + err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, 643 + ifibss->chandef.chan->band, 644 + sta_flags, ifibss->bssid, 645 + &params.count, &mode, 646 + &params.chandef); 647 + 648 + /* can't switch to destination channel, fail */ 649 + if (err < 0) 650 + goto disconnect; 651 + 652 + /* did not contain a CSA */ 653 + if (err) 654 + return false; 655 + 656 + if (ifibss->chandef.chan->band != params.chandef.chan->band) 657 + goto disconnect; 658 + 659 + switch (ifibss->chandef.width) { 660 + case NL80211_CHAN_WIDTH_20_NOHT: 661 + case NL80211_CHAN_WIDTH_20: 662 + case NL80211_CHAN_WIDTH_40: 663 + /* keep our current HT mode (HT20/HT40+/HT40-), even if 664 + * another mode has been announced. The mode is not adopted 665 + * within the beacon while doing CSA and we should therefore 666 + * keep the mode which we announce. 667 + */ 668 + ch_type = cfg80211_get_chandef_type(&ifibss->chandef); 669 + cfg80211_chandef_create(&params.chandef, params.chandef.chan, 670 + ch_type); 671 + break; 672 + case NL80211_CHAN_WIDTH_5: 673 + case NL80211_CHAN_WIDTH_10: 674 + if (params.chandef.width != ifibss->chandef.width) { 675 + sdata_info(sdata, 676 + "IBSS %pM received channel switch from incompatible channel width (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n", 677 + ifibss->bssid, 678 + params.chandef.chan->center_freq, 679 + params.chandef.width, 680 + params.chandef.center_freq1, 681 + params.chandef.center_freq2); 682 + goto disconnect; 683 + } 684 + break; 685 + default: 686 + /* should not happen, sta_flags should prevent VHT modes. */ 687 + WARN_ON(1); 688 + goto disconnect; 689 + } 690 + 691 + if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, &params.chandef, 692 + IEEE80211_CHAN_DISABLED)) { 693 + sdata_info(sdata, 694 + "IBSS %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n", 695 + ifibss->bssid, 696 + params.chandef.chan->center_freq, 697 + params.chandef.width, 698 + params.chandef.center_freq1, 699 + params.chandef.center_freq2); 700 + goto disconnect; 701 + } 702 + 703 + err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy, 704 + &params.chandef); 705 + if (err < 0) 706 + goto disconnect; 707 + if (err) { 708 + params.radar_required = true; 709 + 710 + /* TODO: IBSS-DFS not (yet) supported, disconnect. */ 711 + goto disconnect; 712 + } 713 + 714 + rcu_read_lock(); 715 + chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 716 + if (!chanctx_conf) { 717 + rcu_read_unlock(); 718 + goto disconnect; 719 + } 720 + 721 + /* don't handle for multi-VIF cases */ 722 + chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf); 723 + if (chanctx->refcount > 1) { 724 + rcu_read_unlock(); 725 + goto disconnect; 726 + } 727 + num_chanctx = 0; 728 + list_for_each_entry_rcu(chanctx, &sdata->local->chanctx_list, list) 729 + num_chanctx++; 730 + 731 + if (num_chanctx > 1) { 732 + rcu_read_unlock(); 733 + goto disconnect; 734 + } 735 + rcu_read_unlock(); 736 + 737 + /* all checks done, now perform the channel switch. */ 738 + ibss_dbg(sdata, 739 + "received channel switch announcement to go to channel %d MHz\n", 740 + params.chandef.chan->center_freq); 741 + 742 + params.block_tx = !!mode; 743 + 744 + ieee80211_ibss_csa_beacon(sdata, &params); 745 + sdata->csa_radar_required = params.radar_required; 746 + 747 + if (params.block_tx) 748 + ieee80211_stop_queues_by_reason(&sdata->local->hw, 749 + IEEE80211_MAX_QUEUE_MAP, 750 + IEEE80211_QUEUE_STOP_REASON_CSA); 751 + 752 + sdata->local->csa_chandef = params.chandef; 753 + sdata->vif.csa_active = true; 754 + 755 + ieee80211_bss_info_change_notify(sdata, err); 756 + drv_channel_switch_beacon(sdata, &params.chandef); 757 + 758 + return true; 759 + disconnect: 760 + ibss_dbg(sdata, "Can't handle channel switch, disconnect\n"); 761 + ieee80211_queue_work(&sdata->local->hw, 762 + &ifibss->csa_connection_drop_work); 763 + 764 + return true; 765 + } 766 + 767 + static void 768 + ieee80211_rx_mgmt_spectrum_mgmt(struct ieee80211_sub_if_data *sdata, 769 + struct ieee80211_mgmt *mgmt, size_t len, 770 + struct ieee80211_rx_status *rx_status, 771 + struct ieee802_11_elems *elems) 772 + { 773 + int required_len; 774 + 775 + if (len < IEEE80211_MIN_ACTION_SIZE + 1) 776 + return; 777 + 778 + /* CSA is the only action we handle for now */ 779 + if (mgmt->u.action.u.measurement.action_code != 780 + WLAN_ACTION_SPCT_CHL_SWITCH) 781 + return; 782 + 783 + required_len = IEEE80211_MIN_ACTION_SIZE + 784 + sizeof(mgmt->u.action.u.chan_switch); 785 + if (len < required_len) 786 + return; 787 + 788 + ieee80211_ibss_process_chanswitch(sdata, elems, false); 692 789 } 693 790 694 791 static void ieee80211_rx_mgmt_deauth_ibss(struct ieee80211_sub_if_data *sdata, ··· 1142 661 1143 662 /* check if we need to merge IBSS */ 1144 663 1145 - /* we use a fixed BSSID */ 1146 - if (sdata->u.ibss.fixed_bssid) 1147 - goto put_bss; 1148 - 1149 664 /* not an IBSS */ 1150 665 if (!(cbss->capability & WLAN_CAPABILITY_IBSS)) 1151 666 goto put_bss; ··· 1157 680 sdata->u.ibss.ssid_len)) 1158 681 goto put_bss; 1159 682 683 + /* process channel switch */ 684 + if (ieee80211_ibss_process_chanswitch(sdata, elems, true)) 685 + goto put_bss; 686 + 1160 687 /* same BSSID */ 1161 688 if (ether_addr_equal(cbss->bssid, sdata->u.ibss.bssid)) 689 + goto put_bss; 690 + 691 + /* we use a fixed BSSID */ 692 + if (sdata->u.ibss.fixed_bssid) 1162 693 goto put_bss; 1163 694 1164 695 if (ieee80211_have_rx_timestamp(rx_status)) { ··· 1258 773 list_add(&sta->list, &ifibss->incomplete_stations); 1259 774 spin_unlock(&ifibss->incomplete_lock); 1260 775 ieee80211_queue_work(&local->hw, &sdata->work); 1261 - } 1262 - 1263 - static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) 1264 - { 1265 - struct ieee80211_local *local = sdata->local; 1266 - int active = 0; 1267 - struct sta_info *sta; 1268 - 1269 - sdata_assert_lock(sdata); 1270 - 1271 - rcu_read_lock(); 1272 - 1273 - list_for_each_entry_rcu(sta, &local->sta_list, list) { 1274 - if (sta->sdata == sdata && 1275 - time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL, 1276 - jiffies)) { 1277 - active++; 1278 - break; 1279 - } 1280 - } 1281 - 1282 - rcu_read_unlock(); 1283 - 1284 - return active; 1285 776 } 1286 777 1287 778 static void ieee80211_ibss_sta_expire(struct ieee80211_sub_if_data *sdata) ··· 1537 1076 struct ieee80211_rx_status *rx_status; 1538 1077 struct ieee80211_mgmt *mgmt; 1539 1078 u16 fc; 1079 + struct ieee802_11_elems elems; 1080 + int ies_len; 1540 1081 1541 1082 rx_status = IEEE80211_SKB_RXCB(skb); 1542 1083 mgmt = (struct ieee80211_mgmt *) skb->data; ··· 1564 1101 case IEEE80211_STYPE_DEAUTH: 1565 1102 ieee80211_rx_mgmt_deauth_ibss(sdata, mgmt, skb->len); 1566 1103 break; 1104 + case IEEE80211_STYPE_ACTION: 1105 + switch (mgmt->u.action.category) { 1106 + case WLAN_CATEGORY_SPECTRUM_MGMT: 1107 + ies_len = skb->len - 1108 + offsetof(struct ieee80211_mgmt, 1109 + u.action.u.chan_switch.variable); 1110 + 1111 + if (ies_len < 0) 1112 + break; 1113 + 1114 + ieee802_11_parse_elems( 1115 + mgmt->u.action.u.chan_switch.variable, 1116 + ies_len, true, &elems); 1117 + 1118 + if (elems.parse_error) 1119 + break; 1120 + 1121 + ieee80211_rx_mgmt_spectrum_mgmt(sdata, mgmt, skb->len, 1122 + rx_status, &elems); 1123 + break; 1124 + } 1567 1125 } 1568 1126 1569 1127 mgmt_out: ··· 1651 1167 (unsigned long) sdata); 1652 1168 INIT_LIST_HEAD(&ifibss->incomplete_stations); 1653 1169 spin_lock_init(&ifibss->incomplete_lock); 1170 + INIT_WORK(&ifibss->csa_connection_drop_work, 1171 + ieee80211_csa_connection_drop_work); 1654 1172 } 1655 1173 1656 1174 /* scan finished notification */ ··· 1751 1265 int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) 1752 1266 { 1753 1267 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 1754 - struct ieee80211_local *local = sdata->local; 1755 - struct cfg80211_bss *cbss; 1756 - u16 capability; 1757 - int active_ibss; 1758 - struct sta_info *sta; 1759 - struct beacon_data *presp; 1760 1268 1761 - active_ibss = ieee80211_sta_active_ibss(sdata); 1762 - 1763 - if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) { 1764 - capability = WLAN_CAPABILITY_IBSS; 1765 - 1766 - if (ifibss->privacy) 1767 - capability |= WLAN_CAPABILITY_PRIVACY; 1768 - 1769 - cbss = cfg80211_get_bss(local->hw.wiphy, ifibss->chandef.chan, 1770 - ifibss->bssid, ifibss->ssid, 1771 - ifibss->ssid_len, WLAN_CAPABILITY_IBSS | 1772 - WLAN_CAPABILITY_PRIVACY, 1773 - capability); 1774 - 1775 - if (cbss) { 1776 - cfg80211_unlink_bss(local->hw.wiphy, cbss); 1777 - cfg80211_put_bss(local->hw.wiphy, cbss); 1778 - } 1779 - } 1780 - 1781 - ifibss->state = IEEE80211_IBSS_MLME_SEARCH; 1782 - memset(ifibss->bssid, 0, ETH_ALEN); 1269 + ieee80211_ibss_disconnect(sdata); 1783 1270 ifibss->ssid_len = 0; 1784 - 1785 - sta_info_flush(sdata); 1786 - 1787 - spin_lock_bh(&ifibss->incomplete_lock); 1788 - while (!list_empty(&ifibss->incomplete_stations)) { 1789 - sta = list_first_entry(&ifibss->incomplete_stations, 1790 - struct sta_info, list); 1791 - list_del(&sta->list); 1792 - spin_unlock_bh(&ifibss->incomplete_lock); 1793 - 1794 - sta_info_free(local, sta); 1795 - spin_lock_bh(&ifibss->incomplete_lock); 1796 - } 1797 - spin_unlock_bh(&ifibss->incomplete_lock); 1798 - 1799 - netif_carrier_off(sdata->dev); 1271 + memset(ifibss->bssid, 0, ETH_ALEN); 1800 1272 1801 1273 /* remove beacon */ 1802 1274 kfree(sdata->u.ibss.ie); 1803 - presp = rcu_dereference_protected(ifibss->presp, 1804 - lockdep_is_held(&sdata->wdev.mtx)); 1805 - RCU_INIT_POINTER(sdata->u.ibss.presp, NULL); 1806 1275 1807 1276 /* on the next join, re-program HT parameters */ 1808 1277 memset(&ifibss->ht_capa, 0, sizeof(ifibss->ht_capa)); 1809 1278 memset(&ifibss->ht_capa_mask, 0, sizeof(ifibss->ht_capa_mask)); 1810 1279 1811 - sdata->vif.bss_conf.ibss_joined = false; 1812 - sdata->vif.bss_conf.ibss_creator = false; 1813 - sdata->vif.bss_conf.enable_beacon = false; 1814 - sdata->vif.bss_conf.ssid_len = 0; 1815 - clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); 1816 - ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | 1817 - BSS_CHANGED_IBSS); 1818 - ieee80211_vif_release_channel(sdata); 1819 1280 synchronize_rcu(); 1820 - kfree(presp); 1821 1281 1822 1282 skb_queue_purge(&sdata->skb_queue); 1823 1283
+29 -1
net/mac80211/ieee80211_i.h
··· 322 322 323 323 /* flags used in struct ieee80211_if_managed.flags */ 324 324 enum ieee80211_sta_flags { 325 - IEEE80211_STA_BEACON_POLL = BIT(0), 326 325 IEEE80211_STA_CONNECTION_POLL = BIT(1), 327 326 IEEE80211_STA_CONTROL_PORT = BIT(2), 328 327 IEEE80211_STA_DISABLE_HT = BIT(4), ··· 486 487 487 488 struct ieee80211_if_ibss { 488 489 struct timer_list timer; 490 + struct work_struct csa_connection_drop_work; 489 491 490 492 unsigned long last_scan_completed; 491 493 ··· 1330 1330 void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata); 1331 1331 void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, 1332 1332 struct sk_buff *skb); 1333 + int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata, 1334 + struct cfg80211_csa_settings *csa_settings); 1335 + int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata); 1336 + void ieee80211_ibss_stop(struct ieee80211_sub_if_data *sdata); 1333 1337 1334 1338 /* mesh code */ 1335 1339 void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata); ··· 1485 1481 void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, 1486 1482 struct ieee80211_mgmt *mgmt, 1487 1483 size_t len); 1484 + /** 1485 + * ieee80211_parse_ch_switch_ie - parses channel switch IEs 1486 + * @sdata: the sdata of the interface which has received the frame 1487 + * @elems: parsed 802.11 elements received with the frame 1488 + * @beacon: indicates if the frame was a beacon or probe response 1489 + * @current_band: indicates the current band 1490 + * @sta_flags: contains information about own capabilities and restrictions 1491 + * to decide which channel switch announcements can be accepted. Only the 1492 + * following subset of &enum ieee80211_sta_flags are evaluated: 1493 + * %IEEE80211_STA_DISABLE_HT, %IEEE80211_STA_DISABLE_VHT, 1494 + * %IEEE80211_STA_DISABLE_40MHZ, %IEEE80211_STA_DISABLE_80P80MHZ, 1495 + * %IEEE80211_STA_DISABLE_160MHZ. 1496 + * @count: to be filled with the counter until the switch (on success only) 1497 + * @bssid: the currently connected bssid (for reporting) 1498 + * @mode: to be filled with CSA mode (on success only) 1499 + * @new_chandef: to be filled with destination chandef (on success only) 1500 + * Return: 0 on success, <0 on error and >0 if there is nothing to parse. 1501 + */ 1502 + int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, 1503 + struct ieee802_11_elems *elems, bool beacon, 1504 + enum ieee80211_band current_band, 1505 + u32 sta_flags, u8 *bssid, u8 *count, u8 *mode, 1506 + struct cfg80211_chan_def *new_chandef); 1488 1507 1489 1508 /* Suspend/resume and hw reconfiguration */ 1490 1509 int ieee80211_reconfig(struct ieee80211_local *local); ··· 1681 1654 void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, 1682 1655 const struct ieee80211_ht_operation *ht_oper, 1683 1656 struct cfg80211_chan_def *chandef); 1657 + u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c); 1684 1658 1685 1659 int __must_check 1686 1660 ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
+4
net/mac80211/iface.c
··· 766 766 if (sdata->vif.type == NL80211_IFTYPE_STATION) 767 767 ieee80211_mgd_stop(sdata); 768 768 769 + if (sdata->vif.type == NL80211_IFTYPE_ADHOC) 770 + ieee80211_ibss_stop(sdata); 771 + 772 + 769 773 /* 770 774 * Remove all stations associated with this interface. 771 775 *
+1 -1
net/mac80211/key.c
··· 879 879 keyconf->keylen, keyconf->key, 880 880 0, NULL); 881 881 if (IS_ERR(key)) 882 - return ERR_PTR(PTR_ERR(key)); 882 + return ERR_CAST(key); 883 883 884 884 if (sdata->u.mgd.mfp != IEEE80211_MFP_DISABLED) 885 885 key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT;
+70 -268
net/mac80211/mlme.c
··· 145 145 return (1 << ecw) - 1; 146 146 } 147 147 148 - static u32 chandef_downgrade(struct cfg80211_chan_def *c) 149 - { 150 - u32 ret; 151 - int tmp; 152 - 153 - switch (c->width) { 154 - case NL80211_CHAN_WIDTH_20: 155 - c->width = NL80211_CHAN_WIDTH_20_NOHT; 156 - ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; 157 - break; 158 - case NL80211_CHAN_WIDTH_40: 159 - c->width = NL80211_CHAN_WIDTH_20; 160 - c->center_freq1 = c->chan->center_freq; 161 - ret = IEEE80211_STA_DISABLE_40MHZ | 162 - IEEE80211_STA_DISABLE_VHT; 163 - break; 164 - case NL80211_CHAN_WIDTH_80: 165 - tmp = (30 + c->chan->center_freq - c->center_freq1)/20; 166 - /* n_P40 */ 167 - tmp /= 2; 168 - /* freq_P40 */ 169 - c->center_freq1 = c->center_freq1 - 20 + 40 * tmp; 170 - c->width = NL80211_CHAN_WIDTH_40; 171 - ret = IEEE80211_STA_DISABLE_VHT; 172 - break; 173 - case NL80211_CHAN_WIDTH_80P80: 174 - c->center_freq2 = 0; 175 - c->width = NL80211_CHAN_WIDTH_80; 176 - ret = IEEE80211_STA_DISABLE_80P80MHZ | 177 - IEEE80211_STA_DISABLE_160MHZ; 178 - break; 179 - case NL80211_CHAN_WIDTH_160: 180 - /* n_P20 */ 181 - tmp = (70 + c->chan->center_freq - c->center_freq1)/20; 182 - /* n_P80 */ 183 - tmp /= 4; 184 - c->center_freq1 = c->center_freq1 - 40 + 80 * tmp; 185 - c->width = NL80211_CHAN_WIDTH_80; 186 - ret = IEEE80211_STA_DISABLE_80P80MHZ | 187 - IEEE80211_STA_DISABLE_160MHZ; 188 - break; 189 - default: 190 - case NL80211_CHAN_WIDTH_20_NOHT: 191 - WARN_ON_ONCE(1); 192 - c->width = NL80211_CHAN_WIDTH_20_NOHT; 193 - ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; 194 - break; 195 - case NL80211_CHAN_WIDTH_5: 196 - case NL80211_CHAN_WIDTH_10: 197 - WARN_ON_ONCE(1); 198 - /* keep c->width */ 199 - ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; 200 - break; 201 - } 202 - 203 - WARN_ON_ONCE(!cfg80211_chandef_valid(c)); 204 - 205 - return ret; 206 - } 207 - 208 148 static u32 209 149 ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, 210 150 struct ieee80211_supported_band *sband, ··· 292 352 break; 293 353 } 294 354 295 - ret |= chandef_downgrade(chandef); 355 + ret |= ieee80211_chandef_downgrade(chandef); 296 356 } 297 357 298 358 if (chandef->width != vht_chandef.width && !tracking) ··· 346 406 */ 347 407 if (ifmgd->flags & IEEE80211_STA_DISABLE_80P80MHZ && 348 408 chandef.width == NL80211_CHAN_WIDTH_80P80) 349 - flags |= chandef_downgrade(&chandef); 409 + flags |= ieee80211_chandef_downgrade(&chandef); 350 410 if (ifmgd->flags & IEEE80211_STA_DISABLE_160MHZ && 351 411 chandef.width == NL80211_CHAN_WIDTH_160) 352 - flags |= chandef_downgrade(&chandef); 412 + flags |= ieee80211_chandef_downgrade(&chandef); 353 413 if (ifmgd->flags & IEEE80211_STA_DISABLE_40MHZ && 354 414 chandef.width > NL80211_CHAN_WIDTH_20) 355 - flags |= chandef_downgrade(&chandef); 415 + flags |= ieee80211_chandef_downgrade(&chandef); 356 416 357 417 if (cfg80211_chandef_identical(&chandef, &sdata->vif.bss_conf.chandef)) 358 418 return 0; ··· 833 893 if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) 834 894 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; 835 895 836 - if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | 837 - IEEE80211_STA_CONNECTION_POLL)) 896 + if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL) 838 897 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_USE_MINRATE; 839 898 840 899 ieee80211_tx_skb(sdata, skb); ··· 876 937 container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work); 877 938 struct ieee80211_local *local = sdata->local; 878 939 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 940 + u32 changed = 0; 941 + int ret; 879 942 880 943 if (!ieee80211_sdata_running(sdata)) 881 944 return; ··· 886 945 if (!ifmgd->associated) 887 946 goto out; 888 947 889 - local->_oper_chandef = local->csa_chandef; 948 + ret = ieee80211_vif_change_channel(sdata, &local->csa_chandef, 949 + &changed); 950 + if (ret) { 951 + sdata_info(sdata, 952 + "vif channel switch failed, disconnecting\n"); 953 + ieee80211_queue_work(&sdata->local->hw, 954 + &ifmgd->csa_connection_drop_work); 955 + goto out; 956 + } 890 957 891 - if (!local->ops->channel_switch) { 892 - /* call "hw_config" only if doing sw channel switch */ 893 - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); 894 - } else { 895 - /* update the device channel directly */ 896 - local->hw.conf.chandef = local->_oper_chandef; 958 + if (!local->use_chanctx) { 959 + local->_oper_chandef = local->csa_chandef; 960 + /* Call "hw_config" only if doing sw channel switch. 961 + * Otherwise update the channel directly 962 + */ 963 + if (!local->ops->channel_switch) 964 + ieee80211_hw_config(local, 0); 965 + else 966 + local->hw.conf.chandef = local->_oper_chandef; 897 967 } 898 968 899 969 /* XXX: shouldn't really modify cfg80211-owned data! */ 900 - ifmgd->associated->channel = local->_oper_chandef.chan; 970 + ifmgd->associated->channel = local->csa_chandef.chan; 901 971 902 972 /* XXX: wait for a beacon first? */ 903 973 ieee80211_wake_queues_by_reason(&local->hw, 904 974 IEEE80211_MAX_QUEUE_MAP, 905 975 IEEE80211_QUEUE_STOP_REASON_CSA); 976 + 977 + ieee80211_bss_info_change_notify(sdata, changed); 978 + 906 979 out: 980 + sdata->vif.csa_active = false; 907 981 ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; 908 982 sdata_unlock(sdata); 909 983 } ··· 956 1000 struct ieee80211_local *local = sdata->local; 957 1001 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 958 1002 struct cfg80211_bss *cbss = ifmgd->associated; 959 - struct ieee80211_bss *bss; 960 1003 struct ieee80211_chanctx *chanctx; 961 - enum ieee80211_band new_band; 962 - int new_freq; 963 - u8 new_chan_no; 1004 + enum ieee80211_band current_band; 964 1005 u8 count; 965 1006 u8 mode; 966 - struct ieee80211_channel *new_chan; 967 1007 struct cfg80211_chan_def new_chandef = {}; 968 - struct cfg80211_chan_def new_vht_chandef = {}; 969 - const struct ieee80211_sec_chan_offs_ie *sec_chan_offs; 970 - const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie; 971 - const struct ieee80211_ht_operation *ht_oper; 972 - int secondary_channel_offset = -1; 1008 + int res; 973 1009 974 1010 sdata_assert_lock(sdata); 975 1011 ··· 975 1027 if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED) 976 1028 return; 977 1029 978 - sec_chan_offs = elems->sec_chan_offs; 979 - wide_bw_chansw_ie = elems->wide_bw_chansw_ie; 980 - ht_oper = elems->ht_operation; 981 - 982 - if (ifmgd->flags & (IEEE80211_STA_DISABLE_HT | 983 - IEEE80211_STA_DISABLE_40MHZ)) { 984 - sec_chan_offs = NULL; 985 - wide_bw_chansw_ie = NULL; 986 - /* only used for bandwidth here */ 987 - ht_oper = NULL; 988 - } 989 - 990 - if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT) 991 - wide_bw_chansw_ie = NULL; 992 - 993 - if (elems->ext_chansw_ie) { 994 - if (!ieee80211_operating_class_to_band( 995 - elems->ext_chansw_ie->new_operating_class, 996 - &new_band)) { 997 - sdata_info(sdata, 998 - "cannot understand ECSA IE operating class %d, disconnecting\n", 999 - elems->ext_chansw_ie->new_operating_class); 1000 - ieee80211_queue_work(&local->hw, 1001 - &ifmgd->csa_connection_drop_work); 1002 - } 1003 - new_chan_no = elems->ext_chansw_ie->new_ch_num; 1004 - count = elems->ext_chansw_ie->count; 1005 - mode = elems->ext_chansw_ie->mode; 1006 - } else if (elems->ch_switch_ie) { 1007 - new_band = cbss->channel->band; 1008 - new_chan_no = elems->ch_switch_ie->new_ch_num; 1009 - count = elems->ch_switch_ie->count; 1010 - mode = elems->ch_switch_ie->mode; 1011 - } else { 1012 - /* nothing here we understand */ 1013 - return; 1014 - } 1015 - 1016 - bss = (void *)cbss->priv; 1017 - 1018 - new_freq = ieee80211_channel_to_frequency(new_chan_no, new_band); 1019 - new_chan = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq); 1020 - if (!new_chan || new_chan->flags & IEEE80211_CHAN_DISABLED) { 1021 - sdata_info(sdata, 1022 - "AP %pM switches to unsupported channel (%d MHz), disconnecting\n", 1023 - ifmgd->associated->bssid, new_freq); 1030 + current_band = cbss->channel->band; 1031 + res = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, current_band, 1032 + ifmgd->flags, 1033 + ifmgd->associated->bssid, &count, 1034 + &mode, &new_chandef); 1035 + if (res < 0) 1024 1036 ieee80211_queue_work(&local->hw, 1025 1037 &ifmgd->csa_connection_drop_work); 1038 + if (res) 1026 1039 return; 1027 - } 1028 - 1029 - if (!beacon && sec_chan_offs) { 1030 - secondary_channel_offset = sec_chan_offs->sec_chan_offs; 1031 - } else if (beacon && ht_oper) { 1032 - secondary_channel_offset = 1033 - ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET; 1034 - } else if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { 1035 - /* 1036 - * If it's not a beacon, HT is enabled and the IE not present, 1037 - * it's 20 MHz, 802.11-2012 8.5.2.6: 1038 - * This element [the Secondary Channel Offset Element] is 1039 - * present when switching to a 40 MHz channel. It may be 1040 - * present when switching to a 20 MHz channel (in which 1041 - * case the secondary channel offset is set to SCN). 1042 - */ 1043 - secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; 1044 - } 1045 - 1046 - switch (secondary_channel_offset) { 1047 - default: 1048 - /* secondary_channel_offset was present but is invalid */ 1049 - case IEEE80211_HT_PARAM_CHA_SEC_NONE: 1050 - cfg80211_chandef_create(&new_chandef, new_chan, 1051 - NL80211_CHAN_HT20); 1052 - break; 1053 - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: 1054 - cfg80211_chandef_create(&new_chandef, new_chan, 1055 - NL80211_CHAN_HT40PLUS); 1056 - break; 1057 - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: 1058 - cfg80211_chandef_create(&new_chandef, new_chan, 1059 - NL80211_CHAN_HT40MINUS); 1060 - break; 1061 - case -1: 1062 - cfg80211_chandef_create(&new_chandef, new_chan, 1063 - NL80211_CHAN_NO_HT); 1064 - /* keep width for 5/10 MHz channels */ 1065 - switch (sdata->vif.bss_conf.chandef.width) { 1066 - case NL80211_CHAN_WIDTH_5: 1067 - case NL80211_CHAN_WIDTH_10: 1068 - new_chandef.width = sdata->vif.bss_conf.chandef.width; 1069 - break; 1070 - default: 1071 - break; 1072 - } 1073 - break; 1074 - } 1075 - 1076 - if (wide_bw_chansw_ie) { 1077 - new_vht_chandef.chan = new_chan; 1078 - new_vht_chandef.center_freq1 = 1079 - ieee80211_channel_to_frequency( 1080 - wide_bw_chansw_ie->new_center_freq_seg0, 1081 - new_band); 1082 - 1083 - switch (wide_bw_chansw_ie->new_channel_width) { 1084 - default: 1085 - /* hmmm, ignore VHT and use HT if present */ 1086 - case IEEE80211_VHT_CHANWIDTH_USE_HT: 1087 - new_vht_chandef.chan = NULL; 1088 - break; 1089 - case IEEE80211_VHT_CHANWIDTH_80MHZ: 1090 - new_vht_chandef.width = NL80211_CHAN_WIDTH_80; 1091 - break; 1092 - case IEEE80211_VHT_CHANWIDTH_160MHZ: 1093 - new_vht_chandef.width = NL80211_CHAN_WIDTH_160; 1094 - break; 1095 - case IEEE80211_VHT_CHANWIDTH_80P80MHZ: 1096 - /* field is otherwise reserved */ 1097 - new_vht_chandef.center_freq2 = 1098 - ieee80211_channel_to_frequency( 1099 - wide_bw_chansw_ie->new_center_freq_seg1, 1100 - new_band); 1101 - new_vht_chandef.width = NL80211_CHAN_WIDTH_80P80; 1102 - break; 1103 - } 1104 - if (ifmgd->flags & IEEE80211_STA_DISABLE_80P80MHZ && 1105 - new_vht_chandef.width == NL80211_CHAN_WIDTH_80P80) 1106 - chandef_downgrade(&new_vht_chandef); 1107 - if (ifmgd->flags & IEEE80211_STA_DISABLE_160MHZ && 1108 - new_vht_chandef.width == NL80211_CHAN_WIDTH_160) 1109 - chandef_downgrade(&new_vht_chandef); 1110 - if (ifmgd->flags & IEEE80211_STA_DISABLE_40MHZ && 1111 - new_vht_chandef.width > NL80211_CHAN_WIDTH_20) 1112 - chandef_downgrade(&new_vht_chandef); 1113 - } 1114 - 1115 - /* if VHT data is there validate & use it */ 1116 - if (new_vht_chandef.chan) { 1117 - if (!cfg80211_chandef_compatible(&new_vht_chandef, 1118 - &new_chandef)) { 1119 - sdata_info(sdata, 1120 - "AP %pM CSA has inconsistent channel data, disconnecting\n", 1121 - ifmgd->associated->bssid); 1122 - ieee80211_queue_work(&local->hw, 1123 - &ifmgd->csa_connection_drop_work); 1124 - return; 1125 - } 1126 - new_chandef = new_vht_chandef; 1127 - } 1128 1040 1129 1041 if (!cfg80211_chandef_usable(local->hw.wiphy, &new_chandef, 1130 1042 IEEE80211_CHAN_DISABLED)) { 1131 1043 sdata_info(sdata, 1132 1044 "AP %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n", 1133 - ifmgd->associated->bssid, new_freq, 1045 + ifmgd->associated->bssid, 1046 + new_chandef.chan->center_freq, 1134 1047 new_chandef.width, new_chandef.center_freq1, 1135 1048 new_chandef.center_freq2); 1136 1049 ieee80211_queue_work(&local->hw, ··· 1000 1191 } 1001 1192 1002 1193 ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; 1003 - 1004 - if (local->use_chanctx) { 1005 - sdata_info(sdata, 1006 - "not handling channel switch with channel contexts\n"); 1007 - ieee80211_queue_work(&local->hw, 1008 - &ifmgd->csa_connection_drop_work); 1009 - return; 1010 - } 1194 + sdata->vif.csa_active = true; 1011 1195 1012 1196 mutex_lock(&local->chanctx_mtx); 1197 + if (local->use_chanctx) { 1198 + u32 num_chanctx = 0; 1199 + list_for_each_entry(chanctx, &local->chanctx_list, list) 1200 + num_chanctx++; 1201 + 1202 + if (num_chanctx > 1 || 1203 + !(local->hw.flags & IEEE80211_HW_CHANCTX_STA_CSA)) { 1204 + sdata_info(sdata, 1205 + "not handling chan-switch with channel contexts\n"); 1206 + ieee80211_queue_work(&local->hw, 1207 + &ifmgd->csa_connection_drop_work); 1208 + mutex_unlock(&local->chanctx_mtx); 1209 + return; 1210 + } 1211 + } 1212 + 1013 1213 if (WARN_ON(!rcu_access_pointer(sdata->vif.chanctx_conf))) { 1214 + ieee80211_queue_work(&local->hw, 1215 + &ifmgd->csa_connection_drop_work); 1014 1216 mutex_unlock(&local->chanctx_mtx); 1015 1217 return; 1016 1218 } ··· 1194 1374 if (!mgd->associated) 1195 1375 return false; 1196 1376 1197 - if (mgd->flags & (IEEE80211_STA_BEACON_POLL | 1198 - IEEE80211_STA_CONNECTION_POLL)) 1377 + if (mgd->flags & IEEE80211_STA_CONNECTION_POLL) 1199 1378 return false; 1200 1379 1201 1380 if (!mgd->have_beacon) ··· 1510 1691 { 1511 1692 lockdep_assert_held(&sdata->local->mtx); 1512 1693 1513 - sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | 1514 - IEEE80211_STA_BEACON_POLL); 1694 + sdata->u.mgd.flags &= ~IEEE80211_STA_CONNECTION_POLL; 1515 1695 ieee80211_run_deferred_scan(sdata->local); 1516 1696 } 1517 1697 ··· 1772 1954 struct ieee80211_local *local = sdata->local; 1773 1955 1774 1956 mutex_lock(&local->mtx); 1775 - if (!(ifmgd->flags & (IEEE80211_STA_BEACON_POLL | 1776 - IEEE80211_STA_CONNECTION_POLL))) { 1777 - mutex_unlock(&local->mtx); 1778 - return; 1779 - } 1957 + if (!(ifmgd->flags & IEEE80211_STA_CONNECTION_POLL)) 1958 + goto out; 1780 1959 1781 1960 __ieee80211_stop_poll(sdata); 1782 1961 ··· 1909 2094 * because otherwise we would reset the timer every time and 1910 2095 * never check whether we received a probe response! 1911 2096 */ 1912 - if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | 1913 - IEEE80211_STA_CONNECTION_POLL)) 2097 + if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL) 1914 2098 already = true; 1915 - 1916 - if (beacon) 1917 - ifmgd->flags |= IEEE80211_STA_BEACON_POLL; 1918 - else 1919 - ifmgd->flags |= IEEE80211_STA_CONNECTION_POLL; 1920 2099 1921 2100 mutex_unlock(&sdata->local->mtx); 1922 2101 ··· 1983 2174 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, 1984 2175 true, frame_buf); 1985 2176 ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; 2177 + sdata->vif.csa_active = false; 1986 2178 ieee80211_wake_queues_by_reason(&sdata->local->hw, 1987 2179 IEEE80211_MAX_QUEUE_MAP, 1988 2180 IEEE80211_QUEUE_STOP_REASON_CSA); ··· 2871 3061 } 2872 3062 } 2873 3063 2874 - if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) { 3064 + if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL) { 2875 3065 mlme_dbg_ratelimited(sdata, 2876 3066 "cancelling AP probe due to a received beacon\n"); 2877 - mutex_lock(&local->mtx); 2878 - ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL; 2879 - ieee80211_run_deferred_scan(local); 2880 - mutex_unlock(&local->mtx); 2881 - 2882 - mutex_lock(&local->iflist_mtx); 2883 - ieee80211_recalc_ps(local, -1); 2884 - mutex_unlock(&local->iflist_mtx); 3067 + ieee80211_reset_ap_probe(sdata); 2885 3068 } 2886 3069 2887 3070 /* ··· 3346 3543 } else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started) 3347 3544 run_again(sdata, ifmgd->assoc_data->timeout); 3348 3545 3349 - if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | 3350 - IEEE80211_STA_CONNECTION_POLL) && 3546 + if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL && 3351 3547 ifmgd->associated) { 3352 3548 u8 bssid[ETH_ALEN]; 3353 3549 int max_tries; ··· 3678 3876 return ret; 3679 3877 3680 3878 while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) { 3681 - ifmgd->flags |= chandef_downgrade(&chandef); 3879 + ifmgd->flags |= ieee80211_chandef_downgrade(&chandef); 3682 3880 ret = ieee80211_vif_use_channel(sdata, &chandef, 3683 3881 IEEE80211_CHANCTX_SHARED); 3684 3882 }
+14
net/mac80211/rc80211_minstrel.c
··· 203 203 memcpy(mi->max_tp_rate, tmp_tp_rate, sizeof(mi->max_tp_rate)); 204 204 mi->max_prob_rate = tmp_prob_rate; 205 205 206 + #ifdef CONFIG_MAC80211_DEBUGFS 207 + /* use fixed index if set */ 208 + if (mp->fixed_rate_idx != -1) { 209 + mi->max_tp_rate[0] = mp->fixed_rate_idx; 210 + mi->max_tp_rate[1] = mp->fixed_rate_idx; 211 + mi->max_prob_rate = mp->fixed_rate_idx; 212 + } 213 + #endif 214 + 206 215 /* Reset update timer */ 207 216 mi->stats_update = jiffies; 208 217 ··· 318 309 319 310 /* increase sum packet counter */ 320 311 mi->packet_count++; 312 + 313 + #ifdef CONFIG_MAC80211_DEBUGFS 314 + if (mp->fixed_rate_idx != -1) 315 + return; 316 + #endif 321 317 322 318 delta = (mi->packet_count * sampling_ratio / 100) - 323 319 (mi->sample_count + mi->sample_deferred / 2);
+13 -10
net/mac80211/rc80211_minstrel_ht.c
··· 365 365 } 366 366 } 367 367 368 + #ifdef CONFIG_MAC80211_DEBUGFS 369 + /* use fixed index if set */ 370 + if (mp->fixed_rate_idx != -1) { 371 + mi->max_tp_rate = mp->fixed_rate_idx; 372 + mi->max_tp_rate2 = mp->fixed_rate_idx; 373 + mi->max_prob_rate = mp->fixed_rate_idx; 374 + } 375 + #endif 368 376 369 377 mi->stats_update = jiffies; 370 378 } ··· 782 774 info->flags |= mi->tx_flags; 783 775 minstrel_ht_check_cck_shortpreamble(mp, mi, txrc->short_preamble); 784 776 777 + #ifdef CONFIG_MAC80211_DEBUGFS 778 + if (mp->fixed_rate_idx != -1) 779 + return; 780 + #endif 781 + 785 782 /* Don't use EAPOL frames for sampling on non-mrr hw */ 786 783 if (mp->hw->max_rates == 1 && 787 784 (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) 788 785 sample_idx = -1; 789 786 else 790 787 sample_idx = minstrel_get_sample_rate(mp, mi); 791 - 792 - #ifdef CONFIG_MAC80211_DEBUGFS 793 - /* use fixed index if set */ 794 - if (mp->fixed_rate_idx != -1) { 795 - mi->max_tp_rate = mp->fixed_rate_idx; 796 - mi->max_tp_rate2 = mp->fixed_rate_idx; 797 - mi->max_prob_rate = mp->fixed_rate_idx; 798 - sample_idx = -1; 799 - } 800 - #endif 801 788 802 789 mi->total_packets++; 803 790
+13 -13
net/mac80211/rc80211_pid_debugfs.c
··· 167 167 * provide large enough buffers. */ 168 168 length = length < RC_PID_PRINT_BUF_SIZE ? 169 169 length : RC_PID_PRINT_BUF_SIZE; 170 - p = snprintf(pb, length, "%u %lu ", ev->id, ev->timestamp); 170 + p = scnprintf(pb, length, "%u %lu ", ev->id, ev->timestamp); 171 171 switch (ev->type) { 172 172 case RC_PID_EVENT_TYPE_TX_STATUS: 173 - p += snprintf(pb + p, length - p, "tx_status %u %u", 174 - !(ev->data.flags & IEEE80211_TX_STAT_ACK), 175 - ev->data.tx_status.status.rates[0].idx); 173 + p += scnprintf(pb + p, length - p, "tx_status %u %u", 174 + !(ev->data.flags & IEEE80211_TX_STAT_ACK), 175 + ev->data.tx_status.status.rates[0].idx); 176 176 break; 177 177 case RC_PID_EVENT_TYPE_RATE_CHANGE: 178 - p += snprintf(pb + p, length - p, "rate_change %d %d", 179 - ev->data.index, ev->data.rate); 178 + p += scnprintf(pb + p, length - p, "rate_change %d %d", 179 + ev->data.index, ev->data.rate); 180 180 break; 181 181 case RC_PID_EVENT_TYPE_TX_RATE: 182 - p += snprintf(pb + p, length - p, "tx_rate %d %d", 183 - ev->data.index, ev->data.rate); 182 + p += scnprintf(pb + p, length - p, "tx_rate %d %d", 183 + ev->data.index, ev->data.rate); 184 184 break; 185 185 case RC_PID_EVENT_TYPE_PF_SAMPLE: 186 - p += snprintf(pb + p, length - p, 187 - "pf_sample %d %d %d %d", 188 - ev->data.pf_sample, ev->data.prop_err, 189 - ev->data.int_err, ev->data.der_err); 186 + p += scnprintf(pb + p, length - p, 187 + "pf_sample %d %d %d %d", 188 + ev->data.pf_sample, ev->data.prop_err, 189 + ev->data.int_err, ev->data.der_err); 190 190 break; 191 191 } 192 - p += snprintf(pb + p, length - p, "\n"); 192 + p += scnprintf(pb + p, length - p, "\n"); 193 193 194 194 spin_unlock_irqrestore(&events->lock, status); 195 195
+29 -12
net/mac80211/rx.c
··· 995 995 rx->sta->num_duplicates++; 996 996 } 997 997 return RX_DROP_UNUSABLE; 998 - } else 998 + } else if (!(status->flag & RX_FLAG_AMSDU_MORE)) { 999 999 rx->sta->last_seq_ctrl[rx->seqno_idx] = hdr->seq_ctrl; 1000 + } 1000 1001 } 1001 1002 1002 1003 if (unlikely(rx->skb->len < 16)) { ··· 2403 2402 return RX_DROP_UNUSABLE; 2404 2403 2405 2404 if (!rx->sta && mgmt->u.action.category != WLAN_CATEGORY_PUBLIC && 2406 - mgmt->u.action.category != WLAN_CATEGORY_SELF_PROTECTED) 2405 + mgmt->u.action.category != WLAN_CATEGORY_SELF_PROTECTED && 2406 + mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT) 2407 2407 return RX_DROP_UNUSABLE; 2408 2408 2409 2409 if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) ··· 2568 2566 2569 2567 goto queue; 2570 2568 case WLAN_CATEGORY_SPECTRUM_MGMT: 2571 - if (status->band != IEEE80211_BAND_5GHZ) 2572 - break; 2573 - 2574 - if (sdata->vif.type != NL80211_IFTYPE_STATION) 2575 - break; 2576 - 2577 2569 /* verify action_code is present */ 2578 2570 if (len < IEEE80211_MIN_ACTION_SIZE + 1) 2579 2571 break; 2580 2572 2581 2573 switch (mgmt->u.action.u.measurement.action_code) { 2582 2574 case WLAN_ACTION_SPCT_MSR_REQ: 2575 + if (status->band != IEEE80211_BAND_5GHZ) 2576 + break; 2577 + 2583 2578 if (len < (IEEE80211_MIN_ACTION_SIZE + 2584 2579 sizeof(mgmt->u.action.u.measurement))) 2585 2580 break; 2586 - ieee80211_process_measurement_req(sdata, mgmt, len); 2587 - goto handled; 2588 - case WLAN_ACTION_SPCT_CHL_SWITCH: 2581 + 2589 2582 if (sdata->vif.type != NL80211_IFTYPE_STATION) 2590 2583 break; 2591 2584 2592 - if (!ether_addr_equal(mgmt->bssid, sdata->u.mgd.bssid)) 2585 + ieee80211_process_measurement_req(sdata, mgmt, len); 2586 + goto handled; 2587 + case WLAN_ACTION_SPCT_CHL_SWITCH: { 2588 + u8 *bssid; 2589 + if (len < (IEEE80211_MIN_ACTION_SIZE + 2590 + sizeof(mgmt->u.action.u.chan_switch))) 2591 + break; 2592 + 2593 + if (sdata->vif.type != NL80211_IFTYPE_STATION && 2594 + sdata->vif.type != NL80211_IFTYPE_ADHOC) 2595 + break; 2596 + 2597 + if (sdata->vif.type == NL80211_IFTYPE_STATION) 2598 + bssid = sdata->u.mgd.bssid; 2599 + else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) 2600 + bssid = sdata->u.ibss.bssid; 2601 + else 2602 + break; 2603 + 2604 + if (!ether_addr_equal(mgmt->bssid, bssid)) 2593 2605 break; 2594 2606 2595 2607 goto queue; 2608 + } 2596 2609 } 2597 2610 break; 2598 2611 case WLAN_CATEGORY_SA_QUERY:
+1 -2
net/mac80211/scan.c
··· 391 391 return false; 392 392 393 393 if (sdata->vif.type == NL80211_IFTYPE_STATION && 394 - sdata->u.mgd.flags & (IEEE80211_STA_BEACON_POLL | 395 - IEEE80211_STA_CONNECTION_POLL)) 394 + sdata->u.mgd.flags & IEEE80211_STA_CONNECTION_POLL) 396 395 return false; 397 396 398 397 return true;
+162
net/mac80211/spectmgmt.c
··· 21 21 #include "sta_info.h" 22 22 #include "wme.h" 23 23 24 + int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, 25 + struct ieee802_11_elems *elems, bool beacon, 26 + enum ieee80211_band current_band, 27 + u32 sta_flags, u8 *bssid, u8 *count, u8 *mode, 28 + struct cfg80211_chan_def *new_chandef) 29 + { 30 + enum ieee80211_band new_band; 31 + int new_freq; 32 + u8 new_chan_no; 33 + struct ieee80211_channel *new_chan; 34 + struct cfg80211_chan_def new_vht_chandef = {}; 35 + const struct ieee80211_sec_chan_offs_ie *sec_chan_offs; 36 + const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie; 37 + const struct ieee80211_ht_operation *ht_oper; 38 + int secondary_channel_offset = -1; 39 + 40 + sec_chan_offs = elems->sec_chan_offs; 41 + wide_bw_chansw_ie = elems->wide_bw_chansw_ie; 42 + ht_oper = elems->ht_operation; 43 + 44 + if (sta_flags & (IEEE80211_STA_DISABLE_HT | 45 + IEEE80211_STA_DISABLE_40MHZ)) { 46 + sec_chan_offs = NULL; 47 + wide_bw_chansw_ie = NULL; 48 + /* only used for bandwidth here */ 49 + ht_oper = NULL; 50 + } 51 + 52 + if (sta_flags & IEEE80211_STA_DISABLE_VHT) 53 + wide_bw_chansw_ie = NULL; 54 + 55 + if (elems->ext_chansw_ie) { 56 + if (!ieee80211_operating_class_to_band( 57 + elems->ext_chansw_ie->new_operating_class, 58 + &new_band)) { 59 + sdata_info(sdata, 60 + "cannot understand ECSA IE operating class %d, disconnecting\n", 61 + elems->ext_chansw_ie->new_operating_class); 62 + return -EINVAL; 63 + } 64 + new_chan_no = elems->ext_chansw_ie->new_ch_num; 65 + *count = elems->ext_chansw_ie->count; 66 + *mode = elems->ext_chansw_ie->mode; 67 + } else if (elems->ch_switch_ie) { 68 + new_band = current_band; 69 + new_chan_no = elems->ch_switch_ie->new_ch_num; 70 + *count = elems->ch_switch_ie->count; 71 + *mode = elems->ch_switch_ie->mode; 72 + } else { 73 + /* nothing here we understand */ 74 + return 1; 75 + } 76 + 77 + new_freq = ieee80211_channel_to_frequency(new_chan_no, new_band); 78 + new_chan = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq); 79 + if (!new_chan || new_chan->flags & IEEE80211_CHAN_DISABLED) { 80 + sdata_info(sdata, 81 + "BSS %pM switches to unsupported channel (%d MHz), disconnecting\n", 82 + bssid, new_freq); 83 + return -EINVAL; 84 + } 85 + 86 + if (!beacon && sec_chan_offs) { 87 + secondary_channel_offset = sec_chan_offs->sec_chan_offs; 88 + } else if (beacon && ht_oper) { 89 + secondary_channel_offset = 90 + ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET; 91 + } else if (!(sta_flags & IEEE80211_STA_DISABLE_HT)) { 92 + /* If it's not a beacon, HT is enabled and the IE not present, 93 + * it's 20 MHz, 802.11-2012 8.5.2.6: 94 + * This element [the Secondary Channel Offset Element] is 95 + * present when switching to a 40 MHz channel. It may be 96 + * present when switching to a 20 MHz channel (in which 97 + * case the secondary channel offset is set to SCN). 98 + */ 99 + secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; 100 + } 101 + 102 + switch (secondary_channel_offset) { 103 + default: 104 + /* secondary_channel_offset was present but is invalid */ 105 + case IEEE80211_HT_PARAM_CHA_SEC_NONE: 106 + cfg80211_chandef_create(new_chandef, new_chan, 107 + NL80211_CHAN_HT20); 108 + break; 109 + case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: 110 + cfg80211_chandef_create(new_chandef, new_chan, 111 + NL80211_CHAN_HT40PLUS); 112 + break; 113 + case IEEE80211_HT_PARAM_CHA_SEC_BELOW: 114 + cfg80211_chandef_create(new_chandef, new_chan, 115 + NL80211_CHAN_HT40MINUS); 116 + break; 117 + case -1: 118 + cfg80211_chandef_create(new_chandef, new_chan, 119 + NL80211_CHAN_NO_HT); 120 + /* keep width for 5/10 MHz channels */ 121 + switch (sdata->vif.bss_conf.chandef.width) { 122 + case NL80211_CHAN_WIDTH_5: 123 + case NL80211_CHAN_WIDTH_10: 124 + new_chandef->width = sdata->vif.bss_conf.chandef.width; 125 + break; 126 + default: 127 + break; 128 + } 129 + break; 130 + } 131 + 132 + if (wide_bw_chansw_ie) { 133 + new_vht_chandef.chan = new_chan; 134 + new_vht_chandef.center_freq1 = 135 + ieee80211_channel_to_frequency( 136 + wide_bw_chansw_ie->new_center_freq_seg0, 137 + new_band); 138 + 139 + switch (wide_bw_chansw_ie->new_channel_width) { 140 + default: 141 + /* hmmm, ignore VHT and use HT if present */ 142 + case IEEE80211_VHT_CHANWIDTH_USE_HT: 143 + new_vht_chandef.chan = NULL; 144 + break; 145 + case IEEE80211_VHT_CHANWIDTH_80MHZ: 146 + new_vht_chandef.width = NL80211_CHAN_WIDTH_80; 147 + break; 148 + case IEEE80211_VHT_CHANWIDTH_160MHZ: 149 + new_vht_chandef.width = NL80211_CHAN_WIDTH_160; 150 + break; 151 + case IEEE80211_VHT_CHANWIDTH_80P80MHZ: 152 + /* field is otherwise reserved */ 153 + new_vht_chandef.center_freq2 = 154 + ieee80211_channel_to_frequency( 155 + wide_bw_chansw_ie->new_center_freq_seg1, 156 + new_band); 157 + new_vht_chandef.width = NL80211_CHAN_WIDTH_80P80; 158 + break; 159 + } 160 + if (sta_flags & IEEE80211_STA_DISABLE_80P80MHZ && 161 + new_vht_chandef.width == NL80211_CHAN_WIDTH_80P80) 162 + ieee80211_chandef_downgrade(&new_vht_chandef); 163 + if (sta_flags & IEEE80211_STA_DISABLE_160MHZ && 164 + new_vht_chandef.width == NL80211_CHAN_WIDTH_160) 165 + ieee80211_chandef_downgrade(&new_vht_chandef); 166 + if (sta_flags & IEEE80211_STA_DISABLE_40MHZ && 167 + new_vht_chandef.width > NL80211_CHAN_WIDTH_20) 168 + ieee80211_chandef_downgrade(&new_vht_chandef); 169 + } 170 + 171 + /* if VHT data is there validate & use it */ 172 + if (new_vht_chandef.chan) { 173 + if (!cfg80211_chandef_compatible(&new_vht_chandef, 174 + new_chandef)) { 175 + sdata_info(sdata, 176 + "BSS %pM: CSA has inconsistent channel data, disconnecting\n", 177 + bssid); 178 + return -EINVAL; 179 + } 180 + *new_chandef = new_vht_chandef; 181 + } 182 + 183 + return 0; 184 + } 185 + 24 186 static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_data *sdata, 25 187 struct ieee80211_msrment_ie *request_ie, 26 188 const u8 *da, const u8 *bssid,
+35
net/mac80211/trace.h
··· 1475 1475 ); 1476 1476 #endif 1477 1477 1478 + TRACE_EVENT(drv_join_ibss, 1479 + TP_PROTO(struct ieee80211_local *local, 1480 + struct ieee80211_sub_if_data *sdata, 1481 + struct ieee80211_bss_conf *info), 1482 + 1483 + TP_ARGS(local, sdata, info), 1484 + 1485 + TP_STRUCT__entry( 1486 + LOCAL_ENTRY 1487 + VIF_ENTRY 1488 + __field(u8, dtimper) 1489 + __field(u16, bcnint) 1490 + __dynamic_array(u8, ssid, info->ssid_len); 1491 + ), 1492 + 1493 + TP_fast_assign( 1494 + LOCAL_ASSIGN; 1495 + VIF_ASSIGN; 1496 + __entry->dtimper = info->dtim_period; 1497 + __entry->bcnint = info->beacon_int; 1498 + memcpy(__get_dynamic_array(ssid), info->ssid, info->ssid_len); 1499 + ), 1500 + 1501 + TP_printk( 1502 + LOCAL_PR_FMT VIF_PR_FMT, 1503 + LOCAL_PR_ARG, VIF_PR_ARG 1504 + ) 1505 + ); 1506 + 1507 + DEFINE_EVENT(local_sdata_evt, drv_leave_ibss, 1508 + TP_PROTO(struct ieee80211_local *local, 1509 + struct ieee80211_sub_if_data *sdata), 1510 + TP_ARGS(local, sdata) 1511 + ); 1512 + 1478 1513 /* 1479 1514 * Tracing for API calls that drivers call. 1480 1515 */
+35 -6
net/mac80211/tx.c
··· 1981 1981 * EAPOL frames from the local station. 1982 1982 */ 1983 1983 if (unlikely(!ieee80211_vif_is_mesh(&sdata->vif) && 1984 - !is_multicast_ether_addr(hdr.addr1) && !authorized && 1984 + !multicast && !authorized && 1985 1985 (cpu_to_be16(ethertype) != sdata->control_port_protocol || 1986 1986 !ether_addr_equal(sdata->vif.addr, skb->data + ETH_ALEN)))) { 1987 1987 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG ··· 2357 2357 struct probe_resp *resp; 2358 2358 int counter_offset_beacon = sdata->csa_counter_offset_beacon; 2359 2359 int counter_offset_presp = sdata->csa_counter_offset_presp; 2360 + u8 *beacon_data; 2361 + size_t beacon_data_len; 2360 2362 2361 - /* warn if the driver did not check for/react to csa completeness */ 2362 - if (WARN_ON(((u8 *)beacon->tail)[counter_offset_beacon] == 0)) 2363 + switch (sdata->vif.type) { 2364 + case NL80211_IFTYPE_AP: 2365 + beacon_data = beacon->tail; 2366 + beacon_data_len = beacon->tail_len; 2367 + break; 2368 + case NL80211_IFTYPE_ADHOC: 2369 + beacon_data = beacon->head; 2370 + beacon_data_len = beacon->head_len; 2371 + break; 2372 + default: 2373 + return; 2374 + } 2375 + if (WARN_ON(counter_offset_beacon >= beacon_data_len)) 2363 2376 return; 2364 2377 2365 - ((u8 *)beacon->tail)[counter_offset_beacon]--; 2378 + /* warn if the driver did not check for/react to csa completeness */ 2379 + if (WARN_ON(beacon_data[counter_offset_beacon] == 0)) 2380 + return; 2366 2381 2367 - if (sdata->vif.type == NL80211_IFTYPE_AP && 2368 - counter_offset_presp) { 2382 + beacon_data[counter_offset_beacon]--; 2383 + 2384 + if (sdata->vif.type == NL80211_IFTYPE_AP && counter_offset_presp) { 2369 2385 rcu_read_lock(); 2370 2386 resp = rcu_dereference(sdata->u.ap.probe_resp); 2371 2387 ··· 2416 2400 goto out; 2417 2401 beacon_data = beacon->tail; 2418 2402 beacon_data_len = beacon->tail_len; 2403 + } else if (vif->type == NL80211_IFTYPE_ADHOC) { 2404 + struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 2405 + 2406 + beacon = rcu_dereference(ifibss->presp); 2407 + if (!beacon) 2408 + goto out; 2409 + 2410 + beacon_data = beacon->head; 2411 + beacon_data_len = beacon->head_len; 2419 2412 } else { 2420 2413 WARN_ON(1); 2421 2414 goto out; ··· 2508 2483 2509 2484 if (!presp) 2510 2485 goto out; 2486 + 2487 + if (sdata->vif.csa_active) 2488 + ieee80211_update_csa(sdata, presp); 2489 + 2511 2490 2512 2491 skb = dev_alloc_skb(local->tx_headroom + presp->head_len); 2513 2492 if (!skb)
+123 -65
net/mac80211/util.c
··· 567 567 IEEE80211_QUEUE_STOP_REASON_FLUSH); 568 568 } 569 569 570 - void ieee80211_iterate_active_interfaces( 571 - struct ieee80211_hw *hw, u32 iter_flags, 572 - void (*iterator)(void *data, u8 *mac, 573 - struct ieee80211_vif *vif), 574 - void *data) 570 + static void __iterate_active_interfaces(struct ieee80211_local *local, 571 + u32 iter_flags, 572 + void (*iterator)(void *data, u8 *mac, 573 + struct ieee80211_vif *vif), 574 + void *data) 575 575 { 576 - struct ieee80211_local *local = hw_to_local(hw); 577 576 struct ieee80211_sub_if_data *sdata; 578 - 579 - mutex_lock(&local->iflist_mtx); 580 - 581 - list_for_each_entry(sdata, &local->interfaces, list) { 582 - switch (sdata->vif.type) { 583 - case NL80211_IFTYPE_MONITOR: 584 - if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) 585 - continue; 586 - break; 587 - case NL80211_IFTYPE_AP_VLAN: 588 - continue; 589 - default: 590 - break; 591 - } 592 - if (!(iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL) && 593 - !(sdata->flags & IEEE80211_SDATA_IN_DRIVER)) 594 - continue; 595 - if (ieee80211_sdata_running(sdata)) 596 - iterator(data, sdata->vif.addr, 597 - &sdata->vif); 598 - } 599 - 600 - sdata = rcu_dereference_protected(local->monitor_sdata, 601 - lockdep_is_held(&local->iflist_mtx)); 602 - if (sdata && 603 - (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || 604 - sdata->flags & IEEE80211_SDATA_IN_DRIVER)) 605 - iterator(data, sdata->vif.addr, &sdata->vif); 606 - 607 - mutex_unlock(&local->iflist_mtx); 608 - } 609 - EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); 610 - 611 - void ieee80211_iterate_active_interfaces_atomic( 612 - struct ieee80211_hw *hw, u32 iter_flags, 613 - void (*iterator)(void *data, u8 *mac, 614 - struct ieee80211_vif *vif), 615 - void *data) 616 - { 617 - struct ieee80211_local *local = hw_to_local(hw); 618 - struct ieee80211_sub_if_data *sdata; 619 - 620 - rcu_read_lock(); 621 577 622 578 list_for_each_entry_rcu(sdata, &local->interfaces, list) { 623 579 switch (sdata->vif.type) { ··· 594 638 &sdata->vif); 595 639 } 596 640 597 - sdata = rcu_dereference(local->monitor_sdata); 641 + sdata = rcu_dereference_check(local->monitor_sdata, 642 + lockdep_is_held(&local->iflist_mtx) || 643 + lockdep_rtnl_is_held()); 598 644 if (sdata && 599 645 (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || 600 646 sdata->flags & IEEE80211_SDATA_IN_DRIVER)) 601 647 iterator(data, sdata->vif.addr, &sdata->vif); 648 + } 602 649 650 + void ieee80211_iterate_active_interfaces( 651 + struct ieee80211_hw *hw, u32 iter_flags, 652 + void (*iterator)(void *data, u8 *mac, 653 + struct ieee80211_vif *vif), 654 + void *data) 655 + { 656 + struct ieee80211_local *local = hw_to_local(hw); 657 + 658 + mutex_lock(&local->iflist_mtx); 659 + __iterate_active_interfaces(local, iter_flags, iterator, data); 660 + mutex_unlock(&local->iflist_mtx); 661 + } 662 + EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); 663 + 664 + void ieee80211_iterate_active_interfaces_atomic( 665 + struct ieee80211_hw *hw, u32 iter_flags, 666 + void (*iterator)(void *data, u8 *mac, 667 + struct ieee80211_vif *vif), 668 + void *data) 669 + { 670 + struct ieee80211_local *local = hw_to_local(hw); 671 + 672 + rcu_read_lock(); 673 + __iterate_active_interfaces(local, iter_flags, iterator, data); 603 674 rcu_read_unlock(); 604 675 } 605 676 EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); 677 + 678 + void ieee80211_iterate_active_interfaces_rtnl( 679 + struct ieee80211_hw *hw, u32 iter_flags, 680 + void (*iterator)(void *data, u8 *mac, 681 + struct ieee80211_vif *vif), 682 + void *data) 683 + { 684 + struct ieee80211_local *local = hw_to_local(hw); 685 + 686 + ASSERT_RTNL(); 687 + 688 + __iterate_active_interfaces(local, iter_flags, iterator, data); 689 + } 690 + EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_rtnl); 606 691 607 692 /* 608 693 * Nothing should have been stuffed into the workqueue during ··· 1004 1007 */ 1005 1008 enable_qos = (sdata->vif.type != NL80211_IFTYPE_STATION); 1006 1009 1007 - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { 1008 - /* Set defaults according to 802.11-2007 Table 7-37 */ 1009 - aCWmax = 1023; 1010 - if (use_11b) 1011 - aCWmin = 31; 1012 - else 1013 - aCWmin = 15; 1010 + /* Set defaults according to 802.11-2007 Table 7-37 */ 1011 + aCWmax = 1023; 1012 + if (use_11b) 1013 + aCWmin = 31; 1014 + else 1015 + aCWmin = 15; 1014 1016 1017 + /* Confiure old 802.11b/g medium access rules. */ 1018 + qparam.cw_max = aCWmax; 1019 + qparam.cw_min = aCWmin; 1020 + qparam.txop = 0; 1021 + qparam.aifs = 2; 1022 + 1023 + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { 1024 + /* Update if QoS is enabled. */ 1015 1025 if (enable_qos) { 1016 1026 switch (ac) { 1017 1027 case IEEE80211_AC_BK: ··· 1054 1050 qparam.aifs = 2; 1055 1051 break; 1056 1052 } 1057 - } else { 1058 - /* Confiure old 802.11b/g medium access rules. */ 1059 - qparam.cw_max = aCWmax; 1060 - qparam.cw_min = aCWmin; 1061 - qparam.txop = 0; 1062 - qparam.aifs = 2; 1063 1053 } 1064 1054 1065 1055 qparam.uapsd = false; ··· 1082 1084 struct ieee80211_mgmt *mgmt; 1083 1085 int err; 1084 1086 1085 - skb = dev_alloc_skb(local->hw.extra_tx_headroom + 1086 - sizeof(*mgmt) + 6 + extra_len); 1087 + /* 24 + 6 = header + auth_algo + auth_transaction + status_code */ 1088 + skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24 + 6 + extra_len); 1087 1089 if (!skb) 1088 1090 return; 1089 1091 ··· 2290 2292 ieee80211_queue_work(hw, &local->radar_detected_work); 2291 2293 } 2292 2294 EXPORT_SYMBOL(ieee80211_radar_detected); 2295 + 2296 + u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c) 2297 + { 2298 + u32 ret; 2299 + int tmp; 2300 + 2301 + switch (c->width) { 2302 + case NL80211_CHAN_WIDTH_20: 2303 + c->width = NL80211_CHAN_WIDTH_20_NOHT; 2304 + ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; 2305 + break; 2306 + case NL80211_CHAN_WIDTH_40: 2307 + c->width = NL80211_CHAN_WIDTH_20; 2308 + c->center_freq1 = c->chan->center_freq; 2309 + ret = IEEE80211_STA_DISABLE_40MHZ | 2310 + IEEE80211_STA_DISABLE_VHT; 2311 + break; 2312 + case NL80211_CHAN_WIDTH_80: 2313 + tmp = (30 + c->chan->center_freq - c->center_freq1)/20; 2314 + /* n_P40 */ 2315 + tmp /= 2; 2316 + /* freq_P40 */ 2317 + c->center_freq1 = c->center_freq1 - 20 + 40 * tmp; 2318 + c->width = NL80211_CHAN_WIDTH_40; 2319 + ret = IEEE80211_STA_DISABLE_VHT; 2320 + break; 2321 + case NL80211_CHAN_WIDTH_80P80: 2322 + c->center_freq2 = 0; 2323 + c->width = NL80211_CHAN_WIDTH_80; 2324 + ret = IEEE80211_STA_DISABLE_80P80MHZ | 2325 + IEEE80211_STA_DISABLE_160MHZ; 2326 + break; 2327 + case NL80211_CHAN_WIDTH_160: 2328 + /* n_P20 */ 2329 + tmp = (70 + c->chan->center_freq - c->center_freq1)/20; 2330 + /* n_P80 */ 2331 + tmp /= 4; 2332 + c->center_freq1 = c->center_freq1 - 40 + 80 * tmp; 2333 + c->width = NL80211_CHAN_WIDTH_80; 2334 + ret = IEEE80211_STA_DISABLE_80P80MHZ | 2335 + IEEE80211_STA_DISABLE_160MHZ; 2336 + break; 2337 + default: 2338 + case NL80211_CHAN_WIDTH_20_NOHT: 2339 + WARN_ON_ONCE(1); 2340 + c->width = NL80211_CHAN_WIDTH_20_NOHT; 2341 + ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; 2342 + break; 2343 + case NL80211_CHAN_WIDTH_5: 2344 + case NL80211_CHAN_WIDTH_10: 2345 + WARN_ON_ONCE(1); 2346 + /* keep c->width */ 2347 + ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; 2348 + break; 2349 + } 2350 + 2351 + WARN_ON_ONCE(!cfg80211_chandef_valid(c)); 2352 + 2353 + return ret; 2354 + }
+2 -2
net/mac80211/vht.c
··· 185 185 if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) { 186 186 vht_cap->cap |= cap_info & 187 187 (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | 188 - IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX | 189 188 IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX); 190 189 } 191 190 192 191 if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) 193 192 vht_cap->cap |= cap_info & 194 - IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; 193 + (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | 194 + IEEE80211_VHT_CAP_BEAMFORMEE_STS_MAX); 195 195 196 196 if (own_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) 197 197 vht_cap->cap |= cap_info &
+1
net/wireless/chan.c
··· 328 328 return cfg80211_get_chans_dfs_required(wiphy, chandef->center_freq2, 329 329 width); 330 330 } 331 + EXPORT_SYMBOL(cfg80211_chandef_dfs_required); 331 332 332 333 static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, 333 334 u32 center_freq, u32 bandwidth,
-9
net/wireless/core.h
··· 382 382 enum cfg80211_chan_mode chanmode, 383 383 u8 radar_detect); 384 384 385 - /** 386 - * cfg80211_chandef_dfs_required - checks if radar detection is required 387 - * @wiphy: the wiphy to validate against 388 - * @chandef: the channel definition to check 389 - * Return: 1 if radar detection is required, 0 if it is not, < 0 on error 390 - */ 391 - int cfg80211_chandef_dfs_required(struct wiphy *wiphy, 392 - const struct cfg80211_chan_def *c); 393 - 394 385 void cfg80211_set_dfs_state(struct wiphy *wiphy, 395 386 const struct cfg80211_chan_def *chandef, 396 387 enum nl80211_dfs_state dfs_state);
+12 -10
net/wireless/debugfs.c
··· 47 47 return 0; 48 48 49 49 if (chan->flags & IEEE80211_CHAN_DISABLED) 50 - return snprintf(buf + offset, 51 - buf_size - offset, 52 - "%d Disabled\n", 53 - chan->center_freq); 50 + return scnprintf(buf + offset, 51 + buf_size - offset, 52 + "%d Disabled\n", 53 + chan->center_freq); 54 54 55 - return snprintf(buf + offset, 56 - buf_size - offset, 57 - "%d HT40 %c%c\n", 58 - chan->center_freq, 59 - (chan->flags & IEEE80211_CHAN_NO_HT40MINUS) ? ' ' : '-', 60 - (chan->flags & IEEE80211_CHAN_NO_HT40PLUS) ? ' ' : '+'); 55 + return scnprintf(buf + offset, 56 + buf_size - offset, 57 + "%d HT40 %c%c\n", 58 + chan->center_freq, 59 + (chan->flags & IEEE80211_CHAN_NO_HT40MINUS) ? 60 + ' ' : '-', 61 + (chan->flags & IEEE80211_CHAN_NO_HT40PLUS) ? 62 + ' ' : '+'); 61 63 } 62 64 63 65 static ssize_t ht40allow_map_read(struct file *file,
+6
net/wireless/genregdb.awk
··· 46 46 sub(/:/, "", country) 47 47 printf "static const struct ieee80211_regdomain regdom_%s = {\n", country 48 48 printf "\t.alpha2 = \"%s\",\n", country 49 + if ($NF ~ /DFS-ETSI/) 50 + printf "\t.dfs_region = NL80211_DFS_ETSI,\n" 51 + else if ($NF ~ /DFS-FCC/) 52 + printf "\t.dfs_region = NL80211_DFS_FCC,\n" 53 + else if ($NF ~ /DFS-JP/) 54 + printf "\t.dfs_region = NL80211_DFS_JP,\n" 49 55 printf "\t.reg_rules = {\n" 50 56 active = 1 51 57 regdb = regdb "\t&regdom_" country ",\n"
+37 -15
net/wireless/nl80211.c
··· 5591 5591 if (err) 5592 5592 return err; 5593 5593 5594 + if (netif_carrier_ok(dev)) 5595 + return -EBUSY; 5596 + 5594 5597 if (wdev->cac_started) 5595 5598 return -EBUSY; 5596 5599 ··· 5637 5634 static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1]; 5638 5635 u8 radar_detect_width = 0; 5639 5636 int err; 5637 + bool need_new_beacon = false; 5640 5638 5641 5639 if (!rdev->ops->channel_switch || 5642 5640 !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)) 5643 5641 return -EOPNOTSUPP; 5644 5642 5645 - /* may add IBSS support later */ 5646 - if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 5647 - dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) 5643 + switch (dev->ieee80211_ptr->iftype) { 5644 + case NL80211_IFTYPE_AP: 5645 + case NL80211_IFTYPE_P2P_GO: 5646 + need_new_beacon = true; 5647 + 5648 + /* useless if AP is not running */ 5649 + if (!wdev->beacon_interval) 5650 + return -EINVAL; 5651 + break; 5652 + case NL80211_IFTYPE_ADHOC: 5653 + break; 5654 + default: 5648 5655 return -EOPNOTSUPP; 5656 + } 5649 5657 5650 5658 memset(&params, 0, sizeof(params)); 5651 5659 ··· 5665 5651 return -EINVAL; 5666 5652 5667 5653 /* only important for AP, IBSS and mesh create IEs internally */ 5668 - if (!info->attrs[NL80211_ATTR_CSA_IES]) 5669 - return -EINVAL; 5670 - 5671 - /* useless if AP is not running */ 5672 - if (!wdev->beacon_interval) 5654 + if (need_new_beacon && 5655 + (!info->attrs[NL80211_ATTR_CSA_IES] || 5656 + !info->attrs[NL80211_ATTR_CSA_C_OFF_BEACON])) 5673 5657 return -EINVAL; 5674 5658 5675 5659 params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]); 5660 + 5661 + if (!need_new_beacon) 5662 + goto skip_beacons; 5676 5663 5677 5664 err = nl80211_parse_beacon(info->attrs, &params.beacon_after); 5678 5665 if (err) ··· 5714 5699 return -EINVAL; 5715 5700 } 5716 5701 5702 + skip_beacons: 5717 5703 err = nl80211_parse_chandef(rdev, info, &params.chandef); 5718 5704 if (err) 5719 5705 return err; ··· 5722 5706 if (!cfg80211_reg_can_beacon(&rdev->wiphy, &params.chandef)) 5723 5707 return -EINVAL; 5724 5708 5725 - err = cfg80211_chandef_dfs_required(wdev->wiphy, &params.chandef); 5726 - if (err < 0) { 5727 - return err; 5728 - } else if (err) { 5729 - radar_detect_width = BIT(params.chandef.width); 5730 - params.radar_required = true; 5709 + /* DFS channels are only supported for AP/P2P GO ... for now. */ 5710 + if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP || 5711 + dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) { 5712 + err = cfg80211_chandef_dfs_required(wdev->wiphy, 5713 + &params.chandef); 5714 + if (err < 0) { 5715 + return err; 5716 + } else if (err) { 5717 + radar_detect_width = BIT(params.chandef.width); 5718 + params.radar_required = true; 5719 + } 5731 5720 } 5732 5721 5733 5722 err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, ··· 10761 10740 wdev_lock(wdev); 10762 10741 10763 10742 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && 10764 - wdev->iftype != NL80211_IFTYPE_P2P_GO)) 10743 + wdev->iftype != NL80211_IFTYPE_P2P_GO && 10744 + wdev->iftype != NL80211_IFTYPE_ADHOC)) 10765 10745 goto out; 10766 10746 10767 10747 wdev->channel = chandef->chan;
+12 -2
net/wireless/reg.c
··· 172 172 NL80211_RRF_NO_IBSS | 173 173 NL80211_RRF_NO_OFDM), 174 174 /* IEEE 802.11a, channel 36..48 */ 175 - REG_RULE(5180-10, 5240+10, 80, 6, 20, 175 + REG_RULE(5180-10, 5240+10, 160, 6, 20, 176 176 NL80211_RRF_PASSIVE_SCAN | 177 177 NL80211_RRF_NO_IBSS), 178 178 179 - /* NB: 5260 MHz - 5700 MHz requires DFS */ 179 + /* IEEE 802.11a, channel 52..64 - DFS required */ 180 + REG_RULE(5260-10, 5320+10, 160, 6, 20, 181 + NL80211_RRF_PASSIVE_SCAN | 182 + NL80211_RRF_NO_IBSS | 183 + NL80211_RRF_DFS), 184 + 185 + /* IEEE 802.11a, channel 100..144 - DFS required */ 186 + REG_RULE(5500-10, 5720+10, 160, 6, 20, 187 + NL80211_RRF_PASSIVE_SCAN | 188 + NL80211_RRF_NO_IBSS | 189 + NL80211_RRF_DFS), 180 190 181 191 /* IEEE 802.11a, channel 149..165 */ 182 192 REG_RULE(5745-10, 5825+10, 80, 6, 20,
+9
net/wireless/util.c
··· 10 10 #include <net/cfg80211.h> 11 11 #include <net/ip.h> 12 12 #include <net/dsfield.h> 13 + #include <linux/if_vlan.h> 13 14 #include "core.h" 14 15 #include "rdev-ops.h" 15 16 ··· 692 691 unsigned int cfg80211_classify8021d(struct sk_buff *skb) 693 692 { 694 693 unsigned int dscp; 694 + unsigned char vlan_priority; 695 695 696 696 /* skb->priority values from 256->263 are magic values to 697 697 * directly indicate a specific 802.1d priority. This is used ··· 701 699 */ 702 700 if (skb->priority >= 256 && skb->priority <= 263) 703 701 return skb->priority - 256; 702 + 703 + if (vlan_tx_tag_present(skb)) { 704 + vlan_priority = (vlan_tx_tag_get(skb) & VLAN_PRIO_MASK) 705 + >> VLAN_PRIO_SHIFT; 706 + if (vlan_priority > 0) 707 + return vlan_priority; 708 + } 704 709 705 710 switch (skb->protocol) { 706 711 case htons(ETH_P_IP):