diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-10-17 14:02:07 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-10-17 14:02:07 -0400 |
commit | 9f96da4dd2ccf685b506a21104cb13b1aadd907a (patch) | |
tree | 5d9eff61123f096e2434a9d36e6fdbd4cc5c6292 | |
parent | ccdbb6e96beca362db876d820ac1e560ff6d9579 (diff) | |
parent | b6b561c31d51db3dec0cb55412a5d7a1a2397521 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
89 files changed, 11937 insertions, 1309 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 7a86b44a4c56..a46bcf816a6a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -6830,6 +6830,14 @@ L: linux-hexagon@vger.kernel.org | |||
6830 | S: Supported | 6830 | S: Supported |
6831 | F: arch/hexagon/ | 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 | QUICKCAM PARALLEL PORT WEBCAMS | 6841 | QUICKCAM PARALLEL PORT WEBCAMS |
6834 | M: Hans Verkuil <hverkuil@xs4all.nl> | 6842 | M: Hans Verkuil <hverkuil@xs4all.nl> |
6835 | L: linux-media@vger.kernel.org | 6843 | L: linux-media@vger.kernel.org |
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index a355e63a3838..6fb98b53533f 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c | |||
@@ -188,8 +188,11 @@ static int bcma_host_pci_probe(struct pci_dev *dev, | |||
188 | pci_write_config_dword(dev, 0x40, val & 0xffff00ff); | 188 | pci_write_config_dword(dev, 0x40, val & 0xffff00ff); |
189 | 189 | ||
190 | /* SSB needed additional powering up, do we have any AMBA PCI cards? */ | 190 | /* SSB needed additional powering up, do we have any AMBA PCI cards? */ |
191 | if (!pci_is_pcie(dev)) | 191 | if (!pci_is_pcie(dev)) { |
192 | bcma_err(bus, "PCI card detected, report problems.\n"); | 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 | /* Map MMIO */ | 197 | /* Map MMIO */ |
195 | err = -ENOMEM; | 198 | err = -ENOMEM; |
@@ -269,6 +272,7 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend, | |||
269 | 272 | ||
270 | static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { | 273 | static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { |
271 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, | 274 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, |
275 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4313) }, | ||
272 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) }, | 276 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) }, |
273 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, | 277 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, |
274 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, | 278 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, |
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index 1abf1d421173..ba81d6292eeb 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig | |||
@@ -32,5 +32,6 @@ source "drivers/net/wireless/ath/ath6kl/Kconfig" | |||
32 | source "drivers/net/wireless/ath/ar5523/Kconfig" | 32 | source "drivers/net/wireless/ath/ar5523/Kconfig" |
33 | source "drivers/net/wireless/ath/wil6210/Kconfig" | 33 | source "drivers/net/wireless/ath/wil6210/Kconfig" |
34 | source "drivers/net/wireless/ath/ath10k/Kconfig" | 34 | source "drivers/net/wireless/ath/ath10k/Kconfig" |
35 | source "drivers/net/wireless/ath/wcn36xx/Kconfig" | ||
35 | 36 | ||
36 | endif | 37 | endif |
diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile index fb05cfd19361..363b05653c7e 100644 --- a/drivers/net/wireless/ath/Makefile +++ b/drivers/net/wireless/ath/Makefile | |||
@@ -5,6 +5,7 @@ obj-$(CONFIG_ATH6KL) += ath6kl/ | |||
5 | obj-$(CONFIG_AR5523) += ar5523/ | 5 | obj-$(CONFIG_AR5523) += ar5523/ |
6 | obj-$(CONFIG_WIL6210) += wil6210/ | 6 | obj-$(CONFIG_WIL6210) += wil6210/ |
7 | obj-$(CONFIG_ATH10K) += ath10k/ | 7 | obj-$(CONFIG_ATH10K) += ath10k/ |
8 | obj-$(CONFIG_WCN36XX) += wcn36xx/ | ||
8 | 9 | ||
9 | obj-$(CONFIG_ATH_COMMON) += ath.o | 10 | obj-$(CONFIG_ATH_COMMON) += ath.o |
10 | 11 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index be466b0ef7a7..d28923b7435b 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
@@ -338,10 +338,9 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) | |||
338 | aniState->cckNoiseImmunityLevel != | 338 | aniState->cckNoiseImmunityLevel != |
339 | ATH9K_ANI_CCK_DEF_LEVEL) { | 339 | ATH9K_ANI_CCK_DEF_LEVEL) { |
340 | ath_dbg(common, ANI, | 340 | ath_dbg(common, ANI, |
341 | "Restore defaults: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n", | 341 | "Restore defaults: opmode %u chan %d Mhz is_scanning=%d ofdm:%d cck:%d\n", |
342 | ah->opmode, | 342 | ah->opmode, |
343 | chan->channel, | 343 | chan->channel, |
344 | chan->channelFlags, | ||
345 | is_scanning, | 344 | is_scanning, |
346 | aniState->ofdmNoiseImmunityLevel, | 345 | aniState->ofdmNoiseImmunityLevel, |
347 | aniState->cckNoiseImmunityLevel); | 346 | aniState->cckNoiseImmunityLevel); |
@@ -354,10 +353,9 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) | |||
354 | * restore historical levels for this channel | 353 | * restore historical levels for this channel |
355 | */ | 354 | */ |
356 | ath_dbg(common, ANI, | 355 | ath_dbg(common, ANI, |
357 | "Restore history: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n", | 356 | "Restore history: opmode %u chan %d Mhz is_scanning=%d ofdm:%d cck:%d\n", |
358 | ah->opmode, | 357 | ah->opmode, |
359 | chan->channel, | 358 | chan->channel, |
360 | chan->channelFlags, | ||
361 | is_scanning, | 359 | is_scanning, |
362 | aniState->ofdmNoiseImmunityLevel, | 360 | aniState->ofdmNoiseImmunityLevel, |
363 | aniState->cckNoiseImmunityLevel); | 361 | aniState->cckNoiseImmunityLevel); |
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index cb6435e7c6f5..ff415e863ee9 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c | |||
@@ -666,14 +666,13 @@ static void ar5008_hw_set_channel_regs(struct ath_hw *ah, | |||
666 | if (IS_CHAN_HT40(chan)) { | 666 | if (IS_CHAN_HT40(chan)) { |
667 | phymode |= AR_PHY_FC_DYN2040_EN; | 667 | phymode |= AR_PHY_FC_DYN2040_EN; |
668 | 668 | ||
669 | if ((chan->chanmode == CHANNEL_A_HT40PLUS) || | 669 | if (IS_CHAN_HT40PLUS(chan)) |
670 | (chan->chanmode == CHANNEL_G_HT40PLUS)) | ||
671 | phymode |= AR_PHY_FC_DYN2040_PRI_CH; | 670 | phymode |= AR_PHY_FC_DYN2040_PRI_CH; |
672 | 671 | ||
673 | } | 672 | } |
674 | REG_WRITE(ah, AR_PHY_TURBO, phymode); | 673 | REG_WRITE(ah, AR_PHY_TURBO, phymode); |
675 | 674 | ||
676 | ath9k_hw_set11nmac2040(ah); | 675 | ath9k_hw_set11nmac2040(ah, chan); |
677 | 676 | ||
678 | ENABLE_REGWRITE_BUFFER(ah); | 677 | ENABLE_REGWRITE_BUFFER(ah); |
679 | 678 | ||
@@ -691,31 +690,12 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, | |||
691 | int i, regWrites = 0; | 690 | int i, regWrites = 0; |
692 | u32 modesIndex, freqIndex; | 691 | u32 modesIndex, freqIndex; |
693 | 692 | ||
694 | switch (chan->chanmode) { | 693 | if (IS_CHAN_5GHZ(chan)) { |
695 | case CHANNEL_A: | ||
696 | case CHANNEL_A_HT20: | ||
697 | modesIndex = 1; | ||
698 | freqIndex = 1; | 694 | freqIndex = 1; |
699 | break; | 695 | modesIndex = IS_CHAN_HT40(chan) ? 2 : 1; |
700 | case CHANNEL_A_HT40PLUS: | 696 | } else { |
701 | case CHANNEL_A_HT40MINUS: | ||
702 | modesIndex = 2; | ||
703 | freqIndex = 1; | ||
704 | break; | ||
705 | case CHANNEL_G: | ||
706 | case CHANNEL_G_HT20: | ||
707 | case CHANNEL_B: | ||
708 | modesIndex = 4; | ||
709 | freqIndex = 2; | ||
710 | break; | ||
711 | case CHANNEL_G_HT40PLUS: | ||
712 | case CHANNEL_G_HT40MINUS: | ||
713 | modesIndex = 3; | ||
714 | freqIndex = 2; | 697 | freqIndex = 2; |
715 | break; | 698 | modesIndex = IS_CHAN_HT40(chan) ? 3 : 4; |
716 | |||
717 | default: | ||
718 | return -EINVAL; | ||
719 | } | 699 | } |
720 | 700 | ||
721 | /* | 701 | /* |
@@ -814,8 +794,10 @@ static void ar5008_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan) | |||
814 | if (chan == NULL) | 794 | if (chan == NULL) |
815 | return; | 795 | return; |
816 | 796 | ||
817 | rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan)) | 797 | if (IS_CHAN_2GHZ(chan)) |
818 | ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; | 798 | rfMode |= AR_PHY_MODE_DYNAMIC; |
799 | else | ||
800 | rfMode |= AR_PHY_MODE_OFDM; | ||
819 | 801 | ||
820 | if (!AR_SREV_9280_20_OR_LATER(ah)) | 802 | if (!AR_SREV_9280_20_OR_LATER(ah)) |
821 | rfMode |= (IS_CHAN_5GHZ(chan)) ? | 803 | rfMode |= (IS_CHAN_5GHZ(chan)) ? |
@@ -1218,12 +1200,11 @@ static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah) | |||
1218 | 1200 | ||
1219 | iniDef = &aniState->iniDef; | 1201 | iniDef = &aniState->iniDef; |
1220 | 1202 | ||
1221 | ath_dbg(common, ANI, "ver %d.%d opmode %u chan %d Mhz/0x%x\n", | 1203 | ath_dbg(common, ANI, "ver %d.%d opmode %u chan %d Mhz\n", |
1222 | ah->hw_version.macVersion, | 1204 | ah->hw_version.macVersion, |
1223 | ah->hw_version.macRev, | 1205 | ah->hw_version.macRev, |
1224 | ah->opmode, | 1206 | ah->opmode, |
1225 | chan->channel, | 1207 | chan->channel); |
1226 | chan->channelFlags); | ||
1227 | 1208 | ||
1228 | val = REG_READ(ah, AR_PHY_SFCORR); | 1209 | val = REG_READ(ah, AR_PHY_SFCORR); |
1229 | iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH); | 1210 | iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index 32376ad74011..cdc74005650c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c | |||
@@ -33,15 +33,12 @@ static bool ar9002_hw_is_cal_supported(struct ath_hw *ah, | |||
33 | bool supported = false; | 33 | bool supported = false; |
34 | switch (ah->supp_cals & cal_type) { | 34 | switch (ah->supp_cals & cal_type) { |
35 | case IQ_MISMATCH_CAL: | 35 | case IQ_MISMATCH_CAL: |
36 | /* Run IQ Mismatch for non-CCK only */ | 36 | supported = true; |
37 | if (!IS_CHAN_B(chan)) | ||
38 | supported = true; | ||
39 | break; | 37 | break; |
40 | case ADC_GAIN_CAL: | 38 | case ADC_GAIN_CAL: |
41 | case ADC_DC_CAL: | 39 | case ADC_DC_CAL: |
42 | /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */ | 40 | /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */ |
43 | if (!IS_CHAN_B(chan) && | 41 | if (!((IS_CHAN_2GHZ(chan) || IS_CHAN_A_FAST_CLOCK(ah, chan)) && |
44 | !((IS_CHAN_2GHZ(chan) || IS_CHAN_A_FAST_CLOCK(ah, chan)) && | ||
45 | IS_CHAN_HT20(chan))) | 42 | IS_CHAN_HT20(chan))) |
46 | supported = true; | 43 | supported = true; |
47 | break; | 44 | break; |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index fb61b081d172..5c95fd9e9c9e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c | |||
@@ -419,28 +419,10 @@ void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan) | |||
419 | u32 modesIndex; | 419 | u32 modesIndex; |
420 | int i; | 420 | int i; |
421 | 421 | ||
422 | switch (chan->chanmode) { | 422 | if (IS_CHAN_5GHZ(chan)) |
423 | case CHANNEL_A: | 423 | modesIndex = IS_CHAN_HT40(chan) ? 2 : 1; |
424 | case CHANNEL_A_HT20: | 424 | else |
425 | modesIndex = 1; | 425 | modesIndex = IS_CHAN_HT40(chan) ? 3 : 4; |
426 | break; | ||
427 | case CHANNEL_A_HT40PLUS: | ||
428 | case CHANNEL_A_HT40MINUS: | ||
429 | modesIndex = 2; | ||
430 | break; | ||
431 | case CHANNEL_G: | ||
432 | case CHANNEL_G_HT20: | ||
433 | case CHANNEL_B: | ||
434 | modesIndex = 4; | ||
435 | break; | ||
436 | case CHANNEL_G_HT40PLUS: | ||
437 | case CHANNEL_G_HT40MINUS: | ||
438 | modesIndex = 3; | ||
439 | break; | ||
440 | |||
441 | default: | ||
442 | return; | ||
443 | } | ||
444 | 426 | ||
445 | ENABLE_REGWRITE_BUFFER(ah); | 427 | ENABLE_REGWRITE_BUFFER(ah); |
446 | 428 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 0131ba2f5d51..f3adafd33704 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -551,8 +551,7 @@ static void ar9003_hw_set_channel_regs(struct ath_hw *ah, | |||
551 | if (IS_CHAN_HT40(chan)) { | 551 | if (IS_CHAN_HT40(chan)) { |
552 | phymode |= AR_PHY_GC_DYN2040_EN; | 552 | phymode |= AR_PHY_GC_DYN2040_EN; |
553 | /* Configure control (primary) channel at +-10MHz */ | 553 | /* Configure control (primary) channel at +-10MHz */ |
554 | if ((chan->chanmode == CHANNEL_A_HT40PLUS) || | 554 | if (IS_CHAN_HT40PLUS(chan)) |
555 | (chan->chanmode == CHANNEL_G_HT40PLUS)) | ||
556 | phymode |= AR_PHY_GC_DYN2040_PRI_CH; | 555 | phymode |= AR_PHY_GC_DYN2040_PRI_CH; |
557 | 556 | ||
558 | } | 557 | } |
@@ -565,7 +564,7 @@ static void ar9003_hw_set_channel_regs(struct ath_hw *ah, | |||
565 | REG_WRITE(ah, AR_PHY_GEN_CTRL, phymode); | 564 | REG_WRITE(ah, AR_PHY_GEN_CTRL, phymode); |
566 | 565 | ||
567 | /* Configure MAC for 20/40 operation */ | 566 | /* Configure MAC for 20/40 operation */ |
568 | ath9k_hw_set11nmac2040(ah); | 567 | ath9k_hw_set11nmac2040(ah, chan); |
569 | 568 | ||
570 | /* global transmit timeout (25 TUs default)*/ | 569 | /* global transmit timeout (25 TUs default)*/ |
571 | REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S); | 570 | REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S); |
@@ -682,41 +681,22 @@ static int ar9550_hw_get_modes_txgain_index(struct ath_hw *ah, | |||
682 | { | 681 | { |
683 | int ret; | 682 | int ret; |
684 | 683 | ||
685 | switch (chan->chanmode) { | 684 | if (IS_CHAN_2GHZ(chan)) { |
686 | case CHANNEL_A: | 685 | if (IS_CHAN_HT40(chan)) |
687 | case CHANNEL_A_HT20: | 686 | return 7; |
688 | if (chan->channel <= 5350) | ||
689 | ret = 1; | ||
690 | else if ((chan->channel > 5350) && (chan->channel <= 5600)) | ||
691 | ret = 3; | ||
692 | else | 687 | else |
693 | ret = 5; | 688 | return 8; |
694 | break; | 689 | } |
695 | |||
696 | case CHANNEL_A_HT40PLUS: | ||
697 | case CHANNEL_A_HT40MINUS: | ||
698 | if (chan->channel <= 5350) | ||
699 | ret = 2; | ||
700 | else if ((chan->channel > 5350) && (chan->channel <= 5600)) | ||
701 | ret = 4; | ||
702 | else | ||
703 | ret = 6; | ||
704 | break; | ||
705 | |||
706 | case CHANNEL_G: | ||
707 | case CHANNEL_G_HT20: | ||
708 | case CHANNEL_B: | ||
709 | ret = 8; | ||
710 | break; | ||
711 | 690 | ||
712 | case CHANNEL_G_HT40PLUS: | 691 | if (chan->channel <= 5350) |
713 | case CHANNEL_G_HT40MINUS: | 692 | ret = 1; |
714 | ret = 7; | 693 | else if ((chan->channel > 5350) && (chan->channel <= 5600)) |
715 | break; | 694 | ret = 3; |
695 | else | ||
696 | ret = 5; | ||
716 | 697 | ||
717 | default: | 698 | if (IS_CHAN_HT40(chan)) |
718 | ret = -EINVAL; | 699 | ret++; |
719 | } | ||
720 | 700 | ||
721 | return ret; | 701 | return ret; |
722 | } | 702 | } |
@@ -727,28 +707,10 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, | |||
727 | unsigned int regWrites = 0, i; | 707 | unsigned int regWrites = 0, i; |
728 | u32 modesIndex; | 708 | u32 modesIndex; |
729 | 709 | ||
730 | switch (chan->chanmode) { | 710 | if (IS_CHAN_5GHZ(chan)) |
731 | case CHANNEL_A: | 711 | modesIndex = IS_CHAN_HT40(chan) ? 2 : 1; |
732 | case CHANNEL_A_HT20: | 712 | else |
733 | modesIndex = 1; | 713 | modesIndex = IS_CHAN_HT40(chan) ? 3 : 4; |
734 | break; | ||
735 | case CHANNEL_A_HT40PLUS: | ||
736 | case CHANNEL_A_HT40MINUS: | ||
737 | modesIndex = 2; | ||
738 | break; | ||
739 | case CHANNEL_G: | ||
740 | case CHANNEL_G_HT20: | ||
741 | case CHANNEL_B: | ||
742 | modesIndex = 4; | ||
743 | break; | ||
744 | case CHANNEL_G_HT40PLUS: | ||
745 | case CHANNEL_G_HT40MINUS: | ||
746 | modesIndex = 3; | ||
747 | break; | ||
748 | |||
749 | default: | ||
750 | return -EINVAL; | ||
751 | } | ||
752 | 714 | ||
753 | /* | 715 | /* |
754 | * SOC, MAC, BB, RADIO initvals. | 716 | * SOC, MAC, BB, RADIO initvals. |
@@ -846,8 +808,10 @@ static void ar9003_hw_set_rfmode(struct ath_hw *ah, | |||
846 | if (chan == NULL) | 808 | if (chan == NULL) |
847 | return; | 809 | return; |
848 | 810 | ||
849 | rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan)) | 811 | if (IS_CHAN_2GHZ(chan)) |
850 | ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; | 812 | rfMode |= AR_PHY_MODE_DYNAMIC; |
813 | else | ||
814 | rfMode |= AR_PHY_MODE_OFDM; | ||
851 | 815 | ||
852 | if (IS_CHAN_A_FAST_CLOCK(ah, chan)) | 816 | if (IS_CHAN_A_FAST_CLOCK(ah, chan)) |
853 | rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE); | 817 | rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE); |
@@ -1273,12 +1237,11 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah) | |||
1273 | aniState = &ah->ani; | 1237 | aniState = &ah->ani; |
1274 | iniDef = &aniState->iniDef; | 1238 | iniDef = &aniState->iniDef; |
1275 | 1239 | ||
1276 | ath_dbg(common, ANI, "ver %d.%d opmode %u chan %d Mhz/0x%x\n", | 1240 | ath_dbg(common, ANI, "ver %d.%d opmode %u chan %d Mhz\n", |
1277 | ah->hw_version.macVersion, | 1241 | ah->hw_version.macVersion, |
1278 | ah->hw_version.macRev, | 1242 | ah->hw_version.macRev, |
1279 | ah->opmode, | 1243 | ah->opmode, |
1280 | chan->channel, | 1244 | chan->channel); |
1281 | chan->channelFlags); | ||
1282 | 1245 | ||
1283 | val = REG_READ(ah, AR_PHY_SFCORR); | 1246 | val = REG_READ(ah, AR_PHY_SFCORR); |
1284 | iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH); | 1247 | iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH); |
@@ -1536,28 +1499,10 @@ static int ar9003_hw_fast_chan_change(struct ath_hw *ah, | |||
1536 | unsigned int regWrites = 0; | 1499 | unsigned int regWrites = 0; |
1537 | u32 modesIndex; | 1500 | u32 modesIndex; |
1538 | 1501 | ||
1539 | switch (chan->chanmode) { | 1502 | if (IS_CHAN_5GHZ(chan)) |
1540 | case CHANNEL_A: | 1503 | modesIndex = IS_CHAN_HT40(chan) ? 2 : 1; |
1541 | case CHANNEL_A_HT20: | 1504 | else |
1542 | modesIndex = 1; | 1505 | modesIndex = IS_CHAN_HT40(chan) ? 3 : 4; |
1543 | break; | ||
1544 | case CHANNEL_A_HT40PLUS: | ||
1545 | case CHANNEL_A_HT40MINUS: | ||
1546 | modesIndex = 2; | ||
1547 | break; | ||
1548 | case CHANNEL_G: | ||
1549 | case CHANNEL_G_HT20: | ||
1550 | case CHANNEL_B: | ||
1551 | modesIndex = 4; | ||
1552 | break; | ||
1553 | case CHANNEL_G_HT40PLUS: | ||
1554 | case CHANNEL_G_HT40MINUS: | ||
1555 | modesIndex = 3; | ||
1556 | break; | ||
1557 | |||
1558 | default: | ||
1559 | return -EINVAL; | ||
1560 | } | ||
1561 | 1506 | ||
1562 | if (modesIndex == ah->modes_index) { | 1507 | if (modesIndex == ah->modes_index) { |
1563 | *ini_reloaded = false; | 1508 | *ini_reloaded = false; |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 15afde3c348b..14ff7e9dde4c 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -64,7 +64,6 @@ struct ath_node; | |||
64 | 64 | ||
65 | struct ath_config { | 65 | struct ath_config { |
66 | u16 txpowlimit; | 66 | u16 txpowlimit; |
67 | u8 cabqReadytime; | ||
68 | }; | 67 | }; |
69 | 68 | ||
70 | /*************************/ | 69 | /*************************/ |
@@ -207,6 +206,14 @@ struct ath_frame_info { | |||
207 | u8 baw_tracked : 1; | 206 | u8 baw_tracked : 1; |
208 | }; | 207 | }; |
209 | 208 | ||
209 | struct ath_rxbuf { | ||
210 | struct list_head list; | ||
211 | struct sk_buff *bf_mpdu; | ||
212 | void *bf_desc; | ||
213 | dma_addr_t bf_daddr; | ||
214 | dma_addr_t bf_buf_addr; | ||
215 | }; | ||
216 | |||
210 | struct ath_buf_state { | 217 | struct ath_buf_state { |
211 | u8 bf_type; | 218 | u8 bf_type; |
212 | u8 bfs_paprd; | 219 | u8 bfs_paprd; |
@@ -307,7 +314,7 @@ struct ath_rx { | |||
307 | struct ath_descdma rxdma; | 314 | struct ath_descdma rxdma; |
308 | struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX]; | 315 | struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX]; |
309 | 316 | ||
310 | struct ath_buf *buf_hold; | 317 | struct ath_rxbuf *buf_hold; |
311 | struct sk_buff *frag; | 318 | struct sk_buff *frag; |
312 | 319 | ||
313 | u32 ampdu_ref; | 320 | u32 ampdu_ref; |
@@ -926,7 +933,6 @@ void ath9k_deinit_device(struct ath_softc *sc); | |||
926 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); | 933 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); |
927 | void ath9k_reload_chainmask_settings(struct ath_softc *sc); | 934 | void ath9k_reload_chainmask_settings(struct ath_softc *sc); |
928 | 935 | ||
929 | bool ath9k_uses_beacons(int type); | ||
930 | void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw); | 936 | void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw); |
931 | int ath9k_spectral_scan_config(struct ieee80211_hw *hw, | 937 | int ath9k_spectral_scan_config(struct ieee80211_hw *hw, |
932 | enum spectral_mode spectral_mode); | 938 | enum spectral_mode spectral_mode); |
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index d438a0341e68..d8db74b0ef66 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -186,7 +186,6 @@ void ath9k_hw_reset_calibration(struct ath_hw *ah, | |||
186 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah) | 186 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah) |
187 | { | 187 | { |
188 | struct ath_common *common = ath9k_hw_common(ah); | 188 | struct ath_common *common = ath9k_hw_common(ah); |
189 | struct ieee80211_conf *conf = &common->hw->conf; | ||
190 | struct ath9k_cal_list *currCal = ah->cal_list_curr; | 189 | struct ath9k_cal_list *currCal = ah->cal_list_curr; |
191 | 190 | ||
192 | if (!ah->caldata) | 191 | if (!ah->caldata) |
@@ -208,7 +207,7 @@ bool ath9k_hw_reset_calvalid(struct ath_hw *ah) | |||
208 | return true; | 207 | return true; |
209 | 208 | ||
210 | ath_dbg(common, CALIBRATE, "Resetting Cal %d state for channel %u\n", | 209 | ath_dbg(common, CALIBRATE, "Resetting Cal %d state for channel %u\n", |
211 | currCal->calData->calType, conf->chandef.chan->center_freq); | 210 | currCal->calData->calType, ah->curchan->chan->center_freq); |
212 | 211 | ||
213 | ah->caldata->CalValid &= ~currCal->calData->calType; | 212 | ah->caldata->CalValid &= ~currCal->calData->calType; |
214 | currCal->calState = CAL_WAITING; | 213 | currCal->calState = CAL_WAITING; |
@@ -242,7 +241,6 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
242 | int32_t val; | 241 | int32_t val; |
243 | u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; | 242 | u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; |
244 | struct ath_common *common = ath9k_hw_common(ah); | 243 | struct ath_common *common = ath9k_hw_common(ah); |
245 | struct ieee80211_conf *conf = &common->hw->conf; | ||
246 | s16 default_nf = ath9k_hw_get_default_nf(ah, chan); | 244 | s16 default_nf = ath9k_hw_get_default_nf(ah, chan); |
247 | 245 | ||
248 | if (ah->caldata) | 246 | if (ah->caldata) |
@@ -252,7 +250,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
252 | if (chainmask & (1 << i)) { | 250 | if (chainmask & (1 << i)) { |
253 | s16 nfval; | 251 | s16 nfval; |
254 | 252 | ||
255 | if ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)) | 253 | if ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(chan)) |
256 | continue; | 254 | continue; |
257 | 255 | ||
258 | if (h) | 256 | if (h) |
@@ -314,7 +312,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
314 | ENABLE_REGWRITE_BUFFER(ah); | 312 | ENABLE_REGWRITE_BUFFER(ah); |
315 | for (i = 0; i < NUM_NF_READINGS; i++) { | 313 | for (i = 0; i < NUM_NF_READINGS; i++) { |
316 | if (chainmask & (1 << i)) { | 314 | if (chainmask & (1 << i)) { |
317 | if ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)) | 315 | if ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(chan)) |
318 | continue; | 316 | continue; |
319 | 317 | ||
320 | val = REG_READ(ah, ah->nf_regs[i]); | 318 | val = REG_READ(ah, ah->nf_regs[i]); |
@@ -408,7 +406,6 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, | |||
408 | 406 | ||
409 | ah->caldata->channel = chan->channel; | 407 | ah->caldata->channel = chan->channel; |
410 | ah->caldata->channelFlags = chan->channelFlags; | 408 | ah->caldata->channelFlags = chan->channelFlags; |
411 | ah->caldata->chanmode = chan->chanmode; | ||
412 | h = ah->caldata->nfCalHist; | 409 | h = ah->caldata->nfCalHist; |
413 | default_nf = ath9k_hw_get_default_nf(ah, chan); | 410 | default_nf = ath9k_hw_get_default_nf(ah, chan); |
414 | for (i = 0; i < NUM_NF_READINGS; i++) { | 411 | for (i = 0; i < NUM_NF_READINGS; i++) { |
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index d3063c21e16c..a7e5a05b2eff 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c | |||
@@ -49,103 +49,64 @@ int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb) | |||
49 | } | 49 | } |
50 | EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype); | 50 | EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype); |
51 | 51 | ||
52 | static u32 ath9k_get_extchanmode(struct cfg80211_chan_def *chandef) | ||
53 | { | ||
54 | u32 chanmode = 0; | ||
55 | |||
56 | switch (chandef->chan->band) { | ||
57 | case IEEE80211_BAND_2GHZ: | ||
58 | switch (chandef->width) { | ||
59 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
60 | case NL80211_CHAN_WIDTH_20: | ||
61 | chanmode = CHANNEL_G_HT20; | ||
62 | break; | ||
63 | case NL80211_CHAN_WIDTH_40: | ||
64 | if (chandef->center_freq1 > chandef->chan->center_freq) | ||
65 | chanmode = CHANNEL_G_HT40PLUS; | ||
66 | else | ||
67 | chanmode = CHANNEL_G_HT40MINUS; | ||
68 | break; | ||
69 | default: | ||
70 | break; | ||
71 | } | ||
72 | break; | ||
73 | case IEEE80211_BAND_5GHZ: | ||
74 | switch (chandef->width) { | ||
75 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
76 | case NL80211_CHAN_WIDTH_20: | ||
77 | chanmode = CHANNEL_A_HT20; | ||
78 | break; | ||
79 | case NL80211_CHAN_WIDTH_40: | ||
80 | if (chandef->center_freq1 > chandef->chan->center_freq) | ||
81 | chanmode = CHANNEL_A_HT40PLUS; | ||
82 | else | ||
83 | chanmode = CHANNEL_A_HT40MINUS; | ||
84 | break; | ||
85 | default: | ||
86 | break; | ||
87 | } | ||
88 | break; | ||
89 | default: | ||
90 | break; | ||
91 | } | ||
92 | |||
93 | return chanmode; | ||
94 | } | ||
95 | |||
96 | /* | 52 | /* |
97 | * Update internal channel flags. | 53 | * Update internal channel flags. |
98 | */ | 54 | */ |
99 | void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, | 55 | static void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, |
100 | struct cfg80211_chan_def *chandef) | 56 | struct cfg80211_chan_def *chandef) |
101 | { | 57 | { |
102 | ichan->channel = chandef->chan->center_freq; | 58 | struct ieee80211_channel *chan = chandef->chan; |
103 | ichan->chan = chandef->chan; | 59 | u16 flags = 0; |
104 | 60 | ||
105 | if (chandef->chan->band == IEEE80211_BAND_2GHZ) { | 61 | ichan->channel = chan->center_freq; |
106 | ichan->chanmode = CHANNEL_G; | 62 | ichan->chan = chan; |
107 | ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM; | 63 | |
108 | } else { | 64 | if (chan->band == IEEE80211_BAND_5GHZ) |
109 | ichan->chanmode = CHANNEL_A; | 65 | flags |= CHANNEL_5GHZ; |
110 | ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; | ||
111 | } | ||
112 | 66 | ||
113 | switch (chandef->width) { | 67 | switch (chandef->width) { |
114 | case NL80211_CHAN_WIDTH_5: | 68 | case NL80211_CHAN_WIDTH_5: |
115 | ichan->channelFlags |= CHANNEL_QUARTER; | 69 | flags |= CHANNEL_QUARTER; |
116 | break; | 70 | break; |
117 | case NL80211_CHAN_WIDTH_10: | 71 | case NL80211_CHAN_WIDTH_10: |
118 | ichan->channelFlags |= CHANNEL_HALF; | 72 | flags |= CHANNEL_HALF; |
119 | break; | 73 | break; |
120 | case NL80211_CHAN_WIDTH_20_NOHT: | 74 | case NL80211_CHAN_WIDTH_20_NOHT: |
121 | break; | 75 | break; |
122 | case NL80211_CHAN_WIDTH_20: | 76 | case NL80211_CHAN_WIDTH_20: |
77 | flags |= CHANNEL_HT; | ||
78 | break; | ||
123 | case NL80211_CHAN_WIDTH_40: | 79 | case NL80211_CHAN_WIDTH_40: |
124 | ichan->chanmode = ath9k_get_extchanmode(chandef); | 80 | if (chandef->center_freq1 > chandef->chan->center_freq) |
81 | flags |= CHANNEL_HT40PLUS | CHANNEL_HT; | ||
82 | else | ||
83 | flags |= CHANNEL_HT40MINUS | CHANNEL_HT; | ||
125 | break; | 84 | break; |
126 | default: | 85 | default: |
127 | WARN_ON(1); | 86 | WARN_ON(1); |
128 | } | 87 | } |
88 | |||
89 | ichan->channelFlags = flags; | ||
129 | } | 90 | } |
130 | EXPORT_SYMBOL(ath9k_cmn_update_ichannel); | ||
131 | 91 | ||
132 | /* | 92 | /* |
133 | * Get the internal channel reference. | 93 | * Get the internal channel reference. |
134 | */ | 94 | */ |
135 | struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, | 95 | struct ath9k_channel *ath9k_cmn_get_channel(struct ieee80211_hw *hw, |
136 | struct ath_hw *ah) | 96 | struct ath_hw *ah, |
97 | struct cfg80211_chan_def *chandef) | ||
137 | { | 98 | { |
138 | struct ieee80211_channel *curchan = hw->conf.chandef.chan; | 99 | struct ieee80211_channel *curchan = chandef->chan; |
139 | struct ath9k_channel *channel; | 100 | struct ath9k_channel *channel; |
140 | u8 chan_idx; | 101 | u8 chan_idx; |
141 | 102 | ||
142 | chan_idx = curchan->hw_value; | 103 | chan_idx = curchan->hw_value; |
143 | channel = &ah->channels[chan_idx]; | 104 | channel = &ah->channels[chan_idx]; |
144 | ath9k_cmn_update_ichannel(channel, &hw->conf.chandef); | 105 | ath9k_cmn_update_ichannel(channel, chandef); |
145 | 106 | ||
146 | return channel; | 107 | return channel; |
147 | } | 108 | } |
148 | EXPORT_SYMBOL(ath9k_cmn_get_curchannel); | 109 | EXPORT_SYMBOL(ath9k_cmn_get_channel); |
149 | 110 | ||
150 | int ath9k_cmn_count_streams(unsigned int chainmask, int max) | 111 | int ath9k_cmn_count_streams(unsigned int chainmask, int max) |
151 | { | 112 | { |
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index e039bcbfbd79..eb85e1bdca88 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h | |||
@@ -43,10 +43,9 @@ | |||
43 | (((x) + ((mul)/2)) / (mul)) | 43 | (((x) + ((mul)/2)) / (mul)) |
44 | 44 | ||
45 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); | 45 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); |
46 | void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, | 46 | struct ath9k_channel *ath9k_cmn_get_channel(struct ieee80211_hw *hw, |
47 | struct cfg80211_chan_def *chandef); | 47 | struct ath_hw *ah, |
48 | struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, | 48 | struct cfg80211_chan_def *chandef); |
49 | struct ath_hw *ah); | ||
50 | int ath9k_cmn_count_streams(unsigned int chainmask, int max); | 49 | int ath9k_cmn_count_streams(unsigned int chainmask, int max); |
51 | void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, | 50 | void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, |
52 | enum ath_stomp_type stomp_type); | 51 | enum ath_stomp_type stomp_type); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index d44258172c0f..9a2657fdd9cc 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -24,30 +24,10 @@ | |||
24 | static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv, | 24 | static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv, |
25 | struct ath9k_channel *ichan) | 25 | struct ath9k_channel *ichan) |
26 | { | 26 | { |
27 | enum htc_phymode mode; | 27 | if (IS_CHAN_5GHZ(ichan)) |
28 | 28 | return HTC_MODE_11NA; | |
29 | mode = -EINVAL; | ||
30 | |||
31 | switch (ichan->chanmode) { | ||
32 | case CHANNEL_G: | ||
33 | case CHANNEL_G_HT20: | ||
34 | case CHANNEL_G_HT40PLUS: | ||
35 | case CHANNEL_G_HT40MINUS: | ||
36 | mode = HTC_MODE_11NG; | ||
37 | break; | ||
38 | case CHANNEL_A: | ||
39 | case CHANNEL_A_HT20: | ||
40 | case CHANNEL_A_HT40PLUS: | ||
41 | case CHANNEL_A_HT40MINUS: | ||
42 | mode = HTC_MODE_11NA; | ||
43 | break; | ||
44 | default: | ||
45 | break; | ||
46 | } | ||
47 | 29 | ||
48 | WARN_ON(mode < 0); | 30 | return HTC_MODE_11NG; |
49 | |||
50 | return mode; | ||
51 | } | 31 | } |
52 | 32 | ||
53 | bool ath9k_htc_setpower(struct ath9k_htc_priv *priv, | 33 | bool ath9k_htc_setpower(struct ath9k_htc_priv *priv, |
@@ -926,7 +906,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
926 | WMI_CMD(WMI_FLUSH_RECV_CMDID); | 906 | WMI_CMD(WMI_FLUSH_RECV_CMDID); |
927 | 907 | ||
928 | /* setup initial channel */ | 908 | /* setup initial channel */ |
929 | init_channel = ath9k_cmn_get_curchannel(hw, ah); | 909 | init_channel = ath9k_cmn_get_channel(hw, ah, &hw->conf.chandef); |
930 | 910 | ||
931 | ret = ath9k_hw_reset(ah, init_channel, ah->caldata, false); | 911 | ret = ath9k_hw_reset(ah, init_channel, ah->caldata, false); |
932 | if (ret) { | 912 | if (ret) { |
@@ -1208,9 +1188,7 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) | |||
1208 | ath_dbg(common, CONFIG, "Set channel: %d MHz\n", | 1188 | ath_dbg(common, CONFIG, "Set channel: %d MHz\n", |
1209 | curchan->center_freq); | 1189 | curchan->center_freq); |
1210 | 1190 | ||
1211 | ath9k_cmn_update_ichannel(&priv->ah->channels[pos], | 1191 | ath9k_cmn_get_channel(hw, priv->ah, &hw->conf.chandef); |
1212 | &hw->conf.chandef); | ||
1213 | |||
1214 | if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) { | 1192 | if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) { |
1215 | ath_err(common, "Unable to set channel\n"); | 1193 | ath_err(common, "Unable to set channel\n"); |
1216 | ret = -EINVAL; | 1194 | ret = -EINVAL; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index f11e8389a9be..dcdbab48709e 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -130,29 +130,29 @@ void ath9k_debug_sync_cause(struct ath_common *common, u32 sync_cause) | |||
130 | 130 | ||
131 | static void ath9k_hw_set_clockrate(struct ath_hw *ah) | 131 | static void ath9k_hw_set_clockrate(struct ath_hw *ah) |
132 | { | 132 | { |
133 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | ||
134 | struct ath_common *common = ath9k_hw_common(ah); | 133 | struct ath_common *common = ath9k_hw_common(ah); |
134 | struct ath9k_channel *chan = ah->curchan; | ||
135 | unsigned int clockrate; | 135 | unsigned int clockrate; |
136 | 136 | ||
137 | /* AR9287 v1.3+ uses async FIFO and runs the MAC at 117 MHz */ | 137 | /* AR9287 v1.3+ uses async FIFO and runs the MAC at 117 MHz */ |
138 | if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) | 138 | if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) |
139 | clockrate = 117; | 139 | clockrate = 117; |
140 | else if (!ah->curchan) /* should really check for CCK instead */ | 140 | else if (!chan) /* should really check for CCK instead */ |
141 | clockrate = ATH9K_CLOCK_RATE_CCK; | 141 | clockrate = ATH9K_CLOCK_RATE_CCK; |
142 | else if (conf->chandef.chan->band == IEEE80211_BAND_2GHZ) | 142 | else if (IS_CHAN_2GHZ(chan)) |
143 | clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM; | 143 | clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM; |
144 | else if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK) | 144 | else if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK) |
145 | clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM; | 145 | clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM; |
146 | else | 146 | else |
147 | clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM; | 147 | clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM; |
148 | 148 | ||
149 | if (conf_is_ht40(conf)) | 149 | if (IS_CHAN_HT40(chan)) |
150 | clockrate *= 2; | 150 | clockrate *= 2; |
151 | 151 | ||
152 | if (ah->curchan) { | 152 | if (ah->curchan) { |
153 | if (IS_CHAN_HALF_RATE(ah->curchan)) | 153 | if (IS_CHAN_HALF_RATE(chan)) |
154 | clockrate /= 2; | 154 | clockrate /= 2; |
155 | if (IS_CHAN_QUARTER_RATE(ah->curchan)) | 155 | if (IS_CHAN_QUARTER_RATE(chan)) |
156 | clockrate /= 4; | 156 | clockrate /= 4; |
157 | } | 157 | } |
158 | 158 | ||
@@ -190,10 +190,7 @@ EXPORT_SYMBOL(ath9k_hw_wait); | |||
190 | void ath9k_hw_synth_delay(struct ath_hw *ah, struct ath9k_channel *chan, | 190 | void ath9k_hw_synth_delay(struct ath_hw *ah, struct ath9k_channel *chan, |
191 | int hw_delay) | 191 | int hw_delay) |
192 | { | 192 | { |
193 | if (IS_CHAN_B(chan)) | 193 | hw_delay /= 10; |
194 | hw_delay = (4 * hw_delay) / 22; | ||
195 | else | ||
196 | hw_delay /= 10; | ||
197 | 194 | ||
198 | if (IS_CHAN_HALF_RATE(chan)) | 195 | if (IS_CHAN_HALF_RATE(chan)) |
199 | hw_delay *= 2; | 196 | hw_delay *= 2; |
@@ -294,8 +291,7 @@ void ath9k_hw_get_channel_centers(struct ath_hw *ah, | |||
294 | return; | 291 | return; |
295 | } | 292 | } |
296 | 293 | ||
297 | if ((chan->chanmode == CHANNEL_A_HT40PLUS) || | 294 | if (IS_CHAN_HT40PLUS(chan)) { |
298 | (chan->chanmode == CHANNEL_G_HT40PLUS)) { | ||
299 | centers->synth_center = | 295 | centers->synth_center = |
300 | chan->channel + HT40_CHANNEL_CENTER_SHIFT; | 296 | chan->channel + HT40_CHANNEL_CENTER_SHIFT; |
301 | extoff = 1; | 297 | extoff = 1; |
@@ -1042,7 +1038,6 @@ static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) | |||
1042 | void ath9k_hw_init_global_settings(struct ath_hw *ah) | 1038 | void ath9k_hw_init_global_settings(struct ath_hw *ah) |
1043 | { | 1039 | { |
1044 | struct ath_common *common = ath9k_hw_common(ah); | 1040 | struct ath_common *common = ath9k_hw_common(ah); |
1045 | struct ieee80211_conf *conf = &common->hw->conf; | ||
1046 | const struct ath9k_channel *chan = ah->curchan; | 1041 | const struct ath9k_channel *chan = ah->curchan; |
1047 | int acktimeout, ctstimeout, ack_offset = 0; | 1042 | int acktimeout, ctstimeout, ack_offset = 0; |
1048 | int slottime; | 1043 | int slottime; |
@@ -1117,8 +1112,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) | |||
1117 | * BA frames in some implementations, but it has been found to fix ACK | 1112 | * BA frames in some implementations, but it has been found to fix ACK |
1118 | * timeout issues in other cases as well. | 1113 | * timeout issues in other cases as well. |
1119 | */ | 1114 | */ |
1120 | if (conf->chandef.chan && | 1115 | if (IS_CHAN_2GHZ(chan) && |
1121 | conf->chandef.chan->band == IEEE80211_BAND_2GHZ && | ||
1122 | !IS_CHAN_HALF_RATE(chan) && !IS_CHAN_QUARTER_RATE(chan)) { | 1116 | !IS_CHAN_HALF_RATE(chan) && !IS_CHAN_QUARTER_RATE(chan)) { |
1123 | acktimeout += 64 - sifstime - ah->slottime; | 1117 | acktimeout += 64 - sifstime - ah->slottime; |
1124 | ctstimeout += 48 - sifstime - ah->slottime; | 1118 | ctstimeout += 48 - sifstime - ah->slottime; |
@@ -1160,9 +1154,7 @@ u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan) | |||
1160 | { | 1154 | { |
1161 | u32 ctl = ath_regd_get_band_ctl(reg, chan->chan->band); | 1155 | u32 ctl = ath_regd_get_band_ctl(reg, chan->chan->band); |
1162 | 1156 | ||
1163 | if (IS_CHAN_B(chan)) | 1157 | if (IS_CHAN_2GHZ(chan)) |
1164 | ctl |= CTL_11B; | ||
1165 | else if (IS_CHAN_G(chan)) | ||
1166 | ctl |= CTL_11G; | 1158 | ctl |= CTL_11G; |
1167 | else | 1159 | else |
1168 | ctl |= CTL_11A; | 1160 | ctl |= CTL_11A; |
@@ -1510,10 +1502,8 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, | |||
1510 | int r; | 1502 | int r; |
1511 | 1503 | ||
1512 | if (pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) { | 1504 | if (pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) { |
1513 | u32 cur = ah->curchan->channelFlags & (CHANNEL_2GHZ | CHANNEL_5GHZ); | 1505 | band_switch = IS_CHAN_5GHZ(ah->curchan) != IS_CHAN_5GHZ(chan); |
1514 | u32 new = chan->channelFlags & (CHANNEL_2GHZ | CHANNEL_5GHZ); | 1506 | mode_diff = (chan->channelFlags != ah->curchan->channelFlags); |
1515 | band_switch = (cur != new); | ||
1516 | mode_diff = (chan->chanmode != ah->curchan->chanmode); | ||
1517 | } | 1507 | } |
1518 | 1508 | ||
1519 | for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { | 1509 | for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { |
@@ -1552,9 +1542,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, | |||
1552 | ath9k_hw_set_clockrate(ah); | 1542 | ath9k_hw_set_clockrate(ah); |
1553 | ath9k_hw_apply_txpower(ah, chan, false); | 1543 | ath9k_hw_apply_txpower(ah, chan, false); |
1554 | 1544 | ||
1555 | if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) | 1545 | ath9k_hw_set_delta_slope(ah, chan); |
1556 | ath9k_hw_set_delta_slope(ah, chan); | ||
1557 | |||
1558 | ath9k_hw_spur_mitigate_freq(ah, chan); | 1546 | ath9k_hw_spur_mitigate_freq(ah, chan); |
1559 | 1547 | ||
1560 | if (band_switch || ini_reloaded) | 1548 | if (band_switch || ini_reloaded) |
@@ -1824,20 +1812,11 @@ static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan) | |||
1824 | goto fail; | 1812 | goto fail; |
1825 | 1813 | ||
1826 | /* | 1814 | /* |
1827 | * If cross-band fcc is not supoprted, bail out if | 1815 | * If cross-band fcc is not supoprted, bail out if channelFlags differ. |
1828 | * either channelFlags or chanmode differ. | ||
1829 | * | ||
1830 | * chanmode will be different if the HT operating mode | ||
1831 | * changes because of CSA. | ||
1832 | */ | 1816 | */ |
1833 | if (!(pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH)) { | 1817 | if (!(pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) && |
1834 | if ((chan->channelFlags & CHANNEL_ALL) != | 1818 | chan->channelFlags != ah->curchan->channelFlags) |
1835 | (ah->curchan->channelFlags & CHANNEL_ALL)) | 1819 | goto fail; |
1836 | goto fail; | ||
1837 | |||
1838 | if (chan->chanmode != ah->curchan->chanmode) | ||
1839 | goto fail; | ||
1840 | } | ||
1841 | 1820 | ||
1842 | if (!ath9k_hw_check_alive(ah)) | 1821 | if (!ath9k_hw_check_alive(ah)) |
1843 | goto fail; | 1822 | goto fail; |
@@ -1899,8 +1878,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1899 | 1878 | ||
1900 | ah->caldata = caldata; | 1879 | ah->caldata = caldata; |
1901 | if (caldata && (chan->channel != caldata->channel || | 1880 | if (caldata && (chan->channel != caldata->channel || |
1902 | chan->channelFlags != caldata->channelFlags || | 1881 | chan->channelFlags != caldata->channelFlags)) { |
1903 | chan->chanmode != caldata->chanmode)) { | ||
1904 | /* Operating channel changed, reset channel calibration data */ | 1882 | /* Operating channel changed, reset channel calibration data */ |
1905 | memset(caldata, 0, sizeof(*caldata)); | 1883 | memset(caldata, 0, sizeof(*caldata)); |
1906 | ath9k_init_nfcal_hist_buffer(ah, chan); | 1884 | ath9k_init_nfcal_hist_buffer(ah, chan); |
@@ -1989,9 +1967,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1989 | 1967 | ||
1990 | ath9k_hw_init_mfp(ah); | 1968 | ath9k_hw_init_mfp(ah); |
1991 | 1969 | ||
1992 | if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) | 1970 | ath9k_hw_set_delta_slope(ah, chan); |
1993 | ath9k_hw_set_delta_slope(ah, chan); | ||
1994 | |||
1995 | ath9k_hw_spur_mitigate_freq(ah, chan); | 1971 | ath9k_hw_spur_mitigate_freq(ah, chan); |
1996 | ah->eep_ops->set_board_values(ah, chan); | 1972 | ah->eep_ops->set_board_values(ah, chan); |
1997 | 1973 | ||
@@ -2968,12 +2944,11 @@ void ath9k_hw_set_tsfadjust(struct ath_hw *ah, bool set) | |||
2968 | } | 2944 | } |
2969 | EXPORT_SYMBOL(ath9k_hw_set_tsfadjust); | 2945 | EXPORT_SYMBOL(ath9k_hw_set_tsfadjust); |
2970 | 2946 | ||
2971 | void ath9k_hw_set11nmac2040(struct ath_hw *ah) | 2947 | void ath9k_hw_set11nmac2040(struct ath_hw *ah, struct ath9k_channel *chan) |
2972 | { | 2948 | { |
2973 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | ||
2974 | u32 macmode; | 2949 | u32 macmode; |
2975 | 2950 | ||
2976 | if (conf_is_ht40(conf) && !ah->config.cwm_ignore_extcca) | 2951 | if (IS_CHAN_HT40(chan) && !ah->config.cwm_ignore_extcca) |
2977 | macmode = AR_2040_JOINED_RX_CLEAR; | 2952 | macmode = AR_2040_JOINED_RX_CLEAR; |
2978 | else | 2953 | else |
2979 | macmode = 0; | 2954 | macmode = 0; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 2babf931b459..81fcbc756122 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -369,36 +369,6 @@ enum ath9k_int { | |||
369 | ATH9K_INT_NOCARD = 0xffffffff | 369 | ATH9K_INT_NOCARD = 0xffffffff |
370 | }; | 370 | }; |
371 | 371 | ||
372 | #define CHANNEL_CCK 0x00020 | ||
373 | #define CHANNEL_OFDM 0x00040 | ||
374 | #define CHANNEL_2GHZ 0x00080 | ||
375 | #define CHANNEL_5GHZ 0x00100 | ||
376 | #define CHANNEL_PASSIVE 0x00200 | ||
377 | #define CHANNEL_DYN 0x00400 | ||
378 | #define CHANNEL_HALF 0x04000 | ||
379 | #define CHANNEL_QUARTER 0x08000 | ||
380 | #define CHANNEL_HT20 0x10000 | ||
381 | #define CHANNEL_HT40PLUS 0x20000 | ||
382 | #define CHANNEL_HT40MINUS 0x40000 | ||
383 | |||
384 | #define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM) | ||
385 | #define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK) | ||
386 | #define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM) | ||
387 | #define CHANNEL_G_HT20 (CHANNEL_2GHZ|CHANNEL_HT20) | ||
388 | #define CHANNEL_A_HT20 (CHANNEL_5GHZ|CHANNEL_HT20) | ||
389 | #define CHANNEL_G_HT40PLUS (CHANNEL_2GHZ|CHANNEL_HT40PLUS) | ||
390 | #define CHANNEL_G_HT40MINUS (CHANNEL_2GHZ|CHANNEL_HT40MINUS) | ||
391 | #define CHANNEL_A_HT40PLUS (CHANNEL_5GHZ|CHANNEL_HT40PLUS) | ||
392 | #define CHANNEL_A_HT40MINUS (CHANNEL_5GHZ|CHANNEL_HT40MINUS) | ||
393 | #define CHANNEL_ALL \ | ||
394 | (CHANNEL_OFDM| \ | ||
395 | CHANNEL_CCK| \ | ||
396 | CHANNEL_2GHZ | \ | ||
397 | CHANNEL_5GHZ | \ | ||
398 | CHANNEL_HT20 | \ | ||
399 | CHANNEL_HT40PLUS | \ | ||
400 | CHANNEL_HT40MINUS) | ||
401 | |||
402 | #define MAX_RTT_TABLE_ENTRY 6 | 372 | #define MAX_RTT_TABLE_ENTRY 6 |
403 | #define MAX_IQCAL_MEASUREMENT 8 | 373 | #define MAX_IQCAL_MEASUREMENT 8 |
404 | #define MAX_CL_TAB_ENTRY 16 | 374 | #define MAX_CL_TAB_ENTRY 16 |
@@ -417,8 +387,7 @@ enum ath9k_cal_flags { | |||
417 | 387 | ||
418 | struct ath9k_hw_cal_data { | 388 | struct ath9k_hw_cal_data { |
419 | u16 channel; | 389 | u16 channel; |
420 | u32 channelFlags; | 390 | u16 channelFlags; |
421 | u32 chanmode; | ||
422 | unsigned long cal_flags; | 391 | unsigned long cal_flags; |
423 | int32_t CalValid; | 392 | int32_t CalValid; |
424 | int8_t iCoff; | 393 | int8_t iCoff; |
@@ -436,33 +405,34 @@ struct ath9k_hw_cal_data { | |||
436 | struct ath9k_channel { | 405 | struct ath9k_channel { |
437 | struct ieee80211_channel *chan; | 406 | struct ieee80211_channel *chan; |
438 | u16 channel; | 407 | u16 channel; |
439 | u32 channelFlags; | 408 | u16 channelFlags; |
440 | u32 chanmode; | ||
441 | s16 noisefloor; | 409 | s16 noisefloor; |
442 | }; | 410 | }; |
443 | 411 | ||
444 | #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ | 412 | #define CHANNEL_5GHZ BIT(0) |
445 | (((_c)->channelFlags & CHANNEL_G_HT20) == CHANNEL_G_HT20) || \ | 413 | #define CHANNEL_HALF BIT(1) |
446 | (((_c)->channelFlags & CHANNEL_G_HT40PLUS) == CHANNEL_G_HT40PLUS) || \ | 414 | #define CHANNEL_QUARTER BIT(2) |
447 | (((_c)->channelFlags & CHANNEL_G_HT40MINUS) == CHANNEL_G_HT40MINUS)) | 415 | #define CHANNEL_HT BIT(3) |
448 | #define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0) | 416 | #define CHANNEL_HT40PLUS BIT(4) |
449 | #define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0) | 417 | #define CHANNEL_HT40MINUS BIT(5) |
450 | #define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0) | 418 | |
451 | #define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0) | 419 | #define IS_CHAN_5GHZ(_c) (!!((_c)->channelFlags & CHANNEL_5GHZ)) |
452 | #define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0) | 420 | #define IS_CHAN_2GHZ(_c) (!IS_CHAN_5GHZ(_c)) |
421 | |||
422 | #define IS_CHAN_HALF_RATE(_c) (!!((_c)->channelFlags & CHANNEL_HALF)) | ||
423 | #define IS_CHAN_QUARTER_RATE(_c) (!!((_c)->channelFlags & CHANNEL_QUARTER)) | ||
453 | #define IS_CHAN_A_FAST_CLOCK(_ah, _c) \ | 424 | #define IS_CHAN_A_FAST_CLOCK(_ah, _c) \ |
454 | ((((_c)->channelFlags & CHANNEL_5GHZ) != 0) && \ | 425 | (IS_CHAN_5GHZ(_c) && ((_ah)->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)) |
455 | ((_ah)->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)) | 426 | |
456 | 427 | #define IS_CHAN_HT(_c) ((_c)->channelFlags & CHANNEL_HT) | |
457 | /* These macros check chanmode and not channelFlags */ | 428 | |
458 | #define IS_CHAN_B(_c) ((_c)->chanmode == CHANNEL_B) | 429 | #define IS_CHAN_HT20(_c) (IS_CHAN_HT(_c) && !IS_CHAN_HT40(_c)) |
459 | #define IS_CHAN_HT20(_c) (((_c)->chanmode == CHANNEL_A_HT20) || \ | 430 | |
460 | ((_c)->chanmode == CHANNEL_G_HT20)) | 431 | #define IS_CHAN_HT40(_c) \ |
461 | #define IS_CHAN_HT40(_c) (((_c)->chanmode == CHANNEL_A_HT40PLUS) || \ | 432 | (!!((_c)->channelFlags & (CHANNEL_HT40PLUS | CHANNEL_HT40MINUS))) |
462 | ((_c)->chanmode == CHANNEL_A_HT40MINUS) || \ | 433 | |
463 | ((_c)->chanmode == CHANNEL_G_HT40PLUS) || \ | 434 | #define IS_CHAN_HT40PLUS(_c) ((_c)->channelFlags & CHANNEL_HT40PLUS) |
464 | ((_c)->chanmode == CHANNEL_G_HT40MINUS)) | 435 | #define IS_CHAN_HT40MINUS(_c) ((_c)->channelFlags & CHANNEL_HT40MINUS) |
465 | #define IS_CHAN_HT(_c) (IS_CHAN_HT20((_c)) || IS_CHAN_HT40((_c))) | ||
466 | 436 | ||
467 | enum ath9k_power_mode { | 437 | enum ath9k_power_mode { |
468 | ATH9K_PM_AWAKE = 0, | 438 | ATH9K_PM_AWAKE = 0, |
@@ -1033,7 +1003,7 @@ void ath9k_hw_reset_tsf(struct ath_hw *ah); | |||
1033 | void ath9k_hw_set_tsfadjust(struct ath_hw *ah, bool set); | 1003 | void ath9k_hw_set_tsfadjust(struct ath_hw *ah, bool set); |
1034 | void ath9k_hw_init_global_settings(struct ath_hw *ah); | 1004 | void ath9k_hw_init_global_settings(struct ath_hw *ah); |
1035 | u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah); | 1005 | u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah); |
1036 | void ath9k_hw_set11nmac2040(struct ath_hw *ah); | 1006 | void ath9k_hw_set11nmac2040(struct ath_hw *ah, struct ath9k_channel *chan); |
1037 | void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); | 1007 | void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); |
1038 | void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, | 1008 | void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, |
1039 | const struct ath9k_beacon_state *bs); | 1009 | const struct ath9k_beacon_state *bs); |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index e3d11c41a145..7df728f36330 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -347,7 +347,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
347 | { | 347 | { |
348 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 348 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
349 | u8 *ds; | 349 | u8 *ds; |
350 | struct ath_buf *bf; | ||
351 | int i, bsize, desc_len; | 350 | int i, bsize, desc_len; |
352 | 351 | ||
353 | ath_dbg(common, CONFIG, "%s DMA: %u buffers %u desc/buf\n", | 352 | ath_dbg(common, CONFIG, "%s DMA: %u buffers %u desc/buf\n", |
@@ -399,33 +398,68 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
399 | ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); | 398 | ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); |
400 | 399 | ||
401 | /* allocate buffers */ | 400 | /* allocate buffers */ |
402 | bsize = sizeof(struct ath_buf) * nbuf; | 401 | if (is_tx) { |
403 | bf = devm_kzalloc(sc->dev, bsize, GFP_KERNEL); | 402 | struct ath_buf *bf; |
404 | if (!bf) | 403 | |
405 | return -ENOMEM; | 404 | bsize = sizeof(struct ath_buf) * nbuf; |
405 | bf = devm_kzalloc(sc->dev, bsize, GFP_KERNEL); | ||
406 | if (!bf) | ||
407 | return -ENOMEM; | ||
408 | |||
409 | for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) { | ||
410 | bf->bf_desc = ds; | ||
411 | bf->bf_daddr = DS2PHYS(dd, ds); | ||
412 | |||
413 | if (!(sc->sc_ah->caps.hw_caps & | ||
414 | ATH9K_HW_CAP_4KB_SPLITTRANS)) { | ||
415 | /* | ||
416 | * Skip descriptor addresses which can cause 4KB | ||
417 | * boundary crossing (addr + length) with a 32 dword | ||
418 | * descriptor fetch. | ||
419 | */ | ||
420 | while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { | ||
421 | BUG_ON((caddr_t) bf->bf_desc >= | ||
422 | ((caddr_t) dd->dd_desc + | ||
423 | dd->dd_desc_len)); | ||
424 | |||
425 | ds += (desc_len * ndesc); | ||
426 | bf->bf_desc = ds; | ||
427 | bf->bf_daddr = DS2PHYS(dd, ds); | ||
428 | } | ||
429 | } | ||
430 | list_add_tail(&bf->list, head); | ||
431 | } | ||
432 | } else { | ||
433 | struct ath_rxbuf *bf; | ||
434 | |||
435 | bsize = sizeof(struct ath_rxbuf) * nbuf; | ||
436 | bf = devm_kzalloc(sc->dev, bsize, GFP_KERNEL); | ||
437 | if (!bf) | ||
438 | return -ENOMEM; | ||
406 | 439 | ||
407 | for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) { | 440 | for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) { |
408 | bf->bf_desc = ds; | 441 | bf->bf_desc = ds; |
409 | bf->bf_daddr = DS2PHYS(dd, ds); | 442 | bf->bf_daddr = DS2PHYS(dd, ds); |
410 | 443 | ||
411 | if (!(sc->sc_ah->caps.hw_caps & | 444 | if (!(sc->sc_ah->caps.hw_caps & |
412 | ATH9K_HW_CAP_4KB_SPLITTRANS)) { | 445 | ATH9K_HW_CAP_4KB_SPLITTRANS)) { |
413 | /* | 446 | /* |
414 | * Skip descriptor addresses which can cause 4KB | 447 | * Skip descriptor addresses which can cause 4KB |
415 | * boundary crossing (addr + length) with a 32 dword | 448 | * boundary crossing (addr + length) with a 32 dword |
416 | * descriptor fetch. | 449 | * descriptor fetch. |
417 | */ | 450 | */ |
418 | while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { | 451 | while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { |
419 | BUG_ON((caddr_t) bf->bf_desc >= | 452 | BUG_ON((caddr_t) bf->bf_desc >= |
420 | ((caddr_t) dd->dd_desc + | 453 | ((caddr_t) dd->dd_desc + |
421 | dd->dd_desc_len)); | 454 | dd->dd_desc_len)); |
422 | 455 | ||
423 | ds += (desc_len * ndesc); | 456 | ds += (desc_len * ndesc); |
424 | bf->bf_desc = ds; | 457 | bf->bf_desc = ds; |
425 | bf->bf_daddr = DS2PHYS(dd, ds); | 458 | bf->bf_daddr = DS2PHYS(dd, ds); |
459 | } | ||
426 | } | 460 | } |
461 | list_add_tail(&bf->list, head); | ||
427 | } | 462 | } |
428 | list_add_tail(&bf->list, head); | ||
429 | } | 463 | } |
430 | return 0; | 464 | return 0; |
431 | } | 465 | } |
@@ -437,7 +471,6 @@ static int ath9k_init_queues(struct ath_softc *sc) | |||
437 | sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah); | 471 | sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah); |
438 | sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); | 472 | sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); |
439 | 473 | ||
440 | sc->config.cabqReadytime = ATH_CABQ_READY_TIME; | ||
441 | ath_cabq_update(sc); | 474 | ath_cabq_update(sc); |
442 | 475 | ||
443 | sc->tx.uapsdq = ath_txq_setup(sc, ATH9K_TX_QUEUE_UAPSD, 0); | 476 | sc->tx.uapsdq = ath_txq_setup(sc, ATH9K_TX_QUEUE_UAPSD, 0); |
@@ -768,7 +801,7 @@ static void ath9k_init_band_txpower(struct ath_softc *sc, int band) | |||
768 | chan = &sband->channels[i]; | 801 | chan = &sband->channels[i]; |
769 | ah->curchan = &ah->channels[chan->hw_value]; | 802 | ah->curchan = &ah->channels[chan->hw_value]; |
770 | cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_HT20); | 803 | cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_HT20); |
771 | ath9k_cmn_update_ichannel(ah->curchan, &chandef); | 804 | ath9k_cmn_get_channel(sc->hw, ah, &chandef); |
772 | ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true); | 805 | ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true); |
773 | } | 806 | } |
774 | } | 807 | } |
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index a3eff0986a3f..6a18f9d3e9cc 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -374,7 +374,6 @@ EXPORT_SYMBOL(ath9k_hw_releasetxqueue); | |||
374 | bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) | 374 | bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) |
375 | { | 375 | { |
376 | struct ath_common *common = ath9k_hw_common(ah); | 376 | struct ath_common *common = ath9k_hw_common(ah); |
377 | struct ath9k_channel *chan = ah->curchan; | ||
378 | struct ath9k_tx_queue_info *qi; | 377 | struct ath9k_tx_queue_info *qi; |
379 | u32 cwMin, chanCwMin, value; | 378 | u32 cwMin, chanCwMin, value; |
380 | 379 | ||
@@ -387,10 +386,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) | |||
387 | ath_dbg(common, QUEUE, "Reset TX queue: %u\n", q); | 386 | ath_dbg(common, QUEUE, "Reset TX queue: %u\n", q); |
388 | 387 | ||
389 | if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) { | 388 | if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) { |
390 | if (chan && IS_CHAN_B(chan)) | 389 | chanCwMin = INIT_CWMIN; |
391 | chanCwMin = INIT_CWMIN_11B; | ||
392 | else | ||
393 | chanCwMin = INIT_CWMIN; | ||
394 | 390 | ||
395 | for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1); | 391 | for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1); |
396 | } else | 392 | } else |
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index bfccaceed44e..e3eed81f2439 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -603,8 +603,6 @@ enum ath9k_tx_queue_flags { | |||
603 | #define ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS 0x00000001 | 603 | #define ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS 0x00000001 |
604 | 604 | ||
605 | #define ATH9K_DECOMP_MASK_SIZE 128 | 605 | #define ATH9K_DECOMP_MASK_SIZE 128 |
606 | #define ATH9K_READY_TIME_LO_BOUND 50 | ||
607 | #define ATH9K_READY_TIME_HI_BOUND 96 | ||
608 | 606 | ||
609 | enum ath9k_pkt_type { | 607 | enum ath9k_pkt_type { |
610 | ATH9K_PKT_TYPE_NORMAL = 0, | 608 | ATH9K_PKT_TYPE_NORMAL = 0, |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index cdb3b1e10b95..c42b55c1face 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -302,17 +302,91 @@ out: | |||
302 | * by reseting the chip. To accomplish this we must first cleanup any pending | 302 | * by reseting the chip. To accomplish this we must first cleanup any pending |
303 | * DMA, then restart stuff. | 303 | * DMA, then restart stuff. |
304 | */ | 304 | */ |
305 | static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | 305 | static int ath_set_channel(struct ath_softc *sc, struct cfg80211_chan_def *chandef) |
306 | struct ath9k_channel *hchan) | ||
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 | int r; | 316 | int r; |
309 | 317 | ||
310 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) | 318 | if (test_bit(SC_OP_INVALID, &sc->sc_flags)) |
311 | return -EIO; | 319 | return -EIO; |
312 | 320 | ||
321 | offchannel = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL); | ||
322 | |||
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]; | ||
313 | r = ath_reset_internal(sc, hchan); | 355 | r = ath_reset_internal(sc, hchan); |
356 | if (r) | ||
357 | return r; | ||
314 | 358 | ||
315 | return r; | 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 | static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, | 392 | static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, |
@@ -601,7 +675,7 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
601 | ath9k_ps_wakeup(sc); | 675 | ath9k_ps_wakeup(sc); |
602 | mutex_lock(&sc->mutex); | 676 | mutex_lock(&sc->mutex); |
603 | 677 | ||
604 | init_channel = ath9k_cmn_get_curchannel(hw, ah); | 678 | init_channel = ath9k_cmn_get_channel(hw, ah, &hw->conf.chandef); |
605 | 679 | ||
606 | /* Reset SERDES registers */ | 680 | /* Reset SERDES registers */ |
607 | ath9k_hw_configpcipowersave(ah, false); | 681 | ath9k_hw_configpcipowersave(ah, false); |
@@ -804,7 +878,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
804 | } | 878 | } |
805 | 879 | ||
806 | if (!ah->curchan) | 880 | if (!ah->curchan) |
807 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); | 881 | ah->curchan = ath9k_cmn_get_channel(hw, ah, &hw->conf.chandef); |
808 | 882 | ||
809 | ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); | 883 | ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); |
810 | ath9k_hw_phy_disable(ah); | 884 | ath9k_hw_phy_disable(ah); |
@@ -823,7 +897,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
823 | ath_dbg(common, CONFIG, "Driver halt\n"); | 897 | ath_dbg(common, CONFIG, "Driver halt\n"); |
824 | } | 898 | } |
825 | 899 | ||
826 | bool ath9k_uses_beacons(int type) | 900 | static bool ath9k_uses_beacons(int type) |
827 | { | 901 | { |
828 | switch (type) { | 902 | switch (type) { |
829 | case NL80211_IFTYPE_AP: | 903 | case NL80211_IFTYPE_AP: |
@@ -1208,81 +1282,12 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1208 | } | 1282 | } |
1209 | 1283 | ||
1210 | if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) { | 1284 | if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) { |
1211 | struct ieee80211_channel *curchan = hw->conf.chandef.chan; | 1285 | if (ath_set_channel(sc, &hw->conf.chandef) < 0) { |
1212 | int pos = curchan->hw_value; | ||
1213 | int old_pos = -1; | ||
1214 | unsigned long flags; | ||
1215 | |||
1216 | if (ah->curchan) | ||
1217 | old_pos = ah->curchan - &ah->channels[0]; | ||
1218 | |||
1219 | ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n", | ||
1220 | curchan->center_freq, hw->conf.chandef.width); | ||
1221 | |||
1222 | /* update survey stats for the old channel before switching */ | ||
1223 | spin_lock_irqsave(&common->cc_lock, flags); | ||
1224 | ath_update_survey_stats(sc); | ||
1225 | spin_unlock_irqrestore(&common->cc_lock, flags); | ||
1226 | |||
1227 | ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos], | ||
1228 | &conf->chandef); | ||
1229 | |||
1230 | /* | ||
1231 | * If the operating channel changes, change the survey in-use flags | ||
1232 | * along with it. | ||
1233 | * Reset the survey data for the new channel, unless we're switching | ||
1234 | * back to the operating channel from an off-channel operation. | ||
1235 | */ | ||
1236 | if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) && | ||
1237 | sc->cur_survey != &sc->survey[pos]) { | ||
1238 | |||
1239 | if (sc->cur_survey) | ||
1240 | sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE; | ||
1241 | |||
1242 | sc->cur_survey = &sc->survey[pos]; | ||
1243 | |||
1244 | memset(sc->cur_survey, 0, sizeof(struct survey_info)); | ||
1245 | sc->cur_survey->filled |= SURVEY_INFO_IN_USE; | ||
1246 | } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) { | ||
1247 | memset(&sc->survey[pos], 0, sizeof(struct survey_info)); | ||
1248 | } | ||
1249 | |||
1250 | if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) { | ||
1251 | ath_err(common, "Unable to set channel\n"); | 1286 | ath_err(common, "Unable to set channel\n"); |
1252 | mutex_unlock(&sc->mutex); | 1287 | mutex_unlock(&sc->mutex); |
1253 | ath9k_ps_restore(sc); | 1288 | ath9k_ps_restore(sc); |
1254 | return -EINVAL; | 1289 | return -EINVAL; |
1255 | } | 1290 | } |
1256 | |||
1257 | /* | ||
1258 | * The most recent snapshot of channel->noisefloor for the old | ||
1259 | * channel is only available after the hardware reset. Copy it to | ||
1260 | * the survey stats now. | ||
1261 | */ | ||
1262 | if (old_pos >= 0) | ||
1263 | ath_update_survey_nf(sc, old_pos); | ||
1264 | |||
1265 | /* | ||
1266 | * Enable radar pulse detection if on a DFS channel. Spectral | ||
1267 | * scanning and radar detection can not be used concurrently. | ||
1268 | */ | ||
1269 | if (hw->conf.radar_enabled) { | ||
1270 | u32 rxfilter; | ||
1271 | |||
1272 | /* set HW specific DFS configuration */ | ||
1273 | ath9k_hw_set_radar_params(ah); | ||
1274 | rxfilter = ath9k_hw_getrxfilter(ah); | ||
1275 | rxfilter |= ATH9K_RX_FILTER_PHYRADAR | | ||
1276 | ATH9K_RX_FILTER_PHYERR; | ||
1277 | ath9k_hw_setrxfilter(ah, rxfilter); | ||
1278 | ath_dbg(common, DFS, "DFS enabled at freq %d\n", | ||
1279 | curchan->center_freq); | ||
1280 | } else { | ||
1281 | /* perform spectral scan if requested. */ | ||
1282 | if (test_bit(SC_OP_SCANNING, &sc->sc_flags) && | ||
1283 | sc->spectral_mode == SPECTRAL_CHANSCAN) | ||
1284 | ath9k_spectral_scan_trigger(hw); | ||
1285 | } | ||
1286 | } | 1291 | } |
1287 | 1292 | ||
1288 | if (changed & IEEE80211_CONF_CHANGE_POWER) { | 1293 | if (changed & IEEE80211_CONF_CHANGE_POWER) { |
diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c index 815bee21c19a..0ac1b5f04256 100644 --- a/drivers/net/wireless/ath/ath9k/mci.c +++ b/drivers/net/wireless/ath/ath9k/mci.c | |||
@@ -661,9 +661,9 @@ void ath9k_mci_update_wlan_channels(struct ath_softc *sc, bool allow_all) | |||
661 | chan_start = wlan_chan - 10; | 661 | chan_start = wlan_chan - 10; |
662 | chan_end = wlan_chan + 10; | 662 | chan_end = wlan_chan + 10; |
663 | 663 | ||
664 | if (chan->chanmode == CHANNEL_G_HT40PLUS) | 664 | if (IS_CHAN_HT40PLUS(chan)) |
665 | chan_end += 20; | 665 | chan_end += 20; |
666 | else if (chan->chanmode == CHANNEL_G_HT40MINUS) | 666 | else if (IS_CHAN_HT40MINUS(chan)) |
667 | chan_start -= 20; | 667 | chan_start -= 20; |
668 | 668 | ||
669 | /* adjust side band */ | 669 | /* adjust side band */ |
@@ -707,11 +707,11 @@ void ath9k_mci_set_txpower(struct ath_softc *sc, bool setchannel, | |||
707 | 707 | ||
708 | if (setchannel) { | 708 | if (setchannel) { |
709 | struct ath9k_hw_cal_data *caldata = &sc->caldata; | 709 | struct ath9k_hw_cal_data *caldata = &sc->caldata; |
710 | if ((caldata->chanmode == CHANNEL_G_HT40PLUS) && | 710 | if (IS_CHAN_HT40PLUS(ah->curchan) && |
711 | (ah->curchan->channel > caldata->channel) && | 711 | (ah->curchan->channel > caldata->channel) && |
712 | (ah->curchan->channel <= caldata->channel + 20)) | 712 | (ah->curchan->channel <= caldata->channel + 20)) |
713 | return; | 713 | return; |
714 | if ((caldata->chanmode == CHANNEL_G_HT40MINUS) && | 714 | if (IS_CHAN_HT40MINUS(ah->curchan) && |
715 | (ah->curchan->channel < caldata->channel) && | 715 | (ah->curchan->channel < caldata->channel) && |
716 | (ah->curchan->channel >= caldata->channel - 20)) | 716 | (ah->curchan->channel >= caldata->channel - 20)) |
717 | return; | 717 | return; |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index ab9e3a8410bc..8b788efb41fd 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include "ath9k.h" | 19 | #include "ath9k.h" |
20 | #include "ar9003_mac.h" | 20 | #include "ar9003_mac.h" |
21 | 21 | ||
22 | #define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb)) | 22 | #define SKB_CB_ATHBUF(__skb) (*((struct ath_rxbuf **)__skb->cb)) |
23 | 23 | ||
24 | static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) | 24 | static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) |
25 | { | 25 | { |
@@ -35,7 +35,7 @@ static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) | |||
35 | * buffer (or rx fifo). This can incorrectly acknowledge packets | 35 | * buffer (or rx fifo). This can incorrectly acknowledge packets |
36 | * to a sender if last desc is self-linked. | 36 | * to a sender if last desc is self-linked. |
37 | */ | 37 | */ |
38 | static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) | 38 | static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf) |
39 | { | 39 | { |
40 | struct ath_hw *ah = sc->sc_ah; | 40 | struct ath_hw *ah = sc->sc_ah; |
41 | struct ath_common *common = ath9k_hw_common(ah); | 41 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -68,7 +68,7 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) | |||
68 | sc->rx.rxlink = &ds->ds_link; | 68 | sc->rx.rxlink = &ds->ds_link; |
69 | } | 69 | } |
70 | 70 | ||
71 | static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_buf *bf) | 71 | static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf) |
72 | { | 72 | { |
73 | if (sc->rx.buf_hold) | 73 | if (sc->rx.buf_hold) |
74 | ath_rx_buf_link(sc, sc->rx.buf_hold); | 74 | ath_rx_buf_link(sc, sc->rx.buf_hold); |
@@ -112,13 +112,13 @@ static bool ath_rx_edma_buf_link(struct ath_softc *sc, | |||
112 | struct ath_hw *ah = sc->sc_ah; | 112 | struct ath_hw *ah = sc->sc_ah; |
113 | struct ath_rx_edma *rx_edma; | 113 | struct ath_rx_edma *rx_edma; |
114 | struct sk_buff *skb; | 114 | struct sk_buff *skb; |
115 | struct ath_buf *bf; | 115 | struct ath_rxbuf *bf; |
116 | 116 | ||
117 | rx_edma = &sc->rx.rx_edma[qtype]; | 117 | rx_edma = &sc->rx.rx_edma[qtype]; |
118 | if (skb_queue_len(&rx_edma->rx_fifo) >= rx_edma->rx_fifo_hwsize) | 118 | if (skb_queue_len(&rx_edma->rx_fifo) >= rx_edma->rx_fifo_hwsize) |
119 | return false; | 119 | return false; |
120 | 120 | ||
121 | bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); | 121 | bf = list_first_entry(&sc->rx.rxbuf, struct ath_rxbuf, list); |
122 | list_del_init(&bf->list); | 122 | list_del_init(&bf->list); |
123 | 123 | ||
124 | skb = bf->bf_mpdu; | 124 | skb = bf->bf_mpdu; |
@@ -138,7 +138,7 @@ static void ath_rx_addbuffer_edma(struct ath_softc *sc, | |||
138 | enum ath9k_rx_qtype qtype) | 138 | enum ath9k_rx_qtype qtype) |
139 | { | 139 | { |
140 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 140 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
141 | struct ath_buf *bf, *tbf; | 141 | struct ath_rxbuf *bf, *tbf; |
142 | 142 | ||
143 | if (list_empty(&sc->rx.rxbuf)) { | 143 | if (list_empty(&sc->rx.rxbuf)) { |
144 | ath_dbg(common, QUEUE, "No free rx buf available\n"); | 144 | ath_dbg(common, QUEUE, "No free rx buf available\n"); |
@@ -154,7 +154,7 @@ static void ath_rx_addbuffer_edma(struct ath_softc *sc, | |||
154 | static void ath_rx_remove_buffer(struct ath_softc *sc, | 154 | static void ath_rx_remove_buffer(struct ath_softc *sc, |
155 | enum ath9k_rx_qtype qtype) | 155 | enum ath9k_rx_qtype qtype) |
156 | { | 156 | { |
157 | struct ath_buf *bf; | 157 | struct ath_rxbuf *bf; |
158 | struct ath_rx_edma *rx_edma; | 158 | struct ath_rx_edma *rx_edma; |
159 | struct sk_buff *skb; | 159 | struct sk_buff *skb; |
160 | 160 | ||
@@ -171,7 +171,7 @@ static void ath_rx_edma_cleanup(struct ath_softc *sc) | |||
171 | { | 171 | { |
172 | struct ath_hw *ah = sc->sc_ah; | 172 | struct ath_hw *ah = sc->sc_ah; |
173 | struct ath_common *common = ath9k_hw_common(ah); | 173 | struct ath_common *common = ath9k_hw_common(ah); |
174 | struct ath_buf *bf; | 174 | struct ath_rxbuf *bf; |
175 | 175 | ||
176 | ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP); | 176 | ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP); |
177 | ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP); | 177 | ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP); |
@@ -199,7 +199,7 @@ static int ath_rx_edma_init(struct ath_softc *sc, int nbufs) | |||
199 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 199 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
200 | struct ath_hw *ah = sc->sc_ah; | 200 | struct ath_hw *ah = sc->sc_ah; |
201 | struct sk_buff *skb; | 201 | struct sk_buff *skb; |
202 | struct ath_buf *bf; | 202 | struct ath_rxbuf *bf; |
203 | int error = 0, i; | 203 | int error = 0, i; |
204 | u32 size; | 204 | u32 size; |
205 | 205 | ||
@@ -211,7 +211,7 @@ static int ath_rx_edma_init(struct ath_softc *sc, int nbufs) | |||
211 | ath_rx_edma_init_queue(&sc->rx.rx_edma[ATH9K_RX_QUEUE_HP], | 211 | ath_rx_edma_init_queue(&sc->rx.rx_edma[ATH9K_RX_QUEUE_HP], |
212 | ah->caps.rx_hp_qdepth); | 212 | ah->caps.rx_hp_qdepth); |
213 | 213 | ||
214 | size = sizeof(struct ath_buf) * nbufs; | 214 | size = sizeof(struct ath_rxbuf) * nbufs; |
215 | bf = devm_kzalloc(sc->dev, size, GFP_KERNEL); | 215 | bf = devm_kzalloc(sc->dev, size, GFP_KERNEL); |
216 | if (!bf) | 216 | if (!bf) |
217 | return -ENOMEM; | 217 | return -ENOMEM; |
@@ -271,7 +271,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) | |||
271 | { | 271 | { |
272 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 272 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
273 | struct sk_buff *skb; | 273 | struct sk_buff *skb; |
274 | struct ath_buf *bf; | 274 | struct ath_rxbuf *bf; |
275 | int error = 0; | 275 | int error = 0; |
276 | 276 | ||
277 | spin_lock_init(&sc->sc_pcu_lock); | 277 | spin_lock_init(&sc->sc_pcu_lock); |
@@ -332,7 +332,7 @@ void ath_rx_cleanup(struct ath_softc *sc) | |||
332 | struct ath_hw *ah = sc->sc_ah; | 332 | struct ath_hw *ah = sc->sc_ah; |
333 | struct ath_common *common = ath9k_hw_common(ah); | 333 | struct ath_common *common = ath9k_hw_common(ah); |
334 | struct sk_buff *skb; | 334 | struct sk_buff *skb; |
335 | struct ath_buf *bf; | 335 | struct ath_rxbuf *bf; |
336 | 336 | ||
337 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { | 337 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { |
338 | ath_rx_edma_cleanup(sc); | 338 | ath_rx_edma_cleanup(sc); |
@@ -427,7 +427,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
427 | int ath_startrecv(struct ath_softc *sc) | 427 | int ath_startrecv(struct ath_softc *sc) |
428 | { | 428 | { |
429 | struct ath_hw *ah = sc->sc_ah; | 429 | struct ath_hw *ah = sc->sc_ah; |
430 | struct ath_buf *bf, *tbf; | 430 | struct ath_rxbuf *bf, *tbf; |
431 | 431 | ||
432 | if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { | 432 | if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { |
433 | ath_edma_start_recv(sc); | 433 | ath_edma_start_recv(sc); |
@@ -447,7 +447,7 @@ int ath_startrecv(struct ath_softc *sc) | |||
447 | if (list_empty(&sc->rx.rxbuf)) | 447 | if (list_empty(&sc->rx.rxbuf)) |
448 | goto start_recv; | 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 | ath9k_hw_putrxbuf(ah, bf->bf_daddr); | 451 | ath9k_hw_putrxbuf(ah, bf->bf_daddr); |
452 | ath9k_hw_rxena(ah); | 452 | ath9k_hw_rxena(ah); |
453 | 453 | ||
@@ -603,13 +603,13 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb, bool mybeacon) | |||
603 | static bool ath_edma_get_buffers(struct ath_softc *sc, | 603 | static bool ath_edma_get_buffers(struct ath_softc *sc, |
604 | enum ath9k_rx_qtype qtype, | 604 | enum ath9k_rx_qtype qtype, |
605 | struct ath_rx_status *rs, | 605 | struct ath_rx_status *rs, |
606 | struct ath_buf **dest) | 606 | struct ath_rxbuf **dest) |
607 | { | 607 | { |
608 | struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype]; | 608 | struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype]; |
609 | struct ath_hw *ah = sc->sc_ah; | 609 | struct ath_hw *ah = sc->sc_ah; |
610 | struct ath_common *common = ath9k_hw_common(ah); | 610 | struct ath_common *common = ath9k_hw_common(ah); |
611 | struct sk_buff *skb; | 611 | struct sk_buff *skb; |
612 | struct ath_buf *bf; | 612 | struct ath_rxbuf *bf; |
613 | int ret; | 613 | int ret; |
614 | 614 | ||
615 | skb = skb_peek(&rx_edma->rx_fifo); | 615 | skb = skb_peek(&rx_edma->rx_fifo); |
@@ -653,11 +653,11 @@ static bool ath_edma_get_buffers(struct ath_softc *sc, | |||
653 | return true; | 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 | struct ath_rx_status *rs, | 657 | struct ath_rx_status *rs, |
658 | enum ath9k_rx_qtype qtype) | 658 | enum ath9k_rx_qtype qtype) |
659 | { | 659 | { |
660 | struct ath_buf *bf = NULL; | 660 | struct ath_rxbuf *bf = NULL; |
661 | 661 | ||
662 | while (ath_edma_get_buffers(sc, qtype, rs, &bf)) { | 662 | while (ath_edma_get_buffers(sc, qtype, rs, &bf)) { |
663 | if (!bf) | 663 | if (!bf) |
@@ -668,13 +668,13 @@ static struct ath_buf *ath_edma_get_next_rx_buf(struct ath_softc *sc, | |||
668 | return NULL; | 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 | struct ath_rx_status *rs) | 672 | struct ath_rx_status *rs) |
673 | { | 673 | { |
674 | struct ath_hw *ah = sc->sc_ah; | 674 | struct ath_hw *ah = sc->sc_ah; |
675 | struct ath_common *common = ath9k_hw_common(ah); | 675 | struct ath_common *common = ath9k_hw_common(ah); |
676 | struct ath_desc *ds; | 676 | struct ath_desc *ds; |
677 | struct ath_buf *bf; | 677 | struct ath_rxbuf *bf; |
678 | int ret; | 678 | int ret; |
679 | 679 | ||
680 | if (list_empty(&sc->rx.rxbuf)) { | 680 | if (list_empty(&sc->rx.rxbuf)) { |
@@ -682,7 +682,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, | |||
682 | return NULL; | 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 | if (bf == sc->rx.buf_hold) | 686 | if (bf == sc->rx.buf_hold) |
687 | return NULL; | 687 | return NULL; |
688 | 688 | ||
@@ -702,7 +702,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, | |||
702 | ret = ath9k_hw_rxprocdesc(ah, ds, rs); | 702 | ret = ath9k_hw_rxprocdesc(ah, ds, rs); |
703 | if (ret == -EINPROGRESS) { | 703 | if (ret == -EINPROGRESS) { |
704 | struct ath_rx_status trs; | 704 | struct ath_rx_status trs; |
705 | struct ath_buf *tbf; | 705 | struct ath_rxbuf *tbf; |
706 | struct ath_desc *tds; | 706 | struct ath_desc *tds; |
707 | 707 | ||
708 | memset(&trs, 0, sizeof(trs)); | 708 | memset(&trs, 0, sizeof(trs)); |
@@ -711,7 +711,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, | |||
711 | return NULL; | 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 | * On some hardware the descriptor status words could | 717 | * On some hardware the descriptor status words could |
@@ -1308,7 +1308,7 @@ static void ath9k_apply_ampdu_details(struct ath_softc *sc, | |||
1308 | 1308 | ||
1309 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | 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 | struct sk_buff *skb = NULL, *requeue_skb, *hdr_skb; | 1312 | struct sk_buff *skb = NULL, *requeue_skb, *hdr_skb; |
1313 | struct ieee80211_rx_status *rxs; | 1313 | struct ieee80211_rx_status *rxs; |
1314 | struct ath_hw *ah = sc->sc_ah; | 1314 | struct ath_hw *ah = sc->sc_ah; |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 1ce8af276878..47696d29743c 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -1704,16 +1704,9 @@ int ath_cabq_update(struct ath_softc *sc) | |||
1704 | int qnum = sc->beacon.cabq->axq_qnum; | 1704 | int qnum = sc->beacon.cabq->axq_qnum; |
1705 | 1705 | ||
1706 | ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi); | 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 | qi.tqi_readyTime = (cur_conf->beacon_interval * | 1708 | qi.tqi_readyTime = (cur_conf->beacon_interval * |
1716 | sc->config.cabqReadytime) / 100; | 1709 | ATH_CABQ_READY_TIME) / 100; |
1717 | ath_txq_update(sc, qnum, &qi); | 1710 | ath_txq_update(sc, qnum, &qi); |
1718 | 1711 | ||
1719 | return 0; | 1712 | return 0; |
@@ -2037,8 +2030,7 @@ u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate) | |||
2037 | struct ath_hw *ah = sc->sc_ah; | 2030 | struct ath_hw *ah = sc->sc_ah; |
2038 | struct ath9k_channel *curchan = ah->curchan; | 2031 | struct ath9k_channel *curchan = ah->curchan; |
2039 | 2032 | ||
2040 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && | 2033 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && IS_CHAN_5GHZ(curchan) && |
2041 | (curchan->channelFlags & CHANNEL_5GHZ) && | ||
2042 | (chainmask == 0x7) && (rate < 0x90)) | 2034 | (chainmask == 0x7) && (rate < 0x90)) |
2043 | return 0x3; | 2035 | return 0x3; |
2044 | else if (AR_SREV_9462(ah) && ath9k_hw_btcoex_is_enabled(ah) && | 2036 | else if (AR_SREV_9462(ah) && ath9k_hw_btcoex_is_enabled(ah) && |
diff --git a/drivers/net/wireless/ath/wcn36xx/Kconfig b/drivers/net/wireless/ath/wcn36xx/Kconfig new file mode 100644 index 000000000000..591ebaea8265 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/Kconfig | |||
@@ -0,0 +1,16 @@ | |||
1 | config WCN36XX | ||
2 | tristate "Qualcomm Atheros WCN3660/3680 support" | ||
3 | depends on MAC80211 && HAS_DMA | ||
4 | ---help--- | ||
5 | This module adds support for wireless adapters based on | ||
6 | Qualcomm Atheros WCN3660 and WCN3680 mobile chipsets. | ||
7 | |||
8 | If you choose to build a module, it'll be called wcn36xx. | ||
9 | |||
10 | config WCN36XX_DEBUGFS | ||
11 | bool "WCN36XX debugfs support" | ||
12 | depends on WCN36XX | ||
13 | ---help--- | ||
14 | Enabled debugfs support | ||
15 | |||
16 | If unsure, say Y to make it easier to debug problems. | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/Makefile b/drivers/net/wireless/ath/wcn36xx/Makefile new file mode 100644 index 000000000000..50c43b4382ba --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | obj-$(CONFIG_WCN36XX) := wcn36xx.o | ||
2 | wcn36xx-y += main.o \ | ||
3 | dxe.o \ | ||
4 | txrx.o \ | ||
5 | smd.o \ | ||
6 | pmc.o \ | ||
7 | debug.o | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/debug.c b/drivers/net/wireless/ath/wcn36xx/debug.c new file mode 100644 index 000000000000..5b84f7ae0b1e --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/debug.c | |||
@@ -0,0 +1,181 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
19 | #include <linux/debugfs.h> | ||
20 | #include <linux/uaccess.h> | ||
21 | #include "wcn36xx.h" | ||
22 | #include "debug.h" | ||
23 | #include "pmc.h" | ||
24 | |||
25 | #ifdef CONFIG_WCN36XX_DEBUGFS | ||
26 | |||
27 | static ssize_t read_file_bool_bmps(struct file *file, char __user *user_buf, | ||
28 | size_t count, loff_t *ppos) | ||
29 | { | ||
30 | struct wcn36xx *wcn = file->private_data; | ||
31 | struct wcn36xx_vif *vif_priv = NULL; | ||
32 | struct ieee80211_vif *vif = NULL; | ||
33 | char buf[3]; | ||
34 | |||
35 | list_for_each_entry(vif_priv, &wcn->vif_list, list) { | ||
36 | vif = container_of((void *)vif_priv, | ||
37 | struct ieee80211_vif, | ||
38 | drv_priv); | ||
39 | if (NL80211_IFTYPE_STATION == vif->type) { | ||
40 | if (vif_priv->pw_state == WCN36XX_BMPS) | ||
41 | buf[0] = '1'; | ||
42 | else | ||
43 | buf[0] = '0'; | ||
44 | break; | ||
45 | } | ||
46 | } | ||
47 | buf[1] = '\n'; | ||
48 | buf[2] = 0x00; | ||
49 | |||
50 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | ||
51 | } | ||
52 | |||
53 | static ssize_t write_file_bool_bmps(struct file *file, | ||
54 | const char __user *user_buf, | ||
55 | size_t count, loff_t *ppos) | ||
56 | { | ||
57 | struct wcn36xx *wcn = file->private_data; | ||
58 | struct wcn36xx_vif *vif_priv = NULL; | ||
59 | struct ieee80211_vif *vif = NULL; | ||
60 | |||
61 | char buf[32]; | ||
62 | int buf_size; | ||
63 | |||
64 | buf_size = min(count, (sizeof(buf)-1)); | ||
65 | if (copy_from_user(buf, user_buf, buf_size)) | ||
66 | return -EFAULT; | ||
67 | |||
68 | switch (buf[0]) { | ||
69 | case 'y': | ||
70 | case 'Y': | ||
71 | case '1': | ||
72 | list_for_each_entry(vif_priv, &wcn->vif_list, list) { | ||
73 | vif = container_of((void *)vif_priv, | ||
74 | struct ieee80211_vif, | ||
75 | drv_priv); | ||
76 | if (NL80211_IFTYPE_STATION == vif->type) { | ||
77 | wcn36xx_enable_keep_alive_null_packet(wcn, vif); | ||
78 | wcn36xx_pmc_enter_bmps_state(wcn, vif); | ||
79 | } | ||
80 | } | ||
81 | break; | ||
82 | case 'n': | ||
83 | case 'N': | ||
84 | case '0': | ||
85 | list_for_each_entry(vif_priv, &wcn->vif_list, list) { | ||
86 | vif = container_of((void *)vif_priv, | ||
87 | struct ieee80211_vif, | ||
88 | drv_priv); | ||
89 | if (NL80211_IFTYPE_STATION == vif->type) | ||
90 | wcn36xx_pmc_exit_bmps_state(wcn, vif); | ||
91 | } | ||
92 | break; | ||
93 | } | ||
94 | |||
95 | return count; | ||
96 | } | ||
97 | |||
98 | static const struct file_operations fops_wcn36xx_bmps = { | ||
99 | .open = simple_open, | ||
100 | .read = read_file_bool_bmps, | ||
101 | .write = write_file_bool_bmps, | ||
102 | }; | ||
103 | |||
104 | static ssize_t write_file_dump(struct file *file, | ||
105 | const char __user *user_buf, | ||
106 | size_t count, loff_t *ppos) | ||
107 | { | ||
108 | struct wcn36xx *wcn = file->private_data; | ||
109 | char buf[255], *tmp; | ||
110 | int buf_size; | ||
111 | u32 arg[WCN36xx_MAX_DUMP_ARGS]; | ||
112 | int i; | ||
113 | |||
114 | memset(buf, 0, sizeof(buf)); | ||
115 | memset(arg, 0, sizeof(arg)); | ||
116 | |||
117 | buf_size = min(count, (sizeof(buf) - 1)); | ||
118 | if (copy_from_user(buf, user_buf, buf_size)) | ||
119 | return -EFAULT; | ||
120 | |||
121 | tmp = buf; | ||
122 | |||
123 | for (i = 0; i < WCN36xx_MAX_DUMP_ARGS; i++) { | ||
124 | char *begin; | ||
125 | begin = strsep(&tmp, " "); | ||
126 | if (begin == NULL) | ||
127 | break; | ||
128 | |||
129 | if (kstrtoul(begin, 0, (unsigned long *)(arg + i)) != 0) | ||
130 | break; | ||
131 | } | ||
132 | |||
133 | wcn36xx_info("DUMP args is %d %d %d %d %d\n", arg[0], arg[1], arg[2], | ||
134 | arg[3], arg[4]); | ||
135 | wcn36xx_smd_dump_cmd_req(wcn, arg[0], arg[1], arg[2], arg[3], arg[4]); | ||
136 | |||
137 | return count; | ||
138 | } | ||
139 | |||
140 | static const struct file_operations fops_wcn36xx_dump = { | ||
141 | .open = simple_open, | ||
142 | .write = write_file_dump, | ||
143 | }; | ||
144 | |||
145 | #define ADD_FILE(name, mode, fop, priv_data) \ | ||
146 | do { \ | ||
147 | struct dentry *d; \ | ||
148 | d = debugfs_create_file(__stringify(name), \ | ||
149 | mode, dfs->rootdir, \ | ||
150 | priv_data, fop); \ | ||
151 | dfs->file_##name.dentry = d; \ | ||
152 | if (IS_ERR(d)) { \ | ||
153 | wcn36xx_warn("Create the debugfs entry failed");\ | ||
154 | dfs->file_##name.dentry = NULL; \ | ||
155 | } \ | ||
156 | } while (0) | ||
157 | |||
158 | |||
159 | void wcn36xx_debugfs_init(struct wcn36xx *wcn) | ||
160 | { | ||
161 | struct wcn36xx_dfs_entry *dfs = &wcn->dfs; | ||
162 | |||
163 | dfs->rootdir = debugfs_create_dir(KBUILD_MODNAME, | ||
164 | wcn->hw->wiphy->debugfsdir); | ||
165 | if (IS_ERR(dfs->rootdir)) { | ||
166 | wcn36xx_warn("Create the debugfs failed\n"); | ||
167 | dfs->rootdir = NULL; | ||
168 | } | ||
169 | |||
170 | ADD_FILE(bmps_switcher, S_IRUSR | S_IWUSR, | ||
171 | &fops_wcn36xx_bmps, wcn); | ||
172 | ADD_FILE(dump, S_IWUSR, &fops_wcn36xx_dump, wcn); | ||
173 | } | ||
174 | |||
175 | void wcn36xx_debugfs_exit(struct wcn36xx *wcn) | ||
176 | { | ||
177 | struct wcn36xx_dfs_entry *dfs = &wcn->dfs; | ||
178 | debugfs_remove_recursive(dfs->rootdir); | ||
179 | } | ||
180 | |||
181 | #endif /* CONFIG_WCN36XX_DEBUGFS */ | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/debug.h b/drivers/net/wireless/ath/wcn36xx/debug.h new file mode 100644 index 000000000000..46307aa562d3 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/debug.h | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef _WCN36XX_DEBUG_H_ | ||
18 | #define _WCN36XX_DEBUG_H_ | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | |||
22 | #define WCN36xx_MAX_DUMP_ARGS 5 | ||
23 | |||
24 | #ifdef CONFIG_WCN36XX_DEBUGFS | ||
25 | struct wcn36xx_dfs_file { | ||
26 | struct dentry *dentry; | ||
27 | u32 value; | ||
28 | }; | ||
29 | |||
30 | struct wcn36xx_dfs_entry { | ||
31 | struct dentry *rootdir; | ||
32 | struct wcn36xx_dfs_file file_bmps_switcher; | ||
33 | struct wcn36xx_dfs_file file_dump; | ||
34 | }; | ||
35 | |||
36 | void wcn36xx_debugfs_init(struct wcn36xx *wcn); | ||
37 | void wcn36xx_debugfs_exit(struct wcn36xx *wcn); | ||
38 | |||
39 | #else | ||
40 | static inline void wcn36xx_debugfs_init(struct wcn36xx *wcn) | ||
41 | { | ||
42 | } | ||
43 | static inline void wcn36xx_debugfs_exit(struct wcn36xx *wcn) | ||
44 | { | ||
45 | } | ||
46 | |||
47 | #endif /* CONFIG_WCN36XX_DEBUGFS */ | ||
48 | |||
49 | #endif /* _WCN36XX_DEBUG_H_ */ | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c new file mode 100644 index 000000000000..ee25786b4447 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c | |||
@@ -0,0 +1,805 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | /* DXE - DMA transfer engine | ||
18 | * we have 2 channels(High prio and Low prio) for TX and 2 channels for RX. | ||
19 | * through low channels data packets are transfered | ||
20 | * through high channels managment packets are transfered | ||
21 | */ | ||
22 | |||
23 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
24 | |||
25 | #include <linux/interrupt.h> | ||
26 | #include "wcn36xx.h" | ||
27 | #include "txrx.h" | ||
28 | |||
29 | void *wcn36xx_dxe_get_next_bd(struct wcn36xx *wcn, bool is_low) | ||
30 | { | ||
31 | struct wcn36xx_dxe_ch *ch = is_low ? | ||
32 | &wcn->dxe_tx_l_ch : | ||
33 | &wcn->dxe_tx_h_ch; | ||
34 | |||
35 | return ch->head_blk_ctl->bd_cpu_addr; | ||
36 | } | ||
37 | |||
38 | static void wcn36xx_dxe_write_register(struct wcn36xx *wcn, int addr, int data) | ||
39 | { | ||
40 | wcn36xx_dbg(WCN36XX_DBG_DXE, | ||
41 | "wcn36xx_dxe_write_register: addr=%x, data=%x\n", | ||
42 | addr, data); | ||
43 | |||
44 | writel(data, wcn->mmio + addr); | ||
45 | } | ||
46 | |||
47 | static void wcn36xx_dxe_read_register(struct wcn36xx *wcn, int addr, int *data) | ||
48 | { | ||
49 | *data = readl(wcn->mmio + addr); | ||
50 | |||
51 | wcn36xx_dbg(WCN36XX_DBG_DXE, | ||
52 | "wcn36xx_dxe_read_register: addr=%x, data=%x\n", | ||
53 | addr, *data); | ||
54 | } | ||
55 | |||
56 | static void wcn36xx_dxe_free_ctl_block(struct wcn36xx_dxe_ch *ch) | ||
57 | { | ||
58 | struct wcn36xx_dxe_ctl *ctl = ch->head_blk_ctl, *next; | ||
59 | int i; | ||
60 | |||
61 | for (i = 0; i < ch->desc_num && ctl; i++) { | ||
62 | next = ctl->next; | ||
63 | kfree(ctl); | ||
64 | ctl = next; | ||
65 | } | ||
66 | } | ||
67 | |||
68 | static int wcn36xx_dxe_allocate_ctl_block(struct wcn36xx_dxe_ch *ch) | ||
69 | { | ||
70 | struct wcn36xx_dxe_ctl *prev_ctl = NULL; | ||
71 | struct wcn36xx_dxe_ctl *cur_ctl = NULL; | ||
72 | int i; | ||
73 | |||
74 | for (i = 0; i < ch->desc_num; i++) { | ||
75 | cur_ctl = kzalloc(sizeof(*cur_ctl), GFP_KERNEL); | ||
76 | if (!cur_ctl) | ||
77 | goto out_fail; | ||
78 | |||
79 | cur_ctl->ctl_blk_order = i; | ||
80 | if (i == 0) { | ||
81 | ch->head_blk_ctl = cur_ctl; | ||
82 | ch->tail_blk_ctl = cur_ctl; | ||
83 | } else if (ch->desc_num - 1 == i) { | ||
84 | prev_ctl->next = cur_ctl; | ||
85 | cur_ctl->next = ch->head_blk_ctl; | ||
86 | } else { | ||
87 | prev_ctl->next = cur_ctl; | ||
88 | } | ||
89 | prev_ctl = cur_ctl; | ||
90 | } | ||
91 | |||
92 | return 0; | ||
93 | |||
94 | out_fail: | ||
95 | wcn36xx_dxe_free_ctl_block(ch); | ||
96 | return -ENOMEM; | ||
97 | } | ||
98 | |||
99 | int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn) | ||
100 | { | ||
101 | int ret; | ||
102 | |||
103 | wcn->dxe_tx_l_ch.ch_type = WCN36XX_DXE_CH_TX_L; | ||
104 | wcn->dxe_tx_h_ch.ch_type = WCN36XX_DXE_CH_TX_H; | ||
105 | wcn->dxe_rx_l_ch.ch_type = WCN36XX_DXE_CH_RX_L; | ||
106 | wcn->dxe_rx_h_ch.ch_type = WCN36XX_DXE_CH_RX_H; | ||
107 | |||
108 | wcn->dxe_tx_l_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_TX_L; | ||
109 | wcn->dxe_tx_h_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_TX_H; | ||
110 | wcn->dxe_rx_l_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_RX_L; | ||
111 | wcn->dxe_rx_h_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_RX_H; | ||
112 | |||
113 | wcn->dxe_tx_l_ch.dxe_wq = WCN36XX_DXE_WQ_TX_L; | ||
114 | wcn->dxe_tx_h_ch.dxe_wq = WCN36XX_DXE_WQ_TX_H; | ||
115 | |||
116 | wcn->dxe_tx_l_ch.ctrl_bd = WCN36XX_DXE_CTRL_TX_L_BD; | ||
117 | wcn->dxe_tx_h_ch.ctrl_bd = WCN36XX_DXE_CTRL_TX_H_BD; | ||
118 | |||
119 | wcn->dxe_tx_l_ch.ctrl_skb = WCN36XX_DXE_CTRL_TX_L_SKB; | ||
120 | wcn->dxe_tx_h_ch.ctrl_skb = WCN36XX_DXE_CTRL_TX_H_SKB; | ||
121 | |||
122 | wcn->dxe_tx_l_ch.reg_ctrl = WCN36XX_DXE_REG_CTL_TX_L; | ||
123 | wcn->dxe_tx_h_ch.reg_ctrl = WCN36XX_DXE_REG_CTL_TX_H; | ||
124 | |||
125 | wcn->dxe_tx_l_ch.def_ctrl = WCN36XX_DXE_CH_DEFAULT_CTL_TX_L; | ||
126 | wcn->dxe_tx_h_ch.def_ctrl = WCN36XX_DXE_CH_DEFAULT_CTL_TX_H; | ||
127 | |||
128 | /* DXE control block allocation */ | ||
129 | ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_tx_l_ch); | ||
130 | if (ret) | ||
131 | goto out_err; | ||
132 | ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_tx_h_ch); | ||
133 | if (ret) | ||
134 | goto out_err; | ||
135 | ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_rx_l_ch); | ||
136 | if (ret) | ||
137 | goto out_err; | ||
138 | ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_rx_h_ch); | ||
139 | if (ret) | ||
140 | goto out_err; | ||
141 | |||
142 | /* Initialize SMSM state Clear TX Enable RING EMPTY STATE */ | ||
143 | ret = wcn->ctrl_ops->smsm_change_state( | ||
144 | WCN36XX_SMSM_WLAN_TX_ENABLE, | ||
145 | WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY); | ||
146 | |||
147 | return 0; | ||
148 | |||
149 | out_err: | ||
150 | wcn36xx_err("Failed to allocate DXE control blocks\n"); | ||
151 | wcn36xx_dxe_free_ctl_blks(wcn); | ||
152 | return -ENOMEM; | ||
153 | } | ||
154 | |||
155 | void wcn36xx_dxe_free_ctl_blks(struct wcn36xx *wcn) | ||
156 | { | ||
157 | wcn36xx_dxe_free_ctl_block(&wcn->dxe_tx_l_ch); | ||
158 | wcn36xx_dxe_free_ctl_block(&wcn->dxe_tx_h_ch); | ||
159 | wcn36xx_dxe_free_ctl_block(&wcn->dxe_rx_l_ch); | ||
160 | wcn36xx_dxe_free_ctl_block(&wcn->dxe_rx_h_ch); | ||
161 | } | ||
162 | |||
163 | static int wcn36xx_dxe_init_descs(struct wcn36xx_dxe_ch *wcn_ch) | ||
164 | { | ||
165 | struct wcn36xx_dxe_desc *cur_dxe = NULL; | ||
166 | struct wcn36xx_dxe_desc *prev_dxe = NULL; | ||
167 | struct wcn36xx_dxe_ctl *cur_ctl = NULL; | ||
168 | size_t size; | ||
169 | int i; | ||
170 | |||
171 | size = wcn_ch->desc_num * sizeof(struct wcn36xx_dxe_desc); | ||
172 | wcn_ch->cpu_addr = dma_alloc_coherent(NULL, size, &wcn_ch->dma_addr, | ||
173 | GFP_KERNEL); | ||
174 | if (!wcn_ch->cpu_addr) | ||
175 | return -ENOMEM; | ||
176 | |||
177 | memset(wcn_ch->cpu_addr, 0, size); | ||
178 | |||
179 | cur_dxe = (struct wcn36xx_dxe_desc *)wcn_ch->cpu_addr; | ||
180 | cur_ctl = wcn_ch->head_blk_ctl; | ||
181 | |||
182 | for (i = 0; i < wcn_ch->desc_num; i++) { | ||
183 | cur_ctl->desc = cur_dxe; | ||
184 | cur_ctl->desc_phy_addr = wcn_ch->dma_addr + | ||
185 | i * sizeof(struct wcn36xx_dxe_desc); | ||
186 | |||
187 | switch (wcn_ch->ch_type) { | ||
188 | case WCN36XX_DXE_CH_TX_L: | ||
189 | cur_dxe->ctrl = WCN36XX_DXE_CTRL_TX_L; | ||
190 | cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_L; | ||
191 | break; | ||
192 | case WCN36XX_DXE_CH_TX_H: | ||
193 | cur_dxe->ctrl = WCN36XX_DXE_CTRL_TX_H; | ||
194 | cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_H; | ||
195 | break; | ||
196 | case WCN36XX_DXE_CH_RX_L: | ||
197 | cur_dxe->ctrl = WCN36XX_DXE_CTRL_RX_L; | ||
198 | cur_dxe->src_addr_l = WCN36XX_DXE_WQ_RX_L; | ||
199 | break; | ||
200 | case WCN36XX_DXE_CH_RX_H: | ||
201 | cur_dxe->ctrl = WCN36XX_DXE_CTRL_RX_H; | ||
202 | cur_dxe->src_addr_l = WCN36XX_DXE_WQ_RX_H; | ||
203 | break; | ||
204 | } | ||
205 | if (0 == i) { | ||
206 | cur_dxe->phy_next_l = 0; | ||
207 | } else if ((0 < i) && (i < wcn_ch->desc_num - 1)) { | ||
208 | prev_dxe->phy_next_l = | ||
209 | cur_ctl->desc_phy_addr; | ||
210 | } else if (i == (wcn_ch->desc_num - 1)) { | ||
211 | prev_dxe->phy_next_l = | ||
212 | cur_ctl->desc_phy_addr; | ||
213 | cur_dxe->phy_next_l = | ||
214 | wcn_ch->head_blk_ctl->desc_phy_addr; | ||
215 | } | ||
216 | cur_ctl = cur_ctl->next; | ||
217 | prev_dxe = cur_dxe; | ||
218 | cur_dxe++; | ||
219 | } | ||
220 | |||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | static void wcn36xx_dxe_init_tx_bd(struct wcn36xx_dxe_ch *ch, | ||
225 | struct wcn36xx_dxe_mem_pool *pool) | ||
226 | { | ||
227 | int i, chunk_size = pool->chunk_size; | ||
228 | dma_addr_t bd_phy_addr = pool->phy_addr; | ||
229 | void *bd_cpu_addr = pool->virt_addr; | ||
230 | struct wcn36xx_dxe_ctl *cur = ch->head_blk_ctl; | ||
231 | |||
232 | for (i = 0; i < ch->desc_num; i++) { | ||
233 | /* Only every second dxe needs a bd pointer, | ||
234 | the other will point to the skb data */ | ||
235 | if (!(i & 1)) { | ||
236 | cur->bd_phy_addr = bd_phy_addr; | ||
237 | cur->bd_cpu_addr = bd_cpu_addr; | ||
238 | bd_phy_addr += chunk_size; | ||
239 | bd_cpu_addr += chunk_size; | ||
240 | } else { | ||
241 | cur->bd_phy_addr = 0; | ||
242 | cur->bd_cpu_addr = NULL; | ||
243 | } | ||
244 | cur = cur->next; | ||
245 | } | ||
246 | } | ||
247 | |||
248 | static int wcn36xx_dxe_enable_ch_int(struct wcn36xx *wcn, u16 wcn_ch) | ||
249 | { | ||
250 | int reg_data = 0; | ||
251 | |||
252 | wcn36xx_dxe_read_register(wcn, | ||
253 | WCN36XX_DXE_INT_MASK_REG, | ||
254 | ®_data); | ||
255 | |||
256 | reg_data |= wcn_ch; | ||
257 | |||
258 | wcn36xx_dxe_write_register(wcn, | ||
259 | WCN36XX_DXE_INT_MASK_REG, | ||
260 | (int)reg_data); | ||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | static int wcn36xx_dxe_fill_skb(struct wcn36xx_dxe_ctl *ctl) | ||
265 | { | ||
266 | struct wcn36xx_dxe_desc *dxe = ctl->desc; | ||
267 | struct sk_buff *skb; | ||
268 | |||
269 | skb = alloc_skb(WCN36XX_PKT_SIZE, GFP_ATOMIC); | ||
270 | if (skb == NULL) | ||
271 | return -ENOMEM; | ||
272 | |||
273 | dxe->dst_addr_l = dma_map_single(NULL, | ||
274 | skb_tail_pointer(skb), | ||
275 | WCN36XX_PKT_SIZE, | ||
276 | DMA_FROM_DEVICE); | ||
277 | ctl->skb = skb; | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | static int wcn36xx_dxe_ch_alloc_skb(struct wcn36xx *wcn, | ||
283 | struct wcn36xx_dxe_ch *wcn_ch) | ||
284 | { | ||
285 | int i; | ||
286 | struct wcn36xx_dxe_ctl *cur_ctl = NULL; | ||
287 | |||
288 | cur_ctl = wcn_ch->head_blk_ctl; | ||
289 | |||
290 | for (i = 0; i < wcn_ch->desc_num; i++) { | ||
291 | wcn36xx_dxe_fill_skb(cur_ctl); | ||
292 | cur_ctl = cur_ctl->next; | ||
293 | } | ||
294 | |||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | static void wcn36xx_dxe_ch_free_skbs(struct wcn36xx *wcn, | ||
299 | struct wcn36xx_dxe_ch *wcn_ch) | ||
300 | { | ||
301 | struct wcn36xx_dxe_ctl *cur = wcn_ch->head_blk_ctl; | ||
302 | int i; | ||
303 | |||
304 | for (i = 0; i < wcn_ch->desc_num; i++) { | ||
305 | kfree_skb(cur->skb); | ||
306 | cur = cur->next; | ||
307 | } | ||
308 | } | ||
309 | |||
310 | void wcn36xx_dxe_tx_ack_ind(struct wcn36xx *wcn, u32 status) | ||
311 | { | ||
312 | struct ieee80211_tx_info *info; | ||
313 | struct sk_buff *skb; | ||
314 | unsigned long flags; | ||
315 | |||
316 | spin_lock_irqsave(&wcn->dxe_lock, flags); | ||
317 | skb = wcn->tx_ack_skb; | ||
318 | wcn->tx_ack_skb = NULL; | ||
319 | spin_unlock_irqrestore(&wcn->dxe_lock, flags); | ||
320 | |||
321 | if (!skb) { | ||
322 | wcn36xx_warn("Spurious TX complete indication\n"); | ||
323 | return; | ||
324 | } | ||
325 | |||
326 | info = IEEE80211_SKB_CB(skb); | ||
327 | |||
328 | if (status == 1) | ||
329 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
330 | |||
331 | wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ack status: %d\n", status); | ||
332 | |||
333 | ieee80211_tx_status_irqsafe(wcn->hw, skb); | ||
334 | ieee80211_wake_queues(wcn->hw); | ||
335 | } | ||
336 | |||
337 | static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) | ||
338 | { | ||
339 | struct wcn36xx_dxe_ctl *ctl = ch->tail_blk_ctl; | ||
340 | struct ieee80211_tx_info *info; | ||
341 | unsigned long flags; | ||
342 | |||
343 | /* | ||
344 | * Make at least one loop of do-while because in case ring is | ||
345 | * completely full head and tail are pointing to the same element | ||
346 | * and while-do will not make any cycles. | ||
347 | */ | ||
348 | do { | ||
349 | if (ctl->skb) { | ||
350 | dma_unmap_single(NULL, ctl->desc->src_addr_l, | ||
351 | ctl->skb->len, DMA_TO_DEVICE); | ||
352 | info = IEEE80211_SKB_CB(ctl->skb); | ||
353 | if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) { | ||
354 | /* Keep frame until TX status comes */ | ||
355 | ieee80211_free_txskb(wcn->hw, ctl->skb); | ||
356 | } | ||
357 | spin_lock_irqsave(&ctl->skb_lock, flags); | ||
358 | if (wcn->queues_stopped) { | ||
359 | wcn->queues_stopped = false; | ||
360 | ieee80211_wake_queues(wcn->hw); | ||
361 | } | ||
362 | spin_unlock_irqrestore(&ctl->skb_lock, flags); | ||
363 | |||
364 | ctl->skb = NULL; | ||
365 | } | ||
366 | ctl = ctl->next; | ||
367 | } while (ctl != ch->head_blk_ctl && | ||
368 | !(ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)); | ||
369 | |||
370 | ch->tail_blk_ctl = ctl; | ||
371 | } | ||
372 | |||
373 | static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) | ||
374 | { | ||
375 | struct wcn36xx *wcn = (struct wcn36xx *)dev; | ||
376 | int int_src, int_reason; | ||
377 | |||
378 | wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_INT_SRC_RAW_REG, &int_src); | ||
379 | |||
380 | if (int_src & WCN36XX_INT_MASK_CHAN_TX_H) { | ||
381 | wcn36xx_dxe_read_register(wcn, | ||
382 | WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_H, | ||
383 | &int_reason); | ||
384 | |||
385 | /* TODO: Check int_reason */ | ||
386 | |||
387 | wcn36xx_dxe_write_register(wcn, | ||
388 | WCN36XX_DXE_0_INT_CLR, | ||
389 | WCN36XX_INT_MASK_CHAN_TX_H); | ||
390 | |||
391 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_ED_CLR, | ||
392 | WCN36XX_INT_MASK_CHAN_TX_H); | ||
393 | wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready high\n"); | ||
394 | reap_tx_dxes(wcn, &wcn->dxe_tx_h_ch); | ||
395 | } | ||
396 | |||
397 | if (int_src & WCN36XX_INT_MASK_CHAN_TX_L) { | ||
398 | wcn36xx_dxe_read_register(wcn, | ||
399 | WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_L, | ||
400 | &int_reason); | ||
401 | /* TODO: Check int_reason */ | ||
402 | |||
403 | wcn36xx_dxe_write_register(wcn, | ||
404 | WCN36XX_DXE_0_INT_CLR, | ||
405 | WCN36XX_INT_MASK_CHAN_TX_L); | ||
406 | |||
407 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_ED_CLR, | ||
408 | WCN36XX_INT_MASK_CHAN_TX_L); | ||
409 | wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready low\n"); | ||
410 | reap_tx_dxes(wcn, &wcn->dxe_tx_l_ch); | ||
411 | } | ||
412 | |||
413 | return IRQ_HANDLED; | ||
414 | } | ||
415 | |||
416 | static irqreturn_t wcn36xx_irq_rx_ready(int irq, void *dev) | ||
417 | { | ||
418 | struct wcn36xx *wcn = (struct wcn36xx *)dev; | ||
419 | |||
420 | disable_irq_nosync(wcn->rx_irq); | ||
421 | wcn36xx_dxe_rx_frame(wcn); | ||
422 | enable_irq(wcn->rx_irq); | ||
423 | return IRQ_HANDLED; | ||
424 | } | ||
425 | |||
426 | static int wcn36xx_dxe_request_irqs(struct wcn36xx *wcn) | ||
427 | { | ||
428 | int ret; | ||
429 | |||
430 | ret = request_irq(wcn->tx_irq, wcn36xx_irq_tx_complete, | ||
431 | IRQF_TRIGGER_HIGH, "wcn36xx_tx", wcn); | ||
432 | if (ret) { | ||
433 | wcn36xx_err("failed to alloc tx irq\n"); | ||
434 | goto out_err; | ||
435 | } | ||
436 | |||
437 | ret = request_irq(wcn->rx_irq, wcn36xx_irq_rx_ready, IRQF_TRIGGER_HIGH, | ||
438 | "wcn36xx_rx", wcn); | ||
439 | if (ret) { | ||
440 | wcn36xx_err("failed to alloc rx irq\n"); | ||
441 | goto out_txirq; | ||
442 | } | ||
443 | |||
444 | enable_irq_wake(wcn->rx_irq); | ||
445 | |||
446 | return 0; | ||
447 | |||
448 | out_txirq: | ||
449 | free_irq(wcn->tx_irq, wcn); | ||
450 | out_err: | ||
451 | return ret; | ||
452 | |||
453 | } | ||
454 | |||
455 | static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn, | ||
456 | struct wcn36xx_dxe_ch *ch) | ||
457 | { | ||
458 | struct wcn36xx_dxe_ctl *ctl = ch->head_blk_ctl; | ||
459 | struct wcn36xx_dxe_desc *dxe = ctl->desc; | ||
460 | dma_addr_t dma_addr; | ||
461 | struct sk_buff *skb; | ||
462 | |||
463 | while (!(dxe->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)) { | ||
464 | skb = ctl->skb; | ||
465 | dma_addr = dxe->dst_addr_l; | ||
466 | wcn36xx_dxe_fill_skb(ctl); | ||
467 | |||
468 | switch (ch->ch_type) { | ||
469 | case WCN36XX_DXE_CH_RX_L: | ||
470 | dxe->ctrl = WCN36XX_DXE_CTRL_RX_L; | ||
471 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_ENCH_ADDR, | ||
472 | WCN36XX_DXE_INT_CH1_MASK); | ||
473 | break; | ||
474 | case WCN36XX_DXE_CH_RX_H: | ||
475 | dxe->ctrl = WCN36XX_DXE_CTRL_RX_H; | ||
476 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_ENCH_ADDR, | ||
477 | WCN36XX_DXE_INT_CH3_MASK); | ||
478 | break; | ||
479 | default: | ||
480 | wcn36xx_warn("Unknown channel\n"); | ||
481 | } | ||
482 | |||
483 | dma_unmap_single(NULL, dma_addr, WCN36XX_PKT_SIZE, | ||
484 | DMA_FROM_DEVICE); | ||
485 | wcn36xx_rx_skb(wcn, skb); | ||
486 | ctl = ctl->next; | ||
487 | dxe = ctl->desc; | ||
488 | } | ||
489 | |||
490 | ch->head_blk_ctl = ctl; | ||
491 | |||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | void wcn36xx_dxe_rx_frame(struct wcn36xx *wcn) | ||
496 | { | ||
497 | int int_src; | ||
498 | |||
499 | wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_INT_SRC_RAW_REG, &int_src); | ||
500 | |||
501 | /* RX_LOW_PRI */ | ||
502 | if (int_src & WCN36XX_DXE_INT_CH1_MASK) { | ||
503 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_CLR, | ||
504 | WCN36XX_DXE_INT_CH1_MASK); | ||
505 | wcn36xx_rx_handle_packets(wcn, &(wcn->dxe_rx_l_ch)); | ||
506 | } | ||
507 | |||
508 | /* RX_HIGH_PRI */ | ||
509 | if (int_src & WCN36XX_DXE_INT_CH3_MASK) { | ||
510 | /* Clean up all the INT within this channel */ | ||
511 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_CLR, | ||
512 | WCN36XX_DXE_INT_CH3_MASK); | ||
513 | wcn36xx_rx_handle_packets(wcn, &(wcn->dxe_rx_h_ch)); | ||
514 | } | ||
515 | |||
516 | if (!int_src) | ||
517 | wcn36xx_warn("No DXE interrupt pending\n"); | ||
518 | } | ||
519 | |||
520 | int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn) | ||
521 | { | ||
522 | size_t s; | ||
523 | void *cpu_addr; | ||
524 | |||
525 | /* Allocate BD headers for MGMT frames */ | ||
526 | |||
527 | /* Where this come from ask QC */ | ||
528 | wcn->mgmt_mem_pool.chunk_size = WCN36XX_BD_CHUNK_SIZE + | ||
529 | 16 - (WCN36XX_BD_CHUNK_SIZE % 8); | ||
530 | |||
531 | s = wcn->mgmt_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_H; | ||
532 | cpu_addr = dma_alloc_coherent(NULL, s, &wcn->mgmt_mem_pool.phy_addr, | ||
533 | GFP_KERNEL); | ||
534 | if (!cpu_addr) | ||
535 | goto out_err; | ||
536 | |||
537 | wcn->mgmt_mem_pool.virt_addr = cpu_addr; | ||
538 | memset(cpu_addr, 0, s); | ||
539 | |||
540 | /* Allocate BD headers for DATA frames */ | ||
541 | |||
542 | /* Where this come from ask QC */ | ||
543 | wcn->data_mem_pool.chunk_size = WCN36XX_BD_CHUNK_SIZE + | ||
544 | 16 - (WCN36XX_BD_CHUNK_SIZE % 8); | ||
545 | |||
546 | s = wcn->data_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_L; | ||
547 | cpu_addr = dma_alloc_coherent(NULL, s, &wcn->data_mem_pool.phy_addr, | ||
548 | GFP_KERNEL); | ||
549 | if (!cpu_addr) | ||
550 | goto out_err; | ||
551 | |||
552 | wcn->data_mem_pool.virt_addr = cpu_addr; | ||
553 | memset(cpu_addr, 0, s); | ||
554 | |||
555 | return 0; | ||
556 | |||
557 | out_err: | ||
558 | wcn36xx_dxe_free_mem_pools(wcn); | ||
559 | wcn36xx_err("Failed to allocate BD mempool\n"); | ||
560 | return -ENOMEM; | ||
561 | } | ||
562 | |||
563 | void wcn36xx_dxe_free_mem_pools(struct wcn36xx *wcn) | ||
564 | { | ||
565 | if (wcn->mgmt_mem_pool.virt_addr) | ||
566 | dma_free_coherent(NULL, wcn->mgmt_mem_pool.chunk_size * | ||
567 | WCN36XX_DXE_CH_DESC_NUMB_TX_H, | ||
568 | wcn->mgmt_mem_pool.virt_addr, | ||
569 | wcn->mgmt_mem_pool.phy_addr); | ||
570 | |||
571 | if (wcn->data_mem_pool.virt_addr) { | ||
572 | dma_free_coherent(NULL, wcn->data_mem_pool.chunk_size * | ||
573 | WCN36XX_DXE_CH_DESC_NUMB_TX_L, | ||
574 | wcn->data_mem_pool.virt_addr, | ||
575 | wcn->data_mem_pool.phy_addr); | ||
576 | } | ||
577 | } | ||
578 | |||
579 | int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, | ||
580 | struct wcn36xx_vif *vif_priv, | ||
581 | struct sk_buff *skb, | ||
582 | bool is_low) | ||
583 | { | ||
584 | struct wcn36xx_dxe_ctl *ctl = NULL; | ||
585 | struct wcn36xx_dxe_desc *desc = NULL; | ||
586 | struct wcn36xx_dxe_ch *ch = NULL; | ||
587 | unsigned long flags; | ||
588 | |||
589 | ch = is_low ? &wcn->dxe_tx_l_ch : &wcn->dxe_tx_h_ch; | ||
590 | |||
591 | ctl = ch->head_blk_ctl; | ||
592 | |||
593 | spin_lock_irqsave(&ctl->next->skb_lock, flags); | ||
594 | |||
595 | /* | ||
596 | * If skb is not null that means that we reached the tail of the ring | ||
597 | * hence ring is full. Stop queues to let mac80211 back off until ring | ||
598 | * has an empty slot again. | ||
599 | */ | ||
600 | if (NULL != ctl->next->skb) { | ||
601 | ieee80211_stop_queues(wcn->hw); | ||
602 | wcn->queues_stopped = true; | ||
603 | spin_unlock_irqrestore(&ctl->next->skb_lock, flags); | ||
604 | return -EBUSY; | ||
605 | } | ||
606 | spin_unlock_irqrestore(&ctl->next->skb_lock, flags); | ||
607 | |||
608 | ctl->skb = NULL; | ||
609 | desc = ctl->desc; | ||
610 | |||
611 | /* Set source address of the BD we send */ | ||
612 | desc->src_addr_l = ctl->bd_phy_addr; | ||
613 | |||
614 | desc->dst_addr_l = ch->dxe_wq; | ||
615 | desc->fr_len = sizeof(struct wcn36xx_tx_bd); | ||
616 | desc->ctrl = ch->ctrl_bd; | ||
617 | |||
618 | wcn36xx_dbg(WCN36XX_DBG_DXE, "DXE TX\n"); | ||
619 | |||
620 | wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "DESC1 >>> ", | ||
621 | (char *)desc, sizeof(*desc)); | ||
622 | wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, | ||
623 | "BD >>> ", (char *)ctl->bd_cpu_addr, | ||
624 | sizeof(struct wcn36xx_tx_bd)); | ||
625 | |||
626 | /* Set source address of the SKB we send */ | ||
627 | ctl = ctl->next; | ||
628 | ctl->skb = skb; | ||
629 | desc = ctl->desc; | ||
630 | if (ctl->bd_cpu_addr) { | ||
631 | wcn36xx_err("bd_cpu_addr cannot be NULL for skb DXE\n"); | ||
632 | return -EINVAL; | ||
633 | } | ||
634 | |||
635 | desc->src_addr_l = dma_map_single(NULL, | ||
636 | ctl->skb->data, | ||
637 | ctl->skb->len, | ||
638 | DMA_TO_DEVICE); | ||
639 | |||
640 | desc->dst_addr_l = ch->dxe_wq; | ||
641 | desc->fr_len = ctl->skb->len; | ||
642 | |||
643 | /* set dxe descriptor to VALID */ | ||
644 | desc->ctrl = ch->ctrl_skb; | ||
645 | |||
646 | wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "DESC2 >>> ", | ||
647 | (char *)desc, sizeof(*desc)); | ||
648 | wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "SKB >>> ", | ||
649 | (char *)ctl->skb->data, ctl->skb->len); | ||
650 | |||
651 | /* Move the head of the ring to the next empty descriptor */ | ||
652 | ch->head_blk_ctl = ctl->next; | ||
653 | |||
654 | /* | ||
655 | * When connected and trying to send data frame chip can be in sleep | ||
656 | * mode and writing to the register will not wake up the chip. Instead | ||
657 | * notify chip about new frame through SMSM bus. | ||
658 | */ | ||
659 | if (is_low && vif_priv->pw_state == WCN36XX_BMPS) { | ||
660 | wcn->ctrl_ops->smsm_change_state( | ||
661 | 0, | ||
662 | WCN36XX_SMSM_WLAN_TX_ENABLE); | ||
663 | } else { | ||
664 | /* indicate End Of Packet and generate interrupt on descriptor | ||
665 | * done. | ||
666 | */ | ||
667 | wcn36xx_dxe_write_register(wcn, | ||
668 | ch->reg_ctrl, ch->def_ctrl); | ||
669 | } | ||
670 | |||
671 | return 0; | ||
672 | } | ||
673 | |||
674 | int wcn36xx_dxe_init(struct wcn36xx *wcn) | ||
675 | { | ||
676 | int reg_data = 0, ret; | ||
677 | |||
678 | reg_data = WCN36XX_DXE_REG_RESET; | ||
679 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CSR_RESET, reg_data); | ||
680 | |||
681 | /* Setting interrupt path */ | ||
682 | reg_data = WCN36XX_DXE_CCU_INT; | ||
683 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CCU_INT, reg_data); | ||
684 | |||
685 | /***************************************/ | ||
686 | /* Init descriptors for TX LOW channel */ | ||
687 | /***************************************/ | ||
688 | wcn36xx_dxe_init_descs(&wcn->dxe_tx_l_ch); | ||
689 | wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_l_ch, &wcn->data_mem_pool); | ||
690 | |||
691 | /* Write channel head to a NEXT register */ | ||
692 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_L, | ||
693 | wcn->dxe_tx_l_ch.head_blk_ctl->desc_phy_addr); | ||
694 | |||
695 | /* Program DMA destination addr for TX LOW */ | ||
696 | wcn36xx_dxe_write_register(wcn, | ||
697 | WCN36XX_DXE_CH_DEST_ADDR_TX_L, | ||
698 | WCN36XX_DXE_WQ_TX_L); | ||
699 | |||
700 | wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, ®_data); | ||
701 | wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_L); | ||
702 | |||
703 | /***************************************/ | ||
704 | /* Init descriptors for TX HIGH channel */ | ||
705 | /***************************************/ | ||
706 | wcn36xx_dxe_init_descs(&wcn->dxe_tx_h_ch); | ||
707 | wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_h_ch, &wcn->mgmt_mem_pool); | ||
708 | |||
709 | /* Write channel head to a NEXT register */ | ||
710 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_H, | ||
711 | wcn->dxe_tx_h_ch.head_blk_ctl->desc_phy_addr); | ||
712 | |||
713 | /* Program DMA destination addr for TX HIGH */ | ||
714 | wcn36xx_dxe_write_register(wcn, | ||
715 | WCN36XX_DXE_CH_DEST_ADDR_TX_H, | ||
716 | WCN36XX_DXE_WQ_TX_H); | ||
717 | |||
718 | wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, ®_data); | ||
719 | |||
720 | /* Enable channel interrupts */ | ||
721 | wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_H); | ||
722 | |||
723 | /***************************************/ | ||
724 | /* Init descriptors for RX LOW channel */ | ||
725 | /***************************************/ | ||
726 | wcn36xx_dxe_init_descs(&wcn->dxe_rx_l_ch); | ||
727 | |||
728 | /* For RX we need to preallocated buffers */ | ||
729 | wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch); | ||
730 | |||
731 | /* Write channel head to a NEXT register */ | ||
732 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_L, | ||
733 | wcn->dxe_rx_l_ch.head_blk_ctl->desc_phy_addr); | ||
734 | |||
735 | /* Write DMA source address */ | ||
736 | wcn36xx_dxe_write_register(wcn, | ||
737 | WCN36XX_DXE_CH_SRC_ADDR_RX_L, | ||
738 | WCN36XX_DXE_WQ_RX_L); | ||
739 | |||
740 | /* Program preallocated destination address */ | ||
741 | wcn36xx_dxe_write_register(wcn, | ||
742 | WCN36XX_DXE_CH_DEST_ADDR_RX_L, | ||
743 | wcn->dxe_rx_l_ch.head_blk_ctl->desc->phy_next_l); | ||
744 | |||
745 | /* Enable default control registers */ | ||
746 | wcn36xx_dxe_write_register(wcn, | ||
747 | WCN36XX_DXE_REG_CTL_RX_L, | ||
748 | WCN36XX_DXE_CH_DEFAULT_CTL_RX_L); | ||
749 | |||
750 | /* Enable channel interrupts */ | ||
751 | wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_L); | ||
752 | |||
753 | /***************************************/ | ||
754 | /* Init descriptors for RX HIGH channel */ | ||
755 | /***************************************/ | ||
756 | wcn36xx_dxe_init_descs(&wcn->dxe_rx_h_ch); | ||
757 | |||
758 | /* For RX we need to prealocat buffers */ | ||
759 | wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_h_ch); | ||
760 | |||
761 | /* Write chanel head to a NEXT register */ | ||
762 | wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_H, | ||
763 | wcn->dxe_rx_h_ch.head_blk_ctl->desc_phy_addr); | ||
764 | |||
765 | /* Write DMA source address */ | ||
766 | wcn36xx_dxe_write_register(wcn, | ||
767 | WCN36XX_DXE_CH_SRC_ADDR_RX_H, | ||
768 | WCN36XX_DXE_WQ_RX_H); | ||
769 | |||
770 | /* Program preallocated destination address */ | ||
771 | wcn36xx_dxe_write_register(wcn, | ||
772 | WCN36XX_DXE_CH_DEST_ADDR_RX_H, | ||
773 | wcn->dxe_rx_h_ch.head_blk_ctl->desc->phy_next_l); | ||
774 | |||
775 | /* Enable default control registers */ | ||
776 | wcn36xx_dxe_write_register(wcn, | ||
777 | WCN36XX_DXE_REG_CTL_RX_H, | ||
778 | WCN36XX_DXE_CH_DEFAULT_CTL_RX_H); | ||
779 | |||
780 | /* Enable channel interrupts */ | ||
781 | wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_H); | ||
782 | |||
783 | ret = wcn36xx_dxe_request_irqs(wcn); | ||
784 | if (ret < 0) | ||
785 | goto out_err; | ||
786 | |||
787 | return 0; | ||
788 | |||
789 | out_err: | ||
790 | return ret; | ||
791 | } | ||
792 | |||
793 | void wcn36xx_dxe_deinit(struct wcn36xx *wcn) | ||
794 | { | ||
795 | free_irq(wcn->tx_irq, wcn); | ||
796 | free_irq(wcn->rx_irq, wcn); | ||
797 | |||
798 | if (wcn->tx_ack_skb) { | ||
799 | ieee80211_tx_status_irqsafe(wcn->hw, wcn->tx_ack_skb); | ||
800 | wcn->tx_ack_skb = NULL; | ||
801 | } | ||
802 | |||
803 | wcn36xx_dxe_ch_free_skbs(wcn, &wcn->dxe_rx_l_ch); | ||
804 | wcn36xx_dxe_ch_free_skbs(wcn, &wcn->dxe_rx_h_ch); | ||
805 | } | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.h b/drivers/net/wireless/ath/wcn36xx/dxe.h new file mode 100644 index 000000000000..c88562f85de1 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/dxe.h | |||
@@ -0,0 +1,284 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef _DXE_H_ | ||
18 | #define _DXE_H_ | ||
19 | |||
20 | #include "wcn36xx.h" | ||
21 | |||
22 | /* | ||
23 | TX_LOW = DMA0 | ||
24 | TX_HIGH = DMA4 | ||
25 | RX_LOW = DMA1 | ||
26 | RX_HIGH = DMA3 | ||
27 | H2H_TEST_RX_TX = DMA2 | ||
28 | */ | ||
29 | |||
30 | /* DXE registers */ | ||
31 | #define WCN36XX_DXE_MEM_BASE 0x03000000 | ||
32 | #define WCN36XX_DXE_MEM_REG 0x202000 | ||
33 | |||
34 | #define WCN36XX_DXE_CCU_INT 0xA0011 | ||
35 | #define WCN36XX_DXE_REG_CCU_INT 0x200b10 | ||
36 | |||
37 | /* TODO This must calculated properly but not hardcoded */ | ||
38 | #define WCN36XX_DXE_CTRL_TX_L 0x328a44 | ||
39 | #define WCN36XX_DXE_CTRL_TX_H 0x32ce44 | ||
40 | #define WCN36XX_DXE_CTRL_RX_L 0x12ad2f | ||
41 | #define WCN36XX_DXE_CTRL_RX_H 0x12d12f | ||
42 | #define WCN36XX_DXE_CTRL_TX_H_BD 0x30ce45 | ||
43 | #define WCN36XX_DXE_CTRL_TX_H_SKB 0x32ce4d | ||
44 | #define WCN36XX_DXE_CTRL_TX_L_BD 0x308a45 | ||
45 | #define WCN36XX_DXE_CTRL_TX_L_SKB 0x328a4d | ||
46 | |||
47 | /* TODO This must calculated properly but not hardcoded */ | ||
48 | #define WCN36XX_DXE_WQ_TX_L 0x17 | ||
49 | #define WCN36XX_DXE_WQ_TX_H 0x17 | ||
50 | #define WCN36XX_DXE_WQ_RX_L 0xB | ||
51 | #define WCN36XX_DXE_WQ_RX_H 0x4 | ||
52 | |||
53 | /* DXE descriptor control filed */ | ||
54 | #define WCN36XX_DXE_CTRL_VALID_MASK (0x00000001) | ||
55 | |||
56 | /* TODO This must calculated properly but not hardcoded */ | ||
57 | /* DXE default control register values */ | ||
58 | #define WCN36XX_DXE_CH_DEFAULT_CTL_RX_L 0x847EAD2F | ||
59 | #define WCN36XX_DXE_CH_DEFAULT_CTL_RX_H 0x84FED12F | ||
60 | #define WCN36XX_DXE_CH_DEFAULT_CTL_TX_H 0x853ECF4D | ||
61 | #define WCN36XX_DXE_CH_DEFAULT_CTL_TX_L 0x843e8b4d | ||
62 | |||
63 | /* Common DXE registers */ | ||
64 | #define WCN36XX_DXE_MEM_CSR (WCN36XX_DXE_MEM_REG + 0x00) | ||
65 | #define WCN36XX_DXE_REG_CSR_RESET (WCN36XX_DXE_MEM_REG + 0x00) | ||
66 | #define WCN36XX_DXE_ENCH_ADDR (WCN36XX_DXE_MEM_REG + 0x04) | ||
67 | #define WCN36XX_DXE_REG_CH_EN (WCN36XX_DXE_MEM_REG + 0x08) | ||
68 | #define WCN36XX_DXE_REG_CH_DONE (WCN36XX_DXE_MEM_REG + 0x0C) | ||
69 | #define WCN36XX_DXE_REG_CH_ERR (WCN36XX_DXE_MEM_REG + 0x10) | ||
70 | #define WCN36XX_DXE_INT_MASK_REG (WCN36XX_DXE_MEM_REG + 0x18) | ||
71 | #define WCN36XX_DXE_INT_SRC_RAW_REG (WCN36XX_DXE_MEM_REG + 0x20) | ||
72 | /* #define WCN36XX_DXE_INT_CH6_MASK 0x00000040 */ | ||
73 | /* #define WCN36XX_DXE_INT_CH5_MASK 0x00000020 */ | ||
74 | #define WCN36XX_DXE_INT_CH4_MASK 0x00000010 | ||
75 | #define WCN36XX_DXE_INT_CH3_MASK 0x00000008 | ||
76 | /* #define WCN36XX_DXE_INT_CH2_MASK 0x00000004 */ | ||
77 | #define WCN36XX_DXE_INT_CH1_MASK 0x00000002 | ||
78 | #define WCN36XX_DXE_INT_CH0_MASK 0x00000001 | ||
79 | #define WCN36XX_DXE_0_INT_CLR (WCN36XX_DXE_MEM_REG + 0x30) | ||
80 | #define WCN36XX_DXE_0_INT_ED_CLR (WCN36XX_DXE_MEM_REG + 0x34) | ||
81 | #define WCN36XX_DXE_0_INT_DONE_CLR (WCN36XX_DXE_MEM_REG + 0x38) | ||
82 | #define WCN36XX_DXE_0_INT_ERR_CLR (WCN36XX_DXE_MEM_REG + 0x3C) | ||
83 | |||
84 | #define WCN36XX_DXE_0_CH0_STATUS (WCN36XX_DXE_MEM_REG + 0x404) | ||
85 | #define WCN36XX_DXE_0_CH1_STATUS (WCN36XX_DXE_MEM_REG + 0x444) | ||
86 | #define WCN36XX_DXE_0_CH2_STATUS (WCN36XX_DXE_MEM_REG + 0x484) | ||
87 | #define WCN36XX_DXE_0_CH3_STATUS (WCN36XX_DXE_MEM_REG + 0x4C4) | ||
88 | #define WCN36XX_DXE_0_CH4_STATUS (WCN36XX_DXE_MEM_REG + 0x504) | ||
89 | |||
90 | #define WCN36XX_DXE_REG_RESET 0x5c89 | ||
91 | |||
92 | /* Temporary BMU Workqueue 4 */ | ||
93 | #define WCN36XX_DXE_BMU_WQ_RX_LOW 0xB | ||
94 | #define WCN36XX_DXE_BMU_WQ_RX_HIGH 0x4 | ||
95 | /* DMA channel offset */ | ||
96 | #define WCN36XX_DXE_TX_LOW_OFFSET 0x400 | ||
97 | #define WCN36XX_DXE_TX_HIGH_OFFSET 0x500 | ||
98 | #define WCN36XX_DXE_RX_LOW_OFFSET 0x440 | ||
99 | #define WCN36XX_DXE_RX_HIGH_OFFSET 0x4C0 | ||
100 | |||
101 | /* Address of the next DXE descriptor */ | ||
102 | #define WCN36XX_DXE_CH_NEXT_DESC_ADDR 0x001C | ||
103 | #define WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_L (WCN36XX_DXE_MEM_REG + \ | ||
104 | WCN36XX_DXE_TX_LOW_OFFSET + \ | ||
105 | WCN36XX_DXE_CH_NEXT_DESC_ADDR) | ||
106 | #define WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_H (WCN36XX_DXE_MEM_REG + \ | ||
107 | WCN36XX_DXE_TX_HIGH_OFFSET + \ | ||
108 | WCN36XX_DXE_CH_NEXT_DESC_ADDR) | ||
109 | #define WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_L (WCN36XX_DXE_MEM_REG + \ | ||
110 | WCN36XX_DXE_RX_LOW_OFFSET + \ | ||
111 | WCN36XX_DXE_CH_NEXT_DESC_ADDR) | ||
112 | #define WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_H (WCN36XX_DXE_MEM_REG + \ | ||
113 | WCN36XX_DXE_RX_HIGH_OFFSET + \ | ||
114 | WCN36XX_DXE_CH_NEXT_DESC_ADDR) | ||
115 | |||
116 | /* DXE Descriptor source address */ | ||
117 | #define WCN36XX_DXE_CH_SRC_ADDR 0x000C | ||
118 | #define WCN36XX_DXE_CH_SRC_ADDR_RX_L (WCN36XX_DXE_MEM_REG + \ | ||
119 | WCN36XX_DXE_RX_LOW_OFFSET + \ | ||
120 | WCN36XX_DXE_CH_SRC_ADDR) | ||
121 | #define WCN36XX_DXE_CH_SRC_ADDR_RX_H (WCN36XX_DXE_MEM_REG + \ | ||
122 | WCN36XX_DXE_RX_HIGH_OFFSET + \ | ||
123 | WCN36XX_DXE_CH_SRC_ADDR) | ||
124 | |||
125 | /* DXE Descriptor address destination address */ | ||
126 | #define WCN36XX_DXE_CH_DEST_ADDR 0x0014 | ||
127 | #define WCN36XX_DXE_CH_DEST_ADDR_TX_L (WCN36XX_DXE_MEM_REG + \ | ||
128 | WCN36XX_DXE_TX_LOW_OFFSET + \ | ||
129 | WCN36XX_DXE_CH_DEST_ADDR) | ||
130 | #define WCN36XX_DXE_CH_DEST_ADDR_TX_H (WCN36XX_DXE_MEM_REG + \ | ||
131 | WCN36XX_DXE_TX_HIGH_OFFSET + \ | ||
132 | WCN36XX_DXE_CH_DEST_ADDR) | ||
133 | #define WCN36XX_DXE_CH_DEST_ADDR_RX_L (WCN36XX_DXE_MEM_REG + \ | ||
134 | WCN36XX_DXE_RX_LOW_OFFSET + \ | ||
135 | WCN36XX_DXE_CH_DEST_ADDR) | ||
136 | #define WCN36XX_DXE_CH_DEST_ADDR_RX_H (WCN36XX_DXE_MEM_REG + \ | ||
137 | WCN36XX_DXE_RX_HIGH_OFFSET + \ | ||
138 | WCN36XX_DXE_CH_DEST_ADDR) | ||
139 | |||
140 | /* Interrupt status */ | ||
141 | #define WCN36XX_DXE_CH_STATUS_REG_ADDR 0x0004 | ||
142 | #define WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_L (WCN36XX_DXE_MEM_REG + \ | ||
143 | WCN36XX_DXE_TX_LOW_OFFSET + \ | ||
144 | WCN36XX_DXE_CH_STATUS_REG_ADDR) | ||
145 | #define WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_H (WCN36XX_DXE_MEM_REG + \ | ||
146 | WCN36XX_DXE_TX_HIGH_OFFSET + \ | ||
147 | WCN36XX_DXE_CH_STATUS_REG_ADDR) | ||
148 | #define WCN36XX_DXE_CH_STATUS_REG_ADDR_RX_L (WCN36XX_DXE_MEM_REG + \ | ||
149 | WCN36XX_DXE_RX_LOW_OFFSET + \ | ||
150 | WCN36XX_DXE_CH_STATUS_REG_ADDR) | ||
151 | #define WCN36XX_DXE_CH_STATUS_REG_ADDR_RX_H (WCN36XX_DXE_MEM_REG + \ | ||
152 | WCN36XX_DXE_RX_HIGH_OFFSET + \ | ||
153 | WCN36XX_DXE_CH_STATUS_REG_ADDR) | ||
154 | |||
155 | |||
156 | /* DXE default control register */ | ||
157 | #define WCN36XX_DXE_REG_CTL_RX_L (WCN36XX_DXE_MEM_REG + \ | ||
158 | WCN36XX_DXE_RX_LOW_OFFSET) | ||
159 | #define WCN36XX_DXE_REG_CTL_RX_H (WCN36XX_DXE_MEM_REG + \ | ||
160 | WCN36XX_DXE_RX_HIGH_OFFSET) | ||
161 | #define WCN36XX_DXE_REG_CTL_TX_H (WCN36XX_DXE_MEM_REG + \ | ||
162 | WCN36XX_DXE_TX_HIGH_OFFSET) | ||
163 | #define WCN36XX_DXE_REG_CTL_TX_L (WCN36XX_DXE_MEM_REG + \ | ||
164 | WCN36XX_DXE_TX_LOW_OFFSET) | ||
165 | |||
166 | #define WCN36XX_SMSM_WLAN_TX_ENABLE 0x00000400 | ||
167 | #define WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY 0x00000200 | ||
168 | |||
169 | |||
170 | /* Interrupt control channel mask */ | ||
171 | #define WCN36XX_INT_MASK_CHAN_TX_L 0x00000001 | ||
172 | #define WCN36XX_INT_MASK_CHAN_RX_L 0x00000002 | ||
173 | #define WCN36XX_INT_MASK_CHAN_RX_H 0x00000008 | ||
174 | #define WCN36XX_INT_MASK_CHAN_TX_H 0x00000010 | ||
175 | |||
176 | #define WCN36XX_BD_CHUNK_SIZE 128 | ||
177 | |||
178 | #define WCN36XX_PKT_SIZE 0xF20 | ||
179 | enum wcn36xx_dxe_ch_type { | ||
180 | WCN36XX_DXE_CH_TX_L, | ||
181 | WCN36XX_DXE_CH_TX_H, | ||
182 | WCN36XX_DXE_CH_RX_L, | ||
183 | WCN36XX_DXE_CH_RX_H | ||
184 | }; | ||
185 | |||
186 | /* amount of descriptors per channel */ | ||
187 | enum wcn36xx_dxe_ch_desc_num { | ||
188 | WCN36XX_DXE_CH_DESC_NUMB_TX_L = 128, | ||
189 | WCN36XX_DXE_CH_DESC_NUMB_TX_H = 10, | ||
190 | WCN36XX_DXE_CH_DESC_NUMB_RX_L = 512, | ||
191 | WCN36XX_DXE_CH_DESC_NUMB_RX_H = 40 | ||
192 | }; | ||
193 | |||
194 | /** | ||
195 | * struct wcn36xx_dxe_desc - describes descriptor of one DXE buffer | ||
196 | * | ||
197 | * @ctrl: is a union that consists of following bits: | ||
198 | * union { | ||
199 | * u32 valid :1; //0 = DMA stop, 1 = DMA continue with this | ||
200 | * //descriptor | ||
201 | * u32 transfer_type :2; //0 = Host to Host space | ||
202 | * u32 eop :1; //End of Packet | ||
203 | * u32 bd_handling :1; //if transferType = Host to BMU, then 0 | ||
204 | * // means first 128 bytes contain BD, and 1 | ||
205 | * // means create new empty BD | ||
206 | * u32 siq :1; // SIQ | ||
207 | * u32 diq :1; // DIQ | ||
208 | * u32 pdu_rel :1; //0 = don't release BD and PDUs when done, | ||
209 | * // 1 = release them | ||
210 | * u32 bthld_sel :4; //BMU Threshold Select | ||
211 | * u32 prio :3; //Specifies the priority level to use for | ||
212 | * // the transfer | ||
213 | * u32 stop_channel :1; //1 = DMA stops processing further, channel | ||
214 | * //requires re-enabling after this | ||
215 | * u32 intr :1; //Interrupt on Descriptor Done | ||
216 | * u32 rsvd :1; //reserved | ||
217 | * u32 size :14;//14 bits used - ignored for BMU transfers, | ||
218 | * //only used for host to host transfers? | ||
219 | * } ctrl; | ||
220 | */ | ||
221 | struct wcn36xx_dxe_desc { | ||
222 | u32 ctrl; | ||
223 | u32 fr_len; | ||
224 | |||
225 | u32 src_addr_l; | ||
226 | u32 dst_addr_l; | ||
227 | u32 phy_next_l; | ||
228 | u32 src_addr_h; | ||
229 | u32 dst_addr_h; | ||
230 | u32 phy_next_h; | ||
231 | } __packed; | ||
232 | |||
233 | /* DXE Control block */ | ||
234 | struct wcn36xx_dxe_ctl { | ||
235 | struct wcn36xx_dxe_ctl *next; | ||
236 | struct wcn36xx_dxe_desc *desc; | ||
237 | unsigned int desc_phy_addr; | ||
238 | int ctl_blk_order; | ||
239 | struct sk_buff *skb; | ||
240 | spinlock_t skb_lock; | ||
241 | void *bd_cpu_addr; | ||
242 | dma_addr_t bd_phy_addr; | ||
243 | }; | ||
244 | |||
245 | struct wcn36xx_dxe_ch { | ||
246 | enum wcn36xx_dxe_ch_type ch_type; | ||
247 | void *cpu_addr; | ||
248 | dma_addr_t dma_addr; | ||
249 | enum wcn36xx_dxe_ch_desc_num desc_num; | ||
250 | /* DXE control block ring */ | ||
251 | struct wcn36xx_dxe_ctl *head_blk_ctl; | ||
252 | struct wcn36xx_dxe_ctl *tail_blk_ctl; | ||
253 | |||
254 | /* DXE channel specific configs */ | ||
255 | u32 dxe_wq; | ||
256 | u32 ctrl_bd; | ||
257 | u32 ctrl_skb; | ||
258 | u32 reg_ctrl; | ||
259 | u32 def_ctrl; | ||
260 | }; | ||
261 | |||
262 | /* Memory Pool for BD headers */ | ||
263 | struct wcn36xx_dxe_mem_pool { | ||
264 | int chunk_size; | ||
265 | void *virt_addr; | ||
266 | dma_addr_t phy_addr; | ||
267 | }; | ||
268 | |||
269 | struct wcn36xx_vif; | ||
270 | int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn); | ||
271 | void wcn36xx_dxe_free_mem_pools(struct wcn36xx *wcn); | ||
272 | void wcn36xx_dxe_rx_frame(struct wcn36xx *wcn); | ||
273 | int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn); | ||
274 | void wcn36xx_dxe_free_ctl_blks(struct wcn36xx *wcn); | ||
275 | int wcn36xx_dxe_init(struct wcn36xx *wcn); | ||
276 | void wcn36xx_dxe_deinit(struct wcn36xx *wcn); | ||
277 | int wcn36xx_dxe_init_channels(struct wcn36xx *wcn); | ||
278 | int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, | ||
279 | struct wcn36xx_vif *vif_priv, | ||
280 | struct sk_buff *skb, | ||
281 | bool is_low); | ||
282 | void wcn36xx_dxe_tx_ack_ind(struct wcn36xx *wcn, u32 status); | ||
283 | void *wcn36xx_dxe_get_next_bd(struct wcn36xx *wcn, bool is_low); | ||
284 | #endif /* _DXE_H_ */ | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h new file mode 100644 index 000000000000..c02dbc618724 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/hal.h | |||
@@ -0,0 +1,4657 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef _HAL_H_ | ||
18 | #define _HAL_H_ | ||
19 | |||
20 | /*--------------------------------------------------------------------------- | ||
21 | API VERSIONING INFORMATION | ||
22 | |||
23 | The RIVA API is versioned as MAJOR.MINOR.VERSION.REVISION | ||
24 | The MAJOR is incremented for major product/architecture changes | ||
25 | (and then MINOR/VERSION/REVISION are zeroed) | ||
26 | The MINOR is incremented for minor product/architecture changes | ||
27 | (and then VERSION/REVISION are zeroed) | ||
28 | The VERSION is incremented if a significant API change occurs | ||
29 | (and then REVISION is zeroed) | ||
30 | The REVISION is incremented if an insignificant API change occurs | ||
31 | or if a new API is added | ||
32 | All values are in the range 0..255 (ie they are 8-bit values) | ||
33 | ---------------------------------------------------------------------------*/ | ||
34 | #define WCN36XX_HAL_VER_MAJOR 1 | ||
35 | #define WCN36XX_HAL_VER_MINOR 4 | ||
36 | #define WCN36XX_HAL_VER_VERSION 1 | ||
37 | #define WCN36XX_HAL_VER_REVISION 2 | ||
38 | |||
39 | /* This is to force compiler to use the maximum of an int ( 4 bytes ) */ | ||
40 | #define WCN36XX_HAL_MAX_ENUM_SIZE 0x7FFFFFFF | ||
41 | #define WCN36XX_HAL_MSG_TYPE_MAX_ENUM_SIZE 0x7FFF | ||
42 | |||
43 | /* Max no. of transmit categories */ | ||
44 | #define STACFG_MAX_TC 8 | ||
45 | |||
46 | /* The maximum value of access category */ | ||
47 | #define WCN36XX_HAL_MAX_AC 4 | ||
48 | |||
49 | #define WCN36XX_HAL_IPV4_ADDR_LEN 4 | ||
50 | |||
51 | #define WALN_HAL_STA_INVALID_IDX 0xFF | ||
52 | #define WCN36XX_HAL_BSS_INVALID_IDX 0xFF | ||
53 | |||
54 | /* Default Beacon template size */ | ||
55 | #define BEACON_TEMPLATE_SIZE 0x180 | ||
56 | |||
57 | /* Param Change Bitmap sent to HAL */ | ||
58 | #define PARAM_BCN_INTERVAL_CHANGED (1 << 0) | ||
59 | #define PARAM_SHORT_PREAMBLE_CHANGED (1 << 1) | ||
60 | #define PARAM_SHORT_SLOT_TIME_CHANGED (1 << 2) | ||
61 | #define PARAM_llACOEXIST_CHANGED (1 << 3) | ||
62 | #define PARAM_llBCOEXIST_CHANGED (1 << 4) | ||
63 | #define PARAM_llGCOEXIST_CHANGED (1 << 5) | ||
64 | #define PARAM_HT20MHZCOEXIST_CHANGED (1<<6) | ||
65 | #define PARAM_NON_GF_DEVICES_PRESENT_CHANGED (1<<7) | ||
66 | #define PARAM_RIFS_MODE_CHANGED (1<<8) | ||
67 | #define PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED (1<<9) | ||
68 | #define PARAM_OBSS_MODE_CHANGED (1<<10) | ||
69 | #define PARAM_BEACON_UPDATE_MASK \ | ||
70 | (PARAM_BCN_INTERVAL_CHANGED | \ | ||
71 | PARAM_SHORT_PREAMBLE_CHANGED | \ | ||
72 | PARAM_SHORT_SLOT_TIME_CHANGED | \ | ||
73 | PARAM_llACOEXIST_CHANGED | \ | ||
74 | PARAM_llBCOEXIST_CHANGED | \ | ||
75 | PARAM_llGCOEXIST_CHANGED | \ | ||
76 | PARAM_HT20MHZCOEXIST_CHANGED | \ | ||
77 | PARAM_NON_GF_DEVICES_PRESENT_CHANGED | \ | ||
78 | PARAM_RIFS_MODE_CHANGED | \ | ||
79 | PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED | \ | ||
80 | PARAM_OBSS_MODE_CHANGED) | ||
81 | |||
82 | /* dump command response Buffer size */ | ||
83 | #define DUMPCMD_RSP_BUFFER 100 | ||
84 | |||
85 | /* version string max length (including NULL) */ | ||
86 | #define WCN36XX_HAL_VERSION_LENGTH 64 | ||
87 | |||
88 | /* message types for messages exchanged between WDI and HAL */ | ||
89 | enum wcn36xx_hal_host_msg_type { | ||
90 | /* Init/De-Init */ | ||
91 | WCN36XX_HAL_START_REQ = 0, | ||
92 | WCN36XX_HAL_START_RSP = 1, | ||
93 | WCN36XX_HAL_STOP_REQ = 2, | ||
94 | WCN36XX_HAL_STOP_RSP = 3, | ||
95 | |||
96 | /* Scan */ | ||
97 | WCN36XX_HAL_INIT_SCAN_REQ = 4, | ||
98 | WCN36XX_HAL_INIT_SCAN_RSP = 5, | ||
99 | WCN36XX_HAL_START_SCAN_REQ = 6, | ||
100 | WCN36XX_HAL_START_SCAN_RSP = 7, | ||
101 | WCN36XX_HAL_END_SCAN_REQ = 8, | ||
102 | WCN36XX_HAL_END_SCAN_RSP = 9, | ||
103 | WCN36XX_HAL_FINISH_SCAN_REQ = 10, | ||
104 | WCN36XX_HAL_FINISH_SCAN_RSP = 11, | ||
105 | |||
106 | /* HW STA configuration/deconfiguration */ | ||
107 | WCN36XX_HAL_CONFIG_STA_REQ = 12, | ||
108 | WCN36XX_HAL_CONFIG_STA_RSP = 13, | ||
109 | WCN36XX_HAL_DELETE_STA_REQ = 14, | ||
110 | WCN36XX_HAL_DELETE_STA_RSP = 15, | ||
111 | WCN36XX_HAL_CONFIG_BSS_REQ = 16, | ||
112 | WCN36XX_HAL_CONFIG_BSS_RSP = 17, | ||
113 | WCN36XX_HAL_DELETE_BSS_REQ = 18, | ||
114 | WCN36XX_HAL_DELETE_BSS_RSP = 19, | ||
115 | |||
116 | /* Infra STA asscoiation */ | ||
117 | WCN36XX_HAL_JOIN_REQ = 20, | ||
118 | WCN36XX_HAL_JOIN_RSP = 21, | ||
119 | WCN36XX_HAL_POST_ASSOC_REQ = 22, | ||
120 | WCN36XX_HAL_POST_ASSOC_RSP = 23, | ||
121 | |||
122 | /* Security */ | ||
123 | WCN36XX_HAL_SET_BSSKEY_REQ = 24, | ||
124 | WCN36XX_HAL_SET_BSSKEY_RSP = 25, | ||
125 | WCN36XX_HAL_SET_STAKEY_REQ = 26, | ||
126 | WCN36XX_HAL_SET_STAKEY_RSP = 27, | ||
127 | WCN36XX_HAL_RMV_BSSKEY_REQ = 28, | ||
128 | WCN36XX_HAL_RMV_BSSKEY_RSP = 29, | ||
129 | WCN36XX_HAL_RMV_STAKEY_REQ = 30, | ||
130 | WCN36XX_HAL_RMV_STAKEY_RSP = 31, | ||
131 | |||
132 | /* Qos Related */ | ||
133 | WCN36XX_HAL_ADD_TS_REQ = 32, | ||
134 | WCN36XX_HAL_ADD_TS_RSP = 33, | ||
135 | WCN36XX_HAL_DEL_TS_REQ = 34, | ||
136 | WCN36XX_HAL_DEL_TS_RSP = 35, | ||
137 | WCN36XX_HAL_UPD_EDCA_PARAMS_REQ = 36, | ||
138 | WCN36XX_HAL_UPD_EDCA_PARAMS_RSP = 37, | ||
139 | WCN36XX_HAL_ADD_BA_REQ = 38, | ||
140 | WCN36XX_HAL_ADD_BA_RSP = 39, | ||
141 | WCN36XX_HAL_DEL_BA_REQ = 40, | ||
142 | WCN36XX_HAL_DEL_BA_RSP = 41, | ||
143 | |||
144 | WCN36XX_HAL_CH_SWITCH_REQ = 42, | ||
145 | WCN36XX_HAL_CH_SWITCH_RSP = 43, | ||
146 | WCN36XX_HAL_SET_LINK_ST_REQ = 44, | ||
147 | WCN36XX_HAL_SET_LINK_ST_RSP = 45, | ||
148 | WCN36XX_HAL_GET_STATS_REQ = 46, | ||
149 | WCN36XX_HAL_GET_STATS_RSP = 47, | ||
150 | WCN36XX_HAL_UPDATE_CFG_REQ = 48, | ||
151 | WCN36XX_HAL_UPDATE_CFG_RSP = 49, | ||
152 | |||
153 | WCN36XX_HAL_MISSED_BEACON_IND = 50, | ||
154 | WCN36XX_HAL_UNKNOWN_ADDR2_FRAME_RX_IND = 51, | ||
155 | WCN36XX_HAL_MIC_FAILURE_IND = 52, | ||
156 | WCN36XX_HAL_FATAL_ERROR_IND = 53, | ||
157 | WCN36XX_HAL_SET_KEYDONE_MSG = 54, | ||
158 | |||
159 | /* NV Interface */ | ||
160 | WCN36XX_HAL_DOWNLOAD_NV_REQ = 55, | ||
161 | WCN36XX_HAL_DOWNLOAD_NV_RSP = 56, | ||
162 | |||
163 | WCN36XX_HAL_ADD_BA_SESSION_REQ = 57, | ||
164 | WCN36XX_HAL_ADD_BA_SESSION_RSP = 58, | ||
165 | WCN36XX_HAL_TRIGGER_BA_REQ = 59, | ||
166 | WCN36XX_HAL_TRIGGER_BA_RSP = 60, | ||
167 | WCN36XX_HAL_UPDATE_BEACON_REQ = 61, | ||
168 | WCN36XX_HAL_UPDATE_BEACON_RSP = 62, | ||
169 | WCN36XX_HAL_SEND_BEACON_REQ = 63, | ||
170 | WCN36XX_HAL_SEND_BEACON_RSP = 64, | ||
171 | |||
172 | WCN36XX_HAL_SET_BCASTKEY_REQ = 65, | ||
173 | WCN36XX_HAL_SET_BCASTKEY_RSP = 66, | ||
174 | WCN36XX_HAL_DELETE_STA_CONTEXT_IND = 67, | ||
175 | WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ = 68, | ||
176 | WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_RSP = 69, | ||
177 | |||
178 | /* PTT interface support */ | ||
179 | WCN36XX_HAL_PROCESS_PTT_REQ = 70, | ||
180 | WCN36XX_HAL_PROCESS_PTT_RSP = 71, | ||
181 | |||
182 | /* BTAMP related events */ | ||
183 | WCN36XX_HAL_SIGNAL_BTAMP_EVENT_REQ = 72, | ||
184 | WCN36XX_HAL_SIGNAL_BTAMP_EVENT_RSP = 73, | ||
185 | WCN36XX_HAL_TL_HAL_FLUSH_AC_REQ = 74, | ||
186 | WCN36XX_HAL_TL_HAL_FLUSH_AC_RSP = 75, | ||
187 | |||
188 | WCN36XX_HAL_ENTER_IMPS_REQ = 76, | ||
189 | WCN36XX_HAL_EXIT_IMPS_REQ = 77, | ||
190 | WCN36XX_HAL_ENTER_BMPS_REQ = 78, | ||
191 | WCN36XX_HAL_EXIT_BMPS_REQ = 79, | ||
192 | WCN36XX_HAL_ENTER_UAPSD_REQ = 80, | ||
193 | WCN36XX_HAL_EXIT_UAPSD_REQ = 81, | ||
194 | WCN36XX_HAL_UPDATE_UAPSD_PARAM_REQ = 82, | ||
195 | WCN36XX_HAL_CONFIGURE_RXP_FILTER_REQ = 83, | ||
196 | WCN36XX_HAL_ADD_BCN_FILTER_REQ = 84, | ||
197 | WCN36XX_HAL_REM_BCN_FILTER_REQ = 85, | ||
198 | WCN36XX_HAL_ADD_WOWL_BCAST_PTRN = 86, | ||
199 | WCN36XX_HAL_DEL_WOWL_BCAST_PTRN = 87, | ||
200 | WCN36XX_HAL_ENTER_WOWL_REQ = 88, | ||
201 | WCN36XX_HAL_EXIT_WOWL_REQ = 89, | ||
202 | WCN36XX_HAL_HOST_OFFLOAD_REQ = 90, | ||
203 | WCN36XX_HAL_SET_RSSI_THRESH_REQ = 91, | ||
204 | WCN36XX_HAL_GET_RSSI_REQ = 92, | ||
205 | WCN36XX_HAL_SET_UAPSD_AC_PARAMS_REQ = 93, | ||
206 | WCN36XX_HAL_CONFIGURE_APPS_CPU_WAKEUP_STATE_REQ = 94, | ||
207 | |||
208 | WCN36XX_HAL_ENTER_IMPS_RSP = 95, | ||
209 | WCN36XX_HAL_EXIT_IMPS_RSP = 96, | ||
210 | WCN36XX_HAL_ENTER_BMPS_RSP = 97, | ||
211 | WCN36XX_HAL_EXIT_BMPS_RSP = 98, | ||
212 | WCN36XX_HAL_ENTER_UAPSD_RSP = 99, | ||
213 | WCN36XX_HAL_EXIT_UAPSD_RSP = 100, | ||
214 | WCN36XX_HAL_SET_UAPSD_AC_PARAMS_RSP = 101, | ||
215 | WCN36XX_HAL_UPDATE_UAPSD_PARAM_RSP = 102, | ||
216 | WCN36XX_HAL_CONFIGURE_RXP_FILTER_RSP = 103, | ||
217 | WCN36XX_HAL_ADD_BCN_FILTER_RSP = 104, | ||
218 | WCN36XX_HAL_REM_BCN_FILTER_RSP = 105, | ||
219 | WCN36XX_HAL_SET_RSSI_THRESH_RSP = 106, | ||
220 | WCN36XX_HAL_HOST_OFFLOAD_RSP = 107, | ||
221 | WCN36XX_HAL_ADD_WOWL_BCAST_PTRN_RSP = 108, | ||
222 | WCN36XX_HAL_DEL_WOWL_BCAST_PTRN_RSP = 109, | ||
223 | WCN36XX_HAL_ENTER_WOWL_RSP = 110, | ||
224 | WCN36XX_HAL_EXIT_WOWL_RSP = 111, | ||
225 | WCN36XX_HAL_RSSI_NOTIFICATION_IND = 112, | ||
226 | WCN36XX_HAL_GET_RSSI_RSP = 113, | ||
227 | WCN36XX_HAL_CONFIGURE_APPS_CPU_WAKEUP_STATE_RSP = 114, | ||
228 | |||
229 | /* 11k related events */ | ||
230 | WCN36XX_HAL_SET_MAX_TX_POWER_REQ = 115, | ||
231 | WCN36XX_HAL_SET_MAX_TX_POWER_RSP = 116, | ||
232 | |||
233 | /* 11R related msgs */ | ||
234 | WCN36XX_HAL_AGGR_ADD_TS_REQ = 117, | ||
235 | WCN36XX_HAL_AGGR_ADD_TS_RSP = 118, | ||
236 | |||
237 | /* P2P WLAN_FEATURE_P2P */ | ||
238 | WCN36XX_HAL_SET_P2P_GONOA_REQ = 119, | ||
239 | WCN36XX_HAL_SET_P2P_GONOA_RSP = 120, | ||
240 | |||
241 | /* WLAN Dump commands */ | ||
242 | WCN36XX_HAL_DUMP_COMMAND_REQ = 121, | ||
243 | WCN36XX_HAL_DUMP_COMMAND_RSP = 122, | ||
244 | |||
245 | /* OEM_DATA FEATURE SUPPORT */ | ||
246 | WCN36XX_HAL_START_OEM_DATA_REQ = 123, | ||
247 | WCN36XX_HAL_START_OEM_DATA_RSP = 124, | ||
248 | |||
249 | /* ADD SELF STA REQ and RSP */ | ||
250 | WCN36XX_HAL_ADD_STA_SELF_REQ = 125, | ||
251 | WCN36XX_HAL_ADD_STA_SELF_RSP = 126, | ||
252 | |||
253 | /* DEL SELF STA SUPPORT */ | ||
254 | WCN36XX_HAL_DEL_STA_SELF_REQ = 127, | ||
255 | WCN36XX_HAL_DEL_STA_SELF_RSP = 128, | ||
256 | |||
257 | /* Coex Indication */ | ||
258 | WCN36XX_HAL_COEX_IND = 129, | ||
259 | |||
260 | /* Tx Complete Indication */ | ||
261 | WCN36XX_HAL_OTA_TX_COMPL_IND = 130, | ||
262 | |||
263 | /* Host Suspend/resume messages */ | ||
264 | WCN36XX_HAL_HOST_SUSPEND_IND = 131, | ||
265 | WCN36XX_HAL_HOST_RESUME_REQ = 132, | ||
266 | WCN36XX_HAL_HOST_RESUME_RSP = 133, | ||
267 | |||
268 | WCN36XX_HAL_SET_TX_POWER_REQ = 134, | ||
269 | WCN36XX_HAL_SET_TX_POWER_RSP = 135, | ||
270 | WCN36XX_HAL_GET_TX_POWER_REQ = 136, | ||
271 | WCN36XX_HAL_GET_TX_POWER_RSP = 137, | ||
272 | |||
273 | WCN36XX_HAL_P2P_NOA_ATTR_IND = 138, | ||
274 | |||
275 | WCN36XX_HAL_ENABLE_RADAR_DETECT_REQ = 139, | ||
276 | WCN36XX_HAL_ENABLE_RADAR_DETECT_RSP = 140, | ||
277 | WCN36XX_HAL_GET_TPC_REPORT_REQ = 141, | ||
278 | WCN36XX_HAL_GET_TPC_REPORT_RSP = 142, | ||
279 | WCN36XX_HAL_RADAR_DETECT_IND = 143, | ||
280 | WCN36XX_HAL_RADAR_DETECT_INTR_IND = 144, | ||
281 | WCN36XX_HAL_KEEP_ALIVE_REQ = 145, | ||
282 | WCN36XX_HAL_KEEP_ALIVE_RSP = 146, | ||
283 | |||
284 | /* PNO messages */ | ||
285 | WCN36XX_HAL_SET_PREF_NETWORK_REQ = 147, | ||
286 | WCN36XX_HAL_SET_PREF_NETWORK_RSP = 148, | ||
287 | WCN36XX_HAL_SET_RSSI_FILTER_REQ = 149, | ||
288 | WCN36XX_HAL_SET_RSSI_FILTER_RSP = 150, | ||
289 | WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ = 151, | ||
290 | WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP = 152, | ||
291 | WCN36XX_HAL_PREF_NETW_FOUND_IND = 153, | ||
292 | |||
293 | WCN36XX_HAL_SET_TX_PER_TRACKING_REQ = 154, | ||
294 | WCN36XX_HAL_SET_TX_PER_TRACKING_RSP = 155, | ||
295 | WCN36XX_HAL_TX_PER_HIT_IND = 156, | ||
296 | |||
297 | WCN36XX_HAL_8023_MULTICAST_LIST_REQ = 157, | ||
298 | WCN36XX_HAL_8023_MULTICAST_LIST_RSP = 158, | ||
299 | |||
300 | WCN36XX_HAL_SET_PACKET_FILTER_REQ = 159, | ||
301 | WCN36XX_HAL_SET_PACKET_FILTER_RSP = 160, | ||
302 | WCN36XX_HAL_PACKET_FILTER_MATCH_COUNT_REQ = 161, | ||
303 | WCN36XX_HAL_PACKET_FILTER_MATCH_COUNT_RSP = 162, | ||
304 | WCN36XX_HAL_CLEAR_PACKET_FILTER_REQ = 163, | ||
305 | WCN36XX_HAL_CLEAR_PACKET_FILTER_RSP = 164, | ||
306 | |||
307 | /* | ||
308 | * This is temp fix. Should be removed once Host and Riva code is | ||
309 | * in sync. | ||
310 | */ | ||
311 | WCN36XX_HAL_INIT_SCAN_CON_REQ = 165, | ||
312 | |||
313 | WCN36XX_HAL_SET_POWER_PARAMS_REQ = 166, | ||
314 | WCN36XX_HAL_SET_POWER_PARAMS_RSP = 167, | ||
315 | |||
316 | WCN36XX_HAL_TSM_STATS_REQ = 168, | ||
317 | WCN36XX_HAL_TSM_STATS_RSP = 169, | ||
318 | |||
319 | /* wake reason indication (WOW) */ | ||
320 | WCN36XX_HAL_WAKE_REASON_IND = 170, | ||
321 | |||
322 | /* GTK offload support */ | ||
323 | WCN36XX_HAL_GTK_OFFLOAD_REQ = 171, | ||
324 | WCN36XX_HAL_GTK_OFFLOAD_RSP = 172, | ||
325 | WCN36XX_HAL_GTK_OFFLOAD_GETINFO_REQ = 173, | ||
326 | WCN36XX_HAL_GTK_OFFLOAD_GETINFO_RSP = 174, | ||
327 | |||
328 | WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ = 175, | ||
329 | WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP = 176, | ||
330 | WCN36XX_HAL_EXCLUDE_UNENCRYPTED_IND = 177, | ||
331 | |||
332 | WCN36XX_HAL_SET_THERMAL_MITIGATION_REQ = 178, | ||
333 | WCN36XX_HAL_SET_THERMAL_MITIGATION_RSP = 179, | ||
334 | |||
335 | WCN36XX_HAL_UPDATE_VHT_OP_MODE_REQ = 182, | ||
336 | WCN36XX_HAL_UPDATE_VHT_OP_MODE_RSP = 183, | ||
337 | |||
338 | WCN36XX_HAL_P2P_NOA_START_IND = 184, | ||
339 | |||
340 | WCN36XX_HAL_GET_ROAM_RSSI_REQ = 185, | ||
341 | WCN36XX_HAL_GET_ROAM_RSSI_RSP = 186, | ||
342 | |||
343 | WCN36XX_HAL_CLASS_B_STATS_IND = 187, | ||
344 | WCN36XX_HAL_DEL_BA_IND = 188, | ||
345 | WCN36XX_HAL_DHCP_START_IND = 189, | ||
346 | WCN36XX_HAL_DHCP_STOP_IND = 190, | ||
347 | |||
348 | WCN36XX_HAL_MSG_MAX = WCN36XX_HAL_MSG_TYPE_MAX_ENUM_SIZE | ||
349 | }; | ||
350 | |||
351 | /* Enumeration for Version */ | ||
352 | enum wcn36xx_hal_host_msg_version { | ||
353 | WCN36XX_HAL_MSG_VERSION0 = 0, | ||
354 | WCN36XX_HAL_MSG_VERSION1 = 1, | ||
355 | /* define as 2 bytes data */ | ||
356 | WCN36XX_HAL_MSG_WCNSS_CTRL_VERSION = 0x7FFF, | ||
357 | WCN36XX_HAL_MSG_VERSION_MAX_FIELD = WCN36XX_HAL_MSG_WCNSS_CTRL_VERSION | ||
358 | }; | ||
359 | |||
360 | enum driver_type { | ||
361 | DRIVER_TYPE_PRODUCTION = 0, | ||
362 | DRIVER_TYPE_MFG = 1, | ||
363 | DRIVER_TYPE_DVT = 2, | ||
364 | DRIVER_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
365 | }; | ||
366 | |||
367 | enum wcn36xx_hal_stop_type { | ||
368 | HAL_STOP_TYPE_SYS_RESET, | ||
369 | HAL_STOP_TYPE_SYS_DEEP_SLEEP, | ||
370 | HAL_STOP_TYPE_RF_KILL, | ||
371 | HAL_STOP_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
372 | }; | ||
373 | |||
374 | enum wcn36xx_hal_sys_mode { | ||
375 | HAL_SYS_MODE_NORMAL, | ||
376 | HAL_SYS_MODE_LEARN, | ||
377 | HAL_SYS_MODE_SCAN, | ||
378 | HAL_SYS_MODE_PROMISC, | ||
379 | HAL_SYS_MODE_SUSPEND_LINK, | ||
380 | HAL_SYS_MODE_ROAM_SCAN, | ||
381 | HAL_SYS_MODE_ROAM_SUSPEND_LINK, | ||
382 | HAL_SYS_MODE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
383 | }; | ||
384 | |||
385 | enum phy_chan_bond_state { | ||
386 | /* 20MHz IF bandwidth centered on IF carrier */ | ||
387 | PHY_SINGLE_CHANNEL_CENTERED = 0, | ||
388 | |||
389 | /* 40MHz IF bandwidth with lower 20MHz supporting the primary channel */ | ||
390 | PHY_DOUBLE_CHANNEL_LOW_PRIMARY = 1, | ||
391 | |||
392 | /* 40MHz IF bandwidth centered on IF carrier */ | ||
393 | PHY_DOUBLE_CHANNEL_CENTERED = 2, | ||
394 | |||
395 | /* 40MHz IF bandwidth with higher 20MHz supporting the primary ch */ | ||
396 | PHY_DOUBLE_CHANNEL_HIGH_PRIMARY = 3, | ||
397 | |||
398 | /* 20/40MHZ offset LOW 40/80MHZ offset CENTERED */ | ||
399 | PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED = 4, | ||
400 | |||
401 | /* 20/40MHZ offset CENTERED 40/80MHZ offset CENTERED */ | ||
402 | PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED = 5, | ||
403 | |||
404 | /* 20/40MHZ offset HIGH 40/80MHZ offset CENTERED */ | ||
405 | PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED = 6, | ||
406 | |||
407 | /* 20/40MHZ offset LOW 40/80MHZ offset LOW */ | ||
408 | PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW = 7, | ||
409 | |||
410 | /* 20/40MHZ offset HIGH 40/80MHZ offset LOW */ | ||
411 | PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW = 8, | ||
412 | |||
413 | /* 20/40MHZ offset LOW 40/80MHZ offset HIGH */ | ||
414 | PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH = 9, | ||
415 | |||
416 | /* 20/40MHZ offset-HIGH 40/80MHZ offset HIGH */ | ||
417 | PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH = 10, | ||
418 | |||
419 | PHY_CHANNEL_BONDING_STATE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
420 | }; | ||
421 | |||
422 | /* Spatial Multiplexing(SM) Power Save mode */ | ||
423 | enum wcn36xx_hal_ht_mimo_state { | ||
424 | /* Static SM Power Save mode */ | ||
425 | WCN36XX_HAL_HT_MIMO_PS_STATIC = 0, | ||
426 | |||
427 | /* Dynamic SM Power Save mode */ | ||
428 | WCN36XX_HAL_HT_MIMO_PS_DYNAMIC = 1, | ||
429 | |||
430 | /* reserved */ | ||
431 | WCN36XX_HAL_HT_MIMO_PS_NA = 2, | ||
432 | |||
433 | /* SM Power Save disabled */ | ||
434 | WCN36XX_HAL_HT_MIMO_PS_NO_LIMIT = 3, | ||
435 | |||
436 | WCN36XX_HAL_HT_MIMO_PS_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
437 | }; | ||
438 | |||
439 | /* each station added has a rate mode which specifies the sta attributes */ | ||
440 | enum sta_rate_mode { | ||
441 | STA_TAURUS = 0, | ||
442 | STA_TITAN, | ||
443 | STA_POLARIS, | ||
444 | STA_11b, | ||
445 | STA_11bg, | ||
446 | STA_11a, | ||
447 | STA_11n, | ||
448 | STA_11ac, | ||
449 | STA_INVALID_RATE_MODE = WCN36XX_HAL_MAX_ENUM_SIZE | ||
450 | }; | ||
451 | |||
452 | /* 1,2,5.5,11 */ | ||
453 | #define WCN36XX_HAL_NUM_DSSS_RATES 4 | ||
454 | |||
455 | /* 6,9,12,18,24,36,48,54 */ | ||
456 | #define WCN36XX_HAL_NUM_OFDM_RATES 8 | ||
457 | |||
458 | /* 72,96,108 */ | ||
459 | #define WCN36XX_HAL_NUM_POLARIS_RATES 3 | ||
460 | |||
461 | #define WCN36XX_HAL_MAC_MAX_SUPPORTED_MCS_SET 16 | ||
462 | |||
463 | enum wcn36xx_hal_bss_type { | ||
464 | WCN36XX_HAL_INFRASTRUCTURE_MODE, | ||
465 | |||
466 | /* Added for softAP support */ | ||
467 | WCN36XX_HAL_INFRA_AP_MODE, | ||
468 | |||
469 | WCN36XX_HAL_IBSS_MODE, | ||
470 | |||
471 | /* Added for BT-AMP support */ | ||
472 | WCN36XX_HAL_BTAMP_STA_MODE, | ||
473 | |||
474 | /* Added for BT-AMP support */ | ||
475 | WCN36XX_HAL_BTAMP_AP_MODE, | ||
476 | |||
477 | WCN36XX_HAL_AUTO_MODE, | ||
478 | |||
479 | WCN36XX_HAL_DONOT_USE_BSS_TYPE = WCN36XX_HAL_MAX_ENUM_SIZE | ||
480 | }; | ||
481 | |||
482 | enum wcn36xx_hal_nw_type { | ||
483 | WCN36XX_HAL_11A_NW_TYPE, | ||
484 | WCN36XX_HAL_11B_NW_TYPE, | ||
485 | WCN36XX_HAL_11G_NW_TYPE, | ||
486 | WCN36XX_HAL_11N_NW_TYPE, | ||
487 | WCN36XX_HAL_DONOT_USE_NW_TYPE = WCN36XX_HAL_MAX_ENUM_SIZE | ||
488 | }; | ||
489 | |||
490 | #define WCN36XX_HAL_MAC_RATESET_EID_MAX 12 | ||
491 | |||
492 | enum wcn36xx_hal_ht_operating_mode { | ||
493 | /* No Protection */ | ||
494 | WCN36XX_HAL_HT_OP_MODE_PURE, | ||
495 | |||
496 | /* Overlap Legacy device present, protection is optional */ | ||
497 | WCN36XX_HAL_HT_OP_MODE_OVERLAP_LEGACY, | ||
498 | |||
499 | /* No legacy device, but 20 MHz HT present */ | ||
500 | WCN36XX_HAL_HT_OP_MODE_NO_LEGACY_20MHZ_HT, | ||
501 | |||
502 | /* Protection is required */ | ||
503 | WCN36XX_HAL_HT_OP_MODE_MIXED, | ||
504 | |||
505 | WCN36XX_HAL_HT_OP_MODE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
506 | }; | ||
507 | |||
508 | /* Encryption type enum used with peer */ | ||
509 | enum ani_ed_type { | ||
510 | WCN36XX_HAL_ED_NONE, | ||
511 | WCN36XX_HAL_ED_WEP40, | ||
512 | WCN36XX_HAL_ED_WEP104, | ||
513 | WCN36XX_HAL_ED_TKIP, | ||
514 | WCN36XX_HAL_ED_CCMP, | ||
515 | WCN36XX_HAL_ED_WPI, | ||
516 | WCN36XX_HAL_ED_AES_128_CMAC, | ||
517 | WCN36XX_HAL_ED_NOT_IMPLEMENTED = WCN36XX_HAL_MAX_ENUM_SIZE | ||
518 | }; | ||
519 | |||
520 | #define WLAN_MAX_KEY_RSC_LEN 16 | ||
521 | #define WLAN_WAPI_KEY_RSC_LEN 16 | ||
522 | |||
523 | /* MAX key length when ULA is used */ | ||
524 | #define WCN36XX_HAL_MAC_MAX_KEY_LENGTH 32 | ||
525 | #define WCN36XX_HAL_MAC_MAX_NUM_OF_DEFAULT_KEYS 4 | ||
526 | |||
527 | /* | ||
528 | * Enum to specify whether key is used for TX only, RX only or both. | ||
529 | */ | ||
530 | enum ani_key_direction { | ||
531 | WCN36XX_HAL_TX_ONLY, | ||
532 | WCN36XX_HAL_RX_ONLY, | ||
533 | WCN36XX_HAL_TX_RX, | ||
534 | WCN36XX_HAL_TX_DEFAULT, | ||
535 | WCN36XX_HAL_DONOT_USE_KEY_DIRECTION = WCN36XX_HAL_MAX_ENUM_SIZE | ||
536 | }; | ||
537 | |||
538 | enum ani_wep_type { | ||
539 | WCN36XX_HAL_WEP_STATIC, | ||
540 | WCN36XX_HAL_WEP_DYNAMIC, | ||
541 | WCN36XX_HAL_WEP_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
542 | }; | ||
543 | |||
544 | enum wcn36xx_hal_link_state { | ||
545 | |||
546 | WCN36XX_HAL_LINK_IDLE_STATE = 0, | ||
547 | WCN36XX_HAL_LINK_PREASSOC_STATE = 1, | ||
548 | WCN36XX_HAL_LINK_POSTASSOC_STATE = 2, | ||
549 | WCN36XX_HAL_LINK_AP_STATE = 3, | ||
550 | WCN36XX_HAL_LINK_IBSS_STATE = 4, | ||
551 | |||
552 | /* BT-AMP Case */ | ||
553 | WCN36XX_HAL_LINK_BTAMP_PREASSOC_STATE = 5, | ||
554 | WCN36XX_HAL_LINK_BTAMP_POSTASSOC_STATE = 6, | ||
555 | WCN36XX_HAL_LINK_BTAMP_AP_STATE = 7, | ||
556 | WCN36XX_HAL_LINK_BTAMP_STA_STATE = 8, | ||
557 | |||
558 | /* Reserved for HAL Internal Use */ | ||
559 | WCN36XX_HAL_LINK_LEARN_STATE = 9, | ||
560 | WCN36XX_HAL_LINK_SCAN_STATE = 10, | ||
561 | WCN36XX_HAL_LINK_FINISH_SCAN_STATE = 11, | ||
562 | WCN36XX_HAL_LINK_INIT_CAL_STATE = 12, | ||
563 | WCN36XX_HAL_LINK_FINISH_CAL_STATE = 13, | ||
564 | WCN36XX_HAL_LINK_LISTEN_STATE = 14, | ||
565 | |||
566 | WCN36XX_HAL_LINK_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
567 | }; | ||
568 | |||
569 | enum wcn36xx_hal_stats_mask { | ||
570 | HAL_SUMMARY_STATS_INFO = 0x00000001, | ||
571 | HAL_GLOBAL_CLASS_A_STATS_INFO = 0x00000002, | ||
572 | HAL_GLOBAL_CLASS_B_STATS_INFO = 0x00000004, | ||
573 | HAL_GLOBAL_CLASS_C_STATS_INFO = 0x00000008, | ||
574 | HAL_GLOBAL_CLASS_D_STATS_INFO = 0x00000010, | ||
575 | HAL_PER_STA_STATS_INFO = 0x00000020 | ||
576 | }; | ||
577 | |||
578 | /* BT-AMP events type */ | ||
579 | enum bt_amp_event_type { | ||
580 | BTAMP_EVENT_CONNECTION_START, | ||
581 | BTAMP_EVENT_CONNECTION_STOP, | ||
582 | BTAMP_EVENT_CONNECTION_TERMINATED, | ||
583 | |||
584 | /* This and beyond are invalid values */ | ||
585 | BTAMP_EVENT_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE, | ||
586 | }; | ||
587 | |||
588 | /* PE Statistics */ | ||
589 | enum pe_stats_mask { | ||
590 | PE_SUMMARY_STATS_INFO = 0x00000001, | ||
591 | PE_GLOBAL_CLASS_A_STATS_INFO = 0x00000002, | ||
592 | PE_GLOBAL_CLASS_B_STATS_INFO = 0x00000004, | ||
593 | PE_GLOBAL_CLASS_C_STATS_INFO = 0x00000008, | ||
594 | PE_GLOBAL_CLASS_D_STATS_INFO = 0x00000010, | ||
595 | PE_PER_STA_STATS_INFO = 0x00000020, | ||
596 | |||
597 | /* This and beyond are invalid values */ | ||
598 | PE_STATS_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
599 | }; | ||
600 | |||
601 | /* | ||
602 | * Configuration Parameter IDs | ||
603 | */ | ||
604 | #define WCN36XX_HAL_CFG_STA_ID 0 | ||
605 | #define WCN36XX_HAL_CFG_CURRENT_TX_ANTENNA 1 | ||
606 | #define WCN36XX_HAL_CFG_CURRENT_RX_ANTENNA 2 | ||
607 | #define WCN36XX_HAL_CFG_LOW_GAIN_OVERRIDE 3 | ||
608 | #define WCN36XX_HAL_CFG_POWER_STATE_PER_CHAIN 4 | ||
609 | #define WCN36XX_HAL_CFG_CAL_PERIOD 5 | ||
610 | #define WCN36XX_HAL_CFG_CAL_CONTROL 6 | ||
611 | #define WCN36XX_HAL_CFG_PROXIMITY 7 | ||
612 | #define WCN36XX_HAL_CFG_NETWORK_DENSITY 8 | ||
613 | #define WCN36XX_HAL_CFG_MAX_MEDIUM_TIME 9 | ||
614 | #define WCN36XX_HAL_CFG_MAX_MPDUS_IN_AMPDU 10 | ||
615 | #define WCN36XX_HAL_CFG_RTS_THRESHOLD 11 | ||
616 | #define WCN36XX_HAL_CFG_SHORT_RETRY_LIMIT 12 | ||
617 | #define WCN36XX_HAL_CFG_LONG_RETRY_LIMIT 13 | ||
618 | #define WCN36XX_HAL_CFG_FRAGMENTATION_THRESHOLD 14 | ||
619 | #define WCN36XX_HAL_CFG_DYNAMIC_THRESHOLD_ZERO 15 | ||
620 | #define WCN36XX_HAL_CFG_DYNAMIC_THRESHOLD_ONE 16 | ||
621 | #define WCN36XX_HAL_CFG_DYNAMIC_THRESHOLD_TWO 17 | ||
622 | #define WCN36XX_HAL_CFG_FIXED_RATE 18 | ||
623 | #define WCN36XX_HAL_CFG_RETRYRATE_POLICY 19 | ||
624 | #define WCN36XX_HAL_CFG_RETRYRATE_SECONDARY 20 | ||
625 | #define WCN36XX_HAL_CFG_RETRYRATE_TERTIARY 21 | ||
626 | #define WCN36XX_HAL_CFG_FORCE_POLICY_PROTECTION 22 | ||
627 | #define WCN36XX_HAL_CFG_FIXED_RATE_MULTICAST_24GHZ 23 | ||
628 | #define WCN36XX_HAL_CFG_FIXED_RATE_MULTICAST_5GHZ 24 | ||
629 | #define WCN36XX_HAL_CFG_DEFAULT_RATE_INDEX_24GHZ 25 | ||
630 | #define WCN36XX_HAL_CFG_DEFAULT_RATE_INDEX_5GHZ 26 | ||
631 | #define WCN36XX_HAL_CFG_MAX_BA_SESSIONS 27 | ||
632 | #define WCN36XX_HAL_CFG_PS_DATA_INACTIVITY_TIMEOUT 28 | ||
633 | #define WCN36XX_HAL_CFG_PS_ENABLE_BCN_FILTER 29 | ||
634 | #define WCN36XX_HAL_CFG_PS_ENABLE_RSSI_MONITOR 30 | ||
635 | #define WCN36XX_HAL_CFG_NUM_BEACON_PER_RSSI_AVERAGE 31 | ||
636 | #define WCN36XX_HAL_CFG_STATS_PERIOD 32 | ||
637 | #define WCN36XX_HAL_CFG_CFP_MAX_DURATION 33 | ||
638 | #define WCN36XX_HAL_CFG_FRAME_TRANS_ENABLED 34 | ||
639 | #define WCN36XX_HAL_CFG_DTIM_PERIOD 35 | ||
640 | #define WCN36XX_HAL_CFG_EDCA_WMM_ACBK 36 | ||
641 | #define WCN36XX_HAL_CFG_EDCA_WMM_ACBE 37 | ||
642 | #define WCN36XX_HAL_CFG_EDCA_WMM_ACVO 38 | ||
643 | #define WCN36XX_HAL_CFG_EDCA_WMM_ACVI 39 | ||
644 | #define WCN36XX_HAL_CFG_BA_THRESHOLD_HIGH 40 | ||
645 | #define WCN36XX_HAL_CFG_MAX_BA_BUFFERS 41 | ||
646 | #define WCN36XX_HAL_CFG_RPE_POLLING_THRESHOLD 42 | ||
647 | #define WCN36XX_HAL_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG 43 | ||
648 | #define WCN36XX_HAL_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG 44 | ||
649 | #define WCN36XX_HAL_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG 45 | ||
650 | #define WCN36XX_HAL_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG 46 | ||
651 | #define WCN36XX_HAL_CFG_NO_OF_ONCHIP_REORDER_SESSIONS 47 | ||
652 | #define WCN36XX_HAL_CFG_PS_LISTEN_INTERVAL 48 | ||
653 | #define WCN36XX_HAL_CFG_PS_HEART_BEAT_THRESHOLD 49 | ||
654 | #define WCN36XX_HAL_CFG_PS_NTH_BEACON_FILTER 50 | ||
655 | #define WCN36XX_HAL_CFG_PS_MAX_PS_POLL 51 | ||
656 | #define WCN36XX_HAL_CFG_PS_MIN_RSSI_THRESHOLD 52 | ||
657 | #define WCN36XX_HAL_CFG_PS_RSSI_FILTER_PERIOD 53 | ||
658 | #define WCN36XX_HAL_CFG_PS_BROADCAST_FRAME_FILTER_ENABLE 54 | ||
659 | #define WCN36XX_HAL_CFG_PS_IGNORE_DTIM 55 | ||
660 | #define WCN36XX_HAL_CFG_PS_ENABLE_BCN_EARLY_TERM 56 | ||
661 | #define WCN36XX_HAL_CFG_DYNAMIC_PS_POLL_VALUE 57 | ||
662 | #define WCN36XX_HAL_CFG_PS_NULLDATA_AP_RESP_TIMEOUT 58 | ||
663 | #define WCN36XX_HAL_CFG_TELE_BCN_WAKEUP_EN 59 | ||
664 | #define WCN36XX_HAL_CFG_TELE_BCN_TRANS_LI 60 | ||
665 | #define WCN36XX_HAL_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS 61 | ||
666 | #define WCN36XX_HAL_CFG_TELE_BCN_MAX_LI 62 | ||
667 | #define WCN36XX_HAL_CFG_TELE_BCN_MAX_LI_IDLE_BCNS 63 | ||
668 | #define WCN36XX_HAL_CFG_TX_PWR_CTRL_ENABLE 64 | ||
669 | #define WCN36XX_HAL_CFG_VALID_RADAR_CHANNEL_LIST 65 | ||
670 | #define WCN36XX_HAL_CFG_TX_POWER_24_20 66 | ||
671 | #define WCN36XX_HAL_CFG_TX_POWER_24_40 67 | ||
672 | #define WCN36XX_HAL_CFG_TX_POWER_50_20 68 | ||
673 | #define WCN36XX_HAL_CFG_TX_POWER_50_40 69 | ||
674 | #define WCN36XX_HAL_CFG_MCAST_BCAST_FILTER_SETTING 70 | ||
675 | #define WCN36XX_HAL_CFG_BCN_EARLY_TERM_WAKEUP_INTERVAL 71 | ||
676 | #define WCN36XX_HAL_CFG_MAX_TX_POWER_2_4 72 | ||
677 | #define WCN36XX_HAL_CFG_MAX_TX_POWER_5 73 | ||
678 | #define WCN36XX_HAL_CFG_INFRA_STA_KEEP_ALIVE_PERIOD 74 | ||
679 | #define WCN36XX_HAL_CFG_ENABLE_CLOSE_LOOP 75 | ||
680 | #define WCN36XX_HAL_CFG_BTC_EXECUTION_MODE 76 | ||
681 | #define WCN36XX_HAL_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK 77 | ||
682 | #define WCN36XX_HAL_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS 78 | ||
683 | #define WCN36XX_HAL_CFG_PS_TX_INACTIVITY_TIMEOUT 79 | ||
684 | #define WCN36XX_HAL_CFG_WCNSS_API_VERSION 80 | ||
685 | #define WCN36XX_HAL_CFG_AP_KEEPALIVE_TIMEOUT 81 | ||
686 | #define WCN36XX_HAL_CFG_GO_KEEPALIVE_TIMEOUT 82 | ||
687 | #define WCN36XX_HAL_CFG_ENABLE_MC_ADDR_LIST 83 | ||
688 | #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_INQ_BT 84 | ||
689 | #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_PAGE_BT 85 | ||
690 | #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_CONN_BT 86 | ||
691 | #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_LE_BT 87 | ||
692 | #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_INQ_WLAN 88 | ||
693 | #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_PAGE_WLAN 89 | ||
694 | #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_CONN_WLAN 90 | ||
695 | #define WCN36XX_HAL_CFG_BTC_STATIC_LEN_LE_WLAN 91 | ||
696 | #define WCN36XX_HAL_CFG_BTC_DYN_MAX_LEN_BT 92 | ||
697 | #define WCN36XX_HAL_CFG_BTC_DYN_MAX_LEN_WLAN 93 | ||
698 | #define WCN36XX_HAL_CFG_BTC_MAX_SCO_BLOCK_PERC 94 | ||
699 | #define WCN36XX_HAL_CFG_BTC_DHCP_PROT_ON_A2DP 95 | ||
700 | #define WCN36XX_HAL_CFG_BTC_DHCP_PROT_ON_SCO 96 | ||
701 | #define WCN36XX_HAL_CFG_ENABLE_UNICAST_FILTER 97 | ||
702 | #define WCN36XX_HAL_CFG_MAX_ASSOC_LIMIT 98 | ||
703 | #define WCN36XX_HAL_CFG_ENABLE_LPWR_IMG_TRANSITION 99 | ||
704 | #define WCN36XX_HAL_CFG_ENABLE_MCC_ADAPTIVE_SCHEDULER 100 | ||
705 | #define WCN36XX_HAL_CFG_ENABLE_DETECT_PS_SUPPORT 101 | ||
706 | #define WCN36XX_HAL_CFG_AP_LINK_MONITOR_TIMEOUT 102 | ||
707 | #define WCN36XX_HAL_CFG_BTC_DWELL_TIME_MULTIPLIER 103 | ||
708 | #define WCN36XX_HAL_CFG_ENABLE_TDLS_OXYGEN_MODE 104 | ||
709 | #define WCN36XX_HAL_CFG_MAX_PARAMS 105 | ||
710 | |||
711 | /* Message definitons - All the messages below need to be packed */ | ||
712 | |||
713 | /* Definition for HAL API Version. */ | ||
714 | struct wcnss_wlan_version { | ||
715 | u8 revision; | ||
716 | u8 version; | ||
717 | u8 minor; | ||
718 | u8 major; | ||
719 | } __packed; | ||
720 | |||
721 | /* Definition for Encryption Keys */ | ||
722 | struct wcn36xx_hal_keys { | ||
723 | u8 id; | ||
724 | |||
725 | /* 0 for multicast */ | ||
726 | u8 unicast; | ||
727 | |||
728 | enum ani_key_direction direction; | ||
729 | |||
730 | /* Usage is unknown */ | ||
731 | u8 rsc[WLAN_MAX_KEY_RSC_LEN]; | ||
732 | |||
733 | /* =1 for authenticator,=0 for supplicant */ | ||
734 | u8 pae_role; | ||
735 | |||
736 | u16 length; | ||
737 | u8 key[WCN36XX_HAL_MAC_MAX_KEY_LENGTH]; | ||
738 | } __packed; | ||
739 | |||
740 | /* | ||
741 | * set_sta_key_params Moving here since it is shared by | ||
742 | * configbss/setstakey msgs | ||
743 | */ | ||
744 | struct wcn36xx_hal_set_sta_key_params { | ||
745 | /* STA Index */ | ||
746 | u16 sta_index; | ||
747 | |||
748 | /* Encryption Type used with peer */ | ||
749 | enum ani_ed_type enc_type; | ||
750 | |||
751 | /* STATIC/DYNAMIC - valid only for WEP */ | ||
752 | enum ani_wep_type wep_type; | ||
753 | |||
754 | /* Default WEP key, valid only for static WEP, must between 0 and 3. */ | ||
755 | u8 def_wep_idx; | ||
756 | |||
757 | /* valid only for non-static WEP encyrptions */ | ||
758 | struct wcn36xx_hal_keys key[WCN36XX_HAL_MAC_MAX_NUM_OF_DEFAULT_KEYS]; | ||
759 | |||
760 | /* | ||
761 | * Control for Replay Count, 1= Single TID based replay count on Tx | ||
762 | * 0 = Per TID based replay count on TX | ||
763 | */ | ||
764 | u8 single_tid_rc; | ||
765 | |||
766 | } __packed; | ||
767 | |||
768 | /* 4-byte control message header used by HAL*/ | ||
769 | struct wcn36xx_hal_msg_header { | ||
770 | enum wcn36xx_hal_host_msg_type msg_type:16; | ||
771 | enum wcn36xx_hal_host_msg_version msg_version:16; | ||
772 | u32 len; | ||
773 | } __packed; | ||
774 | |||
775 | /* Config format required by HAL for each CFG item*/ | ||
776 | struct wcn36xx_hal_cfg { | ||
777 | /* Cfg Id. The Id required by HAL is exported by HAL | ||
778 | * in shared header file between UMAC and HAL.*/ | ||
779 | u16 id; | ||
780 | |||
781 | /* Length of the Cfg. This parameter is used to go to next cfg | ||
782 | * in the TLV format.*/ | ||
783 | u16 len; | ||
784 | |||
785 | /* Padding bytes for unaligned address's */ | ||
786 | u16 pad_bytes; | ||
787 | |||
788 | /* Reserve bytes for making cfgVal to align address */ | ||
789 | u16 reserve; | ||
790 | |||
791 | /* Following the uCfgLen field there should be a 'uCfgLen' bytes | ||
792 | * containing the uCfgValue ; u8 uCfgValue[uCfgLen] */ | ||
793 | } __packed; | ||
794 | |||
795 | struct wcn36xx_hal_mac_start_parameters { | ||
796 | /* Drive Type - Production or FTM etc */ | ||
797 | enum driver_type type; | ||
798 | |||
799 | /* Length of the config buffer */ | ||
800 | u32 len; | ||
801 | |||
802 | /* Following this there is a TLV formatted buffer of length | ||
803 | * "len" bytes containing all config values. | ||
804 | * The TLV is expected to be formatted like this: | ||
805 | * 0 15 31 31+CFG_LEN-1 length-1 | ||
806 | * | CFG_ID | CFG_LEN | CFG_BODY | CFG_ID |......| | ||
807 | */ | ||
808 | } __packed; | ||
809 | |||
810 | struct wcn36xx_hal_mac_start_req_msg { | ||
811 | /* config buffer must start in TLV format just here */ | ||
812 | struct wcn36xx_hal_msg_header header; | ||
813 | struct wcn36xx_hal_mac_start_parameters params; | ||
814 | } __packed; | ||
815 | |||
816 | struct wcn36xx_hal_mac_start_rsp_params { | ||
817 | /* success or failure */ | ||
818 | u16 status; | ||
819 | |||
820 | /* Max number of STA supported by the device */ | ||
821 | u8 stations; | ||
822 | |||
823 | /* Max number of BSS supported by the device */ | ||
824 | u8 bssids; | ||
825 | |||
826 | /* API Version */ | ||
827 | struct wcnss_wlan_version version; | ||
828 | |||
829 | /* CRM build information */ | ||
830 | u8 crm_version[WCN36XX_HAL_VERSION_LENGTH]; | ||
831 | |||
832 | /* hardware/chipset/misc version information */ | ||
833 | u8 wlan_version[WCN36XX_HAL_VERSION_LENGTH]; | ||
834 | |||
835 | } __packed; | ||
836 | |||
837 | struct wcn36xx_hal_mac_start_rsp_msg { | ||
838 | struct wcn36xx_hal_msg_header header; | ||
839 | struct wcn36xx_hal_mac_start_rsp_params start_rsp_params; | ||
840 | } __packed; | ||
841 | |||
842 | struct wcn36xx_hal_mac_stop_req_params { | ||
843 | /* The reason for which the device is being stopped */ | ||
844 | enum wcn36xx_hal_stop_type reason; | ||
845 | |||
846 | } __packed; | ||
847 | |||
848 | struct wcn36xx_hal_mac_stop_req_msg { | ||
849 | struct wcn36xx_hal_msg_header header; | ||
850 | struct wcn36xx_hal_mac_stop_req_params stop_req_params; | ||
851 | } __packed; | ||
852 | |||
853 | struct wcn36xx_hal_mac_stop_rsp_msg { | ||
854 | struct wcn36xx_hal_msg_header header; | ||
855 | |||
856 | /* success or failure */ | ||
857 | u32 status; | ||
858 | } __packed; | ||
859 | |||
860 | struct wcn36xx_hal_update_cfg_req_msg { | ||
861 | /* | ||
862 | * Note: The length specified in tHalUpdateCfgReqMsg messages should be | ||
863 | * header.msgLen = sizeof(tHalUpdateCfgReqMsg) + uConfigBufferLen | ||
864 | */ | ||
865 | struct wcn36xx_hal_msg_header header; | ||
866 | |||
867 | /* Length of the config buffer. Allows UMAC to update multiple CFGs */ | ||
868 | u32 len; | ||
869 | |||
870 | /* | ||
871 | * Following this there is a TLV formatted buffer of length | ||
872 | * "uConfigBufferLen" bytes containing all config values. | ||
873 | * The TLV is expected to be formatted like this: | ||
874 | * 0 15 31 31+CFG_LEN-1 length-1 | ||
875 | * | CFG_ID | CFG_LEN | CFG_BODY | CFG_ID |......| | ||
876 | */ | ||
877 | |||
878 | } __packed; | ||
879 | |||
880 | struct wcn36xx_hal_update_cfg_rsp_msg { | ||
881 | struct wcn36xx_hal_msg_header header; | ||
882 | |||
883 | /* success or failure */ | ||
884 | u32 status; | ||
885 | |||
886 | } __packed; | ||
887 | |||
888 | /* Frame control field format (2 bytes) */ | ||
889 | struct wcn36xx_hal_mac_frame_ctl { | ||
890 | |||
891 | #ifndef ANI_LITTLE_BIT_ENDIAN | ||
892 | |||
893 | u8 subType:4; | ||
894 | u8 type:2; | ||
895 | u8 protVer:2; | ||
896 | |||
897 | u8 order:1; | ||
898 | u8 wep:1; | ||
899 | u8 moreData:1; | ||
900 | u8 powerMgmt:1; | ||
901 | u8 retry:1; | ||
902 | u8 moreFrag:1; | ||
903 | u8 fromDS:1; | ||
904 | u8 toDS:1; | ||
905 | |||
906 | #else | ||
907 | |||
908 | u8 protVer:2; | ||
909 | u8 type:2; | ||
910 | u8 subType:4; | ||
911 | |||
912 | u8 toDS:1; | ||
913 | u8 fromDS:1; | ||
914 | u8 moreFrag:1; | ||
915 | u8 retry:1; | ||
916 | u8 powerMgmt:1; | ||
917 | u8 moreData:1; | ||
918 | u8 wep:1; | ||
919 | u8 order:1; | ||
920 | |||
921 | #endif | ||
922 | |||
923 | }; | ||
924 | |||
925 | /* Sequence control field */ | ||
926 | struct wcn36xx_hal_mac_seq_ctl { | ||
927 | u8 fragNum:4; | ||
928 | u8 seqNumLo:4; | ||
929 | u8 seqNumHi:8; | ||
930 | }; | ||
931 | |||
932 | /* Management header format */ | ||
933 | struct wcn36xx_hal_mac_mgmt_hdr { | ||
934 | struct wcn36xx_hal_mac_frame_ctl fc; | ||
935 | u8 durationLo; | ||
936 | u8 durationHi; | ||
937 | u8 da[6]; | ||
938 | u8 sa[6]; | ||
939 | u8 bssId[6]; | ||
940 | struct wcn36xx_hal_mac_seq_ctl seqControl; | ||
941 | }; | ||
942 | |||
943 | /* FIXME: pronto v1 apparently has 4 */ | ||
944 | #define WCN36XX_HAL_NUM_BSSID 2 | ||
945 | |||
946 | /* Scan Entry to hold active BSS idx's */ | ||
947 | struct wcn36xx_hal_scan_entry { | ||
948 | u8 bss_index[WCN36XX_HAL_NUM_BSSID]; | ||
949 | u8 active_bss_count; | ||
950 | }; | ||
951 | |||
952 | struct wcn36xx_hal_init_scan_req_msg { | ||
953 | struct wcn36xx_hal_msg_header header; | ||
954 | |||
955 | /* LEARN - AP Role | ||
956 | SCAN - STA Role */ | ||
957 | enum wcn36xx_hal_sys_mode mode; | ||
958 | |||
959 | /* BSSID of the BSS */ | ||
960 | u8 bssid[ETH_ALEN]; | ||
961 | |||
962 | /* Whether BSS needs to be notified */ | ||
963 | u8 notify; | ||
964 | |||
965 | /* Kind of frame to be used for notifying the BSS (Data Null, QoS | ||
966 | * Null, or CTS to Self). Must always be a valid frame type. */ | ||
967 | u8 frame_type; | ||
968 | |||
969 | /* UMAC has the option of passing the MAC frame to be used for | ||
970 | * notifying the BSS. If non-zero, HAL will use the MAC frame | ||
971 | * buffer pointed to by macMgmtHdr. If zero, HAL will generate the | ||
972 | * appropriate MAC frame based on frameType. */ | ||
973 | u8 frame_len; | ||
974 | |||
975 | /* Following the framelength there is a MAC frame buffer if | ||
976 | * frameLength is non-zero. */ | ||
977 | struct wcn36xx_hal_mac_mgmt_hdr mac_mgmt_hdr; | ||
978 | |||
979 | /* Entry to hold number of active BSS idx's */ | ||
980 | struct wcn36xx_hal_scan_entry scan_entry; | ||
981 | }; | ||
982 | |||
983 | struct wcn36xx_hal_init_scan_con_req_msg { | ||
984 | struct wcn36xx_hal_msg_header header; | ||
985 | |||
986 | /* LEARN - AP Role | ||
987 | SCAN - STA Role */ | ||
988 | enum wcn36xx_hal_sys_mode mode; | ||
989 | |||
990 | /* BSSID of the BSS */ | ||
991 | u8 bssid[ETH_ALEN]; | ||
992 | |||
993 | /* Whether BSS needs to be notified */ | ||
994 | u8 notify; | ||
995 | |||
996 | /* Kind of frame to be used for notifying the BSS (Data Null, QoS | ||
997 | * Null, or CTS to Self). Must always be a valid frame type. */ | ||
998 | u8 frame_type; | ||
999 | |||
1000 | /* UMAC has the option of passing the MAC frame to be used for | ||
1001 | * notifying the BSS. If non-zero, HAL will use the MAC frame | ||
1002 | * buffer pointed to by macMgmtHdr. If zero, HAL will generate the | ||
1003 | * appropriate MAC frame based on frameType. */ | ||
1004 | u8 frame_length; | ||
1005 | |||
1006 | /* Following the framelength there is a MAC frame buffer if | ||
1007 | * frameLength is non-zero. */ | ||
1008 | struct wcn36xx_hal_mac_mgmt_hdr mac_mgmt_hdr; | ||
1009 | |||
1010 | /* Entry to hold number of active BSS idx's */ | ||
1011 | struct wcn36xx_hal_scan_entry scan_entry; | ||
1012 | |||
1013 | /* Single NoA usage in Scanning */ | ||
1014 | u8 use_noa; | ||
1015 | |||
1016 | /* Indicates the scan duration (in ms) */ | ||
1017 | u16 scan_duration; | ||
1018 | |||
1019 | }; | ||
1020 | |||
1021 | struct wcn36xx_hal_init_scan_rsp_msg { | ||
1022 | struct wcn36xx_hal_msg_header header; | ||
1023 | |||
1024 | /* success or failure */ | ||
1025 | u32 status; | ||
1026 | |||
1027 | } __packed; | ||
1028 | |||
1029 | struct wcn36xx_hal_start_scan_req_msg { | ||
1030 | struct wcn36xx_hal_msg_header header; | ||
1031 | |||
1032 | /* Indicates the channel to scan */ | ||
1033 | u8 scan_channel; | ||
1034 | } __packed; | ||
1035 | |||
1036 | struct wcn36xx_hal_start_rsp_msg { | ||
1037 | struct wcn36xx_hal_msg_header header; | ||
1038 | |||
1039 | /* success or failure */ | ||
1040 | u32 status; | ||
1041 | |||
1042 | u32 start_tsf[2]; | ||
1043 | u8 tx_mgmt_power; | ||
1044 | |||
1045 | } __packed; | ||
1046 | |||
1047 | struct wcn36xx_hal_end_scan_req_msg { | ||
1048 | struct wcn36xx_hal_msg_header header; | ||
1049 | |||
1050 | /* Indicates the channel to stop scanning. Not used really. But | ||
1051 | * retained for symmetry with "start Scan" message. It can also | ||
1052 | * help in error check if needed. */ | ||
1053 | u8 scan_channel; | ||
1054 | } __packed; | ||
1055 | |||
1056 | struct wcn36xx_hal_end_scan_rsp_msg { | ||
1057 | struct wcn36xx_hal_msg_header header; | ||
1058 | |||
1059 | /* success or failure */ | ||
1060 | u32 status; | ||
1061 | } __packed; | ||
1062 | |||
1063 | struct wcn36xx_hal_finish_scan_req_msg { | ||
1064 | struct wcn36xx_hal_msg_header header; | ||
1065 | |||
1066 | /* Identifies the operational state of the AP/STA | ||
1067 | * LEARN - AP Role SCAN - STA Role */ | ||
1068 | enum wcn36xx_hal_sys_mode mode; | ||
1069 | |||
1070 | /* Operating channel to tune to. */ | ||
1071 | u8 oper_channel; | ||
1072 | |||
1073 | /* Channel Bonding state If 20/40 MHz is operational, this will | ||
1074 | * indicate the 40 MHz extension channel in combination with the | ||
1075 | * control channel */ | ||
1076 | enum phy_chan_bond_state cb_state; | ||
1077 | |||
1078 | /* BSSID of the BSS */ | ||
1079 | u8 bssid[ETH_ALEN]; | ||
1080 | |||
1081 | /* Whether BSS needs to be notified */ | ||
1082 | u8 notify; | ||
1083 | |||
1084 | /* Kind of frame to be used for notifying the BSS (Data Null, QoS | ||
1085 | * Null, or CTS to Self). Must always be a valid frame type. */ | ||
1086 | u8 frame_type; | ||
1087 | |||
1088 | /* UMAC has the option of passing the MAC frame to be used for | ||
1089 | * notifying the BSS. If non-zero, HAL will use the MAC frame | ||
1090 | * buffer pointed to by macMgmtHdr. If zero, HAL will generate the | ||
1091 | * appropriate MAC frame based on frameType. */ | ||
1092 | u8 frame_length; | ||
1093 | |||
1094 | /* Following the framelength there is a MAC frame buffer if | ||
1095 | * frameLength is non-zero. */ | ||
1096 | struct wcn36xx_hal_mac_mgmt_hdr mac_mgmt_hdr; | ||
1097 | |||
1098 | /* Entry to hold number of active BSS idx's */ | ||
1099 | struct wcn36xx_hal_scan_entry scan_entry; | ||
1100 | |||
1101 | } __packed; | ||
1102 | |||
1103 | struct wcn36xx_hal_finish_scan_rsp_msg { | ||
1104 | struct wcn36xx_hal_msg_header header; | ||
1105 | |||
1106 | /* success or failure */ | ||
1107 | u32 status; | ||
1108 | |||
1109 | } __packed; | ||
1110 | |||
1111 | enum wcn36xx_hal_rate_index { | ||
1112 | HW_RATE_INDEX_1MBPS = 0x82, | ||
1113 | HW_RATE_INDEX_2MBPS = 0x84, | ||
1114 | HW_RATE_INDEX_5_5MBPS = 0x8B, | ||
1115 | HW_RATE_INDEX_6MBPS = 0x0C, | ||
1116 | HW_RATE_INDEX_9MBPS = 0x12, | ||
1117 | HW_RATE_INDEX_11MBPS = 0x96, | ||
1118 | HW_RATE_INDEX_12MBPS = 0x18, | ||
1119 | HW_RATE_INDEX_18MBPS = 0x24, | ||
1120 | HW_RATE_INDEX_24MBPS = 0x30, | ||
1121 | HW_RATE_INDEX_36MBPS = 0x48, | ||
1122 | HW_RATE_INDEX_48MBPS = 0x60, | ||
1123 | HW_RATE_INDEX_54MBPS = 0x6C | ||
1124 | }; | ||
1125 | |||
1126 | struct wcn36xx_hal_supported_rates { | ||
1127 | /* | ||
1128 | * For Self STA Entry: this represents Self Mode. | ||
1129 | * For Peer Stations, this represents the mode of the peer. | ||
1130 | * On Station: | ||
1131 | * | ||
1132 | * --this mode is updated when PE adds the Self Entry. | ||
1133 | * | ||
1134 | * -- OR when PE sends 'ADD_BSS' message and station context in BSS | ||
1135 | * is used to indicate the mode of the AP. | ||
1136 | * | ||
1137 | * ON AP: | ||
1138 | * | ||
1139 | * -- this mode is updated when PE sends 'ADD_BSS' and Sta entry | ||
1140 | * for that BSS is used to indicate the self mode of the AP. | ||
1141 | * | ||
1142 | * -- OR when a station is associated, PE sends 'ADD_STA' message | ||
1143 | * with this mode updated. | ||
1144 | */ | ||
1145 | |||
1146 | enum sta_rate_mode op_rate_mode; | ||
1147 | |||
1148 | /* 11b, 11a and aniLegacyRates are IE rates which gives rate in | ||
1149 | * unit of 500Kbps */ | ||
1150 | u16 dsss_rates[WCN36XX_HAL_NUM_DSSS_RATES]; | ||
1151 | u16 ofdm_rates[WCN36XX_HAL_NUM_OFDM_RATES]; | ||
1152 | u16 legacy_rates[WCN36XX_HAL_NUM_POLARIS_RATES]; | ||
1153 | u16 reserved; | ||
1154 | |||
1155 | /* Taurus only supports 26 Titan Rates(no ESF/concat Rates will be | ||
1156 | * supported) First 26 bits are reserved for those Titan rates and | ||
1157 | * the last 4 bits(bit28-31) for Taurus, 2(bit26-27) bits are | ||
1158 | * reserved. */ | ||
1159 | /* Titan and Taurus Rates */ | ||
1160 | u32 enhanced_rate_bitmap; | ||
1161 | |||
1162 | /* | ||
1163 | * 0-76 bits used, remaining reserved | ||
1164 | * bits 0-15 and 32 should be set. | ||
1165 | */ | ||
1166 | u8 supported_mcs_set[WCN36XX_HAL_MAC_MAX_SUPPORTED_MCS_SET]; | ||
1167 | |||
1168 | /* | ||
1169 | * RX Highest Supported Data Rate defines the highest data | ||
1170 | * rate that the STA is able to receive, in unites of 1Mbps. | ||
1171 | * This value is derived from "Supported MCS Set field" inside | ||
1172 | * the HT capability element. | ||
1173 | */ | ||
1174 | u16 rx_highest_data_rate; | ||
1175 | |||
1176 | } __packed; | ||
1177 | |||
1178 | struct wcn36xx_hal_config_sta_params { | ||
1179 | /* BSSID of STA */ | ||
1180 | u8 bssid[ETH_ALEN]; | ||
1181 | |||
1182 | /* ASSOC ID, as assigned by UMAC */ | ||
1183 | u16 aid; | ||
1184 | |||
1185 | /* STA entry Type: 0 - Self, 1 - Other/Peer, 2 - BSSID, 3 - BCAST */ | ||
1186 | u8 type; | ||
1187 | |||
1188 | /* Short Preamble Supported. */ | ||
1189 | u8 short_preamble_supported; | ||
1190 | |||
1191 | /* MAC Address of STA */ | ||
1192 | u8 mac[ETH_ALEN]; | ||
1193 | |||
1194 | /* Listen interval of the STA */ | ||
1195 | u16 listen_interval; | ||
1196 | |||
1197 | /* Support for 11e/WMM */ | ||
1198 | u8 wmm_enabled; | ||
1199 | |||
1200 | /* 11n HT capable STA */ | ||
1201 | u8 ht_capable; | ||
1202 | |||
1203 | /* TX Width Set: 0 - 20 MHz only, 1 - 20/40 MHz */ | ||
1204 | u8 tx_channel_width_set; | ||
1205 | |||
1206 | /* RIFS mode 0 - NA, 1 - Allowed */ | ||
1207 | u8 rifs_mode; | ||
1208 | |||
1209 | /* L-SIG TXOP Protection mechanism | ||
1210 | 0 - No Support, 1 - Supported | ||
1211 | SG - there is global field */ | ||
1212 | u8 lsig_txop_protection; | ||
1213 | |||
1214 | /* Max Ampdu Size supported by STA. TPE programming. | ||
1215 | 0 : 8k , 1 : 16k, 2 : 32k, 3 : 64k */ | ||
1216 | u8 max_ampdu_size; | ||
1217 | |||
1218 | /* Max Ampdu density. Used by RA. 3 : 0~7 : 2^(11nAMPDUdensity -4) */ | ||
1219 | u8 max_ampdu_density; | ||
1220 | |||
1221 | /* Max AMSDU size 1 : 3839 bytes, 0 : 7935 bytes */ | ||
1222 | u8 max_amsdu_size; | ||
1223 | |||
1224 | /* Short GI support for 40Mhz packets */ | ||
1225 | u8 sgi_40mhz; | ||
1226 | |||
1227 | /* Short GI support for 20Mhz packets */ | ||
1228 | u8 sgi_20Mhz; | ||
1229 | |||
1230 | /* TODO move this parameter to the end for 3680 */ | ||
1231 | /* These rates are the intersection of peer and self capabilities. */ | ||
1232 | struct wcn36xx_hal_supported_rates supported_rates; | ||
1233 | |||
1234 | /* Robust Management Frame (RMF) enabled/disabled */ | ||
1235 | u8 rmf; | ||
1236 | |||
1237 | /* The unicast encryption type in the association */ | ||
1238 | u32 encrypt_type; | ||
1239 | |||
1240 | /* HAL should update the existing STA entry, if this flag is set. UMAC | ||
1241 | will set this flag in case of RE-ASSOC, where we want to reuse the | ||
1242 | old STA ID. 0 = Add, 1 = Update */ | ||
1243 | u8 action; | ||
1244 | |||
1245 | /* U-APSD Flags: 1b per AC. Encoded as follows: | ||
1246 | b7 b6 b5 b4 b3 b2 b1 b0 = | ||
1247 | X X X X BE BK VI VO */ | ||
1248 | u8 uapsd; | ||
1249 | |||
1250 | /* Max SP Length */ | ||
1251 | u8 max_sp_len; | ||
1252 | |||
1253 | /* 11n Green Field preamble support | ||
1254 | 0 - Not supported, 1 - Supported */ | ||
1255 | u8 green_field_capable; | ||
1256 | |||
1257 | /* MIMO Power Save mode */ | ||
1258 | enum wcn36xx_hal_ht_mimo_state mimo_ps; | ||
1259 | |||
1260 | /* Delayed BA Support */ | ||
1261 | u8 delayed_ba_support; | ||
1262 | |||
1263 | /* Max AMPDU duration in 32us */ | ||
1264 | u8 max_ampdu_duration; | ||
1265 | |||
1266 | /* HT STA should set it to 1 if it is enabled in BSS. HT STA should | ||
1267 | * set it to 0 if AP does not support it. This indication is sent | ||
1268 | * to HAL and HAL uses this flag to pickup up appropriate 40Mhz | ||
1269 | * rates. */ | ||
1270 | u8 dsss_cck_mode_40mhz; | ||
1271 | |||
1272 | /* Valid STA Idx when action=Update. Set to 0xFF when invalid! | ||
1273 | * Retained for backward compalibity with existing HAL code */ | ||
1274 | u8 sta_index; | ||
1275 | |||
1276 | /* BSSID of BSS to which station is associated. Set to 0xFF when | ||
1277 | * invalid. Retained for backward compalibity with existing HAL | ||
1278 | * code */ | ||
1279 | u8 bssid_index; | ||
1280 | |||
1281 | u8 p2p; | ||
1282 | |||
1283 | /* TODO add this parameter for 3680. */ | ||
1284 | /* Reserved to align next field on a dword boundary */ | ||
1285 | /* u8 reserved; */ | ||
1286 | } __packed; | ||
1287 | |||
1288 | struct wcn36xx_hal_config_sta_req_msg { | ||
1289 | struct wcn36xx_hal_msg_header header; | ||
1290 | struct wcn36xx_hal_config_sta_params sta_params; | ||
1291 | } __packed; | ||
1292 | |||
1293 | struct wcn36xx_hal_config_sta_params_v1 { | ||
1294 | /* BSSID of STA */ | ||
1295 | u8 bssid[ETH_ALEN]; | ||
1296 | |||
1297 | /* ASSOC ID, as assigned by UMAC */ | ||
1298 | u16 aid; | ||
1299 | |||
1300 | /* STA entry Type: 0 - Self, 1 - Other/Peer, 2 - BSSID, 3 - BCAST */ | ||
1301 | u8 type; | ||
1302 | |||
1303 | /* Short Preamble Supported. */ | ||
1304 | u8 short_preamble_supported; | ||
1305 | |||
1306 | /* MAC Address of STA */ | ||
1307 | u8 mac[ETH_ALEN]; | ||
1308 | |||
1309 | /* Listen interval of the STA */ | ||
1310 | u16 listen_interval; | ||
1311 | |||
1312 | /* Support for 11e/WMM */ | ||
1313 | u8 wmm_enabled; | ||
1314 | |||
1315 | /* 11n HT capable STA */ | ||
1316 | u8 ht_capable; | ||
1317 | |||
1318 | /* TX Width Set: 0 - 20 MHz only, 1 - 20/40 MHz */ | ||
1319 | u8 tx_channel_width_set; | ||
1320 | |||
1321 | /* RIFS mode 0 - NA, 1 - Allowed */ | ||
1322 | u8 rifs_mode; | ||
1323 | |||
1324 | /* L-SIG TXOP Protection mechanism | ||
1325 | 0 - No Support, 1 - Supported | ||
1326 | SG - there is global field */ | ||
1327 | u8 lsig_txop_protection; | ||
1328 | |||
1329 | /* Max Ampdu Size supported by STA. TPE programming. | ||
1330 | 0 : 8k , 1 : 16k, 2 : 32k, 3 : 64k */ | ||
1331 | u8 max_ampdu_size; | ||
1332 | |||
1333 | /* Max Ampdu density. Used by RA. 3 : 0~7 : 2^(11nAMPDUdensity -4) */ | ||
1334 | u8 max_ampdu_density; | ||
1335 | |||
1336 | /* Max AMSDU size 1 : 3839 bytes, 0 : 7935 bytes */ | ||
1337 | u8 max_amsdu_size; | ||
1338 | |||
1339 | /* Short GI support for 40Mhz packets */ | ||
1340 | u8 sgi_40mhz; | ||
1341 | |||
1342 | /* Short GI support for 20Mhz packets */ | ||
1343 | u8 sgi_20Mhz; | ||
1344 | |||
1345 | /* Robust Management Frame (RMF) enabled/disabled */ | ||
1346 | u8 rmf; | ||
1347 | |||
1348 | /* The unicast encryption type in the association */ | ||
1349 | u32 encrypt_type; | ||
1350 | |||
1351 | /* HAL should update the existing STA entry, if this flag is set. UMAC | ||
1352 | will set this flag in case of RE-ASSOC, where we want to reuse the | ||
1353 | old STA ID. 0 = Add, 1 = Update */ | ||
1354 | u8 action; | ||
1355 | |||
1356 | /* U-APSD Flags: 1b per AC. Encoded as follows: | ||
1357 | b7 b6 b5 b4 b3 b2 b1 b0 = | ||
1358 | X X X X BE BK VI VO */ | ||
1359 | u8 uapsd; | ||
1360 | |||
1361 | /* Max SP Length */ | ||
1362 | u8 max_sp_len; | ||
1363 | |||
1364 | /* 11n Green Field preamble support | ||
1365 | 0 - Not supported, 1 - Supported */ | ||
1366 | u8 green_field_capable; | ||
1367 | |||
1368 | /* MIMO Power Save mode */ | ||
1369 | enum wcn36xx_hal_ht_mimo_state mimo_ps; | ||
1370 | |||
1371 | /* Delayed BA Support */ | ||
1372 | u8 delayed_ba_support; | ||
1373 | |||
1374 | /* Max AMPDU duration in 32us */ | ||
1375 | u8 max_ampdu_duration; | ||
1376 | |||
1377 | /* HT STA should set it to 1 if it is enabled in BSS. HT STA should | ||
1378 | * set it to 0 if AP does not support it. This indication is sent | ||
1379 | * to HAL and HAL uses this flag to pickup up appropriate 40Mhz | ||
1380 | * rates. */ | ||
1381 | u8 dsss_cck_mode_40mhz; | ||
1382 | |||
1383 | /* Valid STA Idx when action=Update. Set to 0xFF when invalid! | ||
1384 | * Retained for backward compalibity with existing HAL code */ | ||
1385 | u8 sta_index; | ||
1386 | |||
1387 | /* BSSID of BSS to which station is associated. Set to 0xFF when | ||
1388 | * invalid. Retained for backward compalibity with existing HAL | ||
1389 | * code */ | ||
1390 | u8 bssid_index; | ||
1391 | |||
1392 | u8 p2p; | ||
1393 | |||
1394 | /* Reserved to align next field on a dword boundary */ | ||
1395 | u8 reserved; | ||
1396 | |||
1397 | /* These rates are the intersection of peer and self capabilities. */ | ||
1398 | struct wcn36xx_hal_supported_rates supported_rates; | ||
1399 | } __packed; | ||
1400 | |||
1401 | struct wcn36xx_hal_config_sta_req_msg_v1 { | ||
1402 | struct wcn36xx_hal_msg_header header; | ||
1403 | struct wcn36xx_hal_config_sta_params_v1 sta_params; | ||
1404 | } __packed; | ||
1405 | |||
1406 | struct config_sta_rsp_params { | ||
1407 | /* success or failure */ | ||
1408 | u32 status; | ||
1409 | |||
1410 | /* Station index; valid only when 'status' field value SUCCESS */ | ||
1411 | u8 sta_index; | ||
1412 | |||
1413 | /* BSSID Index of BSS to which the station is associated */ | ||
1414 | u8 bssid_index; | ||
1415 | |||
1416 | /* DPU Index for PTK */ | ||
1417 | u8 dpu_index; | ||
1418 | |||
1419 | /* DPU Index for GTK */ | ||
1420 | u8 bcast_dpu_index; | ||
1421 | |||
1422 | /* DPU Index for IGTK */ | ||
1423 | u8 bcast_mgmt_dpu_idx; | ||
1424 | |||
1425 | /* PTK DPU signature */ | ||
1426 | u8 uc_ucast_sig; | ||
1427 | |||
1428 | /* GTK DPU isignature */ | ||
1429 | u8 uc_bcast_sig; | ||
1430 | |||
1431 | /* IGTK DPU signature */ | ||
1432 | u8 uc_mgmt_sig; | ||
1433 | |||
1434 | u8 p2p; | ||
1435 | |||
1436 | } __packed; | ||
1437 | |||
1438 | struct wcn36xx_hal_config_sta_rsp_msg { | ||
1439 | struct wcn36xx_hal_msg_header header; | ||
1440 | |||
1441 | struct config_sta_rsp_params params; | ||
1442 | } __packed; | ||
1443 | |||
1444 | /* Delete STA Request message */ | ||
1445 | struct wcn36xx_hal_delete_sta_req_msg { | ||
1446 | struct wcn36xx_hal_msg_header header; | ||
1447 | |||
1448 | /* Index of STA to delete */ | ||
1449 | u8 sta_index; | ||
1450 | |||
1451 | } __packed; | ||
1452 | |||
1453 | /* Delete STA Response message */ | ||
1454 | struct wcn36xx_hal_delete_sta_rsp_msg { | ||
1455 | struct wcn36xx_hal_msg_header header; | ||
1456 | |||
1457 | /* success or failure */ | ||
1458 | u32 status; | ||
1459 | |||
1460 | /* Index of STA deleted */ | ||
1461 | u8 sta_id; | ||
1462 | } __packed; | ||
1463 | |||
1464 | /* 12 Bytes long because this structure can be used to represent rate and | ||
1465 | * extended rate set IEs. The parser assume this to be at least 12 */ | ||
1466 | struct wcn36xx_hal_rate_set { | ||
1467 | u8 num_rates; | ||
1468 | u8 rate[WCN36XX_HAL_MAC_RATESET_EID_MAX]; | ||
1469 | } __packed; | ||
1470 | |||
1471 | /* access category record */ | ||
1472 | struct wcn36xx_hal_aci_aifsn { | ||
1473 | #ifndef ANI_LITTLE_BIT_ENDIAN | ||
1474 | u8 rsvd:1; | ||
1475 | u8 aci:2; | ||
1476 | u8 acm:1; | ||
1477 | u8 aifsn:4; | ||
1478 | #else | ||
1479 | u8 aifsn:4; | ||
1480 | u8 acm:1; | ||
1481 | u8 aci:2; | ||
1482 | u8 rsvd:1; | ||
1483 | #endif | ||
1484 | } __packed; | ||
1485 | |||
1486 | /* contention window size */ | ||
1487 | struct wcn36xx_hal_mac_cw { | ||
1488 | #ifndef ANI_LITTLE_BIT_ENDIAN | ||
1489 | u8 max:4; | ||
1490 | u8 min:4; | ||
1491 | #else | ||
1492 | u8 min:4; | ||
1493 | u8 max:4; | ||
1494 | #endif | ||
1495 | } __packed; | ||
1496 | |||
1497 | struct wcn36xx_hal_edca_param_record { | ||
1498 | struct wcn36xx_hal_aci_aifsn aci; | ||
1499 | struct wcn36xx_hal_mac_cw cw; | ||
1500 | u16 txop_limit; | ||
1501 | } __packed; | ||
1502 | |||
1503 | struct wcn36xx_hal_mac_ssid { | ||
1504 | u8 length; | ||
1505 | u8 ssid[32]; | ||
1506 | } __packed; | ||
1507 | |||
1508 | /* Concurrency role. These are generic IDs that identify the various roles | ||
1509 | * in the software system. */ | ||
1510 | enum wcn36xx_hal_con_mode { | ||
1511 | WCN36XX_HAL_STA_MODE = 0, | ||
1512 | |||
1513 | /* to support softAp mode . This is misleading. | ||
1514 | It means AP MODE only. */ | ||
1515 | WCN36XX_HAL_STA_SAP_MODE = 1, | ||
1516 | |||
1517 | WCN36XX_HAL_P2P_CLIENT_MODE, | ||
1518 | WCN36XX_HAL_P2P_GO_MODE, | ||
1519 | WCN36XX_HAL_MONITOR_MODE, | ||
1520 | }; | ||
1521 | |||
1522 | /* This is a bit pattern to be set for each mode | ||
1523 | * bit 0 - sta mode | ||
1524 | * bit 1 - ap mode | ||
1525 | * bit 2 - p2p client mode | ||
1526 | * bit 3 - p2p go mode */ | ||
1527 | enum wcn36xx_hal_concurrency_mode { | ||
1528 | HAL_STA = 1, | ||
1529 | HAL_SAP = 2, | ||
1530 | |||
1531 | /* to support sta, softAp mode . This means STA+AP mode */ | ||
1532 | HAL_STA_SAP = 3, | ||
1533 | |||
1534 | HAL_P2P_CLIENT = 4, | ||
1535 | HAL_P2P_GO = 8, | ||
1536 | HAL_MAX_CONCURRENCY_PERSONA = 4 | ||
1537 | }; | ||
1538 | |||
1539 | struct wcn36xx_hal_config_bss_params { | ||
1540 | /* BSSID */ | ||
1541 | u8 bssid[ETH_ALEN]; | ||
1542 | |||
1543 | /* Self Mac Address */ | ||
1544 | u8 self_mac_addr[ETH_ALEN]; | ||
1545 | |||
1546 | /* BSS type */ | ||
1547 | enum wcn36xx_hal_bss_type bss_type; | ||
1548 | |||
1549 | /* Operational Mode: AP =0, STA = 1 */ | ||
1550 | u8 oper_mode; | ||
1551 | |||
1552 | /* Network Type */ | ||
1553 | enum wcn36xx_hal_nw_type nw_type; | ||
1554 | |||
1555 | /* Used to classify PURE_11G/11G_MIXED to program MTU */ | ||
1556 | u8 short_slot_time_supported; | ||
1557 | |||
1558 | /* Co-exist with 11a STA */ | ||
1559 | u8 lla_coexist; | ||
1560 | |||
1561 | /* Co-exist with 11b STA */ | ||
1562 | u8 llb_coexist; | ||
1563 | |||
1564 | /* Co-exist with 11g STA */ | ||
1565 | u8 llg_coexist; | ||
1566 | |||
1567 | /* Coexistence with 11n STA */ | ||
1568 | u8 ht20_coexist; | ||
1569 | |||
1570 | /* Non GF coexist flag */ | ||
1571 | u8 lln_non_gf_coexist; | ||
1572 | |||
1573 | /* TXOP protection support */ | ||
1574 | u8 lsig_tx_op_protection_full_support; | ||
1575 | |||
1576 | /* RIFS mode */ | ||
1577 | u8 rifs_mode; | ||
1578 | |||
1579 | /* Beacon Interval in TU */ | ||
1580 | u16 beacon_interval; | ||
1581 | |||
1582 | /* DTIM period */ | ||
1583 | u8 dtim_period; | ||
1584 | |||
1585 | /* TX Width Set: 0 - 20 MHz only, 1 - 20/40 MHz */ | ||
1586 | u8 tx_channel_width_set; | ||
1587 | |||
1588 | /* Operating channel */ | ||
1589 | u8 oper_channel; | ||
1590 | |||
1591 | /* Extension channel for channel bonding */ | ||
1592 | u8 ext_channel; | ||
1593 | |||
1594 | /* Reserved to align next field on a dword boundary */ | ||
1595 | u8 reserved; | ||
1596 | |||
1597 | /* TODO move sta to the end for 3680 */ | ||
1598 | /* Context of the station being added in HW | ||
1599 | * Add a STA entry for "itself" - | ||
1600 | * | ||
1601 | * On AP - Add the AP itself in an "STA context" | ||
1602 | * | ||
1603 | * On STA - Add the AP to which this STA is joining in an | ||
1604 | * "STA context" | ||
1605 | */ | ||
1606 | struct wcn36xx_hal_config_sta_params sta; | ||
1607 | /* SSID of the BSS */ | ||
1608 | struct wcn36xx_hal_mac_ssid ssid; | ||
1609 | |||
1610 | /* HAL should update the existing BSS entry, if this flag is set. | ||
1611 | * UMAC will set this flag in case of reassoc, where we want to | ||
1612 | * resue the the old BSSID and still return success 0 = Add, 1 = | ||
1613 | * Update */ | ||
1614 | u8 action; | ||
1615 | |||
1616 | /* MAC Rate Set */ | ||
1617 | struct wcn36xx_hal_rate_set rateset; | ||
1618 | |||
1619 | /* Enable/Disable HT capabilities of the BSS */ | ||
1620 | u8 ht; | ||
1621 | |||
1622 | /* Enable/Disable OBSS protection */ | ||
1623 | u8 obss_prot_enabled; | ||
1624 | |||
1625 | /* RMF enabled/disabled */ | ||
1626 | u8 rmf; | ||
1627 | |||
1628 | /* HT Operating Mode operating mode of the 802.11n STA */ | ||
1629 | enum wcn36xx_hal_ht_operating_mode ht_oper_mode; | ||
1630 | |||
1631 | /* Dual CTS Protection: 0 - Unused, 1 - Used */ | ||
1632 | u8 dual_cts_protection; | ||
1633 | |||
1634 | /* Probe Response Max retries */ | ||
1635 | u8 max_probe_resp_retry_limit; | ||
1636 | |||
1637 | /* To Enable Hidden ssid */ | ||
1638 | u8 hidden_ssid; | ||
1639 | |||
1640 | /* To Enable Disable FW Proxy Probe Resp */ | ||
1641 | u8 proxy_probe_resp; | ||
1642 | |||
1643 | /* Boolean to indicate if EDCA params are valid. UMAC might not | ||
1644 | * have valid EDCA params or might not desire to apply EDCA params | ||
1645 | * during config BSS. 0 implies Not Valid ; Non-Zero implies | ||
1646 | * valid */ | ||
1647 | u8 edca_params_valid; | ||
1648 | |||
1649 | /* EDCA Parameters for Best Effort Access Category */ | ||
1650 | struct wcn36xx_hal_edca_param_record acbe; | ||
1651 | |||
1652 | /* EDCA Parameters forBackground Access Category */ | ||
1653 | struct wcn36xx_hal_edca_param_record acbk; | ||
1654 | |||
1655 | /* EDCA Parameters for Video Access Category */ | ||
1656 | struct wcn36xx_hal_edca_param_record acvi; | ||
1657 | |||
1658 | /* EDCA Parameters for Voice Access Category */ | ||
1659 | struct wcn36xx_hal_edca_param_record acvo; | ||
1660 | |||
1661 | /* Ext Bss Config Msg if set */ | ||
1662 | u8 ext_set_sta_key_param_valid; | ||
1663 | |||
1664 | /* SetStaKeyParams for ext bss msg */ | ||
1665 | struct wcn36xx_hal_set_sta_key_params ext_set_sta_key_param; | ||
1666 | |||
1667 | /* Persona for the BSS can be STA,AP,GO,CLIENT value same as enum | ||
1668 | * wcn36xx_hal_con_mode */ | ||
1669 | u8 wcn36xx_hal_persona; | ||
1670 | |||
1671 | u8 spectrum_mgt_enable; | ||
1672 | |||
1673 | /* HAL fills in the tx power used for mgmt frames in txMgmtPower */ | ||
1674 | s8 tx_mgmt_power; | ||
1675 | |||
1676 | /* maxTxPower has max power to be used after applying the power | ||
1677 | * constraint if any */ | ||
1678 | s8 max_tx_power; | ||
1679 | } __packed; | ||
1680 | |||
1681 | struct wcn36xx_hal_config_bss_req_msg { | ||
1682 | struct wcn36xx_hal_msg_header header; | ||
1683 | struct wcn36xx_hal_config_bss_params bss_params; | ||
1684 | } __packed; | ||
1685 | |||
1686 | struct wcn36xx_hal_config_bss_params_v1 { | ||
1687 | /* BSSID */ | ||
1688 | u8 bssid[ETH_ALEN]; | ||
1689 | |||
1690 | /* Self Mac Address */ | ||
1691 | u8 self_mac_addr[ETH_ALEN]; | ||
1692 | |||
1693 | /* BSS type */ | ||
1694 | enum wcn36xx_hal_bss_type bss_type; | ||
1695 | |||
1696 | /* Operational Mode: AP =0, STA = 1 */ | ||
1697 | u8 oper_mode; | ||
1698 | |||
1699 | /* Network Type */ | ||
1700 | enum wcn36xx_hal_nw_type nw_type; | ||
1701 | |||
1702 | /* Used to classify PURE_11G/11G_MIXED to program MTU */ | ||
1703 | u8 short_slot_time_supported; | ||
1704 | |||
1705 | /* Co-exist with 11a STA */ | ||
1706 | u8 lla_coexist; | ||
1707 | |||
1708 | /* Co-exist with 11b STA */ | ||
1709 | u8 llb_coexist; | ||
1710 | |||
1711 | /* Co-exist with 11g STA */ | ||
1712 | u8 llg_coexist; | ||
1713 | |||
1714 | /* Coexistence with 11n STA */ | ||
1715 | u8 ht20_coexist; | ||
1716 | |||
1717 | /* Non GF coexist flag */ | ||
1718 | u8 lln_non_gf_coexist; | ||
1719 | |||
1720 | /* TXOP protection support */ | ||
1721 | u8 lsig_tx_op_protection_full_support; | ||
1722 | |||
1723 | /* RIFS mode */ | ||
1724 | u8 rifs_mode; | ||
1725 | |||
1726 | /* Beacon Interval in TU */ | ||
1727 | u16 beacon_interval; | ||
1728 | |||
1729 | /* DTIM period */ | ||
1730 | u8 dtim_period; | ||
1731 | |||
1732 | /* TX Width Set: 0 - 20 MHz only, 1 - 20/40 MHz */ | ||
1733 | u8 tx_channel_width_set; | ||
1734 | |||
1735 | /* Operating channel */ | ||
1736 | u8 oper_channel; | ||
1737 | |||
1738 | /* Extension channel for channel bonding */ | ||
1739 | u8 ext_channel; | ||
1740 | |||
1741 | /* Reserved to align next field on a dword boundary */ | ||
1742 | u8 reserved; | ||
1743 | |||
1744 | /* SSID of the BSS */ | ||
1745 | struct wcn36xx_hal_mac_ssid ssid; | ||
1746 | |||
1747 | /* HAL should update the existing BSS entry, if this flag is set. | ||
1748 | * UMAC will set this flag in case of reassoc, where we want to | ||
1749 | * resue the the old BSSID and still return success 0 = Add, 1 = | ||
1750 | * Update */ | ||
1751 | u8 action; | ||
1752 | |||
1753 | /* MAC Rate Set */ | ||
1754 | struct wcn36xx_hal_rate_set rateset; | ||
1755 | |||
1756 | /* Enable/Disable HT capabilities of the BSS */ | ||
1757 | u8 ht; | ||
1758 | |||
1759 | /* Enable/Disable OBSS protection */ | ||
1760 | u8 obss_prot_enabled; | ||
1761 | |||
1762 | /* RMF enabled/disabled */ | ||
1763 | u8 rmf; | ||
1764 | |||
1765 | /* HT Operating Mode operating mode of the 802.11n STA */ | ||
1766 | enum wcn36xx_hal_ht_operating_mode ht_oper_mode; | ||
1767 | |||
1768 | /* Dual CTS Protection: 0 - Unused, 1 - Used */ | ||
1769 | u8 dual_cts_protection; | ||
1770 | |||
1771 | /* Probe Response Max retries */ | ||
1772 | u8 max_probe_resp_retry_limit; | ||
1773 | |||
1774 | /* To Enable Hidden ssid */ | ||
1775 | u8 hidden_ssid; | ||
1776 | |||
1777 | /* To Enable Disable FW Proxy Probe Resp */ | ||
1778 | u8 proxy_probe_resp; | ||
1779 | |||
1780 | /* Boolean to indicate if EDCA params are valid. UMAC might not | ||
1781 | * have valid EDCA params or might not desire to apply EDCA params | ||
1782 | * during config BSS. 0 implies Not Valid ; Non-Zero implies | ||
1783 | * valid */ | ||
1784 | u8 edca_params_valid; | ||
1785 | |||
1786 | /* EDCA Parameters for Best Effort Access Category */ | ||
1787 | struct wcn36xx_hal_edca_param_record acbe; | ||
1788 | |||
1789 | /* EDCA Parameters forBackground Access Category */ | ||
1790 | struct wcn36xx_hal_edca_param_record acbk; | ||
1791 | |||
1792 | /* EDCA Parameters for Video Access Category */ | ||
1793 | struct wcn36xx_hal_edca_param_record acvi; | ||
1794 | |||
1795 | /* EDCA Parameters for Voice Access Category */ | ||
1796 | struct wcn36xx_hal_edca_param_record acvo; | ||
1797 | |||
1798 | /* Ext Bss Config Msg if set */ | ||
1799 | u8 ext_set_sta_key_param_valid; | ||
1800 | |||
1801 | /* SetStaKeyParams for ext bss msg */ | ||
1802 | struct wcn36xx_hal_set_sta_key_params ext_set_sta_key_param; | ||
1803 | |||
1804 | /* Persona for the BSS can be STA,AP,GO,CLIENT value same as enum | ||
1805 | * wcn36xx_hal_con_mode */ | ||
1806 | u8 wcn36xx_hal_persona; | ||
1807 | |||
1808 | u8 spectrum_mgt_enable; | ||
1809 | |||
1810 | /* HAL fills in the tx power used for mgmt frames in txMgmtPower */ | ||
1811 | s8 tx_mgmt_power; | ||
1812 | |||
1813 | /* maxTxPower has max power to be used after applying the power | ||
1814 | * constraint if any */ | ||
1815 | s8 max_tx_power; | ||
1816 | |||
1817 | /* Context of the station being added in HW | ||
1818 | * Add a STA entry for "itself" - | ||
1819 | * | ||
1820 | * On AP - Add the AP itself in an "STA context" | ||
1821 | * | ||
1822 | * On STA - Add the AP to which this STA is joining in an | ||
1823 | * "STA context" | ||
1824 | */ | ||
1825 | struct wcn36xx_hal_config_sta_params_v1 sta; | ||
1826 | } __packed; | ||
1827 | |||
1828 | struct wcn36xx_hal_config_bss_req_msg_v1 { | ||
1829 | struct wcn36xx_hal_msg_header header; | ||
1830 | struct wcn36xx_hal_config_bss_params_v1 bss_params; | ||
1831 | } __packed; | ||
1832 | |||
1833 | struct wcn36xx_hal_config_bss_rsp_params { | ||
1834 | /* Success or Failure */ | ||
1835 | u32 status; | ||
1836 | |||
1837 | /* BSS index allocated by HAL */ | ||
1838 | u8 bss_index; | ||
1839 | |||
1840 | /* DPU descriptor index for PTK */ | ||
1841 | u8 dpu_desc_index; | ||
1842 | |||
1843 | /* PTK DPU signature */ | ||
1844 | u8 ucast_dpu_signature; | ||
1845 | |||
1846 | /* DPU descriptor index for GTK */ | ||
1847 | u8 bcast_dpu_desc_indx; | ||
1848 | |||
1849 | /* GTK DPU signature */ | ||
1850 | u8 bcast_dpu_signature; | ||
1851 | |||
1852 | /* DPU descriptor for IGTK */ | ||
1853 | u8 mgmt_dpu_desc_index; | ||
1854 | |||
1855 | /* IGTK DPU signature */ | ||
1856 | u8 mgmt_dpu_signature; | ||
1857 | |||
1858 | /* Station Index for BSS entry */ | ||
1859 | u8 bss_sta_index; | ||
1860 | |||
1861 | /* Self station index for this BSS */ | ||
1862 | u8 bss_self_sta_index; | ||
1863 | |||
1864 | /* Bcast station for buffering bcast frames in AP role */ | ||
1865 | u8 bss_bcast_sta_idx; | ||
1866 | |||
1867 | /* MAC Address of STA(PEER/SELF) in staContext of configBSSReq */ | ||
1868 | u8 mac[ETH_ALEN]; | ||
1869 | |||
1870 | /* HAL fills in the tx power used for mgmt frames in this field. */ | ||
1871 | s8 tx_mgmt_power; | ||
1872 | |||
1873 | } __packed; | ||
1874 | |||
1875 | struct wcn36xx_hal_config_bss_rsp_msg { | ||
1876 | struct wcn36xx_hal_msg_header header; | ||
1877 | struct wcn36xx_hal_config_bss_rsp_params bss_rsp_params; | ||
1878 | } __packed; | ||
1879 | |||
1880 | struct wcn36xx_hal_delete_bss_req_msg { | ||
1881 | struct wcn36xx_hal_msg_header header; | ||
1882 | |||
1883 | /* BSS index to be deleted */ | ||
1884 | u8 bss_index; | ||
1885 | |||
1886 | } __packed; | ||
1887 | |||
1888 | struct wcn36xx_hal_delete_bss_rsp_msg { | ||
1889 | struct wcn36xx_hal_msg_header header; | ||
1890 | |||
1891 | /* Success or Failure */ | ||
1892 | u32 status; | ||
1893 | |||
1894 | /* BSS index that has been deleted */ | ||
1895 | u8 bss_index; | ||
1896 | |||
1897 | } __packed; | ||
1898 | |||
1899 | struct wcn36xx_hal_join_req_msg { | ||
1900 | struct wcn36xx_hal_msg_header header; | ||
1901 | |||
1902 | /* Indicates the BSSID to which STA is going to associate */ | ||
1903 | u8 bssid[ETH_ALEN]; | ||
1904 | |||
1905 | /* Indicates the channel to switch to. */ | ||
1906 | u8 channel; | ||
1907 | |||
1908 | /* Self STA MAC */ | ||
1909 | u8 self_sta_mac_addr[ETH_ALEN]; | ||
1910 | |||
1911 | /* Local power constraint */ | ||
1912 | u8 local_power_constraint; | ||
1913 | |||
1914 | /* Secondary channel offset */ | ||
1915 | enum phy_chan_bond_state secondary_channel_offset; | ||
1916 | |||
1917 | /* link State */ | ||
1918 | enum wcn36xx_hal_link_state link_state; | ||
1919 | |||
1920 | /* Max TX power */ | ||
1921 | s8 max_tx_power; | ||
1922 | } __packed; | ||
1923 | |||
1924 | struct wcn36xx_hal_join_rsp_msg { | ||
1925 | struct wcn36xx_hal_msg_header header; | ||
1926 | |||
1927 | /* success or failure */ | ||
1928 | u32 status; | ||
1929 | |||
1930 | /* HAL fills in the tx power used for mgmt frames in this field */ | ||
1931 | u8 tx_mgmt_power; | ||
1932 | } __packed; | ||
1933 | |||
1934 | struct post_assoc_req_msg { | ||
1935 | struct wcn36xx_hal_msg_header header; | ||
1936 | |||
1937 | struct wcn36xx_hal_config_sta_params sta_params; | ||
1938 | struct wcn36xx_hal_config_bss_params bss_params; | ||
1939 | }; | ||
1940 | |||
1941 | struct post_assoc_rsp_msg { | ||
1942 | struct wcn36xx_hal_msg_header header; | ||
1943 | struct config_sta_rsp_params sta_rsp_params; | ||
1944 | struct wcn36xx_hal_config_bss_rsp_params bss_rsp_params; | ||
1945 | }; | ||
1946 | |||
1947 | /* This is used to create a set of WEP keys for a given BSS. */ | ||
1948 | struct wcn36xx_hal_set_bss_key_req_msg { | ||
1949 | struct wcn36xx_hal_msg_header header; | ||
1950 | |||
1951 | /* BSS Index of the BSS */ | ||
1952 | u8 bss_idx; | ||
1953 | |||
1954 | /* Encryption Type used with peer */ | ||
1955 | enum ani_ed_type enc_type; | ||
1956 | |||
1957 | /* Number of keys */ | ||
1958 | u8 num_keys; | ||
1959 | |||
1960 | /* Array of keys. */ | ||
1961 | struct wcn36xx_hal_keys keys[WCN36XX_HAL_MAC_MAX_NUM_OF_DEFAULT_KEYS]; | ||
1962 | |||
1963 | /* Control for Replay Count, 1= Single TID based replay count on Tx | ||
1964 | * 0 = Per TID based replay count on TX */ | ||
1965 | u8 single_tid_rc; | ||
1966 | } __packed; | ||
1967 | |||
1968 | /* tagged version of set bss key */ | ||
1969 | struct wcn36xx_hal_set_bss_key_req_msg_tagged { | ||
1970 | struct wcn36xx_hal_set_bss_key_req_msg Msg; | ||
1971 | u32 tag; | ||
1972 | } __packed; | ||
1973 | |||
1974 | struct wcn36xx_hal_set_bss_key_rsp_msg { | ||
1975 | struct wcn36xx_hal_msg_header header; | ||
1976 | |||
1977 | /* success or failure */ | ||
1978 | u32 status; | ||
1979 | } __packed; | ||
1980 | |||
1981 | /* | ||
1982 | * This is used configure the key information on a given station. | ||
1983 | * When the sec_type is WEP40 or WEP104, the def_wep_idx is used to locate | ||
1984 | * a preconfigured key from a BSS the station assoicated with; otherwise | ||
1985 | * a new key descriptor is created based on the key field. | ||
1986 | */ | ||
1987 | struct wcn36xx_hal_set_sta_key_req_msg { | ||
1988 | struct wcn36xx_hal_msg_header header; | ||
1989 | struct wcn36xx_hal_set_sta_key_params set_sta_key_params; | ||
1990 | } __packed; | ||
1991 | |||
1992 | struct wcn36xx_hal_set_sta_key_rsp_msg { | ||
1993 | struct wcn36xx_hal_msg_header header; | ||
1994 | |||
1995 | /* success or failure */ | ||
1996 | u32 status; | ||
1997 | } __packed; | ||
1998 | |||
1999 | struct wcn36xx_hal_remove_bss_key_req_msg { | ||
2000 | struct wcn36xx_hal_msg_header header; | ||
2001 | |||
2002 | /* BSS Index of the BSS */ | ||
2003 | u8 bss_idx; | ||
2004 | |||
2005 | /* Encryption Type used with peer */ | ||
2006 | enum ani_ed_type enc_type; | ||
2007 | |||
2008 | /* Key Id */ | ||
2009 | u8 key_id; | ||
2010 | |||
2011 | /* STATIC/DYNAMIC. Used in Nullifying in Key Descriptors for | ||
2012 | * Static/Dynamic keys */ | ||
2013 | enum ani_wep_type wep_type; | ||
2014 | } __packed; | ||
2015 | |||
2016 | struct wcn36xx_hal_remove_bss_key_rsp_msg { | ||
2017 | struct wcn36xx_hal_msg_header header; | ||
2018 | |||
2019 | /* success or failure */ | ||
2020 | u32 status; | ||
2021 | } __packed; | ||
2022 | |||
2023 | /* | ||
2024 | * This is used by PE to Remove the key information on a given station. | ||
2025 | */ | ||
2026 | struct wcn36xx_hal_remove_sta_key_req_msg { | ||
2027 | struct wcn36xx_hal_msg_header header; | ||
2028 | |||
2029 | /* STA Index */ | ||
2030 | u16 sta_idx; | ||
2031 | |||
2032 | /* Encryption Type used with peer */ | ||
2033 | enum ani_ed_type enc_type; | ||
2034 | |||
2035 | /* Key Id */ | ||
2036 | u8 key_id; | ||
2037 | |||
2038 | /* Whether to invalidate the Broadcast key or Unicast key. In case | ||
2039 | * of WEP, the same key is used for both broadcast and unicast. */ | ||
2040 | u8 unicast; | ||
2041 | |||
2042 | } __packed; | ||
2043 | |||
2044 | struct wcn36xx_hal_remove_sta_key_rsp_msg { | ||
2045 | struct wcn36xx_hal_msg_header header; | ||
2046 | |||
2047 | /*success or failure */ | ||
2048 | u32 status; | ||
2049 | |||
2050 | } __packed; | ||
2051 | |||
2052 | #ifdef FEATURE_OEM_DATA_SUPPORT | ||
2053 | |||
2054 | #ifndef OEM_DATA_REQ_SIZE | ||
2055 | #define OEM_DATA_REQ_SIZE 134 | ||
2056 | #endif | ||
2057 | |||
2058 | #ifndef OEM_DATA_RSP_SIZE | ||
2059 | #define OEM_DATA_RSP_SIZE 1968 | ||
2060 | #endif | ||
2061 | |||
2062 | struct start_oem_data_req_msg { | ||
2063 | struct wcn36xx_hal_msg_header header; | ||
2064 | |||
2065 | u32 status; | ||
2066 | tSirMacAddr self_mac_addr; | ||
2067 | u8 oem_data_req[OEM_DATA_REQ_SIZE]; | ||
2068 | |||
2069 | }; | ||
2070 | |||
2071 | struct start_oem_data_rsp_msg { | ||
2072 | struct wcn36xx_hal_msg_header header; | ||
2073 | |||
2074 | u8 oem_data_rsp[OEM_DATA_RSP_SIZE]; | ||
2075 | }; | ||
2076 | |||
2077 | #endif | ||
2078 | |||
2079 | struct wcn36xx_hal_switch_channel_req_msg { | ||
2080 | struct wcn36xx_hal_msg_header header; | ||
2081 | |||
2082 | /* Channel number */ | ||
2083 | u8 channel_number; | ||
2084 | |||
2085 | /* Local power constraint */ | ||
2086 | u8 local_power_constraint; | ||
2087 | |||
2088 | /* Secondary channel offset */ | ||
2089 | enum phy_chan_bond_state secondary_channel_offset; | ||
2090 | |||
2091 | /* HAL fills in the tx power used for mgmt frames in this field. */ | ||
2092 | u8 tx_mgmt_power; | ||
2093 | |||
2094 | /* Max TX power */ | ||
2095 | u8 max_tx_power; | ||
2096 | |||
2097 | /* Self STA MAC */ | ||
2098 | u8 self_sta_mac_addr[ETH_ALEN]; | ||
2099 | |||
2100 | /* VO WIFI comment: BSSID needed to identify session. As the | ||
2101 | * request has power constraints, this should be applied only to | ||
2102 | * that session Since MTU timing and EDCA are sessionized, this | ||
2103 | * struct needs to be sessionized and bssid needs to be out of the | ||
2104 | * VOWifi feature flag V IMP: Keep bssId field at the end of this | ||
2105 | * msg. It is used to mantain backward compatbility by way of | ||
2106 | * ignoring if using new host/old FW or old host/new FW since it is | ||
2107 | * at the end of this struct | ||
2108 | */ | ||
2109 | u8 bssid[ETH_ALEN]; | ||
2110 | } __packed; | ||
2111 | |||
2112 | struct wcn36xx_hal_switch_channel_rsp_msg { | ||
2113 | struct wcn36xx_hal_msg_header header; | ||
2114 | |||
2115 | /* Status */ | ||
2116 | u32 status; | ||
2117 | |||
2118 | /* Channel number - same as in request */ | ||
2119 | u8 channel_number; | ||
2120 | |||
2121 | /* HAL fills in the tx power used for mgmt frames in this field */ | ||
2122 | u8 tx_mgmt_power; | ||
2123 | |||
2124 | /* BSSID needed to identify session - same as in request */ | ||
2125 | u8 bssid[ETH_ALEN]; | ||
2126 | |||
2127 | } __packed; | ||
2128 | |||
2129 | struct update_edca_params_req_msg { | ||
2130 | struct wcn36xx_hal_msg_header header; | ||
2131 | |||
2132 | /*BSS Index */ | ||
2133 | u16 bss_index; | ||
2134 | |||
2135 | /* Best Effort */ | ||
2136 | struct wcn36xx_hal_edca_param_record acbe; | ||
2137 | |||
2138 | /* Background */ | ||
2139 | struct wcn36xx_hal_edca_param_record acbk; | ||
2140 | |||
2141 | /* Video */ | ||
2142 | struct wcn36xx_hal_edca_param_record acvi; | ||
2143 | |||
2144 | /* Voice */ | ||
2145 | struct wcn36xx_hal_edca_param_record acvo; | ||
2146 | }; | ||
2147 | |||
2148 | struct update_edca_params_rsp_msg { | ||
2149 | struct wcn36xx_hal_msg_header header; | ||
2150 | |||
2151 | /* success or failure */ | ||
2152 | u32 status; | ||
2153 | }; | ||
2154 | |||
2155 | struct dpu_stats_params { | ||
2156 | /* Index of STA to which the statistics */ | ||
2157 | u16 sta_index; | ||
2158 | |||
2159 | /* Encryption mode */ | ||
2160 | u8 enc_mode; | ||
2161 | |||
2162 | /* status */ | ||
2163 | u32 status; | ||
2164 | |||
2165 | /* Statistics */ | ||
2166 | u32 send_blocks; | ||
2167 | u32 recv_blocks; | ||
2168 | u32 replays; | ||
2169 | u8 mic_error_cnt; | ||
2170 | u32 prot_excl_cnt; | ||
2171 | u16 format_err_cnt; | ||
2172 | u16 un_decryptable_cnt; | ||
2173 | u32 decrypt_err_cnt; | ||
2174 | u32 decrypt_ok_cnt; | ||
2175 | }; | ||
2176 | |||
2177 | struct wcn36xx_hal_stats_req_msg { | ||
2178 | struct wcn36xx_hal_msg_header header; | ||
2179 | |||
2180 | /* Valid STA Idx for per STA stats request */ | ||
2181 | u32 sta_id; | ||
2182 | |||
2183 | /* Categories of stats requested as specified in eHalStatsMask */ | ||
2184 | u32 stats_mask; | ||
2185 | }; | ||
2186 | |||
2187 | struct ani_summary_stats_info { | ||
2188 | /* Total number of packets(per AC) that were successfully | ||
2189 | * transmitted with retries */ | ||
2190 | u32 retry_cnt[4]; | ||
2191 | |||
2192 | /* The number of MSDU packets and MMPDU frames per AC that the | ||
2193 | * 802.11 station successfully transmitted after more than one | ||
2194 | * retransmission attempt */ | ||
2195 | u32 multiple_retry_cnt[4]; | ||
2196 | |||
2197 | /* Total number of packets(per AC) that were successfully | ||
2198 | * transmitted (with and without retries, including multi-cast, | ||
2199 | * broadcast) */ | ||
2200 | u32 tx_frm_cnt[4]; | ||
2201 | |||
2202 | /* Total number of packets that were successfully received (after | ||
2203 | * appropriate filter rules including multi-cast, broadcast) */ | ||
2204 | u32 rx_frm_cnt; | ||
2205 | |||
2206 | /* Total number of duplicate frames received successfully */ | ||
2207 | u32 frm_dup_cnt; | ||
2208 | |||
2209 | /* Total number packets(per AC) failed to transmit */ | ||
2210 | u32 fail_cnt[4]; | ||
2211 | |||
2212 | /* Total number of RTS/CTS sequence failures for transmission of a | ||
2213 | * packet */ | ||
2214 | u32 rts_fail_cnt; | ||
2215 | |||
2216 | /* Total number packets failed transmit because of no ACK from the | ||
2217 | * remote entity */ | ||
2218 | u32 ack_fail_cnt; | ||
2219 | |||
2220 | /* Total number of RTS/CTS sequence success for transmission of a | ||
2221 | * packet */ | ||
2222 | u32 rts_succ_cnt; | ||
2223 | |||
2224 | /* The sum of the receive error count and dropped-receive-buffer | ||
2225 | * error count. HAL will provide this as a sum of (FCS error) + | ||
2226 | * (Fail get BD/PDU in HW) */ | ||
2227 | u32 rx_discard_cnt; | ||
2228 | |||
2229 | /* | ||
2230 | * The receive error count. HAL will provide the RxP FCS error | ||
2231 | * global counter. */ | ||
2232 | u32 rx_error_cnt; | ||
2233 | |||
2234 | /* The sum of the transmit-directed byte count, transmit-multicast | ||
2235 | * byte count and transmit-broadcast byte count. HAL will sum TPE | ||
2236 | * UC/MC/BCAST global counters to provide this. */ | ||
2237 | u32 tx_byte_cnt; | ||
2238 | }; | ||
2239 | |||
2240 | /* defines tx_rate_flags */ | ||
2241 | enum tx_rate_info { | ||
2242 | /* Legacy rates */ | ||
2243 | HAL_TX_RATE_LEGACY = 0x1, | ||
2244 | |||
2245 | /* HT20 rates */ | ||
2246 | HAL_TX_RATE_HT20 = 0x2, | ||
2247 | |||
2248 | /* HT40 rates */ | ||
2249 | HAL_TX_RATE_HT40 = 0x4, | ||
2250 | |||
2251 | /* Rate with Short guard interval */ | ||
2252 | HAL_TX_RATE_SGI = 0x8, | ||
2253 | |||
2254 | /* Rate with Long guard interval */ | ||
2255 | HAL_TX_RATE_LGI = 0x10 | ||
2256 | }; | ||
2257 | |||
2258 | struct ani_global_class_a_stats_info { | ||
2259 | /* The number of MPDU frames received by the 802.11 station for | ||
2260 | * MSDU packets or MMPDU frames */ | ||
2261 | u32 rx_frag_cnt; | ||
2262 | |||
2263 | /* The number of MPDU frames received by the 802.11 station for | ||
2264 | * MSDU packets or MMPDU frames when a promiscuous packet filter | ||
2265 | * was enabled */ | ||
2266 | u32 promiscuous_rx_frag_cnt; | ||
2267 | |||
2268 | /* The receiver input sensitivity referenced to a FER of 8% at an | ||
2269 | * MPDU length of 1024 bytes at the antenna connector. Each element | ||
2270 | * of the array shall correspond to a supported rate and the order | ||
2271 | * shall be the same as the supporteRates parameter. */ | ||
2272 | u32 rx_input_sensitivity; | ||
2273 | |||
2274 | /* The maximum transmit power in dBm upto one decimal. for eg: if | ||
2275 | * it is 10.5dBm, the value would be 105 */ | ||
2276 | u32 max_pwr; | ||
2277 | |||
2278 | /* Number of times the receiver failed to synchronize with the | ||
2279 | * incoming signal after detecting the sync in the preamble of the | ||
2280 | * transmitted PLCP protocol data unit. */ | ||
2281 | u32 sync_fail_cnt; | ||
2282 | |||
2283 | /* Legacy transmit rate, in units of 500 kbit/sec, for the most | ||
2284 | * recently transmitted frame */ | ||
2285 | u32 tx_rate; | ||
2286 | |||
2287 | /* mcs index for HT20 and HT40 rates */ | ||
2288 | u32 mcs_index; | ||
2289 | |||
2290 | /* to differentiate between HT20 and HT40 rates; short and long | ||
2291 | * guard interval */ | ||
2292 | u32 tx_rate_flags; | ||
2293 | }; | ||
2294 | |||
2295 | struct ani_global_security_stats { | ||
2296 | /* The number of unencrypted received MPDU frames that the MAC | ||
2297 | * layer discarded when the IEEE 802.11 dot11ExcludeUnencrypted | ||
2298 | * management information base (MIB) object is enabled */ | ||
2299 | u32 rx_wep_unencrypted_frm_cnt; | ||
2300 | |||
2301 | /* The number of received MSDU packets that that the 802.11 station | ||
2302 | * discarded because of MIC failures */ | ||
2303 | u32 rx_mic_fail_cnt; | ||
2304 | |||
2305 | /* The number of encrypted MPDU frames that the 802.11 station | ||
2306 | * failed to decrypt because of a TKIP ICV error */ | ||
2307 | u32 tkip_icv_err; | ||
2308 | |||
2309 | /* The number of received MPDU frames that the 802.11 discarded | ||
2310 | * because of an invalid AES-CCMP format */ | ||
2311 | u32 aes_ccmp_format_err; | ||
2312 | |||
2313 | /* The number of received MPDU frames that the 802.11 station | ||
2314 | * discarded because of the AES-CCMP replay protection procedure */ | ||
2315 | u32 aes_ccmp_replay_cnt; | ||
2316 | |||
2317 | /* The number of received MPDU frames that the 802.11 station | ||
2318 | * discarded because of errors detected by the AES-CCMP decryption | ||
2319 | * algorithm */ | ||
2320 | u32 aes_ccmp_decrpt_err; | ||
2321 | |||
2322 | /* The number of encrypted MPDU frames received for which a WEP | ||
2323 | * decryption key was not available on the 802.11 station */ | ||
2324 | u32 wep_undecryptable_cnt; | ||
2325 | |||
2326 | /* The number of encrypted MPDU frames that the 802.11 station | ||
2327 | * failed to decrypt because of a WEP ICV error */ | ||
2328 | u32 wep_icv_err; | ||
2329 | |||
2330 | /* The number of received encrypted packets that the 802.11 station | ||
2331 | * successfully decrypted */ | ||
2332 | u32 rx_decrypt_succ_cnt; | ||
2333 | |||
2334 | /* The number of encrypted packets that the 802.11 station failed | ||
2335 | * to decrypt */ | ||
2336 | u32 rx_decrypt_fail_cnt; | ||
2337 | }; | ||
2338 | |||
2339 | struct ani_global_class_b_stats_info { | ||
2340 | struct ani_global_security_stats uc_stats; | ||
2341 | struct ani_global_security_stats mc_bc_stats; | ||
2342 | }; | ||
2343 | |||
2344 | struct ani_global_class_c_stats_info { | ||
2345 | /* This counter shall be incremented for a received A-MSDU frame | ||
2346 | * with the stations MAC address in the address 1 field or an | ||
2347 | * A-MSDU frame with a group address in the address 1 field */ | ||
2348 | u32 rx_amsdu_cnt; | ||
2349 | |||
2350 | /* This counter shall be incremented when the MAC receives an AMPDU | ||
2351 | * from the PHY */ | ||
2352 | u32 rx_ampdu_cnt; | ||
2353 | |||
2354 | /* This counter shall be incremented when a Frame is transmitted | ||
2355 | * only on the primary channel */ | ||
2356 | u32 tx_20_frm_cnt; | ||
2357 | |||
2358 | /* This counter shall be incremented when a Frame is received only | ||
2359 | * on the primary channel */ | ||
2360 | u32 rx_20_frm_cnt; | ||
2361 | |||
2362 | /* This counter shall be incremented by the number of MPDUs | ||
2363 | * received in the A-MPDU when an A-MPDU is received */ | ||
2364 | u32 rx_mpdu_in_ampdu_cnt; | ||
2365 | |||
2366 | /* This counter shall be incremented when an MPDU delimiter has a | ||
2367 | * CRC error when this is the first CRC error in the received AMPDU | ||
2368 | * or when the previous delimiter has been decoded correctly */ | ||
2369 | u32 ampdu_delimiter_crc_err; | ||
2370 | }; | ||
2371 | |||
2372 | struct ani_per_sta_stats_info { | ||
2373 | /* The number of MPDU frames that the 802.11 station transmitted | ||
2374 | * and acknowledged through a received 802.11 ACK frame */ | ||
2375 | u32 tx_frag_cnt[4]; | ||
2376 | |||
2377 | /* This counter shall be incremented when an A-MPDU is transmitted */ | ||
2378 | u32 tx_ampdu_cnt; | ||
2379 | |||
2380 | /* This counter shall increment by the number of MPDUs in the AMPDU | ||
2381 | * when an A-MPDU is transmitted */ | ||
2382 | u32 tx_mpdu_in_ampdu_cnt; | ||
2383 | }; | ||
2384 | |||
2385 | struct wcn36xx_hal_stats_rsp_msg { | ||
2386 | struct wcn36xx_hal_msg_header header; | ||
2387 | |||
2388 | /* Success or Failure */ | ||
2389 | u32 status; | ||
2390 | |||
2391 | /* STA Idx */ | ||
2392 | u32 sta_index; | ||
2393 | |||
2394 | /* Categories of STATS being returned as per eHalStatsMask */ | ||
2395 | u32 stats_mask; | ||
2396 | |||
2397 | /* message type is same as the request type */ | ||
2398 | u16 msg_type; | ||
2399 | |||
2400 | /* length of the entire request, includes the pStatsBuf length too */ | ||
2401 | u16 msg_len; | ||
2402 | }; | ||
2403 | |||
2404 | struct wcn36xx_hal_set_link_state_req_msg { | ||
2405 | struct wcn36xx_hal_msg_header header; | ||
2406 | |||
2407 | u8 bssid[ETH_ALEN]; | ||
2408 | enum wcn36xx_hal_link_state state; | ||
2409 | u8 self_mac_addr[ETH_ALEN]; | ||
2410 | |||
2411 | } __packed; | ||
2412 | |||
2413 | struct set_link_state_rsp_msg { | ||
2414 | struct wcn36xx_hal_msg_header header; | ||
2415 | |||
2416 | /* success or failure */ | ||
2417 | u32 status; | ||
2418 | }; | ||
2419 | |||
2420 | /* TSPEC Params */ | ||
2421 | struct wcn36xx_hal_ts_info_tfc { | ||
2422 | #ifndef ANI_LITTLE_BIT_ENDIAN | ||
2423 | u16 ackPolicy:2; | ||
2424 | u16 userPrio:3; | ||
2425 | u16 psb:1; | ||
2426 | u16 aggregation:1; | ||
2427 | u16 accessPolicy:2; | ||
2428 | u16 direction:2; | ||
2429 | u16 tsid:4; | ||
2430 | u16 trafficType:1; | ||
2431 | #else | ||
2432 | u16 trafficType:1; | ||
2433 | u16 tsid:4; | ||
2434 | u16 direction:2; | ||
2435 | u16 accessPolicy:2; | ||
2436 | u16 aggregation:1; | ||
2437 | u16 psb:1; | ||
2438 | u16 userPrio:3; | ||
2439 | u16 ackPolicy:2; | ||
2440 | #endif | ||
2441 | }; | ||
2442 | |||
2443 | /* Flag to schedule the traffic type */ | ||
2444 | struct wcn36xx_hal_ts_info_sch { | ||
2445 | #ifndef ANI_LITTLE_BIT_ENDIAN | ||
2446 | u8 rsvd:7; | ||
2447 | u8 schedule:1; | ||
2448 | #else | ||
2449 | u8 schedule:1; | ||
2450 | u8 rsvd:7; | ||
2451 | #endif | ||
2452 | }; | ||
2453 | |||
2454 | /* Traffic and scheduling info */ | ||
2455 | struct wcn36xx_hal_ts_info { | ||
2456 | struct wcn36xx_hal_ts_info_tfc traffic; | ||
2457 | struct wcn36xx_hal_ts_info_sch schedule; | ||
2458 | }; | ||
2459 | |||
2460 | /* Information elements */ | ||
2461 | struct wcn36xx_hal_tspec_ie { | ||
2462 | u8 type; | ||
2463 | u8 length; | ||
2464 | struct wcn36xx_hal_ts_info ts_info; | ||
2465 | u16 nom_msdu_size; | ||
2466 | u16 max_msdu_size; | ||
2467 | u32 min_svc_interval; | ||
2468 | u32 max_svc_interval; | ||
2469 | u32 inact_interval; | ||
2470 | u32 suspend_interval; | ||
2471 | u32 svc_start_time; | ||
2472 | u32 min_data_rate; | ||
2473 | u32 mean_data_rate; | ||
2474 | u32 peak_data_rate; | ||
2475 | u32 max_burst_sz; | ||
2476 | u32 delay_bound; | ||
2477 | u32 min_phy_rate; | ||
2478 | u16 surplus_bw; | ||
2479 | u16 medium_time; | ||
2480 | }; | ||
2481 | |||
2482 | struct add_ts_req_msg { | ||
2483 | struct wcn36xx_hal_msg_header header; | ||
2484 | |||
2485 | /* Station Index */ | ||
2486 | u16 sta_index; | ||
2487 | |||
2488 | /* TSPEC handler uniquely identifying a TSPEC for a STA in a BSS */ | ||
2489 | u16 tspec_index; | ||
2490 | |||
2491 | /* To program TPE with required parameters */ | ||
2492 | struct wcn36xx_hal_tspec_ie tspec; | ||
2493 | |||
2494 | /* U-APSD Flags: 1b per AC. Encoded as follows: | ||
2495 | b7 b6 b5 b4 b3 b2 b1 b0 = | ||
2496 | X X X X BE BK VI VO */ | ||
2497 | u8 uapsd; | ||
2498 | |||
2499 | /* These parameters are for all the access categories */ | ||
2500 | |||
2501 | /* Service Interval */ | ||
2502 | u32 service_interval[WCN36XX_HAL_MAX_AC]; | ||
2503 | |||
2504 | /* Suspend Interval */ | ||
2505 | u32 suspend_interval[WCN36XX_HAL_MAX_AC]; | ||
2506 | |||
2507 | /* Delay Interval */ | ||
2508 | u32 delay_interval[WCN36XX_HAL_MAX_AC]; | ||
2509 | }; | ||
2510 | |||
2511 | struct add_rs_rsp_msg { | ||
2512 | struct wcn36xx_hal_msg_header header; | ||
2513 | |||
2514 | /* success or failure */ | ||
2515 | u32 status; | ||
2516 | }; | ||
2517 | |||
2518 | struct del_ts_req_msg { | ||
2519 | struct wcn36xx_hal_msg_header header; | ||
2520 | |||
2521 | /* Station Index */ | ||
2522 | u16 sta_index; | ||
2523 | |||
2524 | /* TSPEC identifier uniquely identifying a TSPEC for a STA in a BSS */ | ||
2525 | u16 tspec_index; | ||
2526 | |||
2527 | /* To lookup station id using the mac address */ | ||
2528 | u8 bssid[ETH_ALEN]; | ||
2529 | }; | ||
2530 | |||
2531 | struct del_ts_rsp_msg { | ||
2532 | struct wcn36xx_hal_msg_header header; | ||
2533 | |||
2534 | /* success or failure */ | ||
2535 | u32 status; | ||
2536 | }; | ||
2537 | |||
2538 | /* End of TSpec Parameters */ | ||
2539 | |||
2540 | /* Start of BLOCK ACK related Parameters */ | ||
2541 | |||
2542 | struct wcn36xx_hal_add_ba_session_req_msg { | ||
2543 | struct wcn36xx_hal_msg_header header; | ||
2544 | |||
2545 | /* Station Index */ | ||
2546 | u16 sta_index; | ||
2547 | |||
2548 | /* Peer MAC Address */ | ||
2549 | u8 mac_addr[ETH_ALEN]; | ||
2550 | |||
2551 | /* ADDBA Action Frame dialog token | ||
2552 | HAL will not interpret this object */ | ||
2553 | u8 dialog_token; | ||
2554 | |||
2555 | /* TID for which the BA is being setup | ||
2556 | This identifies the TC or TS of interest */ | ||
2557 | u8 tid; | ||
2558 | |||
2559 | /* 0 - Delayed BA (Not supported) | ||
2560 | 1 - Immediate BA */ | ||
2561 | u8 policy; | ||
2562 | |||
2563 | /* Indicates the number of buffers for this TID (baTID) | ||
2564 | NOTE - This is the requested buffer size. When this | ||
2565 | is processed by HAL and subsequently by HDD, it is | ||
2566 | possible that HDD may change this buffer size. Any | ||
2567 | change in the buffer size should be noted by PE and | ||
2568 | advertized appropriately in the ADDBA response */ | ||
2569 | u16 buffer_size; | ||
2570 | |||
2571 | /* BA timeout in TU's 0 means no timeout will occur */ | ||
2572 | u16 timeout; | ||
2573 | |||
2574 | /* b0..b3 - Fragment Number - Always set to 0 | ||
2575 | b4..b15 - Starting Sequence Number of first MSDU | ||
2576 | for which this BA is setup */ | ||
2577 | u16 ssn; | ||
2578 | |||
2579 | /* ADDBA direction | ||
2580 | 1 - Originator | ||
2581 | 0 - Recipient */ | ||
2582 | u8 direction; | ||
2583 | } __packed; | ||
2584 | |||
2585 | struct wcn36xx_hal_add_ba_session_rsp_msg { | ||
2586 | struct wcn36xx_hal_msg_header header; | ||
2587 | |||
2588 | /* success or failure */ | ||
2589 | u32 status; | ||
2590 | |||
2591 | /* Dialog token */ | ||
2592 | u8 dialog_token; | ||
2593 | |||
2594 | /* TID for which the BA session has been setup */ | ||
2595 | u8 ba_tid; | ||
2596 | |||
2597 | /* BA Buffer Size allocated for the current BA session */ | ||
2598 | u8 ba_buffer_size; | ||
2599 | |||
2600 | u8 ba_session_id; | ||
2601 | |||
2602 | /* Reordering Window buffer */ | ||
2603 | u8 win_size; | ||
2604 | |||
2605 | /* Station Index to id the sta */ | ||
2606 | u8 sta_index; | ||
2607 | |||
2608 | /* Starting Sequence Number */ | ||
2609 | u16 ssn; | ||
2610 | } __packed; | ||
2611 | |||
2612 | struct wcn36xx_hal_add_ba_req_msg { | ||
2613 | struct wcn36xx_hal_msg_header header; | ||
2614 | |||
2615 | /* Session Id */ | ||
2616 | u8 session_id; | ||
2617 | |||
2618 | /* Reorder Window Size */ | ||
2619 | u8 win_size; | ||
2620 | /* Old FW 1.2.2.4 does not support this*/ | ||
2621 | #ifdef FEATURE_ON_CHIP_REORDERING | ||
2622 | u8 reordering_done_on_chip; | ||
2623 | #endif | ||
2624 | } __packed; | ||
2625 | |||
2626 | struct wcn36xx_hal_add_ba_rsp_msg { | ||
2627 | struct wcn36xx_hal_msg_header header; | ||
2628 | |||
2629 | /* success or failure */ | ||
2630 | u32 status; | ||
2631 | |||
2632 | /* Dialog token */ | ||
2633 | u8 dialog_token; | ||
2634 | } __packed; | ||
2635 | |||
2636 | struct add_ba_info { | ||
2637 | u16 ba_enable:1; | ||
2638 | u16 starting_seq_num:12; | ||
2639 | u16 reserved:3; | ||
2640 | }; | ||
2641 | |||
2642 | struct wcn36xx_hal_trigger_ba_rsp_candidate { | ||
2643 | u8 sta_addr[ETH_ALEN]; | ||
2644 | struct add_ba_info ba_info[STACFG_MAX_TC]; | ||
2645 | } __packed; | ||
2646 | |||
2647 | struct wcn36xx_hal_trigget_ba_req_candidate { | ||
2648 | u8 sta_index; | ||
2649 | u8 tid_bitmap; | ||
2650 | } __packed; | ||
2651 | |||
2652 | struct wcn36xx_hal_trigger_ba_req_msg { | ||
2653 | struct wcn36xx_hal_msg_header header; | ||
2654 | |||
2655 | /* Session Id */ | ||
2656 | u8 session_id; | ||
2657 | |||
2658 | /* baCandidateCnt is followed by trigger BA | ||
2659 | * Candidate List(tTriggerBaCandidate) | ||
2660 | */ | ||
2661 | u16 candidate_cnt; | ||
2662 | |||
2663 | } __packed; | ||
2664 | |||
2665 | struct wcn36xx_hal_trigger_ba_rsp_msg { | ||
2666 | struct wcn36xx_hal_msg_header header; | ||
2667 | |||
2668 | /* TO SUPPORT BT-AMP */ | ||
2669 | u8 bssid[ETH_ALEN]; | ||
2670 | |||
2671 | /* success or failure */ | ||
2672 | u32 status; | ||
2673 | |||
2674 | /* baCandidateCnt is followed by trigger BA | ||
2675 | * Rsp Candidate List(tTriggerRspBaCandidate) | ||
2676 | */ | ||
2677 | u16 candidate_cnt; | ||
2678 | } __packed; | ||
2679 | |||
2680 | struct wcn36xx_hal_del_ba_req_msg { | ||
2681 | struct wcn36xx_hal_msg_header header; | ||
2682 | |||
2683 | /* Station Index */ | ||
2684 | u16 sta_index; | ||
2685 | |||
2686 | /* TID for which the BA session is being deleted */ | ||
2687 | u8 tid; | ||
2688 | |||
2689 | /* DELBA direction | ||
2690 | 1 - Originator | ||
2691 | 0 - Recipient */ | ||
2692 | u8 direction; | ||
2693 | } __packed; | ||
2694 | |||
2695 | struct wcn36xx_hal_del_ba_rsp_msg { | ||
2696 | struct wcn36xx_hal_msg_header header; | ||
2697 | |||
2698 | /* success or failure */ | ||
2699 | u32 status; | ||
2700 | } __packed; | ||
2701 | |||
2702 | struct tsm_stats_req_msg { | ||
2703 | struct wcn36xx_hal_msg_header header; | ||
2704 | |||
2705 | /* Traffic Id */ | ||
2706 | u8 tid; | ||
2707 | |||
2708 | u8 bssid[ETH_ALEN]; | ||
2709 | }; | ||
2710 | |||
2711 | struct tsm_stats_rsp_msg { | ||
2712 | struct wcn36xx_hal_msg_header header; | ||
2713 | |||
2714 | /*success or failure */ | ||
2715 | u32 status; | ||
2716 | |||
2717 | /* Uplink Packet Queue delay */ | ||
2718 | u16 uplink_pkt_queue_delay; | ||
2719 | |||
2720 | /* Uplink Packet Queue delay histogram */ | ||
2721 | u16 uplink_pkt_queue_delay_hist[4]; | ||
2722 | |||
2723 | /* Uplink Packet Transmit delay */ | ||
2724 | u32 uplink_pkt_tx_delay; | ||
2725 | |||
2726 | /* Uplink Packet loss */ | ||
2727 | u16 uplink_pkt_loss; | ||
2728 | |||
2729 | /* Uplink Packet count */ | ||
2730 | u16 uplink_pkt_count; | ||
2731 | |||
2732 | /* Roaming count */ | ||
2733 | u8 roaming_count; | ||
2734 | |||
2735 | /* Roaming Delay */ | ||
2736 | u16 roaming_delay; | ||
2737 | }; | ||
2738 | |||
2739 | struct set_key_done_msg { | ||
2740 | struct wcn36xx_hal_msg_header header; | ||
2741 | |||
2742 | /*bssid of the keys */ | ||
2743 | u8 bssidx; | ||
2744 | u8 enc_type; | ||
2745 | }; | ||
2746 | |||
2747 | struct wcn36xx_hal_nv_img_download_req_msg { | ||
2748 | /* Note: The length specified in wcn36xx_hal_nv_img_download_req_msg | ||
2749 | * messages should be | ||
2750 | * header.len = sizeof(wcn36xx_hal_nv_img_download_req_msg) + | ||
2751 | * nv_img_buffer_size */ | ||
2752 | struct wcn36xx_hal_msg_header header; | ||
2753 | |||
2754 | /* Fragment sequence number of the NV Image. Note that NV Image | ||
2755 | * might not fit into one message due to size limitation of the SMD | ||
2756 | * channel FIFO. UMAC can hence choose to chop the NV blob into | ||
2757 | * multiple fragments starting with seqeunce number 0, 1, 2 etc. | ||
2758 | * The last fragment MUST be indicated by marking the | ||
2759 | * isLastFragment field to 1. Note that all the NV blobs would be | ||
2760 | * concatenated together by HAL without any padding bytes in | ||
2761 | * between.*/ | ||
2762 | u16 frag_number; | ||
2763 | |||
2764 | /* Is this the last fragment? When set to 1 it indicates that no | ||
2765 | * more fragments will be sent by UMAC and HAL can concatenate all | ||
2766 | * the NV blobs rcvd & proceed with the parsing. HAL would generate | ||
2767 | * a WCN36XX_HAL_DOWNLOAD_NV_RSP to the WCN36XX_HAL_DOWNLOAD_NV_REQ | ||
2768 | * after it receives each fragment */ | ||
2769 | u16 last_fragment; | ||
2770 | |||
2771 | /* NV Image size (number of bytes) */ | ||
2772 | u32 nv_img_buffer_size; | ||
2773 | |||
2774 | /* Following the 'nv_img_buffer_size', there should be | ||
2775 | * nv_img_buffer_size bytes of NV Image i.e. | ||
2776 | * u8[nv_img_buffer_size] */ | ||
2777 | } __packed; | ||
2778 | |||
2779 | struct wcn36xx_hal_nv_img_download_rsp_msg { | ||
2780 | struct wcn36xx_hal_msg_header header; | ||
2781 | |||
2782 | /* Success or Failure. HAL would generate a | ||
2783 | * WCN36XX_HAL_DOWNLOAD_NV_RSP after each fragment */ | ||
2784 | u32 status; | ||
2785 | } __packed; | ||
2786 | |||
2787 | struct wcn36xx_hal_nv_store_ind { | ||
2788 | /* Note: The length specified in tHalNvStoreInd messages should be | ||
2789 | * header.msgLen = sizeof(tHalNvStoreInd) + nvBlobSize */ | ||
2790 | struct wcn36xx_hal_msg_header header; | ||
2791 | |||
2792 | /* NV Item */ | ||
2793 | u32 table_id; | ||
2794 | |||
2795 | /* Size of NV Blob */ | ||
2796 | u32 nv_blob_size; | ||
2797 | |||
2798 | /* Following the 'nvBlobSize', there should be nvBlobSize bytes of | ||
2799 | * NV blob i.e. u8[nvBlobSize] */ | ||
2800 | }; | ||
2801 | |||
2802 | /* End of Block Ack Related Parameters */ | ||
2803 | |||
2804 | #define WCN36XX_HAL_CIPHER_SEQ_CTR_SIZE 6 | ||
2805 | |||
2806 | /* Definition for MIC failure indication MAC reports this each time a MIC | ||
2807 | * failure occures on Rx TKIP packet | ||
2808 | */ | ||
2809 | struct mic_failure_ind_msg { | ||
2810 | struct wcn36xx_hal_msg_header header; | ||
2811 | |||
2812 | u8 bssid[ETH_ALEN]; | ||
2813 | |||
2814 | /* address used to compute MIC */ | ||
2815 | u8 src_addr[ETH_ALEN]; | ||
2816 | |||
2817 | /* transmitter address */ | ||
2818 | u8 ta_addr[ETH_ALEN]; | ||
2819 | |||
2820 | u8 dst_addr[ETH_ALEN]; | ||
2821 | |||
2822 | u8 multicast; | ||
2823 | |||
2824 | /* first byte of IV */ | ||
2825 | u8 iv1; | ||
2826 | |||
2827 | /* second byte of IV */ | ||
2828 | u8 key_id; | ||
2829 | |||
2830 | /* sequence number */ | ||
2831 | u8 tsc[WCN36XX_HAL_CIPHER_SEQ_CTR_SIZE]; | ||
2832 | |||
2833 | /* receive address */ | ||
2834 | u8 rx_addr[ETH_ALEN]; | ||
2835 | }; | ||
2836 | |||
2837 | struct update_vht_op_mode_req_msg { | ||
2838 | struct wcn36xx_hal_msg_header header; | ||
2839 | |||
2840 | u16 op_mode; | ||
2841 | u16 sta_id; | ||
2842 | }; | ||
2843 | |||
2844 | struct update_vht_op_mode_params_rsp_msg { | ||
2845 | struct wcn36xx_hal_msg_header header; | ||
2846 | |||
2847 | u32 status; | ||
2848 | }; | ||
2849 | |||
2850 | struct update_beacon_req_msg { | ||
2851 | struct wcn36xx_hal_msg_header header; | ||
2852 | |||
2853 | u8 bss_index; | ||
2854 | |||
2855 | /* shortPreamble mode. HAL should update all the STA rates when it | ||
2856 | * receives this message */ | ||
2857 | u8 short_preamble; | ||
2858 | |||
2859 | /* short Slot time. */ | ||
2860 | u8 short_slot_time; | ||
2861 | |||
2862 | /* Beacon Interval */ | ||
2863 | u16 beacon_interval; | ||
2864 | |||
2865 | /* Protection related */ | ||
2866 | u8 lla_coexist; | ||
2867 | u8 llb_coexist; | ||
2868 | u8 llg_coexist; | ||
2869 | u8 ht20_coexist; | ||
2870 | u8 lln_non_gf_coexist; | ||
2871 | u8 lsig_tx_op_protection_full_support; | ||
2872 | u8 rifs_mode; | ||
2873 | |||
2874 | u16 param_change_bitmap; | ||
2875 | }; | ||
2876 | |||
2877 | struct update_beacon_rsp_msg { | ||
2878 | struct wcn36xx_hal_msg_header header; | ||
2879 | u32 status; | ||
2880 | }; | ||
2881 | |||
2882 | struct wcn36xx_hal_send_beacon_req_msg { | ||
2883 | struct wcn36xx_hal_msg_header header; | ||
2884 | |||
2885 | /* length of the template. */ | ||
2886 | u32 beacon_length; | ||
2887 | |||
2888 | /* Beacon data. */ | ||
2889 | u8 beacon[BEACON_TEMPLATE_SIZE]; | ||
2890 | |||
2891 | u8 bssid[ETH_ALEN]; | ||
2892 | |||
2893 | /* TIM IE offset from the beginning of the template. */ | ||
2894 | u32 tim_ie_offset; | ||
2895 | |||
2896 | /* P2P IE offset from the begining of the template */ | ||
2897 | u16 p2p_ie_offset; | ||
2898 | } __packed; | ||
2899 | |||
2900 | struct send_beacon_rsp_msg { | ||
2901 | struct wcn36xx_hal_msg_header header; | ||
2902 | u32 status; | ||
2903 | } __packed; | ||
2904 | |||
2905 | struct enable_radar_req_msg { | ||
2906 | struct wcn36xx_hal_msg_header header; | ||
2907 | |||
2908 | u8 bssid[ETH_ALEN]; | ||
2909 | u8 channel; | ||
2910 | }; | ||
2911 | |||
2912 | struct enable_radar_rsp_msg { | ||
2913 | struct wcn36xx_hal_msg_header header; | ||
2914 | |||
2915 | /* Link Parameters */ | ||
2916 | u8 bssid[ETH_ALEN]; | ||
2917 | |||
2918 | /* success or failure */ | ||
2919 | u32 status; | ||
2920 | }; | ||
2921 | |||
2922 | struct radar_detect_intr_ind_msg { | ||
2923 | struct wcn36xx_hal_msg_header header; | ||
2924 | |||
2925 | u8 radar_det_channel; | ||
2926 | }; | ||
2927 | |||
2928 | struct radar_detect_ind_msg { | ||
2929 | struct wcn36xx_hal_msg_header header; | ||
2930 | |||
2931 | /* channel number in which the RADAR detected */ | ||
2932 | u8 channel_number; | ||
2933 | |||
2934 | /* RADAR pulse width in usecond */ | ||
2935 | u16 radar_pulse_width; | ||
2936 | |||
2937 | /* Number of RADAR pulses */ | ||
2938 | u16 num_radar_pulse; | ||
2939 | }; | ||
2940 | |||
2941 | struct wcn36xx_hal_get_tpc_report_req_msg { | ||
2942 | struct wcn36xx_hal_msg_header header; | ||
2943 | |||
2944 | u8 sta[ETH_ALEN]; | ||
2945 | u8 dialog_token; | ||
2946 | u8 txpower; | ||
2947 | }; | ||
2948 | |||
2949 | struct wcn36xx_hal_get_tpc_report_rsp_msg { | ||
2950 | struct wcn36xx_hal_msg_header header; | ||
2951 | |||
2952 | /* success or failure */ | ||
2953 | u32 status; | ||
2954 | }; | ||
2955 | |||
2956 | struct wcn36xx_hal_send_probe_resp_req_msg { | ||
2957 | struct wcn36xx_hal_msg_header header; | ||
2958 | |||
2959 | u8 probe_resp_template[BEACON_TEMPLATE_SIZE]; | ||
2960 | u32 probe_resp_template_len; | ||
2961 | u32 proxy_probe_req_valid_ie_bmap[8]; | ||
2962 | u8 bssid[ETH_ALEN]; | ||
2963 | }; | ||
2964 | |||
2965 | struct send_probe_resp_rsp_msg { | ||
2966 | struct wcn36xx_hal_msg_header header; | ||
2967 | |||
2968 | /* success or failure */ | ||
2969 | u32 status; | ||
2970 | }; | ||
2971 | |||
2972 | struct send_unknown_frame_rx_ind_msg { | ||
2973 | struct wcn36xx_hal_msg_header header; | ||
2974 | |||
2975 | /* success or failure */ | ||
2976 | u32 status; | ||
2977 | }; | ||
2978 | |||
2979 | struct wcn36xx_hal_delete_sta_context_ind_msg { | ||
2980 | struct wcn36xx_hal_msg_header header; | ||
2981 | |||
2982 | u16 aid; | ||
2983 | u16 sta_id; | ||
2984 | |||
2985 | /* TO SUPPORT BT-AMP */ | ||
2986 | u8 bssid[ETH_ALEN]; | ||
2987 | |||
2988 | /* HAL copies bssid from the sta table. */ | ||
2989 | u8 addr2[ETH_ALEN]; | ||
2990 | |||
2991 | /* To unify the keepalive / unknown A2 / tim-based disa */ | ||
2992 | u16 reason_code; | ||
2993 | } __packed; | ||
2994 | |||
2995 | struct indicate_del_sta { | ||
2996 | struct wcn36xx_hal_msg_header header; | ||
2997 | u8 aid; | ||
2998 | u8 sta_index; | ||
2999 | u8 bss_index; | ||
3000 | u8 reason_code; | ||
3001 | u32 status; | ||
3002 | }; | ||
3003 | |||
3004 | struct bt_amp_event_msg { | ||
3005 | struct wcn36xx_hal_msg_header header; | ||
3006 | |||
3007 | enum bt_amp_event_type btAmpEventType; | ||
3008 | }; | ||
3009 | |||
3010 | struct bt_amp_event_rsp { | ||
3011 | struct wcn36xx_hal_msg_header header; | ||
3012 | |||
3013 | /* success or failure */ | ||
3014 | u32 status; | ||
3015 | }; | ||
3016 | |||
3017 | struct tl_hal_flush_ac_req_msg { | ||
3018 | struct wcn36xx_hal_msg_header header; | ||
3019 | |||
3020 | /* Station Index. originates from HAL */ | ||
3021 | u8 sta_id; | ||
3022 | |||
3023 | /* TID for which the transmit queue is being flushed */ | ||
3024 | u8 tid; | ||
3025 | }; | ||
3026 | |||
3027 | struct tl_hal_flush_ac_rsp_msg { | ||
3028 | struct wcn36xx_hal_msg_header header; | ||
3029 | |||
3030 | /* Station Index. originates from HAL */ | ||
3031 | u8 sta_id; | ||
3032 | |||
3033 | /* TID for which the transmit queue is being flushed */ | ||
3034 | u8 tid; | ||
3035 | |||
3036 | /* success or failure */ | ||
3037 | u32 status; | ||
3038 | }; | ||
3039 | |||
3040 | struct wcn36xx_hal_enter_imps_req_msg { | ||
3041 | struct wcn36xx_hal_msg_header header; | ||
3042 | }; | ||
3043 | |||
3044 | struct wcn36xx_hal_exit_imps_req { | ||
3045 | struct wcn36xx_hal_msg_header header; | ||
3046 | }; | ||
3047 | |||
3048 | struct wcn36xx_hal_enter_bmps_req_msg { | ||
3049 | struct wcn36xx_hal_msg_header header; | ||
3050 | |||
3051 | u8 bss_index; | ||
3052 | |||
3053 | /* TBTT value derived from the last beacon */ | ||
3054 | #ifndef BUILD_QWPTTSTATIC | ||
3055 | u64 tbtt; | ||
3056 | #endif | ||
3057 | u8 dtim_count; | ||
3058 | |||
3059 | /* DTIM period given to HAL during association may not be valid, if | ||
3060 | * association is based on ProbeRsp instead of beacon. */ | ||
3061 | u8 dtim_period; | ||
3062 | |||
3063 | /* For CCX and 11R Roaming */ | ||
3064 | u32 rssi_filter_period; | ||
3065 | |||
3066 | u32 num_beacon_per_rssi_average; | ||
3067 | u8 rssi_filter_enable; | ||
3068 | } __packed; | ||
3069 | |||
3070 | struct wcn36xx_hal_exit_bmps_req_msg { | ||
3071 | struct wcn36xx_hal_msg_header header; | ||
3072 | |||
3073 | u8 send_data_null; | ||
3074 | u8 bss_index; | ||
3075 | } __packed; | ||
3076 | |||
3077 | struct wcn36xx_hal_missed_beacon_ind_msg { | ||
3078 | struct wcn36xx_hal_msg_header header; | ||
3079 | |||
3080 | u8 bss_index; | ||
3081 | } __packed; | ||
3082 | |||
3083 | /* Beacon Filtering data structures */ | ||
3084 | |||
3085 | /* The above structure would be followed by multiple of below mentioned | ||
3086 | * structure | ||
3087 | */ | ||
3088 | struct beacon_filter_ie { | ||
3089 | u8 element_id; | ||
3090 | u8 check_ie_presence; | ||
3091 | u8 offset; | ||
3092 | u8 value; | ||
3093 | u8 bitmask; | ||
3094 | u8 ref; | ||
3095 | }; | ||
3096 | |||
3097 | struct wcn36xx_hal_add_bcn_filter_req_msg { | ||
3098 | struct wcn36xx_hal_msg_header header; | ||
3099 | |||
3100 | u16 capability_info; | ||
3101 | u16 capability_mask; | ||
3102 | u16 beacon_interval; | ||
3103 | u16 ie_num; | ||
3104 | u8 bss_index; | ||
3105 | u8 reserved; | ||
3106 | }; | ||
3107 | |||
3108 | struct wcn36xx_hal_rem_bcn_filter_req { | ||
3109 | struct wcn36xx_hal_msg_header header; | ||
3110 | |||
3111 | u8 ie_Count; | ||
3112 | u8 rem_ie_id[1]; | ||
3113 | }; | ||
3114 | |||
3115 | #define WCN36XX_HAL_IPV4_ARP_REPLY_OFFLOAD 0 | ||
3116 | #define WCN36XX_HAL_IPV6_NEIGHBOR_DISCOVERY_OFFLOAD 1 | ||
3117 | #define WCN36XX_HAL_IPV6_NS_OFFLOAD 2 | ||
3118 | #define WCN36XX_HAL_IPV6_ADDR_LEN 16 | ||
3119 | #define WCN36XX_HAL_OFFLOAD_DISABLE 0 | ||
3120 | #define WCN36XX_HAL_OFFLOAD_ENABLE 1 | ||
3121 | #define WCN36XX_HAL_OFFLOAD_BCAST_FILTER_ENABLE 0x2 | ||
3122 | #define WCN36XX_HAL_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE \ | ||
3123 | (HAL_OFFLOAD_ENABLE|HAL_OFFLOAD_BCAST_FILTER_ENABLE) | ||
3124 | |||
3125 | struct wcn36xx_hal_ns_offload_params { | ||
3126 | u8 src_ipv6_addr[WCN36XX_HAL_IPV6_ADDR_LEN]; | ||
3127 | u8 self_ipv6_addr[WCN36XX_HAL_IPV6_ADDR_LEN]; | ||
3128 | |||
3129 | /* Only support 2 possible Network Advertisement IPv6 address */ | ||
3130 | u8 target_ipv6_addr1[WCN36XX_HAL_IPV6_ADDR_LEN]; | ||
3131 | u8 target_ipv6_addr2[WCN36XX_HAL_IPV6_ADDR_LEN]; | ||
3132 | |||
3133 | u8 self_addr[ETH_ALEN]; | ||
3134 | u8 src_ipv6_addr_valid:1; | ||
3135 | u8 target_ipv6_addr1_valid:1; | ||
3136 | u8 target_ipv6_addr2_valid:1; | ||
3137 | u8 reserved1:5; | ||
3138 | |||
3139 | /* make it DWORD aligned */ | ||
3140 | u8 reserved2; | ||
3141 | |||
3142 | /* slot index for this offload */ | ||
3143 | u32 slot_index; | ||
3144 | u8 bss_index; | ||
3145 | }; | ||
3146 | |||
3147 | struct wcn36xx_hal_host_offload_req { | ||
3148 | u8 offload_Type; | ||
3149 | |||
3150 | /* enable or disable */ | ||
3151 | u8 enable; | ||
3152 | |||
3153 | union { | ||
3154 | u8 host_ipv4_addr[4]; | ||
3155 | u8 host_ipv6_addr[WCN36XX_HAL_IPV6_ADDR_LEN]; | ||
3156 | } u; | ||
3157 | }; | ||
3158 | |||
3159 | struct wcn36xx_hal_host_offload_req_msg { | ||
3160 | struct wcn36xx_hal_msg_header header; | ||
3161 | struct wcn36xx_hal_host_offload_req host_offload_params; | ||
3162 | struct wcn36xx_hal_ns_offload_params ns_offload_params; | ||
3163 | }; | ||
3164 | |||
3165 | /* Packet Types. */ | ||
3166 | #define WCN36XX_HAL_KEEP_ALIVE_NULL_PKT 1 | ||
3167 | #define WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP 2 | ||
3168 | |||
3169 | /* Enable or disable keep alive */ | ||
3170 | #define WCN36XX_HAL_KEEP_ALIVE_DISABLE 0 | ||
3171 | #define WCN36XX_HAL_KEEP_ALIVE_ENABLE 1 | ||
3172 | #define WCN36XX_KEEP_ALIVE_TIME_PERIOD 30 /* unit: s */ | ||
3173 | |||
3174 | /* Keep Alive request. */ | ||
3175 | struct wcn36xx_hal_keep_alive_req_msg { | ||
3176 | struct wcn36xx_hal_msg_header header; | ||
3177 | |||
3178 | u8 packet_type; | ||
3179 | u32 time_period; | ||
3180 | u8 host_ipv4_addr[WCN36XX_HAL_IPV4_ADDR_LEN]; | ||
3181 | u8 dest_ipv4_addr[WCN36XX_HAL_IPV4_ADDR_LEN]; | ||
3182 | u8 dest_addr[ETH_ALEN]; | ||
3183 | u8 bss_index; | ||
3184 | } __packed; | ||
3185 | |||
3186 | struct wcn36xx_hal_rssi_threshold_req_msg { | ||
3187 | struct wcn36xx_hal_msg_header header; | ||
3188 | |||
3189 | s8 threshold1:8; | ||
3190 | s8 threshold2:8; | ||
3191 | s8 threshold3:8; | ||
3192 | u8 thres1_pos_notify:1; | ||
3193 | u8 thres1_neg_notify:1; | ||
3194 | u8 thres2_pos_notify:1; | ||
3195 | u8 thres2_neg_notify:1; | ||
3196 | u8 thres3_pos_notify:1; | ||
3197 | u8 thres3_neg_notify:1; | ||
3198 | u8 reserved10:2; | ||
3199 | }; | ||
3200 | |||
3201 | struct wcn36xx_hal_enter_uapsd_req_msg { | ||
3202 | struct wcn36xx_hal_msg_header header; | ||
3203 | |||
3204 | u8 bk_delivery:1; | ||
3205 | u8 be_delivery:1; | ||
3206 | u8 vi_delivery:1; | ||
3207 | u8 vo_delivery:1; | ||
3208 | u8 bk_trigger:1; | ||
3209 | u8 be_trigger:1; | ||
3210 | u8 vi_trigger:1; | ||
3211 | u8 vo_trigger:1; | ||
3212 | u8 bss_index; | ||
3213 | }; | ||
3214 | |||
3215 | struct wcn36xx_hal_exit_uapsd_req_msg { | ||
3216 | struct wcn36xx_hal_msg_header header; | ||
3217 | u8 bss_index; | ||
3218 | }; | ||
3219 | |||
3220 | #define WCN36XX_HAL_WOWL_BCAST_PATTERN_MAX_SIZE 128 | ||
3221 | #define WCN36XX_HAL_WOWL_BCAST_MAX_NUM_PATTERNS 16 | ||
3222 | |||
3223 | struct wcn36xx_hal_wowl_add_bcast_ptrn_req_msg { | ||
3224 | struct wcn36xx_hal_msg_header header; | ||
3225 | |||
3226 | /* Pattern ID */ | ||
3227 | u8 id; | ||
3228 | |||
3229 | /* Pattern byte offset from beginning of the 802.11 packet to start | ||
3230 | * of the wake-up pattern */ | ||
3231 | u8 byte_Offset; | ||
3232 | |||
3233 | /* Non-Zero Pattern size */ | ||
3234 | u8 size; | ||
3235 | |||
3236 | /* Pattern */ | ||
3237 | u8 pattern[WCN36XX_HAL_WOWL_BCAST_PATTERN_MAX_SIZE]; | ||
3238 | |||
3239 | /* Non-zero pattern mask size */ | ||
3240 | u8 mask_size; | ||
3241 | |||
3242 | /* Pattern mask */ | ||
3243 | u8 mask[WCN36XX_HAL_WOWL_BCAST_PATTERN_MAX_SIZE]; | ||
3244 | |||
3245 | /* Extra pattern */ | ||
3246 | u8 extra[WCN36XX_HAL_WOWL_BCAST_PATTERN_MAX_SIZE]; | ||
3247 | |||
3248 | /* Extra pattern mask */ | ||
3249 | u8 mask_extra[WCN36XX_HAL_WOWL_BCAST_PATTERN_MAX_SIZE]; | ||
3250 | |||
3251 | u8 bss_index; | ||
3252 | }; | ||
3253 | |||
3254 | struct wcn36xx_hal_wow_del_bcast_ptrn_req_msg { | ||
3255 | struct wcn36xx_hal_msg_header header; | ||
3256 | |||
3257 | /* Pattern ID of the wakeup pattern to be deleted */ | ||
3258 | u8 id; | ||
3259 | u8 bss_index; | ||
3260 | }; | ||
3261 | |||
3262 | struct wcn36xx_hal_wowl_enter_req_msg { | ||
3263 | struct wcn36xx_hal_msg_header header; | ||
3264 | |||
3265 | /* Enables/disables magic packet filtering */ | ||
3266 | u8 magic_packet_enable; | ||
3267 | |||
3268 | /* Magic pattern */ | ||
3269 | u8 magic_pattern[ETH_ALEN]; | ||
3270 | |||
3271 | /* Enables/disables packet pattern filtering in firmware. Enabling | ||
3272 | * this flag enables broadcast pattern matching in Firmware. If | ||
3273 | * unicast pattern matching is also desired, | ||
3274 | * ucUcastPatternFilteringEnable flag must be set tot true as well | ||
3275 | */ | ||
3276 | u8 pattern_filtering_enable; | ||
3277 | |||
3278 | /* Enables/disables unicast packet pattern filtering. This flag | ||
3279 | * specifies whether we want to do pattern match on unicast packets | ||
3280 | * as well and not just broadcast packets. This flag has no effect | ||
3281 | * if the ucPatternFilteringEnable (main controlling flag) is set | ||
3282 | * to false | ||
3283 | */ | ||
3284 | u8 ucast_pattern_filtering_enable; | ||
3285 | |||
3286 | /* This configuration is valid only when magicPktEnable=1. It | ||
3287 | * requests hardware to wake up when it receives the Channel Switch | ||
3288 | * Action Frame. | ||
3289 | */ | ||
3290 | u8 wow_channel_switch_receive; | ||
3291 | |||
3292 | /* This configuration is valid only when magicPktEnable=1. It | ||
3293 | * requests hardware to wake up when it receives the | ||
3294 | * Deauthentication Frame. | ||
3295 | */ | ||
3296 | u8 wow_deauth_receive; | ||
3297 | |||
3298 | /* This configuration is valid only when magicPktEnable=1. It | ||
3299 | * requests hardware to wake up when it receives the Disassociation | ||
3300 | * Frame. | ||
3301 | */ | ||
3302 | u8 wow_disassoc_receive; | ||
3303 | |||
3304 | /* This configuration is valid only when magicPktEnable=1. It | ||
3305 | * requests hardware to wake up when it has missed consecutive | ||
3306 | * beacons. This is a hardware register configuration (NOT a | ||
3307 | * firmware configuration). | ||
3308 | */ | ||
3309 | u8 wow_max_missed_beacons; | ||
3310 | |||
3311 | /* This configuration is valid only when magicPktEnable=1. This is | ||
3312 | * a timeout value in units of microsec. It requests hardware to | ||
3313 | * unconditionally wake up after it has stayed in WoWLAN mode for | ||
3314 | * some time. Set 0 to disable this feature. | ||
3315 | */ | ||
3316 | u8 wow_max_sleep; | ||
3317 | |||
3318 | /* This configuration directs the WoW packet filtering to look for | ||
3319 | * EAP-ID requests embedded in EAPOL frames and use this as a wake | ||
3320 | * source. | ||
3321 | */ | ||
3322 | u8 wow_eap_id_request_enable; | ||
3323 | |||
3324 | /* This configuration directs the WoW packet filtering to look for | ||
3325 | * EAPOL-4WAY requests and use this as a wake source. | ||
3326 | */ | ||
3327 | u8 wow_eapol_4way_enable; | ||
3328 | |||
3329 | /* This configuration allows a host wakeup on an network scan | ||
3330 | * offload match. | ||
3331 | */ | ||
3332 | u8 wow_net_scan_offload_match; | ||
3333 | |||
3334 | /* This configuration allows a host wakeup on any GTK rekeying | ||
3335 | * error. | ||
3336 | */ | ||
3337 | u8 wow_gtk_rekey_error; | ||
3338 | |||
3339 | /* This configuration allows a host wakeup on BSS connection loss. | ||
3340 | */ | ||
3341 | u8 wow_bss_connection_loss; | ||
3342 | |||
3343 | u8 bss_index; | ||
3344 | }; | ||
3345 | |||
3346 | struct wcn36xx_hal_wowl_exit_req_msg { | ||
3347 | struct wcn36xx_hal_msg_header header; | ||
3348 | |||
3349 | u8 bss_index; | ||
3350 | }; | ||
3351 | |||
3352 | struct wcn36xx_hal_get_rssi_req_msg { | ||
3353 | struct wcn36xx_hal_msg_header header; | ||
3354 | }; | ||
3355 | |||
3356 | struct wcn36xx_hal_get_roam_rssi_req_msg { | ||
3357 | struct wcn36xx_hal_msg_header header; | ||
3358 | |||
3359 | /* Valid STA Idx for per STA stats request */ | ||
3360 | u32 sta_id; | ||
3361 | }; | ||
3362 | |||
3363 | struct wcn36xx_hal_set_uapsd_ac_params_req_msg { | ||
3364 | struct wcn36xx_hal_msg_header header; | ||
3365 | |||
3366 | /* STA index */ | ||
3367 | u8 sta_idx; | ||
3368 | |||
3369 | /* Access Category */ | ||
3370 | u8 ac; | ||
3371 | |||
3372 | /* User Priority */ | ||
3373 | u8 up; | ||
3374 | |||
3375 | /* Service Interval */ | ||
3376 | u32 service_interval; | ||
3377 | |||
3378 | /* Suspend Interval */ | ||
3379 | u32 suspend_interval; | ||
3380 | |||
3381 | /* Delay Interval */ | ||
3382 | u32 delay_interval; | ||
3383 | }; | ||
3384 | |||
3385 | struct wcn36xx_hal_configure_rxp_filter_req_msg { | ||
3386 | struct wcn36xx_hal_msg_header header; | ||
3387 | |||
3388 | u8 set_mcst_bcst_filter_setting; | ||
3389 | u8 set_mcst_bcst_filter; | ||
3390 | }; | ||
3391 | |||
3392 | struct wcn36xx_hal_enter_imps_rsp_msg { | ||
3393 | struct wcn36xx_hal_msg_header header; | ||
3394 | |||
3395 | /* success or failure */ | ||
3396 | u32 status; | ||
3397 | }; | ||
3398 | |||
3399 | struct wcn36xx_hal_exit_imps_rsp_msg { | ||
3400 | struct wcn36xx_hal_msg_header header; | ||
3401 | |||
3402 | /* success or failure */ | ||
3403 | u32 status; | ||
3404 | }; | ||
3405 | |||
3406 | struct wcn36xx_hal_enter_bmps_rsp_msg { | ||
3407 | struct wcn36xx_hal_msg_header header; | ||
3408 | |||
3409 | /* success or failure */ | ||
3410 | u32 status; | ||
3411 | |||
3412 | u8 bss_index; | ||
3413 | } __packed; | ||
3414 | |||
3415 | struct wcn36xx_hal_exit_bmps_rsp_msg { | ||
3416 | struct wcn36xx_hal_msg_header header; | ||
3417 | |||
3418 | /* success or failure */ | ||
3419 | u32 status; | ||
3420 | |||
3421 | u8 bss_index; | ||
3422 | } __packed; | ||
3423 | |||
3424 | struct wcn36xx_hal_enter_uapsd_rsp_msg { | ||
3425 | struct wcn36xx_hal_msg_header header; | ||
3426 | |||
3427 | /* success or failure */ | ||
3428 | u32 status; | ||
3429 | |||
3430 | u8 bss_index; | ||
3431 | }; | ||
3432 | |||
3433 | struct wcn36xx_hal_exit_uapsd_rsp_msg { | ||
3434 | struct wcn36xx_hal_msg_header header; | ||
3435 | |||
3436 | /* success or failure */ | ||
3437 | u32 status; | ||
3438 | |||
3439 | u8 bss_index; | ||
3440 | }; | ||
3441 | |||
3442 | struct wcn36xx_hal_rssi_notification_ind_msg { | ||
3443 | struct wcn36xx_hal_msg_header header; | ||
3444 | |||
3445 | u32 rssi_thres1_pos_cross:1; | ||
3446 | u32 rssi_thres1_neg_cross:1; | ||
3447 | u32 rssi_thres2_pos_cross:1; | ||
3448 | u32 rssi_thres2_neg_cross:1; | ||
3449 | u32 rssi_thres3_pos_cross:1; | ||
3450 | u32 rssi_thres3_neg_cross:1; | ||
3451 | u32 avg_rssi:8; | ||
3452 | u32 reserved:18; | ||
3453 | |||
3454 | }; | ||
3455 | |||
3456 | struct wcn36xx_hal_get_rssio_rsp_msg { | ||
3457 | struct wcn36xx_hal_msg_header header; | ||
3458 | |||
3459 | /* success or failure */ | ||
3460 | u32 status; | ||
3461 | s8 rssi; | ||
3462 | |||
3463 | }; | ||
3464 | |||
3465 | struct wcn36xx_hal_get_roam_rssi_rsp_msg { | ||
3466 | struct wcn36xx_hal_msg_header header; | ||
3467 | |||
3468 | /* success or failure */ | ||
3469 | u32 status; | ||
3470 | |||
3471 | u8 sta_id; | ||
3472 | s8 rssi; | ||
3473 | }; | ||
3474 | |||
3475 | struct wcn36xx_hal_wowl_enter_rsp_msg { | ||
3476 | struct wcn36xx_hal_msg_header header; | ||
3477 | |||
3478 | /* success or failure */ | ||
3479 | u32 status; | ||
3480 | u8 bss_index; | ||
3481 | }; | ||
3482 | |||
3483 | struct wcn36xx_hal_wowl_exit_rsp_msg { | ||
3484 | struct wcn36xx_hal_msg_header header; | ||
3485 | |||
3486 | /* success or failure */ | ||
3487 | u32 status; | ||
3488 | u8 bss_index; | ||
3489 | }; | ||
3490 | |||
3491 | struct wcn36xx_hal_add_bcn_filter_rsp_msg { | ||
3492 | struct wcn36xx_hal_msg_header header; | ||
3493 | |||
3494 | /* success or failure */ | ||
3495 | u32 status; | ||
3496 | }; | ||
3497 | |||
3498 | struct wcn36xx_hal_rem_bcn_filter_rsp_msg { | ||
3499 | struct wcn36xx_hal_msg_header header; | ||
3500 | |||
3501 | /* success or failure */ | ||
3502 | u32 status; | ||
3503 | }; | ||
3504 | |||
3505 | struct wcn36xx_hal_add_wowl_bcast_ptrn_rsp_msg { | ||
3506 | struct wcn36xx_hal_msg_header header; | ||
3507 | |||
3508 | /* success or failure */ | ||
3509 | u32 status; | ||
3510 | u8 bss_index; | ||
3511 | }; | ||
3512 | |||
3513 | struct wcn36xx_hal_del_wowl_bcast_ptrn_rsp_msg { | ||
3514 | struct wcn36xx_hal_msg_header header; | ||
3515 | |||
3516 | /* success or failure */ | ||
3517 | u32 status; | ||
3518 | u8 bss_index; | ||
3519 | }; | ||
3520 | |||
3521 | struct wcn36xx_hal_host_offload_rsp_msg { | ||
3522 | struct wcn36xx_hal_msg_header header; | ||
3523 | |||
3524 | /* success or failure */ | ||
3525 | u32 status; | ||
3526 | }; | ||
3527 | |||
3528 | struct wcn36xx_hal_keep_alive_rsp_msg { | ||
3529 | struct wcn36xx_hal_msg_header header; | ||
3530 | |||
3531 | /* success or failure */ | ||
3532 | u32 status; | ||
3533 | }; | ||
3534 | |||
3535 | struct wcn36xx_hal_set_rssi_thresh_rsp_msg { | ||
3536 | struct wcn36xx_hal_msg_header header; | ||
3537 | |||
3538 | /* success or failure */ | ||
3539 | u32 status; | ||
3540 | }; | ||
3541 | |||
3542 | struct wcn36xx_hal_set_uapsd_ac_params_rsp_msg { | ||
3543 | struct wcn36xx_hal_msg_header header; | ||
3544 | |||
3545 | /* success or failure */ | ||
3546 | u32 status; | ||
3547 | }; | ||
3548 | |||
3549 | struct wcn36xx_hal_configure_rxp_filter_rsp_msg { | ||
3550 | struct wcn36xx_hal_msg_header header; | ||
3551 | |||
3552 | /* success or failure */ | ||
3553 | u32 status; | ||
3554 | }; | ||
3555 | |||
3556 | struct set_max_tx_pwr_req { | ||
3557 | struct wcn36xx_hal_msg_header header; | ||
3558 | |||
3559 | /* BSSID is needed to identify which session issued this request. | ||
3560 | * As the request has power constraints, this should be applied | ||
3561 | * only to that session */ | ||
3562 | u8 bssid[ETH_ALEN]; | ||
3563 | |||
3564 | u8 self_addr[ETH_ALEN]; | ||
3565 | |||
3566 | /* In request, power == MaxTx power to be used. */ | ||
3567 | u8 power; | ||
3568 | }; | ||
3569 | |||
3570 | struct set_max_tx_pwr_rsp_msg { | ||
3571 | struct wcn36xx_hal_msg_header header; | ||
3572 | |||
3573 | /* power == tx power used for management frames */ | ||
3574 | u8 power; | ||
3575 | |||
3576 | /* success or failure */ | ||
3577 | u32 status; | ||
3578 | }; | ||
3579 | |||
3580 | struct set_tx_pwr_req_msg { | ||
3581 | struct wcn36xx_hal_msg_header header; | ||
3582 | |||
3583 | /* TX Power in milli watts */ | ||
3584 | u32 tx_power; | ||
3585 | |||
3586 | u8 bss_index; | ||
3587 | }; | ||
3588 | |||
3589 | struct set_tx_pwr_rsp_msg { | ||
3590 | struct wcn36xx_hal_msg_header header; | ||
3591 | |||
3592 | /* success or failure */ | ||
3593 | u32 status; | ||
3594 | }; | ||
3595 | |||
3596 | struct get_tx_pwr_req_msg { | ||
3597 | struct wcn36xx_hal_msg_header header; | ||
3598 | |||
3599 | u8 sta_id; | ||
3600 | }; | ||
3601 | |||
3602 | struct get_tx_pwr_rsp_msg { | ||
3603 | struct wcn36xx_hal_msg_header header; | ||
3604 | |||
3605 | /* success or failure */ | ||
3606 | u32 status; | ||
3607 | |||
3608 | /* TX Power in milli watts */ | ||
3609 | u32 tx_power; | ||
3610 | }; | ||
3611 | |||
3612 | struct set_p2p_gonoa_req_msg { | ||
3613 | struct wcn36xx_hal_msg_header header; | ||
3614 | |||
3615 | u8 opp_ps; | ||
3616 | u32 ct_window; | ||
3617 | u8 count; | ||
3618 | u32 duration; | ||
3619 | u32 interval; | ||
3620 | u32 single_noa_duration; | ||
3621 | u8 ps_selection; | ||
3622 | }; | ||
3623 | |||
3624 | struct set_p2p_gonoa_rsp_msg { | ||
3625 | struct wcn36xx_hal_msg_header header; | ||
3626 | |||
3627 | /* success or failure */ | ||
3628 | u32 status; | ||
3629 | }; | ||
3630 | |||
3631 | struct wcn36xx_hal_add_sta_self_req { | ||
3632 | struct wcn36xx_hal_msg_header header; | ||
3633 | |||
3634 | u8 self_addr[ETH_ALEN]; | ||
3635 | u32 status; | ||
3636 | } __packed; | ||
3637 | |||
3638 | struct wcn36xx_hal_add_sta_self_rsp_msg { | ||
3639 | struct wcn36xx_hal_msg_header header; | ||
3640 | |||
3641 | /* success or failure */ | ||
3642 | u32 status; | ||
3643 | |||
3644 | /* Self STA Index */ | ||
3645 | u8 self_sta_index; | ||
3646 | |||
3647 | /* DPU Index (IGTK, PTK, GTK all same) */ | ||
3648 | u8 dpu_index; | ||
3649 | |||
3650 | /* DPU Signature */ | ||
3651 | u8 dpu_signature; | ||
3652 | } __packed; | ||
3653 | |||
3654 | struct wcn36xx_hal_del_sta_self_req_msg { | ||
3655 | struct wcn36xx_hal_msg_header header; | ||
3656 | |||
3657 | u8 self_addr[ETH_ALEN]; | ||
3658 | } __packed; | ||
3659 | |||
3660 | struct wcn36xx_hal_del_sta_self_rsp_msg { | ||
3661 | struct wcn36xx_hal_msg_header header; | ||
3662 | |||
3663 | /*success or failure */ | ||
3664 | u32 status; | ||
3665 | |||
3666 | u8 self_addr[ETH_ALEN]; | ||
3667 | } __packed; | ||
3668 | |||
3669 | struct aggr_add_ts_req { | ||
3670 | struct wcn36xx_hal_msg_header header; | ||
3671 | |||
3672 | /* Station Index */ | ||
3673 | u16 sta_idx; | ||
3674 | |||
3675 | /* TSPEC handler uniquely identifying a TSPEC for a STA in a BSS. | ||
3676 | * This will carry the bitmap with the bit positions representing | ||
3677 | * different AC.s */ | ||
3678 | u16 tspec_index; | ||
3679 | |||
3680 | /* Tspec info per AC To program TPE with required parameters */ | ||
3681 | struct wcn36xx_hal_tspec_ie tspec[WCN36XX_HAL_MAX_AC]; | ||
3682 | |||
3683 | /* U-APSD Flags: 1b per AC. Encoded as follows: | ||
3684 | b7 b6 b5 b4 b3 b2 b1 b0 = | ||
3685 | X X X X BE BK VI VO */ | ||
3686 | u8 uapsd; | ||
3687 | |||
3688 | /* These parameters are for all the access categories */ | ||
3689 | |||
3690 | /* Service Interval */ | ||
3691 | u32 service_interval[WCN36XX_HAL_MAX_AC]; | ||
3692 | |||
3693 | /* Suspend Interval */ | ||
3694 | u32 suspend_interval[WCN36XX_HAL_MAX_AC]; | ||
3695 | |||
3696 | /* Delay Interval */ | ||
3697 | u32 delay_interval[WCN36XX_HAL_MAX_AC]; | ||
3698 | }; | ||
3699 | |||
3700 | struct aggr_add_ts_rsp_msg { | ||
3701 | struct wcn36xx_hal_msg_header header; | ||
3702 | |||
3703 | /* success or failure */ | ||
3704 | u32 status0; | ||
3705 | |||
3706 | /* FIXME PRIMA for future use for 11R */ | ||
3707 | u32 status1; | ||
3708 | }; | ||
3709 | |||
3710 | struct wcn36xx_hal_configure_apps_cpu_wakeup_state_req_msg { | ||
3711 | struct wcn36xx_hal_msg_header header; | ||
3712 | |||
3713 | u8 is_apps_cpu_awake; | ||
3714 | }; | ||
3715 | |||
3716 | struct wcn36xx_hal_configure_apps_cpu_wakeup_state_rsp_msg { | ||
3717 | struct wcn36xx_hal_msg_header header; | ||
3718 | |||
3719 | /* success or failure */ | ||
3720 | u32 status; | ||
3721 | }; | ||
3722 | |||
3723 | struct wcn36xx_hal_dump_cmd_req_msg { | ||
3724 | struct wcn36xx_hal_msg_header header; | ||
3725 | |||
3726 | u32 arg1; | ||
3727 | u32 arg2; | ||
3728 | u32 arg3; | ||
3729 | u32 arg4; | ||
3730 | u32 arg5; | ||
3731 | } __packed; | ||
3732 | |||
3733 | struct wcn36xx_hal_dump_cmd_rsp_msg { | ||
3734 | struct wcn36xx_hal_msg_header header; | ||
3735 | |||
3736 | /* success or failure */ | ||
3737 | u32 status; | ||
3738 | |||
3739 | /* Length of the responce message */ | ||
3740 | u32 rsp_length; | ||
3741 | |||
3742 | /* FIXME: Currently considering the the responce will be less than | ||
3743 | * 100bytes */ | ||
3744 | u8 rsp_buffer[DUMPCMD_RSP_BUFFER]; | ||
3745 | } __packed; | ||
3746 | |||
3747 | #define WLAN_COEX_IND_DATA_SIZE (4) | ||
3748 | #define WLAN_COEX_IND_TYPE_DISABLE_HB_MONITOR (0) | ||
3749 | #define WLAN_COEX_IND_TYPE_ENABLE_HB_MONITOR (1) | ||
3750 | |||
3751 | struct coex_ind_msg { | ||
3752 | struct wcn36xx_hal_msg_header header; | ||
3753 | |||
3754 | /* Coex Indication Type */ | ||
3755 | u32 type; | ||
3756 | |||
3757 | /* Coex Indication Data */ | ||
3758 | u32 data[WLAN_COEX_IND_DATA_SIZE]; | ||
3759 | }; | ||
3760 | |||
3761 | struct wcn36xx_hal_tx_compl_ind_msg { | ||
3762 | struct wcn36xx_hal_msg_header header; | ||
3763 | |||
3764 | /* Tx Complete Indication Success or Failure */ | ||
3765 | u32 status; | ||
3766 | }; | ||
3767 | |||
3768 | struct wcn36xx_hal_wlan_host_suspend_ind_msg { | ||
3769 | struct wcn36xx_hal_msg_header header; | ||
3770 | |||
3771 | u32 configured_mcst_bcst_filter_setting; | ||
3772 | u32 active_session_count; | ||
3773 | }; | ||
3774 | |||
3775 | struct wcn36xx_hal_wlan_exclude_unencrpted_ind_msg { | ||
3776 | struct wcn36xx_hal_msg_header header; | ||
3777 | |||
3778 | u8 dot11_exclude_unencrypted; | ||
3779 | u8 bssid[ETH_ALEN]; | ||
3780 | }; | ||
3781 | |||
3782 | struct noa_attr_ind_msg { | ||
3783 | struct wcn36xx_hal_msg_header header; | ||
3784 | |||
3785 | u8 index; | ||
3786 | u8 opp_ps_flag; | ||
3787 | u16 ctwin; | ||
3788 | |||
3789 | u16 noa1_interval_count; | ||
3790 | u16 bss_index; | ||
3791 | u32 noa1_duration; | ||
3792 | u32 noa1_interval; | ||
3793 | u32 noa1_starttime; | ||
3794 | |||
3795 | u16 noa2_interval_count; | ||
3796 | u16 reserved2; | ||
3797 | u32 noa2_duration; | ||
3798 | u32 noa2_interval; | ||
3799 | u32 noa2_start_time; | ||
3800 | |||
3801 | u32 status; | ||
3802 | }; | ||
3803 | |||
3804 | struct noa_start_ind_msg { | ||
3805 | struct wcn36xx_hal_msg_header header; | ||
3806 | |||
3807 | u32 status; | ||
3808 | u32 bss_index; | ||
3809 | }; | ||
3810 | |||
3811 | struct wcn36xx_hal_wlan_host_resume_req_msg { | ||
3812 | struct wcn36xx_hal_msg_header header; | ||
3813 | |||
3814 | u8 configured_mcst_bcst_filter_setting; | ||
3815 | }; | ||
3816 | |||
3817 | struct wcn36xx_hal_host_resume_rsp_msg { | ||
3818 | struct wcn36xx_hal_msg_header header; | ||
3819 | |||
3820 | /* success or failure */ | ||
3821 | u32 status; | ||
3822 | }; | ||
3823 | |||
3824 | struct wcn36xx_hal_del_ba_ind_msg { | ||
3825 | struct wcn36xx_hal_msg_header header; | ||
3826 | |||
3827 | u16 sta_idx; | ||
3828 | |||
3829 | /* Peer MAC Address, whose BA session has timed out */ | ||
3830 | u8 peer_addr[ETH_ALEN]; | ||
3831 | |||
3832 | /* TID for which a BA session timeout is being triggered */ | ||
3833 | u8 ba_tid; | ||
3834 | |||
3835 | /* DELBA direction | ||
3836 | * 1 - Originator | ||
3837 | * 0 - Recipient | ||
3838 | */ | ||
3839 | u8 direction; | ||
3840 | |||
3841 | u32 reason_code; | ||
3842 | |||
3843 | /* TO SUPPORT BT-AMP */ | ||
3844 | u8 bssid[ETH_ALEN]; | ||
3845 | }; | ||
3846 | |||
3847 | /* PNO Messages */ | ||
3848 | |||
3849 | /* Max number of channels that a network can be found on */ | ||
3850 | #define WCN36XX_HAL_PNO_MAX_NETW_CHANNELS 26 | ||
3851 | |||
3852 | /* Max number of channels that a network can be found on */ | ||
3853 | #define WCN36XX_HAL_PNO_MAX_NETW_CHANNELS_EX 60 | ||
3854 | |||
3855 | /* Maximum numbers of networks supported by PNO */ | ||
3856 | #define WCN36XX_HAL_PNO_MAX_SUPP_NETWORKS 16 | ||
3857 | |||
3858 | /* The number of scan time intervals that can be programmed into PNO */ | ||
3859 | #define WCN36XX_HAL_PNO_MAX_SCAN_TIMERS 10 | ||
3860 | |||
3861 | /* Maximum size of the probe template */ | ||
3862 | #define WCN36XX_HAL_PNO_MAX_PROBE_SIZE 450 | ||
3863 | |||
3864 | /* Type of PNO enabling: | ||
3865 | * | ||
3866 | * Immediate - scanning will start immediately and PNO procedure will be | ||
3867 | * repeated based on timer | ||
3868 | * | ||
3869 | * Suspend - scanning will start at suspend | ||
3870 | * | ||
3871 | * Resume - scanning will start on system resume | ||
3872 | */ | ||
3873 | enum pno_mode { | ||
3874 | PNO_MODE_IMMEDIATE, | ||
3875 | PNO_MODE_ON_SUSPEND, | ||
3876 | PNO_MODE_ON_RESUME, | ||
3877 | PNO_MODE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
3878 | }; | ||
3879 | |||
3880 | /* Authentication type */ | ||
3881 | enum auth_type { | ||
3882 | AUTH_TYPE_ANY = 0, | ||
3883 | AUTH_TYPE_OPEN_SYSTEM = 1, | ||
3884 | |||
3885 | /* Upper layer authentication types */ | ||
3886 | AUTH_TYPE_WPA = 2, | ||
3887 | AUTH_TYPE_WPA_PSK = 3, | ||
3888 | |||
3889 | AUTH_TYPE_RSN = 4, | ||
3890 | AUTH_TYPE_RSN_PSK = 5, | ||
3891 | AUTH_TYPE_FT_RSN = 6, | ||
3892 | AUTH_TYPE_FT_RSN_PSK = 7, | ||
3893 | AUTH_TYPE_WAPI_WAI_CERTIFICATE = 8, | ||
3894 | AUTH_TYPE_WAPI_WAI_PSK = 9, | ||
3895 | |||
3896 | AUTH_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
3897 | }; | ||
3898 | |||
3899 | /* Encryption type */ | ||
3900 | enum ed_type { | ||
3901 | ED_ANY = 0, | ||
3902 | ED_NONE = 1, | ||
3903 | ED_WEP = 2, | ||
3904 | ED_TKIP = 3, | ||
3905 | ED_CCMP = 4, | ||
3906 | ED_WPI = 5, | ||
3907 | |||
3908 | ED_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
3909 | }; | ||
3910 | |||
3911 | /* SSID broadcast type */ | ||
3912 | enum ssid_bcast_type { | ||
3913 | BCAST_UNKNOWN = 0, | ||
3914 | BCAST_NORMAL = 1, | ||
3915 | BCAST_HIDDEN = 2, | ||
3916 | |||
3917 | BCAST_TYPE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE | ||
3918 | }; | ||
3919 | |||
3920 | /* The network description for which PNO will have to look for */ | ||
3921 | struct network_type { | ||
3922 | /* SSID of the BSS */ | ||
3923 | struct wcn36xx_hal_mac_ssid ssid; | ||
3924 | |||
3925 | /* Authentication type for the network */ | ||
3926 | enum auth_type authentication; | ||
3927 | |||
3928 | /* Encryption type for the network */ | ||
3929 | enum ed_type encryption; | ||
3930 | |||
3931 | /* Indicate the channel on which the Network can be found 0 - if | ||
3932 | * all channels */ | ||
3933 | u8 channel_count; | ||
3934 | u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS]; | ||
3935 | |||
3936 | /* Indicates the RSSI threshold for the network to be considered */ | ||
3937 | u8 rssi_threshold; | ||
3938 | }; | ||
3939 | |||
3940 | struct scan_timer { | ||
3941 | /* How much it should wait */ | ||
3942 | u32 value; | ||
3943 | |||
3944 | /* How many times it should repeat that wait value 0 - keep using | ||
3945 | * this timer until PNO is disabled */ | ||
3946 | u32 repeat; | ||
3947 | |||
3948 | /* e.g: 2 3 4 0 - it will wait 2s between consecutive scans for 3 | ||
3949 | * times - after that it will wait 4s between consecutive scans | ||
3950 | * until disabled */ | ||
3951 | }; | ||
3952 | |||
3953 | /* The network parameters to be sent to the PNO algorithm */ | ||
3954 | struct scan_timers_type { | ||
3955 | /* set to 0 if you wish for PNO to use its default telescopic timer */ | ||
3956 | u8 count; | ||
3957 | |||
3958 | /* A set value represents the amount of time that PNO will wait | ||
3959 | * between two consecutive scan procedures If the desired is for a | ||
3960 | * uniform timer that fires always at the exact same interval - one | ||
3961 | * single value is to be set If there is a desire for a more | ||
3962 | * complex - telescopic like timer multiple values can be set - | ||
3963 | * once PNO reaches the end of the array it will continue scanning | ||
3964 | * at intervals presented by the last value */ | ||
3965 | struct scan_timer values[WCN36XX_HAL_PNO_MAX_SCAN_TIMERS]; | ||
3966 | }; | ||
3967 | |||
3968 | /* Preferred network list request */ | ||
3969 | struct set_pref_netw_list_req { | ||
3970 | struct wcn36xx_hal_msg_header header; | ||
3971 | |||
3972 | /* Enable PNO */ | ||
3973 | u32 enable; | ||
3974 | |||
3975 | /* Immediate, On Suspend, On Resume */ | ||
3976 | enum pno_mode mode; | ||
3977 | |||
3978 | /* Number of networks sent for PNO */ | ||
3979 | u32 networks_count; | ||
3980 | |||
3981 | /* The networks that PNO needs to look for */ | ||
3982 | struct network_type networks[WCN36XX_HAL_PNO_MAX_SUPP_NETWORKS]; | ||
3983 | |||
3984 | /* The scan timers required for PNO */ | ||
3985 | struct scan_timers_type scan_timers; | ||
3986 | |||
3987 | /* Probe template for 2.4GHz band */ | ||
3988 | u16 band_24g_probe_size; | ||
3989 | u8 band_24g_probe_template[WCN36XX_HAL_PNO_MAX_PROBE_SIZE]; | ||
3990 | |||
3991 | /* Probe template for 5GHz band */ | ||
3992 | u16 band_5g_probe_size; | ||
3993 | u8 band_5g_probe_template[WCN36XX_HAL_PNO_MAX_PROBE_SIZE]; | ||
3994 | }; | ||
3995 | |||
3996 | /* The network description for which PNO will have to look for */ | ||
3997 | struct network_type_new { | ||
3998 | /* SSID of the BSS */ | ||
3999 | struct wcn36xx_hal_mac_ssid ssid; | ||
4000 | |||
4001 | /* Authentication type for the network */ | ||
4002 | enum auth_type authentication; | ||
4003 | |||
4004 | /* Encryption type for the network */ | ||
4005 | enum ed_type encryption; | ||
4006 | |||
4007 | /* SSID broadcast type, normal, hidden or unknown */ | ||
4008 | enum ssid_bcast_type bcast_network_type; | ||
4009 | |||
4010 | /* Indicate the channel on which the Network can be found 0 - if | ||
4011 | * all channels */ | ||
4012 | u8 channel_count; | ||
4013 | u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS]; | ||
4014 | |||
4015 | /* Indicates the RSSI threshold for the network to be considered */ | ||
4016 | u8 rssi_threshold; | ||
4017 | }; | ||
4018 | |||
4019 | /* Preferred network list request new */ | ||
4020 | struct set_pref_netw_list_req_new { | ||
4021 | struct wcn36xx_hal_msg_header header; | ||
4022 | |||
4023 | /* Enable PNO */ | ||
4024 | u32 enable; | ||
4025 | |||
4026 | /* Immediate, On Suspend, On Resume */ | ||
4027 | enum pno_mode mode; | ||
4028 | |||
4029 | /* Number of networks sent for PNO */ | ||
4030 | u32 networks_count; | ||
4031 | |||
4032 | /* The networks that PNO needs to look for */ | ||
4033 | struct network_type_new networks[WCN36XX_HAL_PNO_MAX_SUPP_NETWORKS]; | ||
4034 | |||
4035 | /* The scan timers required for PNO */ | ||
4036 | struct scan_timers_type scan_timers; | ||
4037 | |||
4038 | /* Probe template for 2.4GHz band */ | ||
4039 | u16 band_24g_probe_size; | ||
4040 | u8 band_24g_probe_template[WCN36XX_HAL_PNO_MAX_PROBE_SIZE]; | ||
4041 | |||
4042 | /* Probe template for 5GHz band */ | ||
4043 | u16 band_5g_probe_size; | ||
4044 | u8 band_5g_probe_template[WCN36XX_HAL_PNO_MAX_PROBE_SIZE]; | ||
4045 | }; | ||
4046 | |||
4047 | /* Preferred network list response */ | ||
4048 | struct set_pref_netw_list_resp { | ||
4049 | struct wcn36xx_hal_msg_header header; | ||
4050 | |||
4051 | /* status of the request - just to indicate that PNO has | ||
4052 | * acknowledged the request and will start scanning */ | ||
4053 | u32 status; | ||
4054 | }; | ||
4055 | |||
4056 | /* Preferred network found indication */ | ||
4057 | struct pref_netw_found_ind { | ||
4058 | |||
4059 | struct wcn36xx_hal_msg_header header; | ||
4060 | |||
4061 | /* Network that was found with the highest RSSI */ | ||
4062 | struct wcn36xx_hal_mac_ssid ssid; | ||
4063 | |||
4064 | /* Indicates the RSSI */ | ||
4065 | u8 rssi; | ||
4066 | }; | ||
4067 | |||
4068 | /* RSSI Filter request */ | ||
4069 | struct set_rssi_filter_req { | ||
4070 | struct wcn36xx_hal_msg_header header; | ||
4071 | |||
4072 | /* RSSI Threshold */ | ||
4073 | u8 rssi_threshold; | ||
4074 | }; | ||
4075 | |||
4076 | /* Set RSSI filter resp */ | ||
4077 | struct set_rssi_filter_resp { | ||
4078 | struct wcn36xx_hal_msg_header header; | ||
4079 | |||
4080 | /* status of the request */ | ||
4081 | u32 status; | ||
4082 | }; | ||
4083 | |||
4084 | /* Update scan params - sent from host to PNO to be used during PNO | ||
4085 | * scanningx */ | ||
4086 | struct wcn36xx_hal_update_scan_params_req { | ||
4087 | |||
4088 | struct wcn36xx_hal_msg_header header; | ||
4089 | |||
4090 | /* Host setting for 11d */ | ||
4091 | u8 dot11d_enabled; | ||
4092 | |||
4093 | /* Lets PNO know that host has determined the regulatory domain */ | ||
4094 | u8 dot11d_resolved; | ||
4095 | |||
4096 | /* Channels on which PNO is allowed to scan */ | ||
4097 | u8 channel_count; | ||
4098 | u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS]; | ||
4099 | |||
4100 | /* Minimum channel time */ | ||
4101 | u16 active_min_ch_time; | ||
4102 | |||
4103 | /* Maximum channel time */ | ||
4104 | u16 active_max_ch_time; | ||
4105 | |||
4106 | /* Minimum channel time */ | ||
4107 | u16 passive_min_ch_time; | ||
4108 | |||
4109 | /* Maximum channel time */ | ||
4110 | u16 passive_max_ch_time; | ||
4111 | |||
4112 | /* Cb State */ | ||
4113 | enum phy_chan_bond_state state; | ||
4114 | } __packed; | ||
4115 | |||
4116 | /* Update scan params - sent from host to PNO to be used during PNO | ||
4117 | * scanningx */ | ||
4118 | struct update_scan_params_req_ex { | ||
4119 | |||
4120 | struct wcn36xx_hal_msg_header header; | ||
4121 | |||
4122 | /* Host setting for 11d */ | ||
4123 | u8 dot11d_enabled; | ||
4124 | |||
4125 | /* Lets PNO know that host has determined the regulatory domain */ | ||
4126 | u8 dot11d_resolved; | ||
4127 | |||
4128 | /* Channels on which PNO is allowed to scan */ | ||
4129 | u8 channel_count; | ||
4130 | u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS_EX]; | ||
4131 | |||
4132 | /* Minimum channel time */ | ||
4133 | u16 active_min_ch_time; | ||
4134 | |||
4135 | /* Maximum channel time */ | ||
4136 | u16 active_max_ch_time; | ||
4137 | |||
4138 | /* Minimum channel time */ | ||
4139 | u16 passive_min_ch_time; | ||
4140 | |||
4141 | /* Maximum channel time */ | ||
4142 | u16 passive_max_ch_time; | ||
4143 | |||
4144 | /* Cb State */ | ||
4145 | enum phy_chan_bond_state state; | ||
4146 | }; | ||
4147 | |||
4148 | /* Update scan params - sent from host to PNO to be used during PNO | ||
4149 | * scanningx */ | ||
4150 | struct wcn36xx_hal_update_scan_params_resp { | ||
4151 | |||
4152 | struct wcn36xx_hal_msg_header header; | ||
4153 | |||
4154 | /* status of the request */ | ||
4155 | u32 status; | ||
4156 | } __packed; | ||
4157 | |||
4158 | struct wcn36xx_hal_set_tx_per_tracking_req_msg { | ||
4159 | struct wcn36xx_hal_msg_header header; | ||
4160 | |||
4161 | /* 0: disable, 1:enable */ | ||
4162 | u8 tx_per_tracking_enable; | ||
4163 | |||
4164 | /* Check period, unit is sec. */ | ||
4165 | u8 tx_per_tracking_period; | ||
4166 | |||
4167 | /* (Fail TX packet)/(Total TX packet) ratio, the unit is 10%. */ | ||
4168 | u8 tx_per_tracking_ratio; | ||
4169 | |||
4170 | /* A watermark of check number, once the tx packet exceed this | ||
4171 | * number, we do the check, default is 5 */ | ||
4172 | u32 tx_per_tracking_watermark; | ||
4173 | }; | ||
4174 | |||
4175 | struct wcn36xx_hal_set_tx_per_tracking_rsp_msg { | ||
4176 | struct wcn36xx_hal_msg_header header; | ||
4177 | |||
4178 | /* success or failure */ | ||
4179 | u32 status; | ||
4180 | |||
4181 | }; | ||
4182 | |||
4183 | struct tx_per_hit_ind_msg { | ||
4184 | struct wcn36xx_hal_msg_header header; | ||
4185 | }; | ||
4186 | |||
4187 | /* Packet Filtering Definitions Begin */ | ||
4188 | #define WCN36XX_HAL_PROTOCOL_DATA_LEN 8 | ||
4189 | #define WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS 240 | ||
4190 | #define WCN36XX_HAL_MAX_NUM_FILTERS 20 | ||
4191 | #define WCN36XX_HAL_MAX_CMP_PER_FILTER 10 | ||
4192 | |||
4193 | enum wcn36xx_hal_receive_packet_filter_type { | ||
4194 | HAL_RCV_FILTER_TYPE_INVALID, | ||
4195 | HAL_RCV_FILTER_TYPE_FILTER_PKT, | ||
4196 | HAL_RCV_FILTER_TYPE_BUFFER_PKT, | ||
4197 | HAL_RCV_FILTER_TYPE_MAX_ENUM_SIZE | ||
4198 | }; | ||
4199 | |||
4200 | enum wcn36xx_hal_rcv_pkt_flt_protocol_type { | ||
4201 | HAL_FILTER_PROTO_TYPE_INVALID, | ||
4202 | HAL_FILTER_PROTO_TYPE_MAC, | ||
4203 | HAL_FILTER_PROTO_TYPE_ARP, | ||
4204 | HAL_FILTER_PROTO_TYPE_IPV4, | ||
4205 | HAL_FILTER_PROTO_TYPE_IPV6, | ||
4206 | HAL_FILTER_PROTO_TYPE_UDP, | ||
4207 | HAL_FILTER_PROTO_TYPE_MAX | ||
4208 | }; | ||
4209 | |||
4210 | enum wcn36xx_hal_rcv_pkt_flt_cmp_flag_type { | ||
4211 | HAL_FILTER_CMP_TYPE_INVALID, | ||
4212 | HAL_FILTER_CMP_TYPE_EQUAL, | ||
4213 | HAL_FILTER_CMP_TYPE_MASK_EQUAL, | ||
4214 | HAL_FILTER_CMP_TYPE_NOT_EQUAL, | ||
4215 | HAL_FILTER_CMP_TYPE_MAX | ||
4216 | }; | ||
4217 | |||
4218 | struct wcn36xx_hal_rcv_pkt_filter_params { | ||
4219 | u8 protocol_layer; | ||
4220 | u8 cmp_flag; | ||
4221 | |||
4222 | /* Length of the data to compare */ | ||
4223 | u16 data_length; | ||
4224 | |||
4225 | /* from start of the respective frame header */ | ||
4226 | u8 data_offset; | ||
4227 | |||
4228 | /* Reserved field */ | ||
4229 | u8 reserved; | ||
4230 | |||
4231 | /* Data to compare */ | ||
4232 | u8 compare_data[WCN36XX_HAL_PROTOCOL_DATA_LEN]; | ||
4233 | |||
4234 | /* Mask to be applied on the received packet data before compare */ | ||
4235 | u8 data_mask[WCN36XX_HAL_PROTOCOL_DATA_LEN]; | ||
4236 | }; | ||
4237 | |||
4238 | struct wcn36xx_hal_sessionized_rcv_pkt_filter_cfg_type { | ||
4239 | u8 id; | ||
4240 | u8 type; | ||
4241 | u8 params_count; | ||
4242 | u32 coleasce_time; | ||
4243 | u8 bss_index; | ||
4244 | struct wcn36xx_hal_rcv_pkt_filter_params params[1]; | ||
4245 | }; | ||
4246 | |||
4247 | struct wcn36xx_hal_set_rcv_pkt_filter_req_msg { | ||
4248 | struct wcn36xx_hal_msg_header header; | ||
4249 | |||
4250 | u8 id; | ||
4251 | u8 type; | ||
4252 | u8 params_count; | ||
4253 | u32 coalesce_time; | ||
4254 | struct wcn36xx_hal_rcv_pkt_filter_params params[1]; | ||
4255 | }; | ||
4256 | |||
4257 | struct wcn36xx_hal_rcv_flt_mc_addr_list_type { | ||
4258 | /* from start of the respective frame header */ | ||
4259 | u8 data_offset; | ||
4260 | |||
4261 | u32 mc_addr_count; | ||
4262 | u8 mc_addr[ETH_ALEN][WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS]; | ||
4263 | u8 bss_index; | ||
4264 | }; | ||
4265 | |||
4266 | struct wcn36xx_hal_set_pkt_filter_rsp_msg { | ||
4267 | struct wcn36xx_hal_msg_header header; | ||
4268 | |||
4269 | /* success or failure */ | ||
4270 | u32 status; | ||
4271 | |||
4272 | u8 bss_index; | ||
4273 | }; | ||
4274 | |||
4275 | struct wcn36xx_hal_rcv_flt_pkt_match_cnt_req_msg { | ||
4276 | struct wcn36xx_hal_msg_header header; | ||
4277 | |||
4278 | u8 bss_index; | ||
4279 | }; | ||
4280 | |||
4281 | struct wcn36xx_hal_rcv_flt_pkt_match_cnt { | ||
4282 | u8 id; | ||
4283 | u32 match_cnt; | ||
4284 | }; | ||
4285 | |||
4286 | struct wcn36xx_hal_rcv_flt_pkt_match_cnt_rsp_msg { | ||
4287 | struct wcn36xx_hal_msg_header header; | ||
4288 | |||
4289 | /* Success or Failure */ | ||
4290 | u32 status; | ||
4291 | |||
4292 | u32 match_count; | ||
4293 | struct wcn36xx_hal_rcv_flt_pkt_match_cnt | ||
4294 | matches[WCN36XX_HAL_MAX_NUM_FILTERS]; | ||
4295 | u8 bss_index; | ||
4296 | }; | ||
4297 | |||
4298 | struct wcn36xx_hal_rcv_flt_pkt_clear_param { | ||
4299 | /* only valid for response message */ | ||
4300 | u32 status; | ||
4301 | u8 id; | ||
4302 | u8 bss_index; | ||
4303 | }; | ||
4304 | |||
4305 | struct wcn36xx_hal_rcv_flt_pkt_clear_req_msg { | ||
4306 | struct wcn36xx_hal_msg_header header; | ||
4307 | struct wcn36xx_hal_rcv_flt_pkt_clear_param param; | ||
4308 | }; | ||
4309 | |||
4310 | struct wcn36xx_hal_rcv_flt_pkt_clear_rsp_msg { | ||
4311 | struct wcn36xx_hal_msg_header header; | ||
4312 | struct wcn36xx_hal_rcv_flt_pkt_clear_param param; | ||
4313 | }; | ||
4314 | |||
4315 | struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_req_msg { | ||
4316 | struct wcn36xx_hal_msg_header header; | ||
4317 | struct wcn36xx_hal_rcv_flt_mc_addr_list_type mc_addr_list; | ||
4318 | }; | ||
4319 | |||
4320 | struct wcn36xx_hal_rcv_flt_pkt_set_mc_list_rsp_msg { | ||
4321 | struct wcn36xx_hal_msg_header header; | ||
4322 | u32 status; | ||
4323 | u8 bss_index; | ||
4324 | }; | ||
4325 | |||
4326 | /* Packet Filtering Definitions End */ | ||
4327 | |||
4328 | struct wcn36xx_hal_set_power_params_req_msg { | ||
4329 | struct wcn36xx_hal_msg_header header; | ||
4330 | |||
4331 | /* Ignore DTIM */ | ||
4332 | u32 ignore_dtim; | ||
4333 | |||
4334 | /* DTIM Period */ | ||
4335 | u32 dtim_period; | ||
4336 | |||
4337 | /* Listen Interval */ | ||
4338 | u32 listen_interval; | ||
4339 | |||
4340 | /* Broadcast Multicast Filter */ | ||
4341 | u32 bcast_mcast_filter; | ||
4342 | |||
4343 | /* Beacon Early Termination */ | ||
4344 | u32 enable_bet; | ||
4345 | |||
4346 | /* Beacon Early Termination Interval */ | ||
4347 | u32 bet_interval; | ||
4348 | } __packed; | ||
4349 | |||
4350 | struct wcn36xx_hal_set_power_params_resp { | ||
4351 | |||
4352 | struct wcn36xx_hal_msg_header header; | ||
4353 | |||
4354 | /* status of the request */ | ||
4355 | u32 status; | ||
4356 | } __packed; | ||
4357 | |||
4358 | /* Capability bitmap exchange definitions and macros starts */ | ||
4359 | |||
4360 | enum place_holder_in_cap_bitmap { | ||
4361 | MCC = 0, | ||
4362 | P2P = 1, | ||
4363 | DOT11AC = 2, | ||
4364 | SLM_SESSIONIZATION = 3, | ||
4365 | DOT11AC_OPMODE = 4, | ||
4366 | SAP32STA = 5, | ||
4367 | TDLS = 6, | ||
4368 | P2P_GO_NOA_DECOUPLE_INIT_SCAN = 7, | ||
4369 | WLANACTIVE_OFFLOAD = 8, | ||
4370 | BEACON_OFFLOAD = 9, | ||
4371 | SCAN_OFFLOAD = 10, | ||
4372 | ROAM_OFFLOAD = 11, | ||
4373 | BCN_MISS_OFFLOAD = 12, | ||
4374 | STA_POWERSAVE = 13, | ||
4375 | STA_ADVANCED_PWRSAVE = 14, | ||
4376 | AP_UAPSD = 15, | ||
4377 | AP_DFS = 16, | ||
4378 | BLOCKACK = 17, | ||
4379 | PHY_ERR = 18, | ||
4380 | BCN_FILTER = 19, | ||
4381 | RTT = 20, | ||
4382 | RATECTRL = 21, | ||
4383 | WOW = 22, | ||
4384 | MAX_FEATURE_SUPPORTED = 128, | ||
4385 | }; | ||
4386 | |||
4387 | struct wcn36xx_hal_feat_caps_msg { | ||
4388 | |||
4389 | struct wcn36xx_hal_msg_header header; | ||
4390 | |||
4391 | u32 feat_caps[4]; | ||
4392 | } __packed; | ||
4393 | |||
4394 | /* status codes to help debug rekey failures */ | ||
4395 | enum gtk_rekey_status { | ||
4396 | WCN36XX_HAL_GTK_REKEY_STATUS_SUCCESS = 0, | ||
4397 | |||
4398 | /* rekey detected, but not handled */ | ||
4399 | WCN36XX_HAL_GTK_REKEY_STATUS_NOT_HANDLED = 1, | ||
4400 | |||
4401 | /* MIC check error on M1 */ | ||
4402 | WCN36XX_HAL_GTK_REKEY_STATUS_MIC_ERROR = 2, | ||
4403 | |||
4404 | /* decryption error on M1 */ | ||
4405 | WCN36XX_HAL_GTK_REKEY_STATUS_DECRYPT_ERROR = 3, | ||
4406 | |||
4407 | /* M1 replay detected */ | ||
4408 | WCN36XX_HAL_GTK_REKEY_STATUS_REPLAY_ERROR = 4, | ||
4409 | |||
4410 | /* missing GTK key descriptor in M1 */ | ||
4411 | WCN36XX_HAL_GTK_REKEY_STATUS_MISSING_KDE = 5, | ||
4412 | |||
4413 | /* missing iGTK key descriptor in M1 */ | ||
4414 | WCN36XX_HAL_GTK_REKEY_STATUS_MISSING_IGTK_KDE = 6, | ||
4415 | |||
4416 | /* key installation error */ | ||
4417 | WCN36XX_HAL_GTK_REKEY_STATUS_INSTALL_ERROR = 7, | ||
4418 | |||
4419 | /* iGTK key installation error */ | ||
4420 | WCN36XX_HAL_GTK_REKEY_STATUS_IGTK_INSTALL_ERROR = 8, | ||
4421 | |||
4422 | /* GTK rekey M2 response TX error */ | ||
4423 | WCN36XX_HAL_GTK_REKEY_STATUS_RESP_TX_ERROR = 9, | ||
4424 | |||
4425 | /* non-specific general error */ | ||
4426 | WCN36XX_HAL_GTK_REKEY_STATUS_GEN_ERROR = 255 | ||
4427 | }; | ||
4428 | |||
4429 | /* wake reason types */ | ||
4430 | enum wake_reason_type { | ||
4431 | WCN36XX_HAL_WAKE_REASON_NONE = 0, | ||
4432 | |||
4433 | /* magic packet match */ | ||
4434 | WCN36XX_HAL_WAKE_REASON_MAGIC_PACKET = 1, | ||
4435 | |||
4436 | /* host defined pattern match */ | ||
4437 | WCN36XX_HAL_WAKE_REASON_PATTERN_MATCH = 2, | ||
4438 | |||
4439 | /* EAP-ID frame detected */ | ||
4440 | WCN36XX_HAL_WAKE_REASON_EAPID_PACKET = 3, | ||
4441 | |||
4442 | /* start of EAPOL 4-way handshake detected */ | ||
4443 | WCN36XX_HAL_WAKE_REASON_EAPOL4WAY_PACKET = 4, | ||
4444 | |||
4445 | /* network scan offload match */ | ||
4446 | WCN36XX_HAL_WAKE_REASON_NETSCAN_OFFL_MATCH = 5, | ||
4447 | |||
4448 | /* GTK rekey status wakeup (see status) */ | ||
4449 | WCN36XX_HAL_WAKE_REASON_GTK_REKEY_STATUS = 6, | ||
4450 | |||
4451 | /* BSS connection lost */ | ||
4452 | WCN36XX_HAL_WAKE_REASON_BSS_CONN_LOST = 7, | ||
4453 | }; | ||
4454 | |||
4455 | /* | ||
4456 | Wake Packet which is saved at tWakeReasonParams.DataStart | ||
4457 | This data is sent for any wake reasons that involve a packet-based wakeup : | ||
4458 | |||
4459 | WCN36XX_HAL_WAKE_REASON_TYPE_MAGIC_PACKET | ||
4460 | WCN36XX_HAL_WAKE_REASON_TYPE_PATTERN_MATCH | ||
4461 | WCN36XX_HAL_WAKE_REASON_TYPE_EAPID_PACKET | ||
4462 | WCN36XX_HAL_WAKE_REASON_TYPE_EAPOL4WAY_PACKET | ||
4463 | WCN36XX_HAL_WAKE_REASON_TYPE_GTK_REKEY_STATUS | ||
4464 | |||
4465 | The information is provided to the host for auditing and debug purposes | ||
4466 | |||
4467 | */ | ||
4468 | |||
4469 | /* Wake reason indication */ | ||
4470 | struct wcn36xx_hal_wake_reason_ind { | ||
4471 | struct wcn36xx_hal_msg_header header; | ||
4472 | |||
4473 | /* see tWakeReasonType */ | ||
4474 | u32 reason; | ||
4475 | |||
4476 | /* argument specific to the reason type */ | ||
4477 | u32 reason_arg; | ||
4478 | |||
4479 | /* length of optional data stored in this message, in case HAL | ||
4480 | * truncates the data (i.e. data packets) this length will be less | ||
4481 | * than the actual length */ | ||
4482 | u32 stored_data_len; | ||
4483 | |||
4484 | /* actual length of data */ | ||
4485 | u32 actual_data_len; | ||
4486 | |||
4487 | /* variable length start of data (length == storedDataLen) see | ||
4488 | * specific wake type */ | ||
4489 | u8 data_start[1]; | ||
4490 | |||
4491 | u32 bss_index:8; | ||
4492 | u32 reserved:24; | ||
4493 | }; | ||
4494 | |||
4495 | #define WCN36XX_HAL_GTK_KEK_BYTES 16 | ||
4496 | #define WCN36XX_HAL_GTK_KCK_BYTES 16 | ||
4497 | |||
4498 | #define WCN36XX_HAL_GTK_OFFLOAD_FLAGS_DISABLE (1 << 0) | ||
4499 | |||
4500 | #define GTK_SET_BSS_KEY_TAG 0x1234AA55 | ||
4501 | |||
4502 | struct wcn36xx_hal_gtk_offload_req_msg { | ||
4503 | struct wcn36xx_hal_msg_header header; | ||
4504 | |||
4505 | /* optional flags */ | ||
4506 | u32 flags; | ||
4507 | |||
4508 | /* Key confirmation key */ | ||
4509 | u8 kck[WCN36XX_HAL_GTK_KCK_BYTES]; | ||
4510 | |||
4511 | /* key encryption key */ | ||
4512 | u8 kek[WCN36XX_HAL_GTK_KEK_BYTES]; | ||
4513 | |||
4514 | /* replay counter */ | ||
4515 | u64 key_replay_counter; | ||
4516 | |||
4517 | u8 bss_index; | ||
4518 | }; | ||
4519 | |||
4520 | struct wcn36xx_hal_gtk_offload_rsp_msg { | ||
4521 | struct wcn36xx_hal_msg_header header; | ||
4522 | |||
4523 | /* success or failure */ | ||
4524 | u32 status; | ||
4525 | |||
4526 | u8 bss_index; | ||
4527 | }; | ||
4528 | |||
4529 | struct wcn36xx_hal_gtk_offload_get_info_req_msg { | ||
4530 | struct wcn36xx_hal_msg_header header; | ||
4531 | u8 bss_index; | ||
4532 | }; | ||
4533 | |||
4534 | struct wcn36xx_hal_gtk_offload_get_info_rsp_msg { | ||
4535 | struct wcn36xx_hal_msg_header header; | ||
4536 | |||
4537 | /* success or failure */ | ||
4538 | u32 status; | ||
4539 | |||
4540 | /* last rekey status when the rekey was offloaded */ | ||
4541 | u32 last_rekey_status; | ||
4542 | |||
4543 | /* current replay counter value */ | ||
4544 | u64 key_replay_counter; | ||
4545 | |||
4546 | /* total rekey attempts */ | ||
4547 | u32 total_rekey_count; | ||
4548 | |||
4549 | /* successful GTK rekeys */ | ||
4550 | u32 gtk_rekey_count; | ||
4551 | |||
4552 | /* successful iGTK rekeys */ | ||
4553 | u32 igtk_rekey_count; | ||
4554 | |||
4555 | u8 bss_index; | ||
4556 | }; | ||
4557 | |||
4558 | struct dhcp_info { | ||
4559 | /* Indicates the device mode which indicates about the DHCP activity */ | ||
4560 | u8 device_mode; | ||
4561 | |||
4562 | u8 addr[ETH_ALEN]; | ||
4563 | }; | ||
4564 | |||
4565 | struct dhcp_ind_status { | ||
4566 | struct wcn36xx_hal_msg_header header; | ||
4567 | |||
4568 | /* success or failure */ | ||
4569 | u32 status; | ||
4570 | }; | ||
4571 | |||
4572 | /* | ||
4573 | * Thermal Mitigation mode of operation. | ||
4574 | * | ||
4575 | * WCN36XX_HAL_THERMAL_MITIGATION_MODE_0 - Based on AMPDU disabling aggregation | ||
4576 | * | ||
4577 | * WCN36XX_HAL_THERMAL_MITIGATION_MODE_1 - Based on AMPDU disabling aggregation | ||
4578 | * and reducing transmit power | ||
4579 | * | ||
4580 | * WCN36XX_HAL_THERMAL_MITIGATION_MODE_2 - Not supported */ | ||
4581 | enum wcn36xx_hal_thermal_mitigation_mode_type { | ||
4582 | HAL_THERMAL_MITIGATION_MODE_INVALID = -1, | ||
4583 | HAL_THERMAL_MITIGATION_MODE_0, | ||
4584 | HAL_THERMAL_MITIGATION_MODE_1, | ||
4585 | HAL_THERMAL_MITIGATION_MODE_2, | ||
4586 | HAL_THERMAL_MITIGATION_MODE_MAX = WCN36XX_HAL_MAX_ENUM_SIZE, | ||
4587 | }; | ||
4588 | |||
4589 | |||
4590 | /* | ||
4591 | * Thermal Mitigation level. | ||
4592 | * Note the levels are incremental i.e WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_2 = | ||
4593 | * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_0 + | ||
4594 | * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_1 | ||
4595 | * | ||
4596 | * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_0 - lowest level of thermal mitigation. | ||
4597 | * This level indicates normal mode of operation | ||
4598 | * | ||
4599 | * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_1 - 1st level of thermal mitigation | ||
4600 | * | ||
4601 | * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_2 - 2nd level of thermal mitigation | ||
4602 | * | ||
4603 | * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_3 - 3rd level of thermal mitigation | ||
4604 | * | ||
4605 | * WCN36XX_HAL_THERMAL_MITIGATION_LEVEL_4 - 4th level of thermal mitigation | ||
4606 | */ | ||
4607 | enum wcn36xx_hal_thermal_mitigation_level_type { | ||
4608 | HAL_THERMAL_MITIGATION_LEVEL_INVALID = -1, | ||
4609 | HAL_THERMAL_MITIGATION_LEVEL_0, | ||
4610 | HAL_THERMAL_MITIGATION_LEVEL_1, | ||
4611 | HAL_THERMAL_MITIGATION_LEVEL_2, | ||
4612 | HAL_THERMAL_MITIGATION_LEVEL_3, | ||
4613 | HAL_THERMAL_MITIGATION_LEVEL_4, | ||
4614 | HAL_THERMAL_MITIGATION_LEVEL_MAX = WCN36XX_HAL_MAX_ENUM_SIZE, | ||
4615 | }; | ||
4616 | |||
4617 | |||
4618 | /* WCN36XX_HAL_SET_THERMAL_MITIGATION_REQ */ | ||
4619 | struct set_thermal_mitigation_req_msg { | ||
4620 | struct wcn36xx_hal_msg_header header; | ||
4621 | |||
4622 | /* Thermal Mitigation Operation Mode */ | ||
4623 | enum wcn36xx_hal_thermal_mitigation_mode_type mode; | ||
4624 | |||
4625 | /* Thermal Mitigation Level */ | ||
4626 | enum wcn36xx_hal_thermal_mitigation_level_type level; | ||
4627 | }; | ||
4628 | |||
4629 | struct set_thermal_mitigation_resp { | ||
4630 | |||
4631 | struct wcn36xx_hal_msg_header header; | ||
4632 | |||
4633 | /* status of the request */ | ||
4634 | u32 status; | ||
4635 | }; | ||
4636 | |||
4637 | /* Per STA Class B Statistics. Class B statistics are STA TX/RX stats | ||
4638 | * provided to FW from Host via periodic messages */ | ||
4639 | struct stats_class_b_ind { | ||
4640 | struct wcn36xx_hal_msg_header header; | ||
4641 | |||
4642 | /* Duration over which this stats was collected */ | ||
4643 | u32 duration; | ||
4644 | |||
4645 | /* Per STA Stats */ | ||
4646 | |||
4647 | /* TX stats */ | ||
4648 | u32 tx_bytes_pushed; | ||
4649 | u32 tx_packets_pushed; | ||
4650 | |||
4651 | /* RX stats */ | ||
4652 | u32 rx_bytes_rcvd; | ||
4653 | u32 rx_packets_rcvd; | ||
4654 | u32 rx_time_total; | ||
4655 | }; | ||
4656 | |||
4657 | #endif /* _HAL_H_ */ | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c new file mode 100644 index 000000000000..7839b31e4826 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/main.c | |||
@@ -0,0 +1,1036 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include "wcn36xx.h" | ||
22 | |||
23 | unsigned int wcn36xx_dbg_mask; | ||
24 | module_param_named(debug_mask, wcn36xx_dbg_mask, uint, 0644); | ||
25 | MODULE_PARM_DESC(debug_mask, "Debugging mask"); | ||
26 | |||
27 | #define CHAN2G(_freq, _idx) { \ | ||
28 | .band = IEEE80211_BAND_2GHZ, \ | ||
29 | .center_freq = (_freq), \ | ||
30 | .hw_value = (_idx), \ | ||
31 | .max_power = 25, \ | ||
32 | } | ||
33 | |||
34 | #define CHAN5G(_freq, _idx) { \ | ||
35 | .band = IEEE80211_BAND_5GHZ, \ | ||
36 | .center_freq = (_freq), \ | ||
37 | .hw_value = (_idx), \ | ||
38 | .max_power = 25, \ | ||
39 | } | ||
40 | |||
41 | /* The wcn firmware expects channel values to matching | ||
42 | * their mnemonic values. So use these for .hw_value. */ | ||
43 | static struct ieee80211_channel wcn_2ghz_channels[] = { | ||
44 | CHAN2G(2412, 1), /* Channel 1 */ | ||
45 | CHAN2G(2417, 2), /* Channel 2 */ | ||
46 | CHAN2G(2422, 3), /* Channel 3 */ | ||
47 | CHAN2G(2427, 4), /* Channel 4 */ | ||
48 | CHAN2G(2432, 5), /* Channel 5 */ | ||
49 | CHAN2G(2437, 6), /* Channel 6 */ | ||
50 | CHAN2G(2442, 7), /* Channel 7 */ | ||
51 | CHAN2G(2447, 8), /* Channel 8 */ | ||
52 | CHAN2G(2452, 9), /* Channel 9 */ | ||
53 | CHAN2G(2457, 10), /* Channel 10 */ | ||
54 | CHAN2G(2462, 11), /* Channel 11 */ | ||
55 | CHAN2G(2467, 12), /* Channel 12 */ | ||
56 | CHAN2G(2472, 13), /* Channel 13 */ | ||
57 | CHAN2G(2484, 14) /* Channel 14 */ | ||
58 | |||
59 | }; | ||
60 | |||
61 | static struct ieee80211_channel wcn_5ghz_channels[] = { | ||
62 | CHAN5G(5180, 36), | ||
63 | CHAN5G(5200, 40), | ||
64 | CHAN5G(5220, 44), | ||
65 | CHAN5G(5240, 48), | ||
66 | CHAN5G(5260, 52), | ||
67 | CHAN5G(5280, 56), | ||
68 | CHAN5G(5300, 60), | ||
69 | CHAN5G(5320, 64), | ||
70 | CHAN5G(5500, 100), | ||
71 | CHAN5G(5520, 104), | ||
72 | CHAN5G(5540, 108), | ||
73 | CHAN5G(5560, 112), | ||
74 | CHAN5G(5580, 116), | ||
75 | CHAN5G(5600, 120), | ||
76 | CHAN5G(5620, 124), | ||
77 | CHAN5G(5640, 128), | ||
78 | CHAN5G(5660, 132), | ||
79 | CHAN5G(5700, 140), | ||
80 | CHAN5G(5745, 149), | ||
81 | CHAN5G(5765, 153), | ||
82 | CHAN5G(5785, 157), | ||
83 | CHAN5G(5805, 161), | ||
84 | CHAN5G(5825, 165) | ||
85 | }; | ||
86 | |||
87 | #define RATE(_bitrate, _hw_rate, _flags) { \ | ||
88 | .bitrate = (_bitrate), \ | ||
89 | .flags = (_flags), \ | ||
90 | .hw_value = (_hw_rate), \ | ||
91 | .hw_value_short = (_hw_rate) \ | ||
92 | } | ||
93 | |||
94 | static struct ieee80211_rate wcn_2ghz_rates[] = { | ||
95 | RATE(10, HW_RATE_INDEX_1MBPS, 0), | ||
96 | RATE(20, HW_RATE_INDEX_2MBPS, IEEE80211_RATE_SHORT_PREAMBLE), | ||
97 | RATE(55, HW_RATE_INDEX_5_5MBPS, IEEE80211_RATE_SHORT_PREAMBLE), | ||
98 | RATE(110, HW_RATE_INDEX_11MBPS, IEEE80211_RATE_SHORT_PREAMBLE), | ||
99 | RATE(60, HW_RATE_INDEX_6MBPS, 0), | ||
100 | RATE(90, HW_RATE_INDEX_9MBPS, 0), | ||
101 | RATE(120, HW_RATE_INDEX_12MBPS, 0), | ||
102 | RATE(180, HW_RATE_INDEX_18MBPS, 0), | ||
103 | RATE(240, HW_RATE_INDEX_24MBPS, 0), | ||
104 | RATE(360, HW_RATE_INDEX_36MBPS, 0), | ||
105 | RATE(480, HW_RATE_INDEX_48MBPS, 0), | ||
106 | RATE(540, HW_RATE_INDEX_54MBPS, 0) | ||
107 | }; | ||
108 | |||
109 | static struct ieee80211_rate wcn_5ghz_rates[] = { | ||
110 | RATE(60, HW_RATE_INDEX_6MBPS, 0), | ||
111 | RATE(90, HW_RATE_INDEX_9MBPS, 0), | ||
112 | RATE(120, HW_RATE_INDEX_12MBPS, 0), | ||
113 | RATE(180, HW_RATE_INDEX_18MBPS, 0), | ||
114 | RATE(240, HW_RATE_INDEX_24MBPS, 0), | ||
115 | RATE(360, HW_RATE_INDEX_36MBPS, 0), | ||
116 | RATE(480, HW_RATE_INDEX_48MBPS, 0), | ||
117 | RATE(540, HW_RATE_INDEX_54MBPS, 0) | ||
118 | }; | ||
119 | |||
120 | static struct ieee80211_supported_band wcn_band_2ghz = { | ||
121 | .channels = wcn_2ghz_channels, | ||
122 | .n_channels = ARRAY_SIZE(wcn_2ghz_channels), | ||
123 | .bitrates = wcn_2ghz_rates, | ||
124 | .n_bitrates = ARRAY_SIZE(wcn_2ghz_rates), | ||
125 | .ht_cap = { | ||
126 | .cap = IEEE80211_HT_CAP_GRN_FLD | | ||
127 | IEEE80211_HT_CAP_SGI_20 | | ||
128 | IEEE80211_HT_CAP_DSSSCCK40 | | ||
129 | IEEE80211_HT_CAP_LSIG_TXOP_PROT, | ||
130 | .ht_supported = true, | ||
131 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, | ||
132 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, | ||
133 | .mcs = { | ||
134 | .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, | ||
135 | .rx_highest = cpu_to_le16(72), | ||
136 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, | ||
137 | } | ||
138 | } | ||
139 | }; | ||
140 | |||
141 | static struct ieee80211_supported_band wcn_band_5ghz = { | ||
142 | .channels = wcn_5ghz_channels, | ||
143 | .n_channels = ARRAY_SIZE(wcn_5ghz_channels), | ||
144 | .bitrates = wcn_5ghz_rates, | ||
145 | .n_bitrates = ARRAY_SIZE(wcn_5ghz_rates), | ||
146 | .ht_cap = { | ||
147 | .cap = IEEE80211_HT_CAP_GRN_FLD | | ||
148 | IEEE80211_HT_CAP_SGI_20 | | ||
149 | IEEE80211_HT_CAP_DSSSCCK40 | | ||
150 | IEEE80211_HT_CAP_LSIG_TXOP_PROT | | ||
151 | IEEE80211_HT_CAP_SGI_40 | | ||
152 | IEEE80211_HT_CAP_SUP_WIDTH_20_40, | ||
153 | .ht_supported = true, | ||
154 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, | ||
155 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, | ||
156 | .mcs = { | ||
157 | .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, | ||
158 | .rx_highest = cpu_to_le16(72), | ||
159 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, | ||
160 | } | ||
161 | } | ||
162 | }; | ||
163 | |||
164 | #ifdef CONFIG_PM | ||
165 | |||
166 | static const struct wiphy_wowlan_support wowlan_support = { | ||
167 | .flags = WIPHY_WOWLAN_ANY | ||
168 | }; | ||
169 | |||
170 | #endif | ||
171 | |||
172 | static inline u8 get_sta_index(struct ieee80211_vif *vif, | ||
173 | struct wcn36xx_sta *sta_priv) | ||
174 | { | ||
175 | return NL80211_IFTYPE_STATION == vif->type ? | ||
176 | sta_priv->bss_sta_index : | ||
177 | sta_priv->sta_index; | ||
178 | } | ||
179 | |||
180 | static int wcn36xx_start(struct ieee80211_hw *hw) | ||
181 | { | ||
182 | struct wcn36xx *wcn = hw->priv; | ||
183 | int ret; | ||
184 | |||
185 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac start\n"); | ||
186 | |||
187 | /* SMD initialization */ | ||
188 | ret = wcn36xx_smd_open(wcn); | ||
189 | if (ret) { | ||
190 | wcn36xx_err("Failed to open smd channel: %d\n", ret); | ||
191 | goto out_err; | ||
192 | } | ||
193 | |||
194 | /* Allocate memory pools for Mgmt BD headers and Data BD headers */ | ||
195 | ret = wcn36xx_dxe_allocate_mem_pools(wcn); | ||
196 | if (ret) { | ||
197 | wcn36xx_err("Failed to alloc DXE mempool: %d\n", ret); | ||
198 | goto out_smd_close; | ||
199 | } | ||
200 | |||
201 | ret = wcn36xx_dxe_alloc_ctl_blks(wcn); | ||
202 | if (ret) { | ||
203 | wcn36xx_err("Failed to alloc DXE ctl blocks: %d\n", ret); | ||
204 | goto out_free_dxe_pool; | ||
205 | } | ||
206 | |||
207 | wcn->hal_buf = kmalloc(WCN36XX_HAL_BUF_SIZE, GFP_KERNEL); | ||
208 | if (!wcn->hal_buf) { | ||
209 | wcn36xx_err("Failed to allocate smd buf\n"); | ||
210 | ret = -ENOMEM; | ||
211 | goto out_free_dxe_ctl; | ||
212 | } | ||
213 | |||
214 | ret = wcn36xx_smd_load_nv(wcn); | ||
215 | if (ret) { | ||
216 | wcn36xx_err("Failed to push NV to chip\n"); | ||
217 | goto out_free_smd_buf; | ||
218 | } | ||
219 | |||
220 | ret = wcn36xx_smd_start(wcn); | ||
221 | if (ret) { | ||
222 | wcn36xx_err("Failed to start chip\n"); | ||
223 | goto out_free_smd_buf; | ||
224 | } | ||
225 | |||
226 | /* DMA channel initialization */ | ||
227 | ret = wcn36xx_dxe_init(wcn); | ||
228 | if (ret) { | ||
229 | wcn36xx_err("DXE init failed\n"); | ||
230 | goto out_smd_stop; | ||
231 | } | ||
232 | |||
233 | wcn36xx_debugfs_init(wcn); | ||
234 | |||
235 | if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { | ||
236 | ret = wcn36xx_smd_feature_caps_exchange(wcn); | ||
237 | if (ret) | ||
238 | wcn36xx_warn("Exchange feature caps failed\n"); | ||
239 | } | ||
240 | INIT_LIST_HEAD(&wcn->vif_list); | ||
241 | return 0; | ||
242 | |||
243 | out_smd_stop: | ||
244 | wcn36xx_smd_stop(wcn); | ||
245 | out_free_smd_buf: | ||
246 | kfree(wcn->hal_buf); | ||
247 | out_free_dxe_pool: | ||
248 | wcn36xx_dxe_free_mem_pools(wcn); | ||
249 | out_free_dxe_ctl: | ||
250 | wcn36xx_dxe_free_ctl_blks(wcn); | ||
251 | out_smd_close: | ||
252 | wcn36xx_smd_close(wcn); | ||
253 | out_err: | ||
254 | return ret; | ||
255 | } | ||
256 | |||
257 | static void wcn36xx_stop(struct ieee80211_hw *hw) | ||
258 | { | ||
259 | struct wcn36xx *wcn = hw->priv; | ||
260 | |||
261 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac stop\n"); | ||
262 | |||
263 | wcn36xx_debugfs_exit(wcn); | ||
264 | wcn36xx_smd_stop(wcn); | ||
265 | wcn36xx_dxe_deinit(wcn); | ||
266 | wcn36xx_smd_close(wcn); | ||
267 | |||
268 | wcn36xx_dxe_free_mem_pools(wcn); | ||
269 | wcn36xx_dxe_free_ctl_blks(wcn); | ||
270 | |||
271 | kfree(wcn->hal_buf); | ||
272 | } | ||
273 | |||
274 | static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed) | ||
275 | { | ||
276 | struct wcn36xx *wcn = hw->priv; | ||
277 | struct ieee80211_vif *vif = NULL; | ||
278 | struct wcn36xx_vif *tmp; | ||
279 | |||
280 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac config changed 0x%08x\n", changed); | ||
281 | |||
282 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | ||
283 | int ch = WCN36XX_HW_CHANNEL(wcn); | ||
284 | wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n", | ||
285 | ch); | ||
286 | list_for_each_entry(tmp, &wcn->vif_list, list) { | ||
287 | vif = container_of((void *)tmp, | ||
288 | struct ieee80211_vif, | ||
289 | drv_priv); | ||
290 | wcn36xx_smd_switch_channel(wcn, vif, ch); | ||
291 | } | ||
292 | } | ||
293 | |||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | #define WCN36XX_SUPPORTED_FILTERS (0) | ||
298 | |||
299 | static void wcn36xx_configure_filter(struct ieee80211_hw *hw, | ||
300 | unsigned int changed, | ||
301 | unsigned int *total, u64 multicast) | ||
302 | { | ||
303 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n"); | ||
304 | |||
305 | *total &= WCN36XX_SUPPORTED_FILTERS; | ||
306 | } | ||
307 | |||
308 | static void wcn36xx_tx(struct ieee80211_hw *hw, | ||
309 | struct ieee80211_tx_control *control, | ||
310 | struct sk_buff *skb) | ||
311 | { | ||
312 | struct wcn36xx *wcn = hw->priv; | ||
313 | struct wcn36xx_sta *sta_priv = NULL; | ||
314 | |||
315 | if (control->sta) | ||
316 | sta_priv = (struct wcn36xx_sta *)control->sta->drv_priv; | ||
317 | |||
318 | if (wcn36xx_start_tx(wcn, sta_priv, skb)) | ||
319 | ieee80211_free_txskb(wcn->hw, skb); | ||
320 | } | ||
321 | |||
322 | static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | ||
323 | struct ieee80211_vif *vif, | ||
324 | struct ieee80211_sta *sta, | ||
325 | struct ieee80211_key_conf *key_conf) | ||
326 | { | ||
327 | struct wcn36xx *wcn = hw->priv; | ||
328 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
329 | struct wcn36xx_sta *sta_priv = vif_priv->sta; | ||
330 | int ret = 0; | ||
331 | u8 key[WLAN_MAX_KEY_LEN]; | ||
332 | |||
333 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 set key\n"); | ||
334 | wcn36xx_dbg(WCN36XX_DBG_MAC, "Key: cmd=0x%x algo:0x%x, id:%d, len:%d flags 0x%x\n", | ||
335 | cmd, key_conf->cipher, key_conf->keyidx, | ||
336 | key_conf->keylen, key_conf->flags); | ||
337 | wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "KEY: ", | ||
338 | key_conf->key, | ||
339 | key_conf->keylen); | ||
340 | |||
341 | switch (key_conf->cipher) { | ||
342 | case WLAN_CIPHER_SUITE_WEP40: | ||
343 | vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40; | ||
344 | break; | ||
345 | case WLAN_CIPHER_SUITE_WEP104: | ||
346 | vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40; | ||
347 | break; | ||
348 | case WLAN_CIPHER_SUITE_CCMP: | ||
349 | vif_priv->encrypt_type = WCN36XX_HAL_ED_CCMP; | ||
350 | break; | ||
351 | case WLAN_CIPHER_SUITE_TKIP: | ||
352 | vif_priv->encrypt_type = WCN36XX_HAL_ED_TKIP; | ||
353 | break; | ||
354 | default: | ||
355 | wcn36xx_err("Unsupported key type 0x%x\n", | ||
356 | key_conf->cipher); | ||
357 | ret = -EOPNOTSUPP; | ||
358 | goto out; | ||
359 | } | ||
360 | |||
361 | switch (cmd) { | ||
362 | case SET_KEY: | ||
363 | if (WCN36XX_HAL_ED_TKIP == vif_priv->encrypt_type) { | ||
364 | /* | ||
365 | * Supplicant is sending key in the wrong order: | ||
366 | * Temporal Key (16 b) - TX MIC (8 b) - RX MIC (8 b) | ||
367 | * but HW expects it to be in the order as described in | ||
368 | * IEEE 802.11 spec (see chapter 11.7) like this: | ||
369 | * Temporal Key (16 b) - RX MIC (8 b) - TX MIC (8 b) | ||
370 | */ | ||
371 | memcpy(key, key_conf->key, 16); | ||
372 | memcpy(key + 16, key_conf->key + 24, 8); | ||
373 | memcpy(key + 24, key_conf->key + 16, 8); | ||
374 | } else { | ||
375 | memcpy(key, key_conf->key, key_conf->keylen); | ||
376 | } | ||
377 | |||
378 | if (IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags) { | ||
379 | sta_priv->is_data_encrypted = true; | ||
380 | /* Reconfigure bss with encrypt_type */ | ||
381 | if (NL80211_IFTYPE_STATION == vif->type) | ||
382 | wcn36xx_smd_config_bss(wcn, | ||
383 | vif, | ||
384 | sta, | ||
385 | sta->addr, | ||
386 | true); | ||
387 | |||
388 | wcn36xx_smd_set_stakey(wcn, | ||
389 | vif_priv->encrypt_type, | ||
390 | key_conf->keyidx, | ||
391 | key_conf->keylen, | ||
392 | key, | ||
393 | get_sta_index(vif, sta_priv)); | ||
394 | } else { | ||
395 | wcn36xx_smd_set_bsskey(wcn, | ||
396 | vif_priv->encrypt_type, | ||
397 | key_conf->keyidx, | ||
398 | key_conf->keylen, | ||
399 | key); | ||
400 | if ((WLAN_CIPHER_SUITE_WEP40 == key_conf->cipher) || | ||
401 | (WLAN_CIPHER_SUITE_WEP104 == key_conf->cipher)) { | ||
402 | sta_priv->is_data_encrypted = true; | ||
403 | wcn36xx_smd_set_stakey(wcn, | ||
404 | vif_priv->encrypt_type, | ||
405 | key_conf->keyidx, | ||
406 | key_conf->keylen, | ||
407 | key, | ||
408 | get_sta_index(vif, sta_priv)); | ||
409 | } | ||
410 | } | ||
411 | break; | ||
412 | case DISABLE_KEY: | ||
413 | if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) { | ||
414 | wcn36xx_smd_remove_bsskey(wcn, | ||
415 | vif_priv->encrypt_type, | ||
416 | key_conf->keyidx); | ||
417 | } else { | ||
418 | sta_priv->is_data_encrypted = false; | ||
419 | /* do not remove key if disassociated */ | ||
420 | if (sta_priv->aid) | ||
421 | wcn36xx_smd_remove_stakey(wcn, | ||
422 | vif_priv->encrypt_type, | ||
423 | key_conf->keyidx, | ||
424 | get_sta_index(vif, sta_priv)); | ||
425 | } | ||
426 | break; | ||
427 | default: | ||
428 | wcn36xx_err("Unsupported key cmd 0x%x\n", cmd); | ||
429 | ret = -EOPNOTSUPP; | ||
430 | goto out; | ||
431 | break; | ||
432 | } | ||
433 | |||
434 | out: | ||
435 | return ret; | ||
436 | } | ||
437 | |||
438 | static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw) | ||
439 | { | ||
440 | struct wcn36xx *wcn = hw->priv; | ||
441 | |||
442 | wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN); | ||
443 | wcn36xx_smd_start_scan(wcn); | ||
444 | } | ||
445 | |||
446 | static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw) | ||
447 | { | ||
448 | struct wcn36xx *wcn = hw->priv; | ||
449 | |||
450 | wcn36xx_smd_end_scan(wcn); | ||
451 | wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN); | ||
452 | } | ||
453 | |||
454 | static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta, | ||
455 | enum ieee80211_band band) | ||
456 | { | ||
457 | int i, size; | ||
458 | u16 *rates_table; | ||
459 | struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; | ||
460 | u32 rates = sta->supp_rates[band]; | ||
461 | |||
462 | memset(&sta_priv->supported_rates, 0, | ||
463 | sizeof(sta_priv->supported_rates)); | ||
464 | sta_priv->supported_rates.op_rate_mode = STA_11n; | ||
465 | |||
466 | size = ARRAY_SIZE(sta_priv->supported_rates.dsss_rates); | ||
467 | rates_table = sta_priv->supported_rates.dsss_rates; | ||
468 | if (band == IEEE80211_BAND_2GHZ) { | ||
469 | for (i = 0; i < size; i++) { | ||
470 | if (rates & 0x01) { | ||
471 | rates_table[i] = wcn_2ghz_rates[i].hw_value; | ||
472 | rates = rates >> 1; | ||
473 | } | ||
474 | } | ||
475 | } | ||
476 | |||
477 | size = ARRAY_SIZE(sta_priv->supported_rates.ofdm_rates); | ||
478 | rates_table = sta_priv->supported_rates.ofdm_rates; | ||
479 | for (i = 0; i < size; i++) { | ||
480 | if (rates & 0x01) { | ||
481 | rates_table[i] = wcn_5ghz_rates[i].hw_value; | ||
482 | rates = rates >> 1; | ||
483 | } | ||
484 | } | ||
485 | |||
486 | if (sta->ht_cap.ht_supported) { | ||
487 | BUILD_BUG_ON(sizeof(sta->ht_cap.mcs.rx_mask) > | ||
488 | sizeof(sta_priv->supported_rates.supported_mcs_set)); | ||
489 | memcpy(sta_priv->supported_rates.supported_mcs_set, | ||
490 | sta->ht_cap.mcs.rx_mask, | ||
491 | sizeof(sta->ht_cap.mcs.rx_mask)); | ||
492 | } | ||
493 | } | ||
494 | void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates) | ||
495 | { | ||
496 | u16 ofdm_rates[WCN36XX_HAL_NUM_OFDM_RATES] = { | ||
497 | HW_RATE_INDEX_6MBPS, | ||
498 | HW_RATE_INDEX_9MBPS, | ||
499 | HW_RATE_INDEX_12MBPS, | ||
500 | HW_RATE_INDEX_18MBPS, | ||
501 | HW_RATE_INDEX_24MBPS, | ||
502 | HW_RATE_INDEX_36MBPS, | ||
503 | HW_RATE_INDEX_48MBPS, | ||
504 | HW_RATE_INDEX_54MBPS | ||
505 | }; | ||
506 | u16 dsss_rates[WCN36XX_HAL_NUM_DSSS_RATES] = { | ||
507 | HW_RATE_INDEX_1MBPS, | ||
508 | HW_RATE_INDEX_2MBPS, | ||
509 | HW_RATE_INDEX_5_5MBPS, | ||
510 | HW_RATE_INDEX_11MBPS | ||
511 | }; | ||
512 | |||
513 | rates->op_rate_mode = STA_11n; | ||
514 | memcpy(rates->dsss_rates, dsss_rates, | ||
515 | sizeof(*dsss_rates) * WCN36XX_HAL_NUM_DSSS_RATES); | ||
516 | memcpy(rates->ofdm_rates, ofdm_rates, | ||
517 | sizeof(*ofdm_rates) * WCN36XX_HAL_NUM_OFDM_RATES); | ||
518 | rates->supported_mcs_set[0] = 0xFF; | ||
519 | } | ||
520 | static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, | ||
521 | struct ieee80211_vif *vif, | ||
522 | struct ieee80211_bss_conf *bss_conf, | ||
523 | u32 changed) | ||
524 | { | ||
525 | struct wcn36xx *wcn = hw->priv; | ||
526 | struct sk_buff *skb = NULL; | ||
527 | u16 tim_off, tim_len; | ||
528 | enum wcn36xx_hal_link_state link_state; | ||
529 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
530 | |||
531 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n", | ||
532 | vif, changed); | ||
533 | |||
534 | if (changed & BSS_CHANGED_BEACON_INFO) { | ||
535 | wcn36xx_dbg(WCN36XX_DBG_MAC, | ||
536 | "mac bss changed dtim period %d\n", | ||
537 | bss_conf->dtim_period); | ||
538 | |||
539 | vif_priv->dtim_period = bss_conf->dtim_period; | ||
540 | } | ||
541 | |||
542 | if (changed & BSS_CHANGED_PS) { | ||
543 | wcn36xx_dbg(WCN36XX_DBG_MAC, | ||
544 | "mac bss PS set %d\n", | ||
545 | bss_conf->ps); | ||
546 | if (bss_conf->ps) { | ||
547 | wcn36xx_pmc_enter_bmps_state(wcn, vif); | ||
548 | } else { | ||
549 | wcn36xx_pmc_exit_bmps_state(wcn, vif); | ||
550 | } | ||
551 | } | ||
552 | |||
553 | if (changed & BSS_CHANGED_BSSID) { | ||
554 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed_bssid %pM\n", | ||
555 | bss_conf->bssid); | ||
556 | |||
557 | if (!is_zero_ether_addr(bss_conf->bssid)) { | ||
558 | vif_priv->is_joining = true; | ||
559 | vif_priv->bss_index = 0xff; | ||
560 | wcn36xx_smd_join(wcn, bss_conf->bssid, | ||
561 | vif->addr, WCN36XX_HW_CHANNEL(wcn)); | ||
562 | wcn36xx_smd_config_bss(wcn, vif, NULL, | ||
563 | bss_conf->bssid, false); | ||
564 | } else { | ||
565 | vif_priv->is_joining = false; | ||
566 | wcn36xx_smd_delete_bss(wcn, vif); | ||
567 | } | ||
568 | } | ||
569 | |||
570 | if (changed & BSS_CHANGED_SSID) { | ||
571 | wcn36xx_dbg(WCN36XX_DBG_MAC, | ||
572 | "mac bss changed ssid\n"); | ||
573 | wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "ssid ", | ||
574 | bss_conf->ssid, bss_conf->ssid_len); | ||
575 | |||
576 | vif_priv->ssid.length = bss_conf->ssid_len; | ||
577 | memcpy(&vif_priv->ssid.ssid, | ||
578 | bss_conf->ssid, | ||
579 | bss_conf->ssid_len); | ||
580 | } | ||
581 | |||
582 | if (changed & BSS_CHANGED_ASSOC) { | ||
583 | vif_priv->is_joining = false; | ||
584 | if (bss_conf->assoc) { | ||
585 | struct ieee80211_sta *sta; | ||
586 | struct wcn36xx_sta *sta_priv; | ||
587 | |||
588 | wcn36xx_dbg(WCN36XX_DBG_MAC, | ||
589 | "mac assoc bss %pM vif %pM AID=%d\n", | ||
590 | bss_conf->bssid, | ||
591 | vif->addr, | ||
592 | bss_conf->aid); | ||
593 | |||
594 | rcu_read_lock(); | ||
595 | sta = ieee80211_find_sta(vif, bss_conf->bssid); | ||
596 | if (!sta) { | ||
597 | wcn36xx_err("sta %pM is not found\n", | ||
598 | bss_conf->bssid); | ||
599 | rcu_read_unlock(); | ||
600 | goto out; | ||
601 | } | ||
602 | sta_priv = (struct wcn36xx_sta *)sta->drv_priv; | ||
603 | |||
604 | wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn)); | ||
605 | |||
606 | wcn36xx_smd_set_link_st(wcn, bss_conf->bssid, | ||
607 | vif->addr, | ||
608 | WCN36XX_HAL_LINK_POSTASSOC_STATE); | ||
609 | wcn36xx_smd_config_bss(wcn, vif, sta, | ||
610 | bss_conf->bssid, | ||
611 | true); | ||
612 | sta_priv->aid = bss_conf->aid; | ||
613 | /* | ||
614 | * config_sta must be called from because this is the | ||
615 | * place where AID is available. | ||
616 | */ | ||
617 | wcn36xx_smd_config_sta(wcn, vif, sta); | ||
618 | rcu_read_unlock(); | ||
619 | } else { | ||
620 | wcn36xx_dbg(WCN36XX_DBG_MAC, | ||
621 | "disassociated bss %pM vif %pM AID=%d\n", | ||
622 | bss_conf->bssid, | ||
623 | vif->addr, | ||
624 | bss_conf->aid); | ||
625 | wcn36xx_smd_set_link_st(wcn, | ||
626 | bss_conf->bssid, | ||
627 | vif->addr, | ||
628 | WCN36XX_HAL_LINK_IDLE_STATE); | ||
629 | } | ||
630 | } | ||
631 | |||
632 | if (changed & BSS_CHANGED_AP_PROBE_RESP) { | ||
633 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed ap probe resp\n"); | ||
634 | skb = ieee80211_proberesp_get(hw, vif); | ||
635 | if (!skb) { | ||
636 | wcn36xx_err("failed to alloc probereq skb\n"); | ||
637 | goto out; | ||
638 | } | ||
639 | |||
640 | wcn36xx_smd_update_proberesp_tmpl(wcn, vif, skb); | ||
641 | dev_kfree_skb(skb); | ||
642 | } | ||
643 | |||
644 | if (changed & BSS_CHANGED_BEACON_ENABLED) { | ||
645 | wcn36xx_dbg(WCN36XX_DBG_MAC, | ||
646 | "mac bss changed beacon enabled %d\n", | ||
647 | bss_conf->enable_beacon); | ||
648 | |||
649 | if (bss_conf->enable_beacon) { | ||
650 | vif_priv->bss_index = 0xff; | ||
651 | wcn36xx_smd_config_bss(wcn, vif, NULL, | ||
652 | vif->addr, false); | ||
653 | skb = ieee80211_beacon_get_tim(hw, vif, &tim_off, | ||
654 | &tim_len); | ||
655 | if (!skb) { | ||
656 | wcn36xx_err("failed to alloc beacon skb\n"); | ||
657 | goto out; | ||
658 | } | ||
659 | wcn36xx_smd_send_beacon(wcn, vif, skb, tim_off, 0); | ||
660 | dev_kfree_skb(skb); | ||
661 | |||
662 | if (vif->type == NL80211_IFTYPE_ADHOC || | ||
663 | vif->type == NL80211_IFTYPE_MESH_POINT) | ||
664 | link_state = WCN36XX_HAL_LINK_IBSS_STATE; | ||
665 | else | ||
666 | link_state = WCN36XX_HAL_LINK_AP_STATE; | ||
667 | |||
668 | wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr, | ||
669 | link_state); | ||
670 | } else { | ||
671 | wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr, | ||
672 | WCN36XX_HAL_LINK_IDLE_STATE); | ||
673 | wcn36xx_smd_delete_bss(wcn, vif); | ||
674 | } | ||
675 | } | ||
676 | out: | ||
677 | return; | ||
678 | } | ||
679 | |||
680 | /* this is required when using IEEE80211_HW_HAS_RATE_CONTROL */ | ||
681 | static int wcn36xx_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | ||
682 | { | ||
683 | struct wcn36xx *wcn = hw->priv; | ||
684 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac set RTS threshold %d\n", value); | ||
685 | |||
686 | wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_RTS_THRESHOLD, value); | ||
687 | return 0; | ||
688 | } | ||
689 | |||
690 | static void wcn36xx_remove_interface(struct ieee80211_hw *hw, | ||
691 | struct ieee80211_vif *vif) | ||
692 | { | ||
693 | struct wcn36xx *wcn = hw->priv; | ||
694 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
695 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif); | ||
696 | |||
697 | list_del(&vif_priv->list); | ||
698 | wcn36xx_smd_delete_sta_self(wcn, vif->addr); | ||
699 | } | ||
700 | |||
701 | static int wcn36xx_add_interface(struct ieee80211_hw *hw, | ||
702 | struct ieee80211_vif *vif) | ||
703 | { | ||
704 | struct wcn36xx *wcn = hw->priv; | ||
705 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
706 | |||
707 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac add interface vif %p type %d\n", | ||
708 | vif, vif->type); | ||
709 | |||
710 | if (!(NL80211_IFTYPE_STATION == vif->type || | ||
711 | NL80211_IFTYPE_AP == vif->type || | ||
712 | NL80211_IFTYPE_ADHOC == vif->type || | ||
713 | NL80211_IFTYPE_MESH_POINT == vif->type)) { | ||
714 | wcn36xx_warn("Unsupported interface type requested: %d\n", | ||
715 | vif->type); | ||
716 | return -EOPNOTSUPP; | ||
717 | } | ||
718 | |||
719 | list_add(&vif_priv->list, &wcn->vif_list); | ||
720 | wcn36xx_smd_add_sta_self(wcn, vif); | ||
721 | |||
722 | return 0; | ||
723 | } | ||
724 | |||
725 | static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
726 | struct ieee80211_sta *sta) | ||
727 | { | ||
728 | struct wcn36xx *wcn = hw->priv; | ||
729 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
730 | struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; | ||
731 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n", | ||
732 | vif, sta->addr); | ||
733 | |||
734 | vif_priv->sta = sta_priv; | ||
735 | sta_priv->vif = vif_priv; | ||
736 | /* | ||
737 | * For STA mode HW will be configured on BSS_CHANGED_ASSOC because | ||
738 | * at this stage AID is not available yet. | ||
739 | */ | ||
740 | if (NL80211_IFTYPE_STATION != vif->type) { | ||
741 | wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn)); | ||
742 | sta_priv->aid = sta->aid; | ||
743 | wcn36xx_smd_config_sta(wcn, vif, sta); | ||
744 | } | ||
745 | return 0; | ||
746 | } | ||
747 | |||
748 | static int wcn36xx_sta_remove(struct ieee80211_hw *hw, | ||
749 | struct ieee80211_vif *vif, | ||
750 | struct ieee80211_sta *sta) | ||
751 | { | ||
752 | struct wcn36xx *wcn = hw->priv; | ||
753 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
754 | struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; | ||
755 | |||
756 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n", | ||
757 | vif, sta->addr, sta_priv->sta_index); | ||
758 | |||
759 | wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index); | ||
760 | vif_priv->sta = NULL; | ||
761 | sta_priv->vif = NULL; | ||
762 | return 0; | ||
763 | } | ||
764 | |||
765 | #ifdef CONFIG_PM | ||
766 | |||
767 | static int wcn36xx_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wow) | ||
768 | { | ||
769 | struct wcn36xx *wcn = hw->priv; | ||
770 | |||
771 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac suspend\n"); | ||
772 | |||
773 | flush_workqueue(wcn->hal_ind_wq); | ||
774 | wcn36xx_smd_set_power_params(wcn, true); | ||
775 | return 0; | ||
776 | } | ||
777 | |||
778 | static int wcn36xx_resume(struct ieee80211_hw *hw) | ||
779 | { | ||
780 | struct wcn36xx *wcn = hw->priv; | ||
781 | |||
782 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac resume\n"); | ||
783 | |||
784 | flush_workqueue(wcn->hal_ind_wq); | ||
785 | wcn36xx_smd_set_power_params(wcn, false); | ||
786 | return 0; | ||
787 | } | ||
788 | |||
789 | #endif | ||
790 | |||
791 | static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, | ||
792 | struct ieee80211_vif *vif, | ||
793 | enum ieee80211_ampdu_mlme_action action, | ||
794 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, | ||
795 | u8 buf_size) | ||
796 | { | ||
797 | struct wcn36xx *wcn = hw->priv; | ||
798 | struct wcn36xx_sta *sta_priv = NULL; | ||
799 | |||
800 | wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n", | ||
801 | action, tid); | ||
802 | |||
803 | sta_priv = (struct wcn36xx_sta *)sta->drv_priv; | ||
804 | |||
805 | switch (action) { | ||
806 | case IEEE80211_AMPDU_RX_START: | ||
807 | sta_priv->tid = tid; | ||
808 | wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 0, | ||
809 | get_sta_index(vif, sta_priv)); | ||
810 | wcn36xx_smd_add_ba(wcn); | ||
811 | wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv)); | ||
812 | ieee80211_start_tx_ba_session(sta, tid, 0); | ||
813 | break; | ||
814 | case IEEE80211_AMPDU_RX_STOP: | ||
815 | wcn36xx_smd_del_ba(wcn, tid, get_sta_index(vif, sta_priv)); | ||
816 | break; | ||
817 | case IEEE80211_AMPDU_TX_START: | ||
818 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
819 | break; | ||
820 | case IEEE80211_AMPDU_TX_OPERATIONAL: | ||
821 | wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 1, | ||
822 | get_sta_index(vif, sta_priv)); | ||
823 | break; | ||
824 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | ||
825 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | ||
826 | case IEEE80211_AMPDU_TX_STOP_CONT: | ||
827 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
828 | break; | ||
829 | default: | ||
830 | wcn36xx_err("Unknown AMPDU action\n"); | ||
831 | } | ||
832 | |||
833 | return 0; | ||
834 | } | ||
835 | |||
836 | static const struct ieee80211_ops wcn36xx_ops = { | ||
837 | .start = wcn36xx_start, | ||
838 | .stop = wcn36xx_stop, | ||
839 | .add_interface = wcn36xx_add_interface, | ||
840 | .remove_interface = wcn36xx_remove_interface, | ||
841 | #ifdef CONFIG_PM | ||
842 | .suspend = wcn36xx_suspend, | ||
843 | .resume = wcn36xx_resume, | ||
844 | #endif | ||
845 | .config = wcn36xx_config, | ||
846 | .configure_filter = wcn36xx_configure_filter, | ||
847 | .tx = wcn36xx_tx, | ||
848 | .set_key = wcn36xx_set_key, | ||
849 | .sw_scan_start = wcn36xx_sw_scan_start, | ||
850 | .sw_scan_complete = wcn36xx_sw_scan_complete, | ||
851 | .bss_info_changed = wcn36xx_bss_info_changed, | ||
852 | .set_rts_threshold = wcn36xx_set_rts_threshold, | ||
853 | .sta_add = wcn36xx_sta_add, | ||
854 | .sta_remove = wcn36xx_sta_remove, | ||
855 | .ampdu_action = wcn36xx_ampdu_action, | ||
856 | }; | ||
857 | |||
858 | static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) | ||
859 | { | ||
860 | int ret = 0; | ||
861 | |||
862 | static const u32 cipher_suites[] = { | ||
863 | WLAN_CIPHER_SUITE_WEP40, | ||
864 | WLAN_CIPHER_SUITE_WEP104, | ||
865 | WLAN_CIPHER_SUITE_TKIP, | ||
866 | WLAN_CIPHER_SUITE_CCMP, | ||
867 | }; | ||
868 | |||
869 | wcn->hw->flags = IEEE80211_HW_SIGNAL_DBM | | ||
870 | IEEE80211_HW_HAS_RATE_CONTROL | | ||
871 | IEEE80211_HW_SUPPORTS_PS | | ||
872 | IEEE80211_HW_CONNECTION_MONITOR | | ||
873 | IEEE80211_HW_AMPDU_AGGREGATION | | ||
874 | IEEE80211_HW_TIMING_BEACON_ONLY; | ||
875 | |||
876 | wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | ||
877 | BIT(NL80211_IFTYPE_AP) | | ||
878 | BIT(NL80211_IFTYPE_ADHOC) | | ||
879 | BIT(NL80211_IFTYPE_MESH_POINT); | ||
880 | |||
881 | wcn->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wcn_band_2ghz; | ||
882 | wcn->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wcn_band_5ghz; | ||
883 | |||
884 | wcn->hw->wiphy->cipher_suites = cipher_suites; | ||
885 | wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | ||
886 | |||
887 | wcn->hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; | ||
888 | |||
889 | #ifdef CONFIG_PM | ||
890 | wcn->hw->wiphy->wowlan = &wowlan_support; | ||
891 | #endif | ||
892 | |||
893 | wcn->hw->max_listen_interval = 200; | ||
894 | |||
895 | wcn->hw->queues = 4; | ||
896 | |||
897 | SET_IEEE80211_DEV(wcn->hw, wcn->dev); | ||
898 | |||
899 | wcn->hw->sta_data_size = sizeof(struct wcn36xx_sta); | ||
900 | wcn->hw->vif_data_size = sizeof(struct wcn36xx_vif); | ||
901 | |||
902 | return ret; | ||
903 | } | ||
904 | |||
905 | static int wcn36xx_platform_get_resources(struct wcn36xx *wcn, | ||
906 | struct platform_device *pdev) | ||
907 | { | ||
908 | struct resource *res; | ||
909 | /* Set TX IRQ */ | ||
910 | res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, | ||
911 | "wcnss_wlantx_irq"); | ||
912 | if (!res) { | ||
913 | wcn36xx_err("failed to get tx_irq\n"); | ||
914 | return -ENOENT; | ||
915 | } | ||
916 | wcn->tx_irq = res->start; | ||
917 | |||
918 | /* Set RX IRQ */ | ||
919 | res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, | ||
920 | "wcnss_wlanrx_irq"); | ||
921 | if (!res) { | ||
922 | wcn36xx_err("failed to get rx_irq\n"); | ||
923 | return -ENOENT; | ||
924 | } | ||
925 | wcn->rx_irq = res->start; | ||
926 | |||
927 | /* Map the memory */ | ||
928 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | ||
929 | "wcnss_mmio"); | ||
930 | if (!res) { | ||
931 | wcn36xx_err("failed to get mmio\n"); | ||
932 | return -ENOENT; | ||
933 | } | ||
934 | wcn->mmio = ioremap(res->start, resource_size(res)); | ||
935 | if (!wcn->mmio) { | ||
936 | wcn36xx_err("failed to map io memory\n"); | ||
937 | return -ENOMEM; | ||
938 | } | ||
939 | return 0; | ||
940 | } | ||
941 | |||
942 | static int wcn36xx_probe(struct platform_device *pdev) | ||
943 | { | ||
944 | struct ieee80211_hw *hw; | ||
945 | struct wcn36xx *wcn; | ||
946 | int ret; | ||
947 | u8 addr[ETH_ALEN]; | ||
948 | |||
949 | wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n"); | ||
950 | |||
951 | hw = ieee80211_alloc_hw(sizeof(struct wcn36xx), &wcn36xx_ops); | ||
952 | if (!hw) { | ||
953 | wcn36xx_err("failed to alloc hw\n"); | ||
954 | ret = -ENOMEM; | ||
955 | goto out_err; | ||
956 | } | ||
957 | platform_set_drvdata(pdev, hw); | ||
958 | wcn = hw->priv; | ||
959 | wcn->hw = hw; | ||
960 | wcn->dev = &pdev->dev; | ||
961 | wcn->ctrl_ops = pdev->dev.platform_data; | ||
962 | |||
963 | mutex_init(&wcn->hal_mutex); | ||
964 | |||
965 | if (!wcn->ctrl_ops->get_hw_mac(addr)) { | ||
966 | wcn36xx_info("mac address: %pM\n", addr); | ||
967 | SET_IEEE80211_PERM_ADDR(wcn->hw, addr); | ||
968 | } | ||
969 | |||
970 | ret = wcn36xx_platform_get_resources(wcn, pdev); | ||
971 | if (ret) | ||
972 | goto out_wq; | ||
973 | |||
974 | wcn36xx_init_ieee80211(wcn); | ||
975 | ret = ieee80211_register_hw(wcn->hw); | ||
976 | if (ret) | ||
977 | goto out_unmap; | ||
978 | |||
979 | return 0; | ||
980 | |||
981 | out_unmap: | ||
982 | iounmap(wcn->mmio); | ||
983 | out_wq: | ||
984 | ieee80211_free_hw(hw); | ||
985 | out_err: | ||
986 | return ret; | ||
987 | } | ||
988 | static int wcn36xx_remove(struct platform_device *pdev) | ||
989 | { | ||
990 | struct ieee80211_hw *hw = platform_get_drvdata(pdev); | ||
991 | struct wcn36xx *wcn = hw->priv; | ||
992 | wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n"); | ||
993 | |||
994 | mutex_destroy(&wcn->hal_mutex); | ||
995 | |||
996 | ieee80211_unregister_hw(hw); | ||
997 | iounmap(wcn->mmio); | ||
998 | ieee80211_free_hw(hw); | ||
999 | |||
1000 | return 0; | ||
1001 | } | ||
1002 | static const struct platform_device_id wcn36xx_platform_id_table[] = { | ||
1003 | { | ||
1004 | .name = "wcn36xx", | ||
1005 | .driver_data = 0 | ||
1006 | }, | ||
1007 | {} | ||
1008 | }; | ||
1009 | MODULE_DEVICE_TABLE(platform, wcn36xx_platform_id_table); | ||
1010 | |||
1011 | static struct platform_driver wcn36xx_driver = { | ||
1012 | .probe = wcn36xx_probe, | ||
1013 | .remove = wcn36xx_remove, | ||
1014 | .driver = { | ||
1015 | .name = "wcn36xx", | ||
1016 | .owner = THIS_MODULE, | ||
1017 | }, | ||
1018 | .id_table = wcn36xx_platform_id_table, | ||
1019 | }; | ||
1020 | |||
1021 | static int __init wcn36xx_init(void) | ||
1022 | { | ||
1023 | platform_driver_register(&wcn36xx_driver); | ||
1024 | return 0; | ||
1025 | } | ||
1026 | module_init(wcn36xx_init); | ||
1027 | |||
1028 | static void __exit wcn36xx_exit(void) | ||
1029 | { | ||
1030 | platform_driver_unregister(&wcn36xx_driver); | ||
1031 | } | ||
1032 | module_exit(wcn36xx_exit); | ||
1033 | |||
1034 | MODULE_LICENSE("Dual BSD/GPL"); | ||
1035 | MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com"); | ||
1036 | MODULE_FIRMWARE(WLAN_NV_FILE); | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/pmc.c b/drivers/net/wireless/ath/wcn36xx/pmc.c new file mode 100644 index 000000000000..28b515c81b0e --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/pmc.c | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
19 | #include "wcn36xx.h" | ||
20 | |||
21 | int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn, | ||
22 | struct ieee80211_vif *vif) | ||
23 | { | ||
24 | int ret = 0; | ||
25 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
26 | /* TODO: Make sure the TX chain clean */ | ||
27 | ret = wcn36xx_smd_enter_bmps(wcn, vif); | ||
28 | if (!ret) { | ||
29 | wcn36xx_dbg(WCN36XX_DBG_PMC, "Entered BMPS\n"); | ||
30 | vif_priv->pw_state = WCN36XX_BMPS; | ||
31 | } else { | ||
32 | /* | ||
33 | * One of the reasons why HW will not enter BMPS is because | ||
34 | * driver is trying to enter bmps before first beacon was | ||
35 | * received just after auth complete | ||
36 | */ | ||
37 | wcn36xx_err("Can not enter BMPS!\n"); | ||
38 | } | ||
39 | return ret; | ||
40 | } | ||
41 | |||
42 | int wcn36xx_pmc_exit_bmps_state(struct wcn36xx *wcn, | ||
43 | struct ieee80211_vif *vif) | ||
44 | { | ||
45 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
46 | |||
47 | if (WCN36XX_BMPS != vif_priv->pw_state) { | ||
48 | wcn36xx_err("Not in BMPS mode, no need to exit from BMPS mode!\n"); | ||
49 | return -EINVAL; | ||
50 | } | ||
51 | wcn36xx_smd_exit_bmps(wcn, vif); | ||
52 | vif_priv->pw_state = WCN36XX_FULL_POWER; | ||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | int wcn36xx_enable_keep_alive_null_packet(struct wcn36xx *wcn, | ||
57 | struct ieee80211_vif *vif) | ||
58 | { | ||
59 | wcn36xx_dbg(WCN36XX_DBG_PMC, "%s\n", __func__); | ||
60 | return wcn36xx_smd_keep_alive_req(wcn, vif, | ||
61 | WCN36XX_HAL_KEEP_ALIVE_NULL_PKT); | ||
62 | } | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/pmc.h b/drivers/net/wireless/ath/wcn36xx/pmc.h new file mode 100644 index 000000000000..f72ed68b5a07 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/pmc.h | |||
@@ -0,0 +1,33 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef _WCN36XX_PMC_H_ | ||
18 | #define _WCN36XX_PMC_H_ | ||
19 | |||
20 | struct wcn36xx; | ||
21 | |||
22 | enum wcn36xx_power_state { | ||
23 | WCN36XX_FULL_POWER, | ||
24 | WCN36XX_BMPS | ||
25 | }; | ||
26 | |||
27 | int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn, | ||
28 | struct ieee80211_vif *vif); | ||
29 | int wcn36xx_pmc_exit_bmps_state(struct wcn36xx *wcn, | ||
30 | struct ieee80211_vif *vif); | ||
31 | int wcn36xx_enable_keep_alive_null_packet(struct wcn36xx *wcn, | ||
32 | struct ieee80211_vif *vif); | ||
33 | #endif /* _WCN36XX_PMC_H_ */ | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c new file mode 100644 index 000000000000..f8c3a10510c2 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/smd.c | |||
@@ -0,0 +1,2126 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
19 | #include <linux/etherdevice.h> | ||
20 | #include <linux/firmware.h> | ||
21 | #include <linux/bitops.h> | ||
22 | #include "smd.h" | ||
23 | |||
24 | static int put_cfg_tlv_u32(struct wcn36xx *wcn, size_t *len, u32 id, u32 value) | ||
25 | { | ||
26 | struct wcn36xx_hal_cfg *entry; | ||
27 | u32 *val; | ||
28 | |||
29 | if (*len + sizeof(*entry) + sizeof(u32) >= WCN36XX_HAL_BUF_SIZE) { | ||
30 | wcn36xx_err("Not enough room for TLV entry\n"); | ||
31 | return -ENOMEM; | ||
32 | } | ||
33 | |||
34 | entry = (struct wcn36xx_hal_cfg *) (wcn->hal_buf + *len); | ||
35 | entry->id = id; | ||
36 | entry->len = sizeof(u32); | ||
37 | entry->pad_bytes = 0; | ||
38 | entry->reserve = 0; | ||
39 | |||
40 | val = (u32 *) (entry + 1); | ||
41 | *val = value; | ||
42 | |||
43 | *len += sizeof(*entry) + sizeof(u32); | ||
44 | |||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | static void wcn36xx_smd_set_bss_nw_type(struct wcn36xx *wcn, | ||
49 | struct ieee80211_sta *sta, | ||
50 | struct wcn36xx_hal_config_bss_params *bss_params) | ||
51 | { | ||
52 | if (IEEE80211_BAND_5GHZ == WCN36XX_BAND(wcn)) | ||
53 | bss_params->nw_type = WCN36XX_HAL_11A_NW_TYPE; | ||
54 | else if (sta && sta->ht_cap.ht_supported) | ||
55 | bss_params->nw_type = WCN36XX_HAL_11N_NW_TYPE; | ||
56 | else if (sta && (sta->supp_rates[IEEE80211_BAND_2GHZ] & 0x7f)) | ||
57 | bss_params->nw_type = WCN36XX_HAL_11G_NW_TYPE; | ||
58 | else | ||
59 | bss_params->nw_type = WCN36XX_HAL_11B_NW_TYPE; | ||
60 | } | ||
61 | |||
62 | static inline u8 is_cap_supported(unsigned long caps, unsigned long flag) | ||
63 | { | ||
64 | return caps & flag ? 1 : 0; | ||
65 | } | ||
66 | static void wcn36xx_smd_set_bss_ht_params(struct ieee80211_vif *vif, | ||
67 | struct ieee80211_sta *sta, | ||
68 | struct wcn36xx_hal_config_bss_params *bss_params) | ||
69 | { | ||
70 | if (sta && sta->ht_cap.ht_supported) { | ||
71 | unsigned long caps = sta->ht_cap.cap; | ||
72 | bss_params->ht = sta->ht_cap.ht_supported; | ||
73 | bss_params->tx_channel_width_set = is_cap_supported(caps, | ||
74 | IEEE80211_HT_CAP_SUP_WIDTH_20_40); | ||
75 | bss_params->lsig_tx_op_protection_full_support = | ||
76 | is_cap_supported(caps, | ||
77 | IEEE80211_HT_CAP_LSIG_TXOP_PROT); | ||
78 | |||
79 | bss_params->ht_oper_mode = vif->bss_conf.ht_operation_mode; | ||
80 | bss_params->lln_non_gf_coexist = | ||
81 | !!(vif->bss_conf.ht_operation_mode & | ||
82 | IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); | ||
83 | /* IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT */ | ||
84 | bss_params->dual_cts_protection = 0; | ||
85 | /* IEEE80211_HT_OP_MODE_PROTECTION_20MHZ */ | ||
86 | bss_params->ht20_coexist = 0; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta *sta, | ||
91 | struct wcn36xx_hal_config_sta_params *sta_params) | ||
92 | { | ||
93 | if (sta->ht_cap.ht_supported) { | ||
94 | unsigned long caps = sta->ht_cap.cap; | ||
95 | sta_params->ht_capable = sta->ht_cap.ht_supported; | ||
96 | sta_params->tx_channel_width_set = is_cap_supported(caps, | ||
97 | IEEE80211_HT_CAP_SUP_WIDTH_20_40); | ||
98 | sta_params->lsig_txop_protection = is_cap_supported(caps, | ||
99 | IEEE80211_HT_CAP_LSIG_TXOP_PROT); | ||
100 | |||
101 | sta_params->max_ampdu_size = sta->ht_cap.ampdu_factor; | ||
102 | sta_params->max_ampdu_density = sta->ht_cap.ampdu_density; | ||
103 | sta_params->max_amsdu_size = is_cap_supported(caps, | ||
104 | IEEE80211_HT_CAP_MAX_AMSDU); | ||
105 | sta_params->sgi_20Mhz = is_cap_supported(caps, | ||
106 | IEEE80211_HT_CAP_SGI_20); | ||
107 | sta_params->sgi_40mhz = is_cap_supported(caps, | ||
108 | IEEE80211_HT_CAP_SGI_40); | ||
109 | sta_params->green_field_capable = is_cap_supported(caps, | ||
110 | IEEE80211_HT_CAP_GRN_FLD); | ||
111 | sta_params->delayed_ba_support = is_cap_supported(caps, | ||
112 | IEEE80211_HT_CAP_DELAY_BA); | ||
113 | sta_params->dsss_cck_mode_40mhz = is_cap_supported(caps, | ||
114 | IEEE80211_HT_CAP_DSSSCCK40); | ||
115 | } | ||
116 | } | ||
117 | |||
118 | static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn, | ||
119 | struct ieee80211_vif *vif, | ||
120 | struct ieee80211_sta *sta, | ||
121 | struct wcn36xx_hal_config_sta_params *sta_params) | ||
122 | { | ||
123 | struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; | ||
124 | struct wcn36xx_sta *priv_sta = NULL; | ||
125 | if (vif->type == NL80211_IFTYPE_ADHOC || | ||
126 | vif->type == NL80211_IFTYPE_AP || | ||
127 | vif->type == NL80211_IFTYPE_MESH_POINT) { | ||
128 | sta_params->type = 1; | ||
129 | sta_params->sta_index = 0xFF; | ||
130 | } else { | ||
131 | sta_params->type = 0; | ||
132 | sta_params->sta_index = 1; | ||
133 | } | ||
134 | |||
135 | sta_params->listen_interval = WCN36XX_LISTEN_INTERVAL(wcn); | ||
136 | |||
137 | /* | ||
138 | * In STA mode ieee80211_sta contains bssid and ieee80211_vif | ||
139 | * contains our mac address. In AP mode we are bssid so vif | ||
140 | * contains bssid and ieee80211_sta contains mac. | ||
141 | */ | ||
142 | if (NL80211_IFTYPE_STATION == vif->type) | ||
143 | memcpy(&sta_params->mac, vif->addr, ETH_ALEN); | ||
144 | else | ||
145 | memcpy(&sta_params->bssid, vif->addr, ETH_ALEN); | ||
146 | |||
147 | sta_params->encrypt_type = priv_vif->encrypt_type; | ||
148 | sta_params->short_preamble_supported = | ||
149 | !(WCN36XX_FLAGS(wcn) & | ||
150 | IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE); | ||
151 | |||
152 | sta_params->rifs_mode = 0; | ||
153 | sta_params->rmf = 0; | ||
154 | sta_params->action = 0; | ||
155 | sta_params->uapsd = 0; | ||
156 | sta_params->mimo_ps = WCN36XX_HAL_HT_MIMO_PS_STATIC; | ||
157 | sta_params->max_ampdu_duration = 0; | ||
158 | sta_params->bssid_index = priv_vif->bss_index; | ||
159 | sta_params->p2p = 0; | ||
160 | |||
161 | if (sta) { | ||
162 | priv_sta = (struct wcn36xx_sta *)sta->drv_priv; | ||
163 | if (NL80211_IFTYPE_STATION == vif->type) | ||
164 | memcpy(&sta_params->bssid, sta->addr, ETH_ALEN); | ||
165 | else | ||
166 | memcpy(&sta_params->mac, sta->addr, ETH_ALEN); | ||
167 | sta_params->wmm_enabled = sta->wme; | ||
168 | sta_params->max_sp_len = sta->max_sp; | ||
169 | sta_params->aid = priv_sta->aid; | ||
170 | wcn36xx_smd_set_sta_ht_params(sta, sta_params); | ||
171 | memcpy(&sta_params->supported_rates, &priv_sta->supported_rates, | ||
172 | sizeof(priv_sta->supported_rates)); | ||
173 | } else { | ||
174 | wcn36xx_set_default_rates(&sta_params->supported_rates); | ||
175 | } | ||
176 | } | ||
177 | |||
178 | static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len) | ||
179 | { | ||
180 | int ret = 0; | ||
181 | wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "HAL >>> ", wcn->hal_buf, len); | ||
182 | |||
183 | init_completion(&wcn->hal_rsp_compl); | ||
184 | ret = wcn->ctrl_ops->tx(wcn->hal_buf, len); | ||
185 | if (ret) { | ||
186 | wcn36xx_err("HAL TX failed\n"); | ||
187 | goto out; | ||
188 | } | ||
189 | if (wait_for_completion_timeout(&wcn->hal_rsp_compl, | ||
190 | msecs_to_jiffies(HAL_MSG_TIMEOUT)) <= 0) { | ||
191 | wcn36xx_err("Timeout while waiting SMD response\n"); | ||
192 | ret = -ETIME; | ||
193 | goto out; | ||
194 | } | ||
195 | out: | ||
196 | return ret; | ||
197 | } | ||
198 | |||
199 | #define INIT_HAL_MSG(msg_body, type) \ | ||
200 | do { \ | ||
201 | memset(&msg_body, 0, sizeof(msg_body)); \ | ||
202 | msg_body.header.msg_type = type; \ | ||
203 | msg_body.header.msg_version = WCN36XX_HAL_MSG_VERSION0; \ | ||
204 | msg_body.header.len = sizeof(msg_body); \ | ||
205 | } while (0) \ | ||
206 | |||
207 | #define PREPARE_HAL_BUF(send_buf, msg_body) \ | ||
208 | do { \ | ||
209 | memset(send_buf, 0, msg_body.header.len); \ | ||
210 | memcpy(send_buf, &msg_body, sizeof(msg_body)); \ | ||
211 | } while (0) \ | ||
212 | |||
213 | static int wcn36xx_smd_rsp_status_check(void *buf, size_t len) | ||
214 | { | ||
215 | struct wcn36xx_fw_msg_status_rsp *rsp; | ||
216 | |||
217 | if (len < sizeof(struct wcn36xx_hal_msg_header) + | ||
218 | sizeof(struct wcn36xx_fw_msg_status_rsp)) | ||
219 | return -EIO; | ||
220 | |||
221 | rsp = (struct wcn36xx_fw_msg_status_rsp *) | ||
222 | (buf + sizeof(struct wcn36xx_hal_msg_header)); | ||
223 | |||
224 | if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status) | ||
225 | return rsp->status; | ||
226 | |||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | int wcn36xx_smd_load_nv(struct wcn36xx *wcn) | ||
231 | { | ||
232 | const struct firmware *nv; | ||
233 | struct nv_data *nv_d; | ||
234 | struct wcn36xx_hal_nv_img_download_req_msg msg_body; | ||
235 | int fw_bytes_left; | ||
236 | int ret; | ||
237 | u16 fm_offset = 0; | ||
238 | |||
239 | ret = request_firmware(&nv, WLAN_NV_FILE, wcn->dev); | ||
240 | if (ret) { | ||
241 | wcn36xx_err("Failed to load nv file %s: %d\n", | ||
242 | WLAN_NV_FILE, ret); | ||
243 | goto out_free_nv; | ||
244 | } | ||
245 | |||
246 | nv_d = (struct nv_data *)nv->data; | ||
247 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_DOWNLOAD_NV_REQ); | ||
248 | |||
249 | msg_body.header.len += WCN36XX_NV_FRAGMENT_SIZE; | ||
250 | |||
251 | msg_body.frag_number = 0; | ||
252 | /* hal_buf must be protected with mutex */ | ||
253 | mutex_lock(&wcn->hal_mutex); | ||
254 | |||
255 | do { | ||
256 | fw_bytes_left = nv->size - fm_offset - 4; | ||
257 | if (fw_bytes_left > WCN36XX_NV_FRAGMENT_SIZE) { | ||
258 | msg_body.last_fragment = 0; | ||
259 | msg_body.nv_img_buffer_size = WCN36XX_NV_FRAGMENT_SIZE; | ||
260 | } else { | ||
261 | msg_body.last_fragment = 1; | ||
262 | msg_body.nv_img_buffer_size = fw_bytes_left; | ||
263 | |||
264 | /* Do not forget update general message len */ | ||
265 | msg_body.header.len = sizeof(msg_body) + fw_bytes_left; | ||
266 | |||
267 | } | ||
268 | |||
269 | /* Add load NV request message header */ | ||
270 | memcpy(wcn->hal_buf, &msg_body, sizeof(msg_body)); | ||
271 | |||
272 | /* Add NV body itself */ | ||
273 | memcpy(wcn->hal_buf + sizeof(msg_body), | ||
274 | &nv_d->table + fm_offset, | ||
275 | msg_body.nv_img_buffer_size); | ||
276 | |||
277 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
278 | if (ret) | ||
279 | goto out_unlock; | ||
280 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, | ||
281 | wcn->hal_rsp_len); | ||
282 | if (ret) { | ||
283 | wcn36xx_err("hal_load_nv response failed err=%d\n", | ||
284 | ret); | ||
285 | goto out_unlock; | ||
286 | } | ||
287 | msg_body.frag_number++; | ||
288 | fm_offset += WCN36XX_NV_FRAGMENT_SIZE; | ||
289 | |||
290 | } while (msg_body.last_fragment != 1); | ||
291 | |||
292 | out_unlock: | ||
293 | mutex_unlock(&wcn->hal_mutex); | ||
294 | out_free_nv: | ||
295 | release_firmware(nv); | ||
296 | |||
297 | return ret; | ||
298 | } | ||
299 | |||
300 | static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len) | ||
301 | { | ||
302 | struct wcn36xx_hal_mac_start_rsp_msg *rsp; | ||
303 | |||
304 | if (len < sizeof(*rsp)) | ||
305 | return -EIO; | ||
306 | |||
307 | rsp = (struct wcn36xx_hal_mac_start_rsp_msg *)buf; | ||
308 | |||
309 | if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->start_rsp_params.status) | ||
310 | return -EIO; | ||
311 | |||
312 | memcpy(wcn->crm_version, rsp->start_rsp_params.crm_version, | ||
313 | WCN36XX_HAL_VERSION_LENGTH); | ||
314 | memcpy(wcn->wlan_version, rsp->start_rsp_params.wlan_version, | ||
315 | WCN36XX_HAL_VERSION_LENGTH); | ||
316 | |||
317 | /* null terminate the strings, just in case */ | ||
318 | wcn->crm_version[WCN36XX_HAL_VERSION_LENGTH] = '\0'; | ||
319 | wcn->wlan_version[WCN36XX_HAL_VERSION_LENGTH] = '\0'; | ||
320 | |||
321 | wcn->fw_revision = rsp->start_rsp_params.version.revision; | ||
322 | wcn->fw_version = rsp->start_rsp_params.version.version; | ||
323 | wcn->fw_minor = rsp->start_rsp_params.version.minor; | ||
324 | wcn->fw_major = rsp->start_rsp_params.version.major; | ||
325 | |||
326 | wcn36xx_info("firmware WLAN version '%s' and CRM version '%s'\n", | ||
327 | wcn->wlan_version, wcn->crm_version); | ||
328 | |||
329 | wcn36xx_info("firmware API %u.%u.%u.%u, %u stations, %u bssids\n", | ||
330 | wcn->fw_major, wcn->fw_minor, | ||
331 | wcn->fw_version, wcn->fw_revision, | ||
332 | rsp->start_rsp_params.stations, | ||
333 | rsp->start_rsp_params.bssids); | ||
334 | |||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | int wcn36xx_smd_start(struct wcn36xx *wcn) | ||
339 | { | ||
340 | struct wcn36xx_hal_mac_start_req_msg msg_body; | ||
341 | int ret = 0; | ||
342 | |||
343 | mutex_lock(&wcn->hal_mutex); | ||
344 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_REQ); | ||
345 | |||
346 | msg_body.params.type = DRIVER_TYPE_PRODUCTION; | ||
347 | msg_body.params.len = 0; | ||
348 | |||
349 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
350 | |||
351 | wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start type %d\n", | ||
352 | msg_body.params.type); | ||
353 | |||
354 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
355 | if (ret) { | ||
356 | wcn36xx_err("Sending hal_start failed\n"); | ||
357 | goto out; | ||
358 | } | ||
359 | |||
360 | ret = wcn36xx_smd_start_rsp(wcn, wcn->hal_buf, wcn->hal_rsp_len); | ||
361 | if (ret) { | ||
362 | wcn36xx_err("hal_start response failed err=%d\n", ret); | ||
363 | goto out; | ||
364 | } | ||
365 | |||
366 | out: | ||
367 | mutex_unlock(&wcn->hal_mutex); | ||
368 | return ret; | ||
369 | } | ||
370 | |||
371 | int wcn36xx_smd_stop(struct wcn36xx *wcn) | ||
372 | { | ||
373 | struct wcn36xx_hal_mac_stop_req_msg msg_body; | ||
374 | int ret = 0; | ||
375 | |||
376 | mutex_lock(&wcn->hal_mutex); | ||
377 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_STOP_REQ); | ||
378 | |||
379 | msg_body.stop_req_params.reason = HAL_STOP_TYPE_RF_KILL; | ||
380 | |||
381 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
382 | |||
383 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
384 | if (ret) { | ||
385 | wcn36xx_err("Sending hal_stop failed\n"); | ||
386 | goto out; | ||
387 | } | ||
388 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
389 | if (ret) { | ||
390 | wcn36xx_err("hal_stop response failed err=%d\n", ret); | ||
391 | goto out; | ||
392 | } | ||
393 | out: | ||
394 | mutex_unlock(&wcn->hal_mutex); | ||
395 | return ret; | ||
396 | } | ||
397 | |||
398 | int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode) | ||
399 | { | ||
400 | struct wcn36xx_hal_init_scan_req_msg msg_body; | ||
401 | int ret = 0; | ||
402 | |||
403 | mutex_lock(&wcn->hal_mutex); | ||
404 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_INIT_SCAN_REQ); | ||
405 | |||
406 | msg_body.mode = mode; | ||
407 | |||
408 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
409 | |||
410 | wcn36xx_dbg(WCN36XX_DBG_HAL, "hal init scan mode %d\n", msg_body.mode); | ||
411 | |||
412 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
413 | if (ret) { | ||
414 | wcn36xx_err("Sending hal_init_scan failed\n"); | ||
415 | goto out; | ||
416 | } | ||
417 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
418 | if (ret) { | ||
419 | wcn36xx_err("hal_init_scan response failed err=%d\n", ret); | ||
420 | goto out; | ||
421 | } | ||
422 | out: | ||
423 | mutex_unlock(&wcn->hal_mutex); | ||
424 | return ret; | ||
425 | } | ||
426 | |||
427 | int wcn36xx_smd_start_scan(struct wcn36xx *wcn) | ||
428 | { | ||
429 | struct wcn36xx_hal_start_scan_req_msg msg_body; | ||
430 | int ret = 0; | ||
431 | |||
432 | mutex_lock(&wcn->hal_mutex); | ||
433 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_SCAN_REQ); | ||
434 | |||
435 | msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn); | ||
436 | |||
437 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
438 | |||
439 | wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start scan channel %d\n", | ||
440 | msg_body.scan_channel); | ||
441 | |||
442 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
443 | if (ret) { | ||
444 | wcn36xx_err("Sending hal_start_scan failed\n"); | ||
445 | goto out; | ||
446 | } | ||
447 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
448 | if (ret) { | ||
449 | wcn36xx_err("hal_start_scan response failed err=%d\n", ret); | ||
450 | goto out; | ||
451 | } | ||
452 | out: | ||
453 | mutex_unlock(&wcn->hal_mutex); | ||
454 | return ret; | ||
455 | } | ||
456 | |||
457 | int wcn36xx_smd_end_scan(struct wcn36xx *wcn) | ||
458 | { | ||
459 | struct wcn36xx_hal_end_scan_req_msg msg_body; | ||
460 | int ret = 0; | ||
461 | |||
462 | mutex_lock(&wcn->hal_mutex); | ||
463 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_END_SCAN_REQ); | ||
464 | |||
465 | msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn); | ||
466 | |||
467 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
468 | |||
469 | wcn36xx_dbg(WCN36XX_DBG_HAL, "hal end scan channel %d\n", | ||
470 | msg_body.scan_channel); | ||
471 | |||
472 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
473 | if (ret) { | ||
474 | wcn36xx_err("Sending hal_end_scan failed\n"); | ||
475 | goto out; | ||
476 | } | ||
477 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
478 | if (ret) { | ||
479 | wcn36xx_err("hal_end_scan response failed err=%d\n", ret); | ||
480 | goto out; | ||
481 | } | ||
482 | out: | ||
483 | mutex_unlock(&wcn->hal_mutex); | ||
484 | return ret; | ||
485 | } | ||
486 | |||
487 | int wcn36xx_smd_finish_scan(struct wcn36xx *wcn, | ||
488 | enum wcn36xx_hal_sys_mode mode) | ||
489 | { | ||
490 | struct wcn36xx_hal_finish_scan_req_msg msg_body; | ||
491 | int ret = 0; | ||
492 | |||
493 | mutex_lock(&wcn->hal_mutex); | ||
494 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_FINISH_SCAN_REQ); | ||
495 | |||
496 | msg_body.mode = mode; | ||
497 | |||
498 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
499 | |||
500 | wcn36xx_dbg(WCN36XX_DBG_HAL, "hal finish scan mode %d\n", | ||
501 | msg_body.mode); | ||
502 | |||
503 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
504 | if (ret) { | ||
505 | wcn36xx_err("Sending hal_finish_scan failed\n"); | ||
506 | goto out; | ||
507 | } | ||
508 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
509 | if (ret) { | ||
510 | wcn36xx_err("hal_finish_scan response failed err=%d\n", ret); | ||
511 | goto out; | ||
512 | } | ||
513 | out: | ||
514 | mutex_unlock(&wcn->hal_mutex); | ||
515 | return ret; | ||
516 | } | ||
517 | |||
518 | static int wcn36xx_smd_switch_channel_rsp(void *buf, size_t len) | ||
519 | { | ||
520 | struct wcn36xx_hal_switch_channel_rsp_msg *rsp; | ||
521 | int ret = 0; | ||
522 | |||
523 | ret = wcn36xx_smd_rsp_status_check(buf, len); | ||
524 | if (ret) | ||
525 | return ret; | ||
526 | rsp = (struct wcn36xx_hal_switch_channel_rsp_msg *)buf; | ||
527 | wcn36xx_dbg(WCN36XX_DBG_HAL, "channel switched to: %d, status: %d\n", | ||
528 | rsp->channel_number, rsp->status); | ||
529 | return ret; | ||
530 | } | ||
531 | |||
532 | int wcn36xx_smd_switch_channel(struct wcn36xx *wcn, | ||
533 | struct ieee80211_vif *vif, int ch) | ||
534 | { | ||
535 | struct wcn36xx_hal_switch_channel_req_msg msg_body; | ||
536 | int ret = 0; | ||
537 | |||
538 | mutex_lock(&wcn->hal_mutex); | ||
539 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_CH_SWITCH_REQ); | ||
540 | |||
541 | msg_body.channel_number = (u8)ch; | ||
542 | msg_body.tx_mgmt_power = 0xbf; | ||
543 | msg_body.max_tx_power = 0xbf; | ||
544 | memcpy(msg_body.self_sta_mac_addr, vif->addr, ETH_ALEN); | ||
545 | |||
546 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
547 | |||
548 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
549 | if (ret) { | ||
550 | wcn36xx_err("Sending hal_switch_channel failed\n"); | ||
551 | goto out; | ||
552 | } | ||
553 | ret = wcn36xx_smd_switch_channel_rsp(wcn->hal_buf, wcn->hal_rsp_len); | ||
554 | if (ret) { | ||
555 | wcn36xx_err("hal_switch_channel response failed err=%d\n", ret); | ||
556 | goto out; | ||
557 | } | ||
558 | out: | ||
559 | mutex_unlock(&wcn->hal_mutex); | ||
560 | return ret; | ||
561 | } | ||
562 | |||
563 | static int wcn36xx_smd_update_scan_params_rsp(void *buf, size_t len) | ||
564 | { | ||
565 | struct wcn36xx_hal_update_scan_params_resp *rsp; | ||
566 | |||
567 | rsp = (struct wcn36xx_hal_update_scan_params_resp *)buf; | ||
568 | |||
569 | /* Remove the PNO version bit */ | ||
570 | rsp->status &= (~(WCN36XX_FW_MSG_PNO_VERSION_MASK)); | ||
571 | |||
572 | if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status) { | ||
573 | wcn36xx_warn("error response from update scan\n"); | ||
574 | return rsp->status; | ||
575 | } | ||
576 | |||
577 | return 0; | ||
578 | } | ||
579 | |||
580 | int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn) | ||
581 | { | ||
582 | struct wcn36xx_hal_update_scan_params_req msg_body; | ||
583 | int ret = 0; | ||
584 | |||
585 | mutex_lock(&wcn->hal_mutex); | ||
586 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ); | ||
587 | |||
588 | msg_body.dot11d_enabled = 0; | ||
589 | msg_body.dot11d_resolved = 0; | ||
590 | msg_body.channel_count = 26; | ||
591 | msg_body.active_min_ch_time = 60; | ||
592 | msg_body.active_max_ch_time = 120; | ||
593 | msg_body.passive_min_ch_time = 60; | ||
594 | msg_body.passive_max_ch_time = 110; | ||
595 | msg_body.state = 0; | ||
596 | |||
597 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
598 | |||
599 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
600 | "hal update scan params channel_count %d\n", | ||
601 | msg_body.channel_count); | ||
602 | |||
603 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
604 | if (ret) { | ||
605 | wcn36xx_err("Sending hal_update_scan_params failed\n"); | ||
606 | goto out; | ||
607 | } | ||
608 | ret = wcn36xx_smd_update_scan_params_rsp(wcn->hal_buf, | ||
609 | wcn->hal_rsp_len); | ||
610 | if (ret) { | ||
611 | wcn36xx_err("hal_update_scan_params response failed err=%d\n", | ||
612 | ret); | ||
613 | goto out; | ||
614 | } | ||
615 | out: | ||
616 | mutex_unlock(&wcn->hal_mutex); | ||
617 | return ret; | ||
618 | } | ||
619 | |||
620 | static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn, | ||
621 | struct ieee80211_vif *vif, | ||
622 | void *buf, | ||
623 | size_t len) | ||
624 | { | ||
625 | struct wcn36xx_hal_add_sta_self_rsp_msg *rsp; | ||
626 | struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; | ||
627 | |||
628 | if (len < sizeof(*rsp)) | ||
629 | return -EINVAL; | ||
630 | |||
631 | rsp = (struct wcn36xx_hal_add_sta_self_rsp_msg *)buf; | ||
632 | |||
633 | if (rsp->status != WCN36XX_FW_MSG_RESULT_SUCCESS) { | ||
634 | wcn36xx_warn("hal add sta self failure: %d\n", | ||
635 | rsp->status); | ||
636 | return rsp->status; | ||
637 | } | ||
638 | |||
639 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
640 | "hal add sta self status %d self_sta_index %d dpu_index %d\n", | ||
641 | rsp->status, rsp->self_sta_index, rsp->dpu_index); | ||
642 | |||
643 | priv_vif->self_sta_index = rsp->self_sta_index; | ||
644 | priv_vif->self_dpu_desc_index = rsp->dpu_index; | ||
645 | |||
646 | return 0; | ||
647 | } | ||
648 | |||
649 | int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif) | ||
650 | { | ||
651 | struct wcn36xx_hal_add_sta_self_req msg_body; | ||
652 | int ret = 0; | ||
653 | |||
654 | mutex_lock(&wcn->hal_mutex); | ||
655 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_STA_SELF_REQ); | ||
656 | |||
657 | memcpy(&msg_body.self_addr, vif->addr, ETH_ALEN); | ||
658 | |||
659 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
660 | |||
661 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
662 | "hal add sta self self_addr %pM status %d\n", | ||
663 | msg_body.self_addr, msg_body.status); | ||
664 | |||
665 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
666 | if (ret) { | ||
667 | wcn36xx_err("Sending hal_add_sta_self failed\n"); | ||
668 | goto out; | ||
669 | } | ||
670 | ret = wcn36xx_smd_add_sta_self_rsp(wcn, | ||
671 | vif, | ||
672 | wcn->hal_buf, | ||
673 | wcn->hal_rsp_len); | ||
674 | if (ret) { | ||
675 | wcn36xx_err("hal_add_sta_self response failed err=%d\n", ret); | ||
676 | goto out; | ||
677 | } | ||
678 | out: | ||
679 | mutex_unlock(&wcn->hal_mutex); | ||
680 | return ret; | ||
681 | } | ||
682 | |||
683 | int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr) | ||
684 | { | ||
685 | struct wcn36xx_hal_del_sta_self_req_msg msg_body; | ||
686 | int ret = 0; | ||
687 | |||
688 | mutex_lock(&wcn->hal_mutex); | ||
689 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_STA_SELF_REQ); | ||
690 | |||
691 | memcpy(&msg_body.self_addr, addr, ETH_ALEN); | ||
692 | |||
693 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
694 | |||
695 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
696 | if (ret) { | ||
697 | wcn36xx_err("Sending hal_delete_sta_self failed\n"); | ||
698 | goto out; | ||
699 | } | ||
700 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
701 | if (ret) { | ||
702 | wcn36xx_err("hal_delete_sta_self response failed err=%d\n", | ||
703 | ret); | ||
704 | goto out; | ||
705 | } | ||
706 | out: | ||
707 | mutex_unlock(&wcn->hal_mutex); | ||
708 | return ret; | ||
709 | } | ||
710 | |||
711 | int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index) | ||
712 | { | ||
713 | struct wcn36xx_hal_delete_sta_req_msg msg_body; | ||
714 | int ret = 0; | ||
715 | |||
716 | mutex_lock(&wcn->hal_mutex); | ||
717 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_STA_REQ); | ||
718 | |||
719 | msg_body.sta_index = sta_index; | ||
720 | |||
721 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
722 | |||
723 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
724 | "hal delete sta sta_index %d\n", | ||
725 | msg_body.sta_index); | ||
726 | |||
727 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
728 | if (ret) { | ||
729 | wcn36xx_err("Sending hal_delete_sta failed\n"); | ||
730 | goto out; | ||
731 | } | ||
732 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
733 | if (ret) { | ||
734 | wcn36xx_err("hal_delete_sta response failed err=%d\n", ret); | ||
735 | goto out; | ||
736 | } | ||
737 | out: | ||
738 | mutex_unlock(&wcn->hal_mutex); | ||
739 | return ret; | ||
740 | } | ||
741 | |||
742 | static int wcn36xx_smd_join_rsp(void *buf, size_t len) | ||
743 | { | ||
744 | struct wcn36xx_hal_join_rsp_msg *rsp; | ||
745 | |||
746 | if (wcn36xx_smd_rsp_status_check(buf, len)) | ||
747 | return -EIO; | ||
748 | |||
749 | rsp = (struct wcn36xx_hal_join_rsp_msg *)buf; | ||
750 | |||
751 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
752 | "hal rsp join status %d tx_mgmt_power %d\n", | ||
753 | rsp->status, rsp->tx_mgmt_power); | ||
754 | |||
755 | return 0; | ||
756 | } | ||
757 | |||
758 | int wcn36xx_smd_join(struct wcn36xx *wcn, const u8 *bssid, u8 *vif, u8 ch) | ||
759 | { | ||
760 | struct wcn36xx_hal_join_req_msg msg_body; | ||
761 | int ret = 0; | ||
762 | |||
763 | mutex_lock(&wcn->hal_mutex); | ||
764 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_JOIN_REQ); | ||
765 | |||
766 | memcpy(&msg_body.bssid, bssid, ETH_ALEN); | ||
767 | memcpy(&msg_body.self_sta_mac_addr, vif, ETH_ALEN); | ||
768 | msg_body.channel = ch; | ||
769 | |||
770 | if (conf_is_ht40_minus(&wcn->hw->conf)) | ||
771 | msg_body.secondary_channel_offset = | ||
772 | PHY_DOUBLE_CHANNEL_HIGH_PRIMARY; | ||
773 | else if (conf_is_ht40_plus(&wcn->hw->conf)) | ||
774 | msg_body.secondary_channel_offset = | ||
775 | PHY_DOUBLE_CHANNEL_LOW_PRIMARY; | ||
776 | else | ||
777 | msg_body.secondary_channel_offset = | ||
778 | PHY_SINGLE_CHANNEL_CENTERED; | ||
779 | |||
780 | msg_body.link_state = WCN36XX_HAL_LINK_PREASSOC_STATE; | ||
781 | |||
782 | msg_body.max_tx_power = 0xbf; | ||
783 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
784 | |||
785 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
786 | "hal join req bssid %pM self_sta_mac_addr %pM channel %d link_state %d\n", | ||
787 | msg_body.bssid, msg_body.self_sta_mac_addr, | ||
788 | msg_body.channel, msg_body.link_state); | ||
789 | |||
790 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
791 | if (ret) { | ||
792 | wcn36xx_err("Sending hal_join failed\n"); | ||
793 | goto out; | ||
794 | } | ||
795 | ret = wcn36xx_smd_join_rsp(wcn->hal_buf, wcn->hal_rsp_len); | ||
796 | if (ret) { | ||
797 | wcn36xx_err("hal_join response failed err=%d\n", ret); | ||
798 | goto out; | ||
799 | } | ||
800 | out: | ||
801 | mutex_unlock(&wcn->hal_mutex); | ||
802 | return ret; | ||
803 | } | ||
804 | |||
805 | int wcn36xx_smd_set_link_st(struct wcn36xx *wcn, const u8 *bssid, | ||
806 | const u8 *sta_mac, | ||
807 | enum wcn36xx_hal_link_state state) | ||
808 | { | ||
809 | struct wcn36xx_hal_set_link_state_req_msg msg_body; | ||
810 | int ret = 0; | ||
811 | |||
812 | mutex_lock(&wcn->hal_mutex); | ||
813 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_LINK_ST_REQ); | ||
814 | |||
815 | memcpy(&msg_body.bssid, bssid, ETH_ALEN); | ||
816 | memcpy(&msg_body.self_mac_addr, sta_mac, ETH_ALEN); | ||
817 | msg_body.state = state; | ||
818 | |||
819 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
820 | |||
821 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
822 | "hal set link state bssid %pM self_mac_addr %pM state %d\n", | ||
823 | msg_body.bssid, msg_body.self_mac_addr, msg_body.state); | ||
824 | |||
825 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
826 | if (ret) { | ||
827 | wcn36xx_err("Sending hal_set_link_st failed\n"); | ||
828 | goto out; | ||
829 | } | ||
830 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
831 | if (ret) { | ||
832 | wcn36xx_err("hal_set_link_st response failed err=%d\n", ret); | ||
833 | goto out; | ||
834 | } | ||
835 | out: | ||
836 | mutex_unlock(&wcn->hal_mutex); | ||
837 | return ret; | ||
838 | } | ||
839 | |||
840 | static void wcn36xx_smd_convert_sta_to_v1(struct wcn36xx *wcn, | ||
841 | const struct wcn36xx_hal_config_sta_params *orig, | ||
842 | struct wcn36xx_hal_config_sta_params_v1 *v1) | ||
843 | { | ||
844 | /* convert orig to v1 format */ | ||
845 | memcpy(&v1->bssid, orig->bssid, ETH_ALEN); | ||
846 | memcpy(&v1->mac, orig->mac, ETH_ALEN); | ||
847 | v1->aid = orig->aid; | ||
848 | v1->type = orig->type; | ||
849 | v1->listen_interval = orig->listen_interval; | ||
850 | v1->ht_capable = orig->ht_capable; | ||
851 | |||
852 | v1->max_ampdu_size = orig->max_ampdu_size; | ||
853 | v1->max_ampdu_density = orig->max_ampdu_density; | ||
854 | v1->sgi_40mhz = orig->sgi_40mhz; | ||
855 | v1->sgi_20Mhz = orig->sgi_20Mhz; | ||
856 | |||
857 | memcpy(&v1->supported_rates, &orig->supported_rates, | ||
858 | sizeof(orig->supported_rates)); | ||
859 | v1->sta_index = orig->sta_index; | ||
860 | } | ||
861 | |||
862 | static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn, | ||
863 | struct ieee80211_sta *sta, | ||
864 | void *buf, | ||
865 | size_t len) | ||
866 | { | ||
867 | struct wcn36xx_hal_config_sta_rsp_msg *rsp; | ||
868 | struct config_sta_rsp_params *params; | ||
869 | struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv; | ||
870 | |||
871 | if (len < sizeof(*rsp)) | ||
872 | return -EINVAL; | ||
873 | |||
874 | rsp = (struct wcn36xx_hal_config_sta_rsp_msg *)buf; | ||
875 | params = &rsp->params; | ||
876 | |||
877 | if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) { | ||
878 | wcn36xx_warn("hal config sta response failure: %d\n", | ||
879 | params->status); | ||
880 | return -EIO; | ||
881 | } | ||
882 | |||
883 | sta_priv->sta_index = params->sta_index; | ||
884 | sta_priv->dpu_desc_index = params->dpu_index; | ||
885 | |||
886 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
887 | "hal config sta rsp status %d sta_index %d bssid_index %d p2p %d\n", | ||
888 | params->status, params->sta_index, params->bssid_index, | ||
889 | params->p2p); | ||
890 | |||
891 | return 0; | ||
892 | } | ||
893 | |||
894 | static int wcn36xx_smd_config_sta_v1(struct wcn36xx *wcn, | ||
895 | const struct wcn36xx_hal_config_sta_req_msg *orig) | ||
896 | { | ||
897 | struct wcn36xx_hal_config_sta_req_msg_v1 msg_body; | ||
898 | struct wcn36xx_hal_config_sta_params_v1 *sta = &msg_body.sta_params; | ||
899 | |||
900 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_STA_REQ); | ||
901 | |||
902 | wcn36xx_smd_convert_sta_to_v1(wcn, &orig->sta_params, | ||
903 | &msg_body.sta_params); | ||
904 | |||
905 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
906 | |||
907 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
908 | "hal config sta v1 action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n", | ||
909 | sta->action, sta->sta_index, sta->bssid_index, | ||
910 | sta->bssid, sta->type, sta->mac, sta->aid); | ||
911 | |||
912 | return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
913 | } | ||
914 | |||
915 | int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif, | ||
916 | struct ieee80211_sta *sta) | ||
917 | { | ||
918 | struct wcn36xx_hal_config_sta_req_msg msg; | ||
919 | struct wcn36xx_hal_config_sta_params *sta_params; | ||
920 | int ret = 0; | ||
921 | |||
922 | mutex_lock(&wcn->hal_mutex); | ||
923 | INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_STA_REQ); | ||
924 | |||
925 | sta_params = &msg.sta_params; | ||
926 | |||
927 | wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params); | ||
928 | |||
929 | if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { | ||
930 | ret = wcn36xx_smd_config_sta_v1(wcn, &msg); | ||
931 | } else { | ||
932 | PREPARE_HAL_BUF(wcn->hal_buf, msg); | ||
933 | |||
934 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
935 | "hal config sta action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n", | ||
936 | sta_params->action, sta_params->sta_index, | ||
937 | sta_params->bssid_index, sta_params->bssid, | ||
938 | sta_params->type, sta_params->mac, sta_params->aid); | ||
939 | |||
940 | ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len); | ||
941 | } | ||
942 | if (ret) { | ||
943 | wcn36xx_err("Sending hal_config_sta failed\n"); | ||
944 | goto out; | ||
945 | } | ||
946 | ret = wcn36xx_smd_config_sta_rsp(wcn, | ||
947 | sta, | ||
948 | wcn->hal_buf, | ||
949 | wcn->hal_rsp_len); | ||
950 | if (ret) { | ||
951 | wcn36xx_err("hal_config_sta response failed err=%d\n", ret); | ||
952 | goto out; | ||
953 | } | ||
954 | out: | ||
955 | mutex_unlock(&wcn->hal_mutex); | ||
956 | return ret; | ||
957 | } | ||
958 | |||
959 | static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn, | ||
960 | const struct wcn36xx_hal_config_bss_req_msg *orig) | ||
961 | { | ||
962 | struct wcn36xx_hal_config_bss_req_msg_v1 msg_body; | ||
963 | struct wcn36xx_hal_config_bss_params_v1 *bss = &msg_body.bss_params; | ||
964 | struct wcn36xx_hal_config_sta_params_v1 *sta = &bss->sta; | ||
965 | |||
966 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_BSS_REQ); | ||
967 | |||
968 | /* convert orig to v1 */ | ||
969 | memcpy(&msg_body.bss_params.bssid, | ||
970 | &orig->bss_params.bssid, ETH_ALEN); | ||
971 | memcpy(&msg_body.bss_params.self_mac_addr, | ||
972 | &orig->bss_params.self_mac_addr, ETH_ALEN); | ||
973 | |||
974 | msg_body.bss_params.bss_type = orig->bss_params.bss_type; | ||
975 | msg_body.bss_params.oper_mode = orig->bss_params.oper_mode; | ||
976 | msg_body.bss_params.nw_type = orig->bss_params.nw_type; | ||
977 | |||
978 | msg_body.bss_params.short_slot_time_supported = | ||
979 | orig->bss_params.short_slot_time_supported; | ||
980 | msg_body.bss_params.lla_coexist = orig->bss_params.lla_coexist; | ||
981 | msg_body.bss_params.llb_coexist = orig->bss_params.llb_coexist; | ||
982 | msg_body.bss_params.llg_coexist = orig->bss_params.llg_coexist; | ||
983 | msg_body.bss_params.ht20_coexist = orig->bss_params.ht20_coexist; | ||
984 | msg_body.bss_params.lln_non_gf_coexist = | ||
985 | orig->bss_params.lln_non_gf_coexist; | ||
986 | |||
987 | msg_body.bss_params.lsig_tx_op_protection_full_support = | ||
988 | orig->bss_params.lsig_tx_op_protection_full_support; | ||
989 | msg_body.bss_params.rifs_mode = orig->bss_params.rifs_mode; | ||
990 | msg_body.bss_params.beacon_interval = orig->bss_params.beacon_interval; | ||
991 | msg_body.bss_params.dtim_period = orig->bss_params.dtim_period; | ||
992 | msg_body.bss_params.tx_channel_width_set = | ||
993 | orig->bss_params.tx_channel_width_set; | ||
994 | msg_body.bss_params.oper_channel = orig->bss_params.oper_channel; | ||
995 | msg_body.bss_params.ext_channel = orig->bss_params.ext_channel; | ||
996 | |||
997 | msg_body.bss_params.reserved = orig->bss_params.reserved; | ||
998 | |||
999 | memcpy(&msg_body.bss_params.ssid, | ||
1000 | &orig->bss_params.ssid, | ||
1001 | sizeof(orig->bss_params.ssid)); | ||
1002 | |||
1003 | msg_body.bss_params.action = orig->bss_params.action; | ||
1004 | msg_body.bss_params.rateset = orig->bss_params.rateset; | ||
1005 | msg_body.bss_params.ht = orig->bss_params.ht; | ||
1006 | msg_body.bss_params.obss_prot_enabled = | ||
1007 | orig->bss_params.obss_prot_enabled; | ||
1008 | msg_body.bss_params.rmf = orig->bss_params.rmf; | ||
1009 | msg_body.bss_params.ht_oper_mode = orig->bss_params.ht_oper_mode; | ||
1010 | msg_body.bss_params.dual_cts_protection = | ||
1011 | orig->bss_params.dual_cts_protection; | ||
1012 | |||
1013 | msg_body.bss_params.max_probe_resp_retry_limit = | ||
1014 | orig->bss_params.max_probe_resp_retry_limit; | ||
1015 | msg_body.bss_params.hidden_ssid = orig->bss_params.hidden_ssid; | ||
1016 | msg_body.bss_params.proxy_probe_resp = | ||
1017 | orig->bss_params.proxy_probe_resp; | ||
1018 | msg_body.bss_params.edca_params_valid = | ||
1019 | orig->bss_params.edca_params_valid; | ||
1020 | |||
1021 | memcpy(&msg_body.bss_params.acbe, | ||
1022 | &orig->bss_params.acbe, | ||
1023 | sizeof(orig->bss_params.acbe)); | ||
1024 | memcpy(&msg_body.bss_params.acbk, | ||
1025 | &orig->bss_params.acbk, | ||
1026 | sizeof(orig->bss_params.acbk)); | ||
1027 | memcpy(&msg_body.bss_params.acvi, | ||
1028 | &orig->bss_params.acvi, | ||
1029 | sizeof(orig->bss_params.acvi)); | ||
1030 | memcpy(&msg_body.bss_params.acvo, | ||
1031 | &orig->bss_params.acvo, | ||
1032 | sizeof(orig->bss_params.acvo)); | ||
1033 | |||
1034 | msg_body.bss_params.ext_set_sta_key_param_valid = | ||
1035 | orig->bss_params.ext_set_sta_key_param_valid; | ||
1036 | |||
1037 | memcpy(&msg_body.bss_params.ext_set_sta_key_param, | ||
1038 | &orig->bss_params.ext_set_sta_key_param, | ||
1039 | sizeof(orig->bss_params.acvo)); | ||
1040 | |||
1041 | msg_body.bss_params.wcn36xx_hal_persona = | ||
1042 | orig->bss_params.wcn36xx_hal_persona; | ||
1043 | msg_body.bss_params.spectrum_mgt_enable = | ||
1044 | orig->bss_params.spectrum_mgt_enable; | ||
1045 | msg_body.bss_params.tx_mgmt_power = orig->bss_params.tx_mgmt_power; | ||
1046 | msg_body.bss_params.max_tx_power = orig->bss_params.max_tx_power; | ||
1047 | |||
1048 | wcn36xx_smd_convert_sta_to_v1(wcn, &orig->bss_params.sta, | ||
1049 | &msg_body.bss_params.sta); | ||
1050 | |||
1051 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1052 | |||
1053 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
1054 | "hal config bss v1 bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n", | ||
1055 | bss->bssid, bss->self_mac_addr, bss->bss_type, | ||
1056 | bss->oper_mode, bss->nw_type); | ||
1057 | |||
1058 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
1059 | "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n", | ||
1060 | sta->bssid, sta->action, sta->sta_index, | ||
1061 | sta->bssid_index, sta->aid, sta->type, sta->mac); | ||
1062 | |||
1063 | return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1064 | } | ||
1065 | |||
1066 | |||
1067 | static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn, | ||
1068 | struct ieee80211_vif *vif, | ||
1069 | void *buf, | ||
1070 | size_t len) | ||
1071 | { | ||
1072 | struct wcn36xx_hal_config_bss_rsp_msg *rsp; | ||
1073 | struct wcn36xx_hal_config_bss_rsp_params *params; | ||
1074 | struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; | ||
1075 | |||
1076 | if (len < sizeof(*rsp)) | ||
1077 | return -EINVAL; | ||
1078 | |||
1079 | rsp = (struct wcn36xx_hal_config_bss_rsp_msg *)buf; | ||
1080 | params = &rsp->bss_rsp_params; | ||
1081 | |||
1082 | if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) { | ||
1083 | wcn36xx_warn("hal config bss response failure: %d\n", | ||
1084 | params->status); | ||
1085 | return -EIO; | ||
1086 | } | ||
1087 | |||
1088 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
1089 | "hal config bss rsp status %d bss_idx %d dpu_desc_index %d" | ||
1090 | " sta_idx %d self_idx %d bcast_idx %d mac %pM" | ||
1091 | " power %d ucast_dpu_signature %d\n", | ||
1092 | params->status, params->bss_index, params->dpu_desc_index, | ||
1093 | params->bss_sta_index, params->bss_self_sta_index, | ||
1094 | params->bss_bcast_sta_idx, params->mac, | ||
1095 | params->tx_mgmt_power, params->ucast_dpu_signature); | ||
1096 | |||
1097 | priv_vif->bss_index = params->bss_index; | ||
1098 | |||
1099 | if (priv_vif->sta) { | ||
1100 | priv_vif->sta->bss_sta_index = params->bss_sta_index; | ||
1101 | priv_vif->sta->bss_dpu_desc_index = params->dpu_desc_index; | ||
1102 | } | ||
1103 | |||
1104 | priv_vif->ucast_dpu_signature = params->ucast_dpu_signature; | ||
1105 | |||
1106 | return 0; | ||
1107 | } | ||
1108 | |||
1109 | int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, | ||
1110 | struct ieee80211_sta *sta, const u8 *bssid, | ||
1111 | bool update) | ||
1112 | { | ||
1113 | struct wcn36xx_hal_config_bss_req_msg msg; | ||
1114 | struct wcn36xx_hal_config_bss_params *bss; | ||
1115 | struct wcn36xx_hal_config_sta_params *sta_params; | ||
1116 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
1117 | int ret = 0; | ||
1118 | |||
1119 | mutex_lock(&wcn->hal_mutex); | ||
1120 | INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_BSS_REQ); | ||
1121 | |||
1122 | bss = &msg.bss_params; | ||
1123 | sta_params = &bss->sta; | ||
1124 | |||
1125 | WARN_ON(is_zero_ether_addr(bssid)); | ||
1126 | |||
1127 | memcpy(&bss->bssid, bssid, ETH_ALEN); | ||
1128 | |||
1129 | memcpy(bss->self_mac_addr, vif->addr, ETH_ALEN); | ||
1130 | |||
1131 | if (vif->type == NL80211_IFTYPE_STATION) { | ||
1132 | bss->bss_type = WCN36XX_HAL_INFRASTRUCTURE_MODE; | ||
1133 | |||
1134 | /* STA */ | ||
1135 | bss->oper_mode = 1; | ||
1136 | bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_MODE; | ||
1137 | } else if (vif->type == NL80211_IFTYPE_AP) { | ||
1138 | bss->bss_type = WCN36XX_HAL_INFRA_AP_MODE; | ||
1139 | |||
1140 | /* AP */ | ||
1141 | bss->oper_mode = 0; | ||
1142 | bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_SAP_MODE; | ||
1143 | } else if (vif->type == NL80211_IFTYPE_ADHOC || | ||
1144 | vif->type == NL80211_IFTYPE_MESH_POINT) { | ||
1145 | bss->bss_type = WCN36XX_HAL_IBSS_MODE; | ||
1146 | |||
1147 | /* STA */ | ||
1148 | bss->oper_mode = 1; | ||
1149 | } else { | ||
1150 | wcn36xx_warn("Unknown type for bss config: %d\n", vif->type); | ||
1151 | } | ||
1152 | |||
1153 | if (vif->type == NL80211_IFTYPE_STATION) | ||
1154 | wcn36xx_smd_set_bss_nw_type(wcn, sta, bss); | ||
1155 | else | ||
1156 | bss->nw_type = WCN36XX_HAL_11N_NW_TYPE; | ||
1157 | |||
1158 | bss->short_slot_time_supported = vif->bss_conf.use_short_slot; | ||
1159 | bss->lla_coexist = 0; | ||
1160 | bss->llb_coexist = 0; | ||
1161 | bss->llg_coexist = 0; | ||
1162 | bss->rifs_mode = 0; | ||
1163 | bss->beacon_interval = vif->bss_conf.beacon_int; | ||
1164 | bss->dtim_period = vif_priv->dtim_period; | ||
1165 | |||
1166 | wcn36xx_smd_set_bss_ht_params(vif, sta, bss); | ||
1167 | |||
1168 | bss->oper_channel = WCN36XX_HW_CHANNEL(wcn); | ||
1169 | |||
1170 | if (conf_is_ht40_minus(&wcn->hw->conf)) | ||
1171 | bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_BELOW; | ||
1172 | else if (conf_is_ht40_plus(&wcn->hw->conf)) | ||
1173 | bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | ||
1174 | else | ||
1175 | bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_NONE; | ||
1176 | |||
1177 | bss->reserved = 0; | ||
1178 | wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params); | ||
1179 | |||
1180 | /* wcn->ssid is only valid in AP and IBSS mode */ | ||
1181 | bss->ssid.length = vif_priv->ssid.length; | ||
1182 | memcpy(bss->ssid.ssid, vif_priv->ssid.ssid, vif_priv->ssid.length); | ||
1183 | |||
1184 | bss->obss_prot_enabled = 0; | ||
1185 | bss->rmf = 0; | ||
1186 | bss->max_probe_resp_retry_limit = 0; | ||
1187 | bss->hidden_ssid = vif->bss_conf.hidden_ssid; | ||
1188 | bss->proxy_probe_resp = 0; | ||
1189 | bss->edca_params_valid = 0; | ||
1190 | |||
1191 | /* FIXME: set acbe, acbk, acvi and acvo */ | ||
1192 | |||
1193 | bss->ext_set_sta_key_param_valid = 0; | ||
1194 | |||
1195 | /* FIXME: set ext_set_sta_key_param */ | ||
1196 | |||
1197 | bss->spectrum_mgt_enable = 0; | ||
1198 | bss->tx_mgmt_power = 0; | ||
1199 | bss->max_tx_power = WCN36XX_MAX_POWER(wcn); | ||
1200 | |||
1201 | bss->action = update; | ||
1202 | |||
1203 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
1204 | "hal config bss bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n", | ||
1205 | bss->bssid, bss->self_mac_addr, bss->bss_type, | ||
1206 | bss->oper_mode, bss->nw_type); | ||
1207 | |||
1208 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
1209 | "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n", | ||
1210 | sta_params->bssid, sta_params->action, | ||
1211 | sta_params->sta_index, sta_params->bssid_index, | ||
1212 | sta_params->aid, sta_params->type, | ||
1213 | sta_params->mac); | ||
1214 | |||
1215 | if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { | ||
1216 | ret = wcn36xx_smd_config_bss_v1(wcn, &msg); | ||
1217 | } else { | ||
1218 | PREPARE_HAL_BUF(wcn->hal_buf, msg); | ||
1219 | |||
1220 | ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len); | ||
1221 | } | ||
1222 | if (ret) { | ||
1223 | wcn36xx_err("Sending hal_config_bss failed\n"); | ||
1224 | goto out; | ||
1225 | } | ||
1226 | ret = wcn36xx_smd_config_bss_rsp(wcn, | ||
1227 | vif, | ||
1228 | wcn->hal_buf, | ||
1229 | wcn->hal_rsp_len); | ||
1230 | if (ret) { | ||
1231 | wcn36xx_err("hal_config_bss response failed err=%d\n", ret); | ||
1232 | goto out; | ||
1233 | } | ||
1234 | out: | ||
1235 | mutex_unlock(&wcn->hal_mutex); | ||
1236 | return ret; | ||
1237 | } | ||
1238 | |||
1239 | int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif) | ||
1240 | { | ||
1241 | struct wcn36xx_hal_delete_bss_req_msg msg_body; | ||
1242 | struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv; | ||
1243 | int ret = 0; | ||
1244 | |||
1245 | mutex_lock(&wcn->hal_mutex); | ||
1246 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_BSS_REQ); | ||
1247 | |||
1248 | msg_body.bss_index = priv_vif->bss_index; | ||
1249 | |||
1250 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1251 | |||
1252 | wcn36xx_dbg(WCN36XX_DBG_HAL, "hal delete bss %d\n", msg_body.bss_index); | ||
1253 | |||
1254 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1255 | if (ret) { | ||
1256 | wcn36xx_err("Sending hal_delete_bss failed\n"); | ||
1257 | goto out; | ||
1258 | } | ||
1259 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1260 | if (ret) { | ||
1261 | wcn36xx_err("hal_delete_bss response failed err=%d\n", ret); | ||
1262 | goto out; | ||
1263 | } | ||
1264 | out: | ||
1265 | mutex_unlock(&wcn->hal_mutex); | ||
1266 | return ret; | ||
1267 | } | ||
1268 | |||
1269 | int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif, | ||
1270 | struct sk_buff *skb_beacon, u16 tim_off, | ||
1271 | u16 p2p_off) | ||
1272 | { | ||
1273 | struct wcn36xx_hal_send_beacon_req_msg msg_body; | ||
1274 | int ret = 0; | ||
1275 | |||
1276 | mutex_lock(&wcn->hal_mutex); | ||
1277 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ); | ||
1278 | |||
1279 | /* TODO need to find out why this is needed? */ | ||
1280 | msg_body.beacon_length = skb_beacon->len + 6; | ||
1281 | |||
1282 | if (BEACON_TEMPLATE_SIZE > msg_body.beacon_length) { | ||
1283 | memcpy(&msg_body.beacon, &skb_beacon->len, sizeof(u32)); | ||
1284 | memcpy(&(msg_body.beacon[4]), skb_beacon->data, | ||
1285 | skb_beacon->len); | ||
1286 | } else { | ||
1287 | wcn36xx_err("Beacon is to big: beacon size=%d\n", | ||
1288 | msg_body.beacon_length); | ||
1289 | return -ENOMEM; | ||
1290 | } | ||
1291 | memcpy(msg_body.bssid, vif->addr, ETH_ALEN); | ||
1292 | |||
1293 | /* TODO need to find out why this is needed? */ | ||
1294 | msg_body.tim_ie_offset = tim_off+4; | ||
1295 | msg_body.p2p_ie_offset = p2p_off; | ||
1296 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1297 | |||
1298 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
1299 | "hal send beacon beacon_length %d\n", | ||
1300 | msg_body.beacon_length); | ||
1301 | |||
1302 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1303 | if (ret) { | ||
1304 | wcn36xx_err("Sending hal_send_beacon failed\n"); | ||
1305 | goto out; | ||
1306 | } | ||
1307 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1308 | if (ret) { | ||
1309 | wcn36xx_err("hal_send_beacon response failed err=%d\n", ret); | ||
1310 | goto out; | ||
1311 | } | ||
1312 | out: | ||
1313 | mutex_unlock(&wcn->hal_mutex); | ||
1314 | return ret; | ||
1315 | } | ||
1316 | |||
1317 | int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn, | ||
1318 | struct ieee80211_vif *vif, | ||
1319 | struct sk_buff *skb) | ||
1320 | { | ||
1321 | struct wcn36xx_hal_send_probe_resp_req_msg msg; | ||
1322 | int ret = 0; | ||
1323 | |||
1324 | mutex_lock(&wcn->hal_mutex); | ||
1325 | INIT_HAL_MSG(msg, WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ); | ||
1326 | |||
1327 | if (skb->len > BEACON_TEMPLATE_SIZE) { | ||
1328 | wcn36xx_warn("probe response template is too big: %d\n", | ||
1329 | skb->len); | ||
1330 | return -E2BIG; | ||
1331 | } | ||
1332 | |||
1333 | msg.probe_resp_template_len = skb->len; | ||
1334 | memcpy(&msg.probe_resp_template, skb->data, skb->len); | ||
1335 | |||
1336 | memcpy(msg.bssid, vif->addr, ETH_ALEN); | ||
1337 | |||
1338 | PREPARE_HAL_BUF(wcn->hal_buf, msg); | ||
1339 | |||
1340 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
1341 | "hal update probe rsp len %d bssid %pM\n", | ||
1342 | msg.probe_resp_template_len, msg.bssid); | ||
1343 | |||
1344 | ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len); | ||
1345 | if (ret) { | ||
1346 | wcn36xx_err("Sending hal_update_proberesp_tmpl failed\n"); | ||
1347 | goto out; | ||
1348 | } | ||
1349 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1350 | if (ret) { | ||
1351 | wcn36xx_err("hal_update_proberesp_tmpl response failed err=%d\n", | ||
1352 | ret); | ||
1353 | goto out; | ||
1354 | } | ||
1355 | out: | ||
1356 | mutex_unlock(&wcn->hal_mutex); | ||
1357 | return ret; | ||
1358 | } | ||
1359 | |||
1360 | int wcn36xx_smd_set_stakey(struct wcn36xx *wcn, | ||
1361 | enum ani_ed_type enc_type, | ||
1362 | u8 keyidx, | ||
1363 | u8 keylen, | ||
1364 | u8 *key, | ||
1365 | u8 sta_index) | ||
1366 | { | ||
1367 | struct wcn36xx_hal_set_sta_key_req_msg msg_body; | ||
1368 | int ret = 0; | ||
1369 | |||
1370 | mutex_lock(&wcn->hal_mutex); | ||
1371 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_STAKEY_REQ); | ||
1372 | |||
1373 | msg_body.set_sta_key_params.sta_index = sta_index; | ||
1374 | msg_body.set_sta_key_params.enc_type = enc_type; | ||
1375 | |||
1376 | msg_body.set_sta_key_params.key[0].id = keyidx; | ||
1377 | msg_body.set_sta_key_params.key[0].unicast = 1; | ||
1378 | msg_body.set_sta_key_params.key[0].direction = WCN36XX_HAL_TX_RX; | ||
1379 | msg_body.set_sta_key_params.key[0].pae_role = 0; | ||
1380 | msg_body.set_sta_key_params.key[0].length = keylen; | ||
1381 | memcpy(msg_body.set_sta_key_params.key[0].key, key, keylen); | ||
1382 | msg_body.set_sta_key_params.single_tid_rc = 1; | ||
1383 | |||
1384 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1385 | |||
1386 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1387 | if (ret) { | ||
1388 | wcn36xx_err("Sending hal_set_stakey failed\n"); | ||
1389 | goto out; | ||
1390 | } | ||
1391 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1392 | if (ret) { | ||
1393 | wcn36xx_err("hal_set_stakey response failed err=%d\n", ret); | ||
1394 | goto out; | ||
1395 | } | ||
1396 | out: | ||
1397 | mutex_unlock(&wcn->hal_mutex); | ||
1398 | return ret; | ||
1399 | } | ||
1400 | |||
1401 | int wcn36xx_smd_set_bsskey(struct wcn36xx *wcn, | ||
1402 | enum ani_ed_type enc_type, | ||
1403 | u8 keyidx, | ||
1404 | u8 keylen, | ||
1405 | u8 *key) | ||
1406 | { | ||
1407 | struct wcn36xx_hal_set_bss_key_req_msg msg_body; | ||
1408 | int ret = 0; | ||
1409 | |||
1410 | mutex_lock(&wcn->hal_mutex); | ||
1411 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_BSSKEY_REQ); | ||
1412 | msg_body.bss_idx = 0; | ||
1413 | msg_body.enc_type = enc_type; | ||
1414 | msg_body.num_keys = 1; | ||
1415 | msg_body.keys[0].id = keyidx; | ||
1416 | msg_body.keys[0].unicast = 0; | ||
1417 | msg_body.keys[0].direction = WCN36XX_HAL_RX_ONLY; | ||
1418 | msg_body.keys[0].pae_role = 0; | ||
1419 | msg_body.keys[0].length = keylen; | ||
1420 | memcpy(msg_body.keys[0].key, key, keylen); | ||
1421 | |||
1422 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1423 | |||
1424 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1425 | if (ret) { | ||
1426 | wcn36xx_err("Sending hal_set_bsskey failed\n"); | ||
1427 | goto out; | ||
1428 | } | ||
1429 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1430 | if (ret) { | ||
1431 | wcn36xx_err("hal_set_bsskey response failed err=%d\n", ret); | ||
1432 | goto out; | ||
1433 | } | ||
1434 | out: | ||
1435 | mutex_unlock(&wcn->hal_mutex); | ||
1436 | return ret; | ||
1437 | } | ||
1438 | |||
1439 | int wcn36xx_smd_remove_stakey(struct wcn36xx *wcn, | ||
1440 | enum ani_ed_type enc_type, | ||
1441 | u8 keyidx, | ||
1442 | u8 sta_index) | ||
1443 | { | ||
1444 | struct wcn36xx_hal_remove_sta_key_req_msg msg_body; | ||
1445 | int ret = 0; | ||
1446 | |||
1447 | mutex_lock(&wcn->hal_mutex); | ||
1448 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_STAKEY_REQ); | ||
1449 | |||
1450 | msg_body.sta_idx = sta_index; | ||
1451 | msg_body.enc_type = enc_type; | ||
1452 | msg_body.key_id = keyidx; | ||
1453 | |||
1454 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1455 | |||
1456 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1457 | if (ret) { | ||
1458 | wcn36xx_err("Sending hal_remove_stakey failed\n"); | ||
1459 | goto out; | ||
1460 | } | ||
1461 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1462 | if (ret) { | ||
1463 | wcn36xx_err("hal_remove_stakey response failed err=%d\n", ret); | ||
1464 | goto out; | ||
1465 | } | ||
1466 | out: | ||
1467 | mutex_unlock(&wcn->hal_mutex); | ||
1468 | return ret; | ||
1469 | } | ||
1470 | |||
1471 | int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn, | ||
1472 | enum ani_ed_type enc_type, | ||
1473 | u8 keyidx) | ||
1474 | { | ||
1475 | struct wcn36xx_hal_remove_bss_key_req_msg msg_body; | ||
1476 | int ret = 0; | ||
1477 | |||
1478 | mutex_lock(&wcn->hal_mutex); | ||
1479 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_BSSKEY_REQ); | ||
1480 | msg_body.bss_idx = 0; | ||
1481 | msg_body.enc_type = enc_type; | ||
1482 | msg_body.key_id = keyidx; | ||
1483 | |||
1484 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1485 | |||
1486 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1487 | if (ret) { | ||
1488 | wcn36xx_err("Sending hal_remove_bsskey failed\n"); | ||
1489 | goto out; | ||
1490 | } | ||
1491 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1492 | if (ret) { | ||
1493 | wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret); | ||
1494 | goto out; | ||
1495 | } | ||
1496 | out: | ||
1497 | mutex_unlock(&wcn->hal_mutex); | ||
1498 | return ret; | ||
1499 | } | ||
1500 | |||
1501 | int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) | ||
1502 | { | ||
1503 | struct wcn36xx_hal_enter_bmps_req_msg msg_body; | ||
1504 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
1505 | int ret = 0; | ||
1506 | |||
1507 | mutex_lock(&wcn->hal_mutex); | ||
1508 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_BMPS_REQ); | ||
1509 | |||
1510 | msg_body.bss_index = vif_priv->bss_index; | ||
1511 | msg_body.tbtt = vif->bss_conf.sync_tsf; | ||
1512 | msg_body.dtim_period = vif_priv->dtim_period; | ||
1513 | |||
1514 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1515 | |||
1516 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1517 | if (ret) { | ||
1518 | wcn36xx_err("Sending hal_enter_bmps failed\n"); | ||
1519 | goto out; | ||
1520 | } | ||
1521 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1522 | if (ret) { | ||
1523 | wcn36xx_err("hal_enter_bmps response failed err=%d\n", ret); | ||
1524 | goto out; | ||
1525 | } | ||
1526 | out: | ||
1527 | mutex_unlock(&wcn->hal_mutex); | ||
1528 | return ret; | ||
1529 | } | ||
1530 | |||
1531 | int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif) | ||
1532 | { | ||
1533 | struct wcn36xx_hal_enter_bmps_req_msg msg_body; | ||
1534 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
1535 | int ret = 0; | ||
1536 | |||
1537 | mutex_lock(&wcn->hal_mutex); | ||
1538 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_BMPS_REQ); | ||
1539 | |||
1540 | msg_body.bss_index = vif_priv->bss_index; | ||
1541 | |||
1542 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1543 | |||
1544 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1545 | if (ret) { | ||
1546 | wcn36xx_err("Sending hal_exit_bmps failed\n"); | ||
1547 | goto out; | ||
1548 | } | ||
1549 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1550 | if (ret) { | ||
1551 | wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret); | ||
1552 | goto out; | ||
1553 | } | ||
1554 | out: | ||
1555 | mutex_unlock(&wcn->hal_mutex); | ||
1556 | return ret; | ||
1557 | } | ||
1558 | int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim) | ||
1559 | { | ||
1560 | struct wcn36xx_hal_set_power_params_req_msg msg_body; | ||
1561 | int ret = 0; | ||
1562 | |||
1563 | mutex_lock(&wcn->hal_mutex); | ||
1564 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_POWER_PARAMS_REQ); | ||
1565 | |||
1566 | /* | ||
1567 | * When host is down ignore every second dtim | ||
1568 | */ | ||
1569 | if (ignore_dtim) { | ||
1570 | msg_body.ignore_dtim = 1; | ||
1571 | msg_body.dtim_period = 2; | ||
1572 | } | ||
1573 | msg_body.listen_interval = WCN36XX_LISTEN_INTERVAL(wcn); | ||
1574 | |||
1575 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1576 | |||
1577 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1578 | if (ret) { | ||
1579 | wcn36xx_err("Sending hal_set_power_params failed\n"); | ||
1580 | goto out; | ||
1581 | } | ||
1582 | |||
1583 | out: | ||
1584 | mutex_unlock(&wcn->hal_mutex); | ||
1585 | return ret; | ||
1586 | } | ||
1587 | /* Notice: This function should be called after associated, or else it | ||
1588 | * will be invalid | ||
1589 | */ | ||
1590 | int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn, | ||
1591 | struct ieee80211_vif *vif, | ||
1592 | int packet_type) | ||
1593 | { | ||
1594 | struct wcn36xx_hal_keep_alive_req_msg msg_body; | ||
1595 | struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv; | ||
1596 | int ret = 0; | ||
1597 | |||
1598 | mutex_lock(&wcn->hal_mutex); | ||
1599 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_KEEP_ALIVE_REQ); | ||
1600 | |||
1601 | if (packet_type == WCN36XX_HAL_KEEP_ALIVE_NULL_PKT) { | ||
1602 | msg_body.bss_index = vif_priv->bss_index; | ||
1603 | msg_body.packet_type = WCN36XX_HAL_KEEP_ALIVE_NULL_PKT; | ||
1604 | msg_body.time_period = WCN36XX_KEEP_ALIVE_TIME_PERIOD; | ||
1605 | } else if (packet_type == WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP) { | ||
1606 | /* TODO: it also support ARP response type */ | ||
1607 | } else { | ||
1608 | wcn36xx_warn("unknow keep alive packet type %d\n", packet_type); | ||
1609 | return -EINVAL; | ||
1610 | } | ||
1611 | |||
1612 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1613 | |||
1614 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1615 | if (ret) { | ||
1616 | wcn36xx_err("Sending hal_exit_bmps failed\n"); | ||
1617 | goto out; | ||
1618 | } | ||
1619 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1620 | if (ret) { | ||
1621 | wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret); | ||
1622 | goto out; | ||
1623 | } | ||
1624 | out: | ||
1625 | mutex_unlock(&wcn->hal_mutex); | ||
1626 | return ret; | ||
1627 | } | ||
1628 | |||
1629 | int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2, | ||
1630 | u32 arg3, u32 arg4, u32 arg5) | ||
1631 | { | ||
1632 | struct wcn36xx_hal_dump_cmd_req_msg msg_body; | ||
1633 | int ret = 0; | ||
1634 | |||
1635 | mutex_lock(&wcn->hal_mutex); | ||
1636 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_DUMP_COMMAND_REQ); | ||
1637 | |||
1638 | msg_body.arg1 = arg1; | ||
1639 | msg_body.arg2 = arg2; | ||
1640 | msg_body.arg3 = arg3; | ||
1641 | msg_body.arg4 = arg4; | ||
1642 | msg_body.arg5 = arg5; | ||
1643 | |||
1644 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1645 | |||
1646 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1647 | if (ret) { | ||
1648 | wcn36xx_err("Sending hal_dump_cmd failed\n"); | ||
1649 | goto out; | ||
1650 | } | ||
1651 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1652 | if (ret) { | ||
1653 | wcn36xx_err("hal_dump_cmd response failed err=%d\n", ret); | ||
1654 | goto out; | ||
1655 | } | ||
1656 | out: | ||
1657 | mutex_unlock(&wcn->hal_mutex); | ||
1658 | return ret; | ||
1659 | } | ||
1660 | |||
1661 | static inline void set_feat_caps(u32 *bitmap, | ||
1662 | enum place_holder_in_cap_bitmap cap) | ||
1663 | { | ||
1664 | int arr_idx, bit_idx; | ||
1665 | |||
1666 | if (cap < 0 || cap > 127) { | ||
1667 | wcn36xx_warn("error cap idx %d\n", cap); | ||
1668 | return; | ||
1669 | } | ||
1670 | |||
1671 | arr_idx = cap / 32; | ||
1672 | bit_idx = cap % 32; | ||
1673 | bitmap[arr_idx] |= (1 << bit_idx); | ||
1674 | } | ||
1675 | |||
1676 | static inline int get_feat_caps(u32 *bitmap, | ||
1677 | enum place_holder_in_cap_bitmap cap) | ||
1678 | { | ||
1679 | int arr_idx, bit_idx; | ||
1680 | int ret = 0; | ||
1681 | |||
1682 | if (cap < 0 || cap > 127) { | ||
1683 | wcn36xx_warn("error cap idx %d\n", cap); | ||
1684 | return -EINVAL; | ||
1685 | } | ||
1686 | |||
1687 | arr_idx = cap / 32; | ||
1688 | bit_idx = cap % 32; | ||
1689 | ret = (bitmap[arr_idx] & (1 << bit_idx)) ? 1 : 0; | ||
1690 | return ret; | ||
1691 | } | ||
1692 | |||
1693 | static inline void clear_feat_caps(u32 *bitmap, | ||
1694 | enum place_holder_in_cap_bitmap cap) | ||
1695 | { | ||
1696 | int arr_idx, bit_idx; | ||
1697 | |||
1698 | if (cap < 0 || cap > 127) { | ||
1699 | wcn36xx_warn("error cap idx %d\n", cap); | ||
1700 | return; | ||
1701 | } | ||
1702 | |||
1703 | arr_idx = cap / 32; | ||
1704 | bit_idx = cap % 32; | ||
1705 | bitmap[arr_idx] &= ~(1 << bit_idx); | ||
1706 | } | ||
1707 | |||
1708 | int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn) | ||
1709 | { | ||
1710 | struct wcn36xx_hal_feat_caps_msg msg_body; | ||
1711 | int ret = 0; | ||
1712 | |||
1713 | mutex_lock(&wcn->hal_mutex); | ||
1714 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ); | ||
1715 | |||
1716 | set_feat_caps(msg_body.feat_caps, STA_POWERSAVE); | ||
1717 | |||
1718 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1719 | |||
1720 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1721 | if (ret) { | ||
1722 | wcn36xx_err("Sending hal_feature_caps_exchange failed\n"); | ||
1723 | goto out; | ||
1724 | } | ||
1725 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1726 | if (ret) { | ||
1727 | wcn36xx_err("hal_feature_caps_exchange response failed err=%d\n", | ||
1728 | ret); | ||
1729 | goto out; | ||
1730 | } | ||
1731 | out: | ||
1732 | mutex_unlock(&wcn->hal_mutex); | ||
1733 | return ret; | ||
1734 | } | ||
1735 | |||
1736 | int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn, | ||
1737 | struct ieee80211_sta *sta, | ||
1738 | u16 tid, | ||
1739 | u16 *ssn, | ||
1740 | u8 direction, | ||
1741 | u8 sta_index) | ||
1742 | { | ||
1743 | struct wcn36xx_hal_add_ba_session_req_msg msg_body; | ||
1744 | int ret = 0; | ||
1745 | |||
1746 | mutex_lock(&wcn->hal_mutex); | ||
1747 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_SESSION_REQ); | ||
1748 | |||
1749 | msg_body.sta_index = sta_index; | ||
1750 | memcpy(&msg_body.mac_addr, sta->addr, ETH_ALEN); | ||
1751 | msg_body.dialog_token = 0x10; | ||
1752 | msg_body.tid = tid; | ||
1753 | |||
1754 | /* Immediate BA because Delayed BA is not supported */ | ||
1755 | msg_body.policy = 1; | ||
1756 | msg_body.buffer_size = WCN36XX_AGGR_BUFFER_SIZE; | ||
1757 | msg_body.timeout = 0; | ||
1758 | if (ssn) | ||
1759 | msg_body.ssn = *ssn; | ||
1760 | msg_body.direction = direction; | ||
1761 | |||
1762 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1763 | |||
1764 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1765 | if (ret) { | ||
1766 | wcn36xx_err("Sending hal_add_ba_session failed\n"); | ||
1767 | goto out; | ||
1768 | } | ||
1769 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1770 | if (ret) { | ||
1771 | wcn36xx_err("hal_add_ba_session response failed err=%d\n", ret); | ||
1772 | goto out; | ||
1773 | } | ||
1774 | out: | ||
1775 | mutex_unlock(&wcn->hal_mutex); | ||
1776 | return ret; | ||
1777 | } | ||
1778 | |||
1779 | int wcn36xx_smd_add_ba(struct wcn36xx *wcn) | ||
1780 | { | ||
1781 | struct wcn36xx_hal_add_ba_req_msg msg_body; | ||
1782 | int ret = 0; | ||
1783 | |||
1784 | mutex_lock(&wcn->hal_mutex); | ||
1785 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_REQ); | ||
1786 | |||
1787 | msg_body.session_id = 0; | ||
1788 | msg_body.win_size = WCN36XX_AGGR_BUFFER_SIZE; | ||
1789 | |||
1790 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1791 | |||
1792 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1793 | if (ret) { | ||
1794 | wcn36xx_err("Sending hal_add_ba failed\n"); | ||
1795 | goto out; | ||
1796 | } | ||
1797 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1798 | if (ret) { | ||
1799 | wcn36xx_err("hal_add_ba response failed err=%d\n", ret); | ||
1800 | goto out; | ||
1801 | } | ||
1802 | out: | ||
1803 | mutex_unlock(&wcn->hal_mutex); | ||
1804 | return ret; | ||
1805 | } | ||
1806 | |||
1807 | int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index) | ||
1808 | { | ||
1809 | struct wcn36xx_hal_del_ba_req_msg msg_body; | ||
1810 | int ret = 0; | ||
1811 | |||
1812 | mutex_lock(&wcn->hal_mutex); | ||
1813 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_BA_REQ); | ||
1814 | |||
1815 | msg_body.sta_index = sta_index; | ||
1816 | msg_body.tid = tid; | ||
1817 | msg_body.direction = 0; | ||
1818 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1819 | |||
1820 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1821 | if (ret) { | ||
1822 | wcn36xx_err("Sending hal_del_ba failed\n"); | ||
1823 | goto out; | ||
1824 | } | ||
1825 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1826 | if (ret) { | ||
1827 | wcn36xx_err("hal_del_ba response failed err=%d\n", ret); | ||
1828 | goto out; | ||
1829 | } | ||
1830 | out: | ||
1831 | mutex_unlock(&wcn->hal_mutex); | ||
1832 | return ret; | ||
1833 | } | ||
1834 | |||
1835 | int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index) | ||
1836 | { | ||
1837 | struct wcn36xx_hal_trigger_ba_req_msg msg_body; | ||
1838 | struct wcn36xx_hal_trigget_ba_req_candidate *candidate; | ||
1839 | int ret = 0; | ||
1840 | |||
1841 | mutex_lock(&wcn->hal_mutex); | ||
1842 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_TRIGGER_BA_REQ); | ||
1843 | |||
1844 | msg_body.session_id = 0; | ||
1845 | msg_body.candidate_cnt = 1; | ||
1846 | msg_body.header.len += sizeof(*candidate); | ||
1847 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1848 | |||
1849 | candidate = (struct wcn36xx_hal_trigget_ba_req_candidate *) | ||
1850 | (wcn->hal_buf + sizeof(msg_body)); | ||
1851 | candidate->sta_index = sta_index; | ||
1852 | candidate->tid_bitmap = 1; | ||
1853 | |||
1854 | ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); | ||
1855 | if (ret) { | ||
1856 | wcn36xx_err("Sending hal_trigger_ba failed\n"); | ||
1857 | goto out; | ||
1858 | } | ||
1859 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1860 | if (ret) { | ||
1861 | wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret); | ||
1862 | goto out; | ||
1863 | } | ||
1864 | out: | ||
1865 | mutex_unlock(&wcn->hal_mutex); | ||
1866 | return ret; | ||
1867 | } | ||
1868 | |||
1869 | static int wcn36xx_smd_tx_compl_ind(struct wcn36xx *wcn, void *buf, size_t len) | ||
1870 | { | ||
1871 | struct wcn36xx_hal_tx_compl_ind_msg *rsp = buf; | ||
1872 | |||
1873 | if (len != sizeof(*rsp)) { | ||
1874 | wcn36xx_warn("Bad TX complete indication\n"); | ||
1875 | return -EIO; | ||
1876 | } | ||
1877 | |||
1878 | wcn36xx_dxe_tx_ack_ind(wcn, rsp->status); | ||
1879 | |||
1880 | return 0; | ||
1881 | } | ||
1882 | |||
1883 | static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn, | ||
1884 | void *buf, | ||
1885 | size_t len) | ||
1886 | { | ||
1887 | struct wcn36xx_hal_missed_beacon_ind_msg *rsp = buf; | ||
1888 | struct ieee80211_vif *vif = NULL; | ||
1889 | struct wcn36xx_vif *tmp; | ||
1890 | |||
1891 | /* Old FW does not have bss index */ | ||
1892 | if (wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { | ||
1893 | list_for_each_entry(tmp, &wcn->vif_list, list) { | ||
1894 | wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n", | ||
1895 | tmp->bss_index); | ||
1896 | vif = container_of((void *)tmp, | ||
1897 | struct ieee80211_vif, | ||
1898 | drv_priv); | ||
1899 | ieee80211_connection_loss(vif); | ||
1900 | } | ||
1901 | return 0; | ||
1902 | } | ||
1903 | |||
1904 | if (len != sizeof(*rsp)) { | ||
1905 | wcn36xx_warn("Corrupted missed beacon indication\n"); | ||
1906 | return -EIO; | ||
1907 | } | ||
1908 | |||
1909 | list_for_each_entry(tmp, &wcn->vif_list, list) { | ||
1910 | if (tmp->bss_index == rsp->bss_index) { | ||
1911 | wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n", | ||
1912 | rsp->bss_index); | ||
1913 | vif = container_of((void *)tmp, | ||
1914 | struct ieee80211_vif, | ||
1915 | drv_priv); | ||
1916 | ieee80211_connection_loss(vif); | ||
1917 | return 0; | ||
1918 | } | ||
1919 | } | ||
1920 | |||
1921 | wcn36xx_warn("BSS index %d not found\n", rsp->bss_index); | ||
1922 | return -ENOENT; | ||
1923 | } | ||
1924 | |||
1925 | static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn, | ||
1926 | void *buf, | ||
1927 | size_t len) | ||
1928 | { | ||
1929 | struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf; | ||
1930 | struct wcn36xx_vif *tmp; | ||
1931 | struct ieee80211_sta *sta = NULL; | ||
1932 | |||
1933 | if (len != sizeof(*rsp)) { | ||
1934 | wcn36xx_warn("Corrupted delete sta indication\n"); | ||
1935 | return -EIO; | ||
1936 | } | ||
1937 | |||
1938 | list_for_each_entry(tmp, &wcn->vif_list, list) { | ||
1939 | if (sta && (tmp->sta->sta_index == rsp->sta_id)) { | ||
1940 | sta = container_of((void *)tmp->sta, | ||
1941 | struct ieee80211_sta, | ||
1942 | drv_priv); | ||
1943 | wcn36xx_dbg(WCN36XX_DBG_HAL, | ||
1944 | "delete station indication %pM index %d\n", | ||
1945 | rsp->addr2, | ||
1946 | rsp->sta_id); | ||
1947 | ieee80211_report_low_ack(sta, 0); | ||
1948 | return 0; | ||
1949 | } | ||
1950 | } | ||
1951 | |||
1952 | wcn36xx_warn("STA with addr %pM and index %d not found\n", | ||
1953 | rsp->addr2, | ||
1954 | rsp->sta_id); | ||
1955 | return -ENOENT; | ||
1956 | } | ||
1957 | |||
1958 | int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value) | ||
1959 | { | ||
1960 | struct wcn36xx_hal_update_cfg_req_msg msg_body, *body; | ||
1961 | size_t len; | ||
1962 | int ret = 0; | ||
1963 | |||
1964 | mutex_lock(&wcn->hal_mutex); | ||
1965 | INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_CFG_REQ); | ||
1966 | |||
1967 | PREPARE_HAL_BUF(wcn->hal_buf, msg_body); | ||
1968 | |||
1969 | body = (struct wcn36xx_hal_update_cfg_req_msg *) wcn->hal_buf; | ||
1970 | len = msg_body.header.len; | ||
1971 | |||
1972 | put_cfg_tlv_u32(wcn, &len, cfg_id, value); | ||
1973 | body->header.len = len; | ||
1974 | body->len = len - sizeof(*body); | ||
1975 | |||
1976 | ret = wcn36xx_smd_send_and_wait(wcn, body->header.len); | ||
1977 | if (ret) { | ||
1978 | wcn36xx_err("Sending hal_update_cfg failed\n"); | ||
1979 | goto out; | ||
1980 | } | ||
1981 | ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); | ||
1982 | if (ret) { | ||
1983 | wcn36xx_err("hal_update_cfg response failed err=%d\n", ret); | ||
1984 | goto out; | ||
1985 | } | ||
1986 | out: | ||
1987 | mutex_unlock(&wcn->hal_mutex); | ||
1988 | return ret; | ||
1989 | } | ||
1990 | static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len) | ||
1991 | { | ||
1992 | struct wcn36xx_hal_msg_header *msg_header = buf; | ||
1993 | struct wcn36xx_hal_ind_msg *msg_ind; | ||
1994 | wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len); | ||
1995 | |||
1996 | switch (msg_header->msg_type) { | ||
1997 | case WCN36XX_HAL_START_RSP: | ||
1998 | case WCN36XX_HAL_CONFIG_STA_RSP: | ||
1999 | case WCN36XX_HAL_CONFIG_BSS_RSP: | ||
2000 | case WCN36XX_HAL_ADD_STA_SELF_RSP: | ||
2001 | case WCN36XX_HAL_STOP_RSP: | ||
2002 | case WCN36XX_HAL_DEL_STA_SELF_RSP: | ||
2003 | case WCN36XX_HAL_DELETE_STA_RSP: | ||
2004 | case WCN36XX_HAL_INIT_SCAN_RSP: | ||
2005 | case WCN36XX_HAL_START_SCAN_RSP: | ||
2006 | case WCN36XX_HAL_END_SCAN_RSP: | ||
2007 | case WCN36XX_HAL_FINISH_SCAN_RSP: | ||
2008 | case WCN36XX_HAL_DOWNLOAD_NV_RSP: | ||
2009 | case WCN36XX_HAL_DELETE_BSS_RSP: | ||
2010 | case WCN36XX_HAL_SEND_BEACON_RSP: | ||
2011 | case WCN36XX_HAL_SET_LINK_ST_RSP: | ||
2012 | case WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_RSP: | ||
2013 | case WCN36XX_HAL_SET_BSSKEY_RSP: | ||
2014 | case WCN36XX_HAL_SET_STAKEY_RSP: | ||
2015 | case WCN36XX_HAL_RMV_STAKEY_RSP: | ||
2016 | case WCN36XX_HAL_RMV_BSSKEY_RSP: | ||
2017 | case WCN36XX_HAL_ENTER_BMPS_RSP: | ||
2018 | case WCN36XX_HAL_SET_POWER_PARAMS_RSP: | ||
2019 | case WCN36XX_HAL_EXIT_BMPS_RSP: | ||
2020 | case WCN36XX_HAL_KEEP_ALIVE_RSP: | ||
2021 | case WCN36XX_HAL_DUMP_COMMAND_RSP: | ||
2022 | case WCN36XX_HAL_ADD_BA_SESSION_RSP: | ||
2023 | case WCN36XX_HAL_ADD_BA_RSP: | ||
2024 | case WCN36XX_HAL_DEL_BA_RSP: | ||
2025 | case WCN36XX_HAL_TRIGGER_BA_RSP: | ||
2026 | case WCN36XX_HAL_UPDATE_CFG_RSP: | ||
2027 | case WCN36XX_HAL_JOIN_RSP: | ||
2028 | case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP: | ||
2029 | case WCN36XX_HAL_CH_SWITCH_RSP: | ||
2030 | case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP: | ||
2031 | memcpy(wcn->hal_buf, buf, len); | ||
2032 | wcn->hal_rsp_len = len; | ||
2033 | complete(&wcn->hal_rsp_compl); | ||
2034 | break; | ||
2035 | |||
2036 | case WCN36XX_HAL_OTA_TX_COMPL_IND: | ||
2037 | case WCN36XX_HAL_MISSED_BEACON_IND: | ||
2038 | case WCN36XX_HAL_DELETE_STA_CONTEXT_IND: | ||
2039 | mutex_lock(&wcn->hal_ind_mutex); | ||
2040 | msg_ind = kmalloc(sizeof(*msg_ind), GFP_KERNEL); | ||
2041 | msg_ind->msg_len = len; | ||
2042 | msg_ind->msg = kmalloc(len, GFP_KERNEL); | ||
2043 | memcpy(msg_ind->msg, buf, len); | ||
2044 | list_add_tail(&msg_ind->list, &wcn->hal_ind_queue); | ||
2045 | queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work); | ||
2046 | wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n"); | ||
2047 | mutex_unlock(&wcn->hal_ind_mutex); | ||
2048 | break; | ||
2049 | default: | ||
2050 | wcn36xx_err("SMD_EVENT (%d) not supported\n", | ||
2051 | msg_header->msg_type); | ||
2052 | } | ||
2053 | } | ||
2054 | static void wcn36xx_ind_smd_work(struct work_struct *work) | ||
2055 | { | ||
2056 | struct wcn36xx *wcn = | ||
2057 | container_of(work, struct wcn36xx, hal_ind_work); | ||
2058 | struct wcn36xx_hal_msg_header *msg_header; | ||
2059 | struct wcn36xx_hal_ind_msg *hal_ind_msg; | ||
2060 | |||
2061 | mutex_lock(&wcn->hal_ind_mutex); | ||
2062 | |||
2063 | hal_ind_msg = list_first_entry(&wcn->hal_ind_queue, | ||
2064 | struct wcn36xx_hal_ind_msg, | ||
2065 | list); | ||
2066 | |||
2067 | msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg; | ||
2068 | |||
2069 | switch (msg_header->msg_type) { | ||
2070 | case WCN36XX_HAL_OTA_TX_COMPL_IND: | ||
2071 | wcn36xx_smd_tx_compl_ind(wcn, | ||
2072 | hal_ind_msg->msg, | ||
2073 | hal_ind_msg->msg_len); | ||
2074 | break; | ||
2075 | case WCN36XX_HAL_MISSED_BEACON_IND: | ||
2076 | wcn36xx_smd_missed_beacon_ind(wcn, | ||
2077 | hal_ind_msg->msg, | ||
2078 | hal_ind_msg->msg_len); | ||
2079 | break; | ||
2080 | case WCN36XX_HAL_DELETE_STA_CONTEXT_IND: | ||
2081 | wcn36xx_smd_delete_sta_context_ind(wcn, | ||
2082 | hal_ind_msg->msg, | ||
2083 | hal_ind_msg->msg_len); | ||
2084 | break; | ||
2085 | default: | ||
2086 | wcn36xx_err("SMD_EVENT (%d) not supported\n", | ||
2087 | msg_header->msg_type); | ||
2088 | } | ||
2089 | list_del(wcn->hal_ind_queue.next); | ||
2090 | kfree(hal_ind_msg->msg); | ||
2091 | kfree(hal_ind_msg); | ||
2092 | mutex_unlock(&wcn->hal_ind_mutex); | ||
2093 | } | ||
2094 | int wcn36xx_smd_open(struct wcn36xx *wcn) | ||
2095 | { | ||
2096 | int ret = 0; | ||
2097 | wcn->hal_ind_wq = create_freezable_workqueue("wcn36xx_smd_ind"); | ||
2098 | if (!wcn->hal_ind_wq) { | ||
2099 | wcn36xx_err("failed to allocate wq\n"); | ||
2100 | ret = -ENOMEM; | ||
2101 | goto out; | ||
2102 | } | ||
2103 | INIT_WORK(&wcn->hal_ind_work, wcn36xx_ind_smd_work); | ||
2104 | INIT_LIST_HEAD(&wcn->hal_ind_queue); | ||
2105 | mutex_init(&wcn->hal_ind_mutex); | ||
2106 | |||
2107 | ret = wcn->ctrl_ops->open(wcn, wcn36xx_smd_rsp_process); | ||
2108 | if (ret) { | ||
2109 | wcn36xx_err("failed to open control channel\n"); | ||
2110 | goto free_wq; | ||
2111 | } | ||
2112 | |||
2113 | return ret; | ||
2114 | |||
2115 | free_wq: | ||
2116 | destroy_workqueue(wcn->hal_ind_wq); | ||
2117 | out: | ||
2118 | return ret; | ||
2119 | } | ||
2120 | |||
2121 | void wcn36xx_smd_close(struct wcn36xx *wcn) | ||
2122 | { | ||
2123 | wcn->ctrl_ops->close(); | ||
2124 | destroy_workqueue(wcn->hal_ind_wq); | ||
2125 | mutex_destroy(&wcn->hal_ind_mutex); | ||
2126 | } | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h new file mode 100644 index 000000000000..e7c39019c6f1 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/smd.h | |||
@@ -0,0 +1,127 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef _SMD_H_ | ||
18 | #define _SMD_H_ | ||
19 | |||
20 | #include "wcn36xx.h" | ||
21 | |||
22 | /* Max shared size is 4k but we take less.*/ | ||
23 | #define WCN36XX_NV_FRAGMENT_SIZE 3072 | ||
24 | |||
25 | #define WCN36XX_HAL_BUF_SIZE 4096 | ||
26 | |||
27 | #define HAL_MSG_TIMEOUT 200 | ||
28 | #define WCN36XX_SMSM_WLAN_TX_ENABLE 0x00000400 | ||
29 | #define WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY 0x00000200 | ||
30 | /* The PNO version info be contained in the rsp msg */ | ||
31 | #define WCN36XX_FW_MSG_PNO_VERSION_MASK 0x8000 | ||
32 | |||
33 | enum wcn36xx_fw_msg_result { | ||
34 | WCN36XX_FW_MSG_RESULT_SUCCESS = 0, | ||
35 | WCN36XX_FW_MSG_RESULT_SUCCESS_SYNC = 1, | ||
36 | |||
37 | WCN36XX_FW_MSG_RESULT_MEM_FAIL = 5, | ||
38 | }; | ||
39 | |||
40 | /******************************/ | ||
41 | /* SMD requests and responses */ | ||
42 | /******************************/ | ||
43 | struct wcn36xx_fw_msg_status_rsp { | ||
44 | u32 status; | ||
45 | } __packed; | ||
46 | |||
47 | struct wcn36xx_hal_ind_msg { | ||
48 | struct list_head list; | ||
49 | u8 *msg; | ||
50 | size_t msg_len; | ||
51 | }; | ||
52 | |||
53 | struct wcn36xx; | ||
54 | |||
55 | int wcn36xx_smd_open(struct wcn36xx *wcn); | ||
56 | void wcn36xx_smd_close(struct wcn36xx *wcn); | ||
57 | |||
58 | int wcn36xx_smd_load_nv(struct wcn36xx *wcn); | ||
59 | int wcn36xx_smd_start(struct wcn36xx *wcn); | ||
60 | int wcn36xx_smd_stop(struct wcn36xx *wcn); | ||
61 | int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode); | ||
62 | int wcn36xx_smd_start_scan(struct wcn36xx *wcn); | ||
63 | int wcn36xx_smd_end_scan(struct wcn36xx *wcn); | ||
64 | int wcn36xx_smd_finish_scan(struct wcn36xx *wcn, | ||
65 | enum wcn36xx_hal_sys_mode mode); | ||
66 | int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn); | ||
67 | int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif); | ||
68 | int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr); | ||
69 | int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index); | ||
70 | int wcn36xx_smd_join(struct wcn36xx *wcn, const u8 *bssid, u8 *vif, u8 ch); | ||
71 | int wcn36xx_smd_set_link_st(struct wcn36xx *wcn, const u8 *bssid, | ||
72 | const u8 *sta_mac, | ||
73 | enum wcn36xx_hal_link_state state); | ||
74 | int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif, | ||
75 | struct ieee80211_sta *sta, const u8 *bssid, | ||
76 | bool update); | ||
77 | int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif); | ||
78 | int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif, | ||
79 | struct ieee80211_sta *sta); | ||
80 | int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif, | ||
81 | struct sk_buff *skb_beacon, u16 tim_off, | ||
82 | u16 p2p_off); | ||
83 | int wcn36xx_smd_switch_channel(struct wcn36xx *wcn, | ||
84 | struct ieee80211_vif *vif, int ch); | ||
85 | int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn, | ||
86 | struct ieee80211_vif *vif, | ||
87 | struct sk_buff *skb); | ||
88 | int wcn36xx_smd_set_stakey(struct wcn36xx *wcn, | ||
89 | enum ani_ed_type enc_type, | ||
90 | u8 keyidx, | ||
91 | u8 keylen, | ||
92 | u8 *key, | ||
93 | u8 sta_index); | ||
94 | int wcn36xx_smd_set_bsskey(struct wcn36xx *wcn, | ||
95 | enum ani_ed_type enc_type, | ||
96 | u8 keyidx, | ||
97 | u8 keylen, | ||
98 | u8 *key); | ||
99 | int wcn36xx_smd_remove_stakey(struct wcn36xx *wcn, | ||
100 | enum ani_ed_type enc_type, | ||
101 | u8 keyidx, | ||
102 | u8 sta_index); | ||
103 | int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn, | ||
104 | enum ani_ed_type enc_type, | ||
105 | u8 keyidx); | ||
106 | int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif); | ||
107 | int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif); | ||
108 | int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim); | ||
109 | int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn, | ||
110 | struct ieee80211_vif *vif, | ||
111 | int packet_type); | ||
112 | int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2, | ||
113 | u32 arg3, u32 arg4, u32 arg5); | ||
114 | int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn); | ||
115 | |||
116 | int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn, | ||
117 | struct ieee80211_sta *sta, | ||
118 | u16 tid, | ||
119 | u16 *ssn, | ||
120 | u8 direction, | ||
121 | u8 sta_index); | ||
122 | int wcn36xx_smd_add_ba(struct wcn36xx *wcn); | ||
123 | int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index); | ||
124 | int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index); | ||
125 | |||
126 | int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value); | ||
127 | #endif /* _SMD_H_ */ | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.c b/drivers/net/wireless/ath/wcn36xx/txrx.c new file mode 100644 index 000000000000..b2b60e30caaf --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/txrx.c | |||
@@ -0,0 +1,284 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
19 | #include "txrx.h" | ||
20 | |||
21 | static inline int get_rssi0(struct wcn36xx_rx_bd *bd) | ||
22 | { | ||
23 | return 100 - ((bd->phy_stat0 >> 24) & 0xff); | ||
24 | } | ||
25 | |||
26 | int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb) | ||
27 | { | ||
28 | struct ieee80211_rx_status status; | ||
29 | struct ieee80211_hdr *hdr; | ||
30 | struct wcn36xx_rx_bd *bd; | ||
31 | u16 fc, sn; | ||
32 | |||
33 | /* | ||
34 | * All fields must be 0, otherwise it can lead to | ||
35 | * unexpected consequences. | ||
36 | */ | ||
37 | memset(&status, 0, sizeof(status)); | ||
38 | |||
39 | bd = (struct wcn36xx_rx_bd *)skb->data; | ||
40 | buff_to_be((u32 *)bd, sizeof(*bd)/sizeof(u32)); | ||
41 | wcn36xx_dbg_dump(WCN36XX_DBG_RX_DUMP, | ||
42 | "BD <<< ", (char *)bd, | ||
43 | sizeof(struct wcn36xx_rx_bd)); | ||
44 | |||
45 | skb_put(skb, bd->pdu.mpdu_header_off + bd->pdu.mpdu_len); | ||
46 | skb_pull(skb, bd->pdu.mpdu_header_off); | ||
47 | |||
48 | status.mactime = 10; | ||
49 | status.freq = WCN36XX_CENTER_FREQ(wcn); | ||
50 | status.band = WCN36XX_BAND(wcn); | ||
51 | status.signal = -get_rssi0(bd); | ||
52 | status.antenna = 1; | ||
53 | status.rate_idx = 1; | ||
54 | status.flag = 0; | ||
55 | status.rx_flags = 0; | ||
56 | status.flag |= RX_FLAG_IV_STRIPPED | | ||
57 | RX_FLAG_MMIC_STRIPPED | | ||
58 | RX_FLAG_DECRYPTED; | ||
59 | |||
60 | wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%x status->vendor_radiotap_len=%x\n", | ||
61 | status.flag, status.vendor_radiotap_len); | ||
62 | |||
63 | memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); | ||
64 | |||
65 | hdr = (struct ieee80211_hdr *) skb->data; | ||
66 | fc = __le16_to_cpu(hdr->frame_control); | ||
67 | sn = IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl)); | ||
68 | |||
69 | if (ieee80211_is_beacon(hdr->frame_control)) { | ||
70 | wcn36xx_dbg(WCN36XX_DBG_BEACON, "beacon skb %p len %d fc %04x sn %d\n", | ||
71 | skb, skb->len, fc, sn); | ||
72 | wcn36xx_dbg_dump(WCN36XX_DBG_BEACON_DUMP, "SKB <<< ", | ||
73 | (char *)skb->data, skb->len); | ||
74 | } else { | ||
75 | wcn36xx_dbg(WCN36XX_DBG_RX, "rx skb %p len %d fc %04x sn %d\n", | ||
76 | skb, skb->len, fc, sn); | ||
77 | wcn36xx_dbg_dump(WCN36XX_DBG_RX_DUMP, "SKB <<< ", | ||
78 | (char *)skb->data, skb->len); | ||
79 | } | ||
80 | |||
81 | ieee80211_rx_irqsafe(wcn->hw, skb); | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static void wcn36xx_set_tx_pdu(struct wcn36xx_tx_bd *bd, | ||
87 | u32 mpdu_header_len, | ||
88 | u32 len, | ||
89 | u16 tid) | ||
90 | { | ||
91 | bd->pdu.mpdu_header_len = mpdu_header_len; | ||
92 | bd->pdu.mpdu_header_off = sizeof(*bd); | ||
93 | bd->pdu.mpdu_data_off = bd->pdu.mpdu_header_len + | ||
94 | bd->pdu.mpdu_header_off; | ||
95 | bd->pdu.mpdu_len = len; | ||
96 | bd->pdu.tid = tid; | ||
97 | } | ||
98 | |||
99 | static inline struct wcn36xx_vif *get_vif_by_addr(struct wcn36xx *wcn, | ||
100 | u8 *addr) | ||
101 | { | ||
102 | struct wcn36xx_vif *vif_priv = NULL; | ||
103 | struct ieee80211_vif *vif = NULL; | ||
104 | list_for_each_entry(vif_priv, &wcn->vif_list, list) { | ||
105 | vif = container_of((void *)vif_priv, | ||
106 | struct ieee80211_vif, | ||
107 | drv_priv); | ||
108 | if (memcmp(vif->addr, addr, ETH_ALEN) == 0) | ||
109 | return vif_priv; | ||
110 | } | ||
111 | wcn36xx_warn("vif %pM not found\n", addr); | ||
112 | return NULL; | ||
113 | } | ||
114 | static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd, | ||
115 | struct wcn36xx *wcn, | ||
116 | struct wcn36xx_vif **vif_priv, | ||
117 | struct wcn36xx_sta *sta_priv, | ||
118 | struct ieee80211_hdr *hdr, | ||
119 | bool bcast) | ||
120 | { | ||
121 | struct ieee80211_vif *vif = NULL; | ||
122 | struct wcn36xx_vif *__vif_priv = NULL; | ||
123 | bd->bd_rate = WCN36XX_BD_RATE_DATA; | ||
124 | |||
125 | /* | ||
126 | * For not unicast frames mac80211 will not set sta pointer so use | ||
127 | * self_sta_index instead. | ||
128 | */ | ||
129 | if (sta_priv) { | ||
130 | __vif_priv = sta_priv->vif; | ||
131 | vif = container_of((void *)__vif_priv, | ||
132 | struct ieee80211_vif, | ||
133 | drv_priv); | ||
134 | |||
135 | if (vif->type == NL80211_IFTYPE_STATION) { | ||
136 | bd->sta_index = sta_priv->bss_sta_index; | ||
137 | bd->dpu_desc_idx = sta_priv->bss_dpu_desc_index; | ||
138 | } else if (vif->type == NL80211_IFTYPE_AP || | ||
139 | vif->type == NL80211_IFTYPE_ADHOC || | ||
140 | vif->type == NL80211_IFTYPE_MESH_POINT) { | ||
141 | bd->sta_index = sta_priv->sta_index; | ||
142 | bd->dpu_desc_idx = sta_priv->dpu_desc_index; | ||
143 | } | ||
144 | } else { | ||
145 | __vif_priv = get_vif_by_addr(wcn, hdr->addr2); | ||
146 | bd->sta_index = __vif_priv->self_sta_index; | ||
147 | bd->dpu_desc_idx = __vif_priv->self_dpu_desc_index; | ||
148 | } | ||
149 | |||
150 | bd->dpu_sign = __vif_priv->ucast_dpu_signature; | ||
151 | |||
152 | if (ieee80211_is_nullfunc(hdr->frame_control) || | ||
153 | (sta_priv && !sta_priv->is_data_encrypted)) | ||
154 | bd->dpu_ne = 1; | ||
155 | |||
156 | if (bcast) { | ||
157 | bd->ub = 1; | ||
158 | bd->ack_policy = 1; | ||
159 | } | ||
160 | *vif_priv = __vif_priv; | ||
161 | } | ||
162 | |||
163 | static void wcn36xx_set_tx_mgmt(struct wcn36xx_tx_bd *bd, | ||
164 | struct wcn36xx *wcn, | ||
165 | struct wcn36xx_vif **vif_priv, | ||
166 | struct ieee80211_hdr *hdr, | ||
167 | bool bcast) | ||
168 | { | ||
169 | struct wcn36xx_vif *__vif_priv = | ||
170 | get_vif_by_addr(wcn, hdr->addr2); | ||
171 | bd->sta_index = __vif_priv->self_sta_index; | ||
172 | bd->dpu_desc_idx = __vif_priv->self_dpu_desc_index; | ||
173 | bd->dpu_ne = 1; | ||
174 | |||
175 | /* default rate for unicast */ | ||
176 | if (ieee80211_is_mgmt(hdr->frame_control)) | ||
177 | bd->bd_rate = (WCN36XX_BAND(wcn) == IEEE80211_BAND_5GHZ) ? | ||
178 | WCN36XX_BD_RATE_CTRL : | ||
179 | WCN36XX_BD_RATE_MGMT; | ||
180 | else if (ieee80211_is_ctl(hdr->frame_control)) | ||
181 | bd->bd_rate = WCN36XX_BD_RATE_CTRL; | ||
182 | else | ||
183 | wcn36xx_warn("frame control type unknown\n"); | ||
184 | |||
185 | /* | ||
186 | * In joining state trick hardware that probe is sent as | ||
187 | * unicast even if address is broadcast. | ||
188 | */ | ||
189 | if (__vif_priv->is_joining && | ||
190 | ieee80211_is_probe_req(hdr->frame_control)) | ||
191 | bcast = false; | ||
192 | |||
193 | if (bcast) { | ||
194 | /* broadcast */ | ||
195 | bd->ub = 1; | ||
196 | /* No ack needed not unicast */ | ||
197 | bd->ack_policy = 1; | ||
198 | bd->queue_id = WCN36XX_TX_B_WQ_ID; | ||
199 | } else | ||
200 | bd->queue_id = WCN36XX_TX_U_WQ_ID; | ||
201 | *vif_priv = __vif_priv; | ||
202 | } | ||
203 | |||
204 | int wcn36xx_start_tx(struct wcn36xx *wcn, | ||
205 | struct wcn36xx_sta *sta_priv, | ||
206 | struct sk_buff *skb) | ||
207 | { | ||
208 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
209 | struct wcn36xx_vif *vif_priv = NULL; | ||
210 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
211 | unsigned long flags; | ||
212 | bool is_low = ieee80211_is_data(hdr->frame_control); | ||
213 | bool bcast = is_broadcast_ether_addr(hdr->addr1) || | ||
214 | is_multicast_ether_addr(hdr->addr1); | ||
215 | struct wcn36xx_tx_bd *bd = wcn36xx_dxe_get_next_bd(wcn, is_low); | ||
216 | |||
217 | if (!bd) { | ||
218 | /* | ||
219 | * TX DXE are used in pairs. One for the BD and one for the | ||
220 | * actual frame. The BD DXE's has a preallocated buffer while | ||
221 | * the skb ones does not. If this isn't true something is really | ||
222 | * wierd. TODO: Recover from this situation | ||
223 | */ | ||
224 | |||
225 | wcn36xx_err("bd address may not be NULL for BD DXE\n"); | ||
226 | return -EINVAL; | ||
227 | } | ||
228 | |||
229 | memset(bd, 0, sizeof(*bd)); | ||
230 | |||
231 | wcn36xx_dbg(WCN36XX_DBG_TX, | ||
232 | "tx skb %p len %d fc %04x sn %d %s %s\n", | ||
233 | skb, skb->len, __le16_to_cpu(hdr->frame_control), | ||
234 | IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl)), | ||
235 | is_low ? "low" : "high", bcast ? "bcast" : "ucast"); | ||
236 | |||
237 | wcn36xx_dbg_dump(WCN36XX_DBG_TX_DUMP, "", skb->data, skb->len); | ||
238 | |||
239 | bd->dpu_rf = WCN36XX_BMU_WQ_TX; | ||
240 | |||
241 | bd->tx_comp = info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
242 | if (bd->tx_comp) { | ||
243 | wcn36xx_dbg(WCN36XX_DBG_DXE, "TX_ACK status requested\n"); | ||
244 | spin_lock_irqsave(&wcn->dxe_lock, flags); | ||
245 | if (wcn->tx_ack_skb) { | ||
246 | spin_unlock_irqrestore(&wcn->dxe_lock, flags); | ||
247 | wcn36xx_warn("tx_ack_skb already set\n"); | ||
248 | return -EINVAL; | ||
249 | } | ||
250 | |||
251 | wcn->tx_ack_skb = skb; | ||
252 | spin_unlock_irqrestore(&wcn->dxe_lock, flags); | ||
253 | |||
254 | /* Only one at a time is supported by fw. Stop the TX queues | ||
255 | * until the ack status gets back. | ||
256 | * | ||
257 | * TODO: Add watchdog in case FW does not answer | ||
258 | */ | ||
259 | ieee80211_stop_queues(wcn->hw); | ||
260 | } | ||
261 | |||
262 | /* Data frames served first*/ | ||
263 | if (is_low) { | ||
264 | wcn36xx_set_tx_data(bd, wcn, &vif_priv, sta_priv, hdr, bcast); | ||
265 | wcn36xx_set_tx_pdu(bd, | ||
266 | ieee80211_is_data_qos(hdr->frame_control) ? | ||
267 | sizeof(struct ieee80211_qos_hdr) : | ||
268 | sizeof(struct ieee80211_hdr_3addr), | ||
269 | skb->len, sta_priv ? sta_priv->tid : 0); | ||
270 | } else { | ||
271 | /* MGMT and CTRL frames are handeld here*/ | ||
272 | wcn36xx_set_tx_mgmt(bd, wcn, &vif_priv, hdr, bcast); | ||
273 | wcn36xx_set_tx_pdu(bd, | ||
274 | ieee80211_is_data_qos(hdr->frame_control) ? | ||
275 | sizeof(struct ieee80211_qos_hdr) : | ||
276 | sizeof(struct ieee80211_hdr_3addr), | ||
277 | skb->len, WCN36XX_TID); | ||
278 | } | ||
279 | |||
280 | buff_to_be((u32 *)bd, sizeof(*bd)/sizeof(u32)); | ||
281 | bd->tx_bd_sign = 0xbdbdbdbd; | ||
282 | |||
283 | return wcn36xx_dxe_tx_frame(wcn, vif_priv, skb, is_low); | ||
284 | } | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.h b/drivers/net/wireless/ath/wcn36xx/txrx.h new file mode 100644 index 000000000000..bbfbcf808c77 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/txrx.h | |||
@@ -0,0 +1,160 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef _TXRX_H_ | ||
18 | #define _TXRX_H_ | ||
19 | |||
20 | #include <linux/etherdevice.h> | ||
21 | #include "wcn36xx.h" | ||
22 | |||
23 | /* TODO describe all properties */ | ||
24 | #define WCN36XX_802_11_HEADER_LEN 24 | ||
25 | #define WCN36XX_BMU_WQ_TX 25 | ||
26 | #define WCN36XX_TID 7 | ||
27 | /* broadcast wq ID */ | ||
28 | #define WCN36XX_TX_B_WQ_ID 0xA | ||
29 | #define WCN36XX_TX_U_WQ_ID 0x9 | ||
30 | /* bd_rate */ | ||
31 | #define WCN36XX_BD_RATE_DATA 0 | ||
32 | #define WCN36XX_BD_RATE_MGMT 2 | ||
33 | #define WCN36XX_BD_RATE_CTRL 3 | ||
34 | |||
35 | struct wcn36xx_pdu { | ||
36 | u32 dpu_fb:8; | ||
37 | u32 adu_fb:8; | ||
38 | u32 pdu_id:16; | ||
39 | |||
40 | /* 0x04*/ | ||
41 | u32 tail_pdu_idx:16; | ||
42 | u32 head_pdu_idx:16; | ||
43 | |||
44 | /* 0x08*/ | ||
45 | u32 pdu_count:7; | ||
46 | u32 mpdu_data_off:9; | ||
47 | u32 mpdu_header_off:8; | ||
48 | u32 mpdu_header_len:8; | ||
49 | |||
50 | /* 0x0c*/ | ||
51 | u32 reserved4:8; | ||
52 | u32 tid:4; | ||
53 | u32 reserved3:4; | ||
54 | u32 mpdu_len:16; | ||
55 | }; | ||
56 | |||
57 | struct wcn36xx_rx_bd { | ||
58 | u32 bdt:2; | ||
59 | u32 ft:1; | ||
60 | u32 dpu_ne:1; | ||
61 | u32 rx_key_id:3; | ||
62 | u32 ub:1; | ||
63 | u32 rmf:1; | ||
64 | u32 uma_bypass:1; | ||
65 | u32 csr11:1; | ||
66 | u32 reserved0:1; | ||
67 | u32 scan_learn:1; | ||
68 | u32 rx_ch:4; | ||
69 | u32 rtsf:1; | ||
70 | u32 bsf:1; | ||
71 | u32 a2hf:1; | ||
72 | u32 st_auf:1; | ||
73 | u32 dpu_sign:3; | ||
74 | u32 dpu_rf:8; | ||
75 | |||
76 | struct wcn36xx_pdu pdu; | ||
77 | |||
78 | /* 0x14*/ | ||
79 | u32 addr3:8; | ||
80 | u32 addr2:8; | ||
81 | u32 addr1:8; | ||
82 | u32 dpu_desc_idx:8; | ||
83 | |||
84 | /* 0x18*/ | ||
85 | u32 rxp_flags:23; | ||
86 | u32 rate_id:9; | ||
87 | |||
88 | u32 phy_stat0; | ||
89 | u32 phy_stat1; | ||
90 | |||
91 | /* 0x24 */ | ||
92 | u32 rx_times; | ||
93 | |||
94 | u32 pmi_cmd[6]; | ||
95 | |||
96 | /* 0x40 */ | ||
97 | u32 reserved7:4; | ||
98 | u32 reorder_slot_id:6; | ||
99 | u32 reorder_fwd_id:6; | ||
100 | u32 reserved6:12; | ||
101 | u32 reorder_code:4; | ||
102 | |||
103 | /* 0x44 */ | ||
104 | u32 exp_seq_num:12; | ||
105 | u32 cur_seq_num:12; | ||
106 | u32 fr_type_subtype:8; | ||
107 | |||
108 | /* 0x48 */ | ||
109 | u32 msdu_size:16; | ||
110 | u32 sub_fr_id:4; | ||
111 | u32 proc_order:4; | ||
112 | u32 reserved9:4; | ||
113 | u32 aef:1; | ||
114 | u32 lsf:1; | ||
115 | u32 esf:1; | ||
116 | u32 asf:1; | ||
117 | }; | ||
118 | |||
119 | struct wcn36xx_tx_bd { | ||
120 | u32 bdt:2; | ||
121 | u32 ft:1; | ||
122 | u32 dpu_ne:1; | ||
123 | u32 fw_tx_comp:1; | ||
124 | u32 tx_comp:1; | ||
125 | u32 reserved1:1; | ||
126 | u32 ub:1; | ||
127 | u32 rmf:1; | ||
128 | u32 reserved0:12; | ||
129 | u32 dpu_sign:3; | ||
130 | u32 dpu_rf:8; | ||
131 | |||
132 | struct wcn36xx_pdu pdu; | ||
133 | |||
134 | /* 0x14*/ | ||
135 | u32 reserved5:7; | ||
136 | u32 queue_id:5; | ||
137 | u32 bd_rate:2; | ||
138 | u32 ack_policy:2; | ||
139 | u32 sta_index:8; | ||
140 | u32 dpu_desc_idx:8; | ||
141 | |||
142 | u32 tx_bd_sign; | ||
143 | u32 reserved6; | ||
144 | u32 dxe_start_time; | ||
145 | u32 dxe_end_time; | ||
146 | |||
147 | /*u32 tcp_udp_start_off:10; | ||
148 | u32 header_cks:16; | ||
149 | u32 reserved7:6;*/ | ||
150 | }; | ||
151 | |||
152 | struct wcn36xx_sta; | ||
153 | struct wcn36xx; | ||
154 | |||
155 | int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb); | ||
156 | int wcn36xx_start_tx(struct wcn36xx *wcn, | ||
157 | struct wcn36xx_sta *sta_priv, | ||
158 | struct sk_buff *skb); | ||
159 | |||
160 | #endif /* _TXRX_H_ */ | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h new file mode 100644 index 000000000000..58b63833e8e7 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h | |||
@@ -0,0 +1,238 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef _WCN36XX_H_ | ||
18 | #define _WCN36XX_H_ | ||
19 | |||
20 | #include <linux/completion.h> | ||
21 | #include <linux/printk.h> | ||
22 | #include <linux/spinlock.h> | ||
23 | #include <net/mac80211.h> | ||
24 | |||
25 | #include "hal.h" | ||
26 | #include "smd.h" | ||
27 | #include "txrx.h" | ||
28 | #include "dxe.h" | ||
29 | #include "pmc.h" | ||
30 | #include "debug.h" | ||
31 | |||
32 | #define WLAN_NV_FILE "wlan/prima/WCNSS_qcom_wlan_nv.bin" | ||
33 | #define WCN36XX_AGGR_BUFFER_SIZE 64 | ||
34 | |||
35 | extern unsigned int wcn36xx_dbg_mask; | ||
36 | |||
37 | enum wcn36xx_debug_mask { | ||
38 | WCN36XX_DBG_DXE = 0x00000001, | ||
39 | WCN36XX_DBG_DXE_DUMP = 0x00000002, | ||
40 | WCN36XX_DBG_SMD = 0x00000004, | ||
41 | WCN36XX_DBG_SMD_DUMP = 0x00000008, | ||
42 | WCN36XX_DBG_RX = 0x00000010, | ||
43 | WCN36XX_DBG_RX_DUMP = 0x00000020, | ||
44 | WCN36XX_DBG_TX = 0x00000040, | ||
45 | WCN36XX_DBG_TX_DUMP = 0x00000080, | ||
46 | WCN36XX_DBG_HAL = 0x00000100, | ||
47 | WCN36XX_DBG_HAL_DUMP = 0x00000200, | ||
48 | WCN36XX_DBG_MAC = 0x00000400, | ||
49 | WCN36XX_DBG_BEACON = 0x00000800, | ||
50 | WCN36XX_DBG_BEACON_DUMP = 0x00001000, | ||
51 | WCN36XX_DBG_PMC = 0x00002000, | ||
52 | WCN36XX_DBG_PMC_DUMP = 0x00004000, | ||
53 | WCN36XX_DBG_ANY = 0xffffffff, | ||
54 | }; | ||
55 | |||
56 | #define wcn36xx_err(fmt, arg...) \ | ||
57 | printk(KERN_ERR pr_fmt("ERROR " fmt), ##arg); | ||
58 | |||
59 | #define wcn36xx_warn(fmt, arg...) \ | ||
60 | printk(KERN_WARNING pr_fmt("WARNING " fmt), ##arg) | ||
61 | |||
62 | #define wcn36xx_info(fmt, arg...) \ | ||
63 | printk(KERN_INFO pr_fmt(fmt), ##arg) | ||
64 | |||
65 | #define wcn36xx_dbg(mask, fmt, arg...) do { \ | ||
66 | if (wcn36xx_dbg_mask & mask) \ | ||
67 | printk(KERN_DEBUG pr_fmt(fmt), ##arg); \ | ||
68 | } while (0) | ||
69 | |||
70 | #define wcn36xx_dbg_dump(mask, prefix_str, buf, len) do { \ | ||
71 | if (wcn36xx_dbg_mask & mask) \ | ||
72 | print_hex_dump(KERN_DEBUG, pr_fmt(prefix_str), \ | ||
73 | DUMP_PREFIX_OFFSET, 32, 1, \ | ||
74 | buf, len, false); \ | ||
75 | } while (0) | ||
76 | |||
77 | #define WCN36XX_HW_CHANNEL(__wcn) (__wcn->hw->conf.chandef.chan->hw_value) | ||
78 | #define WCN36XX_BAND(__wcn) (__wcn->hw->conf.chandef.chan->band) | ||
79 | #define WCN36XX_CENTER_FREQ(__wcn) (__wcn->hw->conf.chandef.chan->center_freq) | ||
80 | #define WCN36XX_LISTEN_INTERVAL(__wcn) (__wcn->hw->conf.listen_interval) | ||
81 | #define WCN36XX_FLAGS(__wcn) (__wcn->hw->flags) | ||
82 | #define WCN36XX_MAX_POWER(__wcn) (__wcn->hw->conf.chandef.chan->max_power) | ||
83 | |||
84 | static inline void buff_to_be(u32 *buf, size_t len) | ||
85 | { | ||
86 | int i; | ||
87 | for (i = 0; i < len; i++) | ||
88 | buf[i] = cpu_to_be32(buf[i]); | ||
89 | } | ||
90 | |||
91 | struct nv_data { | ||
92 | int is_valid; | ||
93 | u8 table; | ||
94 | }; | ||
95 | |||
96 | /* Interface for platform control path | ||
97 | * | ||
98 | * @open: hook must be called when wcn36xx wants to open control channel. | ||
99 | * @tx: sends a buffer. | ||
100 | */ | ||
101 | struct wcn36xx_platform_ctrl_ops { | ||
102 | int (*open)(void *drv_priv, void *rsp_cb); | ||
103 | void (*close)(void); | ||
104 | int (*tx)(char *buf, size_t len); | ||
105 | int (*get_hw_mac)(u8 *addr); | ||
106 | int (*smsm_change_state)(u32 clear_mask, u32 set_mask); | ||
107 | }; | ||
108 | |||
109 | /** | ||
110 | * struct wcn36xx_vif - holds VIF related fields | ||
111 | * | ||
112 | * @bss_index: bss_index is initially set to 0xFF. bss_index is received from | ||
113 | * HW after first config_bss call and must be used in delete_bss and | ||
114 | * enter/exit_bmps. | ||
115 | */ | ||
116 | struct wcn36xx_vif { | ||
117 | struct list_head list; | ||
118 | struct wcn36xx_sta *sta; | ||
119 | u8 dtim_period; | ||
120 | enum ani_ed_type encrypt_type; | ||
121 | bool is_joining; | ||
122 | struct wcn36xx_hal_mac_ssid ssid; | ||
123 | |||
124 | /* Power management */ | ||
125 | enum wcn36xx_power_state pw_state; | ||
126 | |||
127 | u8 bss_index; | ||
128 | u8 ucast_dpu_signature; | ||
129 | /* Returned from WCN36XX_HAL_ADD_STA_SELF_RSP */ | ||
130 | u8 self_sta_index; | ||
131 | u8 self_dpu_desc_index; | ||
132 | }; | ||
133 | |||
134 | /** | ||
135 | * struct wcn36xx_sta - holds STA related fields | ||
136 | * | ||
137 | * @tid: traffic ID that is used during AMPDU and in TX BD. | ||
138 | * @sta_index: STA index is returned from HW after config_sta call and is | ||
139 | * used in both SMD channel and TX BD. | ||
140 | * @dpu_desc_index: DPU descriptor index is returned from HW after config_sta | ||
141 | * call and is used in TX BD. | ||
142 | * @bss_sta_index: STA index is returned from HW after config_bss call and is | ||
143 | * used in both SMD channel and TX BD. See table bellow when it is used. | ||
144 | * @bss_dpu_desc_index: DPU descriptor index is returned from HW after | ||
145 | * config_bss call and is used in TX BD. | ||
146 | * ______________________________________________ | ||
147 | * | | STA | AP | | ||
148 | * |______________|_____________|_______________| | ||
149 | * | TX BD |bss_sta_index| sta_index | | ||
150 | * |______________|_____________|_______________| | ||
151 | * |all SMD calls |bss_sta_index| sta_index | | ||
152 | * |______________|_____________|_______________| | ||
153 | * |smd_delete_sta| sta_index | sta_index | | ||
154 | * |______________|_____________|_______________| | ||
155 | */ | ||
156 | struct wcn36xx_sta { | ||
157 | struct wcn36xx_vif *vif; | ||
158 | u16 aid; | ||
159 | u16 tid; | ||
160 | u8 sta_index; | ||
161 | u8 dpu_desc_index; | ||
162 | u8 bss_sta_index; | ||
163 | u8 bss_dpu_desc_index; | ||
164 | bool is_data_encrypted; | ||
165 | /* Rates */ | ||
166 | struct wcn36xx_hal_supported_rates supported_rates; | ||
167 | }; | ||
168 | struct wcn36xx_dxe_ch; | ||
169 | struct wcn36xx { | ||
170 | struct ieee80211_hw *hw; | ||
171 | struct device *dev; | ||
172 | struct list_head vif_list; | ||
173 | |||
174 | u8 fw_revision; | ||
175 | u8 fw_version; | ||
176 | u8 fw_minor; | ||
177 | u8 fw_major; | ||
178 | |||
179 | /* extra byte for the NULL termination */ | ||
180 | u8 crm_version[WCN36XX_HAL_VERSION_LENGTH + 1]; | ||
181 | u8 wlan_version[WCN36XX_HAL_VERSION_LENGTH + 1]; | ||
182 | |||
183 | /* IRQs */ | ||
184 | int tx_irq; | ||
185 | int rx_irq; | ||
186 | void __iomem *mmio; | ||
187 | |||
188 | struct wcn36xx_platform_ctrl_ops *ctrl_ops; | ||
189 | /* | ||
190 | * smd_buf must be protected with smd_mutex to garantee | ||
191 | * that all messages are sent one after another | ||
192 | */ | ||
193 | u8 *hal_buf; | ||
194 | size_t hal_rsp_len; | ||
195 | struct mutex hal_mutex; | ||
196 | struct completion hal_rsp_compl; | ||
197 | struct workqueue_struct *hal_ind_wq; | ||
198 | struct work_struct hal_ind_work; | ||
199 | struct mutex hal_ind_mutex; | ||
200 | struct list_head hal_ind_queue; | ||
201 | |||
202 | /* DXE channels */ | ||
203 | struct wcn36xx_dxe_ch dxe_tx_l_ch; /* TX low */ | ||
204 | struct wcn36xx_dxe_ch dxe_tx_h_ch; /* TX high */ | ||
205 | struct wcn36xx_dxe_ch dxe_rx_l_ch; /* RX low */ | ||
206 | struct wcn36xx_dxe_ch dxe_rx_h_ch; /* RX high */ | ||
207 | |||
208 | /* For synchronization of DXE resources from BH, IRQ and WQ contexts */ | ||
209 | spinlock_t dxe_lock; | ||
210 | bool queues_stopped; | ||
211 | |||
212 | /* Memory pools */ | ||
213 | struct wcn36xx_dxe_mem_pool mgmt_mem_pool; | ||
214 | struct wcn36xx_dxe_mem_pool data_mem_pool; | ||
215 | |||
216 | struct sk_buff *tx_ack_skb; | ||
217 | |||
218 | #ifdef CONFIG_WCN36XX_DEBUGFS | ||
219 | /* Debug file system entry */ | ||
220 | struct wcn36xx_dfs_entry dfs; | ||
221 | #endif /* CONFIG_WCN36XX_DEBUGFS */ | ||
222 | |||
223 | }; | ||
224 | |||
225 | static inline bool wcn36xx_is_fw_version(struct wcn36xx *wcn, | ||
226 | u8 major, | ||
227 | u8 minor, | ||
228 | u8 version, | ||
229 | u8 revision) | ||
230 | { | ||
231 | return (wcn->fw_major == major && | ||
232 | wcn->fw_minor == minor && | ||
233 | wcn->fw_version == version && | ||
234 | wcn->fw_revision == revision); | ||
235 | } | ||
236 | void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates); | ||
237 | |||
238 | #endif /* _WCN36XX_H_ */ | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index 69b14dc4dd55..8138f1cff4e5 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c | |||
@@ -5695,7 +5695,7 @@ static bool brcms_c_chipmatch_pci(struct bcma_device *core) | |||
5695 | return true; | 5695 | return true; |
5696 | if ((device == BCM43224_D11N_ID) || (device == BCM43225_D11N2G_ID)) | 5696 | if ((device == BCM43224_D11N_ID) || (device == BCM43225_D11N2G_ID)) |
5697 | return true; | 5697 | return true; |
5698 | if (device == BCM4313_D11N2G_ID) | 5698 | if (device == BCM4313_D11N2G_ID || device == BCM4313_CHIP_ID) |
5699 | return true; | 5699 | return true; |
5700 | if ((device == BCM43236_D11N_ID) || (device == BCM43236_D11N2G_ID)) | 5700 | if ((device == BCM43236_D11N_ID) || (device == BCM43236_D11N2G_ID)) |
5701 | return true; | 5701 | return true; |
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index a6c46f3b6e3a..e47f4e3012b8 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c | |||
@@ -1048,7 +1048,7 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) | |||
1048 | struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; | 1048 | struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; |
1049 | unsigned long cmd_flags; | 1049 | unsigned long cmd_flags; |
1050 | unsigned long scan_pending_q_flags; | 1050 | unsigned long scan_pending_q_flags; |
1051 | uint16_t cancel_scan_cmd = false; | 1051 | bool cancel_scan_cmd = false; |
1052 | 1052 | ||
1053 | if ((adapter->curr_cmd) && | 1053 | if ((adapter->curr_cmd) && |
1054 | (adapter->curr_cmd->wait_q_enabled)) { | 1054 | (adapter->curr_cmd->wait_q_enabled)) { |
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 9d7c0e6c4fc7..717fbe2e0e5a 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c | |||
@@ -621,7 +621,7 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, | |||
621 | int ret = 0; | 621 | int ret = 0; |
622 | struct ieee_types_assoc_rsp *assoc_rsp; | 622 | struct ieee_types_assoc_rsp *assoc_rsp; |
623 | struct mwifiex_bssdescriptor *bss_desc; | 623 | struct mwifiex_bssdescriptor *bss_desc; |
624 | u8 enable_data = true; | 624 | bool enable_data = true; |
625 | u16 cap_info, status_code; | 625 | u16 cap_info, status_code; |
626 | 626 | ||
627 | assoc_rsp = (struct ieee_types_assoc_rsp *) &resp->params; | 627 | assoc_rsp = (struct ieee_types_assoc_rsp *) &resp->params; |
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index c2b91f566e05..9d7c9d354d34 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
@@ -882,7 +882,9 @@ mwifiex_add_card(void *card, struct semaphore *sem, | |||
882 | adapter->cmd_wait_q.status = 0; | 882 | adapter->cmd_wait_q.status = 0; |
883 | adapter->scan_wait_q_woken = false; | 883 | adapter->scan_wait_q_woken = false; |
884 | 884 | ||
885 | adapter->workqueue = create_workqueue("MWIFIEX_WORK_QUEUE"); | 885 | adapter->workqueue = |
886 | alloc_workqueue("MWIFIEX_WORK_QUEUE", | ||
887 | WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1); | ||
886 | if (!adapter->workqueue) | 888 | if (!adapter->workqueue) |
887 | goto err_kmalloc; | 889 | goto err_kmalloc; |
888 | 890 | ||
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index c0268b597748..7d66018a2e33 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
@@ -327,7 +327,7 @@ mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv, | |||
327 | { | 327 | { |
328 | struct mwifiex_adapter *adapter = priv->adapter; | 328 | struct mwifiex_adapter *adapter = priv->adapter; |
329 | struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = &cmd->params.opt_hs_cfg; | 329 | struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = &cmd->params.opt_hs_cfg; |
330 | u16 hs_activate = false; | 330 | bool hs_activate = false; |
331 | 331 | ||
332 | if (!hscfg_param) | 332 | if (!hscfg_param) |
333 | /* New Activate command */ | 333 | /* New Activate command */ |
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 95fa3599b407..5dd0ccc70b86 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c | |||
@@ -708,7 +708,7 @@ int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv, | |||
708 | { | 708 | { |
709 | u8 *curr = (u8 *) &resp->params.get_wmm_status; | 709 | u8 *curr = (u8 *) &resp->params.get_wmm_status; |
710 | uint16_t resp_len = le16_to_cpu(resp->size), tlv_len; | 710 | uint16_t resp_len = le16_to_cpu(resp->size), tlv_len; |
711 | int valid = true; | 711 | bool valid = true; |
712 | 712 | ||
713 | struct mwifiex_ie_types_data *tlv_hdr; | 713 | struct mwifiex_ie_types_data *tlv_hdr; |
714 | struct mwifiex_ie_types_wmm_queue_status *tlv_wmm_qstatus; | 714 | struct mwifiex_ie_types_wmm_queue_status *tlv_wmm_qstatus; |
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index 7fc46f26cf2b..de15171e2cd8 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c | |||
@@ -636,7 +636,7 @@ static int p54spi_probe(struct spi_device *spi) | |||
636 | gpio_direction_input(p54spi_gpio_irq); | 636 | gpio_direction_input(p54spi_gpio_irq); |
637 | 637 | ||
638 | ret = request_irq(gpio_to_irq(p54spi_gpio_irq), | 638 | ret = request_irq(gpio_to_irq(p54spi_gpio_irq), |
639 | p54spi_interrupt, IRQF_DISABLED, "p54spi", | 639 | p54spi_interrupt, 0, "p54spi", |
640 | priv->spi); | 640 | priv->spi); |
641 | if (ret < 0) { | 641 | if (ret < 0) { |
642 | dev_err(&priv->spi->dev, "request_irq() failed"); | 642 | dev_err(&priv->spi->dev, "request_irq() failed"); |
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 68dbbb9c6d12..a18b0051a745 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig | |||
@@ -219,6 +219,7 @@ config RT2X00_LIB_USB | |||
219 | 219 | ||
220 | config RT2X00_LIB | 220 | config RT2X00_LIB |
221 | tristate | 221 | tristate |
222 | select AVERAGE | ||
222 | 223 | ||
223 | config RT2X00_LIB_FIRMWARE | 224 | config RT2X00_LIB_FIRMWARE |
224 | boolean | 225 | boolean |
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index e3eb95292a7f..aab6b5e4f5dd 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
@@ -124,7 +124,7 @@ | |||
124 | /* | 124 | /* |
125 | * MAC_CSR0_3290: MAC_CSR0 for RT3290 to identity MAC version number. | 125 | * MAC_CSR0_3290: MAC_CSR0 for RT3290 to identity MAC version number. |
126 | */ | 126 | */ |
127 | #define MAC_CSR0_3290 0x0000 | 127 | #define MAC_CSR0_3290 0x0000 |
128 | 128 | ||
129 | /* | 129 | /* |
130 | * E2PROM_CSR: PCI EEPROM control register. | 130 | * E2PROM_CSR: PCI EEPROM control register. |
@@ -213,17 +213,17 @@ | |||
213 | /* | 213 | /* |
214 | * COEX_CFG_0 | 214 | * COEX_CFG_0 |
215 | */ | 215 | */ |
216 | #define COEX_CFG0 0x0040 | 216 | #define COEX_CFG0 0x0040 |
217 | #define COEX_CFG_ANT FIELD32(0xff000000) | 217 | #define COEX_CFG_ANT FIELD32(0xff000000) |
218 | /* | 218 | /* |
219 | * COEX_CFG_1 | 219 | * COEX_CFG_1 |
220 | */ | 220 | */ |
221 | #define COEX_CFG1 0x0044 | 221 | #define COEX_CFG1 0x0044 |
222 | 222 | ||
223 | /* | 223 | /* |
224 | * COEX_CFG_2 | 224 | * COEX_CFG_2 |
225 | */ | 225 | */ |
226 | #define COEX_CFG2 0x0048 | 226 | #define COEX_CFG2 0x0048 |
227 | #define BT_COEX_CFG1 FIELD32(0xff000000) | 227 | #define BT_COEX_CFG1 FIELD32(0xff000000) |
228 | #define BT_COEX_CFG0 FIELD32(0x00ff0000) | 228 | #define BT_COEX_CFG0 FIELD32(0x00ff0000) |
229 | #define WL_COEX_CFG1 FIELD32(0x0000ff00) | 229 | #define WL_COEX_CFG1 FIELD32(0x0000ff00) |
@@ -237,8 +237,8 @@ | |||
237 | #define PLL_RESERVED_INPUT2 FIELD32(0x0000ff00) | 237 | #define PLL_RESERVED_INPUT2 FIELD32(0x0000ff00) |
238 | #define PLL_CONTROL FIELD32(0x00070000) | 238 | #define PLL_CONTROL FIELD32(0x00070000) |
239 | #define PLL_LPF_R1 FIELD32(0x00080000) | 239 | #define PLL_LPF_R1 FIELD32(0x00080000) |
240 | #define PLL_LPF_C1_CTRL FIELD32(0x00300000) | 240 | #define PLL_LPF_C1_CTRL FIELD32(0x00300000) |
241 | #define PLL_LPF_C2_CTRL FIELD32(0x00c00000) | 241 | #define PLL_LPF_C2_CTRL FIELD32(0x00c00000) |
242 | #define PLL_CP_CURRENT_CTRL FIELD32(0x03000000) | 242 | #define PLL_CP_CURRENT_CTRL FIELD32(0x03000000) |
243 | #define PLL_PFD_DELAY_CTRL FIELD32(0x0c000000) | 243 | #define PLL_PFD_DELAY_CTRL FIELD32(0x0c000000) |
244 | #define PLL_LOCK_CTRL FIELD32(0x70000000) | 244 | #define PLL_LOCK_CTRL FIELD32(0x70000000) |
@@ -2166,7 +2166,7 @@ struct mac_iveiv_entry { | |||
2166 | */ | 2166 | */ |
2167 | #define RFCSR6_R1 FIELD8(0x03) | 2167 | #define RFCSR6_R1 FIELD8(0x03) |
2168 | #define RFCSR6_R2 FIELD8(0x40) | 2168 | #define RFCSR6_R2 FIELD8(0x40) |
2169 | #define RFCSR6_TXDIV FIELD8(0x0c) | 2169 | #define RFCSR6_TXDIV FIELD8(0x0c) |
2170 | /* bits for RF3053 */ | 2170 | /* bits for RF3053 */ |
2171 | #define RFCSR6_VCO_IC FIELD8(0xc0) | 2171 | #define RFCSR6_VCO_IC FIELD8(0xc0) |
2172 | 2172 | ||
@@ -2204,13 +2204,13 @@ struct mac_iveiv_entry { | |||
2204 | * RFCSR 12: | 2204 | * RFCSR 12: |
2205 | */ | 2205 | */ |
2206 | #define RFCSR12_TX_POWER FIELD8(0x1f) | 2206 | #define RFCSR12_TX_POWER FIELD8(0x1f) |
2207 | #define RFCSR12_DR0 FIELD8(0xe0) | 2207 | #define RFCSR12_DR0 FIELD8(0xe0) |
2208 | 2208 | ||
2209 | /* | 2209 | /* |
2210 | * RFCSR 13: | 2210 | * RFCSR 13: |
2211 | */ | 2211 | */ |
2212 | #define RFCSR13_TX_POWER FIELD8(0x1f) | 2212 | #define RFCSR13_TX_POWER FIELD8(0x1f) |
2213 | #define RFCSR13_DR0 FIELD8(0xe0) | 2213 | #define RFCSR13_DR0 FIELD8(0xe0) |
2214 | 2214 | ||
2215 | /* | 2215 | /* |
2216 | * RFCSR 15: | 2216 | * RFCSR 15: |
@@ -2228,7 +2228,7 @@ struct mac_iveiv_entry { | |||
2228 | #define RFCSR17_TXMIXER_GAIN FIELD8(0x07) | 2228 | #define RFCSR17_TXMIXER_GAIN FIELD8(0x07) |
2229 | #define RFCSR17_TX_LO1_EN FIELD8(0x08) | 2229 | #define RFCSR17_TX_LO1_EN FIELD8(0x08) |
2230 | #define RFCSR17_R FIELD8(0x20) | 2230 | #define RFCSR17_R FIELD8(0x20) |
2231 | #define RFCSR17_CODE FIELD8(0x7f) | 2231 | #define RFCSR17_CODE FIELD8(0x7f) |
2232 | 2232 | ||
2233 | /* RFCSR 18 */ | 2233 | /* RFCSR 18 */ |
2234 | #define RFCSR18_XO_TUNE_BYPASS FIELD8(0x40) | 2234 | #define RFCSR18_XO_TUNE_BYPASS FIELD8(0x40) |
@@ -2451,7 +2451,7 @@ enum rt2800_eeprom_word { | |||
2451 | */ | 2451 | */ |
2452 | #define EEPROM_NIC_CONF0_RXPATH FIELD16(0x000f) | 2452 | #define EEPROM_NIC_CONF0_RXPATH FIELD16(0x000f) |
2453 | #define EEPROM_NIC_CONF0_TXPATH FIELD16(0x00f0) | 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 | * EEPROM NIC Configuration 1 | 2457 | * EEPROM NIC Configuration 1 |
@@ -2473,18 +2473,18 @@ enum rt2800_eeprom_word { | |||
2473 | * DAC_TEST: 0: disable, 1: enable | 2473 | * DAC_TEST: 0: disable, 1: enable |
2474 | */ | 2474 | */ |
2475 | #define EEPROM_NIC_CONF1_HW_RADIO FIELD16(0x0001) | 2475 | #define EEPROM_NIC_CONF1_HW_RADIO FIELD16(0x0001) |
2476 | #define EEPROM_NIC_CONF1_EXTERNAL_TX_ALC FIELD16(0x0002) | 2476 | #define EEPROM_NIC_CONF1_EXTERNAL_TX_ALC FIELD16(0x0002) |
2477 | #define EEPROM_NIC_CONF1_EXTERNAL_LNA_2G FIELD16(0x0004) | 2477 | #define EEPROM_NIC_CONF1_EXTERNAL_LNA_2G FIELD16(0x0004) |
2478 | #define EEPROM_NIC_CONF1_EXTERNAL_LNA_5G FIELD16(0x0008) | 2478 | #define EEPROM_NIC_CONF1_EXTERNAL_LNA_5G FIELD16(0x0008) |
2479 | #define EEPROM_NIC_CONF1_CARDBUS_ACCEL FIELD16(0x0010) | 2479 | #define EEPROM_NIC_CONF1_CARDBUS_ACCEL FIELD16(0x0010) |
2480 | #define EEPROM_NIC_CONF1_BW40M_SB_2G FIELD16(0x0020) | 2480 | #define EEPROM_NIC_CONF1_BW40M_SB_2G FIELD16(0x0020) |
2481 | #define EEPROM_NIC_CONF1_BW40M_SB_5G FIELD16(0x0040) | 2481 | #define EEPROM_NIC_CONF1_BW40M_SB_5G FIELD16(0x0040) |
2482 | #define EEPROM_NIC_CONF1_WPS_PBC FIELD16(0x0080) | 2482 | #define EEPROM_NIC_CONF1_WPS_PBC FIELD16(0x0080) |
2483 | #define EEPROM_NIC_CONF1_BW40M_2G FIELD16(0x0100) | 2483 | #define EEPROM_NIC_CONF1_BW40M_2G FIELD16(0x0100) |
2484 | #define EEPROM_NIC_CONF1_BW40M_5G FIELD16(0x0200) | 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 | #define EEPROM_NIC_CONF1_ANT_DIVERSITY FIELD16(0x1800) | 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 | #define EEPROM_NIC_CONF1_BT_COEXIST FIELD16(0x4000) | 2488 | #define EEPROM_NIC_CONF1_BT_COEXIST FIELD16(0x4000) |
2489 | #define EEPROM_NIC_CONF1_DAC_TEST FIELD16(0x8000) | 2489 | #define EEPROM_NIC_CONF1_DAC_TEST FIELD16(0x8000) |
2490 | 2490 | ||
@@ -2523,9 +2523,9 @@ enum rt2800_eeprom_word { | |||
2523 | * TX_STREAM: 0: Reserved, 1: 1 Stream, 2: 2 Stream | 2523 | * TX_STREAM: 0: Reserved, 1: 1 Stream, 2: 2 Stream |
2524 | * CRYSTAL: 00: Reserved, 01: One crystal, 10: Two crystal, 11: Reserved | 2524 | * CRYSTAL: 00: Reserved, 01: One crystal, 10: Two crystal, 11: Reserved |
2525 | */ | 2525 | */ |
2526 | #define EEPROM_NIC_CONF2_RX_STREAM FIELD16(0x000f) | 2526 | #define EEPROM_NIC_CONF2_RX_STREAM FIELD16(0x000f) |
2527 | #define EEPROM_NIC_CONF2_TX_STREAM FIELD16(0x00f0) | 2527 | #define EEPROM_NIC_CONF2_TX_STREAM FIELD16(0x00f0) |
2528 | #define EEPROM_NIC_CONF2_CRYSTAL FIELD16(0x0600) | 2528 | #define EEPROM_NIC_CONF2_CRYSTAL FIELD16(0x0600) |
2529 | 2529 | ||
2530 | /* | 2530 | /* |
2531 | * EEPROM LNA | 2531 | * EEPROM LNA |
@@ -2792,7 +2792,7 @@ enum rt2800_eeprom_word { | |||
2792 | #define MCU_CURRENT 0x36 | 2792 | #define MCU_CURRENT 0x36 |
2793 | #define MCU_LED 0x50 | 2793 | #define MCU_LED 0x50 |
2794 | #define MCU_LED_STRENGTH 0x51 | 2794 | #define MCU_LED_STRENGTH 0x51 |
2795 | #define MCU_LED_AG_CONF 0x52 | 2795 | #define MCU_LED_AG_CONF 0x52 |
2796 | #define MCU_LED_ACT_CONF 0x53 | 2796 | #define MCU_LED_ACT_CONF 0x53 |
2797 | #define MCU_LED_LED_POLARITY 0x54 | 2797 | #define MCU_LED_LED_POLARITY 0x54 |
2798 | #define MCU_RADAR 0x60 | 2798 | #define MCU_RADAR 0x60 |
@@ -2801,7 +2801,7 @@ enum rt2800_eeprom_word { | |||
2801 | #define MCU_FREQ_OFFSET 0x74 | 2801 | #define MCU_FREQ_OFFSET 0x74 |
2802 | #define MCU_BBP_SIGNAL 0x80 | 2802 | #define MCU_BBP_SIGNAL 0x80 |
2803 | #define MCU_POWER_SAVE 0x83 | 2803 | #define MCU_POWER_SAVE 0x83 |
2804 | #define MCU_BAND_SELECT 0x91 | 2804 | #define MCU_BAND_SELECT 0x91 |
2805 | 2805 | ||
2806 | /* | 2806 | /* |
2807 | * MCU mailbox tokens | 2807 | * MCU mailbox tokens |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 25aaa5e12d4e..aa8789423937 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -278,12 +278,9 @@ static const unsigned int rt2800_eeprom_map_ext[EEPROM_WORD_COUNT] = { | |||
278 | [EEPROM_LNA] = 0x0026, | 278 | [EEPROM_LNA] = 0x0026, |
279 | [EEPROM_EXT_LNA2] = 0x0027, | 279 | [EEPROM_EXT_LNA2] = 0x0027, |
280 | [EEPROM_RSSI_BG] = 0x0028, | 280 | [EEPROM_RSSI_BG] = 0x0028, |
281 | [EEPROM_TXPOWER_DELTA] = 0x0028, /* Overlaps with RSSI_BG */ | ||
282 | [EEPROM_RSSI_BG2] = 0x0029, | 281 | [EEPROM_RSSI_BG2] = 0x0029, |
283 | [EEPROM_TXMIXER_GAIN_BG] = 0x0029, /* Overlaps with RSSI_BG2 */ | ||
284 | [EEPROM_RSSI_A] = 0x002a, | 282 | [EEPROM_RSSI_A] = 0x002a, |
285 | [EEPROM_RSSI_A2] = 0x002b, | 283 | [EEPROM_RSSI_A2] = 0x002b, |
286 | [EEPROM_TXMIXER_GAIN_A] = 0x002b, /* Overlaps with RSSI_A2 */ | ||
287 | [EEPROM_TXPOWER_BG1] = 0x0030, | 284 | [EEPROM_TXPOWER_BG1] = 0x0030, |
288 | [EEPROM_TXPOWER_BG2] = 0x0037, | 285 | [EEPROM_TXPOWER_BG2] = 0x0037, |
289 | [EEPROM_EXT_TXPOWER_BG3] = 0x003e, | 286 | [EEPROM_EXT_TXPOWER_BG3] = 0x003e, |
@@ -1783,7 +1780,7 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant) | |||
1783 | rt2800_bbp_read(rt2x00dev, 3, &r3); | 1780 | rt2800_bbp_read(rt2x00dev, 3, &r3); |
1784 | 1781 | ||
1785 | if (rt2x00_rt(rt2x00dev, RT3572) && | 1782 | if (rt2x00_rt(rt2x00dev, RT3572) && |
1786 | test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) | 1783 | rt2x00_has_cap_bt_coexist(rt2x00dev)) |
1787 | rt2800_config_3572bt_ant(rt2x00dev); | 1784 | rt2800_config_3572bt_ant(rt2x00dev); |
1788 | 1785 | ||
1789 | /* | 1786 | /* |
@@ -1795,7 +1792,7 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant) | |||
1795 | break; | 1792 | break; |
1796 | case 2: | 1793 | case 2: |
1797 | if (rt2x00_rt(rt2x00dev, RT3572) && | 1794 | if (rt2x00_rt(rt2x00dev, RT3572) && |
1798 | test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) | 1795 | rt2x00_has_cap_bt_coexist(rt2x00dev)) |
1799 | rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 1); | 1796 | rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 1); |
1800 | else | 1797 | else |
1801 | rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); | 1798 | rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); |
@@ -1825,7 +1822,7 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant) | |||
1825 | break; | 1822 | break; |
1826 | case 2: | 1823 | case 2: |
1827 | if (rt2x00_rt(rt2x00dev, RT3572) && | 1824 | if (rt2x00_rt(rt2x00dev, RT3572) && |
1828 | test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { | 1825 | rt2x00_has_cap_bt_coexist(rt2x00dev)) { |
1829 | rt2x00_set_field8(&r3, BBP3_RX_ADC, 1); | 1826 | rt2x00_set_field8(&r3, BBP3_RX_ADC, 1); |
1830 | rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, | 1827 | rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, |
1831 | rt2x00dev->curr_band == IEEE80211_BAND_5GHZ); | 1828 | rt2x00dev->curr_band == IEEE80211_BAND_5GHZ); |
@@ -2029,13 +2026,6 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev, | |||
2029 | rt2x00dev->default_ant.tx_chain_num <= 2); | 2026 | rt2x00dev->default_ant.tx_chain_num <= 2); |
2030 | rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); | 2027 | rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); |
2031 | 2028 | ||
2032 | rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); | ||
2033 | rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1); | ||
2034 | rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); | ||
2035 | msleep(1); | ||
2036 | rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); | ||
2037 | rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); | ||
2038 | |||
2039 | rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); | 2029 | rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); |
2040 | rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); | 2030 | rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); |
2041 | rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); | 2031 | rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); |
@@ -2141,7 +2131,7 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, | |||
2141 | rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); | 2131 | rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); |
2142 | rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); | 2132 | rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); |
2143 | rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); | 2133 | rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); |
2144 | if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { | 2134 | if (rt2x00_has_cap_bt_coexist(rt2x00dev)) { |
2145 | if (rf->channel <= 14) { | 2135 | if (rf->channel <= 14) { |
2146 | rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); | 2136 | rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); |
2147 | rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); | 2137 | rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); |
@@ -2674,7 +2664,7 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, | |||
2674 | if (rf->channel <= 14) { | 2664 | if (rf->channel <= 14) { |
2675 | int idx = rf->channel-1; | 2665 | int idx = rf->channel-1; |
2676 | 2666 | ||
2677 | if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { | 2667 | if (rt2x00_has_cap_bt_coexist(rt2x00dev)) { |
2678 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) { | 2668 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) { |
2679 | /* r55/r59 value array of channel 1~14 */ | 2669 | /* r55/r59 value array of channel 1~14 */ |
2680 | static const char r55_bt_rev[] = {0x83, 0x83, | 2670 | static const char r55_bt_rev[] = {0x83, 0x83, |
@@ -3220,8 +3210,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
3220 | if (rf->channel <= 14) { | 3210 | if (rf->channel <= 14) { |
3221 | if (!rt2x00_rt(rt2x00dev, RT5390) && | 3211 | if (!rt2x00_rt(rt2x00dev, RT5390) && |
3222 | !rt2x00_rt(rt2x00dev, RT5392)) { | 3212 | !rt2x00_rt(rt2x00dev, RT5392)) { |
3223 | if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, | 3213 | if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { |
3224 | &rt2x00dev->cap_flags)) { | ||
3225 | rt2800_bbp_write(rt2x00dev, 82, 0x62); | 3214 | rt2800_bbp_write(rt2x00dev, 82, 0x62); |
3226 | rt2800_bbp_write(rt2x00dev, 75, 0x46); | 3215 | rt2800_bbp_write(rt2x00dev, 75, 0x46); |
3227 | } else { | 3216 | } else { |
@@ -3246,7 +3235,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
3246 | if (rt2x00_rt(rt2x00dev, RT3593)) | 3235 | if (rt2x00_rt(rt2x00dev, RT3593)) |
3247 | rt2800_bbp_write(rt2x00dev, 83, 0x9a); | 3236 | rt2800_bbp_write(rt2x00dev, 83, 0x9a); |
3248 | 3237 | ||
3249 | if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) | 3238 | if (rt2x00_has_cap_external_lna_a(rt2x00dev)) |
3250 | rt2800_bbp_write(rt2x00dev, 75, 0x46); | 3239 | rt2800_bbp_write(rt2x00dev, 75, 0x46); |
3251 | else | 3240 | else |
3252 | rt2800_bbp_write(rt2x00dev, 75, 0x50); | 3241 | rt2800_bbp_write(rt2x00dev, 75, 0x50); |
@@ -3282,7 +3271,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
3282 | /* Turn on primary PAs */ | 3271 | /* Turn on primary PAs */ |
3283 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, | 3272 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, |
3284 | rf->channel > 14); | 3273 | rf->channel > 14); |
3285 | if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) | 3274 | if (rt2x00_has_cap_bt_coexist(rt2x00dev)) |
3286 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1); | 3275 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1); |
3287 | else | 3276 | else |
3288 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, | 3277 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, |
@@ -3313,9 +3302,18 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
3313 | 3302 | ||
3314 | rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); | 3303 | rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); |
3315 | 3304 | ||
3316 | if (rt2x00_rt(rt2x00dev, RT3572)) | 3305 | if (rt2x00_rt(rt2x00dev, RT3572)) { |
3317 | rt2800_rfcsr_write(rt2x00dev, 8, 0x80); | 3306 | rt2800_rfcsr_write(rt2x00dev, 8, 0x80); |
3318 | 3307 | ||
3308 | /* AGC init */ | ||
3309 | if (rf->channel <= 14) | ||
3310 | reg = 0x1c + (2 * rt2x00dev->lna_gain); | ||
3311 | else | ||
3312 | reg = 0x22 + ((rt2x00dev->lna_gain * 5) / 3); | ||
3313 | |||
3314 | rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg); | ||
3315 | } | ||
3316 | |||
3319 | if (rt2x00_rt(rt2x00dev, RT3593)) { | 3317 | if (rt2x00_rt(rt2x00dev, RT3593)) { |
3320 | rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); | 3318 | rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); |
3321 | 3319 | ||
@@ -3575,7 +3573,7 @@ static int rt2800_get_txpower_reg_delta(struct rt2x00_dev *rt2x00dev, | |||
3575 | { | 3573 | { |
3576 | int delta; | 3574 | int delta; |
3577 | 3575 | ||
3578 | if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) | 3576 | if (rt2x00_has_cap_power_limit(rt2x00dev)) |
3579 | return 0; | 3577 | return 0; |
3580 | 3578 | ||
3581 | /* | 3579 | /* |
@@ -3604,7 +3602,7 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, | |||
3604 | if (rt2x00_rt(rt2x00dev, RT3593)) | 3602 | if (rt2x00_rt(rt2x00dev, RT3593)) |
3605 | return min_t(u8, txpower, 0xc); | 3603 | return min_t(u8, txpower, 0xc); |
3606 | 3604 | ||
3607 | if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) { | 3605 | if (rt2x00_has_cap_power_limit(rt2x00dev)) { |
3608 | /* | 3606 | /* |
3609 | * Check if eirp txpower exceed txpower_limit. | 3607 | * Check if eirp txpower exceed txpower_limit. |
3610 | * We use OFDM 6M as criterion and its eirp txpower | 3608 | * We use OFDM 6M as criterion and its eirp txpower |
@@ -4416,6 +4414,7 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) | |||
4416 | rt2x00_rt(rt2x00dev, RT3290) || | 4414 | rt2x00_rt(rt2x00dev, RT3290) || |
4417 | rt2x00_rt(rt2x00dev, RT3390) || | 4415 | rt2x00_rt(rt2x00dev, RT3390) || |
4418 | rt2x00_rt(rt2x00dev, RT3572) || | 4416 | rt2x00_rt(rt2x00dev, RT3572) || |
4417 | rt2x00_rt(rt2x00dev, RT3593) || | ||
4419 | rt2x00_rt(rt2x00dev, RT5390) || | 4418 | rt2x00_rt(rt2x00dev, RT5390) || |
4420 | rt2x00_rt(rt2x00dev, RT5392) || | 4419 | rt2x00_rt(rt2x00dev, RT5392) || |
4421 | rt2x00_rt(rt2x00dev, RT5592)) | 4420 | rt2x00_rt(rt2x00dev, RT5592)) |
@@ -4423,8 +4422,8 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) | |||
4423 | else | 4422 | else |
4424 | vgc = 0x2e + rt2x00dev->lna_gain; | 4423 | vgc = 0x2e + rt2x00dev->lna_gain; |
4425 | } else { /* 5GHZ band */ | 4424 | } else { /* 5GHZ band */ |
4426 | if (rt2x00_rt(rt2x00dev, RT3572)) | 4425 | if (rt2x00_rt(rt2x00dev, RT3593)) |
4427 | vgc = 0x22 + (rt2x00dev->lna_gain * 5) / 3; | 4426 | vgc = 0x20 + (rt2x00dev->lna_gain * 5) / 3; |
4428 | else if (rt2x00_rt(rt2x00dev, RT5592)) | 4427 | else if (rt2x00_rt(rt2x00dev, RT5592)) |
4429 | vgc = 0x24 + (2 * rt2x00dev->lna_gain); | 4428 | vgc = 0x24 + (2 * rt2x00dev->lna_gain); |
4430 | else { | 4429 | else { |
@@ -4442,11 +4441,17 @@ static inline void rt2800_set_vgc(struct rt2x00_dev *rt2x00dev, | |||
4442 | struct link_qual *qual, u8 vgc_level) | 4441 | struct link_qual *qual, u8 vgc_level) |
4443 | { | 4442 | { |
4444 | if (qual->vgc_level != vgc_level) { | 4443 | if (qual->vgc_level != vgc_level) { |
4445 | if (rt2x00_rt(rt2x00dev, RT5592)) { | 4444 | if (rt2x00_rt(rt2x00dev, RT3572) || |
4445 | rt2x00_rt(rt2x00dev, RT3593)) { | ||
4446 | rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, | ||
4447 | vgc_level); | ||
4448 | } else if (rt2x00_rt(rt2x00dev, RT5592)) { | ||
4446 | rt2800_bbp_write(rt2x00dev, 83, qual->rssi > -65 ? 0x4a : 0x7a); | 4449 | rt2800_bbp_write(rt2x00dev, 83, qual->rssi > -65 ? 0x4a : 0x7a); |
4447 | rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, vgc_level); | 4450 | rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, vgc_level); |
4448 | } else | 4451 | } else { |
4449 | rt2800_bbp_write(rt2x00dev, 66, vgc_level); | 4452 | rt2800_bbp_write(rt2x00dev, 66, vgc_level); |
4453 | } | ||
4454 | |||
4450 | qual->vgc_level = vgc_level; | 4455 | qual->vgc_level = vgc_level; |
4451 | qual->vgc_level_reg = vgc_level; | 4456 | qual->vgc_level_reg = vgc_level; |
4452 | } | 4457 | } |
@@ -4465,17 +4470,35 @@ void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, | |||
4465 | 4470 | ||
4466 | if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) | 4471 | if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) |
4467 | return; | 4472 | return; |
4468 | /* | 4473 | |
4469 | * When RSSI is better then -80 increase VGC level with 0x10, except | 4474 | /* When RSSI is better than a certain threshold, increase VGC |
4470 | * for rt5592 chip. | 4475 | * with a chip specific value in order to improve the balance |
4476 | * between sensibility and noise isolation. | ||
4471 | */ | 4477 | */ |
4472 | 4478 | ||
4473 | vgc = rt2800_get_default_vgc(rt2x00dev); | 4479 | vgc = rt2800_get_default_vgc(rt2x00dev); |
4474 | 4480 | ||
4475 | if (rt2x00_rt(rt2x00dev, RT5592) && qual->rssi > -65) | 4481 | switch (rt2x00dev->chip.rt) { |
4476 | vgc += 0x20; | 4482 | case RT3572: |
4477 | else if (qual->rssi > -80) | 4483 | case RT3593: |
4478 | vgc += 0x10; | 4484 | if (qual->rssi > -65) { |
4485 | if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) | ||
4486 | vgc += 0x20; | ||
4487 | else | ||
4488 | vgc += 0x10; | ||
4489 | } | ||
4490 | break; | ||
4491 | |||
4492 | case RT5592: | ||
4493 | if (qual->rssi > -65) | ||
4494 | vgc += 0x20; | ||
4495 | break; | ||
4496 | |||
4497 | default: | ||
4498 | if (qual->rssi > -80) | ||
4499 | vgc += 0x10; | ||
4500 | break; | ||
4501 | } | ||
4479 | 4502 | ||
4480 | rt2800_set_vgc(rt2x00dev, qual, vgc); | 4503 | rt2800_set_vgc(rt2x00dev, qual, vgc); |
4481 | } | 4504 | } |
@@ -5500,7 +5523,7 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) | |||
5500 | ant = (div_mode == 3) ? 1 : 0; | 5523 | ant = (div_mode == 3) ? 1 : 0; |
5501 | 5524 | ||
5502 | /* check if this is a Bluetooth combo card */ | 5525 | /* check if this is a Bluetooth combo card */ |
5503 | if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { | 5526 | if (rt2x00_has_cap_bt_coexist(rt2x00dev)) { |
5504 | u32 reg; | 5527 | u32 reg; |
5505 | 5528 | ||
5506 | rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); | 5529 | rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); |
@@ -5809,7 +5832,7 @@ static void rt2800_normal_mode_setup_3xxx(struct rt2x00_dev *rt2x00dev) | |||
5809 | rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || | 5832 | rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || |
5810 | rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || | 5833 | rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || |
5811 | rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { | 5834 | rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { |
5812 | if (!test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) | 5835 | if (!rt2x00_has_cap_external_lna_bg(rt2x00dev)) |
5813 | rt2x00_set_field8(&rfcsr, RFCSR17_R, 1); | 5836 | rt2x00_set_field8(&rfcsr, RFCSR17_R, 1); |
5814 | } | 5837 | } |
5815 | 5838 | ||
@@ -6452,7 +6475,7 @@ static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) | |||
6452 | rt2800_rfcsr_write(rt2x00dev, 28, 0x00); | 6475 | rt2800_rfcsr_write(rt2x00dev, 28, 0x00); |
6453 | rt2800_rfcsr_write(rt2x00dev, 29, 0x10); | 6476 | rt2800_rfcsr_write(rt2x00dev, 29, 0x10); |
6454 | 6477 | ||
6455 | rt2800_rfcsr_write(rt2x00dev, 30, 0x00); | 6478 | rt2800_rfcsr_write(rt2x00dev, 30, 0x10); |
6456 | rt2800_rfcsr_write(rt2x00dev, 31, 0x80); | 6479 | rt2800_rfcsr_write(rt2x00dev, 31, 0x80); |
6457 | rt2800_rfcsr_write(rt2x00dev, 32, 0x80); | 6480 | rt2800_rfcsr_write(rt2x00dev, 32, 0x80); |
6458 | rt2800_rfcsr_write(rt2x00dev, 33, 0x00); | 6481 | rt2800_rfcsr_write(rt2x00dev, 33, 0x00); |
@@ -6490,7 +6513,7 @@ static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) | |||
6490 | rt2800_rfcsr_write(rt2x00dev, 56, 0x22); | 6513 | rt2800_rfcsr_write(rt2x00dev, 56, 0x22); |
6491 | rt2800_rfcsr_write(rt2x00dev, 57, 0x80); | 6514 | rt2800_rfcsr_write(rt2x00dev, 57, 0x80); |
6492 | rt2800_rfcsr_write(rt2x00dev, 58, 0x7f); | 6515 | rt2800_rfcsr_write(rt2x00dev, 58, 0x7f); |
6493 | rt2800_rfcsr_write(rt2x00dev, 59, 0x63); | 6516 | rt2800_rfcsr_write(rt2x00dev, 59, 0x8f); |
6494 | 6517 | ||
6495 | rt2800_rfcsr_write(rt2x00dev, 60, 0x45); | 6518 | rt2800_rfcsr_write(rt2x00dev, 60, 0x45); |
6496 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) | 6519 | if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) |
@@ -6510,7 +6533,6 @@ static void rt2800_init_rfcsr_5392(struct rt2x00_dev *rt2x00dev) | |||
6510 | rt2800_rf_init_calibration(rt2x00dev, 2); | 6533 | rt2800_rf_init_calibration(rt2x00dev, 2); |
6511 | 6534 | ||
6512 | rt2800_rfcsr_write(rt2x00dev, 1, 0x17); | 6535 | rt2800_rfcsr_write(rt2x00dev, 1, 0x17); |
6513 | rt2800_rfcsr_write(rt2x00dev, 2, 0x80); | ||
6514 | rt2800_rfcsr_write(rt2x00dev, 3, 0x88); | 6536 | rt2800_rfcsr_write(rt2x00dev, 3, 0x88); |
6515 | rt2800_rfcsr_write(rt2x00dev, 5, 0x10); | 6537 | rt2800_rfcsr_write(rt2x00dev, 5, 0x10); |
6516 | rt2800_rfcsr_write(rt2x00dev, 6, 0xe0); | 6538 | rt2800_rfcsr_write(rt2x00dev, 6, 0xe0); |
@@ -7224,7 +7246,7 @@ static const struct rf_channel rf_vals[] = { | |||
7224 | 7246 | ||
7225 | /* | 7247 | /* |
7226 | * RF value list for rt3xxx | 7248 | * RF value list for rt3xxx |
7227 | * Supports: 2.4 GHz (all) & 5.2 GHz (RF3052) | 7249 | * Supports: 2.4 GHz (all) & 5.2 GHz (RF3052 & RF3053) |
7228 | */ | 7250 | */ |
7229 | static const struct rf_channel rf_vals_3x[] = { | 7251 | static const struct rf_channel rf_vals_3x[] = { |
7230 | {1, 241, 2, 2 }, | 7252 | {1, 241, 2, 2 }, |
@@ -7420,72 +7442,6 @@ static const struct rf_channel rf_vals_5592_xtal40[] = { | |||
7420 | {196, 83, 0, 12, 1}, | 7442 | {196, 83, 0, 12, 1}, |
7421 | }; | 7443 | }; |
7422 | 7444 | ||
7423 | static const struct rf_channel rf_vals_3053[] = { | ||
7424 | /* Channel, N, R, K */ | ||
7425 | {1, 241, 2, 2}, | ||
7426 | {2, 241, 2, 7}, | ||
7427 | {3, 242, 2, 2}, | ||
7428 | {4, 242, 2, 7}, | ||
7429 | {5, 243, 2, 2}, | ||
7430 | {6, 243, 2, 7}, | ||
7431 | {7, 244, 2, 2}, | ||
7432 | {8, 244, 2, 7}, | ||
7433 | {9, 245, 2, 2}, | ||
7434 | {10, 245, 2, 7}, | ||
7435 | {11, 246, 2, 2}, | ||
7436 | {12, 246, 2, 7}, | ||
7437 | {13, 247, 2, 2}, | ||
7438 | {14, 248, 2, 4}, | ||
7439 | |||
7440 | {36, 0x56, 0, 4}, | ||
7441 | {38, 0x56, 0, 6}, | ||
7442 | {40, 0x56, 0, 8}, | ||
7443 | {44, 0x57, 0, 0}, | ||
7444 | {46, 0x57, 0, 2}, | ||
7445 | {48, 0x57, 0, 4}, | ||
7446 | {52, 0x57, 0, 8}, | ||
7447 | {54, 0x57, 0, 10}, | ||
7448 | {56, 0x58, 0, 0}, | ||
7449 | {60, 0x58, 0, 4}, | ||
7450 | {62, 0x58, 0, 6}, | ||
7451 | {64, 0x58, 0, 8}, | ||
7452 | |||
7453 | {100, 0x5B, 0, 8}, | ||
7454 | {102, 0x5B, 0, 10}, | ||
7455 | {104, 0x5C, 0, 0}, | ||
7456 | {108, 0x5C, 0, 4}, | ||
7457 | {110, 0x5C, 0, 6}, | ||
7458 | {112, 0x5C, 0, 8}, | ||
7459 | |||
7460 | /* NOTE: Channel 114 has been removed intentionally. | ||
7461 | * The EEPROM contains no TX power values for that, | ||
7462 | * and it is disabled in the vendor driver as well. | ||
7463 | */ | ||
7464 | |||
7465 | {116, 0x5D, 0, 0}, | ||
7466 | {118, 0x5D, 0, 2}, | ||
7467 | {120, 0x5D, 0, 4}, | ||
7468 | {124, 0x5D, 0, 8}, | ||
7469 | {126, 0x5D, 0, 10}, | ||
7470 | {128, 0x5E, 0, 0}, | ||
7471 | {132, 0x5E, 0, 4}, | ||
7472 | {134, 0x5E, 0, 6}, | ||
7473 | {136, 0x5E, 0, 8}, | ||
7474 | {140, 0x5F, 0, 0}, | ||
7475 | |||
7476 | {149, 0x5F, 0, 9}, | ||
7477 | {151, 0x5F, 0, 11}, | ||
7478 | {153, 0x60, 0, 1}, | ||
7479 | {157, 0x60, 0, 5}, | ||
7480 | {159, 0x60, 0, 7}, | ||
7481 | {161, 0x60, 0, 9}, | ||
7482 | {165, 0x61, 0, 1}, | ||
7483 | {167, 0x61, 0, 3}, | ||
7484 | {169, 0x61, 0, 5}, | ||
7485 | {171, 0x61, 0, 7}, | ||
7486 | {173, 0x61, 0, 9}, | ||
7487 | }; | ||
7488 | |||
7489 | static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | 7445 | static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) |
7490 | { | 7446 | { |
7491 | struct hw_mode_spec *spec = &rt2x00dev->spec; | 7447 | struct hw_mode_spec *spec = &rt2x00dev->spec; |
@@ -7575,14 +7531,11 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
7575 | rt2x00_rf(rt2x00dev, RF5392)) { | 7531 | rt2x00_rf(rt2x00dev, RF5392)) { |
7576 | spec->num_channels = 14; | 7532 | spec->num_channels = 14; |
7577 | spec->channels = rf_vals_3x; | 7533 | spec->channels = rf_vals_3x; |
7578 | } else if (rt2x00_rf(rt2x00dev, RF3052)) { | 7534 | } else if (rt2x00_rf(rt2x00dev, RF3052) || |
7535 | rt2x00_rf(rt2x00dev, RF3053)) { | ||
7579 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 7536 | spec->supported_bands |= SUPPORT_BAND_5GHZ; |
7580 | spec->num_channels = ARRAY_SIZE(rf_vals_3x); | 7537 | spec->num_channels = ARRAY_SIZE(rf_vals_3x); |
7581 | spec->channels = rf_vals_3x; | 7538 | spec->channels = rf_vals_3x; |
7582 | } else if (rt2x00_rf(rt2x00dev, RF3053)) { | ||
7583 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | ||
7584 | spec->num_channels = ARRAY_SIZE(rf_vals_3053); | ||
7585 | spec->channels = rf_vals_3053; | ||
7586 | } else if (rt2x00_rf(rt2x00dev, RF5592)) { | 7539 | } else if (rt2x00_rf(rt2x00dev, RF5592)) { |
7587 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 7540 | spec->supported_bands |= SUPPORT_BAND_5GHZ; |
7588 | 7541 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index fe4c572db52c..e4ba2ce0f212 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/input-polldev.h> | 39 | #include <linux/input-polldev.h> |
40 | #include <linux/kfifo.h> | 40 | #include <linux/kfifo.h> |
41 | #include <linux/hrtimer.h> | 41 | #include <linux/hrtimer.h> |
42 | #include <linux/average.h> | ||
42 | 43 | ||
43 | #include <net/mac80211.h> | 44 | #include <net/mac80211.h> |
44 | 45 | ||
@@ -138,17 +139,6 @@ | |||
138 | #define SHORT_EIFS ( SIFS + SHORT_DIFS + \ | 139 | #define SHORT_EIFS ( SIFS + SHORT_DIFS + \ |
139 | GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) ) | 140 | GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) ) |
140 | 141 | ||
141 | /* | ||
142 | * Structure for average calculation | ||
143 | * The avg field contains the actual average value, | ||
144 | * but avg_weight is internally used during calculations | ||
145 | * to prevent rounding errors. | ||
146 | */ | ||
147 | struct avg_val { | ||
148 | int avg; | ||
149 | int avg_weight; | ||
150 | }; | ||
151 | |||
152 | enum rt2x00_chip_intf { | 142 | enum rt2x00_chip_intf { |
153 | RT2X00_CHIP_INTF_PCI, | 143 | RT2X00_CHIP_INTF_PCI, |
154 | RT2X00_CHIP_INTF_PCIE, | 144 | RT2X00_CHIP_INTF_PCIE, |
@@ -297,7 +287,7 @@ struct link_ant { | |||
297 | * Similar to the avg_rssi in the link_qual structure | 287 | * Similar to the avg_rssi in the link_qual structure |
298 | * this value is updated by using the walking average. | 288 | * this value is updated by using the walking average. |
299 | */ | 289 | */ |
300 | struct avg_val rssi_ant; | 290 | struct ewma rssi_ant; |
301 | }; | 291 | }; |
302 | 292 | ||
303 | /* | 293 | /* |
@@ -326,7 +316,7 @@ struct link { | |||
326 | /* | 316 | /* |
327 | * Currently active average RSSI value | 317 | * Currently active average RSSI value |
328 | */ | 318 | */ |
329 | struct avg_val avg_rssi; | 319 | struct ewma avg_rssi; |
330 | 320 | ||
331 | /* | 321 | /* |
332 | * Work structure for scheduling periodic link tuning. | 322 | * Work structure for scheduling periodic link tuning. |
@@ -1179,6 +1169,93 @@ static inline bool rt2x00_is_soc(struct rt2x00_dev *rt2x00dev) | |||
1179 | return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC); | 1169 | return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC); |
1180 | } | 1170 | } |
1181 | 1171 | ||
1172 | /* Helpers for capability flags */ | ||
1173 | |||
1174 | static inline bool | ||
1175 | rt2x00_has_cap_flag(struct rt2x00_dev *rt2x00dev, | ||
1176 | enum rt2x00_capability_flags cap_flag) | ||
1177 | { | ||
1178 | return test_bit(cap_flag, &rt2x00dev->cap_flags); | ||
1179 | } | ||
1180 | |||
1181 | static inline bool | ||
1182 | rt2x00_has_cap_hw_crypto(struct rt2x00_dev *rt2x00dev) | ||
1183 | { | ||
1184 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_HW_CRYPTO); | ||
1185 | } | ||
1186 | |||
1187 | static inline bool | ||
1188 | rt2x00_has_cap_power_limit(struct rt2x00_dev *rt2x00dev) | ||
1189 | { | ||
1190 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_POWER_LIMIT); | ||
1191 | } | ||
1192 | |||
1193 | static inline bool | ||
1194 | rt2x00_has_cap_control_filters(struct rt2x00_dev *rt2x00dev) | ||
1195 | { | ||
1196 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_CONTROL_FILTERS); | ||
1197 | } | ||
1198 | |||
1199 | static inline bool | ||
1200 | rt2x00_has_cap_control_filter_pspoll(struct rt2x00_dev *rt2x00dev) | ||
1201 | { | ||
1202 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_CONTROL_FILTER_PSPOLL); | ||
1203 | } | ||
1204 | |||
1205 | static inline bool | ||
1206 | rt2x00_has_cap_pre_tbtt_interrupt(struct rt2x00_dev *rt2x00dev) | ||
1207 | { | ||
1208 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_PRE_TBTT_INTERRUPT); | ||
1209 | } | ||
1210 | |||
1211 | static inline bool | ||
1212 | rt2x00_has_cap_link_tuning(struct rt2x00_dev *rt2x00dev) | ||
1213 | { | ||
1214 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_LINK_TUNING); | ||
1215 | } | ||
1216 | |||
1217 | static inline bool | ||
1218 | rt2x00_has_cap_frame_type(struct rt2x00_dev *rt2x00dev) | ||
1219 | { | ||
1220 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_FRAME_TYPE); | ||
1221 | } | ||
1222 | |||
1223 | static inline bool | ||
1224 | rt2x00_has_cap_rf_sequence(struct rt2x00_dev *rt2x00dev) | ||
1225 | { | ||
1226 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_RF_SEQUENCE); | ||
1227 | } | ||
1228 | |||
1229 | static inline bool | ||
1230 | rt2x00_has_cap_external_lna_a(struct rt2x00_dev *rt2x00dev) | ||
1231 | { | ||
1232 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_EXTERNAL_LNA_A); | ||
1233 | } | ||
1234 | |||
1235 | static inline bool | ||
1236 | rt2x00_has_cap_external_lna_bg(struct rt2x00_dev *rt2x00dev) | ||
1237 | { | ||
1238 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_EXTERNAL_LNA_BG); | ||
1239 | } | ||
1240 | |||
1241 | static inline bool | ||
1242 | rt2x00_has_cap_double_antenna(struct rt2x00_dev *rt2x00dev) | ||
1243 | { | ||
1244 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_DOUBLE_ANTENNA); | ||
1245 | } | ||
1246 | |||
1247 | static inline bool | ||
1248 | rt2x00_has_cap_bt_coexist(struct rt2x00_dev *rt2x00dev) | ||
1249 | { | ||
1250 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_BT_COEXIST); | ||
1251 | } | ||
1252 | |||
1253 | static inline bool | ||
1254 | rt2x00_has_cap_vco_recalibration(struct rt2x00_dev *rt2x00dev) | ||
1255 | { | ||
1256 | return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_VCO_RECALIBRATION); | ||
1257 | } | ||
1258 | |||
1182 | /** | 1259 | /** |
1183 | * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes. | 1260 | * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes. |
1184 | * @entry: Pointer to &struct queue_entry | 1261 | * @entry: Pointer to &struct queue_entry |
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c index 1ca4c7ffc189..3db0d99d9da7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c | |||
@@ -52,7 +52,7 @@ void rt2x00crypto_create_tx_descriptor(struct rt2x00_dev *rt2x00dev, | |||
52 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 52 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
53 | struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; | 53 | struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; |
54 | 54 | ||
55 | if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !hw_key) | 55 | if (!rt2x00_has_cap_hw_crypto(rt2x00dev) || !hw_key) |
56 | return; | 56 | return; |
57 | 57 | ||
58 | __set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags); | 58 | __set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags); |
@@ -80,7 +80,7 @@ unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev, | |||
80 | struct ieee80211_key_conf *key = tx_info->control.hw_key; | 80 | struct ieee80211_key_conf *key = tx_info->control.hw_key; |
81 | unsigned int overhead = 0; | 81 | unsigned int overhead = 0; |
82 | 82 | ||
83 | if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !key) | 83 | if (!rt2x00_has_cap_hw_crypto(rt2x00dev) || !key) |
84 | return overhead; | 84 | return overhead; |
85 | 85 | ||
86 | /* | 86 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index fe7a7f63a9ed..7f7baae5ae02 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c | |||
@@ -750,7 +750,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) | |||
750 | intf, &rt2x00debug_fop_queue_stats); | 750 | intf, &rt2x00debug_fop_queue_stats); |
751 | 751 | ||
752 | #ifdef CONFIG_RT2X00_LIB_CRYPTO | 752 | #ifdef CONFIG_RT2X00_LIB_CRYPTO |
753 | if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) | 753 | if (rt2x00_has_cap_hw_crypto(rt2x00dev)) |
754 | intf->crypto_stats_entry = | 754 | intf->crypto_stats_entry = |
755 | debugfs_create_file("crypto", S_IRUGO, intf->queue_folder, | 755 | debugfs_create_file("crypto", S_IRUGO, intf->queue_folder, |
756 | intf, &rt2x00debug_fop_crypto_stats); | 756 | intf, &rt2x00debug_fop_crypto_stats); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 712eea9d398f..080b1fcae5fa 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -88,7 +88,7 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
88 | rt2x00queue_start_queues(rt2x00dev); | 88 | rt2x00queue_start_queues(rt2x00dev); |
89 | rt2x00link_start_tuner(rt2x00dev); | 89 | rt2x00link_start_tuner(rt2x00dev); |
90 | rt2x00link_start_agc(rt2x00dev); | 90 | rt2x00link_start_agc(rt2x00dev); |
91 | if (test_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags)) | 91 | if (rt2x00_has_cap_vco_recalibration(rt2x00dev)) |
92 | rt2x00link_start_vcocal(rt2x00dev); | 92 | rt2x00link_start_vcocal(rt2x00dev); |
93 | 93 | ||
94 | /* | 94 | /* |
@@ -113,7 +113,7 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) | |||
113 | * Stop all queues | 113 | * Stop all queues |
114 | */ | 114 | */ |
115 | rt2x00link_stop_agc(rt2x00dev); | 115 | rt2x00link_stop_agc(rt2x00dev); |
116 | if (test_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags)) | 116 | if (rt2x00_has_cap_vco_recalibration(rt2x00dev)) |
117 | rt2x00link_stop_vcocal(rt2x00dev); | 117 | rt2x00link_stop_vcocal(rt2x00dev); |
118 | rt2x00link_stop_tuner(rt2x00dev); | 118 | rt2x00link_stop_tuner(rt2x00dev); |
119 | rt2x00queue_stop_queues(rt2x00dev); | 119 | rt2x00queue_stop_queues(rt2x00dev); |
@@ -234,7 +234,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) | |||
234 | * here as they will fetch the next beacon directly prior to | 234 | * here as they will fetch the next beacon directly prior to |
235 | * transmission. | 235 | * transmission. |
236 | */ | 236 | */ |
237 | if (test_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags)) | 237 | if (rt2x00_has_cap_pre_tbtt_interrupt(rt2x00dev)) |
238 | return; | 238 | return; |
239 | 239 | ||
240 | /* fetch next beacon */ | 240 | /* fetch next beacon */ |
@@ -358,7 +358,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
358 | * mac80211 will expect the same data to be present it the | 358 | * mac80211 will expect the same data to be present it the |
359 | * frame as it was passed to us. | 359 | * frame as it was passed to us. |
360 | */ | 360 | */ |
361 | if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) | 361 | if (rt2x00_has_cap_hw_crypto(rt2x00dev)) |
362 | rt2x00crypto_tx_insert_iv(entry->skb, header_length); | 362 | rt2x00crypto_tx_insert_iv(entry->skb, header_length); |
363 | 363 | ||
364 | /* | 364 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index 8368aab86f28..c2b3b6629188 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c | |||
@@ -35,50 +35,28 @@ | |||
35 | */ | 35 | */ |
36 | #define DEFAULT_RSSI -128 | 36 | #define DEFAULT_RSSI -128 |
37 | 37 | ||
38 | /* | 38 | /* Constants for EWMA calculations. */ |
39 | * Helper struct and macro to work with moving/walking averages. | 39 | #define RT2X00_EWMA_FACTOR 1024 |
40 | * When adding a value to the average value the following calculation | 40 | #define RT2X00_EWMA_WEIGHT 8 |
41 | * is needed: | 41 | |
42 | * | 42 | static inline int rt2x00link_get_avg_rssi(struct ewma *ewma) |
43 | * avg_rssi = ((avg_rssi * 7) + rssi) / 8; | 43 | { |
44 | * | 44 | unsigned long avg; |
45 | * The advantage of this approach is that we only need 1 variable | 45 | |
46 | * to store the average in (No need for a count and a total). | 46 | avg = ewma_read(ewma); |
47 | * But more importantly, normal average values will over time | 47 | if (avg) |
48 | * move less and less towards newly added values this results | 48 | return -avg; |
49 | * that with link tuning, the device can have a very good RSSI | 49 | |
50 | * for a few minutes but when the device is moved away from the AP | 50 | return DEFAULT_RSSI; |
51 | * the average will not decrease fast enough to compensate. | 51 | } |
52 | * The walking average compensates this and will move towards | ||
53 | * the new values correctly allowing a effective link tuning, | ||
54 | * the speed of the average moving towards other values depends | ||
55 | * on the value for the number of samples. The higher the number | ||
56 | * of samples, the slower the average will move. | ||
57 | * We use two variables to keep track of the average value to | ||
58 | * compensate for the rounding errors. This can be a significant | ||
59 | * error (>5dBm) if the factor is too low. | ||
60 | */ | ||
61 | #define AVG_SAMPLES 8 | ||
62 | #define AVG_FACTOR 1000 | ||
63 | #define MOVING_AVERAGE(__avg, __val) \ | ||
64 | ({ \ | ||
65 | struct avg_val __new; \ | ||
66 | __new.avg_weight = \ | ||
67 | (__avg).avg_weight ? \ | ||
68 | ((((__avg).avg_weight * ((AVG_SAMPLES) - 1)) + \ | ||
69 | ((__val) * (AVG_FACTOR))) / \ | ||
70 | (AVG_SAMPLES)) : \ | ||
71 | ((__val) * (AVG_FACTOR)); \ | ||
72 | __new.avg = __new.avg_weight / (AVG_FACTOR); \ | ||
73 | __new; \ | ||
74 | }) | ||
75 | 52 | ||
76 | static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev) | 53 | static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev) |
77 | { | 54 | { |
78 | struct link_ant *ant = &rt2x00dev->link.ant; | 55 | struct link_ant *ant = &rt2x00dev->link.ant; |
79 | 56 | ||
80 | if (ant->rssi_ant.avg && rt2x00dev->link.qual.rx_success) | 57 | if (rt2x00dev->link.qual.rx_success) |
81 | return ant->rssi_ant.avg; | 58 | return rt2x00link_get_avg_rssi(&ant->rssi_ant); |
59 | |||
82 | return DEFAULT_RSSI; | 60 | return DEFAULT_RSSI; |
83 | } | 61 | } |
84 | 62 | ||
@@ -100,8 +78,8 @@ static void rt2x00link_antenna_update_rssi_history(struct rt2x00_dev *rt2x00dev, | |||
100 | 78 | ||
101 | static void rt2x00link_antenna_reset(struct rt2x00_dev *rt2x00dev) | 79 | static void rt2x00link_antenna_reset(struct rt2x00_dev *rt2x00dev) |
102 | { | 80 | { |
103 | rt2x00dev->link.ant.rssi_ant.avg = 0; | 81 | ewma_init(&rt2x00dev->link.ant.rssi_ant, RT2X00_EWMA_FACTOR, |
104 | rt2x00dev->link.ant.rssi_ant.avg_weight = 0; | 82 | RT2X00_EWMA_WEIGHT); |
105 | } | 83 | } |
106 | 84 | ||
107 | static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev) | 85 | static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev) |
@@ -249,12 +227,12 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev, | |||
249 | /* | 227 | /* |
250 | * Update global RSSI | 228 | * Update global RSSI |
251 | */ | 229 | */ |
252 | link->avg_rssi = MOVING_AVERAGE(link->avg_rssi, rxdesc->rssi); | 230 | ewma_add(&link->avg_rssi, -rxdesc->rssi); |
253 | 231 | ||
254 | /* | 232 | /* |
255 | * Update antenna RSSI | 233 | * Update antenna RSSI |
256 | */ | 234 | */ |
257 | ant->rssi_ant = MOVING_AVERAGE(ant->rssi_ant, rxdesc->rssi); | 235 | ewma_add(&ant->rssi_ant, -rxdesc->rssi); |
258 | } | 236 | } |
259 | 237 | ||
260 | void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev) | 238 | void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev) |
@@ -309,6 +287,8 @@ void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna) | |||
309 | */ | 287 | */ |
310 | rt2x00dev->link.count = 0; | 288 | rt2x00dev->link.count = 0; |
311 | memset(qual, 0, sizeof(*qual)); | 289 | memset(qual, 0, sizeof(*qual)); |
290 | ewma_init(&rt2x00dev->link.avg_rssi, RT2X00_EWMA_FACTOR, | ||
291 | RT2X00_EWMA_WEIGHT); | ||
312 | 292 | ||
313 | /* | 293 | /* |
314 | * Restore the VGC level as stored in the registers, | 294 | * Restore the VGC level as stored in the registers, |
@@ -363,17 +343,17 @@ static void rt2x00link_tuner(struct work_struct *work) | |||
363 | * collect the RSSI data we could use this. Otherwise we | 343 | * collect the RSSI data we could use this. Otherwise we |
364 | * must fallback to the default RSSI value. | 344 | * must fallback to the default RSSI value. |
365 | */ | 345 | */ |
366 | if (!link->avg_rssi.avg || !qual->rx_success) | 346 | if (!qual->rx_success) |
367 | qual->rssi = DEFAULT_RSSI; | 347 | qual->rssi = DEFAULT_RSSI; |
368 | else | 348 | else |
369 | qual->rssi = link->avg_rssi.avg; | 349 | qual->rssi = rt2x00link_get_avg_rssi(&link->avg_rssi); |
370 | 350 | ||
371 | /* | 351 | /* |
372 | * Check if link tuning is supported by the hardware, some hardware | 352 | * Check if link tuning is supported by the hardware, some hardware |
373 | * do not support link tuning at all, while other devices can disable | 353 | * do not support link tuning at all, while other devices can disable |
374 | * the feature from the EEPROM. | 354 | * the feature from the EEPROM. |
375 | */ | 355 | */ |
376 | if (test_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags)) | 356 | if (rt2x00_has_cap_link_tuning(rt2x00dev)) |
377 | rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count); | 357 | rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count); |
378 | 358 | ||
379 | /* | 359 | /* |
@@ -513,7 +493,7 @@ static void rt2x00link_vcocal(struct work_struct *work) | |||
513 | void rt2x00link_register(struct rt2x00_dev *rt2x00dev) | 493 | void rt2x00link_register(struct rt2x00_dev *rt2x00dev) |
514 | { | 494 | { |
515 | INIT_DELAYED_WORK(&rt2x00dev->link.agc_work, rt2x00link_agc); | 495 | INIT_DELAYED_WORK(&rt2x00dev->link.agc_work, rt2x00link_agc); |
516 | if (test_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags)) | 496 | if (rt2x00_has_cap_vco_recalibration(rt2x00dev)) |
517 | INIT_DELAYED_WORK(&rt2x00dev->link.vco_work, rt2x00link_vcocal); | 497 | INIT_DELAYED_WORK(&rt2x00dev->link.vco_work, rt2x00link_vcocal); |
518 | INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog); | 498 | INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog); |
519 | INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner); | 499 | INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index f883802f3505..51f17cfb93f9 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -382,11 +382,11 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw, | |||
382 | * of different types, but has no a separate filter for PS Poll frames, | 382 | * of different types, but has no a separate filter for PS Poll frames, |
383 | * FIF_CONTROL flag implies FIF_PSPOLL. | 383 | * FIF_CONTROL flag implies FIF_PSPOLL. |
384 | */ | 384 | */ |
385 | if (!test_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags)) { | 385 | if (!rt2x00_has_cap_control_filters(rt2x00dev)) { |
386 | if (*total_flags & FIF_CONTROL || *total_flags & FIF_PSPOLL) | 386 | if (*total_flags & FIF_CONTROL || *total_flags & FIF_PSPOLL) |
387 | *total_flags |= FIF_CONTROL | FIF_PSPOLL; | 387 | *total_flags |= FIF_CONTROL | FIF_PSPOLL; |
388 | } | 388 | } |
389 | if (!test_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags)) { | 389 | if (!rt2x00_has_cap_control_filter_pspoll(rt2x00dev)) { |
390 | if (*total_flags & FIF_CONTROL) | 390 | if (*total_flags & FIF_CONTROL) |
391 | *total_flags |= FIF_PSPOLL; | 391 | *total_flags |= FIF_PSPOLL; |
392 | } | 392 | } |
@@ -469,7 +469,7 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
469 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) | 469 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) |
470 | return 0; | 470 | return 0; |
471 | 471 | ||
472 | if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) | 472 | if (!rt2x00_has_cap_hw_crypto(rt2x00dev)) |
473 | return -EOPNOTSUPP; | 473 | return -EOPNOTSUPP; |
474 | 474 | ||
475 | /* | 475 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index dc49e525ae5e..25da20e7e1f3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c | |||
@@ -119,7 +119,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops) | |||
119 | rt2x00dev->ops = ops; | 119 | rt2x00dev->ops = ops; |
120 | rt2x00dev->hw = hw; | 120 | rt2x00dev->hw = hw; |
121 | rt2x00dev->irq = pci_dev->irq; | 121 | rt2x00dev->irq = pci_dev->irq; |
122 | rt2x00dev->name = pci_name(pci_dev); | 122 | rt2x00dev->name = ops->name; |
123 | 123 | ||
124 | if (pci_is_pcie(pci_dev)) | 124 | if (pci_is_pcie(pci_dev)) |
125 | rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE); | 125 | rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 6c8a33b6ee22..50590b1420a5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -61,7 +61,7 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry, gfp_t gfp) | |||
61 | * at least 8 bytes bytes available in headroom for IV/EIV | 61 | * at least 8 bytes bytes available in headroom for IV/EIV |
62 | * and 8 bytes for ICV data as tailroon. | 62 | * and 8 bytes for ICV data as tailroon. |
63 | */ | 63 | */ |
64 | if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) { | 64 | if (rt2x00_has_cap_hw_crypto(rt2x00dev)) { |
65 | head_size += 8; | 65 | head_size += 8; |
66 | tail_size += 8; | 66 | tail_size += 8; |
67 | } | 67 | } |
@@ -1033,38 +1033,21 @@ EXPORT_SYMBOL_GPL(rt2x00queue_stop_queue); | |||
1033 | 1033 | ||
1034 | void rt2x00queue_flush_queue(struct data_queue *queue, bool drop) | 1034 | void rt2x00queue_flush_queue(struct data_queue *queue, bool drop) |
1035 | { | 1035 | { |
1036 | bool started; | ||
1037 | bool tx_queue = | 1036 | bool tx_queue = |
1038 | (queue->qid == QID_AC_VO) || | 1037 | (queue->qid == QID_AC_VO) || |
1039 | (queue->qid == QID_AC_VI) || | 1038 | (queue->qid == QID_AC_VI) || |
1040 | (queue->qid == QID_AC_BE) || | 1039 | (queue->qid == QID_AC_BE) || |
1041 | (queue->qid == QID_AC_BK); | 1040 | (queue->qid == QID_AC_BK); |
1042 | 1041 | ||
1043 | mutex_lock(&queue->status_lock); | ||
1044 | 1042 | ||
1045 | /* | 1043 | /* |
1046 | * If the queue has been started, we must stop it temporarily | 1044 | * If we are not supposed to drop any pending |
1047 | * to prevent any new frames to be queued on the device. If | 1045 | * frames, this means we must force a start (=kick) |
1048 | * we are not dropping the pending frames, the queue must | 1046 | * to the queue to make sure the hardware will |
1049 | * only be stopped in the software and not the hardware, | 1047 | * start transmitting. |
1050 | * otherwise the queue will never become empty on its own. | ||
1051 | */ | 1048 | */ |
1052 | started = test_bit(QUEUE_STARTED, &queue->flags); | 1049 | if (!drop && tx_queue) |
1053 | if (started) { | 1050 | queue->rt2x00dev->ops->lib->kick_queue(queue); |
1054 | /* | ||
1055 | * Pause the queue | ||
1056 | */ | ||
1057 | rt2x00queue_pause_queue(queue); | ||
1058 | |||
1059 | /* | ||
1060 | * If we are not supposed to drop any pending | ||
1061 | * frames, this means we must force a start (=kick) | ||
1062 | * to the queue to make sure the hardware will | ||
1063 | * start transmitting. | ||
1064 | */ | ||
1065 | if (!drop && tx_queue) | ||
1066 | queue->rt2x00dev->ops->lib->kick_queue(queue); | ||
1067 | } | ||
1068 | 1051 | ||
1069 | /* | 1052 | /* |
1070 | * Check if driver supports flushing, if that is the case we can | 1053 | * Check if driver supports flushing, if that is the case we can |
@@ -1080,14 +1063,6 @@ void rt2x00queue_flush_queue(struct data_queue *queue, bool drop) | |||
1080 | if (unlikely(!rt2x00queue_empty(queue))) | 1063 | if (unlikely(!rt2x00queue_empty(queue))) |
1081 | rt2x00_warn(queue->rt2x00dev, "Queue %d failed to flush\n", | 1064 | rt2x00_warn(queue->rt2x00dev, "Queue %d failed to flush\n", |
1082 | queue->qid); | 1065 | queue->qid); |
1083 | |||
1084 | /* | ||
1085 | * Restore the queue to the previous status | ||
1086 | */ | ||
1087 | if (started) | ||
1088 | rt2x00queue_unpause_queue(queue); | ||
1089 | |||
1090 | mutex_unlock(&queue->status_lock); | ||
1091 | } | 1066 | } |
1092 | EXPORT_SYMBOL_GPL(rt2x00queue_flush_queue); | 1067 | EXPORT_SYMBOL_GPL(rt2x00queue_flush_queue); |
1093 | 1068 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 88289873c0cf..4e121627925d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -523,7 +523,9 @@ static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue) | |||
523 | rt2x00_warn(queue->rt2x00dev, "TX queue %d DMA timed out, invoke forced forced reset\n", | 523 | rt2x00_warn(queue->rt2x00dev, "TX queue %d DMA timed out, invoke forced forced reset\n", |
524 | queue->qid); | 524 | queue->qid); |
525 | 525 | ||
526 | rt2x00queue_stop_queue(queue); | ||
526 | rt2x00queue_flush_queue(queue, true); | 527 | rt2x00queue_flush_queue(queue, true); |
528 | rt2x00queue_start_queue(queue); | ||
527 | } | 529 | } |
528 | 530 | ||
529 | static int rt2x00usb_dma_timeout(struct data_queue *queue) | 531 | static int rt2x00usb_dma_timeout(struct data_queue *queue) |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 54d3ddfc9888..a5b69cb49012 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -685,7 +685,7 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev, | |||
685 | 685 | ||
686 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529)); | 686 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529)); |
687 | rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, | 687 | rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, |
688 | !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags)); | 688 | !rt2x00_has_cap_frame_type(rt2x00dev)); |
689 | 689 | ||
690 | /* | 690 | /* |
691 | * Configure the RX antenna. | 691 | * Configure the RX antenna. |
@@ -813,10 +813,10 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev, | |||
813 | 813 | ||
814 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { | 814 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { |
815 | sel = antenna_sel_a; | 815 | sel = antenna_sel_a; |
816 | lna = test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags); | 816 | lna = rt2x00_has_cap_external_lna_a(rt2x00dev); |
817 | } else { | 817 | } else { |
818 | sel = antenna_sel_bg; | 818 | sel = antenna_sel_bg; |
819 | lna = test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags); | 819 | lna = rt2x00_has_cap_external_lna_bg(rt2x00dev); |
820 | } | 820 | } |
821 | 821 | ||
822 | for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) | 822 | for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) |
@@ -836,7 +836,7 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev, | |||
836 | else if (rt2x00_rf(rt2x00dev, RF2527)) | 836 | else if (rt2x00_rf(rt2x00dev, RF2527)) |
837 | rt61pci_config_antenna_2x(rt2x00dev, ant); | 837 | rt61pci_config_antenna_2x(rt2x00dev, ant); |
838 | else if (rt2x00_rf(rt2x00dev, RF2529)) { | 838 | else if (rt2x00_rf(rt2x00dev, RF2529)) { |
839 | if (test_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags)) | 839 | if (rt2x00_has_cap_double_antenna(rt2x00dev)) |
840 | rt61pci_config_antenna_2x(rt2x00dev, ant); | 840 | rt61pci_config_antenna_2x(rt2x00dev, ant); |
841 | else | 841 | else |
842 | rt61pci_config_antenna_2529(rt2x00dev, ant); | 842 | rt61pci_config_antenna_2529(rt2x00dev, ant); |
@@ -850,13 +850,13 @@ static void rt61pci_config_lna_gain(struct rt2x00_dev *rt2x00dev, | |||
850 | short lna_gain = 0; | 850 | short lna_gain = 0; |
851 | 851 | ||
852 | if (libconf->conf->chandef.chan->band == IEEE80211_BAND_2GHZ) { | 852 | if (libconf->conf->chandef.chan->band == IEEE80211_BAND_2GHZ) { |
853 | if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) | 853 | if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) |
854 | lna_gain += 14; | 854 | lna_gain += 14; |
855 | 855 | ||
856 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom); | 856 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom); |
857 | lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1); | 857 | lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1); |
858 | } else { | 858 | } else { |
859 | if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) | 859 | if (rt2x00_has_cap_external_lna_a(rt2x00dev)) |
860 | lna_gain += 14; | 860 | lna_gain += 14; |
861 | 861 | ||
862 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom); | 862 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom); |
@@ -1054,14 +1054,14 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev, | |||
1054 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { | 1054 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { |
1055 | low_bound = 0x28; | 1055 | low_bound = 0x28; |
1056 | up_bound = 0x48; | 1056 | up_bound = 0x48; |
1057 | if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) { | 1057 | if (rt2x00_has_cap_external_lna_a(rt2x00dev)) { |
1058 | low_bound += 0x10; | 1058 | low_bound += 0x10; |
1059 | up_bound += 0x10; | 1059 | up_bound += 0x10; |
1060 | } | 1060 | } |
1061 | } else { | 1061 | } else { |
1062 | low_bound = 0x20; | 1062 | low_bound = 0x20; |
1063 | up_bound = 0x40; | 1063 | up_bound = 0x40; |
1064 | if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) { | 1064 | if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { |
1065 | low_bound += 0x10; | 1065 | low_bound += 0x10; |
1066 | up_bound += 0x10; | 1066 | up_bound += 0x10; |
1067 | } | 1067 | } |
@@ -2578,7 +2578,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
2578 | * eeprom word. | 2578 | * eeprom word. |
2579 | */ | 2579 | */ |
2580 | if (rt2x00_rf(rt2x00dev, RF2529) && | 2580 | if (rt2x00_rf(rt2x00dev, RF2529) && |
2581 | !test_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags)) { | 2581 | !rt2x00_has_cap_double_antenna(rt2x00dev)) { |
2582 | rt2x00dev->default_ant.rx = | 2582 | rt2x00dev->default_ant.rx = |
2583 | ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED); | 2583 | ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED); |
2584 | rt2x00dev->default_ant.tx = | 2584 | rt2x00dev->default_ant.tx = |
@@ -2793,7 +2793,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
2793 | spec->supported_bands = SUPPORT_BAND_2GHZ; | 2793 | spec->supported_bands = SUPPORT_BAND_2GHZ; |
2794 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; | 2794 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; |
2795 | 2795 | ||
2796 | if (!test_bit(CAPABILITY_RF_SEQUENCE, &rt2x00dev->cap_flags)) { | 2796 | if (!rt2x00_has_cap_rf_sequence(rt2x00dev)) { |
2797 | spec->num_channels = 14; | 2797 | spec->num_channels = 14; |
2798 | spec->channels = rf_vals_noseq; | 2798 | spec->channels = rf_vals_noseq; |
2799 | } else { | 2799 | } else { |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 1d3880e09a13..1baf9c896dcd 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -595,8 +595,8 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev, | |||
595 | switch (ant->rx) { | 595 | switch (ant->rx) { |
596 | case ANTENNA_HW_DIVERSITY: | 596 | case ANTENNA_HW_DIVERSITY: |
597 | rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2); | 597 | rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2); |
598 | temp = !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags) | 598 | temp = !rt2x00_has_cap_frame_type(rt2x00dev) && |
599 | && (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ); | 599 | (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ); |
600 | rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp); | 600 | rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp); |
601 | break; | 601 | break; |
602 | case ANTENNA_A: | 602 | case ANTENNA_A: |
@@ -636,7 +636,7 @@ static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev, | |||
636 | 636 | ||
637 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0); | 637 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0); |
638 | rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, | 638 | rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, |
639 | !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags)); | 639 | !rt2x00_has_cap_frame_type(rt2x00dev)); |
640 | 640 | ||
641 | /* | 641 | /* |
642 | * Configure the RX antenna. | 642 | * Configure the RX antenna. |
@@ -709,10 +709,10 @@ static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev, | |||
709 | 709 | ||
710 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { | 710 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { |
711 | sel = antenna_sel_a; | 711 | sel = antenna_sel_a; |
712 | lna = test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags); | 712 | lna = rt2x00_has_cap_external_lna_a(rt2x00dev); |
713 | } else { | 713 | } else { |
714 | sel = antenna_sel_bg; | 714 | sel = antenna_sel_bg; |
715 | lna = test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags); | 715 | lna = rt2x00_has_cap_external_lna_bg(rt2x00dev); |
716 | } | 716 | } |
717 | 717 | ||
718 | for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) | 718 | for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) |
@@ -740,7 +740,7 @@ static void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev, | |||
740 | short lna_gain = 0; | 740 | short lna_gain = 0; |
741 | 741 | ||
742 | if (libconf->conf->chandef.chan->band == IEEE80211_BAND_2GHZ) { | 742 | if (libconf->conf->chandef.chan->band == IEEE80211_BAND_2GHZ) { |
743 | if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) | 743 | if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) |
744 | lna_gain += 14; | 744 | lna_gain += 14; |
745 | 745 | ||
746 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom); | 746 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom); |
@@ -930,7 +930,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev, | |||
930 | low_bound = 0x28; | 930 | low_bound = 0x28; |
931 | up_bound = 0x48; | 931 | up_bound = 0x48; |
932 | 932 | ||
933 | if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) { | 933 | if (rt2x00_has_cap_external_lna_a(rt2x00dev)) { |
934 | low_bound += 0x10; | 934 | low_bound += 0x10; |
935 | up_bound += 0x10; | 935 | up_bound += 0x10; |
936 | } | 936 | } |
@@ -946,7 +946,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev, | |||
946 | up_bound = 0x1c; | 946 | up_bound = 0x1c; |
947 | } | 947 | } |
948 | 948 | ||
949 | if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) { | 949 | if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { |
950 | low_bound += 0x14; | 950 | low_bound += 0x14; |
951 | up_bound += 0x10; | 951 | up_bound += 0x10; |
952 | } | 952 | } |
@@ -1661,7 +1661,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) | |||
1661 | } | 1661 | } |
1662 | 1662 | ||
1663 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { | 1663 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { |
1664 | if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) { | 1664 | if (rt2x00_has_cap_external_lna_a(rt2x00dev)) { |
1665 | if (lna == 3 || lna == 2) | 1665 | if (lna == 3 || lna == 2) |
1666 | offset += 10; | 1666 | offset += 10; |
1667 | } else { | 1667 | } else { |
diff --git a/drivers/net/wireless/ti/wl1251/wl1251.h b/drivers/net/wireless/ti/wl1251/wl1251.h index fd02060038de..2c3bd1bff3f6 100644 --- a/drivers/net/wireless/ti/wl1251/wl1251.h +++ b/drivers/net/wireless/ti/wl1251/wl1251.h | |||
@@ -424,8 +424,8 @@ void wl1251_disable_interrupts(struct wl1251 *wl); | |||
424 | #define CHIP_ID_1271_PG10 (0x4030101) | 424 | #define CHIP_ID_1271_PG10 (0x4030101) |
425 | #define CHIP_ID_1271_PG20 (0x4030111) | 425 | #define CHIP_ID_1271_PG20 (0x4030111) |
426 | 426 | ||
427 | #define WL1251_FW_NAME "wl1251-fw.bin" | 427 | #define WL1251_FW_NAME "ti-connectivity/wl1251-fw.bin" |
428 | #define WL1251_NVS_NAME "wl1251-nvs.bin" | 428 | #define WL1251_NVS_NAME "ti-connectivity/wl1251-nvs.bin" |
429 | 429 | ||
430 | #define WL1251_POWER_ON_SLEEP 10 /* in milliseconds */ | 430 | #define WL1251_POWER_ON_SLEEP 10 /* in milliseconds */ |
431 | 431 | ||
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index a5b598a79bec..7c1e1ebc0e23 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -1391,8 +1391,8 @@ struct ieee80211_vht_operation { | |||
1391 | #define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700 | 1391 | #define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700 |
1392 | #define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 | 1392 | #define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 |
1393 | #define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 | 1393 | #define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 |
1394 | #define IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX 0x00006000 | 1394 | #define IEEE80211_VHT_CAP_BEAMFORMEE_STS_MAX 0x0000e000 |
1395 | #define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX 0x00030000 | 1395 | #define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX 0x00070000 |
1396 | #define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000 | 1396 | #define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000 |
1397 | #define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000 | 1397 | #define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000 |
1398 | #define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000 | 1398 | #define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000 |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index cb710913d5c8..45f6bf591104 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -437,6 +437,15 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy, | |||
437 | u32 prohibited_flags); | 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 | * ieee80211_chandef_rate_flags - returns rate flags for a channel | 449 | * ieee80211_chandef_rate_flags - returns rate flags for a channel |
441 | * | 450 | * |
442 | * In some channel types, not all rates may be used - for example CCK | 451 | * In some channel types, not all rates may be used - for example CCK |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index cc6035f1a2f1..f386c480e134 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -829,6 +829,15 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) | |||
829 | * @RX_FLAG_STBC_MASK: STBC 2 bit bitmask. 1 - Nss=1, 2 - Nss=2, 3 - Nss=3 | 829 | * @RX_FLAG_STBC_MASK: STBC 2 bit bitmask. 1 - Nss=1, 2 - Nss=2, 3 - Nss=3 |
830 | * @RX_FLAG_10MHZ: 10 MHz (half channel) was used | 830 | * @RX_FLAG_10MHZ: 10 MHz (half channel) was used |
831 | * @RX_FLAG_5MHZ: 5 MHz (quarter channel) was used | 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 | enum mac80211_rx_flags { | 842 | enum mac80211_rx_flags { |
834 | RX_FLAG_MMIC_ERROR = BIT(0), | 843 | RX_FLAG_MMIC_ERROR = BIT(0), |
@@ -859,6 +868,7 @@ enum mac80211_rx_flags { | |||
859 | RX_FLAG_STBC_MASK = BIT(26) | BIT(27), | 868 | RX_FLAG_STBC_MASK = BIT(26) | BIT(27), |
860 | RX_FLAG_10MHZ = BIT(28), | 869 | RX_FLAG_10MHZ = BIT(28), |
861 | RX_FLAG_5MHZ = BIT(29), | 870 | RX_FLAG_5MHZ = BIT(29), |
871 | RX_FLAG_AMSDU_MORE = BIT(30), | ||
862 | }; | 872 | }; |
863 | 873 | ||
864 | #define RX_FLAG_STBC_SHIFT 26 | 874 | #define RX_FLAG_STBC_SHIFT 26 |
@@ -1492,6 +1502,11 @@ struct ieee80211_tx_control { | |||
1492 | * | 1502 | * |
1493 | * @IEEE80211_HW_TIMING_BEACON_ONLY: Use sync timing from beacon frames | 1503 | * @IEEE80211_HW_TIMING_BEACON_ONLY: Use sync timing from beacon frames |
1494 | * only, to allow getting TBTT of a DTIM beacon. | 1504 | * only, to allow getting TBTT of a DTIM beacon. |
1505 | * | ||
1506 | * @IEEE80211_HW_CHANCTX_STA_CSA: Support 802.11h based channel-switch (CSA) | ||
1507 | * for a single active channel while using channel contexts. When support | ||
1508 | * is not enabled the default action is to disconnect when getting the | ||
1509 | * CSA frame. | ||
1495 | */ | 1510 | */ |
1496 | enum ieee80211_hw_flags { | 1511 | enum ieee80211_hw_flags { |
1497 | IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, | 1512 | IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, |
@@ -1522,6 +1537,7 @@ enum ieee80211_hw_flags { | |||
1522 | IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF = 1<<25, | 1537 | IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF = 1<<25, |
1523 | IEEE80211_HW_TIMING_BEACON_ONLY = 1<<26, | 1538 | IEEE80211_HW_TIMING_BEACON_ONLY = 1<<26, |
1524 | IEEE80211_HW_SUPPORTS_HT_CCK_RATES = 1<<27, | 1539 | IEEE80211_HW_SUPPORTS_HT_CCK_RATES = 1<<27, |
1540 | IEEE80211_HW_CHANCTX_STA_CSA = 1<<28, | ||
1525 | }; | 1541 | }; |
1526 | 1542 | ||
1527 | /** | 1543 | /** |
@@ -2666,6 +2682,10 @@ enum ieee80211_roc_type { | |||
2666 | * zero using ieee80211_csa_is_complete() after the beacon has been | 2682 | * zero using ieee80211_csa_is_complete() after the beacon has been |
2667 | * transmitted and then call ieee80211_csa_finish(). | 2683 | * transmitted and then call ieee80211_csa_finish(). |
2668 | * | 2684 | * |
2685 | * @join_ibss: Join an IBSS (on an IBSS interface); this is called after all | ||
2686 | * information in bss_conf is set up and the beacon can be retrieved. A | ||
2687 | * channel context is bound before this is called. | ||
2688 | * @leave_ibss: Leave the IBSS again. | ||
2669 | */ | 2689 | */ |
2670 | struct ieee80211_ops { | 2690 | struct ieee80211_ops { |
2671 | void (*tx)(struct ieee80211_hw *hw, | 2691 | void (*tx)(struct ieee80211_hw *hw, |
@@ -2857,6 +2877,9 @@ struct ieee80211_ops { | |||
2857 | void (*channel_switch_beacon)(struct ieee80211_hw *hw, | 2877 | void (*channel_switch_beacon)(struct ieee80211_hw *hw, |
2858 | struct ieee80211_vif *vif, | 2878 | struct ieee80211_vif *vif, |
2859 | struct cfg80211_chan_def *chandef); | 2879 | struct cfg80211_chan_def *chandef); |
2880 | |||
2881 | int (*join_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); | ||
2882 | void (*leave_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); | ||
2860 | }; | 2883 | }; |
2861 | 2884 | ||
2862 | /** | 2885 | /** |
@@ -3920,6 +3943,25 @@ void ieee80211_iterate_active_interfaces_atomic(struct ieee80211_hw *hw, | |||
3920 | void *data); | 3943 | void *data); |
3921 | 3944 | ||
3922 | /** | 3945 | /** |
3946 | * ieee80211_iterate_active_interfaces_rtnl - iterate active interfaces | ||
3947 | * | ||
3948 | * This function iterates over the interfaces associated with a given | ||
3949 | * hardware that are currently active and calls the callback for them. | ||
3950 | * This version can only be used while holding the RTNL. | ||
3951 | * | ||
3952 | * @hw: the hardware struct of which the interfaces should be iterated over | ||
3953 | * @iter_flags: iteration flags, see &enum ieee80211_interface_iteration_flags | ||
3954 | * @iterator: the iterator function to call, cannot sleep | ||
3955 | * @data: first argument of the iterator function | ||
3956 | */ | ||
3957 | void ieee80211_iterate_active_interfaces_rtnl(struct ieee80211_hw *hw, | ||
3958 | u32 iter_flags, | ||
3959 | void (*iterator)(void *data, | ||
3960 | u8 *mac, | ||
3961 | struct ieee80211_vif *vif), | ||
3962 | void *data); | ||
3963 | |||
3964 | /** | ||
3923 | * ieee80211_queue_work - add work onto the mac80211 workqueue | 3965 | * ieee80211_queue_work - add work onto the mac80211 workqueue |
3924 | * | 3966 | * |
3925 | * Drivers and mac80211 use this to add work onto the mac80211 workqueue. | 3967 | * Drivers and mac80211 use this to add work onto the mac80211 workqueue. |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 2e7855a1b10d..ac28af74a414 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -2865,30 +2865,43 @@ void ieee80211_csa_finalize_work(struct work_struct *work) | |||
2865 | if (!ieee80211_sdata_running(sdata)) | 2865 | if (!ieee80211_sdata_running(sdata)) |
2866 | return; | 2866 | return; |
2867 | 2867 | ||
2868 | if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP)) | ||
2869 | return; | ||
2870 | |||
2871 | sdata->radar_required = sdata->csa_radar_required; | 2868 | sdata->radar_required = sdata->csa_radar_required; |
2872 | err = ieee80211_vif_change_channel(sdata, &local->csa_chandef, | 2869 | err = ieee80211_vif_change_channel(sdata, &local->csa_chandef, |
2873 | &changed); | 2870 | &changed); |
2874 | if (WARN_ON(err < 0)) | 2871 | if (WARN_ON(err < 0)) |
2875 | return; | 2872 | return; |
2876 | 2873 | ||
2877 | err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); | 2874 | if (!local->use_chanctx) { |
2878 | if (err < 0) | 2875 | local->_oper_chandef = local->csa_chandef; |
2879 | return; | 2876 | ieee80211_hw_config(local, 0); |
2877 | } | ||
2880 | 2878 | ||
2881 | changed |= err; | 2879 | ieee80211_bss_info_change_notify(sdata, changed); |
2882 | kfree(sdata->u.ap.next_beacon); | 2880 | |
2883 | sdata->u.ap.next_beacon = NULL; | 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 | sdata->vif.csa_active = false; | 2899 | sdata->vif.csa_active = false; |
2885 | 2900 | ||
2886 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | 2901 | ieee80211_wake_queues_by_reason(&sdata->local->hw, |
2887 | IEEE80211_MAX_QUEUE_MAP, | 2902 | IEEE80211_MAX_QUEUE_MAP, |
2888 | IEEE80211_QUEUE_STOP_REASON_CSA); | 2903 | IEEE80211_QUEUE_STOP_REASON_CSA); |
2889 | 2904 | ||
2890 | ieee80211_bss_info_change_notify(sdata, changed); | ||
2891 | |||
2892 | cfg80211_ch_switch_notify(sdata->dev, &local->csa_chandef); | 2905 | cfg80211_ch_switch_notify(sdata->dev, &local->csa_chandef); |
2893 | } | 2906 | } |
2894 | 2907 | ||
@@ -2936,20 +2949,56 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
2936 | if (sdata->vif.csa_active) | 2949 | if (sdata->vif.csa_active) |
2937 | return -EBUSY; | 2950 | return -EBUSY; |
2938 | 2951 | ||
2939 | /* only handle AP for now. */ | ||
2940 | switch (sdata->vif.type) { | 2952 | switch (sdata->vif.type) { |
2941 | case NL80211_IFTYPE_AP: | 2953 | case NL80211_IFTYPE_AP: |
2954 | sdata->csa_counter_offset_beacon = | ||
2955 | params->counter_offset_beacon; | ||
2956 | sdata->csa_counter_offset_presp = params->counter_offset_presp; | ||
2957 | sdata->u.ap.next_beacon = | ||
2958 | cfg80211_beacon_dup(¶ms->beacon_after); | ||
2959 | if (!sdata->u.ap.next_beacon) | ||
2960 | return -ENOMEM; | ||
2961 | |||
2962 | err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa); | ||
2963 | if (err < 0) { | ||
2964 | kfree(sdata->u.ap.next_beacon); | ||
2965 | return err; | ||
2966 | } | ||
2967 | break; | ||
2968 | case NL80211_IFTYPE_ADHOC: | ||
2969 | if (!sdata->vif.bss_conf.ibss_joined) | ||
2970 | return -EINVAL; | ||
2971 | |||
2972 | if (params->chandef.width != sdata->u.ibss.chandef.width) | ||
2973 | return -EINVAL; | ||
2974 | |||
2975 | switch (params->chandef.width) { | ||
2976 | case NL80211_CHAN_WIDTH_40: | ||
2977 | if (cfg80211_get_chandef_type(¶ms->chandef) != | ||
2978 | cfg80211_get_chandef_type(&sdata->u.ibss.chandef)) | ||
2979 | return -EINVAL; | ||
2980 | case NL80211_CHAN_WIDTH_5: | ||
2981 | case NL80211_CHAN_WIDTH_10: | ||
2982 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
2983 | case NL80211_CHAN_WIDTH_20: | ||
2984 | break; | ||
2985 | default: | ||
2986 | return -EINVAL; | ||
2987 | } | ||
2988 | |||
2989 | /* changes into another band are not supported */ | ||
2990 | if (sdata->u.ibss.chandef.chan->band != | ||
2991 | params->chandef.chan->band) | ||
2992 | return -EINVAL; | ||
2993 | |||
2994 | err = ieee80211_ibss_csa_beacon(sdata, params); | ||
2995 | if (err < 0) | ||
2996 | return err; | ||
2942 | break; | 2997 | break; |
2943 | default: | 2998 | default: |
2944 | return -EOPNOTSUPP; | 2999 | return -EOPNOTSUPP; |
2945 | } | 3000 | } |
2946 | 3001 | ||
2947 | sdata->u.ap.next_beacon = cfg80211_beacon_dup(¶ms->beacon_after); | ||
2948 | if (!sdata->u.ap.next_beacon) | ||
2949 | return -ENOMEM; | ||
2950 | |||
2951 | sdata->csa_counter_offset_beacon = params->counter_offset_beacon; | ||
2952 | sdata->csa_counter_offset_presp = params->counter_offset_presp; | ||
2953 | sdata->csa_radar_required = params->radar_required; | 3002 | sdata->csa_radar_required = params->radar_required; |
2954 | 3003 | ||
2955 | if (params->block_tx) | 3004 | if (params->block_tx) |
@@ -2957,10 +3006,6 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
2957 | IEEE80211_MAX_QUEUE_MAP, | 3006 | IEEE80211_MAX_QUEUE_MAP, |
2958 | IEEE80211_QUEUE_STOP_REASON_CSA); | 3007 | IEEE80211_QUEUE_STOP_REASON_CSA); |
2959 | 3008 | ||
2960 | err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa); | ||
2961 | if (err < 0) | ||
2962 | return err; | ||
2963 | |||
2964 | local->csa_chandef = params->chandef; | 3009 | local->csa_chandef = params->chandef; |
2965 | sdata->vif.csa_active = true; | 3010 | sdata->vif.csa_active = true; |
2966 | 3011 | ||
@@ -3014,7 +3059,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
3014 | need_offchan = true; | 3059 | need_offchan = true; |
3015 | if (!ieee80211_is_action(mgmt->frame_control) || | 3060 | if (!ieee80211_is_action(mgmt->frame_control) || |
3016 | mgmt->u.action.category == WLAN_CATEGORY_PUBLIC || | 3061 | mgmt->u.action.category == WLAN_CATEGORY_PUBLIC || |
3017 | mgmt->u.action.category == WLAN_CATEGORY_SELF_PROTECTED) | 3062 | mgmt->u.action.category == WLAN_CATEGORY_SELF_PROTECTED || |
3063 | mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) | ||
3018 | break; | 3064 | break; |
3019 | rcu_read_lock(); | 3065 | rcu_read_lock(); |
3020 | sta = sta_info_get(sdata, mgmt->da); | 3066 | sta = sta_info_get(sdata, mgmt->da); |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 3a4764b2869e..03ba6b5c5373 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -453,11 +453,6 @@ int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata, | |||
453 | chanctx_changed |= IEEE80211_CHANCTX_CHANGE_CHANNEL; | 453 | chanctx_changed |= IEEE80211_CHANCTX_CHANGE_CHANNEL; |
454 | drv_change_chanctx(local, ctx, chanctx_changed); | 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 | ieee80211_recalc_chanctx_chantype(local, ctx); | 456 | ieee80211_recalc_chanctx_chantype(local, ctx); |
462 | ieee80211_recalc_smps_chanctx(local, ctx); | 457 | ieee80211_recalc_smps_chanctx(local, ctx); |
463 | ieee80211_recalc_radar_chanctx(local, ctx); | 458 | ieee80211_recalc_radar_chanctx(local, ctx); |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index b0e32d628114..5c090e41d9bb 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -103,54 +103,57 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf, | |||
103 | if (!buf) | 103 | if (!buf) |
104 | return 0; | 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 | if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) | 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 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) | 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 | if (local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING) | 111 | if (local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING) |
112 | sf += snprintf(buf + sf, mxln - sf, | 112 | sf += scnprintf(buf + sf, mxln - sf, |
113 | "HOST_BCAST_PS_BUFFERING\n"); | 113 | "HOST_BCAST_PS_BUFFERING\n"); |
114 | if (local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE) | 114 | if (local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE) |
115 | sf += snprintf(buf + sf, mxln - sf, | 115 | sf += scnprintf(buf + sf, mxln - sf, |
116 | "2GHZ_SHORT_SLOT_INCAPABLE\n"); | 116 | "2GHZ_SHORT_SLOT_INCAPABLE\n"); |
117 | if (local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE) | 117 | if (local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE) |
118 | sf += snprintf(buf + sf, mxln - sf, | 118 | sf += scnprintf(buf + sf, mxln - sf, |
119 | "2GHZ_SHORT_PREAMBLE_INCAPABLE\n"); | 119 | "2GHZ_SHORT_PREAMBLE_INCAPABLE\n"); |
120 | if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) | 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 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | 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 | if (local->hw.flags & IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC) | 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 | if (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT) | 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 | if (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) | 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 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_PS) | 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 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) | 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 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) | 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 | if (local->hw.flags & IEEE80211_HW_MFP_CAPABLE) | 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 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS) | 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 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) | 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 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) | 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 | if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) | 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 | if (local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) | 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 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK) | 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 | if (local->hw.flags & IEEE80211_HW_AP_LINK_PS) | 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 | if (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW) | 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 | rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); | 158 | rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); |
156 | kfree(buf); | 159 | kfree(buf); |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index b3ea11f3d526..5d03c47c0a4c 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -1085,4 +1085,31 @@ drv_channel_switch_beacon(struct ieee80211_sub_if_data *sdata, | |||
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 | #endif /* __MAC80211_DRIVER_OPS */ | 1115 | #endif /* __MAC80211_DRIVER_OPS */ |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index a12afe77bb26..21a0b8835cb3 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -39,7 +39,8 @@ ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata, | |||
39 | const int beacon_int, const u32 basic_rates, | 39 | const int beacon_int, const u32 basic_rates, |
40 | const u16 capability, u64 tsf, | 40 | const u16 capability, u64 tsf, |
41 | struct cfg80211_chan_def *chandef, | 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 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 45 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
45 | struct ieee80211_local *local = sdata->local; | 46 | struct ieee80211_local *local = sdata->local; |
@@ -59,6 +60,7 @@ ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata, | |||
59 | 2 + 8 /* max Supported Rates */ + | 60 | 2 + 8 /* max Supported Rates */ + |
60 | 3 /* max DS params */ + | 61 | 3 /* max DS params */ + |
61 | 4 /* IBSS params */ + | 62 | 4 /* IBSS params */ + |
63 | 5 /* Channel Switch Announcement */ + | ||
62 | 2 + (IEEE80211_MAX_SUPP_RATES - 8) + | 64 | 2 + (IEEE80211_MAX_SUPP_RATES - 8) + |
63 | 2 + sizeof(struct ieee80211_ht_cap) + | 65 | 2 + sizeof(struct ieee80211_ht_cap) + |
64 | 2 + sizeof(struct ieee80211_ht_operation) + | 66 | 2 + sizeof(struct ieee80211_ht_operation) + |
@@ -135,6 +137,16 @@ ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata, | |||
135 | *pos++ = 0; | 137 | *pos++ = 0; |
136 | *pos++ = 0; | 138 | *pos++ = 0; |
137 | 139 | ||
140 | if (csa_settings) { | ||
141 | *pos++ = WLAN_EID_CHANNEL_SWITCH; | ||
142 | *pos++ = 3; | ||
143 | *pos++ = csa_settings->block_tx ? 1 : 0; | ||
144 | *pos++ = ieee80211_frequency_to_channel( | ||
145 | csa_settings->chandef.chan->center_freq); | ||
146 | sdata->csa_counter_offset_beacon = (pos - presp->head); | ||
147 | *pos++ = csa_settings->count; | ||
148 | } | ||
149 | |||
138 | /* put the remaining rates in WLAN_EID_EXT_SUPP_RATES */ | 150 | /* put the remaining rates in WLAN_EID_EXT_SUPP_RATES */ |
139 | if (rates_n > 8) { | 151 | if (rates_n > 8) { |
140 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | 152 | *pos++ = WLAN_EID_EXT_SUPP_RATES; |
@@ -217,6 +229,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
217 | struct beacon_data *presp; | 229 | struct beacon_data *presp; |
218 | enum nl80211_bss_scan_width scan_width; | 230 | enum nl80211_bss_scan_width scan_width; |
219 | bool have_higher_than_11mbit; | 231 | bool have_higher_than_11mbit; |
232 | int err; | ||
220 | 233 | ||
221 | sdata_assert_lock(sdata); | 234 | sdata_assert_lock(sdata); |
222 | 235 | ||
@@ -235,6 +248,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
235 | ieee80211_bss_info_change_notify(sdata, | 248 | ieee80211_bss_info_change_notify(sdata, |
236 | BSS_CHANGED_IBSS | | 249 | BSS_CHANGED_IBSS | |
237 | BSS_CHANGED_BEACON_ENABLED); | 250 | BSS_CHANGED_BEACON_ENABLED); |
251 | drv_leave_ibss(local, sdata); | ||
238 | } | 252 | } |
239 | 253 | ||
240 | presp = rcu_dereference_protected(ifibss->presp, | 254 | presp = rcu_dereference_protected(ifibss->presp, |
@@ -276,7 +290,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
276 | 290 | ||
277 | presp = ieee80211_ibss_build_presp(sdata, beacon_int, basic_rates, | 291 | presp = ieee80211_ibss_build_presp(sdata, beacon_int, basic_rates, |
278 | capability, tsf, &chandef, | 292 | capability, tsf, &chandef, |
279 | &have_higher_than_11mbit); | 293 | &have_higher_than_11mbit, NULL); |
280 | if (!presp) | 294 | if (!presp) |
281 | return; | 295 | return; |
282 | 296 | ||
@@ -317,11 +331,26 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
317 | else | 331 | else |
318 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; | 332 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; |
319 | 333 | ||
334 | ieee80211_set_wmm_default(sdata, true); | ||
335 | |||
320 | sdata->vif.bss_conf.ibss_joined = true; | 336 | sdata->vif.bss_conf.ibss_joined = true; |
321 | sdata->vif.bss_conf.ibss_creator = creator; | 337 | sdata->vif.bss_conf.ibss_creator = creator; |
322 | ieee80211_bss_info_change_notify(sdata, bss_change); | ||
323 | 338 | ||
324 | ieee80211_set_wmm_default(sdata, true); | 339 | err = drv_join_ibss(local, sdata); |
340 | if (err) { | ||
341 | sdata->vif.bss_conf.ibss_joined = false; | ||
342 | sdata->vif.bss_conf.ibss_creator = false; | ||
343 | sdata->vif.bss_conf.enable_beacon = false; | ||
344 | sdata->vif.bss_conf.ssid_len = 0; | ||
345 | RCU_INIT_POINTER(ifibss->presp, NULL); | ||
346 | kfree_rcu(presp, rcu_head); | ||
347 | ieee80211_vif_release_channel(sdata); | ||
348 | sdata_info(sdata, "Failed to join IBSS, driver failure: %d\n", | ||
349 | err); | ||
350 | return; | ||
351 | } | ||
352 | |||
353 | ieee80211_bss_info_change_notify(sdata, bss_change); | ||
325 | 354 | ||
326 | ifibss->state = IEEE80211_IBSS_MLME_JOINED; | 355 | ifibss->state = IEEE80211_IBSS_MLME_JOINED; |
327 | mod_timer(&ifibss->timer, | 356 | mod_timer(&ifibss->timer, |
@@ -416,6 +445,169 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
416 | tsf, false); | 445 | tsf, false); |
417 | } | 446 | } |
418 | 447 | ||
448 | static int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata, | ||
449 | struct cfg80211_csa_settings *csa_settings) | ||
450 | { | ||
451 | struct sk_buff *skb; | ||
452 | struct ieee80211_mgmt *mgmt; | ||
453 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
454 | struct ieee80211_local *local = sdata->local; | ||
455 | int freq; | ||
456 | int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.chan_switch) + | ||
457 | sizeof(mgmt->u.action.u.chan_switch); | ||
458 | u8 *pos; | ||
459 | |||
460 | skb = dev_alloc_skb(local->tx_headroom + hdr_len + | ||
461 | 5 + /* channel switch announcement element */ | ||
462 | 3); /* secondary channel offset element */ | ||
463 | if (!skb) | ||
464 | return -1; | ||
465 | |||
466 | skb_reserve(skb, local->tx_headroom); | ||
467 | mgmt = (struct ieee80211_mgmt *)skb_put(skb, hdr_len); | ||
468 | memset(mgmt, 0, hdr_len); | ||
469 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
470 | IEEE80211_STYPE_ACTION); | ||
471 | |||
472 | eth_broadcast_addr(mgmt->da); | ||
473 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | ||
474 | memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN); | ||
475 | mgmt->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT; | ||
476 | mgmt->u.action.u.chan_switch.action_code = WLAN_ACTION_SPCT_CHL_SWITCH; | ||
477 | pos = skb_put(skb, 5); | ||
478 | *pos++ = WLAN_EID_CHANNEL_SWITCH; /* EID */ | ||
479 | *pos++ = 3; /* IE length */ | ||
480 | *pos++ = csa_settings->block_tx ? 1 : 0; /* CSA mode */ | ||
481 | freq = csa_settings->chandef.chan->center_freq; | ||
482 | *pos++ = ieee80211_frequency_to_channel(freq); /* channel */ | ||
483 | *pos++ = csa_settings->count; /* count */ | ||
484 | |||
485 | if (csa_settings->chandef.width == NL80211_CHAN_WIDTH_40) { | ||
486 | enum nl80211_channel_type ch_type; | ||
487 | |||
488 | skb_put(skb, 3); | ||
489 | *pos++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET; /* EID */ | ||
490 | *pos++ = 1; /* IE length */ | ||
491 | ch_type = cfg80211_get_chandef_type(&csa_settings->chandef); | ||
492 | if (ch_type == NL80211_CHAN_HT40PLUS) | ||
493 | *pos++ = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | ||
494 | else | ||
495 | *pos++ = IEEE80211_HT_PARAM_CHA_SEC_BELOW; | ||
496 | } | ||
497 | |||
498 | ieee80211_tx_skb(sdata, skb); | ||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata, | ||
503 | struct cfg80211_csa_settings *csa_settings) | ||
504 | { | ||
505 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
506 | struct beacon_data *presp, *old_presp; | ||
507 | struct cfg80211_bss *cbss; | ||
508 | const struct cfg80211_bss_ies *ies; | ||
509 | u16 capability; | ||
510 | u64 tsf; | ||
511 | int ret = 0; | ||
512 | |||
513 | sdata_assert_lock(sdata); | ||
514 | |||
515 | capability = WLAN_CAPABILITY_IBSS; | ||
516 | |||
517 | if (ifibss->privacy) | ||
518 | capability |= WLAN_CAPABILITY_PRIVACY; | ||
519 | |||
520 | cbss = cfg80211_get_bss(sdata->local->hw.wiphy, ifibss->chandef.chan, | ||
521 | ifibss->bssid, ifibss->ssid, | ||
522 | ifibss->ssid_len, WLAN_CAPABILITY_IBSS | | ||
523 | WLAN_CAPABILITY_PRIVACY, | ||
524 | capability); | ||
525 | |||
526 | if (WARN_ON(!cbss)) { | ||
527 | ret = -EINVAL; | ||
528 | goto out; | ||
529 | } | ||
530 | |||
531 | rcu_read_lock(); | ||
532 | ies = rcu_dereference(cbss->ies); | ||
533 | tsf = ies->tsf; | ||
534 | rcu_read_unlock(); | ||
535 | cfg80211_put_bss(sdata->local->hw.wiphy, cbss); | ||
536 | |||
537 | old_presp = rcu_dereference_protected(ifibss->presp, | ||
538 | lockdep_is_held(&sdata->wdev.mtx)); | ||
539 | |||
540 | presp = ieee80211_ibss_build_presp(sdata, | ||
541 | sdata->vif.bss_conf.beacon_int, | ||
542 | sdata->vif.bss_conf.basic_rates, | ||
543 | capability, tsf, &ifibss->chandef, | ||
544 | NULL, csa_settings); | ||
545 | if (!presp) { | ||
546 | ret = -ENOMEM; | ||
547 | goto out; | ||
548 | } | ||
549 | |||
550 | rcu_assign_pointer(ifibss->presp, presp); | ||
551 | if (old_presp) | ||
552 | kfree_rcu(old_presp, rcu_head); | ||
553 | |||
554 | /* it might not send the beacon for a while. send an action frame | ||
555 | * immediately to announce the channel switch. | ||
556 | */ | ||
557 | if (csa_settings) | ||
558 | ieee80211_send_action_csa(sdata, csa_settings); | ||
559 | |||
560 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); | ||
561 | out: | ||
562 | return ret; | ||
563 | } | ||
564 | |||
565 | int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata) | ||
566 | { | ||
567 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
568 | struct cfg80211_bss *cbss; | ||
569 | int err; | ||
570 | u16 capability; | ||
571 | |||
572 | sdata_lock(sdata); | ||
573 | /* update cfg80211 bss information with the new channel */ | ||
574 | if (!is_zero_ether_addr(ifibss->bssid)) { | ||
575 | capability = WLAN_CAPABILITY_IBSS; | ||
576 | |||
577 | if (ifibss->privacy) | ||
578 | capability |= WLAN_CAPABILITY_PRIVACY; | ||
579 | |||
580 | cbss = cfg80211_get_bss(sdata->local->hw.wiphy, | ||
581 | ifibss->chandef.chan, | ||
582 | ifibss->bssid, ifibss->ssid, | ||
583 | ifibss->ssid_len, WLAN_CAPABILITY_IBSS | | ||
584 | WLAN_CAPABILITY_PRIVACY, | ||
585 | capability); | ||
586 | /* XXX: should not really modify cfg80211 data */ | ||
587 | if (cbss) { | ||
588 | cbss->channel = sdata->local->csa_chandef.chan; | ||
589 | cfg80211_put_bss(sdata->local->hw.wiphy, cbss); | ||
590 | } | ||
591 | } | ||
592 | |||
593 | ifibss->chandef = sdata->local->csa_chandef; | ||
594 | |||
595 | /* generate the beacon */ | ||
596 | err = ieee80211_ibss_csa_beacon(sdata, NULL); | ||
597 | sdata_unlock(sdata); | ||
598 | if (err < 0) | ||
599 | return err; | ||
600 | |||
601 | return 0; | ||
602 | } | ||
603 | |||
604 | void ieee80211_ibss_stop(struct ieee80211_sub_if_data *sdata) | ||
605 | { | ||
606 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
607 | |||
608 | cancel_work_sync(&ifibss->csa_connection_drop_work); | ||
609 | } | ||
610 | |||
419 | static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta) | 611 | static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta) |
420 | __acquires(RCU) | 612 | __acquires(RCU) |
421 | { | 613 | { |
@@ -499,6 +691,295 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, const u8 *bssid, | |||
499 | return ieee80211_ibss_finish_sta(sta); | 691 | return ieee80211_ibss_finish_sta(sta); |
500 | } | 692 | } |
501 | 693 | ||
694 | static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) | ||
695 | { | ||
696 | struct ieee80211_local *local = sdata->local; | ||
697 | int active = 0; | ||
698 | struct sta_info *sta; | ||
699 | |||
700 | sdata_assert_lock(sdata); | ||
701 | |||
702 | rcu_read_lock(); | ||
703 | |||
704 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | ||
705 | if (sta->sdata == sdata && | ||
706 | time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL, | ||
707 | jiffies)) { | ||
708 | active++; | ||
709 | break; | ||
710 | } | ||
711 | } | ||
712 | |||
713 | rcu_read_unlock(); | ||
714 | |||
715 | return active; | ||
716 | } | ||
717 | |||
718 | static void ieee80211_ibss_disconnect(struct ieee80211_sub_if_data *sdata) | ||
719 | { | ||
720 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
721 | struct ieee80211_local *local = sdata->local; | ||
722 | struct cfg80211_bss *cbss; | ||
723 | struct beacon_data *presp; | ||
724 | struct sta_info *sta; | ||
725 | int active_ibss; | ||
726 | u16 capability; | ||
727 | |||
728 | active_ibss = ieee80211_sta_active_ibss(sdata); | ||
729 | |||
730 | if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) { | ||
731 | capability = WLAN_CAPABILITY_IBSS; | ||
732 | |||
733 | if (ifibss->privacy) | ||
734 | capability |= WLAN_CAPABILITY_PRIVACY; | ||
735 | |||
736 | cbss = cfg80211_get_bss(local->hw.wiphy, ifibss->chandef.chan, | ||
737 | ifibss->bssid, ifibss->ssid, | ||
738 | ifibss->ssid_len, WLAN_CAPABILITY_IBSS | | ||
739 | WLAN_CAPABILITY_PRIVACY, | ||
740 | capability); | ||
741 | |||
742 | if (cbss) { | ||
743 | cfg80211_unlink_bss(local->hw.wiphy, cbss); | ||
744 | cfg80211_put_bss(sdata->local->hw.wiphy, cbss); | ||
745 | } | ||
746 | } | ||
747 | |||
748 | ifibss->state = IEEE80211_IBSS_MLME_SEARCH; | ||
749 | |||
750 | sta_info_flush(sdata); | ||
751 | |||
752 | spin_lock_bh(&ifibss->incomplete_lock); | ||
753 | while (!list_empty(&ifibss->incomplete_stations)) { | ||
754 | sta = list_first_entry(&ifibss->incomplete_stations, | ||
755 | struct sta_info, list); | ||
756 | list_del(&sta->list); | ||
757 | spin_unlock_bh(&ifibss->incomplete_lock); | ||
758 | |||
759 | sta_info_free(local, sta); | ||
760 | spin_lock_bh(&ifibss->incomplete_lock); | ||
761 | } | ||
762 | spin_unlock_bh(&ifibss->incomplete_lock); | ||
763 | |||
764 | netif_carrier_off(sdata->dev); | ||
765 | |||
766 | sdata->vif.bss_conf.ibss_joined = false; | ||
767 | sdata->vif.bss_conf.ibss_creator = false; | ||
768 | sdata->vif.bss_conf.enable_beacon = false; | ||
769 | sdata->vif.bss_conf.ssid_len = 0; | ||
770 | |||
771 | /* remove beacon */ | ||
772 | presp = rcu_dereference_protected(ifibss->presp, | ||
773 | lockdep_is_held(&sdata->wdev.mtx)); | ||
774 | RCU_INIT_POINTER(sdata->u.ibss.presp, NULL); | ||
775 | if (presp) | ||
776 | kfree_rcu(presp, rcu_head); | ||
777 | |||
778 | clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); | ||
779 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | | ||
780 | BSS_CHANGED_IBSS); | ||
781 | drv_leave_ibss(local, sdata); | ||
782 | ieee80211_vif_release_channel(sdata); | ||
783 | } | ||
784 | |||
785 | static void ieee80211_csa_connection_drop_work(struct work_struct *work) | ||
786 | { | ||
787 | struct ieee80211_sub_if_data *sdata = | ||
788 | container_of(work, struct ieee80211_sub_if_data, | ||
789 | u.ibss.csa_connection_drop_work); | ||
790 | |||
791 | ieee80211_ibss_disconnect(sdata); | ||
792 | synchronize_rcu(); | ||
793 | skb_queue_purge(&sdata->skb_queue); | ||
794 | |||
795 | /* trigger a scan to find another IBSS network to join */ | ||
796 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); | ||
797 | } | ||
798 | |||
799 | static bool | ||
800 | ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, | ||
801 | struct ieee802_11_elems *elems, | ||
802 | bool beacon) | ||
803 | { | ||
804 | struct cfg80211_csa_settings params; | ||
805 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
806 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
807 | struct ieee80211_chanctx *chanctx; | ||
808 | enum nl80211_channel_type ch_type; | ||
809 | int err, num_chanctx; | ||
810 | u32 sta_flags; | ||
811 | u8 mode; | ||
812 | |||
813 | if (sdata->vif.csa_active) | ||
814 | return true; | ||
815 | |||
816 | if (!sdata->vif.bss_conf.ibss_joined) | ||
817 | return false; | ||
818 | |||
819 | sta_flags = IEEE80211_STA_DISABLE_VHT; | ||
820 | switch (ifibss->chandef.width) { | ||
821 | case NL80211_CHAN_WIDTH_5: | ||
822 | case NL80211_CHAN_WIDTH_10: | ||
823 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
824 | sta_flags |= IEEE80211_STA_DISABLE_HT; | ||
825 | /* fall through */ | ||
826 | case NL80211_CHAN_WIDTH_20: | ||
827 | sta_flags |= IEEE80211_STA_DISABLE_40MHZ; | ||
828 | break; | ||
829 | default: | ||
830 | break; | ||
831 | } | ||
832 | |||
833 | memset(¶ms, 0, sizeof(params)); | ||
834 | err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, | ||
835 | ifibss->chandef.chan->band, | ||
836 | sta_flags, ifibss->bssid, | ||
837 | ¶ms.count, &mode, | ||
838 | ¶ms.chandef); | ||
839 | |||
840 | /* can't switch to destination channel, fail */ | ||
841 | if (err < 0) | ||
842 | goto disconnect; | ||
843 | |||
844 | /* did not contain a CSA */ | ||
845 | if (err) | ||
846 | return false; | ||
847 | |||
848 | if (ifibss->chandef.chan->band != params.chandef.chan->band) | ||
849 | goto disconnect; | ||
850 | |||
851 | switch (ifibss->chandef.width) { | ||
852 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
853 | case NL80211_CHAN_WIDTH_20: | ||
854 | case NL80211_CHAN_WIDTH_40: | ||
855 | /* keep our current HT mode (HT20/HT40+/HT40-), even if | ||
856 | * another mode has been announced. The mode is not adopted | ||
857 | * within the beacon while doing CSA and we should therefore | ||
858 | * keep the mode which we announce. | ||
859 | */ | ||
860 | ch_type = cfg80211_get_chandef_type(&ifibss->chandef); | ||
861 | cfg80211_chandef_create(¶ms.chandef, params.chandef.chan, | ||
862 | ch_type); | ||
863 | break; | ||
864 | case NL80211_CHAN_WIDTH_5: | ||
865 | case NL80211_CHAN_WIDTH_10: | ||
866 | if (params.chandef.width != ifibss->chandef.width) { | ||
867 | sdata_info(sdata, | ||
868 | "IBSS %pM received channel switch from incompatible channel width (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n", | ||
869 | ifibss->bssid, | ||
870 | params.chandef.chan->center_freq, | ||
871 | params.chandef.width, | ||
872 | params.chandef.center_freq1, | ||
873 | params.chandef.center_freq2); | ||
874 | goto disconnect; | ||
875 | } | ||
876 | break; | ||
877 | default: | ||
878 | /* should not happen, sta_flags should prevent VHT modes. */ | ||
879 | WARN_ON(1); | ||
880 | goto disconnect; | ||
881 | } | ||
882 | |||
883 | if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, ¶ms.chandef, | ||
884 | IEEE80211_CHAN_DISABLED)) { | ||
885 | sdata_info(sdata, | ||
886 | "IBSS %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n", | ||
887 | ifibss->bssid, | ||
888 | params.chandef.chan->center_freq, | ||
889 | params.chandef.width, | ||
890 | params.chandef.center_freq1, | ||
891 | params.chandef.center_freq2); | ||
892 | goto disconnect; | ||
893 | } | ||
894 | |||
895 | err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy, | ||
896 | ¶ms.chandef); | ||
897 | if (err < 0) | ||
898 | goto disconnect; | ||
899 | if (err) { | ||
900 | params.radar_required = true; | ||
901 | |||
902 | /* TODO: IBSS-DFS not (yet) supported, disconnect. */ | ||
903 | goto disconnect; | ||
904 | } | ||
905 | |||
906 | rcu_read_lock(); | ||
907 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
908 | if (!chanctx_conf) { | ||
909 | rcu_read_unlock(); | ||
910 | goto disconnect; | ||
911 | } | ||
912 | |||
913 | /* don't handle for multi-VIF cases */ | ||
914 | chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf); | ||
915 | if (chanctx->refcount > 1) { | ||
916 | rcu_read_unlock(); | ||
917 | goto disconnect; | ||
918 | } | ||
919 | num_chanctx = 0; | ||
920 | list_for_each_entry_rcu(chanctx, &sdata->local->chanctx_list, list) | ||
921 | num_chanctx++; | ||
922 | |||
923 | if (num_chanctx > 1) { | ||
924 | rcu_read_unlock(); | ||
925 | goto disconnect; | ||
926 | } | ||
927 | rcu_read_unlock(); | ||
928 | |||
929 | /* all checks done, now perform the channel switch. */ | ||
930 | ibss_dbg(sdata, | ||
931 | "received channel switch announcement to go to channel %d MHz\n", | ||
932 | params.chandef.chan->center_freq); | ||
933 | |||
934 | params.block_tx = !!mode; | ||
935 | |||
936 | ieee80211_ibss_csa_beacon(sdata, ¶ms); | ||
937 | sdata->csa_radar_required = params.radar_required; | ||
938 | |||
939 | if (params.block_tx) | ||
940 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | ||
941 | IEEE80211_MAX_QUEUE_MAP, | ||
942 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
943 | |||
944 | sdata->local->csa_chandef = params.chandef; | ||
945 | sdata->vif.csa_active = true; | ||
946 | |||
947 | ieee80211_bss_info_change_notify(sdata, err); | ||
948 | drv_channel_switch_beacon(sdata, ¶ms.chandef); | ||
949 | |||
950 | return true; | ||
951 | disconnect: | ||
952 | ibss_dbg(sdata, "Can't handle channel switch, disconnect\n"); | ||
953 | ieee80211_queue_work(&sdata->local->hw, | ||
954 | &ifibss->csa_connection_drop_work); | ||
955 | |||
956 | return true; | ||
957 | } | ||
958 | |||
959 | static void | ||
960 | ieee80211_rx_mgmt_spectrum_mgmt(struct ieee80211_sub_if_data *sdata, | ||
961 | struct ieee80211_mgmt *mgmt, size_t len, | ||
962 | struct ieee80211_rx_status *rx_status, | ||
963 | struct ieee802_11_elems *elems) | ||
964 | { | ||
965 | int required_len; | ||
966 | |||
967 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) | ||
968 | return; | ||
969 | |||
970 | /* CSA is the only action we handle for now */ | ||
971 | if (mgmt->u.action.u.measurement.action_code != | ||
972 | WLAN_ACTION_SPCT_CHL_SWITCH) | ||
973 | return; | ||
974 | |||
975 | required_len = IEEE80211_MIN_ACTION_SIZE + | ||
976 | sizeof(mgmt->u.action.u.chan_switch); | ||
977 | if (len < required_len) | ||
978 | return; | ||
979 | |||
980 | ieee80211_ibss_process_chanswitch(sdata, elems, false); | ||
981 | } | ||
982 | |||
502 | static void ieee80211_rx_mgmt_deauth_ibss(struct ieee80211_sub_if_data *sdata, | 983 | static void ieee80211_rx_mgmt_deauth_ibss(struct ieee80211_sub_if_data *sdata, |
503 | struct ieee80211_mgmt *mgmt, | 984 | struct ieee80211_mgmt *mgmt, |
504 | size_t len) | 985 | size_t len) |
@@ -661,10 +1142,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
661 | 1142 | ||
662 | /* check if we need to merge IBSS */ | 1143 | /* check if we need to merge IBSS */ |
663 | 1144 | ||
664 | /* we use a fixed BSSID */ | ||
665 | if (sdata->u.ibss.fixed_bssid) | ||
666 | goto put_bss; | ||
667 | |||
668 | /* not an IBSS */ | 1145 | /* not an IBSS */ |
669 | if (!(cbss->capability & WLAN_CAPABILITY_IBSS)) | 1146 | if (!(cbss->capability & WLAN_CAPABILITY_IBSS)) |
670 | goto put_bss; | 1147 | goto put_bss; |
@@ -680,10 +1157,18 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
680 | sdata->u.ibss.ssid_len)) | 1157 | sdata->u.ibss.ssid_len)) |
681 | goto put_bss; | 1158 | goto put_bss; |
682 | 1159 | ||
1160 | /* process channel switch */ | ||
1161 | if (ieee80211_ibss_process_chanswitch(sdata, elems, true)) | ||
1162 | goto put_bss; | ||
1163 | |||
683 | /* same BSSID */ | 1164 | /* same BSSID */ |
684 | if (ether_addr_equal(cbss->bssid, sdata->u.ibss.bssid)) | 1165 | if (ether_addr_equal(cbss->bssid, sdata->u.ibss.bssid)) |
685 | goto put_bss; | 1166 | goto put_bss; |
686 | 1167 | ||
1168 | /* we use a fixed BSSID */ | ||
1169 | if (sdata->u.ibss.fixed_bssid) | ||
1170 | goto put_bss; | ||
1171 | |||
687 | if (ieee80211_have_rx_timestamp(rx_status)) { | 1172 | if (ieee80211_have_rx_timestamp(rx_status)) { |
688 | /* time when timestamp field was received */ | 1173 | /* time when timestamp field was received */ |
689 | rx_timestamp = | 1174 | rx_timestamp = |
@@ -775,30 +1260,6 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, | |||
775 | ieee80211_queue_work(&local->hw, &sdata->work); | 1260 | ieee80211_queue_work(&local->hw, &sdata->work); |
776 | } | 1261 | } |
777 | 1262 | ||
778 | static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) | ||
779 | { | ||
780 | struct ieee80211_local *local = sdata->local; | ||
781 | int active = 0; | ||
782 | struct sta_info *sta; | ||
783 | |||
784 | sdata_assert_lock(sdata); | ||
785 | |||
786 | rcu_read_lock(); | ||
787 | |||
788 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | ||
789 | if (sta->sdata == sdata && | ||
790 | time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL, | ||
791 | jiffies)) { | ||
792 | active++; | ||
793 | break; | ||
794 | } | ||
795 | } | ||
796 | |||
797 | rcu_read_unlock(); | ||
798 | |||
799 | return active; | ||
800 | } | ||
801 | |||
802 | static void ieee80211_ibss_sta_expire(struct ieee80211_sub_if_data *sdata) | 1263 | static void ieee80211_ibss_sta_expire(struct ieee80211_sub_if_data *sdata) |
803 | { | 1264 | { |
804 | struct ieee80211_local *local = sdata->local; | 1265 | struct ieee80211_local *local = sdata->local; |
@@ -1076,6 +1537,8 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1076 | struct ieee80211_rx_status *rx_status; | 1537 | struct ieee80211_rx_status *rx_status; |
1077 | struct ieee80211_mgmt *mgmt; | 1538 | struct ieee80211_mgmt *mgmt; |
1078 | u16 fc; | 1539 | u16 fc; |
1540 | struct ieee802_11_elems elems; | ||
1541 | int ies_len; | ||
1079 | 1542 | ||
1080 | rx_status = IEEE80211_SKB_RXCB(skb); | 1543 | rx_status = IEEE80211_SKB_RXCB(skb); |
1081 | mgmt = (struct ieee80211_mgmt *) skb->data; | 1544 | mgmt = (struct ieee80211_mgmt *) skb->data; |
@@ -1101,6 +1564,27 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1101 | case IEEE80211_STYPE_DEAUTH: | 1564 | case IEEE80211_STYPE_DEAUTH: |
1102 | ieee80211_rx_mgmt_deauth_ibss(sdata, mgmt, skb->len); | 1565 | ieee80211_rx_mgmt_deauth_ibss(sdata, mgmt, skb->len); |
1103 | break; | 1566 | break; |
1567 | case IEEE80211_STYPE_ACTION: | ||
1568 | switch (mgmt->u.action.category) { | ||
1569 | case WLAN_CATEGORY_SPECTRUM_MGMT: | ||
1570 | ies_len = skb->len - | ||
1571 | offsetof(struct ieee80211_mgmt, | ||
1572 | u.action.u.chan_switch.variable); | ||
1573 | |||
1574 | if (ies_len < 0) | ||
1575 | break; | ||
1576 | |||
1577 | ieee802_11_parse_elems( | ||
1578 | mgmt->u.action.u.chan_switch.variable, | ||
1579 | ies_len, true, &elems); | ||
1580 | |||
1581 | if (elems.parse_error) | ||
1582 | break; | ||
1583 | |||
1584 | ieee80211_rx_mgmt_spectrum_mgmt(sdata, mgmt, skb->len, | ||
1585 | rx_status, &elems); | ||
1586 | break; | ||
1587 | } | ||
1104 | } | 1588 | } |
1105 | 1589 | ||
1106 | mgmt_out: | 1590 | mgmt_out: |
@@ -1167,6 +1651,8 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
1167 | (unsigned long) sdata); | 1651 | (unsigned long) sdata); |
1168 | INIT_LIST_HEAD(&ifibss->incomplete_stations); | 1652 | INIT_LIST_HEAD(&ifibss->incomplete_stations); |
1169 | spin_lock_init(&ifibss->incomplete_lock); | 1653 | spin_lock_init(&ifibss->incomplete_lock); |
1654 | INIT_WORK(&ifibss->csa_connection_drop_work, | ||
1655 | ieee80211_csa_connection_drop_work); | ||
1170 | } | 1656 | } |
1171 | 1657 | ||
1172 | /* scan finished notification */ | 1658 | /* scan finished notification */ |
@@ -1265,73 +1751,19 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
1265 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | 1751 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) |
1266 | { | 1752 | { |
1267 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 1753 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
1268 | struct ieee80211_local *local = sdata->local; | ||
1269 | struct cfg80211_bss *cbss; | ||
1270 | u16 capability; | ||
1271 | int active_ibss; | ||
1272 | struct sta_info *sta; | ||
1273 | struct beacon_data *presp; | ||
1274 | |||
1275 | active_ibss = ieee80211_sta_active_ibss(sdata); | ||
1276 | |||
1277 | if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) { | ||
1278 | capability = WLAN_CAPABILITY_IBSS; | ||
1279 | |||
1280 | if (ifibss->privacy) | ||
1281 | capability |= WLAN_CAPABILITY_PRIVACY; | ||
1282 | |||
1283 | cbss = cfg80211_get_bss(local->hw.wiphy, ifibss->chandef.chan, | ||
1284 | ifibss->bssid, ifibss->ssid, | ||
1285 | ifibss->ssid_len, WLAN_CAPABILITY_IBSS | | ||
1286 | WLAN_CAPABILITY_PRIVACY, | ||
1287 | capability); | ||
1288 | 1754 | ||
1289 | if (cbss) { | 1755 | ieee80211_ibss_disconnect(sdata); |
1290 | cfg80211_unlink_bss(local->hw.wiphy, cbss); | ||
1291 | cfg80211_put_bss(local->hw.wiphy, cbss); | ||
1292 | } | ||
1293 | } | ||
1294 | |||
1295 | ifibss->state = IEEE80211_IBSS_MLME_SEARCH; | ||
1296 | memset(ifibss->bssid, 0, ETH_ALEN); | ||
1297 | ifibss->ssid_len = 0; | 1756 | ifibss->ssid_len = 0; |
1298 | 1757 | memset(ifibss->bssid, 0, ETH_ALEN); | |
1299 | sta_info_flush(sdata); | ||
1300 | |||
1301 | spin_lock_bh(&ifibss->incomplete_lock); | ||
1302 | while (!list_empty(&ifibss->incomplete_stations)) { | ||
1303 | sta = list_first_entry(&ifibss->incomplete_stations, | ||
1304 | struct sta_info, list); | ||
1305 | list_del(&sta->list); | ||
1306 | spin_unlock_bh(&ifibss->incomplete_lock); | ||
1307 | |||
1308 | sta_info_free(local, sta); | ||
1309 | spin_lock_bh(&ifibss->incomplete_lock); | ||
1310 | } | ||
1311 | spin_unlock_bh(&ifibss->incomplete_lock); | ||
1312 | |||
1313 | netif_carrier_off(sdata->dev); | ||
1314 | 1758 | ||
1315 | /* remove beacon */ | 1759 | /* remove beacon */ |
1316 | kfree(sdata->u.ibss.ie); | 1760 | kfree(sdata->u.ibss.ie); |
1317 | presp = rcu_dereference_protected(ifibss->presp, | ||
1318 | lockdep_is_held(&sdata->wdev.mtx)); | ||
1319 | RCU_INIT_POINTER(sdata->u.ibss.presp, NULL); | ||
1320 | 1761 | ||
1321 | /* on the next join, re-program HT parameters */ | 1762 | /* on the next join, re-program HT parameters */ |
1322 | memset(&ifibss->ht_capa, 0, sizeof(ifibss->ht_capa)); | 1763 | memset(&ifibss->ht_capa, 0, sizeof(ifibss->ht_capa)); |
1323 | memset(&ifibss->ht_capa_mask, 0, sizeof(ifibss->ht_capa_mask)); | 1764 | memset(&ifibss->ht_capa_mask, 0, sizeof(ifibss->ht_capa_mask)); |
1324 | 1765 | ||
1325 | sdata->vif.bss_conf.ibss_joined = false; | ||
1326 | sdata->vif.bss_conf.ibss_creator = false; | ||
1327 | sdata->vif.bss_conf.enable_beacon = false; | ||
1328 | sdata->vif.bss_conf.ssid_len = 0; | ||
1329 | clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); | ||
1330 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | | ||
1331 | BSS_CHANGED_IBSS); | ||
1332 | ieee80211_vif_release_channel(sdata); | ||
1333 | synchronize_rcu(); | 1766 | synchronize_rcu(); |
1334 | kfree(presp); | ||
1335 | 1767 | ||
1336 | skb_queue_purge(&sdata->skb_queue); | 1768 | skb_queue_purge(&sdata->skb_queue); |
1337 | 1769 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index b6186517ec56..3a87c8976a32 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -322,7 +322,6 @@ struct ieee80211_roc_work { | |||
322 | 322 | ||
323 | /* flags used in struct ieee80211_if_managed.flags */ | 323 | /* flags used in struct ieee80211_if_managed.flags */ |
324 | enum ieee80211_sta_flags { | 324 | enum ieee80211_sta_flags { |
325 | IEEE80211_STA_BEACON_POLL = BIT(0), | ||
326 | IEEE80211_STA_CONNECTION_POLL = BIT(1), | 325 | IEEE80211_STA_CONNECTION_POLL = BIT(1), |
327 | IEEE80211_STA_CONTROL_PORT = BIT(2), | 326 | IEEE80211_STA_CONTROL_PORT = BIT(2), |
328 | IEEE80211_STA_DISABLE_HT = BIT(4), | 327 | IEEE80211_STA_DISABLE_HT = BIT(4), |
@@ -487,6 +486,7 @@ struct ieee80211_if_managed { | |||
487 | 486 | ||
488 | struct ieee80211_if_ibss { | 487 | struct ieee80211_if_ibss { |
489 | struct timer_list timer; | 488 | struct timer_list timer; |
489 | struct work_struct csa_connection_drop_work; | ||
490 | 490 | ||
491 | unsigned long last_scan_completed; | 491 | unsigned long last_scan_completed; |
492 | 492 | ||
@@ -1330,6 +1330,10 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); | |||
1330 | void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata); | 1330 | void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata); |
1331 | void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | 1331 | void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, |
1332 | struct sk_buff *skb); | 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 | /* mesh code */ | 1338 | /* mesh code */ |
1335 | void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata); | 1339 | void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata); |
@@ -1481,6 +1485,29 @@ void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata, | |||
1481 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, | 1485 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, |
1482 | struct ieee80211_mgmt *mgmt, | 1486 | struct ieee80211_mgmt *mgmt, |
1483 | size_t len); | 1487 | size_t len); |
1488 | /** | ||
1489 | * ieee80211_parse_ch_switch_ie - parses channel switch IEs | ||
1490 | * @sdata: the sdata of the interface which has received the frame | ||
1491 | * @elems: parsed 802.11 elements received with the frame | ||
1492 | * @beacon: indicates if the frame was a beacon or probe response | ||
1493 | * @current_band: indicates the current band | ||
1494 | * @sta_flags: contains information about own capabilities and restrictions | ||
1495 | * to decide which channel switch announcements can be accepted. Only the | ||
1496 | * following subset of &enum ieee80211_sta_flags are evaluated: | ||
1497 | * %IEEE80211_STA_DISABLE_HT, %IEEE80211_STA_DISABLE_VHT, | ||
1498 | * %IEEE80211_STA_DISABLE_40MHZ, %IEEE80211_STA_DISABLE_80P80MHZ, | ||
1499 | * %IEEE80211_STA_DISABLE_160MHZ. | ||
1500 | * @count: to be filled with the counter until the switch (on success only) | ||
1501 | * @bssid: the currently connected bssid (for reporting) | ||
1502 | * @mode: to be filled with CSA mode (on success only) | ||
1503 | * @new_chandef: to be filled with destination chandef (on success only) | ||
1504 | * Return: 0 on success, <0 on error and >0 if there is nothing to parse. | ||
1505 | */ | ||
1506 | int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, | ||
1507 | struct ieee802_11_elems *elems, bool beacon, | ||
1508 | enum ieee80211_band current_band, | ||
1509 | u32 sta_flags, u8 *bssid, u8 *count, u8 *mode, | ||
1510 | struct cfg80211_chan_def *new_chandef); | ||
1484 | 1511 | ||
1485 | /* Suspend/resume and hw reconfiguration */ | 1512 | /* Suspend/resume and hw reconfiguration */ |
1486 | int ieee80211_reconfig(struct ieee80211_local *local); | 1513 | int ieee80211_reconfig(struct ieee80211_local *local); |
@@ -1654,6 +1681,7 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, | |||
1654 | void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, | 1681 | void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, |
1655 | const struct ieee80211_ht_operation *ht_oper, | 1682 | const struct ieee80211_ht_operation *ht_oper, |
1656 | struct cfg80211_chan_def *chandef); | 1683 | struct cfg80211_chan_def *chandef); |
1684 | u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c); | ||
1657 | 1685 | ||
1658 | int __must_check | 1686 | int __must_check |
1659 | ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, | 1687 | ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index fcecd633514e..e48f103b9ade 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -766,6 +766,10 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
766 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | 766 | if (sdata->vif.type == NL80211_IFTYPE_STATION) |
767 | ieee80211_mgd_stop(sdata); | 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 | * Remove all stations associated with this interface. | 774 | * Remove all stations associated with this interface. |
771 | * | 775 | * |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 620677e897bd..3e51dd7d98b3 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -879,7 +879,7 @@ ieee80211_gtk_rekey_add(struct ieee80211_vif *vif, | |||
879 | keyconf->keylen, keyconf->key, | 879 | keyconf->keylen, keyconf->key, |
880 | 0, NULL); | 880 | 0, NULL); |
881 | if (IS_ERR(key)) | 881 | if (IS_ERR(key)) |
882 | return ERR_PTR(PTR_ERR(key)); | 882 | return ERR_CAST(key); |
883 | 883 | ||
884 | if (sdata->u.mgd.mfp != IEEE80211_MFP_DISABLED) | 884 | if (sdata->u.mgd.mfp != IEEE80211_MFP_DISABLED) |
885 | key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT; | 885 | key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT; |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 86e4ad56b573..91cc8281e266 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -145,66 +145,6 @@ static int ecw2cw(int ecw) | |||
145 | return (1 << ecw) - 1; | 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 | static u32 | 148 | static u32 |
209 | ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, | 149 | ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, |
210 | struct ieee80211_supported_band *sband, | 150 | struct ieee80211_supported_band *sband, |
@@ -352,7 +292,7 @@ out: | |||
352 | break; | 292 | break; |
353 | } | 293 | } |
354 | 294 | ||
355 | ret |= chandef_downgrade(chandef); | 295 | ret |= ieee80211_chandef_downgrade(chandef); |
356 | } | 296 | } |
357 | 297 | ||
358 | if (chandef->width != vht_chandef.width && !tracking) | 298 | if (chandef->width != vht_chandef.width && !tracking) |
@@ -406,13 +346,13 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata, | |||
406 | */ | 346 | */ |
407 | if (ifmgd->flags & IEEE80211_STA_DISABLE_80P80MHZ && | 347 | if (ifmgd->flags & IEEE80211_STA_DISABLE_80P80MHZ && |
408 | chandef.width == NL80211_CHAN_WIDTH_80P80) | 348 | chandef.width == NL80211_CHAN_WIDTH_80P80) |
409 | flags |= chandef_downgrade(&chandef); | 349 | flags |= ieee80211_chandef_downgrade(&chandef); |
410 | if (ifmgd->flags & IEEE80211_STA_DISABLE_160MHZ && | 350 | if (ifmgd->flags & IEEE80211_STA_DISABLE_160MHZ && |
411 | chandef.width == NL80211_CHAN_WIDTH_160) | 351 | chandef.width == NL80211_CHAN_WIDTH_160) |
412 | flags |= chandef_downgrade(&chandef); | 352 | flags |= ieee80211_chandef_downgrade(&chandef); |
413 | if (ifmgd->flags & IEEE80211_STA_DISABLE_40MHZ && | 353 | if (ifmgd->flags & IEEE80211_STA_DISABLE_40MHZ && |
414 | chandef.width > NL80211_CHAN_WIDTH_20) | 354 | chandef.width > NL80211_CHAN_WIDTH_20) |
415 | flags |= chandef_downgrade(&chandef); | 355 | flags |= ieee80211_chandef_downgrade(&chandef); |
416 | 356 | ||
417 | if (cfg80211_chandef_identical(&chandef, &sdata->vif.bss_conf.chandef)) | 357 | if (cfg80211_chandef_identical(&chandef, &sdata->vif.bss_conf.chandef)) |
418 | return 0; | 358 | return 0; |
@@ -893,8 +833,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, | |||
893 | if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) | 833 | if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) |
894 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; | 834 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; |
895 | 835 | ||
896 | if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | | 836 | if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL) |
897 | IEEE80211_STA_CONNECTION_POLL)) | ||
898 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_USE_MINRATE; | 837 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_USE_MINRATE; |
899 | 838 | ||
900 | ieee80211_tx_skb(sdata, skb); | 839 | ieee80211_tx_skb(sdata, skb); |
@@ -937,6 +876,8 @@ static void ieee80211_chswitch_work(struct work_struct *work) | |||
937 | container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work); | 876 | container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work); |
938 | struct ieee80211_local *local = sdata->local; | 877 | struct ieee80211_local *local = sdata->local; |
939 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 878 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
879 | u32 changed = 0; | ||
880 | int ret; | ||
940 | 881 | ||
941 | if (!ieee80211_sdata_running(sdata)) | 882 | if (!ieee80211_sdata_running(sdata)) |
942 | return; | 883 | return; |
@@ -945,24 +886,39 @@ static void ieee80211_chswitch_work(struct work_struct *work) | |||
945 | if (!ifmgd->associated) | 886 | if (!ifmgd->associated) |
946 | goto out; | 887 | goto out; |
947 | 888 | ||
948 | local->_oper_chandef = local->csa_chandef; | 889 | ret = ieee80211_vif_change_channel(sdata, &local->csa_chandef, |
890 | &changed); | ||
891 | if (ret) { | ||
892 | sdata_info(sdata, | ||
893 | "vif channel switch failed, disconnecting\n"); | ||
894 | ieee80211_queue_work(&sdata->local->hw, | ||
895 | &ifmgd->csa_connection_drop_work); | ||
896 | goto out; | ||
897 | } | ||
949 | 898 | ||
950 | if (!local->ops->channel_switch) { | 899 | if (!local->use_chanctx) { |
951 | /* call "hw_config" only if doing sw channel switch */ | 900 | local->_oper_chandef = local->csa_chandef; |
952 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 901 | /* Call "hw_config" only if doing sw channel switch. |
953 | } else { | 902 | * Otherwise update the channel directly |
954 | /* update the device channel directly */ | 903 | */ |
955 | local->hw.conf.chandef = local->_oper_chandef; | 904 | if (!local->ops->channel_switch) |
905 | ieee80211_hw_config(local, 0); | ||
906 | else | ||
907 | local->hw.conf.chandef = local->_oper_chandef; | ||
956 | } | 908 | } |
957 | 909 | ||
958 | /* XXX: shouldn't really modify cfg80211-owned data! */ | 910 | /* XXX: shouldn't really modify cfg80211-owned data! */ |
959 | ifmgd->associated->channel = local->_oper_chandef.chan; | 911 | ifmgd->associated->channel = local->csa_chandef.chan; |
960 | 912 | ||
961 | /* XXX: wait for a beacon first? */ | 913 | /* XXX: wait for a beacon first? */ |
962 | ieee80211_wake_queues_by_reason(&local->hw, | 914 | ieee80211_wake_queues_by_reason(&local->hw, |
963 | IEEE80211_MAX_QUEUE_MAP, | 915 | IEEE80211_MAX_QUEUE_MAP, |
964 | IEEE80211_QUEUE_STOP_REASON_CSA); | 916 | IEEE80211_QUEUE_STOP_REASON_CSA); |
917 | |||
918 | ieee80211_bss_info_change_notify(sdata, changed); | ||
919 | |||
965 | out: | 920 | out: |
921 | sdata->vif.csa_active = false; | ||
966 | ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; | 922 | ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; |
967 | sdata_unlock(sdata); | 923 | sdata_unlock(sdata); |
968 | } | 924 | } |
@@ -1000,20 +956,12 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1000 | struct ieee80211_local *local = sdata->local; | 956 | struct ieee80211_local *local = sdata->local; |
1001 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 957 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1002 | struct cfg80211_bss *cbss = ifmgd->associated; | 958 | struct cfg80211_bss *cbss = ifmgd->associated; |
1003 | struct ieee80211_bss *bss; | ||
1004 | struct ieee80211_chanctx *chanctx; | 959 | struct ieee80211_chanctx *chanctx; |
1005 | enum ieee80211_band new_band; | 960 | enum ieee80211_band current_band; |
1006 | int new_freq; | ||
1007 | u8 new_chan_no; | ||
1008 | u8 count; | 961 | u8 count; |
1009 | u8 mode; | 962 | u8 mode; |
1010 | struct ieee80211_channel *new_chan; | ||
1011 | struct cfg80211_chan_def new_chandef = {}; | 963 | struct cfg80211_chan_def new_chandef = {}; |
1012 | struct cfg80211_chan_def new_vht_chandef = {}; | 964 | int res; |
1013 | const struct ieee80211_sec_chan_offs_ie *sec_chan_offs; | ||
1014 | const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie; | ||
1015 | const struct ieee80211_ht_operation *ht_oper; | ||
1016 | int secondary_channel_offset = -1; | ||
1017 | 965 | ||
1018 | sdata_assert_lock(sdata); | 966 | sdata_assert_lock(sdata); |
1019 | 967 | ||
@@ -1027,162 +975,23 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1027 | if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED) | 975 | if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED) |
1028 | return; | 976 | return; |
1029 | 977 | ||
1030 | sec_chan_offs = elems->sec_chan_offs; | 978 | current_band = cbss->channel->band; |
1031 | wide_bw_chansw_ie = elems->wide_bw_chansw_ie; | 979 | res = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, current_band, |
1032 | ht_oper = elems->ht_operation; | 980 | ifmgd->flags, |
1033 | 981 | ifmgd->associated->bssid, &count, | |
1034 | if (ifmgd->flags & (IEEE80211_STA_DISABLE_HT | | 982 | &mode, &new_chandef); |
1035 | IEEE80211_STA_DISABLE_40MHZ)) { | 983 | if (res < 0) |
1036 | sec_chan_offs = NULL; | ||
1037 | wide_bw_chansw_ie = NULL; | ||
1038 | /* only used for bandwidth here */ | ||
1039 | ht_oper = NULL; | ||
1040 | } | ||
1041 | |||
1042 | if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT) | ||
1043 | wide_bw_chansw_ie = NULL; | ||
1044 | |||
1045 | if (elems->ext_chansw_ie) { | ||
1046 | if (!ieee80211_operating_class_to_band( | ||
1047 | elems->ext_chansw_ie->new_operating_class, | ||
1048 | &new_band)) { | ||
1049 | sdata_info(sdata, | ||
1050 | "cannot understand ECSA IE operating class %d, disconnecting\n", | ||
1051 | elems->ext_chansw_ie->new_operating_class); | ||
1052 | ieee80211_queue_work(&local->hw, | ||
1053 | &ifmgd->csa_connection_drop_work); | ||
1054 | } | ||
1055 | new_chan_no = elems->ext_chansw_ie->new_ch_num; | ||
1056 | count = elems->ext_chansw_ie->count; | ||
1057 | mode = elems->ext_chansw_ie->mode; | ||
1058 | } else if (elems->ch_switch_ie) { | ||
1059 | new_band = cbss->channel->band; | ||
1060 | new_chan_no = elems->ch_switch_ie->new_ch_num; | ||
1061 | count = elems->ch_switch_ie->count; | ||
1062 | mode = elems->ch_switch_ie->mode; | ||
1063 | } else { | ||
1064 | /* nothing here we understand */ | ||
1065 | return; | ||
1066 | } | ||
1067 | |||
1068 | bss = (void *)cbss->priv; | ||
1069 | |||
1070 | new_freq = ieee80211_channel_to_frequency(new_chan_no, new_band); | ||
1071 | new_chan = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq); | ||
1072 | if (!new_chan || new_chan->flags & IEEE80211_CHAN_DISABLED) { | ||
1073 | sdata_info(sdata, | ||
1074 | "AP %pM switches to unsupported channel (%d MHz), disconnecting\n", | ||
1075 | ifmgd->associated->bssid, new_freq); | ||
1076 | ieee80211_queue_work(&local->hw, | 984 | ieee80211_queue_work(&local->hw, |
1077 | &ifmgd->csa_connection_drop_work); | 985 | &ifmgd->csa_connection_drop_work); |
986 | if (res) | ||
1078 | return; | 987 | return; |
1079 | } | ||
1080 | |||
1081 | if (!beacon && sec_chan_offs) { | ||
1082 | secondary_channel_offset = sec_chan_offs->sec_chan_offs; | ||
1083 | } else if (beacon && ht_oper) { | ||
1084 | secondary_channel_offset = | ||
1085 | ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET; | ||
1086 | } else if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { | ||
1087 | /* | ||
1088 | * If it's not a beacon, HT is enabled and the IE not present, | ||
1089 | * it's 20 MHz, 802.11-2012 8.5.2.6: | ||
1090 | * This element [the Secondary Channel Offset Element] is | ||
1091 | * present when switching to a 40 MHz channel. It may be | ||
1092 | * present when switching to a 20 MHz channel (in which | ||
1093 | * case the secondary channel offset is set to SCN). | ||
1094 | */ | ||
1095 | secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; | ||
1096 | } | ||
1097 | |||
1098 | switch (secondary_channel_offset) { | ||
1099 | default: | ||
1100 | /* secondary_channel_offset was present but is invalid */ | ||
1101 | case IEEE80211_HT_PARAM_CHA_SEC_NONE: | ||
1102 | cfg80211_chandef_create(&new_chandef, new_chan, | ||
1103 | NL80211_CHAN_HT20); | ||
1104 | break; | ||
1105 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | ||
1106 | cfg80211_chandef_create(&new_chandef, new_chan, | ||
1107 | NL80211_CHAN_HT40PLUS); | ||
1108 | break; | ||
1109 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | ||
1110 | cfg80211_chandef_create(&new_chandef, new_chan, | ||
1111 | NL80211_CHAN_HT40MINUS); | ||
1112 | break; | ||
1113 | case -1: | ||
1114 | cfg80211_chandef_create(&new_chandef, new_chan, | ||
1115 | NL80211_CHAN_NO_HT); | ||
1116 | /* keep width for 5/10 MHz channels */ | ||
1117 | switch (sdata->vif.bss_conf.chandef.width) { | ||
1118 | case NL80211_CHAN_WIDTH_5: | ||
1119 | case NL80211_CHAN_WIDTH_10: | ||
1120 | new_chandef.width = sdata->vif.bss_conf.chandef.width; | ||
1121 | break; | ||
1122 | default: | ||
1123 | break; | ||
1124 | } | ||
1125 | break; | ||
1126 | } | ||
1127 | |||
1128 | if (wide_bw_chansw_ie) { | ||
1129 | new_vht_chandef.chan = new_chan; | ||
1130 | new_vht_chandef.center_freq1 = | ||
1131 | ieee80211_channel_to_frequency( | ||
1132 | wide_bw_chansw_ie->new_center_freq_seg0, | ||
1133 | new_band); | ||
1134 | |||
1135 | switch (wide_bw_chansw_ie->new_channel_width) { | ||
1136 | default: | ||
1137 | /* hmmm, ignore VHT and use HT if present */ | ||
1138 | case IEEE80211_VHT_CHANWIDTH_USE_HT: | ||
1139 | new_vht_chandef.chan = NULL; | ||
1140 | break; | ||
1141 | case IEEE80211_VHT_CHANWIDTH_80MHZ: | ||
1142 | new_vht_chandef.width = NL80211_CHAN_WIDTH_80; | ||
1143 | break; | ||
1144 | case IEEE80211_VHT_CHANWIDTH_160MHZ: | ||
1145 | new_vht_chandef.width = NL80211_CHAN_WIDTH_160; | ||
1146 | break; | ||
1147 | case IEEE80211_VHT_CHANWIDTH_80P80MHZ: | ||
1148 | /* field is otherwise reserved */ | ||
1149 | new_vht_chandef.center_freq2 = | ||
1150 | ieee80211_channel_to_frequency( | ||
1151 | wide_bw_chansw_ie->new_center_freq_seg1, | ||
1152 | new_band); | ||
1153 | new_vht_chandef.width = NL80211_CHAN_WIDTH_80P80; | ||
1154 | break; | ||
1155 | } | ||
1156 | if (ifmgd->flags & IEEE80211_STA_DISABLE_80P80MHZ && | ||
1157 | new_vht_chandef.width == NL80211_CHAN_WIDTH_80P80) | ||
1158 | chandef_downgrade(&new_vht_chandef); | ||
1159 | if (ifmgd->flags & IEEE80211_STA_DISABLE_160MHZ && | ||
1160 | new_vht_chandef.width == NL80211_CHAN_WIDTH_160) | ||
1161 | chandef_downgrade(&new_vht_chandef); | ||
1162 | if (ifmgd->flags & IEEE80211_STA_DISABLE_40MHZ && | ||
1163 | new_vht_chandef.width > NL80211_CHAN_WIDTH_20) | ||
1164 | chandef_downgrade(&new_vht_chandef); | ||
1165 | } | ||
1166 | |||
1167 | /* if VHT data is there validate & use it */ | ||
1168 | if (new_vht_chandef.chan) { | ||
1169 | if (!cfg80211_chandef_compatible(&new_vht_chandef, | ||
1170 | &new_chandef)) { | ||
1171 | sdata_info(sdata, | ||
1172 | "AP %pM CSA has inconsistent channel data, disconnecting\n", | ||
1173 | ifmgd->associated->bssid); | ||
1174 | ieee80211_queue_work(&local->hw, | ||
1175 | &ifmgd->csa_connection_drop_work); | ||
1176 | return; | ||
1177 | } | ||
1178 | new_chandef = new_vht_chandef; | ||
1179 | } | ||
1180 | 988 | ||
1181 | if (!cfg80211_chandef_usable(local->hw.wiphy, &new_chandef, | 989 | if (!cfg80211_chandef_usable(local->hw.wiphy, &new_chandef, |
1182 | IEEE80211_CHAN_DISABLED)) { | 990 | IEEE80211_CHAN_DISABLED)) { |
1183 | sdata_info(sdata, | 991 | sdata_info(sdata, |
1184 | "AP %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n", | 992 | "AP %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n", |
1185 | ifmgd->associated->bssid, new_freq, | 993 | ifmgd->associated->bssid, |
994 | new_chandef.chan->center_freq, | ||
1186 | new_chandef.width, new_chandef.center_freq1, | 995 | new_chandef.width, new_chandef.center_freq1, |
1187 | new_chandef.center_freq2); | 996 | new_chandef.center_freq2); |
1188 | ieee80211_queue_work(&local->hw, | 997 | ieee80211_queue_work(&local->hw, |
@@ -1191,17 +1000,28 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1191 | } | 1000 | } |
1192 | 1001 | ||
1193 | ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; | 1002 | ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; |
1003 | sdata->vif.csa_active = true; | ||
1194 | 1004 | ||
1005 | mutex_lock(&local->chanctx_mtx); | ||
1195 | if (local->use_chanctx) { | 1006 | if (local->use_chanctx) { |
1196 | sdata_info(sdata, | 1007 | u32 num_chanctx = 0; |
1197 | "not handling channel switch with channel contexts\n"); | 1008 | list_for_each_entry(chanctx, &local->chanctx_list, list) |
1198 | ieee80211_queue_work(&local->hw, | 1009 | num_chanctx++; |
1199 | &ifmgd->csa_connection_drop_work); | 1010 | |
1200 | return; | 1011 | if (num_chanctx > 1 || |
1012 | !(local->hw.flags & IEEE80211_HW_CHANCTX_STA_CSA)) { | ||
1013 | sdata_info(sdata, | ||
1014 | "not handling chan-switch with channel contexts\n"); | ||
1015 | ieee80211_queue_work(&local->hw, | ||
1016 | &ifmgd->csa_connection_drop_work); | ||
1017 | mutex_unlock(&local->chanctx_mtx); | ||
1018 | return; | ||
1019 | } | ||
1201 | } | 1020 | } |
1202 | 1021 | ||
1203 | mutex_lock(&local->chanctx_mtx); | ||
1204 | if (WARN_ON(!rcu_access_pointer(sdata->vif.chanctx_conf))) { | 1022 | if (WARN_ON(!rcu_access_pointer(sdata->vif.chanctx_conf))) { |
1023 | ieee80211_queue_work(&local->hw, | ||
1024 | &ifmgd->csa_connection_drop_work); | ||
1205 | mutex_unlock(&local->chanctx_mtx); | 1025 | mutex_unlock(&local->chanctx_mtx); |
1206 | return; | 1026 | return; |
1207 | } | 1027 | } |
@@ -1374,8 +1194,7 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata) | |||
1374 | if (!mgd->associated) | 1194 | if (!mgd->associated) |
1375 | return false; | 1195 | return false; |
1376 | 1196 | ||
1377 | if (mgd->flags & (IEEE80211_STA_BEACON_POLL | | 1197 | if (mgd->flags & IEEE80211_STA_CONNECTION_POLL) |
1378 | IEEE80211_STA_CONNECTION_POLL)) | ||
1379 | return false; | 1198 | return false; |
1380 | 1199 | ||
1381 | if (!mgd->have_beacon) | 1200 | if (!mgd->have_beacon) |
@@ -1691,8 +1510,7 @@ static void __ieee80211_stop_poll(struct ieee80211_sub_if_data *sdata) | |||
1691 | { | 1510 | { |
1692 | lockdep_assert_held(&sdata->local->mtx); | 1511 | lockdep_assert_held(&sdata->local->mtx); |
1693 | 1512 | ||
1694 | sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | | 1513 | sdata->u.mgd.flags &= ~IEEE80211_STA_CONNECTION_POLL; |
1695 | IEEE80211_STA_BEACON_POLL); | ||
1696 | ieee80211_run_deferred_scan(sdata->local); | 1514 | ieee80211_run_deferred_scan(sdata->local); |
1697 | } | 1515 | } |
1698 | 1516 | ||
@@ -1954,11 +1772,8 @@ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata) | |||
1954 | struct ieee80211_local *local = sdata->local; | 1772 | struct ieee80211_local *local = sdata->local; |
1955 | 1773 | ||
1956 | mutex_lock(&local->mtx); | 1774 | mutex_lock(&local->mtx); |
1957 | if (!(ifmgd->flags & (IEEE80211_STA_BEACON_POLL | | 1775 | if (!(ifmgd->flags & IEEE80211_STA_CONNECTION_POLL)) |
1958 | IEEE80211_STA_CONNECTION_POLL))) { | 1776 | goto out; |
1959 | mutex_unlock(&local->mtx); | ||
1960 | return; | ||
1961 | } | ||
1962 | 1777 | ||
1963 | __ieee80211_stop_poll(sdata); | 1778 | __ieee80211_stop_poll(sdata); |
1964 | 1779 | ||
@@ -2094,15 +1909,9 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, | |||
2094 | * because otherwise we would reset the timer every time and | 1909 | * because otherwise we would reset the timer every time and |
2095 | * never check whether we received a probe response! | 1910 | * never check whether we received a probe response! |
2096 | */ | 1911 | */ |
2097 | if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | | 1912 | if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL) |
2098 | IEEE80211_STA_CONNECTION_POLL)) | ||
2099 | already = true; | 1913 | already = true; |
2100 | 1914 | ||
2101 | if (beacon) | ||
2102 | ifmgd->flags |= IEEE80211_STA_BEACON_POLL; | ||
2103 | else | ||
2104 | ifmgd->flags |= IEEE80211_STA_CONNECTION_POLL; | ||
2105 | |||
2106 | mutex_unlock(&sdata->local->mtx); | 1915 | mutex_unlock(&sdata->local->mtx); |
2107 | 1916 | ||
2108 | if (already) | 1917 | if (already) |
@@ -2174,6 +1983,7 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) | |||
2174 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | 1983 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, |
2175 | true, frame_buf); | 1984 | true, frame_buf); |
2176 | ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; | 1985 | ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; |
1986 | sdata->vif.csa_active = false; | ||
2177 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | 1987 | ieee80211_wake_queues_by_reason(&sdata->local->hw, |
2178 | IEEE80211_MAX_QUEUE_MAP, | 1988 | IEEE80211_MAX_QUEUE_MAP, |
2179 | IEEE80211_QUEUE_STOP_REASON_CSA); | 1989 | IEEE80211_QUEUE_STOP_REASON_CSA); |
@@ -3061,17 +2871,10 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
3061 | } | 2871 | } |
3062 | } | 2872 | } |
3063 | 2873 | ||
3064 | if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) { | 2874 | if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL) { |
3065 | mlme_dbg_ratelimited(sdata, | 2875 | mlme_dbg_ratelimited(sdata, |
3066 | "cancelling AP probe due to a received beacon\n"); | 2876 | "cancelling AP probe due to a received beacon\n"); |
3067 | mutex_lock(&local->mtx); | 2877 | ieee80211_reset_ap_probe(sdata); |
3068 | ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL; | ||
3069 | ieee80211_run_deferred_scan(local); | ||
3070 | mutex_unlock(&local->mtx); | ||
3071 | |||
3072 | mutex_lock(&local->iflist_mtx); | ||
3073 | ieee80211_recalc_ps(local, -1); | ||
3074 | mutex_unlock(&local->iflist_mtx); | ||
3075 | } | 2878 | } |
3076 | 2879 | ||
3077 | /* | 2880 | /* |
@@ -3543,8 +3346,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
3543 | } else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started) | 3346 | } else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started) |
3544 | run_again(sdata, ifmgd->assoc_data->timeout); | 3347 | run_again(sdata, ifmgd->assoc_data->timeout); |
3545 | 3348 | ||
3546 | if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | | 3349 | if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL && |
3547 | IEEE80211_STA_CONNECTION_POLL) && | ||
3548 | ifmgd->associated) { | 3350 | ifmgd->associated) { |
3549 | u8 bssid[ETH_ALEN]; | 3351 | u8 bssid[ETH_ALEN]; |
3550 | int max_tries; | 3352 | int max_tries; |
@@ -3876,7 +3678,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | |||
3876 | return ret; | 3678 | return ret; |
3877 | 3679 | ||
3878 | while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) { | 3680 | while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) { |
3879 | ifmgd->flags |= chandef_downgrade(&chandef); | 3681 | ifmgd->flags |= ieee80211_chandef_downgrade(&chandef); |
3880 | ret = ieee80211_vif_use_channel(sdata, &chandef, | 3682 | ret = ieee80211_vif_use_channel(sdata, &chandef, |
3881 | IEEE80211_CHANCTX_SHARED); | 3683 | IEEE80211_CHANCTX_SHARED); |
3882 | } | 3684 | } |
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 8b5f7ef7c0c9..7fa1b36e6202 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
@@ -203,6 +203,15 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) | |||
203 | memcpy(mi->max_tp_rate, tmp_tp_rate, sizeof(mi->max_tp_rate)); | 203 | memcpy(mi->max_tp_rate, tmp_tp_rate, sizeof(mi->max_tp_rate)); |
204 | mi->max_prob_rate = tmp_prob_rate; | 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 | /* Reset update timer */ | 215 | /* Reset update timer */ |
207 | mi->stats_update = jiffies; | 216 | mi->stats_update = jiffies; |
208 | 217 | ||
@@ -310,6 +319,11 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, | |||
310 | /* increase sum packet counter */ | 319 | /* increase sum packet counter */ |
311 | mi->packet_count++; | 320 | mi->packet_count++; |
312 | 321 | ||
322 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
323 | if (mp->fixed_rate_idx != -1) | ||
324 | return; | ||
325 | #endif | ||
326 | |||
313 | delta = (mi->packet_count * sampling_ratio / 100) - | 327 | delta = (mi->packet_count * sampling_ratio / 100) - |
314 | (mi->sample_count + mi->sample_deferred / 2); | 328 | (mi->sample_count + mi->sample_deferred / 2); |
315 | 329 | ||
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 7c323f27ba23..5d60779a0c1b 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -365,6 +365,14 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
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 | mi->stats_update = jiffies; | 377 | mi->stats_update = jiffies; |
370 | } | 378 | } |
@@ -774,6 +782,11 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
774 | info->flags |= mi->tx_flags; | 782 | info->flags |= mi->tx_flags; |
775 | minstrel_ht_check_cck_shortpreamble(mp, mi, txrc->short_preamble); | 783 | minstrel_ht_check_cck_shortpreamble(mp, mi, txrc->short_preamble); |
776 | 784 | ||
785 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
786 | if (mp->fixed_rate_idx != -1) | ||
787 | return; | ||
788 | #endif | ||
789 | |||
777 | /* Don't use EAPOL frames for sampling on non-mrr hw */ | 790 | /* Don't use EAPOL frames for sampling on non-mrr hw */ |
778 | if (mp->hw->max_rates == 1 && | 791 | if (mp->hw->max_rates == 1 && |
779 | (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) | 792 | (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) |
@@ -781,16 +794,6 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
781 | else | 794 | else |
782 | sample_idx = minstrel_get_sample_rate(mp, mi); | 795 | sample_idx = minstrel_get_sample_rate(mp, mi); |
783 | 796 | ||
784 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
785 | /* use fixed index if set */ | ||
786 | if (mp->fixed_rate_idx != -1) { | ||
787 | mi->max_tp_rate = mp->fixed_rate_idx; | ||
788 | mi->max_tp_rate2 = mp->fixed_rate_idx; | ||
789 | mi->max_prob_rate = mp->fixed_rate_idx; | ||
790 | sample_idx = -1; | ||
791 | } | ||
792 | #endif | ||
793 | |||
794 | mi->total_packets++; | 797 | mi->total_packets++; |
795 | 798 | ||
796 | /* wraparound */ | 799 | /* wraparound */ |
diff --git a/net/mac80211/rc80211_pid_debugfs.c b/net/mac80211/rc80211_pid_debugfs.c index c97a0657c043..6ff134650a84 100644 --- a/net/mac80211/rc80211_pid_debugfs.c +++ b/net/mac80211/rc80211_pid_debugfs.c | |||
@@ -167,29 +167,29 @@ static ssize_t rate_control_pid_events_read(struct file *file, char __user *buf, | |||
167 | * provide large enough buffers. */ | 167 | * provide large enough buffers. */ |
168 | length = length < RC_PID_PRINT_BUF_SIZE ? | 168 | length = length < RC_PID_PRINT_BUF_SIZE ? |
169 | length : RC_PID_PRINT_BUF_SIZE; | 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 | switch (ev->type) { | 171 | switch (ev->type) { |
172 | case RC_PID_EVENT_TYPE_TX_STATUS: | 172 | case RC_PID_EVENT_TYPE_TX_STATUS: |
173 | p += snprintf(pb + p, length - p, "tx_status %u %u", | 173 | p += scnprintf(pb + p, length - p, "tx_status %u %u", |
174 | !(ev->data.flags & IEEE80211_TX_STAT_ACK), | 174 | !(ev->data.flags & IEEE80211_TX_STAT_ACK), |
175 | ev->data.tx_status.status.rates[0].idx); | 175 | ev->data.tx_status.status.rates[0].idx); |
176 | break; | 176 | break; |
177 | case RC_PID_EVENT_TYPE_RATE_CHANGE: | 177 | case RC_PID_EVENT_TYPE_RATE_CHANGE: |
178 | p += snprintf(pb + p, length - p, "rate_change %d %d", | 178 | p += scnprintf(pb + p, length - p, "rate_change %d %d", |
179 | ev->data.index, ev->data.rate); | 179 | ev->data.index, ev->data.rate); |
180 | break; | 180 | break; |
181 | case RC_PID_EVENT_TYPE_TX_RATE: | 181 | case RC_PID_EVENT_TYPE_TX_RATE: |
182 | p += snprintf(pb + p, length - p, "tx_rate %d %d", | 182 | p += scnprintf(pb + p, length - p, "tx_rate %d %d", |
183 | ev->data.index, ev->data.rate); | 183 | ev->data.index, ev->data.rate); |
184 | break; | 184 | break; |
185 | case RC_PID_EVENT_TYPE_PF_SAMPLE: | 185 | case RC_PID_EVENT_TYPE_PF_SAMPLE: |
186 | p += snprintf(pb + p, length - p, | 186 | p += scnprintf(pb + p, length - p, |
187 | "pf_sample %d %d %d %d", | 187 | "pf_sample %d %d %d %d", |
188 | ev->data.pf_sample, ev->data.prop_err, | 188 | ev->data.pf_sample, ev->data.prop_err, |
189 | ev->data.int_err, ev->data.der_err); | 189 | ev->data.int_err, ev->data.der_err); |
190 | break; | 190 | break; |
191 | } | 191 | } |
192 | p += snprintf(pb + p, length - p, "\n"); | 192 | p += scnprintf(pb + p, length - p, "\n"); |
193 | 193 | ||
194 | spin_unlock_irqrestore(&events->lock, status); | 194 | spin_unlock_irqrestore(&events->lock, status); |
195 | 195 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 674eac1f996c..0011ac815097 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -995,8 +995,9 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
995 | rx->sta->num_duplicates++; | 995 | rx->sta->num_duplicates++; |
996 | } | 996 | } |
997 | return RX_DROP_UNUSABLE; | 997 | return RX_DROP_UNUSABLE; |
998 | } else | 998 | } else if (!(status->flag & RX_FLAG_AMSDU_MORE)) { |
999 | rx->sta->last_seq_ctrl[rx->seqno_idx] = hdr->seq_ctrl; | 999 | rx->sta->last_seq_ctrl[rx->seqno_idx] = hdr->seq_ctrl; |
1000 | } | ||
1000 | } | 1001 | } |
1001 | 1002 | ||
1002 | if (unlikely(rx->skb->len < 16)) { | 1003 | if (unlikely(rx->skb->len < 16)) { |
@@ -2402,7 +2403,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2402 | return RX_DROP_UNUSABLE; | 2403 | return RX_DROP_UNUSABLE; |
2403 | 2404 | ||
2404 | if (!rx->sta && mgmt->u.action.category != WLAN_CATEGORY_PUBLIC && | 2405 | if (!rx->sta && mgmt->u.action.category != WLAN_CATEGORY_PUBLIC && |
2405 | mgmt->u.action.category != WLAN_CATEGORY_SELF_PROTECTED) | 2406 | mgmt->u.action.category != WLAN_CATEGORY_SELF_PROTECTED && |
2407 | mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT) | ||
2406 | return RX_DROP_UNUSABLE; | 2408 | return RX_DROP_UNUSABLE; |
2407 | 2409 | ||
2408 | if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) | 2410 | if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) |
@@ -2566,31 +2568,46 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2566 | 2568 | ||
2567 | goto queue; | 2569 | goto queue; |
2568 | case WLAN_CATEGORY_SPECTRUM_MGMT: | 2570 | case WLAN_CATEGORY_SPECTRUM_MGMT: |
2569 | if (status->band != IEEE80211_BAND_5GHZ) | ||
2570 | break; | ||
2571 | |||
2572 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
2573 | break; | ||
2574 | |||
2575 | /* verify action_code is present */ | 2571 | /* verify action_code is present */ |
2576 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) | 2572 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) |
2577 | break; | 2573 | break; |
2578 | 2574 | ||
2579 | switch (mgmt->u.action.u.measurement.action_code) { | 2575 | switch (mgmt->u.action.u.measurement.action_code) { |
2580 | case WLAN_ACTION_SPCT_MSR_REQ: | 2576 | case WLAN_ACTION_SPCT_MSR_REQ: |
2577 | if (status->band != IEEE80211_BAND_5GHZ) | ||
2578 | break; | ||
2579 | |||
2581 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 2580 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
2582 | sizeof(mgmt->u.action.u.measurement))) | 2581 | sizeof(mgmt->u.action.u.measurement))) |
2583 | break; | 2582 | break; |
2583 | |||
2584 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
2585 | break; | ||
2586 | |||
2584 | ieee80211_process_measurement_req(sdata, mgmt, len); | 2587 | ieee80211_process_measurement_req(sdata, mgmt, len); |
2585 | goto handled; | 2588 | goto handled; |
2586 | case WLAN_ACTION_SPCT_CHL_SWITCH: | 2589 | case WLAN_ACTION_SPCT_CHL_SWITCH: { |
2587 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 2590 | u8 *bssid; |
2591 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
2592 | sizeof(mgmt->u.action.u.chan_switch))) | ||
2593 | break; | ||
2594 | |||
2595 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | ||
2596 | sdata->vif.type != NL80211_IFTYPE_ADHOC) | ||
2588 | break; | 2597 | break; |
2589 | 2598 | ||
2590 | if (!ether_addr_equal(mgmt->bssid, sdata->u.mgd.bssid)) | 2599 | if (sdata->vif.type == NL80211_IFTYPE_STATION) |
2600 | bssid = sdata->u.mgd.bssid; | ||
2601 | else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
2602 | bssid = sdata->u.ibss.bssid; | ||
2603 | else | ||
2604 | break; | ||
2605 | |||
2606 | if (!ether_addr_equal(mgmt->bssid, bssid)) | ||
2591 | break; | 2607 | break; |
2592 | 2608 | ||
2593 | goto queue; | 2609 | goto queue; |
2610 | } | ||
2594 | } | 2611 | } |
2595 | break; | 2612 | break; |
2596 | case WLAN_CATEGORY_SA_QUERY: | 2613 | case WLAN_CATEGORY_SA_QUERY: |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 08afe74b98f4..ecb57b0bf74a 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -391,8 +391,7 @@ static bool ieee80211_can_scan(struct ieee80211_local *local, | |||
391 | return false; | 391 | return false; |
392 | 392 | ||
393 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 393 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
394 | sdata->u.mgd.flags & (IEEE80211_STA_BEACON_POLL | | 394 | sdata->u.mgd.flags & IEEE80211_STA_CONNECTION_POLL) |
395 | IEEE80211_STA_CONNECTION_POLL)) | ||
396 | return false; | 395 | return false; |
397 | 396 | ||
398 | return true; | 397 | return true; |
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c index 578eea3fc04d..921597e279a3 100644 --- a/net/mac80211/spectmgmt.c +++ b/net/mac80211/spectmgmt.c | |||
@@ -21,6 +21,168 @@ | |||
21 | #include "sta_info.h" | 21 | #include "sta_info.h" |
22 | #include "wme.h" | 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 | static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_data *sdata, | 186 | static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_data *sdata, |
25 | struct ieee80211_msrment_ie *request_ie, | 187 | struct ieee80211_msrment_ie *request_ie, |
26 | const u8 *da, const u8 *bssid, | 188 | const u8 *da, const u8 *bssid, |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 3fb9dd6d02fc..d4cee98533fd 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -1475,6 +1475,41 @@ DEFINE_EVENT(local_sdata_evt, drv_ipv6_addr_change, | |||
1475 | ); | 1475 | ); |
1476 | #endif | 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 | * Tracing for API calls that drivers call. | 1514 | * Tracing for API calls that drivers call. |
1480 | */ | 1515 | */ |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 3456c0486b48..4fcbf634b548 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1981,7 +1981,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1981 | * EAPOL frames from the local station. | 1981 | * EAPOL frames from the local station. |
1982 | */ | 1982 | */ |
1983 | if (unlikely(!ieee80211_vif_is_mesh(&sdata->vif) && | 1983 | if (unlikely(!ieee80211_vif_is_mesh(&sdata->vif) && |
1984 | !is_multicast_ether_addr(hdr.addr1) && !authorized && | 1984 | !multicast && !authorized && |
1985 | (cpu_to_be16(ethertype) != sdata->control_port_protocol || | 1985 | (cpu_to_be16(ethertype) != sdata->control_port_protocol || |
1986 | !ether_addr_equal(sdata->vif.addr, skb->data + ETH_ALEN)))) { | 1986 | !ether_addr_equal(sdata->vif.addr, skb->data + ETH_ALEN)))) { |
1987 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1987 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
@@ -2357,15 +2357,31 @@ static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata, | |||
2357 | struct probe_resp *resp; | 2357 | struct probe_resp *resp; |
2358 | int counter_offset_beacon = sdata->csa_counter_offset_beacon; | 2358 | int counter_offset_beacon = sdata->csa_counter_offset_beacon; |
2359 | int counter_offset_presp = sdata->csa_counter_offset_presp; | 2359 | int counter_offset_presp = sdata->csa_counter_offset_presp; |
2360 | u8 *beacon_data; | ||
2361 | size_t beacon_data_len; | ||
2362 | |||
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)) | ||
2376 | return; | ||
2360 | 2377 | ||
2361 | /* warn if the driver did not check for/react to csa completeness */ | 2378 | /* warn if the driver did not check for/react to csa completeness */ |
2362 | if (WARN_ON(((u8 *)beacon->tail)[counter_offset_beacon] == 0)) | 2379 | if (WARN_ON(beacon_data[counter_offset_beacon] == 0)) |
2363 | return; | 2380 | return; |
2364 | 2381 | ||
2365 | ((u8 *)beacon->tail)[counter_offset_beacon]--; | 2382 | beacon_data[counter_offset_beacon]--; |
2366 | 2383 | ||
2367 | if (sdata->vif.type == NL80211_IFTYPE_AP && | 2384 | if (sdata->vif.type == NL80211_IFTYPE_AP && counter_offset_presp) { |
2368 | counter_offset_presp) { | ||
2369 | rcu_read_lock(); | 2385 | rcu_read_lock(); |
2370 | resp = rcu_dereference(sdata->u.ap.probe_resp); | 2386 | resp = rcu_dereference(sdata->u.ap.probe_resp); |
2371 | 2387 | ||
@@ -2400,6 +2416,15 @@ bool ieee80211_csa_is_complete(struct ieee80211_vif *vif) | |||
2400 | goto out; | 2416 | goto out; |
2401 | beacon_data = beacon->tail; | 2417 | beacon_data = beacon->tail; |
2402 | beacon_data_len = beacon->tail_len; | 2418 | beacon_data_len = beacon->tail_len; |
2419 | } else if (vif->type == NL80211_IFTYPE_ADHOC) { | ||
2420 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
2421 | |||
2422 | beacon = rcu_dereference(ifibss->presp); | ||
2423 | if (!beacon) | ||
2424 | goto out; | ||
2425 | |||
2426 | beacon_data = beacon->head; | ||
2427 | beacon_data_len = beacon->head_len; | ||
2403 | } else { | 2428 | } else { |
2404 | WARN_ON(1); | 2429 | WARN_ON(1); |
2405 | goto out; | 2430 | goto out; |
@@ -2484,6 +2509,10 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2484 | if (!presp) | 2509 | if (!presp) |
2485 | goto out; | 2510 | goto out; |
2486 | 2511 | ||
2512 | if (sdata->vif.csa_active) | ||
2513 | ieee80211_update_csa(sdata, presp); | ||
2514 | |||
2515 | |||
2487 | skb = dev_alloc_skb(local->tx_headroom + presp->head_len); | 2516 | skb = dev_alloc_skb(local->tx_headroom + presp->head_len); |
2488 | if (!skb) | 2517 | if (!skb) |
2489 | goto out; | 2518 | goto out; |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 9c3200bcfc02..1220f5afdb7e 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -567,18 +567,15 @@ void ieee80211_flush_queues(struct ieee80211_local *local, | |||
567 | IEEE80211_QUEUE_STOP_REASON_FLUSH); | 567 | IEEE80211_QUEUE_STOP_REASON_FLUSH); |
568 | } | 568 | } |
569 | 569 | ||
570 | void ieee80211_iterate_active_interfaces( | 570 | static void __iterate_active_interfaces(struct ieee80211_local *local, |
571 | struct ieee80211_hw *hw, u32 iter_flags, | 571 | u32 iter_flags, |
572 | void (*iterator)(void *data, u8 *mac, | 572 | void (*iterator)(void *data, u8 *mac, |
573 | struct ieee80211_vif *vif), | 573 | struct ieee80211_vif *vif), |
574 | void *data) | 574 | void *data) |
575 | { | 575 | { |
576 | struct ieee80211_local *local = hw_to_local(hw); | ||
577 | struct ieee80211_sub_if_data *sdata; | 576 | struct ieee80211_sub_if_data *sdata; |
578 | 577 | ||
579 | mutex_lock(&local->iflist_mtx); | 578 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
580 | |||
581 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
582 | switch (sdata->vif.type) { | 579 | switch (sdata->vif.type) { |
583 | case NL80211_IFTYPE_MONITOR: | 580 | case NL80211_IFTYPE_MONITOR: |
584 | if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) | 581 | if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) |
@@ -597,13 +594,25 @@ void ieee80211_iterate_active_interfaces( | |||
597 | &sdata->vif); | 594 | &sdata->vif); |
598 | } | 595 | } |
599 | 596 | ||
600 | sdata = rcu_dereference_protected(local->monitor_sdata, | 597 | sdata = rcu_dereference_check(local->monitor_sdata, |
601 | lockdep_is_held(&local->iflist_mtx)); | 598 | lockdep_is_held(&local->iflist_mtx) || |
599 | lockdep_rtnl_is_held()); | ||
602 | if (sdata && | 600 | if (sdata && |
603 | (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || | 601 | (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || |
604 | sdata->flags & IEEE80211_SDATA_IN_DRIVER)) | 602 | sdata->flags & IEEE80211_SDATA_IN_DRIVER)) |
605 | iterator(data, sdata->vif.addr, &sdata->vif); | 603 | iterator(data, sdata->vif.addr, &sdata->vif); |
604 | } | ||
605 | |||
606 | void ieee80211_iterate_active_interfaces( | ||
607 | struct ieee80211_hw *hw, u32 iter_flags, | ||
608 | void (*iterator)(void *data, u8 *mac, | ||
609 | struct ieee80211_vif *vif), | ||
610 | void *data) | ||
611 | { | ||
612 | struct ieee80211_local *local = hw_to_local(hw); | ||
606 | 613 | ||
614 | mutex_lock(&local->iflist_mtx); | ||
615 | __iterate_active_interfaces(local, iter_flags, iterator, data); | ||
607 | mutex_unlock(&local->iflist_mtx); | 616 | mutex_unlock(&local->iflist_mtx); |
608 | } | 617 | } |
609 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); | 618 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); |
@@ -615,38 +624,26 @@ void ieee80211_iterate_active_interfaces_atomic( | |||
615 | void *data) | 624 | void *data) |
616 | { | 625 | { |
617 | struct ieee80211_local *local = hw_to_local(hw); | 626 | struct ieee80211_local *local = hw_to_local(hw); |
618 | struct ieee80211_sub_if_data *sdata; | ||
619 | 627 | ||
620 | rcu_read_lock(); | 628 | rcu_read_lock(); |
629 | __iterate_active_interfaces(local, iter_flags, iterator, data); | ||
630 | rcu_read_unlock(); | ||
631 | } | ||
632 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); | ||
621 | 633 | ||
622 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 634 | void ieee80211_iterate_active_interfaces_rtnl( |
623 | switch (sdata->vif.type) { | 635 | struct ieee80211_hw *hw, u32 iter_flags, |
624 | case NL80211_IFTYPE_MONITOR: | 636 | void (*iterator)(void *data, u8 *mac, |
625 | if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) | 637 | struct ieee80211_vif *vif), |
626 | continue; | 638 | void *data) |
627 | break; | 639 | { |
628 | case NL80211_IFTYPE_AP_VLAN: | 640 | struct ieee80211_local *local = hw_to_local(hw); |
629 | continue; | ||
630 | default: | ||
631 | break; | ||
632 | } | ||
633 | if (!(iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL) && | ||
634 | !(sdata->flags & IEEE80211_SDATA_IN_DRIVER)) | ||
635 | continue; | ||
636 | if (ieee80211_sdata_running(sdata)) | ||
637 | iterator(data, sdata->vif.addr, | ||
638 | &sdata->vif); | ||
639 | } | ||
640 | 641 | ||
641 | sdata = rcu_dereference(local->monitor_sdata); | 642 | ASSERT_RTNL(); |
642 | if (sdata && | ||
643 | (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || | ||
644 | sdata->flags & IEEE80211_SDATA_IN_DRIVER)) | ||
645 | iterator(data, sdata->vif.addr, &sdata->vif); | ||
646 | 643 | ||
647 | rcu_read_unlock(); | 644 | __iterate_active_interfaces(local, iter_flags, iterator, data); |
648 | } | 645 | } |
649 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); | 646 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_rtnl); |
650 | 647 | ||
651 | /* | 648 | /* |
652 | * Nothing should have been stuffed into the workqueue during | 649 | * Nothing should have been stuffed into the workqueue during |
@@ -1007,14 +1004,21 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
1007 | */ | 1004 | */ |
1008 | enable_qos = (sdata->vif.type != NL80211_IFTYPE_STATION); | 1005 | enable_qos = (sdata->vif.type != NL80211_IFTYPE_STATION); |
1009 | 1006 | ||
1010 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | 1007 | /* Set defaults according to 802.11-2007 Table 7-37 */ |
1011 | /* Set defaults according to 802.11-2007 Table 7-37 */ | 1008 | aCWmax = 1023; |
1012 | aCWmax = 1023; | 1009 | if (use_11b) |
1013 | if (use_11b) | 1010 | aCWmin = 31; |
1014 | aCWmin = 31; | 1011 | else |
1015 | else | 1012 | aCWmin = 15; |
1016 | aCWmin = 15; | 1013 | |
1014 | /* Confiure old 802.11b/g medium access rules. */ | ||
1015 | qparam.cw_max = aCWmax; | ||
1016 | qparam.cw_min = aCWmin; | ||
1017 | qparam.txop = 0; | ||
1018 | qparam.aifs = 2; | ||
1017 | 1019 | ||
1020 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | ||
1021 | /* Update if QoS is enabled. */ | ||
1018 | if (enable_qos) { | 1022 | if (enable_qos) { |
1019 | switch (ac) { | 1023 | switch (ac) { |
1020 | case IEEE80211_AC_BK: | 1024 | case IEEE80211_AC_BK: |
@@ -1050,12 +1054,6 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
1050 | qparam.aifs = 2; | 1054 | qparam.aifs = 2; |
1051 | break; | 1055 | break; |
1052 | } | 1056 | } |
1053 | } else { | ||
1054 | /* Confiure old 802.11b/g medium access rules. */ | ||
1055 | qparam.cw_max = aCWmax; | ||
1056 | qparam.cw_min = aCWmin; | ||
1057 | qparam.txop = 0; | ||
1058 | qparam.aifs = 2; | ||
1059 | } | 1057 | } |
1060 | 1058 | ||
1061 | qparam.uapsd = false; | 1059 | qparam.uapsd = false; |
@@ -1084,8 +1082,8 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | |||
1084 | struct ieee80211_mgmt *mgmt; | 1082 | struct ieee80211_mgmt *mgmt; |
1085 | int err; | 1083 | int err; |
1086 | 1084 | ||
1087 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | 1085 | /* 24 + 6 = header + auth_algo + auth_transaction + status_code */ |
1088 | sizeof(*mgmt) + 6 + extra_len); | 1086 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24 + 6 + extra_len); |
1089 | if (!skb) | 1087 | if (!skb) |
1090 | return; | 1088 | return; |
1091 | 1089 | ||
@@ -2292,3 +2290,63 @@ void ieee80211_radar_detected(struct ieee80211_hw *hw) | |||
2292 | ieee80211_queue_work(hw, &local->radar_detected_work); | 2290 | ieee80211_queue_work(hw, &local->radar_detected_work); |
2293 | } | 2291 | } |
2294 | EXPORT_SYMBOL(ieee80211_radar_detected); | 2292 | EXPORT_SYMBOL(ieee80211_radar_detected); |
2293 | |||
2294 | u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c) | ||
2295 | { | ||
2296 | u32 ret; | ||
2297 | int tmp; | ||
2298 | |||
2299 | switch (c->width) { | ||
2300 | case NL80211_CHAN_WIDTH_20: | ||
2301 | c->width = NL80211_CHAN_WIDTH_20_NOHT; | ||
2302 | ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; | ||
2303 | break; | ||
2304 | case NL80211_CHAN_WIDTH_40: | ||
2305 | c->width = NL80211_CHAN_WIDTH_20; | ||
2306 | c->center_freq1 = c->chan->center_freq; | ||
2307 | ret = IEEE80211_STA_DISABLE_40MHZ | | ||
2308 | IEEE80211_STA_DISABLE_VHT; | ||
2309 | break; | ||
2310 | case NL80211_CHAN_WIDTH_80: | ||
2311 | tmp = (30 + c->chan->center_freq - c->center_freq1)/20; | ||
2312 | /* n_P40 */ | ||
2313 | tmp /= 2; | ||
2314 | /* freq_P40 */ | ||
2315 | c->center_freq1 = c->center_freq1 - 20 + 40 * tmp; | ||
2316 | c->width = NL80211_CHAN_WIDTH_40; | ||
2317 | ret = IEEE80211_STA_DISABLE_VHT; | ||
2318 | break; | ||
2319 | case NL80211_CHAN_WIDTH_80P80: | ||
2320 | c->center_freq2 = 0; | ||
2321 | c->width = NL80211_CHAN_WIDTH_80; | ||
2322 | ret = IEEE80211_STA_DISABLE_80P80MHZ | | ||
2323 | IEEE80211_STA_DISABLE_160MHZ; | ||
2324 | break; | ||
2325 | case NL80211_CHAN_WIDTH_160: | ||
2326 | /* n_P20 */ | ||
2327 | tmp = (70 + c->chan->center_freq - c->center_freq1)/20; | ||
2328 | /* n_P80 */ | ||
2329 | tmp /= 4; | ||
2330 | c->center_freq1 = c->center_freq1 - 40 + 80 * tmp; | ||
2331 | c->width = NL80211_CHAN_WIDTH_80; | ||
2332 | ret = IEEE80211_STA_DISABLE_80P80MHZ | | ||
2333 | IEEE80211_STA_DISABLE_160MHZ; | ||
2334 | break; | ||
2335 | default: | ||
2336 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
2337 | WARN_ON_ONCE(1); | ||
2338 | c->width = NL80211_CHAN_WIDTH_20_NOHT; | ||
2339 | ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; | ||
2340 | break; | ||
2341 | case NL80211_CHAN_WIDTH_5: | ||
2342 | case NL80211_CHAN_WIDTH_10: | ||
2343 | WARN_ON_ONCE(1); | ||
2344 | /* keep c->width */ | ||
2345 | ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; | ||
2346 | break; | ||
2347 | } | ||
2348 | |||
2349 | WARN_ON_ONCE(!cfg80211_chandef_valid(c)); | ||
2350 | |||
2351 | return ret; | ||
2352 | } | ||
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index 97c289414e32..de0112785aae 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c | |||
@@ -185,13 +185,13 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, | |||
185 | if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) { | 185 | if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) { |
186 | vht_cap->cap |= cap_info & | 186 | vht_cap->cap |= cap_info & |
187 | (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | | 187 | (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | |
188 | IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX | | ||
189 | IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX); | 188 | IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX); |
190 | } | 189 | } |
191 | 190 | ||
192 | if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) | 191 | if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) |
193 | vht_cap->cap |= cap_info & | 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 | if (own_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) | 196 | if (own_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) |
197 | vht_cap->cap |= cap_info & | 197 | vht_cap->cap |= cap_info & |
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 50f6195c8b70..16f3c3a7b2c1 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c | |||
@@ -328,6 +328,7 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy, | |||
328 | return cfg80211_get_chans_dfs_required(wiphy, chandef->center_freq2, | 328 | return cfg80211_get_chans_dfs_required(wiphy, chandef->center_freq2, |
329 | width); | 329 | width); |
330 | } | 330 | } |
331 | EXPORT_SYMBOL(cfg80211_chandef_dfs_required); | ||
331 | 332 | ||
332 | static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, | 333 | static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, |
333 | u32 center_freq, u32 bandwidth, | 334 | u32 center_freq, u32 bandwidth, |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 9ad43c619c54..b43efac4efca 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -382,15 +382,6 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
382 | enum cfg80211_chan_mode chanmode, | 382 | enum cfg80211_chan_mode chanmode, |
383 | u8 radar_detect); | 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 | void cfg80211_set_dfs_state(struct wiphy *wiphy, | 385 | void cfg80211_set_dfs_state(struct wiphy *wiphy, |
395 | const struct cfg80211_chan_def *chandef, | 386 | const struct cfg80211_chan_def *chandef, |
396 | enum nl80211_dfs_state dfs_state); | 387 | enum nl80211_dfs_state dfs_state); |
diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c index 90d050036624..454157717efa 100644 --- a/net/wireless/debugfs.c +++ b/net/wireless/debugfs.c | |||
@@ -47,17 +47,19 @@ static int ht_print_chan(struct ieee80211_channel *chan, | |||
47 | return 0; | 47 | return 0; |
48 | 48 | ||
49 | if (chan->flags & IEEE80211_CHAN_DISABLED) | 49 | if (chan->flags & IEEE80211_CHAN_DISABLED) |
50 | return snprintf(buf + offset, | 50 | return scnprintf(buf + offset, |
51 | buf_size - offset, | 51 | buf_size - offset, |
52 | "%d Disabled\n", | 52 | "%d Disabled\n", |
53 | chan->center_freq); | 53 | chan->center_freq); |
54 | 54 | ||
55 | return snprintf(buf + offset, | 55 | return scnprintf(buf + offset, |
56 | buf_size - offset, | 56 | buf_size - offset, |
57 | "%d HT40 %c%c\n", | 57 | "%d HT40 %c%c\n", |
58 | chan->center_freq, | 58 | chan->center_freq, |
59 | (chan->flags & IEEE80211_CHAN_NO_HT40MINUS) ? ' ' : '-', | 59 | (chan->flags & IEEE80211_CHAN_NO_HT40MINUS) ? |
60 | (chan->flags & IEEE80211_CHAN_NO_HT40PLUS) ? ' ' : '+'); | 60 | ' ' : '-', |
61 | (chan->flags & IEEE80211_CHAN_NO_HT40PLUS) ? | ||
62 | ' ' : '+'); | ||
61 | } | 63 | } |
62 | 64 | ||
63 | static ssize_t ht40allow_map_read(struct file *file, | 65 | static ssize_t ht40allow_map_read(struct file *file, |
diff --git a/net/wireless/genregdb.awk b/net/wireless/genregdb.awk index 9392f8cbb901..42ed274e81f4 100644 --- a/net/wireless/genregdb.awk +++ b/net/wireless/genregdb.awk | |||
@@ -46,6 +46,12 @@ BEGIN { | |||
46 | sub(/:/, "", country) | 46 | sub(/:/, "", country) |
47 | printf "static const struct ieee80211_regdomain regdom_%s = {\n", country | 47 | printf "static const struct ieee80211_regdomain regdom_%s = {\n", country |
48 | printf "\t.alpha2 = \"%s\",\n", country | 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 | printf "\t.reg_rules = {\n" | 55 | printf "\t.reg_rules = {\n" |
50 | active = 1 | 56 | active = 1 |
51 | regdb = regdb "\t®dom_" country ",\n" | 57 | regdb = regdb "\t®dom_" country ",\n" |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 626dc3b5fd8d..cbbef88a8ebd 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -5591,6 +5591,9 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, | |||
5591 | if (err) | 5591 | if (err) |
5592 | return err; | 5592 | return err; |
5593 | 5593 | ||
5594 | if (netif_carrier_ok(dev)) | ||
5595 | return -EBUSY; | ||
5596 | |||
5594 | if (wdev->cac_started) | 5597 | if (wdev->cac_started) |
5595 | return -EBUSY; | 5598 | return -EBUSY; |
5596 | 5599 | ||
@@ -5634,15 +5637,26 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) | |||
5634 | static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1]; | 5637 | static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1]; |
5635 | u8 radar_detect_width = 0; | 5638 | u8 radar_detect_width = 0; |
5636 | int err; | 5639 | int err; |
5640 | bool need_new_beacon = false; | ||
5637 | 5641 | ||
5638 | if (!rdev->ops->channel_switch || | 5642 | if (!rdev->ops->channel_switch || |
5639 | !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)) | 5643 | !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)) |
5640 | return -EOPNOTSUPP; | 5644 | return -EOPNOTSUPP; |
5641 | 5645 | ||
5642 | /* may add IBSS support later */ | 5646 | switch (dev->ieee80211_ptr->iftype) { |
5643 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 5647 | case NL80211_IFTYPE_AP: |
5644 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) | 5648 | case NL80211_IFTYPE_P2P_GO: |
5649 | need_new_beacon = true; | ||
5650 | |||
5651 | /* useless if AP is not running */ | ||
5652 | if (!wdev->beacon_interval) | ||
5653 | return -EINVAL; | ||
5654 | break; | ||
5655 | case NL80211_IFTYPE_ADHOC: | ||
5656 | break; | ||
5657 | default: | ||
5645 | return -EOPNOTSUPP; | 5658 | return -EOPNOTSUPP; |
5659 | } | ||
5646 | 5660 | ||
5647 | memset(¶ms, 0, sizeof(params)); | 5661 | memset(¶ms, 0, sizeof(params)); |
5648 | 5662 | ||
@@ -5651,15 +5665,16 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) | |||
5651 | return -EINVAL; | 5665 | return -EINVAL; |
5652 | 5666 | ||
5653 | /* only important for AP, IBSS and mesh create IEs internally */ | 5667 | /* only important for AP, IBSS and mesh create IEs internally */ |
5654 | if (!info->attrs[NL80211_ATTR_CSA_IES]) | 5668 | if (need_new_beacon && |
5655 | return -EINVAL; | 5669 | (!info->attrs[NL80211_ATTR_CSA_IES] || |
5656 | 5670 | !info->attrs[NL80211_ATTR_CSA_C_OFF_BEACON])) | |
5657 | /* useless if AP is not running */ | ||
5658 | if (!wdev->beacon_interval) | ||
5659 | return -EINVAL; | 5671 | return -EINVAL; |
5660 | 5672 | ||
5661 | params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]); | 5673 | params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]); |
5662 | 5674 | ||
5675 | if (!need_new_beacon) | ||
5676 | goto skip_beacons; | ||
5677 | |||
5663 | err = nl80211_parse_beacon(info->attrs, ¶ms.beacon_after); | 5678 | err = nl80211_parse_beacon(info->attrs, ¶ms.beacon_after); |
5664 | if (err) | 5679 | if (err) |
5665 | return err; | 5680 | return err; |
@@ -5699,6 +5714,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) | |||
5699 | return -EINVAL; | 5714 | return -EINVAL; |
5700 | } | 5715 | } |
5701 | 5716 | ||
5717 | skip_beacons: | ||
5702 | err = nl80211_parse_chandef(rdev, info, ¶ms.chandef); | 5718 | err = nl80211_parse_chandef(rdev, info, ¶ms.chandef); |
5703 | if (err) | 5719 | if (err) |
5704 | return err; | 5720 | return err; |
@@ -5706,12 +5722,17 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) | |||
5706 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef)) | 5722 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef)) |
5707 | return -EINVAL; | 5723 | return -EINVAL; |
5708 | 5724 | ||
5709 | err = cfg80211_chandef_dfs_required(wdev->wiphy, ¶ms.chandef); | 5725 | /* DFS channels are only supported for AP/P2P GO ... for now. */ |
5710 | if (err < 0) { | 5726 | if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP || |
5711 | return err; | 5727 | dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) { |
5712 | } else if (err) { | 5728 | err = cfg80211_chandef_dfs_required(wdev->wiphy, |
5713 | radar_detect_width = BIT(params.chandef.width); | 5729 | ¶ms.chandef); |
5714 | params.radar_required = true; | 5730 | if (err < 0) { |
5731 | return err; | ||
5732 | } else if (err) { | ||
5733 | radar_detect_width = BIT(params.chandef.width); | ||
5734 | params.radar_required = true; | ||
5735 | } | ||
5715 | } | 5736 | } |
5716 | 5737 | ||
5717 | err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, | 5738 | err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, |
@@ -10740,7 +10761,8 @@ void cfg80211_ch_switch_notify(struct net_device *dev, | |||
10740 | wdev_lock(wdev); | 10761 | wdev_lock(wdev); |
10741 | 10762 | ||
10742 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && | 10763 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && |
10743 | wdev->iftype != NL80211_IFTYPE_P2P_GO)) | 10764 | wdev->iftype != NL80211_IFTYPE_P2P_GO && |
10765 | wdev->iftype != NL80211_IFTYPE_ADHOC)) | ||
10744 | goto out; | 10766 | goto out; |
10745 | 10767 | ||
10746 | wdev->channel = chandef->chan; | 10768 | wdev->channel = chandef->chan; |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index de06d5d1287f..d62cb1e91475 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -172,11 +172,21 @@ static const struct ieee80211_regdomain world_regdom = { | |||
172 | NL80211_RRF_NO_IBSS | | 172 | NL80211_RRF_NO_IBSS | |
173 | NL80211_RRF_NO_OFDM), | 173 | NL80211_RRF_NO_OFDM), |
174 | /* IEEE 802.11a, channel 36..48 */ | 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 | NL80211_RRF_PASSIVE_SCAN | | 176 | NL80211_RRF_PASSIVE_SCAN | |
177 | NL80211_RRF_NO_IBSS), | 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 | /* IEEE 802.11a, channel 149..165 */ | 191 | /* IEEE 802.11a, channel 149..165 */ |
182 | REG_RULE(5745-10, 5825+10, 80, 6, 20, | 192 | REG_RULE(5745-10, 5825+10, 80, 6, 20, |
diff --git a/net/wireless/util.c b/net/wireless/util.c index ce090c1c5e4f..3c8be6104ba4 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <net/cfg80211.h> | 10 | #include <net/cfg80211.h> |
11 | #include <net/ip.h> | 11 | #include <net/ip.h> |
12 | #include <net/dsfield.h> | 12 | #include <net/dsfield.h> |
13 | #include <linux/if_vlan.h> | ||
13 | #include "core.h" | 14 | #include "core.h" |
14 | #include "rdev-ops.h" | 15 | #include "rdev-ops.h" |
15 | 16 | ||
@@ -691,6 +692,7 @@ EXPORT_SYMBOL(ieee80211_amsdu_to_8023s); | |||
691 | unsigned int cfg80211_classify8021d(struct sk_buff *skb) | 692 | unsigned int cfg80211_classify8021d(struct sk_buff *skb) |
692 | { | 693 | { |
693 | unsigned int dscp; | 694 | unsigned int dscp; |
695 | unsigned char vlan_priority; | ||
694 | 696 | ||
695 | /* skb->priority values from 256->263 are magic values to | 697 | /* skb->priority values from 256->263 are magic values to |
696 | * directly indicate a specific 802.1d priority. This is used | 698 | * directly indicate a specific 802.1d priority. This is used |
@@ -700,6 +702,13 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb) | |||
700 | if (skb->priority >= 256 && skb->priority <= 263) | 702 | if (skb->priority >= 256 && skb->priority <= 263) |
701 | return skb->priority - 256; | 703 | return skb->priority - 256; |
702 | 704 | ||
705 | if (vlan_tx_tag_present(skb)) { | ||
706 | vlan_priority = (vlan_tx_tag_get(skb) & VLAN_PRIO_MASK) | ||
707 | >> VLAN_PRIO_SHIFT; | ||
708 | if (vlan_priority > 0) | ||
709 | return vlan_priority; | ||
710 | } | ||
711 | |||
703 | switch (skb->protocol) { | 712 | switch (skb->protocol) { |
704 | case htons(ETH_P_IP): | 713 | case htons(ETH_P_IP): |
705 | dscp = ipv4_get_dsfield(ip_hdr(skb)) & 0xfc; | 714 | dscp = ipv4_get_dsfield(ip_hdr(skb)) & 0xfc; |