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