diff options
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9002_calib.c | 43 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_calib.c | 18 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 388 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_paprd.c | 17 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_phy.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/calib.c | 118 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/calib.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_main.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.c | 25 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.h | 25 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 104 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/recv.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 36 |
15 files changed, 618 insertions, 195 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index dabafb874c36..fe7418aefc4a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c | |||
@@ -63,6 +63,7 @@ static bool ar9002_hw_per_calibration(struct ath_hw *ah, | |||
63 | u8 rxchainmask, | 63 | u8 rxchainmask, |
64 | struct ath9k_cal_list *currCal) | 64 | struct ath9k_cal_list *currCal) |
65 | { | 65 | { |
66 | struct ath9k_hw_cal_data *caldata = ah->caldata; | ||
66 | bool iscaldone = false; | 67 | bool iscaldone = false; |
67 | 68 | ||
68 | if (currCal->calState == CAL_RUNNING) { | 69 | if (currCal->calState == CAL_RUNNING) { |
@@ -81,14 +82,14 @@ static bool ar9002_hw_per_calibration(struct ath_hw *ah, | |||
81 | } | 82 | } |
82 | 83 | ||
83 | currCal->calData->calPostProc(ah, numChains); | 84 | currCal->calData->calPostProc(ah, numChains); |
84 | ichan->CalValid |= currCal->calData->calType; | 85 | caldata->CalValid |= currCal->calData->calType; |
85 | currCal->calState = CAL_DONE; | 86 | currCal->calState = CAL_DONE; |
86 | iscaldone = true; | 87 | iscaldone = true; |
87 | } else { | 88 | } else { |
88 | ar9002_hw_setup_calibration(ah, currCal); | 89 | ar9002_hw_setup_calibration(ah, currCal); |
89 | } | 90 | } |
90 | } | 91 | } |
91 | } else if (!(ichan->CalValid & currCal->calData->calType)) { | 92 | } else if (!(caldata->CalValid & currCal->calData->calType)) { |
92 | ath9k_hw_reset_calibration(ah, currCal); | 93 | ath9k_hw_reset_calibration(ah, currCal); |
93 | } | 94 | } |
94 | 95 | ||
@@ -686,8 +687,13 @@ static bool ar9002_hw_calibrate(struct ath_hw *ah, | |||
686 | { | 687 | { |
687 | bool iscaldone = true; | 688 | bool iscaldone = true; |
688 | struct ath9k_cal_list *currCal = ah->cal_list_curr; | 689 | struct ath9k_cal_list *currCal = ah->cal_list_curr; |
690 | bool nfcal, nfcal_pending = false; | ||
689 | 691 | ||
690 | if (currCal && | 692 | nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF); |
693 | if (ah->caldata) | ||
694 | nfcal_pending = ah->caldata->nfcal_pending; | ||
695 | |||
696 | if (currCal && !nfcal && | ||
691 | (currCal->calState == CAL_RUNNING || | 697 | (currCal->calState == CAL_RUNNING || |
692 | currCal->calState == CAL_WAITING)) { | 698 | currCal->calState == CAL_WAITING)) { |
693 | iscaldone = ar9002_hw_per_calibration(ah, chan, | 699 | iscaldone = ar9002_hw_per_calibration(ah, chan, |
@@ -703,7 +709,7 @@ static bool ar9002_hw_calibrate(struct ath_hw *ah, | |||
703 | } | 709 | } |
704 | 710 | ||
705 | /* Do NF cal only at longer intervals */ | 711 | /* Do NF cal only at longer intervals */ |
706 | if (longcal) { | 712 | if (longcal || nfcal_pending) { |
707 | /* Do periodic PAOffset Cal */ | 713 | /* Do periodic PAOffset Cal */ |
708 | ar9002_hw_pa_cal(ah, false); | 714 | ar9002_hw_pa_cal(ah, false); |
709 | ar9002_hw_olc_temp_compensation(ah); | 715 | ar9002_hw_olc_temp_compensation(ah); |
@@ -712,16 +718,18 @@ static bool ar9002_hw_calibrate(struct ath_hw *ah, | |||
712 | * Get the value from the previous NF cal and update | 718 | * Get the value from the previous NF cal and update |
713 | * history buffer. | 719 | * history buffer. |
714 | */ | 720 | */ |
715 | ath9k_hw_getnf(ah, chan); | 721 | if (ath9k_hw_getnf(ah, chan)) { |
716 | 722 | /* | |
717 | /* | 723 | * Load the NF from history buffer of the current |
718 | * Load the NF from history buffer of the current channel. | 724 | * channel. |
719 | * NF is slow time-variant, so it is OK to use a historical | 725 | * NF is slow time-variant, so it is OK to use a |
720 | * value. | 726 | * historical value. |
721 | */ | 727 | */ |
722 | ath9k_hw_loadnf(ah, ah->curchan); | 728 | ath9k_hw_loadnf(ah, ah->curchan); |
729 | } | ||
723 | 730 | ||
724 | ath9k_hw_start_nfcal(ah); | 731 | if (longcal) |
732 | ath9k_hw_start_nfcal(ah, false); | ||
725 | } | 733 | } |
726 | 734 | ||
727 | return iscaldone; | 735 | return iscaldone; |
@@ -869,8 +877,10 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
869 | ar9002_hw_pa_cal(ah, true); | 877 | ar9002_hw_pa_cal(ah, true); |
870 | 878 | ||
871 | /* Do NF Calibration after DC offset and other calibrations */ | 879 | /* Do NF Calibration after DC offset and other calibrations */ |
872 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, | 880 | ath9k_hw_start_nfcal(ah, true); |
873 | REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF); | 881 | |
882 | if (ah->caldata) | ||
883 | ah->caldata->nfcal_pending = true; | ||
874 | 884 | ||
875 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; | 885 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; |
876 | 886 | ||
@@ -901,7 +911,8 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
901 | ath9k_hw_reset_calibration(ah, ah->cal_list_curr); | 911 | ath9k_hw_reset_calibration(ah, ah->cal_list_curr); |
902 | } | 912 | } |
903 | 913 | ||
904 | chan->CalValid = 0; | 914 | if (ah->caldata) |
915 | ah->caldata->CalValid = 0; | ||
905 | 916 | ||
906 | return true; | 917 | return true; |
907 | } | 918 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 5a0650399136..4674ea8c9c99 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
@@ -68,6 +68,7 @@ static bool ar9003_hw_per_calibration(struct ath_hw *ah, | |||
68 | u8 rxchainmask, | 68 | u8 rxchainmask, |
69 | struct ath9k_cal_list *currCal) | 69 | struct ath9k_cal_list *currCal) |
70 | { | 70 | { |
71 | struct ath9k_hw_cal_data *caldata = ah->caldata; | ||
71 | /* Cal is assumed not done until explicitly set below */ | 72 | /* Cal is assumed not done until explicitly set below */ |
72 | bool iscaldone = false; | 73 | bool iscaldone = false; |
73 | 74 | ||
@@ -95,7 +96,7 @@ static bool ar9003_hw_per_calibration(struct ath_hw *ah, | |||
95 | currCal->calData->calPostProc(ah, numChains); | 96 | currCal->calData->calPostProc(ah, numChains); |
96 | 97 | ||
97 | /* Calibration has finished. */ | 98 | /* Calibration has finished. */ |
98 | ichan->CalValid |= currCal->calData->calType; | 99 | caldata->CalValid |= currCal->calData->calType; |
99 | currCal->calState = CAL_DONE; | 100 | currCal->calState = CAL_DONE; |
100 | iscaldone = true; | 101 | iscaldone = true; |
101 | } else { | 102 | } else { |
@@ -106,7 +107,7 @@ static bool ar9003_hw_per_calibration(struct ath_hw *ah, | |||
106 | ar9003_hw_setup_calibration(ah, currCal); | 107 | ar9003_hw_setup_calibration(ah, currCal); |
107 | } | 108 | } |
108 | } | 109 | } |
109 | } else if (!(ichan->CalValid & currCal->calData->calType)) { | 110 | } else if (!(caldata->CalValid & currCal->calData->calType)) { |
110 | /* If current cal is marked invalid in channel, kick it off */ | 111 | /* If current cal is marked invalid in channel, kick it off */ |
111 | ath9k_hw_reset_calibration(ah, currCal); | 112 | ath9k_hw_reset_calibration(ah, currCal); |
112 | } | 113 | } |
@@ -149,6 +150,12 @@ static bool ar9003_hw_calibrate(struct ath_hw *ah, | |||
149 | /* Do NF cal only at longer intervals */ | 150 | /* Do NF cal only at longer intervals */ |
150 | if (longcal) { | 151 | if (longcal) { |
151 | /* | 152 | /* |
153 | * Get the value from the previous NF cal and update | ||
154 | * history buffer. | ||
155 | */ | ||
156 | ath9k_hw_getnf(ah, chan); | ||
157 | |||
158 | /* | ||
152 | * Load the NF from history buffer of the current channel. | 159 | * Load the NF from history buffer of the current channel. |
153 | * NF is slow time-variant, so it is OK to use a historical | 160 | * NF is slow time-variant, so it is OK to use a historical |
154 | * value. | 161 | * value. |
@@ -156,7 +163,7 @@ static bool ar9003_hw_calibrate(struct ath_hw *ah, | |||
156 | ath9k_hw_loadnf(ah, ah->curchan); | 163 | ath9k_hw_loadnf(ah, ah->curchan); |
157 | 164 | ||
158 | /* start NF calibration, without updating BB NF register */ | 165 | /* start NF calibration, without updating BB NF register */ |
159 | ath9k_hw_start_nfcal(ah); | 166 | ath9k_hw_start_nfcal(ah, false); |
160 | } | 167 | } |
161 | 168 | ||
162 | return iscaldone; | 169 | return iscaldone; |
@@ -762,6 +769,8 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
762 | /* Revert chainmasks to their original values before NF cal */ | 769 | /* Revert chainmasks to their original values before NF cal */ |
763 | ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); | 770 | ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); |
764 | 771 | ||
772 | ath9k_hw_start_nfcal(ah, true); | ||
773 | |||
765 | /* Initialize list pointers */ | 774 | /* Initialize list pointers */ |
766 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; | 775 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; |
767 | 776 | ||
@@ -785,7 +794,8 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
785 | if (ah->cal_list_curr) | 794 | if (ah->cal_list_curr) |
786 | ath9k_hw_reset_calibration(ah, ah->cal_list_curr); | 795 | ath9k_hw_reset_calibration(ah, ah->cal_list_curr); |
787 | 796 | ||
788 | chan->CalValid = 0; | 797 | if (ah->caldata) |
798 | ah->caldata->CalValid = 0; | ||
789 | 799 | ||
790 | return true; | 800 | return true; |
791 | } | 801 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index ace8d2678b18..b883b174385b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -41,6 +41,20 @@ | |||
41 | #define LE16(x) __constant_cpu_to_le16(x) | 41 | #define LE16(x) __constant_cpu_to_le16(x) |
42 | #define LE32(x) __constant_cpu_to_le32(x) | 42 | #define LE32(x) __constant_cpu_to_le32(x) |
43 | 43 | ||
44 | /* Local defines to distinguish between extension and control CTL's */ | ||
45 | #define EXT_ADDITIVE (0x8000) | ||
46 | #define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE) | ||
47 | #define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE) | ||
48 | #define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE) | ||
49 | #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ | ||
50 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*2 */ | ||
51 | #define PWRINCR_3_TO_1_CHAIN 9 /* 10*log(3)*2 */ | ||
52 | #define PWRINCR_3_TO_2_CHAIN 3 /* floor(10*log(3/2)*2) */ | ||
53 | #define PWRINCR_2_TO_1_CHAIN 6 /* 10*log(2)*2 */ | ||
54 | |||
55 | #define SUB_NUM_CTL_MODES_AT_5G_40 2 /* excluding HT40, EXT-OFDM */ | ||
56 | #define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */ | ||
57 | |||
44 | static const struct ar9300_eeprom ar9300_default = { | 58 | static const struct ar9300_eeprom ar9300_default = { |
45 | .eepromVersion = 2, | 59 | .eepromVersion = 2, |
46 | .templateVersion = 2, | 60 | .templateVersion = 2, |
@@ -609,6 +623,14 @@ static const struct ar9300_eeprom ar9300_default = { | |||
609 | } | 623 | } |
610 | }; | 624 | }; |
611 | 625 | ||
626 | static u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz) | ||
627 | { | ||
628 | if (fbin == AR9300_BCHAN_UNUSED) | ||
629 | return fbin; | ||
630 | |||
631 | return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); | ||
632 | } | ||
633 | |||
612 | static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah) | 634 | static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah) |
613 | { | 635 | { |
614 | return 0; | 636 | return 0; |
@@ -1417,9 +1439,9 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray) | |||
1417 | #undef POW_SM | 1439 | #undef POW_SM |
1418 | } | 1440 | } |
1419 | 1441 | ||
1420 | static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq) | 1442 | static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq, |
1443 | u8 *targetPowerValT2) | ||
1421 | { | 1444 | { |
1422 | u8 targetPowerValT2[ar9300RateSize]; | ||
1423 | /* XXX: hard code for now, need to get from eeprom struct */ | 1445 | /* XXX: hard code for now, need to get from eeprom struct */ |
1424 | u8 ht40PowerIncForPdadc = 0; | 1446 | u8 ht40PowerIncForPdadc = 0; |
1425 | bool is2GHz = false; | 1447 | bool is2GHz = false; |
@@ -1553,9 +1575,6 @@ static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq) | |||
1553 | "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]); | 1575 | "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]); |
1554 | i++; | 1576 | i++; |
1555 | } | 1577 | } |
1556 | |||
1557 | /* Write target power array to registers */ | ||
1558 | ar9003_hw_tx_power_regwrite(ah, targetPowerValT2); | ||
1559 | } | 1578 | } |
1560 | 1579 | ||
1561 | static int ar9003_hw_cal_pier_get(struct ath_hw *ah, | 1580 | static int ar9003_hw_cal_pier_get(struct ath_hw *ah, |
@@ -1799,14 +1818,369 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) | |||
1799 | return 0; | 1818 | return 0; |
1800 | } | 1819 | } |
1801 | 1820 | ||
1821 | static u16 ar9003_hw_get_direct_edge_power(struct ar9300_eeprom *eep, | ||
1822 | int idx, | ||
1823 | int edge, | ||
1824 | bool is2GHz) | ||
1825 | { | ||
1826 | struct cal_ctl_data_2g *ctl_2g = eep->ctlPowerData_2G; | ||
1827 | struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G; | ||
1828 | |||
1829 | if (is2GHz) | ||
1830 | return ctl_2g[idx].ctlEdges[edge].tPower; | ||
1831 | else | ||
1832 | return ctl_5g[idx].ctlEdges[edge].tPower; | ||
1833 | } | ||
1834 | |||
1835 | static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep, | ||
1836 | int idx, | ||
1837 | unsigned int edge, | ||
1838 | u16 freq, | ||
1839 | bool is2GHz) | ||
1840 | { | ||
1841 | struct cal_ctl_data_2g *ctl_2g = eep->ctlPowerData_2G; | ||
1842 | struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G; | ||
1843 | |||
1844 | u8 *ctl_freqbin = is2GHz ? | ||
1845 | &eep->ctl_freqbin_2G[idx][0] : | ||
1846 | &eep->ctl_freqbin_5G[idx][0]; | ||
1847 | |||
1848 | if (is2GHz) { | ||
1849 | if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 1) < freq && | ||
1850 | ctl_2g[idx].ctlEdges[edge - 1].flag) | ||
1851 | return ctl_2g[idx].ctlEdges[edge - 1].tPower; | ||
1852 | } else { | ||
1853 | if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 0) < freq && | ||
1854 | ctl_5g[idx].ctlEdges[edge - 1].flag) | ||
1855 | return ctl_5g[idx].ctlEdges[edge - 1].tPower; | ||
1856 | } | ||
1857 | |||
1858 | return AR9300_MAX_RATE_POWER; | ||
1859 | } | ||
1860 | |||
1861 | /* | ||
1862 | * Find the maximum conformance test limit for the given channel and CTL info | ||
1863 | */ | ||
1864 | static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep, | ||
1865 | u16 freq, int idx, bool is2GHz) | ||
1866 | { | ||
1867 | u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER; | ||
1868 | u8 *ctl_freqbin = is2GHz ? | ||
1869 | &eep->ctl_freqbin_2G[idx][0] : | ||
1870 | &eep->ctl_freqbin_5G[idx][0]; | ||
1871 | u16 num_edges = is2GHz ? | ||
1872 | AR9300_NUM_BAND_EDGES_2G : AR9300_NUM_BAND_EDGES_5G; | ||
1873 | unsigned int edge; | ||
1874 | |||
1875 | /* Get the edge power */ | ||
1876 | for (edge = 0; | ||
1877 | (edge < num_edges) && (ctl_freqbin[edge] != AR9300_BCHAN_UNUSED); | ||
1878 | edge++) { | ||
1879 | /* | ||
1880 | * If there's an exact channel match or an inband flag set | ||
1881 | * on the lower channel use the given rdEdgePower | ||
1882 | */ | ||
1883 | if (freq == ath9k_hw_fbin2freq(ctl_freqbin[edge], is2GHz)) { | ||
1884 | twiceMaxEdgePower = | ||
1885 | ar9003_hw_get_direct_edge_power(eep, idx, | ||
1886 | edge, is2GHz); | ||
1887 | break; | ||
1888 | } else if ((edge > 0) && | ||
1889 | (freq < ath9k_hw_fbin2freq(ctl_freqbin[edge], | ||
1890 | is2GHz))) { | ||
1891 | twiceMaxEdgePower = | ||
1892 | ar9003_hw_get_indirect_edge_power(eep, idx, | ||
1893 | edge, freq, | ||
1894 | is2GHz); | ||
1895 | /* | ||
1896 | * Leave loop - no more affecting edges possible in | ||
1897 | * this monotonic increasing list | ||
1898 | */ | ||
1899 | break; | ||
1900 | } | ||
1901 | } | ||
1902 | return twiceMaxEdgePower; | ||
1903 | } | ||
1904 | |||
1905 | static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, | ||
1906 | struct ath9k_channel *chan, | ||
1907 | u8 *pPwrArray, u16 cfgCtl, | ||
1908 | u8 twiceAntennaReduction, | ||
1909 | u8 twiceMaxRegulatoryPower, | ||
1910 | u16 powerLimit) | ||
1911 | { | ||
1912 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | ||
1913 | struct ath_common *common = ath9k_hw_common(ah); | ||
1914 | struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep; | ||
1915 | u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER; | ||
1916 | static const u16 tpScaleReductionTable[5] = { | ||
1917 | 0, 3, 6, 9, AR9300_MAX_RATE_POWER | ||
1918 | }; | ||
1919 | int i; | ||
1920 | int16_t twiceLargestAntenna; | ||
1921 | u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; | ||
1922 | u16 ctlModesFor11a[] = { | ||
1923 | CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 | ||
1924 | }; | ||
1925 | u16 ctlModesFor11g[] = { | ||
1926 | CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, | ||
1927 | CTL_11G_EXT, CTL_2GHT40 | ||
1928 | }; | ||
1929 | u16 numCtlModes, *pCtlMode, ctlMode, freq; | ||
1930 | struct chan_centers centers; | ||
1931 | u8 *ctlIndex; | ||
1932 | u8 ctlNum; | ||
1933 | u16 twiceMinEdgePower; | ||
1934 | bool is2ghz = IS_CHAN_2GHZ(chan); | ||
1935 | |||
1936 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
1937 | |||
1938 | /* Compute TxPower reduction due to Antenna Gain */ | ||
1939 | if (is2ghz) | ||
1940 | twiceLargestAntenna = pEepData->modalHeader2G.antennaGain; | ||
1941 | else | ||
1942 | twiceLargestAntenna = pEepData->modalHeader5G.antennaGain; | ||
1943 | |||
1944 | twiceLargestAntenna = (int16_t)min((twiceAntennaReduction) - | ||
1945 | twiceLargestAntenna, 0); | ||
1946 | |||
1947 | /* | ||
1948 | * scaledPower is the minimum of the user input power level | ||
1949 | * and the regulatory allowed power level | ||
1950 | */ | ||
1951 | maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; | ||
1952 | |||
1953 | if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) { | ||
1954 | maxRegAllowedPower -= | ||
1955 | (tpScaleReductionTable[(regulatory->tp_scale)] * 2); | ||
1956 | } | ||
1957 | |||
1958 | scaledPower = min(powerLimit, maxRegAllowedPower); | ||
1959 | |||
1960 | /* | ||
1961 | * Reduce scaled Power by number of chains active to get | ||
1962 | * to per chain tx power level | ||
1963 | */ | ||
1964 | switch (ar5416_get_ntxchains(ah->txchainmask)) { | ||
1965 | case 1: | ||
1966 | break; | ||
1967 | case 2: | ||
1968 | scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; | ||
1969 | break; | ||
1970 | case 3: | ||
1971 | scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; | ||
1972 | break; | ||
1973 | } | ||
1974 | |||
1975 | scaledPower = max((u16)0, scaledPower); | ||
1976 | |||
1977 | /* | ||
1978 | * Get target powers from EEPROM - our baseline for TX Power | ||
1979 | */ | ||
1980 | if (is2ghz) { | ||
1981 | /* Setup for CTL modes */ | ||
1982 | /* CTL_11B, CTL_11G, CTL_2GHT20 */ | ||
1983 | numCtlModes = | ||
1984 | ARRAY_SIZE(ctlModesFor11g) - | ||
1985 | SUB_NUM_CTL_MODES_AT_2G_40; | ||
1986 | pCtlMode = ctlModesFor11g; | ||
1987 | if (IS_CHAN_HT40(chan)) | ||
1988 | /* All 2G CTL's */ | ||
1989 | numCtlModes = ARRAY_SIZE(ctlModesFor11g); | ||
1990 | } else { | ||
1991 | /* Setup for CTL modes */ | ||
1992 | /* CTL_11A, CTL_5GHT20 */ | ||
1993 | numCtlModes = ARRAY_SIZE(ctlModesFor11a) - | ||
1994 | SUB_NUM_CTL_MODES_AT_5G_40; | ||
1995 | pCtlMode = ctlModesFor11a; | ||
1996 | if (IS_CHAN_HT40(chan)) | ||
1997 | /* All 5G CTL's */ | ||
1998 | numCtlModes = ARRAY_SIZE(ctlModesFor11a); | ||
1999 | } | ||
2000 | |||
2001 | /* | ||
2002 | * For MIMO, need to apply regulatory caps individually across | ||
2003 | * dynamically running modes: CCK, OFDM, HT20, HT40 | ||
2004 | * | ||
2005 | * The outer loop walks through each possible applicable runtime mode. | ||
2006 | * The inner loop walks through each ctlIndex entry in EEPROM. | ||
2007 | * The ctl value is encoded as [7:4] == test group, [3:0] == test mode. | ||
2008 | */ | ||
2009 | for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { | ||
2010 | bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || | ||
2011 | (pCtlMode[ctlMode] == CTL_2GHT40); | ||
2012 | if (isHt40CtlMode) | ||
2013 | freq = centers.synth_center; | ||
2014 | else if (pCtlMode[ctlMode] & EXT_ADDITIVE) | ||
2015 | freq = centers.ext_center; | ||
2016 | else | ||
2017 | freq = centers.ctl_center; | ||
2018 | |||
2019 | ath_print(common, ATH_DBG_REGULATORY, | ||
2020 | "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, " | ||
2021 | "EXT_ADDITIVE %d\n", | ||
2022 | ctlMode, numCtlModes, isHt40CtlMode, | ||
2023 | (pCtlMode[ctlMode] & EXT_ADDITIVE)); | ||
2024 | |||
2025 | /* walk through each CTL index stored in EEPROM */ | ||
2026 | if (is2ghz) { | ||
2027 | ctlIndex = pEepData->ctlIndex_2G; | ||
2028 | ctlNum = AR9300_NUM_CTLS_2G; | ||
2029 | } else { | ||
2030 | ctlIndex = pEepData->ctlIndex_5G; | ||
2031 | ctlNum = AR9300_NUM_CTLS_5G; | ||
2032 | } | ||
2033 | |||
2034 | for (i = 0; (i < ctlNum) && ctlIndex[i]; i++) { | ||
2035 | ath_print(common, ATH_DBG_REGULATORY, | ||
2036 | "LOOP-Ctlidx %d: cfgCtl 0x%2.2x " | ||
2037 | "pCtlMode 0x%2.2x ctlIndex 0x%2.2x " | ||
2038 | "chan %dn", | ||
2039 | i, cfgCtl, pCtlMode[ctlMode], ctlIndex[i], | ||
2040 | chan->channel); | ||
2041 | |||
2042 | /* | ||
2043 | * compare test group from regulatory | ||
2044 | * channel list with test mode from pCtlMode | ||
2045 | * list | ||
2046 | */ | ||
2047 | if ((((cfgCtl & ~CTL_MODE_M) | | ||
2048 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
2049 | ctlIndex[i]) || | ||
2050 | (((cfgCtl & ~CTL_MODE_M) | | ||
2051 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
2052 | ((ctlIndex[i] & CTL_MODE_M) | | ||
2053 | SD_NO_CTL))) { | ||
2054 | twiceMinEdgePower = | ||
2055 | ar9003_hw_get_max_edge_power(pEepData, | ||
2056 | freq, i, | ||
2057 | is2ghz); | ||
2058 | |||
2059 | if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) | ||
2060 | /* | ||
2061 | * Find the minimum of all CTL | ||
2062 | * edge powers that apply to | ||
2063 | * this channel | ||
2064 | */ | ||
2065 | twiceMaxEdgePower = | ||
2066 | min(twiceMaxEdgePower, | ||
2067 | twiceMinEdgePower); | ||
2068 | else { | ||
2069 | /* specific */ | ||
2070 | twiceMaxEdgePower = | ||
2071 | twiceMinEdgePower; | ||
2072 | break; | ||
2073 | } | ||
2074 | } | ||
2075 | } | ||
2076 | |||
2077 | minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); | ||
2078 | |||
2079 | ath_print(common, ATH_DBG_REGULATORY, | ||
2080 | "SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d " | ||
2081 | "sP %d minCtlPwr %d\n", | ||
2082 | ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower, | ||
2083 | scaledPower, minCtlPower); | ||
2084 | |||
2085 | /* Apply ctl mode to correct target power set */ | ||
2086 | switch (pCtlMode[ctlMode]) { | ||
2087 | case CTL_11B: | ||
2088 | for (i = ALL_TARGET_LEGACY_1L_5L; | ||
2089 | i <= ALL_TARGET_LEGACY_11S; i++) | ||
2090 | pPwrArray[i] = | ||
2091 | (u8)min((u16)pPwrArray[i], | ||
2092 | minCtlPower); | ||
2093 | break; | ||
2094 | case CTL_11A: | ||
2095 | case CTL_11G: | ||
2096 | for (i = ALL_TARGET_LEGACY_6_24; | ||
2097 | i <= ALL_TARGET_LEGACY_54; i++) | ||
2098 | pPwrArray[i] = | ||
2099 | (u8)min((u16)pPwrArray[i], | ||
2100 | minCtlPower); | ||
2101 | break; | ||
2102 | case CTL_5GHT20: | ||
2103 | case CTL_2GHT20: | ||
2104 | for (i = ALL_TARGET_HT20_0_8_16; | ||
2105 | i <= ALL_TARGET_HT20_21; i++) | ||
2106 | pPwrArray[i] = | ||
2107 | (u8)min((u16)pPwrArray[i], | ||
2108 | minCtlPower); | ||
2109 | pPwrArray[ALL_TARGET_HT20_22] = | ||
2110 | (u8)min((u16)pPwrArray[ALL_TARGET_HT20_22], | ||
2111 | minCtlPower); | ||
2112 | pPwrArray[ALL_TARGET_HT20_23] = | ||
2113 | (u8)min((u16)pPwrArray[ALL_TARGET_HT20_23], | ||
2114 | minCtlPower); | ||
2115 | break; | ||
2116 | case CTL_5GHT40: | ||
2117 | case CTL_2GHT40: | ||
2118 | for (i = ALL_TARGET_HT40_0_8_16; | ||
2119 | i <= ALL_TARGET_HT40_23; i++) | ||
2120 | pPwrArray[i] = | ||
2121 | (u8)min((u16)pPwrArray[i], | ||
2122 | minCtlPower); | ||
2123 | break; | ||
2124 | default: | ||
2125 | break; | ||
2126 | } | ||
2127 | } /* end ctl mode checking */ | ||
2128 | } | ||
2129 | |||
1802 | static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah, | 2130 | static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah, |
1803 | struct ath9k_channel *chan, u16 cfgCtl, | 2131 | struct ath9k_channel *chan, u16 cfgCtl, |
1804 | u8 twiceAntennaReduction, | 2132 | u8 twiceAntennaReduction, |
1805 | u8 twiceMaxRegulatoryPower, | 2133 | u8 twiceMaxRegulatoryPower, |
1806 | u8 powerLimit) | 2134 | u8 powerLimit) |
1807 | { | 2135 | { |
1808 | ah->txpower_limit = powerLimit; | 2136 | struct ath_common *common = ath9k_hw_common(ah); |
1809 | ar9003_hw_set_target_power_eeprom(ah, chan->channel); | 2137 | u8 targetPowerValT2[ar9300RateSize]; |
2138 | unsigned int i = 0; | ||
2139 | |||
2140 | ar9003_hw_set_target_power_eeprom(ah, chan->channel, targetPowerValT2); | ||
2141 | ar9003_hw_set_power_per_rate_table(ah, chan, | ||
2142 | targetPowerValT2, cfgCtl, | ||
2143 | twiceAntennaReduction, | ||
2144 | twiceMaxRegulatoryPower, | ||
2145 | powerLimit); | ||
2146 | |||
2147 | while (i < ar9300RateSize) { | ||
2148 | ath_print(common, ATH_DBG_EEPROM, | ||
2149 | "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); | ||
2150 | i++; | ||
2151 | ath_print(common, ATH_DBG_EEPROM, | ||
2152 | "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); | ||
2153 | i++; | ||
2154 | ath_print(common, ATH_DBG_EEPROM, | ||
2155 | "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); | ||
2156 | i++; | ||
2157 | ath_print(common, ATH_DBG_EEPROM, | ||
2158 | "TPC[%02d] 0x%08x\n\n", i, targetPowerValT2[i]); | ||
2159 | i++; | ||
2160 | } | ||
2161 | |||
2162 | /* Write target power array to registers */ | ||
2163 | ar9003_hw_tx_power_regwrite(ah, targetPowerValT2); | ||
2164 | |||
2165 | /* | ||
2166 | * This is the TX power we send back to driver core, | ||
2167 | * and it can use to pass to userspace to display our | ||
2168 | * currently configured TX power setting. | ||
2169 | * | ||
2170 | * Since power is rate dependent, use one of the indices | ||
2171 | * from the AR9300_Rates enum to select an entry from | ||
2172 | * targetPowerValT2[] to report. Currently returns the | ||
2173 | * power for HT40 MCS 0, HT20 MCS 0, or OFDM 6 Mbps | ||
2174 | * as CCK power is less interesting (?). | ||
2175 | */ | ||
2176 | i = ALL_TARGET_LEGACY_6_24; /* legacy */ | ||
2177 | if (IS_CHAN_HT40(chan)) | ||
2178 | i = ALL_TARGET_HT40_0_8_16; /* ht40 */ | ||
2179 | else if (IS_CHAN_HT20(chan)) | ||
2180 | i = ALL_TARGET_HT20_0_8_16; /* ht20 */ | ||
2181 | |||
2182 | ah->txpower_limit = targetPowerValT2[i]; | ||
2183 | |||
1810 | ar9003_hw_calibration_apply(ah, chan->channel); | 2184 | ar9003_hw_calibration_apply(ah, chan->channel); |
1811 | } | 2185 | } |
1812 | 2186 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c index 49e0c865ce5c..7c38229ba670 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c | |||
@@ -577,10 +577,11 @@ static bool create_pa_curve(u32 *data_L, u32 *data_U, u32 *pa_table, u16 *gain) | |||
577 | } | 577 | } |
578 | 578 | ||
579 | void ar9003_paprd_populate_single_table(struct ath_hw *ah, | 579 | void ar9003_paprd_populate_single_table(struct ath_hw *ah, |
580 | struct ath9k_channel *chan, int chain) | 580 | struct ath9k_hw_cal_data *caldata, |
581 | int chain) | ||
581 | { | 582 | { |
582 | u32 *paprd_table_val = chan->pa_table[chain]; | 583 | u32 *paprd_table_val = caldata->pa_table[chain]; |
583 | u32 small_signal_gain = chan->small_signal_gain[chain]; | 584 | u32 small_signal_gain = caldata->small_signal_gain[chain]; |
584 | u32 training_power; | 585 | u32 training_power; |
585 | u32 reg = 0; | 586 | u32 reg = 0; |
586 | int i; | 587 | int i; |
@@ -654,17 +655,17 @@ int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain) | |||
654 | } | 655 | } |
655 | EXPORT_SYMBOL(ar9003_paprd_setup_gain_table); | 656 | EXPORT_SYMBOL(ar9003_paprd_setup_gain_table); |
656 | 657 | ||
657 | int ar9003_paprd_create_curve(struct ath_hw *ah, struct ath9k_channel *chan, | 658 | int ar9003_paprd_create_curve(struct ath_hw *ah, |
658 | int chain) | 659 | struct ath9k_hw_cal_data *caldata, int chain) |
659 | { | 660 | { |
660 | u16 *small_signal_gain = &chan->small_signal_gain[chain]; | 661 | u16 *small_signal_gain = &caldata->small_signal_gain[chain]; |
661 | u32 *pa_table = chan->pa_table[chain]; | 662 | u32 *pa_table = caldata->pa_table[chain]; |
662 | u32 *data_L, *data_U; | 663 | u32 *data_L, *data_U; |
663 | int i, status = 0; | 664 | int i, status = 0; |
664 | u32 *buf; | 665 | u32 *buf; |
665 | u32 reg; | 666 | u32 reg; |
666 | 667 | ||
667 | memset(chan->pa_table[chain], 0, sizeof(chan->pa_table[chain])); | 668 | memset(caldata->pa_table[chain], 0, sizeof(caldata->pa_table[chain])); |
668 | 669 | ||
669 | buf = kmalloc(2 * 48 * sizeof(u32), GFP_ATOMIC); | 670 | buf = kmalloc(2 * 48 * sizeof(u32), GFP_ATOMIC); |
670 | if (!buf) | 671 | if (!buf) |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index a753a431bb13..a491854fa38a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -542,7 +542,11 @@ static void ar9003_hw_prog_ini(struct ath_hw *ah, | |||
542 | u32 reg = INI_RA(iniArr, i, 0); | 542 | u32 reg = INI_RA(iniArr, i, 0); |
543 | u32 val = INI_RA(iniArr, i, column); | 543 | u32 val = INI_RA(iniArr, i, column); |
544 | 544 | ||
545 | REG_WRITE(ah, reg, val); | 545 | if (reg >= 0x16000 && reg < 0x17000) |
546 | ath9k_hw_analog_shift_regwrite(ah, reg, val); | ||
547 | else | ||
548 | REG_WRITE(ah, reg, val); | ||
549 | |||
546 | DO_DELAY(regWrites); | 550 | DO_DELAY(regWrites); |
547 | } | 551 | } |
548 | } | 552 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 998ae2c49ed2..07f26ee7a723 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -510,7 +510,7 @@ void ath_deinit_leds(struct ath_softc *sc); | |||
510 | #define SC_OP_BEACONS BIT(1) | 510 | #define SC_OP_BEACONS BIT(1) |
511 | #define SC_OP_RXAGGR BIT(2) | 511 | #define SC_OP_RXAGGR BIT(2) |
512 | #define SC_OP_TXAGGR BIT(3) | 512 | #define SC_OP_TXAGGR BIT(3) |
513 | #define SC_OP_FULL_RESET BIT(4) | 513 | #define SC_OP_OFFCHANNEL BIT(4) |
514 | #define SC_OP_PREAMBLE_SHORT BIT(5) | 514 | #define SC_OP_PREAMBLE_SHORT BIT(5) |
515 | #define SC_OP_PROTECT_ENABLE BIT(6) | 515 | #define SC_OP_PROTECT_ENABLE BIT(6) |
516 | #define SC_OP_RXFLUSH BIT(7) | 516 | #define SC_OP_RXFLUSH BIT(7) |
@@ -609,6 +609,7 @@ struct ath_softc { | |||
609 | struct ath_wiphy { | 609 | struct ath_wiphy { |
610 | struct ath_softc *sc; /* shared for all virtual wiphys */ | 610 | struct ath_softc *sc; /* shared for all virtual wiphys */ |
611 | struct ieee80211_hw *hw; | 611 | struct ieee80211_hw *hw; |
612 | struct ath9k_hw_cal_data caldata; | ||
612 | enum ath_wiphy_state { | 613 | enum ath_wiphy_state { |
613 | ATH_WIPHY_INACTIVE, | 614 | ATH_WIPHY_INACTIVE, |
614 | ATH_WIPHY_ACTIVE, | 615 | ATH_WIPHY_ACTIVE, |
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 139289e4e933..45208690c0ec 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -22,23 +22,6 @@ | |||
22 | /* We can tune this as we go by monitoring really low values */ | 22 | /* We can tune this as we go by monitoring really low values */ |
23 | #define ATH9K_NF_TOO_LOW -60 | 23 | #define ATH9K_NF_TOO_LOW -60 |
24 | 24 | ||
25 | /* AR5416 may return very high value (like -31 dBm), in those cases the nf | ||
26 | * is incorrect and we should use the static NF value. Later we can try to | ||
27 | * find out why they are reporting these values */ | ||
28 | |||
29 | static bool ath9k_hw_nf_in_range(struct ath_hw *ah, s16 nf) | ||
30 | { | ||
31 | if (nf > ATH9K_NF_TOO_LOW) { | ||
32 | ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, | ||
33 | "noise floor value detected (%d) is " | ||
34 | "lower than what we think is a " | ||
35 | "reasonable value (%d)\n", | ||
36 | nf, ATH9K_NF_TOO_LOW); | ||
37 | return false; | ||
38 | } | ||
39 | return true; | ||
40 | } | ||
41 | |||
42 | static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) | 25 | static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) |
43 | { | 26 | { |
44 | int16_t nfval; | 27 | int16_t nfval; |
@@ -121,6 +104,19 @@ void ath9k_hw_reset_calibration(struct ath_hw *ah, | |||
121 | ah->cal_samples = 0; | 104 | ah->cal_samples = 0; |
122 | } | 105 | } |
123 | 106 | ||
107 | static s16 ath9k_hw_get_default_nf(struct ath_hw *ah, | ||
108 | struct ath9k_channel *chan) | ||
109 | { | ||
110 | struct ath_nf_limits *limit; | ||
111 | |||
112 | if (!chan || IS_CHAN_2GHZ(chan)) | ||
113 | limit = &ah->nf_2g; | ||
114 | else | ||
115 | limit = &ah->nf_5g; | ||
116 | |||
117 | return limit->nominal; | ||
118 | } | ||
119 | |||
124 | /* This is done for the currently configured channel */ | 120 | /* This is done for the currently configured channel */ |
125 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah) | 121 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah) |
126 | { | 122 | { |
@@ -128,7 +124,7 @@ bool ath9k_hw_reset_calvalid(struct ath_hw *ah) | |||
128 | struct ieee80211_conf *conf = &common->hw->conf; | 124 | struct ieee80211_conf *conf = &common->hw->conf; |
129 | struct ath9k_cal_list *currCal = ah->cal_list_curr; | 125 | struct ath9k_cal_list *currCal = ah->cal_list_curr; |
130 | 126 | ||
131 | if (!ah->curchan) | 127 | if (!ah->caldata) |
132 | return true; | 128 | return true; |
133 | 129 | ||
134 | if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah)) | 130 | if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah)) |
@@ -151,37 +147,55 @@ bool ath9k_hw_reset_calvalid(struct ath_hw *ah) | |||
151 | "Resetting Cal %d state for channel %u\n", | 147 | "Resetting Cal %d state for channel %u\n", |
152 | currCal->calData->calType, conf->channel->center_freq); | 148 | currCal->calData->calType, conf->channel->center_freq); |
153 | 149 | ||
154 | ah->curchan->CalValid &= ~currCal->calData->calType; | 150 | ah->caldata->CalValid &= ~currCal->calData->calType; |
155 | currCal->calState = CAL_WAITING; | 151 | currCal->calState = CAL_WAITING; |
156 | 152 | ||
157 | return false; | 153 | return false; |
158 | } | 154 | } |
159 | EXPORT_SYMBOL(ath9k_hw_reset_calvalid); | 155 | EXPORT_SYMBOL(ath9k_hw_reset_calvalid); |
160 | 156 | ||
161 | void ath9k_hw_start_nfcal(struct ath_hw *ah) | 157 | void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update) |
162 | { | 158 | { |
159 | if (ah->caldata) | ||
160 | ah->caldata->nfcal_pending = true; | ||
161 | |||
163 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, | 162 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, |
164 | AR_PHY_AGC_CONTROL_ENABLE_NF); | 163 | AR_PHY_AGC_CONTROL_ENABLE_NF); |
165 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, | 164 | |
165 | if (update) | ||
166 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, | ||
167 | AR_PHY_AGC_CONTROL_NO_UPDATE_NF); | ||
168 | else | ||
169 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, | ||
166 | AR_PHY_AGC_CONTROL_NO_UPDATE_NF); | 170 | AR_PHY_AGC_CONTROL_NO_UPDATE_NF); |
171 | |||
167 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); | 172 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); |
168 | } | 173 | } |
169 | 174 | ||
170 | void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | 175 | void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) |
171 | { | 176 | { |
172 | struct ath9k_nfcal_hist *h; | 177 | struct ath9k_nfcal_hist *h = NULL; |
173 | unsigned i, j; | 178 | unsigned i, j; |
174 | int32_t val; | 179 | int32_t val; |
175 | u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; | 180 | u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; |
176 | struct ath_common *common = ath9k_hw_common(ah); | 181 | struct ath_common *common = ath9k_hw_common(ah); |
182 | s16 default_nf = ath9k_hw_get_default_nf(ah, chan); | ||
177 | 183 | ||
178 | h = ah->nfCalHist; | 184 | if (ah->caldata) |
185 | h = ah->caldata->nfCalHist; | ||
179 | 186 | ||
180 | for (i = 0; i < NUM_NF_READINGS; i++) { | 187 | for (i = 0; i < NUM_NF_READINGS; i++) { |
181 | if (chainmask & (1 << i)) { | 188 | if (chainmask & (1 << i)) { |
189 | s16 nfval; | ||
190 | |||
191 | if (h) | ||
192 | nfval = h[i].privNF; | ||
193 | else | ||
194 | nfval = default_nf; | ||
195 | |||
182 | val = REG_READ(ah, ah->nf_regs[i]); | 196 | val = REG_READ(ah, ah->nf_regs[i]); |
183 | val &= 0xFFFFFE00; | 197 | val &= 0xFFFFFE00; |
184 | val |= (((u32) (h[i].privNF) << 1) & 0x1ff); | 198 | val |= (((u32) nfval << 1) & 0x1ff); |
185 | REG_WRITE(ah, ah->nf_regs[i], val); | 199 | REG_WRITE(ah, ah->nf_regs[i], val); |
186 | } | 200 | } |
187 | } | 201 | } |
@@ -277,22 +291,25 @@ static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf) | |||
277 | } | 291 | } |
278 | } | 292 | } |
279 | 293 | ||
280 | int16_t ath9k_hw_getnf(struct ath_hw *ah, | 294 | bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) |
281 | struct ath9k_channel *chan) | ||
282 | { | 295 | { |
283 | struct ath_common *common = ath9k_hw_common(ah); | 296 | struct ath_common *common = ath9k_hw_common(ah); |
284 | int16_t nf, nfThresh; | 297 | int16_t nf, nfThresh; |
285 | int16_t nfarray[NUM_NF_READINGS] = { 0 }; | 298 | int16_t nfarray[NUM_NF_READINGS] = { 0 }; |
286 | struct ath9k_nfcal_hist *h; | 299 | struct ath9k_nfcal_hist *h; |
287 | struct ieee80211_channel *c = chan->chan; | 300 | struct ieee80211_channel *c = chan->chan; |
301 | struct ath9k_hw_cal_data *caldata = ah->caldata; | ||
302 | |||
303 | if (!caldata) | ||
304 | return false; | ||
288 | 305 | ||
289 | chan->channelFlags &= (~CHANNEL_CW_INT); | 306 | chan->channelFlags &= (~CHANNEL_CW_INT); |
290 | if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { | 307 | if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { |
291 | ath_print(common, ATH_DBG_CALIBRATE, | 308 | ath_print(common, ATH_DBG_CALIBRATE, |
292 | "NF did not complete in calibration window\n"); | 309 | "NF did not complete in calibration window\n"); |
293 | nf = 0; | 310 | nf = 0; |
294 | chan->rawNoiseFloor = nf; | 311 | caldata->rawNoiseFloor = nf; |
295 | return chan->rawNoiseFloor; | 312 | return false; |
296 | } else { | 313 | } else { |
297 | ath9k_hw_do_getnf(ah, nfarray); | 314 | ath9k_hw_do_getnf(ah, nfarray); |
298 | ath9k_hw_nf_sanitize(ah, nfarray); | 315 | ath9k_hw_nf_sanitize(ah, nfarray); |
@@ -307,47 +324,40 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah, | |||
307 | } | 324 | } |
308 | } | 325 | } |
309 | 326 | ||
310 | h = ah->nfCalHist; | 327 | h = caldata->nfCalHist; |
311 | 328 | caldata->nfcal_pending = false; | |
312 | ath9k_hw_update_nfcal_hist_buffer(h, nfarray); | 329 | ath9k_hw_update_nfcal_hist_buffer(h, nfarray); |
313 | chan->rawNoiseFloor = h[0].privNF; | 330 | caldata->rawNoiseFloor = h[0].privNF; |
314 | 331 | return true; | |
315 | return chan->rawNoiseFloor; | ||
316 | } | 332 | } |
317 | 333 | ||
318 | void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah) | 334 | void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, |
335 | struct ath9k_channel *chan) | ||
319 | { | 336 | { |
320 | struct ath_nf_limits *limit; | 337 | struct ath9k_nfcal_hist *h; |
338 | s16 default_nf; | ||
321 | int i, j; | 339 | int i, j; |
322 | 340 | ||
323 | if (!ah->curchan || IS_CHAN_2GHZ(ah->curchan)) | 341 | if (!ah->caldata) |
324 | limit = &ah->nf_2g; | 342 | return; |
325 | else | ||
326 | limit = &ah->nf_5g; | ||
327 | 343 | ||
344 | h = ah->caldata->nfCalHist; | ||
345 | default_nf = ath9k_hw_get_default_nf(ah, chan); | ||
328 | for (i = 0; i < NUM_NF_READINGS; i++) { | 346 | for (i = 0; i < NUM_NF_READINGS; i++) { |
329 | ah->nfCalHist[i].currIndex = 0; | 347 | h[i].currIndex = 0; |
330 | ah->nfCalHist[i].privNF = limit->nominal; | 348 | h[i].privNF = default_nf; |
331 | ah->nfCalHist[i].invalidNFcount = | 349 | h[i].invalidNFcount = AR_PHY_CCA_FILTERWINDOW_LENGTH; |
332 | AR_PHY_CCA_FILTERWINDOW_LENGTH; | ||
333 | for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) { | 350 | for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) { |
334 | ah->nfCalHist[i].nfCalBuffer[j] = limit->nominal; | 351 | h[i].nfCalBuffer[j] = default_nf; |
335 | } | 352 | } |
336 | } | 353 | } |
337 | } | 354 | } |
338 | 355 | ||
339 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) | 356 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) |
340 | { | 357 | { |
341 | s16 nf; | 358 | if (!ah->caldata || !ah->caldata->rawNoiseFloor) |
342 | 359 | return ath9k_hw_get_default_nf(ah, chan); | |
343 | if (chan->rawNoiseFloor == 0) | ||
344 | nf = -96; | ||
345 | else | ||
346 | nf = chan->rawNoiseFloor; | ||
347 | |||
348 | if (!ath9k_hw_nf_in_range(ah, nf)) | ||
349 | nf = ATH_DEFAULT_NOISE_FLOOR; | ||
350 | 360 | ||
351 | return nf; | 361 | return ah->caldata->rawNoiseFloor; |
352 | } | 362 | } |
353 | EXPORT_SYMBOL(ath9k_hw_getchan_noise); | 363 | EXPORT_SYMBOL(ath9k_hw_getchan_noise); |
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index cd60d09cdda7..0a304b3eeeb6 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h | |||
@@ -108,11 +108,11 @@ struct ath9k_pacal_info{ | |||
108 | }; | 108 | }; |
109 | 109 | ||
110 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah); | 110 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah); |
111 | void ath9k_hw_start_nfcal(struct ath_hw *ah); | 111 | void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update); |
112 | void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan); | 112 | void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan); |
113 | int16_t ath9k_hw_getnf(struct ath_hw *ah, | 113 | bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan); |
114 | struct ath9k_channel *chan); | 114 | void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, |
115 | void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah); | 115 | struct ath9k_channel *chan); |
116 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); | 116 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); |
117 | void ath9k_hw_reset_calibration(struct ath_hw *ah, | 117 | void ath9k_hw_reset_calibration(struct ath_hw *ah, |
118 | struct ath9k_cal_list *currCal); | 118 | struct ath9k_cal_list *currCal); |
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 3756400e6bf9..43b9e21bc562 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -353,6 +353,8 @@ struct ath9k_htc_priv { | |||
353 | u16 seq_no; | 353 | u16 seq_no; |
354 | u32 bmiss_cnt; | 354 | u32 bmiss_cnt; |
355 | 355 | ||
356 | struct ath9k_hw_cal_data caldata[38]; | ||
357 | |||
356 | spinlock_t beacon_lock; | 358 | spinlock_t beacon_lock; |
357 | 359 | ||
358 | bool tx_queues_stop; | 360 | bool tx_queues_stop; |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index cf9bcc67ade2..ebed9d1691a5 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -125,6 +125,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
125 | struct ieee80211_conf *conf = &common->hw->conf; | 125 | struct ieee80211_conf *conf = &common->hw->conf; |
126 | bool fastcc = true; | 126 | bool fastcc = true; |
127 | struct ieee80211_channel *channel = hw->conf.channel; | 127 | struct ieee80211_channel *channel = hw->conf.channel; |
128 | struct ath9k_hw_cal_data *caldata; | ||
128 | enum htc_phymode mode; | 129 | enum htc_phymode mode; |
129 | __be16 htc_mode; | 130 | __be16 htc_mode; |
130 | u8 cmd_rsp; | 131 | u8 cmd_rsp; |
@@ -149,7 +150,8 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
149 | priv->ah->curchan->channel, | 150 | priv->ah->curchan->channel, |
150 | channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf)); | 151 | channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf)); |
151 | 152 | ||
152 | ret = ath9k_hw_reset(ah, hchan, fastcc); | 153 | caldata = &priv->caldata[channel->hw_value]; |
154 | ret = ath9k_hw_reset(ah, hchan, caldata, fastcc); | ||
153 | if (ret) { | 155 | if (ret) { |
154 | ath_print(common, ATH_DBG_FATAL, | 156 | ath_print(common, ATH_DBG_FATAL, |
155 | "Unable to reset channel (%u Mhz) " | 157 | "Unable to reset channel (%u Mhz) " |
@@ -1028,7 +1030,7 @@ static void ath9k_htc_radio_enable(struct ieee80211_hw *hw) | |||
1028 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); | 1030 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); |
1029 | 1031 | ||
1030 | /* Reset the HW */ | 1032 | /* Reset the HW */ |
1031 | ret = ath9k_hw_reset(ah, ah->curchan, false); | 1033 | ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); |
1032 | if (ret) { | 1034 | if (ret) { |
1033 | ath_print(common, ATH_DBG_FATAL, | 1035 | ath_print(common, ATH_DBG_FATAL, |
1034 | "Unable to reset hardware; reset status %d " | 1036 | "Unable to reset hardware; reset status %d " |
@@ -1091,7 +1093,7 @@ static void ath9k_htc_radio_disable(struct ieee80211_hw *hw) | |||
1091 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); | 1093 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); |
1092 | 1094 | ||
1093 | /* Reset the HW */ | 1095 | /* Reset the HW */ |
1094 | ret = ath9k_hw_reset(ah, ah->curchan, false); | 1096 | ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); |
1095 | if (ret) { | 1097 | if (ret) { |
1096 | ath_print(common, ATH_DBG_FATAL, | 1098 | ath_print(common, ATH_DBG_FATAL, |
1097 | "Unable to reset hardware; reset status %d " | 1099 | "Unable to reset hardware; reset status %d " |
@@ -1179,7 +1181,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
1179 | ath9k_hw_configpcipowersave(ah, 0, 0); | 1181 | ath9k_hw_configpcipowersave(ah, 0, 0); |
1180 | 1182 | ||
1181 | ath9k_hw_htc_resetinit(ah); | 1183 | ath9k_hw_htc_resetinit(ah); |
1182 | ret = ath9k_hw_reset(ah, init_channel, false); | 1184 | ret = ath9k_hw_reset(ah, init_channel, ah->caldata, false); |
1183 | if (ret) { | 1185 | if (ret) { |
1184 | ath_print(common, ATH_DBG_FATAL, | 1186 | ath_print(common, ATH_DBG_FATAL, |
1185 | "Unable to reset hardware; reset status %d " | 1187 | "Unable to reset hardware; reset status %d " |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 8d291ccf5c88..3384ca164562 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -610,7 +610,6 @@ static int __ath9k_hw_init(struct ath_hw *ah) | |||
610 | else | 610 | else |
611 | ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S); | 611 | ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S); |
612 | 612 | ||
613 | ath9k_init_nfcal_hist_buffer(ah); | ||
614 | ah->bb_watchdog_timeout_ms = 25; | 613 | ah->bb_watchdog_timeout_ms = 25; |
615 | 614 | ||
616 | common->state = ATH_HW_INITIALIZED; | 615 | common->state = ATH_HW_INITIALIZED; |
@@ -1183,9 +1182,6 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, | |||
1183 | 1182 | ||
1184 | ath9k_hw_spur_mitigate_freq(ah, chan); | 1183 | ath9k_hw_spur_mitigate_freq(ah, chan); |
1185 | 1184 | ||
1186 | if (!chan->oneTimeCalsDone) | ||
1187 | chan->oneTimeCalsDone = true; | ||
1188 | |||
1189 | return true; | 1185 | return true; |
1190 | } | 1186 | } |
1191 | 1187 | ||
@@ -1218,7 +1214,7 @@ bool ath9k_hw_check_alive(struct ath_hw *ah) | |||
1218 | EXPORT_SYMBOL(ath9k_hw_check_alive); | 1214 | EXPORT_SYMBOL(ath9k_hw_check_alive); |
1219 | 1215 | ||
1220 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | 1216 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, |
1221 | bool bChannelChange) | 1217 | struct ath9k_hw_cal_data *caldata, bool bChannelChange) |
1222 | { | 1218 | { |
1223 | struct ath_common *common = ath9k_hw_common(ah); | 1219 | struct ath_common *common = ath9k_hw_common(ah); |
1224 | u32 saveLedState; | 1220 | u32 saveLedState; |
@@ -1243,9 +1239,19 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1243 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) | 1239 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) |
1244 | return -EIO; | 1240 | return -EIO; |
1245 | 1241 | ||
1246 | if (curchan && !ah->chip_fullsleep) | 1242 | if (curchan && !ah->chip_fullsleep && ah->caldata) |
1247 | ath9k_hw_getnf(ah, curchan); | 1243 | ath9k_hw_getnf(ah, curchan); |
1248 | 1244 | ||
1245 | ah->caldata = caldata; | ||
1246 | if (caldata && | ||
1247 | (chan->channel != caldata->channel || | ||
1248 | (chan->channelFlags & ~CHANNEL_CW_INT) != | ||
1249 | (caldata->channelFlags & ~CHANNEL_CW_INT))) { | ||
1250 | /* Operating channel changed, reset channel calibration data */ | ||
1251 | memset(caldata, 0, sizeof(*caldata)); | ||
1252 | ath9k_init_nfcal_hist_buffer(ah, chan); | ||
1253 | } | ||
1254 | |||
1249 | if (bChannelChange && | 1255 | if (bChannelChange && |
1250 | (ah->chip_fullsleep != true) && | 1256 | (ah->chip_fullsleep != true) && |
1251 | (ah->curchan != NULL) && | 1257 | (ah->curchan != NULL) && |
@@ -1256,7 +1262,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1256 | 1262 | ||
1257 | if (ath9k_hw_channel_change(ah, chan)) { | 1263 | if (ath9k_hw_channel_change(ah, chan)) { |
1258 | ath9k_hw_loadnf(ah, ah->curchan); | 1264 | ath9k_hw_loadnf(ah, ah->curchan); |
1259 | ath9k_hw_start_nfcal(ah); | 1265 | ath9k_hw_start_nfcal(ah, true); |
1260 | return 0; | 1266 | return 0; |
1261 | } | 1267 | } |
1262 | } | 1268 | } |
@@ -1461,11 +1467,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1461 | if (ah->btcoex_hw.enabled) | 1467 | if (ah->btcoex_hw.enabled) |
1462 | ath9k_hw_btcoex_enable(ah); | 1468 | ath9k_hw_btcoex_enable(ah); |
1463 | 1469 | ||
1464 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 1470 | if (AR_SREV_9300_20_OR_LATER(ah)) |
1465 | ath9k_hw_loadnf(ah, curchan); | ||
1466 | ath9k_hw_start_nfcal(ah); | ||
1467 | ar9003_hw_bb_watchdog_config(ah); | 1471 | ar9003_hw_bb_watchdog_config(ah); |
1468 | } | ||
1469 | 1472 | ||
1470 | return 0; | 1473 | return 0; |
1471 | } | 1474 | } |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 2d30efc0b94f..399f7c1283cd 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -346,19 +346,25 @@ enum ath9k_int { | |||
346 | CHANNEL_HT40PLUS | \ | 346 | CHANNEL_HT40PLUS | \ |
347 | CHANNEL_HT40MINUS) | 347 | CHANNEL_HT40MINUS) |
348 | 348 | ||
349 | struct ath9k_channel { | 349 | struct ath9k_hw_cal_data { |
350 | struct ieee80211_channel *chan; | ||
351 | u16 channel; | 350 | u16 channel; |
352 | u32 channelFlags; | 351 | u32 channelFlags; |
353 | u32 chanmode; | ||
354 | int32_t CalValid; | 352 | int32_t CalValid; |
355 | bool oneTimeCalsDone; | ||
356 | int8_t iCoff; | 353 | int8_t iCoff; |
357 | int8_t qCoff; | 354 | int8_t qCoff; |
358 | int16_t rawNoiseFloor; | 355 | int16_t rawNoiseFloor; |
359 | bool paprd_done; | 356 | bool paprd_done; |
357 | bool nfcal_pending; | ||
360 | u16 small_signal_gain[AR9300_MAX_CHAINS]; | 358 | u16 small_signal_gain[AR9300_MAX_CHAINS]; |
361 | u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ]; | 359 | u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ]; |
360 | struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; | ||
361 | }; | ||
362 | |||
363 | struct ath9k_channel { | ||
364 | struct ieee80211_channel *chan; | ||
365 | u16 channel; | ||
366 | u32 channelFlags; | ||
367 | u32 chanmode; | ||
362 | }; | 368 | }; |
363 | 369 | ||
364 | #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ | 370 | #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ |
@@ -669,7 +675,7 @@ struct ath_hw { | |||
669 | enum nl80211_iftype opmode; | 675 | enum nl80211_iftype opmode; |
670 | enum ath9k_power_mode power_mode; | 676 | enum ath9k_power_mode power_mode; |
671 | 677 | ||
672 | struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; | 678 | struct ath9k_hw_cal_data *caldata; |
673 | struct ath9k_pacal_info pacal_info; | 679 | struct ath9k_pacal_info pacal_info; |
674 | struct ar5416Stats stats; | 680 | struct ar5416Stats stats; |
675 | struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES]; | 681 | struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES]; |
@@ -863,7 +869,7 @@ const char *ath9k_hw_probe(u16 vendorid, u16 devid); | |||
863 | void ath9k_hw_deinit(struct ath_hw *ah); | 869 | void ath9k_hw_deinit(struct ath_hw *ah); |
864 | int ath9k_hw_init(struct ath_hw *ah); | 870 | int ath9k_hw_init(struct ath_hw *ah); |
865 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | 871 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, |
866 | bool bChannelChange); | 872 | struct ath9k_hw_cal_data *caldata, bool bChannelChange); |
867 | int ath9k_hw_fill_cap_info(struct ath_hw *ah); | 873 | int ath9k_hw_fill_cap_info(struct ath_hw *ah); |
868 | u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan); | 874 | u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan); |
869 | 875 | ||
@@ -958,9 +964,10 @@ void ar9003_hw_bb_watchdog_read(struct ath_hw *ah); | |||
958 | void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah); | 964 | void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah); |
959 | void ar9003_paprd_enable(struct ath_hw *ah, bool val); | 965 | void ar9003_paprd_enable(struct ath_hw *ah, bool val); |
960 | void ar9003_paprd_populate_single_table(struct ath_hw *ah, | 966 | void ar9003_paprd_populate_single_table(struct ath_hw *ah, |
961 | struct ath9k_channel *chan, int chain); | 967 | struct ath9k_hw_cal_data *caldata, |
962 | int ar9003_paprd_create_curve(struct ath_hw *ah, struct ath9k_channel *chan, | 968 | int chain); |
963 | int chain); | 969 | int ar9003_paprd_create_curve(struct ath_hw *ah, |
970 | struct ath9k_hw_cal_data *caldata, int chain); | ||
964 | int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain); | 971 | int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain); |
965 | int ar9003_paprd_init_table(struct ath_hw *ah); | 972 | int ar9003_paprd_init_table(struct ath_hw *ah); |
966 | bool ar9003_paprd_is_done(struct ath_hw *ah); | 973 | bool ar9003_paprd_is_done(struct ath_hw *ah); |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 0429dda0961f..3caa32316e7b 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -154,6 +154,27 @@ void ath9k_ps_restore(struct ath_softc *sc) | |||
154 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | 154 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); |
155 | } | 155 | } |
156 | 156 | ||
157 | static void ath_start_ani(struct ath_common *common) | ||
158 | { | ||
159 | struct ath_hw *ah = common->ah; | ||
160 | unsigned long timestamp = jiffies_to_msecs(jiffies); | ||
161 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
162 | |||
163 | if (!(sc->sc_flags & SC_OP_ANI_RUN)) | ||
164 | return; | ||
165 | |||
166 | if (sc->sc_flags & SC_OP_OFFCHANNEL) | ||
167 | return; | ||
168 | |||
169 | common->ani.longcal_timer = timestamp; | ||
170 | common->ani.shortcal_timer = timestamp; | ||
171 | common->ani.checkani_timer = timestamp; | ||
172 | |||
173 | mod_timer(&common->ani.timer, | ||
174 | jiffies + | ||
175 | msecs_to_jiffies((u32)ah->config.ani_poll_interval)); | ||
176 | } | ||
177 | |||
157 | /* | 178 | /* |
158 | * Set/change channels. If the channel is really being changed, it's done | 179 | * Set/change channels. If the channel is really being changed, it's done |
159 | * by reseting the chip. To accomplish this we must first cleanup any pending | 180 | * by reseting the chip. To accomplish this we must first cleanup any pending |
@@ -162,16 +183,23 @@ void ath9k_ps_restore(struct ath_softc *sc) | |||
162 | int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | 183 | int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, |
163 | struct ath9k_channel *hchan) | 184 | struct ath9k_channel *hchan) |
164 | { | 185 | { |
186 | struct ath_wiphy *aphy = hw->priv; | ||
165 | struct ath_hw *ah = sc->sc_ah; | 187 | struct ath_hw *ah = sc->sc_ah; |
166 | struct ath_common *common = ath9k_hw_common(ah); | 188 | struct ath_common *common = ath9k_hw_common(ah); |
167 | struct ieee80211_conf *conf = &common->hw->conf; | 189 | struct ieee80211_conf *conf = &common->hw->conf; |
168 | bool fastcc = true, stopped; | 190 | bool fastcc = true, stopped; |
169 | struct ieee80211_channel *channel = hw->conf.channel; | 191 | struct ieee80211_channel *channel = hw->conf.channel; |
192 | struct ath9k_hw_cal_data *caldata = NULL; | ||
170 | int r; | 193 | int r; |
171 | 194 | ||
172 | if (sc->sc_flags & SC_OP_INVALID) | 195 | if (sc->sc_flags & SC_OP_INVALID) |
173 | return -EIO; | 196 | return -EIO; |
174 | 197 | ||
198 | del_timer_sync(&common->ani.timer); | ||
199 | cancel_work_sync(&sc->paprd_work); | ||
200 | cancel_work_sync(&sc->hw_check_work); | ||
201 | cancel_delayed_work_sync(&sc->tx_complete_work); | ||
202 | |||
175 | ath9k_ps_wakeup(sc); | 203 | ath9k_ps_wakeup(sc); |
176 | 204 | ||
177 | /* | 205 | /* |
@@ -191,9 +219,12 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
191 | * to flush data frames already in queue because of | 219 | * to flush data frames already in queue because of |
192 | * changing channel. */ | 220 | * changing channel. */ |
193 | 221 | ||
194 | if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET)) | 222 | if (!stopped || !(sc->sc_flags & SC_OP_OFFCHANNEL)) |
195 | fastcc = false; | 223 | fastcc = false; |
196 | 224 | ||
225 | if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) | ||
226 | caldata = &aphy->caldata; | ||
227 | |||
197 | ath_print(common, ATH_DBG_CONFIG, | 228 | ath_print(common, ATH_DBG_CONFIG, |
198 | "(%u MHz) -> (%u MHz), conf_is_ht40: %d\n", | 229 | "(%u MHz) -> (%u MHz), conf_is_ht40: %d\n", |
199 | sc->sc_ah->curchan->channel, | 230 | sc->sc_ah->curchan->channel, |
@@ -201,7 +232,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
201 | 232 | ||
202 | spin_lock_bh(&sc->sc_resetlock); | 233 | spin_lock_bh(&sc->sc_resetlock); |
203 | 234 | ||
204 | r = ath9k_hw_reset(ah, hchan, fastcc); | 235 | r = ath9k_hw_reset(ah, hchan, caldata, fastcc); |
205 | if (r) { | 236 | if (r) { |
206 | ath_print(common, ATH_DBG_FATAL, | 237 | ath_print(common, ATH_DBG_FATAL, |
207 | "Unable to reset channel (%u MHz), " | 238 | "Unable to reset channel (%u MHz), " |
@@ -212,8 +243,6 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
212 | } | 243 | } |
213 | spin_unlock_bh(&sc->sc_resetlock); | 244 | spin_unlock_bh(&sc->sc_resetlock); |
214 | 245 | ||
215 | sc->sc_flags &= ~SC_OP_FULL_RESET; | ||
216 | |||
217 | if (ath_startrecv(sc) != 0) { | 246 | if (ath_startrecv(sc) != 0) { |
218 | ath_print(common, ATH_DBG_FATAL, | 247 | ath_print(common, ATH_DBG_FATAL, |
219 | "Unable to restart recv logic\n"); | 248 | "Unable to restart recv logic\n"); |
@@ -225,6 +254,12 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
225 | ath_update_txpow(sc); | 254 | ath_update_txpow(sc); |
226 | ath9k_hw_set_interrupts(ah, ah->imask); | 255 | ath9k_hw_set_interrupts(ah, ah->imask); |
227 | 256 | ||
257 | if (!(sc->sc_flags & (SC_OP_OFFCHANNEL | SC_OP_SCANNING))) { | ||
258 | ath_start_ani(common); | ||
259 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); | ||
260 | ath_beacon_config(sc, NULL); | ||
261 | } | ||
262 | |||
228 | ps_restore: | 263 | ps_restore: |
229 | ath9k_ps_restore(sc); | 264 | ath9k_ps_restore(sc); |
230 | return r; | 265 | return r; |
@@ -233,17 +268,19 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
233 | static void ath_paprd_activate(struct ath_softc *sc) | 268 | static void ath_paprd_activate(struct ath_softc *sc) |
234 | { | 269 | { |
235 | struct ath_hw *ah = sc->sc_ah; | 270 | struct ath_hw *ah = sc->sc_ah; |
271 | struct ath9k_hw_cal_data *caldata = ah->caldata; | ||
236 | int chain; | 272 | int chain; |
237 | 273 | ||
238 | if (!ah->curchan->paprd_done) | 274 | if (!caldata || !caldata->paprd_done) |
239 | return; | 275 | return; |
240 | 276 | ||
241 | ath9k_ps_wakeup(sc); | 277 | ath9k_ps_wakeup(sc); |
278 | ar9003_paprd_enable(ah, false); | ||
242 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { | 279 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { |
243 | if (!(ah->caps.tx_chainmask & BIT(chain))) | 280 | if (!(ah->caps.tx_chainmask & BIT(chain))) |
244 | continue; | 281 | continue; |
245 | 282 | ||
246 | ar9003_paprd_populate_single_table(ah, ah->curchan, chain); | 283 | ar9003_paprd_populate_single_table(ah, caldata, chain); |
247 | } | 284 | } |
248 | 285 | ||
249 | ar9003_paprd_enable(ah, true); | 286 | ar9003_paprd_enable(ah, true); |
@@ -261,6 +298,7 @@ void ath_paprd_calibrate(struct work_struct *work) | |||
261 | int band = hw->conf.channel->band; | 298 | int band = hw->conf.channel->band; |
262 | struct ieee80211_supported_band *sband = &sc->sbands[band]; | 299 | struct ieee80211_supported_band *sband = &sc->sbands[band]; |
263 | struct ath_tx_control txctl; | 300 | struct ath_tx_control txctl; |
301 | struct ath9k_hw_cal_data *caldata = ah->caldata; | ||
264 | int qnum, ftype; | 302 | int qnum, ftype; |
265 | int chain_ok = 0; | 303 | int chain_ok = 0; |
266 | int chain; | 304 | int chain; |
@@ -268,6 +306,9 @@ void ath_paprd_calibrate(struct work_struct *work) | |||
268 | int time_left; | 306 | int time_left; |
269 | int i; | 307 | int i; |
270 | 308 | ||
309 | if (!caldata) | ||
310 | return; | ||
311 | |||
271 | skb = alloc_skb(len, GFP_KERNEL); | 312 | skb = alloc_skb(len, GFP_KERNEL); |
272 | if (!skb) | 313 | if (!skb) |
273 | return; | 314 | return; |
@@ -322,7 +363,7 @@ void ath_paprd_calibrate(struct work_struct *work) | |||
322 | if (!ar9003_paprd_is_done(ah)) | 363 | if (!ar9003_paprd_is_done(ah)) |
323 | break; | 364 | break; |
324 | 365 | ||
325 | if (ar9003_paprd_create_curve(ah, ah->curchan, chain) != 0) | 366 | if (ar9003_paprd_create_curve(ah, caldata, chain) != 0) |
326 | break; | 367 | break; |
327 | 368 | ||
328 | chain_ok = 1; | 369 | chain_ok = 1; |
@@ -330,7 +371,7 @@ void ath_paprd_calibrate(struct work_struct *work) | |||
330 | kfree_skb(skb); | 371 | kfree_skb(skb); |
331 | 372 | ||
332 | if (chain_ok) { | 373 | if (chain_ok) { |
333 | ah->curchan->paprd_done = true; | 374 | caldata->paprd_done = true; |
334 | ath_paprd_activate(sc); | 375 | ath_paprd_activate(sc); |
335 | } | 376 | } |
336 | 377 | ||
@@ -439,33 +480,14 @@ set_timer: | |||
439 | cal_interval = min(cal_interval, (u32)short_cal_interval); | 480 | cal_interval = min(cal_interval, (u32)short_cal_interval); |
440 | 481 | ||
441 | mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); | 482 | mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); |
442 | if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && | 483 | if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) { |
443 | !(sc->sc_flags & SC_OP_SCANNING)) { | 484 | if (!ah->caldata->paprd_done) |
444 | if (!sc->sc_ah->curchan->paprd_done) | ||
445 | ieee80211_queue_work(sc->hw, &sc->paprd_work); | 485 | ieee80211_queue_work(sc->hw, &sc->paprd_work); |
446 | else | 486 | else |
447 | ath_paprd_activate(sc); | 487 | ath_paprd_activate(sc); |
448 | } | 488 | } |
449 | } | 489 | } |
450 | 490 | ||
451 | static void ath_start_ani(struct ath_common *common) | ||
452 | { | ||
453 | struct ath_hw *ah = common->ah; | ||
454 | unsigned long timestamp = jiffies_to_msecs(jiffies); | ||
455 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
456 | |||
457 | if (!(sc->sc_flags & SC_OP_ANI_RUN)) | ||
458 | return; | ||
459 | |||
460 | common->ani.longcal_timer = timestamp; | ||
461 | common->ani.shortcal_timer = timestamp; | ||
462 | common->ani.checkani_timer = timestamp; | ||
463 | |||
464 | mod_timer(&common->ani.timer, | ||
465 | jiffies + | ||
466 | msecs_to_jiffies((u32)ah->config.ani_poll_interval)); | ||
467 | } | ||
468 | |||
469 | /* | 491 | /* |
470 | * Update tx/rx chainmask. For legacy association, | 492 | * Update tx/rx chainmask. For legacy association, |
471 | * hard code chainmask to 1x1, for 11n association, use | 493 | * hard code chainmask to 1x1, for 11n association, use |
@@ -477,7 +499,7 @@ void ath_update_chainmask(struct ath_softc *sc, int is_ht) | |||
477 | struct ath_hw *ah = sc->sc_ah; | 499 | struct ath_hw *ah = sc->sc_ah; |
478 | struct ath_common *common = ath9k_hw_common(ah); | 500 | struct ath_common *common = ath9k_hw_common(ah); |
479 | 501 | ||
480 | if ((sc->sc_flags & SC_OP_SCANNING) || is_ht || | 502 | if ((sc->sc_flags & SC_OP_OFFCHANNEL) || is_ht || |
481 | (ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE)) { | 503 | (ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE)) { |
482 | common->tx_chainmask = ah->caps.tx_chainmask; | 504 | common->tx_chainmask = ah->caps.tx_chainmask; |
483 | common->rx_chainmask = ah->caps.rx_chainmask; | 505 | common->rx_chainmask = ah->caps.rx_chainmask; |
@@ -817,7 +839,7 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
817 | ah->curchan = ath_get_curchannel(sc, sc->hw); | 839 | ah->curchan = ath_get_curchannel(sc, sc->hw); |
818 | 840 | ||
819 | spin_lock_bh(&sc->sc_resetlock); | 841 | spin_lock_bh(&sc->sc_resetlock); |
820 | r = ath9k_hw_reset(ah, ah->curchan, false); | 842 | r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); |
821 | if (r) { | 843 | if (r) { |
822 | ath_print(common, ATH_DBG_FATAL, | 844 | ath_print(common, ATH_DBG_FATAL, |
823 | "Unable to reset channel (%u MHz), " | 845 | "Unable to reset channel (%u MHz), " |
@@ -877,7 +899,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
877 | ah->curchan = ath_get_curchannel(sc, hw); | 899 | ah->curchan = ath_get_curchannel(sc, hw); |
878 | 900 | ||
879 | spin_lock_bh(&sc->sc_resetlock); | 901 | spin_lock_bh(&sc->sc_resetlock); |
880 | r = ath9k_hw_reset(ah, ah->curchan, false); | 902 | r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); |
881 | if (r) { | 903 | if (r) { |
882 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, | 904 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, |
883 | "Unable to reset channel (%u MHz), " | 905 | "Unable to reset channel (%u MHz), " |
@@ -910,7 +932,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) | |||
910 | ath_flushrecv(sc); | 932 | ath_flushrecv(sc); |
911 | 933 | ||
912 | spin_lock_bh(&sc->sc_resetlock); | 934 | spin_lock_bh(&sc->sc_resetlock); |
913 | r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false); | 935 | r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false); |
914 | if (r) | 936 | if (r) |
915 | ath_print(common, ATH_DBG_FATAL, | 937 | ath_print(common, ATH_DBG_FATAL, |
916 | "Unable to reset hardware; reset status %d\n", r); | 938 | "Unable to reset hardware; reset status %d\n", r); |
@@ -1085,7 +1107,7 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1085 | * and then setup of the interrupt mask. | 1107 | * and then setup of the interrupt mask. |
1086 | */ | 1108 | */ |
1087 | spin_lock_bh(&sc->sc_resetlock); | 1109 | spin_lock_bh(&sc->sc_resetlock); |
1088 | r = ath9k_hw_reset(ah, init_channel, false); | 1110 | r = ath9k_hw_reset(ah, init_channel, ah->caldata, false); |
1089 | if (r) { | 1111 | if (r) { |
1090 | ath_print(common, ATH_DBG_FATAL, | 1112 | ath_print(common, ATH_DBG_FATAL, |
1091 | "Unable to reset hardware; reset status %d " | 1113 | "Unable to reset hardware; reset status %d " |
@@ -1579,6 +1601,10 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1579 | 1601 | ||
1580 | aphy->chan_idx = pos; | 1602 | aphy->chan_idx = pos; |
1581 | aphy->chan_is_ht = conf_is_ht(conf); | 1603 | aphy->chan_is_ht = conf_is_ht(conf); |
1604 | if (hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) | ||
1605 | sc->sc_flags |= SC_OP_OFFCHANNEL; | ||
1606 | else | ||
1607 | sc->sc_flags &= ~SC_OP_OFFCHANNEL; | ||
1582 | 1608 | ||
1583 | if (aphy->state == ATH_WIPHY_SCAN || | 1609 | if (aphy->state == ATH_WIPHY_SCAN || |
1584 | aphy->state == ATH_WIPHY_ACTIVE) | 1610 | aphy->state == ATH_WIPHY_ACTIVE) |
@@ -1990,7 +2016,6 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw) | |||
1990 | { | 2016 | { |
1991 | struct ath_wiphy *aphy = hw->priv; | 2017 | struct ath_wiphy *aphy = hw->priv; |
1992 | struct ath_softc *sc = aphy->sc; | 2018 | struct ath_softc *sc = aphy->sc; |
1993 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1994 | 2019 | ||
1995 | mutex_lock(&sc->mutex); | 2020 | mutex_lock(&sc->mutex); |
1996 | if (ath9k_wiphy_scanning(sc)) { | 2021 | if (ath9k_wiphy_scanning(sc)) { |
@@ -2008,10 +2033,6 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw) | |||
2008 | aphy->state = ATH_WIPHY_SCAN; | 2033 | aphy->state = ATH_WIPHY_SCAN; |
2009 | ath9k_wiphy_pause_all_forced(sc, aphy); | 2034 | ath9k_wiphy_pause_all_forced(sc, aphy); |
2010 | sc->sc_flags |= SC_OP_SCANNING; | 2035 | sc->sc_flags |= SC_OP_SCANNING; |
2011 | del_timer_sync(&common->ani.timer); | ||
2012 | cancel_work_sync(&sc->paprd_work); | ||
2013 | cancel_work_sync(&sc->hw_check_work); | ||
2014 | cancel_delayed_work_sync(&sc->tx_complete_work); | ||
2015 | mutex_unlock(&sc->mutex); | 2036 | mutex_unlock(&sc->mutex); |
2016 | } | 2037 | } |
2017 | 2038 | ||
@@ -2023,15 +2044,10 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) | |||
2023 | { | 2044 | { |
2024 | struct ath_wiphy *aphy = hw->priv; | 2045 | struct ath_wiphy *aphy = hw->priv; |
2025 | struct ath_softc *sc = aphy->sc; | 2046 | struct ath_softc *sc = aphy->sc; |
2026 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
2027 | 2047 | ||
2028 | mutex_lock(&sc->mutex); | 2048 | mutex_lock(&sc->mutex); |
2029 | aphy->state = ATH_WIPHY_ACTIVE; | 2049 | aphy->state = ATH_WIPHY_ACTIVE; |
2030 | sc->sc_flags &= ~SC_OP_SCANNING; | 2050 | sc->sc_flags &= ~SC_OP_SCANNING; |
2031 | sc->sc_flags |= SC_OP_FULL_RESET; | ||
2032 | ath_start_ani(common); | ||
2033 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); | ||
2034 | ath_beacon_config(sc, NULL); | ||
2035 | mutex_unlock(&sc->mutex); | 2051 | mutex_unlock(&sc->mutex); |
2036 | } | 2052 | } |
2037 | 2053 | ||
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index da0cfe90c38a..a3fc987ebab0 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -1140,6 +1140,11 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1140 | if (flush) | 1140 | if (flush) |
1141 | goto requeue; | 1141 | goto requeue; |
1142 | 1142 | ||
1143 | retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs, | ||
1144 | rxs, &decrypt_error); | ||
1145 | if (retval) | ||
1146 | goto requeue; | ||
1147 | |||
1143 | rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; | 1148 | rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; |
1144 | if (rs.rs_tstamp > tsf_lower && | 1149 | if (rs.rs_tstamp > tsf_lower && |
1145 | unlikely(rs.rs_tstamp - tsf_lower > 0x10000000)) | 1150 | unlikely(rs.rs_tstamp - tsf_lower > 0x10000000)) |
@@ -1149,11 +1154,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1149 | unlikely(tsf_lower - rs.rs_tstamp > 0x10000000)) | 1154 | unlikely(tsf_lower - rs.rs_tstamp > 0x10000000)) |
1150 | rxs->mactime += 0x100000000ULL; | 1155 | rxs->mactime += 0x100000000ULL; |
1151 | 1156 | ||
1152 | retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs, | ||
1153 | rxs, &decrypt_error); | ||
1154 | if (retval) | ||
1155 | goto requeue; | ||
1156 | |||
1157 | /* Ensure we always have an skb to requeue once we are done | 1157 | /* Ensure we always have an skb to requeue once we are done |
1158 | * processing the current buffer's skb */ | 1158 | * processing the current buffer's skb */ |
1159 | requeue_skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_ATOMIC); | 1159 | requeue_skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_ATOMIC); |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 501b72821b4d..4dda14e36227 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -120,26 +120,14 @@ static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid) | |||
120 | list_add_tail(&ac->list, &txq->axq_acq); | 120 | list_add_tail(&ac->list, &txq->axq_acq); |
121 | } | 121 | } |
122 | 122 | ||
123 | static void ath_tx_pause_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | ||
124 | { | ||
125 | struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; | ||
126 | |||
127 | spin_lock_bh(&txq->axq_lock); | ||
128 | tid->paused++; | ||
129 | spin_unlock_bh(&txq->axq_lock); | ||
130 | } | ||
131 | |||
132 | static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | 123 | static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid) |
133 | { | 124 | { |
134 | struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; | 125 | struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; |
135 | 126 | ||
136 | BUG_ON(tid->paused <= 0); | 127 | WARN_ON(!tid->paused); |
137 | spin_lock_bh(&txq->axq_lock); | ||
138 | |||
139 | tid->paused--; | ||
140 | 128 | ||
141 | if (tid->paused > 0) | 129 | spin_lock_bh(&txq->axq_lock); |
142 | goto unlock; | 130 | tid->paused = false; |
143 | 131 | ||
144 | if (list_empty(&tid->buf_q)) | 132 | if (list_empty(&tid->buf_q)) |
145 | goto unlock; | 133 | goto unlock; |
@@ -157,15 +145,10 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | |||
157 | struct list_head bf_head; | 145 | struct list_head bf_head; |
158 | INIT_LIST_HEAD(&bf_head); | 146 | INIT_LIST_HEAD(&bf_head); |
159 | 147 | ||
160 | BUG_ON(tid->paused <= 0); | 148 | WARN_ON(!tid->paused); |
161 | spin_lock_bh(&txq->axq_lock); | ||
162 | 149 | ||
163 | tid->paused--; | 150 | spin_lock_bh(&txq->axq_lock); |
164 | 151 | tid->paused = false; | |
165 | if (tid->paused > 0) { | ||
166 | spin_unlock_bh(&txq->axq_lock); | ||
167 | return; | ||
168 | } | ||
169 | 152 | ||
170 | while (!list_empty(&tid->buf_q)) { | 153 | while (!list_empty(&tid->buf_q)) { |
171 | bf = list_first_entry(&tid->buf_q, struct ath_buf, list); | 154 | bf = list_first_entry(&tid->buf_q, struct ath_buf, list); |
@@ -811,7 +794,7 @@ void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
811 | an = (struct ath_node *)sta->drv_priv; | 794 | an = (struct ath_node *)sta->drv_priv; |
812 | txtid = ATH_AN_2_TID(an, tid); | 795 | txtid = ATH_AN_2_TID(an, tid); |
813 | txtid->state |= AGGR_ADDBA_PROGRESS; | 796 | txtid->state |= AGGR_ADDBA_PROGRESS; |
814 | ath_tx_pause_tid(sc, txtid); | 797 | txtid->paused = true; |
815 | *ssn = txtid->seq_start; | 798 | *ssn = txtid->seq_start; |
816 | } | 799 | } |
817 | 800 | ||
@@ -835,10 +818,9 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | |||
835 | return; | 818 | return; |
836 | } | 819 | } |
837 | 820 | ||
838 | ath_tx_pause_tid(sc, txtid); | ||
839 | |||
840 | /* drop all software retried frames and mark this TID */ | 821 | /* drop all software retried frames and mark this TID */ |
841 | spin_lock_bh(&txq->axq_lock); | 822 | spin_lock_bh(&txq->axq_lock); |
823 | txtid->paused = true; | ||
842 | while (!list_empty(&txtid->buf_q)) { | 824 | while (!list_empty(&txtid->buf_q)) { |
843 | bf = list_first_entry(&txtid->buf_q, struct ath_buf, list); | 825 | bf = list_first_entry(&txtid->buf_q, struct ath_buf, list); |
844 | if (!bf_isretried(bf)) { | 826 | if (!bf_isretried(bf)) { |
@@ -1181,7 +1163,7 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) | |||
1181 | "Failed to stop TX DMA. Resetting hardware!\n"); | 1163 | "Failed to stop TX DMA. Resetting hardware!\n"); |
1182 | 1164 | ||
1183 | spin_lock_bh(&sc->sc_resetlock); | 1165 | spin_lock_bh(&sc->sc_resetlock); |
1184 | r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false); | 1166 | r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false); |
1185 | if (r) | 1167 | if (r) |
1186 | ath_print(common, ATH_DBG_FATAL, | 1168 | ath_print(common, ATH_DBG_FATAL, |
1187 | "Unable to reset hardware; reset status %d\n", | 1169 | "Unable to reset hardware; reset status %d\n", |