diff options
258 files changed, 23444 insertions, 3956 deletions
diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl index 284ced7a228f..0f6a3edcd44b 100644 --- a/Documentation/DocBook/80211.tmpl +++ b/Documentation/DocBook/80211.tmpl | |||
@@ -437,7 +437,7 @@ | |||
437 | </section> | 437 | </section> |
438 | !Finclude/net/mac80211.h ieee80211_get_buffered_bc | 438 | !Finclude/net/mac80211.h ieee80211_get_buffered_bc |
439 | !Finclude/net/mac80211.h ieee80211_beacon_get | 439 | !Finclude/net/mac80211.h ieee80211_beacon_get |
440 | !Finclude/net/mac80211.h ieee80211_sta_eosp_irqsafe | 440 | !Finclude/net/mac80211.h ieee80211_sta_eosp |
441 | !Finclude/net/mac80211.h ieee80211_frame_release_type | 441 | !Finclude/net/mac80211.h ieee80211_frame_release_type |
442 | !Finclude/net/mac80211.h ieee80211_sta_ps_transition | 442 | !Finclude/net/mac80211.h ieee80211_sta_ps_transition |
443 | !Finclude/net/mac80211.h ieee80211_sta_ps_transition_ni | 443 | !Finclude/net/mac80211.h ieee80211_sta_ps_transition_ni |
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c index 28fa50ad87be..036c6744b39b 100644 --- a/drivers/bcma/driver_chipcommon.c +++ b/drivers/bcma/driver_chipcommon.c | |||
@@ -25,13 +25,14 @@ static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset, | |||
25 | return value; | 25 | return value; |
26 | } | 26 | } |
27 | 27 | ||
28 | static u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc) | 28 | u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc) |
29 | { | 29 | { |
30 | if (cc->capabilities & BCMA_CC_CAP_PMU) | 30 | if (cc->capabilities & BCMA_CC_CAP_PMU) |
31 | return bcma_pmu_get_alp_clock(cc); | 31 | return bcma_pmu_get_alp_clock(cc); |
32 | 32 | ||
33 | return 20000000; | 33 | return 20000000; |
34 | } | 34 | } |
35 | EXPORT_SYMBOL_GPL(bcma_chipco_get_alp_clock); | ||
35 | 36 | ||
36 | static u32 bcma_chipco_watchdog_get_max_timer(struct bcma_drv_cc *cc) | 37 | static u32 bcma_chipco_watchdog_get_max_timer(struct bcma_drv_cc *cc) |
37 | { | 38 | { |
@@ -213,6 +214,7 @@ u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value) | |||
213 | 214 | ||
214 | return res; | 215 | return res; |
215 | } | 216 | } |
217 | EXPORT_SYMBOL_GPL(bcma_chipco_gpio_out); | ||
216 | 218 | ||
217 | u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value) | 219 | u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value) |
218 | { | 220 | { |
@@ -225,6 +227,7 @@ u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value) | |||
225 | 227 | ||
226 | return res; | 228 | return res; |
227 | } | 229 | } |
230 | EXPORT_SYMBOL_GPL(bcma_chipco_gpio_outen); | ||
228 | 231 | ||
229 | /* | 232 | /* |
230 | * If the bit is set to 0, chipcommon controlls this GPIO, | 233 | * If the bit is set to 0, chipcommon controlls this GPIO, |
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c index 932b101dee36..edca73af3cc0 100644 --- a/drivers/bcma/driver_chipcommon_pmu.c +++ b/drivers/bcma/driver_chipcommon_pmu.c | |||
@@ -174,19 +174,35 @@ u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc) | |||
174 | struct bcma_bus *bus = cc->core->bus; | 174 | struct bcma_bus *bus = cc->core->bus; |
175 | 175 | ||
176 | switch (bus->chipinfo.id) { | 176 | switch (bus->chipinfo.id) { |
177 | case BCMA_CHIP_ID_BCM4313: | ||
178 | case BCMA_CHIP_ID_BCM43224: | ||
179 | case BCMA_CHIP_ID_BCM43225: | ||
180 | case BCMA_CHIP_ID_BCM43227: | ||
181 | case BCMA_CHIP_ID_BCM43228: | ||
182 | case BCMA_CHIP_ID_BCM4331: | ||
183 | case BCMA_CHIP_ID_BCM43421: | ||
184 | case BCMA_CHIP_ID_BCM43428: | ||
185 | case BCMA_CHIP_ID_BCM43431: | ||
177 | case BCMA_CHIP_ID_BCM4716: | 186 | case BCMA_CHIP_ID_BCM4716: |
178 | case BCMA_CHIP_ID_BCM4748: | ||
179 | case BCMA_CHIP_ID_BCM47162: | 187 | case BCMA_CHIP_ID_BCM47162: |
180 | case BCMA_CHIP_ID_BCM4313: | 188 | case BCMA_CHIP_ID_BCM4748: |
181 | case BCMA_CHIP_ID_BCM5357: | ||
182 | case BCMA_CHIP_ID_BCM4749: | 189 | case BCMA_CHIP_ID_BCM4749: |
190 | case BCMA_CHIP_ID_BCM5357: | ||
183 | case BCMA_CHIP_ID_BCM53572: | 191 | case BCMA_CHIP_ID_BCM53572: |
192 | case BCMA_CHIP_ID_BCM6362: | ||
184 | /* always 20Mhz */ | 193 | /* always 20Mhz */ |
185 | return 20000 * 1000; | 194 | return 20000 * 1000; |
186 | case BCMA_CHIP_ID_BCM5356: | ||
187 | case BCMA_CHIP_ID_BCM4706: | 195 | case BCMA_CHIP_ID_BCM4706: |
196 | case BCMA_CHIP_ID_BCM5356: | ||
188 | /* always 25Mhz */ | 197 | /* always 25Mhz */ |
189 | return 25000 * 1000; | 198 | return 25000 * 1000; |
199 | case BCMA_CHIP_ID_BCM43460: | ||
200 | case BCMA_CHIP_ID_BCM4352: | ||
201 | case BCMA_CHIP_ID_BCM4360: | ||
202 | if (cc->status & BCMA_CC_CHIPST_4360_XTAL_40MZ) | ||
203 | return 40000 * 1000; | ||
204 | else | ||
205 | return 20000 * 1000; | ||
190 | default: | 206 | default: |
191 | bcma_warn(bus, "No ALP clock specified for %04X device, pmu rev. %d, using default %d Hz\n", | 207 | bcma_warn(bus, "No ALP clock specified for %04X device, pmu rev. %d, using default %d Hz\n", |
192 | bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK); | 208 | bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK); |
@@ -373,7 +389,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) | |||
373 | tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT; | 389 | tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT; |
374 | bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp); | 390 | bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp); |
375 | 391 | ||
376 | tmp = 1 << 10; | 392 | tmp = BCMA_CC_PMU_CTL_PLL_UPD; |
377 | break; | 393 | break; |
378 | 394 | ||
379 | case BCMA_CHIP_ID_BCM4331: | 395 | case BCMA_CHIP_ID_BCM4331: |
@@ -394,7 +410,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) | |||
394 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, | 410 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, |
395 | 0x03000a08); | 411 | 0x03000a08); |
396 | } | 412 | } |
397 | tmp = 1 << 10; | 413 | tmp = BCMA_CC_PMU_CTL_PLL_UPD; |
398 | break; | 414 | break; |
399 | 415 | ||
400 | case BCMA_CHIP_ID_BCM43224: | 416 | case BCMA_CHIP_ID_BCM43224: |
@@ -427,7 +443,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) | |||
427 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, | 443 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, |
428 | 0x88888815); | 444 | 0x88888815); |
429 | } | 445 | } |
430 | tmp = 1 << 10; | 446 | tmp = BCMA_CC_PMU_CTL_PLL_UPD; |
431 | break; | 447 | break; |
432 | 448 | ||
433 | case BCMA_CHIP_ID_BCM4716: | 449 | case BCMA_CHIP_ID_BCM4716: |
@@ -461,7 +477,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) | |||
461 | 0x88888815); | 477 | 0x88888815); |
462 | } | 478 | } |
463 | 479 | ||
464 | tmp = 3 << 9; | 480 | tmp = BCMA_CC_PMU_CTL_PLL_UPD | BCMA_CC_PMU_CTL_NOILPONW; |
465 | break; | 481 | break; |
466 | 482 | ||
467 | case BCMA_CHIP_ID_BCM43227: | 483 | case BCMA_CHIP_ID_BCM43227: |
@@ -497,7 +513,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) | |||
497 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, | 513 | bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, |
498 | 0x88888815); | 514 | 0x88888815); |
499 | } | 515 | } |
500 | tmp = 1 << 10; | 516 | tmp = BCMA_CC_PMU_CTL_PLL_UPD; |
501 | break; | 517 | break; |
502 | default: | 518 | default: |
503 | bcma_err(bus, "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n", | 519 | bcma_err(bus, "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n", |
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c index 8d0b57164018..bca9c80056fe 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c | |||
@@ -137,19 +137,19 @@ static void bcma_scan_switch_core(struct bcma_bus *bus, u32 addr) | |||
137 | addr); | 137 | addr); |
138 | } | 138 | } |
139 | 139 | ||
140 | static u32 bcma_erom_get_ent(struct bcma_bus *bus, u32 **eromptr) | 140 | static u32 bcma_erom_get_ent(struct bcma_bus *bus, u32 __iomem **eromptr) |
141 | { | 141 | { |
142 | u32 ent = readl(*eromptr); | 142 | u32 ent = readl(*eromptr); |
143 | (*eromptr)++; | 143 | (*eromptr)++; |
144 | return ent; | 144 | return ent; |
145 | } | 145 | } |
146 | 146 | ||
147 | static void bcma_erom_push_ent(u32 **eromptr) | 147 | static void bcma_erom_push_ent(u32 __iomem **eromptr) |
148 | { | 148 | { |
149 | (*eromptr)--; | 149 | (*eromptr)--; |
150 | } | 150 | } |
151 | 151 | ||
152 | static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 **eromptr) | 152 | static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 __iomem **eromptr) |
153 | { | 153 | { |
154 | u32 ent = bcma_erom_get_ent(bus, eromptr); | 154 | u32 ent = bcma_erom_get_ent(bus, eromptr); |
155 | if (!(ent & SCAN_ER_VALID)) | 155 | if (!(ent & SCAN_ER_VALID)) |
@@ -159,14 +159,14 @@ static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 **eromptr) | |||
159 | return ent; | 159 | return ent; |
160 | } | 160 | } |
161 | 161 | ||
162 | static bool bcma_erom_is_end(struct bcma_bus *bus, u32 **eromptr) | 162 | static bool bcma_erom_is_end(struct bcma_bus *bus, u32 __iomem **eromptr) |
163 | { | 163 | { |
164 | u32 ent = bcma_erom_get_ent(bus, eromptr); | 164 | u32 ent = bcma_erom_get_ent(bus, eromptr); |
165 | bcma_erom_push_ent(eromptr); | 165 | bcma_erom_push_ent(eromptr); |
166 | return (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID)); | 166 | return (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID)); |
167 | } | 167 | } |
168 | 168 | ||
169 | static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 **eromptr) | 169 | static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 __iomem **eromptr) |
170 | { | 170 | { |
171 | u32 ent = bcma_erom_get_ent(bus, eromptr); | 171 | u32 ent = bcma_erom_get_ent(bus, eromptr); |
172 | bcma_erom_push_ent(eromptr); | 172 | bcma_erom_push_ent(eromptr); |
@@ -175,7 +175,7 @@ static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 **eromptr) | |||
175 | ((ent & SCAN_ADDR_TYPE) == SCAN_ADDR_TYPE_BRIDGE)); | 175 | ((ent & SCAN_ADDR_TYPE) == SCAN_ADDR_TYPE_BRIDGE)); |
176 | } | 176 | } |
177 | 177 | ||
178 | static void bcma_erom_skip_component(struct bcma_bus *bus, u32 **eromptr) | 178 | static void bcma_erom_skip_component(struct bcma_bus *bus, u32 __iomem **eromptr) |
179 | { | 179 | { |
180 | u32 ent; | 180 | u32 ent; |
181 | while (1) { | 181 | while (1) { |
@@ -189,7 +189,7 @@ static void bcma_erom_skip_component(struct bcma_bus *bus, u32 **eromptr) | |||
189 | bcma_erom_push_ent(eromptr); | 189 | bcma_erom_push_ent(eromptr); |
190 | } | 190 | } |
191 | 191 | ||
192 | static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 **eromptr) | 192 | static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 __iomem **eromptr) |
193 | { | 193 | { |
194 | u32 ent = bcma_erom_get_ent(bus, eromptr); | 194 | u32 ent = bcma_erom_get_ent(bus, eromptr); |
195 | if (!(ent & SCAN_ER_VALID)) | 195 | if (!(ent & SCAN_ER_VALID)) |
@@ -199,7 +199,7 @@ static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 **eromptr) | |||
199 | return ent; | 199 | return ent; |
200 | } | 200 | } |
201 | 201 | ||
202 | static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 **eromptr, | 202 | static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 __iomem **eromptr, |
203 | u32 type, u8 port) | 203 | u32 type, u8 port) |
204 | { | 204 | { |
205 | u32 addrl, addrh, sizel, sizeh = 0; | 205 | u32 addrl, addrh, sizel, sizeh = 0; |
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index 4adf9ef9a113..8934298a638d 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c | |||
@@ -217,6 +217,7 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) | |||
217 | } | 217 | } |
218 | 218 | ||
219 | SPEX(board_rev, SSB_SPROM8_BOARDREV, ~0, 0); | 219 | SPEX(board_rev, SSB_SPROM8_BOARDREV, ~0, 0); |
220 | SPEX(board_type, SSB_SPROM1_SPID, ~0, 0); | ||
220 | 221 | ||
221 | SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0, | 222 | SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0, |
222 | SSB_SPROM4_TXPID2G0_SHIFT); | 223 | SSB_SPROM4_TXPID2G0_SHIFT); |
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 9959d4cb23dc..1cb51839912d 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c | |||
@@ -83,8 +83,8 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = { | |||
83 | }; | 83 | }; |
84 | 84 | ||
85 | static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = { | 85 | static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = { |
86 | .helper = "sd8688_helper.bin", | 86 | .helper = "mrvl/sd8688_helper.bin", |
87 | .firmware = "sd8688.bin", | 87 | .firmware = "mrvl/sd8688.bin", |
88 | .reg = &btmrvl_reg_8688, | 88 | .reg = &btmrvl_reg_8688, |
89 | .sd_blksz_fw_dl = 64, | 89 | .sd_blksz_fw_dl = 64, |
90 | }; | 90 | }; |
@@ -1185,7 +1185,7 @@ MODULE_AUTHOR("Marvell International Ltd."); | |||
1185 | MODULE_DESCRIPTION("Marvell BT-over-SDIO driver ver " VERSION); | 1185 | MODULE_DESCRIPTION("Marvell BT-over-SDIO driver ver " VERSION); |
1186 | MODULE_VERSION(VERSION); | 1186 | MODULE_VERSION(VERSION); |
1187 | MODULE_LICENSE("GPL v2"); | 1187 | MODULE_LICENSE("GPL v2"); |
1188 | MODULE_FIRMWARE("sd8688_helper.bin"); | 1188 | MODULE_FIRMWARE("mrvl/sd8688_helper.bin"); |
1189 | MODULE_FIRMWARE("sd8688.bin"); | 1189 | MODULE_FIRMWARE("mrvl/sd8688.bin"); |
1190 | MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); | 1190 | MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); |
1191 | MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin"); | 1191 | MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin"); |
diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c index 7157f7d311c5..afd1e36d308f 100644 --- a/drivers/net/wireless/ath/ar5523/ar5523.c +++ b/drivers/net/wireless/ath/ar5523/ar5523.c | |||
@@ -1091,7 +1091,7 @@ static int ar5523_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | |||
1091 | return ret; | 1091 | return ret; |
1092 | } | 1092 | } |
1093 | 1093 | ||
1094 | static void ar5523_flush(struct ieee80211_hw *hw, bool drop) | 1094 | static void ar5523_flush(struct ieee80211_hw *hw, u32 queues, bool drop) |
1095 | { | 1095 | { |
1096 | struct ar5523 *ar = hw->priv; | 1096 | struct ar5523 *ar = hw->priv; |
1097 | 1097 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index c55e5bbafc46..9f589744a9f9 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c | |||
@@ -731,7 +731,8 @@ static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
731 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, | 731 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, |
732 | AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { | 732 | AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { |
733 | ath_dbg(common, CALIBRATE, | 733 | ath_dbg(common, CALIBRATE, |
734 | "offset calibration failed to complete in 1ms; noisy environment?\n"); | 734 | "offset calibration failed to complete in %d ms; noisy environment?\n", |
735 | AH_WAIT_TIMEOUT / 1000); | ||
735 | return false; | 736 | return false; |
736 | } | 737 | } |
737 | REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); | 738 | REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); |
@@ -745,7 +746,8 @@ static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
745 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, | 746 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, |
746 | 0, AH_WAIT_TIMEOUT)) { | 747 | 0, AH_WAIT_TIMEOUT)) { |
747 | ath_dbg(common, CALIBRATE, | 748 | ath_dbg(common, CALIBRATE, |
748 | "offset calibration failed to complete in 1ms; noisy environment?\n"); | 749 | "offset calibration failed to complete in %d ms; noisy environment?\n", |
750 | AH_WAIT_TIMEOUT / 1000); | ||
749 | return false; | 751 | return false; |
750 | } | 752 | } |
751 | 753 | ||
@@ -841,7 +843,8 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
841 | AR_PHY_AGC_CONTROL_CAL, | 843 | AR_PHY_AGC_CONTROL_CAL, |
842 | 0, AH_WAIT_TIMEOUT)) { | 844 | 0, AH_WAIT_TIMEOUT)) { |
843 | ath_dbg(common, CALIBRATE, | 845 | ath_dbg(common, CALIBRATE, |
844 | "offset calibration failed to complete in 1ms; noisy environment?\n"); | 846 | "offset calibration failed to complete in %d ms; noisy environment?\n", |
847 | AH_WAIT_TIMEOUT / 1000); | ||
845 | return false; | 848 | return false; |
846 | } | 849 | } |
847 | 850 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index f76c3ca07a45..639ba7d18ea4 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
@@ -1126,7 +1126,8 @@ skip_tx_iqcal: | |||
1126 | ar9003_hw_rtt_disable(ah); | 1126 | ar9003_hw_rtt_disable(ah); |
1127 | 1127 | ||
1128 | ath_dbg(common, CALIBRATE, | 1128 | ath_dbg(common, CALIBRATE, |
1129 | "offset calibration failed to complete in 1ms; noisy environment?\n"); | 1129 | "offset calibration failed to complete in %d ms; noisy environment?\n", |
1130 | AH_WAIT_TIMEOUT / 1000); | ||
1130 | return false; | 1131 | return false; |
1131 | } | 1132 | } |
1132 | 1133 | ||
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 67a2a4b3b883..e6307b86363a 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -2072,7 +2072,7 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
2072 | &fops_modal_eeprom); | 2072 | &fops_modal_eeprom); |
2073 | sc->rfs_chan_spec_scan = relay_open("spectral_scan", | 2073 | sc->rfs_chan_spec_scan = relay_open("spectral_scan", |
2074 | sc->debug.debugfs_phy, | 2074 | sc->debug.debugfs_phy, |
2075 | 262144, 4, &rfs_spec_scan_cb, | 2075 | 1024, 256, &rfs_spec_scan_cb, |
2076 | NULL); | 2076 | NULL); |
2077 | debugfs_create_file("spectral_scan_ctl", S_IRUSR | S_IWUSR, | 2077 | debugfs_create_file("spectral_scan_ctl", S_IRUSR | S_IWUSR, |
2078 | sc->debug.debugfs_phy, sc, | 2078 | sc->debug.debugfs_phy, sc, |
diff --git a/drivers/net/wireless/ath/ath9k/dfs.c b/drivers/net/wireless/ath/ath9k/dfs.c index ecc81792f2dc..508f8b33f0ef 100644 --- a/drivers/net/wireless/ath/ath9k/dfs.c +++ b/drivers/net/wireless/ath/ath9k/dfs.c | |||
@@ -193,9 +193,7 @@ void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data, | |||
193 | DFS_STAT_INC(sc, pulses_processed); | 193 | DFS_STAT_INC(sc, pulses_processed); |
194 | if (pd != NULL && pd->add_pulse(pd, &pe)) { | 194 | if (pd != NULL && pd->add_pulse(pd, &pe)) { |
195 | DFS_STAT_INC(sc, radar_detected); | 195 | DFS_STAT_INC(sc, radar_detected); |
196 | /* | 196 | ieee80211_radar_detected(sc->hw); |
197 | * TODO: forward radar event to DFS management layer | ||
198 | */ | ||
199 | } | 197 | } |
200 | } | 198 | } |
201 | } | 199 | } |
diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.c b/drivers/net/wireless/ath/ath9k/dfs_debug.c index 55d28072adeb..b7611b7bbe43 100644 --- a/drivers/net/wireless/ath/ath9k/dfs_debug.c +++ b/drivers/net/wireless/ath/ath9k/dfs_debug.c | |||
@@ -105,6 +105,24 @@ static ssize_t write_file_dfs(struct file *file, const char __user *user_buf, | |||
105 | return count; | 105 | return count; |
106 | } | 106 | } |
107 | 107 | ||
108 | static ssize_t write_file_simulate_radar(struct file *file, | ||
109 | const char __user *user_buf, | ||
110 | size_t count, loff_t *ppos) | ||
111 | { | ||
112 | struct ath_softc *sc = file->private_data; | ||
113 | |||
114 | ieee80211_radar_detected(sc->hw); | ||
115 | |||
116 | return count; | ||
117 | } | ||
118 | |||
119 | static const struct file_operations fops_simulate_radar = { | ||
120 | .write = write_file_simulate_radar, | ||
121 | .open = simple_open, | ||
122 | .owner = THIS_MODULE, | ||
123 | .llseek = default_llseek, | ||
124 | }; | ||
125 | |||
108 | static const struct file_operations fops_dfs_stats = { | 126 | static const struct file_operations fops_dfs_stats = { |
109 | .read = read_file_dfs, | 127 | .read = read_file_dfs, |
110 | .write = write_file_dfs, | 128 | .write = write_file_dfs, |
@@ -117,4 +135,6 @@ void ath9k_dfs_init_debug(struct ath_softc *sc) | |||
117 | { | 135 | { |
118 | debugfs_create_file("dfs_stats", S_IRUSR, | 136 | debugfs_create_file("dfs_stats", S_IRUSR, |
119 | sc->debug.debugfs_phy, sc, &fops_dfs_stats); | 137 | sc->debug.debugfs_phy, sc, &fops_dfs_stats); |
138 | debugfs_create_file("dfs_simulate_radar", S_IWUSR, | ||
139 | sc->debug.debugfs_phy, sc, &fops_simulate_radar); | ||
120 | } | 140 | } |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 4fa2bb167050..3473a797651a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -2380,8 +2380,11 @@ static bool ath9k_hw_dfs_tested(struct ath_hw *ah) | |||
2380 | { | 2380 | { |
2381 | 2381 | ||
2382 | switch (ah->hw_version.macVersion) { | 2382 | switch (ah->hw_version.macVersion) { |
2383 | /* for temporary testing DFS with 9280 */ | ||
2384 | case AR_SREV_VERSION_9280: | ||
2383 | /* AR9580 will likely be our first target to get testing on */ | 2385 | /* AR9580 will likely be our first target to get testing on */ |
2384 | case AR_SREV_VERSION_9580: | 2386 | case AR_SREV_VERSION_9580: |
2387 | return true; | ||
2385 | default: | 2388 | default: |
2386 | return false; | 2389 | return false; |
2387 | } | 2390 | } |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index af932c9444de..3be2eb0da84a 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -319,6 +319,10 @@ static void ath9k_reg_notifier(struct wiphy *wiphy, | |||
319 | ath9k_ps_wakeup(sc); | 319 | ath9k_ps_wakeup(sc); |
320 | ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false); | 320 | ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false); |
321 | sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit; | 321 | sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit; |
322 | /* synchronize DFS detector if regulatory domain changed */ | ||
323 | if (sc->dfs_detector != NULL) | ||
324 | sc->dfs_detector->set_dfs_domain(sc->dfs_detector, | ||
325 | request->dfs_region); | ||
322 | ath9k_ps_restore(sc); | 326 | ath9k_ps_restore(sc); |
323 | } | 327 | } |
324 | } | 328 | } |
@@ -727,12 +731,28 @@ static const struct ieee80211_iface_limit if_limits[] = { | |||
727 | BIT(NL80211_IFTYPE_P2P_GO) }, | 731 | BIT(NL80211_IFTYPE_P2P_GO) }, |
728 | }; | 732 | }; |
729 | 733 | ||
730 | static const struct ieee80211_iface_combination if_comb = { | 734 | |
731 | .limits = if_limits, | 735 | static const struct ieee80211_iface_limit if_dfs_limits[] = { |
732 | .n_limits = ARRAY_SIZE(if_limits), | 736 | { .max = 1, .types = BIT(NL80211_IFTYPE_AP) }, |
733 | .max_interfaces = 2048, | 737 | }; |
734 | .num_different_channels = 1, | 738 | |
735 | .beacon_int_infra_match = true, | 739 | static const struct ieee80211_iface_combination if_comb[] = { |
740 | { | ||
741 | .limits = if_limits, | ||
742 | .n_limits = ARRAY_SIZE(if_limits), | ||
743 | .max_interfaces = 2048, | ||
744 | .num_different_channels = 1, | ||
745 | .beacon_int_infra_match = true, | ||
746 | }, | ||
747 | { | ||
748 | .limits = if_dfs_limits, | ||
749 | .n_limits = ARRAY_SIZE(if_dfs_limits), | ||
750 | .max_interfaces = 1, | ||
751 | .num_different_channels = 1, | ||
752 | .beacon_int_infra_match = true, | ||
753 | .radar_detect_widths = BIT(NL80211_CHAN_NO_HT) | | ||
754 | BIT(NL80211_CHAN_HT20), | ||
755 | } | ||
736 | }; | 756 | }; |
737 | 757 | ||
738 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | 758 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) |
@@ -763,8 +783,8 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
763 | BIT(NL80211_IFTYPE_ADHOC) | | 783 | BIT(NL80211_IFTYPE_ADHOC) | |
764 | BIT(NL80211_IFTYPE_MESH_POINT); | 784 | BIT(NL80211_IFTYPE_MESH_POINT); |
765 | 785 | ||
766 | hw->wiphy->iface_combinations = &if_comb; | 786 | hw->wiphy->iface_combinations = if_comb; |
767 | hw->wiphy->n_iface_combinations = 1; | 787 | hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); |
768 | 788 | ||
769 | if (AR_SREV_5416(sc->sc_ah)) | 789 | if (AR_SREV_5416(sc->sc_ah)) |
770 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 790 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 6e66f9c6782b..1bf52c88004a 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -280,6 +280,10 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan) | |||
280 | if (r) { | 280 | if (r) { |
281 | ath_err(common, | 281 | ath_err(common, |
282 | "Unable to reset channel, reset status %d\n", r); | 282 | "Unable to reset channel, reset status %d\n", r); |
283 | |||
284 | ath9k_hw_enable_interrupts(ah); | ||
285 | ath9k_queue_reset(sc, RESET_TYPE_BB_HANG); | ||
286 | |||
283 | goto out; | 287 | goto out; |
284 | } | 288 | } |
285 | 289 | ||
@@ -1245,10 +1249,27 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1245 | if (old_pos >= 0) | 1249 | if (old_pos >= 0) |
1246 | ath_update_survey_nf(sc, old_pos); | 1250 | ath_update_survey_nf(sc, old_pos); |
1247 | 1251 | ||
1248 | /* perform spectral scan if requested. */ | 1252 | /* |
1249 | if (sc->scanning && sc->spectral_mode == SPECTRAL_CHANSCAN) | 1253 | * Enable radar pulse detection if on a DFS channel. Spectral |
1250 | ath9k_spectral_scan_trigger(hw); | 1254 | * scanning and radar detection can not be used concurrently. |
1251 | 1255 | */ | |
1256 | if (hw->conf.radar_enabled) { | ||
1257 | u32 rxfilter; | ||
1258 | |||
1259 | /* set HW specific DFS configuration */ | ||
1260 | ath9k_hw_set_radar_params(ah); | ||
1261 | rxfilter = ath9k_hw_getrxfilter(ah); | ||
1262 | rxfilter |= ATH9K_RX_FILTER_PHYRADAR | | ||
1263 | ATH9K_RX_FILTER_PHYERR; | ||
1264 | ath9k_hw_setrxfilter(ah, rxfilter); | ||
1265 | ath_dbg(common, DFS, "DFS enabled at freq %d\n", | ||
1266 | curchan->center_freq); | ||
1267 | } else { | ||
1268 | /* perform spectral scan if requested. */ | ||
1269 | if (sc->scanning && | ||
1270 | sc->spectral_mode == SPECTRAL_CHANSCAN) | ||
1271 | ath9k_spectral_scan_trigger(hw); | ||
1272 | } | ||
1252 | } | 1273 | } |
1253 | 1274 | ||
1254 | if (changed & IEEE80211_CONF_CHANGE_POWER) { | 1275 | if (changed & IEEE80211_CONF_CHANGE_POWER) { |
@@ -1745,7 +1766,7 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) | |||
1745 | mutex_unlock(&sc->mutex); | 1766 | mutex_unlock(&sc->mutex); |
1746 | } | 1767 | } |
1747 | 1768 | ||
1748 | static void ath9k_flush(struct ieee80211_hw *hw, bool drop) | 1769 | static void ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) |
1749 | { | 1770 | { |
1750 | struct ath_softc *sc = hw->priv; | 1771 | struct ath_softc *sc = hw->priv; |
1751 | struct ath_hw *ah = sc->sc_ah; | 1772 | struct ath_hw *ah = sc->sc_ah; |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index ee156e543147..ee7ca5aecdb0 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -381,6 +381,10 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
381 | rfilt = ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST | 381 | rfilt = ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST |
382 | | ATH9K_RX_FILTER_MCAST; | 382 | | ATH9K_RX_FILTER_MCAST; |
383 | 383 | ||
384 | /* if operating on a DFS channel, enable radar pulse detection */ | ||
385 | if (sc->hw->conf.radar_enabled) | ||
386 | rfilt |= ATH9K_RX_FILTER_PHYRADAR | ATH9K_RX_FILTER_PHYERR; | ||
387 | |||
384 | if (sc->rx.rxfilter & FIF_PROBE_REQ) | 388 | if (sc->rx.rxfilter & FIF_PROBE_REQ) |
385 | rfilt |= ATH9K_RX_FILTER_PROBEREQ; | 389 | rfilt |= ATH9K_RX_FILTER_PROBEREQ; |
386 | 390 | ||
@@ -1228,6 +1232,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1228 | unlikely(tsf_lower - rs.rs_tstamp > 0x10000000)) | 1232 | unlikely(tsf_lower - rs.rs_tstamp > 0x10000000)) |
1229 | rxs->mactime += 0x100000000ULL; | 1233 | rxs->mactime += 0x100000000ULL; |
1230 | 1234 | ||
1235 | if (rs.rs_phyerr == ATH9K_PHYERR_RADAR) | ||
1236 | ath9k_dfs_process_phyerr(sc, hdr, &rs, rxs->mactime); | ||
1237 | |||
1231 | if (rs.rs_status & ATH9K_RXERR_PHY) { | 1238 | if (rs.rs_status & ATH9K_RXERR_PHY) { |
1232 | if (ath_process_fft(sc, hdr, &rs, rxs->mactime)) { | 1239 | if (ath_process_fft(sc, hdr, &rs, rxs->mactime)) { |
1233 | RX_STAT_INC(rx_spectral); | 1240 | RX_STAT_INC(rx_spectral); |
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index 25599741cd8a..9dce106cd6d4 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h | |||
@@ -70,12 +70,6 @@ | |||
70 | 70 | ||
71 | static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 3, 2, 1, 0 }; | 71 | static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 3, 2, 1, 0 }; |
72 | 72 | ||
73 | enum carl9170_rf_init_mode { | ||
74 | CARL9170_RFI_NONE, | ||
75 | CARL9170_RFI_WARM, | ||
76 | CARL9170_RFI_COLD, | ||
77 | }; | ||
78 | |||
79 | #define CARL9170_MAX_RX_BUFFER_SIZE 8192 | 73 | #define CARL9170_MAX_RX_BUFFER_SIZE 8192 |
80 | 74 | ||
81 | enum carl9170_device_state { | 75 | enum carl9170_device_state { |
@@ -599,7 +593,7 @@ int carl9170_led_set_state(struct ar9170 *ar, const u32 led_state); | |||
599 | 593 | ||
600 | /* PHY / RF */ | 594 | /* PHY / RF */ |
601 | int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, | 595 | int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, |
602 | enum nl80211_channel_type bw, enum carl9170_rf_init_mode rfi); | 596 | enum nl80211_channel_type bw); |
603 | int carl9170_get_noisefloor(struct ar9170 *ar); | 597 | int carl9170_get_noisefloor(struct ar9170 *ar); |
604 | 598 | ||
605 | /* FW */ | 599 | /* FW */ |
diff --git a/drivers/net/wireless/ath/carl9170/debug.c b/drivers/net/wireless/ath/carl9170/debug.c index 93fe6003a493..40109be81f7c 100644 --- a/drivers/net/wireless/ath/carl9170/debug.c +++ b/drivers/net/wireless/ath/carl9170/debug.c | |||
@@ -655,7 +655,7 @@ static ssize_t carl9170_debugfs_bug_write(struct ar9170 *ar, const char *buf, | |||
655 | 655 | ||
656 | case 'P': | 656 | case 'P': |
657 | err = carl9170_set_channel(ar, ar->hw->conf.channel, | 657 | err = carl9170_set_channel(ar, ar->hw->conf.channel, |
658 | ar->hw->conf.channel_type, CARL9170_RFI_COLD); | 658 | ar->hw->conf.channel_type); |
659 | if (err < 0) | 659 | if (err < 0) |
660 | count = err; | 660 | count = err; |
661 | 661 | ||
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index f293b3ff4756..699c557bc2c7 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c | |||
@@ -939,7 +939,7 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed) | |||
939 | goto out; | 939 | goto out; |
940 | 940 | ||
941 | err = carl9170_set_channel(ar, hw->conf.channel, | 941 | err = carl9170_set_channel(ar, hw->conf.channel, |
942 | hw->conf.channel_type, CARL9170_RFI_NONE); | 942 | hw->conf.channel_type); |
943 | if (err) | 943 | if (err) |
944 | goto out; | 944 | goto out; |
945 | 945 | ||
@@ -1703,7 +1703,7 @@ found: | |||
1703 | return 0; | 1703 | return 0; |
1704 | } | 1704 | } |
1705 | 1705 | ||
1706 | static void carl9170_op_flush(struct ieee80211_hw *hw, bool drop) | 1706 | static void carl9170_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop) |
1707 | { | 1707 | { |
1708 | struct ar9170 *ar = hw->priv; | 1708 | struct ar9170 *ar = hw->priv; |
1709 | unsigned int vid; | 1709 | unsigned int vid; |
diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c index b72c09cf43a4..07f82234c860 100644 --- a/drivers/net/wireless/ath/carl9170/phy.c +++ b/drivers/net/wireless/ath/carl9170/phy.c | |||
@@ -1569,16 +1569,14 @@ static enum carl9170_bw nl80211_to_carl(enum nl80211_channel_type type) | |||
1569 | } | 1569 | } |
1570 | 1570 | ||
1571 | int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, | 1571 | int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, |
1572 | enum nl80211_channel_type _bw, | 1572 | enum nl80211_channel_type _bw) |
1573 | enum carl9170_rf_init_mode rfi) | ||
1574 | { | 1573 | { |
1575 | const struct carl9170_phy_freq_params *freqpar; | 1574 | const struct carl9170_phy_freq_params *freqpar; |
1576 | struct carl9170_rf_init_result rf_res; | 1575 | struct carl9170_rf_init_result rf_res; |
1577 | struct carl9170_rf_init rf; | 1576 | struct carl9170_rf_init rf; |
1578 | u32 cmd, tmp, offs = 0, new_ht = 0; | 1577 | u32 tmp, offs = 0, new_ht = 0; |
1579 | int err; | 1578 | int err; |
1580 | enum carl9170_bw bw; | 1579 | enum carl9170_bw bw; |
1581 | bool warm_reset; | ||
1582 | struct ieee80211_channel *old_channel = NULL; | 1580 | struct ieee80211_channel *old_channel = NULL; |
1583 | 1581 | ||
1584 | bw = nl80211_to_carl(_bw); | 1582 | bw = nl80211_to_carl(_bw); |
@@ -1592,51 +1590,27 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, | |||
1592 | /* may be NULL at first setup */ | 1590 | /* may be NULL at first setup */ |
1593 | if (ar->channel) { | 1591 | if (ar->channel) { |
1594 | old_channel = ar->channel; | 1592 | old_channel = ar->channel; |
1595 | warm_reset = (old_channel->band != channel->band) || | ||
1596 | (old_channel->center_freq == | ||
1597 | channel->center_freq) || | ||
1598 | (ar->ht_settings != new_ht); | ||
1599 | |||
1600 | ar->channel = NULL; | 1593 | ar->channel = NULL; |
1601 | } else { | ||
1602 | warm_reset = true; | ||
1603 | } | 1594 | } |
1604 | 1595 | ||
1605 | /* HW workaround */ | 1596 | /* cold reset BB/ADDA */ |
1606 | if (!ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] && | 1597 | err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, |
1607 | channel->center_freq <= 2417) | 1598 | AR9170_PWR_RESET_BB_COLD_RESET); |
1608 | warm_reset = true; | 1599 | if (err) |
1609 | 1600 | return err; | |
1610 | if (rfi != CARL9170_RFI_NONE || warm_reset) { | ||
1611 | u32 val; | ||
1612 | |||
1613 | if (rfi == CARL9170_RFI_COLD) | ||
1614 | val = AR9170_PWR_RESET_BB_COLD_RESET; | ||
1615 | else | ||
1616 | val = AR9170_PWR_RESET_BB_WARM_RESET; | ||
1617 | |||
1618 | /* warm/cold reset BB/ADDA */ | ||
1619 | err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, val); | ||
1620 | if (err) | ||
1621 | return err; | ||
1622 | |||
1623 | err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, 0x0); | ||
1624 | if (err) | ||
1625 | return err; | ||
1626 | 1601 | ||
1627 | err = carl9170_init_phy(ar, channel->band); | 1602 | err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, 0x0); |
1628 | if (err) | 1603 | if (err) |
1629 | return err; | 1604 | return err; |
1630 | 1605 | ||
1631 | err = carl9170_init_rf_banks_0_7(ar, | 1606 | err = carl9170_init_phy(ar, channel->band); |
1632 | channel->band == IEEE80211_BAND_5GHZ); | 1607 | if (err) |
1633 | if (err) | 1608 | return err; |
1634 | return err; | ||
1635 | 1609 | ||
1636 | cmd = CARL9170_CMD_RF_INIT; | 1610 | err = carl9170_init_rf_banks_0_7(ar, |
1637 | } else { | 1611 | channel->band == IEEE80211_BAND_5GHZ); |
1638 | cmd = CARL9170_CMD_FREQUENCY; | 1612 | if (err) |
1639 | } | 1613 | return err; |
1640 | 1614 | ||
1641 | err = carl9170_exec_cmd(ar, CARL9170_CMD_FREQ_START, 0, NULL, 0, NULL); | 1615 | err = carl9170_exec_cmd(ar, CARL9170_CMD_FREQ_START, 0, NULL, 0, NULL); |
1642 | if (err) | 1616 | if (err) |
@@ -1648,8 +1622,8 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, | |||
1648 | return err; | 1622 | return err; |
1649 | 1623 | ||
1650 | err = carl9170_init_rf_bank4_pwr(ar, | 1624 | err = carl9170_init_rf_bank4_pwr(ar, |
1651 | channel->band == IEEE80211_BAND_5GHZ, | 1625 | channel->band == IEEE80211_BAND_5GHZ, |
1652 | channel->center_freq, bw); | 1626 | channel->center_freq, bw); |
1653 | if (err) | 1627 | if (err) |
1654 | return err; | 1628 | return err; |
1655 | 1629 | ||
@@ -1703,13 +1677,8 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, | |||
1703 | rf.delta_slope_coeff_man = cpu_to_le32(freqpar->coeff_man); | 1677 | rf.delta_slope_coeff_man = cpu_to_le32(freqpar->coeff_man); |
1704 | rf.delta_slope_coeff_exp_shgi = cpu_to_le32(freqpar->coeff_exp_shgi); | 1678 | rf.delta_slope_coeff_exp_shgi = cpu_to_le32(freqpar->coeff_exp_shgi); |
1705 | rf.delta_slope_coeff_man_shgi = cpu_to_le32(freqpar->coeff_man_shgi); | 1679 | rf.delta_slope_coeff_man_shgi = cpu_to_le32(freqpar->coeff_man_shgi); |
1706 | 1680 | rf.finiteLoopCount = cpu_to_le32(2000); | |
1707 | if (rfi != CARL9170_RFI_NONE) | 1681 | err = carl9170_exec_cmd(ar, CARL9170_CMD_RF_INIT, sizeof(rf), &rf, |
1708 | rf.finiteLoopCount = cpu_to_le32(2000); | ||
1709 | else | ||
1710 | rf.finiteLoopCount = cpu_to_le32(1000); | ||
1711 | |||
1712 | err = carl9170_exec_cmd(ar, cmd, sizeof(rf), &rf, | ||
1713 | sizeof(rf_res), &rf_res); | 1682 | sizeof(rf_res), &rf_res); |
1714 | if (err) | 1683 | if (err) |
1715 | return err; | 1684 | return err; |
@@ -1724,9 +1693,8 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, | |||
1724 | old_channel->center_freq : -1, channel->center_freq, | 1693 | old_channel->center_freq : -1, channel->center_freq, |
1725 | err); | 1694 | err); |
1726 | 1695 | ||
1727 | if ((rfi == CARL9170_RFI_COLD) || (ar->chan_fail > 3)) { | 1696 | if (ar->chan_fail > 3) { |
1728 | /* | 1697 | /* We have tried very hard to change to _another_ |
1729 | * We have tried very hard to change to _another_ | ||
1730 | * channel and we've failed to do so! | 1698 | * channel and we've failed to do so! |
1731 | * Chances are that the PHY/RF is no longer | 1699 | * Chances are that the PHY/RF is no longer |
1732 | * operable (due to corruptions/fatal events/bugs?) | 1700 | * operable (due to corruptions/fatal events/bugs?) |
@@ -1736,8 +1704,7 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, | |||
1736 | return 0; | 1704 | return 0; |
1737 | } | 1705 | } |
1738 | 1706 | ||
1739 | err = carl9170_set_channel(ar, channel, _bw, | 1707 | err = carl9170_set_channel(ar, channel, _bw); |
1740 | CARL9170_RFI_COLD); | ||
1741 | if (err) | 1708 | if (err) |
1742 | return err; | 1709 | return err; |
1743 | } else { | 1710 | } else { |
diff --git a/drivers/net/wireless/ath/key.c b/drivers/net/wireless/ath/key.c index 5c54aa43ca2d..1816b4e7dc26 100644 --- a/drivers/net/wireless/ath/key.c +++ b/drivers/net/wireless/ath/key.c | |||
@@ -45,7 +45,8 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry) | |||
45 | void *ah = common->ah; | 45 | void *ah = common->ah; |
46 | 46 | ||
47 | if (entry >= common->keymax) { | 47 | if (entry >= common->keymax) { |
48 | ath_err(common, "keycache entry %u out of range\n", entry); | 48 | ath_err(common, "keyreset: keycache entry %u out of range\n", |
49 | entry); | ||
49 | return false; | 50 | return false; |
50 | } | 51 | } |
51 | 52 | ||
@@ -91,7 +92,8 @@ static bool ath_hw_keysetmac(struct ath_common *common, | |||
91 | void *ah = common->ah; | 92 | void *ah = common->ah; |
92 | 93 | ||
93 | if (entry >= common->keymax) { | 94 | if (entry >= common->keymax) { |
94 | ath_err(common, "keycache entry %u out of range\n", entry); | 95 | ath_err(common, "keysetmac: keycache entry %u out of range\n", |
96 | entry); | ||
95 | return false; | 97 | return false; |
96 | } | 98 | } |
97 | 99 | ||
@@ -133,7 +135,8 @@ static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry, | |||
133 | u32 keyType; | 135 | u32 keyType; |
134 | 136 | ||
135 | if (entry >= common->keymax) { | 137 | if (entry >= common->keymax) { |
136 | ath_err(common, "keycache entry %u out of range\n", entry); | 138 | ath_err(common, "set-entry: keycache entry %u out of range\n", |
139 | entry); | ||
137 | return false; | 140 | return false; |
138 | } | 141 | } |
139 | 142 | ||
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index fe4a77ee05c9..f5e840104f4b 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -285,7 +285,9 @@ enum { | |||
285 | #define B43_SHM_SH_DTIMPER 0x0012 /* DTIM period */ | 285 | #define B43_SHM_SH_DTIMPER 0x0012 /* DTIM period */ |
286 | #define B43_SHM_SH_NOSLPZNATDTIM 0x004C /* NOSLPZNAT DTIM */ | 286 | #define B43_SHM_SH_NOSLPZNATDTIM 0x004C /* NOSLPZNAT DTIM */ |
287 | /* SHM_SHARED beacon/AP variables */ | 287 | /* SHM_SHARED beacon/AP variables */ |
288 | #define B43_SHM_SH_BT_BASE0 0x0068 /* Beacon template base 0 */ | ||
288 | #define B43_SHM_SH_BTL0 0x0018 /* Beacon template length 0 */ | 289 | #define B43_SHM_SH_BTL0 0x0018 /* Beacon template length 0 */ |
290 | #define B43_SHM_SH_BT_BASE1 0x0468 /* Beacon template base 1 */ | ||
289 | #define B43_SHM_SH_BTL1 0x001A /* Beacon template length 1 */ | 291 | #define B43_SHM_SH_BTL1 0x001A /* Beacon template length 1 */ |
290 | #define B43_SHM_SH_BTSFOFF 0x001C /* Beacon TSF offset */ | 292 | #define B43_SHM_SH_BTSFOFF 0x001C /* Beacon TSF offset */ |
291 | #define B43_SHM_SH_TIMBPOS 0x001E /* TIM B position in beacon */ | 293 | #define B43_SHM_SH_TIMBPOS 0x001E /* TIM B position in beacon */ |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index c4d0cc582555..4ac73d2f8605 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -1310,17 +1310,19 @@ static u32 b43_jssi_read(struct b43_wldev *dev) | |||
1310 | { | 1310 | { |
1311 | u32 val = 0; | 1311 | u32 val = 0; |
1312 | 1312 | ||
1313 | val = b43_shm_read16(dev, B43_SHM_SHARED, 0x08A); | 1313 | val = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_JSSI1); |
1314 | val <<= 16; | 1314 | val <<= 16; |
1315 | val |= b43_shm_read16(dev, B43_SHM_SHARED, 0x088); | 1315 | val |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_JSSI0); |
1316 | 1316 | ||
1317 | return val; | 1317 | return val; |
1318 | } | 1318 | } |
1319 | 1319 | ||
1320 | static void b43_jssi_write(struct b43_wldev *dev, u32 jssi) | 1320 | static void b43_jssi_write(struct b43_wldev *dev, u32 jssi) |
1321 | { | 1321 | { |
1322 | b43_shm_write16(dev, B43_SHM_SHARED, 0x088, (jssi & 0x0000FFFF)); | 1322 | b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_JSSI0, |
1323 | b43_shm_write16(dev, B43_SHM_SHARED, 0x08A, (jssi & 0xFFFF0000) >> 16); | 1323 | (jssi & 0x0000FFFF)); |
1324 | b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_JSSI1, | ||
1325 | (jssi & 0xFFFF0000) >> 16); | ||
1324 | } | 1326 | } |
1325 | 1327 | ||
1326 | static void b43_generate_noise_sample(struct b43_wldev *dev) | 1328 | static void b43_generate_noise_sample(struct b43_wldev *dev) |
@@ -1623,7 +1625,7 @@ static void b43_upload_beacon0(struct b43_wldev *dev) | |||
1623 | 1625 | ||
1624 | if (wl->beacon0_uploaded) | 1626 | if (wl->beacon0_uploaded) |
1625 | return; | 1627 | return; |
1626 | b43_write_beacon_template(dev, 0x68, 0x18); | 1628 | b43_write_beacon_template(dev, B43_SHM_SH_BT_BASE0, B43_SHM_SH_BTL0); |
1627 | wl->beacon0_uploaded = true; | 1629 | wl->beacon0_uploaded = true; |
1628 | } | 1630 | } |
1629 | 1631 | ||
@@ -1633,7 +1635,7 @@ static void b43_upload_beacon1(struct b43_wldev *dev) | |||
1633 | 1635 | ||
1634 | if (wl->beacon1_uploaded) | 1636 | if (wl->beacon1_uploaded) |
1635 | return; | 1637 | return; |
1636 | b43_write_beacon_template(dev, 0x468, 0x1A); | 1638 | b43_write_beacon_template(dev, B43_SHM_SH_BT_BASE1, B43_SHM_SH_BTL1); |
1637 | wl->beacon1_uploaded = true; | 1639 | wl->beacon1_uploaded = true; |
1638 | } | 1640 | } |
1639 | 1641 | ||
@@ -2780,9 +2782,7 @@ static int b43_gpio_init(struct b43_wldev *dev) | |||
2780 | switch (dev->dev->bus_type) { | 2782 | switch (dev->dev->bus_type) { |
2781 | #ifdef CONFIG_B43_BCMA | 2783 | #ifdef CONFIG_B43_BCMA |
2782 | case B43_BUS_BCMA: | 2784 | case B43_BUS_BCMA: |
2783 | bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL, | 2785 | bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc, mask, set); |
2784 | (bcma_cc_read32(&dev->dev->bdev->bus->drv_cc, | ||
2785 | BCMA_CC_GPIOCTL) & ~mask) | set); | ||
2786 | break; | 2786 | break; |
2787 | #endif | 2787 | #endif |
2788 | #ifdef CONFIG_B43_SSB | 2788 | #ifdef CONFIG_B43_SSB |
@@ -2807,8 +2807,7 @@ static void b43_gpio_cleanup(struct b43_wldev *dev) | |||
2807 | switch (dev->dev->bus_type) { | 2807 | switch (dev->dev->bus_type) { |
2808 | #ifdef CONFIG_B43_BCMA | 2808 | #ifdef CONFIG_B43_BCMA |
2809 | case B43_BUS_BCMA: | 2809 | case B43_BUS_BCMA: |
2810 | bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL, | 2810 | bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc, ~0, 0); |
2811 | 0); | ||
2812 | break; | 2811 | break; |
2813 | #endif | 2812 | #endif |
2814 | #ifdef CONFIG_B43_SSB | 2813 | #ifdef CONFIG_B43_SSB |
@@ -3116,7 +3115,7 @@ static int b43_chip_init(struct b43_wldev *dev) | |||
3116 | 3115 | ||
3117 | /* Probe Response Timeout value */ | 3116 | /* Probe Response Timeout value */ |
3118 | /* FIXME: Default to 0, has to be set by ioctl probably... :-/ */ | 3117 | /* FIXME: Default to 0, has to be set by ioctl probably... :-/ */ |
3119 | b43_shm_write16(dev, B43_SHM_SHARED, 0x0074, 0x0000); | 3118 | b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRMAXTIME, 0); |
3120 | 3119 | ||
3121 | /* Initially set the wireless operation mode. */ | 3120 | /* Initially set the wireless operation mode. */ |
3122 | b43_adjust_opmode(dev); | 3121 | b43_adjust_opmode(dev); |
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 3ae28561f7a4..5ed352ddae9e 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c | |||
@@ -104,14 +104,8 @@ static void lpphy_read_band_sprom(struct b43_wldev *dev) | |||
104 | maxpwr = sprom->maxpwr_bg; | 104 | maxpwr = sprom->maxpwr_bg; |
105 | lpphy->max_tx_pwr_med_band = maxpwr; | 105 | lpphy->max_tx_pwr_med_band = maxpwr; |
106 | cckpo = sprom->cck2gpo; | 106 | cckpo = sprom->cck2gpo; |
107 | /* | ||
108 | * We don't read SPROM's opo as specs say. On rev8 SPROMs | ||
109 | * opo == ofdm2gpo and we don't know any SSB with LP-PHY | ||
110 | * and SPROM rev below 8. | ||
111 | */ | ||
112 | B43_WARN_ON(sprom->revision < 8); | ||
113 | ofdmpo = sprom->ofdm2gpo; | ||
114 | if (cckpo) { | 107 | if (cckpo) { |
108 | ofdmpo = sprom->ofdm2gpo; | ||
115 | for (i = 0; i < 4; i++) { | 109 | for (i = 0; i < 4; i++) { |
116 | lpphy->tx_max_rate[i] = | 110 | lpphy->tx_max_rate[i] = |
117 | maxpwr - (ofdmpo & 0xF) * 2; | 111 | maxpwr - (ofdmpo & 0xF) * 2; |
@@ -124,11 +118,11 @@ static void lpphy_read_band_sprom(struct b43_wldev *dev) | |||
124 | ofdmpo >>= 4; | 118 | ofdmpo >>= 4; |
125 | } | 119 | } |
126 | } else { | 120 | } else { |
127 | ofdmpo &= 0xFF; | 121 | u8 opo = sprom->opo; |
128 | for (i = 0; i < 4; i++) | 122 | for (i = 0; i < 4; i++) |
129 | lpphy->tx_max_rate[i] = maxpwr; | 123 | lpphy->tx_max_rate[i] = maxpwr; |
130 | for (i = 4; i < 15; i++) | 124 | for (i = 4; i < 15; i++) |
131 | lpphy->tx_max_rate[i] = maxpwr - ofdmpo; | 125 | lpphy->tx_max_rate[i] = maxpwr - opo; |
132 | } | 126 | } |
133 | } else { /* 5GHz */ | 127 | } else { /* 5GHz */ |
134 | lpphy->tx_isolation_low_band = sprom->tri5gl; | 128 | lpphy->tx_isolation_low_band = sprom->tri5gl; |
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index e8486c1e091a..f9339e7ea6af 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c | |||
@@ -2789,10 +2789,6 @@ static void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core, | |||
2789 | * Tx and Rx | 2789 | * Tx and Rx |
2790 | **************************************************/ | 2790 | **************************************************/ |
2791 | 2791 | ||
2792 | void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) | ||
2793 | {//TODO | ||
2794 | } | ||
2795 | |||
2796 | static void b43_nphy_op_adjust_txpower(struct b43_wldev *dev) | 2792 | static void b43_nphy_op_adjust_txpower(struct b43_wldev *dev) |
2797 | {//TODO | 2793 | {//TODO |
2798 | } | 2794 | } |
@@ -4892,7 +4888,7 @@ static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init) | |||
4892 | } | 4888 | } |
4893 | 4889 | ||
4894 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N */ | 4890 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N */ |
4895 | int b43_phy_initn(struct b43_wldev *dev) | 4891 | static int b43_phy_initn(struct b43_wldev *dev) |
4896 | { | 4892 | { |
4897 | struct ssb_sprom *sprom = dev->dev->bus_sprom; | 4893 | struct ssb_sprom *sprom = dev->dev->bus_sprom; |
4898 | struct b43_phy *phy = &dev->phy; | 4894 | struct b43_phy *phy = &dev->phy; |
diff --git a/drivers/net/wireless/b43/radio_2056.c b/drivers/net/wireless/b43/radio_2056.c index ce037fb6789a..b4fd9345d673 100644 --- a/drivers/net/wireless/b43/radio_2056.c +++ b/drivers/net/wireless/b43/radio_2056.c | |||
@@ -2980,7 +2980,7 @@ static const struct b2056_inittab_entry b2056_inittab_rev8_rx[] = { | |||
2980 | .rx = prefix##_rx, \ | 2980 | .rx = prefix##_rx, \ |
2981 | .rx_length = ARRAY_SIZE(prefix##_rx) | 2981 | .rx_length = ARRAY_SIZE(prefix##_rx) |
2982 | 2982 | ||
2983 | struct b2056_inittabs_pts b2056_inittabs[] = { | 2983 | static const struct b2056_inittabs_pts b2056_inittabs[] = { |
2984 | [3] = { INITTABSPTS(b2056_inittab_rev3) }, | 2984 | [3] = { INITTABSPTS(b2056_inittab_rev3) }, |
2985 | [4] = { INITTABSPTS(b2056_inittab_rev4) }, | 2985 | [4] = { INITTABSPTS(b2056_inittab_rev4) }, |
2986 | [5] = { INITTABSPTS(b2056_inittab_rev5) }, | 2986 | [5] = { INITTABSPTS(b2056_inittab_rev5) }, |
@@ -9035,7 +9035,7 @@ static void b2056_upload_inittab(struct b43_wldev *dev, bool ghz5, | |||
9035 | void b2056_upload_inittabs(struct b43_wldev *dev, | 9035 | void b2056_upload_inittabs(struct b43_wldev *dev, |
9036 | bool ghz5, bool ignore_uploadflag) | 9036 | bool ghz5, bool ignore_uploadflag) |
9037 | { | 9037 | { |
9038 | struct b2056_inittabs_pts *pts; | 9038 | const struct b2056_inittabs_pts *pts; |
9039 | 9039 | ||
9040 | if (dev->phy.rev >= ARRAY_SIZE(b2056_inittabs)) { | 9040 | if (dev->phy.rev >= ARRAY_SIZE(b2056_inittabs)) { |
9041 | B43_WARN_ON(1); | 9041 | B43_WARN_ON(1); |
@@ -9057,7 +9057,7 @@ void b2056_upload_inittabs(struct b43_wldev *dev, | |||
9057 | 9057 | ||
9058 | void b2056_upload_syn_pll_cp2(struct b43_wldev *dev, bool ghz5) | 9058 | void b2056_upload_syn_pll_cp2(struct b43_wldev *dev, bool ghz5) |
9059 | { | 9059 | { |
9060 | struct b2056_inittabs_pts *pts; | 9060 | const struct b2056_inittabs_pts *pts; |
9061 | const struct b2056_inittab_entry *e; | 9061 | const struct b2056_inittab_entry *e; |
9062 | 9062 | ||
9063 | if (dev->phy.rev >= ARRAY_SIZE(b2056_inittabs)) { | 9063 | if (dev->phy.rev >= ARRAY_SIZE(b2056_inittabs)) { |
diff --git a/drivers/net/wireless/b43/sdio.h b/drivers/net/wireless/b43/sdio.h index fb633094403a..1e93926f388f 100644 --- a/drivers/net/wireless/b43/sdio.h +++ b/drivers/net/wireless/b43/sdio.h | |||
@@ -25,12 +25,12 @@ void b43_sdio_exit(void); | |||
25 | #else /* CONFIG_B43_SDIO */ | 25 | #else /* CONFIG_B43_SDIO */ |
26 | 26 | ||
27 | 27 | ||
28 | int b43_sdio_request_irq(struct b43_wldev *dev, | 28 | static inline int b43_sdio_request_irq(struct b43_wldev *dev, |
29 | void (*handler)(struct b43_wldev *dev)) | 29 | void (*handler)(struct b43_wldev *dev)) |
30 | { | 30 | { |
31 | return -ENODEV; | 31 | return -ENODEV; |
32 | } | 32 | } |
33 | void b43_sdio_free_irq(struct b43_wldev *dev) | 33 | static inline void b43_sdio_free_irq(struct b43_wldev *dev) |
34 | { | 34 | { |
35 | } | 35 | } |
36 | static inline int b43_sdio_init(void) | 36 | static inline int b43_sdio_init(void) |
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index aaca60c6f575..110510d53958 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c | |||
@@ -2800,7 +2800,7 @@ static const struct nphy_rf_control_override_rev7 | |||
2800 | { 0x0010, 0x344, 0x345, 0x0010, 4 }, | 2800 | { 0x0010, 0x344, 0x345, 0x0010, 4 }, |
2801 | }; | 2801 | }; |
2802 | 2802 | ||
2803 | struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_wa_phy6_radio11_ghz2 = { | 2803 | static struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_wa_phy6_radio11_ghz2 = { |
2804 | { 10, 14, 19, 27 }, | 2804 | { 10, 14, 19, 27 }, |
2805 | { -5, 6, 10, 15 }, | 2805 | { -5, 6, 10, 15 }, |
2806 | { 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA }, | 2806 | { 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA }, |
@@ -2811,7 +2811,7 @@ struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_wa_phy6_radio11_ghz2 = { | |||
2811 | 0x18, 0x18, 0x18, | 2811 | 0x18, 0x18, 0x18, |
2812 | 0x01D0, 0x5, | 2812 | 0x01D0, 0x5, |
2813 | }; | 2813 | }; |
2814 | struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_workaround[2][4] = { | 2814 | static struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_workaround[2][4] = { |
2815 | { /* 2GHz */ | 2815 | { /* 2GHz */ |
2816 | { /* PHY rev 3 */ | 2816 | { /* PHY rev 3 */ |
2817 | { 7, 11, 16, 23 }, | 2817 | { 7, 11, 16, 23 }, |
diff --git a/drivers/net/wireless/b43/tables_phy_lcn.c b/drivers/net/wireless/b43/tables_phy_lcn.c index 5176363cadf2..e347b8d80ea4 100644 --- a/drivers/net/wireless/b43/tables_phy_lcn.c +++ b/drivers/net/wireless/b43/tables_phy_lcn.c | |||
@@ -313,7 +313,7 @@ static const u32 b43_lcntab_0x18[] = { | |||
313 | * TX gain. | 313 | * TX gain. |
314 | **************************************************/ | 314 | **************************************************/ |
315 | 315 | ||
316 | const struct b43_lcntab_tx_gain_tbl_entry | 316 | static const struct b43_lcntab_tx_gain_tbl_entry |
317 | b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0[B43_LCNTAB_TX_GAIN_SIZE] = { | 317 | b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0[B43_LCNTAB_TX_GAIN_SIZE] = { |
318 | { 0x03, 0x00, 0x1f, 0x0, 0x48 }, | 318 | { 0x03, 0x00, 0x1f, 0x0, 0x48 }, |
319 | { 0x03, 0x00, 0x1f, 0x0, 0x46 }, | 319 | { 0x03, 0x00, 0x1f, 0x0, 0x46 }, |
@@ -449,7 +449,7 @@ const struct b43_lcntab_tx_gain_tbl_entry | |||
449 | * SW control. | 449 | * SW control. |
450 | **************************************************/ | 450 | **************************************************/ |
451 | 451 | ||
452 | const u16 b43_lcntab_sw_ctl_4313_epa_rev0[] = { | 452 | static const u16 b43_lcntab_sw_ctl_4313_epa_rev0[] = { |
453 | 0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008, | 453 | 0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008, |
454 | 0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001, | 454 | 0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001, |
455 | 0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008, | 455 | 0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008, |
@@ -631,7 +631,7 @@ static void b43_phy_lcn_upload_static_tables(struct b43_wldev *dev) | |||
631 | lcntab_upload(dev, B43_LCNTAB32(0x18, 0), b43_lcntab_0x18); | 631 | lcntab_upload(dev, B43_LCNTAB32(0x18, 0), b43_lcntab_0x18); |
632 | } | 632 | } |
633 | 633 | ||
634 | void b43_phy_lcn_load_tx_gain_tab(struct b43_wldev *dev, | 634 | static void b43_phy_lcn_load_tx_gain_tab(struct b43_wldev *dev, |
635 | const struct b43_lcntab_tx_gain_tbl_entry *gain_table) | 635 | const struct b43_lcntab_tx_gain_tbl_entry *gain_table) |
636 | { | 636 | { |
637 | u32 i; | 637 | u32 i; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 11fd1c735589..f3149debede0 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
@@ -65,7 +65,7 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) | |||
65 | u8 data; | 65 | u8 data; |
66 | unsigned long flags; | 66 | unsigned long flags; |
67 | 67 | ||
68 | brcmf_dbg(TRACE, "Entering: irq %d\n", sdiodev->irq); | 68 | brcmf_dbg(SDIO, "Entering: irq %d\n", sdiodev->irq); |
69 | 69 | ||
70 | ret = request_irq(sdiodev->irq, brcmf_sdio_irqhandler, | 70 | ret = request_irq(sdiodev->irq, brcmf_sdio_irqhandler, |
71 | sdiodev->irq_flags, "brcmf_oob_intr", | 71 | sdiodev->irq_flags, "brcmf_oob_intr", |
@@ -102,7 +102,7 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) | |||
102 | 102 | ||
103 | int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev) | 103 | int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev) |
104 | { | 104 | { |
105 | brcmf_dbg(TRACE, "Entering\n"); | 105 | brcmf_dbg(SDIO, "Entering\n"); |
106 | 106 | ||
107 | sdio_claim_host(sdiodev->func[1]); | 107 | sdio_claim_host(sdiodev->func[1]); |
108 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL); | 108 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL); |
@@ -136,7 +136,7 @@ static void brcmf_sdio_dummy_irqhandler(struct sdio_func *func) | |||
136 | 136 | ||
137 | int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) | 137 | int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) |
138 | { | 138 | { |
139 | brcmf_dbg(TRACE, "Entering\n"); | 139 | brcmf_dbg(SDIO, "Entering\n"); |
140 | 140 | ||
141 | sdio_claim_host(sdiodev->func[1]); | 141 | sdio_claim_host(sdiodev->func[1]); |
142 | sdio_claim_irq(sdiodev->func[1], brcmf_sdio_irqhandler); | 142 | sdio_claim_irq(sdiodev->func[1], brcmf_sdio_irqhandler); |
@@ -148,7 +148,7 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) | |||
148 | 148 | ||
149 | int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev) | 149 | int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev) |
150 | { | 150 | { |
151 | brcmf_dbg(TRACE, "Entering\n"); | 151 | brcmf_dbg(SDIO, "Entering\n"); |
152 | 152 | ||
153 | sdio_claim_host(sdiodev->func[1]); | 153 | sdio_claim_host(sdiodev->func[1]); |
154 | sdio_release_irq(sdiodev->func[2]); | 154 | sdio_release_irq(sdiodev->func[2]); |
@@ -253,9 +253,9 @@ u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) | |||
253 | u8 data; | 253 | u8 data; |
254 | int retval; | 254 | int retval; |
255 | 255 | ||
256 | brcmf_dbg(INFO, "addr:0x%08x\n", addr); | 256 | brcmf_dbg(SDIO, "addr:0x%08x\n", addr); |
257 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false); | 257 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false); |
258 | brcmf_dbg(INFO, "data:0x%02x\n", data); | 258 | brcmf_dbg(SDIO, "data:0x%02x\n", data); |
259 | 259 | ||
260 | if (ret) | 260 | if (ret) |
261 | *ret = retval; | 261 | *ret = retval; |
@@ -268,9 +268,9 @@ u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) | |||
268 | u32 data; | 268 | u32 data; |
269 | int retval; | 269 | int retval; |
270 | 270 | ||
271 | brcmf_dbg(INFO, "addr:0x%08x\n", addr); | 271 | brcmf_dbg(SDIO, "addr:0x%08x\n", addr); |
272 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false); | 272 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false); |
273 | brcmf_dbg(INFO, "data:0x%08x\n", data); | 273 | brcmf_dbg(SDIO, "data:0x%08x\n", data); |
274 | 274 | ||
275 | if (ret) | 275 | if (ret) |
276 | *ret = retval; | 276 | *ret = retval; |
@@ -283,7 +283,7 @@ void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
283 | { | 283 | { |
284 | int retval; | 284 | int retval; |
285 | 285 | ||
286 | brcmf_dbg(INFO, "addr:0x%08x, data:0x%02x\n", addr, data); | 286 | brcmf_dbg(SDIO, "addr:0x%08x, data:0x%02x\n", addr, data); |
287 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true); | 287 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true); |
288 | 288 | ||
289 | if (ret) | 289 | if (ret) |
@@ -295,7 +295,7 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, | |||
295 | { | 295 | { |
296 | int retval; | 296 | int retval; |
297 | 297 | ||
298 | brcmf_dbg(INFO, "addr:0x%08x, data:0x%08x\n", addr, data); | 298 | brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data); |
299 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true); | 299 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true); |
300 | 300 | ||
301 | if (ret) | 301 | if (ret) |
@@ -358,7 +358,7 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
358 | uint width; | 358 | uint width; |
359 | int err = 0; | 359 | int err = 0; |
360 | 360 | ||
361 | brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", | 361 | brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n", |
362 | fn, addr, pkt->len); | 362 | fn, addr, pkt->len); |
363 | 363 | ||
364 | width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; | 364 | width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; |
@@ -381,7 +381,7 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
381 | uint width; | 381 | uint width; |
382 | int err = 0; | 382 | int err = 0; |
383 | 383 | ||
384 | brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", | 384 | brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n", |
385 | fn, addr, pktq->qlen); | 385 | fn, addr, pktq->qlen); |
386 | 386 | ||
387 | width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; | 387 | width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; |
@@ -428,7 +428,7 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, | |||
428 | uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; | 428 | uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; |
429 | int err = 0; | 429 | int err = 0; |
430 | 430 | ||
431 | brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", | 431 | brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n", |
432 | fn, addr, pkt->len); | 432 | fn, addr, pkt->len); |
433 | 433 | ||
434 | /* Async not implemented yet */ | 434 | /* Async not implemented yet */ |
@@ -492,13 +492,13 @@ int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr, | |||
492 | int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn) | 492 | int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn) |
493 | { | 493 | { |
494 | char t_func = (char)fn; | 494 | char t_func = (char)fn; |
495 | brcmf_dbg(TRACE, "Enter\n"); | 495 | brcmf_dbg(SDIO, "Enter\n"); |
496 | 496 | ||
497 | /* issue abort cmd52 command through F0 */ | 497 | /* issue abort cmd52 command through F0 */ |
498 | brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0, | 498 | brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0, |
499 | SDIO_CCCR_ABORT, &t_func); | 499 | SDIO_CCCR_ABORT, &t_func); |
500 | 500 | ||
501 | brcmf_dbg(TRACE, "Exit\n"); | 501 | brcmf_dbg(SDIO, "Exit\n"); |
502 | return 0; | 502 | return 0; |
503 | } | 503 | } |
504 | 504 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index d92d373733d7..716548989e4f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | |||
@@ -139,7 +139,7 @@ int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func, | |||
139 | { | 139 | { |
140 | int err_ret; | 140 | int err_ret; |
141 | 141 | ||
142 | brcmf_dbg(INFO, "rw=%d, func=%d, addr=0x%05x\n", rw, func, regaddr); | 142 | brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x\n", rw, func, regaddr); |
143 | 143 | ||
144 | brcmf_pm_resume_wait(sdiodev, &sdiodev->request_byte_wait); | 144 | brcmf_pm_resume_wait(sdiodev, &sdiodev->request_byte_wait); |
145 | if (brcmf_pm_resume_error(sdiodev)) | 145 | if (brcmf_pm_resume_error(sdiodev)) |
@@ -179,7 +179,7 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, | |||
179 | return -EINVAL; | 179 | return -EINVAL; |
180 | } | 180 | } |
181 | 181 | ||
182 | brcmf_dbg(INFO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", | 182 | brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", |
183 | rw, func, addr, nbytes); | 183 | rw, func, addr, nbytes); |
184 | 184 | ||
185 | brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait); | 185 | brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait); |
@@ -252,7 +252,7 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc, | |||
252 | 252 | ||
253 | struct sk_buff *pkt; | 253 | struct sk_buff *pkt; |
254 | 254 | ||
255 | brcmf_dbg(TRACE, "Enter\n"); | 255 | brcmf_dbg(SDIO, "Enter\n"); |
256 | 256 | ||
257 | brcmf_pm_resume_wait(sdiodev, &sdiodev->request_chain_wait); | 257 | brcmf_pm_resume_wait(sdiodev, &sdiodev->request_chain_wait); |
258 | if (brcmf_pm_resume_error(sdiodev)) | 258 | if (brcmf_pm_resume_error(sdiodev)) |
@@ -270,7 +270,7 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc, | |||
270 | write ? "TX" : "RX", pkt, SGCount, addr, | 270 | write ? "TX" : "RX", pkt, SGCount, addr, |
271 | pkt_len, err_ret); | 271 | pkt_len, err_ret); |
272 | } else { | 272 | } else { |
273 | brcmf_dbg(TRACE, "%s xfr'd %p[%d], addr=0x%05x, len=%d\n", | 273 | brcmf_dbg(SDIO, "%s xfr'd %p[%d], addr=0x%05x, len=%d\n", |
274 | write ? "TX" : "RX", pkt, SGCount, addr, | 274 | write ? "TX" : "RX", pkt, SGCount, addr, |
275 | pkt_len); | 275 | pkt_len); |
276 | } | 276 | } |
@@ -280,7 +280,7 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc, | |||
280 | SGCount++; | 280 | SGCount++; |
281 | } | 281 | } |
282 | 282 | ||
283 | brcmf_dbg(TRACE, "Exit\n"); | 283 | brcmf_dbg(SDIO, "Exit\n"); |
284 | return err_ret; | 284 | return err_ret; |
285 | } | 285 | } |
286 | 286 | ||
@@ -295,7 +295,7 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, | |||
295 | uint pkt_len; | 295 | uint pkt_len; |
296 | bool fifo = (fix_inc == SDIOH_DATA_FIX); | 296 | bool fifo = (fix_inc == SDIOH_DATA_FIX); |
297 | 297 | ||
298 | brcmf_dbg(TRACE, "Enter\n"); | 298 | brcmf_dbg(SDIO, "Enter\n"); |
299 | 299 | ||
300 | if (pkt == NULL) | 300 | if (pkt == NULL) |
301 | return -EINVAL; | 301 | return -EINVAL; |
@@ -314,7 +314,7 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, | |||
314 | brcmf_err("%s FAILED %p, addr=0x%05x, pkt_len=%d, ERR=0x%08x\n", | 314 | brcmf_err("%s FAILED %p, addr=0x%05x, pkt_len=%d, ERR=0x%08x\n", |
315 | write ? "TX" : "RX", pkt, addr, pkt_len, status); | 315 | write ? "TX" : "RX", pkt, addr, pkt_len, status); |
316 | } else { | 316 | } else { |
317 | brcmf_dbg(TRACE, "%s xfr'd %p, addr=0x%05x, len=%d\n", | 317 | brcmf_dbg(SDIO, "%s xfr'd %p, addr=0x%05x, len=%d\n", |
318 | write ? "TX" : "RX", pkt, addr, pkt_len); | 318 | write ? "TX" : "RX", pkt, addr, pkt_len); |
319 | } | 319 | } |
320 | 320 | ||
@@ -350,12 +350,12 @@ static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev) | |||
350 | u32 fbraddr; | 350 | u32 fbraddr; |
351 | u8 func; | 351 | u8 func; |
352 | 352 | ||
353 | brcmf_dbg(TRACE, "\n"); | 353 | brcmf_dbg(SDIO, "\n"); |
354 | 354 | ||
355 | /* Get the Card's common CIS address */ | 355 | /* Get the Card's common CIS address */ |
356 | sdiodev->func_cis_ptr[0] = brcmf_sdioh_get_cisaddr(sdiodev, | 356 | sdiodev->func_cis_ptr[0] = brcmf_sdioh_get_cisaddr(sdiodev, |
357 | SDIO_CCCR_CIS); | 357 | SDIO_CCCR_CIS); |
358 | brcmf_dbg(INFO, "Card's Common CIS Ptr = 0x%x\n", | 358 | brcmf_dbg(SDIO, "Card's Common CIS Ptr = 0x%x\n", |
359 | sdiodev->func_cis_ptr[0]); | 359 | sdiodev->func_cis_ptr[0]); |
360 | 360 | ||
361 | /* Get the Card's function CIS (for each function) */ | 361 | /* Get the Card's function CIS (for each function) */ |
@@ -363,7 +363,7 @@ static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev) | |||
363 | func <= sdiodev->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) { | 363 | func <= sdiodev->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) { |
364 | sdiodev->func_cis_ptr[func] = | 364 | sdiodev->func_cis_ptr[func] = |
365 | brcmf_sdioh_get_cisaddr(sdiodev, SDIO_FBR_CIS + fbraddr); | 365 | brcmf_sdioh_get_cisaddr(sdiodev, SDIO_FBR_CIS + fbraddr); |
366 | brcmf_dbg(INFO, "Function %d CIS Ptr = 0x%x\n", | 366 | brcmf_dbg(SDIO, "Function %d CIS Ptr = 0x%x\n", |
367 | func, sdiodev->func_cis_ptr[func]); | 367 | func, sdiodev->func_cis_ptr[func]); |
368 | } | 368 | } |
369 | 369 | ||
@@ -382,7 +382,7 @@ int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev) | |||
382 | { | 382 | { |
383 | int err_ret = 0; | 383 | int err_ret = 0; |
384 | 384 | ||
385 | brcmf_dbg(TRACE, "\n"); | 385 | brcmf_dbg(SDIO, "\n"); |
386 | 386 | ||
387 | sdiodev->num_funcs = 2; | 387 | sdiodev->num_funcs = 2; |
388 | 388 | ||
@@ -404,13 +404,13 @@ int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev) | |||
404 | 404 | ||
405 | out: | 405 | out: |
406 | sdio_release_host(sdiodev->func[1]); | 406 | sdio_release_host(sdiodev->func[1]); |
407 | brcmf_dbg(TRACE, "Done\n"); | 407 | brcmf_dbg(SDIO, "Done\n"); |
408 | return err_ret; | 408 | return err_ret; |
409 | } | 409 | } |
410 | 410 | ||
411 | void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev) | 411 | void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev) |
412 | { | 412 | { |
413 | brcmf_dbg(TRACE, "\n"); | 413 | brcmf_dbg(SDIO, "\n"); |
414 | 414 | ||
415 | /* Disable Function 2 */ | 415 | /* Disable Function 2 */ |
416 | sdio_claim_host(sdiodev->func[2]); | 416 | sdio_claim_host(sdiodev->func[2]); |
@@ -458,11 +458,11 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, | |||
458 | struct brcmf_sdio_dev *sdiodev; | 458 | struct brcmf_sdio_dev *sdiodev; |
459 | struct brcmf_bus *bus_if; | 459 | struct brcmf_bus *bus_if; |
460 | 460 | ||
461 | brcmf_dbg(TRACE, "Enter\n"); | 461 | brcmf_dbg(SDIO, "Enter\n"); |
462 | brcmf_dbg(TRACE, "Class=%x\n", func->class); | 462 | brcmf_dbg(SDIO, "Class=%x\n", func->class); |
463 | brcmf_dbg(TRACE, "sdio vendor ID: 0x%04x\n", func->vendor); | 463 | brcmf_dbg(SDIO, "sdio vendor ID: 0x%04x\n", func->vendor); |
464 | brcmf_dbg(TRACE, "sdio device ID: 0x%04x\n", func->device); | 464 | brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device); |
465 | brcmf_dbg(TRACE, "Function#: %d\n", func->num); | 465 | brcmf_dbg(SDIO, "Function#: %d\n", func->num); |
466 | 466 | ||
467 | /* Consume func num 1 but dont do anything with it. */ | 467 | /* Consume func num 1 but dont do anything with it. */ |
468 | if (func->num == 1) | 468 | if (func->num == 1) |
@@ -501,13 +501,13 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, | |||
501 | if (err) | 501 | if (err) |
502 | goto fail; | 502 | goto fail; |
503 | 503 | ||
504 | brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_probe...\n"); | 504 | brcmf_dbg(SDIO, "F2 found, calling brcmf_sdio_probe...\n"); |
505 | err = brcmf_sdio_probe(sdiodev); | 505 | err = brcmf_sdio_probe(sdiodev); |
506 | if (err) { | 506 | if (err) { |
507 | brcmf_err("F2 error, probe failed %d...\n", err); | 507 | brcmf_err("F2 error, probe failed %d...\n", err); |
508 | goto fail; | 508 | goto fail; |
509 | } | 509 | } |
510 | brcmf_dbg(TRACE, "F2 init completed...\n"); | 510 | brcmf_dbg(SDIO, "F2 init completed...\n"); |
511 | return 0; | 511 | return 0; |
512 | 512 | ||
513 | fail: | 513 | fail: |
@@ -523,10 +523,10 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func) | |||
523 | struct brcmf_bus *bus_if; | 523 | struct brcmf_bus *bus_if; |
524 | struct brcmf_sdio_dev *sdiodev; | 524 | struct brcmf_sdio_dev *sdiodev; |
525 | 525 | ||
526 | brcmf_dbg(TRACE, "Enter\n"); | 526 | brcmf_dbg(SDIO, "Enter\n"); |
527 | brcmf_dbg(TRACE, "sdio vendor ID: 0x%04x\n", func->vendor); | 527 | brcmf_dbg(SDIO, "sdio vendor ID: 0x%04x\n", func->vendor); |
528 | brcmf_dbg(TRACE, "sdio device ID: 0x%04x\n", func->device); | 528 | brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device); |
529 | brcmf_dbg(TRACE, "Function: %d\n", func->num); | 529 | brcmf_dbg(SDIO, "Function: %d\n", func->num); |
530 | 530 | ||
531 | if (func->num != 1 && func->num != 2) | 531 | if (func->num != 1 && func->num != 2) |
532 | return; | 532 | return; |
@@ -543,7 +543,7 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func) | |||
543 | kfree(sdiodev); | 543 | kfree(sdiodev); |
544 | } | 544 | } |
545 | 545 | ||
546 | brcmf_dbg(TRACE, "Exit\n"); | 546 | brcmf_dbg(SDIO, "Exit\n"); |
547 | } | 547 | } |
548 | 548 | ||
549 | #ifdef CONFIG_PM_SLEEP | 549 | #ifdef CONFIG_PM_SLEEP |
@@ -554,7 +554,7 @@ static int brcmf_sdio_suspend(struct device *dev) | |||
554 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 554 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
555 | int ret = 0; | 555 | int ret = 0; |
556 | 556 | ||
557 | brcmf_dbg(TRACE, "\n"); | 557 | brcmf_dbg(SDIO, "\n"); |
558 | 558 | ||
559 | atomic_set(&sdiodev->suspend, true); | 559 | atomic_set(&sdiodev->suspend, true); |
560 | 560 | ||
@@ -645,7 +645,7 @@ static struct platform_driver brcmf_sdio_pd = { | |||
645 | 645 | ||
646 | void brcmf_sdio_exit(void) | 646 | void brcmf_sdio_exit(void) |
647 | { | 647 | { |
648 | brcmf_dbg(TRACE, "Enter\n"); | 648 | brcmf_dbg(SDIO, "Enter\n"); |
649 | 649 | ||
650 | sdio_unregister_driver(&brcmf_sdmmc_driver); | 650 | sdio_unregister_driver(&brcmf_sdmmc_driver); |
651 | 651 | ||
@@ -656,7 +656,7 @@ void brcmf_sdio_init(void) | |||
656 | { | 656 | { |
657 | int ret; | 657 | int ret; |
658 | 658 | ||
659 | brcmf_dbg(TRACE, "Enter\n"); | 659 | brcmf_dbg(SDIO, "Enter\n"); |
660 | 660 | ||
661 | ret = platform_driver_register(&brcmf_sdio_pd); | 661 | ret = platform_driver_register(&brcmf_sdio_pd); |
662 | 662 | ||
@@ -666,7 +666,7 @@ void brcmf_sdio_init(void) | |||
666 | #else | 666 | #else |
667 | void brcmf_sdio_exit(void) | 667 | void brcmf_sdio_exit(void) |
668 | { | 668 | { |
669 | brcmf_dbg(TRACE, "Enter\n"); | 669 | brcmf_dbg(SDIO, "Enter\n"); |
670 | 670 | ||
671 | sdio_unregister_driver(&brcmf_sdmmc_driver); | 671 | sdio_unregister_driver(&brcmf_sdmmc_driver); |
672 | } | 672 | } |
@@ -675,7 +675,7 @@ void brcmf_sdio_init(void) | |||
675 | { | 675 | { |
676 | int ret; | 676 | int ret; |
677 | 677 | ||
678 | brcmf_dbg(TRACE, "Enter\n"); | 678 | brcmf_dbg(SDIO, "Enter\n"); |
679 | 679 | ||
680 | ret = sdio_register_driver(&brcmf_sdmmc_driver); | 680 | ret = sdio_register_driver(&brcmf_sdmmc_driver); |
681 | 681 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index c7fa20846b32..5249c67b466c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h | |||
@@ -72,6 +72,7 @@ | |||
72 | #define BRCMF_C_SET_WSEC 134 | 72 | #define BRCMF_C_SET_WSEC 134 |
73 | #define BRCMF_C_GET_PHY_NOISE 135 | 73 | #define BRCMF_C_GET_PHY_NOISE 135 |
74 | #define BRCMF_C_GET_BSS_INFO 136 | 74 | #define BRCMF_C_GET_BSS_INFO 136 |
75 | #define BRCMF_C_GET_BANDLIST 140 | ||
75 | #define BRCMF_C_SET_SCB_TIMEOUT 158 | 76 | #define BRCMF_C_SET_SCB_TIMEOUT 158 |
76 | #define BRCMF_C_GET_PHYLIST 180 | 77 | #define BRCMF_C_GET_PHYLIST 180 |
77 | #define BRCMF_C_SET_SCAN_CHANNEL_TIME 185 | 78 | #define BRCMF_C_SET_SCAN_CHANNEL_TIME 185 |
@@ -475,6 +476,11 @@ struct brcmf_sta_info_le { | |||
475 | __le32 rx_decrypt_failures; /* # of packet decrypted failed */ | 476 | __le32 rx_decrypt_failures; /* # of packet decrypted failed */ |
476 | }; | 477 | }; |
477 | 478 | ||
479 | struct brcmf_chanspec_list { | ||
480 | __le32 count; /* # of entries */ | ||
481 | __le32 element[1]; /* variable length uint32 list */ | ||
482 | }; | ||
483 | |||
478 | /* | 484 | /* |
479 | * WLC_E_PROBRESP_MSG | 485 | * WLC_E_PROBRESP_MSG |
480 | * WLC_E_P2P_PROBREQ_MSG | 486 | * WLC_E_P2P_PROBREQ_MSG |
@@ -542,10 +548,25 @@ struct brcmf_if_event { | |||
542 | u8 action; | 548 | u8 action; |
543 | u8 flags; | 549 | u8 flags; |
544 | u8 bssidx; | 550 | u8 bssidx; |
551 | u8 role; | ||
545 | }; | 552 | }; |
546 | 553 | ||
547 | /* forward declaration */ | 554 | /* forward declarations */ |
548 | struct brcmf_cfg80211_vif; | 555 | struct brcmf_cfg80211_vif; |
556 | struct brcmf_fws_mac_descriptor; | ||
557 | |||
558 | /** | ||
559 | * enum brcmf_netif_stop_reason - reason for stopping netif queue. | ||
560 | * | ||
561 | * @BRCMF_NETIF_STOP_REASON_FWS_FC: | ||
562 | * netif stopped due to firmware signalling flow control. | ||
563 | * @BRCMF_NETIF_STOP_REASON_BLOCK_BUS: | ||
564 | * netif stopped due to bus blocking. | ||
565 | */ | ||
566 | enum brcmf_netif_stop_reason { | ||
567 | BRCMF_NETIF_STOP_REASON_FWS_FC = 1, | ||
568 | BRCMF_NETIF_STOP_REASON_BLOCK_BUS = 2 | ||
569 | }; | ||
549 | 570 | ||
550 | /** | 571 | /** |
551 | * struct brcmf_if - interface control information. | 572 | * struct brcmf_if - interface control information. |
@@ -554,9 +575,13 @@ struct brcmf_cfg80211_vif; | |||
554 | * @vif: points to cfg80211 specific interface information. | 575 | * @vif: points to cfg80211 specific interface information. |
555 | * @ndev: associated network device. | 576 | * @ndev: associated network device. |
556 | * @stats: interface specific network statistics. | 577 | * @stats: interface specific network statistics. |
578 | * @setmacaddr_work: worker object for setting mac address. | ||
579 | * @multicast_work: worker object for multicast provisioning. | ||
580 | * @fws_desc: interface specific firmware-signalling descriptor. | ||
557 | * @ifidx: interface index in device firmware. | 581 | * @ifidx: interface index in device firmware. |
558 | * @bssidx: index of bss associated with this interface. | 582 | * @bssidx: index of bss associated with this interface. |
559 | * @mac_addr: assigned mac address. | 583 | * @mac_addr: assigned mac address. |
584 | * @netif_stop: bitmap indicates reason why netif queues are stopped. | ||
560 | * @pend_8021x_cnt: tracks outstanding number of 802.1x frames. | 585 | * @pend_8021x_cnt: tracks outstanding number of 802.1x frames. |
561 | * @pend_8021x_wait: used for signalling change in count. | 586 | * @pend_8021x_wait: used for signalling change in count. |
562 | */ | 587 | */ |
@@ -567,9 +592,11 @@ struct brcmf_if { | |||
567 | struct net_device_stats stats; | 592 | struct net_device_stats stats; |
568 | struct work_struct setmacaddr_work; | 593 | struct work_struct setmacaddr_work; |
569 | struct work_struct multicast_work; | 594 | struct work_struct multicast_work; |
595 | struct brcmf_fws_mac_descriptor *fws_desc; | ||
570 | int ifidx; | 596 | int ifidx; |
571 | s32 bssidx; | 597 | s32 bssidx; |
572 | u8 mac_addr[ETH_ALEN]; | 598 | u8 mac_addr[ETH_ALEN]; |
599 | u8 netif_stop; | ||
573 | atomic_t pend_8021x_cnt; | 600 | atomic_t pend_8021x_cnt; |
574 | wait_queue_head_t pend_8021x_wait; | 601 | wait_queue_head_t pend_8021x_wait; |
575 | }; | 602 | }; |
@@ -594,6 +621,10 @@ extern int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked); | |||
594 | extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, | 621 | extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, |
595 | s32 ifidx, char *name, u8 *mac_addr); | 622 | s32 ifidx, char *name, u8 *mac_addr); |
596 | extern void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx); | 623 | extern void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx); |
624 | void brcmf_txflowblock_if(struct brcmf_if *ifp, | ||
625 | enum brcmf_netif_stop_reason reason, bool state); | ||
597 | extern u32 brcmf_get_chip_info(struct brcmf_if *ifp); | 626 | extern u32 brcmf_get_chip_info(struct brcmf_if *ifp); |
627 | extern void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, | ||
628 | bool success); | ||
598 | 629 | ||
599 | #endif /* _BRCMF_H_ */ | 630 | #endif /* _BRCMF_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h index 883ef9063e8a..080395f49fa5 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h | |||
@@ -39,10 +39,12 @@ struct brcmf_bus_dcmd { | |||
39 | * @txdata: send a data frame to the dongle (callee disposes skb). | 39 | * @txdata: send a data frame to the dongle (callee disposes skb). |
40 | * @txctl: transmit a control request message to dongle. | 40 | * @txctl: transmit a control request message to dongle. |
41 | * @rxctl: receive a control response message from dongle. | 41 | * @rxctl: receive a control response message from dongle. |
42 | * @gettxq: obtain a reference of bus transmit queue (optional). | ||
42 | * | 43 | * |
43 | * This structure provides an abstract interface towards the | 44 | * This structure provides an abstract interface towards the |
44 | * bus specific driver. For control messages to common driver | 45 | * bus specific driver. For control messages to common driver |
45 | * will assure there is only one active transaction. | 46 | * will assure there is only one active transaction. Unless |
47 | * indicated otherwise these callbacks are mandatory. | ||
46 | */ | 48 | */ |
47 | struct brcmf_bus_ops { | 49 | struct brcmf_bus_ops { |
48 | int (*init)(struct device *dev); | 50 | int (*init)(struct device *dev); |
@@ -50,6 +52,7 @@ struct brcmf_bus_ops { | |||
50 | int (*txdata)(struct device *dev, struct sk_buff *skb); | 52 | int (*txdata)(struct device *dev, struct sk_buff *skb); |
51 | int (*txctl)(struct device *dev, unsigned char *msg, uint len); | 53 | int (*txctl)(struct device *dev, unsigned char *msg, uint len); |
52 | int (*rxctl)(struct device *dev, unsigned char *msg, uint len); | 54 | int (*rxctl)(struct device *dev, unsigned char *msg, uint len); |
55 | struct pktq * (*gettxq)(struct device *dev); | ||
53 | }; | 56 | }; |
54 | 57 | ||
55 | /** | 58 | /** |
@@ -115,6 +118,14 @@ int brcmf_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint len) | |||
115 | return bus->ops->rxctl(bus->dev, msg, len); | 118 | return bus->ops->rxctl(bus->dev, msg, len); |
116 | } | 119 | } |
117 | 120 | ||
121 | static inline | ||
122 | struct pktq *brcmf_bus_gettxq(struct brcmf_bus *bus) | ||
123 | { | ||
124 | if (!bus->ops->gettxq) | ||
125 | return ERR_PTR(-ENOENT); | ||
126 | |||
127 | return bus->ops->gettxq(bus->dev); | ||
128 | } | ||
118 | /* | 129 | /* |
119 | * interface functions from common layer | 130 | * interface functions from common layer |
120 | */ | 131 | */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c index e224bcb90024..59c77aa3b959 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c | |||
@@ -303,8 +303,8 @@ int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, | |||
303 | 303 | ||
304 | /* Pop BDC header used to convey priority for buses that don't */ | 304 | /* Pop BDC header used to convey priority for buses that don't */ |
305 | 305 | ||
306 | if (pktbuf->len < BDC_HEADER_LEN) { | 306 | if (pktbuf->len <= BDC_HEADER_LEN) { |
307 | brcmf_err("rx data too short (%d < %d)\n", | 307 | brcmf_dbg(INFO, "rx data too short (%d <= %d)\n", |
308 | pktbuf->len, BDC_HEADER_LEN); | 308 | pktbuf->len, BDC_HEADER_LEN); |
309 | return -EBADE; | 309 | return -EBADE; |
310 | } | 310 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c index ac792499b46a..202869cd0932 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c | |||
@@ -130,7 +130,7 @@ ssize_t brcmf_debugfs_fws_stats_read(struct file *f, char __user *data, | |||
130 | size_t count, loff_t *ppos) | 130 | size_t count, loff_t *ppos) |
131 | { | 131 | { |
132 | struct brcmf_fws_stats *fwstats = f->private_data; | 132 | struct brcmf_fws_stats *fwstats = f->private_data; |
133 | char buf[100]; | 133 | char buf[650]; |
134 | int res; | 134 | int res; |
135 | 135 | ||
136 | /* only allow read from start */ | 136 | /* only allow read from start */ |
@@ -138,14 +138,52 @@ ssize_t brcmf_debugfs_fws_stats_read(struct file *f, char __user *data, | |||
138 | return 0; | 138 | return 0; |
139 | 139 | ||
140 | res = scnprintf(buf, sizeof(buf), | 140 | res = scnprintf(buf, sizeof(buf), |
141 | "header_pulls: %u\n" | 141 | "header_pulls: %u\n" |
142 | "header_only_pkt: %u\n" | 142 | "header_only_pkt: %u\n" |
143 | "tlv_parse_failed: %u\n" | 143 | "tlv_parse_failed: %u\n" |
144 | "tlv_invalid_type: %u\n", | 144 | "tlv_invalid_type: %u\n" |
145 | "mac_update_fails: %u\n" | ||
146 | "ps_update_fails: %u\n" | ||
147 | "if_update_fails: %u\n" | ||
148 | "pkt2bus: %u\n" | ||
149 | "generic_error: %u\n" | ||
150 | "rollback_success: %u\n" | ||
151 | "rollback_failed: %u\n" | ||
152 | "delayq_full: %u\n" | ||
153 | "supprq_full: %u\n" | ||
154 | "txs_indicate: %u\n" | ||
155 | "txs_discard: %u\n" | ||
156 | "txs_suppr_core: %u\n" | ||
157 | "txs_suppr_ps: %u\n" | ||
158 | "txs_tossed: %u\n" | ||
159 | "send_pkts: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n" | ||
160 | "fifo_credits_sent: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n", | ||
145 | fwstats->header_pulls, | 161 | fwstats->header_pulls, |
146 | fwstats->header_only_pkt, | 162 | fwstats->header_only_pkt, |
147 | fwstats->tlv_parse_failed, | 163 | fwstats->tlv_parse_failed, |
148 | fwstats->tlv_invalid_type); | 164 | fwstats->tlv_invalid_type, |
165 | fwstats->mac_update_failed, | ||
166 | fwstats->mac_ps_update_failed, | ||
167 | fwstats->if_update_failed, | ||
168 | fwstats->pkt2bus, | ||
169 | fwstats->generic_error, | ||
170 | fwstats->rollback_success, | ||
171 | fwstats->rollback_failed, | ||
172 | fwstats->delayq_full_error, | ||
173 | fwstats->supprq_full_error, | ||
174 | fwstats->txs_indicate, | ||
175 | fwstats->txs_discard, | ||
176 | fwstats->txs_supp_core, | ||
177 | fwstats->txs_supp_ps, | ||
178 | fwstats->txs_tossed, | ||
179 | fwstats->send_pkts[0], fwstats->send_pkts[1], | ||
180 | fwstats->send_pkts[2], fwstats->send_pkts[3], | ||
181 | fwstats->send_pkts[4], | ||
182 | fwstats->fifo_credits_sent[0], | ||
183 | fwstats->fifo_credits_sent[1], | ||
184 | fwstats->fifo_credits_sent[2], | ||
185 | fwstats->fifo_credits_sent[3], | ||
186 | fwstats->fifo_credits_sent[4]); | ||
149 | 187 | ||
150 | return simple_read_from_buffer(data, count, ppos, buf, res); | 188 | return simple_read_from_buffer(data, count, ppos, buf, res); |
151 | } | 189 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h index 4bc646bde16f..009c87bfd9ae 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h | |||
@@ -34,6 +34,7 @@ | |||
34 | #define BRCMF_SCAN_VAL 0x00004000 | 34 | #define BRCMF_SCAN_VAL 0x00004000 |
35 | #define BRCMF_CONN_VAL 0x00008000 | 35 | #define BRCMF_CONN_VAL 0x00008000 |
36 | #define BRCMF_CDC_VAL 0x00010000 | 36 | #define BRCMF_CDC_VAL 0x00010000 |
37 | #define BRCMF_SDIO_VAL 0x00020000 | ||
37 | 38 | ||
38 | /* set default print format */ | 39 | /* set default print format */ |
39 | #undef pr_fmt | 40 | #undef pr_fmt |
@@ -92,6 +93,7 @@ do { \ | |||
92 | 93 | ||
93 | #define brcmf_dbg_hex_dump(test, data, len, fmt, ...) \ | 94 | #define brcmf_dbg_hex_dump(test, data, len, fmt, ...) \ |
94 | do { \ | 95 | do { \ |
96 | trace_brcmf_hexdump((void *)data, len); \ | ||
95 | if (test) \ | 97 | if (test) \ |
96 | brcmu_dbg_hex_dump(data, len, fmt, ##__VA_ARGS__); \ | 98 | brcmu_dbg_hex_dump(data, len, fmt, ##__VA_ARGS__); \ |
97 | } while (0) | 99 | } while (0) |
@@ -137,6 +139,25 @@ struct brcmf_fws_stats { | |||
137 | u32 tlv_invalid_type; | 139 | u32 tlv_invalid_type; |
138 | u32 header_only_pkt; | 140 | u32 header_only_pkt; |
139 | u32 header_pulls; | 141 | u32 header_pulls; |
142 | u32 pkt2bus; | ||
143 | u32 send_pkts[5]; | ||
144 | u32 fifo_credits_sent[5]; | ||
145 | u32 fifo_credits_back[6]; | ||
146 | u32 generic_error; | ||
147 | u32 mac_update_failed; | ||
148 | u32 mac_ps_update_failed; | ||
149 | u32 if_update_failed; | ||
150 | u32 packet_request_failed; | ||
151 | u32 credit_request_failed; | ||
152 | u32 rollback_success; | ||
153 | u32 rollback_failed; | ||
154 | u32 delayq_full_error; | ||
155 | u32 supprq_full_error; | ||
156 | u32 txs_indicate; | ||
157 | u32 txs_discard; | ||
158 | u32 txs_supp_core; | ||
159 | u32 txs_supp_ps; | ||
160 | u32 txs_tossed; | ||
140 | }; | 161 | }; |
141 | 162 | ||
142 | struct brcmf_pub; | 163 | struct brcmf_pub; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index fa5a2af04d46..763a84eba216 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | |||
@@ -223,18 +223,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, | |||
223 | goto done; | 223 | goto done; |
224 | } | 224 | } |
225 | 225 | ||
226 | /* handle ethernet header */ | 226 | ret = brcmf_fws_process_skb(ifp, skb); |
227 | eh = (struct ethhdr *)(skb->data); | ||
228 | if (is_multicast_ether_addr(eh->h_dest)) | ||
229 | drvr->tx_multicast++; | ||
230 | if (ntohs(eh->h_proto) == ETH_P_PAE) | ||
231 | atomic_inc(&ifp->pend_8021x_cnt); | ||
232 | |||
233 | /* If the protocol uses a data header, apply it */ | ||
234 | brcmf_proto_hdrpush(drvr, ifp->ifidx, 0, skb); | ||
235 | |||
236 | /* Use bus module to send data frame */ | ||
237 | ret = brcmf_bus_txdata(drvr->bus_if, skb); | ||
238 | 227 | ||
239 | done: | 228 | done: |
240 | if (ret) { | 229 | if (ret) { |
@@ -248,9 +237,27 @@ done: | |||
248 | return NETDEV_TX_OK; | 237 | return NETDEV_TX_OK; |
249 | } | 238 | } |
250 | 239 | ||
240 | void brcmf_txflowblock_if(struct brcmf_if *ifp, | ||
241 | enum brcmf_netif_stop_reason reason, bool state) | ||
242 | { | ||
243 | if (!ifp) | ||
244 | return; | ||
245 | |||
246 | brcmf_dbg(TRACE, "enter: idx=%d stop=0x%X reason=%d state=%d\n", | ||
247 | ifp->bssidx, ifp->netif_stop, reason, state); | ||
248 | if (state) { | ||
249 | if (!ifp->netif_stop) | ||
250 | netif_stop_queue(ifp->ndev); | ||
251 | ifp->netif_stop |= reason; | ||
252 | } else { | ||
253 | ifp->netif_stop &= ~reason; | ||
254 | if (!ifp->netif_stop) | ||
255 | netif_wake_queue(ifp->ndev); | ||
256 | } | ||
257 | } | ||
258 | |||
251 | void brcmf_txflowblock(struct device *dev, bool state) | 259 | void brcmf_txflowblock(struct device *dev, bool state) |
252 | { | 260 | { |
253 | struct net_device *ndev; | ||
254 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 261 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
255 | struct brcmf_pub *drvr = bus_if->drvr; | 262 | struct brcmf_pub *drvr = bus_if->drvr; |
256 | int i; | 263 | int i; |
@@ -258,13 +265,8 @@ void brcmf_txflowblock(struct device *dev, bool state) | |||
258 | brcmf_dbg(TRACE, "Enter\n"); | 265 | brcmf_dbg(TRACE, "Enter\n"); |
259 | 266 | ||
260 | for (i = 0; i < BRCMF_MAX_IFS; i++) | 267 | for (i = 0; i < BRCMF_MAX_IFS; i++) |
261 | if (drvr->iflist[i]) { | 268 | brcmf_txflowblock_if(drvr->iflist[i], |
262 | ndev = drvr->iflist[i]->ndev; | 269 | BRCMF_NETIF_STOP_REASON_BLOCK_BUS, state); |
263 | if (state) | ||
264 | netif_stop_queue(ndev); | ||
265 | else | ||
266 | netif_wake_queue(ndev); | ||
267 | } | ||
268 | } | 270 | } |
269 | 271 | ||
270 | void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) | 272 | void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) |
@@ -321,13 +323,8 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) | |||
321 | /* Strip header, count, deliver upward */ | 323 | /* Strip header, count, deliver upward */ |
322 | skb_pull(skb, ETH_HLEN); | 324 | skb_pull(skb, ETH_HLEN); |
323 | 325 | ||
324 | /* Process special event packets and then discard them */ | 326 | /* Process special event packets */ |
325 | brcmf_fweh_process_skb(drvr, skb, &ifidx); | 327 | brcmf_fweh_process_skb(drvr, skb); |
326 | |||
327 | if (drvr->iflist[ifidx]) { | ||
328 | ifp = drvr->iflist[ifidx]; | ||
329 | ifp->ndev->last_rx = jiffies; | ||
330 | } | ||
331 | 328 | ||
332 | if (!(ifp->ndev->flags & IFF_UP)) { | 329 | if (!(ifp->ndev->flags & IFF_UP)) { |
333 | brcmu_pkt_buf_free_skb(skb); | 330 | brcmu_pkt_buf_free_skb(skb); |
@@ -350,14 +347,13 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) | |||
350 | } | 347 | } |
351 | } | 348 | } |
352 | 349 | ||
353 | void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success) | 350 | void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, |
351 | bool success) | ||
354 | { | 352 | { |
355 | u8 ifidx; | 353 | struct brcmf_if *ifp; |
356 | struct ethhdr *eh; | 354 | struct ethhdr *eh; |
355 | u8 ifidx; | ||
357 | u16 type; | 356 | u16 type; |
358 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | ||
359 | struct brcmf_pub *drvr = bus_if->drvr; | ||
360 | struct brcmf_if *ifp; | ||
361 | int res; | 357 | int res; |
362 | 358 | ||
363 | res = brcmf_proto_hdrpull(drvr, false, &ifidx, txp); | 359 | res = brcmf_proto_hdrpull(drvr, false, &ifidx, txp); |
@@ -378,11 +374,24 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success) | |||
378 | } | 374 | } |
379 | if (!success) | 375 | if (!success) |
380 | ifp->stats.tx_errors++; | 376 | ifp->stats.tx_errors++; |
381 | |||
382 | done: | 377 | done: |
383 | brcmu_pkt_buf_free_skb(txp); | 378 | brcmu_pkt_buf_free_skb(txp); |
384 | } | 379 | } |
385 | 380 | ||
381 | void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success) | ||
382 | { | ||
383 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | ||
384 | struct brcmf_pub *drvr = bus_if->drvr; | ||
385 | |||
386 | /* await txstatus signal for firmware if active */ | ||
387 | if (brcmf_fws_fc_active(drvr->fws)) { | ||
388 | if (!success) | ||
389 | brcmf_fws_bustxfail(drvr->fws, txp); | ||
390 | } else { | ||
391 | brcmf_txfinalize(drvr, txp, success); | ||
392 | } | ||
393 | } | ||
394 | |||
386 | static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev) | 395 | static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev) |
387 | { | 396 | { |
388 | struct brcmf_if *ifp = netdev_priv(ndev); | 397 | struct brcmf_if *ifp = netdev_priv(ndev); |
@@ -741,28 +750,35 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, | |||
741 | } | 750 | } |
742 | } | 751 | } |
743 | 752 | ||
744 | /* Allocate netdev, including space for private structure */ | 753 | if (!brcmf_p2p_enable && bssidx == 1) { |
745 | ndev = alloc_netdev(sizeof(struct brcmf_if), name, ether_setup); | 754 | /* this is P2P_DEVICE interface */ |
746 | if (!ndev) { | 755 | brcmf_dbg(INFO, "allocate non-netdev interface\n"); |
747 | brcmf_err("OOM - alloc_netdev\n"); | 756 | ifp = kzalloc(sizeof(*ifp), GFP_KERNEL); |
748 | return ERR_PTR(-ENOMEM); | 757 | } else { |
758 | brcmf_dbg(INFO, "allocate netdev interface\n"); | ||
759 | /* Allocate netdev, including space for private structure */ | ||
760 | ndev = alloc_netdev(sizeof(*ifp), name, ether_setup); | ||
761 | if (!ndev) { | ||
762 | brcmf_err("OOM - alloc_netdev\n"); | ||
763 | return ERR_PTR(-ENOMEM); | ||
764 | } | ||
765 | |||
766 | ifp = netdev_priv(ndev); | ||
767 | ifp->ndev = ndev; | ||
749 | } | 768 | } |
750 | 769 | ||
751 | ifp = netdev_priv(ndev); | ||
752 | ifp->ndev = ndev; | ||
753 | ifp->drvr = drvr; | 770 | ifp->drvr = drvr; |
754 | drvr->iflist[bssidx] = ifp; | 771 | drvr->iflist[bssidx] = ifp; |
755 | ifp->ifidx = ifidx; | 772 | ifp->ifidx = ifidx; |
756 | ifp->bssidx = bssidx; | 773 | ifp->bssidx = bssidx; |
757 | 774 | ||
758 | |||
759 | init_waitqueue_head(&ifp->pend_8021x_wait); | 775 | init_waitqueue_head(&ifp->pend_8021x_wait); |
760 | 776 | ||
761 | if (mac_addr != NULL) | 777 | if (mac_addr != NULL) |
762 | memcpy(ifp->mac_addr, mac_addr, ETH_ALEN); | 778 | memcpy(ifp->mac_addr, mac_addr, ETH_ALEN); |
763 | 779 | ||
764 | brcmf_dbg(TRACE, " ==== pid:%x, if:%s (%pM) created ===\n", | 780 | brcmf_dbg(TRACE, " ==== pid:%x, if:%s (%pM) created ===\n", |
765 | current->pid, ifp->ndev->name, ifp->mac_addr); | 781 | current->pid, name, ifp->mac_addr); |
766 | 782 | ||
767 | return ifp; | 783 | return ifp; |
768 | } | 784 | } |
@@ -794,11 +810,13 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx) | |||
794 | } | 810 | } |
795 | 811 | ||
796 | unregister_netdev(ifp->ndev); | 812 | unregister_netdev(ifp->ndev); |
797 | drvr->iflist[bssidx] = NULL; | ||
798 | if (bssidx == 0) | 813 | if (bssidx == 0) |
799 | brcmf_cfg80211_detach(drvr->config); | 814 | brcmf_cfg80211_detach(drvr->config); |
800 | free_netdev(ifp->ndev); | 815 | free_netdev(ifp->ndev); |
816 | } else { | ||
817 | kfree(ifp); | ||
801 | } | 818 | } |
819 | drvr->iflist[bssidx] = NULL; | ||
802 | } | 820 | } |
803 | 821 | ||
804 | int brcmf_attach(uint bus_hdrlen, struct device *dev) | 822 | int brcmf_attach(uint bus_hdrlen, struct device *dev) |
@@ -882,6 +900,7 @@ int brcmf_bus_start(struct device *dev) | |||
882 | 900 | ||
883 | drvr->fw_signals = true; | 901 | drvr->fw_signals = true; |
884 | (void)brcmf_fws_init(drvr); | 902 | (void)brcmf_fws_init(drvr); |
903 | brcmf_fws_add_interface(ifp); | ||
885 | 904 | ||
886 | drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev); | 905 | drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev); |
887 | if (drvr->config == NULL) { | 906 | if (drvr->config == NULL) { |
@@ -899,8 +918,10 @@ fail: | |||
899 | brcmf_err("failed: %d\n", ret); | 918 | brcmf_err("failed: %d\n", ret); |
900 | if (drvr->config) | 919 | if (drvr->config) |
901 | brcmf_cfg80211_detach(drvr->config); | 920 | brcmf_cfg80211_detach(drvr->config); |
902 | if (drvr->fws) | 921 | if (drvr->fws) { |
922 | brcmf_fws_del_interface(ifp); | ||
903 | brcmf_fws_deinit(drvr); | 923 | brcmf_fws_deinit(drvr); |
924 | } | ||
904 | free_netdev(ifp->ndev); | 925 | free_netdev(ifp->ndev); |
905 | drvr->iflist[0] = NULL; | 926 | drvr->iflist[0] = NULL; |
906 | if (p2p_ifp) { | 927 | if (p2p_ifp) { |
@@ -956,16 +977,17 @@ void brcmf_detach(struct device *dev) | |||
956 | 977 | ||
957 | /* make sure primary interface removed last */ | 978 | /* make sure primary interface removed last */ |
958 | for (i = BRCMF_MAX_IFS-1; i > -1; i--) | 979 | for (i = BRCMF_MAX_IFS-1; i > -1; i--) |
959 | if (drvr->iflist[i]) | 980 | if (drvr->iflist[i]) { |
981 | brcmf_fws_del_interface(drvr->iflist[i]); | ||
960 | brcmf_del_if(drvr, i); | 982 | brcmf_del_if(drvr, i); |
983 | } | ||
961 | 984 | ||
962 | brcmf_bus_detach(drvr); | 985 | brcmf_bus_detach(drvr); |
963 | 986 | ||
964 | if (drvr->prot) | 987 | if (drvr->prot) |
965 | brcmf_proto_detach(drvr); | 988 | brcmf_proto_detach(drvr); |
966 | 989 | ||
967 | if (drvr->fws) | 990 | brcmf_fws_deinit(drvr); |
968 | brcmf_fws_deinit(drvr); | ||
969 | 991 | ||
970 | brcmf_debugfs_detach(drvr); | 992 | brcmf_debugfs_detach(drvr); |
971 | bus_if->drvr = NULL; | 993 | bus_if->drvr = NULL; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 9a2edd3f0a5c..4ff2d3c52ee6 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -94,6 +94,7 @@ struct rte_console { | |||
94 | 94 | ||
95 | #include "dhd_bus.h" | 95 | #include "dhd_bus.h" |
96 | #include "dhd_dbg.h" | 96 | #include "dhd_dbg.h" |
97 | #include "tracepoint.h" | ||
97 | 98 | ||
98 | #define TXQLEN 2048 /* bulk tx queue length */ | 99 | #define TXQLEN 2048 /* bulk tx queue length */ |
99 | #define TXHI (TXQLEN - 256) /* turn on flow control above TXHI */ | 100 | #define TXHI (TXQLEN - 256) /* turn on flow control above TXHI */ |
@@ -675,7 +676,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | |||
675 | u8 clkctl, clkreq, devctl; | 676 | u8 clkctl, clkreq, devctl; |
676 | unsigned long timeout; | 677 | unsigned long timeout; |
677 | 678 | ||
678 | brcmf_dbg(TRACE, "Enter\n"); | 679 | brcmf_dbg(SDIO, "Enter\n"); |
679 | 680 | ||
680 | clkctl = 0; | 681 | clkctl = 0; |
681 | 682 | ||
@@ -713,7 +714,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | |||
713 | devctl |= SBSDIO_DEVCTL_CA_INT_ONLY; | 714 | devctl |= SBSDIO_DEVCTL_CA_INT_ONLY; |
714 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, | 715 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, |
715 | devctl, &err); | 716 | devctl, &err); |
716 | brcmf_dbg(INFO, "CLKCTL: set PENDING\n"); | 717 | brcmf_dbg(SDIO, "CLKCTL: set PENDING\n"); |
717 | bus->clkstate = CLK_PENDING; | 718 | bus->clkstate = CLK_PENDING; |
718 | 719 | ||
719 | return 0; | 720 | return 0; |
@@ -750,7 +751,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | |||
750 | 751 | ||
751 | /* Mark clock available */ | 752 | /* Mark clock available */ |
752 | bus->clkstate = CLK_AVAIL; | 753 | bus->clkstate = CLK_AVAIL; |
753 | brcmf_dbg(INFO, "CLKCTL: turned ON\n"); | 754 | brcmf_dbg(SDIO, "CLKCTL: turned ON\n"); |
754 | 755 | ||
755 | #if defined(DEBUG) | 756 | #if defined(DEBUG) |
756 | if (!bus->alp_only) { | 757 | if (!bus->alp_only) { |
@@ -775,7 +776,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | |||
775 | bus->clkstate = CLK_SDONLY; | 776 | bus->clkstate = CLK_SDONLY; |
776 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, | 777 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, |
777 | clkreq, &err); | 778 | clkreq, &err); |
778 | brcmf_dbg(INFO, "CLKCTL: turned OFF\n"); | 779 | brcmf_dbg(SDIO, "CLKCTL: turned OFF\n"); |
779 | if (err) { | 780 | if (err) { |
780 | brcmf_err("Failed access turning clock off: %d\n", | 781 | brcmf_err("Failed access turning clock off: %d\n", |
781 | err); | 782 | err); |
@@ -788,7 +789,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | |||
788 | /* Change idle/active SD state */ | 789 | /* Change idle/active SD state */ |
789 | static int brcmf_sdbrcm_sdclk(struct brcmf_sdio *bus, bool on) | 790 | static int brcmf_sdbrcm_sdclk(struct brcmf_sdio *bus, bool on) |
790 | { | 791 | { |
791 | brcmf_dbg(TRACE, "Enter\n"); | 792 | brcmf_dbg(SDIO, "Enter\n"); |
792 | 793 | ||
793 | if (on) | 794 | if (on) |
794 | bus->clkstate = CLK_SDONLY; | 795 | bus->clkstate = CLK_SDONLY; |
@@ -805,7 +806,7 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok) | |||
805 | uint oldstate = bus->clkstate; | 806 | uint oldstate = bus->clkstate; |
806 | #endif /* DEBUG */ | 807 | #endif /* DEBUG */ |
807 | 808 | ||
808 | brcmf_dbg(TRACE, "Enter\n"); | 809 | brcmf_dbg(SDIO, "Enter\n"); |
809 | 810 | ||
810 | /* Early exit if we're already there */ | 811 | /* Early exit if we're already there */ |
811 | if (bus->clkstate == target) { | 812 | if (bus->clkstate == target) { |
@@ -849,7 +850,7 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok) | |||
849 | break; | 850 | break; |
850 | } | 851 | } |
851 | #ifdef DEBUG | 852 | #ifdef DEBUG |
852 | brcmf_dbg(INFO, "%d -> %d\n", oldstate, bus->clkstate); | 853 | brcmf_dbg(SDIO, "%d -> %d\n", oldstate, bus->clkstate); |
853 | #endif /* DEBUG */ | 854 | #endif /* DEBUG */ |
854 | 855 | ||
855 | return 0; | 856 | return 0; |
@@ -862,7 +863,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) | |||
862 | u8 fcbits; | 863 | u8 fcbits; |
863 | int ret; | 864 | int ret; |
864 | 865 | ||
865 | brcmf_dbg(TRACE, "Enter\n"); | 866 | brcmf_dbg(SDIO, "Enter\n"); |
866 | 867 | ||
867 | /* Read mailbox data and ack that we did so */ | 868 | /* Read mailbox data and ack that we did so */ |
868 | ret = r_sdreg32(bus, &hmb_data, | 869 | ret = r_sdreg32(bus, &hmb_data, |
@@ -875,7 +876,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) | |||
875 | 876 | ||
876 | /* Dongle recomposed rx frames, accept them again */ | 877 | /* Dongle recomposed rx frames, accept them again */ |
877 | if (hmb_data & HMB_DATA_NAKHANDLED) { | 878 | if (hmb_data & HMB_DATA_NAKHANDLED) { |
878 | brcmf_dbg(INFO, "Dongle reports NAK handled, expect rtx of %d\n", | 879 | brcmf_dbg(SDIO, "Dongle reports NAK handled, expect rtx of %d\n", |
879 | bus->rx_seq); | 880 | bus->rx_seq); |
880 | if (!bus->rxskip) | 881 | if (!bus->rxskip) |
881 | brcmf_err("unexpected NAKHANDLED!\n"); | 882 | brcmf_err("unexpected NAKHANDLED!\n"); |
@@ -896,7 +897,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) | |||
896 | "expecting %d\n", | 897 | "expecting %d\n", |
897 | bus->sdpcm_ver, SDPCM_PROT_VERSION); | 898 | bus->sdpcm_ver, SDPCM_PROT_VERSION); |
898 | else | 899 | else |
899 | brcmf_dbg(INFO, "Dongle ready, protocol version %d\n", | 900 | brcmf_dbg(SDIO, "Dongle ready, protocol version %d\n", |
900 | bus->sdpcm_ver); | 901 | bus->sdpcm_ver); |
901 | } | 902 | } |
902 | 903 | ||
@@ -970,7 +971,7 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) | |||
970 | if (!retries) | 971 | if (!retries) |
971 | brcmf_err("count never zeroed: last 0x%04x\n", lastrbc); | 972 | brcmf_err("count never zeroed: last 0x%04x\n", lastrbc); |
972 | else | 973 | else |
973 | brcmf_dbg(INFO, "flush took %d iterations\n", 0xffff - retries); | 974 | brcmf_dbg(SDIO, "flush took %d iterations\n", 0xffff - retries); |
974 | 975 | ||
975 | if (rtx) { | 976 | if (rtx) { |
976 | bus->sdcnt.rxrtx++; | 977 | bus->sdcnt.rxrtx++; |
@@ -1173,7 +1174,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1173 | /* If packets, issue read(s) and send up packet chain */ | 1174 | /* If packets, issue read(s) and send up packet chain */ |
1174 | /* Return sequence numbers consumed? */ | 1175 | /* Return sequence numbers consumed? */ |
1175 | 1176 | ||
1176 | brcmf_dbg(TRACE, "start: glomd %p glom %p\n", | 1177 | brcmf_dbg(SDIO, "start: glomd %p glom %p\n", |
1177 | bus->glomd, skb_peek(&bus->glom)); | 1178 | bus->glomd, skb_peek(&bus->glom)); |
1178 | 1179 | ||
1179 | /* If there's a descriptor, generate the packet chain */ | 1180 | /* If there's a descriptor, generate the packet chain */ |
@@ -1781,7 +1782,6 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, | |||
1781 | u8 *frame; | 1782 | u8 *frame; |
1782 | u16 len, pad = 0; | 1783 | u16 len, pad = 0; |
1783 | u32 swheader; | 1784 | u32 swheader; |
1784 | struct sk_buff *new; | ||
1785 | int i; | 1785 | int i; |
1786 | 1786 | ||
1787 | brcmf_dbg(TRACE, "Enter\n"); | 1787 | brcmf_dbg(TRACE, "Enter\n"); |
@@ -1795,27 +1795,14 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, | |||
1795 | brcmf_dbg(INFO, "insufficient headroom %d for %d pad\n", | 1795 | brcmf_dbg(INFO, "insufficient headroom %d for %d pad\n", |
1796 | skb_headroom(pkt), pad); | 1796 | skb_headroom(pkt), pad); |
1797 | bus->sdiodev->bus_if->tx_realloc++; | 1797 | bus->sdiodev->bus_if->tx_realloc++; |
1798 | new = brcmu_pkt_buf_get_skb(pkt->len + BRCMF_SDALIGN); | 1798 | ret = skb_cow(pkt, BRCMF_SDALIGN); |
1799 | if (!new) { | 1799 | if (ret) |
1800 | brcmf_err("couldn't allocate new %d-byte packet\n", | ||
1801 | pkt->len + BRCMF_SDALIGN); | ||
1802 | ret = -ENOMEM; | ||
1803 | goto done; | 1800 | goto done; |
1804 | } | 1801 | pad = ((unsigned long)frame % BRCMF_SDALIGN); |
1805 | |||
1806 | pkt_align(new, pkt->len, BRCMF_SDALIGN); | ||
1807 | memcpy(new->data, pkt->data, pkt->len); | ||
1808 | brcmu_pkt_buf_free_skb(pkt); | ||
1809 | pkt = new; | ||
1810 | frame = (u8 *) (pkt->data); | ||
1811 | /* precondition: (frame % BRCMF_SDALIGN) == 0) */ | ||
1812 | pad = 0; | ||
1813 | } else { | ||
1814 | skb_push(pkt, pad); | ||
1815 | frame = (u8 *) (pkt->data); | ||
1816 | /* precondition: pad + SDPCM_HDRLEN <= pkt->len */ | ||
1817 | memset(frame, 0, pad + SDPCM_HDRLEN); | ||
1818 | } | 1802 | } |
1803 | skb_push(pkt, pad); | ||
1804 | frame = (u8 *) (pkt->data); | ||
1805 | memset(frame, 0, pad + SDPCM_HDRLEN); | ||
1819 | } | 1806 | } |
1820 | /* precondition: pad < BRCMF_SDALIGN */ | 1807 | /* precondition: pad < BRCMF_SDALIGN */ |
1821 | 1808 | ||
@@ -1830,8 +1817,8 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, | |||
1830 | (((pad + | 1817 | (((pad + |
1831 | SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK); | 1818 | SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK); |
1832 | 1819 | ||
1833 | put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN); | 1820 | *(((__le32 *) frame) + 1) = cpu_to_le32(swheader); |
1834 | put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader)); | 1821 | *(((__le32 *) frame) + 2) = 0; |
1835 | 1822 | ||
1836 | #ifdef DEBUG | 1823 | #ifdef DEBUG |
1837 | tx_packets[pkt->priority]++; | 1824 | tx_packets[pkt->priority]++; |
@@ -1897,7 +1884,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, | |||
1897 | done: | 1884 | done: |
1898 | /* restore pkt buffer pointer before calling tx complete routine */ | 1885 | /* restore pkt buffer pointer before calling tx complete routine */ |
1899 | skb_pull(pkt, SDPCM_HDRLEN + pad); | 1886 | skb_pull(pkt, SDPCM_HDRLEN + pad); |
1900 | brcmf_txcomplete(bus->sdiodev->dev, pkt, ret != 0); | 1887 | brcmf_txcomplete(bus->sdiodev->dev, pkt, ret == 0); |
1901 | return ret; | 1888 | return ret; |
1902 | } | 1889 | } |
1903 | 1890 | ||
@@ -2131,7 +2118,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2131 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 2118 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
2132 | } | 2119 | } |
2133 | 2120 | ||
2134 | brcmf_dbg(INFO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", | 2121 | brcmf_dbg(SDIO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", |
2135 | devctl, clkctl); | 2122 | devctl, clkctl); |
2136 | 2123 | ||
2137 | if (SBSDIO_HTAV(clkctl)) { | 2124 | if (SBSDIO_HTAV(clkctl)) { |
@@ -2307,6 +2294,15 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2307 | } | 2294 | } |
2308 | } | 2295 | } |
2309 | 2296 | ||
2297 | static struct pktq *brcmf_sdbrcm_bus_gettxq(struct device *dev) | ||
2298 | { | ||
2299 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | ||
2300 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | ||
2301 | struct brcmf_sdio *bus = sdiodev->bus; | ||
2302 | |||
2303 | return &bus->txq; | ||
2304 | } | ||
2305 | |||
2310 | static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) | 2306 | static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) |
2311 | { | 2307 | { |
2312 | int ret = -EBADE; | 2308 | int ret = -EBADE; |
@@ -2392,7 +2388,7 @@ brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data, | |||
2392 | 2388 | ||
2393 | /* Do the transfer(s) */ | 2389 | /* Do the transfer(s) */ |
2394 | while (size) { | 2390 | while (size) { |
2395 | brcmf_dbg(INFO, "%s %d bytes at offset 0x%08x in window 0x%08x\n", | 2391 | brcmf_dbg(SDIO, "%s %d bytes at offset 0x%08x in window 0x%08x\n", |
2396 | write ? "write" : "read", dsize, | 2392 | write ? "write" : "read", dsize, |
2397 | sdaddr, address & SBSDIO_SBWINDOW_MASK); | 2393 | sdaddr, address & SBSDIO_SBWINDOW_MASK); |
2398 | bcmerror = brcmf_sdcard_rwdata(bus->sdiodev, write, | 2394 | bcmerror = brcmf_sdcard_rwdata(bus->sdiodev, write, |
@@ -2625,10 +2621,10 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2625 | msecs_to_jiffies(2000)); | 2621 | msecs_to_jiffies(2000)); |
2626 | 2622 | ||
2627 | if (!bus->ctrl_frame_stat) { | 2623 | if (!bus->ctrl_frame_stat) { |
2628 | brcmf_dbg(INFO, "ctrl_frame_stat == false\n"); | 2624 | brcmf_dbg(SDIO, "ctrl_frame_stat == false\n"); |
2629 | ret = 0; | 2625 | ret = 0; |
2630 | } else { | 2626 | } else { |
2631 | brcmf_dbg(INFO, "ctrl_frame_stat == true\n"); | 2627 | brcmf_dbg(SDIO, "ctrl_frame_stat == true\n"); |
2632 | ret = -1; | 2628 | ret = -1; |
2633 | } | 2629 | } |
2634 | } | 2630 | } |
@@ -2699,7 +2695,7 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus, | |||
2699 | 2695 | ||
2700 | addr = le32_to_cpu(addr_le); | 2696 | addr = le32_to_cpu(addr_le); |
2701 | 2697 | ||
2702 | brcmf_dbg(INFO, "sdpcm_shared address 0x%08X\n", addr); | 2698 | brcmf_dbg(SDIO, "sdpcm_shared address 0x%08X\n", addr); |
2703 | 2699 | ||
2704 | /* | 2700 | /* |
2705 | * Check if addr is valid. | 2701 | * Check if addr is valid. |
@@ -2726,8 +2722,8 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus, | |||
2726 | sh->console_addr = le32_to_cpu(sh_le.console_addr); | 2722 | sh->console_addr = le32_to_cpu(sh_le.console_addr); |
2727 | sh->msgtrace_addr = le32_to_cpu(sh_le.msgtrace_addr); | 2723 | sh->msgtrace_addr = le32_to_cpu(sh_le.msgtrace_addr); |
2728 | 2724 | ||
2729 | if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) { | 2725 | if ((sh->flags & SDPCM_SHARED_VERSION_MASK) > SDPCM_SHARED_VERSION) { |
2730 | brcmf_err("sdpcm_shared version mismatch: dhd %d dongle %d\n", | 2726 | brcmf_err("sdpcm shared version unsupported: dhd %d dongle %d\n", |
2731 | SDPCM_SHARED_VERSION, | 2727 | SDPCM_SHARED_VERSION, |
2732 | sh->flags & SDPCM_SHARED_VERSION_MASK); | 2728 | sh->flags & SDPCM_SHARED_VERSION_MASK); |
2733 | return -EPROTO; | 2729 | return -EPROTO; |
@@ -2809,21 +2805,18 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh, | |||
2809 | int error, res; | 2805 | int error, res; |
2810 | char buf[350]; | 2806 | char buf[350]; |
2811 | struct brcmf_trap_info tr; | 2807 | struct brcmf_trap_info tr; |
2812 | int nbytes; | ||
2813 | loff_t pos = 0; | 2808 | loff_t pos = 0; |
2814 | 2809 | ||
2815 | if ((sh->flags & SDPCM_SHARED_TRAP) == 0) | 2810 | if ((sh->flags & SDPCM_SHARED_TRAP) == 0) { |
2811 | brcmf_dbg(INFO, "no trap in firmware\n"); | ||
2816 | return 0; | 2812 | return 0; |
2813 | } | ||
2817 | 2814 | ||
2818 | error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr, | 2815 | error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr, |
2819 | sizeof(struct brcmf_trap_info)); | 2816 | sizeof(struct brcmf_trap_info)); |
2820 | if (error < 0) | 2817 | if (error < 0) |
2821 | return error; | 2818 | return error; |
2822 | 2819 | ||
2823 | nbytes = brcmf_sdio_dump_console(bus, sh, data, count); | ||
2824 | if (nbytes < 0) | ||
2825 | return nbytes; | ||
2826 | |||
2827 | res = scnprintf(buf, sizeof(buf), | 2820 | res = scnprintf(buf, sizeof(buf), |
2828 | "dongle trap info: type 0x%x @ epc 0x%08x\n" | 2821 | "dongle trap info: type 0x%x @ epc 0x%08x\n" |
2829 | " cpsr 0x%08x spsr 0x%08x sp 0x%08x\n" | 2822 | " cpsr 0x%08x spsr 0x%08x sp 0x%08x\n" |
@@ -2839,12 +2832,7 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh, | |||
2839 | le32_to_cpu(tr.r4), le32_to_cpu(tr.r5), | 2832 | le32_to_cpu(tr.r4), le32_to_cpu(tr.r5), |
2840 | le32_to_cpu(tr.r6), le32_to_cpu(tr.r7)); | 2833 | le32_to_cpu(tr.r6), le32_to_cpu(tr.r7)); |
2841 | 2834 | ||
2842 | error = simple_read_from_buffer(data+nbytes, count, &pos, buf, res); | 2835 | return simple_read_from_buffer(data, count, &pos, buf, res); |
2843 | if (error < 0) | ||
2844 | return error; | ||
2845 | |||
2846 | nbytes += error; | ||
2847 | return nbytes; | ||
2848 | } | 2836 | } |
2849 | 2837 | ||
2850 | static int brcmf_sdio_assert_info(struct brcmf_sdio *bus, | 2838 | static int brcmf_sdio_assert_info(struct brcmf_sdio *bus, |
@@ -2926,14 +2914,20 @@ static int brcmf_sdbrcm_died_dump(struct brcmf_sdio *bus, char __user *data, | |||
2926 | error = brcmf_sdio_assert_info(bus, &sh, data, count); | 2914 | error = brcmf_sdio_assert_info(bus, &sh, data, count); |
2927 | if (error < 0) | 2915 | if (error < 0) |
2928 | goto done; | 2916 | goto done; |
2929 | |||
2930 | nbytes = error; | 2917 | nbytes = error; |
2931 | error = brcmf_sdio_trap_info(bus, &sh, data, count); | 2918 | |
2919 | error = brcmf_sdio_trap_info(bus, &sh, data+nbytes, count); | ||
2920 | if (error < 0) | ||
2921 | goto done; | ||
2922 | nbytes += error; | ||
2923 | |||
2924 | error = brcmf_sdio_dump_console(bus, &sh, data+nbytes, count); | ||
2932 | if (error < 0) | 2925 | if (error < 0) |
2933 | goto done; | 2926 | goto done; |
2927 | nbytes += error; | ||
2934 | 2928 | ||
2935 | error += nbytes; | 2929 | error = nbytes; |
2936 | *ppos += error; | 2930 | *ppos += nbytes; |
2937 | done: | 2931 | done: |
2938 | return error; | 2932 | return error; |
2939 | } | 2933 | } |
@@ -3309,15 +3303,15 @@ static int _brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus) | |||
3309 | goto err; | 3303 | goto err; |
3310 | } | 3304 | } |
3311 | 3305 | ||
3312 | /* External image takes precedence if specified */ | ||
3313 | if (brcmf_sdbrcm_download_code_file(bus)) { | 3306 | if (brcmf_sdbrcm_download_code_file(bus)) { |
3314 | brcmf_err("dongle image file download failed\n"); | 3307 | brcmf_err("dongle image file download failed\n"); |
3315 | goto err; | 3308 | goto err; |
3316 | } | 3309 | } |
3317 | 3310 | ||
3318 | /* External nvram takes precedence if specified */ | 3311 | if (brcmf_sdbrcm_download_nvram(bus)) { |
3319 | if (brcmf_sdbrcm_download_nvram(bus)) | ||
3320 | brcmf_err("dongle nvram file download failed\n"); | 3312 | brcmf_err("dongle nvram file download failed\n"); |
3313 | goto err; | ||
3314 | } | ||
3321 | 3315 | ||
3322 | /* Take arm out of reset */ | 3316 | /* Take arm out of reset */ |
3323 | if (brcmf_sdbrcm_download_state(bus, false)) { | 3317 | if (brcmf_sdbrcm_download_state(bus, false)) { |
@@ -3848,6 +3842,7 @@ static struct brcmf_bus_ops brcmf_sdio_bus_ops = { | |||
3848 | .txdata = brcmf_sdbrcm_bus_txdata, | 3842 | .txdata = brcmf_sdbrcm_bus_txdata, |
3849 | .txctl = brcmf_sdbrcm_bus_txctl, | 3843 | .txctl = brcmf_sdbrcm_bus_txctl, |
3850 | .rxctl = brcmf_sdbrcm_bus_rxctl, | 3844 | .rxctl = brcmf_sdbrcm_bus_rxctl, |
3845 | .gettxq = brcmf_sdbrcm_bus_gettxq, | ||
3851 | }; | 3846 | }; |
3852 | 3847 | ||
3853 | void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | 3848 | void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c index e9d6f91a1f2b..5a64280e6485 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c | |||
@@ -20,6 +20,8 @@ | |||
20 | 20 | ||
21 | #include "dhd.h" | 21 | #include "dhd.h" |
22 | #include "dhd_dbg.h" | 22 | #include "dhd_dbg.h" |
23 | #include "tracepoint.h" | ||
24 | #include "fwsignal.h" | ||
23 | #include "fweh.h" | 25 | #include "fweh.h" |
24 | #include "fwil.h" | 26 | #include "fwil.h" |
25 | 27 | ||
@@ -154,7 +156,7 @@ static int brcmf_fweh_call_event_handler(struct brcmf_if *ifp, | |||
154 | fweh = &ifp->drvr->fweh; | 156 | fweh = &ifp->drvr->fweh; |
155 | 157 | ||
156 | /* handle the event if valid interface and handler */ | 158 | /* handle the event if valid interface and handler */ |
157 | if (ifp->ndev && fweh->evt_handler[code]) | 159 | if (fweh->evt_handler[code]) |
158 | err = fweh->evt_handler[code](ifp, emsg, data); | 160 | err = fweh->evt_handler[code](ifp, emsg, data); |
159 | else | 161 | else |
160 | brcmf_err("unhandled event %d ignored\n", code); | 162 | brcmf_err("unhandled event %d ignored\n", code); |
@@ -179,9 +181,9 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr, | |||
179 | struct brcmf_if *ifp; | 181 | struct brcmf_if *ifp; |
180 | int err = 0; | 182 | int err = 0; |
181 | 183 | ||
182 | brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u\n", | 184 | brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u role: %u\n", |
183 | ifevent->action, ifevent->ifidx, | 185 | ifevent->action, ifevent->ifidx, ifevent->bssidx, |
184 | ifevent->bssidx, ifevent->flags); | 186 | ifevent->flags, ifevent->role); |
185 | 187 | ||
186 | if (ifevent->ifidx >= BRCMF_MAX_IFS) { | 188 | if (ifevent->ifidx >= BRCMF_MAX_IFS) { |
187 | brcmf_err("invalid interface index: %u\n", | 189 | brcmf_err("invalid interface index: %u\n", |
@@ -198,15 +200,20 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr, | |||
198 | emsg->ifname, emsg->addr); | 200 | emsg->ifname, emsg->addr); |
199 | if (IS_ERR(ifp)) | 201 | if (IS_ERR(ifp)) |
200 | return; | 202 | return; |
201 | 203 | brcmf_fws_add_interface(ifp); | |
202 | if (!drvr->fweh.evt_handler[BRCMF_E_IF]) | 204 | if (!drvr->fweh.evt_handler[BRCMF_E_IF]) |
203 | err = brcmf_net_attach(ifp, false); | 205 | err = brcmf_net_attach(ifp, false); |
204 | } | 206 | } |
205 | 207 | ||
208 | if (ifevent->action == BRCMF_E_IF_CHANGE) | ||
209 | brcmf_fws_reset_interface(ifp); | ||
210 | |||
206 | err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data); | 211 | err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data); |
207 | 212 | ||
208 | if (ifevent->action == BRCMF_E_IF_DEL) | 213 | if (ifevent->action == BRCMF_E_IF_DEL) { |
214 | brcmf_fws_del_interface(ifp); | ||
209 | brcmf_del_if(drvr, ifevent->bssidx); | 215 | brcmf_del_if(drvr, ifevent->bssidx); |
216 | } | ||
210 | } | 217 | } |
211 | 218 | ||
212 | /** | 219 | /** |
@@ -400,13 +407,12 @@ int brcmf_fweh_activate_events(struct brcmf_if *ifp) | |||
400 | * | 407 | * |
401 | * @drvr: driver information object. | 408 | * @drvr: driver information object. |
402 | * @event_packet: event packet to process. | 409 | * @event_packet: event packet to process. |
403 | * @ifidx: index of the firmware interface (may change). | ||
404 | * | 410 | * |
405 | * If the packet buffer contains a firmware event message it will | 411 | * If the packet buffer contains a firmware event message it will |
406 | * dispatch the event to a registered handler (using worker). | 412 | * dispatch the event to a registered handler (using worker). |
407 | */ | 413 | */ |
408 | void brcmf_fweh_process_event(struct brcmf_pub *drvr, | 414 | void brcmf_fweh_process_event(struct brcmf_pub *drvr, |
409 | struct brcmf_event *event_packet, u8 *ifidx) | 415 | struct brcmf_event *event_packet) |
410 | { | 416 | { |
411 | enum brcmf_fweh_event_code code; | 417 | enum brcmf_fweh_event_code code; |
412 | struct brcmf_fweh_info *fweh = &drvr->fweh; | 418 | struct brcmf_fweh_info *fweh = &drvr->fweh; |
@@ -418,7 +424,6 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr, | |||
418 | /* get event info */ | 424 | /* get event info */ |
419 | code = get_unaligned_be32(&event_packet->msg.event_type); | 425 | code = get_unaligned_be32(&event_packet->msg.event_type); |
420 | datalen = get_unaligned_be32(&event_packet->msg.datalen); | 426 | datalen = get_unaligned_be32(&event_packet->msg.datalen); |
421 | *ifidx = event_packet->msg.ifidx; | ||
422 | data = &event_packet[1]; | 427 | data = &event_packet[1]; |
423 | 428 | ||
424 | if (code >= BRCMF_E_LAST) | 429 | if (code >= BRCMF_E_LAST) |
@@ -435,7 +440,7 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr, | |||
435 | return; | 440 | return; |
436 | 441 | ||
437 | event->code = code; | 442 | event->code = code; |
438 | event->ifidx = *ifidx; | 443 | event->ifidx = event_packet->msg.ifidx; |
439 | 444 | ||
440 | /* use memcpy to get aligned event message */ | 445 | /* use memcpy to get aligned event message */ |
441 | memcpy(&event->emsg, &event_packet->msg, sizeof(event->emsg)); | 446 | memcpy(&event->emsg, &event_packet->msg, sizeof(event->emsg)); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h index 8c39b51dcccf..6ec5db9c60a5 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h | |||
@@ -187,10 +187,10 @@ void brcmf_fweh_unregister(struct brcmf_pub *drvr, | |||
187 | enum brcmf_fweh_event_code code); | 187 | enum brcmf_fweh_event_code code); |
188 | int brcmf_fweh_activate_events(struct brcmf_if *ifp); | 188 | int brcmf_fweh_activate_events(struct brcmf_if *ifp); |
189 | void brcmf_fweh_process_event(struct brcmf_pub *drvr, | 189 | void brcmf_fweh_process_event(struct brcmf_pub *drvr, |
190 | struct brcmf_event *event_packet, u8 *ifidx); | 190 | struct brcmf_event *event_packet); |
191 | 191 | ||
192 | static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr, | 192 | static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr, |
193 | struct sk_buff *skb, u8 *ifidx) | 193 | struct sk_buff *skb) |
194 | { | 194 | { |
195 | struct brcmf_event *event_packet; | 195 | struct brcmf_event *event_packet; |
196 | u8 *data; | 196 | u8 *data; |
@@ -213,7 +213,7 @@ static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr, | |||
213 | if (usr_stype != BCMILCP_BCM_SUBTYPE_EVENT) | 213 | if (usr_stype != BCMILCP_BCM_SUBTYPE_EVENT) |
214 | return; | 214 | return; |
215 | 215 | ||
216 | brcmf_fweh_process_event(drvr, event_packet, ifidx); | 216 | brcmf_fweh_process_event(drvr, event_packet); |
217 | } | 217 | } |
218 | 218 | ||
219 | #endif /* FWEH_H_ */ | 219 | #endif /* FWEH_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c index 8d1def935b8d..04f395930d86 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include "dhd.h" | 25 | #include "dhd.h" |
26 | #include "dhd_bus.h" | 26 | #include "dhd_bus.h" |
27 | #include "dhd_dbg.h" | 27 | #include "dhd_dbg.h" |
28 | #include "tracepoint.h" | ||
28 | #include "fwil.h" | 29 | #include "fwil.h" |
29 | 30 | ||
30 | 31 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 071d55f9cd4d..b3c608ee37cf 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | |||
@@ -14,17 +14,22 @@ | |||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
17 | #include <linux/module.h> | ||
17 | #include <linux/if_ether.h> | 18 | #include <linux/if_ether.h> |
18 | #include <linux/spinlock.h> | 19 | #include <linux/spinlock.h> |
19 | #include <linux/skbuff.h> | 20 | #include <linux/skbuff.h> |
20 | #include <linux/netdevice.h> | 21 | #include <linux/netdevice.h> |
22 | #include <linux/etherdevice.h> | ||
21 | #include <linux/err.h> | 23 | #include <linux/err.h> |
22 | #include <uapi/linux/nl80211.h> | 24 | #include <uapi/linux/nl80211.h> |
25 | #include <net/cfg80211.h> | ||
23 | 26 | ||
24 | #include <brcmu_utils.h> | 27 | #include <brcmu_utils.h> |
25 | #include <brcmu_wifi.h> | 28 | #include <brcmu_wifi.h> |
26 | #include "dhd.h" | 29 | #include "dhd.h" |
30 | #include "dhd_proto.h" | ||
27 | #include "dhd_dbg.h" | 31 | #include "dhd_dbg.h" |
32 | #include "dhd_bus.h" | ||
28 | #include "fwil.h" | 33 | #include "fwil.h" |
29 | #include "fweh.h" | 34 | #include "fweh.h" |
30 | #include "fwsignal.h" | 35 | #include "fwsignal.h" |
@@ -54,7 +59,7 @@ | |||
54 | BRCMF_FWS_TLV_DEF(RSSI, 8, 1) \ | 59 | BRCMF_FWS_TLV_DEF(RSSI, 8, 1) \ |
55 | BRCMF_FWS_TLV_DEF(INTERFACE_OPEN, 9, 1) \ | 60 | BRCMF_FWS_TLV_DEF(INTERFACE_OPEN, 9, 1) \ |
56 | BRCMF_FWS_TLV_DEF(INTERFACE_CLOSE, 10, 1) \ | 61 | BRCMF_FWS_TLV_DEF(INTERFACE_CLOSE, 10, 1) \ |
57 | BRCMF_FWS_TLV_DEF(FIFO_CREDITBACK, 11, 8) \ | 62 | BRCMF_FWS_TLV_DEF(FIFO_CREDITBACK, 11, 6) \ |
58 | BRCMF_FWS_TLV_DEF(PENDING_TRAFFIC_BMP, 12, 2) \ | 63 | BRCMF_FWS_TLV_DEF(PENDING_TRAFFIC_BMP, 12, 2) \ |
59 | BRCMF_FWS_TLV_DEF(MAC_REQUEST_PACKET, 13, 3) \ | 64 | BRCMF_FWS_TLV_DEF(MAC_REQUEST_PACKET, 13, 3) \ |
60 | BRCMF_FWS_TLV_DEF(HOST_REORDER_RXPKTS, 14, 10) \ | 65 | BRCMF_FWS_TLV_DEF(HOST_REORDER_RXPKTS, 14, 10) \ |
@@ -62,7 +67,7 @@ | |||
62 | BRCMF_FWS_TLV_DEF(COMP_TXSTATUS, 19, 1) \ | 67 | BRCMF_FWS_TLV_DEF(COMP_TXSTATUS, 19, 1) \ |
63 | BRCMF_FWS_TLV_DEF(FILLER, 255, 0) | 68 | BRCMF_FWS_TLV_DEF(FILLER, 255, 0) |
64 | 69 | ||
65 | /** | 70 | /* |
66 | * enum brcmf_fws_tlv_type - definition of tlv identifiers. | 71 | * enum brcmf_fws_tlv_type - definition of tlv identifiers. |
67 | */ | 72 | */ |
68 | #define BRCMF_FWS_TLV_DEF(name, id, len) \ | 73 | #define BRCMF_FWS_TLV_DEF(name, id, len) \ |
@@ -73,18 +78,18 @@ enum brcmf_fws_tlv_type { | |||
73 | }; | 78 | }; |
74 | #undef BRCMF_FWS_TLV_DEF | 79 | #undef BRCMF_FWS_TLV_DEF |
75 | 80 | ||
76 | /** | 81 | /* |
77 | * enum brcmf_fws_tlv_len - length values for tlvs. | 82 | * enum brcmf_fws_tlv_len - definition of tlv lengths. |
78 | */ | 83 | */ |
79 | #define BRCMF_FWS_TLV_DEF(name, id, len) \ | 84 | #define BRCMF_FWS_TLV_DEF(name, id, len) \ |
80 | BRCMF_FWS_TYPE_ ## name ## _LEN = len, | 85 | BRCMF_FWS_TYPE_ ## name ## _LEN = (len), |
81 | enum brcmf_fws_tlv_len { | 86 | enum brcmf_fws_tlv_len { |
82 | BRCMF_FWS_TLV_DEFLIST | 87 | BRCMF_FWS_TLV_DEFLIST |
83 | }; | 88 | }; |
84 | #undef BRCMF_FWS_TLV_DEF | 89 | #undef BRCMF_FWS_TLV_DEF |
85 | 90 | ||
86 | #ifdef DEBUG | 91 | #ifdef DEBUG |
87 | /** | 92 | /* |
88 | * brcmf_fws_tlv_names - array of tlv names. | 93 | * brcmf_fws_tlv_names - array of tlv names. |
89 | */ | 94 | */ |
90 | #define BRCMF_FWS_TLV_DEF(name, id, len) \ | 95 | #define BRCMF_FWS_TLV_DEF(name, id, len) \ |
@@ -114,43 +119,109 @@ static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id) | |||
114 | } | 119 | } |
115 | #endif /* DEBUG */ | 120 | #endif /* DEBUG */ |
116 | 121 | ||
117 | /** | 122 | /* |
118 | * flags used to enable tlv signalling from firmware. | 123 | * flags used to enable tlv signalling from firmware. |
119 | */ | 124 | */ |
120 | #define BRCMF_FWS_FLAGS_RSSI_SIGNALS 0x0001 | 125 | #define BRCMF_FWS_FLAGS_RSSI_SIGNALS 0x0001 |
121 | #define BRCMF_FWS_FLAGS_XONXOFF_SIGNALS 0x0002 | 126 | #define BRCMF_FWS_FLAGS_XONXOFF_SIGNALS 0x0002 |
122 | #define BRCMF_FWS_FLAGS_CREDIT_STATUS_SIGNALS 0x0004 | 127 | #define BRCMF_FWS_FLAGS_CREDIT_STATUS_SIGNALS 0x0004 |
123 | #define BRCMF_FWS_FLAGS_HOST_PROPTXSTATUS_ACTIVE 0x0008 | 128 | #define BRCMF_FWS_FLAGS_HOST_PROPTXSTATUS_ACTIVE 0x0008 |
124 | #define BRCMF_FWS_FLAGS_PSQ_GENERATIONFSM_ENABLE 0x0010 | 129 | #define BRCMF_FWS_FLAGS_PSQ_GENERATIONFSM_ENABLE 0x0010 |
125 | #define BRCMF_FWS_FLAGS_PSQ_ZERO_BUFFER_ENABLE 0x0020 | 130 | #define BRCMF_FWS_FLAGS_PSQ_ZERO_BUFFER_ENABLE 0x0020 |
126 | #define BRCMF_FWS_FLAGS_HOST_RXREORDER_ACTIVE 0x0040 | 131 | #define BRCMF_FWS_FLAGS_HOST_RXREORDER_ACTIVE 0x0040 |
127 | |||
128 | #define BRCMF_FWS_HANGER_MAXITEMS 1024 | ||
129 | #define BRCMF_FWS_HANGER_ITEM_STATE_FREE 1 | ||
130 | #define BRCMF_FWS_HANGER_ITEM_STATE_INUSE 2 | ||
131 | #define BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED 3 | ||
132 | |||
133 | #define BRCMF_FWS_STATE_OPEN 1 | ||
134 | #define BRCMF_FWS_STATE_CLOSE 2 | ||
135 | |||
136 | #define BRCMF_FWS_FCMODE_NONE 0 | ||
137 | #define BRCMF_FWS_FCMODE_IMPLIED_CREDIT 1 | ||
138 | #define BRCMF_FWS_FCMODE_EXPLICIT_CREDIT 2 | ||
139 | 132 | ||
140 | #define BRCMF_FWS_MAC_DESC_TABLE_SIZE 32 | 133 | #define BRCMF_FWS_MAC_DESC_TABLE_SIZE 32 |
141 | #define BRCMF_FWS_MAX_IFNUM 16 | ||
142 | #define BRCMF_FWS_MAC_DESC_ID_INVALID 0xff | 134 | #define BRCMF_FWS_MAC_DESC_ID_INVALID 0xff |
143 | 135 | ||
144 | #define BRCMF_FWS_HOSTIF_FLOWSTATE_OFF 0 | 136 | #define BRCMF_FWS_HOSTIF_FLOWSTATE_OFF 0 |
145 | #define BRCMF_FWS_HOSTIF_FLOWSTATE_ON 1 | 137 | #define BRCMF_FWS_HOSTIF_FLOWSTATE_ON 1 |
138 | #define BRCMF_FWS_FLOWCONTROL_HIWATER 128 | ||
139 | #define BRCMF_FWS_FLOWCONTROL_LOWATER 64 | ||
140 | |||
141 | #define BRCMF_FWS_PSQ_PREC_COUNT ((NL80211_NUM_ACS + 1) * 2) | ||
142 | #define BRCMF_FWS_PSQ_LEN 256 | ||
143 | |||
144 | #define BRCMF_FWS_HTOD_FLAG_PKTFROMHOST 0x01 | ||
145 | #define BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED 0x02 | ||
146 | 146 | ||
147 | /** | 147 | /** |
148 | * FWFC packet identifier | 148 | * enum brcmf_fws_skb_state - indicates processing state of skb. |
149 | * | ||
150 | * @BRCMF_FWS_SKBSTATE_NEW: sk_buff is newly arrived in the driver. | ||
151 | * @BRCMF_FWS_SKBSTATE_DELAYED: sk_buff had to wait on queue. | ||
152 | * @BRCMF_FWS_SKBSTATE_SUPPRESSED: sk_buff has been suppressed by firmware. | ||
153 | */ | ||
154 | enum brcmf_fws_skb_state { | ||
155 | BRCMF_FWS_SKBSTATE_NEW, | ||
156 | BRCMF_FWS_SKBSTATE_DELAYED, | ||
157 | BRCMF_FWS_SKBSTATE_SUPPRESSED | ||
158 | }; | ||
159 | |||
160 | /** | ||
161 | * struct brcmf_skbuff_cb - control buffer associated with skbuff. | ||
162 | * | ||
163 | * @if_flags: holds interface index and packet related flags. | ||
164 | * @htod: host to device packet identifier (used in PKTTAG tlv). | ||
165 | * @state: transmit state of the packet. | ||
166 | * @mac: descriptor related to destination for this packet. | ||
167 | * | ||
168 | * This information is stored in control buffer struct sk_buff::cb, which | ||
169 | * provides 48 bytes of storage so this structure should not exceed that. | ||
170 | */ | ||
171 | struct brcmf_skbuff_cb { | ||
172 | u16 if_flags; | ||
173 | u32 htod; | ||
174 | enum brcmf_fws_skb_state state; | ||
175 | struct brcmf_fws_mac_descriptor *mac; | ||
176 | }; | ||
177 | |||
178 | /* | ||
179 | * macro casting skbuff control buffer to struct brcmf_skbuff_cb. | ||
180 | */ | ||
181 | #define brcmf_skbcb(skb) ((struct brcmf_skbuff_cb *)((skb)->cb)) | ||
182 | |||
183 | /* | ||
184 | * sk_buff control if flags | ||
185 | * | ||
186 | * b[11] - packet sent upon firmware request. | ||
187 | * b[10] - packet only contains signalling data. | ||
188 | * b[9] - packet is a tx packet. | ||
189 | * b[8] - packet uses FIFO credit (non-pspoll). | ||
190 | * b[7] - interface in AP mode. | ||
191 | * b[6:4] - AC FIFO number. | ||
192 | * b[3:0] - interface index. | ||
193 | */ | ||
194 | #define BRCMF_SKB_IF_FLAGS_REQUESTED_MASK 0x0800 | ||
195 | #define BRCMF_SKB_IF_FLAGS_REQUESTED_SHIFT 11 | ||
196 | #define BRCMF_SKB_IF_FLAGS_SIGNAL_ONLY_MASK 0x0400 | ||
197 | #define BRCMF_SKB_IF_FLAGS_SIGNAL_ONLY_SHIFT 10 | ||
198 | #define BRCMF_SKB_IF_FLAGS_TRANSMIT_MASK 0x0200 | ||
199 | #define BRCMF_SKB_IF_FLAGS_TRANSMIT_SHIFT 9 | ||
200 | #define BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK 0x0100 | ||
201 | #define BRCMF_SKB_IF_FLAGS_CREDITCHECK_SHIFT 8 | ||
202 | #define BRCMF_SKB_IF_FLAGS_IF_AP_MASK 0x0080 | ||
203 | #define BRCMF_SKB_IF_FLAGS_IF_AP_SHIFT 7 | ||
204 | #define BRCMF_SKB_IF_FLAGS_FIFO_MASK 0x0070 | ||
205 | #define BRCMF_SKB_IF_FLAGS_FIFO_SHIFT 4 | ||
206 | #define BRCMF_SKB_IF_FLAGS_INDEX_MASK 0x000f | ||
207 | #define BRCMF_SKB_IF_FLAGS_INDEX_SHIFT 0 | ||
208 | |||
209 | #define brcmf_skb_if_flags_set_field(skb, field, value) \ | ||
210 | brcmu_maskset16(&(brcmf_skbcb(skb)->if_flags), \ | ||
211 | BRCMF_SKB_IF_FLAGS_ ## field ## _MASK, \ | ||
212 | BRCMF_SKB_IF_FLAGS_ ## field ## _SHIFT, (value)) | ||
213 | #define brcmf_skb_if_flags_get_field(skb, field) \ | ||
214 | brcmu_maskget16(brcmf_skbcb(skb)->if_flags, \ | ||
215 | BRCMF_SKB_IF_FLAGS_ ## field ## _MASK, \ | ||
216 | BRCMF_SKB_IF_FLAGS_ ## field ## _SHIFT) | ||
217 | |||
218 | /* | ||
219 | * sk_buff control packet identifier | ||
149 | * | 220 | * |
150 | * 32-bit packet identifier used in PKTTAG tlv from host to dongle. | 221 | * 32-bit packet identifier used in PKTTAG tlv from host to dongle. |
151 | * | 222 | * |
152 | * - Generated at the host (e.g. dhd) | 223 | * - Generated at the host (e.g. dhd) |
153 | * - Seen as a generic sequence number by wlc except the flags field | 224 | * - Seen as a generic sequence number by firmware except for the flags field. |
154 | * | 225 | * |
155 | * Generation : b[31] => generation number for this packet [host->fw] | 226 | * Generation : b[31] => generation number for this packet [host->fw] |
156 | * OR, current generation number [fw->host] | 227 | * OR, current generation number [fw->host] |
@@ -159,35 +230,1057 @@ static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id) | |||
159 | * h-slot : b[23:8] => hanger-slot | 230 | * h-slot : b[23:8] => hanger-slot |
160 | * freerun : b[7:0] => A free running counter | 231 | * freerun : b[7:0] => A free running counter |
161 | */ | 232 | */ |
162 | #define BRCMF_FWS_PKTTAG_GENERATION_MASK 0x80000000 | 233 | #define BRCMF_SKB_HTOD_TAG_GENERATION_MASK 0x80000000 |
163 | #define BRCMF_FWS_PKTTAG_GENERATION_SHIFT 31 | 234 | #define BRCMF_SKB_HTOD_TAG_GENERATION_SHIFT 31 |
164 | #define BRCMF_FWS_PKTTAG_FLAGS_MASK 0x78000000 | 235 | #define BRCMF_SKB_HTOD_TAG_FLAGS_MASK 0x78000000 |
165 | #define BRCMF_FWS_PKTTAG_FLAGS_SHIFT 27 | 236 | #define BRCMF_SKB_HTOD_TAG_FLAGS_SHIFT 27 |
166 | #define BRCMF_FWS_PKTTAG_FIFO_MASK 0x07000000 | 237 | #define BRCMF_SKB_HTOD_TAG_FIFO_MASK 0x07000000 |
167 | #define BRCMF_FWS_PKTTAG_FIFO_SHIFT 24 | 238 | #define BRCMF_SKB_HTOD_TAG_FIFO_SHIFT 24 |
168 | #define BRCMF_FWS_PKTTAG_HSLOT_MASK 0x00ffff00 | 239 | #define BRCMF_SKB_HTOD_TAG_HSLOT_MASK 0x00ffff00 |
169 | #define BRCMF_FWS_PKTTAG_HSLOT_SHIFT 8 | 240 | #define BRCMF_SKB_HTOD_TAG_HSLOT_SHIFT 8 |
170 | #define BRCMF_FWS_PKTTAG_FREERUN_MASK 0x000000ff | 241 | #define BRCMF_SKB_HTOD_TAG_FREERUN_MASK 0x000000ff |
171 | #define BRCMF_FWS_PKTTAG_FREERUN_SHIFT 0 | 242 | #define BRCMF_SKB_HTOD_TAG_FREERUN_SHIFT 0 |
172 | 243 | ||
173 | #define brcmf_fws_pkttag_set_field(var, field, value) \ | 244 | #define brcmf_skb_htod_tag_set_field(skb, field, value) \ |
174 | brcmu_maskset32((var), BRCMF_FWS_PKTTAG_ ## field ## _MASK, \ | 245 | brcmu_maskset32(&(brcmf_skbcb(skb)->htod), \ |
175 | BRCMF_FWS_PKTTAG_ ## field ## _SHIFT, (value)) | 246 | BRCMF_SKB_HTOD_TAG_ ## field ## _MASK, \ |
176 | #define brcmf_fws_pkttag_get_field(var, field) \ | 247 | BRCMF_SKB_HTOD_TAG_ ## field ## _SHIFT, (value)) |
177 | brcmu_maskget32((var), BRCMF_FWS_PKTTAG_ ## field ## _MASK, \ | 248 | #define brcmf_skb_htod_tag_get_field(skb, field) \ |
178 | BRCMF_FWS_PKTTAG_ ## field ## _SHIFT) | 249 | brcmu_maskget32(brcmf_skbcb(skb)->htod, \ |
250 | BRCMF_SKB_HTOD_TAG_ ## field ## _MASK, \ | ||
251 | BRCMF_SKB_HTOD_TAG_ ## field ## _SHIFT) | ||
252 | |||
253 | #define BRCMF_FWS_TXSTAT_GENERATION_MASK 0x80000000 | ||
254 | #define BRCMF_FWS_TXSTAT_GENERATION_SHIFT 31 | ||
255 | #define BRCMF_FWS_TXSTAT_FLAGS_MASK 0x78000000 | ||
256 | #define BRCMF_FWS_TXSTAT_FLAGS_SHIFT 27 | ||
257 | #define BRCMF_FWS_TXSTAT_FIFO_MASK 0x07000000 | ||
258 | #define BRCMF_FWS_TXSTAT_FIFO_SHIFT 24 | ||
259 | #define BRCMF_FWS_TXSTAT_HSLOT_MASK 0x00FFFF00 | ||
260 | #define BRCMF_FWS_TXSTAT_HSLOT_SHIFT 8 | ||
261 | #define BRCMF_FWS_TXSTAT_PKTID_MASK 0x00FFFFFF | ||
262 | #define BRCMF_FWS_TXSTAT_PKTID_SHIFT 0 | ||
263 | |||
264 | #define brcmf_txstatus_get_field(txs, field) \ | ||
265 | brcmu_maskget32(txs, BRCMF_FWS_TXSTAT_ ## field ## _MASK, \ | ||
266 | BRCMF_FWS_TXSTAT_ ## field ## _SHIFT) | ||
267 | |||
268 | /** | ||
269 | * enum brcmf_fws_fifo - fifo indices used by dongle firmware. | ||
270 | * | ||
271 | * @BRCMF_FWS_FIFO_AC_BK: fifo for background traffic. | ||
272 | * @BRCMF_FWS_FIFO_AC_BE: fifo for best-effort traffic. | ||
273 | * @BRCMF_FWS_FIFO_AC_VI: fifo for video traffic. | ||
274 | * @BRCMF_FWS_FIFO_AC_VO: fifo for voice traffic. | ||
275 | * @BRCMF_FWS_FIFO_BCMC: fifo for broadcast/multicast (AP only). | ||
276 | * @BRCMF_FWS_FIFO_ATIM: fifo for ATIM (AP only). | ||
277 | * @BRCMF_FWS_FIFO_COUNT: number of fifos. | ||
278 | */ | ||
279 | enum brcmf_fws_fifo { | ||
280 | BRCMF_FWS_FIFO_AC_BK, | ||
281 | BRCMF_FWS_FIFO_AC_BE, | ||
282 | BRCMF_FWS_FIFO_AC_VI, | ||
283 | BRCMF_FWS_FIFO_AC_VO, | ||
284 | BRCMF_FWS_FIFO_BCMC, | ||
285 | BRCMF_FWS_FIFO_ATIM, | ||
286 | BRCMF_FWS_FIFO_COUNT | ||
287 | }; | ||
288 | |||
289 | /** | ||
290 | * enum brcmf_fws_txstatus - txstatus flag values. | ||
291 | * | ||
292 | * @BRCMF_FWS_TXSTATUS_DISCARD: | ||
293 | * host is free to discard the packet. | ||
294 | * @BRCMF_FWS_TXSTATUS_CORE_SUPPRESS: | ||
295 | * 802.11 core suppressed the packet. | ||
296 | * @BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS: | ||
297 | * firmware suppress the packet as device is already in PS mode. | ||
298 | * @BRCMF_FWS_TXSTATUS_FW_TOSSED: | ||
299 | * firmware tossed the packet. | ||
300 | */ | ||
301 | enum brcmf_fws_txstatus { | ||
302 | BRCMF_FWS_TXSTATUS_DISCARD, | ||
303 | BRCMF_FWS_TXSTATUS_CORE_SUPPRESS, | ||
304 | BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS, | ||
305 | BRCMF_FWS_TXSTATUS_FW_TOSSED | ||
306 | }; | ||
307 | |||
308 | enum brcmf_fws_fcmode { | ||
309 | BRCMF_FWS_FCMODE_NONE, | ||
310 | BRCMF_FWS_FCMODE_IMPLIED_CREDIT, | ||
311 | BRCMF_FWS_FCMODE_EXPLICIT_CREDIT | ||
312 | }; | ||
313 | |||
314 | enum brcmf_fws_mac_desc_state { | ||
315 | BRCMF_FWS_STATE_OPEN = 1, | ||
316 | BRCMF_FWS_STATE_CLOSE | ||
317 | }; | ||
318 | |||
319 | /** | ||
320 | * struct brcmf_fws_mac_descriptor - firmware signalling data per node/interface | ||
321 | * | ||
322 | * @occupied: slot is in use. | ||
323 | * @mac_handle: handle for mac entry determined by firmware. | ||
324 | * @interface_id: interface index. | ||
325 | * @state: current state. | ||
326 | * @suppressed: mac entry is suppressed. | ||
327 | * @generation: generation bit. | ||
328 | * @ac_bitmap: ac queue bitmap. | ||
329 | * @requested_credit: credits requested by firmware. | ||
330 | * @ea: ethernet address. | ||
331 | * @seq: per-node free-running sequence. | ||
332 | * @psq: power-save queue. | ||
333 | * @transit_count: packet in transit to firmware. | ||
334 | */ | ||
335 | struct brcmf_fws_mac_descriptor { | ||
336 | u8 occupied; | ||
337 | u8 mac_handle; | ||
338 | u8 interface_id; | ||
339 | u8 state; | ||
340 | bool suppressed; | ||
341 | u8 generation; | ||
342 | u8 ac_bitmap; | ||
343 | u8 requested_credit; | ||
344 | u8 requested_packet; | ||
345 | u8 ea[ETH_ALEN]; | ||
346 | u8 seq[BRCMF_FWS_FIFO_COUNT]; | ||
347 | struct pktq psq; | ||
348 | int transit_count; | ||
349 | int suppress_count; | ||
350 | int suppr_transit_count; | ||
351 | bool send_tim_signal; | ||
352 | u8 traffic_pending_bmp; | ||
353 | u8 traffic_lastreported_bmp; | ||
354 | }; | ||
355 | |||
356 | #define BRCMF_FWS_HANGER_MAXITEMS 1024 | ||
357 | |||
358 | /** | ||
359 | * enum brcmf_fws_hanger_item_state - state of hanger item. | ||
360 | * | ||
361 | * @BRCMF_FWS_HANGER_ITEM_STATE_FREE: item is free for use. | ||
362 | * @BRCMF_FWS_HANGER_ITEM_STATE_INUSE: item is in use. | ||
363 | * @BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED: item was suppressed. | ||
364 | */ | ||
365 | enum brcmf_fws_hanger_item_state { | ||
366 | BRCMF_FWS_HANGER_ITEM_STATE_FREE = 1, | ||
367 | BRCMF_FWS_HANGER_ITEM_STATE_INUSE, | ||
368 | BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED | ||
369 | }; | ||
370 | |||
371 | |||
372 | /** | ||
373 | * struct brcmf_fws_hanger_item - single entry for tx pending packet. | ||
374 | * | ||
375 | * @state: entry is either free or occupied. | ||
376 | * @gen: generation. | ||
377 | * @pkt: packet itself. | ||
378 | */ | ||
379 | struct brcmf_fws_hanger_item { | ||
380 | enum brcmf_fws_hanger_item_state state; | ||
381 | u8 gen; | ||
382 | struct sk_buff *pkt; | ||
383 | }; | ||
384 | |||
385 | /** | ||
386 | * struct brcmf_fws_hanger - holds packets awaiting firmware txstatus. | ||
387 | * | ||
388 | * @pushed: packets pushed to await txstatus. | ||
389 | * @popped: packets popped upon handling txstatus. | ||
390 | * @failed_to_push: packets that could not be pushed. | ||
391 | * @failed_to_pop: packets that could not be popped. | ||
392 | * @failed_slotfind: packets for which failed to find an entry. | ||
393 | * @slot_pos: last returned item index for a free entry. | ||
394 | * @items: array of hanger items. | ||
395 | */ | ||
396 | struct brcmf_fws_hanger { | ||
397 | u32 pushed; | ||
398 | u32 popped; | ||
399 | u32 failed_to_push; | ||
400 | u32 failed_to_pop; | ||
401 | u32 failed_slotfind; | ||
402 | u32 slot_pos; | ||
403 | struct brcmf_fws_hanger_item items[BRCMF_FWS_HANGER_MAXITEMS]; | ||
404 | }; | ||
405 | |||
406 | struct brcmf_fws_macdesc_table { | ||
407 | struct brcmf_fws_mac_descriptor nodes[BRCMF_FWS_MAC_DESC_TABLE_SIZE]; | ||
408 | struct brcmf_fws_mac_descriptor iface[BRCMF_MAX_IFS]; | ||
409 | struct brcmf_fws_mac_descriptor other; | ||
410 | }; | ||
179 | 411 | ||
180 | struct brcmf_fws_info { | 412 | struct brcmf_fws_info { |
181 | struct brcmf_pub *drvr; | 413 | struct brcmf_pub *drvr; |
182 | struct brcmf_fws_stats stats; | 414 | struct brcmf_fws_stats stats; |
415 | struct brcmf_fws_hanger hanger; | ||
416 | enum brcmf_fws_fcmode fcmode; | ||
417 | struct brcmf_fws_macdesc_table desc; | ||
418 | struct workqueue_struct *fws_wq; | ||
419 | struct work_struct fws_dequeue_work; | ||
420 | u32 fifo_enqpkt[BRCMF_FWS_FIFO_COUNT]; | ||
421 | int fifo_credit[BRCMF_FWS_FIFO_COUNT]; | ||
422 | int deq_node_pos[BRCMF_FWS_FIFO_COUNT]; | ||
423 | u32 fifo_credit_map; | ||
424 | u32 fifo_delay_map; | ||
183 | }; | 425 | }; |
184 | 426 | ||
427 | /* | ||
428 | * brcmf_fws_prio2fifo - mapping from 802.1d priority to firmware fifo index. | ||
429 | */ | ||
430 | static const int brcmf_fws_prio2fifo[] = { | ||
431 | BRCMF_FWS_FIFO_AC_BE, | ||
432 | BRCMF_FWS_FIFO_AC_BK, | ||
433 | BRCMF_FWS_FIFO_AC_BK, | ||
434 | BRCMF_FWS_FIFO_AC_BE, | ||
435 | BRCMF_FWS_FIFO_AC_VI, | ||
436 | BRCMF_FWS_FIFO_AC_VI, | ||
437 | BRCMF_FWS_FIFO_AC_VO, | ||
438 | BRCMF_FWS_FIFO_AC_VO | ||
439 | }; | ||
440 | |||
441 | static int fcmode; | ||
442 | module_param(fcmode, int, S_IRUSR); | ||
443 | MODULE_PARM_DESC(fcmode, "mode of firmware signalled flow control"); | ||
444 | |||
445 | #define BRCMF_FWS_TLV_DEF(name, id, len) \ | ||
446 | case BRCMF_FWS_TYPE_ ## name: \ | ||
447 | return len; | ||
448 | |||
449 | /** | ||
450 | * brcmf_fws_get_tlv_len() - returns defined length for given tlv id. | ||
451 | * | ||
452 | * @fws: firmware-signalling information. | ||
453 | * @id: identifier of the TLV. | ||
454 | * | ||
455 | * Return: the specified length for the given TLV; Otherwise -EINVAL. | ||
456 | */ | ||
457 | static int brcmf_fws_get_tlv_len(struct brcmf_fws_info *fws, | ||
458 | enum brcmf_fws_tlv_type id) | ||
459 | { | ||
460 | switch (id) { | ||
461 | BRCMF_FWS_TLV_DEFLIST | ||
462 | default: | ||
463 | fws->stats.tlv_invalid_type++; | ||
464 | break; | ||
465 | } | ||
466 | return -EINVAL; | ||
467 | } | ||
468 | #undef BRCMF_FWS_TLV_DEF | ||
469 | |||
470 | static bool brcmf_fws_ifidx_match(struct sk_buff *skb, void *arg) | ||
471 | { | ||
472 | u32 ifidx = brcmf_skb_if_flags_get_field(skb, INDEX); | ||
473 | return ifidx == *(int *)arg; | ||
474 | } | ||
475 | |||
476 | static void brcmf_fws_psq_flush(struct brcmf_fws_info *fws, struct pktq *q, | ||
477 | int ifidx) | ||
478 | { | ||
479 | bool (*matchfn)(struct sk_buff *, void *) = NULL; | ||
480 | struct sk_buff *skb; | ||
481 | int prec; | ||
482 | |||
483 | if (ifidx != -1) | ||
484 | matchfn = brcmf_fws_ifidx_match; | ||
485 | for (prec = 0; prec < q->num_prec; prec++) { | ||
486 | skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx); | ||
487 | while (skb) { | ||
488 | brcmu_pkt_buf_free_skb(skb); | ||
489 | skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx); | ||
490 | } | ||
491 | } | ||
492 | } | ||
493 | |||
494 | static void brcmf_fws_hanger_init(struct brcmf_fws_hanger *hanger) | ||
495 | { | ||
496 | int i; | ||
497 | |||
498 | brcmf_dbg(TRACE, "enter\n"); | ||
499 | memset(hanger, 0, sizeof(*hanger)); | ||
500 | for (i = 0; i < ARRAY_SIZE(hanger->items); i++) | ||
501 | hanger->items[i].state = BRCMF_FWS_HANGER_ITEM_STATE_FREE; | ||
502 | } | ||
503 | |||
504 | static u32 brcmf_fws_hanger_get_free_slot(struct brcmf_fws_hanger *h) | ||
505 | { | ||
506 | u32 i; | ||
507 | |||
508 | brcmf_dbg(TRACE, "enter\n"); | ||
509 | i = (h->slot_pos + 1) % BRCMF_FWS_HANGER_MAXITEMS; | ||
510 | |||
511 | while (i != h->slot_pos) { | ||
512 | if (h->items[i].state == BRCMF_FWS_HANGER_ITEM_STATE_FREE) { | ||
513 | h->slot_pos = i; | ||
514 | goto done; | ||
515 | } | ||
516 | i++; | ||
517 | if (i == BRCMF_FWS_HANGER_MAXITEMS) | ||
518 | i = 0; | ||
519 | } | ||
520 | brcmf_err("all slots occupied\n"); | ||
521 | h->failed_slotfind++; | ||
522 | i = BRCMF_FWS_HANGER_MAXITEMS; | ||
523 | done: | ||
524 | brcmf_dbg(TRACE, "exit: %d\n", i); | ||
525 | return i; | ||
526 | } | ||
527 | |||
528 | static int brcmf_fws_hanger_pushpkt(struct brcmf_fws_hanger *h, | ||
529 | struct sk_buff *pkt, u32 slot_id) | ||
530 | { | ||
531 | brcmf_dbg(TRACE, "enter\n"); | ||
532 | if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS) | ||
533 | return -ENOENT; | ||
534 | |||
535 | if (h->items[slot_id].state != BRCMF_FWS_HANGER_ITEM_STATE_FREE) { | ||
536 | brcmf_err("slot is not free\n"); | ||
537 | h->failed_to_push++; | ||
538 | return -EINVAL; | ||
539 | } | ||
540 | |||
541 | h->items[slot_id].state = BRCMF_FWS_HANGER_ITEM_STATE_INUSE; | ||
542 | h->items[slot_id].pkt = pkt; | ||
543 | h->pushed++; | ||
544 | return 0; | ||
545 | } | ||
546 | |||
547 | static int brcmf_fws_hanger_poppkt(struct brcmf_fws_hanger *h, | ||
548 | u32 slot_id, struct sk_buff **pktout, | ||
549 | bool remove_item) | ||
550 | { | ||
551 | brcmf_dbg(TRACE, "enter\n"); | ||
552 | if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS) | ||
553 | return -ENOENT; | ||
554 | |||
555 | if (h->items[slot_id].state == BRCMF_FWS_HANGER_ITEM_STATE_FREE) { | ||
556 | brcmf_err("entry not in use\n"); | ||
557 | h->failed_to_pop++; | ||
558 | return -EINVAL; | ||
559 | } | ||
560 | |||
561 | *pktout = h->items[slot_id].pkt; | ||
562 | if (remove_item) { | ||
563 | h->items[slot_id].state = BRCMF_FWS_HANGER_ITEM_STATE_FREE; | ||
564 | h->items[slot_id].pkt = NULL; | ||
565 | h->items[slot_id].gen = 0xff; | ||
566 | h->popped++; | ||
567 | } | ||
568 | return 0; | ||
569 | } | ||
570 | |||
571 | static int brcmf_fws_hanger_mark_suppressed(struct brcmf_fws_hanger *h, | ||
572 | u32 slot_id, u8 gen) | ||
573 | { | ||
574 | brcmf_dbg(TRACE, "enter\n"); | ||
575 | |||
576 | if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS) | ||
577 | return -ENOENT; | ||
578 | |||
579 | h->items[slot_id].gen = gen; | ||
580 | |||
581 | if (h->items[slot_id].state != BRCMF_FWS_HANGER_ITEM_STATE_INUSE) { | ||
582 | brcmf_err("entry not in use\n"); | ||
583 | return -EINVAL; | ||
584 | } | ||
585 | |||
586 | h->items[slot_id].state = BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED; | ||
587 | return 0; | ||
588 | } | ||
589 | |||
590 | static int brcmf_fws_hanger_get_genbit(struct brcmf_fws_hanger *hanger, | ||
591 | struct sk_buff *pkt, u32 slot_id, | ||
592 | int *gen) | ||
593 | { | ||
594 | brcmf_dbg(TRACE, "enter\n"); | ||
595 | *gen = 0xff; | ||
596 | |||
597 | if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS) | ||
598 | return -ENOENT; | ||
599 | |||
600 | if (hanger->items[slot_id].state == BRCMF_FWS_HANGER_ITEM_STATE_FREE) { | ||
601 | brcmf_err("slot not in use\n"); | ||
602 | return -EINVAL; | ||
603 | } | ||
604 | |||
605 | *gen = hanger->items[slot_id].gen; | ||
606 | return 0; | ||
607 | } | ||
608 | |||
609 | static void brcmf_fws_hanger_cleanup(struct brcmf_fws_info *fws, | ||
610 | bool (*fn)(struct sk_buff *, void *), | ||
611 | int ifidx) | ||
612 | { | ||
613 | struct brcmf_fws_hanger *h = &fws->hanger; | ||
614 | struct sk_buff *skb; | ||
615 | int i; | ||
616 | enum brcmf_fws_hanger_item_state s; | ||
617 | |||
618 | brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx); | ||
619 | for (i = 0; i < ARRAY_SIZE(h->items); i++) { | ||
620 | s = h->items[i].state; | ||
621 | if (s == BRCMF_FWS_HANGER_ITEM_STATE_INUSE || | ||
622 | s == BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED) { | ||
623 | skb = h->items[i].pkt; | ||
624 | if (fn == NULL || fn(skb, &ifidx)) { | ||
625 | /* suppress packets freed from psq */ | ||
626 | if (s == BRCMF_FWS_HANGER_ITEM_STATE_INUSE) | ||
627 | brcmu_pkt_buf_free_skb(skb); | ||
628 | h->items[i].state = | ||
629 | BRCMF_FWS_HANGER_ITEM_STATE_FREE; | ||
630 | } | ||
631 | } | ||
632 | } | ||
633 | } | ||
634 | |||
635 | static void brcmf_fws_init_mac_descriptor(struct brcmf_fws_mac_descriptor *desc, | ||
636 | u8 *addr, u8 ifidx) | ||
637 | { | ||
638 | brcmf_dbg(TRACE, | ||
639 | "enter: desc %p ea=%pM, ifidx=%u\n", desc, addr, ifidx); | ||
640 | desc->occupied = 1; | ||
641 | desc->state = BRCMF_FWS_STATE_OPEN; | ||
642 | desc->requested_credit = 0; | ||
643 | /* depending on use may need ifp->bssidx instead */ | ||
644 | desc->interface_id = ifidx; | ||
645 | desc->ac_bitmap = 0xff; /* update this when handling APSD */ | ||
646 | if (addr) | ||
647 | memcpy(&desc->ea[0], addr, ETH_ALEN); | ||
648 | } | ||
649 | |||
650 | static | ||
651 | void brcmf_fws_clear_mac_descriptor(struct brcmf_fws_mac_descriptor *desc) | ||
652 | { | ||
653 | brcmf_dbg(TRACE, | ||
654 | "enter: ea=%pM, ifidx=%u\n", desc->ea, desc->interface_id); | ||
655 | desc->occupied = 0; | ||
656 | desc->state = BRCMF_FWS_STATE_CLOSE; | ||
657 | desc->requested_credit = 0; | ||
658 | } | ||
659 | |||
660 | static struct brcmf_fws_mac_descriptor * | ||
661 | brcmf_fws_mac_descriptor_lookup(struct brcmf_fws_info *fws, u8 *ea) | ||
662 | { | ||
663 | struct brcmf_fws_mac_descriptor *entry; | ||
664 | int i; | ||
665 | |||
666 | brcmf_dbg(TRACE, "enter: ea=%pM\n", ea); | ||
667 | if (ea == NULL) | ||
668 | return ERR_PTR(-EINVAL); | ||
669 | |||
670 | entry = &fws->desc.nodes[0]; | ||
671 | for (i = 0; i < ARRAY_SIZE(fws->desc.nodes); i++) { | ||
672 | if (entry->occupied && !memcmp(entry->ea, ea, ETH_ALEN)) | ||
673 | return entry; | ||
674 | entry++; | ||
675 | } | ||
676 | |||
677 | return ERR_PTR(-ENOENT); | ||
678 | } | ||
679 | |||
680 | static struct brcmf_fws_mac_descriptor* | ||
681 | brcmf_fws_find_mac_desc(struct brcmf_fws_info *fws, int ifidx, u8 *da) | ||
682 | { | ||
683 | struct brcmf_fws_mac_descriptor *entry = &fws->desc.other; | ||
684 | struct brcmf_if *ifp; | ||
685 | bool multicast; | ||
686 | |||
687 | brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx); | ||
688 | |||
689 | multicast = is_multicast_ether_addr(da); | ||
690 | ifp = fws->drvr->iflist[ifidx ? ifidx + 1 : 0]; | ||
691 | if (WARN_ON(!ifp)) | ||
692 | goto done; | ||
693 | |||
694 | /* Multicast destination and P2P clients get the interface entry. | ||
695 | * STA gets the interface entry if there is no exact match. For | ||
696 | * example, TDLS destinations have their own entry. | ||
697 | */ | ||
698 | entry = NULL; | ||
699 | if (multicast && ifp->fws_desc) | ||
700 | entry = ifp->fws_desc; | ||
701 | |||
702 | if (entry != NULL && multicast) | ||
703 | goto done; | ||
704 | |||
705 | entry = brcmf_fws_mac_descriptor_lookup(fws, da); | ||
706 | if (IS_ERR(entry)) | ||
707 | entry = &fws->desc.other; | ||
708 | |||
709 | done: | ||
710 | brcmf_dbg(TRACE, "exit: entry=%p\n", entry); | ||
711 | return entry; | ||
712 | } | ||
713 | |||
714 | static bool brcmf_fws_mac_desc_ready(struct brcmf_fws_mac_descriptor *entry, | ||
715 | int fifo) | ||
716 | { | ||
717 | bool ready; | ||
718 | |||
719 | /* | ||
720 | * destination entry is ready when firmware says it is OPEN | ||
721 | * and there are no packets enqueued for it. | ||
722 | */ | ||
723 | ready = entry->state == BRCMF_FWS_STATE_OPEN && | ||
724 | !entry->suppressed && | ||
725 | brcmu_pktq_mlen(&entry->psq, 3 << (fifo * 2)) == 0; | ||
726 | |||
727 | /* | ||
728 | * Or when the destination entry is CLOSED, but firmware has | ||
729 | * specifically requested packets for this entry. | ||
730 | */ | ||
731 | ready = ready || (entry->state == BRCMF_FWS_STATE_CLOSE && | ||
732 | (entry->requested_credit + entry->requested_packet)); | ||
733 | return ready; | ||
734 | } | ||
735 | |||
736 | static void brcmf_fws_mac_desc_cleanup(struct brcmf_fws_info *fws, | ||
737 | struct brcmf_fws_mac_descriptor *entry, | ||
738 | int ifidx) | ||
739 | { | ||
740 | brcmf_dbg(TRACE, "enter: entry=(ea=%pM, ifid=%d), ifidx=%d\n", | ||
741 | entry->ea, entry->interface_id, ifidx); | ||
742 | if (entry->occupied && (ifidx == -1 || ifidx == entry->interface_id)) { | ||
743 | brcmf_dbg(TRACE, "flush psq: ifidx=%d, qlen=%d\n", | ||
744 | ifidx, entry->psq.len); | ||
745 | brcmf_fws_psq_flush(fws, &entry->psq, ifidx); | ||
746 | entry->occupied = !!(entry->psq.len); | ||
747 | } | ||
748 | } | ||
749 | |||
750 | static void brcmf_fws_bus_txq_cleanup(struct brcmf_fws_info *fws, | ||
751 | bool (*fn)(struct sk_buff *, void *), | ||
752 | int ifidx) | ||
753 | { | ||
754 | struct brcmf_fws_hanger_item *hi; | ||
755 | struct pktq *txq; | ||
756 | struct sk_buff *skb; | ||
757 | int prec; | ||
758 | u32 hslot; | ||
759 | |||
760 | brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx); | ||
761 | txq = brcmf_bus_gettxq(fws->drvr->bus_if); | ||
762 | if (IS_ERR(txq)) { | ||
763 | brcmf_dbg(TRACE, "no txq to clean up\n"); | ||
764 | return; | ||
765 | } | ||
766 | |||
767 | for (prec = 0; prec < txq->num_prec; prec++) { | ||
768 | skb = brcmu_pktq_pdeq_match(txq, prec, fn, &ifidx); | ||
769 | while (skb) { | ||
770 | hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); | ||
771 | hi = &fws->hanger.items[hslot]; | ||
772 | WARN_ON(skb != hi->pkt); | ||
773 | hi->state = BRCMF_FWS_HANGER_ITEM_STATE_FREE; | ||
774 | brcmu_pkt_buf_free_skb(skb); | ||
775 | skb = brcmu_pktq_pdeq_match(txq, prec, fn, &ifidx); | ||
776 | } | ||
777 | } | ||
778 | } | ||
779 | |||
780 | static void brcmf_fws_cleanup(struct brcmf_fws_info *fws, int ifidx) | ||
781 | { | ||
782 | int i; | ||
783 | struct brcmf_fws_mac_descriptor *table; | ||
784 | bool (*matchfn)(struct sk_buff *, void *) = NULL; | ||
785 | |||
786 | brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx); | ||
787 | if (fws == NULL) | ||
788 | return; | ||
789 | |||
790 | if (ifidx != -1) | ||
791 | matchfn = brcmf_fws_ifidx_match; | ||
792 | |||
793 | /* cleanup individual nodes */ | ||
794 | table = &fws->desc.nodes[0]; | ||
795 | for (i = 0; i < ARRAY_SIZE(fws->desc.nodes); i++) | ||
796 | brcmf_fws_mac_desc_cleanup(fws, &table[i], ifidx); | ||
797 | |||
798 | brcmf_fws_mac_desc_cleanup(fws, &fws->desc.other, ifidx); | ||
799 | brcmf_fws_bus_txq_cleanup(fws, matchfn, ifidx); | ||
800 | brcmf_fws_hanger_cleanup(fws, matchfn, ifidx); | ||
801 | } | ||
802 | |||
803 | static void brcmf_fws_tim_update(struct brcmf_fws_info *ctx, | ||
804 | struct brcmf_fws_mac_descriptor *entry, | ||
805 | int prec) | ||
806 | { | ||
807 | brcmf_dbg(TRACE, "enter: ea=%pM\n", entry->ea); | ||
808 | if (entry->state == BRCMF_FWS_STATE_CLOSE) { | ||
809 | /* check delayedQ and suppressQ in one call using bitmap */ | ||
810 | if (brcmu_pktq_mlen(&entry->psq, 3 << (prec * 2)) == 0) | ||
811 | entry->traffic_pending_bmp = | ||
812 | entry->traffic_pending_bmp & ~NBITVAL(prec); | ||
813 | else | ||
814 | entry->traffic_pending_bmp = | ||
815 | entry->traffic_pending_bmp | NBITVAL(prec); | ||
816 | } | ||
817 | /* request a TIM update to firmware at the next piggyback opportunity */ | ||
818 | if (entry->traffic_lastreported_bmp != entry->traffic_pending_bmp) | ||
819 | entry->send_tim_signal = true; | ||
820 | } | ||
821 | |||
822 | static void | ||
823 | brcmf_fws_flow_control_check(struct brcmf_fws_info *fws, struct pktq *pq, | ||
824 | u8 if_id) | ||
825 | { | ||
826 | struct brcmf_if *ifp = fws->drvr->iflist[if_id]; | ||
827 | |||
828 | brcmf_dbg(TRACE, | ||
829 | "enter: bssidx=%d, ifidx=%d\n", ifp->bssidx, ifp->ifidx); | ||
830 | if (WARN_ON(!ifp)) | ||
831 | return; | ||
832 | |||
833 | if ((ifp->netif_stop & BRCMF_NETIF_STOP_REASON_FWS_FC) && | ||
834 | pq->len <= BRCMF_FWS_FLOWCONTROL_LOWATER) | ||
835 | brcmf_txflowblock_if(ifp, | ||
836 | BRCMF_NETIF_STOP_REASON_FWS_FC, false); | ||
837 | if (!(ifp->netif_stop & BRCMF_NETIF_STOP_REASON_FWS_FC) && | ||
838 | pq->len >= BRCMF_FWS_FLOWCONTROL_HIWATER) | ||
839 | brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FWS_FC, true); | ||
840 | return; | ||
841 | } | ||
842 | |||
185 | static int brcmf_fws_rssi_indicate(struct brcmf_fws_info *fws, s8 rssi) | 843 | static int brcmf_fws_rssi_indicate(struct brcmf_fws_info *fws, s8 rssi) |
186 | { | 844 | { |
187 | brcmf_dbg(CTL, "rssi %d\n", rssi); | 845 | brcmf_dbg(CTL, "rssi %d\n", rssi); |
188 | return 0; | 846 | return 0; |
189 | } | 847 | } |
190 | 848 | ||
849 | static | ||
850 | int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data) | ||
851 | { | ||
852 | struct brcmf_fws_mac_descriptor *entry, *existing; | ||
853 | u8 mac_handle; | ||
854 | u8 ifidx; | ||
855 | u8 *addr; | ||
856 | |||
857 | mac_handle = *data++; | ||
858 | ifidx = *data++; | ||
859 | addr = data; | ||
860 | |||
861 | entry = &fws->desc.nodes[mac_handle & 0x1F]; | ||
862 | if (type == BRCMF_FWS_TYPE_MACDESC_DEL) { | ||
863 | brcmf_dbg(TRACE, "deleting mac %pM idx %d\n", addr, ifidx); | ||
864 | if (entry->occupied) | ||
865 | brcmf_fws_clear_mac_descriptor(entry); | ||
866 | else | ||
867 | fws->stats.mac_update_failed++; | ||
868 | return 0; | ||
869 | } | ||
870 | |||
871 | brcmf_dbg(TRACE, | ||
872 | "add mac %pM handle %u idx %d\n", addr, mac_handle, ifidx); | ||
873 | existing = brcmf_fws_mac_descriptor_lookup(fws, addr); | ||
874 | if (IS_ERR(existing)) { | ||
875 | if (!entry->occupied) { | ||
876 | entry->mac_handle = mac_handle; | ||
877 | brcmf_fws_init_mac_descriptor(entry, addr, ifidx); | ||
878 | brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT, | ||
879 | BRCMF_FWS_PSQ_LEN); | ||
880 | } else { | ||
881 | fws->stats.mac_update_failed++; | ||
882 | } | ||
883 | } else { | ||
884 | if (entry != existing) { | ||
885 | brcmf_dbg(TRACE, "relocate mac\n"); | ||
886 | memcpy(entry, existing, | ||
887 | offsetof(struct brcmf_fws_mac_descriptor, psq)); | ||
888 | entry->mac_handle = mac_handle; | ||
889 | brcmf_fws_clear_mac_descriptor(existing); | ||
890 | } else { | ||
891 | brcmf_dbg(TRACE, "use existing\n"); | ||
892 | WARN_ON(entry->mac_handle != mac_handle); | ||
893 | /* TODO: what should we do here: continue, reinit, .. */ | ||
894 | } | ||
895 | } | ||
896 | return 0; | ||
897 | } | ||
898 | |||
899 | static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws, | ||
900 | u8 type, u8 *data) | ||
901 | { | ||
902 | struct brcmf_fws_mac_descriptor *entry; | ||
903 | u8 mac_handle; | ||
904 | int i; | ||
905 | |||
906 | mac_handle = data[0]; | ||
907 | entry = &fws->desc.nodes[mac_handle & 0x1F]; | ||
908 | if (!entry->occupied) { | ||
909 | fws->stats.mac_ps_update_failed++; | ||
910 | return -ESRCH; | ||
911 | } | ||
912 | |||
913 | /* a state update should wipe old credits? */ | ||
914 | entry->requested_credit = 0; | ||
915 | if (type == BRCMF_FWS_TYPE_MAC_OPEN) { | ||
916 | entry->state = BRCMF_FWS_STATE_OPEN; | ||
917 | } else { | ||
918 | entry->state = BRCMF_FWS_STATE_CLOSE; | ||
919 | for (i = BRCMF_FWS_FIFO_AC_BE; i < NL80211_NUM_ACS; i++) | ||
920 | brcmf_fws_tim_update(fws, entry, i); | ||
921 | } | ||
922 | return 0; | ||
923 | } | ||
924 | |||
925 | static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws, | ||
926 | u8 type, u8 *data) | ||
927 | { | ||
928 | struct brcmf_fws_mac_descriptor *entry; | ||
929 | u8 ifidx; | ||
930 | int ret; | ||
931 | |||
932 | ifidx = data[0]; | ||
933 | |||
934 | brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx); | ||
935 | if (ifidx >= BRCMF_MAX_IFS) { | ||
936 | ret = -ERANGE; | ||
937 | goto fail; | ||
938 | } | ||
939 | |||
940 | entry = &fws->desc.iface[ifidx]; | ||
941 | if (!entry->occupied) { | ||
942 | ret = -ESRCH; | ||
943 | goto fail; | ||
944 | } | ||
945 | |||
946 | switch (type) { | ||
947 | case BRCMF_FWS_TYPE_INTERFACE_OPEN: | ||
948 | entry->state = BRCMF_FWS_STATE_OPEN; | ||
949 | return 0; | ||
950 | case BRCMF_FWS_TYPE_INTERFACE_CLOSE: | ||
951 | entry->state = BRCMF_FWS_STATE_CLOSE; | ||
952 | return 0; | ||
953 | default: | ||
954 | ret = -EINVAL; | ||
955 | break; | ||
956 | } | ||
957 | fail: | ||
958 | fws->stats.if_update_failed++; | ||
959 | return ret; | ||
960 | } | ||
961 | |||
962 | static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type, | ||
963 | u8 *data) | ||
964 | { | ||
965 | struct brcmf_fws_mac_descriptor *entry; | ||
966 | |||
967 | entry = &fws->desc.nodes[data[1] & 0x1F]; | ||
968 | if (!entry->occupied) { | ||
969 | if (type == BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT) | ||
970 | fws->stats.credit_request_failed++; | ||
971 | else | ||
972 | fws->stats.packet_request_failed++; | ||
973 | return -ESRCH; | ||
974 | } | ||
975 | |||
976 | if (type == BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT) | ||
977 | entry->requested_credit = data[0]; | ||
978 | else | ||
979 | entry->requested_packet = data[0]; | ||
980 | |||
981 | entry->ac_bitmap = data[2]; | ||
982 | return 0; | ||
983 | } | ||
984 | |||
985 | static void brcmf_fws_return_credits(struct brcmf_fws_info *fws, | ||
986 | u8 fifo, u8 credits) | ||
987 | { | ||
988 | if (!credits) | ||
989 | return; | ||
990 | |||
991 | fws->fifo_credit_map |= 1 << fifo; | ||
992 | fws->fifo_credit[fifo] += credits; | ||
993 | } | ||
994 | |||
995 | static void brcmf_fws_schedule_deq(struct brcmf_fws_info *fws) | ||
996 | { | ||
997 | /* only schedule dequeue when there are credits for delayed traffic */ | ||
998 | if (fws->fifo_credit_map & fws->fifo_delay_map) | ||
999 | queue_work(fws->fws_wq, &fws->fws_dequeue_work); | ||
1000 | } | ||
1001 | |||
1002 | static void brcmf_skb_pick_up_credit(struct brcmf_fws_info *fws, int fifo, | ||
1003 | struct sk_buff *p) | ||
1004 | { | ||
1005 | struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(p)->mac; | ||
1006 | |||
1007 | if (brcmf_skbcb(p)->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK) { | ||
1008 | if (fws->fcmode != BRCMF_FWS_FCMODE_IMPLIED_CREDIT) | ||
1009 | return; | ||
1010 | brcmf_fws_return_credits(fws, fifo, 1); | ||
1011 | } else { | ||
1012 | /* | ||
1013 | * if this packet did not count against FIFO credit, it | ||
1014 | * must have taken a requested_credit from the destination | ||
1015 | * entry (for pspoll etc.) | ||
1016 | */ | ||
1017 | if (!brcmf_skb_if_flags_get_field(p, REQUESTED)) | ||
1018 | entry->requested_credit++; | ||
1019 | } | ||
1020 | brcmf_fws_schedule_deq(fws); | ||
1021 | } | ||
1022 | |||
1023 | static int brcmf_fws_enq(struct brcmf_fws_info *fws, | ||
1024 | enum brcmf_fws_skb_state state, int fifo, | ||
1025 | struct sk_buff *p) | ||
1026 | { | ||
1027 | int prec = 2 * fifo; | ||
1028 | u32 *qfull_stat = &fws->stats.delayq_full_error; | ||
1029 | |||
1030 | struct brcmf_fws_mac_descriptor *entry; | ||
1031 | |||
1032 | entry = brcmf_skbcb(p)->mac; | ||
1033 | if (entry == NULL) { | ||
1034 | brcmf_err("no mac descriptor found for skb %p\n", p); | ||
1035 | return -ENOENT; | ||
1036 | } | ||
1037 | |||
1038 | brcmf_dbg(TRACE, "enter: ea=%pM, qlen=%d\n", entry->ea, entry->psq.len); | ||
1039 | if (state == BRCMF_FWS_SKBSTATE_SUPPRESSED) { | ||
1040 | prec += 1; | ||
1041 | qfull_stat = &fws->stats.supprq_full_error; | ||
1042 | } | ||
1043 | |||
1044 | if (brcmu_pktq_penq(&entry->psq, prec, p) == NULL) { | ||
1045 | *qfull_stat += 1; | ||
1046 | return -ENFILE; | ||
1047 | } | ||
1048 | |||
1049 | /* increment total enqueued packet count */ | ||
1050 | fws->fifo_delay_map |= 1 << fifo; | ||
1051 | fws->fifo_enqpkt[fifo]++; | ||
1052 | |||
1053 | /* update the sk_buff state */ | ||
1054 | brcmf_skbcb(p)->state = state; | ||
1055 | if (state == BRCMF_FWS_SKBSTATE_SUPPRESSED) | ||
1056 | entry->suppress_count++; | ||
1057 | |||
1058 | /* | ||
1059 | * A packet has been pushed so update traffic | ||
1060 | * availability bitmap, if applicable | ||
1061 | */ | ||
1062 | brcmf_fws_tim_update(fws, entry, fifo); | ||
1063 | brcmf_fws_flow_control_check(fws, &entry->psq, | ||
1064 | brcmf_skb_if_flags_get_field(p, INDEX)); | ||
1065 | return 0; | ||
1066 | } | ||
1067 | |||
1068 | static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo) | ||
1069 | { | ||
1070 | struct brcmf_fws_mac_descriptor *table; | ||
1071 | struct brcmf_fws_mac_descriptor *entry; | ||
1072 | struct sk_buff *p; | ||
1073 | int use_credit = 1; | ||
1074 | int num_nodes; | ||
1075 | int node_pos; | ||
1076 | int prec_out; | ||
1077 | int pmsk = 3; | ||
1078 | int i; | ||
1079 | |||
1080 | table = (struct brcmf_fws_mac_descriptor *)&fws->desc; | ||
1081 | num_nodes = sizeof(fws->desc) / sizeof(struct brcmf_fws_mac_descriptor); | ||
1082 | node_pos = fws->deq_node_pos[fifo]; | ||
1083 | |||
1084 | for (i = 0; i < num_nodes; i++) { | ||
1085 | entry = &table[(node_pos + i) % num_nodes]; | ||
1086 | if (!entry->occupied) | ||
1087 | continue; | ||
1088 | |||
1089 | if (entry->suppressed) | ||
1090 | pmsk = 2; | ||
1091 | p = brcmu_pktq_mdeq(&entry->psq, pmsk << (fifo * 2), &prec_out); | ||
1092 | if (p == NULL) { | ||
1093 | if (entry->suppressed) { | ||
1094 | if (entry->suppr_transit_count > | ||
1095 | entry->suppress_count) | ||
1096 | return NULL; | ||
1097 | entry->suppressed = false; | ||
1098 | p = brcmu_pktq_mdeq(&entry->psq, | ||
1099 | 1 << (fifo * 2), &prec_out); | ||
1100 | } | ||
1101 | } | ||
1102 | if (p == NULL) | ||
1103 | continue; | ||
1104 | |||
1105 | /* did the packet come from suppress sub-queue? */ | ||
1106 | if (entry->requested_credit > 0) { | ||
1107 | entry->requested_credit--; | ||
1108 | /* | ||
1109 | * if the packet was pulled out while destination is in | ||
1110 | * closed state but had a non-zero packets requested, | ||
1111 | * then this should not count against the FIFO credit. | ||
1112 | * That is due to the fact that the firmware will | ||
1113 | * most likely hold onto this packet until a suitable | ||
1114 | * time later to push it to the appropriate AC FIFO. | ||
1115 | */ | ||
1116 | if (entry->state == BRCMF_FWS_STATE_CLOSE) | ||
1117 | use_credit = 0; | ||
1118 | } else if (entry->requested_packet > 0) { | ||
1119 | entry->requested_packet--; | ||
1120 | brcmf_skb_if_flags_set_field(p, REQUESTED, 1); | ||
1121 | if (entry->state == BRCMF_FWS_STATE_CLOSE) | ||
1122 | use_credit = 0; | ||
1123 | } | ||
1124 | brcmf_skb_if_flags_set_field(p, CREDITCHECK, use_credit); | ||
1125 | |||
1126 | /* move dequeue position to ensure fair round-robin */ | ||
1127 | fws->deq_node_pos[fifo] = (node_pos + i + 1) % num_nodes; | ||
1128 | brcmf_fws_flow_control_check(fws, &entry->psq, | ||
1129 | brcmf_skb_if_flags_get_field(p, | ||
1130 | INDEX) | ||
1131 | ); | ||
1132 | /* | ||
1133 | * A packet has been picked up, update traffic | ||
1134 | * availability bitmap, if applicable | ||
1135 | */ | ||
1136 | brcmf_fws_tim_update(fws, entry, fifo); | ||
1137 | |||
1138 | /* | ||
1139 | * decrement total enqueued fifo packets and | ||
1140 | * clear delay bitmap if done. | ||
1141 | */ | ||
1142 | fws->fifo_enqpkt[fifo]--; | ||
1143 | if (fws->fifo_enqpkt[fifo] == 0) | ||
1144 | fws->fifo_delay_map &= ~(1 << fifo); | ||
1145 | goto done; | ||
1146 | } | ||
1147 | p = NULL; | ||
1148 | done: | ||
1149 | brcmf_dbg(TRACE, "exit: fifo %d skb %p\n", fifo, p); | ||
1150 | return p; | ||
1151 | } | ||
1152 | |||
1153 | static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, | ||
1154 | struct sk_buff *skb, u32 genbit) | ||
1155 | { | ||
1156 | struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; | ||
1157 | u32 hslot; | ||
1158 | int ret; | ||
1159 | |||
1160 | hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); | ||
1161 | |||
1162 | /* this packet was suppressed */ | ||
1163 | if (!entry->suppressed || entry->generation != genbit) { | ||
1164 | entry->suppressed = true; | ||
1165 | entry->suppress_count = brcmu_pktq_mlen(&entry->psq, | ||
1166 | 1 << (fifo * 2 + 1)); | ||
1167 | entry->suppr_transit_count = entry->transit_count; | ||
1168 | } | ||
1169 | |||
1170 | entry->generation = genbit; | ||
1171 | |||
1172 | ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo, skb); | ||
1173 | if (ret != 0) { | ||
1174 | /* suppress q is full, drop this packet */ | ||
1175 | brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb, | ||
1176 | true); | ||
1177 | } else { | ||
1178 | /* | ||
1179 | * Mark suppressed to avoid a double free during | ||
1180 | * wlfc cleanup | ||
1181 | */ | ||
1182 | brcmf_fws_hanger_mark_suppressed(&fws->hanger, hslot, | ||
1183 | genbit); | ||
1184 | entry->suppress_count++; | ||
1185 | } | ||
1186 | |||
1187 | return ret; | ||
1188 | } | ||
1189 | |||
1190 | static int | ||
1191 | brcmf_fws_txstatus_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, | ||
1192 | u32 genbit) | ||
1193 | { | ||
1194 | u32 fifo; | ||
1195 | int ret; | ||
1196 | bool remove_from_hanger = true; | ||
1197 | struct sk_buff *skb; | ||
1198 | struct brcmf_fws_mac_descriptor *entry = NULL; | ||
1199 | |||
1200 | brcmf_dbg(TRACE, "status: flags=0x%X, hslot=%d\n", | ||
1201 | flags, hslot); | ||
1202 | |||
1203 | if (flags == BRCMF_FWS_TXSTATUS_DISCARD) | ||
1204 | fws->stats.txs_discard++; | ||
1205 | else if (flags == BRCMF_FWS_TXSTATUS_CORE_SUPPRESS) { | ||
1206 | fws->stats.txs_supp_core++; | ||
1207 | remove_from_hanger = false; | ||
1208 | } else if (flags == BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS) { | ||
1209 | fws->stats.txs_supp_ps++; | ||
1210 | remove_from_hanger = false; | ||
1211 | } else if (flags == BRCMF_FWS_TXSTATUS_FW_TOSSED) | ||
1212 | fws->stats.txs_tossed++; | ||
1213 | else | ||
1214 | brcmf_err("unexpected txstatus\n"); | ||
1215 | |||
1216 | ret = brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb, | ||
1217 | remove_from_hanger); | ||
1218 | if (ret != 0) { | ||
1219 | brcmf_err("no packet in hanger slot: hslot=%d\n", hslot); | ||
1220 | return ret; | ||
1221 | } | ||
1222 | |||
1223 | entry = brcmf_skbcb(skb)->mac; | ||
1224 | if (WARN_ON(!entry)) { | ||
1225 | brcmu_pkt_buf_free_skb(skb); | ||
1226 | return -EINVAL; | ||
1227 | } | ||
1228 | |||
1229 | /* pick up the implicit credit from this packet */ | ||
1230 | fifo = brcmf_skb_htod_tag_get_field(skb, FIFO); | ||
1231 | brcmf_skb_pick_up_credit(fws, fifo, skb); | ||
1232 | |||
1233 | if (!remove_from_hanger) | ||
1234 | ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, genbit); | ||
1235 | |||
1236 | if (remove_from_hanger || ret) { | ||
1237 | entry->transit_count--; | ||
1238 | if (entry->suppressed) | ||
1239 | entry->suppr_transit_count--; | ||
1240 | |||
1241 | brcmf_txfinalize(fws->drvr, skb, true); | ||
1242 | } | ||
1243 | return 0; | ||
1244 | } | ||
1245 | |||
1246 | static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws, | ||
1247 | u8 *data) | ||
1248 | { | ||
1249 | int i; | ||
1250 | |||
1251 | if (fws->fcmode != BRCMF_FWS_FCMODE_EXPLICIT_CREDIT) { | ||
1252 | brcmf_dbg(INFO, "ignored\n"); | ||
1253 | return 0; | ||
1254 | } | ||
1255 | |||
1256 | brcmf_dbg(TRACE, "enter: data %pM\n", data); | ||
1257 | for (i = 0; i < BRCMF_FWS_FIFO_COUNT; i++) | ||
1258 | brcmf_fws_return_credits(fws, i, data[i]); | ||
1259 | |||
1260 | brcmf_dbg(INFO, "map: credit %x delay %x\n", fws->fifo_credit_map, | ||
1261 | fws->fifo_delay_map); | ||
1262 | brcmf_fws_schedule_deq(fws); | ||
1263 | return 0; | ||
1264 | } | ||
1265 | |||
1266 | static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data) | ||
1267 | { | ||
1268 | __le32 status_le; | ||
1269 | u32 status; | ||
1270 | u32 hslot; | ||
1271 | u32 genbit; | ||
1272 | u8 flags; | ||
1273 | |||
1274 | fws->stats.txs_indicate++; | ||
1275 | memcpy(&status_le, data, sizeof(status_le)); | ||
1276 | status = le32_to_cpu(status_le); | ||
1277 | flags = brcmf_txstatus_get_field(status, FLAGS); | ||
1278 | hslot = brcmf_txstatus_get_field(status, HSLOT); | ||
1279 | genbit = brcmf_txstatus_get_field(status, GENERATION); | ||
1280 | |||
1281 | return brcmf_fws_txstatus_process(fws, flags, hslot, genbit); | ||
1282 | } | ||
1283 | |||
191 | static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data) | 1284 | static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data) |
192 | { | 1285 | { |
193 | __le32 timestamp; | 1286 | __le32 timestamp; |
@@ -213,51 +1306,32 @@ do { \ | |||
213 | #define brcmf_fws_unlock(drvr, flags) \ | 1306 | #define brcmf_fws_unlock(drvr, flags) \ |
214 | spin_unlock_irqrestore(&((drvr)->fws_spinlock), (flags)) | 1307 | spin_unlock_irqrestore(&((drvr)->fws_spinlock), (flags)) |
215 | 1308 | ||
216 | int brcmf_fws_init(struct brcmf_pub *drvr) | 1309 | static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp, |
1310 | const struct brcmf_event_msg *e, | ||
1311 | void *data) | ||
217 | { | 1312 | { |
218 | u32 tlv; | 1313 | struct brcmf_fws_info *fws = ifp->drvr->fws; |
219 | int rc; | 1314 | int i; |
220 | 1315 | ulong flags; | |
221 | /* enable rssi signals */ | 1316 | u8 *credits = data; |
222 | tlv = drvr->fw_signals ? BRCMF_FWS_FLAGS_RSSI_SIGNALS : 0; | ||
223 | |||
224 | spin_lock_init(&drvr->fws_spinlock); | ||
225 | 1317 | ||
226 | drvr->fws = kzalloc(sizeof(*(drvr->fws)), GFP_KERNEL); | 1318 | if (e->datalen < BRCMF_FWS_FIFO_COUNT) { |
227 | if (!drvr->fws) { | 1319 | brcmf_err("event payload too small (%d)\n", e->datalen); |
228 | rc = -ENOMEM; | 1320 | return -EINVAL; |
229 | goto fail; | ||
230 | } | 1321 | } |
231 | 1322 | ||
232 | /* enable proptxtstatus signaling by default */ | 1323 | brcmf_dbg(TRACE, "enter: credits %pM\n", credits); |
233 | rc = brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv); | 1324 | brcmf_fws_lock(ifp->drvr, flags); |
234 | if (rc < 0) { | 1325 | for (i = 0; i < ARRAY_SIZE(fws->fifo_credit); i++) { |
235 | brcmf_err("failed to set bdcv2 tlv signaling\n"); | 1326 | if (*credits) |
236 | goto fail; | 1327 | fws->fifo_credit_map |= 1 << i; |
1328 | else | ||
1329 | fws->fifo_credit_map &= ~(1 << i); | ||
1330 | fws->fifo_credit[i] = *credits++; | ||
237 | } | 1331 | } |
238 | /* set linkage back */ | 1332 | brcmf_fws_schedule_deq(fws); |
239 | drvr->fws->drvr = drvr; | 1333 | brcmf_fws_unlock(ifp->drvr, flags); |
240 | |||
241 | /* create debugfs file for statistics */ | ||
242 | brcmf_debugfs_create_fws_stats(drvr, &drvr->fws->stats); | ||
243 | |||
244 | /* TODO: remove upon feature delivery */ | ||
245 | brcmf_err("%s bdcv2 tlv signaling [%x]\n", | ||
246 | drvr->fw_signals ? "enabled" : "disabled", tlv); | ||
247 | return 0; | 1334 | return 0; |
248 | |||
249 | fail: | ||
250 | /* disable flow control entirely */ | ||
251 | drvr->fw_signals = false; | ||
252 | brcmf_fws_deinit(drvr); | ||
253 | return rc; | ||
254 | } | ||
255 | |||
256 | void brcmf_fws_deinit(struct brcmf_pub *drvr) | ||
257 | { | ||
258 | /* free top structure */ | ||
259 | kfree(drvr->fws); | ||
260 | drvr->fws = NULL; | ||
261 | } | 1335 | } |
262 | 1336 | ||
263 | int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, | 1337 | int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, |
@@ -304,57 +1378,50 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, | |||
304 | len = signal_data[1]; | 1378 | len = signal_data[1]; |
305 | data = signal_data + 2; | 1379 | data = signal_data + 2; |
306 | 1380 | ||
1381 | brcmf_dbg(INFO, "tlv type=%d (%s), len=%d, data[0]=%d\n", type, | ||
1382 | brcmf_fws_get_tlv_name(type), len, *data); | ||
1383 | |||
307 | /* abort parsing when length invalid */ | 1384 | /* abort parsing when length invalid */ |
308 | if (data_len < len + 2) | 1385 | if (data_len < len + 2) |
309 | break; | 1386 | break; |
310 | 1387 | ||
311 | brcmf_dbg(INFO, "tlv type=%d (%s), len=%d\n", type, | 1388 | if (len != brcmf_fws_get_tlv_len(fws, type)) |
312 | brcmf_fws_get_tlv_name(type), len); | ||
313 | switch (type) { | ||
314 | case BRCMF_FWS_TYPE_MAC_OPEN: | ||
315 | case BRCMF_FWS_TYPE_MAC_CLOSE: | ||
316 | WARN_ON(len != BRCMF_FWS_TYPE_MAC_OPEN_LEN); | ||
317 | break; | ||
318 | case BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT: | ||
319 | WARN_ON(len != BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT_LEN); | ||
320 | break; | ||
321 | case BRCMF_FWS_TYPE_TXSTATUS: | ||
322 | WARN_ON(len != BRCMF_FWS_TYPE_TXSTATUS_LEN); | ||
323 | break; | 1389 | break; |
324 | case BRCMF_FWS_TYPE_PKTTAG: | 1390 | |
325 | WARN_ON(len != BRCMF_FWS_TYPE_PKTTAG_LEN); | 1391 | switch (type) { |
1392 | case BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS: | ||
1393 | case BRCMF_FWS_TYPE_COMP_TXSTATUS: | ||
326 | break; | 1394 | break; |
327 | case BRCMF_FWS_TYPE_MACDESC_ADD: | 1395 | case BRCMF_FWS_TYPE_MACDESC_ADD: |
328 | case BRCMF_FWS_TYPE_MACDESC_DEL: | 1396 | case BRCMF_FWS_TYPE_MACDESC_DEL: |
329 | WARN_ON(len != BRCMF_FWS_TYPE_MACDESC_ADD_LEN); | 1397 | brcmf_fws_macdesc_indicate(fws, type, data); |
330 | break; | 1398 | break; |
331 | case BRCMF_FWS_TYPE_RSSI: | 1399 | case BRCMF_FWS_TYPE_MAC_OPEN: |
332 | WARN_ON(len != BRCMF_FWS_TYPE_RSSI_LEN); | 1400 | case BRCMF_FWS_TYPE_MAC_CLOSE: |
333 | brcmf_fws_rssi_indicate(fws, *(s8 *)data); | 1401 | brcmf_fws_macdesc_state_indicate(fws, type, data); |
334 | break; | 1402 | break; |
335 | case BRCMF_FWS_TYPE_INTERFACE_OPEN: | 1403 | case BRCMF_FWS_TYPE_INTERFACE_OPEN: |
336 | case BRCMF_FWS_TYPE_INTERFACE_CLOSE: | 1404 | case BRCMF_FWS_TYPE_INTERFACE_CLOSE: |
337 | WARN_ON(len != BRCMF_FWS_TYPE_INTERFACE_OPEN_LEN); | 1405 | brcmf_fws_interface_state_indicate(fws, type, data); |
338 | break; | 1406 | break; |
339 | case BRCMF_FWS_TYPE_FIFO_CREDITBACK: | 1407 | case BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT: |
340 | WARN_ON(len != BRCMF_FWS_TYPE_FIFO_CREDITBACK_LEN); | 1408 | case BRCMF_FWS_TYPE_MAC_REQUEST_PACKET: |
1409 | brcmf_fws_request_indicate(fws, type, data); | ||
341 | break; | 1410 | break; |
342 | case BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP: | 1411 | case BRCMF_FWS_TYPE_TXSTATUS: |
343 | WARN_ON(len != BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN); | 1412 | brcmf_fws_txstatus_indicate(fws, data); |
344 | break; | 1413 | break; |
345 | case BRCMF_FWS_TYPE_MAC_REQUEST_PACKET: | 1414 | case BRCMF_FWS_TYPE_FIFO_CREDITBACK: |
346 | WARN_ON(len != BRCMF_FWS_TYPE_MAC_REQUEST_PACKET_LEN); | 1415 | brcmf_fws_fifocreditback_indicate(fws, data); |
347 | break; | 1416 | break; |
348 | case BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS: | 1417 | case BRCMF_FWS_TYPE_RSSI: |
349 | WARN_ON(len != BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS_LEN); | 1418 | brcmf_fws_rssi_indicate(fws, *data); |
350 | break; | 1419 | break; |
351 | case BRCMF_FWS_TYPE_TRANS_ID: | 1420 | case BRCMF_FWS_TYPE_TRANS_ID: |
352 | WARN_ON(len != BRCMF_FWS_TYPE_TRANS_ID_LEN); | ||
353 | brcmf_fws_dbg_seqnum_check(fws, data); | 1421 | brcmf_fws_dbg_seqnum_check(fws, data); |
354 | break; | 1422 | break; |
355 | case BRCMF_FWS_TYPE_COMP_TXSTATUS: | 1423 | case BRCMF_FWS_TYPE_PKTTAG: |
356 | WARN_ON(len != BRCMF_FWS_TYPE_COMP_TXSTATUS_LEN); | 1424 | case BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP: |
357 | break; | ||
358 | default: | 1425 | default: |
359 | fws->stats.tlv_invalid_type++; | 1426 | fws->stats.tlv_invalid_type++; |
360 | break; | 1427 | break; |
@@ -380,3 +1447,505 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, | |||
380 | brcmf_fws_unlock(drvr, flags); | 1447 | brcmf_fws_unlock(drvr, flags); |
381 | return 0; | 1448 | return 0; |
382 | } | 1449 | } |
1450 | |||
1451 | static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb) | ||
1452 | { | ||
1453 | struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; | ||
1454 | u8 *wlh; | ||
1455 | u16 data_offset = 0; | ||
1456 | u8 fillers; | ||
1457 | __le32 pkttag = cpu_to_le32(brcmf_skbcb(skb)->htod); | ||
1458 | |||
1459 | brcmf_dbg(TRACE, "enter: ea=%pM, ifidx=%u, pkttag=0x%08X\n", | ||
1460 | entry->ea, entry->interface_id, le32_to_cpu(pkttag)); | ||
1461 | if (entry->send_tim_signal) | ||
1462 | data_offset += 2 + BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN; | ||
1463 | |||
1464 | /* +2 is for Type[1] and Len[1] in TLV, plus TIM signal */ | ||
1465 | data_offset += 2 + BRCMF_FWS_TYPE_PKTTAG_LEN; | ||
1466 | fillers = round_up(data_offset, 4) - data_offset; | ||
1467 | data_offset += fillers; | ||
1468 | |||
1469 | skb_push(skb, data_offset); | ||
1470 | wlh = skb->data; | ||
1471 | |||
1472 | wlh[0] = BRCMF_FWS_TYPE_PKTTAG; | ||
1473 | wlh[1] = BRCMF_FWS_TYPE_PKTTAG_LEN; | ||
1474 | memcpy(&wlh[2], &pkttag, sizeof(pkttag)); | ||
1475 | wlh += BRCMF_FWS_TYPE_PKTTAG_LEN + 2; | ||
1476 | |||
1477 | if (entry->send_tim_signal) { | ||
1478 | entry->send_tim_signal = 0; | ||
1479 | wlh[0] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP; | ||
1480 | wlh[1] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN; | ||
1481 | wlh[2] = entry->mac_handle; | ||
1482 | wlh[3] = entry->traffic_pending_bmp; | ||
1483 | wlh += BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN + 2; | ||
1484 | entry->traffic_lastreported_bmp = entry->traffic_pending_bmp; | ||
1485 | } | ||
1486 | if (fillers) | ||
1487 | memset(wlh, BRCMF_FWS_TYPE_FILLER, fillers); | ||
1488 | |||
1489 | brcmf_proto_hdrpush(fws->drvr, brcmf_skb_if_flags_get_field(skb, INDEX), | ||
1490 | data_offset >> 2, skb); | ||
1491 | return 0; | ||
1492 | } | ||
1493 | |||
1494 | static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, | ||
1495 | struct sk_buff *p) | ||
1496 | { | ||
1497 | struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p); | ||
1498 | struct brcmf_fws_mac_descriptor *entry = skcb->mac; | ||
1499 | int rc = 0; | ||
1500 | bool header_needed; | ||
1501 | int hslot = BRCMF_FWS_HANGER_MAXITEMS; | ||
1502 | u8 free_ctr; | ||
1503 | u8 ifidx; | ||
1504 | u8 flags; | ||
1505 | |||
1506 | header_needed = skcb->state != BRCMF_FWS_SKBSTATE_SUPPRESSED; | ||
1507 | |||
1508 | if (header_needed) { | ||
1509 | /* obtaining free slot may fail, but that will be caught | ||
1510 | * by the hanger push. This assures the packet has a BDC | ||
1511 | * header upon return. | ||
1512 | */ | ||
1513 | hslot = brcmf_fws_hanger_get_free_slot(&fws->hanger); | ||
1514 | free_ctr = entry->seq[fifo]; | ||
1515 | brcmf_skb_htod_tag_set_field(p, HSLOT, hslot); | ||
1516 | brcmf_skb_htod_tag_set_field(p, FREERUN, free_ctr); | ||
1517 | brcmf_skb_htod_tag_set_field(p, GENERATION, 1); | ||
1518 | entry->transit_count++; | ||
1519 | } | ||
1520 | brcmf_skb_if_flags_set_field(p, TRANSMIT, 1); | ||
1521 | brcmf_skb_htod_tag_set_field(p, FIFO, fifo); | ||
1522 | |||
1523 | flags = BRCMF_FWS_HTOD_FLAG_PKTFROMHOST; | ||
1524 | if (!(skcb->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK)) { | ||
1525 | /* | ||
1526 | Indicate that this packet is being sent in response to an | ||
1527 | explicit request from the firmware side. | ||
1528 | */ | ||
1529 | flags |= BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED; | ||
1530 | } | ||
1531 | brcmf_skb_htod_tag_set_field(p, FLAGS, flags); | ||
1532 | if (header_needed) { | ||
1533 | brcmf_fws_hdrpush(fws, p); | ||
1534 | rc = brcmf_fws_hanger_pushpkt(&fws->hanger, p, hslot); | ||
1535 | if (rc) | ||
1536 | brcmf_err("hanger push failed: rc=%d\n", rc); | ||
1537 | } else { | ||
1538 | int gen; | ||
1539 | |||
1540 | /* remove old header */ | ||
1541 | rc = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, p); | ||
1542 | if (rc == 0) { | ||
1543 | hslot = brcmf_skb_htod_tag_get_field(p, HSLOT); | ||
1544 | brcmf_fws_hanger_get_genbit(&fws->hanger, p, | ||
1545 | hslot, &gen); | ||
1546 | brcmf_skb_htod_tag_set_field(p, GENERATION, gen); | ||
1547 | |||
1548 | /* push new header */ | ||
1549 | brcmf_fws_hdrpush(fws, p); | ||
1550 | } | ||
1551 | } | ||
1552 | |||
1553 | return rc; | ||
1554 | } | ||
1555 | |||
1556 | static int | ||
1557 | brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, struct sk_buff *skb) | ||
1558 | { | ||
1559 | /* | ||
1560 | put the packet back to the head of queue | ||
1561 | |||
1562 | - suppressed packet goes back to suppress sub-queue | ||
1563 | - pull out the header, if new or delayed packet | ||
1564 | |||
1565 | Note: hslot is used only when header removal is done. | ||
1566 | */ | ||
1567 | struct brcmf_fws_mac_descriptor *entry; | ||
1568 | enum brcmf_fws_skb_state state; | ||
1569 | struct sk_buff *pktout; | ||
1570 | int rc = 0; | ||
1571 | int fifo; | ||
1572 | int hslot; | ||
1573 | u8 ifidx; | ||
1574 | |||
1575 | fifo = brcmf_skb_if_flags_get_field(skb, FIFO); | ||
1576 | state = brcmf_skbcb(skb)->state; | ||
1577 | entry = brcmf_skbcb(skb)->mac; | ||
1578 | |||
1579 | if (entry != NULL) { | ||
1580 | if (state == BRCMF_FWS_SKBSTATE_SUPPRESSED) { | ||
1581 | /* wl-header is saved for suppressed packets */ | ||
1582 | pktout = brcmu_pktq_penq_head(&entry->psq, 2 * fifo + 1, | ||
1583 | skb); | ||
1584 | if (pktout == NULL) { | ||
1585 | brcmf_err("suppress queue full\n"); | ||
1586 | rc = -ENOSPC; | ||
1587 | } | ||
1588 | } else { | ||
1589 | hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); | ||
1590 | |||
1591 | /* remove header first */ | ||
1592 | rc = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb); | ||
1593 | if (rc) { | ||
1594 | brcmf_err("header removal failed\n"); | ||
1595 | /* free the hanger slot */ | ||
1596 | brcmf_fws_hanger_poppkt(&fws->hanger, hslot, | ||
1597 | &pktout, true); | ||
1598 | brcmf_txfinalize(fws->drvr, skb, false); | ||
1599 | rc = -EINVAL; | ||
1600 | goto fail; | ||
1601 | } | ||
1602 | |||
1603 | /* delay-q packets are going to delay-q */ | ||
1604 | pktout = brcmu_pktq_penq_head(&entry->psq, | ||
1605 | 2 * fifo, skb); | ||
1606 | if (pktout == NULL) { | ||
1607 | brcmf_err("delay queue full\n"); | ||
1608 | rc = -ENOSPC; | ||
1609 | } | ||
1610 | |||
1611 | /* free the hanger slot */ | ||
1612 | brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &pktout, | ||
1613 | true); | ||
1614 | |||
1615 | /* decrement sequence count */ | ||
1616 | entry->seq[fifo]--; | ||
1617 | } | ||
1618 | /* | ||
1619 | if this packet did not count against FIFO credit, it must have | ||
1620 | taken a requested_credit from the firmware (for pspoll etc.) | ||
1621 | */ | ||
1622 | if (!(brcmf_skbcb(skb)->if_flags & | ||
1623 | BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK)) | ||
1624 | entry->requested_credit++; | ||
1625 | } else { | ||
1626 | brcmf_err("no mac entry linked\n"); | ||
1627 | rc = -ENOENT; | ||
1628 | } | ||
1629 | |||
1630 | |||
1631 | fail: | ||
1632 | if (rc) | ||
1633 | fws->stats.rollback_failed++; | ||
1634 | else | ||
1635 | fws->stats.rollback_success++; | ||
1636 | return rc; | ||
1637 | } | ||
1638 | |||
1639 | static int brcmf_fws_consume_credit(struct brcmf_fws_info *fws, int fifo, | ||
1640 | struct sk_buff *skb) | ||
1641 | { | ||
1642 | struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; | ||
1643 | int *credit = &fws->fifo_credit[fifo]; | ||
1644 | int use_credit = 1; | ||
1645 | |||
1646 | brcmf_dbg(TRACE, "enter: ac=%d, credits=%d\n", fifo, *credit); | ||
1647 | |||
1648 | if (entry->requested_credit > 0) { | ||
1649 | /* | ||
1650 | * if the packet was pulled out while destination is in | ||
1651 | * closed state but had a non-zero packets requested, | ||
1652 | * then this should not count against the FIFO credit. | ||
1653 | * That is due to the fact that the firmware will | ||
1654 | * most likely hold onto this packet until a suitable | ||
1655 | * time later to push it to the appropriate AC FIFO. | ||
1656 | */ | ||
1657 | entry->requested_credit--; | ||
1658 | if (entry->state == BRCMF_FWS_STATE_CLOSE) | ||
1659 | use_credit = 0; | ||
1660 | } else if (entry->requested_packet > 0) { | ||
1661 | entry->requested_packet--; | ||
1662 | brcmf_skb_if_flags_set_field(skb, REQUESTED, 1); | ||
1663 | if (entry->state == BRCMF_FWS_STATE_CLOSE) | ||
1664 | use_credit = 0; | ||
1665 | } | ||
1666 | brcmf_skb_if_flags_set_field(skb, CREDITCHECK, use_credit); | ||
1667 | if (!use_credit) { | ||
1668 | brcmf_dbg(TRACE, "exit: no creditcheck set\n"); | ||
1669 | return 0; | ||
1670 | } | ||
1671 | |||
1672 | if (!(*credit)) { | ||
1673 | brcmf_dbg(TRACE, "exit: credits depleted\n"); | ||
1674 | return -ENAVAIL; | ||
1675 | } | ||
1676 | (*credit)--; | ||
1677 | if (!(*credit)) | ||
1678 | fws->fifo_credit_map &= ~(1 << fifo); | ||
1679 | brcmf_dbg(TRACE, "exit: ac=%d, credits=%d\n", fifo, *credit); | ||
1680 | return 0; | ||
1681 | } | ||
1682 | |||
1683 | static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo, | ||
1684 | struct sk_buff *skb) | ||
1685 | { | ||
1686 | struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb); | ||
1687 | struct brcmf_fws_mac_descriptor *entry; | ||
1688 | struct brcmf_bus *bus = fws->drvr->bus_if; | ||
1689 | int rc; | ||
1690 | |||
1691 | entry = skcb->mac; | ||
1692 | if (IS_ERR(entry)) | ||
1693 | return PTR_ERR(entry); | ||
1694 | |||
1695 | rc = brcmf_fws_precommit_skb(fws, fifo, skb); | ||
1696 | if (rc < 0) { | ||
1697 | fws->stats.generic_error++; | ||
1698 | goto rollback; | ||
1699 | } | ||
1700 | |||
1701 | rc = brcmf_bus_txdata(bus, skb); | ||
1702 | if (rc < 0) | ||
1703 | goto rollback; | ||
1704 | |||
1705 | entry->seq[fifo]++; | ||
1706 | fws->stats.pkt2bus++; | ||
1707 | if (brcmf_skbcb(skb)->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK) { | ||
1708 | fws->stats.send_pkts[fifo]++; | ||
1709 | fws->stats.fifo_credits_sent[fifo]++; | ||
1710 | } | ||
1711 | |||
1712 | return rc; | ||
1713 | |||
1714 | rollback: | ||
1715 | rc = brcmf_fws_rollback_toq(fws, skb); | ||
1716 | return rc; | ||
1717 | } | ||
1718 | |||
1719 | int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) | ||
1720 | { | ||
1721 | struct brcmf_pub *drvr = ifp->drvr; | ||
1722 | struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb); | ||
1723 | struct ethhdr *eh = (struct ethhdr *)(skb->data); | ||
1724 | ulong flags; | ||
1725 | u8 ifidx = ifp->ifidx; | ||
1726 | int fifo = BRCMF_FWS_FIFO_BCMC; | ||
1727 | bool multicast = is_multicast_ether_addr(eh->h_dest); | ||
1728 | |||
1729 | /* determine the priority */ | ||
1730 | if (!skb->priority) | ||
1731 | skb->priority = cfg80211_classify8021d(skb); | ||
1732 | |||
1733 | drvr->tx_multicast += !!multicast; | ||
1734 | if (ntohs(eh->h_proto) == ETH_P_PAE) | ||
1735 | atomic_inc(&ifp->pend_8021x_cnt); | ||
1736 | |||
1737 | if (!brcmf_fws_fc_active(drvr->fws)) { | ||
1738 | /* If the protocol uses a data header, apply it */ | ||
1739 | brcmf_proto_hdrpush(drvr, ifidx, 0, skb); | ||
1740 | |||
1741 | /* Use bus module to send data frame */ | ||
1742 | return brcmf_bus_txdata(drvr->bus_if, skb); | ||
1743 | } | ||
1744 | |||
1745 | /* set control buffer information */ | ||
1746 | skcb->if_flags = 0; | ||
1747 | skcb->mac = brcmf_fws_find_mac_desc(drvr->fws, ifidx, eh->h_dest); | ||
1748 | skcb->state = BRCMF_FWS_SKBSTATE_NEW; | ||
1749 | brcmf_skb_if_flags_set_field(skb, INDEX, ifidx); | ||
1750 | if (!multicast) | ||
1751 | fifo = brcmf_fws_prio2fifo[skb->priority]; | ||
1752 | brcmf_skb_if_flags_set_field(skb, FIFO, fifo); | ||
1753 | |||
1754 | brcmf_dbg(TRACE, "ea=%pM, multi=%d, fifo=%d\n", eh->h_dest, | ||
1755 | multicast, fifo); | ||
1756 | |||
1757 | brcmf_fws_lock(drvr, flags); | ||
1758 | if (!brcmf_fws_mac_desc_ready(skcb->mac, fifo) || | ||
1759 | (!multicast && | ||
1760 | brcmf_fws_consume_credit(drvr->fws, fifo, skb) < 0)) { | ||
1761 | /* enqueue the packet in delayQ */ | ||
1762 | drvr->fws->fifo_delay_map |= 1 << fifo; | ||
1763 | brcmf_fws_enq(drvr->fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb); | ||
1764 | } else { | ||
1765 | brcmf_fws_commit_skb(drvr->fws, fifo, skb); | ||
1766 | } | ||
1767 | brcmf_fws_unlock(drvr, flags); | ||
1768 | return 0; | ||
1769 | } | ||
1770 | |||
1771 | void brcmf_fws_reset_interface(struct brcmf_if *ifp) | ||
1772 | { | ||
1773 | struct brcmf_fws_mac_descriptor *entry = ifp->fws_desc; | ||
1774 | |||
1775 | brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx); | ||
1776 | if (!entry) | ||
1777 | return; | ||
1778 | |||
1779 | brcmf_fws_init_mac_descriptor(entry, ifp->mac_addr, ifp->ifidx); | ||
1780 | } | ||
1781 | |||
1782 | void brcmf_fws_add_interface(struct brcmf_if *ifp) | ||
1783 | { | ||
1784 | struct brcmf_fws_info *fws = ifp->drvr->fws; | ||
1785 | struct brcmf_fws_mac_descriptor *entry; | ||
1786 | |||
1787 | brcmf_dbg(TRACE, "enter: idx=%d, mac=%pM\n", | ||
1788 | ifp->bssidx, ifp->mac_addr); | ||
1789 | if (!ifp->ndev || !ifp->drvr->fw_signals) | ||
1790 | return; | ||
1791 | |||
1792 | entry = &fws->desc.iface[ifp->ifidx]; | ||
1793 | ifp->fws_desc = entry; | ||
1794 | brcmf_fws_init_mac_descriptor(entry, ifp->mac_addr, ifp->ifidx); | ||
1795 | brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT, | ||
1796 | BRCMF_FWS_PSQ_LEN); | ||
1797 | } | ||
1798 | |||
1799 | void brcmf_fws_del_interface(struct brcmf_if *ifp) | ||
1800 | { | ||
1801 | struct brcmf_fws_mac_descriptor *entry = ifp->fws_desc; | ||
1802 | |||
1803 | brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx); | ||
1804 | if (!entry) | ||
1805 | return; | ||
1806 | |||
1807 | ifp->fws_desc = NULL; | ||
1808 | brcmf_fws_clear_mac_descriptor(entry); | ||
1809 | brcmf_fws_cleanup(ifp->drvr->fws, ifp->ifidx); | ||
1810 | } | ||
1811 | |||
1812 | static void brcmf_fws_dequeue_worker(struct work_struct *worker) | ||
1813 | { | ||
1814 | struct brcmf_fws_info *fws; | ||
1815 | struct sk_buff *skb; | ||
1816 | ulong flags; | ||
1817 | int fifo; | ||
1818 | int credit; | ||
1819 | |||
1820 | fws = container_of(worker, struct brcmf_fws_info, fws_dequeue_work); | ||
1821 | |||
1822 | brcmf_dbg(TRACE, "enter: fws=%p\n", fws); | ||
1823 | brcmf_fws_lock(fws->drvr, flags); | ||
1824 | for (fifo = NL80211_NUM_ACS; fifo >= 0; fifo--) { | ||
1825 | brcmf_dbg(TRACE, "fifo %d credit %d\n", fifo, | ||
1826 | fws->fifo_credit[fifo]); | ||
1827 | for (credit = 0; credit < fws->fifo_credit[fifo]; /* nop */) { | ||
1828 | skb = brcmf_fws_deq(fws, fifo); | ||
1829 | if (!skb) | ||
1830 | break; | ||
1831 | if (!brcmf_fws_commit_skb(fws, fifo, skb) && | ||
1832 | brcmf_skbcb(skb)->if_flags & | ||
1833 | BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK) | ||
1834 | credit++; | ||
1835 | } | ||
1836 | fws->fifo_credit[fifo] -= credit; | ||
1837 | } | ||
1838 | brcmf_fws_unlock(fws->drvr, flags); | ||
1839 | } | ||
1840 | |||
1841 | int brcmf_fws_init(struct brcmf_pub *drvr) | ||
1842 | { | ||
1843 | u32 tlv = BRCMF_FWS_FLAGS_RSSI_SIGNALS; | ||
1844 | int rc; | ||
1845 | |||
1846 | if (!drvr->fw_signals) | ||
1847 | return 0; | ||
1848 | |||
1849 | spin_lock_init(&drvr->fws_spinlock); | ||
1850 | |||
1851 | drvr->fws = kzalloc(sizeof(*(drvr->fws)), GFP_KERNEL); | ||
1852 | if (!drvr->fws) { | ||
1853 | rc = -ENOMEM; | ||
1854 | goto fail; | ||
1855 | } | ||
1856 | |||
1857 | /* set linkage back */ | ||
1858 | drvr->fws->drvr = drvr; | ||
1859 | drvr->fws->fcmode = fcmode; | ||
1860 | |||
1861 | drvr->fws->fws_wq = create_singlethread_workqueue("brcmf_fws_wq"); | ||
1862 | if (drvr->fws->fws_wq == NULL) { | ||
1863 | brcmf_err("workqueue creation failed\n"); | ||
1864 | rc = -EBADF; | ||
1865 | goto fail; | ||
1866 | } | ||
1867 | INIT_WORK(&drvr->fws->fws_dequeue_work, brcmf_fws_dequeue_worker); | ||
1868 | |||
1869 | /* enable firmware signalling if fcmode active */ | ||
1870 | if (drvr->fws->fcmode != BRCMF_FWS_FCMODE_NONE) | ||
1871 | tlv |= BRCMF_FWS_FLAGS_XONXOFF_SIGNALS | | ||
1872 | BRCMF_FWS_FLAGS_CREDIT_STATUS_SIGNALS | | ||
1873 | BRCMF_FWS_FLAGS_HOST_PROPTXSTATUS_ACTIVE; | ||
1874 | |||
1875 | rc = brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv); | ||
1876 | if (rc < 0) { | ||
1877 | brcmf_err("failed to set bdcv2 tlv signaling\n"); | ||
1878 | goto fail; | ||
1879 | } | ||
1880 | |||
1881 | if (brcmf_fweh_register(drvr, BRCMF_E_FIFO_CREDIT_MAP, | ||
1882 | brcmf_fws_notify_credit_map)) { | ||
1883 | brcmf_err("register credit map handler failed\n"); | ||
1884 | goto fail; | ||
1885 | } | ||
1886 | |||
1887 | brcmf_fws_hanger_init(&drvr->fws->hanger); | ||
1888 | brcmf_fws_init_mac_descriptor(&drvr->fws->desc.other, NULL, 0); | ||
1889 | brcmu_pktq_init(&drvr->fws->desc.other.psq, BRCMF_FWS_PSQ_PREC_COUNT, | ||
1890 | BRCMF_FWS_PSQ_LEN); | ||
1891 | |||
1892 | /* create debugfs file for statistics */ | ||
1893 | brcmf_debugfs_create_fws_stats(drvr, &drvr->fws->stats); | ||
1894 | |||
1895 | /* TODO: remove upon feature delivery */ | ||
1896 | brcmf_err("%s bdcv2 tlv signaling [%x]\n", | ||
1897 | drvr->fw_signals ? "enabled" : "disabled", tlv); | ||
1898 | return 0; | ||
1899 | |||
1900 | fail: | ||
1901 | /* disable flow control entirely */ | ||
1902 | drvr->fw_signals = false; | ||
1903 | brcmf_fws_deinit(drvr); | ||
1904 | return rc; | ||
1905 | } | ||
1906 | |||
1907 | void brcmf_fws_deinit(struct brcmf_pub *drvr) | ||
1908 | { | ||
1909 | struct brcmf_fws_info *fws = drvr->fws; | ||
1910 | ulong flags; | ||
1911 | |||
1912 | if (!fws) | ||
1913 | return; | ||
1914 | |||
1915 | /* cleanup */ | ||
1916 | brcmf_fws_lock(drvr, flags); | ||
1917 | brcmf_fws_cleanup(fws, -1); | ||
1918 | drvr->fws = NULL; | ||
1919 | brcmf_fws_unlock(drvr, flags); | ||
1920 | |||
1921 | /* free top structure */ | ||
1922 | kfree(fws); | ||
1923 | } | ||
1924 | |||
1925 | bool brcmf_fws_fc_active(struct brcmf_fws_info *fws) | ||
1926 | { | ||
1927 | if (!fws) | ||
1928 | return false; | ||
1929 | |||
1930 | brcmf_dbg(TRACE, "enter: mode=%d\n", fws->fcmode); | ||
1931 | return fws->fcmode != BRCMF_FWS_FCMODE_NONE; | ||
1932 | } | ||
1933 | |||
1934 | void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb) | ||
1935 | { | ||
1936 | ulong flags; | ||
1937 | |||
1938 | brcmf_fws_lock(fws->drvr, flags); | ||
1939 | brcmf_fws_txstatus_process(fws, BRCMF_FWS_TXSTATUS_FW_TOSSED, | ||
1940 | brcmf_skb_htod_tag_get_field(skb, HSLOT), 0); | ||
1941 | /* the packet never reached firmware so reclaim credit */ | ||
1942 | if (fws->fcmode == BRCMF_FWS_FCMODE_EXPLICIT_CREDIT && | ||
1943 | brcmf_skbcb(skb)->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK) { | ||
1944 | brcmf_fws_return_credits(fws, | ||
1945 | brcmf_skb_htod_tag_get_field(skb, | ||
1946 | FIFO), | ||
1947 | 1); | ||
1948 | brcmf_fws_schedule_deq(fws); | ||
1949 | } | ||
1950 | brcmf_fws_unlock(fws->drvr, flags); | ||
1951 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h index e728eea72bb4..fbe483d23752 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h | |||
@@ -20,6 +20,14 @@ | |||
20 | 20 | ||
21 | int brcmf_fws_init(struct brcmf_pub *drvr); | 21 | int brcmf_fws_init(struct brcmf_pub *drvr); |
22 | void brcmf_fws_deinit(struct brcmf_pub *drvr); | 22 | void brcmf_fws_deinit(struct brcmf_pub *drvr); |
23 | bool brcmf_fws_fc_active(struct brcmf_fws_info *fws); | ||
23 | int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, | 24 | int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, |
24 | struct sk_buff *skb); | 25 | struct sk_buff *skb); |
26 | int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb); | ||
27 | |||
28 | void brcmf_fws_reset_interface(struct brcmf_if *ifp); | ||
29 | void brcmf_fws_add_interface(struct brcmf_if *ifp); | ||
30 | void brcmf_fws_del_interface(struct brcmf_if *ifp); | ||
31 | void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb); | ||
32 | |||
25 | #endif /* FWSIGNAL_H_ */ | 33 | #endif /* FWSIGNAL_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c index 4166e642068b..94ff045df2b3 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c | |||
@@ -15,6 +15,7 @@ | |||
15 | */ | 15 | */ |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/netdevice.h> | 17 | #include <linux/netdevice.h> |
18 | #include <linux/etherdevice.h> | ||
18 | #include <net/cfg80211.h> | 19 | #include <net/cfg80211.h> |
19 | 20 | ||
20 | #include <brcmu_wifi.h> | 21 | #include <brcmu_wifi.h> |
@@ -455,7 +456,9 @@ static int brcmf_p2p_set_firmware(struct brcmf_if *ifp, u8 *p2p_mac) | |||
455 | { | 456 | { |
456 | s32 ret = 0; | 457 | s32 ret = 0; |
457 | 458 | ||
459 | brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1); | ||
458 | brcmf_fil_iovar_int_set(ifp, "apsta", 1); | 460 | brcmf_fil_iovar_int_set(ifp, "apsta", 1); |
461 | brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1); | ||
459 | 462 | ||
460 | /* In case of COB type, firmware has default mac address | 463 | /* In case of COB type, firmware has default mac address |
461 | * After Initializing firmware, we have to set current mac address to | 464 | * After Initializing firmware, we have to set current mac address to |
@@ -473,28 +476,35 @@ static int brcmf_p2p_set_firmware(struct brcmf_if *ifp, u8 *p2p_mac) | |||
473 | * brcmf_p2p_generate_bss_mac() - derive mac addresses for P2P. | 476 | * brcmf_p2p_generate_bss_mac() - derive mac addresses for P2P. |
474 | * | 477 | * |
475 | * @p2p: P2P specific data. | 478 | * @p2p: P2P specific data. |
479 | * @dev_addr: optional device address. | ||
476 | * | 480 | * |
477 | * P2P needs mac addresses for P2P device and interface. These are | 481 | * P2P needs mac addresses for P2P device and interface. If no device |
478 | * derived from the primary net device, ie. the permanent ethernet | 482 | * address it specified, these are derived from the primary net device, ie. |
479 | * address of the device. | 483 | * the permanent ethernet address of the device. |
480 | */ | 484 | */ |
481 | static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p) | 485 | static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p, u8 *dev_addr) |
482 | { | 486 | { |
483 | struct brcmf_if *pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; | 487 | struct brcmf_if *pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; |
484 | struct brcmf_if *p2p_ifp = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->ifp; | 488 | bool local_admin = false; |
489 | |||
490 | if (!dev_addr || is_zero_ether_addr(dev_addr)) { | ||
491 | dev_addr = pri_ifp->mac_addr; | ||
492 | local_admin = true; | ||
493 | } | ||
485 | 494 | ||
486 | /* Generate the P2P Device Address. This consists of the device's | 495 | /* Generate the P2P Device Address. This consists of the device's |
487 | * primary MAC address with the locally administered bit set. | 496 | * primary MAC address with the locally administered bit set. |
488 | */ | 497 | */ |
489 | memcpy(p2p->dev_addr, pri_ifp->mac_addr, ETH_ALEN); | 498 | memcpy(p2p->dev_addr, dev_addr, ETH_ALEN); |
490 | p2p->dev_addr[0] |= 0x02; | 499 | if (local_admin) |
491 | memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN); | 500 | p2p->dev_addr[0] |= 0x02; |
492 | 501 | ||
493 | /* Generate the P2P Interface Address. If the discovery and connection | 502 | /* Generate the P2P Interface Address. If the discovery and connection |
494 | * BSSCFGs need to simultaneously co-exist, then this address must be | 503 | * BSSCFGs need to simultaneously co-exist, then this address must be |
495 | * different from the P2P Device Address, but also locally administered. | 504 | * different from the P2P Device Address, but also locally administered. |
496 | */ | 505 | */ |
497 | memcpy(p2p->int_addr, p2p->dev_addr, ETH_ALEN); | 506 | memcpy(p2p->int_addr, p2p->dev_addr, ETH_ALEN); |
507 | p2p->int_addr[0] |= 0x02; | ||
498 | p2p->int_addr[4] ^= 0x80; | 508 | p2p->int_addr[4] ^= 0x80; |
499 | } | 509 | } |
500 | 510 | ||
@@ -773,7 +783,7 @@ exit: | |||
773 | * validates the channels in the request. | 783 | * validates the channels in the request. |
774 | */ | 784 | */ |
775 | static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg, | 785 | static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg, |
776 | struct net_device *ndev, | 786 | struct brcmf_if *ifp, |
777 | struct cfg80211_scan_request *request, | 787 | struct cfg80211_scan_request *request, |
778 | u16 action) | 788 | u16 action) |
779 | { | 789 | { |
@@ -1261,7 +1271,7 @@ static void | |||
1261 | brcmf_p2p_stop_wait_next_action_frame(struct brcmf_cfg80211_info *cfg) | 1271 | brcmf_p2p_stop_wait_next_action_frame(struct brcmf_cfg80211_info *cfg) |
1262 | { | 1272 | { |
1263 | struct brcmf_p2p_info *p2p = &cfg->p2p; | 1273 | struct brcmf_p2p_info *p2p = &cfg->p2p; |
1264 | struct net_device *ndev = cfg->escan_info.ndev; | 1274 | struct brcmf_if *ifp = cfg->escan_info.ifp; |
1265 | 1275 | ||
1266 | if (test_bit(BRCMF_P2P_STATUS_SENDING_ACT_FRAME, &p2p->status) && | 1276 | if (test_bit(BRCMF_P2P_STATUS_SENDING_ACT_FRAME, &p2p->status) && |
1267 | (test_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &p2p->status) || | 1277 | (test_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &p2p->status) || |
@@ -1271,12 +1281,12 @@ brcmf_p2p_stop_wait_next_action_frame(struct brcmf_cfg80211_info *cfg) | |||
1271 | * So abort scan for off channel completion. | 1281 | * So abort scan for off channel completion. |
1272 | */ | 1282 | */ |
1273 | if (p2p->af_sent_channel) | 1283 | if (p2p->af_sent_channel) |
1274 | brcmf_notify_escan_complete(cfg, ndev, true, true); | 1284 | brcmf_notify_escan_complete(cfg, ifp, true, true); |
1275 | } else if (test_bit(BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN, | 1285 | } else if (test_bit(BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN, |
1276 | &p2p->status)) { | 1286 | &p2p->status)) { |
1277 | brcmf_dbg(TRACE, "*** Wake UP ** abort listen for next af frame\n"); | 1287 | brcmf_dbg(TRACE, "*** Wake UP ** abort listen for next af frame\n"); |
1278 | /* So abort scan to cancel listen */ | 1288 | /* So abort scan to cancel listen */ |
1279 | brcmf_notify_escan_complete(cfg, ndev, true, true); | 1289 | brcmf_notify_escan_complete(cfg, ifp, true, true); |
1280 | } | 1290 | } |
1281 | } | 1291 | } |
1282 | 1292 | ||
@@ -1384,7 +1394,7 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp, | |||
1384 | /* After complete GO Negotiation, roll back to mpc mode */ | 1394 | /* After complete GO Negotiation, roll back to mpc mode */ |
1385 | if ((action == P2P_PAF_GON_CONF) || | 1395 | if ((action == P2P_PAF_GON_CONF) || |
1386 | (action == P2P_PAF_PROVDIS_RSP)) | 1396 | (action == P2P_PAF_PROVDIS_RSP)) |
1387 | brcmf_set_mpc(ifp->ndev, 1); | 1397 | brcmf_set_mpc(ifp, 1); |
1388 | if (action == P2P_PAF_GON_CONF) { | 1398 | if (action == P2P_PAF_GON_CONF) { |
1389 | brcmf_dbg(TRACE, "P2P: GO_NEG_PHASE status cleared\n"); | 1399 | brcmf_dbg(TRACE, "P2P: GO_NEG_PHASE status cleared\n"); |
1390 | clear_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status); | 1400 | clear_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status); |
@@ -1421,7 +1431,8 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp, | |||
1421 | CHSPEC_IS2G(chanspec) ? | 1431 | CHSPEC_IS2G(chanspec) ? |
1422 | IEEE80211_BAND_2GHZ : | 1432 | IEEE80211_BAND_2GHZ : |
1423 | IEEE80211_BAND_5GHZ); | 1433 | IEEE80211_BAND_5GHZ); |
1424 | wdev = ifp->ndev->ieee80211_ptr; | 1434 | |
1435 | wdev = &ifp->vif->wdev; | ||
1425 | cfg80211_rx_mgmt(wdev, freq, 0, (u8 *)mgmt_frame, mgmt_frame_len, | 1436 | cfg80211_rx_mgmt(wdev, freq, 0, (u8 *)mgmt_frame, mgmt_frame_len, |
1426 | GFP_ATOMIC); | 1437 | GFP_ATOMIC); |
1427 | 1438 | ||
@@ -1637,6 +1648,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg, | |||
1637 | struct brcmf_fil_af_params_le *af_params) | 1648 | struct brcmf_fil_af_params_le *af_params) |
1638 | { | 1649 | { |
1639 | struct brcmf_p2p_info *p2p = &cfg->p2p; | 1650 | struct brcmf_p2p_info *p2p = &cfg->p2p; |
1651 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
1640 | struct brcmf_fil_action_frame_le *action_frame; | 1652 | struct brcmf_fil_action_frame_le *action_frame; |
1641 | struct brcmf_config_af_params config_af_params; | 1653 | struct brcmf_config_af_params config_af_params; |
1642 | struct afx_hdl *afx_hdl = &p2p->afx_hdl; | 1654 | struct afx_hdl *afx_hdl = &p2p->afx_hdl; |
@@ -1725,7 +1737,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg, | |||
1725 | 1737 | ||
1726 | /* To make sure to send successfully action frame, turn off mpc */ | 1738 | /* To make sure to send successfully action frame, turn off mpc */ |
1727 | if (config_af_params.mpc_onoff == 0) | 1739 | if (config_af_params.mpc_onoff == 0) |
1728 | brcmf_set_mpc(ndev, 0); | 1740 | brcmf_set_mpc(ifp, 0); |
1729 | 1741 | ||
1730 | /* set status and destination address before sending af */ | 1742 | /* set status and destination address before sending af */ |
1731 | if (p2p->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) { | 1743 | if (p2p->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) { |
@@ -1753,7 +1765,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg, | |||
1753 | * care of current piggback algo, lets abort the scan here | 1765 | * care of current piggback algo, lets abort the scan here |
1754 | * itself. | 1766 | * itself. |
1755 | */ | 1767 | */ |
1756 | brcmf_notify_escan_complete(cfg, ndev, true, true); | 1768 | brcmf_notify_escan_complete(cfg, ifp, true, true); |
1757 | 1769 | ||
1758 | /* update channel */ | 1770 | /* update channel */ |
1759 | af_params->channel = cpu_to_le32(afx_hdl->peer_chan); | 1771 | af_params->channel = cpu_to_le32(afx_hdl->peer_chan); |
@@ -1820,7 +1832,7 @@ exit: | |||
1820 | clear_bit(BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME, &p2p->status); | 1832 | clear_bit(BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME, &p2p->status); |
1821 | /* if all done, turn mpc on again */ | 1833 | /* if all done, turn mpc on again */ |
1822 | if (config_af_params.mpc_onoff == 1) | 1834 | if (config_af_params.mpc_onoff == 1) |
1823 | brcmf_set_mpc(ndev, 1); | 1835 | brcmf_set_mpc(ifp, 1); |
1824 | 1836 | ||
1825 | return ack; | 1837 | return ack; |
1826 | } | 1838 | } |
@@ -1839,7 +1851,6 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp, | |||
1839 | struct brcmf_cfg80211_info *cfg = ifp->drvr->config; | 1851 | struct brcmf_cfg80211_info *cfg = ifp->drvr->config; |
1840 | struct brcmf_p2p_info *p2p = &cfg->p2p; | 1852 | struct brcmf_p2p_info *p2p = &cfg->p2p; |
1841 | struct afx_hdl *afx_hdl = &p2p->afx_hdl; | 1853 | struct afx_hdl *afx_hdl = &p2p->afx_hdl; |
1842 | struct wireless_dev *wdev; | ||
1843 | struct brcmf_cfg80211_vif *vif = ifp->vif; | 1854 | struct brcmf_cfg80211_vif *vif = ifp->vif; |
1844 | struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data; | 1855 | struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data; |
1845 | u16 chanspec = be16_to_cpu(rxframe->chanspec); | 1856 | u16 chanspec = be16_to_cpu(rxframe->chanspec); |
@@ -1882,8 +1893,9 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp, | |||
1882 | CHSPEC_IS2G(chanspec) ? | 1893 | CHSPEC_IS2G(chanspec) ? |
1883 | IEEE80211_BAND_2GHZ : | 1894 | IEEE80211_BAND_2GHZ : |
1884 | IEEE80211_BAND_5GHZ); | 1895 | IEEE80211_BAND_5GHZ); |
1885 | wdev = ifp->ndev->ieee80211_ptr; | 1896 | |
1886 | cfg80211_rx_mgmt(wdev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC); | 1897 | cfg80211_rx_mgmt(&vif->wdev, freq, 0, mgmt_frame, mgmt_frame_len, |
1898 | GFP_ATOMIC); | ||
1887 | 1899 | ||
1888 | brcmf_dbg(INFO, "mgmt_frame_len (%d) , e->datalen (%d), chanspec (%04x), freq (%d)\n", | 1900 | brcmf_dbg(INFO, "mgmt_frame_len (%d) , e->datalen (%d), chanspec (%04x), freq (%d)\n", |
1889 | mgmt_frame_len, e->datalen, chanspec, freq); | 1901 | mgmt_frame_len, e->datalen, chanspec, freq); |
@@ -1934,7 +1946,8 @@ s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg) | |||
1934 | 1946 | ||
1935 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif; | 1947 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif; |
1936 | 1948 | ||
1937 | brcmf_p2p_generate_bss_mac(p2p); | 1949 | brcmf_p2p_generate_bss_mac(p2p, NULL); |
1950 | memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN); | ||
1938 | brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); | 1951 | brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); |
1939 | 1952 | ||
1940 | /* Initialize P2P Discovery in the firmware */ | 1953 | /* Initialize P2P Discovery in the firmware */ |
@@ -2040,13 +2053,13 @@ int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg, | |||
2040 | brcmf_err("vif for P2PAPI_BSSCFG_PRIMARY does not exist\n"); | 2053 | brcmf_err("vif for P2PAPI_BSSCFG_PRIMARY does not exist\n"); |
2041 | return -EPERM; | 2054 | return -EPERM; |
2042 | } | 2055 | } |
2043 | brcmf_notify_escan_complete(cfg, vif->ifp->ndev, true, true); | 2056 | brcmf_notify_escan_complete(cfg, vif->ifp, true, true); |
2044 | vif = p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif; | 2057 | vif = p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif; |
2045 | if (!vif) { | 2058 | if (!vif) { |
2046 | brcmf_err("vif for P2PAPI_BSSCFG_CONNECTION does not exist\n"); | 2059 | brcmf_err("vif for P2PAPI_BSSCFG_CONNECTION does not exist\n"); |
2047 | return -EPERM; | 2060 | return -EPERM; |
2048 | } | 2061 | } |
2049 | brcmf_set_mpc(vif->ifp->ndev, 0); | 2062 | brcmf_set_mpc(vif->ifp, 0); |
2050 | 2063 | ||
2051 | /* In concurrency case, STA may be already associated in a particular */ | 2064 | /* In concurrency case, STA may be already associated in a particular */ |
2052 | /* channel. so retrieve the current channel of primary interface and */ | 2065 | /* channel. so retrieve the current channel of primary interface and */ |
@@ -2124,13 +2137,105 @@ static int brcmf_p2p_release_p2p_if(struct brcmf_cfg80211_vif *vif) | |||
2124 | } | 2137 | } |
2125 | 2138 | ||
2126 | /** | 2139 | /** |
2140 | * brcmf_p2p_create_p2pdev() - create a P2P_DEVICE virtual interface. | ||
2141 | * | ||
2142 | * @p2p: P2P specific data. | ||
2143 | * @wiphy: wiphy device of new interface. | ||
2144 | * @addr: mac address for this new interface. | ||
2145 | */ | ||
2146 | static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p, | ||
2147 | struct wiphy *wiphy, | ||
2148 | u8 *addr) | ||
2149 | { | ||
2150 | struct brcmf_cfg80211_vif *p2p_vif; | ||
2151 | struct brcmf_if *p2p_ifp; | ||
2152 | struct brcmf_if *pri_ifp; | ||
2153 | int err; | ||
2154 | u32 bssidx; | ||
2155 | |||
2156 | if (p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif) | ||
2157 | return ERR_PTR(-ENOSPC); | ||
2158 | |||
2159 | p2p_vif = brcmf_alloc_vif(p2p->cfg, NL80211_IFTYPE_P2P_DEVICE, | ||
2160 | false); | ||
2161 | if (IS_ERR(p2p_vif)) { | ||
2162 | brcmf_err("could not create discovery vif\n"); | ||
2163 | return (struct wireless_dev *)p2p_vif; | ||
2164 | } | ||
2165 | |||
2166 | pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; | ||
2167 | brcmf_p2p_generate_bss_mac(p2p, addr); | ||
2168 | brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); | ||
2169 | |||
2170 | brcmf_cfg80211_arm_vif_event(p2p->cfg, p2p_vif); | ||
2171 | |||
2172 | /* Initialize P2P Discovery in the firmware */ | ||
2173 | err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1); | ||
2174 | if (err < 0) { | ||
2175 | brcmf_err("set p2p_disc error\n"); | ||
2176 | brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL); | ||
2177 | goto fail; | ||
2178 | } | ||
2179 | |||
2180 | /* wait for firmware event */ | ||
2181 | err = brcmf_cfg80211_wait_vif_event_timeout(p2p->cfg, BRCMF_E_IF_ADD, | ||
2182 | msecs_to_jiffies(1500)); | ||
2183 | brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL); | ||
2184 | if (!err) { | ||
2185 | brcmf_err("timeout occurred\n"); | ||
2186 | err = -EIO; | ||
2187 | goto fail; | ||
2188 | } | ||
2189 | |||
2190 | /* discovery interface created */ | ||
2191 | p2p_ifp = p2p_vif->ifp; | ||
2192 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif; | ||
2193 | memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN); | ||
2194 | memcpy(&p2p_vif->wdev.address, p2p->dev_addr, sizeof(p2p->dev_addr)); | ||
2195 | |||
2196 | /* verify bsscfg index for P2P discovery */ | ||
2197 | err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx); | ||
2198 | if (err < 0) { | ||
2199 | brcmf_err("retrieving discover bsscfg index failed\n"); | ||
2200 | goto fail; | ||
2201 | } | ||
2202 | |||
2203 | WARN_ON(p2p_ifp->bssidx != bssidx); | ||
2204 | |||
2205 | init_completion(&p2p->send_af_done); | ||
2206 | INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler); | ||
2207 | init_completion(&p2p->afx_hdl.act_frm_scan); | ||
2208 | init_completion(&p2p->wait_next_af); | ||
2209 | |||
2210 | return &p2p_vif->wdev; | ||
2211 | |||
2212 | fail: | ||
2213 | brcmf_free_vif(p2p_vif); | ||
2214 | return ERR_PTR(err); | ||
2215 | } | ||
2216 | |||
2217 | /** | ||
2218 | * brcmf_p2p_delete_p2pdev() - delete P2P_DEVICE virtual interface. | ||
2219 | * | ||
2220 | * @vif: virtual interface object to delete. | ||
2221 | */ | ||
2222 | static void brcmf_p2p_delete_p2pdev(struct brcmf_cfg80211_vif *vif) | ||
2223 | { | ||
2224 | struct brcmf_p2p_info *p2p = &vif->ifp->drvr->config->p2p; | ||
2225 | |||
2226 | cfg80211_unregister_wdev(&vif->wdev); | ||
2227 | p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; | ||
2228 | brcmf_free_vif(vif); | ||
2229 | } | ||
2230 | |||
2231 | /** | ||
2127 | * brcmf_p2p_add_vif() - create a new P2P virtual interface. | 2232 | * brcmf_p2p_add_vif() - create a new P2P virtual interface. |
2128 | * | 2233 | * |
2129 | * @wiphy: wiphy device of new interface. | 2234 | * @wiphy: wiphy device of new interface. |
2130 | * @name: name of the new interface. | 2235 | * @name: name of the new interface. |
2131 | * @type: nl80211 interface type. | 2236 | * @type: nl80211 interface type. |
2132 | * @flags: TBD | 2237 | * @flags: not used. |
2133 | * @params: TBD | 2238 | * @params: contains mac address for P2P device. |
2134 | */ | 2239 | */ |
2135 | struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, | 2240 | struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, |
2136 | enum nl80211_iftype type, u32 *flags, | 2241 | enum nl80211_iftype type, u32 *flags, |
@@ -2157,6 +2262,9 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, | |||
2157 | iftype = BRCMF_FIL_P2P_IF_GO; | 2262 | iftype = BRCMF_FIL_P2P_IF_GO; |
2158 | mode = WL_MODE_AP; | 2263 | mode = WL_MODE_AP; |
2159 | break; | 2264 | break; |
2265 | case NL80211_IFTYPE_P2P_DEVICE: | ||
2266 | return brcmf_p2p_create_p2pdev(&cfg->p2p, wiphy, | ||
2267 | params->macaddr); | ||
2160 | default: | 2268 | default: |
2161 | return ERR_PTR(-EOPNOTSUPP); | 2269 | return ERR_PTR(-EOPNOTSUPP); |
2162 | } | 2270 | } |
@@ -2244,6 +2352,8 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
2244 | break; | 2352 | break; |
2245 | 2353 | ||
2246 | case NL80211_IFTYPE_P2P_DEVICE: | 2354 | case NL80211_IFTYPE_P2P_DEVICE: |
2355 | brcmf_p2p_delete_p2pdev(vif); | ||
2356 | return 0; | ||
2247 | default: | 2357 | default: |
2248 | return -ENOTSUPP; | 2358 | return -ENOTSUPP; |
2249 | break; | 2359 | break; |
@@ -2275,3 +2385,33 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
2275 | 2385 | ||
2276 | return err; | 2386 | return err; |
2277 | } | 2387 | } |
2388 | |||
2389 | int brcmf_p2p_start_device(struct wiphy *wiphy, struct wireless_dev *wdev) | ||
2390 | { | ||
2391 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | ||
2392 | struct brcmf_p2p_info *p2p = &cfg->p2p; | ||
2393 | struct brcmf_cfg80211_vif *vif; | ||
2394 | int err; | ||
2395 | |||
2396 | vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev); | ||
2397 | mutex_lock(&cfg->usr_sync); | ||
2398 | err = brcmf_p2p_enable_discovery(p2p); | ||
2399 | if (!err) | ||
2400 | set_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state); | ||
2401 | mutex_unlock(&cfg->usr_sync); | ||
2402 | return err; | ||
2403 | } | ||
2404 | |||
2405 | void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev) | ||
2406 | { | ||
2407 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | ||
2408 | struct brcmf_p2p_info *p2p = &cfg->p2p; | ||
2409 | struct brcmf_cfg80211_vif *vif; | ||
2410 | |||
2411 | vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev); | ||
2412 | mutex_lock(&cfg->usr_sync); | ||
2413 | (void)brcmf_p2p_deinit_discovery(p2p); | ||
2414 | brcmf_abort_scanning(cfg); | ||
2415 | clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state); | ||
2416 | mutex_unlock(&cfg->usr_sync); | ||
2417 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h index 35efc7a67644..9df1f7a681e0 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h | |||
@@ -73,6 +73,20 @@ TRACE_EVENT(brcmf_dbg, | |||
73 | TP_printk("%s: %s", __get_str(func), __get_str(msg)) | 73 | TP_printk("%s: %s", __get_str(func), __get_str(msg)) |
74 | ); | 74 | ); |
75 | 75 | ||
76 | TRACE_EVENT(brcmf_hexdump, | ||
77 | TP_PROTO(void *data, size_t len), | ||
78 | TP_ARGS(data, len), | ||
79 | TP_STRUCT__entry( | ||
80 | __field(unsigned long, len) | ||
81 | __dynamic_array(u8, hdata, len) | ||
82 | ), | ||
83 | TP_fast_assign( | ||
84 | __entry->len = len; | ||
85 | memcpy(__get_dynamic_array(hdata), data, len); | ||
86 | ), | ||
87 | TP_printk("hexdump [length=%lu]", __entry->len) | ||
88 | ); | ||
89 | |||
76 | #ifdef CONFIG_BRCM_TRACING | 90 | #ifdef CONFIG_BRCM_TRACING |
77 | 91 | ||
78 | #undef TRACE_INCLUDE_PATH | 92 | #undef TRACE_INCLUDE_PATH |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 804473fc5c5e..62699203869d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <brcmu_wifi.h> | 26 | #include <brcmu_wifi.h> |
27 | #include "dhd.h" | 27 | #include "dhd.h" |
28 | #include "dhd_dbg.h" | 28 | #include "dhd_dbg.h" |
29 | #include "tracepoint.h" | ||
29 | #include "fwil_types.h" | 30 | #include "fwil_types.h" |
30 | #include "p2p.h" | 31 | #include "p2p.h" |
31 | #include "wl_cfg80211.h" | 32 | #include "wl_cfg80211.h" |
@@ -182,64 +183,6 @@ static struct ieee80211_channel __wl_5ghz_a_channels[] = { | |||
182 | CHAN5G(216, 0), | 183 | CHAN5G(216, 0), |
183 | }; | 184 | }; |
184 | 185 | ||
185 | static struct ieee80211_channel __wl_5ghz_n_channels[] = { | ||
186 | CHAN5G(32, 0), CHAN5G(34, 0), | ||
187 | CHAN5G(36, 0), CHAN5G(38, 0), | ||
188 | CHAN5G(40, 0), CHAN5G(42, 0), | ||
189 | CHAN5G(44, 0), CHAN5G(46, 0), | ||
190 | CHAN5G(48, 0), CHAN5G(50, 0), | ||
191 | CHAN5G(52, 0), CHAN5G(54, 0), | ||
192 | CHAN5G(56, 0), CHAN5G(58, 0), | ||
193 | CHAN5G(60, 0), CHAN5G(62, 0), | ||
194 | CHAN5G(64, 0), CHAN5G(66, 0), | ||
195 | CHAN5G(68, 0), CHAN5G(70, 0), | ||
196 | CHAN5G(72, 0), CHAN5G(74, 0), | ||
197 | CHAN5G(76, 0), CHAN5G(78, 0), | ||
198 | CHAN5G(80, 0), CHAN5G(82, 0), | ||
199 | CHAN5G(84, 0), CHAN5G(86, 0), | ||
200 | CHAN5G(88, 0), CHAN5G(90, 0), | ||
201 | CHAN5G(92, 0), CHAN5G(94, 0), | ||
202 | CHAN5G(96, 0), CHAN5G(98, 0), | ||
203 | CHAN5G(100, 0), CHAN5G(102, 0), | ||
204 | CHAN5G(104, 0), CHAN5G(106, 0), | ||
205 | CHAN5G(108, 0), CHAN5G(110, 0), | ||
206 | CHAN5G(112, 0), CHAN5G(114, 0), | ||
207 | CHAN5G(116, 0), CHAN5G(118, 0), | ||
208 | CHAN5G(120, 0), CHAN5G(122, 0), | ||
209 | CHAN5G(124, 0), CHAN5G(126, 0), | ||
210 | CHAN5G(128, 0), CHAN5G(130, 0), | ||
211 | CHAN5G(132, 0), CHAN5G(134, 0), | ||
212 | CHAN5G(136, 0), CHAN5G(138, 0), | ||
213 | CHAN5G(140, 0), CHAN5G(142, 0), | ||
214 | CHAN5G(144, 0), CHAN5G(145, 0), | ||
215 | CHAN5G(146, 0), CHAN5G(147, 0), | ||
216 | CHAN5G(148, 0), CHAN5G(149, 0), | ||
217 | CHAN5G(150, 0), CHAN5G(151, 0), | ||
218 | CHAN5G(152, 0), CHAN5G(153, 0), | ||
219 | CHAN5G(154, 0), CHAN5G(155, 0), | ||
220 | CHAN5G(156, 0), CHAN5G(157, 0), | ||
221 | CHAN5G(158, 0), CHAN5G(159, 0), | ||
222 | CHAN5G(160, 0), CHAN5G(161, 0), | ||
223 | CHAN5G(162, 0), CHAN5G(163, 0), | ||
224 | CHAN5G(164, 0), CHAN5G(165, 0), | ||
225 | CHAN5G(166, 0), CHAN5G(168, 0), | ||
226 | CHAN5G(170, 0), CHAN5G(172, 0), | ||
227 | CHAN5G(174, 0), CHAN5G(176, 0), | ||
228 | CHAN5G(178, 0), CHAN5G(180, 0), | ||
229 | CHAN5G(182, 0), CHAN5G(184, 0), | ||
230 | CHAN5G(186, 0), CHAN5G(188, 0), | ||
231 | CHAN5G(190, 0), CHAN5G(192, 0), | ||
232 | CHAN5G(194, 0), CHAN5G(196, 0), | ||
233 | CHAN5G(198, 0), CHAN5G(200, 0), | ||
234 | CHAN5G(202, 0), CHAN5G(204, 0), | ||
235 | CHAN5G(206, 0), CHAN5G(208, 0), | ||
236 | CHAN5G(210, 0), CHAN5G(212, 0), | ||
237 | CHAN5G(214, 0), CHAN5G(216, 0), | ||
238 | CHAN5G(218, 0), CHAN5G(220, 0), | ||
239 | CHAN5G(222, 0), CHAN5G(224, 0), | ||
240 | CHAN5G(226, 0), CHAN5G(228, 0), | ||
241 | }; | ||
242 | |||
243 | static struct ieee80211_supported_band __wl_band_2ghz = { | 186 | static struct ieee80211_supported_band __wl_band_2ghz = { |
244 | .band = IEEE80211_BAND_2GHZ, | 187 | .band = IEEE80211_BAND_2GHZ, |
245 | .channels = __wl_2ghz_channels, | 188 | .channels = __wl_2ghz_channels, |
@@ -256,12 +199,28 @@ static struct ieee80211_supported_band __wl_band_5ghz_a = { | |||
256 | .n_bitrates = wl_a_rates_size, | 199 | .n_bitrates = wl_a_rates_size, |
257 | }; | 200 | }; |
258 | 201 | ||
259 | static struct ieee80211_supported_band __wl_band_5ghz_n = { | 202 | /* This is to override regulatory domains defined in cfg80211 module (reg.c) |
260 | .band = IEEE80211_BAND_5GHZ, | 203 | * By default world regulatory domain defined in reg.c puts the flags |
261 | .channels = __wl_5ghz_n_channels, | 204 | * NL80211_RRF_PASSIVE_SCAN and NL80211_RRF_NO_IBSS for 5GHz channels (for |
262 | .n_channels = ARRAY_SIZE(__wl_5ghz_n_channels), | 205 | * 36..48 and 149..165). With respect to these flags, wpa_supplicant doesn't |
263 | .bitrates = wl_a_rates, | 206 | * start p2p operations on 5GHz channels. All the changes in world regulatory |
264 | .n_bitrates = wl_a_rates_size, | 207 | * domain are to be done here. |
208 | */ | ||
209 | static const struct ieee80211_regdomain brcmf_regdom = { | ||
210 | .n_reg_rules = 4, | ||
211 | .alpha2 = "99", | ||
212 | .reg_rules = { | ||
213 | /* IEEE 802.11b/g, channels 1..11 */ | ||
214 | REG_RULE(2412-10, 2472+10, 40, 6, 20, 0), | ||
215 | /* If any */ | ||
216 | /* IEEE 802.11 channel 14 - Only JP enables | ||
217 | * this and for 802.11b only | ||
218 | */ | ||
219 | REG_RULE(2484-10, 2484+10, 20, 6, 20, 0), | ||
220 | /* IEEE 802.11a, channel 36..64 */ | ||
221 | REG_RULE(5150-10, 5350+10, 40, 6, 20, 0), | ||
222 | /* IEEE 802.11a, channel 100..165 */ | ||
223 | REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), } | ||
265 | }; | 224 | }; |
266 | 225 | ||
267 | static const u32 __wl_cipher_suites[] = { | 226 | static const u32 __wl_cipher_suites[] = { |
@@ -523,17 +482,16 @@ static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy, | |||
523 | return ERR_PTR(-EOPNOTSUPP); | 482 | return ERR_PTR(-EOPNOTSUPP); |
524 | case NL80211_IFTYPE_P2P_CLIENT: | 483 | case NL80211_IFTYPE_P2P_CLIENT: |
525 | case NL80211_IFTYPE_P2P_GO: | 484 | case NL80211_IFTYPE_P2P_GO: |
485 | case NL80211_IFTYPE_P2P_DEVICE: | ||
526 | return brcmf_p2p_add_vif(wiphy, name, type, flags, params); | 486 | return brcmf_p2p_add_vif(wiphy, name, type, flags, params); |
527 | case NL80211_IFTYPE_UNSPECIFIED: | 487 | case NL80211_IFTYPE_UNSPECIFIED: |
528 | case NL80211_IFTYPE_P2P_DEVICE: | ||
529 | default: | 488 | default: |
530 | return ERR_PTR(-EINVAL); | 489 | return ERR_PTR(-EINVAL); |
531 | } | 490 | } |
532 | } | 491 | } |
533 | 492 | ||
534 | void brcmf_set_mpc(struct net_device *ndev, int mpc) | 493 | void brcmf_set_mpc(struct brcmf_if *ifp, int mpc) |
535 | { | 494 | { |
536 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
537 | s32 err = 0; | 495 | s32 err = 0; |
538 | 496 | ||
539 | if (check_vif_up(ifp->vif)) { | 497 | if (check_vif_up(ifp->vif)) { |
@@ -546,10 +504,9 @@ void brcmf_set_mpc(struct net_device *ndev, int mpc) | |||
546 | } | 504 | } |
547 | } | 505 | } |
548 | 506 | ||
549 | s32 | 507 | s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, |
550 | brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, | 508 | struct brcmf_if *ifp, bool aborted, |
551 | struct net_device *ndev, | 509 | bool fw_abort) |
552 | bool aborted, bool fw_abort) | ||
553 | { | 510 | { |
554 | struct brcmf_scan_params_le params_le; | 511 | struct brcmf_scan_params_le params_le; |
555 | struct cfg80211_scan_request *scan_request; | 512 | struct cfg80211_scan_request *scan_request; |
@@ -580,7 +537,7 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, | |||
580 | /* Scan is aborted by setting channel_list[0] to -1 */ | 537 | /* Scan is aborted by setting channel_list[0] to -1 */ |
581 | params_le.channel_list[0] = cpu_to_le16(-1); | 538 | params_le.channel_list[0] = cpu_to_le16(-1); |
582 | /* E-Scan (or anyother type) can be aborted by SCAN */ | 539 | /* E-Scan (or anyother type) can be aborted by SCAN */ |
583 | err = brcmf_fil_cmd_data_set(netdev_priv(ndev), BRCMF_C_SCAN, | 540 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN, |
584 | ¶ms_le, sizeof(params_le)); | 541 | ¶ms_le, sizeof(params_le)); |
585 | if (err) | 542 | if (err) |
586 | brcmf_err("Scan abort failed\n"); | 543 | brcmf_err("Scan abort failed\n"); |
@@ -594,12 +551,12 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, | |||
594 | cfg->sched_escan = false; | 551 | cfg->sched_escan = false; |
595 | if (!aborted) | 552 | if (!aborted) |
596 | cfg80211_sched_scan_results(cfg_to_wiphy(cfg)); | 553 | cfg80211_sched_scan_results(cfg_to_wiphy(cfg)); |
597 | brcmf_set_mpc(ndev, 1); | 554 | brcmf_set_mpc(ifp, 1); |
598 | } else if (scan_request) { | 555 | } else if (scan_request) { |
599 | brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n", | 556 | brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n", |
600 | aborted ? "Aborted" : "Done"); | 557 | aborted ? "Aborted" : "Done"); |
601 | cfg80211_scan_done(scan_request, aborted); | 558 | cfg80211_scan_done(scan_request, aborted); |
602 | brcmf_set_mpc(ndev, 1); | 559 | brcmf_set_mpc(ifp, 1); |
603 | } | 560 | } |
604 | if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) | 561 | if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) |
605 | brcmf_dbg(SCAN, "Scan complete, probably P2P scan\n"); | 562 | brcmf_dbg(SCAN, "Scan complete, probably P2P scan\n"); |
@@ -619,9 +576,9 @@ int brcmf_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
619 | 576 | ||
620 | if (ndev) { | 577 | if (ndev) { |
621 | if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status) && | 578 | if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status) && |
622 | cfg->escan_info.ndev == ndev) | 579 | cfg->escan_info.ifp == netdev_priv(ndev)) |
623 | brcmf_notify_escan_complete(cfg, ndev, true, | 580 | brcmf_notify_escan_complete(cfg, netdev_priv(ndev), |
624 | true); | 581 | true, true); |
625 | 582 | ||
626 | brcmf_fil_iovar_int_set(netdev_priv(ndev), "mpc", 1); | 583 | brcmf_fil_iovar_int_set(netdev_priv(ndev), "mpc", 1); |
627 | } | 584 | } |
@@ -637,9 +594,9 @@ int brcmf_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
637 | return -EOPNOTSUPP; | 594 | return -EOPNOTSUPP; |
638 | case NL80211_IFTYPE_P2P_CLIENT: | 595 | case NL80211_IFTYPE_P2P_CLIENT: |
639 | case NL80211_IFTYPE_P2P_GO: | 596 | case NL80211_IFTYPE_P2P_GO: |
597 | case NL80211_IFTYPE_P2P_DEVICE: | ||
640 | return brcmf_p2p_del_vif(wiphy, wdev); | 598 | return brcmf_p2p_del_vif(wiphy, wdev); |
641 | case NL80211_IFTYPE_UNSPECIFIED: | 599 | case NL80211_IFTYPE_UNSPECIFIED: |
642 | case NL80211_IFTYPE_P2P_DEVICE: | ||
643 | default: | 600 | default: |
644 | return -EINVAL; | 601 | return -EINVAL; |
645 | } | 602 | } |
@@ -803,7 +760,7 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le, | |||
803 | } | 760 | } |
804 | 761 | ||
805 | static s32 | 762 | static s32 |
806 | brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, | 763 | brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp, |
807 | struct cfg80211_scan_request *request, u16 action) | 764 | struct cfg80211_scan_request *request, u16 action) |
808 | { | 765 | { |
809 | s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE + | 766 | s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE + |
@@ -832,8 +789,7 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, | |||
832 | params->action = cpu_to_le16(action); | 789 | params->action = cpu_to_le16(action); |
833 | params->sync_id = cpu_to_le16(0x1234); | 790 | params->sync_id = cpu_to_le16(0x1234); |
834 | 791 | ||
835 | err = brcmf_fil_iovar_data_set(netdev_priv(ndev), "escan", | 792 | err = brcmf_fil_iovar_data_set(ifp, "escan", params, params_size); |
836 | params, params_size); | ||
837 | if (err) { | 793 | if (err) { |
838 | if (err == -EBUSY) | 794 | if (err == -EBUSY) |
839 | brcmf_dbg(INFO, "system busy : escan canceled\n"); | 795 | brcmf_dbg(INFO, "system busy : escan canceled\n"); |
@@ -848,7 +804,7 @@ exit: | |||
848 | 804 | ||
849 | static s32 | 805 | static s32 |
850 | brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy, | 806 | brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy, |
851 | struct net_device *ndev, struct cfg80211_scan_request *request) | 807 | struct brcmf_if *ifp, struct cfg80211_scan_request *request) |
852 | { | 808 | { |
853 | s32 err; | 809 | s32 err; |
854 | u32 passive_scan; | 810 | u32 passive_scan; |
@@ -856,35 +812,35 @@ brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy, | |||
856 | struct escan_info *escan = &cfg->escan_info; | 812 | struct escan_info *escan = &cfg->escan_info; |
857 | 813 | ||
858 | brcmf_dbg(SCAN, "Enter\n"); | 814 | brcmf_dbg(SCAN, "Enter\n"); |
859 | escan->ndev = ndev; | 815 | escan->ifp = ifp; |
860 | escan->wiphy = wiphy; | 816 | escan->wiphy = wiphy; |
861 | escan->escan_state = WL_ESCAN_STATE_SCANNING; | 817 | escan->escan_state = WL_ESCAN_STATE_SCANNING; |
862 | passive_scan = cfg->active_scan ? 0 : 1; | 818 | passive_scan = cfg->active_scan ? 0 : 1; |
863 | err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_SET_PASSIVE_SCAN, | 819 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN, |
864 | passive_scan); | 820 | passive_scan); |
865 | if (err) { | 821 | if (err) { |
866 | brcmf_err("error (%d)\n", err); | 822 | brcmf_err("error (%d)\n", err); |
867 | return err; | 823 | return err; |
868 | } | 824 | } |
869 | brcmf_set_mpc(ndev, 0); | 825 | brcmf_set_mpc(ifp, 0); |
870 | results = (struct brcmf_scan_results *)cfg->escan_info.escan_buf; | 826 | results = (struct brcmf_scan_results *)cfg->escan_info.escan_buf; |
871 | results->version = 0; | 827 | results->version = 0; |
872 | results->count = 0; | 828 | results->count = 0; |
873 | results->buflen = WL_ESCAN_RESULTS_FIXED_SIZE; | 829 | results->buflen = WL_ESCAN_RESULTS_FIXED_SIZE; |
874 | 830 | ||
875 | err = escan->run(cfg, ndev, request, WL_ESCAN_ACTION_START); | 831 | err = escan->run(cfg, ifp, request, WL_ESCAN_ACTION_START); |
876 | if (err) | 832 | if (err) |
877 | brcmf_set_mpc(ndev, 1); | 833 | brcmf_set_mpc(ifp, 1); |
878 | return err; | 834 | return err; |
879 | } | 835 | } |
880 | 836 | ||
881 | static s32 | 837 | static s32 |
882 | brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, | 838 | brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif, |
883 | struct cfg80211_scan_request *request, | 839 | struct cfg80211_scan_request *request, |
884 | struct cfg80211_ssid *this_ssid) | 840 | struct cfg80211_ssid *this_ssid) |
885 | { | 841 | { |
886 | struct brcmf_if *ifp = netdev_priv(ndev); | 842 | struct brcmf_if *ifp = vif->ifp; |
887 | struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); | 843 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
888 | struct cfg80211_ssid *ssids; | 844 | struct cfg80211_ssid *ssids; |
889 | struct brcmf_cfg80211_scan_req *sr = &cfg->scan_req_int; | 845 | struct brcmf_cfg80211_scan_req *sr = &cfg->scan_req_int; |
890 | u32 passive_scan; | 846 | u32 passive_scan; |
@@ -910,10 +866,8 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, | |||
910 | } | 866 | } |
911 | 867 | ||
912 | /* If scan req comes for p2p0, send it over primary I/F */ | 868 | /* If scan req comes for p2p0, send it over primary I/F */ |
913 | if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif) { | 869 | if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif) |
914 | ifp = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; | 870 | vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif; |
915 | ndev = ifp->ndev; | ||
916 | } | ||
917 | 871 | ||
918 | /* Arm scan timeout timer */ | 872 | /* Arm scan timeout timer */ |
919 | mod_timer(&cfg->escan_timeout, jiffies + | 873 | mod_timer(&cfg->escan_timeout, jiffies + |
@@ -934,11 +888,11 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, | |||
934 | set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); | 888 | set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); |
935 | if (escan_req) { | 889 | if (escan_req) { |
936 | cfg->escan_info.run = brcmf_run_escan; | 890 | cfg->escan_info.run = brcmf_run_escan; |
937 | err = brcmf_p2p_scan_prep(wiphy, request, ifp->vif); | 891 | err = brcmf_p2p_scan_prep(wiphy, request, vif); |
938 | if (err) | 892 | if (err) |
939 | goto scan_out; | 893 | goto scan_out; |
940 | 894 | ||
941 | err = brcmf_do_escan(cfg, wiphy, ndev, request); | 895 | err = brcmf_do_escan(cfg, wiphy, vif->ifp, request); |
942 | if (err) | 896 | if (err) |
943 | goto scan_out; | 897 | goto scan_out; |
944 | } else { | 898 | } else { |
@@ -962,7 +916,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, | |||
962 | brcmf_err("WLC_SET_PASSIVE_SCAN error (%d)\n", err); | 916 | brcmf_err("WLC_SET_PASSIVE_SCAN error (%d)\n", err); |
963 | goto scan_out; | 917 | goto scan_out; |
964 | } | 918 | } |
965 | brcmf_set_mpc(ndev, 0); | 919 | brcmf_set_mpc(ifp, 0); |
966 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN, | 920 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN, |
967 | &sr->ssid_le, sizeof(sr->ssid_le)); | 921 | &sr->ssid_le, sizeof(sr->ssid_le)); |
968 | if (err) { | 922 | if (err) { |
@@ -972,7 +926,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, | |||
972 | else | 926 | else |
973 | brcmf_err("WLC_SCAN error (%d)\n", err); | 927 | brcmf_err("WLC_SCAN error (%d)\n", err); |
974 | 928 | ||
975 | brcmf_set_mpc(ndev, 1); | 929 | brcmf_set_mpc(ifp, 1); |
976 | goto scan_out; | 930 | goto scan_out; |
977 | } | 931 | } |
978 | } | 932 | } |
@@ -990,16 +944,15 @@ scan_out: | |||
990 | static s32 | 944 | static s32 |
991 | brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) | 945 | brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) |
992 | { | 946 | { |
993 | struct net_device *ndev = request->wdev->netdev; | 947 | struct brcmf_cfg80211_vif *vif; |
994 | s32 err = 0; | 948 | s32 err = 0; |
995 | 949 | ||
996 | brcmf_dbg(TRACE, "Enter\n"); | 950 | brcmf_dbg(TRACE, "Enter\n"); |
997 | 951 | vif = container_of(request->wdev, struct brcmf_cfg80211_vif, wdev); | |
998 | if (!check_vif_up(container_of(request->wdev, | 952 | if (!check_vif_up(vif)) |
999 | struct brcmf_cfg80211_vif, wdev))) | ||
1000 | return -EIO; | 953 | return -EIO; |
1001 | 954 | ||
1002 | err = brcmf_cfg80211_escan(wiphy, ndev, request, NULL); | 955 | err = brcmf_cfg80211_escan(wiphy, vif, request, NULL); |
1003 | 956 | ||
1004 | if (err) | 957 | if (err) |
1005 | brcmf_err("scan error (%d)\n", err); | 958 | brcmf_err("scan error (%d)\n", err); |
@@ -1891,8 +1844,10 @@ static s32 | |||
1891 | brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, | 1844 | brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, |
1892 | u8 key_idx, const u8 *mac_addr, struct key_params *params) | 1845 | u8 key_idx, const u8 *mac_addr, struct key_params *params) |
1893 | { | 1846 | { |
1847 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
1894 | struct brcmf_wsec_key key; | 1848 | struct brcmf_wsec_key key; |
1895 | s32 err = 0; | 1849 | s32 err = 0; |
1850 | u8 keybuf[8]; | ||
1896 | 1851 | ||
1897 | memset(&key, 0, sizeof(key)); | 1852 | memset(&key, 0, sizeof(key)); |
1898 | key.index = (u32) key_idx; | 1853 | key.index = (u32) key_idx; |
@@ -1916,8 +1871,9 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, | |||
1916 | brcmf_dbg(CONN, "Setting the key index %d\n", key.index); | 1871 | brcmf_dbg(CONN, "Setting the key index %d\n", key.index); |
1917 | memcpy(key.data, params->key, key.len); | 1872 | memcpy(key.data, params->key, key.len); |
1918 | 1873 | ||
1919 | if (params->cipher == WLAN_CIPHER_SUITE_TKIP) { | 1874 | if ((ifp->vif->mode != WL_MODE_AP) && |
1920 | u8 keybuf[8]; | 1875 | (params->cipher == WLAN_CIPHER_SUITE_TKIP)) { |
1876 | brcmf_dbg(CONN, "Swapping RX/TX MIC key\n"); | ||
1921 | memcpy(keybuf, &key.data[24], sizeof(keybuf)); | 1877 | memcpy(keybuf, &key.data[24], sizeof(keybuf)); |
1922 | memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); | 1878 | memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); |
1923 | memcpy(&key.data[16], keybuf, sizeof(keybuf)); | 1879 | memcpy(&key.data[16], keybuf, sizeof(keybuf)); |
@@ -2013,7 +1969,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
2013 | break; | 1969 | break; |
2014 | case WLAN_CIPHER_SUITE_TKIP: | 1970 | case WLAN_CIPHER_SUITE_TKIP: |
2015 | if (ifp->vif->mode != WL_MODE_AP) { | 1971 | if (ifp->vif->mode != WL_MODE_AP) { |
2016 | brcmf_dbg(CONN, "Swapping key\n"); | 1972 | brcmf_dbg(CONN, "Swapping RX/TX MIC key\n"); |
2017 | memcpy(keybuf, &key.data[24], sizeof(keybuf)); | 1973 | memcpy(keybuf, &key.data[24], sizeof(keybuf)); |
2018 | memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); | 1974 | memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); |
2019 | memcpy(&key.data[16], keybuf, sizeof(keybuf)); | 1975 | memcpy(&key.data[16], keybuf, sizeof(keybuf)); |
@@ -2118,8 +2074,7 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, | |||
2118 | err = -EAGAIN; | 2074 | err = -EAGAIN; |
2119 | goto done; | 2075 | goto done; |
2120 | } | 2076 | } |
2121 | switch (wsec & ~SES_OW_ENABLED) { | 2077 | if (wsec & WEP_ENABLED) { |
2122 | case WEP_ENABLED: | ||
2123 | sec = &profile->sec; | 2078 | sec = &profile->sec; |
2124 | if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) { | 2079 | if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) { |
2125 | params.cipher = WLAN_CIPHER_SUITE_WEP40; | 2080 | params.cipher = WLAN_CIPHER_SUITE_WEP40; |
@@ -2128,16 +2083,13 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, | |||
2128 | params.cipher = WLAN_CIPHER_SUITE_WEP104; | 2083 | params.cipher = WLAN_CIPHER_SUITE_WEP104; |
2129 | brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n"); | 2084 | brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n"); |
2130 | } | 2085 | } |
2131 | break; | 2086 | } else if (wsec & TKIP_ENABLED) { |
2132 | case TKIP_ENABLED: | ||
2133 | params.cipher = WLAN_CIPHER_SUITE_TKIP; | 2087 | params.cipher = WLAN_CIPHER_SUITE_TKIP; |
2134 | brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n"); | 2088 | brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n"); |
2135 | break; | 2089 | } else if (wsec & AES_ENABLED) { |
2136 | case AES_ENABLED: | ||
2137 | params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; | 2090 | params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; |
2138 | brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n"); | 2091 | brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n"); |
2139 | break; | 2092 | } else { |
2140 | default: | ||
2141 | brcmf_err("Invalid algo (0x%x)\n", wsec); | 2093 | brcmf_err("Invalid algo (0x%x)\n", wsec); |
2142 | err = -EINVAL; | 2094 | err = -EINVAL; |
2143 | goto done; | 2095 | goto done; |
@@ -2511,7 +2463,7 @@ void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg) | |||
2511 | set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status); | 2463 | set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status); |
2512 | if (cfg->scan_request) { | 2464 | if (cfg->scan_request) { |
2513 | escan->escan_state = WL_ESCAN_STATE_IDLE; | 2465 | escan->escan_state = WL_ESCAN_STATE_IDLE; |
2514 | brcmf_notify_escan_complete(cfg, escan->ndev, true, true); | 2466 | brcmf_notify_escan_complete(cfg, escan->ifp, true, true); |
2515 | } | 2467 | } |
2516 | clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); | 2468 | clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); |
2517 | clear_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status); | 2469 | clear_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status); |
@@ -2523,7 +2475,7 @@ static void brcmf_cfg80211_escan_timeout_worker(struct work_struct *work) | |||
2523 | container_of(work, struct brcmf_cfg80211_info, | 2475 | container_of(work, struct brcmf_cfg80211_info, |
2524 | escan_timeout_work); | 2476 | escan_timeout_work); |
2525 | 2477 | ||
2526 | brcmf_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true); | 2478 | brcmf_notify_escan_complete(cfg, cfg->escan_info.ifp, true, true); |
2527 | } | 2479 | } |
2528 | 2480 | ||
2529 | static void brcmf_escan_timeout(unsigned long data) | 2481 | static void brcmf_escan_timeout(unsigned long data) |
@@ -2574,7 +2526,6 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, | |||
2574 | const struct brcmf_event_msg *e, void *data) | 2526 | const struct brcmf_event_msg *e, void *data) |
2575 | { | 2527 | { |
2576 | struct brcmf_cfg80211_info *cfg = ifp->drvr->config; | 2528 | struct brcmf_cfg80211_info *cfg = ifp->drvr->config; |
2577 | struct net_device *ndev = ifp->ndev; | ||
2578 | s32 status; | 2529 | s32 status; |
2579 | s32 err = 0; | 2530 | s32 err = 0; |
2580 | struct brcmf_escan_result_le *escan_result_le; | 2531 | struct brcmf_escan_result_le *escan_result_le; |
@@ -2587,9 +2538,8 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, | |||
2587 | 2538 | ||
2588 | status = e->status; | 2539 | status = e->status; |
2589 | 2540 | ||
2590 | if (!ndev || !test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { | 2541 | if (!test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { |
2591 | brcmf_err("scan not ready ndev %p drv_status %x\n", ndev, | 2542 | brcmf_err("scan not ready, bssidx=%d\n", ifp->bssidx); |
2592 | !test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)); | ||
2593 | return -EPERM; | 2543 | return -EPERM; |
2594 | } | 2544 | } |
2595 | 2545 | ||
@@ -2660,7 +2610,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, | |||
2660 | cfg->escan_info.escan_buf; | 2610 | cfg->escan_info.escan_buf; |
2661 | brcmf_inform_bss(cfg); | 2611 | brcmf_inform_bss(cfg); |
2662 | aborted = status != BRCMF_E_STATUS_SUCCESS; | 2612 | aborted = status != BRCMF_E_STATUS_SUCCESS; |
2663 | brcmf_notify_escan_complete(cfg, ndev, aborted, | 2613 | brcmf_notify_escan_complete(cfg, ifp, aborted, |
2664 | false); | 2614 | false); |
2665 | } else | 2615 | } else |
2666 | brcmf_dbg(SCAN, "Ignored scan complete result 0x%x\n", | 2616 | brcmf_dbg(SCAN, "Ignored scan complete result 0x%x\n", |
@@ -2738,7 +2688,7 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, | |||
2738 | brcmf_abort_scanning(cfg); | 2688 | brcmf_abort_scanning(cfg); |
2739 | 2689 | ||
2740 | /* Turn off watchdog timer */ | 2690 | /* Turn off watchdog timer */ |
2741 | brcmf_set_mpc(ndev, 1); | 2691 | brcmf_set_mpc(netdev_priv(ndev), 1); |
2742 | 2692 | ||
2743 | exit: | 2693 | exit: |
2744 | brcmf_dbg(TRACE, "Exit\n"); | 2694 | brcmf_dbg(TRACE, "Exit\n"); |
@@ -2896,7 +2846,6 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp, | |||
2896 | const struct brcmf_event_msg *e, void *data) | 2846 | const struct brcmf_event_msg *e, void *data) |
2897 | { | 2847 | { |
2898 | struct brcmf_cfg80211_info *cfg = ifp->drvr->config; | 2848 | struct brcmf_cfg80211_info *cfg = ifp->drvr->config; |
2899 | struct net_device *ndev = ifp->ndev; | ||
2900 | struct brcmf_pno_net_info_le *netinfo, *netinfo_start; | 2849 | struct brcmf_pno_net_info_le *netinfo, *netinfo_start; |
2901 | struct cfg80211_scan_request *request = NULL; | 2850 | struct cfg80211_scan_request *request = NULL; |
2902 | struct cfg80211_ssid *ssid = NULL; | 2851 | struct cfg80211_ssid *ssid = NULL; |
@@ -2980,7 +2929,7 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp, | |||
2980 | } | 2929 | } |
2981 | 2930 | ||
2982 | set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); | 2931 | set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); |
2983 | err = brcmf_do_escan(cfg, wiphy, ndev, request); | 2932 | err = brcmf_do_escan(cfg, wiphy, ifp, request); |
2984 | if (err) { | 2933 | if (err) { |
2985 | clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); | 2934 | clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); |
2986 | goto out_err; | 2935 | goto out_err; |
@@ -3137,7 +3086,7 @@ static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy, | |||
3137 | brcmf_dbg(SCAN, "enter\n"); | 3086 | brcmf_dbg(SCAN, "enter\n"); |
3138 | brcmf_dev_pno_clean(ndev); | 3087 | brcmf_dev_pno_clean(ndev); |
3139 | if (cfg->sched_escan) | 3088 | if (cfg->sched_escan) |
3140 | brcmf_notify_escan_complete(cfg, ndev, true, true); | 3089 | brcmf_notify_escan_complete(cfg, netdev_priv(ndev), true, true); |
3141 | return 0; | 3090 | return 0; |
3142 | } | 3091 | } |
3143 | 3092 | ||
@@ -3709,7 +3658,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, | |||
3709 | ssid_le.SSID_len = cpu_to_le32((u32)settings->ssid_len); | 3658 | ssid_le.SSID_len = cpu_to_le32((u32)settings->ssid_len); |
3710 | } | 3659 | } |
3711 | 3660 | ||
3712 | brcmf_set_mpc(ndev, 0); | 3661 | brcmf_set_mpc(ifp, 0); |
3713 | 3662 | ||
3714 | /* find the RSN_IE */ | 3663 | /* find the RSN_IE */ |
3715 | rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail, | 3664 | rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail, |
@@ -3817,15 +3766,16 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, | |||
3817 | 3766 | ||
3818 | exit: | 3767 | exit: |
3819 | if (err) | 3768 | if (err) |
3820 | brcmf_set_mpc(ndev, 1); | 3769 | brcmf_set_mpc(ifp, 1); |
3821 | return err; | 3770 | return err; |
3822 | } | 3771 | } |
3823 | 3772 | ||
3824 | static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) | 3773 | static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) |
3825 | { | 3774 | { |
3826 | struct brcmf_if *ifp = netdev_priv(ndev); | 3775 | struct brcmf_if *ifp = netdev_priv(ndev); |
3827 | s32 err = -EPERM; | 3776 | s32 err; |
3828 | struct brcmf_fil_bss_enable_le bss_enable; | 3777 | struct brcmf_fil_bss_enable_le bss_enable; |
3778 | struct brcmf_join_params join_params; | ||
3829 | 3779 | ||
3830 | brcmf_dbg(TRACE, "Enter\n"); | 3780 | brcmf_dbg(TRACE, "Enter\n"); |
3831 | 3781 | ||
@@ -3833,16 +3783,21 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) | |||
3833 | /* Due to most likely deauths outstanding we sleep */ | 3783 | /* Due to most likely deauths outstanding we sleep */ |
3834 | /* first to make sure they get processed by fw. */ | 3784 | /* first to make sure they get processed by fw. */ |
3835 | msleep(400); | 3785 | msleep(400); |
3836 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0); | 3786 | |
3837 | if (err < 0) { | 3787 | memset(&join_params, 0, sizeof(join_params)); |
3838 | brcmf_err("setting AP mode failed %d\n", err); | 3788 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID, |
3839 | goto exit; | 3789 | &join_params, sizeof(join_params)); |
3840 | } | 3790 | if (err < 0) |
3791 | brcmf_err("SET SSID error (%d)\n", err); | ||
3841 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0); | 3792 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0); |
3842 | if (err < 0) { | 3793 | if (err < 0) |
3843 | brcmf_err("BRCMF_C_UP error %d\n", err); | 3794 | brcmf_err("BRCMF_C_UP error %d\n", err); |
3844 | goto exit; | 3795 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0); |
3845 | } | 3796 | if (err < 0) |
3797 | brcmf_err("setting AP mode failed %d\n", err); | ||
3798 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 0); | ||
3799 | if (err < 0) | ||
3800 | brcmf_err("setting INFRA mode failed %d\n", err); | ||
3846 | } else { | 3801 | } else { |
3847 | bss_enable.bsscfg_idx = cpu_to_le32(ifp->bssidx); | 3802 | bss_enable.bsscfg_idx = cpu_to_le32(ifp->bssidx); |
3848 | bss_enable.enable = cpu_to_le32(0); | 3803 | bss_enable.enable = cpu_to_le32(0); |
@@ -3851,11 +3806,10 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) | |||
3851 | if (err < 0) | 3806 | if (err < 0) |
3852 | brcmf_err("bss_enable config failed %d\n", err); | 3807 | brcmf_err("bss_enable config failed %d\n", err); |
3853 | } | 3808 | } |
3854 | brcmf_set_mpc(ndev, 1); | 3809 | brcmf_set_mpc(ifp, 1); |
3855 | set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state); | 3810 | set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state); |
3856 | clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state); | 3811 | clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state); |
3857 | 3812 | ||
3858 | exit: | ||
3859 | return err; | 3813 | return err; |
3860 | } | 3814 | } |
3861 | 3815 | ||
@@ -3909,13 +3863,13 @@ brcmf_cfg80211_mgmt_frame_register(struct wiphy *wiphy, | |||
3909 | struct wireless_dev *wdev, | 3863 | struct wireless_dev *wdev, |
3910 | u16 frame_type, bool reg) | 3864 | u16 frame_type, bool reg) |
3911 | { | 3865 | { |
3912 | struct brcmf_if *ifp = netdev_priv(wdev->netdev); | 3866 | struct brcmf_cfg80211_vif *vif; |
3913 | struct brcmf_cfg80211_vif *vif = ifp->vif; | ||
3914 | u16 mgmt_type; | 3867 | u16 mgmt_type; |
3915 | 3868 | ||
3916 | brcmf_dbg(TRACE, "Enter, frame_type %04x, reg=%d\n", frame_type, reg); | 3869 | brcmf_dbg(TRACE, "Enter, frame_type %04x, reg=%d\n", frame_type, reg); |
3917 | 3870 | ||
3918 | mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4; | 3871 | mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4; |
3872 | vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev); | ||
3919 | if (reg) | 3873 | if (reg) |
3920 | vif->mgmt_rx_reg |= BIT(mgmt_type); | 3874 | vif->mgmt_rx_reg |= BIT(mgmt_type); |
3921 | else | 3875 | else |
@@ -3931,7 +3885,6 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
3931 | { | 3885 | { |
3932 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 3886 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
3933 | const struct ieee80211_mgmt *mgmt; | 3887 | const struct ieee80211_mgmt *mgmt; |
3934 | struct brcmf_if *ifp; | ||
3935 | struct brcmf_cfg80211_vif *vif; | 3888 | struct brcmf_cfg80211_vif *vif; |
3936 | s32 err = 0; | 3889 | s32 err = 0; |
3937 | s32 ie_offset; | 3890 | s32 ie_offset; |
@@ -3967,8 +3920,7 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
3967 | ie_offset = DOT11_MGMT_HDR_LEN + | 3920 | ie_offset = DOT11_MGMT_HDR_LEN + |
3968 | DOT11_BCN_PRB_FIXED_LEN; | 3921 | DOT11_BCN_PRB_FIXED_LEN; |
3969 | ie_len = len - ie_offset; | 3922 | ie_len = len - ie_offset; |
3970 | ifp = netdev_priv(wdev->netdev); | 3923 | vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev); |
3971 | vif = ifp->vif; | ||
3972 | if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif) | 3924 | if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif) |
3973 | vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif; | 3925 | vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif; |
3974 | err = brcmf_vif_set_mgmt_ie(vif, | 3926 | err = brcmf_vif_set_mgmt_ie(vif, |
@@ -4003,7 +3955,7 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
4003 | *cookie, le16_to_cpu(action_frame->len), | 3955 | *cookie, le16_to_cpu(action_frame->len), |
4004 | chan->center_freq); | 3956 | chan->center_freq); |
4005 | 3957 | ||
4006 | ack = brcmf_p2p_send_action_frame(cfg, wdev->netdev, | 3958 | ack = brcmf_p2p_send_action_frame(cfg, cfg_to_ndev(cfg), |
4007 | af_params); | 3959 | af_params); |
4008 | 3960 | ||
4009 | cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack, | 3961 | cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack, |
@@ -4075,6 +4027,8 @@ static struct cfg80211_ops wl_cfg80211_ops = { | |||
4075 | .mgmt_tx = brcmf_cfg80211_mgmt_tx, | 4027 | .mgmt_tx = brcmf_cfg80211_mgmt_tx, |
4076 | .remain_on_channel = brcmf_p2p_remain_on_channel, | 4028 | .remain_on_channel = brcmf_p2p_remain_on_channel, |
4077 | .cancel_remain_on_channel = brcmf_cfg80211_cancel_remain_on_channel, | 4029 | .cancel_remain_on_channel = brcmf_cfg80211_cancel_remain_on_channel, |
4030 | .start_p2p_device = brcmf_p2p_start_device, | ||
4031 | .stop_p2p_device = brcmf_p2p_stop_device, | ||
4078 | #ifdef CONFIG_NL80211_TESTMODE | 4032 | #ifdef CONFIG_NL80211_TESTMODE |
4079 | .testmode_cmd = brcmf_cfg80211_testmode | 4033 | .testmode_cmd = brcmf_cfg80211_testmode |
4080 | #endif | 4034 | #endif |
@@ -4162,6 +4116,11 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = { | |||
4162 | BIT(IEEE80211_STYPE_AUTH >> 4) | | 4116 | BIT(IEEE80211_STYPE_AUTH >> 4) | |
4163 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | | 4117 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | |
4164 | BIT(IEEE80211_STYPE_ACTION >> 4) | 4118 | BIT(IEEE80211_STYPE_ACTION >> 4) |
4119 | }, | ||
4120 | [NL80211_IFTYPE_P2P_DEVICE] = { | ||
4121 | .tx = 0xffff, | ||
4122 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
4123 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
4165 | } | 4124 | } |
4166 | }; | 4125 | }; |
4167 | 4126 | ||
@@ -4188,13 +4147,6 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev) | |||
4188 | wiphy->iface_combinations = brcmf_iface_combos; | 4147 | wiphy->iface_combinations = brcmf_iface_combos; |
4189 | wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos); | 4148 | wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos); |
4190 | wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; | 4149 | wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; |
4191 | wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set | ||
4192 | * it as 11a by default. | ||
4193 | * This will be updated with | ||
4194 | * 11n phy tables in | ||
4195 | * "ifconfig up" | ||
4196 | * if phy has 11n capability | ||
4197 | */ | ||
4198 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 4150 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
4199 | wiphy->cipher_suites = __wl_cipher_suites; | 4151 | wiphy->cipher_suites = __wl_cipher_suites; |
4200 | wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); | 4152 | wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); |
@@ -4204,6 +4156,9 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev) | |||
4204 | wiphy->mgmt_stypes = brcmf_txrx_stypes; | 4156 | wiphy->mgmt_stypes = brcmf_txrx_stypes; |
4205 | wiphy->max_remain_on_channel_duration = 5000; | 4157 | wiphy->max_remain_on_channel_duration = 5000; |
4206 | brcmf_wiphy_pno_params(wiphy); | 4158 | brcmf_wiphy_pno_params(wiphy); |
4159 | brcmf_dbg(INFO, "Registering custom regulatory\n"); | ||
4160 | wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; | ||
4161 | wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom); | ||
4207 | err = wiphy_register(wiphy); | 4162 | err = wiphy_register(wiphy); |
4208 | if (err < 0) { | 4163 | if (err < 0) { |
4209 | brcmf_err("Could not register wiphy device (%d)\n", err); | 4164 | brcmf_err("Could not register wiphy device (%d)\n", err); |
@@ -4622,9 +4577,11 @@ static s32 brcmf_notify_vif_event(struct brcmf_if *ifp, | |||
4622 | 4577 | ||
4623 | ifp->vif = vif; | 4578 | ifp->vif = vif; |
4624 | vif->ifp = ifp; | 4579 | vif->ifp = ifp; |
4625 | vif->wdev.netdev = ifp->ndev; | 4580 | if (ifp->ndev) { |
4626 | ifp->ndev->ieee80211_ptr = &vif->wdev; | 4581 | vif->wdev.netdev = ifp->ndev; |
4627 | SET_NETDEV_DEV(ifp->ndev, wiphy_dev(cfg->wiphy)); | 4582 | ifp->ndev->ieee80211_ptr = &vif->wdev; |
4583 | SET_NETDEV_DEV(ifp->ndev, wiphy_dev(cfg->wiphy)); | ||
4584 | } | ||
4628 | mutex_unlock(&event->vif_event_lock); | 4585 | mutex_unlock(&event->vif_event_lock); |
4629 | wake_up(&event->vif_wq); | 4586 | wake_up(&event->vif_wq); |
4630 | return 0; | 4587 | return 0; |
@@ -4927,34 +4884,248 @@ dongle_scantime_out: | |||
4927 | return err; | 4884 | return err; |
4928 | } | 4885 | } |
4929 | 4886 | ||
4930 | static s32 wl_update_wiphybands(struct brcmf_cfg80211_info *cfg) | 4887 | |
4888 | static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap) | ||
4889 | { | ||
4890 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); | ||
4891 | struct ieee80211_channel *band_chan_arr; | ||
4892 | struct brcmf_chanspec_list *list; | ||
4893 | s32 err; | ||
4894 | u8 *pbuf; | ||
4895 | u32 i, j; | ||
4896 | u32 total; | ||
4897 | u16 chanspec; | ||
4898 | enum ieee80211_band band; | ||
4899 | u32 channel; | ||
4900 | u32 *n_cnt; | ||
4901 | bool ht40_allowed; | ||
4902 | u32 index; | ||
4903 | u32 ht40_flag; | ||
4904 | bool update; | ||
4905 | u32 array_size; | ||
4906 | |||
4907 | pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL); | ||
4908 | |||
4909 | if (pbuf == NULL) | ||
4910 | return -ENOMEM; | ||
4911 | |||
4912 | list = (struct brcmf_chanspec_list *)pbuf; | ||
4913 | |||
4914 | err = brcmf_fil_iovar_data_get(ifp, "chanspecs", pbuf, | ||
4915 | BRCMF_DCMD_MEDLEN); | ||
4916 | if (err) { | ||
4917 | brcmf_err("get chanspecs error (%d)\n", err); | ||
4918 | goto exit; | ||
4919 | } | ||
4920 | |||
4921 | __wl_band_2ghz.n_channels = 0; | ||
4922 | __wl_band_5ghz_a.n_channels = 0; | ||
4923 | |||
4924 | total = le32_to_cpu(list->count); | ||
4925 | for (i = 0; i < total; i++) { | ||
4926 | chanspec = (u16)le32_to_cpu(list->element[i]); | ||
4927 | channel = CHSPEC_CHANNEL(chanspec); | ||
4928 | |||
4929 | if (CHSPEC_IS40(chanspec)) { | ||
4930 | if (CHSPEC_SB_UPPER(chanspec)) | ||
4931 | channel += CH_10MHZ_APART; | ||
4932 | else | ||
4933 | channel -= CH_10MHZ_APART; | ||
4934 | } else if (CHSPEC_IS80(chanspec)) { | ||
4935 | brcmf_dbg(INFO, "HT80 center channel : %d\n", | ||
4936 | channel); | ||
4937 | continue; | ||
4938 | } | ||
4939 | if (CHSPEC_IS2G(chanspec) && (channel >= CH_MIN_2G_CHANNEL) && | ||
4940 | (channel <= CH_MAX_2G_CHANNEL)) { | ||
4941 | band_chan_arr = __wl_2ghz_channels; | ||
4942 | array_size = ARRAY_SIZE(__wl_2ghz_channels); | ||
4943 | n_cnt = &__wl_band_2ghz.n_channels; | ||
4944 | band = IEEE80211_BAND_2GHZ; | ||
4945 | ht40_allowed = (bw_cap == WLC_N_BW_40ALL); | ||
4946 | } else if (CHSPEC_IS5G(chanspec) && | ||
4947 | channel >= CH_MIN_5G_CHANNEL) { | ||
4948 | band_chan_arr = __wl_5ghz_a_channels; | ||
4949 | array_size = ARRAY_SIZE(__wl_5ghz_a_channels); | ||
4950 | n_cnt = &__wl_band_5ghz_a.n_channels; | ||
4951 | band = IEEE80211_BAND_5GHZ; | ||
4952 | ht40_allowed = !(bw_cap == WLC_N_BW_20ALL); | ||
4953 | } else { | ||
4954 | brcmf_err("Invalid channel Sepc. 0x%x.\n", chanspec); | ||
4955 | continue; | ||
4956 | } | ||
4957 | if (!ht40_allowed && CHSPEC_IS40(chanspec)) | ||
4958 | continue; | ||
4959 | update = false; | ||
4960 | for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) { | ||
4961 | if (band_chan_arr[j].hw_value == channel) { | ||
4962 | update = true; | ||
4963 | break; | ||
4964 | } | ||
4965 | } | ||
4966 | if (update) | ||
4967 | index = j; | ||
4968 | else | ||
4969 | index = *n_cnt; | ||
4970 | if (index < array_size) { | ||
4971 | band_chan_arr[index].center_freq = | ||
4972 | ieee80211_channel_to_frequency(channel, band); | ||
4973 | band_chan_arr[index].hw_value = channel; | ||
4974 | |||
4975 | if (CHSPEC_IS40(chanspec) && ht40_allowed) { | ||
4976 | /* assuming the order is HT20, HT40 Upper, | ||
4977 | * HT40 lower from chanspecs | ||
4978 | */ | ||
4979 | ht40_flag = band_chan_arr[index].flags & | ||
4980 | IEEE80211_CHAN_NO_HT40; | ||
4981 | if (CHSPEC_SB_UPPER(chanspec)) { | ||
4982 | if (ht40_flag == IEEE80211_CHAN_NO_HT40) | ||
4983 | band_chan_arr[index].flags &= | ||
4984 | ~IEEE80211_CHAN_NO_HT40; | ||
4985 | band_chan_arr[index].flags |= | ||
4986 | IEEE80211_CHAN_NO_HT40PLUS; | ||
4987 | } else { | ||
4988 | /* It should be one of | ||
4989 | * IEEE80211_CHAN_NO_HT40 or | ||
4990 | * IEEE80211_CHAN_NO_HT40PLUS | ||
4991 | */ | ||
4992 | band_chan_arr[index].flags &= | ||
4993 | ~IEEE80211_CHAN_NO_HT40; | ||
4994 | if (ht40_flag == IEEE80211_CHAN_NO_HT40) | ||
4995 | band_chan_arr[index].flags |= | ||
4996 | IEEE80211_CHAN_NO_HT40MINUS; | ||
4997 | } | ||
4998 | } else { | ||
4999 | band_chan_arr[index].flags = | ||
5000 | IEEE80211_CHAN_NO_HT40; | ||
5001 | if (band == IEEE80211_BAND_2GHZ) | ||
5002 | channel |= WL_CHANSPEC_BAND_2G; | ||
5003 | else | ||
5004 | channel |= WL_CHANSPEC_BAND_5G; | ||
5005 | channel |= WL_CHANSPEC_BW_20; | ||
5006 | err = brcmf_fil_bsscfg_int_get(ifp, | ||
5007 | "per_chan_info", | ||
5008 | &channel); | ||
5009 | if (!err) { | ||
5010 | if (channel & WL_CHAN_RADAR) | ||
5011 | band_chan_arr[index].flags |= | ||
5012 | (IEEE80211_CHAN_RADAR | | ||
5013 | IEEE80211_CHAN_NO_IBSS); | ||
5014 | if (channel & WL_CHAN_PASSIVE) | ||
5015 | band_chan_arr[index].flags |= | ||
5016 | IEEE80211_CHAN_PASSIVE_SCAN; | ||
5017 | } | ||
5018 | } | ||
5019 | if (!update) | ||
5020 | (*n_cnt)++; | ||
5021 | } | ||
5022 | } | ||
5023 | exit: | ||
5024 | kfree(pbuf); | ||
5025 | return err; | ||
5026 | } | ||
5027 | |||
5028 | |||
5029 | static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg) | ||
4931 | { | 5030 | { |
4932 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); | 5031 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); |
4933 | struct wiphy *wiphy; | 5032 | struct wiphy *wiphy; |
4934 | s32 phy_list; | 5033 | s32 phy_list; |
5034 | u32 band_list[3]; | ||
5035 | u32 nmode; | ||
5036 | u32 bw_cap = 0; | ||
4935 | s8 phy; | 5037 | s8 phy; |
4936 | s32 err = 0; | 5038 | s32 err; |
5039 | u32 nband; | ||
5040 | s32 i; | ||
5041 | struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS]; | ||
5042 | s32 index; | ||
4937 | 5043 | ||
4938 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_PHYLIST, | 5044 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_PHYLIST, |
4939 | &phy_list, sizeof(phy_list)); | 5045 | &phy_list, sizeof(phy_list)); |
4940 | if (err) { | 5046 | if (err) { |
4941 | brcmf_err("error (%d)\n", err); | 5047 | brcmf_err("BRCMF_C_GET_PHYLIST error (%d)\n", err); |
4942 | return err; | 5048 | return err; |
4943 | } | 5049 | } |
4944 | 5050 | ||
4945 | phy = ((char *)&phy_list)[0]; | 5051 | phy = ((char *)&phy_list)[0]; |
4946 | brcmf_dbg(INFO, "%c phy\n", phy); | 5052 | brcmf_dbg(INFO, "BRCMF_C_GET_PHYLIST reported: %c phy\n", phy); |
4947 | if (phy == 'n' || phy == 'a') { | 5053 | |
4948 | wiphy = cfg_to_wiphy(cfg); | 5054 | |
4949 | wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n; | 5055 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BANDLIST, |
5056 | &band_list, sizeof(band_list)); | ||
5057 | if (err) { | ||
5058 | brcmf_err("BRCMF_C_GET_BANDLIST error (%d)\n", err); | ||
5059 | return err; | ||
5060 | } | ||
5061 | brcmf_dbg(INFO, "BRCMF_C_GET_BANDLIST reported: 0x%08x 0x%08x 0x%08x phy\n", | ||
5062 | band_list[0], band_list[1], band_list[2]); | ||
5063 | |||
5064 | err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode); | ||
5065 | if (err) { | ||
5066 | brcmf_err("nmode error (%d)\n", err); | ||
5067 | } else { | ||
5068 | err = brcmf_fil_iovar_int_get(ifp, "mimo_bw_cap", &bw_cap); | ||
5069 | if (err) | ||
5070 | brcmf_err("mimo_bw_cap error (%d)\n", err); | ||
5071 | } | ||
5072 | brcmf_dbg(INFO, "nmode=%d, mimo_bw_cap=%d\n", nmode, bw_cap); | ||
5073 | |||
5074 | err = brcmf_construct_reginfo(cfg, bw_cap); | ||
5075 | if (err) { | ||
5076 | brcmf_err("brcmf_construct_reginfo failed (%d)\n", err); | ||
5077 | return err; | ||
4950 | } | 5078 | } |
4951 | 5079 | ||
5080 | nband = band_list[0]; | ||
5081 | memset(bands, 0, sizeof(bands)); | ||
5082 | |||
5083 | for (i = 1; i <= nband && i < ARRAY_SIZE(band_list); i++) { | ||
5084 | index = -1; | ||
5085 | if ((band_list[i] == WLC_BAND_5G) && | ||
5086 | (__wl_band_5ghz_a.n_channels > 0)) { | ||
5087 | index = IEEE80211_BAND_5GHZ; | ||
5088 | bands[index] = &__wl_band_5ghz_a; | ||
5089 | if ((bw_cap == WLC_N_BW_40ALL) || | ||
5090 | (bw_cap == WLC_N_BW_20IN2G_40IN5G)) | ||
5091 | bands[index]->ht_cap.cap |= | ||
5092 | IEEE80211_HT_CAP_SGI_40; | ||
5093 | } else if ((band_list[i] == WLC_BAND_2G) && | ||
5094 | (__wl_band_2ghz.n_channels > 0)) { | ||
5095 | index = IEEE80211_BAND_2GHZ; | ||
5096 | bands[index] = &__wl_band_2ghz; | ||
5097 | if (bw_cap == WLC_N_BW_40ALL) | ||
5098 | bands[index]->ht_cap.cap |= | ||
5099 | IEEE80211_HT_CAP_SGI_40; | ||
5100 | } | ||
5101 | |||
5102 | if ((index >= 0) && nmode) { | ||
5103 | bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; | ||
5104 | bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40; | ||
5105 | bands[index]->ht_cap.ht_supported = true; | ||
5106 | bands[index]->ht_cap.ampdu_factor = | ||
5107 | IEEE80211_HT_MAX_AMPDU_64K; | ||
5108 | bands[index]->ht_cap.ampdu_density = | ||
5109 | IEEE80211_HT_MPDU_DENSITY_16; | ||
5110 | /* An HT shall support all EQM rates for one spatial | ||
5111 | * stream | ||
5112 | */ | ||
5113 | bands[index]->ht_cap.mcs.rx_mask[0] = 0xff; | ||
5114 | } | ||
5115 | } | ||
5116 | |||
5117 | wiphy = cfg_to_wiphy(cfg); | ||
5118 | wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ]; | ||
5119 | wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ]; | ||
5120 | wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom); | ||
5121 | |||
4952 | return err; | 5122 | return err; |
4953 | } | 5123 | } |
4954 | 5124 | ||
5125 | |||
4955 | static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_info *cfg) | 5126 | static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_info *cfg) |
4956 | { | 5127 | { |
4957 | return wl_update_wiphybands(cfg); | 5128 | return brcmf_update_wiphybands(cfg); |
4958 | } | 5129 | } |
4959 | 5130 | ||
4960 | static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) | 5131 | static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index 8b5d4989906c..2907437ef438 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h | |||
@@ -238,9 +238,8 @@ struct escan_info { | |||
238 | u32 escan_state; | 238 | u32 escan_state; |
239 | u8 escan_buf[WL_ESCAN_BUF_SIZE]; | 239 | u8 escan_buf[WL_ESCAN_BUF_SIZE]; |
240 | struct wiphy *wiphy; | 240 | struct wiphy *wiphy; |
241 | struct net_device *ndev; | 241 | struct brcmf_if *ifp; |
242 | s32 (*run)(struct brcmf_cfg80211_info *cfg, | 242 | s32 (*run)(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp, |
243 | struct net_device *ndev, | ||
244 | struct cfg80211_scan_request *request, u16 action); | 243 | struct cfg80211_scan_request *request, u16 action); |
245 | }; | 244 | }; |
246 | 245 | ||
@@ -493,9 +492,9 @@ bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg); | |||
493 | int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg, | 492 | int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg, |
494 | u8 action, ulong timeout); | 493 | u8 action, ulong timeout); |
495 | s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, | 494 | s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, |
496 | struct net_device *ndev, | 495 | struct brcmf_if *ifp, bool aborted, |
497 | bool aborted, bool fw_abort); | 496 | bool fw_abort); |
498 | void brcmf_set_mpc(struct net_device *ndev, int mpc); | 497 | void brcmf_set_mpc(struct brcmf_if *ndev, int mpc); |
499 | void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg); | 498 | void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg); |
500 | 499 | ||
501 | #endif /* _wl_cfg80211_h_ */ | 500 | #endif /* _wl_cfg80211_h_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c index f0888a9ee32e..e4fd1ee3d690 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c | |||
@@ -318,12 +318,6 @@ | |||
318 | #define IS_SIM(chippkg) \ | 318 | #define IS_SIM(chippkg) \ |
319 | ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) | 319 | ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) |
320 | 320 | ||
321 | #ifdef DEBUG | ||
322 | #define SI_MSG(fmt, ...) pr_debug(fmt, ##__VA_ARGS__) | ||
323 | #else | ||
324 | #define SI_MSG(fmt, ...) no_printk(fmt, ##__VA_ARGS__) | ||
325 | #endif /* DEBUG */ | ||
326 | |||
327 | #define GOODCOREADDR(x, b) \ | 321 | #define GOODCOREADDR(x, b) \ |
328 | (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \ | 322 | (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \ |
329 | IS_ALIGNED((x), SI_CORE_SIZE)) | 323 | IS_ALIGNED((x), SI_CORE_SIZE)) |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/d11.h b/drivers/net/wireless/brcm80211/brcmsmac/d11.h index 3f659e09f1cc..9035cc4d6ff3 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/d11.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/d11.h | |||
@@ -457,6 +457,7 @@ struct d11regs { | |||
457 | /*== maccontrol register ==*/ | 457 | /*== maccontrol register ==*/ |
458 | #define MCTL_GMODE (1U << 31) | 458 | #define MCTL_GMODE (1U << 31) |
459 | #define MCTL_DISCARD_PMQ (1 << 30) | 459 | #define MCTL_DISCARD_PMQ (1 << 30) |
460 | #define MCTL_TBTTHOLD (1 << 28) | ||
460 | #define MCTL_WAKE (1 << 26) | 461 | #define MCTL_WAKE (1 << 26) |
461 | #define MCTL_HPS (1 << 25) | 462 | #define MCTL_HPS (1 << 25) |
462 | #define MCTL_PROMISC (1 << 24) | 463 | #define MCTL_PROMISC (1 << 24) |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index c70cf7b654cd..cd837860cd42 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Broadcom Corporation | 2 | * Copyright (c) 2010 Broadcom Corporation |
3 | * Copyright (c) 2013 Hauke Mehrtens <hauke@hauke-m.de> | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * 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 | * purpose with or without fee is hereby granted, provided that the above |
@@ -356,18 +357,26 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
356 | { | 357 | { |
357 | struct brcms_info *wl = hw->priv; | 358 | struct brcms_info *wl = hw->priv; |
358 | 359 | ||
359 | /* Just STA for now */ | 360 | /* Just STA, AP and ADHOC for now */ |
360 | if (vif->type != NL80211_IFTYPE_STATION) { | 361 | if (vif->type != NL80211_IFTYPE_STATION && |
362 | vif->type != NL80211_IFTYPE_AP && | ||
363 | vif->type != NL80211_IFTYPE_ADHOC) { | ||
361 | brcms_err(wl->wlc->hw->d11core, | 364 | brcms_err(wl->wlc->hw->d11core, |
362 | "%s: Attempt to add type %d, only STA for now\n", | 365 | "%s: Attempt to add type %d, only STA, AP and AdHoc for now\n", |
363 | __func__, vif->type); | 366 | __func__, vif->type); |
364 | return -EOPNOTSUPP; | 367 | return -EOPNOTSUPP; |
365 | } | 368 | } |
366 | 369 | ||
367 | spin_lock_bh(&wl->lock); | 370 | spin_lock_bh(&wl->lock); |
368 | memcpy(wl->pub->cur_etheraddr, vif->addr, sizeof(vif->addr)); | ||
369 | wl->mute_tx = false; | 371 | wl->mute_tx = false; |
370 | brcms_c_mute(wl->wlc, false); | 372 | brcms_c_mute(wl->wlc, false); |
373 | if (vif->type == NL80211_IFTYPE_STATION) | ||
374 | brcms_c_start_station(wl->wlc, vif->addr); | ||
375 | else if (vif->type == NL80211_IFTYPE_AP) | ||
376 | brcms_c_start_ap(wl->wlc, vif->addr, vif->bss_conf.bssid, | ||
377 | vif->bss_conf.ssid, vif->bss_conf.ssid_len); | ||
378 | else if (vif->type == NL80211_IFTYPE_ADHOC) | ||
379 | brcms_c_start_adhoc(wl->wlc, vif->addr); | ||
371 | spin_unlock_bh(&wl->lock); | 380 | spin_unlock_bh(&wl->lock); |
372 | 381 | ||
373 | return 0; | 382 | return 0; |
@@ -519,14 +528,43 @@ brcms_ops_bss_info_changed(struct ieee80211_hw *hw, | |||
519 | brcms_c_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET, info->bssid); | 528 | brcms_c_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET, info->bssid); |
520 | spin_unlock_bh(&wl->lock); | 529 | spin_unlock_bh(&wl->lock); |
521 | } | 530 | } |
522 | if (changed & BSS_CHANGED_BEACON) | 531 | if (changed & BSS_CHANGED_SSID) { |
532 | /* BSSID changed, for whatever reason (IBSS and managed mode) */ | ||
533 | spin_lock_bh(&wl->lock); | ||
534 | brcms_c_set_ssid(wl->wlc, info->ssid, info->ssid_len); | ||
535 | spin_unlock_bh(&wl->lock); | ||
536 | } | ||
537 | if (changed & BSS_CHANGED_BEACON) { | ||
523 | /* Beacon data changed, retrieve new beacon (beaconing modes) */ | 538 | /* Beacon data changed, retrieve new beacon (beaconing modes) */ |
524 | brcms_err(core, "%s: beacon changed\n", __func__); | 539 | struct sk_buff *beacon; |
540 | u16 tim_offset = 0; | ||
541 | |||
542 | spin_lock_bh(&wl->lock); | ||
543 | beacon = ieee80211_beacon_get_tim(hw, vif, &tim_offset, NULL); | ||
544 | brcms_c_set_new_beacon(wl->wlc, beacon, tim_offset, | ||
545 | info->dtim_period); | ||
546 | spin_unlock_bh(&wl->lock); | ||
547 | } | ||
548 | |||
549 | if (changed & BSS_CHANGED_AP_PROBE_RESP) { | ||
550 | struct sk_buff *probe_resp; | ||
551 | |||
552 | spin_lock_bh(&wl->lock); | ||
553 | probe_resp = ieee80211_proberesp_get(hw, vif); | ||
554 | brcms_c_set_new_probe_resp(wl->wlc, probe_resp); | ||
555 | spin_unlock_bh(&wl->lock); | ||
556 | } | ||
525 | 557 | ||
526 | if (changed & BSS_CHANGED_BEACON_ENABLED) { | 558 | if (changed & BSS_CHANGED_BEACON_ENABLED) { |
527 | /* Beaconing should be enabled/disabled (beaconing modes) */ | 559 | /* Beaconing should be enabled/disabled (beaconing modes) */ |
528 | brcms_err(core, "%s: Beacon enabled: %s\n", __func__, | 560 | brcms_err(core, "%s: Beacon enabled: %s\n", __func__, |
529 | info->enable_beacon ? "true" : "false"); | 561 | info->enable_beacon ? "true" : "false"); |
562 | if (info->enable_beacon && | ||
563 | hw->wiphy->flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) { | ||
564 | brcms_c_enable_probe_resp(wl->wlc, true); | ||
565 | } else { | ||
566 | brcms_c_enable_probe_resp(wl->wlc, false); | ||
567 | } | ||
530 | } | 568 | } |
531 | 569 | ||
532 | if (changed & BSS_CHANGED_CQM) { | 570 | if (changed & BSS_CHANGED_CQM) { |
@@ -724,7 +762,7 @@ static bool brcms_tx_flush_completed(struct brcms_info *wl) | |||
724 | return result; | 762 | return result; |
725 | } | 763 | } |
726 | 764 | ||
727 | static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop) | 765 | static void brcms_ops_flush(struct ieee80211_hw *hw, u32 queues, bool drop) |
728 | { | 766 | { |
729 | struct brcms_info *wl = hw->priv; | 767 | struct brcms_info *wl = hw->priv; |
730 | int ret; | 768 | int ret; |
@@ -739,6 +777,28 @@ static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop) | |||
739 | "ret=%d\n", jiffies_to_msecs(ret)); | 777 | "ret=%d\n", jiffies_to_msecs(ret)); |
740 | } | 778 | } |
741 | 779 | ||
780 | static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | ||
781 | { | ||
782 | struct brcms_info *wl = hw->priv; | ||
783 | u64 tsf; | ||
784 | |||
785 | spin_lock_bh(&wl->lock); | ||
786 | tsf = brcms_c_tsf_get(wl->wlc); | ||
787 | spin_unlock_bh(&wl->lock); | ||
788 | |||
789 | return tsf; | ||
790 | } | ||
791 | |||
792 | static void brcms_ops_set_tsf(struct ieee80211_hw *hw, | ||
793 | struct ieee80211_vif *vif, u64 tsf) | ||
794 | { | ||
795 | struct brcms_info *wl = hw->priv; | ||
796 | |||
797 | spin_lock_bh(&wl->lock); | ||
798 | brcms_c_tsf_set(wl->wlc, tsf); | ||
799 | spin_unlock_bh(&wl->lock); | ||
800 | } | ||
801 | |||
742 | static const struct ieee80211_ops brcms_ops = { | 802 | static const struct ieee80211_ops brcms_ops = { |
743 | .tx = brcms_ops_tx, | 803 | .tx = brcms_ops_tx, |
744 | .start = brcms_ops_start, | 804 | .start = brcms_ops_start, |
@@ -755,6 +815,8 @@ static const struct ieee80211_ops brcms_ops = { | |||
755 | .ampdu_action = brcms_ops_ampdu_action, | 815 | .ampdu_action = brcms_ops_ampdu_action, |
756 | .rfkill_poll = brcms_ops_rfkill_poll, | 816 | .rfkill_poll = brcms_ops_rfkill_poll, |
757 | .flush = brcms_ops_flush, | 817 | .flush = brcms_ops_flush, |
818 | .get_tsf = brcms_ops_get_tsf, | ||
819 | .set_tsf = brcms_ops_set_tsf, | ||
758 | }; | 820 | }; |
759 | 821 | ||
760 | void brcms_dpc(unsigned long data) | 822 | void brcms_dpc(unsigned long data) |
@@ -996,7 +1058,16 @@ static int ieee_hw_init(struct ieee80211_hw *hw) | |||
996 | 1058 | ||
997 | /* channel change time is dependent on chip and band */ | 1059 | /* channel change time is dependent on chip and band */ |
998 | hw->channel_change_time = 7 * 1000; | 1060 | hw->channel_change_time = 7 * 1000; |
999 | hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | 1061 | hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
1062 | BIT(NL80211_IFTYPE_AP) | | ||
1063 | BIT(NL80211_IFTYPE_ADHOC); | ||
1064 | |||
1065 | /* | ||
1066 | * deactivate sending probe responses by ucude, because this will | ||
1067 | * cause problems when WPS is used. | ||
1068 | * | ||
1069 | * hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; | ||
1070 | */ | ||
1000 | 1071 | ||
1001 | hw->rate_control_algorithm = "minstrel_ht"; | 1072 | hw->rate_control_algorithm = "minstrel_ht"; |
1002 | 1073 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index 0c8e998bfb1e..59d438409dfb 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Broadcom Corporation | 2 | * Copyright (c) 2010 Broadcom Corporation |
3 | * Copyright (c) 2013 Hauke Mehrtens <hauke@hauke-m.de> | ||
3 | * | 4 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * 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 | * purpose with or without fee is hereby granted, provided that the above |
@@ -448,6 +449,10 @@ static void brcms_c_detach_mfree(struct brcms_c_info *wlc) | |||
448 | kfree(wlc->corestate); | 449 | kfree(wlc->corestate); |
449 | kfree(wlc->hw->bandstate[0]); | 450 | kfree(wlc->hw->bandstate[0]); |
450 | kfree(wlc->hw); | 451 | kfree(wlc->hw); |
452 | if (wlc->beacon) | ||
453 | dev_kfree_skb_any(wlc->beacon); | ||
454 | if (wlc->probe_resp) | ||
455 | dev_kfree_skb_any(wlc->probe_resp); | ||
451 | 456 | ||
452 | /* free the wlc */ | 457 | /* free the wlc */ |
453 | kfree(wlc); | 458 | kfree(wlc); |
@@ -1069,7 +1074,7 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal) | |||
1069 | 1074 | ||
1070 | static void brcms_c_tbtt(struct brcms_c_info *wlc) | 1075 | static void brcms_c_tbtt(struct brcms_c_info *wlc) |
1071 | { | 1076 | { |
1072 | if (!wlc->bsscfg->BSS) | 1077 | if (wlc->bsscfg->type == BRCMS_TYPE_ADHOC) |
1073 | /* | 1078 | /* |
1074 | * DirFrmQ is now valid...defer setting until end | 1079 | * DirFrmQ is now valid...defer setting until end |
1075 | * of ATIM window | 1080 | * of ATIM window |
@@ -2163,6 +2168,32 @@ void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode) | |||
2163 | } | 2168 | } |
2164 | } | 2169 | } |
2165 | 2170 | ||
2171 | void brcms_c_start_station(struct brcms_c_info *wlc, u8 *addr) | ||
2172 | { | ||
2173 | memcpy(wlc->pub->cur_etheraddr, addr, sizeof(wlc->pub->cur_etheraddr)); | ||
2174 | wlc->bsscfg->type = BRCMS_TYPE_STATION; | ||
2175 | } | ||
2176 | |||
2177 | void brcms_c_start_ap(struct brcms_c_info *wlc, u8 *addr, const u8 *bssid, | ||
2178 | u8 *ssid, size_t ssid_len) | ||
2179 | { | ||
2180 | brcms_c_set_ssid(wlc, ssid, ssid_len); | ||
2181 | |||
2182 | memcpy(wlc->pub->cur_etheraddr, addr, sizeof(wlc->pub->cur_etheraddr)); | ||
2183 | memcpy(wlc->bsscfg->BSSID, bssid, sizeof(wlc->bsscfg->BSSID)); | ||
2184 | wlc->bsscfg->type = BRCMS_TYPE_AP; | ||
2185 | |||
2186 | brcms_b_mctrl(wlc->hw, MCTL_AP | MCTL_INFRA, MCTL_AP | MCTL_INFRA); | ||
2187 | } | ||
2188 | |||
2189 | void brcms_c_start_adhoc(struct brcms_c_info *wlc, u8 *addr) | ||
2190 | { | ||
2191 | memcpy(wlc->pub->cur_etheraddr, addr, sizeof(wlc->pub->cur_etheraddr)); | ||
2192 | wlc->bsscfg->type = BRCMS_TYPE_ADHOC; | ||
2193 | |||
2194 | brcms_b_mctrl(wlc->hw, MCTL_AP | MCTL_INFRA, 0); | ||
2195 | } | ||
2196 | |||
2166 | /* Initialize GPIOs that are controlled by D11 core */ | 2197 | /* Initialize GPIOs that are controlled by D11 core */ |
2167 | static void brcms_c_gpio_init(struct brcms_c_info *wlc) | 2198 | static void brcms_c_gpio_init(struct brcms_c_info *wlc) |
2168 | { | 2199 | { |
@@ -3043,8 +3074,6 @@ static void brcms_b_antsel_set(struct brcms_hardware *wlc_hw, u32 antsel_avail) | |||
3043 | */ | 3074 | */ |
3044 | static bool brcms_c_ps_allowed(struct brcms_c_info *wlc) | 3075 | static bool brcms_c_ps_allowed(struct brcms_c_info *wlc) |
3045 | { | 3076 | { |
3046 | struct brcms_bss_cfg *cfg = wlc->bsscfg; | ||
3047 | |||
3048 | /* disallow PS when one of the following global conditions meets */ | 3077 | /* disallow PS when one of the following global conditions meets */ |
3049 | if (!wlc->pub->associated) | 3078 | if (!wlc->pub->associated) |
3050 | return false; | 3079 | return false; |
@@ -3053,16 +3082,11 @@ static bool brcms_c_ps_allowed(struct brcms_c_info *wlc) | |||
3053 | if (wlc->filter_flags & FIF_PROMISC_IN_BSS) | 3082 | if (wlc->filter_flags & FIF_PROMISC_IN_BSS) |
3054 | return false; | 3083 | return false; |
3055 | 3084 | ||
3056 | if (cfg->associated) { | 3085 | if (wlc->bsscfg->type == BRCMS_TYPE_AP) |
3057 | /* | 3086 | return false; |
3058 | * disallow PS when one of the following | ||
3059 | * bsscfg specific conditions meets | ||
3060 | */ | ||
3061 | if (!cfg->BSS) | ||
3062 | return false; | ||
3063 | 3087 | ||
3088 | if (wlc->bsscfg->type == BRCMS_TYPE_ADHOC) | ||
3064 | return false; | 3089 | return false; |
3065 | } | ||
3066 | 3090 | ||
3067 | return true; | 3091 | return true; |
3068 | } | 3092 | } |
@@ -3771,7 +3795,7 @@ static int brcms_c_set_mac(struct brcms_bss_cfg *bsscfg) | |||
3771 | struct brcms_c_info *wlc = bsscfg->wlc; | 3795 | struct brcms_c_info *wlc = bsscfg->wlc; |
3772 | 3796 | ||
3773 | /* enter the MAC addr into the RXE match registers */ | 3797 | /* enter the MAC addr into the RXE match registers */ |
3774 | brcms_c_set_addrmatch(wlc, RCM_MAC_OFFSET, bsscfg->cur_etheraddr); | 3798 | brcms_c_set_addrmatch(wlc, RCM_MAC_OFFSET, wlc->pub->cur_etheraddr); |
3775 | 3799 | ||
3776 | brcms_c_ampdu_macaddr_upd(wlc); | 3800 | brcms_c_ampdu_macaddr_upd(wlc); |
3777 | 3801 | ||
@@ -3787,6 +3811,15 @@ static void brcms_c_set_bssid(struct brcms_bss_cfg *bsscfg) | |||
3787 | brcms_c_set_addrmatch(bsscfg->wlc, RCM_BSSID_OFFSET, bsscfg->BSSID); | 3811 | brcms_c_set_addrmatch(bsscfg->wlc, RCM_BSSID_OFFSET, bsscfg->BSSID); |
3788 | } | 3812 | } |
3789 | 3813 | ||
3814 | void brcms_c_set_ssid(struct brcms_c_info *wlc, u8 *ssid, size_t ssid_len) | ||
3815 | { | ||
3816 | u8 len = min_t(u8, sizeof(wlc->bsscfg->SSID), ssid_len); | ||
3817 | memset(wlc->bsscfg->SSID, 0, sizeof(wlc->bsscfg->SSID)); | ||
3818 | |||
3819 | memcpy(wlc->bsscfg->SSID, ssid, len); | ||
3820 | wlc->bsscfg->SSID_len = len; | ||
3821 | } | ||
3822 | |||
3790 | static void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw, bool shortslot) | 3823 | static void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw, bool shortslot) |
3791 | { | 3824 | { |
3792 | wlc_hw->shortslot = shortslot; | 3825 | wlc_hw->shortslot = shortslot; |
@@ -3821,7 +3854,7 @@ static void brcms_c_set_home_chanspec(struct brcms_c_info *wlc, u16 chanspec) | |||
3821 | if (wlc->home_chanspec != chanspec) { | 3854 | if (wlc->home_chanspec != chanspec) { |
3822 | wlc->home_chanspec = chanspec; | 3855 | wlc->home_chanspec = chanspec; |
3823 | 3856 | ||
3824 | if (wlc->bsscfg->associated) | 3857 | if (wlc->pub->associated) |
3825 | wlc->bsscfg->current_bss->chanspec = chanspec; | 3858 | wlc->bsscfg->current_bss->chanspec = chanspec; |
3826 | } | 3859 | } |
3827 | } | 3860 | } |
@@ -4091,10 +4124,14 @@ void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci, | |||
4091 | *shm_entry++); | 4124 | *shm_entry++); |
4092 | } | 4125 | } |
4093 | 4126 | ||
4094 | if (suspend) { | 4127 | if (suspend) |
4095 | brcms_c_suspend_mac_and_wait(wlc); | 4128 | brcms_c_suspend_mac_and_wait(wlc); |
4129 | |||
4130 | brcms_c_update_beacon(wlc); | ||
4131 | brcms_c_update_probe_resp(wlc, false); | ||
4132 | |||
4133 | if (suspend) | ||
4096 | brcms_c_enable_mac(wlc); | 4134 | brcms_c_enable_mac(wlc); |
4097 | } | ||
4098 | } | 4135 | } |
4099 | 4136 | ||
4100 | static void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend) | 4137 | static void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend) |
@@ -4332,7 +4369,6 @@ static void brcms_c_info_init(struct brcms_c_info *wlc, int unit) | |||
4332 | 4369 | ||
4333 | /* WME QoS mode is Auto by default */ | 4370 | /* WME QoS mode is Auto by default */ |
4334 | wlc->pub->_ampdu = AMPDU_AGG_HOST; | 4371 | wlc->pub->_ampdu = AMPDU_AGG_HOST; |
4335 | wlc->pub->bcmerror = 0; | ||
4336 | } | 4372 | } |
4337 | 4373 | ||
4338 | static uint brcms_c_attach_module(struct brcms_c_info *wlc) | 4374 | static uint brcms_c_attach_module(struct brcms_c_info *wlc) |
@@ -5072,8 +5108,8 @@ int brcms_c_up(struct brcms_c_info *wlc) | |||
5072 | struct brcms_bss_cfg *bsscfg = wlc->bsscfg; | 5108 | struct brcms_bss_cfg *bsscfg = wlc->bsscfg; |
5073 | mboolset(wlc->pub->radio_disabled, | 5109 | mboolset(wlc->pub->radio_disabled, |
5074 | WL_RADIO_HW_DISABLE); | 5110 | WL_RADIO_HW_DISABLE); |
5075 | 5111 | if (bsscfg->type == BRCMS_TYPE_STATION || | |
5076 | if (bsscfg->enable && bsscfg->BSS) | 5112 | bsscfg->type == BRCMS_TYPE_ADHOC) |
5077 | brcms_err(wlc->hw->d11core, | 5113 | brcms_err(wlc->hw->d11core, |
5078 | "wl%d: up: rfdisable -> " | 5114 | "wl%d: up: rfdisable -> " |
5079 | "bsscfg_disable()\n", | 5115 | "bsscfg_disable()\n", |
@@ -5434,7 +5470,7 @@ static void brcms_c_ofdm_rateset_war(struct brcms_c_info *wlc) | |||
5434 | u8 r; | 5470 | u8 r; |
5435 | bool war = false; | 5471 | bool war = false; |
5436 | 5472 | ||
5437 | if (wlc->bsscfg->associated) | 5473 | if (wlc->pub->associated) |
5438 | r = wlc->bsscfg->current_bss->rateset.rates[0]; | 5474 | r = wlc->bsscfg->current_bss->rateset.rates[0]; |
5439 | else | 5475 | else |
5440 | r = wlc->default_bss->rateset.rates[0]; | 5476 | r = wlc->default_bss->rateset.rates[0]; |
@@ -5528,7 +5564,7 @@ int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs) | |||
5528 | /* merge rateset coming in with the current mcsset */ | 5564 | /* merge rateset coming in with the current mcsset */ |
5529 | if (wlc->pub->_n_enab & SUPPORT_11N) { | 5565 | if (wlc->pub->_n_enab & SUPPORT_11N) { |
5530 | struct brcms_bss_info *mcsset_bss; | 5566 | struct brcms_bss_info *mcsset_bss; |
5531 | if (wlc->bsscfg->associated) | 5567 | if (wlc->pub->associated) |
5532 | mcsset_bss = wlc->bsscfg->current_bss; | 5568 | mcsset_bss = wlc->bsscfg->current_bss; |
5533 | else | 5569 | else |
5534 | mcsset_bss = wlc->default_bss; | 5570 | mcsset_bss = wlc->default_bss; |
@@ -5543,12 +5579,36 @@ int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs) | |||
5543 | return bcmerror; | 5579 | return bcmerror; |
5544 | } | 5580 | } |
5545 | 5581 | ||
5582 | static void brcms_c_time_lock(struct brcms_c_info *wlc) | ||
5583 | { | ||
5584 | bcma_set32(wlc->hw->d11core, D11REGOFFS(maccontrol), MCTL_TBTTHOLD); | ||
5585 | /* Commit the write */ | ||
5586 | bcma_read32(wlc->hw->d11core, D11REGOFFS(maccontrol)); | ||
5587 | } | ||
5588 | |||
5589 | static void brcms_c_time_unlock(struct brcms_c_info *wlc) | ||
5590 | { | ||
5591 | bcma_mask32(wlc->hw->d11core, D11REGOFFS(maccontrol), ~MCTL_TBTTHOLD); | ||
5592 | /* Commit the write */ | ||
5593 | bcma_read32(wlc->hw->d11core, D11REGOFFS(maccontrol)); | ||
5594 | } | ||
5595 | |||
5546 | int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period) | 5596 | int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period) |
5547 | { | 5597 | { |
5598 | u32 bcnint_us; | ||
5599 | |||
5548 | if (period == 0) | 5600 | if (period == 0) |
5549 | return -EINVAL; | 5601 | return -EINVAL; |
5550 | 5602 | ||
5551 | wlc->default_bss->beacon_period = period; | 5603 | wlc->default_bss->beacon_period = period; |
5604 | |||
5605 | bcnint_us = period << 10; | ||
5606 | brcms_c_time_lock(wlc); | ||
5607 | bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_cfprep), | ||
5608 | (bcnint_us << CFPREP_CBI_SHIFT)); | ||
5609 | bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_cfpstart), bcnint_us); | ||
5610 | brcms_c_time_unlock(wlc); | ||
5611 | |||
5552 | return 0; | 5612 | return 0; |
5553 | } | 5613 | } |
5554 | 5614 | ||
@@ -7291,72 +7351,110 @@ brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc, uint frame_len) | |||
7291 | } | 7351 | } |
7292 | } | 7352 | } |
7293 | 7353 | ||
7294 | /* Max buffering needed for beacon template/prb resp template is 142 bytes. | 7354 | int brcms_c_get_header_len(void) |
7295 | * | ||
7296 | * PLCP header is 6 bytes. | ||
7297 | * 802.11 A3 header is 24 bytes. | ||
7298 | * Max beacon frame body template length is 112 bytes. | ||
7299 | * Max probe resp frame body template length is 110 bytes. | ||
7300 | * | ||
7301 | * *len on input contains the max length of the packet available. | ||
7302 | * | ||
7303 | * The *len value is set to the number of bytes in buf used, and starts | ||
7304 | * with the PLCP and included up to, but not including, the 4 byte FCS. | ||
7305 | */ | ||
7306 | static void | ||
7307 | brcms_c_bcn_prb_template(struct brcms_c_info *wlc, u16 type, | ||
7308 | u32 bcn_rspec, | ||
7309 | struct brcms_bss_cfg *cfg, u16 *buf, int *len) | ||
7310 | { | 7355 | { |
7311 | static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255}; | 7356 | return TXOFF; |
7312 | struct cck_phy_hdr *plcp; | 7357 | } |
7313 | struct ieee80211_mgmt *h; | ||
7314 | int hdr_len, body_len; | ||
7315 | |||
7316 | hdr_len = D11_PHY_HDR_LEN + DOT11_MAC_HDR_LEN; | ||
7317 | 7358 | ||
7318 | /* calc buffer size provided for frame body */ | 7359 | static void brcms_c_beacon_write(struct brcms_c_info *wlc, |
7319 | body_len = *len - hdr_len; | 7360 | struct sk_buff *beacon, u16 tim_offset, |
7320 | /* return actual size */ | 7361 | u16 dtim_period, bool bcn0, bool bcn1) |
7321 | *len = hdr_len + body_len; | 7362 | { |
7363 | size_t len; | ||
7364 | struct ieee80211_tx_info *tx_info; | ||
7365 | struct brcms_hardware *wlc_hw = wlc->hw; | ||
7366 | struct ieee80211_hw *ieee_hw = brcms_c_pub(wlc)->ieee_hw; | ||
7322 | 7367 | ||
7323 | /* format PHY and MAC headers */ | 7368 | /* Get tx_info */ |
7324 | memset(buf, 0, hdr_len); | 7369 | tx_info = IEEE80211_SKB_CB(beacon); |
7325 | 7370 | ||
7326 | plcp = (struct cck_phy_hdr *) buf; | 7371 | len = min_t(size_t, beacon->len, BCN_TMPL_LEN); |
7372 | wlc->bcn_rspec = ieee80211_get_tx_rate(ieee_hw, tx_info)->hw_value; | ||
7327 | 7373 | ||
7328 | /* | 7374 | brcms_c_compute_plcp(wlc, wlc->bcn_rspec, |
7329 | * PLCP for Probe Response frames are filled in from | 7375 | len + FCS_LEN - D11_PHY_HDR_LEN, beacon->data); |
7330 | * core's rate table | ||
7331 | */ | ||
7332 | if (type == IEEE80211_STYPE_BEACON) | ||
7333 | /* fill in PLCP */ | ||
7334 | brcms_c_compute_plcp(wlc, bcn_rspec, | ||
7335 | (DOT11_MAC_HDR_LEN + body_len + FCS_LEN), | ||
7336 | (u8 *) plcp); | ||
7337 | 7376 | ||
7338 | /* "Regular" and 16 MBSS but not for 4 MBSS */ | 7377 | /* "Regular" and 16 MBSS but not for 4 MBSS */ |
7339 | /* Update the phytxctl for the beacon based on the rspec */ | 7378 | /* Update the phytxctl for the beacon based on the rspec */ |
7340 | brcms_c_beacon_phytxctl_txant_upd(wlc, bcn_rspec); | 7379 | brcms_c_beacon_phytxctl_txant_upd(wlc, wlc->bcn_rspec); |
7341 | 7380 | ||
7342 | h = (struct ieee80211_mgmt *)&plcp[1]; | 7381 | if (bcn0) { |
7382 | /* write the probe response into the template region */ | ||
7383 | brcms_b_write_template_ram(wlc_hw, T_BCN0_TPL_BASE, | ||
7384 | (len + 3) & ~3, beacon->data); | ||
7343 | 7385 | ||
7344 | /* fill in 802.11 header */ | 7386 | /* write beacon length to SCR */ |
7345 | h->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | type); | 7387 | brcms_b_write_shm(wlc_hw, M_BCN0_FRM_BYTESZ, (u16) len); |
7388 | } | ||
7389 | if (bcn1) { | ||
7390 | /* write the probe response into the template region */ | ||
7391 | brcms_b_write_template_ram(wlc_hw, T_BCN1_TPL_BASE, | ||
7392 | (len + 3) & ~3, beacon->data); | ||
7346 | 7393 | ||
7347 | /* DUR is 0 for multicast bcn, or filled in by MAC for prb resp */ | 7394 | /* write beacon length to SCR */ |
7348 | /* A1 filled in by MAC for prb resp, broadcast for bcn */ | 7395 | brcms_b_write_shm(wlc_hw, M_BCN1_FRM_BYTESZ, (u16) len); |
7349 | if (type == IEEE80211_STYPE_BEACON) | 7396 | } |
7350 | memcpy(&h->da, ðer_bcast, ETH_ALEN); | ||
7351 | memcpy(&h->sa, &cfg->cur_etheraddr, ETH_ALEN); | ||
7352 | memcpy(&h->bssid, &cfg->BSSID, ETH_ALEN); | ||
7353 | 7397 | ||
7354 | /* SEQ filled in by MAC */ | 7398 | if (tim_offset != 0) { |
7399 | brcms_b_write_shm(wlc_hw, M_TIMBPOS_INBEACON, | ||
7400 | tim_offset + D11B_PHY_HDR_LEN); | ||
7401 | brcms_b_write_shm(wlc_hw, M_DOT11_DTIMPERIOD, dtim_period); | ||
7402 | } else { | ||
7403 | brcms_b_write_shm(wlc_hw, M_TIMBPOS_INBEACON, | ||
7404 | len + D11B_PHY_HDR_LEN); | ||
7405 | brcms_b_write_shm(wlc_hw, M_DOT11_DTIMPERIOD, 0); | ||
7406 | } | ||
7355 | } | 7407 | } |
7356 | 7408 | ||
7357 | int brcms_c_get_header_len(void) | 7409 | static void brcms_c_update_beacon_hw(struct brcms_c_info *wlc, |
7410 | struct sk_buff *beacon, u16 tim_offset, | ||
7411 | u16 dtim_period) | ||
7358 | { | 7412 | { |
7359 | return TXOFF; | 7413 | struct brcms_hardware *wlc_hw = wlc->hw; |
7414 | struct bcma_device *core = wlc_hw->d11core; | ||
7415 | |||
7416 | /* Hardware beaconing for this config */ | ||
7417 | u32 both_valid = MCMD_BCN0VLD | MCMD_BCN1VLD; | ||
7418 | |||
7419 | /* Check if both templates are in use, if so sched. an interrupt | ||
7420 | * that will call back into this routine | ||
7421 | */ | ||
7422 | if ((bcma_read32(core, D11REGOFFS(maccommand)) & both_valid) == both_valid) | ||
7423 | /* clear any previous status */ | ||
7424 | bcma_write32(core, D11REGOFFS(macintstatus), MI_BCNTPL); | ||
7425 | |||
7426 | if (wlc->beacon_template_virgin) { | ||
7427 | wlc->beacon_template_virgin = false; | ||
7428 | brcms_c_beacon_write(wlc, beacon, tim_offset, dtim_period, true, | ||
7429 | true); | ||
7430 | /* mark beacon0 valid */ | ||
7431 | bcma_set32(core, D11REGOFFS(maccommand), MCMD_BCN0VLD); | ||
7432 | return; | ||
7433 | } | ||
7434 | |||
7435 | /* Check that after scheduling the interrupt both of the | ||
7436 | * templates are still busy. if not clear the int. & remask | ||
7437 | */ | ||
7438 | if ((bcma_read32(core, D11REGOFFS(maccommand)) & both_valid) == both_valid) { | ||
7439 | wlc->defmacintmask |= MI_BCNTPL; | ||
7440 | return; | ||
7441 | } | ||
7442 | |||
7443 | if (!(bcma_read32(core, D11REGOFFS(maccommand)) & MCMD_BCN0VLD)) { | ||
7444 | brcms_c_beacon_write(wlc, beacon, tim_offset, dtim_period, true, | ||
7445 | false); | ||
7446 | /* mark beacon0 valid */ | ||
7447 | bcma_set32(core, D11REGOFFS(maccommand), MCMD_BCN0VLD); | ||
7448 | return; | ||
7449 | } | ||
7450 | if (!(bcma_read32(core, D11REGOFFS(maccommand)) & MCMD_BCN1VLD)) { | ||
7451 | brcms_c_beacon_write(wlc, beacon, tim_offset, dtim_period, | ||
7452 | false, true); | ||
7453 | /* mark beacon0 valid */ | ||
7454 | bcma_set32(core, D11REGOFFS(maccommand), MCMD_BCN1VLD); | ||
7455 | return; | ||
7456 | } | ||
7457 | return; | ||
7360 | } | 7458 | } |
7361 | 7459 | ||
7362 | /* | 7460 | /* |
@@ -7366,9 +7464,57 @@ void brcms_c_update_beacon(struct brcms_c_info *wlc) | |||
7366 | { | 7464 | { |
7367 | struct brcms_bss_cfg *bsscfg = wlc->bsscfg; | 7465 | struct brcms_bss_cfg *bsscfg = wlc->bsscfg; |
7368 | 7466 | ||
7369 | if (bsscfg->up && !bsscfg->BSS) | 7467 | if (wlc->pub->up && (bsscfg->type == BRCMS_TYPE_AP || |
7468 | bsscfg->type == BRCMS_TYPE_ADHOC)) { | ||
7370 | /* Clear the soft intmask */ | 7469 | /* Clear the soft intmask */ |
7371 | wlc->defmacintmask &= ~MI_BCNTPL; | 7470 | wlc->defmacintmask &= ~MI_BCNTPL; |
7471 | if (!wlc->beacon) | ||
7472 | return; | ||
7473 | brcms_c_update_beacon_hw(wlc, wlc->beacon, | ||
7474 | wlc->beacon_tim_offset, | ||
7475 | wlc->beacon_dtim_period); | ||
7476 | } | ||
7477 | } | ||
7478 | |||
7479 | void brcms_c_set_new_beacon(struct brcms_c_info *wlc, struct sk_buff *beacon, | ||
7480 | u16 tim_offset, u16 dtim_period) | ||
7481 | { | ||
7482 | if (!beacon) | ||
7483 | return; | ||
7484 | if (wlc->beacon) | ||
7485 | dev_kfree_skb_any(wlc->beacon); | ||
7486 | wlc->beacon = beacon; | ||
7487 | |||
7488 | /* add PLCP */ | ||
7489 | skb_push(wlc->beacon, D11_PHY_HDR_LEN); | ||
7490 | wlc->beacon_tim_offset = tim_offset; | ||
7491 | wlc->beacon_dtim_period = dtim_period; | ||
7492 | brcms_c_update_beacon(wlc); | ||
7493 | } | ||
7494 | |||
7495 | void brcms_c_set_new_probe_resp(struct brcms_c_info *wlc, | ||
7496 | struct sk_buff *probe_resp) | ||
7497 | { | ||
7498 | if (!probe_resp) | ||
7499 | return; | ||
7500 | if (wlc->probe_resp) | ||
7501 | dev_kfree_skb_any(wlc->probe_resp); | ||
7502 | wlc->probe_resp = probe_resp; | ||
7503 | |||
7504 | /* add PLCP */ | ||
7505 | skb_push(wlc->probe_resp, D11_PHY_HDR_LEN); | ||
7506 | brcms_c_update_probe_resp(wlc, false); | ||
7507 | } | ||
7508 | |||
7509 | void brcms_c_enable_probe_resp(struct brcms_c_info *wlc, bool enable) | ||
7510 | { | ||
7511 | /* | ||
7512 | * prevent ucode from sending probe responses by setting the timeout | ||
7513 | * to 1, it can not send it in that time frame. | ||
7514 | */ | ||
7515 | wlc->prb_resp_timeout = enable ? BRCMS_PRB_RESP_TIMEOUT : 1; | ||
7516 | brcms_b_write_shm(wlc->hw, M_PRS_MAXTIME, wlc->prb_resp_timeout); | ||
7517 | /* TODO: if (enable) => also deactivate receiving of probe request */ | ||
7372 | } | 7518 | } |
7373 | 7519 | ||
7374 | /* Write ssid into shared memory */ | 7520 | /* Write ssid into shared memory */ |
@@ -7390,30 +7536,19 @@ brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg) | |||
7390 | static void | 7536 | static void |
7391 | brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc, | 7537 | brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc, |
7392 | struct brcms_bss_cfg *cfg, | 7538 | struct brcms_bss_cfg *cfg, |
7539 | struct sk_buff *probe_resp, | ||
7393 | bool suspend) | 7540 | bool suspend) |
7394 | { | 7541 | { |
7395 | u16 *prb_resp; | 7542 | int len; |
7396 | int len = BCN_TMPL_LEN; | ||
7397 | |||
7398 | prb_resp = kmalloc(BCN_TMPL_LEN, GFP_ATOMIC); | ||
7399 | if (!prb_resp) | ||
7400 | return; | ||
7401 | |||
7402 | /* | ||
7403 | * write the probe response to hardware, or save in | ||
7404 | * the config structure | ||
7405 | */ | ||
7406 | 7543 | ||
7407 | /* create the probe response template */ | 7544 | len = min_t(size_t, probe_resp->len, BCN_TMPL_LEN); |
7408 | brcms_c_bcn_prb_template(wlc, IEEE80211_STYPE_PROBE_RESP, 0, | ||
7409 | cfg, prb_resp, &len); | ||
7410 | 7545 | ||
7411 | if (suspend) | 7546 | if (suspend) |
7412 | brcms_c_suspend_mac_and_wait(wlc); | 7547 | brcms_c_suspend_mac_and_wait(wlc); |
7413 | 7548 | ||
7414 | /* write the probe response into the template region */ | 7549 | /* write the probe response into the template region */ |
7415 | brcms_b_write_template_ram(wlc->hw, T_PRS_TPL_BASE, | 7550 | brcms_b_write_template_ram(wlc->hw, T_PRS_TPL_BASE, |
7416 | (len + 3) & ~3, prb_resp); | 7551 | (len + 3) & ~3, probe_resp->data); |
7417 | 7552 | ||
7418 | /* write the length of the probe response frame (+PLCP/-FCS) */ | 7553 | /* write the length of the probe response frame (+PLCP/-FCS) */ |
7419 | brcms_b_write_shm(wlc->hw, M_PRB_RESP_FRM_LEN, (u16) len); | 7554 | brcms_b_write_shm(wlc->hw, M_PRB_RESP_FRM_LEN, (u16) len); |
@@ -7427,13 +7562,11 @@ brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc, | |||
7427 | * PLCP header for the call to brcms_c_mod_prb_rsp_rate_table() | 7562 | * PLCP header for the call to brcms_c_mod_prb_rsp_rate_table() |
7428 | * by subtracting the PLCP len and adding the FCS. | 7563 | * by subtracting the PLCP len and adding the FCS. |
7429 | */ | 7564 | */ |
7430 | len += (-D11_PHY_HDR_LEN + FCS_LEN); | 7565 | brcms_c_mod_prb_rsp_rate_table(wlc, |
7431 | brcms_c_mod_prb_rsp_rate_table(wlc, (u16) len); | 7566 | (u16)len + FCS_LEN - D11_PHY_HDR_LEN); |
7432 | 7567 | ||
7433 | if (suspend) | 7568 | if (suspend) |
7434 | brcms_c_enable_mac(wlc); | 7569 | brcms_c_enable_mac(wlc); |
7435 | |||
7436 | kfree(prb_resp); | ||
7437 | } | 7570 | } |
7438 | 7571 | ||
7439 | void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend) | 7572 | void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend) |
@@ -7441,8 +7574,13 @@ void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend) | |||
7441 | struct brcms_bss_cfg *bsscfg = wlc->bsscfg; | 7574 | struct brcms_bss_cfg *bsscfg = wlc->bsscfg; |
7442 | 7575 | ||
7443 | /* update AP or IBSS probe responses */ | 7576 | /* update AP or IBSS probe responses */ |
7444 | if (bsscfg->up && !bsscfg->BSS) | 7577 | if (wlc->pub->up && (bsscfg->type == BRCMS_TYPE_AP || |
7445 | brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend); | 7578 | bsscfg->type == BRCMS_TYPE_ADHOC)) { |
7579 | if (!wlc->probe_resp) | ||
7580 | return; | ||
7581 | brcms_c_bss_update_probe_resp(wlc, bsscfg, wlc->probe_resp, | ||
7582 | suspend); | ||
7583 | } | ||
7446 | } | 7584 | } |
7447 | 7585 | ||
7448 | int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo, | 7586 | int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo, |
@@ -7481,7 +7619,6 @@ void brcms_c_scan_stop(struct brcms_c_info *wlc) | |||
7481 | void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state) | 7619 | void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state) |
7482 | { | 7620 | { |
7483 | wlc->pub->associated = state; | 7621 | wlc->pub->associated = state; |
7484 | wlc->bsscfg->associated = state; | ||
7485 | } | 7622 | } |
7486 | 7623 | ||
7487 | /* | 7624 | /* |
@@ -7526,6 +7663,36 @@ void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval) | |||
7526 | brcms_c_bcn_li_upd(wlc); | 7663 | brcms_c_bcn_li_upd(wlc); |
7527 | } | 7664 | } |
7528 | 7665 | ||
7666 | u64 brcms_c_tsf_get(struct brcms_c_info *wlc) | ||
7667 | { | ||
7668 | u32 tsf_h, tsf_l; | ||
7669 | u64 tsf; | ||
7670 | |||
7671 | brcms_b_read_tsf(wlc->hw, &tsf_l, &tsf_h); | ||
7672 | |||
7673 | tsf = tsf_h; | ||
7674 | tsf <<= 32; | ||
7675 | tsf |= tsf_l; | ||
7676 | |||
7677 | return tsf; | ||
7678 | } | ||
7679 | |||
7680 | void brcms_c_tsf_set(struct brcms_c_info *wlc, u64 tsf) | ||
7681 | { | ||
7682 | u32 tsf_h, tsf_l; | ||
7683 | |||
7684 | brcms_c_time_lock(wlc); | ||
7685 | |||
7686 | tsf_l = tsf; | ||
7687 | tsf_h = (tsf >> 32); | ||
7688 | |||
7689 | /* read the tsf timer low, then high to get an atomic read */ | ||
7690 | bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_timerlow), tsf_l); | ||
7691 | bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_timerhigh), tsf_h); | ||
7692 | |||
7693 | brcms_c_time_unlock(wlc); | ||
7694 | } | ||
7695 | |||
7529 | int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr) | 7696 | int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr) |
7530 | { | 7697 | { |
7531 | uint qdbm; | 7698 | uint qdbm; |
@@ -7737,6 +7904,10 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded) | |||
7737 | brcms_rfkill_set_hw_state(wlc->wl); | 7904 | brcms_rfkill_set_hw_state(wlc->wl); |
7738 | } | 7905 | } |
7739 | 7906 | ||
7907 | /* BCN template is available */ | ||
7908 | if (macintstatus & MI_BCNTPL) | ||
7909 | brcms_c_update_beacon(wlc); | ||
7910 | |||
7740 | /* it isn't done and needs to be resched if macintstatus is non-zero */ | 7911 | /* it isn't done and needs to be resched if macintstatus is non-zero */ |
7741 | return wlc->macintstatus != 0; | 7912 | return wlc->macintstatus != 0; |
7742 | 7913 | ||
@@ -7765,7 +7936,7 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx) | |||
7765 | brcms_c_set_bssid(wlc->bsscfg); | 7936 | brcms_c_set_bssid(wlc->bsscfg); |
7766 | 7937 | ||
7767 | /* Update tsf_cfprep if associated and up */ | 7938 | /* Update tsf_cfprep if associated and up */ |
7768 | if (wlc->pub->associated && wlc->bsscfg->up) { | 7939 | if (wlc->pub->associated && wlc->pub->up) { |
7769 | u32 bi; | 7940 | u32 bi; |
7770 | 7941 | ||
7771 | /* get beacon period and convert to uS */ | 7942 | /* get beacon period and convert to uS */ |
@@ -7873,6 +8044,7 @@ brcms_c_attach(struct brcms_info *wl, struct bcma_device *core, uint unit, | |||
7873 | pub->unit = unit; | 8044 | pub->unit = unit; |
7874 | pub->_piomode = piomode; | 8045 | pub->_piomode = piomode; |
7875 | wlc->bandinit_pending = false; | 8046 | wlc->bandinit_pending = false; |
8047 | wlc->beacon_template_virgin = true; | ||
7876 | 8048 | ||
7877 | /* populate struct brcms_c_info with default values */ | 8049 | /* populate struct brcms_c_info with default values */ |
7878 | brcms_c_info_init(wlc, unit); | 8050 | brcms_c_info_init(wlc, unit); |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.h b/drivers/net/wireless/brcm80211/brcmsmac/main.h index fb447747c2c6..b5d7a38b53fe 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h | |||
@@ -492,6 +492,8 @@ struct brcms_c_info { | |||
492 | bool radio_monitor; | 492 | bool radio_monitor; |
493 | bool going_down; | 493 | bool going_down; |
494 | 494 | ||
495 | bool beacon_template_virgin; | ||
496 | |||
495 | struct brcms_timer *wdtimer; | 497 | struct brcms_timer *wdtimer; |
496 | struct brcms_timer *radio_timer; | 498 | struct brcms_timer *radio_timer; |
497 | 499 | ||
@@ -561,6 +563,11 @@ struct brcms_c_info { | |||
561 | 563 | ||
562 | struct wiphy *wiphy; | 564 | struct wiphy *wiphy; |
563 | struct scb pri_scb; | 565 | struct scb pri_scb; |
566 | |||
567 | struct sk_buff *beacon; | ||
568 | u16 beacon_tim_offset; | ||
569 | u16 beacon_dtim_period; | ||
570 | struct sk_buff *probe_resp; | ||
564 | }; | 571 | }; |
565 | 572 | ||
566 | /* antsel module specific state */ | 573 | /* antsel module specific state */ |
@@ -576,14 +583,17 @@ struct antsel_info { | |||
576 | struct brcms_antselcfg antcfg_cur; /* current antenna config (auto) */ | 583 | struct brcms_antselcfg antcfg_cur; /* current antenna config (auto) */ |
577 | }; | 584 | }; |
578 | 585 | ||
586 | enum brcms_bss_type { | ||
587 | BRCMS_TYPE_STATION, | ||
588 | BRCMS_TYPE_AP, | ||
589 | BRCMS_TYPE_ADHOC, | ||
590 | }; | ||
591 | |||
579 | /* | 592 | /* |
580 | * BSS configuration state | 593 | * BSS configuration state |
581 | * | 594 | * |
582 | * wlc: wlc to which this bsscfg belongs to. | 595 | * wlc: wlc to which this bsscfg belongs to. |
583 | * up: is this configuration up operational | 596 | * type: interface type |
584 | * enable: is this configuration enabled | ||
585 | * associated: is BSS in ASSOCIATED state | ||
586 | * BSS: infraustructure or adhoc | ||
587 | * SSID_len: the length of SSID | 597 | * SSID_len: the length of SSID |
588 | * SSID: SSID string | 598 | * SSID: SSID string |
589 | * | 599 | * |
@@ -599,14 +609,10 @@ struct antsel_info { | |||
599 | */ | 609 | */ |
600 | struct brcms_bss_cfg { | 610 | struct brcms_bss_cfg { |
601 | struct brcms_c_info *wlc; | 611 | struct brcms_c_info *wlc; |
602 | bool up; | 612 | enum brcms_bss_type type; |
603 | bool enable; | ||
604 | bool associated; | ||
605 | bool BSS; | ||
606 | u8 SSID_len; | 613 | u8 SSID_len; |
607 | u8 SSID[IEEE80211_MAX_SSID_LEN]; | 614 | u8 SSID[IEEE80211_MAX_SSID_LEN]; |
608 | u8 BSSID[ETH_ALEN]; | 615 | u8 BSSID[ETH_ALEN]; |
609 | u8 cur_etheraddr[ETH_ALEN]; | ||
610 | struct brcms_bss_info *current_bss; | 616 | struct brcms_bss_info *current_bss; |
611 | }; | 617 | }; |
612 | 618 | ||
@@ -631,7 +637,6 @@ extern u16 brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only, | |||
631 | extern void brcms_c_inval_dma_pkts(struct brcms_hardware *hw, | 637 | extern void brcms_c_inval_dma_pkts(struct brcms_hardware *hw, |
632 | struct ieee80211_sta *sta, | 638 | struct ieee80211_sta *sta, |
633 | void (*dma_callback_fn)); | 639 | void (*dma_callback_fn)); |
634 | extern void brcms_c_update_beacon(struct brcms_c_info *wlc); | ||
635 | extern void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend); | 640 | extern void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend); |
636 | extern int brcms_c_set_nmode(struct brcms_c_info *wlc); | 641 | extern int brcms_c_set_nmode(struct brcms_c_info *wlc); |
637 | extern void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc, | 642 | extern void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc, |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c index 91937c5025ce..b0fd807f2b2b 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c | |||
@@ -198,8 +198,6 @@ u16 read_radio_reg(struct brcms_phy *pi, u16 addr) | |||
198 | 198 | ||
199 | void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) | 199 | void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) |
200 | { | 200 | { |
201 | struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub); | ||
202 | |||
203 | if ((D11REV_GE(pi->sh->corerev, 24)) || | 201 | if ((D11REV_GE(pi->sh->corerev, 24)) || |
204 | (D11REV_IS(pi->sh->corerev, 22) | 202 | (D11REV_IS(pi->sh->corerev, 22) |
205 | && (pi->pubpi.phy_type != PHY_TYPE_SSN))) { | 203 | && (pi->pubpi.phy_type != PHY_TYPE_SSN))) { |
@@ -211,7 +209,7 @@ void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val) | |||
211 | bcma_write16(pi->d11core, D11REGOFFS(phy4wdatalo), val); | 209 | bcma_write16(pi->d11core, D11REGOFFS(phy4wdatalo), val); |
212 | } | 210 | } |
213 | 211 | ||
214 | if ((sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) && | 212 | if ((pi->d11core->bus->hosttype == BCMA_HOSTTYPE_PCI) && |
215 | (++pi->phy_wreg >= pi->phy_wreg_limit)) { | 213 | (++pi->phy_wreg >= pi->phy_wreg_limit)) { |
216 | (void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol)); | 214 | (void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol)); |
217 | pi->phy_wreg = 0; | 215 | pi->phy_wreg = 0; |
@@ -297,10 +295,8 @@ void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val) | |||
297 | if (addr == 0x72) | 295 | if (addr == 0x72) |
298 | (void)bcma_read16(pi->d11core, D11REGOFFS(phyregdata)); | 296 | (void)bcma_read16(pi->d11core, D11REGOFFS(phyregdata)); |
299 | #else | 297 | #else |
300 | struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub); | ||
301 | |||
302 | bcma_write32(pi->d11core, D11REGOFFS(phyregaddr), addr | (val << 16)); | 298 | bcma_write32(pi->d11core, D11REGOFFS(phyregaddr), addr | (val << 16)); |
303 | if ((sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) && | 299 | if ((pi->d11core->bus->hosttype == BCMA_HOSTTYPE_PCI) && |
304 | (++pi->phy_wreg >= pi->phy_wreg_limit)) { | 300 | (++pi->phy_wreg >= pi->phy_wreg_limit)) { |
305 | pi->phy_wreg = 0; | 301 | pi->phy_wreg = 0; |
306 | (void)bcma_read16(pi->d11core, D11REGOFFS(phyversion)); | 302 | (void)bcma_read16(pi->d11core, D11REGOFFS(phyversion)); |
@@ -374,7 +370,6 @@ struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp) | |||
374 | if (sh == NULL) | 370 | if (sh == NULL) |
375 | return NULL; | 371 | return NULL; |
376 | 372 | ||
377 | sh->sih = shp->sih; | ||
378 | sh->physhim = shp->physhim; | 373 | sh->physhim = shp->physhim; |
379 | sh->unit = shp->unit; | 374 | sh->unit = shp->unit; |
380 | sh->corerev = shp->corerev; | 375 | sh->corerev = shp->corerev; |
@@ -2911,29 +2906,24 @@ void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode) | |||
2911 | mod_phy_reg(pi, 0x44c, (0x1 << 2), (1) << 2); | 2906 | mod_phy_reg(pi, 0x44c, (0x1 << 2), (1) << 2); |
2912 | 2907 | ||
2913 | } | 2908 | } |
2914 | ai_cc_reg(pi->sh->sih, | 2909 | |
2915 | offsetof(struct chipcregs, gpiocontrol), | 2910 | bcma_chipco_gpio_control(&pi->d11core->bus->drv_cc, |
2916 | ~0x0, 0x0); | 2911 | 0x0, 0x0); |
2917 | ai_cc_reg(pi->sh->sih, | 2912 | bcma_chipco_gpio_out(&pi->d11core->bus->drv_cc, |
2918 | offsetof(struct chipcregs, gpioout), | 2913 | ~0x40, 0x40); |
2919 | 0x40, 0x40); | 2914 | bcma_chipco_gpio_outen(&pi->d11core->bus->drv_cc, |
2920 | ai_cc_reg(pi->sh->sih, | 2915 | ~0x40, 0x40); |
2921 | offsetof(struct chipcregs, gpioouten), | ||
2922 | 0x40, 0x40); | ||
2923 | } else { | 2916 | } else { |
2924 | mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2); | 2917 | mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2); |
2925 | 2918 | ||
2926 | mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2); | 2919 | mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2); |
2927 | 2920 | ||
2928 | ai_cc_reg(pi->sh->sih, | 2921 | bcma_chipco_gpio_out(&pi->d11core->bus->drv_cc, |
2929 | offsetof(struct chipcregs, gpioout), | 2922 | ~0x40, 0x00); |
2930 | 0x40, 0x00); | 2923 | bcma_chipco_gpio_outen(&pi->d11core->bus->drv_cc, |
2931 | ai_cc_reg(pi->sh->sih, | 2924 | ~0x40, 0x00); |
2932 | offsetof(struct chipcregs, gpioouten), | 2925 | bcma_chipco_gpio_control(&pi->d11core->bus->drv_cc, |
2933 | 0x40, 0x0); | 2926 | 0x0, 0x40); |
2934 | ai_cc_reg(pi->sh->sih, | ||
2935 | offsetof(struct chipcregs, gpiocontrol), | ||
2936 | ~0x0, 0x40); | ||
2937 | } | 2927 | } |
2938 | } | 2928 | } |
2939 | } | 2929 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h index af00e2c2b266..1dc767c31653 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h | |||
@@ -488,7 +488,6 @@ struct lcnphy_cal_results { | |||
488 | struct shared_phy { | 488 | struct shared_phy { |
489 | struct brcms_phy *phy_head; | 489 | struct brcms_phy *phy_head; |
490 | uint unit; | 490 | uint unit; |
491 | struct si_pub *sih; | ||
492 | struct phy_shim_info *physhim; | 491 | struct phy_shim_info *physhim; |
493 | uint corerev; | 492 | uint corerev; |
494 | u32 machwcap; | 493 | u32 machwcap; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c index 18d37645e2cd..3d6b16ce4687 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c | |||
@@ -1595,11 +1595,15 @@ wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi, u16 chanspec) | |||
1595 | if (channel == 1 || channel == 2 || channel == 3 || | 1595 | if (channel == 1 || channel == 2 || channel == 3 || |
1596 | channel == 4 || channel == 9 || | 1596 | channel == 4 || channel == 9 || |
1597 | channel == 10 || channel == 11 || channel == 12) { | 1597 | channel == 10 || channel == 11 || channel == 12) { |
1598 | si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03000c04); | 1598 | bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x2, |
1599 | si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x0); | 1599 | 0x03000c04); |
1600 | si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x200005c0); | 1600 | bcma_chipco_pll_maskset(&pi->d11core->bus->drv_cc, 0x3, |
1601 | 1601 | ~0x00ffffff, 0x0); | |
1602 | si_pmu_pllupd(pi->sh->sih); | 1602 | bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x4, |
1603 | 0x200005c0); | ||
1604 | |||
1605 | bcma_cc_set32(&pi->d11core->bus->drv_cc, BCMA_CC_PMU_CTL, | ||
1606 | BCMA_CC_PMU_CTL_PLL_UPD); | ||
1603 | write_phy_reg(pi, 0x942, 0); | 1607 | write_phy_reg(pi, 0x942, 0); |
1604 | wlc_lcnphy_txrx_spur_avoidance_mode(pi, false); | 1608 | wlc_lcnphy_txrx_spur_avoidance_mode(pi, false); |
1605 | pi_lcn->lcnphy_spurmod = false; | 1609 | pi_lcn->lcnphy_spurmod = false; |
@@ -1607,11 +1611,15 @@ wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi, u16 chanspec) | |||
1607 | 1611 | ||
1608 | write_phy_reg(pi, 0x425, 0x5907); | 1612 | write_phy_reg(pi, 0x425, 0x5907); |
1609 | } else { | 1613 | } else { |
1610 | si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03140c04); | 1614 | bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x2, |
1611 | si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x333333); | 1615 | 0x03140c04); |
1612 | si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x202c2820); | 1616 | bcma_chipco_pll_maskset(&pi->d11core->bus->drv_cc, 0x3, |
1613 | 1617 | ~0x00ffffff, 0x333333); | |
1614 | si_pmu_pllupd(pi->sh->sih); | 1618 | bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x4, |
1619 | 0x202c2820); | ||
1620 | |||
1621 | bcma_cc_set32(&pi->d11core->bus->drv_cc, BCMA_CC_PMU_CTL, | ||
1622 | BCMA_CC_PMU_CTL_PLL_UPD); | ||
1615 | write_phy_reg(pi, 0x942, 0); | 1623 | write_phy_reg(pi, 0x942, 0); |
1616 | wlc_lcnphy_txrx_spur_avoidance_mode(pi, true); | 1624 | wlc_lcnphy_txrx_spur_avoidance_mode(pi, true); |
1617 | 1625 | ||
@@ -4755,9 +4763,10 @@ void wlc_phy_init_lcnphy(struct brcms_phy *pi) | |||
4755 | 4763 | ||
4756 | wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec); | 4764 | wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec); |
4757 | 4765 | ||
4758 | si_pmu_regcontrol(pi->sh->sih, 0, 0xf, 0x9); | 4766 | bcma_chipco_regctl_maskset(&pi->d11core->bus->drv_cc, 0, ~0xf, 0x9); |
4759 | 4767 | ||
4760 | si_pmu_chipcontrol(pi->sh->sih, 0, 0xffffffff, 0x03CDDDDD); | 4768 | bcma_chipco_chipctl_maskset(&pi->d11core->bus->drv_cc, 0, 0x0, |
4769 | 0x03CDDDDD); | ||
4761 | 4770 | ||
4762 | if ((pi->sh->boardflags & BFL_FEM) | 4771 | if ((pi->sh->boardflags & BFL_FEM) |
4763 | && wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) | 4772 | && wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) |
@@ -4968,7 +4977,7 @@ bool wlc_phy_attach_lcnphy(struct brcms_phy *pi) | |||
4968 | pi->hwpwrctrl_capable = true; | 4977 | pi->hwpwrctrl_capable = true; |
4969 | } | 4978 | } |
4970 | 4979 | ||
4971 | pi->xtalfreq = si_pmu_alp_clock(pi->sh->sih); | 4980 | pi->xtalfreq = bcma_chipco_get_alp_clock(&pi->d11core->bus->drv_cc); |
4972 | pi_lcn->lcnphy_papd_rxGnCtrl_init = 0; | 4981 | pi_lcn->lcnphy_papd_rxGnCtrl_init = 0; |
4973 | 4982 | ||
4974 | pi->pi_fptr.init = wlc_phy_init_lcnphy; | 4983 | pi->pi_fptr.init = wlc_phy_init_lcnphy; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c index 65db9b7458dc..3e9f5b25be63 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c | |||
@@ -19321,14 +19321,13 @@ void wlc_phy_init_nphy(struct brcms_phy *pi) | |||
19321 | (pi->sh->chippkg == BCMA_PKG_ID_BCM4718))) { | 19321 | (pi->sh->chippkg == BCMA_PKG_ID_BCM4718))) { |
19322 | if ((pi->sh->boardflags & BFL_EXTLNA) && | 19322 | if ((pi->sh->boardflags & BFL_EXTLNA) && |
19323 | (CHSPEC_IS2G(pi->radio_chanspec))) | 19323 | (CHSPEC_IS2G(pi->radio_chanspec))) |
19324 | ai_cc_reg(pi->sh->sih, | 19324 | bcma_cc_set32(&pi->d11core->bus->drv_cc, |
19325 | offsetof(struct chipcregs, chipcontrol), | 19325 | BCMA_CC_CHIPCTL, 0x40); |
19326 | 0x40, 0x40); | ||
19327 | } | 19326 | } |
19328 | 19327 | ||
19329 | if ((!PHY_IPA(pi)) && (pi->sh->chip == BCMA_CHIP_ID_BCM5357)) | 19328 | if ((!PHY_IPA(pi)) && (pi->sh->chip == BCMA_CHIP_ID_BCM5357)) |
19330 | si_pmu_chipcontrol(pi->sh->sih, 1, CCTRL5357_EXTPA, | 19329 | bcma_chipco_chipctl_maskset(&pi->d11core->bus->drv_cc, 1, |
19331 | CCTRL5357_EXTPA); | 19330 | ~CCTRL5357_EXTPA, CCTRL5357_EXTPA); |
19332 | 19331 | ||
19333 | if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) && | 19332 | if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) && |
19334 | CHSPEC_IS40(pi->radio_chanspec)) { | 19333 | CHSPEC_IS40(pi->radio_chanspec)) { |
@@ -21133,7 +21132,6 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec, | |||
21133 | const struct nphy_sfo_cfg *ci) | 21132 | const struct nphy_sfo_cfg *ci) |
21134 | { | 21133 | { |
21135 | u16 val; | 21134 | u16 val; |
21136 | struct si_info *sii = container_of(pi->sh->sih, struct si_info, pub); | ||
21137 | 21135 | ||
21138 | val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand; | 21136 | val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand; |
21139 | if (CHSPEC_IS5G(chanspec) && !val) { | 21137 | if (CHSPEC_IS5G(chanspec) && !val) { |
@@ -21221,11 +21219,11 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec, | |||
21221 | 21219 | ||
21222 | if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) || | 21220 | if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) || |
21223 | (pi->sh->chip == BCMA_CHIP_ID_BCM43225)) { | 21221 | (pi->sh->chip == BCMA_CHIP_ID_BCM43225)) { |
21224 | bcma_pmu_spuravoid_pllupdate(&sii->icbus->drv_cc, | 21222 | bcma_pmu_spuravoid_pllupdate(&pi->d11core->bus->drv_cc, |
21225 | spuravoid); | 21223 | spuravoid); |
21226 | } else { | 21224 | } else { |
21227 | wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false); | 21225 | wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false); |
21228 | bcma_pmu_spuravoid_pllupdate(&sii->icbus->drv_cc, | 21226 | bcma_pmu_spuravoid_pllupdate(&pi->d11core->bus->drv_cc, |
21229 | spuravoid); | 21227 | spuravoid); |
21230 | wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true); | 21228 | wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true); |
21231 | } | 21229 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pmu.c b/drivers/net/wireless/brcm80211/brcmsmac/pmu.c index 7e9df566c733..71b80381f3ad 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/pmu.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/pmu.c | |||
@@ -115,60 +115,6 @@ u16 si_pmu_fast_pwrup_delay(struct si_pub *sih) | |||
115 | return (u16) delay; | 115 | return (u16) delay; |
116 | } | 116 | } |
117 | 117 | ||
118 | /* Read/write a chipcontrol reg */ | ||
119 | u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val) | ||
120 | { | ||
121 | ai_cc_reg(sih, offsetof(struct chipcregs, chipcontrol_addr), ~0, reg); | ||
122 | return ai_cc_reg(sih, offsetof(struct chipcregs, chipcontrol_data), | ||
123 | mask, val); | ||
124 | } | ||
125 | |||
126 | /* Read/write a regcontrol reg */ | ||
127 | u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val) | ||
128 | { | ||
129 | ai_cc_reg(sih, offsetof(struct chipcregs, regcontrol_addr), ~0, reg); | ||
130 | return ai_cc_reg(sih, offsetof(struct chipcregs, regcontrol_data), | ||
131 | mask, val); | ||
132 | } | ||
133 | |||
134 | /* Read/write a pllcontrol reg */ | ||
135 | u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val) | ||
136 | { | ||
137 | ai_cc_reg(sih, offsetof(struct chipcregs, pllcontrol_addr), ~0, reg); | ||
138 | return ai_cc_reg(sih, offsetof(struct chipcregs, pllcontrol_data), | ||
139 | mask, val); | ||
140 | } | ||
141 | |||
142 | /* PMU PLL update */ | ||
143 | void si_pmu_pllupd(struct si_pub *sih) | ||
144 | { | ||
145 | ai_cc_reg(sih, offsetof(struct chipcregs, pmucontrol), | ||
146 | PCTL_PLL_PLLCTL_UPD, PCTL_PLL_PLLCTL_UPD); | ||
147 | } | ||
148 | |||
149 | /* query alp/xtal clock frequency */ | ||
150 | u32 si_pmu_alp_clock(struct si_pub *sih) | ||
151 | { | ||
152 | u32 clock = ALP_CLOCK; | ||
153 | |||
154 | /* bail out with default */ | ||
155 | if (!(ai_get_cccaps(sih) & CC_CAP_PMU)) | ||
156 | return clock; | ||
157 | |||
158 | switch (ai_get_chip_id(sih)) { | ||
159 | case BCMA_CHIP_ID_BCM43224: | ||
160 | case BCMA_CHIP_ID_BCM43225: | ||
161 | case BCMA_CHIP_ID_BCM4313: | ||
162 | /* always 20Mhz */ | ||
163 | clock = 20000 * 1000; | ||
164 | break; | ||
165 | default: | ||
166 | break; | ||
167 | } | ||
168 | |||
169 | return clock; | ||
170 | } | ||
171 | |||
172 | u32 si_pmu_measure_alpclk(struct si_pub *sih) | 118 | u32 si_pmu_measure_alpclk(struct si_pub *sih) |
173 | { | 119 | { |
174 | struct si_info *sii = container_of(sih, struct si_info, pub); | 120 | struct si_info *sii = container_of(sih, struct si_info, pub); |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pmu.h b/drivers/net/wireless/brcm80211/brcmsmac/pmu.h index f7cff873578b..20e2012d5a3a 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/pmu.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/pmu.h | |||
@@ -21,12 +21,6 @@ | |||
21 | #include "types.h" | 21 | #include "types.h" |
22 | 22 | ||
23 | extern u16 si_pmu_fast_pwrup_delay(struct si_pub *sih); | 23 | extern u16 si_pmu_fast_pwrup_delay(struct si_pub *sih); |
24 | extern void si_pmu_sprom_enable(struct si_pub *sih, bool enable); | ||
25 | extern u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); | ||
26 | extern u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); | ||
27 | extern u32 si_pmu_alp_clock(struct si_pub *sih); | ||
28 | extern void si_pmu_pllupd(struct si_pub *sih); | ||
29 | extern u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val); | ||
30 | extern u32 si_pmu_measure_alpclk(struct si_pub *sih); | 24 | extern u32 si_pmu_measure_alpclk(struct si_pub *sih); |
31 | 25 | ||
32 | #endif /* _BRCM_PMU_H_ */ | 26 | #endif /* _BRCM_PMU_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h index b0f14b7b8616..d36ea5e1cc49 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h | |||
@@ -164,8 +164,6 @@ struct brcms_pub { | |||
164 | 164 | ||
165 | u8 cur_etheraddr[ETH_ALEN]; /* our local ethernet address */ | 165 | u8 cur_etheraddr[ETH_ALEN]; /* our local ethernet address */ |
166 | 166 | ||
167 | int bcmerror; /* last bcm error */ | ||
168 | |||
169 | u32 radio_disabled; /* bit vector for radio disabled reasons */ | 167 | u32 radio_disabled; /* bit vector for radio disabled reasons */ |
170 | 168 | ||
171 | u16 boardrev; /* version # of particular board */ | 169 | u16 boardrev; /* version # of particular board */ |
@@ -326,10 +324,25 @@ extern void brcms_c_set_shortslot_override(struct brcms_c_info *wlc, | |||
326 | s8 sslot_override); | 324 | s8 sslot_override); |
327 | extern void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, | 325 | extern void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, |
328 | u8 interval); | 326 | u8 interval); |
327 | extern u64 brcms_c_tsf_get(struct brcms_c_info *wlc); | ||
328 | extern void brcms_c_tsf_set(struct brcms_c_info *wlc, u64 tsf); | ||
329 | extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr); | 329 | extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr); |
330 | extern int brcms_c_get_tx_power(struct brcms_c_info *wlc); | 330 | extern int brcms_c_get_tx_power(struct brcms_c_info *wlc); |
331 | extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc); | 331 | extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc); |
332 | extern void brcms_c_mute(struct brcms_c_info *wlc, bool on); | 332 | extern void brcms_c_mute(struct brcms_c_info *wlc, bool on); |
333 | extern bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc); | 333 | extern bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc); |
334 | extern void brcms_c_start_station(struct brcms_c_info *wlc, u8 *addr); | ||
335 | extern void brcms_c_start_ap(struct brcms_c_info *wlc, u8 *addr, | ||
336 | const u8 *bssid, u8 *ssid, size_t ssid_len); | ||
337 | extern void brcms_c_start_adhoc(struct brcms_c_info *wlc, u8 *addr); | ||
338 | extern void brcms_c_update_beacon(struct brcms_c_info *wlc); | ||
339 | extern void brcms_c_set_new_beacon(struct brcms_c_info *wlc, | ||
340 | struct sk_buff *beacon, u16 tim_offset, | ||
341 | u16 dtim_period); | ||
342 | extern void brcms_c_set_new_probe_resp(struct brcms_c_info *wlc, | ||
343 | struct sk_buff *probe_resp); | ||
344 | extern void brcms_c_enable_probe_resp(struct brcms_c_info *wlc, bool enable); | ||
345 | extern void brcms_c_set_ssid(struct brcms_c_info *wlc, u8 *ssid, | ||
346 | size_t ssid_len); | ||
334 | 347 | ||
335 | #endif /* _BRCM_PUB_H_ */ | 348 | #endif /* _BRCM_PUB_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_wifi.h b/drivers/net/wireless/brcm80211/include/brcmu_wifi.h index c11a290a1edf..0505cc065e0d 100644 --- a/drivers/net/wireless/brcm80211/include/brcmu_wifi.h +++ b/drivers/net/wireless/brcm80211/include/brcmu_wifi.h | |||
@@ -32,8 +32,9 @@ | |||
32 | #define CH_20MHZ_APART 4 | 32 | #define CH_20MHZ_APART 4 |
33 | #define CH_10MHZ_APART 2 | 33 | #define CH_10MHZ_APART 2 |
34 | #define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */ | 34 | #define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */ |
35 | #define CH_MIN_2G_CHANNEL 1 | ||
35 | #define CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */ | 36 | #define CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */ |
36 | #define BRCM_MAX_2G_CHANNEL CH_MAX_2G_CHANNEL /* legacy define */ | 37 | #define CH_MIN_5G_CHANNEL 34 |
37 | 38 | ||
38 | /* bandstate array indices */ | 39 | /* bandstate array indices */ |
39 | #define BAND_2G_INDEX 0 /* wlc->bandstate[x] index */ | 40 | #define BAND_2G_INDEX 0 /* wlc->bandstate[x] index */ |
@@ -60,6 +61,7 @@ | |||
60 | #define WL_CHANSPEC_BW_10 0x0400 | 61 | #define WL_CHANSPEC_BW_10 0x0400 |
61 | #define WL_CHANSPEC_BW_20 0x0800 | 62 | #define WL_CHANSPEC_BW_20 0x0800 |
62 | #define WL_CHANSPEC_BW_40 0x0C00 | 63 | #define WL_CHANSPEC_BW_40 0x0C00 |
64 | #define WL_CHANSPEC_BW_80 0x2000 | ||
63 | 65 | ||
64 | #define WL_CHANSPEC_BAND_MASK 0xf000 | 66 | #define WL_CHANSPEC_BAND_MASK 0xf000 |
65 | #define WL_CHANSPEC_BAND_SHIFT 12 | 67 | #define WL_CHANSPEC_BAND_SHIFT 12 |
@@ -67,6 +69,25 @@ | |||
67 | #define WL_CHANSPEC_BAND_2G 0x2000 | 69 | #define WL_CHANSPEC_BAND_2G 0x2000 |
68 | #define INVCHANSPEC 255 | 70 | #define INVCHANSPEC 255 |
69 | 71 | ||
72 | #define WL_CHAN_VALID_HW (1 << 0) /* valid with current HW */ | ||
73 | #define WL_CHAN_VALID_SW (1 << 1) /* valid with country sett. */ | ||
74 | #define WL_CHAN_BAND_5G (1 << 2) /* 5GHz-band channel */ | ||
75 | #define WL_CHAN_RADAR (1 << 3) /* radar sensitive channel */ | ||
76 | #define WL_CHAN_INACTIVE (1 << 4) /* inactive due to radar */ | ||
77 | #define WL_CHAN_PASSIVE (1 << 5) /* channel in passive mode */ | ||
78 | #define WL_CHAN_RESTRICTED (1 << 6) /* restricted use channel */ | ||
79 | |||
80 | /* values for band specific 40MHz capabilities */ | ||
81 | #define WLC_N_BW_20ALL 0 | ||
82 | #define WLC_N_BW_40ALL 1 | ||
83 | #define WLC_N_BW_20IN2G_40IN5G 2 | ||
84 | |||
85 | /* band types */ | ||
86 | #define WLC_BAND_AUTO 0 /* auto-select */ | ||
87 | #define WLC_BAND_5G 1 /* 5 Ghz */ | ||
88 | #define WLC_BAND_2G 2 /* 2.4 Ghz */ | ||
89 | #define WLC_BAND_ALL 3 /* all bands */ | ||
90 | |||
70 | #define CHSPEC_CHANNEL(chspec) ((u8)((chspec) & WL_CHANSPEC_CHAN_MASK)) | 91 | #define CHSPEC_CHANNEL(chspec) ((u8)((chspec) & WL_CHANSPEC_CHAN_MASK)) |
71 | #define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) | 92 | #define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) |
72 | 93 | ||
@@ -79,10 +100,11 @@ | |||
79 | #define CHSPEC_IS20(chspec) \ | 100 | #define CHSPEC_IS20(chspec) \ |
80 | (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) | 101 | (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) |
81 | 102 | ||
82 | #ifndef CHSPEC_IS40 | ||
83 | #define CHSPEC_IS40(chspec) \ | 103 | #define CHSPEC_IS40(chspec) \ |
84 | (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) | 104 | (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) |
85 | #endif | 105 | |
106 | #define CHSPEC_IS80(chspec) \ | ||
107 | (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_80) | ||
86 | 108 | ||
87 | #define CHSPEC_IS5G(chspec) \ | 109 | #define CHSPEC_IS5G(chspec) \ |
88 | (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) | 110 | (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) |
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index 5b79819d7bed..3613b3a81ad2 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c | |||
@@ -4701,8 +4701,7 @@ out: | |||
4701 | } | 4701 | } |
4702 | EXPORT_SYMBOL(il_mac_change_interface); | 4702 | EXPORT_SYMBOL(il_mac_change_interface); |
4703 | 4703 | ||
4704 | void | 4704 | void il_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop) |
4705 | il_mac_flush(struct ieee80211_hw *hw, bool drop) | ||
4706 | { | 4705 | { |
4707 | struct il_priv *il = hw->priv; | 4706 | struct il_priv *il = hw->priv; |
4708 | unsigned long timeout = jiffies + msecs_to_jiffies(500); | 4707 | unsigned long timeout = jiffies + msecs_to_jiffies(500); |
diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index 10986aaf9085..f8246f2d88f9 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h | |||
@@ -1720,7 +1720,7 @@ void il_mac_remove_interface(struct ieee80211_hw *hw, | |||
1720 | struct ieee80211_vif *vif); | 1720 | struct ieee80211_vif *vif); |
1721 | int il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 1721 | int il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
1722 | enum nl80211_iftype newtype, bool newp2p); | 1722 | enum nl80211_iftype newtype, bool newp2p); |
1723 | void il_mac_flush(struct ieee80211_hw *hw, bool drop); | 1723 | void il_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop); |
1724 | int il_alloc_txq_mem(struct il_priv *il); | 1724 | int il_alloc_txq_mem(struct il_priv *il); |
1725 | void il_free_txq_mem(struct il_priv *il); | 1725 | void il_free_txq_mem(struct il_priv *il); |
1726 | 1726 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index c7cd2dffa5cd..a7294fa4d7e5 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c | |||
@@ -1100,7 +1100,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw, | |||
1100 | FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; | 1100 | FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; |
1101 | } | 1101 | } |
1102 | 1102 | ||
1103 | static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) | 1103 | static void iwlagn_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop) |
1104 | { | 1104 | { |
1105 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1105 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1106 | 1106 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 3ce4e9d5082d..498300577ac0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
@@ -1266,7 +1266,3 @@ module_param_named(auto_agg, iwlwifi_mod_params.auto_agg, | |||
1266 | bool, S_IRUGO); | 1266 | bool, S_IRUGO); |
1267 | MODULE_PARM_DESC(auto_agg, | 1267 | MODULE_PARM_DESC(auto_agg, |
1268 | "enable agg w/o check traffic load (default: enable)"); | 1268 | "enable agg w/o check traffic load (default: enable)"); |
1269 | |||
1270 | module_param_named(5ghz_disable, iwlwifi_mod_params.disable_5ghz, | ||
1271 | bool, S_IRUGO); | ||
1272 | MODULE_PARM_DESC(5ghz_disable, "disable 5GHz band (default: 0 [enabled])"); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h index 435618574240..c4c446d41eb0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h | |||
@@ -154,6 +154,19 @@ struct iwl_tlv_calib_ctrl { | |||
154 | __le32 event_trigger; | 154 | __le32 event_trigger; |
155 | } __packed; | 155 | } __packed; |
156 | 156 | ||
157 | enum iwl_fw_phy_cfg { | ||
158 | FW_PHY_CFG_RADIO_TYPE_POS = 0, | ||
159 | FW_PHY_CFG_RADIO_TYPE = 0x3 << FW_PHY_CFG_RADIO_TYPE_POS, | ||
160 | FW_PHY_CFG_RADIO_STEP_POS = 2, | ||
161 | FW_PHY_CFG_RADIO_STEP = 0x3 << FW_PHY_CFG_RADIO_STEP_POS, | ||
162 | FW_PHY_CFG_RADIO_DASH_POS = 4, | ||
163 | FW_PHY_CFG_RADIO_DASH = 0x3 << FW_PHY_CFG_RADIO_DASH_POS, | ||
164 | FW_PHY_CFG_TX_CHAIN_POS = 16, | ||
165 | FW_PHY_CFG_TX_CHAIN = 0xf << FW_PHY_CFG_TX_CHAIN_POS, | ||
166 | FW_PHY_CFG_RX_CHAIN_POS = 20, | ||
167 | FW_PHY_CFG_RX_CHAIN = 0xf << FW_PHY_CFG_RX_CHAIN_POS, | ||
168 | }; | ||
169 | |||
157 | /** | 170 | /** |
158 | * struct iwl_fw - variables associated with the firmware | 171 | * struct iwl_fw - variables associated with the firmware |
159 | * | 172 | * |
@@ -190,4 +203,16 @@ struct iwl_fw { | |||
190 | bool mvm_fw; | 203 | bool mvm_fw; |
191 | }; | 204 | }; |
192 | 205 | ||
206 | static inline u8 iwl_fw_valid_tx_ant(const struct iwl_fw *fw) | ||
207 | { | ||
208 | return (fw->phy_config & FW_PHY_CFG_TX_CHAIN) >> | ||
209 | FW_PHY_CFG_TX_CHAIN_POS; | ||
210 | } | ||
211 | |||
212 | static inline u8 iwl_fw_valid_rx_ant(const struct iwl_fw *fw) | ||
213 | { | ||
214 | return (fw->phy_config & FW_PHY_CFG_RX_CHAIN) >> | ||
215 | FW_PHY_CFG_RX_CHAIN_POS; | ||
216 | } | ||
217 | |||
193 | #endif /* __iwl_fw_h__ */ | 218 | #endif /* __iwl_fw_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h index 3cc39ffe8ba5..d6f6c37c09fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h | |||
@@ -103,7 +103,6 @@ enum iwl_power_level { | |||
103 | * @ant_coupling: antenna coupling in dB, default = 0 | 103 | * @ant_coupling: antenna coupling in dB, default = 0 |
104 | * @bt_ch_announce: BT channel inhibition, default = enable | 104 | * @bt_ch_announce: BT channel inhibition, default = enable |
105 | * @auto_agg: enable agg. without check, default = true | 105 | * @auto_agg: enable agg. without check, default = true |
106 | * @disable_5ghz: disable 5GHz capability, default = false | ||
107 | */ | 106 | */ |
108 | struct iwl_mod_params { | 107 | struct iwl_mod_params { |
109 | int sw_crypto; | 108 | int sw_crypto; |
@@ -120,7 +119,6 @@ struct iwl_mod_params { | |||
120 | int ant_coupling; | 119 | int ant_coupling; |
121 | bool bt_ch_announce; | 120 | bool bt_ch_announce; |
122 | bool auto_agg; | 121 | bool auto_agg; |
123 | bool disable_5ghz; | ||
124 | }; | 122 | }; |
125 | 123 | ||
126 | #endif /* #__iwl_modparams_h__ */ | 124 | #endif /* #__iwl_modparams_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-test.c b/drivers/net/wireless/iwlwifi/iwl-test.c index efff2986b5b4..5cfd55b86ed3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-test.c +++ b/drivers/net/wireless/iwlwifi/iwl-test.c | |||
@@ -272,7 +272,7 @@ static int iwl_test_fw_cmd(struct iwl_test *tst, struct nlattr **tb) | |||
272 | 272 | ||
273 | reply_len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | 273 | reply_len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; |
274 | skb = iwl_test_alloc_reply(tst, reply_len + 20); | 274 | skb = iwl_test_alloc_reply(tst, reply_len + 20); |
275 | reply_buf = kmalloc(reply_len, GFP_KERNEL); | 275 | reply_buf = kmemdup(&pkt->hdr, reply_len, GFP_KERNEL); |
276 | if (!skb || !reply_buf) { | 276 | if (!skb || !reply_buf) { |
277 | kfree_skb(skb); | 277 | kfree_skb(skb); |
278 | kfree(reply_buf); | 278 | kfree(reply_buf); |
@@ -280,7 +280,6 @@ static int iwl_test_fw_cmd(struct iwl_test *tst, struct nlattr **tb) | |||
280 | } | 280 | } |
281 | 281 | ||
282 | /* The reply is in a page, that we cannot send to user space. */ | 282 | /* The reply is in a page, that we cannot send to user space. */ |
283 | memcpy(reply_buf, &(pkt->hdr), reply_len); | ||
284 | iwl_free_resp(&cmd); | 283 | iwl_free_resp(&cmd); |
285 | 284 | ||
286 | if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND, | 285 | if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c index 47954deb6493..1700232aa166 100644 --- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c | |||
@@ -125,15 +125,15 @@ enum iwl_bt_kill_msk { | |||
125 | }; | 125 | }; |
126 | 126 | ||
127 | static const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = { | 127 | static const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = { |
128 | 0xffffffff, | 128 | [BT_KILL_MSK_DEFAULT] = 0xffff0000, |
129 | 0xfffffc00, | 129 | [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff, |
130 | 0, | 130 | [BT_KILL_MSK_REDUCED_TXPOW] = 0, |
131 | }; | 131 | }; |
132 | 132 | ||
133 | static const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = { | 133 | static const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = { |
134 | 0xffffffff, | 134 | [BT_KILL_MSK_DEFAULT] = 0xffff0000, |
135 | 0xfffffc00, | 135 | [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff, |
136 | 0, | 136 | [BT_KILL_MSK_REDUCED_TXPOW] = 0, |
137 | }; | 137 | }; |
138 | 138 | ||
139 | #define IWL_BT_DEFAULT_BOOST (0xf0f0f0f0) | 139 | #define IWL_BT_DEFAULT_BOOST (0xf0f0f0f0) |
@@ -188,6 +188,8 @@ static const __le32 iwl_concurrent_lookup[BT_COEX_LUT_SIZE] = { | |||
188 | 188 | ||
189 | /* BT Antenna Coupling Threshold (dB) */ | 189 | /* BT Antenna Coupling Threshold (dB) */ |
190 | #define IWL_BT_ANTENNA_COUPLING_THRESHOLD (35) | 190 | #define IWL_BT_ANTENNA_COUPLING_THRESHOLD (35) |
191 | #define IWL_BT_LOAD_FORCE_SISO_THRESHOLD (3) | ||
192 | |||
191 | 193 | ||
192 | int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | 194 | int iwl_send_bt_init_conf(struct iwl_mvm *mvm) |
193 | { | 195 | { |
@@ -201,8 +203,7 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | |||
201 | 203 | ||
202 | cmd.flags = iwlwifi_mod_params.bt_coex_active ? | 204 | cmd.flags = iwlwifi_mod_params.bt_coex_active ? |
203 | BT_COEX_NW : BT_COEX_DISABLE; | 205 | BT_COEX_NW : BT_COEX_DISABLE; |
204 | cmd.flags |= iwlwifi_mod_params.bt_ch_announce ? | 206 | cmd.flags |= iwlwifi_mod_params.bt_ch_announce ? BT_CH_PRIMARY_EN : 0; |
205 | BT_CH_PRIMARY_EN | BT_CH_SECONDARY_EN : 0; | ||
206 | cmd.flags |= BT_SYNC_2_BT_DISABLE; | 207 | cmd.flags |= BT_SYNC_2_BT_DISABLE; |
207 | 208 | ||
208 | cmd.valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE | | 209 | cmd.valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE | |
@@ -275,7 +276,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
275 | if (data->notif->bt_status) | 276 | if (data->notif->bt_status) |
276 | smps_mode = IEEE80211_SMPS_DYNAMIC; | 277 | smps_mode = IEEE80211_SMPS_DYNAMIC; |
277 | 278 | ||
278 | if (data->notif->bt_traffic_load) | 279 | if (data->notif->bt_traffic_load >= IWL_BT_LOAD_FORCE_SISO_THRESHOLD) |
279 | smps_mode = IEEE80211_SMPS_STATIC; | 280 | smps_mode = IEEE80211_SMPS_STATIC; |
280 | 281 | ||
281 | IWL_DEBUG_COEX(data->mvm, | 282 | IWL_DEBUG_COEX(data->mvm, |
@@ -327,7 +328,7 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, | |||
327 | return 0; | 328 | return 0; |
328 | 329 | ||
329 | IWL_DEBUG_COEX(mvm, | 330 | IWL_DEBUG_COEX(mvm, |
330 | "Udpate kill_msk: %d\n\t SCO %sactive A2DP %sactive SNIFF %sactive\n", | 331 | "Update kill_msk: %d - SCO %sactive A2DP %sactive SNIFF %sactive\n", |
331 | bt_kill_msk, | 332 | bt_kill_msk, |
332 | BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in", | 333 | BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in", |
333 | BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in", | 334 | BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in", |
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index d4578cefe445..bf087abe39f3 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c | |||
@@ -866,17 +866,13 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
866 | cpu_to_le32(IWL_WOWLAN_WAKEUP_PATTERN_MATCH); | 866 | cpu_to_le32(IWL_WOWLAN_WAKEUP_PATTERN_MATCH); |
867 | 867 | ||
868 | if (wowlan->rfkill_release) | 868 | if (wowlan->rfkill_release) |
869 | d3_cfg_cmd.wakeup_flags |= | 869 | wowlan_config_cmd.wakeup_filter |= |
870 | cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT); | 870 | cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT); |
871 | 871 | ||
872 | if (wowlan->tcp) { | 872 | if (wowlan->tcp) { |
873 | /* | 873 | /* |
874 | * The firmware currently doesn't really look at these, only | 874 | * Set the "link change" (really "link lost") flag as well |
875 | * the IWL_WOWLAN_WAKEUP_LINK_CHANGE bit. We have to set that | 875 | * since that implies losing the TCP connection. |
876 | * reason bit since losing the connection to the AP implies | ||
877 | * losing the TCP connection. | ||
878 | * Set the flags anyway as long as they exist, in case this | ||
879 | * will be changed in the firmware. | ||
880 | */ | 876 | */ |
881 | wowlan_config_cmd.wakeup_filter |= | 877 | wowlan_config_cmd.wakeup_filter |= |
882 | cpu_to_le32(IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS | | 878 | cpu_to_le32(IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS | |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h index 6d53850c5448..007a93b25bd7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h | |||
@@ -537,6 +537,12 @@ struct iwl_mac_beacon_cmd { | |||
537 | struct ieee80211_hdr frame[0]; | 537 | struct ieee80211_hdr frame[0]; |
538 | } __packed; | 538 | } __packed; |
539 | 539 | ||
540 | struct iwl_beacon_notif { | ||
541 | struct iwl_mvm_tx_resp beacon_notify_hdr; | ||
542 | __le64 tsf; | ||
543 | __le32 ibss_mgr_status; | ||
544 | } __packed; | ||
545 | |||
540 | /** | 546 | /** |
541 | * enum iwl_dump_control - dump (flush) control flags | 547 | * enum iwl_dump_control - dump (flush) control flags |
542 | * @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty | 548 | * @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index f8d7e88234e4..1073f2682221 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h | |||
@@ -151,6 +151,7 @@ enum { | |||
151 | 151 | ||
152 | SET_CALIB_DEFAULT_CMD = 0x8e, | 152 | SET_CALIB_DEFAULT_CMD = 0x8e, |
153 | 153 | ||
154 | BEACON_NOTIFICATION = 0x90, | ||
154 | BEACON_TEMPLATE_CMD = 0x91, | 155 | BEACON_TEMPLATE_CMD = 0x91, |
155 | TX_ANT_CONFIGURATION_CMD = 0x98, | 156 | TX_ANT_CONFIGURATION_CMD = 0x98, |
156 | BT_CONFIG = 0x9b, | 157 | BT_CONFIG = 0x9b, |
@@ -278,38 +279,7 @@ enum { | |||
278 | NVM_ACCESS_TARGET_EEPROM = 2, | 279 | NVM_ACCESS_TARGET_EEPROM = 2, |
279 | }; | 280 | }; |
280 | 281 | ||
281 | /** | 282 | /* Section types for NVM_ACCESS_CMD */ |
282 | * struct iwl_nvm_access_cmd_ver1 - Request the device to send the NVM. | ||
283 | * @op_code: 0 - read, 1 - write. | ||
284 | * @target: NVM_ACCESS_TARGET_*. should be 0 for read. | ||
285 | * @cache_refresh: 0 - None, 1- NVM. | ||
286 | * @offset: offset in the nvm data. | ||
287 | * @length: of the chunk. | ||
288 | * @data: empty on read, the NVM chunk on write | ||
289 | */ | ||
290 | struct iwl_nvm_access_cmd_ver1 { | ||
291 | u8 op_code; | ||
292 | u8 target; | ||
293 | u8 cache_refresh; | ||
294 | u8 reserved; | ||
295 | __le16 offset; | ||
296 | __le16 length; | ||
297 | u8 data[]; | ||
298 | } __packed; /* NVM_ACCESS_CMD_API_S_VER_1 */ | ||
299 | |||
300 | /** | ||
301 | * struct iwl_nvm_access_resp_ver1 - response to NVM_ACCESS_CMD | ||
302 | * @offset: the offset in the nvm data | ||
303 | * @length: of the chunk | ||
304 | * @data: the nvm chunk on when NVM_ACCESS_CMD was read, nothing on write | ||
305 | */ | ||
306 | struct iwl_nvm_access_resp_ver1 { | ||
307 | __le16 offset; | ||
308 | __le16 length; | ||
309 | u8 data[]; | ||
310 | } __packed; /* NVM_ACCESS_CMD_RESP_API_S_VER_1 */ | ||
311 | |||
312 | /* Section types for NVM_ACCESS_CMD version 2 */ | ||
313 | enum { | 283 | enum { |
314 | NVM_SECTION_TYPE_HW = 0, | 284 | NVM_SECTION_TYPE_HW = 0, |
315 | NVM_SECTION_TYPE_SW, | 285 | NVM_SECTION_TYPE_SW, |
@@ -330,7 +300,7 @@ enum { | |||
330 | * @length: in bytes, to read/write | 300 | * @length: in bytes, to read/write |
331 | * @data: if write operation, the data to write. On read its empty | 301 | * @data: if write operation, the data to write. On read its empty |
332 | */ | 302 | */ |
333 | struct iwl_nvm_access_cmd_ver2 { | 303 | struct iwl_nvm_access_cmd { |
334 | u8 op_code; | 304 | u8 op_code; |
335 | u8 target; | 305 | u8 target; |
336 | __le16 type; | 306 | __le16 type; |
@@ -347,7 +317,7 @@ struct iwl_nvm_access_cmd_ver2 { | |||
347 | * @status: 0 for success, fail otherwise | 317 | * @status: 0 for success, fail otherwise |
348 | * @data: if read operation, the data returned. Empty on write. | 318 | * @data: if read operation, the data returned. Empty on write. |
349 | */ | 319 | */ |
350 | struct iwl_nvm_access_resp_ver2 { | 320 | struct iwl_nvm_access_resp { |
351 | __le16 offset; | 321 | __le16 offset; |
352 | __le16 length; | 322 | __le16 length; |
353 | __le16 type; | 323 | __le16 type; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index 1006b3204e7b..e18c92dd60ec 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c | |||
@@ -114,7 +114,7 @@ static int iwl_send_tx_ant_cfg(struct iwl_mvm *mvm, u8 valid_tx_ant) | |||
114 | .valid = cpu_to_le32(valid_tx_ant), | 114 | .valid = cpu_to_le32(valid_tx_ant), |
115 | }; | 115 | }; |
116 | 116 | ||
117 | IWL_DEBUG_HC(mvm, "select valid tx ant: %u\n", valid_tx_ant); | 117 | IWL_DEBUG_FW(mvm, "select valid tx ant: %u\n", valid_tx_ant); |
118 | return iwl_mvm_send_cmd_pdu(mvm, TX_ANT_CONFIGURATION_CMD, CMD_SYNC, | 118 | return iwl_mvm_send_cmd_pdu(mvm, TX_ANT_CONFIGURATION_CMD, CMD_SYNC, |
119 | sizeof(tx_ant_cmd), &tx_ant_cmd); | 119 | sizeof(tx_ant_cmd), &tx_ant_cmd); |
120 | } | 120 | } |
@@ -134,9 +134,10 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, | |||
134 | alive_data->scd_base_addr = le32_to_cpu(palive->scd_base_ptr); | 134 | alive_data->scd_base_addr = le32_to_cpu(palive->scd_base_ptr); |
135 | 135 | ||
136 | alive_data->valid = le16_to_cpu(palive->status) == IWL_ALIVE_STATUS_OK; | 136 | alive_data->valid = le16_to_cpu(palive->status) == IWL_ALIVE_STATUS_OK; |
137 | IWL_DEBUG_FW(mvm, "Alive ucode status 0x%04x revision 0x%01X 0x%01X\n", | 137 | IWL_DEBUG_FW(mvm, |
138 | "Alive ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n", | ||
138 | le16_to_cpu(palive->status), palive->ver_type, | 139 | le16_to_cpu(palive->status), palive->ver_type, |
139 | palive->ver_subtype); | 140 | palive->ver_subtype, palive->flags); |
140 | 141 | ||
141 | return true; | 142 | return true; |
142 | } | 143 | } |
@@ -326,16 +327,14 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
326 | WARN_ON(ret); | 327 | WARN_ON(ret); |
327 | 328 | ||
328 | /* Send TX valid antennas before triggering calibrations */ | 329 | /* Send TX valid antennas before triggering calibrations */ |
329 | ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant); | 330 | ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw)); |
330 | if (ret) | 331 | if (ret) |
331 | goto error; | 332 | goto error; |
332 | 333 | ||
333 | /* WkP doesn't have all calibrations, need to set default values */ | 334 | /* need to set default values */ |
334 | if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) { | 335 | ret = iwl_set_default_calibrations(mvm); |
335 | ret = iwl_set_default_calibrations(mvm); | 336 | if (ret) |
336 | if (ret) | 337 | goto error; |
337 | goto error; | ||
338 | } | ||
339 | 338 | ||
340 | /* | 339 | /* |
341 | * Send phy configurations command to init uCode | 340 | * Send phy configurations command to init uCode |
@@ -414,7 +413,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm) | |||
414 | goto error; | 413 | goto error; |
415 | } | 414 | } |
416 | 415 | ||
417 | ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant); | 416 | ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw)); |
418 | if (ret) | 417 | if (ret) |
419 | goto error; | 418 | goto error; |
420 | 419 | ||
@@ -468,7 +467,7 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm) | |||
468 | goto error; | 467 | goto error; |
469 | } | 468 | } |
470 | 469 | ||
471 | ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant); | 470 | ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw)); |
472 | if (ret) | 471 | if (ret) |
473 | goto error; | 472 | goto error; |
474 | 473 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 2779235daa35..86e312a4f629 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | |||
@@ -196,7 +196,7 @@ u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm, | |||
196 | u32 qmask, ac; | 196 | u32 qmask, ac; |
197 | 197 | ||
198 | if (vif->type == NL80211_IFTYPE_P2P_DEVICE) | 198 | if (vif->type == NL80211_IFTYPE_P2P_DEVICE) |
199 | return BIT(IWL_OFFCHANNEL_QUEUE); | 199 | return BIT(IWL_MVM_OFFCHANNEL_QUEUE); |
200 | 200 | ||
201 | qmask = (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE) ? | 201 | qmask = (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE) ? |
202 | BIT(vif->cab_queue) : 0; | 202 | BIT(vif->cab_queue) : 0; |
@@ -692,7 +692,12 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm, | |||
692 | WARN_ON(vif->type != NL80211_IFTYPE_MONITOR); | 692 | WARN_ON(vif->type != NL80211_IFTYPE_MONITOR); |
693 | 693 | ||
694 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); | 694 | iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); |
695 | /* No other data to be filled */ | 695 | |
696 | cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROMISC | | ||
697 | MAC_FILTER_IN_CONTROL_AND_MGMT | | ||
698 | MAC_FILTER_IN_BEACON | | ||
699 | MAC_FILTER_IN_PROBE_REQUEST); | ||
700 | |||
696 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); | 701 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); |
697 | } | 702 | } |
698 | 703 | ||
@@ -798,7 +803,7 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, | |||
798 | TX_CMD_FLG_TSF); | 803 | TX_CMD_FLG_TSF); |
799 | 804 | ||
800 | mvm->mgmt_last_antenna_idx = | 805 | mvm->mgmt_last_antenna_idx = |
801 | iwl_mvm_next_antenna(mvm, mvm->nvm_data->valid_tx_ant, | 806 | iwl_mvm_next_antenna(mvm, iwl_fw_valid_tx_ant(mvm->fw), |
802 | mvm->mgmt_last_antenna_idx); | 807 | mvm->mgmt_last_antenna_idx); |
803 | 808 | ||
804 | beacon_cmd.tx.rate_n_flags = | 809 | beacon_cmd.tx.rate_n_flags = |
@@ -1013,3 +1018,22 @@ int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
1013 | mvmvif->uploaded = false; | 1018 | mvmvif->uploaded = false; |
1014 | return 0; | 1019 | return 0; |
1015 | } | 1020 | } |
1021 | |||
1022 | int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, | ||
1023 | struct iwl_rx_cmd_buffer *rxb, | ||
1024 | struct iwl_device_cmd *cmd) | ||
1025 | { | ||
1026 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1027 | struct iwl_beacon_notif *beacon = (void *)pkt->data; | ||
1028 | u16 status __maybe_unused = | ||
1029 | le16_to_cpu(beacon->beacon_notify_hdr.status.status); | ||
1030 | u32 rate __maybe_unused = | ||
1031 | le32_to_cpu(beacon->beacon_notify_hdr.initial_rate); | ||
1032 | |||
1033 | IWL_DEBUG_RX(mvm, "beacon status %#x retries:%d tsf:0x%16llX rate:%d\n", | ||
1034 | status & TX_STATUS_MSK, | ||
1035 | beacon->beacon_notify_hdr.failure_frame, | ||
1036 | le64_to_cpu(beacon->tsf), | ||
1037 | rate); | ||
1038 | return 0; | ||
1039 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 14dd5ee9a01e..3d193f8c33b6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -143,8 +143,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
143 | IEEE80211_HW_AMPDU_AGGREGATION | | 143 | IEEE80211_HW_AMPDU_AGGREGATION | |
144 | IEEE80211_HW_TIMING_BEACON_ONLY; | 144 | IEEE80211_HW_TIMING_BEACON_ONLY; |
145 | 145 | ||
146 | hw->queues = IWL_FIRST_AMPDU_QUEUE; | 146 | hw->queues = IWL_MVM_FIRST_AGG_QUEUE; |
147 | hw->offchannel_tx_hw_queue = IWL_OFFCHANNEL_QUEUE; | 147 | hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE; |
148 | hw->rate_control_algorithm = "iwl-mvm-rs"; | 148 | hw->rate_control_algorithm = "iwl-mvm-rs"; |
149 | 149 | ||
150 | /* | 150 | /* |
@@ -174,7 +174,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
174 | hw->wiphy->n_iface_combinations = | 174 | hw->wiphy->n_iface_combinations = |
175 | ARRAY_SIZE(iwl_mvm_iface_combinations); | 175 | ARRAY_SIZE(iwl_mvm_iface_combinations); |
176 | 176 | ||
177 | hw->wiphy->max_remain_on_channel_duration = 500; | 177 | hw->wiphy->max_remain_on_channel_duration = 10000; |
178 | hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; | 178 | hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; |
179 | 179 | ||
180 | /* Extract MAC address */ | 180 | /* Extract MAC address */ |
@@ -257,7 +257,7 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw, | |||
257 | goto drop; | 257 | goto drop; |
258 | } | 258 | } |
259 | 259 | ||
260 | if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_OFFCHANNEL_QUEUE && | 260 | if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE && |
261 | !test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status)) | 261 | !test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status)) |
262 | goto drop; | 262 | goto drop; |
263 | 263 | ||
@@ -1087,6 +1087,13 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, | |||
1087 | 1087 | ||
1088 | switch (cmd) { | 1088 | switch (cmd) { |
1089 | case SET_KEY: | 1089 | case SET_KEY: |
1090 | if (vif->type == NL80211_IFTYPE_AP && !sta) { | ||
1091 | /* GTK on AP interface is a TX-only key, return 0 */ | ||
1092 | ret = 0; | ||
1093 | key->hw_key_idx = STA_KEY_IDX_INVALID; | ||
1094 | break; | ||
1095 | } | ||
1096 | |||
1090 | IWL_DEBUG_MAC80211(mvm, "set hwcrypto key\n"); | 1097 | IWL_DEBUG_MAC80211(mvm, "set hwcrypto key\n"); |
1091 | ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, false); | 1098 | ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, false); |
1092 | if (ret) { | 1099 | if (ret) { |
@@ -1095,11 +1102,17 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, | |||
1095 | * can't add key for RX, but we don't need it | 1102 | * can't add key for RX, but we don't need it |
1096 | * in the device for TX so still return 0 | 1103 | * in the device for TX so still return 0 |
1097 | */ | 1104 | */ |
1105 | key->hw_key_idx = STA_KEY_IDX_INVALID; | ||
1098 | ret = 0; | 1106 | ret = 0; |
1099 | } | 1107 | } |
1100 | 1108 | ||
1101 | break; | 1109 | break; |
1102 | case DISABLE_KEY: | 1110 | case DISABLE_KEY: |
1111 | if (key->hw_key_idx == STA_KEY_IDX_INVALID) { | ||
1112 | ret = 0; | ||
1113 | break; | ||
1114 | } | ||
1115 | |||
1103 | IWL_DEBUG_MAC80211(mvm, "disable hwcrypto key\n"); | 1116 | IWL_DEBUG_MAC80211(mvm, "disable hwcrypto key\n"); |
1104 | ret = iwl_mvm_remove_sta_key(mvm, vif, sta, key); | 1117 | ret = iwl_mvm_remove_sta_key(mvm, vif, sta, key); |
1105 | break; | 1118 | break; |
@@ -1148,7 +1161,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, | |||
1148 | &chandef, 1, 1); | 1161 | &chandef, 1, 1); |
1149 | 1162 | ||
1150 | /* Schedule the time events */ | 1163 | /* Schedule the time events */ |
1151 | ret = iwl_mvm_start_p2p_roc(mvm, vif, duration); | 1164 | ret = iwl_mvm_start_p2p_roc(mvm, vif, duration, type); |
1152 | 1165 | ||
1153 | mutex_unlock(&mvm->mutex); | 1166 | mutex_unlock(&mvm->mutex); |
1154 | IWL_DEBUG_MAC80211(mvm, "leave\n"); | 1167 | IWL_DEBUG_MAC80211(mvm, "leave\n"); |
@@ -1252,6 +1265,7 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw, | |||
1252 | * will handle quota settings. | 1265 | * will handle quota settings. |
1253 | */ | 1266 | */ |
1254 | if (vif->type == NL80211_IFTYPE_MONITOR) { | 1267 | if (vif->type == NL80211_IFTYPE_MONITOR) { |
1268 | mvmvif->monitor_active = true; | ||
1255 | ret = iwl_mvm_update_quotas(mvm, vif); | 1269 | ret = iwl_mvm_update_quotas(mvm, vif); |
1256 | if (ret) | 1270 | if (ret) |
1257 | goto out_remove_binding; | 1271 | goto out_remove_binding; |
@@ -1282,15 +1296,16 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw, | |||
1282 | if (vif->type == NL80211_IFTYPE_AP) | 1296 | if (vif->type == NL80211_IFTYPE_AP) |
1283 | goto out_unlock; | 1297 | goto out_unlock; |
1284 | 1298 | ||
1285 | iwl_mvm_binding_remove_vif(mvm, vif); | ||
1286 | switch (vif->type) { | 1299 | switch (vif->type) { |
1287 | case NL80211_IFTYPE_MONITOR: | 1300 | case NL80211_IFTYPE_MONITOR: |
1288 | iwl_mvm_update_quotas(mvm, vif); | 1301 | mvmvif->monitor_active = false; |
1302 | iwl_mvm_update_quotas(mvm, NULL); | ||
1289 | break; | 1303 | break; |
1290 | default: | 1304 | default: |
1291 | break; | 1305 | break; |
1292 | } | 1306 | } |
1293 | 1307 | ||
1308 | iwl_mvm_binding_remove_vif(mvm, vif); | ||
1294 | out_unlock: | 1309 | out_unlock: |
1295 | mvmvif->phy_ctxt = NULL; | 1310 | mvmvif->phy_ctxt = NULL; |
1296 | mutex_unlock(&mvm->mutex); | 1311 | mutex_unlock(&mvm->mutex); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 203eb85e03d3..53d58968e30a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -90,10 +90,6 @@ enum iwl_mvm_tx_fifo { | |||
90 | IWL_MVM_TX_FIFO_VO, | 90 | IWL_MVM_TX_FIFO_VO, |
91 | }; | 91 | }; |
92 | 92 | ||
93 | /* Placeholder */ | ||
94 | #define IWL_OFFCHANNEL_QUEUE 8 | ||
95 | #define IWL_FIRST_AMPDU_QUEUE 11 | ||
96 | |||
97 | extern struct ieee80211_ops iwl_mvm_hw_ops; | 93 | extern struct ieee80211_ops iwl_mvm_hw_ops; |
98 | /** | 94 | /** |
99 | * struct iwl_mvm_mod_params - module parameters for iwlmvm | 95 | * struct iwl_mvm_mod_params - module parameters for iwlmvm |
@@ -161,6 +157,8 @@ enum iwl_power_scheme { | |||
161 | * @uploaded: indicates the MAC context has been added to the device | 157 | * @uploaded: indicates the MAC context has been added to the device |
162 | * @ap_active: indicates that ap context is configured, and that the interface | 158 | * @ap_active: indicates that ap context is configured, and that the interface |
163 | * should get quota etc. | 159 | * should get quota etc. |
160 | * @monitor_active: indicates that monitor context is configured, and that the | ||
161 | * interface should get quota etc. | ||
164 | * @queue_params: QoS params for this MAC | 162 | * @queue_params: QoS params for this MAC |
165 | * @bcast_sta: station used for broadcast packets. Used by the following | 163 | * @bcast_sta: station used for broadcast packets. Used by the following |
166 | * vifs: P2P_DEVICE, GO and AP. | 164 | * vifs: P2P_DEVICE, GO and AP. |
@@ -173,6 +171,7 @@ struct iwl_mvm_vif { | |||
173 | 171 | ||
174 | bool uploaded; | 172 | bool uploaded; |
175 | bool ap_active; | 173 | bool ap_active; |
174 | bool monitor_active; | ||
176 | 175 | ||
177 | u32 ap_beacon_time; | 176 | u32 ap_beacon_time; |
178 | 177 | ||
@@ -281,10 +280,7 @@ struct iwl_mvm { | |||
281 | atomic_t queue_stop_count[IWL_MAX_HW_QUEUES]; | 280 | atomic_t queue_stop_count[IWL_MAX_HW_QUEUES]; |
282 | 281 | ||
283 | struct iwl_nvm_data *nvm_data; | 282 | struct iwl_nvm_data *nvm_data; |
284 | /* eeprom blob for debugfs/testmode */ | 283 | /* NVM sections */ |
285 | u8 *eeprom_blob; | ||
286 | size_t eeprom_blob_size; | ||
287 | /* NVM sections for 7000 family */ | ||
288 | struct iwl_nvm_section nvm_sections[NVM_NUM_OF_SECTIONS]; | 284 | struct iwl_nvm_section nvm_sections[NVM_NUM_OF_SECTIONS]; |
289 | 285 | ||
290 | /* EEPROM MAC addresses */ | 286 | /* EEPROM MAC addresses */ |
@@ -451,6 +447,9 @@ u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm, | |||
451 | struct ieee80211_vif *vif); | 447 | struct ieee80211_vif *vif); |
452 | int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm, | 448 | int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm, |
453 | struct ieee80211_vif *vif); | 449 | struct ieee80211_vif *vif); |
450 | int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, | ||
451 | struct iwl_rx_cmd_buffer *rxb, | ||
452 | struct iwl_device_cmd *cmd); | ||
454 | 453 | ||
455 | /* Bindings */ | 454 | /* Bindings */ |
456 | int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 455 | int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index 93e3d0f174cc..b8ec02f89acc 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c | |||
@@ -77,26 +77,8 @@ static const int nvm_to_read[] = { | |||
77 | /* Default NVM size to read */ | 77 | /* Default NVM size to read */ |
78 | #define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024); | 78 | #define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024); |
79 | 79 | ||
80 | /* used to simplify the shared operations on NCM_ACCESS_CMD versions */ | 80 | static inline void iwl_nvm_fill_read(struct iwl_nvm_access_cmd *cmd, |
81 | union iwl_nvm_access_cmd { | 81 | u16 offset, u16 length, u16 section) |
82 | struct iwl_nvm_access_cmd_ver1 ver1; | ||
83 | struct iwl_nvm_access_cmd_ver2 ver2; | ||
84 | }; | ||
85 | union iwl_nvm_access_resp { | ||
86 | struct iwl_nvm_access_resp_ver1 ver1; | ||
87 | struct iwl_nvm_access_resp_ver2 ver2; | ||
88 | }; | ||
89 | |||
90 | static inline void iwl_nvm_fill_read_ver1(struct iwl_nvm_access_cmd_ver1 *cmd, | ||
91 | u16 offset, u16 length) | ||
92 | { | ||
93 | cmd->offset = cpu_to_le16(offset); | ||
94 | cmd->length = cpu_to_le16(length); | ||
95 | cmd->cache_refresh = 1; | ||
96 | } | ||
97 | |||
98 | static inline void iwl_nvm_fill_read_ver2(struct iwl_nvm_access_cmd_ver2 *cmd, | ||
99 | u16 offset, u16 length, u16 section) | ||
100 | { | 82 | { |
101 | cmd->offset = cpu_to_le16(offset); | 83 | cmd->offset = cpu_to_le16(offset); |
102 | cmd->length = cpu_to_le16(length); | 84 | cmd->length = cpu_to_le16(length); |
@@ -106,8 +88,8 @@ static inline void iwl_nvm_fill_read_ver2(struct iwl_nvm_access_cmd_ver2 *cmd, | |||
106 | static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, | 88 | static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, |
107 | u16 offset, u16 length, u8 *data) | 89 | u16 offset, u16 length, u8 *data) |
108 | { | 90 | { |
109 | union iwl_nvm_access_cmd nvm_access_cmd; | 91 | struct iwl_nvm_access_cmd nvm_access_cmd = {}; |
110 | union iwl_nvm_access_resp *nvm_resp; | 92 | struct iwl_nvm_access_resp *nvm_resp; |
111 | struct iwl_rx_packet *pkt; | 93 | struct iwl_rx_packet *pkt; |
112 | struct iwl_host_cmd cmd = { | 94 | struct iwl_host_cmd cmd = { |
113 | .id = NVM_ACCESS_CMD, | 95 | .id = NVM_ACCESS_CMD, |
@@ -117,18 +99,8 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, | |||
117 | int ret, bytes_read, offset_read; | 99 | int ret, bytes_read, offset_read; |
118 | u8 *resp_data; | 100 | u8 *resp_data; |
119 | 101 | ||
120 | memset(&nvm_access_cmd, 0, sizeof(nvm_access_cmd)); | 102 | iwl_nvm_fill_read(&nvm_access_cmd, offset, length, section); |
121 | 103 | cmd.len[0] = sizeof(struct iwl_nvm_access_cmd); | |
122 | /* TODO: not sure family should be the decider, maybe FW version? */ | ||
123 | if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) { | ||
124 | iwl_nvm_fill_read_ver2(&(nvm_access_cmd.ver2), | ||
125 | offset, length, section); | ||
126 | cmd.len[0] = sizeof(struct iwl_nvm_access_cmd_ver2); | ||
127 | } else { | ||
128 | iwl_nvm_fill_read_ver1(&(nvm_access_cmd.ver1), | ||
129 | offset, length); | ||
130 | cmd.len[0] = sizeof(struct iwl_nvm_access_cmd_ver1); | ||
131 | } | ||
132 | 104 | ||
133 | ret = iwl_mvm_send_cmd(mvm, &cmd); | 105 | ret = iwl_mvm_send_cmd(mvm, &cmd); |
134 | if (ret) | 106 | if (ret) |
@@ -144,17 +116,10 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, | |||
144 | 116 | ||
145 | /* Extract NVM response */ | 117 | /* Extract NVM response */ |
146 | nvm_resp = (void *)pkt->data; | 118 | nvm_resp = (void *)pkt->data; |
147 | if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) { | 119 | ret = le16_to_cpu(nvm_resp->status); |
148 | ret = le16_to_cpu(nvm_resp->ver2.status); | 120 | bytes_read = le16_to_cpu(nvm_resp->length); |
149 | bytes_read = le16_to_cpu(nvm_resp->ver2.length); | 121 | offset_read = le16_to_cpu(nvm_resp->offset); |
150 | offset_read = le16_to_cpu(nvm_resp->ver2.offset); | 122 | resp_data = nvm_resp->data; |
151 | resp_data = nvm_resp->ver2.data; | ||
152 | } else { | ||
153 | ret = le16_to_cpu(nvm_resp->ver1.length) <= 0; | ||
154 | bytes_read = le16_to_cpu(nvm_resp->ver1.length); | ||
155 | offset_read = le16_to_cpu(nvm_resp->ver1.offset); | ||
156 | resp_data = nvm_resp->ver1.data; | ||
157 | } | ||
158 | if (ret) { | 123 | if (ret) { |
159 | IWL_ERR(mvm, | 124 | IWL_ERR(mvm, |
160 | "NVM access command failed with status %d (device: %s)\n", | 125 | "NVM access command failed with status %d (device: %s)\n", |
@@ -194,17 +159,10 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section, | |||
194 | { | 159 | { |
195 | u16 length, offset = 0; | 160 | u16 length, offset = 0; |
196 | int ret; | 161 | int ret; |
197 | bool old_eeprom = mvm->cfg->device_family != IWL_DEVICE_FAMILY_7000; | ||
198 | 162 | ||
199 | /* Set nvm section read length */ | 163 | /* Set nvm section read length */ |
200 | length = IWL_NVM_DEFAULT_CHUNK_SIZE; | 164 | length = IWL_NVM_DEFAULT_CHUNK_SIZE; |
201 | 165 | ||
202 | /* | ||
203 | * if length is greater than EEPROM size, truncate it because uCode | ||
204 | * doesn't check it by itself, and exit the loop when reached. | ||
205 | */ | ||
206 | if (old_eeprom && length > mvm->cfg->base_params->eeprom_size) | ||
207 | length = mvm->cfg->base_params->eeprom_size; | ||
208 | ret = length; | 166 | ret = length; |
209 | 167 | ||
210 | /* Read the NVM until exhausted (reading less than requested) */ | 168 | /* Read the NVM until exhausted (reading less than requested) */ |
@@ -217,8 +175,6 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section, | |||
217 | return ret; | 175 | return ret; |
218 | } | 176 | } |
219 | offset += ret; | 177 | offset += ret; |
220 | if (old_eeprom && offset == mvm->cfg->base_params->eeprom_size) | ||
221 | break; | ||
222 | } | 178 | } |
223 | 179 | ||
224 | IWL_INFO(mvm, "NVM section %d read completed\n", section); | 180 | IWL_INFO(mvm, "NVM section %d read completed\n", section); |
@@ -252,63 +208,31 @@ int iwl_nvm_init(struct iwl_mvm *mvm) | |||
252 | int ret, i, section; | 208 | int ret, i, section; |
253 | u8 *nvm_buffer, *temp; | 209 | u8 *nvm_buffer, *temp; |
254 | 210 | ||
255 | if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) { | 211 | /* TODO: find correct NVM max size for a section */ |
256 | /* TODO: find correct NVM max size for a section */ | 212 | nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size, |
257 | nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size, | 213 | GFP_KERNEL); |
258 | GFP_KERNEL); | 214 | if (!nvm_buffer) |
259 | if (!nvm_buffer) | 215 | return -ENOMEM; |
260 | return -ENOMEM; | 216 | for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) { |
261 | for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) { | 217 | section = nvm_to_read[i]; |
262 | section = nvm_to_read[i]; | 218 | /* we override the constness for initial read */ |
263 | /* we override the constness for initial read */ | 219 | ret = iwl_nvm_read_section(mvm, section, nvm_buffer); |
264 | ret = iwl_nvm_read_section(mvm, section, nvm_buffer); | ||
265 | if (ret < 0) | ||
266 | break; | ||
267 | temp = kmemdup(nvm_buffer, ret, GFP_KERNEL); | ||
268 | if (!temp) { | ||
269 | ret = -ENOMEM; | ||
270 | break; | ||
271 | } | ||
272 | mvm->nvm_sections[section].data = temp; | ||
273 | mvm->nvm_sections[section].length = ret; | ||
274 | } | ||
275 | kfree(nvm_buffer); | ||
276 | if (ret < 0) | 220 | if (ret < 0) |
277 | return ret; | 221 | break; |
278 | } else { | 222 | temp = kmemdup(nvm_buffer, ret, GFP_KERNEL); |
279 | /* allocate eeprom */ | 223 | if (!temp) { |
280 | mvm->eeprom_blob_size = mvm->cfg->base_params->eeprom_size; | 224 | ret = -ENOMEM; |
281 | IWL_DEBUG_EEPROM(mvm->trans->dev, "NVM size = %zd\n", | 225 | break; |
282 | mvm->eeprom_blob_size); | ||
283 | mvm->eeprom_blob = kzalloc(mvm->eeprom_blob_size, GFP_KERNEL); | ||
284 | if (!mvm->eeprom_blob) | ||
285 | return -ENOMEM; | ||
286 | |||
287 | ret = iwl_nvm_read_section(mvm, 0, mvm->eeprom_blob); | ||
288 | if (ret != mvm->eeprom_blob_size) { | ||
289 | IWL_ERR(mvm, "Read partial NVM %d/%zd\n", | ||
290 | ret, mvm->eeprom_blob_size); | ||
291 | kfree(mvm->eeprom_blob); | ||
292 | mvm->eeprom_blob = NULL; | ||
293 | return -EINVAL; | ||
294 | } | 226 | } |
227 | mvm->nvm_sections[section].data = temp; | ||
228 | mvm->nvm_sections[section].length = ret; | ||
295 | } | 229 | } |
230 | kfree(nvm_buffer); | ||
231 | if (ret < 0) | ||
232 | return ret; | ||
296 | 233 | ||
297 | ret = 0; | 234 | ret = 0; |
298 | if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) | 235 | mvm->nvm_data = iwl_parse_nvm_sections(mvm); |
299 | mvm->nvm_data = iwl_parse_nvm_sections(mvm); | ||
300 | else | ||
301 | mvm->nvm_data = | ||
302 | iwl_parse_eeprom_data(mvm->trans->dev, | ||
303 | mvm->cfg, | ||
304 | mvm->eeprom_blob, | ||
305 | mvm->eeprom_blob_size); | ||
306 | |||
307 | if (!mvm->nvm_data) { | ||
308 | kfree(mvm->eeprom_blob); | ||
309 | mvm->eeprom_blob = NULL; | ||
310 | ret = -ENOMEM; | ||
311 | } | ||
312 | 236 | ||
313 | return ret; | 237 | return ret; |
314 | } | 238 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 828bdddd07e9..fe031d304d1e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
@@ -143,21 +143,12 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode) | |||
143 | u8 radio_cfg_type, radio_cfg_step, radio_cfg_dash; | 143 | u8 radio_cfg_type, radio_cfg_step, radio_cfg_dash; |
144 | u32 reg_val = 0; | 144 | u32 reg_val = 0; |
145 | 145 | ||
146 | /* | 146 | radio_cfg_type = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_TYPE) >> |
147 | * We can't upload the correct value to the INIT image | 147 | FW_PHY_CFG_RADIO_TYPE_POS; |
148 | * as we don't have nvm_data by that time. | 148 | radio_cfg_step = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_STEP) >> |
149 | * | 149 | FW_PHY_CFG_RADIO_STEP_POS; |
150 | * TODO: Figure out what we should do here | 150 | radio_cfg_dash = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_DASH) >> |
151 | */ | 151 | FW_PHY_CFG_RADIO_DASH_POS; |
152 | if (mvm->nvm_data) { | ||
153 | radio_cfg_type = mvm->nvm_data->radio_cfg_type; | ||
154 | radio_cfg_step = mvm->nvm_data->radio_cfg_step; | ||
155 | radio_cfg_dash = mvm->nvm_data->radio_cfg_dash; | ||
156 | } else { | ||
157 | radio_cfg_type = 0; | ||
158 | radio_cfg_step = 0; | ||
159 | radio_cfg_dash = 0; | ||
160 | } | ||
161 | 152 | ||
162 | /* SKU control */ | 153 | /* SKU control */ |
163 | reg_val |= CSR_HW_REV_STEP(mvm->trans->hw_rev) << | 154 | reg_val |= CSR_HW_REV_STEP(mvm->trans->hw_rev) << |
@@ -175,7 +166,6 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode) | |||
175 | 166 | ||
176 | /* silicon bits */ | 167 | /* silicon bits */ |
177 | reg_val |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI; | 168 | reg_val |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI; |
178 | reg_val |= CSR_HW_IF_CONFIG_REG_BIT_MAC_SI; | ||
179 | 169 | ||
180 | iwl_trans_set_bits_mask(mvm->trans, CSR_HW_IF_CONFIG_REG, | 170 | iwl_trans_set_bits_mask(mvm->trans, CSR_HW_IF_CONFIG_REG, |
181 | CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH | | 171 | CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH | |
@@ -231,6 +221,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { | |||
231 | RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false), | 221 | RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false), |
232 | 222 | ||
233 | RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true), | 223 | RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true), |
224 | RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, false), | ||
234 | 225 | ||
235 | RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false), | 226 | RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false), |
236 | RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false), | 227 | RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false), |
@@ -276,6 +267,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { | |||
276 | CMD(WEP_KEY), | 267 | CMD(WEP_KEY), |
277 | CMD(REPLY_RX_PHY_CMD), | 268 | CMD(REPLY_RX_PHY_CMD), |
278 | CMD(REPLY_RX_MPDU_CMD), | 269 | CMD(REPLY_RX_MPDU_CMD), |
270 | CMD(BEACON_NOTIFICATION), | ||
279 | CMD(BEACON_TEMPLATE_CMD), | 271 | CMD(BEACON_TEMPLATE_CMD), |
280 | CMD(STATISTICS_NOTIFICATION), | 272 | CMD(STATISTICS_NOTIFICATION), |
281 | CMD(TX_ANT_CONFIGURATION_CMD), | 273 | CMD(TX_ANT_CONFIGURATION_CMD), |
@@ -319,16 +311,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
319 | }; | 311 | }; |
320 | int err, scan_size; | 312 | int err, scan_size; |
321 | 313 | ||
322 | switch (cfg->device_family) { | ||
323 | case IWL_DEVICE_FAMILY_6030: | ||
324 | case IWL_DEVICE_FAMILY_6005: | ||
325 | case IWL_DEVICE_FAMILY_7000: | ||
326 | break; | ||
327 | default: | ||
328 | IWL_ERR(trans, "Trying to load mvm on an unsupported device\n"); | ||
329 | return NULL; | ||
330 | } | ||
331 | |||
332 | /******************************** | 314 | /******************************** |
333 | * 1. Allocating and configuring HW data | 315 | * 1. Allocating and configuring HW data |
334 | ********************************/ | 316 | ********************************/ |
@@ -444,7 +426,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
444 | out_free: | 426 | out_free: |
445 | iwl_phy_db_free(mvm->phy_db); | 427 | iwl_phy_db_free(mvm->phy_db); |
446 | kfree(mvm->scan_cmd); | 428 | kfree(mvm->scan_cmd); |
447 | kfree(mvm->eeprom_blob); | ||
448 | iwl_trans_stop_hw(trans, true); | 429 | iwl_trans_stop_hw(trans, true); |
449 | ieee80211_free_hw(mvm->hw); | 430 | ieee80211_free_hw(mvm->hw); |
450 | return NULL; | 431 | return NULL; |
@@ -466,7 +447,6 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) | |||
466 | iwl_phy_db_free(mvm->phy_db); | 447 | iwl_phy_db_free(mvm->phy_db); |
467 | mvm->phy_db = NULL; | 448 | mvm->phy_db = NULL; |
468 | 449 | ||
469 | kfree(mvm->eeprom_blob); | ||
470 | iwl_free_nvm_data(mvm->nvm_data); | 450 | iwl_free_nvm_data(mvm->nvm_data); |
471 | for (i = 0; i < NVM_NUM_OF_SECTIONS; i++) | 451 | for (i = 0; i < NVM_NUM_OF_SECTIONS; i++) |
472 | kfree(mvm->nvm_sections[i].data); | 452 | kfree(mvm->nvm_sections[i].data); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c index 0d537e035ef0..0f0b44eabd93 100644 --- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c | |||
@@ -142,7 +142,7 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm, | |||
142 | struct cfg80211_chan_def *chandef, | 142 | struct cfg80211_chan_def *chandef, |
143 | u8 chains_static, u8 chains_dynamic) | 143 | u8 chains_static, u8 chains_dynamic) |
144 | { | 144 | { |
145 | u8 valid_rx_chains, active_cnt, idle_cnt; | 145 | u8 active_cnt, idle_cnt; |
146 | 146 | ||
147 | /* Set the channel info data */ | 147 | /* Set the channel info data */ |
148 | cmd->ci.band = (chandef->chan->band == IEEE80211_BAND_2GHZ ? | 148 | cmd->ci.band = (chandef->chan->band == IEEE80211_BAND_2GHZ ? |
@@ -158,17 +158,16 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm, | |||
158 | * Need to add on chain noise calibration limitations, and | 158 | * Need to add on chain noise calibration limitations, and |
159 | * BT coex considerations. | 159 | * BT coex considerations. |
160 | */ | 160 | */ |
161 | valid_rx_chains = mvm->nvm_data->valid_rx_ant; | ||
162 | idle_cnt = chains_static; | 161 | idle_cnt = chains_static; |
163 | active_cnt = chains_dynamic; | 162 | active_cnt = chains_dynamic; |
164 | 163 | ||
165 | cmd->rxchain_info = cpu_to_le32(valid_rx_chains << | 164 | cmd->rxchain_info = cpu_to_le32(iwl_fw_valid_rx_ant(mvm->fw) << |
166 | PHY_RX_CHAIN_VALID_POS); | 165 | PHY_RX_CHAIN_VALID_POS); |
167 | cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS); | 166 | cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS); |
168 | cmd->rxchain_info |= cpu_to_le32(active_cnt << | 167 | cmd->rxchain_info |= cpu_to_le32(active_cnt << |
169 | PHY_RX_CHAIN_MIMO_CNT_POS); | 168 | PHY_RX_CHAIN_MIMO_CNT_POS); |
170 | 169 | ||
171 | cmd->txchain_info = cpu_to_le32(mvm->nvm_data->valid_tx_ant); | 170 | cmd->txchain_info = cpu_to_le32(iwl_fw_valid_tx_ant(mvm->fw)); |
172 | } | 171 | } |
173 | 172 | ||
174 | /* | 173 | /* |
diff --git a/drivers/net/wireless/iwlwifi/mvm/quota.c b/drivers/net/wireless/iwlwifi/mvm/quota.c index df85c49dc599..a1e3e923ea3e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/quota.c +++ b/drivers/net/wireless/iwlwifi/mvm/quota.c | |||
@@ -114,7 +114,8 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac, | |||
114 | data->n_interfaces[id]++; | 114 | data->n_interfaces[id]++; |
115 | break; | 115 | break; |
116 | case NL80211_IFTYPE_MONITOR: | 116 | case NL80211_IFTYPE_MONITOR: |
117 | data->n_interfaces[id]++; | 117 | if (mvmvif->monitor_active) |
118 | data->n_interfaces[id]++; | ||
118 | break; | 119 | break; |
119 | case NL80211_IFTYPE_P2P_DEVICE: | 120 | case NL80211_IFTYPE_P2P_DEVICE: |
120 | break; | 121 | break; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 0d3c76b29242..2157b0f8ced5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
@@ -74,7 +74,7 @@ | |||
74 | static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm) | 74 | static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm) |
75 | { | 75 | { |
76 | u16 rx_chain; | 76 | u16 rx_chain; |
77 | u8 rx_ant = mvm->nvm_data->valid_rx_ant; | 77 | u8 rx_ant = iwl_fw_valid_rx_ant(mvm->fw); |
78 | 78 | ||
79 | rx_chain = rx_ant << PHY_RX_CHAIN_VALID_POS; | 79 | rx_chain = rx_ant << PHY_RX_CHAIN_VALID_POS; |
80 | rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_MIMO_SEL_POS; | 80 | rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_MIMO_SEL_POS; |
@@ -115,7 +115,7 @@ iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum ieee80211_band band, | |||
115 | u32 tx_ant; | 115 | u32 tx_ant; |
116 | 116 | ||
117 | mvm->scan_last_antenna_idx = | 117 | mvm->scan_last_antenna_idx = |
118 | iwl_mvm_next_antenna(mvm, mvm->nvm_data->valid_tx_ant, | 118 | iwl_mvm_next_antenna(mvm, iwl_fw_valid_tx_ant(mvm->fw), |
119 | mvm->scan_last_antenna_idx); | 119 | mvm->scan_last_antenna_idx); |
120 | tx_ant = BIT(mvm->scan_last_antenna_idx) << RATE_MCS_ANT_POS; | 120 | tx_ant = BIT(mvm->scan_last_antenna_idx) << RATE_MCS_ANT_POS; |
121 | 121 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index c2c7f5176027..4dc934bed055 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c | |||
@@ -76,14 +76,12 @@ | |||
76 | #define TU_TO_JIFFIES(_tu) (usecs_to_jiffies((_tu) * 1024)) | 76 | #define TU_TO_JIFFIES(_tu) (usecs_to_jiffies((_tu) * 1024)) |
77 | #define MSEC_TO_TU(_msec) (_msec*1000/1024) | 77 | #define MSEC_TO_TU(_msec) (_msec*1000/1024) |
78 | 78 | ||
79 | /* For ROC use a TE type which has priority high enough to be scheduled when | 79 | /* |
80 | * there is a concurrent BSS or GO/AP. Currently, use a TE type that has | 80 | * For the high priority TE use a time event type that has similar priority to |
81 | * priority similar to the TE priority used for action scans by the FW. | 81 | * the FW's action scan priority. |
82 | * TODO: This needs to be changed, based on the reason for the ROC, i.e., use | ||
83 | * TE_P2P_DEVICE_DISCOVERABLE for remain on channel without mgmt skb, and use | ||
84 | * TE_P2P_DEVICE_ACTION_SCAN | ||
85 | */ | 82 | */ |
86 | #define IWL_MVM_ROC_TE_TYPE TE_P2P_DEVICE_ACTION_SCAN | 83 | #define IWL_MVM_ROC_TE_TYPE_NORMAL TE_P2P_DEVICE_DISCOVERABLE |
84 | #define IWL_MVM_ROC_TE_TYPE_MGMT_TX TE_P2P_CLIENT_ASSOC | ||
87 | 85 | ||
88 | void iwl_mvm_te_clear_data(struct iwl_mvm *mvm, | 86 | void iwl_mvm_te_clear_data(struct iwl_mvm *mvm, |
89 | struct iwl_mvm_time_event_data *te_data) | 87 | struct iwl_mvm_time_event_data *te_data) |
@@ -116,7 +114,7 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk) | |||
116 | * issue as it will have to complete before the next command is | 114 | * issue as it will have to complete before the next command is |
117 | * executed, and a new time event means a new command. | 115 | * executed, and a new time event means a new command. |
118 | */ | 116 | */ |
119 | iwl_mvm_flush_tx_path(mvm, BIT(IWL_OFFCHANNEL_QUEUE), false); | 117 | iwl_mvm_flush_tx_path(mvm, BIT(IWL_MVM_OFFCHANNEL_QUEUE), false); |
120 | } | 118 | } |
121 | 119 | ||
122 | static void iwl_mvm_roc_finished(struct iwl_mvm *mvm) | 120 | static void iwl_mvm_roc_finished(struct iwl_mvm *mvm) |
@@ -438,7 +436,7 @@ void iwl_mvm_stop_session_protection(struct iwl_mvm *mvm, | |||
438 | } | 436 | } |
439 | 437 | ||
440 | int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 438 | int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
441 | int duration) | 439 | int duration, enum ieee80211_roc_type type) |
442 | { | 440 | { |
443 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 441 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
444 | struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; | 442 | struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; |
@@ -459,21 +457,29 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
459 | time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD); | 457 | time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD); |
460 | time_cmd.id_and_color = | 458 | time_cmd.id_and_color = |
461 | cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); | 459 | cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); |
462 | time_cmd.id = cpu_to_le32(IWL_MVM_ROC_TE_TYPE); | 460 | |
461 | switch (type) { | ||
462 | case IEEE80211_ROC_TYPE_NORMAL: | ||
463 | time_cmd.id = cpu_to_le32(IWL_MVM_ROC_TE_TYPE_NORMAL); | ||
464 | break; | ||
465 | case IEEE80211_ROC_TYPE_MGMT_TX: | ||
466 | time_cmd.id = cpu_to_le32(IWL_MVM_ROC_TE_TYPE_MGMT_TX); | ||
467 | break; | ||
468 | default: | ||
469 | WARN_ONCE(1, "Got an invalid ROC type\n"); | ||
470 | return -EINVAL; | ||
471 | } | ||
463 | 472 | ||
464 | time_cmd.apply_time = cpu_to_le32(0); | 473 | time_cmd.apply_time = cpu_to_le32(0); |
465 | time_cmd.dep_policy = cpu_to_le32(TE_INDEPENDENT); | 474 | time_cmd.dep_policy = cpu_to_le32(TE_INDEPENDENT); |
466 | time_cmd.is_present = cpu_to_le32(1); | 475 | time_cmd.is_present = cpu_to_le32(1); |
467 | |||
468 | time_cmd.interval = cpu_to_le32(1); | 476 | time_cmd.interval = cpu_to_le32(1); |
469 | 477 | ||
470 | /* | 478 | /* |
471 | * IWL_MVM_ROC_TE_TYPE can have lower priority than other events | 479 | * The P2P Device TEs can have lower priority than other events |
472 | * that are being scheduled by the driver/fw, and thus it might not be | 480 | * that are being scheduled by the driver/fw, and thus it might not be |
473 | * scheduled. To improve the chances of it being scheduled, allow it to | 481 | * scheduled. To improve the chances of it being scheduled, allow them |
474 | * be fragmented. | 482 | * to be fragmented, and in addition allow them to be delayed. |
475 | * In addition, for the same reasons, allow to delay the scheduling of | ||
476 | * the time event. | ||
477 | */ | 483 | */ |
478 | time_cmd.max_frags = cpu_to_le32(MSEC_TO_TU(duration)/20); | 484 | time_cmd.max_frags = cpu_to_le32(MSEC_TO_TU(duration)/20); |
479 | time_cmd.max_delay = cpu_to_le32(MSEC_TO_TU(duration/2)); | 485 | time_cmd.max_delay = cpu_to_le32(MSEC_TO_TU(duration/2)); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.h b/drivers/net/wireless/iwlwifi/mvm/time-event.h index b36424eda361..f86c51065ed3 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.h +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.h | |||
@@ -162,6 +162,7 @@ int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm, | |||
162 | * that the vif type is NL80211_IFTYPE_P2P_DEVICE | 162 | * that the vif type is NL80211_IFTYPE_P2P_DEVICE |
163 | * @duration: the requested duration in millisecond for the fw to be on the | 163 | * @duration: the requested duration in millisecond for the fw to be on the |
164 | * channel that is bound to the vif. | 164 | * channel that is bound to the vif. |
165 | * @type: the remain on channel request type | ||
165 | * | 166 | * |
166 | * This function can be used to issue a remain on channel session, | 167 | * This function can be used to issue a remain on channel session, |
167 | * which means that the fw will stay in the channel for the request %duration | 168 | * which means that the fw will stay in the channel for the request %duration |
@@ -172,7 +173,7 @@ int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm, | |||
172 | * another notification to the driver. | 173 | * another notification to the driver. |
173 | */ | 174 | */ |
174 | int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 175 | int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
175 | int duration); | 176 | int duration, enum ieee80211_roc_type type); |
176 | 177 | ||
177 | /** | 178 | /** |
178 | * iwl_mvm_stop_p2p_roc - stop remain on channel for p2p device functionlity | 179 | * iwl_mvm_stop_p2p_roc - stop remain on channel for p2p device functionlity |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 0556d5e16f4e..0acc0bff43c7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
@@ -417,7 +417,7 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
417 | spin_unlock(&mvmsta->lock); | 417 | spin_unlock(&mvmsta->lock); |
418 | 418 | ||
419 | if (mvmsta->vif->type == NL80211_IFTYPE_AP && | 419 | if (mvmsta->vif->type == NL80211_IFTYPE_AP && |
420 | txq_id < IWL_FIRST_AMPDU_QUEUE) | 420 | txq_id < IWL_MVM_FIRST_AGG_QUEUE) |
421 | atomic_inc(&mvmsta->pending_frames); | 421 | atomic_inc(&mvmsta->pending_frames); |
422 | 422 | ||
423 | return 0; | 423 | return 0; |
@@ -606,7 +606,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
606 | info); | 606 | info); |
607 | 607 | ||
608 | /* Single frame failure in an AMPDU queue => send BAR */ | 608 | /* Single frame failure in an AMPDU queue => send BAR */ |
609 | if (txq_id >= IWL_FIRST_AMPDU_QUEUE && | 609 | if (txq_id >= IWL_MVM_FIRST_AGG_QUEUE && |
610 | !(info->flags & IEEE80211_TX_STAT_ACK)) | 610 | !(info->flags & IEEE80211_TX_STAT_ACK)) |
611 | info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | 611 | info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; |
612 | 612 | ||
@@ -619,7 +619,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
619 | ieee80211_tx_status_ni(mvm->hw, skb); | 619 | ieee80211_tx_status_ni(mvm->hw, skb); |
620 | } | 620 | } |
621 | 621 | ||
622 | if (txq_id >= IWL_FIRST_AMPDU_QUEUE) { | 622 | if (txq_id >= IWL_MVM_FIRST_AGG_QUEUE) { |
623 | /* If this is an aggregation queue, we use the ssn since: | 623 | /* If this is an aggregation queue, we use the ssn since: |
624 | * ssn = wifi seq_num % 256. | 624 | * ssn = wifi seq_num % 256. |
625 | * The seq_ctl is the sequence control of the packet to which | 625 | * The seq_ctl is the sequence control of the packet to which |
@@ -681,7 +681,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
681 | * If there are no pending frames for this STA, notify mac80211 that | 681 | * If there are no pending frames for this STA, notify mac80211 that |
682 | * this station can go to sleep in its STA table. | 682 | * this station can go to sleep in its STA table. |
683 | */ | 683 | */ |
684 | if (txq_id < IWL_FIRST_AMPDU_QUEUE && mvmsta && | 684 | if (txq_id < IWL_MVM_FIRST_AGG_QUEUE && mvmsta && |
685 | !WARN_ON(skb_freed > 1) && | 685 | !WARN_ON(skb_freed > 1) && |
686 | mvmsta->vif->type == NL80211_IFTYPE_AP && | 686 | mvmsta->vif->type == NL80211_IFTYPE_AP && |
687 | atomic_sub_and_test(skb_freed, &mvmsta->pending_frames)) { | 687 | atomic_sub_and_test(skb_freed, &mvmsta->pending_frames)) { |
@@ -750,7 +750,7 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm, | |||
750 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | 750 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); |
751 | struct ieee80211_sta *sta; | 751 | struct ieee80211_sta *sta; |
752 | 752 | ||
753 | if (WARN_ON_ONCE(SEQ_TO_QUEUE(sequence) < IWL_FIRST_AMPDU_QUEUE)) | 753 | if (WARN_ON_ONCE(SEQ_TO_QUEUE(sequence) < IWL_MVM_FIRST_AGG_QUEUE)) |
754 | return; | 754 | return; |
755 | 755 | ||
756 | if (WARN_ON_ONCE(tid == IWL_TID_NON_QOS)) | 756 | if (WARN_ON_ONCE(tid == IWL_TID_NON_QOS)) |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 282a5cafa913..68466ca80770 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
@@ -1564,8 +1564,11 @@ int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
1564 | if (test_bit(STATUS_FW_ERROR, &trans_pcie->status)) | 1564 | if (test_bit(STATUS_FW_ERROR, &trans_pcie->status)) |
1565 | return -EIO; | 1565 | return -EIO; |
1566 | 1566 | ||
1567 | if (test_bit(STATUS_RFKILL, &trans_pcie->status)) | 1567 | if (test_bit(STATUS_RFKILL, &trans_pcie->status)) { |
1568 | IWL_DEBUG_RF_KILL(trans, "Dropping CMD 0x%x: RF KILL\n", | ||
1569 | cmd->id); | ||
1568 | return -ERFKILL; | 1570 | return -ERFKILL; |
1571 | } | ||
1569 | 1572 | ||
1570 | if (cmd->flags & CMD_ASYNC) | 1573 | if (cmd->flags & CMD_ASYNC) |
1571 | return iwl_pcie_send_hcmd_async(trans, cmd); | 1574 | return iwl_pcie_send_hcmd_async(trans, cmd); |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 7490c4fc7177..0064d38276bf 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -964,6 +964,12 @@ static int mac80211_hwsim_change_interface(struct ieee80211_hw *hw, | |||
964 | newtype, vif->addr); | 964 | newtype, vif->addr); |
965 | hwsim_check_magic(vif); | 965 | hwsim_check_magic(vif); |
966 | 966 | ||
967 | /* | ||
968 | * interface may change from non-AP to AP in | ||
969 | * which case this needs to be set up again | ||
970 | */ | ||
971 | vif->cab_queue = 0; | ||
972 | |||
967 | return 0; | 973 | return 0; |
968 | } | 974 | } |
969 | 975 | ||
@@ -1389,7 +1395,7 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw, | |||
1389 | return 0; | 1395 | return 0; |
1390 | } | 1396 | } |
1391 | 1397 | ||
1392 | static void mac80211_hwsim_flush(struct ieee80211_hw *hw, bool drop) | 1398 | static void mac80211_hwsim_flush(struct ieee80211_hw *hw, u32 queues, bool drop) |
1393 | { | 1399 | { |
1394 | /* Not implemented, queues only on kernel side */ | 1400 | /* Not implemented, queues only on kernel side */ |
1395 | } | 1401 | } |
diff --git a/drivers/net/wireless/mwifiex/11ac.c b/drivers/net/wireless/mwifiex/11ac.c index cf43b3c29250..966a78f8e21a 100644 --- a/drivers/net/wireless/mwifiex/11ac.c +++ b/drivers/net/wireless/mwifiex/11ac.c | |||
@@ -259,3 +259,44 @@ int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv, | |||
259 | 259 | ||
260 | return ret_len; | 260 | return ret_len; |
261 | } | 261 | } |
262 | |||
263 | int mwifiex_cmd_11ac_cfg(struct mwifiex_private *priv, | ||
264 | struct host_cmd_ds_command *cmd, u16 cmd_action, | ||
265 | struct mwifiex_11ac_vht_cfg *cfg) | ||
266 | { | ||
267 | struct host_cmd_11ac_vht_cfg *vhtcfg = &cmd->params.vht_cfg; | ||
268 | |||
269 | cmd->command = cpu_to_le16(HostCmd_CMD_11AC_CFG); | ||
270 | cmd->size = cpu_to_le16(sizeof(struct host_cmd_11ac_vht_cfg) + | ||
271 | S_DS_GEN); | ||
272 | vhtcfg->action = cpu_to_le16(cmd_action); | ||
273 | vhtcfg->band_config = cfg->band_config; | ||
274 | vhtcfg->misc_config = cfg->misc_config; | ||
275 | vhtcfg->cap_info = cpu_to_le32(cfg->cap_info); | ||
276 | vhtcfg->mcs_tx_set = cpu_to_le32(cfg->mcs_tx_set); | ||
277 | vhtcfg->mcs_rx_set = cpu_to_le32(cfg->mcs_rx_set); | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | /* This function initializes the BlockACK setup information for given | ||
283 | * mwifiex_private structure for 11ac enabled networks. | ||
284 | */ | ||
285 | void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv) | ||
286 | { | ||
287 | priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT; | ||
288 | |||
289 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { | ||
290 | priv->add_ba_param.tx_win_size = | ||
291 | MWIFIEX_11AC_UAP_AMPDU_DEF_TXWINSIZE; | ||
292 | priv->add_ba_param.rx_win_size = | ||
293 | MWIFIEX_11AC_UAP_AMPDU_DEF_RXWINSIZE; | ||
294 | } else { | ||
295 | priv->add_ba_param.tx_win_size = | ||
296 | MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE; | ||
297 | priv->add_ba_param.rx_win_size = | ||
298 | MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE; | ||
299 | } | ||
300 | |||
301 | return; | ||
302 | } | ||
diff --git a/drivers/net/wireless/mwifiex/11ac.h b/drivers/net/wireless/mwifiex/11ac.h index 80fd1ba46200..7c2c69b5b3eb 100644 --- a/drivers/net/wireless/mwifiex/11ac.h +++ b/drivers/net/wireless/mwifiex/11ac.h | |||
@@ -20,7 +20,24 @@ | |||
20 | #ifndef _MWIFIEX_11AC_H_ | 20 | #ifndef _MWIFIEX_11AC_H_ |
21 | #define _MWIFIEX_11AC_H_ | 21 | #define _MWIFIEX_11AC_H_ |
22 | 22 | ||
23 | #define VHT_CFG_2GHZ BIT(0) | ||
24 | #define VHT_CFG_5GHZ BIT(1) | ||
25 | |||
26 | enum vht_cfg_misc_config { | ||
27 | VHT_CAP_TX_OPERATION = 1, | ||
28 | VHT_CAP_ASSOCIATION, | ||
29 | VHT_CAP_UAP_ONLY | ||
30 | }; | ||
31 | |||
32 | #define DEFAULT_VHT_MCS_SET 0xfffa | ||
33 | #define DISABLE_VHT_MCS_SET 0xffff | ||
34 | |||
35 | #define VHT_BW_80_160_80P80 BIT(2) | ||
36 | |||
23 | int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv, | 37 | int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv, |
24 | struct mwifiex_bssdescriptor *bss_desc, | 38 | struct mwifiex_bssdescriptor *bss_desc, |
25 | u8 **buffer); | 39 | u8 **buffer); |
40 | int mwifiex_cmd_11ac_cfg(struct mwifiex_private *priv, | ||
41 | struct host_cmd_ds_command *cmd, u16 cmd_action, | ||
42 | struct mwifiex_11ac_vht_cfg *cfg); | ||
26 | #endif /* _MWIFIEX_11AC_H_ */ | 43 | #endif /* _MWIFIEX_11AC_H_ */ |
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index 45f19716687e..41e9d25a2d8e 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c | |||
@@ -679,3 +679,25 @@ void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra) | |||
679 | 679 | ||
680 | return; | 680 | return; |
681 | } | 681 | } |
682 | |||
683 | /* This function initializes the BlockACK setup information for given | ||
684 | * mwifiex_private structure. | ||
685 | */ | ||
686 | void mwifiex_set_ba_params(struct mwifiex_private *priv) | ||
687 | { | ||
688 | priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT; | ||
689 | |||
690 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { | ||
691 | priv->add_ba_param.tx_win_size = | ||
692 | MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE; | ||
693 | priv->add_ba_param.rx_win_size = | ||
694 | MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE; | ||
695 | } else { | ||
696 | priv->add_ba_param.tx_win_size = | ||
697 | MWIFIEX_STA_AMPDU_DEF_TXWINSIZE; | ||
698 | priv->add_ba_param.rx_win_size = | ||
699 | MWIFIEX_STA_AMPDU_DEF_RXWINSIZE; | ||
700 | } | ||
701 | |||
702 | return; | ||
703 | } | ||
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 78c2bb8d3726..47012947a447 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -1374,6 +1374,18 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | |||
1374 | } | 1374 | } |
1375 | 1375 | ||
1376 | mwifiex_set_ht_params(priv, bss_cfg, params); | 1376 | mwifiex_set_ht_params(priv, bss_cfg, params); |
1377 | |||
1378 | if (priv->adapter->is_hw_11ac_capable) { | ||
1379 | mwifiex_set_vht_params(priv, bss_cfg, params); | ||
1380 | mwifiex_set_vht_width(priv, params->chandef.width, | ||
1381 | priv->ap_11ac_enabled); | ||
1382 | } | ||
1383 | |||
1384 | if (priv->ap_11ac_enabled) | ||
1385 | mwifiex_set_11ac_ba_params(priv); | ||
1386 | else | ||
1387 | mwifiex_set_ba_params(priv); | ||
1388 | |||
1377 | mwifiex_set_wmm_params(priv, bss_cfg, params); | 1389 | mwifiex_set_wmm_params(priv, bss_cfg, params); |
1378 | 1390 | ||
1379 | if (params->inactivity_timeout > 0) { | 1391 | if (params->inactivity_timeout > 0) { |
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 9a1302bd4c03..da469c336aa1 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c | |||
@@ -153,7 +153,7 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, | |||
153 | " or cmd size is 0, not sending\n"); | 153 | " or cmd size is 0, not sending\n"); |
154 | if (cmd_node->wait_q_enabled) | 154 | if (cmd_node->wait_q_enabled) |
155 | adapter->cmd_wait_q.status = -1; | 155 | adapter->cmd_wait_q.status = -1; |
156 | mwifiex_insert_cmd_to_free_q(adapter, cmd_node); | 156 | mwifiex_recycle_cmd_node(adapter, cmd_node); |
157 | return -1; | 157 | return -1; |
158 | } | 158 | } |
159 | 159 | ||
@@ -167,7 +167,7 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, | |||
167 | "DNLD_CMD: FW in reset state, ignore cmd %#x\n", | 167 | "DNLD_CMD: FW in reset state, ignore cmd %#x\n", |
168 | cmd_code); | 168 | cmd_code); |
169 | mwifiex_complete_cmd(adapter, cmd_node); | 169 | mwifiex_complete_cmd(adapter, cmd_node); |
170 | mwifiex_insert_cmd_to_free_q(adapter, cmd_node); | 170 | mwifiex_recycle_cmd_node(adapter, cmd_node); |
171 | return -1; | 171 | return -1; |
172 | } | 172 | } |
173 | 173 | ||
@@ -228,7 +228,7 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, | |||
228 | adapter->cmd_sent = false; | 228 | adapter->cmd_sent = false; |
229 | if (cmd_node->wait_q_enabled) | 229 | if (cmd_node->wait_q_enabled) |
230 | adapter->cmd_wait_q.status = -1; | 230 | adapter->cmd_wait_q.status = -1; |
231 | mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); | 231 | mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); |
232 | 232 | ||
233 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); | 233 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); |
234 | adapter->curr_cmd = NULL; | 234 | adapter->curr_cmd = NULL; |
@@ -632,6 +632,20 @@ mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, | |||
632 | spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags); | 632 | spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags); |
633 | } | 633 | } |
634 | 634 | ||
635 | /* This function reuses a command node. */ | ||
636 | void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter, | ||
637 | struct cmd_ctrl_node *cmd_node) | ||
638 | { | ||
639 | struct host_cmd_ds_command *host_cmd = (void *)cmd_node->cmd_skb->data; | ||
640 | |||
641 | mwifiex_insert_cmd_to_free_q(adapter, cmd_node); | ||
642 | |||
643 | atomic_dec(&adapter->cmd_pending); | ||
644 | dev_dbg(adapter->dev, "cmd: FREE_CMD: cmd=%#x, cmd_pending=%d\n", | ||
645 | le16_to_cpu(host_cmd->command), | ||
646 | atomic_read(&adapter->cmd_pending)); | ||
647 | } | ||
648 | |||
635 | /* | 649 | /* |
636 | * This function queues a command to the command pending queue. | 650 | * This function queues a command to the command pending queue. |
637 | * | 651 | * |
@@ -673,7 +687,9 @@ mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter, | |||
673 | list_add(&cmd_node->list, &adapter->cmd_pending_q); | 687 | list_add(&cmd_node->list, &adapter->cmd_pending_q); |
674 | spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); | 688 | spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); |
675 | 689 | ||
676 | dev_dbg(adapter->dev, "cmd: QUEUE_CMD: cmd=%#x is queued\n", command); | 690 | atomic_inc(&adapter->cmd_pending); |
691 | dev_dbg(adapter->dev, "cmd: QUEUE_CMD: cmd=%#x, cmd_pending=%d\n", | ||
692 | command, atomic_read(&adapter->cmd_pending)); | ||
677 | } | 693 | } |
678 | 694 | ||
679 | /* | 695 | /* |
@@ -783,7 +799,7 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) | |||
783 | if (adapter->curr_cmd->cmd_flag & CMD_F_CANCELED) { | 799 | if (adapter->curr_cmd->cmd_flag & CMD_F_CANCELED) { |
784 | dev_err(adapter->dev, "CMD_RESP: %#x been canceled\n", | 800 | dev_err(adapter->dev, "CMD_RESP: %#x been canceled\n", |
785 | le16_to_cpu(resp->command)); | 801 | le16_to_cpu(resp->command)); |
786 | mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); | 802 | mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); |
787 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); | 803 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); |
788 | adapter->curr_cmd = NULL; | 804 | adapter->curr_cmd = NULL; |
789 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); | 805 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); |
@@ -833,7 +849,7 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) | |||
833 | if (adapter->curr_cmd->wait_q_enabled) | 849 | if (adapter->curr_cmd->wait_q_enabled) |
834 | adapter->cmd_wait_q.status = -1; | 850 | adapter->cmd_wait_q.status = -1; |
835 | 851 | ||
836 | mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); | 852 | mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); |
837 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); | 853 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); |
838 | adapter->curr_cmd = NULL; | 854 | adapter->curr_cmd = NULL; |
839 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); | 855 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); |
@@ -865,8 +881,7 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) | |||
865 | if (adapter->curr_cmd->wait_q_enabled) | 881 | if (adapter->curr_cmd->wait_q_enabled) |
866 | adapter->cmd_wait_q.status = ret; | 882 | adapter->cmd_wait_q.status = ret; |
867 | 883 | ||
868 | /* Clean up and put current command back to cmd_free_q */ | 884 | mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); |
869 | mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); | ||
870 | 885 | ||
871 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); | 886 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); |
872 | adapter->curr_cmd = NULL; | 887 | adapter->curr_cmd = NULL; |
@@ -993,7 +1008,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) | |||
993 | mwifiex_complete_cmd(adapter, cmd_node); | 1008 | mwifiex_complete_cmd(adapter, cmd_node); |
994 | cmd_node->wait_q_enabled = false; | 1009 | cmd_node->wait_q_enabled = false; |
995 | } | 1010 | } |
996 | mwifiex_insert_cmd_to_free_q(adapter, cmd_node); | 1011 | mwifiex_recycle_cmd_node(adapter, cmd_node); |
997 | spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); | 1012 | spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); |
998 | } | 1013 | } |
999 | spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); | 1014 | spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); |
@@ -1040,7 +1055,7 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) | |||
1040 | cmd_node = adapter->curr_cmd; | 1055 | cmd_node = adapter->curr_cmd; |
1041 | cmd_node->wait_q_enabled = false; | 1056 | cmd_node->wait_q_enabled = false; |
1042 | cmd_node->cmd_flag |= CMD_F_CANCELED; | 1057 | cmd_node->cmd_flag |= CMD_F_CANCELED; |
1043 | mwifiex_insert_cmd_to_free_q(adapter, cmd_node); | 1058 | mwifiex_recycle_cmd_node(adapter, cmd_node); |
1044 | mwifiex_complete_cmd(adapter, adapter->curr_cmd); | 1059 | mwifiex_complete_cmd(adapter, adapter->curr_cmd); |
1045 | adapter->curr_cmd = NULL; | 1060 | adapter->curr_cmd = NULL; |
1046 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); | 1061 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); |
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index e8a569aaa2e8..94cc09d48444 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h | |||
@@ -41,8 +41,15 @@ | |||
41 | #define MWIFIEX_MAX_TX_BASTREAM_SUPPORTED 2 | 41 | #define MWIFIEX_MAX_TX_BASTREAM_SUPPORTED 2 |
42 | #define MWIFIEX_MAX_RX_BASTREAM_SUPPORTED 16 | 42 | #define MWIFIEX_MAX_RX_BASTREAM_SUPPORTED 16 |
43 | 43 | ||
44 | #define MWIFIEX_AMPDU_DEF_TXWINSIZE 32 | 44 | #define MWIFIEX_STA_AMPDU_DEF_TXWINSIZE 16 |
45 | #define MWIFIEX_AMPDU_DEF_RXWINSIZE 16 | 45 | #define MWIFIEX_STA_AMPDU_DEF_RXWINSIZE 32 |
46 | #define MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE 32 | ||
47 | #define MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE 16 | ||
48 | #define MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE 32 | ||
49 | #define MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE 48 | ||
50 | #define MWIFIEX_11AC_UAP_AMPDU_DEF_TXWINSIZE 48 | ||
51 | #define MWIFIEX_11AC_UAP_AMPDU_DEF_RXWINSIZE 32 | ||
52 | |||
46 | #define MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT 0xffff | 53 | #define MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT 0xffff |
47 | 54 | ||
48 | #define MWIFIEX_RATE_BITMAP_MCS0 32 | 55 | #define MWIFIEX_RATE_BITMAP_MCS0 32 |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 57c5defe1f9d..1f7578d553ec 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -295,6 +295,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
295 | #define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa | 295 | #define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa |
296 | #define HostCmd_CMD_MGMT_FRAME_REG 0x010c | 296 | #define HostCmd_CMD_MGMT_FRAME_REG 0x010c |
297 | #define HostCmd_CMD_REMAIN_ON_CHAN 0x010d | 297 | #define HostCmd_CMD_REMAIN_ON_CHAN 0x010d |
298 | #define HostCmd_CMD_11AC_CFG 0x0112 | ||
298 | 299 | ||
299 | #define PROTOCOL_NO_SECURITY 0x01 | 300 | #define PROTOCOL_NO_SECURITY 0x01 |
300 | #define PROTOCOL_STATIC_WEP 0x02 | 301 | #define PROTOCOL_STATIC_WEP 0x02 |
@@ -1363,6 +1364,15 @@ struct host_cmd_ds_sys_config { | |||
1363 | u8 tlv[0]; | 1364 | u8 tlv[0]; |
1364 | }; | 1365 | }; |
1365 | 1366 | ||
1367 | struct host_cmd_11ac_vht_cfg { | ||
1368 | __le16 action; | ||
1369 | u8 band_config; | ||
1370 | u8 misc_config; | ||
1371 | __le32 cap_info; | ||
1372 | __le32 mcs_tx_set; | ||
1373 | __le32 mcs_rx_set; | ||
1374 | } __packed; | ||
1375 | |||
1366 | struct host_cmd_tlv_akmp { | 1376 | struct host_cmd_tlv_akmp { |
1367 | struct host_cmd_tlv tlv; | 1377 | struct host_cmd_tlv tlv; |
1368 | __le16 key_mgmt; | 1378 | __le16 key_mgmt; |
@@ -1620,6 +1630,7 @@ struct host_cmd_ds_command { | |||
1620 | struct host_cmd_ds_802_11_eeprom_access eeprom; | 1630 | struct host_cmd_ds_802_11_eeprom_access eeprom; |
1621 | struct host_cmd_ds_802_11_subsc_evt subsc_evt; | 1631 | struct host_cmd_ds_802_11_subsc_evt subsc_evt; |
1622 | struct host_cmd_ds_sys_config uap_sys_config; | 1632 | struct host_cmd_ds_sys_config uap_sys_config; |
1633 | struct host_cmd_11ac_vht_cfg vht_cfg; | ||
1623 | } params; | 1634 | } params; |
1624 | } __packed; | 1635 | } __packed; |
1625 | 1636 | ||
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index daf8801cecd2..42d7f0adf9bd 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c | |||
@@ -533,10 +533,8 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) | |||
533 | if (!adapter->priv[i]) | 533 | if (!adapter->priv[i]) |
534 | continue; | 534 | continue; |
535 | priv = adapter->priv[i]; | 535 | priv = adapter->priv[i]; |
536 | for (j = 0; j < MAX_NUM_TID; ++j) { | 536 | for (j = 0; j < MAX_NUM_TID; ++j) |
537 | INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[j].ra_list); | 537 | INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[j].ra_list); |
538 | spin_lock_init(&priv->wmm.tid_tbl_ptr[j].tid_tbl_lock); | ||
539 | } | ||
540 | INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr); | 538 | INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr); |
541 | INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); | 539 | INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); |
542 | INIT_LIST_HEAD(&priv->sta_list); | 540 | INIT_LIST_HEAD(&priv->sta_list); |
@@ -713,7 +711,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) | |||
713 | if (adapter->curr_cmd) { | 711 | if (adapter->curr_cmd) { |
714 | dev_warn(adapter->dev, "curr_cmd is still in processing\n"); | 712 | dev_warn(adapter->dev, "curr_cmd is still in processing\n"); |
715 | del_timer(&adapter->cmd_timer); | 713 | del_timer(&adapter->cmd_timer); |
716 | mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); | 714 | mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); |
717 | adapter->curr_cmd = NULL; | 715 | adapter->curr_cmd = NULL; |
718 | } | 716 | } |
719 | 717 | ||
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index 91d522c746ed..7f27e45680b5 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h | |||
@@ -272,6 +272,14 @@ struct mwifiex_ds_pm_cfg { | |||
272 | } param; | 272 | } param; |
273 | }; | 273 | }; |
274 | 274 | ||
275 | struct mwifiex_11ac_vht_cfg { | ||
276 | u8 band_config; | ||
277 | u8 misc_config; | ||
278 | u32 cap_info; | ||
279 | u32 mcs_tx_set; | ||
280 | u32 mcs_rx_set; | ||
281 | }; | ||
282 | |||
275 | struct mwifiex_ds_11n_tx_cfg { | 283 | struct mwifiex_ds_11n_tx_cfg { |
276 | u16 tx_htcap; | 284 | u16 tx_htcap; |
277 | u16 tx_htinfo; | 285 | u16 tx_htinfo; |
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 2fe0ceba4400..6bcb66e6e97c 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c | |||
@@ -1295,6 +1295,14 @@ int mwifiex_associate(struct mwifiex_private *priv, | |||
1295 | (bss_desc->bss_mode != NL80211_IFTYPE_STATION)) | 1295 | (bss_desc->bss_mode != NL80211_IFTYPE_STATION)) |
1296 | return -1; | 1296 | return -1; |
1297 | 1297 | ||
1298 | if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && | ||
1299 | !bss_desc->disable_11n && !bss_desc->disable_11ac && | ||
1300 | (priv->adapter->config_bands & BAND_GAC || | ||
1301 | priv->adapter->config_bands & BAND_AAC)) | ||
1302 | mwifiex_set_11ac_ba_params(priv); | ||
1303 | else | ||
1304 | mwifiex_set_ba_params(priv); | ||
1305 | |||
1298 | memcpy(¤t_bssid, | 1306 | memcpy(¤t_bssid, |
1299 | &priv->curr_bss_params.bss_descriptor.mac_address, | 1307 | &priv->curr_bss_params.bss_descriptor.mac_address, |
1300 | sizeof(current_bssid)); | 1308 | sizeof(current_bssid)); |
@@ -1323,6 +1331,13 @@ mwifiex_adhoc_start(struct mwifiex_private *priv, | |||
1323 | dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %d\n", | 1331 | dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %d\n", |
1324 | priv->curr_bss_params.band); | 1332 | priv->curr_bss_params.band); |
1325 | 1333 | ||
1334 | if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && | ||
1335 | (priv->adapter->config_bands & BAND_GAC || | ||
1336 | priv->adapter->config_bands & BAND_AAC)) | ||
1337 | mwifiex_set_11ac_ba_params(priv); | ||
1338 | else | ||
1339 | mwifiex_set_ba_params(priv); | ||
1340 | |||
1326 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_AD_HOC_START, | 1341 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_AD_HOC_START, |
1327 | HostCmd_ACT_GEN_SET, 0, adhoc_ssid); | 1342 | HostCmd_ACT_GEN_SET, 0, adhoc_ssid); |
1328 | } | 1343 | } |
@@ -1356,6 +1371,14 @@ int mwifiex_adhoc_join(struct mwifiex_private *priv, | |||
1356 | return -1; | 1371 | return -1; |
1357 | } | 1372 | } |
1358 | 1373 | ||
1374 | if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && | ||
1375 | !bss_desc->disable_11n && !bss_desc->disable_11ac && | ||
1376 | (priv->adapter->config_bands & BAND_GAC || | ||
1377 | priv->adapter->config_bands & BAND_AAC)) | ||
1378 | mwifiex_set_11ac_ba_params(priv); | ||
1379 | else | ||
1380 | mwifiex_set_ba_params(priv); | ||
1381 | |||
1359 | dev_dbg(priv->adapter->dev, "info: curr_bss_params.channel = %d\n", | 1382 | dev_dbg(priv->adapter->dev, "info: curr_bss_params.channel = %d\n", |
1360 | priv->curr_bss_params.bss_descriptor.channel); | 1383 | priv->curr_bss_params.bss_descriptor.channel); |
1361 | dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %c\n", | 1384 | dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %c\n", |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 7255289a48ac..b7484efc9443 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -213,15 +213,12 @@ struct mwifiex_ra_list_tbl { | |||
213 | 213 | ||
214 | struct mwifiex_tid_tbl { | 214 | struct mwifiex_tid_tbl { |
215 | struct list_head ra_list; | 215 | struct list_head ra_list; |
216 | /* spin lock for tid table */ | ||
217 | spinlock_t tid_tbl_lock; | ||
218 | struct mwifiex_ra_list_tbl *ra_list_curr; | 216 | struct mwifiex_ra_list_tbl *ra_list_curr; |
219 | }; | 217 | }; |
220 | 218 | ||
221 | #define WMM_HIGHEST_PRIORITY 7 | 219 | #define WMM_HIGHEST_PRIORITY 7 |
222 | #define HIGH_PRIO_TID 7 | 220 | #define HIGH_PRIO_TID 7 |
223 | #define LOW_PRIO_TID 0 | 221 | #define LOW_PRIO_TID 0 |
224 | #define NO_PKT_PRIO_TID (-1) | ||
225 | 222 | ||
226 | struct mwifiex_wmm_desc { | 223 | struct mwifiex_wmm_desc { |
227 | struct mwifiex_tid_tbl tid_tbl_ptr[MAX_NUM_TID]; | 224 | struct mwifiex_tid_tbl tid_tbl_ptr[MAX_NUM_TID]; |
@@ -798,6 +795,8 @@ void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter); | |||
798 | 795 | ||
799 | void mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, | 796 | void mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, |
800 | struct cmd_ctrl_node *cmd_node); | 797 | struct cmd_ctrl_node *cmd_node); |
798 | void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter, | ||
799 | struct cmd_ctrl_node *cmd_node); | ||
801 | 800 | ||
802 | void mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter, | 801 | void mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter, |
803 | struct cmd_ctrl_node *cmd_node, | 802 | struct cmd_ctrl_node *cmd_node, |
@@ -912,12 +911,20 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv, | |||
912 | void mwifiex_set_ht_params(struct mwifiex_private *priv, | 911 | void mwifiex_set_ht_params(struct mwifiex_private *priv, |
913 | struct mwifiex_uap_bss_param *bss_cfg, | 912 | struct mwifiex_uap_bss_param *bss_cfg, |
914 | struct cfg80211_ap_settings *params); | 913 | struct cfg80211_ap_settings *params); |
914 | void mwifiex_set_vht_params(struct mwifiex_private *priv, | ||
915 | struct mwifiex_uap_bss_param *bss_cfg, | ||
916 | struct cfg80211_ap_settings *params); | ||
915 | void mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg, | 917 | void mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg, |
916 | struct cfg80211_ap_settings *params); | 918 | struct cfg80211_ap_settings *params); |
919 | void mwifiex_set_vht_width(struct mwifiex_private *priv, | ||
920 | enum nl80211_chan_width width, | ||
921 | bool ap_11ac_disable); | ||
917 | void | 922 | void |
918 | mwifiex_set_wmm_params(struct mwifiex_private *priv, | 923 | mwifiex_set_wmm_params(struct mwifiex_private *priv, |
919 | struct mwifiex_uap_bss_param *bss_cfg, | 924 | struct mwifiex_uap_bss_param *bss_cfg, |
920 | struct cfg80211_ap_settings *params); | 925 | struct cfg80211_ap_settings *params); |
926 | void mwifiex_set_ba_params(struct mwifiex_private *priv); | ||
927 | void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv); | ||
921 | 928 | ||
922 | /* | 929 | /* |
923 | * This function checks if the queuing is RA based or not. | 930 | * This function checks if the queuing is RA based or not. |
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 8cd8cdc91a7e..856959b64bc7 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c | |||
@@ -287,18 +287,13 @@ static int mwifiex_read_reg(struct mwifiex_adapter *adapter, int reg, u32 *data) | |||
287 | } | 287 | } |
288 | 288 | ||
289 | /* | 289 | /* |
290 | * This function wakes up the card. | 290 | * This function adds delay loop to ensure FW is awake before proceeding. |
291 | * | ||
292 | * A host power up command is written to the card configuration | ||
293 | * register to wake up the card. | ||
294 | */ | 291 | */ |
295 | static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) | 292 | static void mwifiex_pcie_dev_wakeup_delay(struct mwifiex_adapter *adapter) |
296 | { | 293 | { |
297 | int i = 0; | 294 | int i = 0; |
298 | struct pcie_service_card *card = adapter->card; | ||
299 | const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; | ||
300 | 295 | ||
301 | while (reg->sleep_cookie && mwifiex_pcie_ok_to_access_hw(adapter)) { | 296 | while (mwifiex_pcie_ok_to_access_hw(adapter)) { |
302 | i++; | 297 | i++; |
303 | usleep_range(10, 20); | 298 | usleep_range(10, 20); |
304 | /* 50ms max wait */ | 299 | /* 50ms max wait */ |
@@ -306,16 +301,32 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) | |||
306 | break; | 301 | break; |
307 | } | 302 | } |
308 | 303 | ||
304 | return; | ||
305 | } | ||
306 | |||
307 | /* This function wakes up the card by reading fw_status register. */ | ||
308 | static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) | ||
309 | { | ||
310 | u32 fw_status; | ||
311 | struct pcie_service_card *card = adapter->card; | ||
312 | const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; | ||
313 | |||
309 | dev_dbg(adapter->dev, "event: Wakeup device...\n"); | 314 | dev_dbg(adapter->dev, "event: Wakeup device...\n"); |
310 | 315 | ||
311 | /* Enable interrupts or any chip access will wakeup device */ | 316 | if (reg->sleep_cookie) |
312 | if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK, HOST_INTR_MASK)) { | 317 | mwifiex_pcie_dev_wakeup_delay(adapter); |
313 | dev_warn(adapter->dev, "Enable host interrupt failed\n"); | 318 | |
319 | /* Reading fw_status register will wakeup device */ | ||
320 | if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status)) { | ||
321 | dev_warn(adapter->dev, "Reading fw_status register failed\n"); | ||
314 | return -1; | 322 | return -1; |
315 | } | 323 | } |
316 | 324 | ||
317 | dev_dbg(adapter->dev, "PCIE wakeup: Setting PS_STATE_AWAKE\n"); | 325 | if (reg->sleep_cookie) { |
318 | adapter->ps_state = PS_STATE_AWAKE; | 326 | mwifiex_pcie_dev_wakeup_delay(adapter); |
327 | dev_dbg(adapter->dev, "PCIE wakeup: Setting PS_STATE_AWAKE\n"); | ||
328 | adapter->ps_state = PS_STATE_AWAKE; | ||
329 | } | ||
319 | 330 | ||
320 | return 0; | 331 | return 0; |
321 | } | 332 | } |
@@ -1984,12 +1995,13 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter) | |||
1984 | } | 1995 | } |
1985 | } | 1996 | } |
1986 | } else if (!adapter->pps_uapsd_mode && | 1997 | } else if (!adapter->pps_uapsd_mode && |
1987 | adapter->ps_state == PS_STATE_SLEEP) { | 1998 | adapter->ps_state == PS_STATE_SLEEP && |
1999 | mwifiex_pcie_ok_to_access_hw(adapter)) { | ||
1988 | /* Potentially for PCIe we could get other | 2000 | /* Potentially for PCIe we could get other |
1989 | * interrupts like shared. Don't change power | 2001 | * interrupts like shared. Don't change power |
1990 | * state until cookie is set */ | 2002 | * state until cookie is set */ |
1991 | if (mwifiex_pcie_ok_to_access_hw(adapter)) | 2003 | adapter->ps_state = PS_STATE_AWAKE; |
1992 | adapter->ps_state = PS_STATE_AWAKE; | 2004 | adapter->pm_wakeup_fw_try = false; |
1993 | } | 2005 | } |
1994 | } | 2006 | } |
1995 | } | 2007 | } |
@@ -2112,7 +2124,8 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) | |||
2112 | } | 2124 | } |
2113 | dev_dbg(adapter->dev, "info: cmd_sent=%d data_sent=%d\n", | 2125 | dev_dbg(adapter->dev, "info: cmd_sent=%d data_sent=%d\n", |
2114 | adapter->cmd_sent, adapter->data_sent); | 2126 | adapter->cmd_sent, adapter->data_sent); |
2115 | mwifiex_pcie_enable_host_int(adapter); | 2127 | if (adapter->ps_state != PS_STATE_SLEEP) |
2128 | mwifiex_pcie_enable_host_int(adapter); | ||
2116 | 2129 | ||
2117 | return 0; | 2130 | return 0; |
2118 | } | 2131 | } |
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index d215b4d3c51b..e7f6deaf715e 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c | |||
@@ -1393,8 +1393,10 @@ int mwifiex_scan_networks(struct mwifiex_private *priv, | |||
1393 | queue_work(adapter->workqueue, &adapter->main_work); | 1393 | queue_work(adapter->workqueue, &adapter->main_work); |
1394 | 1394 | ||
1395 | /* Perform internal scan synchronously */ | 1395 | /* Perform internal scan synchronously */ |
1396 | if (!priv->scan_request) | 1396 | if (!priv->scan_request) { |
1397 | dev_dbg(adapter->dev, "wait internal scan\n"); | ||
1397 | mwifiex_wait_queue_complete(adapter, cmd_node); | 1398 | mwifiex_wait_queue_complete(adapter, cmd_node); |
1399 | } | ||
1398 | } else { | 1400 | } else { |
1399 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | 1401 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, |
1400 | flags); | 1402 | flags); |
@@ -1793,7 +1795,12 @@ check_next_scan: | |||
1793 | /* Need to indicate IOCTL complete */ | 1795 | /* Need to indicate IOCTL complete */ |
1794 | if (adapter->curr_cmd->wait_q_enabled) { | 1796 | if (adapter->curr_cmd->wait_q_enabled) { |
1795 | adapter->cmd_wait_q.status = 0; | 1797 | adapter->cmd_wait_q.status = 0; |
1796 | mwifiex_complete_cmd(adapter, adapter->curr_cmd); | 1798 | if (!priv->scan_request) { |
1799 | dev_dbg(adapter->dev, | ||
1800 | "complete internal scan\n"); | ||
1801 | mwifiex_complete_cmd(adapter, | ||
1802 | adapter->curr_cmd); | ||
1803 | } | ||
1797 | } | 1804 | } |
1798 | if (priv->report_scan_result) | 1805 | if (priv->report_scan_result) |
1799 | priv->report_scan_result = false; | 1806 | priv->report_scan_result = false; |
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index a2ae690a0a67..b193e25977d2 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "main.h" | 24 | #include "main.h" |
25 | #include "wmm.h" | 25 | #include "wmm.h" |
26 | #include "11n.h" | 26 | #include "11n.h" |
27 | #include "11ac.h" | ||
27 | 28 | ||
28 | /* | 29 | /* |
29 | * This function prepares command to set/get RSSI information. | 30 | * This function prepares command to set/get RSSI information. |
@@ -1258,6 +1259,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | |||
1258 | cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan) + | 1259 | cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan) + |
1259 | S_DS_GEN); | 1260 | S_DS_GEN); |
1260 | break; | 1261 | break; |
1262 | case HostCmd_CMD_11AC_CFG: | ||
1263 | ret = mwifiex_cmd_11ac_cfg(priv, cmd_ptr, cmd_action, data_buf); | ||
1264 | break; | ||
1261 | case HostCmd_CMD_P2P_MODE_CFG: | 1265 | case HostCmd_CMD_P2P_MODE_CFG: |
1262 | cmd_ptr->command = cpu_to_le16(cmd_no); | 1266 | cmd_ptr->command = cpu_to_le16(cmd_no); |
1263 | cmd_ptr->params.mode_cfg.action = cpu_to_le16(cmd_action); | 1267 | cmd_ptr->params.mode_cfg.action = cpu_to_le16(cmd_action); |
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 80b9f2238001..9f990e14966e 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
@@ -95,7 +95,7 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv, | |||
95 | break; | 95 | break; |
96 | } | 96 | } |
97 | /* Handling errors here */ | 97 | /* Handling errors here */ |
98 | mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); | 98 | mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); |
99 | 99 | ||
100 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); | 100 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); |
101 | adapter->curr_cmd = NULL; | 101 | adapter->curr_cmd = NULL; |
@@ -907,6 +907,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, | |||
907 | case HostCmd_CMD_REMAIN_ON_CHAN: | 907 | case HostCmd_CMD_REMAIN_ON_CHAN: |
908 | ret = mwifiex_ret_remain_on_chan(priv, resp, data_buf); | 908 | ret = mwifiex_ret_remain_on_chan(priv, resp, data_buf); |
909 | break; | 909 | break; |
910 | case HostCmd_CMD_11AC_CFG: | ||
911 | break; | ||
910 | case HostCmd_CMD_P2P_MODE_CFG: | 912 | case HostCmd_CMD_P2P_MODE_CFG: |
911 | ret = mwifiex_ret_p2p_mode_cfg(priv, resp, data_buf); | 913 | ret = mwifiex_ret_p2p_mode_cfg(priv, resp, data_buf); |
912 | break; | 914 | break; |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 8c943b6ebf45..e6c9b2ae22ed 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -59,9 +59,6 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter, | |||
59 | { | 59 | { |
60 | int status; | 60 | int status; |
61 | 61 | ||
62 | dev_dbg(adapter->dev, "cmd pending\n"); | ||
63 | atomic_inc(&adapter->cmd_pending); | ||
64 | |||
65 | /* Wait for completion */ | 62 | /* Wait for completion */ |
66 | status = wait_event_interruptible(adapter->cmd_wait_q.wait, | 63 | status = wait_event_interruptible(adapter->cmd_wait_q.wait, |
67 | *(cmd_queued->condition)); | 64 | *(cmd_queued->condition)); |
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c index 6e76a15a8950..b04b1db29100 100644 --- a/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/mwifiex/uap_cmd.c | |||
@@ -18,6 +18,7 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include "main.h" | 20 | #include "main.h" |
21 | #include "11ac.h" | ||
21 | 22 | ||
22 | /* This function parses security related parameters from cfg80211_ap_settings | 23 | /* This function parses security related parameters from cfg80211_ap_settings |
23 | * and sets into FW understandable bss_config structure. | 24 | * and sets into FW understandable bss_config structure. |
@@ -177,6 +178,60 @@ mwifiex_set_ht_params(struct mwifiex_private *priv, | |||
177 | return; | 178 | return; |
178 | } | 179 | } |
179 | 180 | ||
181 | /* This function updates 11ac related parameters from IE | ||
182 | * and sets them into bss_config structure. | ||
183 | */ | ||
184 | void mwifiex_set_vht_params(struct mwifiex_private *priv, | ||
185 | struct mwifiex_uap_bss_param *bss_cfg, | ||
186 | struct cfg80211_ap_settings *params) | ||
187 | { | ||
188 | const u8 *vht_ie; | ||
189 | |||
190 | vht_ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, params->beacon.tail, | ||
191 | params->beacon.tail_len); | ||
192 | if (vht_ie) { | ||
193 | memcpy(&bss_cfg->vht_cap, vht_ie + 2, | ||
194 | sizeof(struct ieee80211_vht_cap)); | ||
195 | priv->ap_11ac_enabled = 1; | ||
196 | } else { | ||
197 | priv->ap_11ac_enabled = 0; | ||
198 | } | ||
199 | |||
200 | return; | ||
201 | } | ||
202 | |||
203 | /* Enable VHT only when cfg80211_ap_settings has VHT IE. | ||
204 | * Otherwise disable VHT. | ||
205 | */ | ||
206 | void mwifiex_set_vht_width(struct mwifiex_private *priv, | ||
207 | enum nl80211_chan_width width, | ||
208 | bool ap_11ac_enable) | ||
209 | { | ||
210 | struct mwifiex_adapter *adapter = priv->adapter; | ||
211 | struct mwifiex_11ac_vht_cfg vht_cfg; | ||
212 | |||
213 | vht_cfg.band_config = VHT_CFG_5GHZ; | ||
214 | vht_cfg.cap_info = adapter->hw_dot_11ac_dev_cap; | ||
215 | |||
216 | if (!ap_11ac_enable) { | ||
217 | vht_cfg.mcs_tx_set = DISABLE_VHT_MCS_SET; | ||
218 | vht_cfg.mcs_rx_set = DISABLE_VHT_MCS_SET; | ||
219 | } else { | ||
220 | vht_cfg.mcs_tx_set = DEFAULT_VHT_MCS_SET; | ||
221 | vht_cfg.mcs_rx_set = DEFAULT_VHT_MCS_SET; | ||
222 | } | ||
223 | |||
224 | vht_cfg.misc_config = VHT_CAP_UAP_ONLY; | ||
225 | |||
226 | if (ap_11ac_enable && width >= NL80211_CHAN_WIDTH_80) | ||
227 | vht_cfg.misc_config |= VHT_BW_80_160_80P80; | ||
228 | |||
229 | mwifiex_send_cmd_sync(priv, HostCmd_CMD_11AC_CFG, | ||
230 | HostCmd_ACT_GEN_SET, 0, &vht_cfg); | ||
231 | |||
232 | return; | ||
233 | } | ||
234 | |||
180 | /* This function finds supported rates IE from beacon parameter and sets | 235 | /* This function finds supported rates IE from beacon parameter and sets |
181 | * these rates into bss_config structure. | 236 | * these rates into bss_config structure. |
182 | */ | 237 | */ |
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c index 54667e65ca47..e57ac0dd3ab5 100644 --- a/drivers/net/wireless/mwifiex/util.c +++ b/drivers/net/wireless/mwifiex/util.c | |||
@@ -239,7 +239,6 @@ int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb) | |||
239 | int mwifiex_complete_cmd(struct mwifiex_adapter *adapter, | 239 | int mwifiex_complete_cmd(struct mwifiex_adapter *adapter, |
240 | struct cmd_ctrl_node *cmd_node) | 240 | struct cmd_ctrl_node *cmd_node) |
241 | { | 241 | { |
242 | atomic_dec(&adapter->cmd_pending); | ||
243 | dev_dbg(adapter->dev, "cmd completed: status=%d\n", | 242 | dev_dbg(adapter->dev, "cmd completed: status=%d\n", |
244 | adapter->cmd_wait_q.status); | 243 | adapter->cmd_wait_q.status); |
245 | 244 | ||
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 32adc878041d..2cc81ba590e3 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c | |||
@@ -436,10 +436,7 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter) | |||
436 | = priv->aggr_prio_tbl[7].ampdu_user | 436 | = priv->aggr_prio_tbl[7].ampdu_user |
437 | = BA_STREAM_NOT_ALLOWED; | 437 | = BA_STREAM_NOT_ALLOWED; |
438 | 438 | ||
439 | priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT; | 439 | mwifiex_set_ba_params(priv); |
440 | priv->add_ba_param.tx_win_size = MWIFIEX_AMPDU_DEF_TXWINSIZE; | ||
441 | priv->add_ba_param.rx_win_size = MWIFIEX_AMPDU_DEF_RXWINSIZE; | ||
442 | |||
443 | mwifiex_reset_11n_rx_seq_num(priv); | 440 | mwifiex_reset_11n_rx_seq_num(priv); |
444 | 441 | ||
445 | atomic_set(&priv->wmm.tx_pkts_queued, 0); | 442 | atomic_set(&priv->wmm.tx_pkts_queued, 0); |
@@ -688,13 +685,13 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, | |||
688 | ra_list->total_pkts_size += skb->len; | 685 | ra_list->total_pkts_size += skb->len; |
689 | ra_list->pkt_count++; | 686 | ra_list->pkt_count++; |
690 | 687 | ||
691 | atomic_inc(&priv->wmm.tx_pkts_queued); | ||
692 | |||
693 | if (atomic_read(&priv->wmm.highest_queued_prio) < | 688 | if (atomic_read(&priv->wmm.highest_queued_prio) < |
694 | tos_to_tid_inv[tid_down]) | 689 | tos_to_tid_inv[tid_down]) |
695 | atomic_set(&priv->wmm.highest_queued_prio, | 690 | atomic_set(&priv->wmm.highest_queued_prio, |
696 | tos_to_tid_inv[tid_down]); | 691 | tos_to_tid_inv[tid_down]); |
697 | 692 | ||
693 | atomic_inc(&priv->wmm.tx_pkts_queued); | ||
694 | |||
698 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); | 695 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); |
699 | } | 696 | } |
700 | 697 | ||
@@ -890,19 +887,15 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, | |||
890 | struct mwifiex_bss_prio_node *bssprio_node, *bssprio_head; | 887 | struct mwifiex_bss_prio_node *bssprio_node, *bssprio_head; |
891 | struct mwifiex_tid_tbl *tid_ptr; | 888 | struct mwifiex_tid_tbl *tid_ptr; |
892 | atomic_t *hqp; | 889 | atomic_t *hqp; |
893 | int is_list_empty; | 890 | unsigned long flags_bss, flags_ra; |
894 | unsigned long flags; | ||
895 | int i, j; | 891 | int i, j; |
896 | 892 | ||
897 | for (j = adapter->priv_num - 1; j >= 0; --j) { | 893 | for (j = adapter->priv_num - 1; j >= 0; --j) { |
898 | spin_lock_irqsave(&adapter->bss_prio_tbl[j].bss_prio_lock, | 894 | spin_lock_irqsave(&adapter->bss_prio_tbl[j].bss_prio_lock, |
899 | flags); | 895 | flags_bss); |
900 | is_list_empty = list_empty(&adapter->bss_prio_tbl[j] | 896 | |
901 | .bss_prio_head); | 897 | if (list_empty(&adapter->bss_prio_tbl[j].bss_prio_head)) |
902 | spin_unlock_irqrestore(&adapter->bss_prio_tbl[j].bss_prio_lock, | 898 | goto skip_prio_tbl; |
903 | flags); | ||
904 | if (is_list_empty) | ||
905 | continue; | ||
906 | 899 | ||
907 | if (adapter->bss_prio_tbl[j].bss_prio_cur == | 900 | if (adapter->bss_prio_tbl[j].bss_prio_cur == |
908 | (struct mwifiex_bss_prio_node *) | 901 | (struct mwifiex_bss_prio_node *) |
@@ -919,26 +912,26 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, | |||
919 | 912 | ||
920 | do { | 913 | do { |
921 | priv_tmp = bssprio_node->priv; | 914 | priv_tmp = bssprio_node->priv; |
922 | hqp = &priv_tmp->wmm.highest_queued_prio; | ||
923 | 915 | ||
916 | if (atomic_read(&priv_tmp->wmm.tx_pkts_queued) == 0) | ||
917 | goto skip_bss; | ||
918 | |||
919 | /* iterate over the WMM queues of the BSS */ | ||
920 | hqp = &priv_tmp->wmm.highest_queued_prio; | ||
924 | for (i = atomic_read(hqp); i >= LOW_PRIO_TID; --i) { | 921 | for (i = atomic_read(hqp); i >= LOW_PRIO_TID; --i) { |
925 | 922 | ||
923 | spin_lock_irqsave(&priv_tmp->wmm. | ||
924 | ra_list_spinlock, flags_ra); | ||
925 | |||
926 | tid_ptr = &(priv_tmp)->wmm. | 926 | tid_ptr = &(priv_tmp)->wmm. |
927 | tid_tbl_ptr[tos_to_tid[i]]; | 927 | tid_tbl_ptr[tos_to_tid[i]]; |
928 | 928 | ||
929 | /* For non-STA ra_list_curr may be NULL */ | 929 | /* For non-STA ra_list_curr may be NULL */ |
930 | if (!tid_ptr->ra_list_curr) | 930 | if (!tid_ptr->ra_list_curr) |
931 | continue; | 931 | goto skip_wmm_queue; |
932 | 932 | ||
933 | spin_lock_irqsave(&tid_ptr->tid_tbl_lock, | 933 | if (list_empty(&tid_ptr->ra_list)) |
934 | flags); | 934 | goto skip_wmm_queue; |
935 | is_list_empty = | ||
936 | list_empty(&adapter->bss_prio_tbl[j] | ||
937 | .bss_prio_head); | ||
938 | spin_unlock_irqrestore(&tid_ptr->tid_tbl_lock, | ||
939 | flags); | ||
940 | if (is_list_empty) | ||
941 | continue; | ||
942 | 935 | ||
943 | /* | 936 | /* |
944 | * Always choose the next ra we transmitted | 937 | * Always choose the next ra we transmitted |
@@ -960,10 +953,8 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, | |||
960 | } | 953 | } |
961 | 954 | ||
962 | do { | 955 | do { |
963 | is_list_empty = | 956 | if (!skb_queue_empty(&ptr->skb_head)) |
964 | skb_queue_empty(&ptr->skb_head); | 957 | /* holds both locks */ |
965 | |||
966 | if (!is_list_empty) | ||
967 | goto found; | 958 | goto found; |
968 | 959 | ||
969 | /* Get next ra */ | 960 | /* Get next ra */ |
@@ -978,14 +969,14 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, | |||
978 | struct mwifiex_ra_list_tbl, | 969 | struct mwifiex_ra_list_tbl, |
979 | list); | 970 | list); |
980 | } while (ptr != head); | 971 | } while (ptr != head); |
981 | } | ||
982 | 972 | ||
983 | /* No packet at any TID for this priv. Mark as such | 973 | skip_wmm_queue: |
984 | * to skip checking TIDs for this priv (until pkt is | 974 | spin_unlock_irqrestore(&priv_tmp->wmm. |
985 | * added). | 975 | ra_list_spinlock, |
986 | */ | 976 | flags_ra); |
987 | atomic_set(hqp, NO_PKT_PRIO_TID); | 977 | } |
988 | 978 | ||
979 | skip_bss: | ||
989 | /* Get next bss priority node */ | 980 | /* Get next bss priority node */ |
990 | bssprio_node = list_first_entry(&bssprio_node->list, | 981 | bssprio_node = list_first_entry(&bssprio_node->list, |
991 | struct mwifiex_bss_prio_node, | 982 | struct mwifiex_bss_prio_node, |
@@ -1000,14 +991,21 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, | |||
1000 | struct mwifiex_bss_prio_node, | 991 | struct mwifiex_bss_prio_node, |
1001 | list); | 992 | list); |
1002 | } while (bssprio_node != bssprio_head); | 993 | } while (bssprio_node != bssprio_head); |
994 | |||
995 | skip_prio_tbl: | ||
996 | spin_unlock_irqrestore(&adapter->bss_prio_tbl[j].bss_prio_lock, | ||
997 | flags_bss); | ||
1003 | } | 998 | } |
999 | |||
1004 | return NULL; | 1000 | return NULL; |
1005 | 1001 | ||
1006 | found: | 1002 | found: |
1007 | spin_lock_irqsave(&priv_tmp->wmm.ra_list_spinlock, flags); | 1003 | /* holds bss_prio_lock / ra_list_spinlock */ |
1008 | if (atomic_read(hqp) > i) | 1004 | if (atomic_read(hqp) > i) |
1009 | atomic_set(hqp, i); | 1005 | atomic_set(hqp, i); |
1010 | spin_unlock_irqrestore(&priv_tmp->wmm.ra_list_spinlock, flags); | 1006 | spin_unlock_irqrestore(&priv_tmp->wmm.ra_list_spinlock, flags_ra); |
1007 | spin_unlock_irqrestore(&adapter->bss_prio_tbl[j].bss_prio_lock, | ||
1008 | flags_bss); | ||
1011 | 1009 | ||
1012 | *priv = priv_tmp; | 1010 | *priv = priv_tmp; |
1013 | *tid = tos_to_tid[i]; | 1011 | *tid = tos_to_tid[i]; |
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 0640e7d7f0c2..956c1084ebf1 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -4807,16 +4807,14 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) | |||
4807 | struct mwl8k_priv *priv = hw->priv; | 4807 | struct mwl8k_priv *priv = hw->priv; |
4808 | int rc; | 4808 | int rc; |
4809 | 4809 | ||
4810 | if (conf->flags & IEEE80211_CONF_IDLE) { | ||
4811 | mwl8k_cmd_radio_disable(hw); | ||
4812 | return 0; | ||
4813 | } | ||
4814 | |||
4815 | rc = mwl8k_fw_lock(hw); | 4810 | rc = mwl8k_fw_lock(hw); |
4816 | if (rc) | 4811 | if (rc) |
4817 | return rc; | 4812 | return rc; |
4818 | 4813 | ||
4819 | rc = mwl8k_cmd_radio_enable(hw); | 4814 | if (conf->flags & IEEE80211_CONF_IDLE) |
4815 | rc = mwl8k_cmd_radio_disable(hw); | ||
4816 | else | ||
4817 | rc = mwl8k_cmd_radio_enable(hw); | ||
4820 | if (rc) | 4818 | if (rc) |
4821 | goto out; | 4819 | goto out; |
4822 | 4820 | ||
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index aadda99989c0..ee654a691f38 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c | |||
@@ -670,7 +670,7 @@ static unsigned int p54_flush_count(struct p54_common *priv) | |||
670 | return total; | 670 | return total; |
671 | } | 671 | } |
672 | 672 | ||
673 | static void p54_flush(struct ieee80211_hw *dev, bool drop) | 673 | static void p54_flush(struct ieee80211_hw *dev, u32 queues, bool drop) |
674 | { | 674 | { |
675 | struct p54_common *priv = dev->priv; | 675 | struct p54_common *priv = dev->priv; |
676 | unsigned int total, i; | 676 | unsigned int total, i; |
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index ffe61d53e3fe..9b915d3a44be 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig | |||
@@ -20,6 +20,7 @@ if RT2X00 | |||
20 | config RT2400PCI | 20 | config RT2400PCI |
21 | tristate "Ralink rt2400 (PCI/PCMCIA) support" | 21 | tristate "Ralink rt2400 (PCI/PCMCIA) support" |
22 | depends on PCI | 22 | depends on PCI |
23 | select RT2X00_LIB_MMIO | ||
23 | select RT2X00_LIB_PCI | 24 | select RT2X00_LIB_PCI |
24 | select EEPROM_93CX6 | 25 | select EEPROM_93CX6 |
25 | ---help--- | 26 | ---help--- |
@@ -31,6 +32,7 @@ config RT2400PCI | |||
31 | config RT2500PCI | 32 | config RT2500PCI |
32 | tristate "Ralink rt2500 (PCI/PCMCIA) support" | 33 | tristate "Ralink rt2500 (PCI/PCMCIA) support" |
33 | depends on PCI | 34 | depends on PCI |
35 | select RT2X00_LIB_MMIO | ||
34 | select RT2X00_LIB_PCI | 36 | select RT2X00_LIB_PCI |
35 | select EEPROM_93CX6 | 37 | select EEPROM_93CX6 |
36 | ---help--- | 38 | ---help--- |
@@ -43,6 +45,7 @@ config RT61PCI | |||
43 | tristate "Ralink rt2501/rt61 (PCI/PCMCIA) support" | 45 | tristate "Ralink rt2501/rt61 (PCI/PCMCIA) support" |
44 | depends on PCI | 46 | depends on PCI |
45 | select RT2X00_LIB_PCI | 47 | select RT2X00_LIB_PCI |
48 | select RT2X00_LIB_MMIO | ||
46 | select RT2X00_LIB_FIRMWARE | 49 | select RT2X00_LIB_FIRMWARE |
47 | select RT2X00_LIB_CRYPTO | 50 | select RT2X00_LIB_CRYPTO |
48 | select CRC_ITU_T | 51 | select CRC_ITU_T |
@@ -57,6 +60,7 @@ config RT2800PCI | |||
57 | tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support" | 60 | tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support" |
58 | depends on PCI || SOC_RT288X || SOC_RT305X | 61 | depends on PCI || SOC_RT288X || SOC_RT305X |
59 | select RT2800_LIB | 62 | select RT2800_LIB |
63 | select RT2X00_LIB_MMIO | ||
60 | select RT2X00_LIB_PCI if PCI | 64 | select RT2X00_LIB_PCI if PCI |
61 | select RT2X00_LIB_SOC if SOC_RT288X || SOC_RT305X | 65 | select RT2X00_LIB_SOC if SOC_RT288X || SOC_RT305X |
62 | select RT2X00_LIB_FIRMWARE | 66 | select RT2X00_LIB_FIRMWARE |
@@ -192,6 +196,9 @@ endif | |||
192 | config RT2800_LIB | 196 | config RT2800_LIB |
193 | tristate | 197 | tristate |
194 | 198 | ||
199 | config RT2X00_LIB_MMIO | ||
200 | tristate | ||
201 | |||
195 | config RT2X00_LIB_PCI | 202 | config RT2X00_LIB_PCI |
196 | tristate | 203 | tristate |
197 | select RT2X00_LIB | 204 | select RT2X00_LIB |
diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile index 349d5b8284a4..f069d8bc5b67 100644 --- a/drivers/net/wireless/rt2x00/Makefile +++ b/drivers/net/wireless/rt2x00/Makefile | |||
@@ -9,6 +9,7 @@ rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o | |||
9 | rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS) += rt2x00leds.o | 9 | rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS) += rt2x00leds.o |
10 | 10 | ||
11 | obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o | 11 | obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o |
12 | obj-$(CONFIG_RT2X00_LIB_MMIO) += rt2x00mmio.o | ||
12 | obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o | 13 | obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o |
13 | obj-$(CONFIG_RT2X00_LIB_SOC) += rt2x00soc.o | 14 | obj-$(CONFIG_RT2X00_LIB_SOC) += rt2x00soc.o |
14 | obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o | 15 | obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o |
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 221beaaa83f1..dcfb54e0c516 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
35 | 35 | ||
36 | #include "rt2x00.h" | 36 | #include "rt2x00.h" |
37 | #include "rt2x00mmio.h" | ||
37 | #include "rt2x00pci.h" | 38 | #include "rt2x00pci.h" |
38 | #include "rt2400pci.h" | 39 | #include "rt2400pci.h" |
39 | 40 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 39edc59e8d03..e1d2dc9ed28a 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
35 | 35 | ||
36 | #include "rt2x00.h" | 36 | #include "rt2x00.h" |
37 | #include "rt2x00mmio.h" | ||
37 | #include "rt2x00pci.h" | 38 | #include "rt2x00pci.h" |
38 | #include "rt2500pci.h" | 39 | #include "rt2500pci.h" |
39 | 40 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index f08a0424fe4d..7deac4d2459f 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -5431,9 +5431,9 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) | |||
5431 | 5431 | ||
5432 | static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) | 5432 | static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) |
5433 | { | 5433 | { |
5434 | u32 reg; | ||
5435 | u16 value; | 5434 | u16 value; |
5436 | u16 eeprom; | 5435 | u16 eeprom; |
5436 | u16 rf; | ||
5437 | 5437 | ||
5438 | /* | 5438 | /* |
5439 | * Read EEPROM word for configuration. | 5439 | * Read EEPROM word for configuration. |
@@ -5445,42 +5445,14 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
5445 | * RT28xx/RT30xx: defined in "EEPROM_NIC_CONF0_RF_TYPE" field | 5445 | * RT28xx/RT30xx: defined in "EEPROM_NIC_CONF0_RF_TYPE" field |
5446 | * RT53xx: defined in "EEPROM_CHIP_ID" field | 5446 | * RT53xx: defined in "EEPROM_CHIP_ID" field |
5447 | */ | 5447 | */ |
5448 | if (rt2x00_rt(rt2x00dev, RT3290)) | 5448 | if (rt2x00_rt(rt2x00dev, RT3290) || |
5449 | rt2800_register_read(rt2x00dev, MAC_CSR0_3290, ®); | 5449 | rt2x00_rt(rt2x00dev, RT5390) || |
5450 | else | 5450 | rt2x00_rt(rt2x00dev, RT5392)) |
5451 | rt2800_register_read(rt2x00dev, MAC_CSR0, ®); | 5451 | rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); |
5452 | |||
5453 | if (rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT3290 || | ||
5454 | rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5390 || | ||
5455 | rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392) | ||
5456 | rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &value); | ||
5457 | else | 5452 | else |
5458 | value = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE); | 5453 | rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE); |
5459 | 5454 | ||
5460 | rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET), | 5455 | switch (rf) { |
5461 | value, rt2x00_get_field32(reg, MAC_CSR0_REVISION)); | ||
5462 | |||
5463 | switch (rt2x00dev->chip.rt) { | ||
5464 | case RT2860: | ||
5465 | case RT2872: | ||
5466 | case RT2883: | ||
5467 | case RT3070: | ||
5468 | case RT3071: | ||
5469 | case RT3090: | ||
5470 | case RT3290: | ||
5471 | case RT3352: | ||
5472 | case RT3390: | ||
5473 | case RT3572: | ||
5474 | case RT5390: | ||
5475 | case RT5392: | ||
5476 | case RT5592: | ||
5477 | break; | ||
5478 | default: | ||
5479 | ERROR(rt2x00dev, "Invalid RT chipset 0x%04x detected.\n", rt2x00dev->chip.rt); | ||
5480 | return -ENODEV; | ||
5481 | } | ||
5482 | |||
5483 | switch (rt2x00dev->chip.rf) { | ||
5484 | case RF2820: | 5456 | case RF2820: |
5485 | case RF2850: | 5457 | case RF2850: |
5486 | case RF2720: | 5458 | case RF2720: |
@@ -5501,11 +5473,12 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
5501 | case RF5592: | 5473 | case RF5592: |
5502 | break; | 5474 | break; |
5503 | default: | 5475 | default: |
5504 | ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n", | 5476 | ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n", rf); |
5505 | rt2x00dev->chip.rf); | ||
5506 | return -ENODEV; | 5477 | return -ENODEV; |
5507 | } | 5478 | } |
5508 | 5479 | ||
5480 | rt2x00_set_rf(rt2x00dev, rf); | ||
5481 | |||
5509 | /* | 5482 | /* |
5510 | * Identify default antenna configuration. | 5483 | * Identify default antenna configuration. |
5511 | */ | 5484 | */ |
@@ -6059,11 +6032,56 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
6059 | return 0; | 6032 | return 0; |
6060 | } | 6033 | } |
6061 | 6034 | ||
6035 | static int rt2800_probe_rt(struct rt2x00_dev *rt2x00dev) | ||
6036 | { | ||
6037 | u32 reg; | ||
6038 | u32 rt; | ||
6039 | u32 rev; | ||
6040 | |||
6041 | if (rt2x00_rt(rt2x00dev, RT3290)) | ||
6042 | rt2800_register_read(rt2x00dev, MAC_CSR0_3290, ®); | ||
6043 | else | ||
6044 | rt2800_register_read(rt2x00dev, MAC_CSR0, ®); | ||
6045 | |||
6046 | rt = rt2x00_get_field32(reg, MAC_CSR0_CHIPSET); | ||
6047 | rev = rt2x00_get_field32(reg, MAC_CSR0_REVISION); | ||
6048 | |||
6049 | switch (rt) { | ||
6050 | case RT2860: | ||
6051 | case RT2872: | ||
6052 | case RT2883: | ||
6053 | case RT3070: | ||
6054 | case RT3071: | ||
6055 | case RT3090: | ||
6056 | case RT3290: | ||
6057 | case RT3352: | ||
6058 | case RT3390: | ||
6059 | case RT3572: | ||
6060 | case RT5390: | ||
6061 | case RT5392: | ||
6062 | case RT5592: | ||
6063 | break; | ||
6064 | default: | ||
6065 | ERROR(rt2x00dev, | ||
6066 | "Invalid RT chipset 0x%04x, rev %04x detected.\n", | ||
6067 | rt, rev); | ||
6068 | return -ENODEV; | ||
6069 | } | ||
6070 | |||
6071 | rt2x00_set_rt(rt2x00dev, rt, rev); | ||
6072 | |||
6073 | return 0; | ||
6074 | } | ||
6075 | |||
6062 | int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev) | 6076 | int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev) |
6063 | { | 6077 | { |
6064 | int retval; | 6078 | int retval; |
6065 | u32 reg; | 6079 | u32 reg; |
6066 | 6080 | ||
6081 | retval = rt2800_probe_rt(rt2x00dev); | ||
6082 | if (retval) | ||
6083 | return retval; | ||
6084 | |||
6067 | /* | 6085 | /* |
6068 | * Allocate eeprom data. | 6086 | * Allocate eeprom data. |
6069 | */ | 6087 | */ |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index f732ded8f1ba..565a80d0e564 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/eeprom_93cx6.h> | 41 | #include <linux/eeprom_93cx6.h> |
42 | 42 | ||
43 | #include "rt2x00.h" | 43 | #include "rt2x00.h" |
44 | #include "rt2x00mmio.h" | ||
44 | #include "rt2x00pci.h" | 45 | #include "rt2x00pci.h" |
45 | #include "rt2x00soc.h" | 46 | #include "rt2x00soc.h" |
46 | #include "rt2800lib.h" | 47 | #include "rt2800lib.h" |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 51922cc179de..0d02d16ca166 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -1106,6 +1106,23 @@ static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev, | |||
1106 | rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev); | 1106 | rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev); |
1107 | } | 1107 | } |
1108 | 1108 | ||
1109 | static inline void rt2x00_set_rt(struct rt2x00_dev *rt2x00dev, | ||
1110 | const u16 rt, const u16 rev) | ||
1111 | { | ||
1112 | rt2x00dev->chip.rt = rt; | ||
1113 | rt2x00dev->chip.rev = rev; | ||
1114 | |||
1115 | INFO(rt2x00dev, "RT chipset %04x, rev %04x detected\n", | ||
1116 | rt2x00dev->chip.rt, rt2x00dev->chip.rev); | ||
1117 | } | ||
1118 | |||
1119 | static inline void rt2x00_set_rf(struct rt2x00_dev *rt2x00dev, const u16 rf) | ||
1120 | { | ||
1121 | rt2x00dev->chip.rf = rf; | ||
1122 | |||
1123 | INFO(rt2x00dev, "RF chipset %04x detected\n", rt2x00dev->chip.rf); | ||
1124 | } | ||
1125 | |||
1109 | static inline bool rt2x00_rt(struct rt2x00_dev *rt2x00dev, const u16 rt) | 1126 | static inline bool rt2x00_rt(struct rt2x00_dev *rt2x00dev, const u16 rt) |
1110 | { | 1127 | { |
1111 | return (rt2x00dev->chip.rt == rt); | 1128 | return (rt2x00dev->chip.rt == rt); |
@@ -1366,7 +1383,7 @@ int rt2x00mac_conf_tx(struct ieee80211_hw *hw, | |||
1366 | struct ieee80211_vif *vif, u16 queue, | 1383 | struct ieee80211_vif *vif, u16 queue, |
1367 | const struct ieee80211_tx_queue_params *params); | 1384 | const struct ieee80211_tx_queue_params *params); |
1368 | void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw); | 1385 | void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw); |
1369 | void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop); | 1386 | void rt2x00mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop); |
1370 | int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant); | 1387 | int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant); |
1371 | int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant); | 1388 | int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant); |
1372 | void rt2x00mac_get_ringparam(struct ieee80211_hw *hw, | 1389 | void rt2x00mac_get_ringparam(struct ieee80211_hw *hw, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 20c6eccce5aa..9161c02d8ff9 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -748,7 +748,7 @@ void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw) | |||
748 | } | 748 | } |
749 | EXPORT_SYMBOL_GPL(rt2x00mac_rfkill_poll); | 749 | EXPORT_SYMBOL_GPL(rt2x00mac_rfkill_poll); |
750 | 750 | ||
751 | void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop) | 751 | void rt2x00mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop) |
752 | { | 752 | { |
753 | struct rt2x00_dev *rt2x00dev = hw->priv; | 753 | struct rt2x00_dev *rt2x00dev = hw->priv; |
754 | struct data_queue *queue; | 754 | struct data_queue *queue; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mmio.c b/drivers/net/wireless/rt2x00/rt2x00mmio.c new file mode 100644 index 000000000000..d84a680ba0c9 --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2x00mmio.c | |||
@@ -0,0 +1,216 @@ | |||
1 | /* | ||
2 | Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> | ||
3 | <http://rt2x00.serialmonkey.com> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the | ||
17 | Free Software Foundation, Inc., | ||
18 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | Module: rt2x00mmio | ||
23 | Abstract: rt2x00 generic mmio device routines. | ||
24 | */ | ||
25 | |||
26 | #include <linux/dma-mapping.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/slab.h> | ||
30 | |||
31 | #include "rt2x00.h" | ||
32 | #include "rt2x00mmio.h" | ||
33 | |||
34 | /* | ||
35 | * Register access. | ||
36 | */ | ||
37 | int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, | ||
38 | const unsigned int offset, | ||
39 | const struct rt2x00_field32 field, | ||
40 | u32 *reg) | ||
41 | { | ||
42 | unsigned int i; | ||
43 | |||
44 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) | ||
45 | return 0; | ||
46 | |||
47 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
48 | rt2x00pci_register_read(rt2x00dev, offset, reg); | ||
49 | if (!rt2x00_get_field32(*reg, field)) | ||
50 | return 1; | ||
51 | udelay(REGISTER_BUSY_DELAY); | ||
52 | } | ||
53 | |||
54 | printk_once(KERN_ERR "%s() Indirect register access failed: " | ||
55 | "offset=0x%.08x, value=0x%.08x\n", __func__, offset, *reg); | ||
56 | *reg = ~0; | ||
57 | |||
58 | return 0; | ||
59 | } | ||
60 | EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read); | ||
61 | |||
62 | bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) | ||
63 | { | ||
64 | struct data_queue *queue = rt2x00dev->rx; | ||
65 | struct queue_entry *entry; | ||
66 | struct queue_entry_priv_pci *entry_priv; | ||
67 | struct skb_frame_desc *skbdesc; | ||
68 | int max_rx = 16; | ||
69 | |||
70 | while (--max_rx) { | ||
71 | entry = rt2x00queue_get_entry(queue, Q_INDEX); | ||
72 | entry_priv = entry->priv_data; | ||
73 | |||
74 | if (rt2x00dev->ops->lib->get_entry_state(entry)) | ||
75 | break; | ||
76 | |||
77 | /* | ||
78 | * Fill in desc fields of the skb descriptor | ||
79 | */ | ||
80 | skbdesc = get_skb_frame_desc(entry->skb); | ||
81 | skbdesc->desc = entry_priv->desc; | ||
82 | skbdesc->desc_len = entry->queue->desc_size; | ||
83 | |||
84 | /* | ||
85 | * DMA is already done, notify rt2x00lib that | ||
86 | * it finished successfully. | ||
87 | */ | ||
88 | rt2x00lib_dmastart(entry); | ||
89 | rt2x00lib_dmadone(entry); | ||
90 | |||
91 | /* | ||
92 | * Send the frame to rt2x00lib for further processing. | ||
93 | */ | ||
94 | rt2x00lib_rxdone(entry, GFP_ATOMIC); | ||
95 | } | ||
96 | |||
97 | return !max_rx; | ||
98 | } | ||
99 | EXPORT_SYMBOL_GPL(rt2x00pci_rxdone); | ||
100 | |||
101 | void rt2x00pci_flush_queue(struct data_queue *queue, bool drop) | ||
102 | { | ||
103 | unsigned int i; | ||
104 | |||
105 | for (i = 0; !rt2x00queue_empty(queue) && i < 10; i++) | ||
106 | msleep(10); | ||
107 | } | ||
108 | EXPORT_SYMBOL_GPL(rt2x00pci_flush_queue); | ||
109 | |||
110 | /* | ||
111 | * Device initialization handlers. | ||
112 | */ | ||
113 | static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, | ||
114 | struct data_queue *queue) | ||
115 | { | ||
116 | struct queue_entry_priv_pci *entry_priv; | ||
117 | void *addr; | ||
118 | dma_addr_t dma; | ||
119 | unsigned int i; | ||
120 | |||
121 | /* | ||
122 | * Allocate DMA memory for descriptor and buffer. | ||
123 | */ | ||
124 | addr = dma_alloc_coherent(rt2x00dev->dev, | ||
125 | queue->limit * queue->desc_size, | ||
126 | &dma, GFP_KERNEL); | ||
127 | if (!addr) | ||
128 | return -ENOMEM; | ||
129 | |||
130 | memset(addr, 0, queue->limit * queue->desc_size); | ||
131 | |||
132 | /* | ||
133 | * Initialize all queue entries to contain valid addresses. | ||
134 | */ | ||
135 | for (i = 0; i < queue->limit; i++) { | ||
136 | entry_priv = queue->entries[i].priv_data; | ||
137 | entry_priv->desc = addr + i * queue->desc_size; | ||
138 | entry_priv->desc_dma = dma + i * queue->desc_size; | ||
139 | } | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev, | ||
145 | struct data_queue *queue) | ||
146 | { | ||
147 | struct queue_entry_priv_pci *entry_priv = | ||
148 | queue->entries[0].priv_data; | ||
149 | |||
150 | if (entry_priv->desc) | ||
151 | dma_free_coherent(rt2x00dev->dev, | ||
152 | queue->limit * queue->desc_size, | ||
153 | entry_priv->desc, entry_priv->desc_dma); | ||
154 | entry_priv->desc = NULL; | ||
155 | } | ||
156 | |||
157 | int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) | ||
158 | { | ||
159 | struct data_queue *queue; | ||
160 | int status; | ||
161 | |||
162 | /* | ||
163 | * Allocate DMA | ||
164 | */ | ||
165 | queue_for_each(rt2x00dev, queue) { | ||
166 | status = rt2x00pci_alloc_queue_dma(rt2x00dev, queue); | ||
167 | if (status) | ||
168 | goto exit; | ||
169 | } | ||
170 | |||
171 | /* | ||
172 | * Register interrupt handler. | ||
173 | */ | ||
174 | status = request_irq(rt2x00dev->irq, | ||
175 | rt2x00dev->ops->lib->irq_handler, | ||
176 | IRQF_SHARED, rt2x00dev->name, rt2x00dev); | ||
177 | if (status) { | ||
178 | ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n", | ||
179 | rt2x00dev->irq, status); | ||
180 | goto exit; | ||
181 | } | ||
182 | |||
183 | return 0; | ||
184 | |||
185 | exit: | ||
186 | queue_for_each(rt2x00dev, queue) | ||
187 | rt2x00pci_free_queue_dma(rt2x00dev, queue); | ||
188 | |||
189 | return status; | ||
190 | } | ||
191 | EXPORT_SYMBOL_GPL(rt2x00pci_initialize); | ||
192 | |||
193 | void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev) | ||
194 | { | ||
195 | struct data_queue *queue; | ||
196 | |||
197 | /* | ||
198 | * Free irq line. | ||
199 | */ | ||
200 | free_irq(rt2x00dev->irq, rt2x00dev); | ||
201 | |||
202 | /* | ||
203 | * Free DMA | ||
204 | */ | ||
205 | queue_for_each(rt2x00dev, queue) | ||
206 | rt2x00pci_free_queue_dma(rt2x00dev, queue); | ||
207 | } | ||
208 | EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize); | ||
209 | |||
210 | /* | ||
211 | * rt2x00mmio module information. | ||
212 | */ | ||
213 | MODULE_AUTHOR(DRV_PROJECT); | ||
214 | MODULE_VERSION(DRV_VERSION); | ||
215 | MODULE_DESCRIPTION("rt2x00 mmio library"); | ||
216 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00mmio.h b/drivers/net/wireless/rt2x00/rt2x00mmio.h new file mode 100644 index 000000000000..4ecaf60175bf --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2x00mmio.h | |||
@@ -0,0 +1,119 @@ | |||
1 | /* | ||
2 | Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> | ||
3 | <http://rt2x00.serialmonkey.com> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the | ||
17 | Free Software Foundation, Inc., | ||
18 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | Module: rt2x00mmio | ||
23 | Abstract: Data structures for the rt2x00mmio module. | ||
24 | */ | ||
25 | |||
26 | #ifndef RT2X00MMIO_H | ||
27 | #define RT2X00MMIO_H | ||
28 | |||
29 | #include <linux/io.h> | ||
30 | |||
31 | /* | ||
32 | * Register access. | ||
33 | */ | ||
34 | static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev, | ||
35 | const unsigned int offset, | ||
36 | u32 *value) | ||
37 | { | ||
38 | *value = readl(rt2x00dev->csr.base + offset); | ||
39 | } | ||
40 | |||
41 | static inline void rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev, | ||
42 | const unsigned int offset, | ||
43 | void *value, const u32 length) | ||
44 | { | ||
45 | memcpy_fromio(value, rt2x00dev->csr.base + offset, length); | ||
46 | } | ||
47 | |||
48 | static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev, | ||
49 | const unsigned int offset, | ||
50 | u32 value) | ||
51 | { | ||
52 | writel(value, rt2x00dev->csr.base + offset); | ||
53 | } | ||
54 | |||
55 | static inline void rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev, | ||
56 | const unsigned int offset, | ||
57 | const void *value, | ||
58 | const u32 length) | ||
59 | { | ||
60 | __iowrite32_copy(rt2x00dev->csr.base + offset, value, length >> 2); | ||
61 | } | ||
62 | |||
63 | /** | ||
64 | * rt2x00pci_regbusy_read - Read from register with busy check | ||
65 | * @rt2x00dev: Device pointer, see &struct rt2x00_dev. | ||
66 | * @offset: Register offset | ||
67 | * @field: Field to check if register is busy | ||
68 | * @reg: Pointer to where register contents should be stored | ||
69 | * | ||
70 | * This function will read the given register, and checks if the | ||
71 | * register is busy. If it is, it will sleep for a couple of | ||
72 | * microseconds before reading the register again. If the register | ||
73 | * is not read after a certain timeout, this function will return | ||
74 | * FALSE. | ||
75 | */ | ||
76 | int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, | ||
77 | const unsigned int offset, | ||
78 | const struct rt2x00_field32 field, | ||
79 | u32 *reg); | ||
80 | |||
81 | /** | ||
82 | * struct queue_entry_priv_pci: Per entry PCI specific information | ||
83 | * | ||
84 | * @desc: Pointer to device descriptor | ||
85 | * @desc_dma: DMA pointer to &desc. | ||
86 | * @data: Pointer to device's entry memory. | ||
87 | * @data_dma: DMA pointer to &data. | ||
88 | */ | ||
89 | struct queue_entry_priv_pci { | ||
90 | __le32 *desc; | ||
91 | dma_addr_t desc_dma; | ||
92 | }; | ||
93 | |||
94 | /** | ||
95 | * rt2x00pci_rxdone - Handle RX done events | ||
96 | * @rt2x00dev: Device pointer, see &struct rt2x00_dev. | ||
97 | * | ||
98 | * Returns true if there are still rx frames pending and false if all | ||
99 | * pending rx frames were processed. | ||
100 | */ | ||
101 | bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev); | ||
102 | |||
103 | /** | ||
104 | * rt2x00pci_flush_queue - Flush data queue | ||
105 | * @queue: Data queue to stop | ||
106 | * @drop: True to drop all pending frames. | ||
107 | * | ||
108 | * This will wait for a maximum of 100ms, waiting for the queues | ||
109 | * to become empty. | ||
110 | */ | ||
111 | void rt2x00pci_flush_queue(struct data_queue *queue, bool drop); | ||
112 | |||
113 | /* | ||
114 | * Device initialization handlers. | ||
115 | */ | ||
116 | int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev); | ||
117 | void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev); | ||
118 | |||
119 | #endif /* RT2X00MMIO_H */ | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index c4009eaeb697..e87865e33113 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c | |||
@@ -33,180 +33,6 @@ | |||
33 | #include "rt2x00pci.h" | 33 | #include "rt2x00pci.h" |
34 | 34 | ||
35 | /* | 35 | /* |
36 | * Register access. | ||
37 | */ | ||
38 | int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, | ||
39 | const unsigned int offset, | ||
40 | const struct rt2x00_field32 field, | ||
41 | u32 *reg) | ||
42 | { | ||
43 | unsigned int i; | ||
44 | |||
45 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) | ||
46 | return 0; | ||
47 | |||
48 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
49 | rt2x00pci_register_read(rt2x00dev, offset, reg); | ||
50 | if (!rt2x00_get_field32(*reg, field)) | ||
51 | return 1; | ||
52 | udelay(REGISTER_BUSY_DELAY); | ||
53 | } | ||
54 | |||
55 | printk_once(KERN_ERR "%s() Indirect register access failed: " | ||
56 | "offset=0x%.08x, value=0x%.08x\n", __func__, offset, *reg); | ||
57 | *reg = ~0; | ||
58 | |||
59 | return 0; | ||
60 | } | ||
61 | EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read); | ||
62 | |||
63 | bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) | ||
64 | { | ||
65 | struct data_queue *queue = rt2x00dev->rx; | ||
66 | struct queue_entry *entry; | ||
67 | struct queue_entry_priv_pci *entry_priv; | ||
68 | struct skb_frame_desc *skbdesc; | ||
69 | int max_rx = 16; | ||
70 | |||
71 | while (--max_rx) { | ||
72 | entry = rt2x00queue_get_entry(queue, Q_INDEX); | ||
73 | entry_priv = entry->priv_data; | ||
74 | |||
75 | if (rt2x00dev->ops->lib->get_entry_state(entry)) | ||
76 | break; | ||
77 | |||
78 | /* | ||
79 | * Fill in desc fields of the skb descriptor | ||
80 | */ | ||
81 | skbdesc = get_skb_frame_desc(entry->skb); | ||
82 | skbdesc->desc = entry_priv->desc; | ||
83 | skbdesc->desc_len = entry->queue->desc_size; | ||
84 | |||
85 | /* | ||
86 | * DMA is already done, notify rt2x00lib that | ||
87 | * it finished successfully. | ||
88 | */ | ||
89 | rt2x00lib_dmastart(entry); | ||
90 | rt2x00lib_dmadone(entry); | ||
91 | |||
92 | /* | ||
93 | * Send the frame to rt2x00lib for further processing. | ||
94 | */ | ||
95 | rt2x00lib_rxdone(entry, GFP_ATOMIC); | ||
96 | } | ||
97 | |||
98 | return !max_rx; | ||
99 | } | ||
100 | EXPORT_SYMBOL_GPL(rt2x00pci_rxdone); | ||
101 | |||
102 | void rt2x00pci_flush_queue(struct data_queue *queue, bool drop) | ||
103 | { | ||
104 | unsigned int i; | ||
105 | |||
106 | for (i = 0; !rt2x00queue_empty(queue) && i < 10; i++) | ||
107 | msleep(10); | ||
108 | } | ||
109 | EXPORT_SYMBOL_GPL(rt2x00pci_flush_queue); | ||
110 | |||
111 | /* | ||
112 | * Device initialization handlers. | ||
113 | */ | ||
114 | static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, | ||
115 | struct data_queue *queue) | ||
116 | { | ||
117 | struct queue_entry_priv_pci *entry_priv; | ||
118 | void *addr; | ||
119 | dma_addr_t dma; | ||
120 | unsigned int i; | ||
121 | |||
122 | /* | ||
123 | * Allocate DMA memory for descriptor and buffer. | ||
124 | */ | ||
125 | addr = dma_alloc_coherent(rt2x00dev->dev, | ||
126 | queue->limit * queue->desc_size, | ||
127 | &dma, GFP_KERNEL | __GFP_ZERO); | ||
128 | if (!addr) | ||
129 | return -ENOMEM; | ||
130 | |||
131 | /* | ||
132 | * Initialize all queue entries to contain valid addresses. | ||
133 | */ | ||
134 | for (i = 0; i < queue->limit; i++) { | ||
135 | entry_priv = queue->entries[i].priv_data; | ||
136 | entry_priv->desc = addr + i * queue->desc_size; | ||
137 | entry_priv->desc_dma = dma + i * queue->desc_size; | ||
138 | } | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev, | ||
144 | struct data_queue *queue) | ||
145 | { | ||
146 | struct queue_entry_priv_pci *entry_priv = | ||
147 | queue->entries[0].priv_data; | ||
148 | |||
149 | if (entry_priv->desc) | ||
150 | dma_free_coherent(rt2x00dev->dev, | ||
151 | queue->limit * queue->desc_size, | ||
152 | entry_priv->desc, entry_priv->desc_dma); | ||
153 | entry_priv->desc = NULL; | ||
154 | } | ||
155 | |||
156 | int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) | ||
157 | { | ||
158 | struct data_queue *queue; | ||
159 | int status; | ||
160 | |||
161 | /* | ||
162 | * Allocate DMA | ||
163 | */ | ||
164 | queue_for_each(rt2x00dev, queue) { | ||
165 | status = rt2x00pci_alloc_queue_dma(rt2x00dev, queue); | ||
166 | if (status) | ||
167 | goto exit; | ||
168 | } | ||
169 | |||
170 | /* | ||
171 | * Register interrupt handler. | ||
172 | */ | ||
173 | status = request_irq(rt2x00dev->irq, | ||
174 | rt2x00dev->ops->lib->irq_handler, | ||
175 | IRQF_SHARED, rt2x00dev->name, rt2x00dev); | ||
176 | if (status) { | ||
177 | ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n", | ||
178 | rt2x00dev->irq, status); | ||
179 | goto exit; | ||
180 | } | ||
181 | |||
182 | return 0; | ||
183 | |||
184 | exit: | ||
185 | queue_for_each(rt2x00dev, queue) | ||
186 | rt2x00pci_free_queue_dma(rt2x00dev, queue); | ||
187 | |||
188 | return status; | ||
189 | } | ||
190 | EXPORT_SYMBOL_GPL(rt2x00pci_initialize); | ||
191 | |||
192 | void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev) | ||
193 | { | ||
194 | struct data_queue *queue; | ||
195 | |||
196 | /* | ||
197 | * Free irq line. | ||
198 | */ | ||
199 | free_irq(rt2x00dev->irq, rt2x00dev); | ||
200 | |||
201 | /* | ||
202 | * Free DMA | ||
203 | */ | ||
204 | queue_for_each(rt2x00dev, queue) | ||
205 | rt2x00pci_free_queue_dma(rt2x00dev, queue); | ||
206 | } | ||
207 | EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize); | ||
208 | |||
209 | /* | ||
210 | * PCI driver handlers. | 36 | * PCI driver handlers. |
211 | */ | 37 | */ |
212 | static void rt2x00pci_free_reg(struct rt2x00_dev *rt2x00dev) | 38 | static void rt2x00pci_free_reg(struct rt2x00_dev *rt2x00dev) |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index e2c99f2b9a14..60d90b20f8b9 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h | |||
@@ -36,94 +36,6 @@ | |||
36 | #define PCI_DEVICE_DATA(__ops) .driver_data = (kernel_ulong_t)(__ops) | 36 | #define PCI_DEVICE_DATA(__ops) .driver_data = (kernel_ulong_t)(__ops) |
37 | 37 | ||
38 | /* | 38 | /* |
39 | * Register access. | ||
40 | */ | ||
41 | static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev, | ||
42 | const unsigned int offset, | ||
43 | u32 *value) | ||
44 | { | ||
45 | *value = readl(rt2x00dev->csr.base + offset); | ||
46 | } | ||
47 | |||
48 | static inline void rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev, | ||
49 | const unsigned int offset, | ||
50 | void *value, const u32 length) | ||
51 | { | ||
52 | memcpy_fromio(value, rt2x00dev->csr.base + offset, length); | ||
53 | } | ||
54 | |||
55 | static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev, | ||
56 | const unsigned int offset, | ||
57 | u32 value) | ||
58 | { | ||
59 | writel(value, rt2x00dev->csr.base + offset); | ||
60 | } | ||
61 | |||
62 | static inline void rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev, | ||
63 | const unsigned int offset, | ||
64 | const void *value, | ||
65 | const u32 length) | ||
66 | { | ||
67 | __iowrite32_copy(rt2x00dev->csr.base + offset, value, length >> 2); | ||
68 | } | ||
69 | |||
70 | /** | ||
71 | * rt2x00pci_regbusy_read - Read from register with busy check | ||
72 | * @rt2x00dev: Device pointer, see &struct rt2x00_dev. | ||
73 | * @offset: Register offset | ||
74 | * @field: Field to check if register is busy | ||
75 | * @reg: Pointer to where register contents should be stored | ||
76 | * | ||
77 | * This function will read the given register, and checks if the | ||
78 | * register is busy. If it is, it will sleep for a couple of | ||
79 | * microseconds before reading the register again. If the register | ||
80 | * is not read after a certain timeout, this function will return | ||
81 | * FALSE. | ||
82 | */ | ||
83 | int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, | ||
84 | const unsigned int offset, | ||
85 | const struct rt2x00_field32 field, | ||
86 | u32 *reg); | ||
87 | |||
88 | /** | ||
89 | * struct queue_entry_priv_pci: Per entry PCI specific information | ||
90 | * | ||
91 | * @desc: Pointer to device descriptor | ||
92 | * @desc_dma: DMA pointer to &desc. | ||
93 | * @data: Pointer to device's entry memory. | ||
94 | * @data_dma: DMA pointer to &data. | ||
95 | */ | ||
96 | struct queue_entry_priv_pci { | ||
97 | __le32 *desc; | ||
98 | dma_addr_t desc_dma; | ||
99 | }; | ||
100 | |||
101 | /** | ||
102 | * rt2x00pci_rxdone - Handle RX done events | ||
103 | * @rt2x00dev: Device pointer, see &struct rt2x00_dev. | ||
104 | * | ||
105 | * Returns true if there are still rx frames pending and false if all | ||
106 | * pending rx frames were processed. | ||
107 | */ | ||
108 | bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev); | ||
109 | |||
110 | /** | ||
111 | * rt2x00pci_flush_queue - Flush data queue | ||
112 | * @queue: Data queue to stop | ||
113 | * @drop: True to drop all pending frames. | ||
114 | * | ||
115 | * This will wait for a maximum of 100ms, waiting for the queues | ||
116 | * to become empty. | ||
117 | */ | ||
118 | void rt2x00pci_flush_queue(struct data_queue *queue, bool drop); | ||
119 | |||
120 | /* | ||
121 | * Device initialization handlers. | ||
122 | */ | ||
123 | int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev); | ||
124 | void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev); | ||
125 | |||
126 | /* | ||
127 | * PCI driver handlers. | 39 | * PCI driver handlers. |
128 | */ | 40 | */ |
129 | int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops); | 41 | int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops); |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index f95792cfcf89..9e3c8ff53e3f 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/eeprom_93cx6.h> | 35 | #include <linux/eeprom_93cx6.h> |
36 | 36 | ||
37 | #include "rt2x00.h" | 37 | #include "rt2x00.h" |
38 | #include "rt2x00mmio.h" | ||
38 | #include "rt2x00pci.h" | 39 | #include "rt2x00pci.h" |
39 | #include "rt61pci.h" | 40 | #include "rt61pci.h" |
40 | 41 | ||
diff --git a/drivers/net/wireless/rtlwifi/Kconfig b/drivers/net/wireless/rtlwifi/Kconfig index b6aa0c40658f..7253de3d8c66 100644 --- a/drivers/net/wireless/rtlwifi/Kconfig +++ b/drivers/net/wireless/rtlwifi/Kconfig | |||
@@ -55,6 +55,15 @@ config RTL8723AE | |||
55 | 55 | ||
56 | If you choose to build it as a module, it will be called rtl8723ae | 56 | If you choose to build it as a module, it will be called rtl8723ae |
57 | 57 | ||
58 | config RTL8188EE | ||
59 | tristate "Realtek RTL8188EE Wireless Network Adapter" | ||
60 | depends on RTLWIFI && PCI | ||
61 | ---help--- | ||
62 | This is the driver for Realtek RTL8188EE 802.11n PCIe | ||
63 | wireless network adapters. | ||
64 | |||
65 | If you choose to build it as a module, it will be called rtl8188ee | ||
66 | |||
58 | config RTL8192CU | 67 | config RTL8192CU |
59 | tristate "Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter" | 68 | tristate "Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter" |
60 | depends on RTLWIFI && USB | 69 | depends on RTLWIFI && USB |
diff --git a/drivers/net/wireless/rtlwifi/Makefile b/drivers/net/wireless/rtlwifi/Makefile index 3b1cbac741e3..ff02b874f8d8 100644 --- a/drivers/net/wireless/rtlwifi/Makefile +++ b/drivers/net/wireless/rtlwifi/Makefile | |||
@@ -26,5 +26,6 @@ obj-$(CONFIG_RTL8192CU) += rtl8192cu/ | |||
26 | obj-$(CONFIG_RTL8192SE) += rtl8192se/ | 26 | obj-$(CONFIG_RTL8192SE) += rtl8192se/ |
27 | obj-$(CONFIG_RTL8192DE) += rtl8192de/ | 27 | obj-$(CONFIG_RTL8192DE) += rtl8192de/ |
28 | obj-$(CONFIG_RTL8723AE) += rtl8723ae/ | 28 | obj-$(CONFIG_RTL8723AE) += rtl8723ae/ |
29 | obj-$(CONFIG_RTL8188EE) += rtl8188ee/ | ||
29 | 30 | ||
30 | ccflags-y += -D__CHECK_ENDIAN__ | 31 | ccflags-y += -D__CHECK_ENDIAN__ |
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index 99c5cea3fe21..cac1fa912e8c 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c | |||
@@ -54,7 +54,8 @@ | |||
54 | *5) frame process functions | 54 | *5) frame process functions |
55 | *6) IOT functions | 55 | *6) IOT functions |
56 | *7) sysfs functions | 56 | *7) sysfs functions |
57 | *8) ... | 57 | *8) vif functions |
58 | *9) ... | ||
58 | */ | 59 | */ |
59 | 60 | ||
60 | /********************************************************* | 61 | /********************************************************* |
@@ -198,34 +199,46 @@ static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw, | |||
198 | 199 | ||
199 | ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | 200 | ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; |
200 | 201 | ||
201 | /* | 202 | /*hw->wiphy->bands[IEEE80211_BAND_2GHZ] |
202 | *hw->wiphy->bands[IEEE80211_BAND_2GHZ] | ||
203 | *base on ant_num | 203 | *base on ant_num |
204 | *rx_mask: RX mask | 204 | *rx_mask: RX mask |
205 | *if rx_ant =1 rx_mask[0]=0xff;==>MCS0-MCS7 | 205 | *if rx_ant = 1 rx_mask[0]= 0xff;==>MCS0-MCS7 |
206 | *if rx_ant =2 rx_mask[1]=0xff;==>MCS8-MCS15 | 206 | *if rx_ant = 2 rx_mask[1]= 0xff;==>MCS8-MCS15 |
207 | *if rx_ant >=3 rx_mask[2]=0xff; | 207 | *if rx_ant >= 3 rx_mask[2]= 0xff; |
208 | *if BW_40 rx_mask[4]=0x01; | 208 | *if BW_40 rx_mask[4]= 0x01; |
209 | *highest supported RX rate | 209 | *highest supported RX rate |
210 | */ | 210 | */ |
211 | if (get_rf_type(rtlphy) == RF_1T2R || get_rf_type(rtlphy) == RF_2T2R) { | 211 | if (rtlpriv->dm.supp_phymode_switch) { |
212 | 212 | ||
213 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "1T2R or 2T2R\n"); | 213 | RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, |
214 | "Support phy mode switch\n"); | ||
214 | 215 | ||
215 | ht_cap->mcs.rx_mask[0] = 0xFF; | 216 | ht_cap->mcs.rx_mask[0] = 0xFF; |
216 | ht_cap->mcs.rx_mask[1] = 0xFF; | 217 | ht_cap->mcs.rx_mask[1] = 0xFF; |
217 | ht_cap->mcs.rx_mask[4] = 0x01; | 218 | ht_cap->mcs.rx_mask[4] = 0x01; |
218 | 219 | ||
219 | ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15); | 220 | ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15); |
220 | } else if (get_rf_type(rtlphy) == RF_1T1R) { | 221 | } else { |
221 | 222 | if (get_rf_type(rtlphy) == RF_1T2R || | |
222 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "1T1R\n"); | 223 | get_rf_type(rtlphy) == RF_2T2R) { |
223 | 224 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | |
224 | ht_cap->mcs.rx_mask[0] = 0xFF; | 225 | "1T2R or 2T2R\n"); |
225 | ht_cap->mcs.rx_mask[1] = 0x00; | 226 | ht_cap->mcs.rx_mask[0] = 0xFF; |
226 | ht_cap->mcs.rx_mask[4] = 0x01; | 227 | ht_cap->mcs.rx_mask[1] = 0xFF; |
227 | 228 | ht_cap->mcs.rx_mask[4] = 0x01; | |
228 | ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS7); | 229 | |
230 | ht_cap->mcs.rx_highest = | ||
231 | cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15); | ||
232 | } else if (get_rf_type(rtlphy) == RF_1T1R) { | ||
233 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "1T1R\n"); | ||
234 | |||
235 | ht_cap->mcs.rx_mask[0] = 0xFF; | ||
236 | ht_cap->mcs.rx_mask[1] = 0x00; | ||
237 | ht_cap->mcs.rx_mask[4] = 0x01; | ||
238 | |||
239 | ht_cap->mcs.rx_highest = | ||
240 | cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS7); | ||
241 | } | ||
229 | } | 242 | } |
230 | } | 243 | } |
231 | 244 | ||
@@ -311,6 +324,8 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw) | |||
311 | IEEE80211_HW_AMPDU_AGGREGATION | | 324 | IEEE80211_HW_AMPDU_AGGREGATION | |
312 | IEEE80211_HW_CONNECTION_MONITOR | | 325 | IEEE80211_HW_CONNECTION_MONITOR | |
313 | /* IEEE80211_HW_SUPPORTS_CQM_RSSI | */ | 326 | /* IEEE80211_HW_SUPPORTS_CQM_RSSI | */ |
327 | IEEE80211_HW_CONNECTION_MONITOR | | ||
328 | IEEE80211_HW_MFP_CAPABLE | | ||
314 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | 0; | 329 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | 0; |
315 | 330 | ||
316 | /* swlps or hwlps has been set in diff chip in init_sw_vars */ | 331 | /* swlps or hwlps has been set in diff chip in init_sw_vars */ |
@@ -323,8 +338,12 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw) | |||
323 | hw->wiphy->interface_modes = | 338 | hw->wiphy->interface_modes = |
324 | BIT(NL80211_IFTYPE_AP) | | 339 | BIT(NL80211_IFTYPE_AP) | |
325 | BIT(NL80211_IFTYPE_STATION) | | 340 | BIT(NL80211_IFTYPE_STATION) | |
326 | BIT(NL80211_IFTYPE_ADHOC); | 341 | BIT(NL80211_IFTYPE_ADHOC) | |
342 | BIT(NL80211_IFTYPE_MESH_POINT) | | ||
343 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
344 | BIT(NL80211_IFTYPE_P2P_GO); | ||
327 | 345 | ||
346 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | ||
328 | hw->wiphy->rts_threshold = 2347; | 347 | hw->wiphy->rts_threshold = 2347; |
329 | 348 | ||
330 | hw->queues = AC_MAX; | 349 | hw->queues = AC_MAX; |
@@ -354,9 +373,10 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw) | |||
354 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 373 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
355 | 374 | ||
356 | /* <1> timer */ | 375 | /* <1> timer */ |
357 | init_timer(&rtlpriv->works.watchdog_timer); | ||
358 | setup_timer(&rtlpriv->works.watchdog_timer, | 376 | setup_timer(&rtlpriv->works.watchdog_timer, |
359 | rtl_watch_dog_timer_callback, (unsigned long)hw); | 377 | rtl_watch_dog_timer_callback, (unsigned long)hw); |
378 | setup_timer(&rtlpriv->works.dualmac_easyconcurrent_retrytimer, | ||
379 | rtl_easy_concurrent_retrytimer_callback, (unsigned long)hw); | ||
360 | 380 | ||
361 | /* <2> work queue */ | 381 | /* <2> work queue */ |
362 | rtlpriv->works.hw = hw; | 382 | rtlpriv->works.hw = hw; |
@@ -369,6 +389,8 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw) | |||
369 | (void *)rtl_swlps_wq_callback); | 389 | (void *)rtl_swlps_wq_callback); |
370 | INIT_DELAYED_WORK(&rtlpriv->works.ps_rfon_wq, | 390 | INIT_DELAYED_WORK(&rtlpriv->works.ps_rfon_wq, |
371 | (void *)rtl_swlps_rfon_wq_callback); | 391 | (void *)rtl_swlps_rfon_wq_callback); |
392 | INIT_DELAYED_WORK(&rtlpriv->works.fwevt_wq, | ||
393 | (void *)rtl_fwevt_wq_callback); | ||
372 | 394 | ||
373 | } | 395 | } |
374 | 396 | ||
@@ -382,6 +404,7 @@ void rtl_deinit_deferred_work(struct ieee80211_hw *hw) | |||
382 | cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq); | 404 | cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq); |
383 | cancel_delayed_work(&rtlpriv->works.ps_work); | 405 | cancel_delayed_work(&rtlpriv->works.ps_work); |
384 | cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); | 406 | cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); |
407 | cancel_delayed_work(&rtlpriv->works.fwevt_wq); | ||
385 | } | 408 | } |
386 | 409 | ||
387 | void rtl_init_rfkill(struct ieee80211_hw *hw) | 410 | void rtl_init_rfkill(struct ieee80211_hw *hw) |
@@ -436,12 +459,6 @@ int rtl_init_core(struct ieee80211_hw *hw) | |||
436 | if (rtl_regd_init(hw, rtl_reg_notifier)) { | 459 | if (rtl_regd_init(hw, rtl_reg_notifier)) { |
437 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "REGD init failed\n"); | 460 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "REGD init failed\n"); |
438 | return 1; | 461 | return 1; |
439 | } else { | ||
440 | /* CRDA regd hint must after init CRDA */ | ||
441 | if (regulatory_hint(hw->wiphy, rtlpriv->regd.alpha2)) { | ||
442 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
443 | "regulatory_hint fail\n"); | ||
444 | } | ||
445 | } | 462 | } |
446 | 463 | ||
447 | /* <4> locks */ | 464 | /* <4> locks */ |
@@ -449,15 +466,25 @@ int rtl_init_core(struct ieee80211_hw *hw) | |||
449 | mutex_init(&rtlpriv->locks.ps_mutex); | 466 | mutex_init(&rtlpriv->locks.ps_mutex); |
450 | spin_lock_init(&rtlpriv->locks.ips_lock); | 467 | spin_lock_init(&rtlpriv->locks.ips_lock); |
451 | spin_lock_init(&rtlpriv->locks.irq_th_lock); | 468 | spin_lock_init(&rtlpriv->locks.irq_th_lock); |
469 | spin_lock_init(&rtlpriv->locks.irq_pci_lock); | ||
470 | spin_lock_init(&rtlpriv->locks.tx_lock); | ||
452 | spin_lock_init(&rtlpriv->locks.h2c_lock); | 471 | spin_lock_init(&rtlpriv->locks.h2c_lock); |
453 | spin_lock_init(&rtlpriv->locks.rf_ps_lock); | 472 | spin_lock_init(&rtlpriv->locks.rf_ps_lock); |
454 | spin_lock_init(&rtlpriv->locks.rf_lock); | 473 | spin_lock_init(&rtlpriv->locks.rf_lock); |
455 | spin_lock_init(&rtlpriv->locks.waitq_lock); | 474 | spin_lock_init(&rtlpriv->locks.waitq_lock); |
475 | spin_lock_init(&rtlpriv->locks.entry_list_lock); | ||
476 | spin_lock_init(&rtlpriv->locks.fw_ps_lock); | ||
456 | spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock); | 477 | spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock); |
478 | spin_lock_init(&rtlpriv->locks.check_sendpkt_lock); | ||
479 | spin_lock_init(&rtlpriv->locks.fw_ps_lock); | ||
480 | spin_lock_init(&rtlpriv->locks.lps_lock); | ||
481 | |||
482 | /* <5> init list */ | ||
483 | INIT_LIST_HEAD(&rtlpriv->entry_list); | ||
457 | 484 | ||
458 | rtlmac->link_state = MAC80211_NOLINK; | 485 | rtlmac->link_state = MAC80211_NOLINK; |
459 | 486 | ||
460 | /* <5> init deferred work */ | 487 | /* <6> init deferred work */ |
461 | _rtl_init_deferred_work(hw); | 488 | _rtl_init_deferred_work(hw); |
462 | 489 | ||
463 | return 0; | 490 | return 0; |
@@ -523,7 +550,8 @@ static void _rtl_query_shortgi(struct ieee80211_hw *hw, | |||
523 | if (mac->opmode == NL80211_IFTYPE_STATION) | 550 | if (mac->opmode == NL80211_IFTYPE_STATION) |
524 | bw_40 = mac->bw_40; | 551 | bw_40 = mac->bw_40; |
525 | else if (mac->opmode == NL80211_IFTYPE_AP || | 552 | else if (mac->opmode == NL80211_IFTYPE_AP || |
526 | mac->opmode == NL80211_IFTYPE_ADHOC) | 553 | mac->opmode == NL80211_IFTYPE_ADHOC || |
554 | mac->opmode == NL80211_IFTYPE_MESH_POINT) | ||
527 | bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40; | 555 | bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40; |
528 | 556 | ||
529 | if (bw_40 && sgi_40) | 557 | if (bw_40 && sgi_40) |
@@ -578,23 +606,26 @@ static void _rtl_txrate_selectmode(struct ieee80211_hw *hw, | |||
578 | if (!tcb_desc->disable_ratefallback || !tcb_desc->use_driver_rate) { | 606 | if (!tcb_desc->disable_ratefallback || !tcb_desc->use_driver_rate) { |
579 | if (mac->opmode == NL80211_IFTYPE_STATION) { | 607 | if (mac->opmode == NL80211_IFTYPE_STATION) { |
580 | tcb_desc->ratr_index = 0; | 608 | tcb_desc->ratr_index = 0; |
581 | } else if (mac->opmode == NL80211_IFTYPE_ADHOC) { | 609 | } else if (mac->opmode == NL80211_IFTYPE_ADHOC || |
610 | mac->opmode == NL80211_IFTYPE_MESH_POINT) { | ||
582 | if (tcb_desc->multicast || tcb_desc->broadcast) { | 611 | if (tcb_desc->multicast || tcb_desc->broadcast) { |
583 | tcb_desc->hw_rate = | 612 | tcb_desc->hw_rate = |
584 | rtlpriv->cfg->maps[RTL_RC_CCK_RATE2M]; | 613 | rtlpriv->cfg->maps[RTL_RC_CCK_RATE2M]; |
585 | tcb_desc->use_driver_rate = 1; | 614 | tcb_desc->use_driver_rate = 1; |
615 | tcb_desc->ratr_index = RATR_INX_WIRELESS_MC; | ||
586 | } else { | 616 | } else { |
587 | /* TODO */ | 617 | tcb_desc->ratr_index = ratr_index; |
588 | } | 618 | } |
589 | tcb_desc->ratr_index = ratr_index; | ||
590 | } else if (mac->opmode == NL80211_IFTYPE_AP) { | 619 | } else if (mac->opmode == NL80211_IFTYPE_AP) { |
591 | tcb_desc->ratr_index = ratr_index; | 620 | tcb_desc->ratr_index = ratr_index; |
592 | } | 621 | } |
593 | } | 622 | } |
594 | 623 | ||
595 | if (rtlpriv->dm.useramask) { | 624 | if (rtlpriv->dm.useramask) { |
596 | /* TODO we will differentiate adhoc and station futrue */ | 625 | tcb_desc->ratr_index = ratr_index; |
597 | if (mac->opmode == NL80211_IFTYPE_STATION) { | 626 | /* TODO we will differentiate adhoc and station future */ |
627 | if (mac->opmode == NL80211_IFTYPE_STATION || | ||
628 | mac->opmode == NL80211_IFTYPE_MESH_POINT) { | ||
598 | tcb_desc->mac_id = 0; | 629 | tcb_desc->mac_id = 0; |
599 | 630 | ||
600 | if (mac->mode == WIRELESS_MODE_N_24G) | 631 | if (mac->mode == WIRELESS_MODE_N_24G) |
@@ -608,7 +639,7 @@ static void _rtl_txrate_selectmode(struct ieee80211_hw *hw, | |||
608 | else if (mac->mode & WIRELESS_MODE_A) | 639 | else if (mac->mode & WIRELESS_MODE_A) |
609 | tcb_desc->ratr_index = RATR_INX_WIRELESS_G; | 640 | tcb_desc->ratr_index = RATR_INX_WIRELESS_G; |
610 | } else if (mac->opmode == NL80211_IFTYPE_AP || | 641 | } else if (mac->opmode == NL80211_IFTYPE_AP || |
611 | mac->opmode == NL80211_IFTYPE_ADHOC) { | 642 | mac->opmode == NL80211_IFTYPE_ADHOC) { |
612 | if (NULL != sta) { | 643 | if (NULL != sta) { |
613 | if (sta->aid > 0) | 644 | if (sta->aid > 0) |
614 | tcb_desc->mac_id = sta->aid + 1; | 645 | tcb_desc->mac_id = sta->aid + 1; |
@@ -619,7 +650,6 @@ static void _rtl_txrate_selectmode(struct ieee80211_hw *hw, | |||
619 | } | 650 | } |
620 | } | 651 | } |
621 | } | 652 | } |
622 | |||
623 | } | 653 | } |
624 | 654 | ||
625 | static void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw, | 655 | static void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw, |
@@ -633,7 +663,8 @@ static void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw, | |||
633 | if (!sta) | 663 | if (!sta) |
634 | return; | 664 | return; |
635 | if (mac->opmode == NL80211_IFTYPE_AP || | 665 | if (mac->opmode == NL80211_IFTYPE_AP || |
636 | mac->opmode == NL80211_IFTYPE_ADHOC) { | 666 | mac->opmode == NL80211_IFTYPE_ADHOC || |
667 | mac->opmode == NL80211_IFTYPE_MESH_POINT) { | ||
637 | if (sta->bandwidth == IEEE80211_STA_RX_BW_20) | 668 | if (sta->bandwidth == IEEE80211_STA_RX_BW_20) |
638 | return; | 669 | return; |
639 | } else if (mac->opmode == NL80211_IFTYPE_STATION) { | 670 | } else if (mac->opmode == NL80211_IFTYPE_STATION) { |
@@ -834,8 +865,8 @@ bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
834 | if (rtlpriv->dm.supp_phymode_switch && | 865 | if (rtlpriv->dm.supp_phymode_switch && |
835 | mac->link_state < MAC80211_LINKED && | 866 | mac->link_state < MAC80211_LINKED && |
836 | (ieee80211_is_auth(fc) || ieee80211_is_probe_req(fc))) { | 867 | (ieee80211_is_auth(fc) || ieee80211_is_probe_req(fc))) { |
837 | if (rtlpriv->cfg->ops->check_switch_to_dmdp) | 868 | if (rtlpriv->cfg->ops->chk_switch_dmdp) |
838 | rtlpriv->cfg->ops->check_switch_to_dmdp(hw); | 869 | rtlpriv->cfg->ops->chk_switch_dmdp(hw); |
839 | } | 870 | } |
840 | if (ieee80211_is_auth(fc)) { | 871 | if (ieee80211_is_auth(fc)) { |
841 | RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n"); | 872 | RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n"); |
@@ -924,6 +955,56 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw, | |||
924 | } | 955 | } |
925 | EXPORT_SYMBOL(rtl_get_tcb_desc); | 956 | EXPORT_SYMBOL(rtl_get_tcb_desc); |
926 | 957 | ||
958 | static bool addbareq_rx(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
959 | { | ||
960 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
961 | struct ieee80211_sta *sta = NULL; | ||
962 | struct ieee80211_hdr *hdr = rtl_get_hdr(skb); | ||
963 | struct rtl_sta_info *sta_entry = NULL; | ||
964 | struct ieee80211_mgmt *mgmt = (void *)skb->data; | ||
965 | u16 capab = 0, tid = 0; | ||
966 | struct rtl_tid_data *tid_data; | ||
967 | struct sk_buff *skb_delba = NULL; | ||
968 | struct ieee80211_rx_status rx_status = { 0 }; | ||
969 | |||
970 | rcu_read_lock(); | ||
971 | sta = rtl_find_sta(hw, hdr->addr3); | ||
972 | if (sta == NULL) { | ||
973 | RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_EMERG, | ||
974 | "sta is NULL\n"); | ||
975 | rcu_read_unlock(); | ||
976 | return true; | ||
977 | } | ||
978 | |||
979 | sta_entry = (struct rtl_sta_info *)sta->drv_priv; | ||
980 | if (!sta_entry) { | ||
981 | rcu_read_unlock(); | ||
982 | return true; | ||
983 | } | ||
984 | capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); | ||
985 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | ||
986 | tid_data = &sta_entry->tids[tid]; | ||
987 | if (tid_data->agg.rx_agg_state == RTL_RX_AGG_START) { | ||
988 | skb_delba = rtl_make_del_ba(hw, hdr->addr2, hdr->addr3, tid); | ||
989 | if (skb_delba) { | ||
990 | rx_status.freq = hw->conf.channel->center_freq; | ||
991 | rx_status.band = hw->conf.channel->band; | ||
992 | rx_status.flag |= RX_FLAG_DECRYPTED; | ||
993 | rx_status.flag |= RX_FLAG_MACTIME_END; | ||
994 | rx_status.rate_idx = 0; | ||
995 | rx_status.signal = 50 + 10; | ||
996 | memcpy(IEEE80211_SKB_RXCB(skb_delba), &rx_status, | ||
997 | sizeof(rx_status)); | ||
998 | RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, | ||
999 | "fake del\n", skb_delba->data, | ||
1000 | skb_delba->len); | ||
1001 | ieee80211_rx_irqsafe(hw, skb_delba); | ||
1002 | } | ||
1003 | } | ||
1004 | rcu_read_unlock(); | ||
1005 | return false; | ||
1006 | } | ||
1007 | |||
927 | bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) | 1008 | bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) |
928 | { | 1009 | { |
929 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 1010 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
@@ -948,6 +1029,11 @@ bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) | |||
948 | RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, | 1029 | RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, |
949 | "%s ACT_ADDBAREQ From :%pM\n", | 1030 | "%s ACT_ADDBAREQ From :%pM\n", |
950 | is_tx ? "Tx" : "Rx", hdr->addr2); | 1031 | is_tx ? "Tx" : "Rx", hdr->addr2); |
1032 | RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "req\n", | ||
1033 | skb->data, skb->len); | ||
1034 | if (!is_tx) | ||
1035 | if (addbareq_rx(hw, skb)) | ||
1036 | return true; | ||
951 | break; | 1037 | break; |
952 | case ACT_ADDBARSP: | 1038 | case ACT_ADDBARSP: |
953 | RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, | 1039 | RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, |
@@ -1003,8 +1089,9 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) | |||
1003 | is_tx ? "Tx" : "Rx"); | 1089 | is_tx ? "Tx" : "Rx"); |
1004 | 1090 | ||
1005 | if (is_tx) { | 1091 | if (is_tx) { |
1092 | rtlpriv->enter_ps = false; | ||
1006 | schedule_work(&rtlpriv-> | 1093 | schedule_work(&rtlpriv-> |
1007 | works.lps_leave_work); | 1094 | works.lps_change_work); |
1008 | ppsc->last_delaylps_stamp_jiffies = | 1095 | ppsc->last_delaylps_stamp_jiffies = |
1009 | jiffies; | 1096 | jiffies; |
1010 | } | 1097 | } |
@@ -1014,7 +1101,8 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) | |||
1014 | } | 1101 | } |
1015 | } else if (ETH_P_ARP == ether_type) { | 1102 | } else if (ETH_P_ARP == ether_type) { |
1016 | if (is_tx) { | 1103 | if (is_tx) { |
1017 | schedule_work(&rtlpriv->works.lps_leave_work); | 1104 | rtlpriv->enter_ps = false; |
1105 | schedule_work(&rtlpriv->works.lps_change_work); | ||
1018 | ppsc->last_delaylps_stamp_jiffies = jiffies; | 1106 | ppsc->last_delaylps_stamp_jiffies = jiffies; |
1019 | } | 1107 | } |
1020 | 1108 | ||
@@ -1024,7 +1112,8 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) | |||
1024 | "802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx"); | 1112 | "802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx"); |
1025 | 1113 | ||
1026 | if (is_tx) { | 1114 | if (is_tx) { |
1027 | schedule_work(&rtlpriv->works.lps_leave_work); | 1115 | rtlpriv->enter_ps = false; |
1116 | schedule_work(&rtlpriv->works.lps_change_work); | ||
1028 | ppsc->last_delaylps_stamp_jiffies = jiffies; | 1117 | ppsc->last_delaylps_stamp_jiffies = jiffies; |
1029 | } | 1118 | } |
1030 | 1119 | ||
@@ -1101,6 +1190,58 @@ int rtl_tx_agg_stop(struct ieee80211_hw *hw, | |||
1101 | return 0; | 1190 | return 0; |
1102 | } | 1191 | } |
1103 | 1192 | ||
1193 | int rtl_rx_agg_start(struct ieee80211_hw *hw, | ||
1194 | struct ieee80211_sta *sta, u16 tid) | ||
1195 | { | ||
1196 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1197 | struct rtl_tid_data *tid_data; | ||
1198 | struct rtl_sta_info *sta_entry = NULL; | ||
1199 | |||
1200 | if (sta == NULL) | ||
1201 | return -EINVAL; | ||
1202 | |||
1203 | if (unlikely(tid >= MAX_TID_COUNT)) | ||
1204 | return -EINVAL; | ||
1205 | |||
1206 | sta_entry = (struct rtl_sta_info *)sta->drv_priv; | ||
1207 | if (!sta_entry) | ||
1208 | return -ENXIO; | ||
1209 | tid_data = &sta_entry->tids[tid]; | ||
1210 | |||
1211 | RT_TRACE(rtlpriv, COMP_RECV, DBG_DMESG, | ||
1212 | "on ra = %pM tid = %d seq:%d\n", sta->addr, tid, | ||
1213 | tid_data->seq_number); | ||
1214 | |||
1215 | tid_data->agg.rx_agg_state = RTL_RX_AGG_START; | ||
1216 | return 0; | ||
1217 | } | ||
1218 | |||
1219 | int rtl_rx_agg_stop(struct ieee80211_hw *hw, | ||
1220 | struct ieee80211_sta *sta, u16 tid) | ||
1221 | { | ||
1222 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1223 | struct rtl_sta_info *sta_entry = NULL; | ||
1224 | |||
1225 | if (sta == NULL) | ||
1226 | return -EINVAL; | ||
1227 | |||
1228 | if (!sta->addr) { | ||
1229 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "ra = NULL\n"); | ||
1230 | return -EINVAL; | ||
1231 | } | ||
1232 | |||
1233 | RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, | ||
1234 | "on ra = %pM tid = %d\n", sta->addr, tid); | ||
1235 | |||
1236 | if (unlikely(tid >= MAX_TID_COUNT)) | ||
1237 | return -EINVAL; | ||
1238 | |||
1239 | sta_entry = (struct rtl_sta_info *)sta->drv_priv; | ||
1240 | sta_entry->tids[tid].agg.rx_agg_state = RTL_RX_AGG_STOP; | ||
1241 | |||
1242 | return 0; | ||
1243 | } | ||
1244 | |||
1104 | int rtl_tx_agg_oper(struct ieee80211_hw *hw, | 1245 | int rtl_tx_agg_oper(struct ieee80211_hw *hw, |
1105 | struct ieee80211_sta *sta, u16 tid) | 1246 | struct ieee80211_sta *sta, u16 tid) |
1106 | { | 1247 | { |
@@ -1132,6 +1273,34 @@ int rtl_tx_agg_oper(struct ieee80211_hw *hw, | |||
1132 | * wq & timer callback functions | 1273 | * wq & timer callback functions |
1133 | * | 1274 | * |
1134 | *********************************************************/ | 1275 | *********************************************************/ |
1276 | /* this function is used for roaming */ | ||
1277 | void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
1278 | { | ||
1279 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1280 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
1281 | |||
1282 | if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION) | ||
1283 | return; | ||
1284 | |||
1285 | if (rtlpriv->mac80211.link_state < MAC80211_LINKED) | ||
1286 | return; | ||
1287 | |||
1288 | /* check if this really is a beacon */ | ||
1289 | if (!ieee80211_is_beacon(hdr->frame_control) && | ||
1290 | !ieee80211_is_probe_resp(hdr->frame_control)) | ||
1291 | return; | ||
1292 | |||
1293 | /* min. beacon length + FCS_LEN */ | ||
1294 | if (skb->len <= 40 + FCS_LEN) | ||
1295 | return; | ||
1296 | |||
1297 | /* and only beacons from the associated BSSID, please */ | ||
1298 | if (compare_ether_addr(hdr->addr3, rtlpriv->mac80211.bssid)) | ||
1299 | return; | ||
1300 | |||
1301 | rtlpriv->link_info.bcn_rx_inperiod++; | ||
1302 | } | ||
1303 | |||
1135 | void rtl_watchdog_wq_callback(void *data) | 1304 | void rtl_watchdog_wq_callback(void *data) |
1136 | { | 1305 | { |
1137 | struct rtl_works *rtlworks = container_of_dwork_rtl(data, | 1306 | struct rtl_works *rtlworks = container_of_dwork_rtl(data, |
@@ -1142,6 +1311,8 @@ void rtl_watchdog_wq_callback(void *data) | |||
1142 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 1311 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
1143 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 1312 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
1144 | bool busytraffic = false; | 1313 | bool busytraffic = false; |
1314 | bool tx_busy_traffic = false; | ||
1315 | bool rx_busy_traffic = false; | ||
1145 | bool higher_busytraffic = false; | 1316 | bool higher_busytraffic = false; |
1146 | bool higher_busyrxtraffic = false; | 1317 | bool higher_busyrxtraffic = false; |
1147 | u8 idx, tid; | 1318 | u8 idx, tid; |
@@ -1151,7 +1322,6 @@ void rtl_watchdog_wq_callback(void *data) | |||
1151 | u32 aver_tx_cnt_inperiod = 0; | 1322 | u32 aver_tx_cnt_inperiod = 0; |
1152 | u32 aver_tidtx_inperiod[MAX_TID_COUNT] = {0}; | 1323 | u32 aver_tidtx_inperiod[MAX_TID_COUNT] = {0}; |
1153 | u32 tidtx_inp4eriod[MAX_TID_COUNT] = {0}; | 1324 | u32 tidtx_inp4eriod[MAX_TID_COUNT] = {0}; |
1154 | bool enter_ps = false; | ||
1155 | 1325 | ||
1156 | if (is_hal_stop(rtlhal)) | 1326 | if (is_hal_stop(rtlhal)) |
1157 | return; | 1327 | return; |
@@ -1191,8 +1361,13 @@ void rtl_watchdog_wq_callback(void *data) | |||
1191 | aver_tx_cnt_inperiod = tx_cnt_inp4eriod / 4; | 1361 | aver_tx_cnt_inperiod = tx_cnt_inp4eriod / 4; |
1192 | 1362 | ||
1193 | /* (2) check traffic busy */ | 1363 | /* (2) check traffic busy */ |
1194 | if (aver_rx_cnt_inperiod > 100 || aver_tx_cnt_inperiod > 100) | 1364 | if (aver_rx_cnt_inperiod > 100 || aver_tx_cnt_inperiod > 100) { |
1195 | busytraffic = true; | 1365 | busytraffic = true; |
1366 | if (aver_rx_cnt_inperiod > aver_tx_cnt_inperiod) | ||
1367 | rx_busy_traffic = true; | ||
1368 | else | ||
1369 | tx_busy_traffic = false; | ||
1370 | } | ||
1196 | 1371 | ||
1197 | /* Higher Tx/Rx data. */ | 1372 | /* Higher Tx/Rx data. */ |
1198 | if (aver_rx_cnt_inperiod > 4000 || | 1373 | if (aver_rx_cnt_inperiod > 4000 || |
@@ -1228,15 +1403,12 @@ void rtl_watchdog_wq_callback(void *data) | |||
1228 | if (((rtlpriv->link_info.num_rx_inperiod + | 1403 | if (((rtlpriv->link_info.num_rx_inperiod + |
1229 | rtlpriv->link_info.num_tx_inperiod) > 8) || | 1404 | rtlpriv->link_info.num_tx_inperiod) > 8) || |
1230 | (rtlpriv->link_info.num_rx_inperiod > 2)) | 1405 | (rtlpriv->link_info.num_rx_inperiod > 2)) |
1231 | enter_ps = false; | 1406 | rtlpriv->enter_ps = true; |
1232 | else | 1407 | else |
1233 | enter_ps = true; | 1408 | rtlpriv->enter_ps = false; |
1234 | 1409 | ||
1235 | /* LeisurePS only work in infra mode. */ | 1410 | /* LeisurePS only work in infra mode. */ |
1236 | if (enter_ps) | 1411 | schedule_work(&rtlpriv->works.lps_change_work); |
1237 | rtl_lps_enter(hw); | ||
1238 | else | ||
1239 | rtl_lps_leave(hw); | ||
1240 | } | 1412 | } |
1241 | 1413 | ||
1242 | rtlpriv->link_info.num_rx_inperiod = 0; | 1414 | rtlpriv->link_info.num_rx_inperiod = 0; |
@@ -1246,10 +1418,37 @@ void rtl_watchdog_wq_callback(void *data) | |||
1246 | 1418 | ||
1247 | rtlpriv->link_info.busytraffic = busytraffic; | 1419 | rtlpriv->link_info.busytraffic = busytraffic; |
1248 | rtlpriv->link_info.higher_busytraffic = higher_busytraffic; | 1420 | rtlpriv->link_info.higher_busytraffic = higher_busytraffic; |
1421 | rtlpriv->link_info.rx_busy_traffic = rx_busy_traffic; | ||
1422 | rtlpriv->link_info.tx_busy_traffic = tx_busy_traffic; | ||
1249 | rtlpriv->link_info.higher_busyrxtraffic = higher_busyrxtraffic; | 1423 | rtlpriv->link_info.higher_busyrxtraffic = higher_busyrxtraffic; |
1250 | 1424 | ||
1251 | /* <3> DM */ | 1425 | /* <3> DM */ |
1252 | rtlpriv->cfg->ops->dm_watchdog(hw); | 1426 | rtlpriv->cfg->ops->dm_watchdog(hw); |
1427 | |||
1428 | /* <4> roaming */ | ||
1429 | if (mac->link_state == MAC80211_LINKED && | ||
1430 | mac->opmode == NL80211_IFTYPE_STATION) { | ||
1431 | if ((rtlpriv->link_info.bcn_rx_inperiod + | ||
1432 | rtlpriv->link_info.num_rx_inperiod) == 0) { | ||
1433 | rtlpriv->link_info.roam_times++; | ||
1434 | RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, | ||
1435 | "AP off for %d s\n", | ||
1436 | (rtlpriv->link_info.roam_times * 2)); | ||
1437 | |||
1438 | /* if we can't recv beacon for 6s, we should | ||
1439 | * reconnect this AP | ||
1440 | */ | ||
1441 | if (rtlpriv->link_info.roam_times >= 3) { | ||
1442 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1443 | "AP off, try to reconnect now\n"); | ||
1444 | rtlpriv->link_info.roam_times = 0; | ||
1445 | ieee80211_connection_loss(rtlpriv->mac80211.vif); | ||
1446 | } | ||
1447 | } else { | ||
1448 | rtlpriv->link_info.roam_times = 0; | ||
1449 | } | ||
1450 | } | ||
1451 | rtlpriv->link_info.bcn_rx_inperiod = 0; | ||
1253 | } | 1452 | } |
1254 | 1453 | ||
1255 | void rtl_watch_dog_timer_callback(unsigned long data) | 1454 | void rtl_watch_dog_timer_callback(unsigned long data) |
@@ -1264,6 +1463,28 @@ void rtl_watch_dog_timer_callback(unsigned long data) | |||
1264 | jiffies + MSECS(RTL_WATCH_DOG_TIME)); | 1463 | jiffies + MSECS(RTL_WATCH_DOG_TIME)); |
1265 | } | 1464 | } |
1266 | 1465 | ||
1466 | void rtl_fwevt_wq_callback(void *data) | ||
1467 | { | ||
1468 | struct rtl_works *rtlworks = | ||
1469 | container_of_dwork_rtl(data, struct rtl_works, fwevt_wq); | ||
1470 | struct ieee80211_hw *hw = rtlworks->hw; | ||
1471 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1472 | |||
1473 | rtlpriv->cfg->ops->c2h_command_handle(hw); | ||
1474 | } | ||
1475 | |||
1476 | void rtl_easy_concurrent_retrytimer_callback(unsigned long data) | ||
1477 | { | ||
1478 | struct ieee80211_hw *hw = (struct ieee80211_hw *)data; | ||
1479 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1480 | struct rtl_priv *buddy_priv = rtlpriv->buddy_priv; | ||
1481 | |||
1482 | if (buddy_priv == NULL) | ||
1483 | return; | ||
1484 | |||
1485 | rtlpriv->cfg->ops->dualmac_easy_concurrent(hw); | ||
1486 | } | ||
1487 | |||
1267 | /********************************************************* | 1488 | /********************************************************* |
1268 | * | 1489 | * |
1269 | * frame process functions | 1490 | * frame process functions |
@@ -1334,14 +1555,16 @@ static struct sk_buff *rtl_make_smps_action(struct ieee80211_hw *hw, | |||
1334 | } | 1555 | } |
1335 | 1556 | ||
1336 | int rtl_send_smps_action(struct ieee80211_hw *hw, | 1557 | int rtl_send_smps_action(struct ieee80211_hw *hw, |
1337 | struct ieee80211_sta *sta, u8 *da, u8 *bssid, | 1558 | struct ieee80211_sta *sta, |
1338 | enum ieee80211_smps_mode smps) | 1559 | enum ieee80211_smps_mode smps) |
1339 | { | 1560 | { |
1340 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1561 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1341 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 1562 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
1342 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | 1563 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
1343 | struct sk_buff *skb = rtl_make_smps_action(hw, smps, da, bssid); | 1564 | struct sk_buff *skb = NULL; |
1344 | struct rtl_tcb_desc tcb_desc; | 1565 | struct rtl_tcb_desc tcb_desc; |
1566 | u8 bssid[ETH_ALEN] = {0}; | ||
1567 | |||
1345 | memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); | 1568 | memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); |
1346 | 1569 | ||
1347 | if (rtlpriv->mac80211.act_scanning) | 1570 | if (rtlpriv->mac80211.act_scanning) |
@@ -1356,21 +1579,67 @@ int rtl_send_smps_action(struct ieee80211_hw *hw, | |||
1356 | if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) | 1579 | if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) |
1357 | goto err_free; | 1580 | goto err_free; |
1358 | 1581 | ||
1582 | if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP) | ||
1583 | memcpy(bssid, rtlpriv->efuse.dev_addr, ETH_ALEN); | ||
1584 | else | ||
1585 | memcpy(bssid, rtlpriv->mac80211.bssid, ETH_ALEN); | ||
1586 | |||
1587 | skb = rtl_make_smps_action(hw, smps, sta->addr, bssid); | ||
1359 | /* this is a type = mgmt * stype = action frame */ | 1588 | /* this is a type = mgmt * stype = action frame */ |
1360 | if (skb) { | 1589 | if (skb) { |
1361 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1590 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1362 | struct rtl_sta_info *sta_entry = | 1591 | struct rtl_sta_info *sta_entry = |
1363 | (struct rtl_sta_info *) sta->drv_priv; | 1592 | (struct rtl_sta_info *) sta->drv_priv; |
1364 | sta_entry->mimo_ps = smps; | 1593 | sta_entry->mimo_ps = smps; |
1365 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); | ||
1366 | 1594 | ||
1367 | info->control.rates[0].idx = 0; | 1595 | info->control.rates[0].idx = 0; |
1368 | info->band = hw->conf.channel->band; | 1596 | info->band = hw->conf.channel->band; |
1369 | rtlpriv->intf_ops->adapter_tx(hw, sta, skb, &tcb_desc); | 1597 | rtlpriv->intf_ops->adapter_tx(hw, sta, skb, &tcb_desc); |
1370 | } | 1598 | } |
1599 | return 1; | ||
1600 | |||
1371 | err_free: | 1601 | err_free: |
1372 | return 0; | 1602 | return 0; |
1373 | } | 1603 | } |
1604 | EXPORT_SYMBOL(rtl_send_smps_action); | ||
1605 | |||
1606 | /* There seem to be issues in mac80211 regarding when del ba frames can be | ||
1607 | * received. As a work around, we make a fake del_ba if we receive a ba_req; | ||
1608 | * however, rx_agg was opened to let mac80211 release some ba related | ||
1609 | * resources. This del_ba is for tx only. | ||
1610 | */ | ||
1611 | struct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw, | ||
1612 | u8 *sa, u8 *bssid, u16 tid) | ||
1613 | { | ||
1614 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1615 | struct sk_buff *skb; | ||
1616 | struct ieee80211_mgmt *action_frame; | ||
1617 | u16 params; | ||
1618 | |||
1619 | /* 27 = header + category + action + smps mode */ | ||
1620 | skb = dev_alloc_skb(34 + hw->extra_tx_headroom); | ||
1621 | if (!skb) | ||
1622 | return NULL; | ||
1623 | |||
1624 | skb_reserve(skb, hw->extra_tx_headroom); | ||
1625 | action_frame = (void *)skb_put(skb, 34); | ||
1626 | memset(action_frame, 0, 34); | ||
1627 | memcpy(action_frame->sa, sa, ETH_ALEN); | ||
1628 | memcpy(action_frame->da, rtlefuse->dev_addr, ETH_ALEN); | ||
1629 | memcpy(action_frame->bssid, bssid, ETH_ALEN); | ||
1630 | action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
1631 | IEEE80211_STYPE_ACTION); | ||
1632 | action_frame->u.action.category = WLAN_CATEGORY_BACK; | ||
1633 | action_frame->u.action.u.delba.action_code = WLAN_ACTION_DELBA; | ||
1634 | params = (u16)(1 << 11); /* bit 11 initiator */ | ||
1635 | params |= (u16)(tid << 12); /* bit 15:12 TID number */ | ||
1636 | |||
1637 | action_frame->u.action.u.delba.params = cpu_to_le16(params); | ||
1638 | action_frame->u.action.u.delba.reason_code = | ||
1639 | cpu_to_le16(WLAN_REASON_QSTA_TIMEOUT); | ||
1640 | |||
1641 | return skb; | ||
1642 | } | ||
1374 | 1643 | ||
1375 | /********************************************************* | 1644 | /********************************************************* |
1376 | * | 1645 | * |
@@ -1587,11 +1856,17 @@ MODULE_AUTHOR("Larry Finger <Larry.FInger@lwfinger.net>"); | |||
1587 | MODULE_LICENSE("GPL"); | 1856 | MODULE_LICENSE("GPL"); |
1588 | MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core"); | 1857 | MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core"); |
1589 | 1858 | ||
1859 | struct rtl_global_var global_var = {}; | ||
1860 | |||
1590 | static int __init rtl_core_module_init(void) | 1861 | static int __init rtl_core_module_init(void) |
1591 | { | 1862 | { |
1592 | if (rtl_rate_control_register()) | 1863 | if (rtl_rate_control_register()) |
1593 | pr_err("Unable to register rtl_rc, use default RC !!\n"); | 1864 | pr_err("Unable to register rtl_rc, use default RC !!\n"); |
1594 | 1865 | ||
1866 | /* init some global vars */ | ||
1867 | INIT_LIST_HEAD(&global_var.glb_priv_list); | ||
1868 | spin_lock_init(&global_var.glb_list_lock); | ||
1869 | |||
1595 | return 0; | 1870 | return 0; |
1596 | } | 1871 | } |
1597 | 1872 | ||
diff --git a/drivers/net/wireless/rtlwifi/base.h b/drivers/net/wireless/rtlwifi/base.h index 5a8c80e259f7..8576bc34b032 100644 --- a/drivers/net/wireless/rtlwifi/base.h +++ b/drivers/net/wireless/rtlwifi/base.h | |||
@@ -113,6 +113,7 @@ void rtl_init_rx_config(struct ieee80211_hw *hw); | |||
113 | void rtl_init_rfkill(struct ieee80211_hw *hw); | 113 | void rtl_init_rfkill(struct ieee80211_hw *hw); |
114 | void rtl_deinit_rfkill(struct ieee80211_hw *hw); | 114 | void rtl_deinit_rfkill(struct ieee80211_hw *hw); |
115 | 115 | ||
116 | void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb); | ||
116 | void rtl_watch_dog_timer_callback(unsigned long data); | 117 | void rtl_watch_dog_timer_callback(unsigned long data); |
117 | void rtl_deinit_deferred_work(struct ieee80211_hw *hw); | 118 | void rtl_deinit_deferred_work(struct ieee80211_hw *hw); |
118 | 119 | ||
@@ -126,7 +127,12 @@ int rtl_tx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | |||
126 | u16 tid); | 127 | u16 tid); |
127 | int rtl_tx_agg_oper(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | 128 | int rtl_tx_agg_oper(struct ieee80211_hw *hw, struct ieee80211_sta *sta, |
128 | u16 tid); | 129 | u16 tid); |
130 | int rtl_rx_agg_start(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | ||
131 | u16 tid); | ||
132 | int rtl_rx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | ||
133 | u16 tid); | ||
129 | void rtl_watchdog_wq_callback(void *data); | 134 | void rtl_watchdog_wq_callback(void *data); |
135 | void rtl_fwevt_wq_callback(void *data); | ||
130 | 136 | ||
131 | void rtl_get_tcb_desc(struct ieee80211_hw *hw, | 137 | void rtl_get_tcb_desc(struct ieee80211_hw *hw, |
132 | struct ieee80211_tx_info *info, | 138 | struct ieee80211_tx_info *info, |
@@ -134,14 +140,18 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw, | |||
134 | struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc); | 140 | struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc); |
135 | 141 | ||
136 | int rtl_send_smps_action(struct ieee80211_hw *hw, | 142 | int rtl_send_smps_action(struct ieee80211_hw *hw, |
137 | struct ieee80211_sta *sta, u8 *da, u8 *bssid, | 143 | struct ieee80211_sta *sta, |
138 | enum ieee80211_smps_mode smps); | 144 | enum ieee80211_smps_mode smps); |
139 | u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie); | 145 | u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie); |
140 | void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len); | 146 | void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len); |
141 | u8 rtl_tid_to_ac(u8 tid); | 147 | u8 rtl_tid_to_ac(u8 tid); |
142 | extern struct attribute_group rtl_attribute_group; | 148 | extern struct attribute_group rtl_attribute_group; |
149 | void rtl_easy_concurrent_retrytimer_callback(unsigned long data); | ||
150 | extern struct rtl_global_var global_var; | ||
143 | int rtlwifi_rate_mapping(struct ieee80211_hw *hw, | 151 | int rtlwifi_rate_mapping(struct ieee80211_hw *hw, |
144 | bool isht, u8 desc_rate, bool first_ampdu); | 152 | bool isht, u8 desc_rate, bool first_ampdu); |
145 | bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb); | 153 | bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb); |
154 | struct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw, | ||
155 | u8 *sa, u8 *bssid, u16 tid); | ||
146 | 156 | ||
147 | #endif | 157 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index d3ce9fbef00e..2201b5cee08f 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c | |||
@@ -104,9 +104,12 @@ static void rtl_op_stop(struct ieee80211_hw *hw) | |||
104 | if (is_hal_stop(rtlhal)) | 104 | if (is_hal_stop(rtlhal)) |
105 | return; | 105 | return; |
106 | 106 | ||
107 | /* here is must, because adhoc do stop and start, | ||
108 | * but stop with RFOFF may cause something wrong, | ||
109 | * like adhoc TP | ||
110 | */ | ||
107 | if (unlikely(ppsc->rfpwr_state == ERFOFF)) { | 111 | if (unlikely(ppsc->rfpwr_state == ERFOFF)) { |
108 | rtl_ips_nic_on(hw); | 112 | rtl_ips_nic_on(hw); |
109 | mdelay(1); | ||
110 | } | 113 | } |
111 | 114 | ||
112 | mutex_lock(&rtlpriv->locks.conf_mutex); | 115 | mutex_lock(&rtlpriv->locks.conf_mutex); |
@@ -167,7 +170,11 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw, | |||
167 | rtl_ips_nic_on(hw); | 170 | rtl_ips_nic_on(hw); |
168 | 171 | ||
169 | mutex_lock(&rtlpriv->locks.conf_mutex); | 172 | mutex_lock(&rtlpriv->locks.conf_mutex); |
170 | switch (vif->type) { | 173 | |
174 | switch (ieee80211_vif_type_p2p(vif)) { | ||
175 | case NL80211_IFTYPE_P2P_CLIENT: | ||
176 | mac->p2p = P2P_ROLE_CLIENT; | ||
177 | /*fall through*/ | ||
171 | case NL80211_IFTYPE_STATION: | 178 | case NL80211_IFTYPE_STATION: |
172 | if (mac->beacon_enabled == 1) { | 179 | if (mac->beacon_enabled == 1) { |
173 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, | 180 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, |
@@ -192,6 +199,9 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw, | |||
192 | (u8 *) (&mac->basic_rates)); | 199 | (u8 *) (&mac->basic_rates)); |
193 | 200 | ||
194 | break; | 201 | break; |
202 | case NL80211_IFTYPE_P2P_GO: | ||
203 | mac->p2p = P2P_ROLE_GO; | ||
204 | /*fall through*/ | ||
195 | case NL80211_IFTYPE_AP: | 205 | case NL80211_IFTYPE_AP: |
196 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, | 206 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, |
197 | "NL80211_IFTYPE_AP\n"); | 207 | "NL80211_IFTYPE_AP\n"); |
@@ -205,6 +215,19 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw, | |||
205 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, | 215 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, |
206 | (u8 *) (&mac->basic_rates)); | 216 | (u8 *) (&mac->basic_rates)); |
207 | break; | 217 | break; |
218 | case NL80211_IFTYPE_MESH_POINT: | ||
219 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, | ||
220 | "NL80211_IFTYPE_MESH_POINT\n"); | ||
221 | |||
222 | mac->link_state = MAC80211_LINKED; | ||
223 | rtlpriv->cfg->ops->set_bcn_reg(hw); | ||
224 | if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) | ||
225 | mac->basic_rates = 0xfff; | ||
226 | else | ||
227 | mac->basic_rates = 0xff0; | ||
228 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, | ||
229 | (u8 *)(&mac->basic_rates)); | ||
230 | break; | ||
208 | default: | 231 | default: |
209 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 232 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
210 | "operation mode %d is not supported!\n", vif->type); | 233 | "operation mode %d is not supported!\n", vif->type); |
@@ -212,6 +235,13 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw, | |||
212 | goto out; | 235 | goto out; |
213 | } | 236 | } |
214 | 237 | ||
238 | if (mac->p2p) { | ||
239 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, | ||
240 | "p2p role %x\n", vif->type); | ||
241 | mac->basic_rates = 0xff0;/*disable cck rate for p2p*/ | ||
242 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, | ||
243 | (u8 *)(&mac->basic_rates)); | ||
244 | } | ||
215 | mac->vif = vif; | 245 | mac->vif = vif; |
216 | mac->opmode = vif->type; | 246 | mac->opmode = vif->type; |
217 | rtlpriv->cfg->ops->set_network_type(hw, vif->type); | 247 | rtlpriv->cfg->ops->set_network_type(hw, vif->type); |
@@ -232,9 +262,9 @@ static void rtl_op_remove_interface(struct ieee80211_hw *hw, | |||
232 | mutex_lock(&rtlpriv->locks.conf_mutex); | 262 | mutex_lock(&rtlpriv->locks.conf_mutex); |
233 | 263 | ||
234 | /* Free beacon resources */ | 264 | /* Free beacon resources */ |
235 | if ((mac->opmode == NL80211_IFTYPE_AP) || | 265 | if ((vif->type == NL80211_IFTYPE_AP) || |
236 | (mac->opmode == NL80211_IFTYPE_ADHOC) || | 266 | (vif->type == NL80211_IFTYPE_ADHOC) || |
237 | (mac->opmode == NL80211_IFTYPE_MESH_POINT)) { | 267 | (vif->type == NL80211_IFTYPE_MESH_POINT)) { |
238 | if (mac->beacon_enabled == 1) { | 268 | if (mac->beacon_enabled == 1) { |
239 | mac->beacon_enabled = 0; | 269 | mac->beacon_enabled = 0; |
240 | rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, | 270 | rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, |
@@ -247,6 +277,7 @@ static void rtl_op_remove_interface(struct ieee80211_hw *hw, | |||
247 | *Note: We assume NL80211_IFTYPE_UNSPECIFIED as | 277 | *Note: We assume NL80211_IFTYPE_UNSPECIFIED as |
248 | *NO LINK for our hardware. | 278 | *NO LINK for our hardware. |
249 | */ | 279 | */ |
280 | mac->p2p = 0; | ||
250 | mac->vif = NULL; | 281 | mac->vif = NULL; |
251 | mac->link_state = MAC80211_NOLINK; | 282 | mac->link_state = MAC80211_NOLINK; |
252 | memset(mac->bssid, 0, 6); | 283 | memset(mac->bssid, 0, 6); |
@@ -256,6 +287,22 @@ static void rtl_op_remove_interface(struct ieee80211_hw *hw, | |||
256 | mutex_unlock(&rtlpriv->locks.conf_mutex); | 287 | mutex_unlock(&rtlpriv->locks.conf_mutex); |
257 | } | 288 | } |
258 | 289 | ||
290 | static int rtl_op_change_interface(struct ieee80211_hw *hw, | ||
291 | struct ieee80211_vif *vif, | ||
292 | enum nl80211_iftype new_type, bool p2p) | ||
293 | { | ||
294 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
295 | int ret; | ||
296 | rtl_op_remove_interface(hw, vif); | ||
297 | |||
298 | vif->type = new_type; | ||
299 | vif->p2p = p2p; | ||
300 | ret = rtl_op_add_interface(hw, vif); | ||
301 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, | ||
302 | "p2p %x\n", p2p); | ||
303 | return ret; | ||
304 | } | ||
305 | |||
259 | static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) | 306 | static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) |
260 | { | 307 | { |
261 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 308 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -264,6 +311,9 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) | |||
264 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | 311 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
265 | struct ieee80211_conf *conf = &hw->conf; | 312 | struct ieee80211_conf *conf = &hw->conf; |
266 | 313 | ||
314 | if (mac->skip_scan) | ||
315 | return 1; | ||
316 | |||
267 | mutex_lock(&rtlpriv->locks.conf_mutex); | 317 | mutex_lock(&rtlpriv->locks.conf_mutex); |
268 | if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { /*BIT(2)*/ | 318 | if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { /*BIT(2)*/ |
269 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, | 319 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, |
@@ -323,6 +373,16 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) | |||
323 | struct ieee80211_channel *channel = hw->conf.channel; | 373 | struct ieee80211_channel *channel = hw->conf.channel; |
324 | u8 wide_chan = (u8) channel->hw_value; | 374 | u8 wide_chan = (u8) channel->hw_value; |
325 | 375 | ||
376 | if (mac->act_scanning) | ||
377 | mac->n_channels++; | ||
378 | |||
379 | if (rtlpriv->dm.supp_phymode_switch && | ||
380 | mac->link_state < MAC80211_LINKED && | ||
381 | !mac->act_scanning) { | ||
382 | if (rtlpriv->cfg->ops->chk_switch_dmdp) | ||
383 | rtlpriv->cfg->ops->chk_switch_dmdp(hw); | ||
384 | } | ||
385 | |||
326 | /* | 386 | /* |
327 | *because we should back channel to | 387 | *because we should back channel to |
328 | *current_network.chan in in scanning, | 388 | *current_network.chan in in scanning, |
@@ -373,13 +433,13 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) | |||
373 | if (wide_chan <= 0) | 433 | if (wide_chan <= 0) |
374 | wide_chan = 1; | 434 | wide_chan = 1; |
375 | 435 | ||
376 | /* In scanning, before we go offchannel we may send a ps=1 null | 436 | /* In scanning, before we go offchannel we may send a ps = 1 |
377 | * to AP, and then we may send a ps = 0 null to AP quickly, but | 437 | * null to AP, and then we may send a ps = 0 null to AP quickly, |
378 | * first null may have caused AP to put lots of packet to hw tx | 438 | * but first null may have caused AP to put lots of packet to |
379 | * buffer. These packets must be tx'd before we go off channel | 439 | * hw tx buffer. These packets must be tx'd before we go off |
380 | * so we must delay more time to let AP flush these packets | 440 | * channel so we must delay more time to let AP flush these |
381 | * before going offchannel, or dis-association or delete BA will | 441 | * packets before going offchannel, or dis-association or |
382 | * happen by AP | 442 | * delete BA will be caused by AP |
383 | */ | 443 | */ |
384 | if (rtlpriv->mac80211.offchan_delay) { | 444 | if (rtlpriv->mac80211.offchan_delay) { |
385 | rtlpriv->mac80211.offchan_delay = false; | 445 | rtlpriv->mac80211.offchan_delay = false; |
@@ -441,7 +501,8 @@ static void rtl_op_configure_filter(struct ieee80211_hw *hw, | |||
441 | * and nolink check bssid is set in set network_type */ | 501 | * and nolink check bssid is set in set network_type */ |
442 | if ((changed_flags & FIF_BCN_PRBRESP_PROMISC) && | 502 | if ((changed_flags & FIF_BCN_PRBRESP_PROMISC) && |
443 | (mac->link_state >= MAC80211_LINKED)) { | 503 | (mac->link_state >= MAC80211_LINKED)) { |
444 | if (mac->opmode != NL80211_IFTYPE_AP) { | 504 | if (mac->opmode != NL80211_IFTYPE_AP && |
505 | mac->opmode != NL80211_IFTYPE_MESH_POINT) { | ||
445 | if (*new_flags & FIF_BCN_PRBRESP_PROMISC) { | 506 | if (*new_flags & FIF_BCN_PRBRESP_PROMISC) { |
446 | rtlpriv->cfg->ops->set_chk_bssid(hw, false); | 507 | rtlpriv->cfg->ops->set_chk_bssid(hw, false); |
447 | } else { | 508 | } else { |
@@ -481,32 +542,43 @@ static int rtl_op_sta_add(struct ieee80211_hw *hw, | |||
481 | { | 542 | { |
482 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 543 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
483 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 544 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
545 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
484 | struct rtl_sta_info *sta_entry; | 546 | struct rtl_sta_info *sta_entry; |
485 | 547 | ||
486 | if (sta) { | 548 | if (sta) { |
487 | sta_entry = (struct rtl_sta_info *) sta->drv_priv; | 549 | sta_entry = (struct rtl_sta_info *) sta->drv_priv; |
550 | spin_lock_bh(&rtlpriv->locks.entry_list_lock); | ||
551 | list_add_tail(&sta_entry->list, &rtlpriv->entry_list); | ||
552 | spin_unlock_bh(&rtlpriv->locks.entry_list_lock); | ||
488 | if (rtlhal->current_bandtype == BAND_ON_2_4G) { | 553 | if (rtlhal->current_bandtype == BAND_ON_2_4G) { |
489 | sta_entry->wireless_mode = WIRELESS_MODE_G; | 554 | sta_entry->wireless_mode = WIRELESS_MODE_G; |
490 | if (sta->supp_rates[0] <= 0xf) | 555 | if (sta->supp_rates[0] <= 0xf) |
491 | sta_entry->wireless_mode = WIRELESS_MODE_B; | 556 | sta_entry->wireless_mode = WIRELESS_MODE_B; |
492 | if (sta->ht_cap.ht_supported) | 557 | if (sta->ht_cap.ht_supported == true) |
493 | sta_entry->wireless_mode = WIRELESS_MODE_N_24G; | 558 | sta_entry->wireless_mode = WIRELESS_MODE_N_24G; |
559 | |||
560 | if (vif->type == NL80211_IFTYPE_ADHOC) | ||
561 | sta_entry->wireless_mode = WIRELESS_MODE_G; | ||
494 | } else if (rtlhal->current_bandtype == BAND_ON_5G) { | 562 | } else if (rtlhal->current_bandtype == BAND_ON_5G) { |
495 | sta_entry->wireless_mode = WIRELESS_MODE_A; | 563 | sta_entry->wireless_mode = WIRELESS_MODE_A; |
496 | if (sta->ht_cap.ht_supported) | 564 | if (sta->ht_cap.ht_supported == true) |
497 | sta_entry->wireless_mode = WIRELESS_MODE_N_24G; | 565 | sta_entry->wireless_mode = WIRELESS_MODE_N_24G; |
498 | } | ||
499 | 566 | ||
500 | /* I found some times mac80211 give wrong supp_rates for adhoc*/ | 567 | if (vif->type == NL80211_IFTYPE_ADHOC) |
501 | if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) | 568 | sta_entry->wireless_mode = WIRELESS_MODE_A; |
502 | sta_entry->wireless_mode = WIRELESS_MODE_G; | 569 | } |
570 | /*disable cck rate for p2p*/ | ||
571 | if (mac->p2p) | ||
572 | sta->supp_rates[0] &= 0xfffffff0; | ||
503 | 573 | ||
574 | memcpy(sta_entry->mac_addr, sta->addr, ETH_ALEN); | ||
504 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, | 575 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, |
505 | "Add sta addr is %pM\n", sta->addr); | 576 | "Add sta addr is %pM\n", sta->addr); |
506 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); | 577 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); |
507 | } | 578 | } |
508 | return 0; | 579 | return 0; |
509 | } | 580 | } |
581 | |||
510 | static int rtl_op_sta_remove(struct ieee80211_hw *hw, | 582 | static int rtl_op_sta_remove(struct ieee80211_hw *hw, |
511 | struct ieee80211_vif *vif, | 583 | struct ieee80211_vif *vif, |
512 | struct ieee80211_sta *sta) | 584 | struct ieee80211_sta *sta) |
@@ -519,9 +591,14 @@ static int rtl_op_sta_remove(struct ieee80211_hw *hw, | |||
519 | sta_entry = (struct rtl_sta_info *) sta->drv_priv; | 591 | sta_entry = (struct rtl_sta_info *) sta->drv_priv; |
520 | sta_entry->wireless_mode = 0; | 592 | sta_entry->wireless_mode = 0; |
521 | sta_entry->ratr_index = 0; | 593 | sta_entry->ratr_index = 0; |
594 | |||
595 | spin_lock_bh(&rtlpriv->locks.entry_list_lock); | ||
596 | list_del(&sta_entry->list); | ||
597 | spin_unlock_bh(&rtlpriv->locks.entry_list_lock); | ||
522 | } | 598 | } |
523 | return 0; | 599 | return 0; |
524 | } | 600 | } |
601 | |||
525 | static int _rtl_get_hal_qnum(u16 queue) | 602 | static int _rtl_get_hal_qnum(u16 queue) |
526 | { | 603 | { |
527 | int qnum; | 604 | int qnum; |
@@ -547,8 +624,8 @@ static int _rtl_get_hal_qnum(u16 queue) | |||
547 | } | 624 | } |
548 | 625 | ||
549 | /* | 626 | /* |
550 | *for mac80211 VO=0, VI=1, BE=2, BK=3 | 627 | *for mac80211 VO = 0, VI = 1, BE = 2, BK = 3 |
551 | *for rtl819x BE=0, BK=1, VI=2, VO=3 | 628 | *for rtl819x BE = 0, BK = 1, VI = 2, VO = 3 |
552 | */ | 629 | */ |
553 | static int rtl_op_conf_tx(struct ieee80211_hw *hw, | 630 | static int rtl_op_conf_tx(struct ieee80211_hw *hw, |
554 | struct ieee80211_vif *vif, u16 queue, | 631 | struct ieee80211_vif *vif, u16 queue, |
@@ -630,6 +707,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, | |||
630 | /*TODO: reference to enum ieee80211_bss_change */ | 707 | /*TODO: reference to enum ieee80211_bss_change */ |
631 | if (changed & BSS_CHANGED_ASSOC) { | 708 | if (changed & BSS_CHANGED_ASSOC) { |
632 | if (bss_conf->assoc) { | 709 | if (bss_conf->assoc) { |
710 | struct ieee80211_sta *sta = NULL; | ||
633 | /* we should reset all sec info & cam | 711 | /* we should reset all sec info & cam |
634 | * before set cam after linked, we should not | 712 | * before set cam after linked, we should not |
635 | * reset in disassoc, that will cause tkip->wep | 713 | * reset in disassoc, that will cause tkip->wep |
@@ -647,23 +725,39 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, | |||
647 | 725 | ||
648 | if (rtlpriv->cfg->ops->linked_set_reg) | 726 | if (rtlpriv->cfg->ops->linked_set_reg) |
649 | rtlpriv->cfg->ops->linked_set_reg(hw); | 727 | rtlpriv->cfg->ops->linked_set_reg(hw); |
650 | if (mac->opmode == NL80211_IFTYPE_STATION && sta) | 728 | rcu_read_lock(); |
729 | sta = ieee80211_find_sta(vif, (u8 *)bss_conf->bssid); | ||
730 | |||
731 | if (vif->type == NL80211_IFTYPE_STATION && sta) | ||
651 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); | 732 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); |
733 | RT_TRACE(rtlpriv, COMP_EASY_CONCURRENT, DBG_LOUD, | ||
734 | "send PS STATIC frame\n"); | ||
735 | if (rtlpriv->dm.supp_phymode_switch) { | ||
736 | if (sta->ht_cap.ht_supported) | ||
737 | rtl_send_smps_action(hw, sta, | ||
738 | IEEE80211_SMPS_STATIC); | ||
739 | } | ||
740 | rcu_read_unlock(); | ||
741 | |||
652 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, | 742 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, |
653 | "BSS_CHANGED_ASSOC\n"); | 743 | "BSS_CHANGED_ASSOC\n"); |
654 | } else { | 744 | } else { |
655 | if (mac->link_state == MAC80211_LINKED) | 745 | if (mac->link_state == MAC80211_LINKED) { |
656 | rtl_lps_leave(hw); | 746 | rtlpriv->enter_ps = false; |
747 | schedule_work(&rtlpriv->works.lps_change_work); | ||
748 | } | ||
657 | 749 | ||
750 | if (ppsc->p2p_ps_info.p2p_ps_mode > P2P_PS_NONE) | ||
751 | rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); | ||
658 | mac->link_state = MAC80211_NOLINK; | 752 | mac->link_state = MAC80211_NOLINK; |
659 | memset(mac->bssid, 0, 6); | 753 | memset(mac->bssid, 0, 6); |
660 | |||
661 | /* reset sec info */ | ||
662 | rtl_cam_reset_sec_info(hw); | ||
663 | |||
664 | rtl_cam_reset_all_entry(hw); | ||
665 | mac->vendor = PEER_UNKNOWN; | 754 | mac->vendor = PEER_UNKNOWN; |
666 | 755 | ||
756 | if (rtlpriv->dm.supp_phymode_switch) { | ||
757 | if (rtlpriv->cfg->ops->chk_switch_dmdp) | ||
758 | rtlpriv->cfg->ops->chk_switch_dmdp(hw); | ||
759 | } | ||
760 | |||
667 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, | 761 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, |
668 | "BSS_CHANGED_UN_ASSOC\n"); | 762 | "BSS_CHANGED_UN_ASSOC\n"); |
669 | } | 763 | } |
@@ -778,7 +872,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, | |||
778 | } | 872 | } |
779 | 873 | ||
780 | if (changed & BSS_CHANGED_BASIC_RATES) { | 874 | if (changed & BSS_CHANGED_BASIC_RATES) { |
781 | /* for 5G must << RATE_6M_INDEX=4, | 875 | /* for 5G must << RATE_6M_INDEX = 4, |
782 | * because 5G have no cck rate*/ | 876 | * because 5G have no cck rate*/ |
783 | if (rtlhal->current_bandtype == BAND_ON_5G) | 877 | if (rtlhal->current_bandtype == BAND_ON_5G) |
784 | basic_rates = sta->supp_rates[1] << 4; | 878 | basic_rates = sta->supp_rates[1] << 4; |
@@ -815,6 +909,9 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, | |||
815 | ppsc->report_linked = false; | 909 | ppsc->report_linked = false; |
816 | } | 910 | } |
817 | } | 911 | } |
912 | if (rtlpriv->cfg->ops->bt_wifi_media_status_notify) | ||
913 | rtlpriv->cfg->ops->bt_wifi_media_status_notify(hw, | ||
914 | ppsc->report_linked); | ||
818 | } | 915 | } |
819 | 916 | ||
820 | out: | 917 | out: |
@@ -885,7 +982,6 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw, | |||
885 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, | 982 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, |
886 | "IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid); | 983 | "IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid); |
887 | return rtl_tx_agg_stop(hw, sta, tid); | 984 | return rtl_tx_agg_stop(hw, sta, tid); |
888 | break; | ||
889 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 985 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
890 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, | 986 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, |
891 | "IEEE80211_AMPDU_TX_OPERATIONAL:TID:%d\n", tid); | 987 | "IEEE80211_AMPDU_TX_OPERATIONAL:TID:%d\n", tid); |
@@ -894,11 +990,11 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw, | |||
894 | case IEEE80211_AMPDU_RX_START: | 990 | case IEEE80211_AMPDU_RX_START: |
895 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, | 991 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, |
896 | "IEEE80211_AMPDU_RX_START:TID:%d\n", tid); | 992 | "IEEE80211_AMPDU_RX_START:TID:%d\n", tid); |
897 | break; | 993 | return rtl_rx_agg_start(hw, sta, tid); |
898 | case IEEE80211_AMPDU_RX_STOP: | 994 | case IEEE80211_AMPDU_RX_STOP: |
899 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, | 995 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, |
900 | "IEEE80211_AMPDU_RX_STOP:TID:%d\n", tid); | 996 | "IEEE80211_AMPDU_RX_STOP:TID:%d\n", tid); |
901 | break; | 997 | return rtl_rx_agg_stop(hw, sta, tid); |
902 | default: | 998 | default: |
903 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 999 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
904 | "IEEE80211_AMPDU_ERR!!!!:\n"); | 1000 | "IEEE80211_AMPDU_ERR!!!!:\n"); |
@@ -912,12 +1008,20 @@ static void rtl_op_sw_scan_start(struct ieee80211_hw *hw) | |||
912 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1008 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
913 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 1009 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
914 | 1010 | ||
915 | mac->act_scanning = true; | ||
916 | |||
917 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n"); | 1011 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n"); |
1012 | mac->act_scanning = true; | ||
1013 | if (rtlpriv->link_info.higher_busytraffic) { | ||
1014 | mac->skip_scan = true; | ||
1015 | return; | ||
1016 | } | ||
918 | 1017 | ||
1018 | if (rtlpriv->dm.supp_phymode_switch) { | ||
1019 | if (rtlpriv->cfg->ops->chk_switch_dmdp) | ||
1020 | rtlpriv->cfg->ops->chk_switch_dmdp(hw); | ||
1021 | } | ||
919 | if (mac->link_state == MAC80211_LINKED) { | 1022 | if (mac->link_state == MAC80211_LINKED) { |
920 | rtl_lps_leave(hw); | 1023 | rtlpriv->enter_ps = false; |
1024 | schedule_work(&rtlpriv->works.lps_change_work); | ||
921 | mac->link_state = MAC80211_LINKED_SCANNING; | 1025 | mac->link_state = MAC80211_LINKED_SCANNING; |
922 | } else { | 1026 | } else { |
923 | rtl_ips_nic_on(hw); | 1027 | rtl_ips_nic_on(hw); |
@@ -937,6 +1041,16 @@ static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw) | |||
937 | 1041 | ||
938 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n"); | 1042 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n"); |
939 | mac->act_scanning = false; | 1043 | mac->act_scanning = false; |
1044 | mac->skip_scan = false; | ||
1045 | if (rtlpriv->link_info.higher_busytraffic) | ||
1046 | return; | ||
1047 | |||
1048 | /*p2p will use 1/6/11 to scan */ | ||
1049 | if (mac->n_channels == 3) | ||
1050 | mac->p2p_in_use = true; | ||
1051 | else | ||
1052 | mac->p2p_in_use = false; | ||
1053 | mac->n_channels = 0; | ||
940 | /* Dual mac */ | 1054 | /* Dual mac */ |
941 | rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false; | 1055 | rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false; |
942 | 1056 | ||
@@ -970,6 +1084,11 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
970 | "not open hw encryption\n"); | 1084 | "not open hw encryption\n"); |
971 | return -ENOSPC; /*User disabled HW-crypto */ | 1085 | return -ENOSPC; /*User disabled HW-crypto */ |
972 | } | 1086 | } |
1087 | /* To support IBSS, use sw-crypto for GTK */ | ||
1088 | if (((vif->type == NL80211_IFTYPE_ADHOC) || | ||
1089 | (vif->type == NL80211_IFTYPE_MESH_POINT)) && | ||
1090 | !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) | ||
1091 | return -ENOSPC; | ||
973 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | 1092 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, |
974 | "%s hardware based encryption for keyidx: %d, mac: %pM\n", | 1093 | "%s hardware based encryption for keyidx: %d, mac: %pM\n", |
975 | cmd == SET_KEY ? "Using" : "Disabling", key->keyidx, | 1094 | cmd == SET_KEY ? "Using" : "Disabling", key->keyidx, |
@@ -996,6 +1115,14 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
996 | key_type = AESCCMP_ENCRYPTION; | 1115 | key_type = AESCCMP_ENCRYPTION; |
997 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CCMP\n"); | 1116 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CCMP\n"); |
998 | break; | 1117 | break; |
1118 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
1119 | /*HW doesn't support CMAC encryption, use software CMAC */ | ||
1120 | key_type = AESCMAC_ENCRYPTION; | ||
1121 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CMAC\n"); | ||
1122 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | ||
1123 | "HW don't support CMAC encryption, use software CMAC\n"); | ||
1124 | err = -EOPNOTSUPP; | ||
1125 | goto out_unlock; | ||
999 | default: | 1126 | default: |
1000 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "alg_err:%x!!!!\n", | 1127 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "alg_err:%x!!!!\n", |
1001 | key->cipher); | 1128 | key->cipher); |
@@ -1017,13 +1144,14 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1017 | * 1) wep only: is just for wep enc, in this condition | 1144 | * 1) wep only: is just for wep enc, in this condition |
1018 | * rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION | 1145 | * rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION |
1019 | * will be true & enable_hw_sec will be set when wep | 1146 | * will be true & enable_hw_sec will be set when wep |
1020 | * ke setting. | 1147 | * key setting. |
1021 | * 2) wep(group) + AES(pairwise): some AP like cisco | 1148 | * 2) wep(group) + AES(pairwise): some AP like cisco |
1022 | * may use it, in this condition enable_hw_sec will not | 1149 | * may use it, in this condition enable_hw_sec will not |
1023 | * be set when wep key setting */ | 1150 | * be set when wep key setting */ |
1024 | /* we must reset sec_info after lingked before set key, | 1151 | /* we must reset sec_info after lingked before set key, |
1025 | * or some flag will be wrong*/ | 1152 | * or some flag will be wrong*/ |
1026 | if (mac->opmode == NL80211_IFTYPE_AP) { | 1153 | if (vif->type == NL80211_IFTYPE_AP || |
1154 | vif->type == NL80211_IFTYPE_MESH_POINT) { | ||
1027 | if (!group_key || key_type == WEP40_ENCRYPTION || | 1155 | if (!group_key || key_type == WEP40_ENCRYPTION || |
1028 | key_type == WEP104_ENCRYPTION) { | 1156 | key_type == WEP104_ENCRYPTION) { |
1029 | if (group_key) | 1157 | if (group_key) |
@@ -1098,12 +1226,16 @@ static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1098 | key->hw_key_idx = key_idx; | 1226 | key->hw_key_idx = key_idx; |
1099 | if (key_type == TKIP_ENCRYPTION) | 1227 | if (key_type == TKIP_ENCRYPTION) |
1100 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | 1228 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; |
1229 | /*use software CCMP encryption for management frames (MFP) */ | ||
1230 | if (key_type == AESCCMP_ENCRYPTION) | ||
1231 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; | ||
1101 | break; | 1232 | break; |
1102 | case DISABLE_KEY: | 1233 | case DISABLE_KEY: |
1103 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | 1234 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, |
1104 | "disable key delete one entry\n"); | 1235 | "disable key delete one entry\n"); |
1105 | /*set local buf about wep key. */ | 1236 | /*set local buf about wep key. */ |
1106 | if (mac->opmode == NL80211_IFTYPE_AP) { | 1237 | if (vif->type == NL80211_IFTYPE_AP || |
1238 | vif->type == NL80211_IFTYPE_MESH_POINT) { | ||
1107 | if (sta) | 1239 | if (sta) |
1108 | rtl_cam_del_entry(hw, sta->addr); | 1240 | rtl_cam_del_entry(hw, sta->addr); |
1109 | } | 1241 | } |
@@ -1163,10 +1295,10 @@ static void rtl_op_rfkill_poll(struct ieee80211_hw *hw) | |||
1163 | } | 1295 | } |
1164 | 1296 | ||
1165 | /* this function is called by mac80211 to flush tx buffer | 1297 | /* this function is called by mac80211 to flush tx buffer |
1166 | * before switch channle or power save, or tx buffer packet | 1298 | * before switch channel or power save, or tx buffer packet |
1167 | * maybe send after offchannel or rf sleep, this may cause | 1299 | * maybe send after offchannel or rf sleep, this may cause |
1168 | * dis-association by AP */ | 1300 | * dis-association by AP */ |
1169 | static void rtl_op_flush(struct ieee80211_hw *hw, bool drop) | 1301 | static void rtl_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop) |
1170 | { | 1302 | { |
1171 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1303 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1172 | 1304 | ||
@@ -1180,6 +1312,7 @@ const struct ieee80211_ops rtl_ops = { | |||
1180 | .tx = rtl_op_tx, | 1312 | .tx = rtl_op_tx, |
1181 | .add_interface = rtl_op_add_interface, | 1313 | .add_interface = rtl_op_add_interface, |
1182 | .remove_interface = rtl_op_remove_interface, | 1314 | .remove_interface = rtl_op_remove_interface, |
1315 | .change_interface = rtl_op_change_interface, | ||
1183 | .config = rtl_op_config, | 1316 | .config = rtl_op_config, |
1184 | .configure_filter = rtl_op_configure_filter, | 1317 | .configure_filter = rtl_op_configure_filter, |
1185 | .sta_add = rtl_op_sta_add, | 1318 | .sta_add = rtl_op_sta_add, |
diff --git a/drivers/net/wireless/rtlwifi/debug.c b/drivers/net/wireless/rtlwifi/debug.c index bdda9b2fffe1..7d52d3d7769f 100644 --- a/drivers/net/wireless/rtlwifi/debug.c +++ b/drivers/net/wireless/rtlwifi/debug.c | |||
@@ -41,7 +41,10 @@ void rtl_dbgp_flag_init(struct ieee80211_hw *hw) | |||
41 | COMP_BEACON | COMP_RATE | COMP_RXDESC | COMP_DIG | COMP_TXAGC | | 41 | COMP_BEACON | COMP_RATE | COMP_RXDESC | COMP_DIG | COMP_TXAGC | |
42 | COMP_POWER | COMP_POWER_TRACKING | COMP_BB_POWERSAVING | COMP_SWAS | | 42 | COMP_POWER | COMP_POWER_TRACKING | COMP_BB_POWERSAVING | COMP_SWAS | |
43 | COMP_RF | COMP_TURBO | COMP_RATR | COMP_CMD | | 43 | COMP_RF | COMP_TURBO | COMP_RATR | COMP_CMD | |
44 | COMP_EFUSE | COMP_QOS | COMP_MAC80211 | COMP_REGD | COMP_CHAN; | 44 | COMP_EFUSE | COMP_QOS | COMP_MAC80211 | COMP_REGD | COMP_CHAN | |
45 | COMP_EASY_CONCURRENT | COMP_EFUSE | COMP_QOS | COMP_MAC80211 | | ||
46 | COMP_REGD | COMP_CHAN | COMP_BT_COEXIST; | ||
47 | |||
45 | 48 | ||
46 | for (i = 0; i < DBGP_TYPE_MAX; i++) | 49 | for (i = 0; i < DBGP_TYPE_MAX; i++) |
47 | rtlpriv->dbg.dbgp_type[i] = 0; | 50 | rtlpriv->dbg.dbgp_type[i] = 0; |
diff --git a/drivers/net/wireless/rtlwifi/debug.h b/drivers/net/wireless/rtlwifi/debug.h index fd3269f47685..6d669364e3d9 100644 --- a/drivers/net/wireless/rtlwifi/debug.h +++ b/drivers/net/wireless/rtlwifi/debug.h | |||
@@ -115,11 +115,11 @@ | |||
115 | /* Define EEPROM and EFUSE check module bit*/ | 115 | /* Define EEPROM and EFUSE check module bit*/ |
116 | #define EEPROM_W BIT(0) | 116 | #define EEPROM_W BIT(0) |
117 | #define EFUSE_PG BIT(1) | 117 | #define EFUSE_PG BIT(1) |
118 | #define EFUSE_READ_ALL BIT(2) | 118 | #define EFUSE_READ_ALL BIT(2) |
119 | 119 | ||
120 | /* Define init check for module bit*/ | 120 | /* Define init check for module bit*/ |
121 | #define INIT_EEPROM BIT(0) | 121 | #define INIT_EEPROM BIT(0) |
122 | #define INIT_TxPower BIT(1) | 122 | #define INIT_TXPOWER BIT(1) |
123 | #define INIT_IQK BIT(2) | 123 | #define INIT_IQK BIT(2) |
124 | #define INIT_RF BIT(3) | 124 | #define INIT_RF BIT(3) |
125 | 125 | ||
@@ -135,6 +135,15 @@ | |||
135 | #define PHY_TXPWR BIT(8) | 135 | #define PHY_TXPWR BIT(8) |
136 | #define PHY_PWRDIFF BIT(9) | 136 | #define PHY_PWRDIFF BIT(9) |
137 | 137 | ||
138 | /* Define Dynamic Mechanism check module bit --> FDM */ | ||
139 | #define WA_IOT BIT(0) | ||
140 | #define DM_PWDB BIT(1) | ||
141 | #define DM_MONITOR BIT(2) | ||
142 | #define DM_DIG BIT(3) | ||
143 | #define DM_EDCA_TURBO BIT(4) | ||
144 | |||
145 | #define DM_PWDB BIT(1) | ||
146 | |||
138 | enum dbgp_flag_e { | 147 | enum dbgp_flag_e { |
139 | FQOS = 0, | 148 | FQOS = 0, |
140 | FTX = 1, | 149 | FTX = 1, |
diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c index 8e2f9afb125a..9e3894178e77 100644 --- a/drivers/net/wireless/rtlwifi/efuse.c +++ b/drivers/net/wireless/rtlwifi/efuse.c | |||
@@ -35,8 +35,6 @@ static const u8 MAX_PGPKT_SIZE = 9; | |||
35 | static const u8 PGPKT_DATA_SIZE = 8; | 35 | static const u8 PGPKT_DATA_SIZE = 8; |
36 | static const int EFUSE_MAX_SIZE = 512; | 36 | static const int EFUSE_MAX_SIZE = 512; |
37 | 37 | ||
38 | static const u8 EFUSE_OOB_PROTECT_BYTES = 15; | ||
39 | |||
40 | static const struct efuse_map RTL8712_SDIO_EFUSE_TABLE[] = { | 38 | static const struct efuse_map RTL8712_SDIO_EFUSE_TABLE[] = { |
41 | {0, 0, 0, 2}, | 39 | {0, 0, 0, 2}, |
42 | {0, 1, 0, 2}, | 40 | {0, 1, 0, 2}, |
@@ -240,6 +238,7 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) | |||
240 | u8 rtemp8[1]; | 238 | u8 rtemp8[1]; |
241 | u16 efuse_addr = 0; | 239 | u16 efuse_addr = 0; |
242 | u8 offset, wren; | 240 | u8 offset, wren; |
241 | u8 u1temp = 0; | ||
243 | u16 i; | 242 | u16 i; |
244 | u16 j; | 243 | u16 j; |
245 | const u16 efuse_max_section = | 244 | const u16 efuse_max_section = |
@@ -285,10 +284,31 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) | |||
285 | } | 284 | } |
286 | 285 | ||
287 | while ((*rtemp8 != 0xFF) && (efuse_addr < efuse_len)) { | 286 | while ((*rtemp8 != 0xFF) && (efuse_addr < efuse_len)) { |
288 | offset = ((*rtemp8 >> 4) & 0x0f); | 287 | /* Check PG header for section num. */ |
288 | if ((*rtemp8 & 0x1F) == 0x0F) {/* extended header */ | ||
289 | u1temp = ((*rtemp8 & 0xE0) >> 5); | ||
290 | read_efuse_byte(hw, efuse_addr, rtemp8); | ||
289 | 291 | ||
290 | if (offset < efuse_max_section) { | 292 | if ((*rtemp8 & 0x0F) == 0x0F) { |
293 | efuse_addr++; | ||
294 | read_efuse_byte(hw, efuse_addr, rtemp8); | ||
295 | |||
296 | if (*rtemp8 != 0xFF && | ||
297 | (efuse_addr < efuse_len)) { | ||
298 | efuse_addr++; | ||
299 | } | ||
300 | continue; | ||
301 | } else { | ||
302 | offset = ((*rtemp8 & 0xF0) >> 1) | u1temp; | ||
303 | wren = (*rtemp8 & 0x0F); | ||
304 | efuse_addr++; | ||
305 | } | ||
306 | } else { | ||
307 | offset = ((*rtemp8 >> 4) & 0x0f); | ||
291 | wren = (*rtemp8 & 0x0f); | 308 | wren = (*rtemp8 & 0x0f); |
309 | } | ||
310 | |||
311 | if (offset < efuse_max_section) { | ||
292 | RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, | 312 | RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, |
293 | "offset-%d Worden=%x\n", offset, wren); | 313 | "offset-%d Worden=%x\n", offset, wren); |
294 | 314 | ||
@@ -391,7 +411,8 @@ bool efuse_shadow_update_chk(struct ieee80211_hw *hw) | |||
391 | efuse_used = rtlefuse->efuse_usedbytes; | 411 | efuse_used = rtlefuse->efuse_usedbytes; |
392 | 412 | ||
393 | if ((totalbytes + efuse_used) >= | 413 | if ((totalbytes + efuse_used) >= |
394 | (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES)) | 414 | (EFUSE_MAX_SIZE - |
415 | rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) | ||
395 | result = false; | 416 | result = false; |
396 | 417 | ||
397 | RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, | 418 | RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, |
@@ -932,8 +953,8 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, | |||
932 | u8 badworden = 0x0F; | 953 | u8 badworden = 0x0F; |
933 | static int repeat_times; | 954 | static int repeat_times; |
934 | 955 | ||
935 | if (efuse_get_current_size(hw) >= | 956 | if (efuse_get_current_size(hw) >= (EFUSE_MAX_SIZE - |
936 | (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES)) { | 957 | rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) { |
937 | RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, | 958 | RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, |
938 | "efuse_pg_packet_write error\n"); | 959 | "efuse_pg_packet_write error\n"); |
939 | return false; | 960 | return false; |
@@ -949,8 +970,8 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, | |||
949 | 970 | ||
950 | RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, "efuse Power ON\n"); | 971 | RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, "efuse Power ON\n"); |
951 | 972 | ||
952 | while (continual && (efuse_addr < | 973 | while (continual && (efuse_addr < (EFUSE_MAX_SIZE - |
953 | (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES))) { | 974 | rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN]))) { |
954 | 975 | ||
955 | if (write_state == PG_STATE_HEADER) { | 976 | if (write_state == PG_STATE_HEADER) { |
956 | badworden = 0x0F; | 977 | badworden = 0x0F; |
@@ -1003,7 +1024,8 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, | |||
1003 | } | 1024 | } |
1004 | } | 1025 | } |
1005 | 1026 | ||
1006 | if (efuse_addr >= (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES)) { | 1027 | if (efuse_addr >= (EFUSE_MAX_SIZE - |
1028 | rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) { | ||
1007 | RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, | 1029 | RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, |
1008 | "efuse_addr(%#x) Out of size!!\n", efuse_addr); | 1030 | "efuse_addr(%#x) Out of size!!\n", efuse_addr); |
1009 | } | 1031 | } |
@@ -1102,8 +1124,11 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) | |||
1102 | u8 tempval; | 1124 | u8 tempval; |
1103 | u16 tmpV16; | 1125 | u16 tmpV16; |
1104 | 1126 | ||
1105 | if (pwrstate && (rtlhal->hw_type != | 1127 | if (pwrstate && (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE)) { |
1106 | HARDWARE_TYPE_RTL8192SE)) { | 1128 | if (rtlhal->hw_type == HARDWARE_TYPE_RTL8188EE) |
1129 | rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_ACCESS], | ||
1130 | 0x69); | ||
1131 | |||
1107 | tmpV16 = rtl_read_word(rtlpriv, | 1132 | tmpV16 = rtl_read_word(rtlpriv, |
1108 | rtlpriv->cfg->maps[SYS_ISO_CTRL]); | 1133 | rtlpriv->cfg->maps[SYS_ISO_CTRL]); |
1109 | if (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_PWC_EV12V])) { | 1134 | if (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_PWC_EV12V])) { |
@@ -1153,6 +1178,10 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) | |||
1153 | } | 1178 | } |
1154 | 1179 | ||
1155 | } else { | 1180 | } else { |
1181 | if (rtlhal->hw_type == HARDWARE_TYPE_RTL8188EE) | ||
1182 | rtl_write_byte(rtlpriv, | ||
1183 | rtlpriv->cfg->maps[EFUSE_ACCESS], 0); | ||
1184 | |||
1156 | if (write) { | 1185 | if (write) { |
1157 | tempval = rtl_read_byte(rtlpriv, | 1186 | tempval = rtl_read_byte(rtlpriv, |
1158 | rtlpriv->cfg->maps[EFUSE_TEST] + | 1187 | rtlpriv->cfg->maps[EFUSE_TEST] + |
diff --git a/drivers/net/wireless/rtlwifi/efuse.h b/drivers/net/wireless/rtlwifi/efuse.h index 2bdea9a8699e..395a326acfb4 100644 --- a/drivers/net/wireless/rtlwifi/efuse.h +++ b/drivers/net/wireless/rtlwifi/efuse.h | |||
@@ -32,7 +32,6 @@ | |||
32 | 32 | ||
33 | #define EFUSE_IC_ID_OFFSET 506 | 33 | #define EFUSE_IC_ID_OFFSET 506 |
34 | 34 | ||
35 | #define EFUSE_REAL_CONTENT_LEN 512 | ||
36 | #define EFUSE_MAP_LEN 128 | 35 | #define EFUSE_MAP_LEN 128 |
37 | #define EFUSE_MAX_WORD_UNIT 4 | 36 | #define EFUSE_MAX_WORD_UNIT 4 |
38 | 37 | ||
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 4261e8ecc4c3..999ffc12578b 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c | |||
@@ -59,7 +59,7 @@ static u8 _rtl_mac_to_hwqueue(struct ieee80211_hw *hw, | |||
59 | 59 | ||
60 | if (unlikely(ieee80211_is_beacon(fc))) | 60 | if (unlikely(ieee80211_is_beacon(fc))) |
61 | return BEACON_QUEUE; | 61 | return BEACON_QUEUE; |
62 | if (ieee80211_is_mgmt(fc)) | 62 | if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) |
63 | return MGNT_QUEUE; | 63 | return MGNT_QUEUE; |
64 | if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) | 64 | if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) |
65 | if (ieee80211_is_nullfunc(fc)) | 65 | if (ieee80211_is_nullfunc(fc)) |
@@ -271,9 +271,6 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw) | |||
271 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | 271 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); |
272 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | 272 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
273 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | 273 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); |
274 | u8 pcibridge_busnum = pcipriv->ndis_adapter.pcibridge_busnum; | ||
275 | u8 pcibridge_devnum = pcipriv->ndis_adapter.pcibridge_devnum; | ||
276 | u8 pcibridge_funcnum = pcipriv->ndis_adapter.pcibridge_funcnum; | ||
277 | u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; | 274 | u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; |
278 | u8 num4bytes = pcipriv->ndis_adapter.num4bytes; | 275 | u8 num4bytes = pcipriv->ndis_adapter.num4bytes; |
279 | u16 aspmlevel; | 276 | u16 aspmlevel; |
@@ -302,8 +299,7 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw) | |||
302 | u_pcibridge_aspmsetting); | 299 | u_pcibridge_aspmsetting); |
303 | 300 | ||
304 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | 301 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, |
305 | "PlatformEnableASPM():PciBridge busnumber[%x], DevNumbe[%x], funcnumber[%x], Write reg[%x] = %x\n", | 302 | "PlatformEnableASPM(): Write reg[%x] = %x\n", |
306 | pcibridge_busnum, pcibridge_devnum, pcibridge_funcnum, | ||
307 | (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10), | 303 | (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10), |
308 | u_pcibridge_aspmsetting); | 304 | u_pcibridge_aspmsetting); |
309 | 305 | ||
@@ -349,6 +345,49 @@ static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw) | |||
349 | return status; | 345 | return status; |
350 | } | 346 | } |
351 | 347 | ||
348 | static bool rtl_pci_check_buddy_priv(struct ieee80211_hw *hw, | ||
349 | struct rtl_priv **buddy_priv) | ||
350 | { | ||
351 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
352 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
353 | bool find_buddy_priv = false; | ||
354 | struct rtl_priv *tpriv = NULL; | ||
355 | struct rtl_pci_priv *tpcipriv = NULL; | ||
356 | |||
357 | if (!list_empty(&rtlpriv->glb_var->glb_priv_list)) { | ||
358 | list_for_each_entry(tpriv, &rtlpriv->glb_var->glb_priv_list, | ||
359 | list) { | ||
360 | if (tpriv) { | ||
361 | tpcipriv = (struct rtl_pci_priv *)tpriv->priv; | ||
362 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
363 | "pcipriv->ndis_adapter.funcnumber %x\n", | ||
364 | pcipriv->ndis_adapter.funcnumber); | ||
365 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
366 | "tpcipriv->ndis_adapter.funcnumber %x\n", | ||
367 | tpcipriv->ndis_adapter.funcnumber); | ||
368 | |||
369 | if ((pcipriv->ndis_adapter.busnumber == | ||
370 | tpcipriv->ndis_adapter.busnumber) && | ||
371 | (pcipriv->ndis_adapter.devnumber == | ||
372 | tpcipriv->ndis_adapter.devnumber) && | ||
373 | (pcipriv->ndis_adapter.funcnumber != | ||
374 | tpcipriv->ndis_adapter.funcnumber)) { | ||
375 | find_buddy_priv = true; | ||
376 | break; | ||
377 | } | ||
378 | } | ||
379 | } | ||
380 | } | ||
381 | |||
382 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
383 | "find_buddy_priv %d\n", find_buddy_priv); | ||
384 | |||
385 | if (find_buddy_priv) | ||
386 | *buddy_priv = tpriv; | ||
387 | |||
388 | return find_buddy_priv; | ||
389 | } | ||
390 | |||
352 | static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw) | 391 | static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw) |
353 | { | 392 | { |
354 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | 393 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); |
@@ -420,17 +459,14 @@ static void _rtl_pci_io_handler_init(struct device *dev, | |||
420 | 459 | ||
421 | } | 460 | } |
422 | 461 | ||
423 | static void _rtl_pci_io_handler_release(struct ieee80211_hw *hw) | ||
424 | { | ||
425 | } | ||
426 | |||
427 | static bool _rtl_update_earlymode_info(struct ieee80211_hw *hw, | 462 | static bool _rtl_update_earlymode_info(struct ieee80211_hw *hw, |
428 | struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc, u8 tid) | 463 | struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc, u8 tid) |
429 | { | 464 | { |
430 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 465 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
431 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 466 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
432 | u8 additionlen = FCS_LEN; | 467 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
433 | struct sk_buff *next_skb; | 468 | struct sk_buff *next_skb; |
469 | u8 additionlen = FCS_LEN; | ||
434 | 470 | ||
435 | /* here open is 4, wep/tkip is 8, aes is 12*/ | 471 | /* here open is 4, wep/tkip is 8, aes is 12*/ |
436 | if (info->control.hw_key) | 472 | if (info->control.hw_key) |
@@ -455,7 +491,7 @@ static bool _rtl_update_earlymode_info(struct ieee80211_hw *hw, | |||
455 | next_skb)) | 491 | next_skb)) |
456 | break; | 492 | break; |
457 | 493 | ||
458 | if (tcb_desc->empkt_num >= 5) | 494 | if (tcb_desc->empkt_num >= rtlhal->max_earlymode_num) |
459 | break; | 495 | break; |
460 | } | 496 | } |
461 | spin_unlock_bh(&rtlpriv->locks.waitq_lock); | 497 | spin_unlock_bh(&rtlpriv->locks.waitq_lock); |
@@ -471,11 +507,17 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw) | |||
471 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | 507 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); |
472 | struct sk_buff *skb = NULL; | 508 | struct sk_buff *skb = NULL; |
473 | struct ieee80211_tx_info *info = NULL; | 509 | struct ieee80211_tx_info *info = NULL; |
510 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
474 | int tid; | 511 | int tid; |
475 | 512 | ||
476 | if (!rtlpriv->rtlhal.earlymode_enable) | 513 | if (!rtlpriv->rtlhal.earlymode_enable) |
477 | return; | 514 | return; |
478 | 515 | ||
516 | if (rtlpriv->dm.supp_phymode_switch && | ||
517 | (rtlpriv->easy_concurrent_ctl.switch_in_process || | ||
518 | (rtlpriv->buddy_priv && | ||
519 | rtlpriv->buddy_priv->easy_concurrent_ctl.switch_in_process))) | ||
520 | return; | ||
479 | /* we juse use em for BE/BK/VI/VO */ | 521 | /* we juse use em for BE/BK/VI/VO */ |
480 | for (tid = 7; tid >= 0; tid--) { | 522 | for (tid = 7; tid >= 0; tid--) { |
481 | u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(tid)]; | 523 | u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(tid)]; |
@@ -487,7 +529,8 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw) | |||
487 | 529 | ||
488 | spin_lock_bh(&rtlpriv->locks.waitq_lock); | 530 | spin_lock_bh(&rtlpriv->locks.waitq_lock); |
489 | if (!skb_queue_empty(&mac->skb_waitq[tid]) && | 531 | if (!skb_queue_empty(&mac->skb_waitq[tid]) && |
490 | (ring->entries - skb_queue_len(&ring->queue) > 5)) { | 532 | (ring->entries - skb_queue_len(&ring->queue) > |
533 | rtlhal->max_earlymode_num)) { | ||
491 | skb = skb_dequeue(&mac->skb_waitq[tid]); | 534 | skb = skb_dequeue(&mac->skb_waitq[tid]); |
492 | } else { | 535 | } else { |
493 | spin_unlock_bh(&rtlpriv->locks.waitq_lock); | 536 | spin_unlock_bh(&rtlpriv->locks.waitq_lock); |
@@ -525,9 +568,8 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) | |||
525 | u8 own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) entry, true, | 568 | u8 own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) entry, true, |
526 | HW_DESC_OWN); | 569 | HW_DESC_OWN); |
527 | 570 | ||
528 | /* | 571 | /*beacon packet will only use the first |
529 | *beacon packet will only use the first | 572 | *descriptor by defaut, and the own may not |
530 | *descriptor defautly,and the own may not | ||
531 | *be cleared by the hardware | 573 | *be cleared by the hardware |
532 | */ | 574 | */ |
533 | if (own) | 575 | if (own) |
@@ -558,8 +600,9 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) | |||
558 | } | 600 | } |
559 | 601 | ||
560 | /* for sw LPS, just after NULL skb send out, we can | 602 | /* for sw LPS, just after NULL skb send out, we can |
561 | * sure AP kown we are sleeped, our we should not let | 603 | * sure AP knows we are sleeping, we should not let |
562 | * rf to sleep*/ | 604 | * rf sleep |
605 | */ | ||
563 | fc = rtl_get_fc(skb); | 606 | fc = rtl_get_fc(skb); |
564 | if (ieee80211_is_nullfunc(fc)) { | 607 | if (ieee80211_is_nullfunc(fc)) { |
565 | if (ieee80211_has_pm(fc)) { | 608 | if (ieee80211_has_pm(fc)) { |
@@ -569,6 +612,15 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) | |||
569 | rtlpriv->psc.state_inap = false; | 612 | rtlpriv->psc.state_inap = false; |
570 | } | 613 | } |
571 | } | 614 | } |
615 | if (ieee80211_is_action(fc)) { | ||
616 | struct ieee80211_mgmt *action_frame = | ||
617 | (struct ieee80211_mgmt *)skb->data; | ||
618 | if (action_frame->u.action.u.ht_smps.action == | ||
619 | WLAN_HT_ACTION_SMPS) { | ||
620 | dev_kfree_skb(skb); | ||
621 | goto tx_status_ok; | ||
622 | } | ||
623 | } | ||
572 | 624 | ||
573 | /* update tid tx pkt num */ | 625 | /* update tid tx pkt num */ |
574 | tid = rtl_get_tid(skb); | 626 | tid = rtl_get_tid(skb); |
@@ -602,7 +654,8 @@ tx_status_ok: | |||
602 | if (((rtlpriv->link_info.num_rx_inperiod + | 654 | if (((rtlpriv->link_info.num_rx_inperiod + |
603 | rtlpriv->link_info.num_tx_inperiod) > 8) || | 655 | rtlpriv->link_info.num_tx_inperiod) > 8) || |
604 | (rtlpriv->link_info.num_rx_inperiod > 2)) { | 656 | (rtlpriv->link_info.num_rx_inperiod > 2)) { |
605 | schedule_work(&rtlpriv->works.lps_leave_work); | 657 | rtlpriv->enter_ps = false; |
658 | schedule_work(&rtlpriv->works.lps_change_work); | ||
606 | } | 659 | } |
607 | } | 660 | } |
608 | 661 | ||
@@ -637,6 +690,10 @@ static void _rtl_receive_one(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
637 | rtlpriv->link_info.num_rx_inperiod++; | 690 | rtlpriv->link_info.num_rx_inperiod++; |
638 | } | 691 | } |
639 | 692 | ||
693 | /* static bcn for roaming */ | ||
694 | rtl_beacon_statistic(hw, skb); | ||
695 | rtl_p2p_info(hw, (void *)skb->data, skb->len); | ||
696 | |||
640 | /* for sw lps */ | 697 | /* for sw lps */ |
641 | rtl_swlps_beacon(hw, (void *)skb->data, skb->len); | 698 | rtl_swlps_beacon(hw, (void *)skb->data, skb->len); |
642 | rtl_recognize_peer(hw, (void *)skb->data, skb->len); | 699 | rtl_recognize_peer(hw, (void *)skb->data, skb->len); |
@@ -727,9 +784,10 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) | |||
727 | _rtl_receive_one(hw, skb, rx_status); | 784 | _rtl_receive_one(hw, skb, rx_status); |
728 | 785 | ||
729 | if (((rtlpriv->link_info.num_rx_inperiod + | 786 | if (((rtlpriv->link_info.num_rx_inperiod + |
730 | rtlpriv->link_info.num_tx_inperiod) > 8) || | 787 | rtlpriv->link_info.num_tx_inperiod) > 8) || |
731 | (rtlpriv->link_info.num_rx_inperiod > 2)) { | 788 | (rtlpriv->link_info.num_rx_inperiod > 2)) { |
732 | schedule_work(&rtlpriv->works.lps_leave_work); | 789 | rtlpriv->enter_ps = false; |
790 | schedule_work(&rtlpriv->works.lps_change_work); | ||
733 | } | 791 | } |
734 | 792 | ||
735 | dev_kfree_skb_any(skb); | 793 | dev_kfree_skb_any(skb); |
@@ -803,7 +861,7 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id) | |||
803 | RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, "beacon interrupt!\n"); | 861 | RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, "beacon interrupt!\n"); |
804 | } | 862 | } |
805 | 863 | ||
806 | if (inta & rtlpriv->cfg->maps[RTL_IMR_BcnInt]) { | 864 | if (inta & rtlpriv->cfg->maps[RTL_IMR_BCNINT]) { |
807 | RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, | 865 | RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, |
808 | "prepare beacon for interrupt!\n"); | 866 | "prepare beacon for interrupt!\n"); |
809 | tasklet_schedule(&rtlpriv->works.irq_prepare_bcn_tasklet); | 867 | tasklet_schedule(&rtlpriv->works.irq_prepare_bcn_tasklet); |
@@ -884,6 +942,16 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id) | |||
884 | _rtl_pci_rx_interrupt(hw); | 942 | _rtl_pci_rx_interrupt(hw); |
885 | } | 943 | } |
886 | 944 | ||
945 | /*fw related*/ | ||
946 | if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723AE) { | ||
947 | if (inta & rtlpriv->cfg->maps[RTL_IMR_C2HCMD]) { | ||
948 | RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, | ||
949 | "firmware interrupt!\n"); | ||
950 | queue_delayed_work(rtlpriv->works.rtl_wq, | ||
951 | &rtlpriv->works.fwevt_wq, 0); | ||
952 | } | ||
953 | } | ||
954 | |||
887 | if (rtlpriv->rtlhal.earlymode_enable) | 955 | if (rtlpriv->rtlhal.earlymode_enable) |
888 | tasklet_schedule(&rtlpriv->works.irq_tasklet); | 956 | tasklet_schedule(&rtlpriv->works.irq_tasklet); |
889 | 957 | ||
@@ -939,13 +1007,17 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) | |||
939 | return; | 1007 | return; |
940 | } | 1008 | } |
941 | 1009 | ||
942 | static void rtl_lps_leave_work_callback(struct work_struct *work) | 1010 | static void rtl_lps_change_work_callback(struct work_struct *work) |
943 | { | 1011 | { |
944 | struct rtl_works *rtlworks = | 1012 | struct rtl_works *rtlworks = |
945 | container_of(work, struct rtl_works, lps_leave_work); | 1013 | container_of(work, struct rtl_works, lps_change_work); |
946 | struct ieee80211_hw *hw = rtlworks->hw; | 1014 | struct ieee80211_hw *hw = rtlworks->hw; |
1015 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
947 | 1016 | ||
948 | rtl_lps_leave(hw); | 1017 | if (rtlpriv->enter_ps) |
1018 | rtl_lps_enter(hw); | ||
1019 | else | ||
1020 | rtl_lps_leave(hw); | ||
949 | } | 1021 | } |
950 | 1022 | ||
951 | static void _rtl_pci_init_trx_var(struct ieee80211_hw *hw) | 1023 | static void _rtl_pci_init_trx_var(struct ieee80211_hw *hw) |
@@ -1009,7 +1081,8 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw, | |||
1009 | tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet, | 1081 | tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet, |
1010 | (void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet, | 1082 | (void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet, |
1011 | (unsigned long)hw); | 1083 | (unsigned long)hw); |
1012 | INIT_WORK(&rtlpriv->works.lps_leave_work, rtl_lps_leave_work_callback); | 1084 | INIT_WORK(&rtlpriv->works.lps_change_work, |
1085 | rtl_lps_change_work_callback); | ||
1013 | } | 1086 | } |
1014 | 1087 | ||
1015 | static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, | 1088 | static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, |
@@ -1458,10 +1531,14 @@ static void rtl_pci_flush(struct ieee80211_hw *hw, bool drop) | |||
1458 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1531 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1459 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | 1532 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); |
1460 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 1533 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
1534 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1461 | u16 i = 0; | 1535 | u16 i = 0; |
1462 | int queue_id; | 1536 | int queue_id; |
1463 | struct rtl8192_tx_ring *ring; | 1537 | struct rtl8192_tx_ring *ring; |
1464 | 1538 | ||
1539 | if (mac->skip_scan) | ||
1540 | return; | ||
1541 | |||
1465 | for (queue_id = RTL_PCI_MAX_TX_QUEUE_COUNT - 1; queue_id >= 0;) { | 1542 | for (queue_id = RTL_PCI_MAX_TX_QUEUE_COUNT - 1; queue_id >= 0;) { |
1466 | u32 queue_len; | 1543 | u32 queue_len; |
1467 | ring = &pcipriv->dev.tx_ring[queue_id]; | 1544 | ring = &pcipriv->dev.tx_ring[queue_id]; |
@@ -1491,7 +1568,7 @@ static void rtl_pci_deinit(struct ieee80211_hw *hw) | |||
1491 | 1568 | ||
1492 | synchronize_irq(rtlpci->pdev->irq); | 1569 | synchronize_irq(rtlpci->pdev->irq); |
1493 | tasklet_kill(&rtlpriv->works.irq_tasklet); | 1570 | tasklet_kill(&rtlpriv->works.irq_tasklet); |
1494 | cancel_work_sync(&rtlpriv->works.lps_leave_work); | 1571 | cancel_work_sync(&rtlpriv->works.lps_change_work); |
1495 | 1572 | ||
1496 | flush_workqueue(rtlpriv->works.rtl_wq); | 1573 | flush_workqueue(rtlpriv->works.rtl_wq); |
1497 | destroy_workqueue(rtlpriv->works.rtl_wq); | 1574 | destroy_workqueue(rtlpriv->works.rtl_wq); |
@@ -1566,7 +1643,7 @@ static void rtl_pci_stop(struct ieee80211_hw *hw) | |||
1566 | set_hal_stop(rtlhal); | 1643 | set_hal_stop(rtlhal); |
1567 | 1644 | ||
1568 | rtlpriv->cfg->ops->disable_interrupt(hw); | 1645 | rtlpriv->cfg->ops->disable_interrupt(hw); |
1569 | cancel_work_sync(&rtlpriv->works.lps_leave_work); | 1646 | cancel_work_sync(&rtlpriv->works.lps_change_work); |
1570 | 1647 | ||
1571 | spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); | 1648 | spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); |
1572 | while (ppsc->rfchange_inprogress) { | 1649 | while (ppsc->rfchange_inprogress) { |
@@ -1673,6 +1750,10 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, | |||
1673 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | 1750 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, |
1674 | "8192D PCI-E is found - vid/did=%x/%x\n", | 1751 | "8192D PCI-E is found - vid/did=%x/%x\n", |
1675 | venderid, deviceid); | 1752 | venderid, deviceid); |
1753 | } else if (deviceid == RTL_PCI_8188EE_DID) { | ||
1754 | rtlhal->hw_type = HARDWARE_TYPE_RTL8188EE; | ||
1755 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1756 | "Find adapter, Hardware type is 8188EE\n"); | ||
1676 | } else { | 1757 | } else { |
1677 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | 1758 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, |
1678 | "Err: Unknown device - vid/did=%x/%x\n", | 1759 | "Err: Unknown device - vid/did=%x/%x\n", |
@@ -1704,6 +1785,9 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, | |||
1704 | pcipriv->ndis_adapter.devnumber = PCI_SLOT(pdev->devfn); | 1785 | pcipriv->ndis_adapter.devnumber = PCI_SLOT(pdev->devfn); |
1705 | pcipriv->ndis_adapter.funcnumber = PCI_FUNC(pdev->devfn); | 1786 | pcipriv->ndis_adapter.funcnumber = PCI_FUNC(pdev->devfn); |
1706 | 1787 | ||
1788 | /* some ARM have no bridge_pdev and will crash here | ||
1789 | * so we should check if bridge_pdev is NULL | ||
1790 | */ | ||
1707 | if (bridge_pdev) { | 1791 | if (bridge_pdev) { |
1708 | /*find bridge info if available */ | 1792 | /*find bridge info if available */ |
1709 | pcipriv->ndis_adapter.pcibridge_vendorid = bridge_pdev->vendor; | 1793 | pcipriv->ndis_adapter.pcibridge_vendorid = bridge_pdev->vendor; |
@@ -1758,6 +1842,7 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, | |||
1758 | pcipriv->ndis_adapter.amd_l1_patch); | 1842 | pcipriv->ndis_adapter.amd_l1_patch); |
1759 | 1843 | ||
1760 | rtl_pci_parse_configuration(pdev, hw); | 1844 | rtl_pci_parse_configuration(pdev, hw); |
1845 | list_add_tail(&rtlpriv->list, &rtlpriv->glb_var->glb_priv_list); | ||
1761 | 1846 | ||
1762 | return true; | 1847 | return true; |
1763 | } | 1848 | } |
@@ -1804,6 +1889,7 @@ int rtl_pci_probe(struct pci_dev *pdev, | |||
1804 | pci_set_drvdata(pdev, hw); | 1889 | pci_set_drvdata(pdev, hw); |
1805 | 1890 | ||
1806 | rtlpriv = hw->priv; | 1891 | rtlpriv = hw->priv; |
1892 | rtlpriv->hw = hw; | ||
1807 | pcipriv = (void *)rtlpriv->priv; | 1893 | pcipriv = (void *)rtlpriv->priv; |
1808 | pcipriv->dev.pdev = pdev; | 1894 | pcipriv->dev.pdev = pdev; |
1809 | init_completion(&rtlpriv->firmware_loading_complete); | 1895 | init_completion(&rtlpriv->firmware_loading_complete); |
@@ -1812,6 +1898,7 @@ int rtl_pci_probe(struct pci_dev *pdev, | |||
1812 | rtlpriv->rtlhal.interface = INTF_PCI; | 1898 | rtlpriv->rtlhal.interface = INTF_PCI; |
1813 | rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data); | 1899 | rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data); |
1814 | rtlpriv->intf_ops = &rtl_pci_ops; | 1900 | rtlpriv->intf_ops = &rtl_pci_ops; |
1901 | rtlpriv->glb_var = &global_var; | ||
1815 | 1902 | ||
1816 | /* | 1903 | /* |
1817 | *init dbgp flags before all | 1904 | *init dbgp flags before all |
@@ -1916,7 +2003,6 @@ int rtl_pci_probe(struct pci_dev *pdev, | |||
1916 | 2003 | ||
1917 | fail3: | 2004 | fail3: |
1918 | rtl_deinit_core(hw); | 2005 | rtl_deinit_core(hw); |
1919 | _rtl_pci_io_handler_release(hw); | ||
1920 | 2006 | ||
1921 | if (rtlpriv->io.pci_mem_start != 0) | 2007 | if (rtlpriv->io.pci_mem_start != 0) |
1922 | pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); | 2008 | pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); |
@@ -1965,14 +2051,15 @@ void rtl_pci_disconnect(struct pci_dev *pdev) | |||
1965 | 2051 | ||
1966 | rtl_pci_deinit(hw); | 2052 | rtl_pci_deinit(hw); |
1967 | rtl_deinit_core(hw); | 2053 | rtl_deinit_core(hw); |
1968 | _rtl_pci_io_handler_release(hw); | ||
1969 | rtlpriv->cfg->ops->deinit_sw_vars(hw); | 2054 | rtlpriv->cfg->ops->deinit_sw_vars(hw); |
1970 | 2055 | ||
1971 | if (rtlpci->irq_alloc) { | 2056 | if (rtlpci->irq_alloc) { |
2057 | synchronize_irq(rtlpci->pdev->irq); | ||
1972 | free_irq(rtlpci->pdev->irq, hw); | 2058 | free_irq(rtlpci->pdev->irq, hw); |
1973 | rtlpci->irq_alloc = 0; | 2059 | rtlpci->irq_alloc = 0; |
1974 | } | 2060 | } |
1975 | 2061 | ||
2062 | list_del(&rtlpriv->list); | ||
1976 | if (rtlpriv->io.pci_mem_start != 0) { | 2063 | if (rtlpriv->io.pci_mem_start != 0) { |
1977 | pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); | 2064 | pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); |
1978 | pci_release_regions(pdev); | 2065 | pci_release_regions(pdev); |
@@ -2034,6 +2121,7 @@ struct rtl_intf_ops rtl_pci_ops = { | |||
2034 | .read_efuse_byte = read_efuse_byte, | 2121 | .read_efuse_byte = read_efuse_byte, |
2035 | .adapter_start = rtl_pci_start, | 2122 | .adapter_start = rtl_pci_start, |
2036 | .adapter_stop = rtl_pci_stop, | 2123 | .adapter_stop = rtl_pci_stop, |
2124 | .check_buddy_priv = rtl_pci_check_buddy_priv, | ||
2037 | .adapter_tx = rtl_pci_tx, | 2125 | .adapter_tx = rtl_pci_tx, |
2038 | .flush = rtl_pci_flush, | 2126 | .flush = rtl_pci_flush, |
2039 | .reset_trx_ring = rtl_pci_reset_trx_ring, | 2127 | .reset_trx_ring = rtl_pci_reset_trx_ring, |
diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h index 65b08f50022e..d3262ec45d23 100644 --- a/drivers/net/wireless/rtlwifi/pci.h +++ b/drivers/net/wireless/rtlwifi/pci.h | |||
@@ -94,6 +94,7 @@ | |||
94 | #define RTL_PCI_8192CU_DID 0x8191 /*8192ce */ | 94 | #define RTL_PCI_8192CU_DID 0x8191 /*8192ce */ |
95 | #define RTL_PCI_8192DE_DID 0x8193 /*8192de */ | 95 | #define RTL_PCI_8192DE_DID 0x8193 /*8192de */ |
96 | #define RTL_PCI_8192DE_DID2 0x002B /*92DE*/ | 96 | #define RTL_PCI_8192DE_DID2 0x002B /*92DE*/ |
97 | #define RTL_PCI_8188EE_DID 0x8179 /*8188ee*/ | ||
97 | 98 | ||
98 | /*8192 support 16 pages of IO registers*/ | 99 | /*8192 support 16 pages of IO registers*/ |
99 | #define RTL_MEM_MAPPED_IO_RANGE_8190PCI 0x1000 | 100 | #define RTL_MEM_MAPPED_IO_RANGE_8190PCI 0x1000 |
@@ -175,6 +176,7 @@ struct rtl_pci { | |||
175 | /*irq */ | 176 | /*irq */ |
176 | u8 irq_alloc; | 177 | u8 irq_alloc; |
177 | u32 irq_mask[2]; | 178 | u32 irq_mask[2]; |
179 | u32 sys_irq_mask; | ||
178 | 180 | ||
179 | /*Bcn control register setting */ | 181 | /*Bcn control register setting */ |
180 | u32 reg_bcn_ctrl_val; | 182 | u32 reg_bcn_ctrl_val; |
diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index 13ad33e85577..884bceae38a9 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c | |||
@@ -180,6 +180,9 @@ void rtl_ips_nic_off_wq_callback(void *data) | |||
180 | return; | 180 | return; |
181 | } | 181 | } |
182 | 182 | ||
183 | if (mac->p2p_in_use) | ||
184 | return; | ||
185 | |||
183 | if (mac->link_state > MAC80211_NOLINK) | 186 | if (mac->link_state > MAC80211_NOLINK) |
184 | return; | 187 | return; |
185 | 188 | ||
@@ -189,6 +192,9 @@ void rtl_ips_nic_off_wq_callback(void *data) | |||
189 | if (rtlpriv->sec.being_setkey) | 192 | if (rtlpriv->sec.being_setkey) |
190 | return; | 193 | return; |
191 | 194 | ||
195 | if (rtlpriv->cfg->ops->bt_coex_off_before_lps) | ||
196 | rtlpriv->cfg->ops->bt_coex_off_before_lps(hw); | ||
197 | |||
192 | if (ppsc->inactiveps) { | 198 | if (ppsc->inactiveps) { |
193 | rtstate = ppsc->rfpwr_state; | 199 | rtstate = ppsc->rfpwr_state; |
194 | 200 | ||
@@ -231,6 +237,9 @@ void rtl_ips_nic_off(struct ieee80211_hw *hw) | |||
231 | &rtlpriv->works.ips_nic_off_wq, MSECS(100)); | 237 | &rtlpriv->works.ips_nic_off_wq, MSECS(100)); |
232 | } | 238 | } |
233 | 239 | ||
240 | /* NOTICE: any opmode should exc nic_on, or disable without | ||
241 | * nic_on may something wrong, like adhoc TP | ||
242 | */ | ||
234 | void rtl_ips_nic_on(struct ieee80211_hw *hw) | 243 | void rtl_ips_nic_on(struct ieee80211_hw *hw) |
235 | { | 244 | { |
236 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 245 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -299,7 +308,7 @@ static void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode) | |||
299 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 308 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
300 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 309 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
301 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | 310 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
302 | u8 rpwm_val, fw_pwrmode; | 311 | bool enter_fwlps; |
303 | 312 | ||
304 | if (mac->opmode == NL80211_IFTYPE_ADHOC) | 313 | if (mac->opmode == NL80211_IFTYPE_ADHOC) |
305 | return; | 314 | return; |
@@ -324,43 +333,31 @@ static void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode) | |||
324 | */ | 333 | */ |
325 | 334 | ||
326 | if ((ppsc->fwctrl_lps) && ppsc->report_linked) { | 335 | if ((ppsc->fwctrl_lps) && ppsc->report_linked) { |
327 | bool fw_current_inps; | ||
328 | if (ppsc->dot11_psmode == EACTIVE) { | 336 | if (ppsc->dot11_psmode == EACTIVE) { |
329 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | 337 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, |
330 | "FW LPS leave ps_mode:%x\n", | 338 | "FW LPS leave ps_mode:%x\n", |
331 | FW_PS_ACTIVE_MODE); | 339 | FW_PS_ACTIVE_MODE); |
332 | 340 | enter_fwlps = false; | |
333 | rpwm_val = 0x0C; /* RF on */ | 341 | ppsc->pwr_mode = FW_PS_ACTIVE_MODE; |
334 | fw_pwrmode = FW_PS_ACTIVE_MODE; | 342 | ppsc->smart_ps = 0; |
335 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, | ||
336 | &rpwm_val); | ||
337 | rtlpriv->cfg->ops->set_hw_reg(hw, | 343 | rtlpriv->cfg->ops->set_hw_reg(hw, |
338 | HW_VAR_H2C_FW_PWRMODE, | 344 | HW_VAR_FW_LPS_ACTION, |
339 | &fw_pwrmode); | 345 | (u8 *)(&enter_fwlps)); |
340 | fw_current_inps = false; | 346 | if (ppsc->p2p_ps_info.opp_ps) |
341 | 347 | rtl_p2p_ps_cmd(hw, P2P_PS_ENABLE); | |
342 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
343 | HW_VAR_FW_PSMODE_STATUS, | ||
344 | (u8 *) (&fw_current_inps)); | ||
345 | 348 | ||
346 | } else { | 349 | } else { |
347 | if (rtl_get_fwlps_doze(hw)) { | 350 | if (rtl_get_fwlps_doze(hw)) { |
348 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | 351 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, |
349 | "FW LPS enter ps_mode:%x\n", | 352 | "FW LPS enter ps_mode:%x\n", |
350 | ppsc->fwctrl_psmode); | 353 | ppsc->fwctrl_psmode); |
351 | 354 | enter_fwlps = true; | |
352 | rpwm_val = 0x02; /* RF off */ | 355 | ppsc->pwr_mode = ppsc->fwctrl_psmode; |
353 | fw_current_inps = true; | 356 | ppsc->smart_ps = 2; |
354 | rtlpriv->cfg->ops->set_hw_reg(hw, | 357 | rtlpriv->cfg->ops->set_hw_reg(hw, |
355 | HW_VAR_FW_PSMODE_STATUS, | 358 | HW_VAR_FW_LPS_ACTION, |
356 | (u8 *) (&fw_current_inps)); | 359 | (u8 *)(&enter_fwlps)); |
357 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
358 | HW_VAR_H2C_FW_PWRMODE, | ||
359 | &ppsc->fwctrl_psmode); | ||
360 | 360 | ||
361 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
362 | HW_VAR_SET_RPWM, | ||
363 | &rpwm_val); | ||
364 | } else { | 361 | } else { |
365 | /* Reset the power save related parameters. */ | 362 | /* Reset the power save related parameters. */ |
366 | ppsc->dot11_psmode = EACTIVE; | 363 | ppsc->dot11_psmode = EACTIVE; |
@@ -642,3 +639,286 @@ void rtl_swlps_wq_callback(void *data) | |||
642 | rtlpriv->psc.state = ps; | 639 | rtlpriv->psc.state = ps; |
643 | } | 640 | } |
644 | } | 641 | } |
642 | |||
643 | static void rtl_p2p_noa_ie(struct ieee80211_hw *hw, void *data, | ||
644 | unsigned int len) | ||
645 | { | ||
646 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
647 | struct ieee80211_mgmt *mgmt = (void *)data; | ||
648 | struct rtl_p2p_ps_info *p2pinfo = &(rtlpriv->psc.p2p_ps_info); | ||
649 | u8 *pos, *end, *ie; | ||
650 | u16 noa_len; | ||
651 | static u8 p2p_oui_ie_type[4] = {0x50, 0x6f, 0x9a, 0x09}; | ||
652 | u8 noa_num, index, i, noa_index = 0; | ||
653 | bool find_p2p_ie = false , find_p2p_ps_ie = false; | ||
654 | pos = (u8 *)mgmt->u.beacon.variable; | ||
655 | end = data + len; | ||
656 | ie = NULL; | ||
657 | |||
658 | while (pos + 1 < end) { | ||
659 | if (pos + 2 + pos[1] > end) | ||
660 | return; | ||
661 | |||
662 | if (pos[0] == 221 && pos[1] > 4) { | ||
663 | if (memcmp(&pos[2], p2p_oui_ie_type, 4) == 0) { | ||
664 | ie = pos + 2+4; | ||
665 | break; | ||
666 | } | ||
667 | } | ||
668 | pos += 2 + pos[1]; | ||
669 | } | ||
670 | |||
671 | if (ie == NULL) | ||
672 | return; | ||
673 | find_p2p_ie = true; | ||
674 | /*to find noa ie*/ | ||
675 | while (ie + 1 < end) { | ||
676 | noa_len = READEF2BYTE(&ie[1]); | ||
677 | if (ie + 3 + ie[1] > end) | ||
678 | return; | ||
679 | |||
680 | if (ie[0] == 12) { | ||
681 | find_p2p_ps_ie = true; | ||
682 | if ((noa_len - 2) % 13 != 0) { | ||
683 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
684 | "P2P notice of absence: invalid length.%d\n", | ||
685 | noa_len); | ||
686 | return; | ||
687 | } else { | ||
688 | noa_num = (noa_len - 2) / 13; | ||
689 | } | ||
690 | noa_index = ie[3]; | ||
691 | if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode == | ||
692 | P2P_PS_NONE || noa_index != p2pinfo->noa_index) { | ||
693 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, | ||
694 | "update NOA ie.\n"); | ||
695 | p2pinfo->noa_index = noa_index; | ||
696 | p2pinfo->opp_ps = (ie[4] >> 7); | ||
697 | p2pinfo->ctwindow = ie[4] & 0x7F; | ||
698 | p2pinfo->noa_num = noa_num; | ||
699 | index = 5; | ||
700 | for (i = 0; i < noa_num; i++) { | ||
701 | p2pinfo->noa_count_type[i] = | ||
702 | READEF1BYTE(ie+index); | ||
703 | index += 1; | ||
704 | p2pinfo->noa_duration[i] = | ||
705 | READEF4BYTE(ie+index); | ||
706 | index += 4; | ||
707 | p2pinfo->noa_interval[i] = | ||
708 | READEF4BYTE(ie+index); | ||
709 | index += 4; | ||
710 | p2pinfo->noa_start_time[i] = | ||
711 | READEF4BYTE(ie+index); | ||
712 | index += 4; | ||
713 | } | ||
714 | |||
715 | if (p2pinfo->opp_ps == 1) { | ||
716 | p2pinfo->p2p_ps_mode = P2P_PS_CTWINDOW; | ||
717 | /* Driver should wait LPS entering | ||
718 | * CTWindow | ||
719 | */ | ||
720 | if (rtlpriv->psc.fw_current_inpsmode) | ||
721 | rtl_p2p_ps_cmd(hw, | ||
722 | P2P_PS_ENABLE); | ||
723 | } else if (p2pinfo->noa_num > 0) { | ||
724 | p2pinfo->p2p_ps_mode = P2P_PS_NOA; | ||
725 | rtl_p2p_ps_cmd(hw, P2P_PS_ENABLE); | ||
726 | } else if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) { | ||
727 | rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); | ||
728 | } | ||
729 | } | ||
730 | break; | ||
731 | } | ||
732 | ie += 3 + noa_len; | ||
733 | } | ||
734 | |||
735 | if (find_p2p_ie == true) { | ||
736 | if ((p2pinfo->p2p_ps_mode > P2P_PS_NONE) && | ||
737 | (find_p2p_ps_ie == false)) | ||
738 | rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); | ||
739 | } | ||
740 | } | ||
741 | |||
742 | static void rtl_p2p_action_ie(struct ieee80211_hw *hw, void *data, | ||
743 | unsigned int len) | ||
744 | { | ||
745 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
746 | struct ieee80211_mgmt *mgmt = (void *)data; | ||
747 | struct rtl_p2p_ps_info *p2pinfo = &(rtlpriv->psc.p2p_ps_info); | ||
748 | u8 noa_num, index, i, noa_index = 0; | ||
749 | u8 *pos, *end, *ie; | ||
750 | u16 noa_len; | ||
751 | static u8 p2p_oui_ie_type[4] = {0x50, 0x6f, 0x9a, 0x09}; | ||
752 | |||
753 | pos = (u8 *)&mgmt->u.action.category; | ||
754 | end = data + len; | ||
755 | ie = NULL; | ||
756 | |||
757 | if (pos[0] == 0x7f) { | ||
758 | if (memcmp(&pos[1], p2p_oui_ie_type, 4) == 0) | ||
759 | ie = pos + 3+4; | ||
760 | } | ||
761 | |||
762 | if (ie == NULL) | ||
763 | return; | ||
764 | |||
765 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "action frame find P2P IE.\n"); | ||
766 | /*to find noa ie*/ | ||
767 | while (ie + 1 < end) { | ||
768 | noa_len = READEF2BYTE(&ie[1]); | ||
769 | if (ie + 3 + ie[1] > end) | ||
770 | return; | ||
771 | |||
772 | if (ie[0] == 12) { | ||
773 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "find NOA IE.\n"); | ||
774 | RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_LOUD, "noa ie ", | ||
775 | ie, noa_len); | ||
776 | if ((noa_len - 2) % 13 != 0) { | ||
777 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, | ||
778 | "P2P notice of absence: invalid length.%d\n", | ||
779 | noa_len); | ||
780 | return; | ||
781 | } else { | ||
782 | noa_num = (noa_len - 2) / 13; | ||
783 | } | ||
784 | noa_index = ie[3]; | ||
785 | if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode == | ||
786 | P2P_PS_NONE || noa_index != p2pinfo->noa_index) { | ||
787 | p2pinfo->noa_index = noa_index; | ||
788 | p2pinfo->opp_ps = (ie[4] >> 7); | ||
789 | p2pinfo->ctwindow = ie[4] & 0x7F; | ||
790 | p2pinfo->noa_num = noa_num; | ||
791 | index = 5; | ||
792 | for (i = 0; i < noa_num; i++) { | ||
793 | p2pinfo->noa_count_type[i] = | ||
794 | READEF1BYTE(ie+index); | ||
795 | index += 1; | ||
796 | p2pinfo->noa_duration[i] = | ||
797 | READEF4BYTE(ie+index); | ||
798 | index += 4; | ||
799 | p2pinfo->noa_interval[i] = | ||
800 | READEF4BYTE(ie+index); | ||
801 | index += 4; | ||
802 | p2pinfo->noa_start_time[i] = | ||
803 | READEF4BYTE(ie+index); | ||
804 | index += 4; | ||
805 | } | ||
806 | |||
807 | if (p2pinfo->opp_ps == 1) { | ||
808 | p2pinfo->p2p_ps_mode = P2P_PS_CTWINDOW; | ||
809 | /* Driver should wait LPS entering | ||
810 | * CTWindow | ||
811 | */ | ||
812 | if (rtlpriv->psc.fw_current_inpsmode) | ||
813 | rtl_p2p_ps_cmd(hw, | ||
814 | P2P_PS_ENABLE); | ||
815 | } else if (p2pinfo->noa_num > 0) { | ||
816 | p2pinfo->p2p_ps_mode = P2P_PS_NOA; | ||
817 | rtl_p2p_ps_cmd(hw, P2P_PS_ENABLE); | ||
818 | } else if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) { | ||
819 | rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); | ||
820 | } | ||
821 | } | ||
822 | break; | ||
823 | } | ||
824 | ie += 3 + noa_len; | ||
825 | } | ||
826 | } | ||
827 | |||
828 | void rtl_p2p_ps_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) | ||
829 | { | ||
830 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
831 | struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); | ||
832 | struct rtl_p2p_ps_info *p2pinfo = &(rtlpriv->psc.p2p_ps_info); | ||
833 | |||
834 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, " p2p state %x\n", p2p_ps_state); | ||
835 | switch (p2p_ps_state) { | ||
836 | case P2P_PS_DISABLE: | ||
837 | p2pinfo->p2p_ps_state = p2p_ps_state; | ||
838 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
839 | HW_VAR_H2C_FW_P2P_PS_OFFLOAD, | ||
840 | (u8 *)(&p2p_ps_state)); | ||
841 | |||
842 | p2pinfo->noa_index = 0; | ||
843 | p2pinfo->ctwindow = 0; | ||
844 | p2pinfo->opp_ps = 0; | ||
845 | p2pinfo->noa_num = 0; | ||
846 | p2pinfo->p2p_ps_mode = P2P_PS_NONE; | ||
847 | if (rtlps->fw_current_inpsmode == true) { | ||
848 | if (rtlps->smart_ps == 0) { | ||
849 | rtlps->smart_ps = 2; | ||
850 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
851 | HW_VAR_H2C_FW_PWRMODE, | ||
852 | (u8 *)(&rtlps->pwr_mode)); | ||
853 | } | ||
854 | } | ||
855 | break; | ||
856 | case P2P_PS_ENABLE: | ||
857 | if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) { | ||
858 | p2pinfo->p2p_ps_state = p2p_ps_state; | ||
859 | |||
860 | if (p2pinfo->ctwindow > 0) { | ||
861 | if (rtlps->smart_ps != 0) { | ||
862 | rtlps->smart_ps = 0; | ||
863 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
864 | HW_VAR_H2C_FW_PWRMODE, | ||
865 | (u8 *)(&rtlps->pwr_mode)); | ||
866 | } | ||
867 | } | ||
868 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
869 | HW_VAR_H2C_FW_P2P_PS_OFFLOAD, | ||
870 | (u8 *)(&p2p_ps_state)); | ||
871 | } | ||
872 | break; | ||
873 | case P2P_PS_SCAN: | ||
874 | case P2P_PS_SCAN_DONE: | ||
875 | case P2P_PS_ALLSTASLEEP: | ||
876 | if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) { | ||
877 | p2pinfo->p2p_ps_state = p2p_ps_state; | ||
878 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
879 | HW_VAR_H2C_FW_P2P_PS_OFFLOAD, | ||
880 | (u8 *)(&p2p_ps_state)); | ||
881 | } | ||
882 | break; | ||
883 | default: | ||
884 | break; | ||
885 | } | ||
886 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, | ||
887 | "ctwindow %x oppps %x\n", p2pinfo->ctwindow, p2pinfo->opp_ps); | ||
888 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, | ||
889 | "count %x duration %x index %x interval %x start time %x noa num %x\n", | ||
890 | p2pinfo->noa_count_type[0], p2pinfo->noa_duration[0], | ||
891 | p2pinfo->noa_index, p2pinfo->noa_interval[0], | ||
892 | p2pinfo->noa_start_time[0], p2pinfo->noa_num); | ||
893 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "end\n"); | ||
894 | } | ||
895 | |||
896 | void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len) | ||
897 | { | ||
898 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
899 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
900 | struct ieee80211_hdr *hdr = (void *)data; | ||
901 | |||
902 | if (!mac->p2p) | ||
903 | return; | ||
904 | if (mac->link_state != MAC80211_LINKED) | ||
905 | return; | ||
906 | /* min. beacon length + FCS_LEN */ | ||
907 | if (len <= 40 + FCS_LEN) | ||
908 | return; | ||
909 | |||
910 | /* and only beacons from the associated BSSID, please */ | ||
911 | if (compare_ether_addr(hdr->addr3, rtlpriv->mac80211.bssid)) | ||
912 | return; | ||
913 | |||
914 | /* check if this really is a beacon */ | ||
915 | if (!(ieee80211_is_beacon(hdr->frame_control) || | ||
916 | ieee80211_is_probe_resp(hdr->frame_control) || | ||
917 | ieee80211_is_action(hdr->frame_control))) | ||
918 | return; | ||
919 | |||
920 | if (ieee80211_is_action(hdr->frame_control)) | ||
921 | rtl_p2p_action_ie(hw, data, len - FCS_LEN); | ||
922 | else | ||
923 | rtl_p2p_noa_ie(hw, data, len - FCS_LEN); | ||
924 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/ps.h b/drivers/net/wireless/rtlwifi/ps.h index 1357856998c2..4d682b753f50 100644 --- a/drivers/net/wireless/rtlwifi/ps.h +++ b/drivers/net/wireless/rtlwifi/ps.h | |||
@@ -47,5 +47,7 @@ void rtl_swlps_wq_callback(void *data); | |||
47 | void rtl_swlps_rfon_wq_callback(void *data); | 47 | void rtl_swlps_rfon_wq_callback(void *data); |
48 | void rtl_swlps_rf_awake(struct ieee80211_hw *hw); | 48 | void rtl_swlps_rf_awake(struct ieee80211_hw *hw); |
49 | void rtl_swlps_rf_sleep(struct ieee80211_hw *hw); | 49 | void rtl_swlps_rf_sleep(struct ieee80211_hw *hw); |
50 | void rtl_p2p_ps_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state); | ||
51 | void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len); | ||
50 | 52 | ||
51 | #endif | 53 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/Makefile b/drivers/net/wireless/rtlwifi/rtl8188ee/Makefile new file mode 100644 index 000000000000..5b194e97f4b3 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/Makefile | |||
@@ -0,0 +1,16 @@ | |||
1 | rtl8188ee-objs := \ | ||
2 | dm.o \ | ||
3 | fw.o \ | ||
4 | hw.o \ | ||
5 | led.o \ | ||
6 | phy.o \ | ||
7 | pwrseq.o \ | ||
8 | pwrseqcmd.o \ | ||
9 | rf.o \ | ||
10 | sw.o \ | ||
11 | table.o \ | ||
12 | trx.o | ||
13 | |||
14 | obj-$(CONFIG_RTL8188EE) += rtl8188ee.o | ||
15 | |||
16 | ccflags-y += -Idrivers/net/wireless/rtlwifi -D__CHECK_ENDIAN__ | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/def.h b/drivers/net/wireless/rtlwifi/rtl8188ee/def.h new file mode 100644 index 000000000000..c764fff9ebe6 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/def.h | |||
@@ -0,0 +1,324 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #ifndef __RTL92C_DEF_H__ | ||
31 | #define __RTL92C_DEF_H__ | ||
32 | |||
33 | #define HAL_RETRY_LIMIT_INFRA 48 | ||
34 | #define HAL_RETRY_LIMIT_AP_ADHOC 7 | ||
35 | |||
36 | #define RESET_DELAY_8185 20 | ||
37 | |||
38 | #define RT_IBSS_INT_MASKS (IMR_BCNINT | IMR_TBDOK | IMR_TBDER) | ||
39 | #define RT_AC_INT_MASKS (IMR_VIDOK | IMR_VODOK | IMR_BEDOK|IMR_BKDOK) | ||
40 | |||
41 | #define NUM_OF_FIRMWARE_QUEUE 10 | ||
42 | #define NUM_OF_PAGES_IN_FW 0x100 | ||
43 | #define NUM_OF_PAGE_IN_FW_QUEUE_BK 0x07 | ||
44 | #define NUM_OF_PAGE_IN_FW_QUEUE_BE 0x07 | ||
45 | #define NUM_OF_PAGE_IN_FW_QUEUE_VI 0x07 | ||
46 | #define NUM_OF_PAGE_IN_FW_QUEUE_VO 0x07 | ||
47 | #define NUM_OF_PAGE_IN_FW_QUEUE_HCCA 0x0 | ||
48 | #define NUM_OF_PAGE_IN_FW_QUEUE_CMD 0x0 | ||
49 | #define NUM_OF_PAGE_IN_FW_QUEUE_MGNT 0x02 | ||
50 | #define NUM_OF_PAGE_IN_FW_QUEUE_HIGH 0x02 | ||
51 | #define NUM_OF_PAGE_IN_FW_QUEUE_BCN 0x2 | ||
52 | #define NUM_OF_PAGE_IN_FW_QUEUE_PUB 0xA1 | ||
53 | |||
54 | #define NUM_OF_PAGE_IN_FW_QUEUE_BK_DTM 0x026 | ||
55 | #define NUM_OF_PAGE_IN_FW_QUEUE_BE_DTM 0x048 | ||
56 | #define NUM_OF_PAGE_IN_FW_QUEUE_VI_DTM 0x048 | ||
57 | #define NUM_OF_PAGE_IN_FW_QUEUE_VO_DTM 0x026 | ||
58 | #define NUM_OF_PAGE_IN_FW_QUEUE_PUB_DTM 0x00 | ||
59 | |||
60 | #define MAX_LINES_HWCONFIG_TXT 1000 | ||
61 | #define MAX_BYTES_LINE_HWCONFIG_TXT 256 | ||
62 | |||
63 | #define SW_THREE_WIRE 0 | ||
64 | #define HW_THREE_WIRE 2 | ||
65 | |||
66 | #define BT_DEMO_BOARD 0 | ||
67 | #define BT_QA_BOARD 1 | ||
68 | #define BT_FPGA 2 | ||
69 | |||
70 | #define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0 | ||
71 | #define HAL_PRIME_CHNL_OFFSET_LOWER 1 | ||
72 | #define HAL_PRIME_CHNL_OFFSET_UPPER 2 | ||
73 | |||
74 | #define MAX_H2C_QUEUE_NUM 10 | ||
75 | |||
76 | #define RX_MPDU_QUEUE 0 | ||
77 | #define RX_CMD_QUEUE 1 | ||
78 | #define RX_MAX_QUEUE 2 | ||
79 | #define AC2QUEUEID(_AC) (_AC) | ||
80 | |||
81 | #define C2H_RX_CMD_HDR_LEN 8 | ||
82 | #define GET_C2H_CMD_CMD_LEN(__prxhdr) \ | ||
83 | LE_BITS_TO_4BYTE((__prxhdr), 0, 16) | ||
84 | #define GET_C2H_CMD_ELEMENT_ID(__prxhdr) \ | ||
85 | LE_BITS_TO_4BYTE((__prxhdr), 16, 8) | ||
86 | #define GET_C2H_CMD_CMD_SEQ(__prxhdr) \ | ||
87 | LE_BITS_TO_4BYTE((__prxhdr), 24, 7) | ||
88 | #define GET_C2H_CMD_CONTINUE(__prxhdr) \ | ||
89 | LE_BITS_TO_4BYTE((__prxhdr), 31, 1) | ||
90 | #define GET_C2H_CMD_CONTENT(__prxhdr) \ | ||
91 | ((u8 *)(__prxhdr) + C2H_RX_CMD_HDR_LEN) | ||
92 | |||
93 | #define GET_C2H_CMD_FEEDBACK_ELEMENT_ID(__pcmdfbhdr) \ | ||
94 | LE_BITS_TO_4BYTE((__pcmdfbhdr), 0, 8) | ||
95 | #define GET_C2H_CMD_FEEDBACK_CCX_LEN(__pcmdfbhdr) \ | ||
96 | LE_BITS_TO_4BYTE((__pcmdfbhdr), 8, 8) | ||
97 | #define GET_C2H_CMD_FEEDBACK_CCX_CMD_CNT(__pcmdfbhdr) \ | ||
98 | LE_BITS_TO_4BYTE((__pcmdfbhdr), 16, 16) | ||
99 | #define GET_C2H_CMD_FEEDBACK_CCX_MAC_ID(__pcmdfbhdr) \ | ||
100 | LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 0, 5) | ||
101 | #define GET_C2H_CMD_FEEDBACK_CCX_VALID(__pcmdfbhdr) \ | ||
102 | LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 7, 1) | ||
103 | #define GET_C2H_CMD_FEEDBACK_CCX_RETRY_CNT(__pcmdfbhdr) \ | ||
104 | LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 8, 5) | ||
105 | #define GET_C2H_CMD_FEEDBACK_CCX_TOK(__pcmdfbhdr) \ | ||
106 | LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 15, 1) | ||
107 | #define GET_C2H_CMD_FEEDBACK_CCX_QSEL(__pcmdfbhdr) \ | ||
108 | LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4) | ||
109 | #define GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr) \ | ||
110 | LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12) | ||
111 | |||
112 | #define CHIP_BONDING_IDENTIFIER(_value) (((_value)>>22)&0x3) | ||
113 | |||
114 | |||
115 | /* [15:12] IC version(CUT): A-cut=0, B-cut=1, C-cut=2, D-cut=3 | ||
116 | * [7] Manufacturer: TSMC=0, UMC=1 | ||
117 | * [6:4] RF type: 1T1R=0, 1T2R=1, 2T2R=2 | ||
118 | * [3] Chip type: TEST=0, NORMAL=1 | ||
119 | * [2:0] IC type: 81xxC=0, 8723=1, 92D=2 | ||
120 | */ | ||
121 | #define CHIP_8723 BIT(0) | ||
122 | #define CHIP_92D BIT(1) | ||
123 | #define NORMAL_CHIP BIT(3) | ||
124 | #define RF_TYPE_1T1R (~(BIT(4)|BIT(5)|BIT(6))) | ||
125 | #define RF_TYPE_1T2R BIT(4) | ||
126 | #define RF_TYPE_2T2R BIT(5) | ||
127 | #define CHIP_VENDOR_UMC BIT(7) | ||
128 | #define B_CUT_VERSION BIT(12) | ||
129 | #define C_CUT_VERSION BIT(13) | ||
130 | #define D_CUT_VERSION ((BIT(12)|BIT(13))) | ||
131 | #define E_CUT_VERSION BIT(14) | ||
132 | |||
133 | |||
134 | /* MASK */ | ||
135 | #define IC_TYPE_MASK (BIT(0)|BIT(1)|BIT(2)) | ||
136 | #define CHIP_TYPE_MASK BIT(3) | ||
137 | #define RF_TYPE_MASK (BIT(4)|BIT(5)|BIT(6)) | ||
138 | #define MANUFACTUER_MASK BIT(7) | ||
139 | #define ROM_VERSION_MASK (BIT(11)|BIT(10)|BIT(9)|BIT(8)) | ||
140 | #define CUT_VERSION_MASK (BIT(15)|BIT(14)|BIT(13)|BIT(12)) | ||
141 | |||
142 | /* Get element */ | ||
143 | #define GET_CVID_IC_TYPE(version) ((version) & IC_TYPE_MASK) | ||
144 | #define GET_CVID_CHIP_TYPE(version) ((version) & CHIP_TYPE_MASK) | ||
145 | #define GET_CVID_RF_TYPE(version) ((version) & RF_TYPE_MASK) | ||
146 | #define GET_CVID_MANUFACTUER(version) ((version) & MANUFACTUER_MASK) | ||
147 | #define GET_CVID_ROM_VERSION(version) ((version) & ROM_VERSION_MASK) | ||
148 | #define GET_CVID_CUT_VERSION(version) ((version) & CUT_VERSION_MASK) | ||
149 | |||
150 | |||
151 | #define IS_81XXC(version) \ | ||
152 | ((GET_CVID_IC_TYPE(version) == 0) ? true : false) | ||
153 | #define IS_8723_SERIES(version) \ | ||
154 | ((GET_CVID_IC_TYPE(version) == CHIP_8723) ? true : false) | ||
155 | #define IS_92D(version) \ | ||
156 | ((GET_CVID_IC_TYPE(version) == CHIP_92D) ? true : false) | ||
157 | |||
158 | #define IS_NORMAL_CHIP(version) \ | ||
159 | ((GET_CVID_CHIP_TYPE(version)) ? true : false) | ||
160 | #define IS_NORMAL_CHIP92D(version) \ | ||
161 | ((GET_CVID_CHIP_TYPE(version)) ? true : false) | ||
162 | |||
163 | #define IS_1T1R(version) \ | ||
164 | ((GET_CVID_RF_TYPE(version)) ? false : true) | ||
165 | #define IS_1T2R(version) \ | ||
166 | ((GET_CVID_RF_TYPE(version) == RF_TYPE_1T2R) ? true : false) | ||
167 | #define IS_2T2R(version) \ | ||
168 | ((GET_CVID_RF_TYPE(version) == RF_TYPE_2T2R) ? true : false) | ||
169 | #define IS_CHIP_VENDOR_UMC(version) \ | ||
170 | ((GET_CVID_MANUFACTUER(version)) ? true : false) | ||
171 | |||
172 | #define IS_92C_SERIAL(version) \ | ||
173 | ((IS_81XXC(version) && IS_2T2R(version)) ? true : false) | ||
174 | #define IS_81xxC_VENDOR_UMC_A_CUT(version) \ | ||
175 | (IS_81XXC(version) ? ((IS_CHIP_VENDOR_UMC(version)) ? \ | ||
176 | ((GET_CVID_CUT_VERSION(version)) ? false : true) : false) : false) | ||
177 | #define IS_81xxC_VENDOR_UMC_B_CUT(version) \ | ||
178 | (IS_81XXC(version) ? (IS_CHIP_VENDOR_UMC(version) ? \ | ||
179 | ((GET_CVID_CUT_VERSION(version) == B_CUT_VERSION) ? true \ | ||
180 | : false) : false) : false) | ||
181 | |||
182 | enum version_8188e { | ||
183 | VERSION_TEST_CHIP_88E = 0x00, | ||
184 | VERSION_NORMAL_CHIP_88E = 0x01, | ||
185 | VERSION_UNKNOWN = 0xFF, | ||
186 | }; | ||
187 | |||
188 | enum rx_packet_type { | ||
189 | NORMAL_RX, | ||
190 | TX_REPORT1, | ||
191 | TX_REPORT2, | ||
192 | HIS_REPORT, | ||
193 | }; | ||
194 | |||
195 | enum rtl819x_loopback_e { | ||
196 | RTL819X_NO_LOOPBACK = 0, | ||
197 | RTL819X_MAC_LOOPBACK = 1, | ||
198 | RTL819X_DMA_LOOPBACK = 2, | ||
199 | RTL819X_CCK_LOOPBACK = 3, | ||
200 | }; | ||
201 | |||
202 | enum rf_optype { | ||
203 | RF_OP_BY_SW_3WIRE = 0, | ||
204 | RF_OP_BY_FW, | ||
205 | RF_OP_MAX | ||
206 | }; | ||
207 | |||
208 | enum rf_power_state { | ||
209 | RF_ON, | ||
210 | RF_OFF, | ||
211 | RF_SLEEP, | ||
212 | RF_SHUT_DOWN, | ||
213 | }; | ||
214 | |||
215 | enum power_save_mode { | ||
216 | POWER_SAVE_MODE_ACTIVE, | ||
217 | POWER_SAVE_MODE_SAVE, | ||
218 | }; | ||
219 | |||
220 | enum power_polocy_config { | ||
221 | POWERCFG_MAX_POWER_SAVINGS, | ||
222 | POWERCFG_GLOBAL_POWER_SAVINGS, | ||
223 | POWERCFG_LOCAL_POWER_SAVINGS, | ||
224 | POWERCFG_LENOVO, | ||
225 | }; | ||
226 | |||
227 | enum interface_select_pci { | ||
228 | INTF_SEL1_MINICARD, | ||
229 | INTF_SEL0_PCIE, | ||
230 | INTF_SEL2_RSV, | ||
231 | INTF_SEL3_RSV, | ||
232 | }; | ||
233 | |||
234 | enum hal_fw_c2h_cmd_id { | ||
235 | HAL_FW_C2H_CMD_Read_MACREG, | ||
236 | HAL_FW_C2H_CMD_Read_BBREG, | ||
237 | HAL_FW_C2H_CMD_Read_RFREG, | ||
238 | HAL_FW_C2H_CMD_Read_EEPROM, | ||
239 | HAL_FW_C2H_CMD_Read_EFUSE, | ||
240 | HAL_FW_C2H_CMD_Read_CAM, | ||
241 | HAL_FW_C2H_CMD_Get_BasicRate, | ||
242 | HAL_FW_C2H_CMD_Get_DataRate, | ||
243 | HAL_FW_C2H_CMD_Survey, | ||
244 | HAL_FW_C2H_CMD_SurveyDone, | ||
245 | HAL_FW_C2H_CMD_JoinBss, | ||
246 | HAL_FW_C2H_CMD_AddSTA, | ||
247 | HAL_FW_C2H_CMD_DelSTA, | ||
248 | HAL_FW_C2H_CMD_AtimDone, | ||
249 | HAL_FW_C2H_CMD_TX_Report, | ||
250 | HAL_FW_C2H_CMD_CCX_Report, | ||
251 | HAL_FW_C2H_CMD_DTM_Report, | ||
252 | HAL_FW_C2H_CMD_TX_Rate_Statistics, | ||
253 | HAL_FW_C2H_CMD_C2HLBK, | ||
254 | HAL_FW_C2H_CMD_C2HDBG, | ||
255 | HAL_FW_C2H_CMD_C2HFEEDBACK, | ||
256 | HAL_FW_C2H_CMD_MAX | ||
257 | }; | ||
258 | |||
259 | enum wake_on_wlan_mode { | ||
260 | ewowlandisable, | ||
261 | ewakeonmagicpacketonly, | ||
262 | ewakeonpatternmatchonly, | ||
263 | ewakeonbothtypepacket | ||
264 | }; | ||
265 | |||
266 | enum rtl_desc_qsel { | ||
267 | QSLT_BK = 0x2, | ||
268 | QSLT_BE = 0x0, | ||
269 | QSLT_VI = 0x5, | ||
270 | QSLT_VO = 0x7, | ||
271 | QSLT_BEACON = 0x10, | ||
272 | QSLT_HIGH = 0x11, | ||
273 | QSLT_MGNT = 0x12, | ||
274 | QSLT_CMD = 0x13, | ||
275 | }; | ||
276 | |||
277 | enum rtl_desc92c_rate { | ||
278 | DESC92C_RATE1M = 0x00, | ||
279 | DESC92C_RATE2M = 0x01, | ||
280 | DESC92C_RATE5_5M = 0x02, | ||
281 | DESC92C_RATE11M = 0x03, | ||
282 | |||
283 | DESC92C_RATE6M = 0x04, | ||
284 | DESC92C_RATE9M = 0x05, | ||
285 | DESC92C_RATE12M = 0x06, | ||
286 | DESC92C_RATE18M = 0x07, | ||
287 | DESC92C_RATE24M = 0x08, | ||
288 | DESC92C_RATE36M = 0x09, | ||
289 | DESC92C_RATE48M = 0x0a, | ||
290 | DESC92C_RATE54M = 0x0b, | ||
291 | |||
292 | DESC92C_RATEMCS0 = 0x0c, | ||
293 | DESC92C_RATEMCS1 = 0x0d, | ||
294 | DESC92C_RATEMCS2 = 0x0e, | ||
295 | DESC92C_RATEMCS3 = 0x0f, | ||
296 | DESC92C_RATEMCS4 = 0x10, | ||
297 | DESC92C_RATEMCS5 = 0x11, | ||
298 | DESC92C_RATEMCS6 = 0x12, | ||
299 | DESC92C_RATEMCS7 = 0x13, | ||
300 | DESC92C_RATEMCS8 = 0x14, | ||
301 | DESC92C_RATEMCS9 = 0x15, | ||
302 | DESC92C_RATEMCS10 = 0x16, | ||
303 | DESC92C_RATEMCS11 = 0x17, | ||
304 | DESC92C_RATEMCS12 = 0x18, | ||
305 | DESC92C_RATEMCS13 = 0x19, | ||
306 | DESC92C_RATEMCS14 = 0x1a, | ||
307 | DESC92C_RATEMCS15 = 0x1b, | ||
308 | DESC92C_RATEMCS15_SG = 0x1c, | ||
309 | DESC92C_RATEMCS32 = 0x20, | ||
310 | }; | ||
311 | |||
312 | struct phy_sts_cck_8192s_t { | ||
313 | u8 adc_pwdb_X[4]; | ||
314 | u8 sq_rpt; | ||
315 | u8 cck_agc_rpt; | ||
316 | }; | ||
317 | |||
318 | struct h2c_cmd_8192c { | ||
319 | u8 element_id; | ||
320 | u32 cmd_len; | ||
321 | u8 *p_cmdbuffer; | ||
322 | }; | ||
323 | |||
324 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c new file mode 100644 index 000000000000..21a5cf060677 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c | |||
@@ -0,0 +1,1794 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "../wifi.h" | ||
31 | #include "../base.h" | ||
32 | #include "../pci.h" | ||
33 | #include "reg.h" | ||
34 | #include "def.h" | ||
35 | #include "phy.h" | ||
36 | #include "dm.h" | ||
37 | #include "fw.h" | ||
38 | #include "trx.h" | ||
39 | |||
40 | static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = { | ||
41 | 0x7f8001fe, /* 0, +6.0dB */ | ||
42 | 0x788001e2, /* 1, +5.5dB */ | ||
43 | 0x71c001c7, /* 2, +5.0dB */ | ||
44 | 0x6b8001ae, /* 3, +4.5dB */ | ||
45 | 0x65400195, /* 4, +4.0dB */ | ||
46 | 0x5fc0017f, /* 5, +3.5dB */ | ||
47 | 0x5a400169, /* 6, +3.0dB */ | ||
48 | 0x55400155, /* 7, +2.5dB */ | ||
49 | 0x50800142, /* 8, +2.0dB */ | ||
50 | 0x4c000130, /* 9, +1.5dB */ | ||
51 | 0x47c0011f, /* 10, +1.0dB */ | ||
52 | 0x43c0010f, /* 11, +0.5dB */ | ||
53 | 0x40000100, /* 12, +0dB */ | ||
54 | 0x3c8000f2, /* 13, -0.5dB */ | ||
55 | 0x390000e4, /* 14, -1.0dB */ | ||
56 | 0x35c000d7, /* 15, -1.5dB */ | ||
57 | 0x32c000cb, /* 16, -2.0dB */ | ||
58 | 0x300000c0, /* 17, -2.5dB */ | ||
59 | 0x2d4000b5, /* 18, -3.0dB */ | ||
60 | 0x2ac000ab, /* 19, -3.5dB */ | ||
61 | 0x288000a2, /* 20, -4.0dB */ | ||
62 | 0x26000098, /* 21, -4.5dB */ | ||
63 | 0x24000090, /* 22, -5.0dB */ | ||
64 | 0x22000088, /* 23, -5.5dB */ | ||
65 | 0x20000080, /* 24, -6.0dB */ | ||
66 | 0x1e400079, /* 25, -6.5dB */ | ||
67 | 0x1c800072, /* 26, -7.0dB */ | ||
68 | 0x1b00006c, /* 27. -7.5dB */ | ||
69 | 0x19800066, /* 28, -8.0dB */ | ||
70 | 0x18000060, /* 29, -8.5dB */ | ||
71 | 0x16c0005b, /* 30, -9.0dB */ | ||
72 | 0x15800056, /* 31, -9.5dB */ | ||
73 | 0x14400051, /* 32, -10.0dB */ | ||
74 | 0x1300004c, /* 33, -10.5dB */ | ||
75 | 0x12000048, /* 34, -11.0dB */ | ||
76 | 0x11000044, /* 35, -11.5dB */ | ||
77 | 0x10000040, /* 36, -12.0dB */ | ||
78 | 0x0f00003c, /* 37, -12.5dB */ | ||
79 | 0x0e400039, /* 38, -13.0dB */ | ||
80 | 0x0d800036, /* 39, -13.5dB */ | ||
81 | 0x0cc00033, /* 40, -14.0dB */ | ||
82 | 0x0c000030, /* 41, -14.5dB */ | ||
83 | 0x0b40002d, /* 42, -15.0dB */ | ||
84 | }; | ||
85 | |||
86 | static const u8 cck_tbl_ch1_13[CCK_TABLE_SIZE][8] = { | ||
87 | {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0dB */ | ||
88 | {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 1, -0.5dB */ | ||
89 | {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 2, -1.0dB */ | ||
90 | {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 3, -1.5dB */ | ||
91 | {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 4, -2.0dB */ | ||
92 | {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 5, -2.5dB */ | ||
93 | {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 6, -3.0dB */ | ||
94 | {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 7, -3.5dB */ | ||
95 | {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 8, -4.0dB */ | ||
96 | {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 9, -4.5dB */ | ||
97 | {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 10, -5.0dB */ | ||
98 | {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 11, -5.5dB */ | ||
99 | {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 12, -6.0dB */ | ||
100 | {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 13, -6.5dB */ | ||
101 | {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 14, -7.0dB */ | ||
102 | {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 15, -7.5dB */ | ||
103 | {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */ | ||
104 | {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 17, -8.5dB */ | ||
105 | {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 18, -9.0dB */ | ||
106 | {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 19, -9.5dB */ | ||
107 | {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 20, -10.0dB*/ | ||
108 | {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 21, -10.5dB*/ | ||
109 | {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 22, -11.0dB*/ | ||
110 | {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 23, -11.5dB*/ | ||
111 | {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 24, -12.0dB*/ | ||
112 | {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 25, -12.5dB*/ | ||
113 | {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 26, -13.0dB*/ | ||
114 | {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 27, -13.5dB*/ | ||
115 | {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 28, -14.0dB*/ | ||
116 | {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 29, -14.5dB*/ | ||
117 | {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 30, -15.0dB*/ | ||
118 | {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 31, -15.5dB*/ | ||
119 | {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} /* 32, -16.0dB*/ | ||
120 | }; | ||
121 | |||
122 | static const u8 cck_tbl_ch14[CCK_TABLE_SIZE][8] = { | ||
123 | {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, /* 0, +0dB */ | ||
124 | {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 1, -0.5dB */ | ||
125 | {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 2, -1.0dB */ | ||
126 | {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 3, -1.5dB */ | ||
127 | {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 4, -2.0dB */ | ||
128 | {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 5, -2.5dB */ | ||
129 | {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 6, -3.0dB */ | ||
130 | {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 7, -3.5dB */ | ||
131 | {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 8, -4.0dB */ | ||
132 | {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 9, -4.5dB */ | ||
133 | {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 10, -5.0dB */ | ||
134 | {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 11, -5.5dB */ | ||
135 | {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 12, -6.0dB */ | ||
136 | {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 13, -6.5dB */ | ||
137 | {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 14, -7.0dB */ | ||
138 | {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 15, -7.5dB */ | ||
139 | {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */ | ||
140 | {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 17, -8.5dB */ | ||
141 | {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 18, -9.0dB */ | ||
142 | {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 19, -9.5dB */ | ||
143 | {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 20, -10.0dB*/ | ||
144 | {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 21, -10.5dB*/ | ||
145 | {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 22, -11.0dB*/ | ||
146 | {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 23, -11.5dB*/ | ||
147 | {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 24, -12.0dB*/ | ||
148 | {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 25, -12.5dB*/ | ||
149 | {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 26, -13.0dB*/ | ||
150 | {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 27, -13.5dB*/ | ||
151 | {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 28, -14.0dB*/ | ||
152 | {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 29, -14.5dB*/ | ||
153 | {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 30, -15.0dB*/ | ||
154 | {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 31, -15.5dB*/ | ||
155 | {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} /* 32, -16.0dB*/ | ||
156 | }; | ||
157 | |||
158 | #define CAL_SWING_OFF(_off, _dir, _size, _del) \ | ||
159 | do { \ | ||
160 | for (_off = 0; _off < _size; _off++) { \ | ||
161 | if (_del < thermal_threshold[_dir][_off]) { \ | ||
162 | if (_off != 0) \ | ||
163 | _off--; \ | ||
164 | break; \ | ||
165 | } \ | ||
166 | } \ | ||
167 | if (_off >= _size) \ | ||
168 | _off = _size - 1; \ | ||
169 | } while (0) | ||
170 | |||
171 | static void rtl88e_set_iqk_matrix(struct ieee80211_hw *hw, | ||
172 | u8 ofdm_index, u8 rfpath, | ||
173 | long iqk_result_x, long iqk_result_y) | ||
174 | { | ||
175 | long ele_a = 0, ele_d, ele_c = 0, value32; | ||
176 | |||
177 | ele_d = (ofdmswing_table[ofdm_index] & 0xFFC00000)>>22; | ||
178 | |||
179 | if (iqk_result_x != 0) { | ||
180 | if ((iqk_result_x & 0x00000200) != 0) | ||
181 | iqk_result_x = iqk_result_x | 0xFFFFFC00; | ||
182 | ele_a = ((iqk_result_x * ele_d)>>8)&0x000003FF; | ||
183 | |||
184 | if ((iqk_result_y & 0x00000200) != 0) | ||
185 | iqk_result_y = iqk_result_y | 0xFFFFFC00; | ||
186 | ele_c = ((iqk_result_y * ele_d)>>8)&0x000003FF; | ||
187 | |||
188 | switch (rfpath) { | ||
189 | case RF90_PATH_A: | ||
190 | value32 = (ele_d << 22)|((ele_c & 0x3F)<<16) | ele_a; | ||
191 | rtl_set_bbreg(hw, ROFDM0_XATXIQIMBAL, MASKDWORD, | ||
192 | value32); | ||
193 | value32 = (ele_c & 0x000003C0) >> 6; | ||
194 | rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, value32); | ||
195 | value32 = ((iqk_result_x * ele_d) >> 7) & 0x01; | ||
196 | rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(24), value32); | ||
197 | break; | ||
198 | case RF90_PATH_B: | ||
199 | value32 = (ele_d << 22)|((ele_c & 0x3F)<<16) | ele_a; | ||
200 | rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBAL, | ||
201 | MASKDWORD, value32); | ||
202 | value32 = (ele_c & 0x000003C0) >> 6; | ||
203 | rtl_set_bbreg(hw, ROFDM0_XDTXAFE, MASKH4BITS, value32); | ||
204 | value32 = ((iqk_result_x * ele_d) >> 7) & 0x01; | ||
205 | rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(28), value32); | ||
206 | break; | ||
207 | default: | ||
208 | break; | ||
209 | } | ||
210 | } else { | ||
211 | switch (rfpath) { | ||
212 | case RF90_PATH_A: | ||
213 | rtl_set_bbreg(hw, ROFDM0_XATXIQIMBAL, MASKDWORD, | ||
214 | ofdmswing_table[ofdm_index]); | ||
215 | rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, 0x00); | ||
216 | rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(24), 0x00); | ||
217 | break; | ||
218 | case RF90_PATH_B: | ||
219 | rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBAL, MASKDWORD, | ||
220 | ofdmswing_table[ofdm_index]); | ||
221 | rtl_set_bbreg(hw, ROFDM0_XDTXAFE, MASKH4BITS, 0x00); | ||
222 | rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(28), 0x00); | ||
223 | break; | ||
224 | default: | ||
225 | break; | ||
226 | } | ||
227 | } | ||
228 | } | ||
229 | |||
230 | void rtl88e_dm_txpower_track_adjust(struct ieee80211_hw *hw, | ||
231 | u8 type, u8 *pdirection, u32 *poutwrite_val) | ||
232 | { | ||
233 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
234 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
235 | u8 pwr_val = 0; | ||
236 | u8 cck_base = rtldm->swing_idx_cck_base; | ||
237 | u8 cck_val = rtldm->swing_idx_cck; | ||
238 | u8 ofdm_base = rtldm->swing_idx_ofdm_base; | ||
239 | u8 ofdm_val = rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A]; | ||
240 | |||
241 | if (type == 0) { | ||
242 | if (ofdm_val <= ofdm_base) { | ||
243 | *pdirection = 1; | ||
244 | pwr_val = ofdm_base - ofdm_val; | ||
245 | } else { | ||
246 | *pdirection = 2; | ||
247 | pwr_val = ofdm_val - ofdm_base; | ||
248 | } | ||
249 | } else if (type == 1) { | ||
250 | if (cck_val <= cck_base) { | ||
251 | *pdirection = 1; | ||
252 | pwr_val = cck_base - cck_val; | ||
253 | } else { | ||
254 | *pdirection = 2; | ||
255 | pwr_val = cck_val - cck_base; | ||
256 | } | ||
257 | } | ||
258 | |||
259 | if (pwr_val >= TXPWRTRACK_MAX_IDX && (*pdirection == 1)) | ||
260 | pwr_val = TXPWRTRACK_MAX_IDX; | ||
261 | |||
262 | *poutwrite_val = pwr_val | (pwr_val << 8) | (pwr_val << 16) | | ||
263 | (pwr_val << 24); | ||
264 | } | ||
265 | |||
266 | |||
267 | static void rtl88e_chk_tx_track(struct ieee80211_hw *hw, | ||
268 | enum pwr_track_control_method method, | ||
269 | u8 rfpath, u8 index) | ||
270 | { | ||
271 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
272 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
273 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
274 | int jj = rtldm->swing_idx_cck; | ||
275 | int i; | ||
276 | |||
277 | if (method == TXAGC) { | ||
278 | if (rtldm->swing_flag_ofdm == true || | ||
279 | rtldm->swing_flag_cck == true) { | ||
280 | u8 chan = rtlphy->current_channel; | ||
281 | rtl88e_phy_set_txpower_level(hw, chan); | ||
282 | rtldm->swing_flag_ofdm = false; | ||
283 | rtldm->swing_flag_cck = false; | ||
284 | } | ||
285 | } else if (method == BBSWING) { | ||
286 | if (!rtldm->cck_inch14) { | ||
287 | for (i = 0; i < 8; i++) | ||
288 | rtl_write_byte(rtlpriv, 0xa22 + i, | ||
289 | cck_tbl_ch1_13[jj][i]); | ||
290 | } else { | ||
291 | for (i = 0; i < 8; i++) | ||
292 | rtl_write_byte(rtlpriv, 0xa22 + i, | ||
293 | cck_tbl_ch14[jj][i]); | ||
294 | } | ||
295 | |||
296 | if (rfpath == RF90_PATH_A) { | ||
297 | long x = rtlphy->iqk_matrix[index].value[0][0]; | ||
298 | long y = rtlphy->iqk_matrix[index].value[0][1]; | ||
299 | u8 indx = rtldm->swing_idx_ofdm[rfpath]; | ||
300 | rtl88e_set_iqk_matrix(hw, indx, rfpath, x, y); | ||
301 | } else if (rfpath == RF90_PATH_B) { | ||
302 | u8 indx = rtldm->swing_idx_ofdm[rfpath]; | ||
303 | long x = rtlphy->iqk_matrix[indx].value[0][4]; | ||
304 | long y = rtlphy->iqk_matrix[indx].value[0][5]; | ||
305 | rtl88e_set_iqk_matrix(hw, indx, rfpath, x, y); | ||
306 | } | ||
307 | } else { | ||
308 | return; | ||
309 | } | ||
310 | } | ||
311 | |||
312 | static void rtl88e_dm_diginit(struct ieee80211_hw *hw) | ||
313 | { | ||
314 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
315 | struct dig_t *dm_dig = &rtlpriv->dm_digtable; | ||
316 | |||
317 | dm_dig->dig_enable_flag = true; | ||
318 | dm_dig->cur_igvalue = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f); | ||
319 | dm_dig->pre_igvalue = 0; | ||
320 | dm_dig->cursta_cstate = DIG_STA_DISCONNECT; | ||
321 | dm_dig->presta_cstate = DIG_STA_DISCONNECT; | ||
322 | dm_dig->curmultista_cstate = DIG_MULTISTA_DISCONNECT; | ||
323 | dm_dig->rssi_lowthresh = DM_DIG_THRESH_LOW; | ||
324 | dm_dig->rssi_highthresh = DM_DIG_THRESH_HIGH; | ||
325 | dm_dig->fa_lowthresh = DM_FALSEALARM_THRESH_LOW; | ||
326 | dm_dig->fa_highthresh = DM_FALSEALARM_THRESH_HIGH; | ||
327 | dm_dig->rx_gain_max = DM_DIG_MAX; | ||
328 | dm_dig->rx_gain_min = DM_DIG_MIN; | ||
329 | dm_dig->back_val = DM_DIG_BACKOFF_DEFAULT; | ||
330 | dm_dig->back_range_max = DM_DIG_BACKOFF_MAX; | ||
331 | dm_dig->back_range_min = DM_DIG_BACKOFF_MIN; | ||
332 | dm_dig->pre_cck_cca_thres = 0xff; | ||
333 | dm_dig->cur_cck_cca_thres = 0x83; | ||
334 | dm_dig->forbidden_igi = DM_DIG_MIN; | ||
335 | dm_dig->large_fa_hit = 0; | ||
336 | dm_dig->recover_cnt = 0; | ||
337 | dm_dig->dig_min_0 = 0x25; | ||
338 | dm_dig->dig_min_1 = 0x25; | ||
339 | dm_dig->media_connect_0 = false; | ||
340 | dm_dig->media_connect_1 = false; | ||
341 | rtlpriv->dm.dm_initialgain_enable = true; | ||
342 | } | ||
343 | |||
344 | static u8 rtl88e_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw) | ||
345 | { | ||
346 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
347 | struct dig_t *dm_dig = &rtlpriv->dm_digtable; | ||
348 | long rssi_val_min = 0; | ||
349 | |||
350 | if ((dm_dig->curmultista_cstate == DIG_MULTISTA_CONNECT) && | ||
351 | (dm_dig->cursta_cstate == DIG_STA_CONNECT)) { | ||
352 | if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0) | ||
353 | rssi_val_min = | ||
354 | (rtlpriv->dm.entry_min_undec_sm_pwdb > | ||
355 | rtlpriv->dm.undec_sm_pwdb) ? | ||
356 | rtlpriv->dm.undec_sm_pwdb : | ||
357 | rtlpriv->dm.entry_min_undec_sm_pwdb; | ||
358 | else | ||
359 | rssi_val_min = rtlpriv->dm.undec_sm_pwdb; | ||
360 | } else if (dm_dig->cursta_cstate == DIG_STA_CONNECT || | ||
361 | dm_dig->cursta_cstate == DIG_STA_BEFORE_CONNECT) { | ||
362 | rssi_val_min = rtlpriv->dm.undec_sm_pwdb; | ||
363 | } else if (dm_dig->curmultista_cstate == | ||
364 | DIG_MULTISTA_CONNECT) { | ||
365 | rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb; | ||
366 | } | ||
367 | return (u8)rssi_val_min; | ||
368 | } | ||
369 | |||
370 | static void rtl88e_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) | ||
371 | { | ||
372 | u32 ret_value; | ||
373 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
374 | struct false_alarm_statistics *alm_cnt = &(rtlpriv->falsealm_cnt); | ||
375 | |||
376 | rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 1); | ||
377 | rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 1); | ||
378 | |||
379 | ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, MASKDWORD); | ||
380 | alm_cnt->cnt_fast_fsync_fail = (ret_value&0xffff); | ||
381 | alm_cnt->cnt_sb_search_fail = ((ret_value&0xffff0000)>>16); | ||
382 | |||
383 | ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD); | ||
384 | alm_cnt->cnt_ofdm_cca = (ret_value&0xffff); | ||
385 | alm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16); | ||
386 | |||
387 | ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD); | ||
388 | alm_cnt->cnt_rate_illegal = (ret_value & 0xffff); | ||
389 | alm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16); | ||
390 | |||
391 | ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD); | ||
392 | alm_cnt->cnt_mcs_fail = (ret_value & 0xffff); | ||
393 | alm_cnt->cnt_ofdm_fail = alm_cnt->cnt_parity_fail + | ||
394 | alm_cnt->cnt_rate_illegal + | ||
395 | alm_cnt->cnt_crc8_fail + | ||
396 | alm_cnt->cnt_mcs_fail + | ||
397 | alm_cnt->cnt_fast_fsync_fail + | ||
398 | alm_cnt->cnt_sb_search_fail; | ||
399 | |||
400 | ret_value = rtl_get_bbreg(hw, REG_SC_CNT, MASKDWORD); | ||
401 | alm_cnt->cnt_bw_lsc = (ret_value & 0xffff); | ||
402 | alm_cnt->cnt_bw_usc = ((ret_value & 0xffff0000) >> 16); | ||
403 | |||
404 | rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(12), 1); | ||
405 | rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1); | ||
406 | |||
407 | ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0); | ||
408 | alm_cnt->cnt_cck_fail = ret_value; | ||
409 | |||
410 | ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3); | ||
411 | alm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8; | ||
412 | |||
413 | ret_value = rtl_get_bbreg(hw, RCCK0_CCA_CNT, MASKDWORD); | ||
414 | alm_cnt->cnt_cck_cca = ((ret_value & 0xff) << 8) | | ||
415 | ((ret_value&0xFF00)>>8); | ||
416 | |||
417 | alm_cnt->cnt_all = alm_cnt->cnt_fast_fsync_fail + | ||
418 | alm_cnt->cnt_sb_search_fail + | ||
419 | alm_cnt->cnt_parity_fail + | ||
420 | alm_cnt->cnt_rate_illegal + | ||
421 | alm_cnt->cnt_crc8_fail + | ||
422 | alm_cnt->cnt_mcs_fail + | ||
423 | alm_cnt->cnt_cck_fail; | ||
424 | alm_cnt->cnt_cca_all = alm_cnt->cnt_ofdm_cca + alm_cnt->cnt_cck_cca; | ||
425 | |||
426 | rtl_set_bbreg(hw, ROFDM0_TRSWISOLATION, BIT(31), 1); | ||
427 | rtl_set_bbreg(hw, ROFDM0_TRSWISOLATION, BIT(31), 0); | ||
428 | rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(27), 1); | ||
429 | rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(27), 0); | ||
430 | rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 0); | ||
431 | rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 0); | ||
432 | rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(13)|BIT(12), 0); | ||
433 | rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(13)|BIT(12), 2); | ||
434 | rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(15)|BIT(14), 0); | ||
435 | rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(15)|BIT(14), 2); | ||
436 | |||
437 | RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, | ||
438 | "cnt_parity_fail = %d, cnt_rate_illegal = %d, " | ||
439 | "cnt_crc8_fail = %d, cnt_mcs_fail = %d\n", | ||
440 | alm_cnt->cnt_parity_fail, | ||
441 | alm_cnt->cnt_rate_illegal, | ||
442 | alm_cnt->cnt_crc8_fail, alm_cnt->cnt_mcs_fail); | ||
443 | |||
444 | RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, | ||
445 | "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n", | ||
446 | alm_cnt->cnt_ofdm_fail, | ||
447 | alm_cnt->cnt_cck_fail, alm_cnt->cnt_all); | ||
448 | } | ||
449 | |||
450 | static void rtl88e_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) | ||
451 | { | ||
452 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
453 | struct dig_t *dm_dig = &rtlpriv->dm_digtable; | ||
454 | u8 cur_cck_cca_thresh; | ||
455 | |||
456 | if (dm_dig->cursta_cstate == DIG_STA_CONNECT) { | ||
457 | dm_dig->rssi_val_min = rtl88e_dm_initial_gain_min_pwdb(hw); | ||
458 | if (dm_dig->rssi_val_min > 25) { | ||
459 | cur_cck_cca_thresh = 0xcd; | ||
460 | } else if ((dm_dig->rssi_val_min <= 25) && | ||
461 | (dm_dig->rssi_val_min > 10)) { | ||
462 | cur_cck_cca_thresh = 0x83; | ||
463 | } else { | ||
464 | if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000) | ||
465 | cur_cck_cca_thresh = 0x83; | ||
466 | else | ||
467 | cur_cck_cca_thresh = 0x40; | ||
468 | } | ||
469 | |||
470 | } else { | ||
471 | if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000) | ||
472 | cur_cck_cca_thresh = 0x83; | ||
473 | else | ||
474 | cur_cck_cca_thresh = 0x40; | ||
475 | } | ||
476 | |||
477 | if (dm_dig->cur_cck_cca_thres != cur_cck_cca_thresh) | ||
478 | rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, cur_cck_cca_thresh); | ||
479 | |||
480 | dm_dig->cur_cck_cca_thres = cur_cck_cca_thresh; | ||
481 | dm_dig->pre_cck_cca_thres = dm_dig->cur_cck_cca_thres; | ||
482 | RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, | ||
483 | "CCK cca thresh hold =%x\n", dm_dig->cur_cck_cca_thres); | ||
484 | } | ||
485 | |||
486 | static void rtl88e_dm_dig(struct ieee80211_hw *hw) | ||
487 | { | ||
488 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
489 | struct dig_t *dm_dig = &rtlpriv->dm_digtable; | ||
490 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
491 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
492 | u8 dig_min, dig_maxofmin; | ||
493 | bool bfirstconnect; | ||
494 | u8 dm_dig_max, dm_dig_min; | ||
495 | u8 current_igi = dm_dig->cur_igvalue; | ||
496 | |||
497 | if (rtlpriv->dm.dm_initialgain_enable == false) | ||
498 | return; | ||
499 | if (dm_dig->dig_enable_flag == false) | ||
500 | return; | ||
501 | if (mac->act_scanning == true) | ||
502 | return; | ||
503 | |||
504 | if (mac->link_state >= MAC80211_LINKED) | ||
505 | dm_dig->cursta_cstate = DIG_STA_CONNECT; | ||
506 | else | ||
507 | dm_dig->cursta_cstate = DIG_STA_DISCONNECT; | ||
508 | if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP || | ||
509 | rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) | ||
510 | dm_dig->cursta_cstate = DIG_STA_DISCONNECT; | ||
511 | |||
512 | dm_dig_max = DM_DIG_MAX; | ||
513 | dm_dig_min = DM_DIG_MIN; | ||
514 | dig_maxofmin = DM_DIG_MAX_AP; | ||
515 | dig_min = dm_dig->dig_min_0; | ||
516 | bfirstconnect = ((mac->link_state >= MAC80211_LINKED) ? true : false) && | ||
517 | (dm_dig->media_connect_0 == false); | ||
518 | |||
519 | dm_dig->rssi_val_min = | ||
520 | rtl88e_dm_initial_gain_min_pwdb(hw); | ||
521 | |||
522 | if (mac->link_state >= MAC80211_LINKED) { | ||
523 | if ((dm_dig->rssi_val_min + 20) > dm_dig_max) | ||
524 | dm_dig->rx_gain_max = dm_dig_max; | ||
525 | else if ((dm_dig->rssi_val_min + 20) < dm_dig_min) | ||
526 | dm_dig->rx_gain_max = dm_dig_min; | ||
527 | else | ||
528 | dm_dig->rx_gain_max = dm_dig->rssi_val_min + 20; | ||
529 | |||
530 | if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) { | ||
531 | dig_min = dm_dig->antdiv_rssi_max; | ||
532 | } else { | ||
533 | if (dm_dig->rssi_val_min < dm_dig_min) | ||
534 | dig_min = dm_dig_min; | ||
535 | else if (dm_dig->rssi_val_min < dig_maxofmin) | ||
536 | dig_min = dig_maxofmin; | ||
537 | else | ||
538 | dig_min = dm_dig->rssi_val_min; | ||
539 | } | ||
540 | } else { | ||
541 | dm_dig->rx_gain_max = dm_dig_max; | ||
542 | dig_min = dm_dig_min; | ||
543 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "no link\n"); | ||
544 | } | ||
545 | |||
546 | if (rtlpriv->falsealm_cnt.cnt_all > 10000) { | ||
547 | dm_dig->large_fa_hit++; | ||
548 | if (dm_dig->forbidden_igi < current_igi) { | ||
549 | dm_dig->forbidden_igi = current_igi; | ||
550 | dm_dig->large_fa_hit = 1; | ||
551 | } | ||
552 | |||
553 | if (dm_dig->large_fa_hit >= 3) { | ||
554 | if ((dm_dig->forbidden_igi + 1) > dm_dig->rx_gain_max) | ||
555 | dm_dig->rx_gain_min = dm_dig->rx_gain_max; | ||
556 | else | ||
557 | dm_dig->rx_gain_min = dm_dig->forbidden_igi + 1; | ||
558 | dm_dig->recover_cnt = 3600; | ||
559 | } | ||
560 | } else { | ||
561 | if (dm_dig->recover_cnt != 0) { | ||
562 | dm_dig->recover_cnt--; | ||
563 | } else { | ||
564 | if (dm_dig->large_fa_hit == 0) { | ||
565 | if ((dm_dig->forbidden_igi - 1) < dig_min) { | ||
566 | dm_dig->forbidden_igi = dig_min; | ||
567 | dm_dig->rx_gain_min = dig_min; | ||
568 | } else { | ||
569 | dm_dig->forbidden_igi--; | ||
570 | dm_dig->rx_gain_min = | ||
571 | dm_dig->forbidden_igi + 1; | ||
572 | } | ||
573 | } else if (dm_dig->large_fa_hit == 3) { | ||
574 | dm_dig->large_fa_hit = 0; | ||
575 | } | ||
576 | } | ||
577 | } | ||
578 | |||
579 | if (dm_dig->cursta_cstate == DIG_STA_CONNECT) { | ||
580 | if (bfirstconnect) { | ||
581 | current_igi = dm_dig->rssi_val_min; | ||
582 | } else { | ||
583 | if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2) | ||
584 | current_igi += 2; | ||
585 | else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1) | ||
586 | current_igi++; | ||
587 | else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0) | ||
588 | current_igi--; | ||
589 | } | ||
590 | } else { | ||
591 | if (rtlpriv->falsealm_cnt.cnt_all > 10000) | ||
592 | current_igi += 2; | ||
593 | else if (rtlpriv->falsealm_cnt.cnt_all > 8000) | ||
594 | current_igi++; | ||
595 | else if (rtlpriv->falsealm_cnt.cnt_all < 500) | ||
596 | current_igi--; | ||
597 | } | ||
598 | |||
599 | if (current_igi > DM_DIG_FA_UPPER) | ||
600 | current_igi = DM_DIG_FA_UPPER; | ||
601 | else if (current_igi < DM_DIG_FA_LOWER) | ||
602 | current_igi = DM_DIG_FA_LOWER; | ||
603 | |||
604 | if (rtlpriv->falsealm_cnt.cnt_all > 10000) | ||
605 | current_igi = DM_DIG_FA_UPPER; | ||
606 | |||
607 | dm_dig->cur_igvalue = current_igi; | ||
608 | rtl88e_dm_write_dig(hw); | ||
609 | dm_dig->media_connect_0 = ((mac->link_state >= MAC80211_LINKED) ? | ||
610 | true : false); | ||
611 | dm_dig->dig_min_0 = dig_min; | ||
612 | |||
613 | rtl88e_dm_cck_packet_detection_thresh(hw); | ||
614 | } | ||
615 | |||
616 | static void rtl88e_dm_init_dynamic_txpower(struct ieee80211_hw *hw) | ||
617 | { | ||
618 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
619 | |||
620 | rtlpriv->dm.dynamic_txpower_enable = false; | ||
621 | |||
622 | rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; | ||
623 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; | ||
624 | } | ||
625 | |||
626 | static void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw) | ||
627 | { | ||
628 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
629 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
630 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
631 | long undec_sm_pwdb; | ||
632 | |||
633 | if (!rtlpriv->dm.dynamic_txpower_enable) | ||
634 | return; | ||
635 | |||
636 | if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { | ||
637 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; | ||
638 | return; | ||
639 | } | ||
640 | |||
641 | if ((mac->link_state < MAC80211_LINKED) && | ||
642 | (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { | ||
643 | RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, | ||
644 | "Not connected\n"); | ||
645 | |||
646 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; | ||
647 | |||
648 | rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; | ||
649 | return; | ||
650 | } | ||
651 | |||
652 | if (mac->link_state >= MAC80211_LINKED) { | ||
653 | if (mac->opmode == NL80211_IFTYPE_ADHOC) { | ||
654 | undec_sm_pwdb = | ||
655 | rtlpriv->dm.entry_min_undec_sm_pwdb; | ||
656 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
657 | "AP Client PWDB = 0x%lx\n", | ||
658 | undec_sm_pwdb); | ||
659 | } else { | ||
660 | undec_sm_pwdb = | ||
661 | rtlpriv->dm.undec_sm_pwdb; | ||
662 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
663 | "STA Default Port PWDB = 0x%lx\n", | ||
664 | undec_sm_pwdb); | ||
665 | } | ||
666 | } else { | ||
667 | undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; | ||
668 | |||
669 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
670 | "AP Ext Port PWDB = 0x%lx\n", undec_sm_pwdb); | ||
671 | } | ||
672 | |||
673 | if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { | ||
674 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; | ||
675 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
676 | "TXHIGHPWRLEVEL_LEVEL1 (TxPwr = 0x0)\n"); | ||
677 | } else if ((undec_sm_pwdb < | ||
678 | (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && | ||
679 | (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) { | ||
680 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; | ||
681 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
682 | "TXHIGHPWRLEVEL_LEVEL1 (TxPwr = 0x10)\n"); | ||
683 | } else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { | ||
684 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; | ||
685 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
686 | "TXHIGHPWRLEVEL_NORMAL\n"); | ||
687 | } | ||
688 | |||
689 | if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) { | ||
690 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
691 | "PHY_SetTxPowerLevel8192S() Channel = %d\n", | ||
692 | rtlphy->current_channel); | ||
693 | rtl88e_phy_set_txpower_level(hw, rtlphy->current_channel); | ||
694 | } | ||
695 | |||
696 | rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; | ||
697 | } | ||
698 | |||
699 | void rtl88e_dm_write_dig(struct ieee80211_hw *hw) | ||
700 | { | ||
701 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
702 | struct dig_t *dm_dig = &rtlpriv->dm_digtable; | ||
703 | |||
704 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, | ||
705 | "cur_igvalue = 0x%x, " | ||
706 | "pre_igvalue = 0x%x, back_val = %d\n", | ||
707 | dm_dig->cur_igvalue, dm_dig->pre_igvalue, | ||
708 | dm_dig->back_val); | ||
709 | |||
710 | if (dm_dig->cur_igvalue > 0x3f) | ||
711 | dm_dig->cur_igvalue = 0x3f; | ||
712 | if (dm_dig->pre_igvalue != dm_dig->cur_igvalue) { | ||
713 | rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, | ||
714 | dm_dig->cur_igvalue); | ||
715 | |||
716 | dm_dig->pre_igvalue = dm_dig->cur_igvalue; | ||
717 | } | ||
718 | } | ||
719 | |||
720 | static void rtl88e_dm_pwdb_monitor(struct ieee80211_hw *hw) | ||
721 | { | ||
722 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
723 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
724 | struct rtl_sta_info *drv_priv; | ||
725 | static u64 last_txok; | ||
726 | static u64 last_rx; | ||
727 | long tmp_entry_max_pwdb = 0, tmp_entry_min_pwdb = 0xff; | ||
728 | |||
729 | if (rtlhal->oem_id == RT_CID_819x_HP) { | ||
730 | u64 cur_txok_cnt = 0; | ||
731 | u64 cur_rxok_cnt = 0; | ||
732 | cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok; | ||
733 | cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rx; | ||
734 | last_txok = cur_txok_cnt; | ||
735 | last_rx = cur_rxok_cnt; | ||
736 | |||
737 | if (cur_rxok_cnt > (cur_txok_cnt * 6)) | ||
738 | rtl_write_dword(rtlpriv, REG_ARFR0, 0x8f015); | ||
739 | else | ||
740 | rtl_write_dword(rtlpriv, REG_ARFR0, 0xff015); | ||
741 | } | ||
742 | |||
743 | /* AP & ADHOC & MESH */ | ||
744 | spin_lock_bh(&rtlpriv->locks.entry_list_lock); | ||
745 | list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) { | ||
746 | if (drv_priv->rssi_stat.undec_sm_pwdb < tmp_entry_min_pwdb) | ||
747 | tmp_entry_min_pwdb = drv_priv->rssi_stat.undec_sm_pwdb; | ||
748 | if (drv_priv->rssi_stat.undec_sm_pwdb > tmp_entry_max_pwdb) | ||
749 | tmp_entry_max_pwdb = drv_priv->rssi_stat.undec_sm_pwdb; | ||
750 | } | ||
751 | spin_unlock_bh(&rtlpriv->locks.entry_list_lock); | ||
752 | |||
753 | /* If associated entry is found */ | ||
754 | if (tmp_entry_max_pwdb != 0) { | ||
755 | rtlpriv->dm.entry_max_undec_sm_pwdb = tmp_entry_max_pwdb; | ||
756 | RTPRINT(rtlpriv, FDM, DM_PWDB, "EntryMaxPWDB = 0x%lx(%ld)\n", | ||
757 | tmp_entry_max_pwdb, tmp_entry_max_pwdb); | ||
758 | } else { | ||
759 | rtlpriv->dm.entry_max_undec_sm_pwdb = 0; | ||
760 | } | ||
761 | /* If associated entry is found */ | ||
762 | if (tmp_entry_min_pwdb != 0xff) { | ||
763 | rtlpriv->dm.entry_min_undec_sm_pwdb = tmp_entry_min_pwdb; | ||
764 | RTPRINT(rtlpriv, FDM, DM_PWDB, "EntryMinPWDB = 0x%lx(%ld)\n", | ||
765 | tmp_entry_min_pwdb, tmp_entry_min_pwdb); | ||
766 | } else { | ||
767 | rtlpriv->dm.entry_min_undec_sm_pwdb = 0; | ||
768 | } | ||
769 | /* Indicate Rx signal strength to FW. */ | ||
770 | if (!rtlpriv->dm.useramask) | ||
771 | rtl_write_byte(rtlpriv, 0x4fe, rtlpriv->dm.undec_sm_pwdb); | ||
772 | } | ||
773 | |||
774 | void rtl88e_dm_init_edca_turbo(struct ieee80211_hw *hw) | ||
775 | { | ||
776 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
777 | |||
778 | rtlpriv->dm.current_turbo_edca = false; | ||
779 | rtlpriv->dm.is_any_nonbepkts = false; | ||
780 | rtlpriv->dm.is_cur_rdlstate = false; | ||
781 | } | ||
782 | |||
783 | static void rtl88e_dm_check_edca_turbo(struct ieee80211_hw *hw) | ||
784 | { | ||
785 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
786 | struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); | ||
787 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
788 | static u64 last_txok_cnt; | ||
789 | static u64 last_rxok_cnt; | ||
790 | static u32 last_bt_edca_ul; | ||
791 | static u32 last_bt_edca_dl; | ||
792 | u64 cur_txok_cnt = 0; | ||
793 | u64 cur_rxok_cnt = 0; | ||
794 | u32 edca_be_ul = 0x5ea42b; | ||
795 | u32 edca_be_dl = 0x5ea42b; | ||
796 | bool change_edca = false; | ||
797 | |||
798 | if ((last_bt_edca_ul != rtlpcipriv->bt_coexist.bt_edca_ul) || | ||
799 | (last_bt_edca_dl != rtlpcipriv->bt_coexist.bt_edca_dl)) { | ||
800 | rtlpriv->dm.current_turbo_edca = false; | ||
801 | last_bt_edca_ul = rtlpcipriv->bt_coexist.bt_edca_ul; | ||
802 | last_bt_edca_dl = rtlpcipriv->bt_coexist.bt_edca_dl; | ||
803 | } | ||
804 | |||
805 | if (rtlpcipriv->bt_coexist.bt_edca_ul != 0) { | ||
806 | edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_ul; | ||
807 | change_edca = true; | ||
808 | } | ||
809 | |||
810 | if (rtlpcipriv->bt_coexist.bt_edca_dl != 0) { | ||
811 | edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_dl; | ||
812 | change_edca = true; | ||
813 | } | ||
814 | |||
815 | if (mac->link_state != MAC80211_LINKED) { | ||
816 | rtlpriv->dm.current_turbo_edca = false; | ||
817 | return; | ||
818 | } | ||
819 | |||
820 | if ((!mac->ht_enable) && (!rtlpcipriv->bt_coexist.bt_coexistence)) { | ||
821 | if (!(edca_be_ul & 0xffff0000)) | ||
822 | edca_be_ul |= 0x005e0000; | ||
823 | |||
824 | if (!(edca_be_dl & 0xffff0000)) | ||
825 | edca_be_dl |= 0x005e0000; | ||
826 | } | ||
827 | |||
828 | if ((change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) && | ||
829 | (!rtlpriv->dm.disable_framebursting))) { | ||
830 | cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; | ||
831 | cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; | ||
832 | |||
833 | if (cur_rxok_cnt > 4 * cur_txok_cnt) { | ||
834 | if (!rtlpriv->dm.is_cur_rdlstate || | ||
835 | !rtlpriv->dm.current_turbo_edca) { | ||
836 | rtl_write_dword(rtlpriv, | ||
837 | REG_EDCA_BE_PARAM, | ||
838 | edca_be_dl); | ||
839 | rtlpriv->dm.is_cur_rdlstate = true; | ||
840 | } | ||
841 | } else { | ||
842 | if (rtlpriv->dm.is_cur_rdlstate || | ||
843 | !rtlpriv->dm.current_turbo_edca) { | ||
844 | rtl_write_dword(rtlpriv, | ||
845 | REG_EDCA_BE_PARAM, | ||
846 | edca_be_ul); | ||
847 | rtlpriv->dm.is_cur_rdlstate = false; | ||
848 | } | ||
849 | } | ||
850 | rtlpriv->dm.current_turbo_edca = true; | ||
851 | } else { | ||
852 | if (rtlpriv->dm.current_turbo_edca) { | ||
853 | u8 tmp = AC0_BE; | ||
854 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
855 | HW_VAR_AC_PARAM, | ||
856 | (u8 *)(&tmp)); | ||
857 | rtlpriv->dm.current_turbo_edca = false; | ||
858 | } | ||
859 | } | ||
860 | |||
861 | rtlpriv->dm.is_any_nonbepkts = false; | ||
862 | last_txok_cnt = rtlpriv->stats.txbytesunicast; | ||
863 | last_rxok_cnt = rtlpriv->stats.rxbytesunicast; | ||
864 | } | ||
865 | |||
866 | static void rtl88e_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw | ||
867 | *hw) | ||
868 | { | ||
869 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
870 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
871 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
872 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
873 | u8 thermalvalue = 0, delta, delta_lck, delta_iqk, off; | ||
874 | u8 th_avg_cnt = 0; | ||
875 | u32 thermalvalue_avg = 0; | ||
876 | long ele_d, temp_cck; | ||
877 | char ofdm_index[2], cck_index = 0, ofdm_old[2] = {0, 0}, cck_old = 0; | ||
878 | int i = 0; | ||
879 | bool is2t = false; | ||
880 | |||
881 | u8 ofdm_min_index = 6, rf = (is2t) ? 2 : 1; | ||
882 | u8 index_for_channel; | ||
883 | enum _dec_inc {dec, power_inc}; | ||
884 | |||
885 | /* 0.1 the following TWO tables decide the final index of | ||
886 | * OFDM/CCK swing table | ||
887 | */ | ||
888 | char del_tbl_idx[2][15] = { | ||
889 | {0, 0, 2, 3, 4, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11}, | ||
890 | {0, 0, -1, -2, -3, -4, -4, -4, -4, -5, -7, -8, -9, -9, -10} | ||
891 | }; | ||
892 | u8 thermal_threshold[2][15] = { | ||
893 | {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 27}, | ||
894 | {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 25, 25} | ||
895 | }; | ||
896 | |||
897 | /*Initilization (7 steps in total) */ | ||
898 | rtlpriv->dm.txpower_trackinginit = true; | ||
899 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | ||
900 | "rtl88e_dm_txpower_tracking_callback_thermalmeter\n"); | ||
901 | |||
902 | thermalvalue = (u8) rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0xfc00); | ||
903 | if (!thermalvalue) | ||
904 | return; | ||
905 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | ||
906 | "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n", | ||
907 | thermalvalue, rtlpriv->dm.thermalvalue, | ||
908 | rtlefuse->eeprom_thermalmeter); | ||
909 | |||
910 | /*1. Query OFDM Default Setting: Path A*/ | ||
911 | ele_d = rtl_get_bbreg(hw, ROFDM0_XATXIQIMBAL, MASKDWORD) & MASKOFDM_D; | ||
912 | for (i = 0; i < OFDM_TABLE_LENGTH; i++) { | ||
913 | if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) { | ||
914 | ofdm_old[0] = (u8) i; | ||
915 | rtldm->swing_idx_ofdm_base = (u8)i; | ||
916 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | ||
917 | "Initial pathA ele_d reg0x%x = 0x%lx, ofdm_index = 0x%x\n", | ||
918 | ROFDM0_XATXIQIMBAL, | ||
919 | ele_d, ofdm_old[0]); | ||
920 | break; | ||
921 | } | ||
922 | } | ||
923 | |||
924 | if (is2t) { | ||
925 | ele_d = rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBAL, | ||
926 | MASKDWORD) & MASKOFDM_D; | ||
927 | for (i = 0; i < OFDM_TABLE_LENGTH; i++) { | ||
928 | if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) { | ||
929 | ofdm_old[1] = (u8)i; | ||
930 | |||
931 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, | ||
932 | DBG_LOUD, | ||
933 | "Initial pathB ele_d reg0x%x = 0x%lx, ofdm_index = 0x%x\n", | ||
934 | ROFDM0_XBTXIQIMBAL, ele_d, | ||
935 | ofdm_old[1]); | ||
936 | break; | ||
937 | } | ||
938 | } | ||
939 | } | ||
940 | /*2.Query CCK default setting From 0xa24*/ | ||
941 | temp_cck = rtl_get_bbreg(hw, RCCK0_TXFILTER2, MASKDWORD) & MASKCCK; | ||
942 | for (i = 0; i < CCK_TABLE_LENGTH; i++) { | ||
943 | if (rtlpriv->dm.cck_inch14) { | ||
944 | if (memcmp(&temp_cck, &cck_tbl_ch14[i][2], 4) == 0) { | ||
945 | cck_old = (u8)i; | ||
946 | rtldm->swing_idx_cck_base = (u8)i; | ||
947 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | ||
948 | "Initial reg0x%x = 0x%lx, cck_index = 0x%x, ch 14 %d\n", | ||
949 | RCCK0_TXFILTER2, temp_cck, cck_old, | ||
950 | rtlpriv->dm.cck_inch14); | ||
951 | break; | ||
952 | } | ||
953 | } else { | ||
954 | if (memcmp(&temp_cck, &cck_tbl_ch1_13[i][2], 4) == 0) { | ||
955 | cck_old = (u8)i; | ||
956 | rtldm->swing_idx_cck_base = (u8)i; | ||
957 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | ||
958 | "Initial reg0x%x = 0x%lx, cck_index = 0x%x, ch14 %d\n", | ||
959 | RCCK0_TXFILTER2, temp_cck, cck_old, | ||
960 | rtlpriv->dm.cck_inch14); | ||
961 | break; | ||
962 | } | ||
963 | } | ||
964 | } | ||
965 | |||
966 | /*3 Initialize ThermalValues of RFCalibrateInfo*/ | ||
967 | if (!rtldm->thermalvalue) { | ||
968 | rtlpriv->dm.thermalvalue = rtlefuse->eeprom_thermalmeter; | ||
969 | rtlpriv->dm.thermalvalue_lck = thermalvalue; | ||
970 | rtlpriv->dm.thermalvalue_iqk = thermalvalue; | ||
971 | for (i = 0; i < rf; i++) | ||
972 | rtlpriv->dm.ofdm_index[i] = ofdm_old[i]; | ||
973 | rtlpriv->dm.cck_index = cck_old; | ||
974 | } | ||
975 | |||
976 | /*4 Calculate average thermal meter*/ | ||
977 | rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermalvalue; | ||
978 | rtldm->thermalvalue_avg_index++; | ||
979 | if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_88E) | ||
980 | rtldm->thermalvalue_avg_index = 0; | ||
981 | |||
982 | for (i = 0; i < AVG_THERMAL_NUM_88E; i++) { | ||
983 | if (rtldm->thermalvalue_avg[i]) { | ||
984 | thermalvalue_avg += rtldm->thermalvalue_avg[i]; | ||
985 | th_avg_cnt++; | ||
986 | } | ||
987 | } | ||
988 | |||
989 | if (th_avg_cnt) | ||
990 | thermalvalue = (u8)(thermalvalue_avg / th_avg_cnt); | ||
991 | |||
992 | /* 5 Calculate delta, delta_LCK, delta_IQK.*/ | ||
993 | if (rtlhal->reloadtxpowerindex) { | ||
994 | delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ? | ||
995 | (thermalvalue - rtlefuse->eeprom_thermalmeter) : | ||
996 | (rtlefuse->eeprom_thermalmeter - thermalvalue); | ||
997 | rtlhal->reloadtxpowerindex = false; | ||
998 | rtlpriv->dm.done_txpower = false; | ||
999 | } else if (rtlpriv->dm.done_txpower) { | ||
1000 | delta = (thermalvalue > rtlpriv->dm.thermalvalue) ? | ||
1001 | (thermalvalue - rtlpriv->dm.thermalvalue) : | ||
1002 | (rtlpriv->dm.thermalvalue - thermalvalue); | ||
1003 | } else { | ||
1004 | delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ? | ||
1005 | (thermalvalue - rtlefuse->eeprom_thermalmeter) : | ||
1006 | (rtlefuse->eeprom_thermalmeter - thermalvalue); | ||
1007 | } | ||
1008 | delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ? | ||
1009 | (thermalvalue - rtlpriv->dm.thermalvalue_lck) : | ||
1010 | (rtlpriv->dm.thermalvalue_lck - thermalvalue); | ||
1011 | delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ? | ||
1012 | (thermalvalue - rtlpriv->dm.thermalvalue_iqk) : | ||
1013 | (rtlpriv->dm.thermalvalue_iqk - thermalvalue); | ||
1014 | |||
1015 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | ||
1016 | "Readback Thermal Meter = 0x%x pre thermal meter 0x%x " | ||
1017 | "eeprom_thermalmeter 0x%x delta 0x%x " | ||
1018 | "delta_lck 0x%x delta_iqk 0x%x\n", | ||
1019 | thermalvalue, rtlpriv->dm.thermalvalue, | ||
1020 | rtlefuse->eeprom_thermalmeter, delta, delta_lck, | ||
1021 | delta_iqk); | ||
1022 | /* 6 If necessary, do LCK.*/ | ||
1023 | if (delta_lck >= 8) { | ||
1024 | rtlpriv->dm.thermalvalue_lck = thermalvalue; | ||
1025 | rtl88e_phy_lc_calibrate(hw); | ||
1026 | } | ||
1027 | |||
1028 | /* 7 If necessary, move the index of swing table to adjust Tx power. */ | ||
1029 | if (delta > 0 && rtlpriv->dm.txpower_track_control) { | ||
1030 | delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ? | ||
1031 | (thermalvalue - rtlefuse->eeprom_thermalmeter) : | ||
1032 | (rtlefuse->eeprom_thermalmeter - thermalvalue); | ||
1033 | |||
1034 | /* 7.1 Get the final CCK_index and OFDM_index for each | ||
1035 | * swing table. | ||
1036 | */ | ||
1037 | if (thermalvalue > rtlefuse->eeprom_thermalmeter) { | ||
1038 | CAL_SWING_OFF(off, power_inc, IDX_MAP, delta); | ||
1039 | for (i = 0; i < rf; i++) | ||
1040 | ofdm_index[i] = rtldm->ofdm_index[i] + | ||
1041 | del_tbl_idx[power_inc][off]; | ||
1042 | cck_index = rtldm->cck_index + | ||
1043 | del_tbl_idx[power_inc][off]; | ||
1044 | } else { | ||
1045 | CAL_SWING_OFF(off, dec, IDX_MAP, delta); | ||
1046 | for (i = 0; i < rf; i++) | ||
1047 | ofdm_index[i] = rtldm->ofdm_index[i] + | ||
1048 | del_tbl_idx[dec][off]; | ||
1049 | cck_index = rtldm->cck_index + del_tbl_idx[dec][off]; | ||
1050 | } | ||
1051 | |||
1052 | /* 7.2 Handle boundary conditions of index.*/ | ||
1053 | for (i = 0; i < rf; i++) { | ||
1054 | if (ofdm_index[i] > OFDM_TABLE_SIZE-1) | ||
1055 | ofdm_index[i] = OFDM_TABLE_SIZE-1; | ||
1056 | else if (rtldm->ofdm_index[i] < ofdm_min_index) | ||
1057 | ofdm_index[i] = ofdm_min_index; | ||
1058 | } | ||
1059 | |||
1060 | if (cck_index > CCK_TABLE_SIZE - 1) | ||
1061 | cck_index = CCK_TABLE_SIZE - 1; | ||
1062 | else if (cck_index < 0) | ||
1063 | cck_index = 0; | ||
1064 | |||
1065 | /*7.3Configure the Swing Table to adjust Tx Power.*/ | ||
1066 | if (rtlpriv->dm.txpower_track_control) { | ||
1067 | rtldm->done_txpower = true; | ||
1068 | rtldm->swing_idx_ofdm[RF90_PATH_A] = | ||
1069 | (u8)ofdm_index[RF90_PATH_A]; | ||
1070 | if (is2t) | ||
1071 | rtldm->swing_idx_ofdm[RF90_PATH_B] = | ||
1072 | (u8)ofdm_index[RF90_PATH_B]; | ||
1073 | rtldm->swing_idx_cck = cck_index; | ||
1074 | if (rtldm->swing_idx_ofdm_cur != | ||
1075 | rtldm->swing_idx_ofdm[0]) { | ||
1076 | rtldm->swing_idx_ofdm_cur = | ||
1077 | rtldm->swing_idx_ofdm[0]; | ||
1078 | rtldm->swing_flag_ofdm = true; | ||
1079 | } | ||
1080 | |||
1081 | if (rtldm->swing_idx_cck != rtldm->swing_idx_cck) { | ||
1082 | rtldm->swing_idx_cck_cur = rtldm->swing_idx_cck; | ||
1083 | rtldm->swing_flag_cck = true; | ||
1084 | } | ||
1085 | |||
1086 | rtl88e_chk_tx_track(hw, TXAGC, 0, 0); | ||
1087 | |||
1088 | if (is2t) | ||
1089 | rtl88e_chk_tx_track(hw, BBSWING, | ||
1090 | RF90_PATH_B, | ||
1091 | index_for_channel); | ||
1092 | } | ||
1093 | } | ||
1094 | |||
1095 | if (delta_iqk >= 8) { | ||
1096 | rtlpriv->dm.thermalvalue_iqk = thermalvalue; | ||
1097 | rtl88e_phy_iq_calibrate(hw, false); | ||
1098 | } | ||
1099 | |||
1100 | if (rtldm->txpower_track_control) | ||
1101 | rtldm->thermalvalue = thermalvalue; | ||
1102 | rtldm->txpowercount = 0; | ||
1103 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "end\n"); | ||
1104 | } | ||
1105 | |||
1106 | static void rtl88e_dm_init_txpower_tracking(struct ieee80211_hw *hw) | ||
1107 | { | ||
1108 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1109 | |||
1110 | rtlpriv->dm.txpower_tracking = true; | ||
1111 | rtlpriv->dm.txpower_trackinginit = false; | ||
1112 | rtlpriv->dm.txpowercount = 0; | ||
1113 | rtlpriv->dm.txpower_track_control = true; | ||
1114 | |||
1115 | rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A] = 12; | ||
1116 | rtlpriv->dm.swing_idx_ofdm_cur = 12; | ||
1117 | rtlpriv->dm.swing_flag_ofdm = false; | ||
1118 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | ||
1119 | " rtlpriv->dm.txpower_tracking = %d\n", | ||
1120 | rtlpriv->dm.txpower_tracking); | ||
1121 | } | ||
1122 | |||
1123 | void rtl88e_dm_check_txpower_tracking(struct ieee80211_hw *hw) | ||
1124 | { | ||
1125 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1126 | static u8 tm_trigger; | ||
1127 | |||
1128 | if (!rtlpriv->dm.txpower_tracking) | ||
1129 | return; | ||
1130 | |||
1131 | if (!tm_trigger) { | ||
1132 | rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17)|BIT(16), | ||
1133 | 0x03); | ||
1134 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | ||
1135 | "Trigger 88E Thermal Meter!!\n"); | ||
1136 | tm_trigger = 1; | ||
1137 | return; | ||
1138 | } else { | ||
1139 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | ||
1140 | "Schedule TxPowerTracking !!\n"); | ||
1141 | rtl88e_dm_txpower_tracking_callback_thermalmeter(hw); | ||
1142 | tm_trigger = 0; | ||
1143 | } | ||
1144 | } | ||
1145 | |||
1146 | void rtl88e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) | ||
1147 | { | ||
1148 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1149 | struct rate_adaptive *p_ra = &(rtlpriv->ra); | ||
1150 | |||
1151 | p_ra->ratr_state = DM_RATR_STA_INIT; | ||
1152 | p_ra->pre_ratr_state = DM_RATR_STA_INIT; | ||
1153 | |||
1154 | if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) | ||
1155 | rtlpriv->dm.useramask = true; | ||
1156 | else | ||
1157 | rtlpriv->dm.useramask = false; | ||
1158 | } | ||
1159 | |||
1160 | static void rtl88e_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) | ||
1161 | { | ||
1162 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1163 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1164 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1165 | struct rate_adaptive *p_ra = &(rtlpriv->ra); | ||
1166 | struct ieee80211_sta *sta = NULL; | ||
1167 | u32 low_rssi, hi_rssi; | ||
1168 | |||
1169 | if (is_hal_stop(rtlhal)) { | ||
1170 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
1171 | "driver is going to unload\n"); | ||
1172 | return; | ||
1173 | } | ||
1174 | |||
1175 | if (!rtlpriv->dm.useramask) { | ||
1176 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
1177 | "driver does not control rate adaptive mask\n"); | ||
1178 | return; | ||
1179 | } | ||
1180 | |||
1181 | if (mac->link_state == MAC80211_LINKED && | ||
1182 | mac->opmode == NL80211_IFTYPE_STATION) { | ||
1183 | switch (p_ra->pre_ratr_state) { | ||
1184 | case DM_RATR_STA_HIGH: | ||
1185 | hi_rssi = 50; | ||
1186 | low_rssi = 20; | ||
1187 | break; | ||
1188 | case DM_RATR_STA_MIDDLE: | ||
1189 | hi_rssi = 55; | ||
1190 | low_rssi = 20; | ||
1191 | break; | ||
1192 | case DM_RATR_STA_LOW: | ||
1193 | hi_rssi = 50; | ||
1194 | low_rssi = 25; | ||
1195 | break; | ||
1196 | default: | ||
1197 | hi_rssi = 50; | ||
1198 | low_rssi = 20; | ||
1199 | break; | ||
1200 | } | ||
1201 | |||
1202 | if (rtlpriv->dm.undec_sm_pwdb > (long)hi_rssi) | ||
1203 | p_ra->ratr_state = DM_RATR_STA_HIGH; | ||
1204 | else if (rtlpriv->dm.undec_sm_pwdb > (long)low_rssi) | ||
1205 | p_ra->ratr_state = DM_RATR_STA_MIDDLE; | ||
1206 | else | ||
1207 | p_ra->ratr_state = DM_RATR_STA_LOW; | ||
1208 | |||
1209 | if (p_ra->pre_ratr_state != p_ra->ratr_state) { | ||
1210 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
1211 | "RSSI = %ld\n", | ||
1212 | rtlpriv->dm.undec_sm_pwdb); | ||
1213 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
1214 | "RSSI_LEVEL = %d\n", p_ra->ratr_state); | ||
1215 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
1216 | "PreState = %d, CurState = %d\n", | ||
1217 | p_ra->pre_ratr_state, p_ra->ratr_state); | ||
1218 | |||
1219 | rcu_read_lock(); | ||
1220 | sta = rtl_find_sta(hw, mac->bssid); | ||
1221 | if (sta) | ||
1222 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, | ||
1223 | p_ra->ratr_state); | ||
1224 | rcu_read_unlock(); | ||
1225 | |||
1226 | p_ra->pre_ratr_state = p_ra->ratr_state; | ||
1227 | } | ||
1228 | } | ||
1229 | } | ||
1230 | |||
1231 | static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw) | ||
1232 | { | ||
1233 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1234 | struct ps_t *dm_pstable = &rtlpriv->dm_pstable; | ||
1235 | |||
1236 | dm_pstable->pre_ccastate = CCA_MAX; | ||
1237 | dm_pstable->cur_ccasate = CCA_MAX; | ||
1238 | dm_pstable->pre_rfstate = RF_MAX; | ||
1239 | dm_pstable->cur_rfstate = RF_MAX; | ||
1240 | dm_pstable->rssi_val_min = 0; | ||
1241 | } | ||
1242 | |||
1243 | static void rtl88e_dm_update_rx_idle_ant(struct ieee80211_hw *hw, u8 ant) | ||
1244 | { | ||
1245 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1246 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1247 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
1248 | struct fast_ant_training *fat_tbl = &(rtldm->fat_table); | ||
1249 | u32 def_ant, opt_ant; | ||
1250 | |||
1251 | if (fat_tbl->rx_idle_ant != ant) { | ||
1252 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1253 | "need to update rx idle ant\n"); | ||
1254 | if (ant == MAIN_ANT) { | ||
1255 | def_ant = (fat_tbl->rx_idle_ant == CG_TRX_HW_ANTDIV) ? | ||
1256 | MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX; | ||
1257 | opt_ant = (fat_tbl->rx_idle_ant == CG_TRX_HW_ANTDIV) ? | ||
1258 | AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX; | ||
1259 | } else { | ||
1260 | def_ant = (fat_tbl->rx_idle_ant == CG_TRX_HW_ANTDIV) ? | ||
1261 | AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX; | ||
1262 | opt_ant = (fat_tbl->rx_idle_ant == CG_TRX_HW_ANTDIV) ? | ||
1263 | MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX; | ||
1264 | } | ||
1265 | |||
1266 | if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) { | ||
1267 | rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(5) | | ||
1268 | BIT(4) | BIT(3), def_ant); | ||
1269 | rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(8) | | ||
1270 | BIT(7) | BIT(6), opt_ant); | ||
1271 | rtl_set_bbreg(hw, DM_REG_ANTSEL_CTRL_11N, BIT(14) | | ||
1272 | BIT(13) | BIT(12), def_ant); | ||
1273 | rtl_set_bbreg(hw, DM_REG_RESP_TX_11N, BIT(6) | BIT(7), | ||
1274 | def_ant); | ||
1275 | } else if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) { | ||
1276 | rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(5) | | ||
1277 | BIT(4) | BIT(3), def_ant); | ||
1278 | rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(8) | | ||
1279 | BIT(7) | BIT(6), opt_ant); | ||
1280 | } | ||
1281 | } | ||
1282 | fat_tbl->rx_idle_ant = ant; | ||
1283 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "RxIdleAnt %s\n", | ||
1284 | ((ant == MAIN_ANT) ? ("MAIN_ANT") : ("AUX_ANT"))); | ||
1285 | } | ||
1286 | |||
1287 | static void rtl88e_dm_update_tx_ant(struct ieee80211_hw *hw, | ||
1288 | u8 ant, u32 mac_id) | ||
1289 | { | ||
1290 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1291 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
1292 | struct fast_ant_training *fat_tbl = &(rtldm->fat_table); | ||
1293 | u8 target_ant; | ||
1294 | |||
1295 | if (ant == MAIN_ANT) | ||
1296 | target_ant = MAIN_ANT_CG_TRX; | ||
1297 | else | ||
1298 | target_ant = AUX_ANT_CG_TRX; | ||
1299 | |||
1300 | fat_tbl->antsel_a[mac_id] = target_ant & BIT(0); | ||
1301 | fat_tbl->antsel_b[mac_id] = (target_ant & BIT(1)) >> 1; | ||
1302 | fat_tbl->antsel_c[mac_id] = (target_ant & BIT(2)) >> 2; | ||
1303 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "txfrominfo target ant %s\n", | ||
1304 | ((ant == MAIN_ANT) ? ("MAIN_ANT") : ("AUX_ANT"))); | ||
1305 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "antsel_tr_mux = 3'b%d%d%d\n", | ||
1306 | fat_tbl->antsel_c[mac_id], | ||
1307 | fat_tbl->antsel_b[mac_id], fat_tbl->antsel_a[mac_id]); | ||
1308 | } | ||
1309 | |||
1310 | static void rtl88e_dm_rx_hw_antena_div_init(struct ieee80211_hw *hw) | ||
1311 | { | ||
1312 | u32 value32; | ||
1313 | /*MAC Setting*/ | ||
1314 | value32 = rtl_get_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD); | ||
1315 | rtl_set_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD, value32 | | ||
1316 | (BIT(23) | BIT(25))); | ||
1317 | /*Pin Setting*/ | ||
1318 | rtl_set_bbreg(hw, DM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0); | ||
1319 | rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(10), 0); | ||
1320 | rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(22), 1); | ||
1321 | rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(31), 1); | ||
1322 | /*OFDM Setting*/ | ||
1323 | rtl_set_bbreg(hw, DM_REG_ANTDIV_PARA1_11N, MASKDWORD, 0x000000a0); | ||
1324 | /*CCK Setting*/ | ||
1325 | rtl_set_bbreg(hw, DM_REG_BB_PWR_SAV4_11N, BIT(7), 1); | ||
1326 | rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1); | ||
1327 | rtl88e_dm_update_rx_idle_ant(hw, MAIN_ANT); | ||
1328 | rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKLWORD, 0x0201); | ||
1329 | } | ||
1330 | |||
1331 | static void rtl88e_dm_trx_hw_antenna_div_init(struct ieee80211_hw *hw) | ||
1332 | { | ||
1333 | u32 value32; | ||
1334 | |||
1335 | /*MAC Setting*/ | ||
1336 | value32 = rtl_get_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD); | ||
1337 | rtl_set_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD, value32 | | ||
1338 | (BIT(23) | BIT(25))); | ||
1339 | /*Pin Setting*/ | ||
1340 | rtl_set_bbreg(hw, DM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0); | ||
1341 | rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(10), 0); | ||
1342 | rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(22), 0); | ||
1343 | rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(31), 1); | ||
1344 | /*OFDM Setting*/ | ||
1345 | rtl_set_bbreg(hw, DM_REG_ANTDIV_PARA1_11N, MASKDWORD, 0x000000a0); | ||
1346 | /*CCK Setting*/ | ||
1347 | rtl_set_bbreg(hw, DM_REG_BB_PWR_SAV4_11N, BIT(7), 1); | ||
1348 | rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1); | ||
1349 | /*TX Setting*/ | ||
1350 | rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, BIT(21), 0); | ||
1351 | rtl88e_dm_update_rx_idle_ant(hw, MAIN_ANT); | ||
1352 | rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKLWORD, 0x0201); | ||
1353 | } | ||
1354 | |||
1355 | static void rtl88e_dm_fast_training_init(struct ieee80211_hw *hw) | ||
1356 | { | ||
1357 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
1358 | struct fast_ant_training *fat_tbl = &(rtldm->fat_table); | ||
1359 | u32 ant_combo = 2; | ||
1360 | u32 value32, i; | ||
1361 | |||
1362 | for (i = 0; i < 6; i++) { | ||
1363 | fat_tbl->bssid[i] = 0; | ||
1364 | fat_tbl->ant_sum[i] = 0; | ||
1365 | fat_tbl->ant_cnt[i] = 0; | ||
1366 | fat_tbl->ant_ave[i] = 0; | ||
1367 | } | ||
1368 | fat_tbl->train_idx = 0; | ||
1369 | fat_tbl->fat_state = FAT_NORMAL_STATE; | ||
1370 | |||
1371 | /*MAC Setting*/ | ||
1372 | value32 = rtl_get_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD); | ||
1373 | rtl_set_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD, value32 | (BIT(23) | | ||
1374 | BIT(25))); | ||
1375 | value32 = rtl_get_bbreg(hw, DM_REG_ANT_TRAIN_2, MASKDWORD); | ||
1376 | rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_2, MASKDWORD, value32 | (BIT(16) | | ||
1377 | BIT(17))); | ||
1378 | rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_2, MASKLWORD, 0); | ||
1379 | rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_1, MASKDWORD, 0); | ||
1380 | |||
1381 | /*Pin Setting*/ | ||
1382 | rtl_set_bbreg(hw, DM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0); | ||
1383 | rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(10), 0); | ||
1384 | rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(22), 0); | ||
1385 | rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(31), 1); | ||
1386 | |||
1387 | /*OFDM Setting*/ | ||
1388 | rtl_set_bbreg(hw, DM_REG_ANTDIV_PARA1_11N, MASKDWORD, 0x000000a0); | ||
1389 | /*antenna mapping table*/ | ||
1390 | if (ant_combo == 2) { | ||
1391 | rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE0, 1); | ||
1392 | rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE1, 2); | ||
1393 | } else if (ant_combo == 7) { | ||
1394 | rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE0, 1); | ||
1395 | rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE1, 2); | ||
1396 | rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE2, 2); | ||
1397 | rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE3, 3); | ||
1398 | rtl_set_bbreg(hw, DM_REG_ANT_MAPPING2_11N, MASKBYTE0, 4); | ||
1399 | rtl_set_bbreg(hw, DM_REG_ANT_MAPPING2_11N, MASKBYTE1, 5); | ||
1400 | rtl_set_bbreg(hw, DM_REG_ANT_MAPPING2_11N, MASKBYTE2, 6); | ||
1401 | rtl_set_bbreg(hw, DM_REG_ANT_MAPPING2_11N, MASKBYTE3, 7); | ||
1402 | } | ||
1403 | |||
1404 | /*TX Setting*/ | ||
1405 | rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, BIT(21), 1); | ||
1406 | rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(5) | BIT(4) | BIT(3), 0); | ||
1407 | rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(8) | BIT(7) | BIT(6), 1); | ||
1408 | rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(2) | BIT(1) | BIT(0), | ||
1409 | (ant_combo - 1)); | ||
1410 | |||
1411 | rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 1); | ||
1412 | } | ||
1413 | |||
1414 | static void rtl88e_dm_antenna_div_init(struct ieee80211_hw *hw) | ||
1415 | { | ||
1416 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1417 | |||
1418 | if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) | ||
1419 | rtl88e_dm_rx_hw_antena_div_init(hw); | ||
1420 | else if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) | ||
1421 | rtl88e_dm_trx_hw_antenna_div_init(hw); | ||
1422 | else if (rtlefuse->antenna_div_type == CG_TRX_SMART_ANTDIV) | ||
1423 | rtl88e_dm_fast_training_init(hw); | ||
1424 | } | ||
1425 | |||
1426 | void rtl88e_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw, | ||
1427 | u8 *pdesc, u32 mac_id) | ||
1428 | { | ||
1429 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1430 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
1431 | struct fast_ant_training *fat_tbl = &(rtldm->fat_table); | ||
1432 | |||
1433 | if ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) || | ||
1434 | (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)) { | ||
1435 | SET_TX_DESC_ANTSEL_A(pdesc, fat_tbl->antsel_a[mac_id]); | ||
1436 | SET_TX_DESC_ANTSEL_B(pdesc, fat_tbl->antsel_b[mac_id]); | ||
1437 | SET_TX_DESC_ANTSEL_C(pdesc, fat_tbl->antsel_c[mac_id]); | ||
1438 | } | ||
1439 | } | ||
1440 | |||
1441 | void rtl88e_dm_ant_sel_statistics(struct ieee80211_hw *hw, | ||
1442 | u8 antsel_tr_mux, u32 mac_id, u32 rx_pwdb_all) | ||
1443 | { | ||
1444 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1445 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
1446 | struct fast_ant_training *fat_tbl = &(rtldm->fat_table); | ||
1447 | |||
1448 | if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) { | ||
1449 | if (antsel_tr_mux == MAIN_ANT_CG_TRX) { | ||
1450 | fat_tbl->main_ant_sum[mac_id] += rx_pwdb_all; | ||
1451 | fat_tbl->main_ant_cnt[mac_id]++; | ||
1452 | } else { | ||
1453 | fat_tbl->aux_ant_sum[mac_id] += rx_pwdb_all; | ||
1454 | fat_tbl->aux_ant_cnt[mac_id]++; | ||
1455 | } | ||
1456 | } else if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) { | ||
1457 | if (antsel_tr_mux == MAIN_ANT_CGCS_RX) { | ||
1458 | fat_tbl->main_ant_sum[mac_id] += rx_pwdb_all; | ||
1459 | fat_tbl->main_ant_cnt[mac_id]++; | ||
1460 | } else { | ||
1461 | fat_tbl->aux_ant_sum[mac_id] += rx_pwdb_all; | ||
1462 | fat_tbl->aux_ant_cnt[mac_id]++; | ||
1463 | } | ||
1464 | } | ||
1465 | } | ||
1466 | |||
1467 | static void rtl88e_dm_hw_ant_div(struct ieee80211_hw *hw) | ||
1468 | { | ||
1469 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1470 | struct dig_t *dm_dig = &rtlpriv->dm_digtable; | ||
1471 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1472 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
1473 | struct rtl_sta_info *drv_priv; | ||
1474 | struct fast_ant_training *fat_tbl = &(rtldm->fat_table); | ||
1475 | u32 i, min_rssi = 0xff, ant_div_max_rssi = 0, max_rssi = 0; | ||
1476 | u32 local_min_rssi, local_max_rssi; | ||
1477 | u32 main_rssi, aux_rssi; | ||
1478 | u8 rx_idle_ant = 0, target_ant = 7; | ||
1479 | |||
1480 | i = 0; | ||
1481 | main_rssi = (fat_tbl->main_ant_cnt[i] != 0) ? | ||
1482 | (fat_tbl->main_ant_sum[i] / | ||
1483 | fat_tbl->main_ant_cnt[i]) : 0; | ||
1484 | aux_rssi = (fat_tbl->aux_ant_cnt[i] != 0) ? | ||
1485 | (fat_tbl->aux_ant_sum[i] / fat_tbl->aux_ant_cnt[i]) : 0; | ||
1486 | target_ant = (main_rssi == aux_rssi) ? | ||
1487 | fat_tbl->rx_idle_ant : ((main_rssi >= aux_rssi) ? | ||
1488 | MAIN_ANT : AUX_ANT); | ||
1489 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1490 | "main_ant_sum %d main_ant_cnt %d\n", | ||
1491 | fat_tbl->main_ant_sum[i], fat_tbl->main_ant_cnt[i]); | ||
1492 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1493 | "aux_ant_sum %d aux_ant_cnt %d\n", | ||
1494 | fat_tbl->aux_ant_sum[i], | ||
1495 | fat_tbl->aux_ant_cnt[i]); | ||
1496 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1497 | "main_rssi %d aux_rssi%d\n", main_rssi, aux_rssi); | ||
1498 | local_max_rssi = (main_rssi > aux_rssi) ? main_rssi : aux_rssi; | ||
1499 | if ((local_max_rssi > ant_div_max_rssi) && (local_max_rssi < 40)) | ||
1500 | ant_div_max_rssi = local_max_rssi; | ||
1501 | if (local_max_rssi > max_rssi) | ||
1502 | max_rssi = local_max_rssi; | ||
1503 | |||
1504 | if ((fat_tbl->rx_idle_ant == MAIN_ANT) && (main_rssi == 0)) | ||
1505 | main_rssi = aux_rssi; | ||
1506 | else if ((fat_tbl->rx_idle_ant == AUX_ANT) && (aux_rssi == 0)) | ||
1507 | aux_rssi = main_rssi; | ||
1508 | |||
1509 | local_min_rssi = (main_rssi > aux_rssi) ? aux_rssi : main_rssi; | ||
1510 | if (local_min_rssi < min_rssi) { | ||
1511 | min_rssi = local_min_rssi; | ||
1512 | rx_idle_ant = target_ant; | ||
1513 | } | ||
1514 | if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) | ||
1515 | rtl88e_dm_update_tx_ant(hw, target_ant, i); | ||
1516 | |||
1517 | if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP || | ||
1518 | rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) { | ||
1519 | spin_lock_bh(&rtlpriv->locks.entry_list_lock); | ||
1520 | list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) { | ||
1521 | i++; | ||
1522 | main_rssi = (fat_tbl->main_ant_cnt[i] != 0) ? | ||
1523 | (fat_tbl->main_ant_sum[i] / | ||
1524 | fat_tbl->main_ant_cnt[i]) : 0; | ||
1525 | aux_rssi = (fat_tbl->aux_ant_cnt[i] != 0) ? | ||
1526 | (fat_tbl->aux_ant_sum[i] / | ||
1527 | fat_tbl->aux_ant_cnt[i]) : 0; | ||
1528 | target_ant = (main_rssi == aux_rssi) ? | ||
1529 | fat_tbl->rx_idle_ant : ((main_rssi >= | ||
1530 | aux_rssi) ? MAIN_ANT : AUX_ANT); | ||
1531 | |||
1532 | |||
1533 | local_max_rssi = max_t(u32, main_rssi, aux_rssi); | ||
1534 | if ((local_max_rssi > ant_div_max_rssi) && | ||
1535 | (local_max_rssi < 40)) | ||
1536 | ant_div_max_rssi = local_max_rssi; | ||
1537 | if (local_max_rssi > max_rssi) | ||
1538 | max_rssi = local_max_rssi; | ||
1539 | |||
1540 | if ((fat_tbl->rx_idle_ant == MAIN_ANT) && !main_rssi) | ||
1541 | main_rssi = aux_rssi; | ||
1542 | else if ((fat_tbl->rx_idle_ant == AUX_ANT) && | ||
1543 | (aux_rssi == 0)) | ||
1544 | aux_rssi = main_rssi; | ||
1545 | |||
1546 | local_min_rssi = (main_rssi > aux_rssi) ? | ||
1547 | aux_rssi : main_rssi; | ||
1548 | if (local_min_rssi < min_rssi) { | ||
1549 | min_rssi = local_min_rssi; | ||
1550 | rx_idle_ant = target_ant; | ||
1551 | } | ||
1552 | if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) | ||
1553 | rtl88e_dm_update_tx_ant(hw, target_ant, i); | ||
1554 | } | ||
1555 | spin_unlock_bh(&rtlpriv->locks.entry_list_lock); | ||
1556 | } | ||
1557 | |||
1558 | for (i = 0; i < ASSOCIATE_ENTRY_NUM; i++) { | ||
1559 | fat_tbl->main_ant_sum[i] = 0; | ||
1560 | fat_tbl->aux_ant_sum[i] = 0; | ||
1561 | fat_tbl->main_ant_cnt[i] = 0; | ||
1562 | fat_tbl->aux_ant_cnt[i] = 0; | ||
1563 | } | ||
1564 | |||
1565 | rtl88e_dm_update_rx_idle_ant(hw, rx_idle_ant); | ||
1566 | |||
1567 | dm_dig->antdiv_rssi_max = ant_div_max_rssi; | ||
1568 | dm_dig->rssi_max = max_rssi; | ||
1569 | } | ||
1570 | |||
1571 | static void rtl88e_set_next_mac_address_target(struct ieee80211_hw *hw) | ||
1572 | { | ||
1573 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1574 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1575 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
1576 | struct rtl_sta_info *drv_priv; | ||
1577 | struct fast_ant_training *fat_tbl = &(rtldm->fat_table); | ||
1578 | u32 value32, i, j = 0; | ||
1579 | |||
1580 | if (mac->link_state >= MAC80211_LINKED) { | ||
1581 | for (i = 0; i < ASSOCIATE_ENTRY_NUM; i++) { | ||
1582 | if ((fat_tbl->train_idx + 1) == ASSOCIATE_ENTRY_NUM) | ||
1583 | fat_tbl->train_idx = 0; | ||
1584 | else | ||
1585 | fat_tbl->train_idx++; | ||
1586 | |||
1587 | if (fat_tbl->train_idx == 0) { | ||
1588 | value32 = (mac->mac_addr[5] << 8) | | ||
1589 | mac->mac_addr[4]; | ||
1590 | rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_2, | ||
1591 | MASKLWORD, value32); | ||
1592 | |||
1593 | value32 = (mac->mac_addr[3] << 24) | | ||
1594 | (mac->mac_addr[2] << 16) | | ||
1595 | (mac->mac_addr[1] << 8) | | ||
1596 | mac->mac_addr[0]; | ||
1597 | rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_1, | ||
1598 | MASKDWORD, value32); | ||
1599 | break; | ||
1600 | } | ||
1601 | |||
1602 | if (rtlpriv->mac80211.opmode != | ||
1603 | NL80211_IFTYPE_STATION) { | ||
1604 | spin_lock_bh(&rtlpriv->locks.entry_list_lock); | ||
1605 | list_for_each_entry(drv_priv, | ||
1606 | &rtlpriv->entry_list, | ||
1607 | list) { | ||
1608 | j++; | ||
1609 | if (j != fat_tbl->train_idx) | ||
1610 | continue; | ||
1611 | |||
1612 | value32 = (drv_priv->mac_addr[5] << 8) | | ||
1613 | drv_priv->mac_addr[4]; | ||
1614 | rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_2, | ||
1615 | MASKLWORD, value32); | ||
1616 | |||
1617 | value32 = (drv_priv->mac_addr[3]<<24) | | ||
1618 | (drv_priv->mac_addr[2]<<16) | | ||
1619 | (drv_priv->mac_addr[1]<<8) | | ||
1620 | drv_priv->mac_addr[0]; | ||
1621 | rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_1, | ||
1622 | MASKDWORD, value32); | ||
1623 | break; | ||
1624 | } | ||
1625 | spin_unlock_bh(&rtlpriv->locks.entry_list_lock); | ||
1626 | /*find entry, break*/ | ||
1627 | if (j == fat_tbl->train_idx) | ||
1628 | break; | ||
1629 | } | ||
1630 | } | ||
1631 | } | ||
1632 | } | ||
1633 | |||
1634 | static void rtl88e_dm_fast_ant_training(struct ieee80211_hw *hw) | ||
1635 | { | ||
1636 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1637 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
1638 | struct fast_ant_training *fat_tbl = &(rtldm->fat_table); | ||
1639 | u32 i, max_rssi = 0; | ||
1640 | u8 target_ant = 2; | ||
1641 | bool bpkt_filter_match = false; | ||
1642 | |||
1643 | if (fat_tbl->fat_state == FAT_TRAINING_STATE) { | ||
1644 | for (i = 0; i < 7; i++) { | ||
1645 | if (fat_tbl->ant_cnt[i] == 0) { | ||
1646 | fat_tbl->ant_ave[i] = 0; | ||
1647 | } else { | ||
1648 | fat_tbl->ant_ave[i] = fat_tbl->ant_sum[i] / | ||
1649 | fat_tbl->ant_cnt[i]; | ||
1650 | bpkt_filter_match = true; | ||
1651 | } | ||
1652 | |||
1653 | if (fat_tbl->ant_ave[i] > max_rssi) { | ||
1654 | max_rssi = fat_tbl->ant_ave[i]; | ||
1655 | target_ant = (u8) i; | ||
1656 | } | ||
1657 | } | ||
1658 | |||
1659 | if (bpkt_filter_match == false) { | ||
1660 | rtl_set_bbreg(hw, DM_REG_TXAGC_A_1_MCS32_11N, | ||
1661 | BIT(16), 0); | ||
1662 | rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 0); | ||
1663 | } else { | ||
1664 | rtl_set_bbreg(hw, DM_REG_TXAGC_A_1_MCS32_11N, | ||
1665 | BIT(16), 0); | ||
1666 | rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(8) | | ||
1667 | BIT(7) | BIT(6), target_ant); | ||
1668 | rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, BIT(21), 1); | ||
1669 | |||
1670 | fat_tbl->antsel_a[fat_tbl->train_idx] = | ||
1671 | target_ant & BIT(0); | ||
1672 | fat_tbl->antsel_b[fat_tbl->train_idx] = | ||
1673 | (target_ant & BIT(1)) >> 1; | ||
1674 | fat_tbl->antsel_c[fat_tbl->train_idx] = | ||
1675 | (target_ant & BIT(2)) >> 2; | ||
1676 | |||
1677 | if (target_ant == 0) | ||
1678 | rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 0); | ||
1679 | } | ||
1680 | |||
1681 | for (i = 0; i < 7; i++) { | ||
1682 | fat_tbl->ant_sum[i] = 0; | ||
1683 | fat_tbl->ant_cnt[i] = 0; | ||
1684 | } | ||
1685 | |||
1686 | fat_tbl->fat_state = FAT_NORMAL_STATE; | ||
1687 | return; | ||
1688 | } | ||
1689 | |||
1690 | if (fat_tbl->fat_state == FAT_NORMAL_STATE) { | ||
1691 | rtl88e_set_next_mac_address_target(hw); | ||
1692 | |||
1693 | fat_tbl->fat_state = FAT_TRAINING_STATE; | ||
1694 | rtl_set_bbreg(hw, DM_REG_TXAGC_A_1_MCS32_11N, BIT(16), 1); | ||
1695 | rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 1); | ||
1696 | |||
1697 | mod_timer(&rtlpriv->works.fast_antenna_training_timer, | ||
1698 | jiffies + MSECS(RTL_WATCH_DOG_TIME)); | ||
1699 | } | ||
1700 | } | ||
1701 | |||
1702 | void rtl88e_dm_fast_antenna_training_callback(unsigned long data) | ||
1703 | { | ||
1704 | struct ieee80211_hw *hw = (struct ieee80211_hw *)data; | ||
1705 | |||
1706 | rtl88e_dm_fast_ant_training(hw); | ||
1707 | } | ||
1708 | |||
1709 | static void rtl88e_dm_antenna_diversity(struct ieee80211_hw *hw) | ||
1710 | { | ||
1711 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1712 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1713 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1714 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
1715 | struct fast_ant_training *fat_tbl = &(rtldm->fat_table); | ||
1716 | |||
1717 | if (mac->link_state < MAC80211_LINKED) { | ||
1718 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "No Link\n"); | ||
1719 | if (fat_tbl->becomelinked == true) { | ||
1720 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, | ||
1721 | "need to turn off HW AntDiv\n"); | ||
1722 | rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 0); | ||
1723 | rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA1_11N, | ||
1724 | BIT(15), 0); | ||
1725 | if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) | ||
1726 | rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, | ||
1727 | BIT(21), 0); | ||
1728 | fat_tbl->becomelinked = | ||
1729 | (mac->link_state == MAC80211_LINKED) ? true : false; | ||
1730 | } | ||
1731 | return; | ||
1732 | } else { | ||
1733 | if (fat_tbl->becomelinked == false) { | ||
1734 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, | ||
1735 | "Need to turn on HW AntDiv\n"); | ||
1736 | rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 1); | ||
1737 | rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA1_11N, | ||
1738 | BIT(15), 1); | ||
1739 | if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) | ||
1740 | rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, | ||
1741 | BIT(21), 1); | ||
1742 | fat_tbl->becomelinked = | ||
1743 | (mac->link_state >= MAC80211_LINKED) ? true : false; | ||
1744 | } | ||
1745 | } | ||
1746 | |||
1747 | if ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) || | ||
1748 | (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV)) | ||
1749 | rtl88e_dm_hw_ant_div(hw); | ||
1750 | else if (rtlefuse->antenna_div_type == CG_TRX_SMART_ANTDIV) | ||
1751 | rtl88e_dm_fast_ant_training(hw); | ||
1752 | } | ||
1753 | |||
1754 | void rtl88e_dm_init(struct ieee80211_hw *hw) | ||
1755 | { | ||
1756 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1757 | |||
1758 | rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; | ||
1759 | rtl88e_dm_diginit(hw); | ||
1760 | rtl88e_dm_init_dynamic_txpower(hw); | ||
1761 | rtl88e_dm_init_edca_turbo(hw); | ||
1762 | rtl88e_dm_init_rate_adaptive_mask(hw); | ||
1763 | rtl88e_dm_init_txpower_tracking(hw); | ||
1764 | rtl92c_dm_init_dynamic_bb_powersaving(hw); | ||
1765 | rtl88e_dm_antenna_div_init(hw); | ||
1766 | } | ||
1767 | |||
1768 | void rtl88e_dm_watchdog(struct ieee80211_hw *hw) | ||
1769 | { | ||
1770 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1771 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
1772 | bool fw_current_inpsmode = false; | ||
1773 | bool fw_ps_awake = true; | ||
1774 | |||
1775 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, | ||
1776 | (u8 *)(&fw_current_inpsmode)); | ||
1777 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, | ||
1778 | (u8 *)(&fw_ps_awake)); | ||
1779 | if (ppsc->p2p_ps_info.p2p_ps_mode) | ||
1780 | fw_ps_awake = false; | ||
1781 | |||
1782 | if ((ppsc->rfpwr_state == ERFON) && | ||
1783 | ((!fw_current_inpsmode) && fw_ps_awake) && | ||
1784 | (!ppsc->rfchange_inprogress)) { | ||
1785 | rtl88e_dm_pwdb_monitor(hw); | ||
1786 | rtl88e_dm_dig(hw); | ||
1787 | rtl88e_dm_false_alarm_counter_statistics(hw); | ||
1788 | rtl92c_dm_dynamic_txpower(hw); | ||
1789 | rtl88e_dm_check_txpower_tracking(hw); | ||
1790 | rtl88e_dm_refresh_rate_adaptive_mask(hw); | ||
1791 | rtl88e_dm_check_edca_turbo(hw); | ||
1792 | rtl88e_dm_antenna_diversity(hw); | ||
1793 | } | ||
1794 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.h b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.h new file mode 100644 index 000000000000..0e07f72ea158 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.h | |||
@@ -0,0 +1,326 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #ifndef __RTL88E_DM_H__ | ||
31 | #define __RTL88E_DM_H__ | ||
32 | |||
33 | #define MAIN_ANT 0 | ||
34 | #define AUX_ANT 1 | ||
35 | #define MAIN_ANT_CG_TRX 1 | ||
36 | #define AUX_ANT_CG_TRX 0 | ||
37 | #define MAIN_ANT_CGCS_RX 0 | ||
38 | #define AUX_ANT_CGCS_RX 1 | ||
39 | |||
40 | /*RF REG LIST*/ | ||
41 | #define DM_REG_RF_MODE_11N 0x00 | ||
42 | #define DM_REG_RF_0B_11N 0x0B | ||
43 | #define DM_REG_CHNBW_11N 0x18 | ||
44 | #define DM_REG_T_METER_11N 0x24 | ||
45 | #define DM_REG_RF_25_11N 0x25 | ||
46 | #define DM_REG_RF_26_11N 0x26 | ||
47 | #define DM_REG_RF_27_11N 0x27 | ||
48 | #define DM_REG_RF_2B_11N 0x2B | ||
49 | #define DM_REG_RF_2C_11N 0x2C | ||
50 | #define DM_REG_RXRF_A3_11N 0x3C | ||
51 | #define DM_REG_T_METER_92D_11N 0x42 | ||
52 | #define DM_REG_T_METER_88E_11N 0x42 | ||
53 | |||
54 | /*BB REG LIST*/ | ||
55 | /*PAGE 8 */ | ||
56 | #define DM_REG_BB_CTRL_11N 0x800 | ||
57 | #define DM_REG_RF_PIN_11N 0x804 | ||
58 | #define DM_REG_PSD_CTRL_11N 0x808 | ||
59 | #define DM_REG_TX_ANT_CTRL_11N 0x80C | ||
60 | #define DM_REG_BB_PWR_SAV5_11N 0x818 | ||
61 | #define DM_REG_CCK_RPT_FORMAT_11N 0x824 | ||
62 | #define DM_REG_RX_DEFAULT_A_11N 0x858 | ||
63 | #define DM_REG_RX_DEFAULT_B_11N 0x85A | ||
64 | #define DM_REG_BB_PWR_SAV3_11N 0x85C | ||
65 | #define DM_REG_ANTSEL_CTRL_11N 0x860 | ||
66 | #define DM_REG_RX_ANT_CTRL_11N 0x864 | ||
67 | #define DM_REG_PIN_CTRL_11N 0x870 | ||
68 | #define DM_REG_BB_PWR_SAV1_11N 0x874 | ||
69 | #define DM_REG_ANTSEL_PATH_11N 0x878 | ||
70 | #define DM_REG_BB_3WIRE_11N 0x88C | ||
71 | #define DM_REG_SC_CNT_11N 0x8C4 | ||
72 | #define DM_REG_PSD_DATA_11N 0x8B4 | ||
73 | /*PAGE 9*/ | ||
74 | #define DM_REG_ANT_MAPPING1_11N 0x914 | ||
75 | #define DM_REG_ANT_MAPPING2_11N 0x918 | ||
76 | /*PAGE A*/ | ||
77 | #define DM_REG_CCK_ANTDIV_PARA1_11N 0xA00 | ||
78 | #define DM_REG_CCK_CCA_11N 0xA0A | ||
79 | #define DM_REG_CCK_ANTDIV_PARA2_11N 0xA0C | ||
80 | #define DM_REG_CCK_ANTDIV_PARA3_11N 0xA10 | ||
81 | #define DM_REG_CCK_ANTDIV_PARA4_11N 0xA14 | ||
82 | #define DM_REG_CCK_FILTER_PARA1_11N 0xA22 | ||
83 | #define DM_REG_CCK_FILTER_PARA2_11N 0xA23 | ||
84 | #define DM_REG_CCK_FILTER_PARA3_11N 0xA24 | ||
85 | #define DM_REG_CCK_FILTER_PARA4_11N 0xA25 | ||
86 | #define DM_REG_CCK_FILTER_PARA5_11N 0xA26 | ||
87 | #define DM_REG_CCK_FILTER_PARA6_11N 0xA27 | ||
88 | #define DM_REG_CCK_FILTER_PARA7_11N 0xA28 | ||
89 | #define DM_REG_CCK_FILTER_PARA8_11N 0xA29 | ||
90 | #define DM_REG_CCK_FA_RST_11N 0xA2C | ||
91 | #define DM_REG_CCK_FA_MSB_11N 0xA58 | ||
92 | #define DM_REG_CCK_FA_LSB_11N 0xA5C | ||
93 | #define DM_REG_CCK_CCA_CNT_11N 0xA60 | ||
94 | #define DM_REG_BB_PWR_SAV4_11N 0xA74 | ||
95 | /*PAGE B */ | ||
96 | #define DM_REG_LNA_SWITCH_11N 0xB2C | ||
97 | #define DM_REG_PATH_SWITCH_11N 0xB30 | ||
98 | #define DM_REG_RSSI_CTRL_11N 0xB38 | ||
99 | #define DM_REG_CONFIG_ANTA_11N 0xB68 | ||
100 | #define DM_REG_RSSI_BT_11N 0xB9C | ||
101 | /*PAGE C */ | ||
102 | #define DM_REG_OFDM_FA_HOLDC_11N 0xC00 | ||
103 | #define DM_REG_RX_PATH_11N 0xC04 | ||
104 | #define DM_REG_TRMUX_11N 0xC08 | ||
105 | #define DM_REG_OFDM_FA_RSTC_11N 0xC0C | ||
106 | #define DM_REG_RXIQI_MATRIX_11N 0xC14 | ||
107 | #define DM_REG_TXIQK_MATRIX_LSB1_11N 0xC4C | ||
108 | #define DM_REG_IGI_A_11N 0xC50 | ||
109 | #define DM_REG_ANTDIV_PARA2_11N 0xC54 | ||
110 | #define DM_REG_IGI_B_11N 0xC58 | ||
111 | #define DM_REG_ANTDIV_PARA3_11N 0xC5C | ||
112 | #define DM_REG_BB_PWR_SAV2_11N 0xC70 | ||
113 | #define DM_REG_RX_OFF_11N 0xC7C | ||
114 | #define DM_REG_TXIQK_MATRIXA_11N 0xC80 | ||
115 | #define DM_REG_TXIQK_MATRIXB_11N 0xC88 | ||
116 | #define DM_REG_TXIQK_MATRIXA_LSB2_11N 0xC94 | ||
117 | #define DM_REG_TXIQK_MATRIXB_LSB2_11N 0xC9C | ||
118 | #define DM_REG_RXIQK_MATRIX_LSB_11N 0xCA0 | ||
119 | #define DM_REG_ANTDIV_PARA1_11N 0xCA4 | ||
120 | #define DM_REG_OFDM_FA_TYPE1_11N 0xCF0 | ||
121 | /*PAGE D */ | ||
122 | #define DM_REG_OFDM_FA_RSTD_11N 0xD00 | ||
123 | #define DM_REG_OFDM_FA_TYPE2_11N 0xDA0 | ||
124 | #define DM_REG_OFDM_FA_TYPE3_11N 0xDA4 | ||
125 | #define DM_REG_OFDM_FA_TYPE4_11N 0xDA8 | ||
126 | /*PAGE E */ | ||
127 | #define DM_REG_TXAGC_A_6_18_11N 0xE00 | ||
128 | #define DM_REG_TXAGC_A_24_54_11N 0xE04 | ||
129 | #define DM_REG_TXAGC_A_1_MCS32_11N 0xE08 | ||
130 | #define DM_REG_TXAGC_A_MCS0_3_11N 0xE10 | ||
131 | #define DM_REG_TXAGC_A_MCS4_7_11N 0xE14 | ||
132 | #define DM_REG_TXAGC_A_MCS8_11_11N 0xE18 | ||
133 | #define DM_REG_TXAGC_A_MCS12_15_11N 0xE1C | ||
134 | #define DM_REG_FPGA0_IQK_11N 0xE28 | ||
135 | #define DM_REG_TXIQK_TONE_A_11N 0xE30 | ||
136 | #define DM_REG_RXIQK_TONE_A_11N 0xE34 | ||
137 | #define DM_REG_TXIQK_PI_A_11N 0xE38 | ||
138 | #define DM_REG_RXIQK_PI_A_11N 0xE3C | ||
139 | #define DM_REG_TXIQK_11N 0xE40 | ||
140 | #define DM_REG_RXIQK_11N 0xE44 | ||
141 | #define DM_REG_IQK_AGC_PTS_11N 0xE48 | ||
142 | #define DM_REG_IQK_AGC_RSP_11N 0xE4C | ||
143 | #define DM_REG_BLUETOOTH_11N 0xE6C | ||
144 | #define DM_REG_RX_WAIT_CCA_11N 0xE70 | ||
145 | #define DM_REG_TX_CCK_RFON_11N 0xE74 | ||
146 | #define DM_REG_TX_CCK_BBON_11N 0xE78 | ||
147 | #define DM_REG_OFDM_RFON_11N 0xE7C | ||
148 | #define DM_REG_OFDM_BBON_11N 0xE80 | ||
149 | #define DM_REG_TX2RX_11N 0xE84 | ||
150 | #define DM_REG_TX2TX_11N 0xE88 | ||
151 | #define DM_REG_RX_CCK_11N 0xE8C | ||
152 | #define DM_REG_RX_OFDM_11N 0xED0 | ||
153 | #define DM_REG_RX_WAIT_RIFS_11N 0xED4 | ||
154 | #define DM_REG_RX2RX_11N 0xED8 | ||
155 | #define DM_REG_STANDBY_11N 0xEDC | ||
156 | #define DM_REG_SLEEP_11N 0xEE0 | ||
157 | #define DM_REG_PMPD_ANAEN_11N 0xEEC | ||
158 | |||
159 | |||
160 | /*MAC REG LIST*/ | ||
161 | #define DM_REG_BB_RST_11N 0x02 | ||
162 | #define DM_REG_ANTSEL_PIN_11N 0x4C | ||
163 | #define DM_REG_EARLY_MODE_11N 0x4D0 | ||
164 | #define DM_REG_RSSI_MONITOR_11N 0x4FE | ||
165 | #define DM_REG_EDCA_VO_11N 0x500 | ||
166 | #define DM_REG_EDCA_VI_11N 0x504 | ||
167 | #define DM_REG_EDCA_BE_11N 0x508 | ||
168 | #define DM_REG_EDCA_BK_11N 0x50C | ||
169 | #define DM_REG_TXPAUSE_11N 0x522 | ||
170 | #define DM_REG_RESP_TX_11N 0x6D8 | ||
171 | #define DM_REG_ANT_TRAIN_1 0x7b0 | ||
172 | #define DM_REG_ANT_TRAIN_2 0x7b4 | ||
173 | |||
174 | /*DIG Related*/ | ||
175 | #define DM_BIT_IGI_11N 0x0000007F | ||
176 | |||
177 | #define HAL_DM_DIG_DISABLE BIT(0) | ||
178 | #define HAL_DM_HIPWR_DISABLE BIT(1) | ||
179 | |||
180 | #define OFDM_TABLE_LENGTH 43 | ||
181 | #define CCK_TABLE_LENGTH 33 | ||
182 | |||
183 | #define OFDM_TABLE_SIZE 43 | ||
184 | #define CCK_TABLE_SIZE 33 | ||
185 | |||
186 | #define BW_AUTO_SWITCH_HIGH_LOW 25 | ||
187 | #define BW_AUTO_SWITCH_LOW_HIGH 30 | ||
188 | |||
189 | #define DM_DIG_THRESH_HIGH 40 | ||
190 | #define DM_DIG_THRESH_LOW 35 | ||
191 | |||
192 | #define DM_FALSEALARM_THRESH_LOW 400 | ||
193 | #define DM_FALSEALARM_THRESH_HIGH 1000 | ||
194 | |||
195 | #define DM_DIG_MAX 0x3e | ||
196 | #define DM_DIG_MIN 0x1e | ||
197 | |||
198 | #define DM_DIG_MAX_AP 0x32 | ||
199 | #define DM_DIG_MIN_AP 0x20 | ||
200 | |||
201 | #define DM_DIG_FA_UPPER 0x3e | ||
202 | #define DM_DIG_FA_LOWER 0x1e | ||
203 | #define DM_DIG_FA_TH0 0x200 | ||
204 | #define DM_DIG_FA_TH1 0x300 | ||
205 | #define DM_DIG_FA_TH2 0x400 | ||
206 | |||
207 | #define DM_DIG_BACKOFF_MAX 12 | ||
208 | #define DM_DIG_BACKOFF_MIN -4 | ||
209 | #define DM_DIG_BACKOFF_DEFAULT 10 | ||
210 | |||
211 | #define RXPATHSELECTION_SS_TH_LOW 30 | ||
212 | #define RXPATHSELECTION_DIFF_TH 18 | ||
213 | |||
214 | #define DM_RATR_STA_INIT 0 | ||
215 | #define DM_RATR_STA_HIGH 1 | ||
216 | #define DM_RATR_STA_MIDDLE 2 | ||
217 | #define DM_RATR_STA_LOW 3 | ||
218 | |||
219 | #define CTS2SELF_THVAL 30 | ||
220 | #define REGC38_TH 20 | ||
221 | |||
222 | #define WAIOTTHVAL 25 | ||
223 | |||
224 | #define TXHIGHPWRLEVEL_NORMAL 0 | ||
225 | #define TXHIGHPWRLEVEL_LEVEL1 1 | ||
226 | #define TXHIGHPWRLEVEL_LEVEL2 2 | ||
227 | #define TXHIGHPWRLEVEL_BT1 3 | ||
228 | #define TXHIGHPWRLEVEL_BT2 4 | ||
229 | |||
230 | #define DM_TYPE_BYFW 0 | ||
231 | #define DM_TYPE_BYDRIVER 1 | ||
232 | |||
233 | #define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 | ||
234 | #define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 | ||
235 | #define TXPWRTRACK_MAX_IDX 6 | ||
236 | |||
237 | struct swat_t { | ||
238 | u8 failure_cnt; | ||
239 | u8 try_flag; | ||
240 | u8 stop_trying; | ||
241 | long pre_rssi; | ||
242 | long trying_threshold; | ||
243 | u8 cur_antenna; | ||
244 | u8 pre_antenna; | ||
245 | }; | ||
246 | |||
247 | enum FAT_STATE { | ||
248 | FAT_NORMAL_STATE = 0, | ||
249 | FAT_TRAINING_STATE = 1, | ||
250 | }; | ||
251 | |||
252 | enum tag_dynamic_init_gain_operation_type_definition { | ||
253 | DIG_TYPE_THRESH_HIGH = 0, | ||
254 | DIG_TYPE_THRESH_LOW = 1, | ||
255 | DIG_TYPE_BACKOFF = 2, | ||
256 | DIG_TYPE_RX_GAIN_MIN = 3, | ||
257 | DIG_TYPE_RX_GAIN_MAX = 4, | ||
258 | DIG_TYPE_ENABLE = 5, | ||
259 | DIG_TYPE_DISABLE = 6, | ||
260 | DIG_OP_TYPE_MAX | ||
261 | }; | ||
262 | |||
263 | enum tag_cck_packet_detection_threshold_type_definition { | ||
264 | CCK_PD_STAGE_LOWRSSI = 0, | ||
265 | CCK_PD_STAGE_HIGHRSSI = 1, | ||
266 | CCK_FA_STAGE_LOW = 2, | ||
267 | CCK_FA_STAGE_HIGH = 3, | ||
268 | CCK_PD_STAGE_MAX = 4, | ||
269 | }; | ||
270 | |||
271 | enum dm_1r_cca_e { | ||
272 | CCA_1R = 0, | ||
273 | CCA_2R = 1, | ||
274 | CCA_MAX = 2, | ||
275 | }; | ||
276 | |||
277 | enum dm_rf_e { | ||
278 | RF_SAVE = 0, | ||
279 | RF_NORMAL = 1, | ||
280 | RF_MAX = 2, | ||
281 | }; | ||
282 | |||
283 | enum dm_sw_ant_switch_e { | ||
284 | ANS_ANTENNA_B = 1, | ||
285 | ANS_ANTENNA_A = 2, | ||
286 | ANS_ANTENNA_MAX = 3, | ||
287 | }; | ||
288 | |||
289 | enum dm_dig_ext_port_alg_e { | ||
290 | DIG_EXT_PORT_STAGE_0 = 0, | ||
291 | DIG_EXT_PORT_STAGE_1 = 1, | ||
292 | DIG_EXT_PORT_STAGE_2 = 2, | ||
293 | DIG_EXT_PORT_STAGE_3 = 3, | ||
294 | DIG_EXT_PORT_STAGE_MAX = 4, | ||
295 | }; | ||
296 | |||
297 | enum dm_dig_connect_e { | ||
298 | DIG_STA_DISCONNECT = 0, | ||
299 | DIG_STA_CONNECT = 1, | ||
300 | DIG_STA_BEFORE_CONNECT = 2, | ||
301 | DIG_MULTISTA_DISCONNECT = 3, | ||
302 | DIG_MULTISTA_CONNECT = 4, | ||
303 | DIG_CONNECT_MAX | ||
304 | }; | ||
305 | |||
306 | enum pwr_track_control_method { | ||
307 | BBSWING, | ||
308 | TXAGC | ||
309 | }; | ||
310 | |||
311 | void rtl88e_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw, | ||
312 | u8 *pdesc, u32 mac_id); | ||
313 | void rtl88e_dm_ant_sel_statistics(struct ieee80211_hw *hw, u8 antsel_tr_mux, | ||
314 | u32 mac_id, u32 rx_pwdb_all); | ||
315 | void rtl88e_dm_fast_antenna_training_callback(unsigned long data); | ||
316 | void rtl88e_dm_init(struct ieee80211_hw *hw); | ||
317 | void rtl88e_dm_watchdog(struct ieee80211_hw *hw); | ||
318 | void rtl88e_dm_write_dig(struct ieee80211_hw *hw); | ||
319 | void rtl88e_dm_init_edca_turbo(struct ieee80211_hw *hw); | ||
320 | void rtl88e_dm_check_txpower_tracking(struct ieee80211_hw *hw); | ||
321 | void rtl88e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw); | ||
322 | void rtl88e_dm_txpower_track_adjust(struct ieee80211_hw *hw, | ||
323 | u8 type, u8 *pdirection, | ||
324 | u32 *poutwrite_val); | ||
325 | |||
326 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c new file mode 100644 index 000000000000..57e4cc5833a9 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c | |||
@@ -0,0 +1,830 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "../wifi.h" | ||
31 | #include "../pci.h" | ||
32 | #include "../base.h" | ||
33 | #include "reg.h" | ||
34 | #include "def.h" | ||
35 | #include "fw.h" | ||
36 | |||
37 | #include <linux/kmemleak.h> | ||
38 | |||
39 | static void _rtl88e_enable_fw_download(struct ieee80211_hw *hw, bool enable) | ||
40 | { | ||
41 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
42 | u8 tmp; | ||
43 | |||
44 | if (enable) { | ||
45 | tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); | ||
46 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04); | ||
47 | |||
48 | tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); | ||
49 | rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01); | ||
50 | |||
51 | tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); | ||
52 | rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); | ||
53 | } else { | ||
54 | tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); | ||
55 | rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); | ||
56 | |||
57 | rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00); | ||
58 | } | ||
59 | } | ||
60 | |||
61 | static void _rtl88e_fw_block_write(struct ieee80211_hw *hw, | ||
62 | const u8 *buffer, u32 size) | ||
63 | { | ||
64 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
65 | u32 blk_sz = sizeof(u32); | ||
66 | u8 *buf_ptr = (u8 *)buffer; | ||
67 | u32 *pu4BytePtr = (u32 *)buffer; | ||
68 | u32 i, offset, blk_cnt, remain; | ||
69 | |||
70 | blk_cnt = size / blk_sz; | ||
71 | remain = size % blk_sz; | ||
72 | |||
73 | for (i = 0; i < blk_cnt; i++) { | ||
74 | offset = i * blk_sz; | ||
75 | rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset), | ||
76 | *(pu4BytePtr + i)); | ||
77 | } | ||
78 | |||
79 | if (remain) { | ||
80 | offset = blk_cnt * blk_sz; | ||
81 | buf_ptr += offset; | ||
82 | for (i = 0; i < remain; i++) { | ||
83 | rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS + | ||
84 | offset + i), *(buf_ptr + i)); | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | |||
89 | static void _rtl88e_fw_page_write(struct ieee80211_hw *hw, | ||
90 | u32 page, const u8 *buffer, u32 size) | ||
91 | { | ||
92 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
93 | u8 value8; | ||
94 | u8 u8page = (u8) (page & 0x07); | ||
95 | |||
96 | value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page; | ||
97 | |||
98 | rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8); | ||
99 | _rtl88e_fw_block_write(hw, buffer, size); | ||
100 | } | ||
101 | |||
102 | static void _rtl88e_fill_dummy(u8 *pfwbuf, u32 *pfwlen) | ||
103 | { | ||
104 | u32 fwlen = *pfwlen; | ||
105 | u8 remain = (u8) (fwlen % 4); | ||
106 | |||
107 | remain = (remain == 0) ? 0 : (4 - remain); | ||
108 | |||
109 | while (remain > 0) { | ||
110 | pfwbuf[fwlen] = 0; | ||
111 | fwlen++; | ||
112 | remain--; | ||
113 | } | ||
114 | |||
115 | *pfwlen = fwlen; | ||
116 | } | ||
117 | |||
118 | static void _rtl88e_write_fw(struct ieee80211_hw *hw, | ||
119 | enum version_8188e version, u8 *buffer, u32 size) | ||
120 | { | ||
121 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
122 | u8 *buf_ptr = (u8 *)buffer; | ||
123 | u32 page_no, remain; | ||
124 | u32 page, offset; | ||
125 | |||
126 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "FW size is %d bytes,\n", size); | ||
127 | |||
128 | _rtl88e_fill_dummy(buf_ptr, &size); | ||
129 | |||
130 | page_no = size / FW_8192C_PAGE_SIZE; | ||
131 | remain = size % FW_8192C_PAGE_SIZE; | ||
132 | |||
133 | if (page_no > 8) { | ||
134 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
135 | "Page numbers should not greater then 8\n"); | ||
136 | } | ||
137 | |||
138 | for (page = 0; page < page_no; page++) { | ||
139 | offset = page * FW_8192C_PAGE_SIZE; | ||
140 | _rtl88e_fw_page_write(hw, page, (buf_ptr + offset), | ||
141 | FW_8192C_PAGE_SIZE); | ||
142 | } | ||
143 | |||
144 | if (remain) { | ||
145 | offset = page_no * FW_8192C_PAGE_SIZE; | ||
146 | page = page_no; | ||
147 | _rtl88e_fw_page_write(hw, page, (buf_ptr + offset), remain); | ||
148 | } | ||
149 | } | ||
150 | |||
151 | static int _rtl88e_fw_free_to_go(struct ieee80211_hw *hw) | ||
152 | { | ||
153 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
154 | int err = -EIO; | ||
155 | u32 counter = 0; | ||
156 | u32 value32; | ||
157 | |||
158 | do { | ||
159 | value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); | ||
160 | } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) && | ||
161 | (!(value32 & FWDL_CHKSUM_RPT))); | ||
162 | |||
163 | if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) { | ||
164 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
165 | "chksum report faill ! REG_MCUFWDL:0x%08x .\n", | ||
166 | value32); | ||
167 | goto exit; | ||
168 | } | ||
169 | |||
170 | RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, | ||
171 | "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32); | ||
172 | |||
173 | value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); | ||
174 | value32 |= MCUFWDL_RDY; | ||
175 | value32 &= ~WINTINI_RDY; | ||
176 | rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); | ||
177 | |||
178 | rtl88e_firmware_selfreset(hw); | ||
179 | counter = 0; | ||
180 | |||
181 | do { | ||
182 | value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); | ||
183 | if (value32 & WINTINI_RDY) { | ||
184 | RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, | ||
185 | "Polling FW ready success!! REG_MCUFWDL:0x%08x.\n", | ||
186 | value32); | ||
187 | err = 0; | ||
188 | goto exit; | ||
189 | } | ||
190 | |||
191 | udelay(FW_8192C_POLLING_DELAY); | ||
192 | |||
193 | } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT); | ||
194 | |||
195 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
196 | "Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32); | ||
197 | |||
198 | exit: | ||
199 | return err; | ||
200 | } | ||
201 | |||
202 | int rtl88e_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw) | ||
203 | { | ||
204 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
205 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
206 | struct rtl92c_firmware_header *pfwheader; | ||
207 | u8 *pfwdata; | ||
208 | u32 fwsize; | ||
209 | int err; | ||
210 | enum version_8188e version = rtlhal->version; | ||
211 | |||
212 | if (!rtlhal->pfirmware) | ||
213 | return 1; | ||
214 | |||
215 | pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware; | ||
216 | pfwdata = (u8 *)rtlhal->pfirmware; | ||
217 | fwsize = rtlhal->fwsize; | ||
218 | RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, | ||
219 | "normal Firmware SIZE %d\n", fwsize); | ||
220 | |||
221 | if (IS_FW_HEADER_EXIST(pfwheader)) { | ||
222 | RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, | ||
223 | "Firmware Version(%d), Signature(%#x), Size(%d)\n", | ||
224 | pfwheader->version, pfwheader->signature, | ||
225 | (int)sizeof(struct rtl92c_firmware_header)); | ||
226 | |||
227 | pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header); | ||
228 | fwsize = fwsize - sizeof(struct rtl92c_firmware_header); | ||
229 | } | ||
230 | |||
231 | if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) { | ||
232 | rtl_write_byte(rtlpriv, REG_MCUFWDL, 0); | ||
233 | rtl88e_firmware_selfreset(hw); | ||
234 | } | ||
235 | _rtl88e_enable_fw_download(hw, true); | ||
236 | _rtl88e_write_fw(hw, version, pfwdata, fwsize); | ||
237 | _rtl88e_enable_fw_download(hw, false); | ||
238 | |||
239 | err = _rtl88e_fw_free_to_go(hw); | ||
240 | |||
241 | RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, | ||
242 | "Firmware is%s ready to run!\n", err ? " not" : ""); | ||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static bool _rtl88e_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum) | ||
247 | { | ||
248 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
249 | u8 val_hmetfr; | ||
250 | |||
251 | val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); | ||
252 | if (((val_hmetfr >> boxnum) & BIT(0)) == 0) | ||
253 | return true; | ||
254 | return false; | ||
255 | } | ||
256 | |||
257 | static void _rtl88e_fill_h2c_command(struct ieee80211_hw *hw, | ||
258 | u8 element_id, u32 cmd_len, | ||
259 | u8 *cmd_b) | ||
260 | { | ||
261 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
262 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
263 | u8 boxnum; | ||
264 | u16 box_reg = 0, box_extreg = 0; | ||
265 | u8 u1b_tmp; | ||
266 | bool isfw_read = false; | ||
267 | u8 buf_index = 0; | ||
268 | bool write_sucess = false; | ||
269 | u8 wait_h2c_limit = 100; | ||
270 | u8 wait_writeh2c_limit = 100; | ||
271 | u8 boxc[4], boxext[2]; | ||
272 | u32 h2c_waitcounter = 0; | ||
273 | unsigned long flag; | ||
274 | u8 idx; | ||
275 | |||
276 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n"); | ||
277 | |||
278 | while (true) { | ||
279 | spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); | ||
280 | if (rtlhal->h2c_setinprogress) { | ||
281 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | ||
282 | "H2C set in progress! Wait to set..element_id(%d).\n", | ||
283 | element_id); | ||
284 | |||
285 | while (rtlhal->h2c_setinprogress) { | ||
286 | spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, | ||
287 | flag); | ||
288 | h2c_waitcounter++; | ||
289 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | ||
290 | "Wait 100 us (%d times)...\n", | ||
291 | h2c_waitcounter); | ||
292 | udelay(100); | ||
293 | |||
294 | if (h2c_waitcounter > 1000) | ||
295 | return; | ||
296 | spin_lock_irqsave(&rtlpriv->locks.h2c_lock, | ||
297 | flag); | ||
298 | } | ||
299 | spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); | ||
300 | } else { | ||
301 | rtlhal->h2c_setinprogress = true; | ||
302 | spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); | ||
303 | break; | ||
304 | } | ||
305 | } | ||
306 | |||
307 | while (!write_sucess) { | ||
308 | wait_writeh2c_limit--; | ||
309 | if (wait_writeh2c_limit == 0) { | ||
310 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
311 | "Write H2C fail because no trigger for FW INT!\n"); | ||
312 | break; | ||
313 | } | ||
314 | |||
315 | boxnum = rtlhal->last_hmeboxnum; | ||
316 | switch (boxnum) { | ||
317 | case 0: | ||
318 | box_reg = REG_HMEBOX_0; | ||
319 | box_extreg = REG_HMEBOX_EXT_0; | ||
320 | break; | ||
321 | case 1: | ||
322 | box_reg = REG_HMEBOX_1; | ||
323 | box_extreg = REG_HMEBOX_EXT_1; | ||
324 | break; | ||
325 | case 2: | ||
326 | box_reg = REG_HMEBOX_2; | ||
327 | box_extreg = REG_HMEBOX_EXT_2; | ||
328 | break; | ||
329 | case 3: | ||
330 | box_reg = REG_HMEBOX_3; | ||
331 | box_extreg = REG_HMEBOX_EXT_3; | ||
332 | break; | ||
333 | default: | ||
334 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
335 | "switch case not processed\n"); | ||
336 | break; | ||
337 | } | ||
338 | |||
339 | isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum); | ||
340 | while (!isfw_read) { | ||
341 | wait_h2c_limit--; | ||
342 | if (wait_h2c_limit == 0) { | ||
343 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | ||
344 | "Wating too long for FW read " | ||
345 | "clear HMEBox(%d)!\n", boxnum); | ||
346 | break; | ||
347 | } | ||
348 | |||
349 | udelay(10); | ||
350 | |||
351 | isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum); | ||
352 | u1b_tmp = rtl_read_byte(rtlpriv, 0x130); | ||
353 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | ||
354 | "Wating for FW read clear HMEBox(%d)!!! " | ||
355 | "0x130 = %2x\n", boxnum, u1b_tmp); | ||
356 | } | ||
357 | |||
358 | if (!isfw_read) { | ||
359 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | ||
360 | "Write H2C register BOX[%d] fail!!!!! " | ||
361 | "Fw do not read.\n", boxnum); | ||
362 | break; | ||
363 | } | ||
364 | |||
365 | memset(boxc, 0, sizeof(boxc)); | ||
366 | memset(boxext, 0, sizeof(boxext)); | ||
367 | boxc[0] = element_id; | ||
368 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | ||
369 | "Write element_id box_reg(%4x) = %2x\n", | ||
370 | box_reg, element_id); | ||
371 | |||
372 | switch (cmd_len) { | ||
373 | case 1: | ||
374 | case 2: | ||
375 | case 3: | ||
376 | /*boxc[0] &= ~(BIT(7));*/ | ||
377 | memcpy((u8 *)(boxc) + 1, cmd_b + buf_index, cmd_len); | ||
378 | |||
379 | for (idx = 0; idx < 4; idx++) | ||
380 | rtl_write_byte(rtlpriv, box_reg+idx, boxc[idx]); | ||
381 | break; | ||
382 | case 4: | ||
383 | case 5: | ||
384 | case 6: | ||
385 | case 7: | ||
386 | /*boxc[0] |= (BIT(7));*/ | ||
387 | memcpy((u8 *)(boxext), cmd_b + buf_index+3, cmd_len-3); | ||
388 | memcpy((u8 *)(boxc) + 1, cmd_b + buf_index, 3); | ||
389 | |||
390 | for (idx = 0; idx < 2; idx++) { | ||
391 | rtl_write_byte(rtlpriv, box_extreg + idx, | ||
392 | boxext[idx]); | ||
393 | } | ||
394 | |||
395 | for (idx = 0; idx < 4; idx++) { | ||
396 | rtl_write_byte(rtlpriv, box_reg + idx, | ||
397 | boxc[idx]); | ||
398 | } | ||
399 | break; | ||
400 | default: | ||
401 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
402 | "switch case not processed\n"); | ||
403 | break; | ||
404 | } | ||
405 | |||
406 | write_sucess = true; | ||
407 | |||
408 | rtlhal->last_hmeboxnum = boxnum + 1; | ||
409 | if (rtlhal->last_hmeboxnum == 4) | ||
410 | rtlhal->last_hmeboxnum = 0; | ||
411 | |||
412 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | ||
413 | "pHalData->last_hmeboxnum = %d\n", | ||
414 | rtlhal->last_hmeboxnum); | ||
415 | } | ||
416 | |||
417 | spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); | ||
418 | rtlhal->h2c_setinprogress = false; | ||
419 | spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); | ||
420 | |||
421 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n"); | ||
422 | } | ||
423 | |||
424 | void rtl88e_fill_h2c_cmd(struct ieee80211_hw *hw, | ||
425 | u8 element_id, u32 cmd_len, u8 *cmd_b) | ||
426 | { | ||
427 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
428 | u32 tmp_cmdbuf[2]; | ||
429 | |||
430 | if (rtlhal->fw_ready == false) { | ||
431 | RT_ASSERT(false, "fail H2C cmd - Fw download fail!!!\n"); | ||
432 | return; | ||
433 | } | ||
434 | |||
435 | memset(tmp_cmdbuf, 0, 8); | ||
436 | memcpy(tmp_cmdbuf, cmd_b, cmd_len); | ||
437 | _rtl88e_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); | ||
438 | |||
439 | return; | ||
440 | } | ||
441 | |||
442 | void rtl88e_firmware_selfreset(struct ieee80211_hw *hw) | ||
443 | { | ||
444 | u8 u1b_tmp; | ||
445 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
446 | |||
447 | u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1); | ||
448 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp & (~BIT(2)))); | ||
449 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp | BIT(2))); | ||
450 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
451 | "8051Reset88E(): 8051 reset success.\n"); | ||
452 | } | ||
453 | |||
454 | void rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) | ||
455 | { | ||
456 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
457 | u8 u1_h2c_set_pwrmode[H2C_88E_PWEMODE_LENGTH] = { 0 }; | ||
458 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
459 | u8 power_state = 0; | ||
460 | |||
461 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); | ||
462 | SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0)); | ||
463 | SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, 0); | ||
464 | SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, | ||
465 | (rtlpriv->mac80211.p2p) ? | ||
466 | ppsc->smart_ps : 1); | ||
467 | SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode, | ||
468 | ppsc->reg_max_lps_awakeintvl); | ||
469 | SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0); | ||
470 | if (mode == FW_PS_ACTIVE_MODE) | ||
471 | power_state |= FW_PWR_STATE_ACTIVE; | ||
472 | else | ||
473 | power_state |= FW_PWR_STATE_RF_OFF; | ||
474 | SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state); | ||
475 | |||
476 | RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, | ||
477 | "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n", | ||
478 | u1_h2c_set_pwrmode, H2C_88E_PWEMODE_LENGTH); | ||
479 | rtl88e_fill_h2c_cmd(hw, H2C_88E_SETPWRMODE, H2C_88E_PWEMODE_LENGTH, | ||
480 | u1_h2c_set_pwrmode); | ||
481 | } | ||
482 | |||
483 | void rtl88e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus) | ||
484 | { | ||
485 | u8 u1_joinbssrpt_parm[1] = { 0 }; | ||
486 | |||
487 | SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus); | ||
488 | |||
489 | rtl88e_fill_h2c_cmd(hw, H2C_88E_JOINBSSRPT, 1, u1_joinbssrpt_parm); | ||
490 | } | ||
491 | |||
492 | void rtl88e_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw, | ||
493 | u8 ap_offload_enable) | ||
494 | { | ||
495 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
496 | u8 u1_apoffload_parm[H2C_88E_AP_OFFLOAD_LENGTH] = { 0 }; | ||
497 | |||
498 | SET_H2CCMD_AP_OFFLOAD_ON(u1_apoffload_parm, ap_offload_enable); | ||
499 | SET_H2CCMD_AP_OFFLOAD_HIDDEN(u1_apoffload_parm, mac->hiddenssid); | ||
500 | SET_H2CCMD_AP_OFFLOAD_DENYANY(u1_apoffload_parm, 0); | ||
501 | |||
502 | rtl88e_fill_h2c_cmd(hw, H2C_88E_AP_OFFLOAD, H2C_88E_AP_OFFLOAD_LENGTH, | ||
503 | u1_apoffload_parm); | ||
504 | } | ||
505 | |||
506 | static bool _rtl88e_cmd_send_packet(struct ieee80211_hw *hw, | ||
507 | struct sk_buff *skb) | ||
508 | { | ||
509 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
510 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
511 | struct rtl8192_tx_ring *ring; | ||
512 | struct rtl_tx_desc *pdesc; | ||
513 | struct sk_buff *pskb = NULL; | ||
514 | unsigned long flags; | ||
515 | |||
516 | ring = &rtlpci->tx_ring[BEACON_QUEUE]; | ||
517 | |||
518 | pskb = __skb_dequeue(&ring->queue); | ||
519 | if (pskb) | ||
520 | kfree_skb(pskb); | ||
521 | |||
522 | spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); | ||
523 | |||
524 | pdesc = &ring->desc[0]; | ||
525 | |||
526 | rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb); | ||
527 | |||
528 | __skb_queue_tail(&ring->queue, skb); | ||
529 | |||
530 | spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); | ||
531 | |||
532 | rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE); | ||
533 | |||
534 | return true; | ||
535 | } | ||
536 | |||
537 | #define BEACON_PG 0 /* ->1 */ | ||
538 | #define PSPOLL_PG 2 | ||
539 | #define NULL_PG 3 | ||
540 | #define PROBERSP_PG 4 /* ->5 */ | ||
541 | |||
542 | #define TOTAL_RESERVED_PKT_LEN 768 | ||
543 | |||
544 | static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { | ||
545 | /* page 0 beacon */ | ||
546 | 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, | ||
547 | 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, | ||
548 | 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08, | ||
549 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
550 | 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, | ||
551 | 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, | ||
552 | 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, | ||
553 | 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, | ||
554 | 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, | ||
555 | 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, | ||
556 | 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
557 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
558 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
559 | 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, | ||
560 | 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
561 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
562 | |||
563 | /* page 1 beacon */ | ||
564 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
565 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
566 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
567 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
568 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
569 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
570 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
571 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
572 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
573 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
574 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
575 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
576 | 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00, | ||
577 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
578 | 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
579 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
580 | |||
581 | /* page 2 ps-poll */ | ||
582 | 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10, | ||
583 | 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, | ||
584 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
585 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
586 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
587 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
588 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
589 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
590 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
591 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
592 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
593 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
594 | 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, | ||
595 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, | ||
596 | 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
597 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
598 | |||
599 | /* page 3 null */ | ||
600 | 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, | ||
601 | 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, | ||
602 | 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, | ||
603 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
604 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
605 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
606 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
607 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
608 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
609 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
610 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
611 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
612 | 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, | ||
613 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, | ||
614 | 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
615 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
616 | |||
617 | /* page 4 probe_resp */ | ||
618 | 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, | ||
619 | 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, | ||
620 | 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, | ||
621 | 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, | ||
622 | 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, | ||
623 | 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, | ||
624 | 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, | ||
625 | 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, | ||
626 | 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, | ||
627 | 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, | ||
628 | 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
629 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
630 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
631 | 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, | ||
632 | 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
633 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
634 | |||
635 | /* page 5 probe_resp */ | ||
636 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
637 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
638 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
639 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
640 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
641 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
642 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
643 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
644 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
645 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
646 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
647 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
648 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
649 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
650 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
651 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
652 | }; | ||
653 | |||
654 | void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) | ||
655 | { | ||
656 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
657 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
658 | struct sk_buff *skb = NULL; | ||
659 | |||
660 | u32 totalpacketlen; | ||
661 | u8 u1RsvdPageLoc[5] = { 0 }; | ||
662 | |||
663 | u8 *beacon; | ||
664 | u8 *pspoll; | ||
665 | u8 *nullfunc; | ||
666 | u8 *probersp; | ||
667 | /*--------------------------------------------------------- | ||
668 | * (1) beacon | ||
669 | *--------------------------------------------------------- | ||
670 | */ | ||
671 | beacon = &reserved_page_packet[BEACON_PG * 128]; | ||
672 | SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); | ||
673 | SET_80211_HDR_ADDRESS3(beacon, mac->bssid); | ||
674 | |||
675 | /*------------------------------------------------------- | ||
676 | * (2) ps-poll | ||
677 | *-------------------------------------------------------- | ||
678 | */ | ||
679 | pspoll = &reserved_page_packet[PSPOLL_PG * 128]; | ||
680 | SET_80211_PS_POLL_AID(pspoll, (mac->assoc_id | 0xc000)); | ||
681 | SET_80211_PS_POLL_BSSID(pspoll, mac->bssid); | ||
682 | SET_80211_PS_POLL_TA(pspoll, mac->mac_addr); | ||
683 | |||
684 | SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG); | ||
685 | |||
686 | /*-------------------------------------------------------- | ||
687 | * (3) null data | ||
688 | *--------------------------------------------------------- | ||
689 | */ | ||
690 | nullfunc = &reserved_page_packet[NULL_PG * 128]; | ||
691 | SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); | ||
692 | SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); | ||
693 | SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); | ||
694 | |||
695 | SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG); | ||
696 | |||
697 | /*--------------------------------------------------------- | ||
698 | * (4) probe response | ||
699 | *---------------------------------------------------------- | ||
700 | */ | ||
701 | probersp = &reserved_page_packet[PROBERSP_PG * 128]; | ||
702 | SET_80211_HDR_ADDRESS1(probersp, mac->bssid); | ||
703 | SET_80211_HDR_ADDRESS2(probersp, mac->mac_addr); | ||
704 | SET_80211_HDR_ADDRESS3(probersp, mac->bssid); | ||
705 | |||
706 | SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG); | ||
707 | |||
708 | totalpacketlen = TOTAL_RESERVED_PKT_LEN; | ||
709 | |||
710 | RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, | ||
711 | "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", | ||
712 | &reserved_page_packet[0], totalpacketlen); | ||
713 | RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, | ||
714 | "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", | ||
715 | u1RsvdPageLoc, 3); | ||
716 | |||
717 | skb = dev_alloc_skb(totalpacketlen); | ||
718 | if (!skb) | ||
719 | return; | ||
720 | kmemleak_not_leak(skb); | ||
721 | memcpy(skb_put(skb, totalpacketlen), | ||
722 | &reserved_page_packet, totalpacketlen); | ||
723 | |||
724 | if (_rtl88e_cmd_send_packet(hw, skb)) { | ||
725 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
726 | "Set RSVD page location to Fw.\n"); | ||
727 | RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, | ||
728 | "H2C_RSVDPAGE:\n", u1RsvdPageLoc, 3); | ||
729 | rtl88e_fill_h2c_cmd(hw, H2C_88E_RSVDPAGE, | ||
730 | sizeof(u1RsvdPageLoc), u1RsvdPageLoc); | ||
731 | } else | ||
732 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
733 | "Set RSVD page location to Fw FAIL!!!!!!.\n"); | ||
734 | } | ||
735 | |||
736 | /*Shoud check FW support p2p or not.*/ | ||
737 | static void rtl88e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow) | ||
738 | { | ||
739 | u8 u1_ctwindow_period[1] = {ctwindow}; | ||
740 | |||
741 | rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period); | ||
742 | } | ||
743 | |||
744 | void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) | ||
745 | { | ||
746 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
747 | struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); | ||
748 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
749 | struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info); | ||
750 | struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; | ||
751 | u8 i; | ||
752 | u16 ctwindow; | ||
753 | u32 start_time, tsf_low; | ||
754 | |||
755 | switch (p2p_ps_state) { | ||
756 | case P2P_PS_DISABLE: | ||
757 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n"); | ||
758 | memset(p2p_ps_offload, 0, sizeof(struct p2p_ps_offload_t)); | ||
759 | break; | ||
760 | case P2P_PS_ENABLE: | ||
761 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n"); | ||
762 | /* update CTWindow value. */ | ||
763 | if (p2pinfo->ctwindow > 0) { | ||
764 | p2p_ps_offload->ctwindow_en = 1; | ||
765 | ctwindow = p2pinfo->ctwindow; | ||
766 | rtl88e_set_p2p_ctw_period_cmd(hw, ctwindow); | ||
767 | } | ||
768 | /* hw only support 2 set of NoA */ | ||
769 | for (i = 0; i < p2pinfo->noa_num; i++) { | ||
770 | /* To control the register setting for which NOA*/ | ||
771 | rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); | ||
772 | if (i == 0) | ||
773 | p2p_ps_offload->noa0_en = 1; | ||
774 | else | ||
775 | p2p_ps_offload->noa1_en = 1; | ||
776 | |||
777 | /* config P2P NoA Descriptor Register */ | ||
778 | rtl_write_dword(rtlpriv, 0x5E0, | ||
779 | p2pinfo->noa_duration[i]); | ||
780 | rtl_write_dword(rtlpriv, 0x5E4, | ||
781 | p2pinfo->noa_interval[i]); | ||
782 | |||
783 | /*Get Current TSF value */ | ||
784 | tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); | ||
785 | |||
786 | start_time = p2pinfo->noa_start_time[i]; | ||
787 | if (p2pinfo->noa_count_type[i] != 1) { | ||
788 | while (start_time <= (tsf_low + (50 * 1024))) { | ||
789 | start_time += p2pinfo->noa_interval[i]; | ||
790 | if (p2pinfo->noa_count_type[i] != 255) | ||
791 | p2pinfo->noa_count_type[i]--; | ||
792 | } | ||
793 | } | ||
794 | rtl_write_dword(rtlpriv, 0x5E8, start_time); | ||
795 | rtl_write_dword(rtlpriv, 0x5EC, | ||
796 | p2pinfo->noa_count_type[i]); | ||
797 | } | ||
798 | |||
799 | if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) { | ||
800 | /* rst p2p circuit */ | ||
801 | rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); | ||
802 | |||
803 | p2p_ps_offload->offload_en = 1; | ||
804 | |||
805 | if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { | ||
806 | p2p_ps_offload->role = 1; | ||
807 | p2p_ps_offload->allstasleep = 0; | ||
808 | } else { | ||
809 | p2p_ps_offload->role = 0; | ||
810 | } | ||
811 | |||
812 | p2p_ps_offload->discovery = 0; | ||
813 | } | ||
814 | break; | ||
815 | case P2P_PS_SCAN: | ||
816 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n"); | ||
817 | p2p_ps_offload->discovery = 1; | ||
818 | break; | ||
819 | case P2P_PS_SCAN_DONE: | ||
820 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n"); | ||
821 | p2p_ps_offload->discovery = 0; | ||
822 | p2pinfo->p2p_ps_state = P2P_PS_ENABLE; | ||
823 | break; | ||
824 | default: | ||
825 | break; | ||
826 | } | ||
827 | |||
828 | rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_OFFLOAD, 1, | ||
829 | (u8 *)p2p_ps_offload); | ||
830 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/fw.h b/drivers/net/wireless/rtlwifi/rtl8188ee/fw.h new file mode 100644 index 000000000000..854a9875cd5f --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/fw.h | |||
@@ -0,0 +1,301 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
26 | * | ||
27 | *****************************************************************************/ | ||
28 | |||
29 | #ifndef __RTL92C__FW__H__ | ||
30 | #define __RTL92C__FW__H__ | ||
31 | |||
32 | #define FW_8192C_SIZE 0x8000 | ||
33 | #define FW_8192C_START_ADDRESS 0x1000 | ||
34 | #define FW_8192C_END_ADDRESS 0x5FFF | ||
35 | #define FW_8192C_PAGE_SIZE 4096 | ||
36 | #define FW_8192C_POLLING_DELAY 5 | ||
37 | #define FW_8192C_POLLING_TIMEOUT_COUNT 3000 | ||
38 | |||
39 | #define IS_FW_HEADER_EXIST(_pfwhdr) \ | ||
40 | ((_pfwhdr->signature&0xFFFF) == 0x88E1) | ||
41 | #define USE_OLD_WOWLAN_DEBUG_FW 0 | ||
42 | |||
43 | #define H2C_88E_RSVDPAGE_LOC_LEN 5 | ||
44 | #define H2C_88E_PWEMODE_LENGTH 5 | ||
45 | #define H2C_88E_JOINBSSRPT_LENGTH 1 | ||
46 | #define H2C_88E_AP_OFFLOAD_LENGTH 3 | ||
47 | #define H2C_88E_WOWLAN_LENGTH 3 | ||
48 | #define H2C_88E_KEEP_ALIVE_CTRL_LENGTH 3 | ||
49 | #if (USE_OLD_WOWLAN_DEBUG_FW == 0) | ||
50 | #define H2C_88E_REMOTE_WAKE_CTRL_LEN 1 | ||
51 | #else | ||
52 | #define H2C_88E_REMOTE_WAKE_CTRL_LEN 3 | ||
53 | #endif | ||
54 | #define H2C_88E_AOAC_GLOBAL_INFO_LEN 2 | ||
55 | #define H2C_88E_AOAC_RSVDPAGE_LOC_LEN 7 | ||
56 | |||
57 | /* Fw PS state for RPWM. | ||
58 | * BIT[2:0] = HW state | ||
59 | * BIT[3] = Protocol PS state, 1: register active state, 0: register sleep state | ||
60 | * BIT[4] = sub-state | ||
61 | */ | ||
62 | #define FW_PS_GO_ON BIT(0) | ||
63 | #define FW_PS_TX_NULL BIT(1) | ||
64 | #define FW_PS_RF_ON BIT(2) | ||
65 | #define FW_PS_REGISTER_ACTIVE BIT(3) | ||
66 | |||
67 | #define FW_PS_DPS BIT(0) | ||
68 | #define FW_PS_LCLK (FW_PS_DPS) | ||
69 | #define FW_PS_RF_OFF BIT(1) | ||
70 | #define FW_PS_ALL_ON BIT(2) | ||
71 | #define FW_PS_ST_ACTIVE BIT(3) | ||
72 | #define FW_PS_ISR_ENABLE BIT(4) | ||
73 | #define FW_PS_IMR_ENABLE BIT(5) | ||
74 | |||
75 | |||
76 | #define FW_PS_ACK BIT(6) | ||
77 | #define FW_PS_TOGGLE BIT(7) | ||
78 | |||
79 | /* 88E RPWM value*/ | ||
80 | /* BIT[0] = 1: 32k, 0: 40M*/ | ||
81 | #define FW_PS_CLOCK_OFF BIT(0) /* 32k*/ | ||
82 | #define FW_PS_CLOCK_ON 0 /*40M*/ | ||
83 | |||
84 | #define FW_PS_STATE_MASK (0x0F) | ||
85 | #define FW_PS_STATE_HW_MASK (0x07) | ||
86 | /*ISR_ENABLE, IMR_ENABLE, and PS mode should be inherited.*/ | ||
87 | #define FW_PS_STATE_INT_MASK (0x3F) | ||
88 | |||
89 | #define FW_PS_STATE(x) (FW_PS_STATE_MASK & (x)) | ||
90 | #define FW_PS_STATE_HW(x) (FW_PS_STATE_HW_MASK & (x)) | ||
91 | #define FW_PS_STATE_INT(x) (FW_PS_STATE_INT_MASK & (x)) | ||
92 | #define FW_PS_ISR_VAL(x) ((x) & 0x70) | ||
93 | #define FW_PS_IMR_MASK(x) ((x) & 0xDF) | ||
94 | #define FW_PS_KEEP_IMR(x) ((x) & 0x20) | ||
95 | |||
96 | #define FW_PS_STATE_S0 (FW_PS_DPS) | ||
97 | #define FW_PS_STATE_S1 (FW_PS_LCLK) | ||
98 | #define FW_PS_STATE_S2 (FW_PS_RF_OFF) | ||
99 | #define FW_PS_STATE_S3 (FW_PS_ALL_ON) | ||
100 | #define FW_PS_STATE_S4 ((FW_PS_ST_ACTIVE) | (FW_PS_ALL_ON)) | ||
101 | |||
102 | #define FW_PS_STATE_ALL_ON_88E (FW_PS_CLOCK_ON) | ||
103 | #define FW_PS_STATE_RF_ON_88E (FW_PS_CLOCK_ON) | ||
104 | #define FW_PS_STATE_RF_OFF_88E (FW_PS_CLOCK_ON) | ||
105 | #define FW_PS_STATE_RF_OFF_LOW_PWR_88E (FW_PS_CLOCK_OFF) | ||
106 | |||
107 | #define FW_PS_STATE_ALL_ON_92C (FW_PS_STATE_S4) | ||
108 | #define FW_PS_STATE_RF_ON_92C (FW_PS_STATE_S3) | ||
109 | #define FW_PS_STATE_RF_OFF_92C (FW_PS_STATE_S2) | ||
110 | #define FW_PS_STATE_RF_OFF_LOW_PWR_92C (FW_PS_STATE_S1) | ||
111 | |||
112 | /* For 88E H2C PwrMode Cmd ID 5.*/ | ||
113 | #define FW_PWR_STATE_ACTIVE ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE)) | ||
114 | #define FW_PWR_STATE_RF_OFF 0 | ||
115 | |||
116 | #define FW_PS_IS_ACK(x) ((x) & FW_PS_ACK) | ||
117 | #define FW_PS_IS_CLK_ON(x) ((x) & (FW_PS_RF_OFF | FW_PS_ALL_ON)) | ||
118 | #define FW_PS_IS_RF_ON(x) ((x) & (FW_PS_ALL_ON)) | ||
119 | #define FW_PS_IS_ACTIVE(x) ((x) & (FW_PS_ST_ACTIVE)) | ||
120 | #define FW_PS_IS_CPWM_INT(x) ((x) & 0x40) | ||
121 | |||
122 | #define FW_CLR_PS_STATE(x) ((x) = ((x) & (0xF0))) | ||
123 | |||
124 | #define IS_IN_LOW_POWER_STATE_88E(fwpsstate) \ | ||
125 | (FW_PS_STATE(fwpsstate) == FW_PS_CLOCK_OFF) | ||
126 | |||
127 | #define FW_PWR_STATE_ACTIVE ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE)) | ||
128 | #define FW_PWR_STATE_RF_OFF 0 | ||
129 | |||
130 | struct rtl92c_firmware_header { | ||
131 | u16 signature; | ||
132 | u8 category; | ||
133 | u8 function; | ||
134 | u16 version; | ||
135 | u8 subversion; | ||
136 | u8 rsvd1; | ||
137 | u8 month; | ||
138 | u8 date; | ||
139 | u8 hour; | ||
140 | u8 minute; | ||
141 | u16 ramcodesize; | ||
142 | u16 rsvd2; | ||
143 | u32 svnindex; | ||
144 | u32 rsvd3; | ||
145 | u32 rsvd4; | ||
146 | u32 rsvd5; | ||
147 | }; | ||
148 | |||
149 | enum rtl8192c_h2c_cmd { | ||
150 | H2C_88E_RSVDPAGE = 0, | ||
151 | H2C_88E_JOINBSSRPT = 1, | ||
152 | H2C_88E_SCAN = 2, | ||
153 | H2C_88E_KEEP_ALIVE_CTRL = 3, | ||
154 | H2C_88E_DISCONNECT_DECISION = 4, | ||
155 | #if (USE_OLD_WOWLAN_DEBUG_FW == 1) | ||
156 | H2C_88E_WO_WLAN = 5, | ||
157 | #endif | ||
158 | H2C_88E_INIT_OFFLOAD = 6, | ||
159 | #if (USE_OLD_WOWLAN_DEBUG_FW == 1) | ||
160 | H2C_88E_REMOTE_WAKE_CTRL = 7, | ||
161 | #endif | ||
162 | H2C_88E_AP_OFFLOAD = 8, | ||
163 | H2C_88E_BCN_RSVDPAGE = 9, | ||
164 | H2C_88E_PROBERSP_RSVDPAGE = 10, | ||
165 | |||
166 | H2C_88E_SETPWRMODE = 0x20, | ||
167 | H2C_88E_PS_TUNING_PARA = 0x21, | ||
168 | H2C_88E_PS_TUNING_PARA2 = 0x22, | ||
169 | H2C_88E_PS_LPS_PARA = 0x23, | ||
170 | H2C_88E_P2P_PS_OFFLOAD = 024, | ||
171 | |||
172 | #if (USE_OLD_WOWLAN_DEBUG_FW == 0) | ||
173 | H2C_88E_WO_WLAN = 0x80, | ||
174 | H2C_88E_REMOTE_WAKE_CTRL = 0x81, | ||
175 | H2C_88E_AOAC_GLOBAL_INFO = 0x82, | ||
176 | H2C_88E_AOAC_RSVDPAGE = 0x83, | ||
177 | #endif | ||
178 | /* Not defined in new 88E H2C CMD Format */ | ||
179 | H2C_88E_RA_MASK, | ||
180 | H2C_88E_SELECTIVE_SUSPEND_ROF_CMD, | ||
181 | H2C_88E_P2P_PS_MODE, | ||
182 | H2C_88E_PSD_RESULT, | ||
183 | /*Not defined CTW CMD for P2P yet*/ | ||
184 | H2C_88E_P2P_PS_CTW_CMD, | ||
185 | MAX_88E_H2CCMD | ||
186 | }; | ||
187 | |||
188 | #define pagenum_128(_len) (u32)(((_len)>>7) + ((_len)&0x7F ? 1 : 0)) | ||
189 | |||
190 | #define SET_88E_H2CCMD_WOWLAN_FUNC_ENABLE(__cmd, __value) \ | ||
191 | SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value) | ||
192 | #define SET_88E_H2CCMD_WOWLAN_PATTERN_MATCH_ENABLE(__cmd, __value) \ | ||
193 | SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value) | ||
194 | #define SET_88E_H2CCMD_WOWLAN_MAGIC_PKT_ENABLE(__cmd, __value) \ | ||
195 | SET_BITS_TO_LE_1BYTE(__cmd, 2, 1, __value) | ||
196 | #define SET_88E_H2CCMD_WOWLAN_UNICAST_PKT_ENABLE(__cmd, __value) \ | ||
197 | SET_BITS_TO_LE_1BYTE(__cmd, 3, 1, __value) | ||
198 | #define SET_88E_H2CCMD_WOWLAN_ALL_PKT_DROP(__cmd, __value) \ | ||
199 | SET_BITS_TO_LE_1BYTE(__cmd, 4, 1, __value) | ||
200 | #define SET_88E_H2CCMD_WOWLAN_GPIO_ACTIVE(__cmd, __value) \ | ||
201 | SET_BITS_TO_LE_1BYTE(__cmd, 5, 1, __value) | ||
202 | #define SET_88E_H2CCMD_WOWLAN_REKEY_WAKE_UP(__cmd, __value) \ | ||
203 | SET_BITS_TO_LE_1BYTE(__cmd, 6, 1, __value) | ||
204 | #define SET_88E_H2CCMD_WOWLAN_DISCONNECT_WAKE_UP(__cmd, __value) \ | ||
205 | SET_BITS_TO_LE_1BYTE(__cmd, 7, 1, __value) | ||
206 | #define SET_88E_H2CCMD_WOWLAN_GPIONUM(__cmd, __value) \ | ||
207 | SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) | ||
208 | #define SET_88E_H2CCMD_WOWLAN_GPIO_DURATION(__cmd, __value) \ | ||
209 | SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) | ||
210 | |||
211 | |||
212 | #define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val) \ | ||
213 | SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) | ||
214 | #define SET_H2CCMD_PWRMODE_PARM_RLBM(__cmd, __value) \ | ||
215 | SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 4, __value) | ||
216 | #define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__cmd, __value) \ | ||
217 | SET_BITS_TO_LE_1BYTE((__cmd)+1, 4, 4, __value) | ||
218 | #define SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(__cmd, __value) \ | ||
219 | SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) | ||
220 | #define SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(__cmd, __value) \ | ||
221 | SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value) | ||
222 | #define SET_H2CCMD_PWRMODE_PARM_PWR_STATE(__cmd, __value) \ | ||
223 | SET_BITS_TO_LE_1BYTE((__cmd)+4, 0, 8, __value) | ||
224 | #define GET_88E_H2CCMD_PWRMODE_PARM_MODE(__cmd) \ | ||
225 | LE_BITS_TO_1BYTE(__cmd, 0, 8) | ||
226 | |||
227 | #define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val) \ | ||
228 | SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) | ||
229 | #define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val) \ | ||
230 | SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) | ||
231 | #define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val) \ | ||
232 | SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val) | ||
233 | #define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val) \ | ||
234 | SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val) | ||
235 | |||
236 | /* AP_OFFLOAD */ | ||
237 | #define SET_H2CCMD_AP_OFFLOAD_ON(__cmd, __value) \ | ||
238 | SET_BITS_TO_LE_1BYTE(__cmd, 0, 8, __value) | ||
239 | #define SET_H2CCMD_AP_OFFLOAD_HIDDEN(__cmd, __value) \ | ||
240 | SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) | ||
241 | #define SET_H2CCMD_AP_OFFLOAD_DENYANY(__cmd, __value) \ | ||
242 | SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) | ||
243 | #define SET_H2CCMD_AP_OFFLOAD_WAKEUP_EVT_RPT(__cmd, __value) \ | ||
244 | SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value) | ||
245 | |||
246 | /* Keep Alive Control*/ | ||
247 | #define SET_88E_H2CCMD_KEEP_ALIVE_ENABLE(__cmd, __value) \ | ||
248 | SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value) | ||
249 | #define SET_88E_H2CCMD_KEEP_ALIVE_ACCPEPT_USER_DEFINED(__cmd, __value) \ | ||
250 | SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value) | ||
251 | #define SET_88E_H2CCMD_KEEP_ALIVE_PERIOD(__cmd, __value) \ | ||
252 | SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) | ||
253 | |||
254 | /*REMOTE_WAKE_CTRL */ | ||
255 | #define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_EN(__cmd, __value) \ | ||
256 | SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value) | ||
257 | #if (USE_OLD_WOWLAN_DEBUG_FW == 0) | ||
258 | #define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_ARP_OFFLOAD_EN(__cmd, __value) \ | ||
259 | SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value) | ||
260 | #define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_NDP_OFFLOAD_EN(__cmd, __value) \ | ||
261 | SET_BITS_TO_LE_1BYTE(__cmd, 2, 1, __value) | ||
262 | #define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_GTK_OFFLOAD_EN(__cmd, __value) \ | ||
263 | SET_BITS_TO_LE_1BYTE(__cmd, 3, 1, __value) | ||
264 | #else | ||
265 | #define SET_88E_H2_REM_WAKE_ENC_ALG(__cmd, __value) \ | ||
266 | SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) | ||
267 | #define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_GROUP_ENC_ALG(__cmd, __value) \ | ||
268 | SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) | ||
269 | #endif | ||
270 | |||
271 | /* GTK_OFFLOAD */ | ||
272 | #define SET_88E_H2CCMD_AOAC_GLOBAL_INFO_PAIRWISE_ENC_ALG(__cmd, __value) \ | ||
273 | SET_BITS_TO_LE_1BYTE(__cmd, 0, 8, __value) | ||
274 | #define SET_88E_H2CCMD_AOAC_GLOBAL_INFO_GROUP_ENC_ALG(__cmd, __value) \ | ||
275 | SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) | ||
276 | |||
277 | /* AOAC_RSVDPAGE_LOC */ | ||
278 | #define SET_88E_H2CCMD_AOAC_RSVD_LOC_REM_WAKE_CTRL_INFO(__cmd, __value) \ | ||
279 | SET_BITS_TO_LE_1BYTE((__cmd), 0, 8, __value) | ||
280 | #define SET_88E_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(__cmd, __value) \ | ||
281 | SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) | ||
282 | #define SET_88E_H2CCMD_AOAC_RSVDPAGE_LOC_NEIGHBOR_ADV(__cmd, __value) \ | ||
283 | SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) | ||
284 | #define SET_88E_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_RSP(__cmd, __value) \ | ||
285 | SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value) | ||
286 | #define SET_88E_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_INFO(__cmd, __value) \ | ||
287 | SET_BITS_TO_LE_1BYTE((__cmd)+4, 0, 8, __value) | ||
288 | |||
289 | int rtl88e_download_fw(struct ieee80211_hw *hw, | ||
290 | bool buse_wake_on_wlan_fw); | ||
291 | void rtl88e_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, | ||
292 | u32 cmd_len, u8 *p_cmdbuffer); | ||
293 | void rtl88e_firmware_selfreset(struct ieee80211_hw *hw); | ||
294 | void rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); | ||
295 | void rtl88e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, | ||
296 | u8 mstatus); | ||
297 | void rtl88e_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw, u8 enable); | ||
298 | void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); | ||
299 | void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state); | ||
300 | |||
301 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c new file mode 100644 index 000000000000..bcff49730a4e --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c | |||
@@ -0,0 +1,2530 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "../wifi.h" | ||
31 | #include "../efuse.h" | ||
32 | #include "../base.h" | ||
33 | #include "../regd.h" | ||
34 | #include "../cam.h" | ||
35 | #include "../ps.h" | ||
36 | #include "../pci.h" | ||
37 | #include "reg.h" | ||
38 | #include "def.h" | ||
39 | #include "phy.h" | ||
40 | #include "dm.h" | ||
41 | #include "fw.h" | ||
42 | #include "led.h" | ||
43 | #include "hw.h" | ||
44 | #include "pwrseqcmd.h" | ||
45 | #include "pwrseq.h" | ||
46 | |||
47 | #define LLT_CONFIG 5 | ||
48 | |||
49 | static void _rtl88ee_set_bcn_ctrl_reg(struct ieee80211_hw *hw, | ||
50 | u8 set_bits, u8 clear_bits) | ||
51 | { | ||
52 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
53 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
54 | |||
55 | rtlpci->reg_bcn_ctrl_val |= set_bits; | ||
56 | rtlpci->reg_bcn_ctrl_val &= ~clear_bits; | ||
57 | |||
58 | rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val); | ||
59 | } | ||
60 | |||
61 | static void _rtl88ee_stop_tx_beacon(struct ieee80211_hw *hw) | ||
62 | { | ||
63 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
64 | u8 tmp1byte; | ||
65 | |||
66 | tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); | ||
67 | rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6))); | ||
68 | rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64); | ||
69 | tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); | ||
70 | tmp1byte &= ~(BIT(0)); | ||
71 | rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); | ||
72 | } | ||
73 | |||
74 | static void _rtl88ee_resume_tx_beacon(struct ieee80211_hw *hw) | ||
75 | { | ||
76 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
77 | u8 tmp1byte; | ||
78 | |||
79 | tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); | ||
80 | rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6)); | ||
81 | rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); | ||
82 | tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); | ||
83 | tmp1byte |= BIT(0); | ||
84 | rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); | ||
85 | } | ||
86 | |||
87 | static void _rtl88ee_enable_bcn_sub_func(struct ieee80211_hw *hw) | ||
88 | { | ||
89 | _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(1)); | ||
90 | } | ||
91 | |||
92 | static void _rtl88ee_return_beacon_queue_skb(struct ieee80211_hw *hw) | ||
93 | { | ||
94 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
95 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
96 | struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[BEACON_QUEUE]; | ||
97 | |||
98 | while (skb_queue_len(&ring->queue)) { | ||
99 | struct rtl_tx_desc *entry = &ring->desc[ring->idx]; | ||
100 | struct sk_buff *skb = __skb_dequeue(&ring->queue); | ||
101 | |||
102 | pci_unmap_single(rtlpci->pdev, | ||
103 | rtlpriv->cfg->ops->get_desc( | ||
104 | (u8 *)entry, true, HW_DESC_TXBUFF_ADDR), | ||
105 | skb->len, PCI_DMA_TODEVICE); | ||
106 | kfree_skb(skb); | ||
107 | ring->idx = (ring->idx + 1) % ring->entries; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | static void _rtl88ee_disable_bcn_sub_func(struct ieee80211_hw *hw) | ||
112 | { | ||
113 | _rtl88ee_set_bcn_ctrl_reg(hw, BIT(1), 0); | ||
114 | } | ||
115 | |||
116 | static void _rtl88ee_set_fw_clock_on(struct ieee80211_hw *hw, | ||
117 | u8 rpwm_val, bool need_turn_off_ckk) | ||
118 | { | ||
119 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
120 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
121 | bool support_remote_wake_up; | ||
122 | u32 count = 0, isr_regaddr, content; | ||
123 | bool schedule_timer = need_turn_off_ckk; | ||
124 | |||
125 | rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, | ||
126 | (u8 *)(&support_remote_wake_up)); | ||
127 | if (!rtlhal->fw_ready) | ||
128 | return; | ||
129 | if (!rtlpriv->psc.fw_current_inpsmode) | ||
130 | return; | ||
131 | |||
132 | while (1) { | ||
133 | spin_lock_bh(&rtlpriv->locks.fw_ps_lock); | ||
134 | if (rtlhal->fw_clk_change_in_progress) { | ||
135 | while (rtlhal->fw_clk_change_in_progress) { | ||
136 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | ||
137 | udelay(100); | ||
138 | if (++count > 1000) | ||
139 | return; | ||
140 | spin_lock_bh(&rtlpriv->locks.fw_ps_lock); | ||
141 | } | ||
142 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | ||
143 | } else { | ||
144 | rtlhal->fw_clk_change_in_progress = false; | ||
145 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | ||
146 | } | ||
147 | } | ||
148 | |||
149 | if (IS_IN_LOW_POWER_STATE_88E(rtlhal->fw_ps_state)) { | ||
150 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_SET_RPWM, | ||
151 | (u8 *)(&rpwm_val)); | ||
152 | if (FW_PS_IS_ACK(rpwm_val)) { | ||
153 | isr_regaddr = REG_HISR; | ||
154 | content = rtl_read_dword(rtlpriv, isr_regaddr); | ||
155 | while (!(content & IMR_CPWM) && (count < 500)) { | ||
156 | udelay(50); | ||
157 | count++; | ||
158 | content = rtl_read_dword(rtlpriv, isr_regaddr); | ||
159 | } | ||
160 | |||
161 | if (content & IMR_CPWM) { | ||
162 | rtl_write_word(rtlpriv, isr_regaddr, 0x0100); | ||
163 | rtlhal->fw_ps_state = FW_PS_STATE_RF_ON_88E; | ||
164 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
165 | "Receive CPWM INT!!! Set pHalData->FwPSState = %X\n", | ||
166 | rtlhal->fw_ps_state); | ||
167 | } | ||
168 | } | ||
169 | |||
170 | spin_lock_bh(&rtlpriv->locks.fw_ps_lock); | ||
171 | rtlhal->fw_clk_change_in_progress = false; | ||
172 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | ||
173 | if (schedule_timer) { | ||
174 | mod_timer(&rtlpriv->works.fw_clockoff_timer, | ||
175 | jiffies + MSECS(10)); | ||
176 | } | ||
177 | } else { | ||
178 | spin_lock_bh(&rtlpriv->locks.fw_ps_lock); | ||
179 | rtlhal->fw_clk_change_in_progress = false; | ||
180 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | ||
181 | } | ||
182 | } | ||
183 | |||
184 | static void _rtl88ee_set_fw_clock_off(struct ieee80211_hw *hw, | ||
185 | u8 rpwm_val) | ||
186 | { | ||
187 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
188 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
189 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
190 | struct rtl8192_tx_ring *ring; | ||
191 | enum rf_pwrstate rtstate; | ||
192 | bool schedule_timer = false; | ||
193 | u8 queue; | ||
194 | |||
195 | if (!rtlhal->fw_ready) | ||
196 | return; | ||
197 | if (!rtlpriv->psc.fw_current_inpsmode) | ||
198 | return; | ||
199 | if (!rtlhal->allow_sw_to_change_hwclc) | ||
200 | return; | ||
201 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, (u8 *)(&rtstate)); | ||
202 | if (rtstate == ERFOFF || rtlpriv->psc.inactive_pwrstate == ERFOFF) | ||
203 | return; | ||
204 | |||
205 | for (queue = 0; queue < RTL_PCI_MAX_TX_QUEUE_COUNT; queue++) { | ||
206 | ring = &rtlpci->tx_ring[queue]; | ||
207 | if (skb_queue_len(&ring->queue)) { | ||
208 | schedule_timer = true; | ||
209 | break; | ||
210 | } | ||
211 | } | ||
212 | |||
213 | if (schedule_timer) { | ||
214 | mod_timer(&rtlpriv->works.fw_clockoff_timer, | ||
215 | jiffies + MSECS(10)); | ||
216 | return; | ||
217 | } | ||
218 | |||
219 | if (FW_PS_STATE(rtlhal->fw_ps_state) != | ||
220 | FW_PS_STATE_RF_OFF_LOW_PWR_88E) { | ||
221 | spin_lock_bh(&rtlpriv->locks.fw_ps_lock); | ||
222 | if (!rtlhal->fw_clk_change_in_progress) { | ||
223 | rtlhal->fw_clk_change_in_progress = true; | ||
224 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | ||
225 | rtlhal->fw_ps_state = FW_PS_STATE(rpwm_val); | ||
226 | rtl_write_word(rtlpriv, REG_HISR, 0x0100); | ||
227 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, | ||
228 | (u8 *)(&rpwm_val)); | ||
229 | spin_lock_bh(&rtlpriv->locks.fw_ps_lock); | ||
230 | rtlhal->fw_clk_change_in_progress = false; | ||
231 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | ||
232 | } else { | ||
233 | spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); | ||
234 | mod_timer(&rtlpriv->works.fw_clockoff_timer, | ||
235 | jiffies + MSECS(10)); | ||
236 | } | ||
237 | } | ||
238 | } | ||
239 | |||
240 | static void _rtl88ee_set_fw_ps_rf_on(struct ieee80211_hw *hw) | ||
241 | { | ||
242 | u8 rpwm_val = 0; | ||
243 | |||
244 | rpwm_val |= (FW_PS_STATE_RF_OFF_88E | FW_PS_ACK); | ||
245 | _rtl88ee_set_fw_clock_on(hw, rpwm_val, true); | ||
246 | } | ||
247 | |||
248 | static void _rtl88ee_set_fw_ps_rf_off_low_power(struct ieee80211_hw *hw) | ||
249 | { | ||
250 | u8 rpwm_val = 0; | ||
251 | |||
252 | rpwm_val |= FW_PS_STATE_RF_OFF_LOW_PWR_88E; | ||
253 | _rtl88ee_set_fw_clock_off(hw, rpwm_val); | ||
254 | } | ||
255 | |||
256 | void rtl88ee_fw_clk_off_timer_callback(unsigned long data) | ||
257 | { | ||
258 | struct ieee80211_hw *hw = (struct ieee80211_hw *)data; | ||
259 | |||
260 | _rtl88ee_set_fw_ps_rf_off_low_power(hw); | ||
261 | } | ||
262 | |||
263 | static void _rtl88ee_fwlps_leave(struct ieee80211_hw *hw) | ||
264 | { | ||
265 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
266 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
267 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
268 | bool fw_current_inps = false; | ||
269 | u8 rpwm_val = 0, fw_pwrmode = FW_PS_ACTIVE_MODE; | ||
270 | |||
271 | if (ppsc->low_power_enable) { | ||
272 | rpwm_val = (FW_PS_STATE_ALL_ON_88E|FW_PS_ACK);/* RF on */ | ||
273 | _rtl88ee_set_fw_clock_on(hw, rpwm_val, false); | ||
274 | rtlhal->allow_sw_to_change_hwclc = false; | ||
275 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, | ||
276 | (u8 *)(&fw_pwrmode)); | ||
277 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, | ||
278 | (u8 *)(&fw_current_inps)); | ||
279 | } else { | ||
280 | rpwm_val = FW_PS_STATE_ALL_ON_88E; /* RF on */ | ||
281 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, | ||
282 | (u8 *)(&rpwm_val)); | ||
283 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, | ||
284 | (u8 *)(&fw_pwrmode)); | ||
285 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, | ||
286 | (u8 *)(&fw_current_inps)); | ||
287 | } | ||
288 | } | ||
289 | |||
290 | static void _rtl88ee_fwlps_enter(struct ieee80211_hw *hw) | ||
291 | { | ||
292 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
293 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
294 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
295 | bool fw_current_inps = true; | ||
296 | u8 rpwm_val; | ||
297 | |||
298 | if (ppsc->low_power_enable) { | ||
299 | rpwm_val = FW_PS_STATE_RF_OFF_LOW_PWR_88E; /* RF off */ | ||
300 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, | ||
301 | (u8 *)(&fw_current_inps)); | ||
302 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, | ||
303 | (u8 *)(&ppsc->fwctrl_psmode)); | ||
304 | rtlhal->allow_sw_to_change_hwclc = true; | ||
305 | _rtl88ee_set_fw_clock_off(hw, rpwm_val); | ||
306 | } else { | ||
307 | rpwm_val = FW_PS_STATE_RF_OFF_88E; /* RF off */ | ||
308 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, | ||
309 | (u8 *)(&fw_current_inps)); | ||
310 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, | ||
311 | (u8 *)(&ppsc->fwctrl_psmode)); | ||
312 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, | ||
313 | (u8 *)(&rpwm_val)); | ||
314 | } | ||
315 | } | ||
316 | |||
317 | void rtl88ee_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | ||
318 | { | ||
319 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
320 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
321 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
322 | |||
323 | switch (variable) { | ||
324 | case HW_VAR_RCR: | ||
325 | *((u32 *)(val)) = rtlpci->receive_config; | ||
326 | break; | ||
327 | case HW_VAR_RF_STATE: | ||
328 | *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; | ||
329 | break; | ||
330 | case HW_VAR_FWLPS_RF_ON:{ | ||
331 | enum rf_pwrstate rfstate; | ||
332 | u32 val_rcr; | ||
333 | |||
334 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, | ||
335 | (u8 *)(&rfstate)); | ||
336 | if (rfstate == ERFOFF) { | ||
337 | *((bool *)(val)) = true; | ||
338 | } else { | ||
339 | val_rcr = rtl_read_dword(rtlpriv, REG_RCR); | ||
340 | val_rcr &= 0x00070000; | ||
341 | if (val_rcr) | ||
342 | *((bool *)(val)) = false; | ||
343 | else | ||
344 | *((bool *)(val)) = true; | ||
345 | } | ||
346 | break; | ||
347 | } | ||
348 | case HW_VAR_FW_PSMODE_STATUS: | ||
349 | *((bool *)(val)) = ppsc->fw_current_inpsmode; | ||
350 | break; | ||
351 | case HW_VAR_CORRECT_TSF:{ | ||
352 | u64 tsf; | ||
353 | u32 *ptsf_low = (u32 *)&tsf; | ||
354 | u32 *ptsf_high = ((u32 *)&tsf) + 1; | ||
355 | |||
356 | *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4)); | ||
357 | *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); | ||
358 | |||
359 | *((u64 *)(val)) = tsf; | ||
360 | break; } | ||
361 | default: | ||
362 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
363 | "switch case not process %x\n", variable); | ||
364 | break; | ||
365 | } | ||
366 | } | ||
367 | |||
368 | void rtl88ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | ||
369 | { | ||
370 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
371 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
372 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
373 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
374 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
375 | u8 idx; | ||
376 | |||
377 | switch (variable) { | ||
378 | case HW_VAR_ETHER_ADDR: | ||
379 | for (idx = 0; idx < ETH_ALEN; idx++) | ||
380 | rtl_write_byte(rtlpriv, (REG_MACID + idx), val[idx]); | ||
381 | break; | ||
382 | case HW_VAR_BASIC_RATE:{ | ||
383 | u16 rate_cfg = ((u16 *)val)[0]; | ||
384 | u8 rate_index = 0; | ||
385 | rate_cfg = rate_cfg & 0x15f; | ||
386 | rate_cfg |= 0x01; | ||
387 | rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff); | ||
388 | rtl_write_byte(rtlpriv, REG_RRSR + 1, (rate_cfg >> 8) & 0xff); | ||
389 | while (rate_cfg > 0x1) { | ||
390 | rate_cfg = (rate_cfg >> 1); | ||
391 | rate_index++; | ||
392 | } | ||
393 | rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, rate_index); | ||
394 | break; } | ||
395 | case HW_VAR_BSSID: | ||
396 | for (idx = 0; idx < ETH_ALEN; idx++) | ||
397 | rtl_write_byte(rtlpriv, (REG_BSSID + idx), val[idx]); | ||
398 | break; | ||
399 | case HW_VAR_SIFS: | ||
400 | rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]); | ||
401 | rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[1]); | ||
402 | |||
403 | rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]); | ||
404 | rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]); | ||
405 | |||
406 | if (!mac->ht_enable) | ||
407 | rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, 0x0e0e); | ||
408 | else | ||
409 | rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, | ||
410 | *((u16 *)val)); | ||
411 | break; | ||
412 | case HW_VAR_SLOT_TIME:{ | ||
413 | u8 e_aci; | ||
414 | |||
415 | RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, | ||
416 | "HW_VAR_SLOT_TIME %x\n", val[0]); | ||
417 | |||
418 | rtl_write_byte(rtlpriv, REG_SLOT, val[0]); | ||
419 | |||
420 | for (e_aci = 0; e_aci < AC_MAX; e_aci++) { | ||
421 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, | ||
422 | (u8 *)(&e_aci)); | ||
423 | } | ||
424 | break; } | ||
425 | case HW_VAR_ACK_PREAMBLE:{ | ||
426 | u8 reg_tmp; | ||
427 | u8 short_preamble = (bool) (*(u8 *)val); | ||
428 | reg_tmp = rtl_read_byte(rtlpriv, REG_TRXPTCL_CTL+2); | ||
429 | if (short_preamble) { | ||
430 | reg_tmp |= 0x02; | ||
431 | rtl_write_byte(rtlpriv, REG_TRXPTCL_CTL + 2, reg_tmp); | ||
432 | } else { | ||
433 | reg_tmp |= 0xFD; | ||
434 | rtl_write_byte(rtlpriv, REG_TRXPTCL_CTL + 2, reg_tmp); | ||
435 | } | ||
436 | break; } | ||
437 | case HW_VAR_WPA_CONFIG: | ||
438 | rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *)val)); | ||
439 | break; | ||
440 | case HW_VAR_AMPDU_MIN_SPACE:{ | ||
441 | u8 min_spacing_to_set; | ||
442 | u8 sec_min_space; | ||
443 | |||
444 | min_spacing_to_set = *((u8 *)val); | ||
445 | if (min_spacing_to_set <= 7) { | ||
446 | sec_min_space = 0; | ||
447 | |||
448 | if (min_spacing_to_set < sec_min_space) | ||
449 | min_spacing_to_set = sec_min_space; | ||
450 | |||
451 | mac->min_space_cfg = ((mac->min_space_cfg & | ||
452 | 0xf8) | min_spacing_to_set); | ||
453 | |||
454 | *val = min_spacing_to_set; | ||
455 | |||
456 | RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, | ||
457 | "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", | ||
458 | mac->min_space_cfg); | ||
459 | |||
460 | rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, | ||
461 | mac->min_space_cfg); | ||
462 | } | ||
463 | break; } | ||
464 | case HW_VAR_SHORTGI_DENSITY:{ | ||
465 | u8 density_to_set; | ||
466 | |||
467 | density_to_set = *((u8 *)val); | ||
468 | mac->min_space_cfg |= (density_to_set << 3); | ||
469 | |||
470 | RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, | ||
471 | "Set HW_VAR_SHORTGI_DENSITY: %#x\n", | ||
472 | mac->min_space_cfg); | ||
473 | |||
474 | rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, | ||
475 | mac->min_space_cfg); | ||
476 | break; } | ||
477 | case HW_VAR_AMPDU_FACTOR:{ | ||
478 | u8 regtoset_normal[4] = { 0x41, 0xa8, 0x72, 0xb9 }; | ||
479 | u8 factor; | ||
480 | u8 *reg = NULL; | ||
481 | u8 id = 0; | ||
482 | |||
483 | reg = regtoset_normal; | ||
484 | |||
485 | factor = *((u8 *)val); | ||
486 | if (factor <= 3) { | ||
487 | factor = (1 << (factor + 2)); | ||
488 | if (factor > 0xf) | ||
489 | factor = 0xf; | ||
490 | |||
491 | for (id = 0; id < 4; id++) { | ||
492 | if ((reg[id] & 0xf0) > (factor << 4)) | ||
493 | reg[id] = (reg[id] & 0x0f) | | ||
494 | (factor << 4); | ||
495 | |||
496 | if ((reg[id] & 0x0f) > factor) | ||
497 | reg[id] = (reg[id] & 0xf0) | (factor); | ||
498 | |||
499 | rtl_write_byte(rtlpriv, (REG_AGGLEN_LMT + id), | ||
500 | reg[id]); | ||
501 | } | ||
502 | |||
503 | RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, | ||
504 | "Set HW_VAR_AMPDU_FACTOR: %#x\n", factor); | ||
505 | } | ||
506 | break; } | ||
507 | case HW_VAR_AC_PARAM:{ | ||
508 | u8 e_aci = *((u8 *)val); | ||
509 | rtl88e_dm_init_edca_turbo(hw); | ||
510 | |||
511 | if (rtlpci->acm_method != eAcmWay2_SW) | ||
512 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACM_CTRL, | ||
513 | (u8 *)(&e_aci)); | ||
514 | break; } | ||
515 | case HW_VAR_ACM_CTRL:{ | ||
516 | u8 e_aci = *((u8 *)val); | ||
517 | union aci_aifsn *p_aci_aifsn = | ||
518 | (union aci_aifsn *)(&(mac->ac[0].aifs)); | ||
519 | u8 acm = p_aci_aifsn->f.acm; | ||
520 | u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL); | ||
521 | |||
522 | acm_ctrl = acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1); | ||
523 | |||
524 | if (acm) { | ||
525 | switch (e_aci) { | ||
526 | case AC0_BE: | ||
527 | acm_ctrl |= ACMHW_BEQEN; | ||
528 | break; | ||
529 | case AC2_VI: | ||
530 | acm_ctrl |= ACMHW_VIQEN; | ||
531 | break; | ||
532 | case AC3_VO: | ||
533 | acm_ctrl |= ACMHW_VOQEN; | ||
534 | break; | ||
535 | default: | ||
536 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
537 | "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n", | ||
538 | acm); | ||
539 | break; | ||
540 | } | ||
541 | } else { | ||
542 | switch (e_aci) { | ||
543 | case AC0_BE: | ||
544 | acm_ctrl &= (~ACMHW_BEQEN); | ||
545 | break; | ||
546 | case AC2_VI: | ||
547 | acm_ctrl &= (~ACMHW_VIQEN); | ||
548 | break; | ||
549 | case AC3_VO: | ||
550 | acm_ctrl &= (~ACMHW_BEQEN); | ||
551 | break; | ||
552 | default: | ||
553 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
554 | "switch case not process\n"); | ||
555 | break; | ||
556 | } | ||
557 | } | ||
558 | |||
559 | RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, | ||
560 | "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", | ||
561 | acm_ctrl); | ||
562 | rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl); | ||
563 | break; } | ||
564 | case HW_VAR_RCR: | ||
565 | rtl_write_dword(rtlpriv, REG_RCR, ((u32 *)(val))[0]); | ||
566 | rtlpci->receive_config = ((u32 *)(val))[0]; | ||
567 | break; | ||
568 | case HW_VAR_RETRY_LIMIT:{ | ||
569 | u8 retry_limit = ((u8 *)(val))[0]; | ||
570 | |||
571 | rtl_write_word(rtlpriv, REG_RL, | ||
572 | retry_limit << RETRY_LIMIT_SHORT_SHIFT | | ||
573 | retry_limit << RETRY_LIMIT_LONG_SHIFT); | ||
574 | break; } | ||
575 | case HW_VAR_DUAL_TSF_RST: | ||
576 | rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1))); | ||
577 | break; | ||
578 | case HW_VAR_EFUSE_BYTES: | ||
579 | rtlefuse->efuse_usedbytes = *((u16 *)val); | ||
580 | break; | ||
581 | case HW_VAR_EFUSE_USAGE: | ||
582 | rtlefuse->efuse_usedpercentage = *((u8 *)val); | ||
583 | break; | ||
584 | case HW_VAR_IO_CMD: | ||
585 | rtl88e_phy_set_io_cmd(hw, (*(enum io_type *)val)); | ||
586 | break; | ||
587 | case HW_VAR_SET_RPWM:{ | ||
588 | u8 rpwm_val; | ||
589 | |||
590 | rpwm_val = rtl_read_byte(rtlpriv, REG_PCIE_HRPWM); | ||
591 | udelay(1); | ||
592 | |||
593 | if (rpwm_val & BIT(7)) { | ||
594 | rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, | ||
595 | (*(u8 *)val)); | ||
596 | } else { | ||
597 | rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, | ||
598 | ((*(u8 *)val) | BIT(7))); | ||
599 | } | ||
600 | break; } | ||
601 | case HW_VAR_H2C_FW_PWRMODE: | ||
602 | rtl88e_set_fw_pwrmode_cmd(hw, (*(u8 *)val)); | ||
603 | break; | ||
604 | case HW_VAR_FW_PSMODE_STATUS: | ||
605 | ppsc->fw_current_inpsmode = *((bool *)val); | ||
606 | break; | ||
607 | case HW_VAR_RESUME_CLK_ON: | ||
608 | _rtl88ee_set_fw_ps_rf_on(hw); | ||
609 | break; | ||
610 | case HW_VAR_FW_LPS_ACTION:{ | ||
611 | bool enter_fwlps = *((bool *)val); | ||
612 | |||
613 | if (enter_fwlps) | ||
614 | _rtl88ee_fwlps_enter(hw); | ||
615 | else | ||
616 | _rtl88ee_fwlps_leave(hw); | ||
617 | break; } | ||
618 | case HW_VAR_H2C_FW_JOINBSSRPT:{ | ||
619 | u8 mstatus = (*(u8 *)val); | ||
620 | u8 tmp, tmp_reg422, uval; | ||
621 | u8 count = 0, dlbcn_count = 0; | ||
622 | bool recover = false; | ||
623 | |||
624 | if (mstatus == RT_MEDIA_CONNECT) { | ||
625 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, NULL); | ||
626 | |||
627 | tmp = rtl_read_byte(rtlpriv, REG_CR + 1); | ||
628 | rtl_write_byte(rtlpriv, REG_CR + 1, (tmp | BIT(0))); | ||
629 | |||
630 | _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(3)); | ||
631 | _rtl88ee_set_bcn_ctrl_reg(hw, BIT(4), 0); | ||
632 | |||
633 | tmp_reg422 = rtl_read_byte(rtlpriv, | ||
634 | REG_FWHW_TXQ_CTRL + 2); | ||
635 | rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, | ||
636 | tmp_reg422 & (~BIT(6))); | ||
637 | if (tmp_reg422 & BIT(6)) | ||
638 | recover = true; | ||
639 | |||
640 | do { | ||
641 | uval = rtl_read_byte(rtlpriv, REG_TDECTRL+2); | ||
642 | rtl_write_byte(rtlpriv, REG_TDECTRL+2, | ||
643 | (uval | BIT(0))); | ||
644 | _rtl88ee_return_beacon_queue_skb(hw); | ||
645 | |||
646 | rtl88e_set_fw_rsvdpagepkt(hw, 0); | ||
647 | uval = rtl_read_byte(rtlpriv, REG_TDECTRL+2); | ||
648 | count = 0; | ||
649 | while (!(uval & BIT(0)) && count < 20) { | ||
650 | count++; | ||
651 | udelay(10); | ||
652 | uval = rtl_read_byte(rtlpriv, | ||
653 | REG_TDECTRL+2); | ||
654 | } | ||
655 | dlbcn_count++; | ||
656 | } while (!(uval & BIT(0)) && dlbcn_count < 5); | ||
657 | |||
658 | if (uval & BIT(0)) | ||
659 | rtl_write_byte(rtlpriv, REG_TDECTRL+2, BIT(0)); | ||
660 | |||
661 | _rtl88ee_set_bcn_ctrl_reg(hw, BIT(3), 0); | ||
662 | _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(4)); | ||
663 | |||
664 | if (recover) { | ||
665 | rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, | ||
666 | tmp_reg422); | ||
667 | } | ||
668 | rtl_write_byte(rtlpriv, REG_CR + 1, (tmp & ~(BIT(0)))); | ||
669 | } | ||
670 | rtl88e_set_fw_joinbss_report_cmd(hw, (*(u8 *)val)); | ||
671 | break; } | ||
672 | case HW_VAR_H2C_FW_P2P_PS_OFFLOAD: | ||
673 | rtl88e_set_p2p_ps_offload_cmd(hw, (*(u8 *)val)); | ||
674 | break; | ||
675 | case HW_VAR_AID:{ | ||
676 | u16 u2btmp; | ||
677 | u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); | ||
678 | u2btmp &= 0xC000; | ||
679 | rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp | | ||
680 | mac->assoc_id)); | ||
681 | break; } | ||
682 | case HW_VAR_CORRECT_TSF:{ | ||
683 | u8 btype_ibss = ((u8 *)(val))[0]; | ||
684 | |||
685 | if (btype_ibss == true) | ||
686 | _rtl88ee_stop_tx_beacon(hw); | ||
687 | |||
688 | _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(3)); | ||
689 | |||
690 | rtl_write_dword(rtlpriv, REG_TSFTR, | ||
691 | (u32) (mac->tsf & 0xffffffff)); | ||
692 | rtl_write_dword(rtlpriv, REG_TSFTR + 4, | ||
693 | (u32) ((mac->tsf >> 32) & 0xffffffff)); | ||
694 | |||
695 | _rtl88ee_set_bcn_ctrl_reg(hw, BIT(3), 0); | ||
696 | |||
697 | if (btype_ibss == true) | ||
698 | _rtl88ee_resume_tx_beacon(hw); | ||
699 | break; } | ||
700 | default: | ||
701 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
702 | "switch case not process %x\n", variable); | ||
703 | break; | ||
704 | } | ||
705 | } | ||
706 | |||
707 | static bool _rtl88ee_llt_write(struct ieee80211_hw *hw, u32 address, u32 data) | ||
708 | { | ||
709 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
710 | bool status = true; | ||
711 | long count = 0; | ||
712 | u32 value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) | | ||
713 | _LLT_OP(_LLT_WRITE_ACCESS); | ||
714 | |||
715 | rtl_write_dword(rtlpriv, REG_LLT_INIT, value); | ||
716 | |||
717 | do { | ||
718 | value = rtl_read_dword(rtlpriv, REG_LLT_INIT); | ||
719 | if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) | ||
720 | break; | ||
721 | |||
722 | if (count > POLLING_LLT_THRESHOLD) { | ||
723 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
724 | "Failed to polling write LLT done at address %d!\n", | ||
725 | address); | ||
726 | status = false; | ||
727 | break; | ||
728 | } | ||
729 | } while (++count); | ||
730 | |||
731 | return status; | ||
732 | } | ||
733 | |||
734 | static bool _rtl88ee_llt_table_init(struct ieee80211_hw *hw) | ||
735 | { | ||
736 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
737 | unsigned short i; | ||
738 | u8 txpktbuf_bndy; | ||
739 | u8 maxpage; | ||
740 | bool status; | ||
741 | |||
742 | maxpage = 0xAF; | ||
743 | txpktbuf_bndy = 0xAB; | ||
744 | |||
745 | rtl_write_byte(rtlpriv, REG_RQPN_NPQ, 0x01); | ||
746 | rtl_write_dword(rtlpriv, REG_RQPN, 0x80730d29); | ||
747 | |||
748 | |||
749 | rtl_write_dword(rtlpriv, REG_TRXFF_BNDY, (0x25FF0000 | txpktbuf_bndy)); | ||
750 | rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy); | ||
751 | |||
752 | rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); | ||
753 | rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); | ||
754 | |||
755 | rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy); | ||
756 | rtl_write_byte(rtlpriv, REG_PBP, 0x11); | ||
757 | rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4); | ||
758 | |||
759 | for (i = 0; i < (txpktbuf_bndy - 1); i++) { | ||
760 | status = _rtl88ee_llt_write(hw, i, i + 1); | ||
761 | if (true != status) | ||
762 | return status; | ||
763 | } | ||
764 | |||
765 | status = _rtl88ee_llt_write(hw, (txpktbuf_bndy - 1), 0xFF); | ||
766 | if (true != status) | ||
767 | return status; | ||
768 | |||
769 | for (i = txpktbuf_bndy; i < maxpage; i++) { | ||
770 | status = _rtl88ee_llt_write(hw, i, (i + 1)); | ||
771 | if (true != status) | ||
772 | return status; | ||
773 | } | ||
774 | |||
775 | status = _rtl88ee_llt_write(hw, maxpage, txpktbuf_bndy); | ||
776 | if (true != status) | ||
777 | return status; | ||
778 | |||
779 | return true; | ||
780 | } | ||
781 | |||
782 | static void _rtl88ee_gen_refresh_led_state(struct ieee80211_hw *hw) | ||
783 | { | ||
784 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
785 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
786 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
787 | struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); | ||
788 | |||
789 | if (rtlpriv->rtlhal.up_first_time) | ||
790 | return; | ||
791 | |||
792 | if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) | ||
793 | rtl88ee_sw_led_on(hw, pLed0); | ||
794 | else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) | ||
795 | rtl88ee_sw_led_on(hw, pLed0); | ||
796 | else | ||
797 | rtl88ee_sw_led_off(hw, pLed0); | ||
798 | } | ||
799 | |||
800 | static bool _rtl88ee_init_mac(struct ieee80211_hw *hw) | ||
801 | { | ||
802 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
803 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
804 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
805 | u8 bytetmp; | ||
806 | u16 wordtmp; | ||
807 | |||
808 | /*Disable XTAL OUTPUT for power saving. YJ, add, 111206. */ | ||
809 | bytetmp = rtl_read_byte(rtlpriv, REG_XCK_OUT_CTRL) & (~BIT(0)); | ||
810 | rtl_write_byte(rtlpriv, REG_XCK_OUT_CTRL, bytetmp); | ||
811 | /*Auto Power Down to CHIP-off State*/ | ||
812 | bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) & (~BIT(7)); | ||
813 | rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, bytetmp); | ||
814 | |||
815 | rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); | ||
816 | /* HW Power on sequence */ | ||
817 | if (!rtl88_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, | ||
818 | PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, | ||
819 | Rtl8188E_NIC_ENABLE_FLOW)) { | ||
820 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
821 | "init MAC Fail as rtl88_hal_pwrseqcmdparsing\n"); | ||
822 | return false; | ||
823 | } | ||
824 | |||
825 | bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO) | BIT(4); | ||
826 | rtl_write_byte(rtlpriv, REG_APS_FSMCO, bytetmp); | ||
827 | |||
828 | bytetmp = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG+2); | ||
829 | rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+2, bytetmp|BIT(2)); | ||
830 | |||
831 | bytetmp = rtl_read_byte(rtlpriv, REG_WATCH_DOG+1); | ||
832 | rtl_write_byte(rtlpriv, REG_WATCH_DOG+1, bytetmp|BIT(7)); | ||
833 | |||
834 | bytetmp = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL_EXT+1); | ||
835 | rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL_EXT+1, bytetmp|BIT(1)); | ||
836 | |||
837 | bytetmp = rtl_read_byte(rtlpriv, REG_TX_RPT_CTRL); | ||
838 | rtl_write_byte(rtlpriv, REG_TX_RPT_CTRL, bytetmp|BIT(1)|BIT(0)); | ||
839 | rtl_write_byte(rtlpriv, REG_TX_RPT_CTRL+1, 2); | ||
840 | rtl_write_word(rtlpriv, REG_TX_RPT_TIME, 0xcdf0); | ||
841 | |||
842 | /*Add for wake up online*/ | ||
843 | bytetmp = rtl_read_byte(rtlpriv, REG_SYS_CLKR); | ||
844 | |||
845 | rtl_write_byte(rtlpriv, REG_SYS_CLKR, bytetmp|BIT(3)); | ||
846 | bytetmp = rtl_read_byte(rtlpriv, REG_GPIO_MUXCFG+1); | ||
847 | rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG+1, (bytetmp & (~BIT(4)))); | ||
848 | rtl_write_byte(rtlpriv, 0x367, 0x80); | ||
849 | |||
850 | rtl_write_word(rtlpriv, REG_CR, 0x2ff); | ||
851 | rtl_write_byte(rtlpriv, REG_CR+1, 0x06); | ||
852 | rtl_write_byte(rtlpriv, REG_CR+2, 0x00); | ||
853 | |||
854 | if (!rtlhal->mac_func_enable) { | ||
855 | if (_rtl88ee_llt_table_init(hw) == false) { | ||
856 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
857 | "LLT table init fail\n"); | ||
858 | return false; | ||
859 | } | ||
860 | } | ||
861 | |||
862 | |||
863 | rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff); | ||
864 | rtl_write_dword(rtlpriv, REG_HISRE, 0xffffffff); | ||
865 | |||
866 | wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL); | ||
867 | wordtmp &= 0xf; | ||
868 | wordtmp |= 0xE771; | ||
869 | rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp); | ||
870 | |||
871 | rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); | ||
872 | rtl_write_word(rtlpriv, REG_RXFLTMAP2, 0xffff); | ||
873 | rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config); | ||
874 | |||
875 | rtl_write_dword(rtlpriv, REG_BCNQ_DESA, | ||
876 | ((u64) rtlpci->tx_ring[BEACON_QUEUE].dma) & | ||
877 | DMA_BIT_MASK(32)); | ||
878 | rtl_write_dword(rtlpriv, REG_MGQ_DESA, | ||
879 | (u64) rtlpci->tx_ring[MGNT_QUEUE].dma & | ||
880 | DMA_BIT_MASK(32)); | ||
881 | rtl_write_dword(rtlpriv, REG_VOQ_DESA, | ||
882 | (u64) rtlpci->tx_ring[VO_QUEUE].dma & DMA_BIT_MASK(32)); | ||
883 | rtl_write_dword(rtlpriv, REG_VIQ_DESA, | ||
884 | (u64) rtlpci->tx_ring[VI_QUEUE].dma & DMA_BIT_MASK(32)); | ||
885 | rtl_write_dword(rtlpriv, REG_BEQ_DESA, | ||
886 | (u64) rtlpci->tx_ring[BE_QUEUE].dma & DMA_BIT_MASK(32)); | ||
887 | rtl_write_dword(rtlpriv, REG_BKQ_DESA, | ||
888 | (u64) rtlpci->tx_ring[BK_QUEUE].dma & DMA_BIT_MASK(32)); | ||
889 | rtl_write_dword(rtlpriv, REG_HQ_DESA, | ||
890 | (u64) rtlpci->tx_ring[HIGH_QUEUE].dma & | ||
891 | DMA_BIT_MASK(32)); | ||
892 | rtl_write_dword(rtlpriv, REG_RX_DESA, | ||
893 | (u64) rtlpci->rx_ring[RX_MPDU_QUEUE].dma & | ||
894 | DMA_BIT_MASK(32)); | ||
895 | |||
896 | /* if we want to support 64 bit DMA, we should set it here, | ||
897 | * but at the moment we do not support 64 bit DMA | ||
898 | */ | ||
899 | |||
900 | rtl_write_dword(rtlpriv, REG_INT_MIG, 0); | ||
901 | |||
902 | rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0); | ||
903 | rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+1, 0);/*Enable RX DMA */ | ||
904 | |||
905 | if (rtlhal->earlymode_enable) {/*Early mode enable*/ | ||
906 | bytetmp = rtl_read_byte(rtlpriv, REG_EARLY_MODE_CONTROL); | ||
907 | bytetmp |= 0x1f; | ||
908 | rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, bytetmp); | ||
909 | rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL+3, 0x81); | ||
910 | } | ||
911 | _rtl88ee_gen_refresh_led_state(hw); | ||
912 | return true; | ||
913 | } | ||
914 | |||
915 | static void _rtl88ee_hw_configure(struct ieee80211_hw *hw) | ||
916 | { | ||
917 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
918 | u32 reg_prsr; | ||
919 | |||
920 | reg_prsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; | ||
921 | |||
922 | rtl_write_dword(rtlpriv, REG_RRSR, reg_prsr); | ||
923 | rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF); | ||
924 | } | ||
925 | |||
926 | static void _rtl88ee_enable_aspm_back_door(struct ieee80211_hw *hw) | ||
927 | { | ||
928 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
929 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
930 | u8 tmp1byte = 0; | ||
931 | u32 tmp4Byte = 0, count; | ||
932 | |||
933 | rtl_write_word(rtlpriv, 0x354, 0x8104); | ||
934 | rtl_write_word(rtlpriv, 0x358, 0x24); | ||
935 | |||
936 | rtl_write_word(rtlpriv, 0x350, 0x70c); | ||
937 | rtl_write_byte(rtlpriv, 0x352, 0x2); | ||
938 | tmp1byte = rtl_read_byte(rtlpriv, 0x352); | ||
939 | count = 0; | ||
940 | while (tmp1byte && count < 20) { | ||
941 | udelay(10); | ||
942 | tmp1byte = rtl_read_byte(rtlpriv, 0x352); | ||
943 | count++; | ||
944 | } | ||
945 | if (0 == tmp1byte) { | ||
946 | tmp4Byte = rtl_read_dword(rtlpriv, 0x34c); | ||
947 | rtl_write_dword(rtlpriv, 0x348, tmp4Byte|BIT(31)); | ||
948 | rtl_write_word(rtlpriv, 0x350, 0xf70c); | ||
949 | rtl_write_byte(rtlpriv, 0x352, 0x1); | ||
950 | } | ||
951 | |||
952 | tmp1byte = rtl_read_byte(rtlpriv, 0x352); | ||
953 | count = 0; | ||
954 | while (tmp1byte && count < 20) { | ||
955 | udelay(10); | ||
956 | tmp1byte = rtl_read_byte(rtlpriv, 0x352); | ||
957 | count++; | ||
958 | } | ||
959 | |||
960 | rtl_write_word(rtlpriv, 0x350, 0x718); | ||
961 | rtl_write_byte(rtlpriv, 0x352, 0x2); | ||
962 | tmp1byte = rtl_read_byte(rtlpriv, 0x352); | ||
963 | count = 0; | ||
964 | while (tmp1byte && count < 20) { | ||
965 | udelay(10); | ||
966 | tmp1byte = rtl_read_byte(rtlpriv, 0x352); | ||
967 | count++; | ||
968 | } | ||
969 | if (ppsc->support_backdoor || (0 == tmp1byte)) { | ||
970 | tmp4Byte = rtl_read_dword(rtlpriv, 0x34c); | ||
971 | rtl_write_dword(rtlpriv, 0x348, tmp4Byte|BIT(11)|BIT(12)); | ||
972 | rtl_write_word(rtlpriv, 0x350, 0xf718); | ||
973 | rtl_write_byte(rtlpriv, 0x352, 0x1); | ||
974 | } | ||
975 | tmp1byte = rtl_read_byte(rtlpriv, 0x352); | ||
976 | count = 0; | ||
977 | while (tmp1byte && count < 20) { | ||
978 | udelay(10); | ||
979 | tmp1byte = rtl_read_byte(rtlpriv, 0x352); | ||
980 | count++; | ||
981 | } | ||
982 | } | ||
983 | |||
984 | void rtl88ee_enable_hw_security_config(struct ieee80211_hw *hw) | ||
985 | { | ||
986 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
987 | u8 sec_reg_value; | ||
988 | |||
989 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | ||
990 | "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", | ||
991 | rtlpriv->sec.pairwise_enc_algorithm, | ||
992 | rtlpriv->sec.group_enc_algorithm); | ||
993 | |||
994 | if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { | ||
995 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | ||
996 | "not open hw encryption\n"); | ||
997 | return; | ||
998 | } | ||
999 | sec_reg_value = SCR_TXENCENABLE | SCR_RXDECENABLE; | ||
1000 | |||
1001 | if (rtlpriv->sec.use_defaultkey) { | ||
1002 | sec_reg_value |= SCR_TXUSEDK; | ||
1003 | sec_reg_value |= SCR_RXUSEDK; | ||
1004 | } | ||
1005 | |||
1006 | sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); | ||
1007 | |||
1008 | rtl_write_byte(rtlpriv, REG_CR + 1, 0x02); | ||
1009 | |||
1010 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | ||
1011 | "The SECR-value %x\n", sec_reg_value); | ||
1012 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); | ||
1013 | } | ||
1014 | |||
1015 | int rtl88ee_hw_init(struct ieee80211_hw *hw) | ||
1016 | { | ||
1017 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1018 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1019 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1020 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1021 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
1022 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1023 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1024 | bool rtstatus = true; | ||
1025 | int err = 0; | ||
1026 | u8 tmp_u1b, u1byte; | ||
1027 | |||
1028 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Rtl8188EE hw init\n"); | ||
1029 | rtlpriv->rtlhal.being_init_adapter = true; | ||
1030 | rtlpriv->intf_ops->disable_aspm(hw); | ||
1031 | |||
1032 | tmp_u1b = rtl_read_byte(rtlpriv, REG_SYS_CLKR+1); | ||
1033 | u1byte = rtl_read_byte(rtlpriv, REG_CR); | ||
1034 | if ((tmp_u1b & BIT(3)) && (u1byte != 0 && u1byte != 0xEA)) { | ||
1035 | rtlhal->mac_func_enable = true; | ||
1036 | } else { | ||
1037 | rtlhal->mac_func_enable = false; | ||
1038 | rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_88E; | ||
1039 | } | ||
1040 | |||
1041 | rtstatus = _rtl88ee_init_mac(hw); | ||
1042 | if (rtstatus != true) { | ||
1043 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n"); | ||
1044 | err = 1; | ||
1045 | return err; | ||
1046 | } | ||
1047 | |||
1048 | err = rtl88e_download_fw(hw, false); | ||
1049 | if (err) { | ||
1050 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
1051 | "Failed to download FW. Init HW without FW now..\n"); | ||
1052 | err = 1; | ||
1053 | rtlhal->fw_ready = false; | ||
1054 | return err; | ||
1055 | } else { | ||
1056 | rtlhal->fw_ready = true; | ||
1057 | } | ||
1058 | /*fw related variable initialize */ | ||
1059 | rtlhal->last_hmeboxnum = 0; | ||
1060 | rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_88E; | ||
1061 | rtlhal->fw_clk_change_in_progress = false; | ||
1062 | rtlhal->allow_sw_to_change_hwclc = false; | ||
1063 | ppsc->fw_current_inpsmode = false; | ||
1064 | |||
1065 | rtl88e_phy_mac_config(hw); | ||
1066 | /* because last function modifies RCR, we update | ||
1067 | * rcr var here, or TP will be unstable for receive_config | ||
1068 | * is wrong, RX RCR_ACRC32 will cause TP unstable & Rx | ||
1069 | * RCR_APP_ICV will cause mac80211 disassoc for cisco 1252 | ||
1070 | */ | ||
1071 | rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV); | ||
1072 | rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); | ||
1073 | |||
1074 | rtl88e_phy_bb_config(hw); | ||
1075 | rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); | ||
1076 | rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); | ||
1077 | |||
1078 | rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; | ||
1079 | rtl88e_phy_rf_config(hw); | ||
1080 | |||
1081 | rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, | ||
1082 | RF_CHNLBW, RFREG_OFFSET_MASK); | ||
1083 | rtlphy->rfreg_chnlval[0] = rtlphy->rfreg_chnlval[0] & 0xfff00fff; | ||
1084 | |||
1085 | _rtl88ee_hw_configure(hw); | ||
1086 | rtl_cam_reset_all_entry(hw); | ||
1087 | rtl88ee_enable_hw_security_config(hw); | ||
1088 | |||
1089 | rtlhal->mac_func_enable = true; | ||
1090 | ppsc->rfpwr_state = ERFON; | ||
1091 | |||
1092 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); | ||
1093 | _rtl88ee_enable_aspm_back_door(hw); | ||
1094 | rtlpriv->intf_ops->enable_aspm(hw); | ||
1095 | |||
1096 | if (ppsc->rfpwr_state == ERFON) { | ||
1097 | if ((rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) || | ||
1098 | ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) && | ||
1099 | (rtlhal->oem_id == RT_CID_819x_HP))) { | ||
1100 | rtl88e_phy_set_rfpath_switch(hw, true); | ||
1101 | rtlpriv->dm.fat_table.rx_idle_ant = MAIN_ANT; | ||
1102 | } else { | ||
1103 | rtl88e_phy_set_rfpath_switch(hw, false); | ||
1104 | rtlpriv->dm.fat_table.rx_idle_ant = AUX_ANT; | ||
1105 | } | ||
1106 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1107 | "rx idle ant %s\n", | ||
1108 | (rtlpriv->dm.fat_table.rx_idle_ant == MAIN_ANT) ? | ||
1109 | ("MAIN_ANT") : ("AUX_ANT")); | ||
1110 | |||
1111 | if (rtlphy->iqk_initialized) { | ||
1112 | rtl88e_phy_iq_calibrate(hw, true); | ||
1113 | } else { | ||
1114 | rtl88e_phy_iq_calibrate(hw, false); | ||
1115 | rtlphy->iqk_initialized = true; | ||
1116 | } | ||
1117 | rtl88e_dm_check_txpower_tracking(hw); | ||
1118 | rtl88e_phy_lc_calibrate(hw); | ||
1119 | } | ||
1120 | |||
1121 | tmp_u1b = efuse_read_1byte(hw, 0x1FA); | ||
1122 | if (!(tmp_u1b & BIT(0))) { | ||
1123 | rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0F, 0x05); | ||
1124 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "PA BIAS path A\n"); | ||
1125 | } | ||
1126 | |||
1127 | if (!(tmp_u1b & BIT(4))) { | ||
1128 | tmp_u1b = rtl_read_byte(rtlpriv, 0x16); | ||
1129 | tmp_u1b &= 0x0F; | ||
1130 | rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x80); | ||
1131 | udelay(10); | ||
1132 | rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x90); | ||
1133 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "under 1.5V\n"); | ||
1134 | } | ||
1135 | rtl_write_byte(rtlpriv, REG_NAV_CTRL+2, ((30000+127)/128)); | ||
1136 | rtl88e_dm_init(hw); | ||
1137 | rtlpriv->rtlhal.being_init_adapter = false; | ||
1138 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "end of Rtl8188EE hw init %x\n", | ||
1139 | err); | ||
1140 | return 0; | ||
1141 | } | ||
1142 | |||
1143 | static enum version_8188e _rtl88ee_read_chip_version(struct ieee80211_hw *hw) | ||
1144 | { | ||
1145 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1146 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1147 | enum version_8188e version = VERSION_UNKNOWN; | ||
1148 | u32 value32; | ||
1149 | |||
1150 | value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG); | ||
1151 | if (value32 & TRP_VAUX_EN) { | ||
1152 | version = (enum version_8188e) VERSION_TEST_CHIP_88E; | ||
1153 | } else { | ||
1154 | version = NORMAL_CHIP; | ||
1155 | version = version | ((value32 & TYPE_ID) ? RF_TYPE_2T2R : 0); | ||
1156 | version = version | ((value32 & VENDOR_ID) ? | ||
1157 | CHIP_VENDOR_UMC : 0); | ||
1158 | } | ||
1159 | |||
1160 | rtlphy->rf_type = RF_1T1R; | ||
1161 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1162 | "Chip RF Type: %s\n", (rtlphy->rf_type == RF_2T2R) ? | ||
1163 | "RF_2T2R" : "RF_1T1R"); | ||
1164 | |||
1165 | return version; | ||
1166 | } | ||
1167 | |||
1168 | static int _rtl88ee_set_media_status(struct ieee80211_hw *hw, | ||
1169 | enum nl80211_iftype type) | ||
1170 | { | ||
1171 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1172 | u8 bt_msr = rtl_read_byte(rtlpriv, MSR); | ||
1173 | enum led_ctl_mode ledaction = LED_CTL_NO_LINK; | ||
1174 | bt_msr &= 0xfc; | ||
1175 | |||
1176 | if (type == NL80211_IFTYPE_UNSPECIFIED || | ||
1177 | type == NL80211_IFTYPE_STATION) { | ||
1178 | _rtl88ee_stop_tx_beacon(hw); | ||
1179 | _rtl88ee_enable_bcn_sub_func(hw); | ||
1180 | } else if (type == NL80211_IFTYPE_ADHOC || | ||
1181 | type == NL80211_IFTYPE_AP || | ||
1182 | type == NL80211_IFTYPE_MESH_POINT) { | ||
1183 | _rtl88ee_resume_tx_beacon(hw); | ||
1184 | _rtl88ee_disable_bcn_sub_func(hw); | ||
1185 | } else { | ||
1186 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
1187 | "Set HW_VAR_MEDIA_STATUS: No such media status(%x).\n", | ||
1188 | type); | ||
1189 | } | ||
1190 | |||
1191 | switch (type) { | ||
1192 | case NL80211_IFTYPE_UNSPECIFIED: | ||
1193 | bt_msr |= MSR_NOLINK; | ||
1194 | ledaction = LED_CTL_LINK; | ||
1195 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1196 | "Set Network type to NO LINK!\n"); | ||
1197 | break; | ||
1198 | case NL80211_IFTYPE_ADHOC: | ||
1199 | bt_msr |= MSR_ADHOC; | ||
1200 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1201 | "Set Network type to Ad Hoc!\n"); | ||
1202 | break; | ||
1203 | case NL80211_IFTYPE_STATION: | ||
1204 | bt_msr |= MSR_INFRA; | ||
1205 | ledaction = LED_CTL_LINK; | ||
1206 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1207 | "Set Network type to STA!\n"); | ||
1208 | break; | ||
1209 | case NL80211_IFTYPE_AP: | ||
1210 | bt_msr |= MSR_AP; | ||
1211 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1212 | "Set Network type to AP!\n"); | ||
1213 | break; | ||
1214 | case NL80211_IFTYPE_MESH_POINT: | ||
1215 | bt_msr |= MSR_ADHOC; | ||
1216 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1217 | "Set Network type to Mesh Point!\n"); | ||
1218 | break; | ||
1219 | default: | ||
1220 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1221 | "Network type %d not support!\n", type); | ||
1222 | return 1; | ||
1223 | } | ||
1224 | |||
1225 | rtl_write_byte(rtlpriv, (MSR), bt_msr); | ||
1226 | rtlpriv->cfg->ops->led_control(hw, ledaction); | ||
1227 | if ((bt_msr & 0xfc) == MSR_AP) | ||
1228 | rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); | ||
1229 | else | ||
1230 | rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66); | ||
1231 | return 0; | ||
1232 | } | ||
1233 | |||
1234 | void rtl88ee_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) | ||
1235 | { | ||
1236 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1237 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1238 | u32 reg_rcr = rtlpci->receive_config; | ||
1239 | |||
1240 | if (rtlpriv->psc.rfpwr_state != ERFON) | ||
1241 | return; | ||
1242 | |||
1243 | if (check_bssid == true) { | ||
1244 | reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); | ||
1245 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, | ||
1246 | (u8 *)(®_rcr)); | ||
1247 | _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(4)); | ||
1248 | } else if (check_bssid == false) { | ||
1249 | reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); | ||
1250 | _rtl88ee_set_bcn_ctrl_reg(hw, BIT(4), 0); | ||
1251 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
1252 | HW_VAR_RCR, (u8 *)(®_rcr)); | ||
1253 | } | ||
1254 | } | ||
1255 | |||
1256 | int rtl88ee_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) | ||
1257 | { | ||
1258 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1259 | |||
1260 | if (_rtl88ee_set_media_status(hw, type)) | ||
1261 | return -EOPNOTSUPP; | ||
1262 | |||
1263 | if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { | ||
1264 | if (type != NL80211_IFTYPE_AP && | ||
1265 | type != NL80211_IFTYPE_MESH_POINT) | ||
1266 | rtl88ee_set_check_bssid(hw, true); | ||
1267 | } else { | ||
1268 | rtl88ee_set_check_bssid(hw, false); | ||
1269 | } | ||
1270 | |||
1271 | return 0; | ||
1272 | } | ||
1273 | |||
1274 | /* don't set REG_EDCA_BE_PARAM here because mac80211 will send pkt when scan */ | ||
1275 | void rtl88ee_set_qos(struct ieee80211_hw *hw, int aci) | ||
1276 | { | ||
1277 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1278 | rtl88e_dm_init_edca_turbo(hw); | ||
1279 | switch (aci) { | ||
1280 | case AC1_BK: | ||
1281 | rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f); | ||
1282 | break; | ||
1283 | case AC0_BE: | ||
1284 | break; | ||
1285 | case AC2_VI: | ||
1286 | rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322); | ||
1287 | break; | ||
1288 | case AC3_VO: | ||
1289 | rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222); | ||
1290 | break; | ||
1291 | default: | ||
1292 | RT_ASSERT(false, "invalid aci: %d !\n", aci); | ||
1293 | break; | ||
1294 | } | ||
1295 | } | ||
1296 | |||
1297 | void rtl88ee_enable_interrupt(struct ieee80211_hw *hw) | ||
1298 | { | ||
1299 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1300 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1301 | |||
1302 | rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF); | ||
1303 | rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF); | ||
1304 | rtlpci->irq_enabled = true; | ||
1305 | /* there are some C2H CMDs have been sent before system interrupt | ||
1306 | * is enabled, e.g., C2H, CPWM. | ||
1307 | * So we need to clear all C2H events that FW has notified, otherwise | ||
1308 | * FW won't schedule any commands anymore. | ||
1309 | */ | ||
1310 | rtl_write_byte(rtlpriv, REG_C2HEVT_CLEAR, 0); | ||
1311 | /*enable system interrupt*/ | ||
1312 | rtl_write_dword(rtlpriv, REG_HSIMR, rtlpci->sys_irq_mask & 0xFFFFFFFF); | ||
1313 | } | ||
1314 | |||
1315 | void rtl88ee_disable_interrupt(struct ieee80211_hw *hw) | ||
1316 | { | ||
1317 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1318 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1319 | |||
1320 | rtl_write_dword(rtlpriv, REG_HIMR, IMR_DISABLED); | ||
1321 | rtl_write_dword(rtlpriv, REG_HIMRE, IMR_DISABLED); | ||
1322 | rtlpci->irq_enabled = false; | ||
1323 | synchronize_irq(rtlpci->pdev->irq); | ||
1324 | } | ||
1325 | |||
1326 | static void _rtl88ee_poweroff_adapter(struct ieee80211_hw *hw) | ||
1327 | { | ||
1328 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1329 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1330 | u8 u1b_tmp; | ||
1331 | u32 count = 0; | ||
1332 | rtlhal->mac_func_enable = false; | ||
1333 | rtlpriv->intf_ops->enable_aspm(hw); | ||
1334 | |||
1335 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "POWER OFF adapter\n"); | ||
1336 | u1b_tmp = rtl_read_byte(rtlpriv, REG_TX_RPT_CTRL); | ||
1337 | rtl_write_byte(rtlpriv, REG_TX_RPT_CTRL, u1b_tmp & (~BIT(1))); | ||
1338 | |||
1339 | u1b_tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); | ||
1340 | while (!(u1b_tmp & BIT(1)) && (count++ < 100)) { | ||
1341 | udelay(10); | ||
1342 | u1b_tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); | ||
1343 | count++; | ||
1344 | } | ||
1345 | rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+1, 0xFF); | ||
1346 | |||
1347 | rtl88_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, | ||
1348 | PWR_INTF_PCI_MSK, | ||
1349 | Rtl8188E_NIC_LPS_ENTER_FLOW); | ||
1350 | |||
1351 | rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00); | ||
1352 | |||
1353 | if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && rtlhal->fw_ready) | ||
1354 | rtl88e_firmware_selfreset(hw); | ||
1355 | |||
1356 | u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1); | ||
1357 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2)))); | ||
1358 | rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); | ||
1359 | |||
1360 | u1b_tmp = rtl_read_byte(rtlpriv, REG_32K_CTRL); | ||
1361 | rtl_write_byte(rtlpriv, REG_32K_CTRL, (u1b_tmp & (~BIT(0)))); | ||
1362 | |||
1363 | rtl88_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, | ||
1364 | PWR_INTF_PCI_MSK, Rtl8188E_NIC_DISABLE_FLOW); | ||
1365 | |||
1366 | u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL+1); | ||
1367 | rtl_write_byte(rtlpriv, REG_RSV_CTRL+1, (u1b_tmp & (~BIT(3)))); | ||
1368 | u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL+1); | ||
1369 | rtl_write_byte(rtlpriv, REG_RSV_CTRL+1, (u1b_tmp | BIT(3))); | ||
1370 | |||
1371 | rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0E); | ||
1372 | |||
1373 | u1b_tmp = rtl_read_byte(rtlpriv, GPIO_IN); | ||
1374 | rtl_write_byte(rtlpriv, GPIO_OUT, u1b_tmp); | ||
1375 | rtl_write_byte(rtlpriv, GPIO_IO_SEL, 0x7F); | ||
1376 | |||
1377 | u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL); | ||
1378 | rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL, (u1b_tmp << 4) | u1b_tmp); | ||
1379 | u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL+1); | ||
1380 | rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL+1, u1b_tmp | 0x0F); | ||
1381 | |||
1382 | rtl_write_dword(rtlpriv, REG_GPIO_IO_SEL_2+2, 0x00080808); | ||
1383 | } | ||
1384 | |||
1385 | void rtl88ee_card_disable(struct ieee80211_hw *hw) | ||
1386 | { | ||
1387 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1388 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
1389 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1390 | enum nl80211_iftype opmode; | ||
1391 | |||
1392 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "RTL8188ee card disable\n"); | ||
1393 | |||
1394 | mac->link_state = MAC80211_NOLINK; | ||
1395 | opmode = NL80211_IFTYPE_UNSPECIFIED; | ||
1396 | |||
1397 | _rtl88ee_set_media_status(hw, opmode); | ||
1398 | |||
1399 | if (rtlpriv->rtlhal.driver_is_goingto_unload || | ||
1400 | ppsc->rfoff_reason > RF_CHANGE_BY_PS) | ||
1401 | rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); | ||
1402 | |||
1403 | RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); | ||
1404 | _rtl88ee_poweroff_adapter(hw); | ||
1405 | |||
1406 | /* after power off we should do iqk again */ | ||
1407 | rtlpriv->phy.iqk_initialized = false; | ||
1408 | } | ||
1409 | |||
1410 | void rtl88ee_interrupt_recognized(struct ieee80211_hw *hw, | ||
1411 | u32 *p_inta, u32 *p_intb) | ||
1412 | { | ||
1413 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1414 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1415 | |||
1416 | *p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0]; | ||
1417 | rtl_write_dword(rtlpriv, ISR, *p_inta); | ||
1418 | |||
1419 | *p_intb = rtl_read_dword(rtlpriv, REG_HISRE) & rtlpci->irq_mask[1]; | ||
1420 | rtl_write_dword(rtlpriv, REG_HISRE, *p_intb); | ||
1421 | } | ||
1422 | |||
1423 | void rtl88ee_set_beacon_related_registers(struct ieee80211_hw *hw) | ||
1424 | { | ||
1425 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1426 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1427 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1428 | u16 bcn_interval, atim_window; | ||
1429 | |||
1430 | bcn_interval = mac->beacon_interval; | ||
1431 | atim_window = 2; /*FIX MERGE */ | ||
1432 | rtl88ee_disable_interrupt(hw); | ||
1433 | rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); | ||
1434 | rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); | ||
1435 | rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f); | ||
1436 | rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x18); | ||
1437 | rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x18); | ||
1438 | rtl_write_byte(rtlpriv, 0x606, 0x30); | ||
1439 | rtlpci->reg_bcn_ctrl_val |= BIT(3); | ||
1440 | rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val); | ||
1441 | /*rtl88ee_enable_interrupt(hw);*/ | ||
1442 | } | ||
1443 | |||
1444 | void rtl88ee_set_beacon_interval(struct ieee80211_hw *hw) | ||
1445 | { | ||
1446 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1447 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1448 | u16 bcn_interval = mac->beacon_interval; | ||
1449 | |||
1450 | RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, | ||
1451 | "beacon_interval:%d\n", bcn_interval); | ||
1452 | /*rtl88ee_disable_interrupt(hw);*/ | ||
1453 | rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); | ||
1454 | /*rtl88ee_enable_interrupt(hw);*/ | ||
1455 | } | ||
1456 | |||
1457 | void rtl88ee_update_interrupt_mask(struct ieee80211_hw *hw, | ||
1458 | u32 add_msr, u32 rm_msr) | ||
1459 | { | ||
1460 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1461 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1462 | |||
1463 | RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, | ||
1464 | "add_msr:%x, rm_msr:%x\n", add_msr, rm_msr); | ||
1465 | |||
1466 | rtl88ee_disable_interrupt(hw); | ||
1467 | if (add_msr) | ||
1468 | rtlpci->irq_mask[0] |= add_msr; | ||
1469 | if (rm_msr) | ||
1470 | rtlpci->irq_mask[0] &= (~rm_msr); | ||
1471 | rtl88ee_enable_interrupt(hw); | ||
1472 | } | ||
1473 | |||
1474 | static inline u8 get_chnl_group(u8 chnl) | ||
1475 | { | ||
1476 | u8 group; | ||
1477 | |||
1478 | group = chnl / 3; | ||
1479 | if (chnl == 14) | ||
1480 | group = 5; | ||
1481 | |||
1482 | return group; | ||
1483 | } | ||
1484 | |||
1485 | static void set_diff0_2g(struct txpower_info_2g *pwr2g, u8 *hwinfo, u32 path, | ||
1486 | u32 i, u32 eadr) | ||
1487 | { | ||
1488 | pwr2g->bw40_diff[path][i] = 0; | ||
1489 | if (hwinfo[eadr] == 0xFF) { | ||
1490 | pwr2g->bw20_diff[path][i] = 0x02; | ||
1491 | } else { | ||
1492 | pwr2g->bw20_diff[path][i] = (hwinfo[eadr]&0xf0)>>4; | ||
1493 | /*bit sign number to 8 bit sign number*/ | ||
1494 | if (pwr2g->bw20_diff[path][i] & BIT(3)) | ||
1495 | pwr2g->bw20_diff[path][i] |= 0xF0; | ||
1496 | } | ||
1497 | |||
1498 | if (hwinfo[eadr] == 0xFF) { | ||
1499 | pwr2g->ofdm_diff[path][i] = 0x04; | ||
1500 | } else { | ||
1501 | pwr2g->ofdm_diff[path][i] = (hwinfo[eadr] & 0x0f); | ||
1502 | /*bit sign number to 8 bit sign number*/ | ||
1503 | if (pwr2g->ofdm_diff[path][i] & BIT(3)) | ||
1504 | pwr2g->ofdm_diff[path][i] |= 0xF0; | ||
1505 | } | ||
1506 | pwr2g->cck_diff[path][i] = 0; | ||
1507 | } | ||
1508 | |||
1509 | static void set_diff0_5g(struct txpower_info_5g *pwr5g, u8 *hwinfo, u32 path, | ||
1510 | u32 i, u32 eadr) | ||
1511 | { | ||
1512 | pwr5g->bw40_diff[path][i] = 0; | ||
1513 | if (hwinfo[eadr] == 0xFF) { | ||
1514 | pwr5g->bw20_diff[path][i] = 0; | ||
1515 | } else { | ||
1516 | pwr5g->bw20_diff[path][i] = (hwinfo[eadr]&0xf0)>>4; | ||
1517 | /*bit sign number to 8 bit sign number*/ | ||
1518 | if (pwr5g->bw20_diff[path][i] & BIT(3)) | ||
1519 | pwr5g->bw20_diff[path][i] |= 0xF0; | ||
1520 | } | ||
1521 | |||
1522 | if (hwinfo[eadr] == 0xFF) { | ||
1523 | pwr5g->ofdm_diff[path][i] = 0x04; | ||
1524 | } else { | ||
1525 | pwr5g->ofdm_diff[path][i] = (hwinfo[eadr] & 0x0f); | ||
1526 | /*bit sign number to 8 bit sign number*/ | ||
1527 | if (pwr5g->ofdm_diff[path][i] & BIT(3)) | ||
1528 | pwr5g->ofdm_diff[path][i] |= 0xF0; | ||
1529 | } | ||
1530 | } | ||
1531 | |||
1532 | static void set_diff1_2g(struct txpower_info_2g *pwr2g, u8 *hwinfo, u32 path, | ||
1533 | u32 i, u32 eadr) | ||
1534 | { | ||
1535 | if (hwinfo[eadr] == 0xFF) { | ||
1536 | pwr2g->bw40_diff[path][i] = 0xFE; | ||
1537 | } else { | ||
1538 | pwr2g->bw40_diff[path][i] = (hwinfo[eadr]&0xf0)>>4; | ||
1539 | if (pwr2g->bw40_diff[path][i] & BIT(3)) | ||
1540 | pwr2g->bw40_diff[path][i] |= 0xF0; | ||
1541 | } | ||
1542 | |||
1543 | if (hwinfo[eadr] == 0xFF) { | ||
1544 | pwr2g->bw20_diff[path][i] = 0xFE; | ||
1545 | } else { | ||
1546 | pwr2g->bw20_diff[path][i] = (hwinfo[eadr]&0x0f); | ||
1547 | if (pwr2g->bw20_diff[path][i] & BIT(3)) | ||
1548 | pwr2g->bw20_diff[path][i] |= 0xF0; | ||
1549 | } | ||
1550 | } | ||
1551 | |||
1552 | static void set_diff1_5g(struct txpower_info_5g *pwr5g, u8 *hwinfo, u32 path, | ||
1553 | u32 i, u32 eadr) | ||
1554 | { | ||
1555 | if (hwinfo[eadr] == 0xFF) { | ||
1556 | pwr5g->bw40_diff[path][i] = 0xFE; | ||
1557 | } else { | ||
1558 | pwr5g->bw40_diff[path][i] = (hwinfo[eadr]&0xf0)>>4; | ||
1559 | if (pwr5g->bw40_diff[path][i] & BIT(3)) | ||
1560 | pwr5g->bw40_diff[path][i] |= 0xF0; | ||
1561 | } | ||
1562 | |||
1563 | if (hwinfo[eadr] == 0xFF) { | ||
1564 | pwr5g->bw20_diff[path][i] = 0xFE; | ||
1565 | } else { | ||
1566 | pwr5g->bw20_diff[path][i] = (hwinfo[eadr] & 0x0f); | ||
1567 | if (pwr5g->bw20_diff[path][i] & BIT(3)) | ||
1568 | pwr5g->bw20_diff[path][i] |= 0xF0; | ||
1569 | } | ||
1570 | } | ||
1571 | |||
1572 | static void set_diff2_2g(struct txpower_info_2g *pwr2g, u8 *hwinfo, u32 path, | ||
1573 | u32 i, u32 eadr) | ||
1574 | { | ||
1575 | if (hwinfo[eadr] == 0xFF) { | ||
1576 | pwr2g->ofdm_diff[path][i] = 0xFE; | ||
1577 | } else { | ||
1578 | pwr2g->ofdm_diff[path][i] = (hwinfo[eadr]&0xf0)>>4; | ||
1579 | if (pwr2g->ofdm_diff[path][i] & BIT(3)) | ||
1580 | pwr2g->ofdm_diff[path][i] |= 0xF0; | ||
1581 | } | ||
1582 | |||
1583 | if (hwinfo[eadr] == 0xFF) { | ||
1584 | pwr2g->cck_diff[path][i] = 0xFE; | ||
1585 | } else { | ||
1586 | pwr2g->cck_diff[path][i] = (hwinfo[eadr]&0x0f); | ||
1587 | if (pwr2g->cck_diff[path][i] & BIT(3)) | ||
1588 | pwr2g->cck_diff[path][i] |= 0xF0; | ||
1589 | } | ||
1590 | } | ||
1591 | |||
1592 | static void _rtl8188e_read_power_value_fromprom(struct ieee80211_hw *hw, | ||
1593 | struct txpower_info_2g *pwr2g, | ||
1594 | struct txpower_info_5g *pwr5g, | ||
1595 | bool autoload_fail, | ||
1596 | u8 *hwinfo) | ||
1597 | { | ||
1598 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1599 | u32 path, eadr = EEPROM_TX_PWR_INX, i; | ||
1600 | |||
1601 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1602 | "hal_ReadPowerValueFromPROM88E(): PROMContent[0x%x]= 0x%x\n", | ||
1603 | (eadr+1), hwinfo[eadr+1]); | ||
1604 | if (0xFF == hwinfo[eadr+1]) | ||
1605 | autoload_fail = true; | ||
1606 | |||
1607 | if (autoload_fail) { | ||
1608 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1609 | "auto load fail : Use Default value!\n"); | ||
1610 | for (path = 0; path < MAX_RF_PATH; path++) { | ||
1611 | /* 2.4G default value */ | ||
1612 | for (i = 0; i < MAX_CHNL_GROUP_24G; i++) { | ||
1613 | pwr2g->index_cck_base[path][i] = 0x2D; | ||
1614 | pwr2g->index_bw40_base[path][i] = 0x2D; | ||
1615 | } | ||
1616 | for (i = 0; i < MAX_TX_COUNT; i++) { | ||
1617 | if (i == 0) { | ||
1618 | pwr2g->bw20_diff[path][0] = 0x02; | ||
1619 | pwr2g->ofdm_diff[path][0] = 0x04; | ||
1620 | } else { | ||
1621 | pwr2g->bw20_diff[path][i] = 0xFE; | ||
1622 | pwr2g->bw40_diff[path][i] = 0xFE; | ||
1623 | pwr2g->cck_diff[path][i] = 0xFE; | ||
1624 | pwr2g->ofdm_diff[path][i] = 0xFE; | ||
1625 | } | ||
1626 | } | ||
1627 | } | ||
1628 | return; | ||
1629 | } | ||
1630 | |||
1631 | for (path = 0; path < MAX_RF_PATH; path++) { | ||
1632 | /*2.4G default value*/ | ||
1633 | for (i = 0; i < MAX_CHNL_GROUP_24G; i++) { | ||
1634 | pwr2g->index_cck_base[path][i] = hwinfo[eadr++]; | ||
1635 | if (pwr2g->index_cck_base[path][i] == 0xFF) | ||
1636 | pwr2g->index_cck_base[path][i] = 0x2D; | ||
1637 | } | ||
1638 | for (i = 0; i < MAX_CHNL_GROUP_24G-1; i++) { | ||
1639 | pwr2g->index_bw40_base[path][i] = hwinfo[eadr++]; | ||
1640 | if (pwr2g->index_bw40_base[path][i] == 0xFF) | ||
1641 | pwr2g->index_bw40_base[path][i] = 0x2D; | ||
1642 | } | ||
1643 | for (i = 0; i < MAX_TX_COUNT; i++) { | ||
1644 | if (i == 0) { | ||
1645 | set_diff0_2g(pwr2g, hwinfo, path, i, eadr); | ||
1646 | eadr++; | ||
1647 | } else { | ||
1648 | set_diff1_2g(pwr2g, hwinfo, path, i, eadr); | ||
1649 | eadr++; | ||
1650 | |||
1651 | set_diff2_2g(pwr2g, hwinfo, path, i, eadr); | ||
1652 | eadr++; | ||
1653 | } | ||
1654 | } | ||
1655 | |||
1656 | /*5G default value*/ | ||
1657 | for (i = 0; i < MAX_CHNL_GROUP_5G; i++) { | ||
1658 | pwr5g->index_bw40_base[path][i] = hwinfo[eadr++]; | ||
1659 | if (pwr5g->index_bw40_base[path][i] == 0xFF) | ||
1660 | pwr5g->index_bw40_base[path][i] = 0xFE; | ||
1661 | } | ||
1662 | |||
1663 | for (i = 0; i < MAX_TX_COUNT; i++) { | ||
1664 | if (i == 0) { | ||
1665 | set_diff0_5g(pwr5g, hwinfo, path, i, eadr); | ||
1666 | eadr++; | ||
1667 | } else { | ||
1668 | set_diff1_5g(pwr5g, hwinfo, path, i, eadr); | ||
1669 | eadr++; | ||
1670 | } | ||
1671 | } | ||
1672 | |||
1673 | if (hwinfo[eadr] == 0xFF) { | ||
1674 | pwr5g->ofdm_diff[path][1] = 0xFE; | ||
1675 | pwr5g->ofdm_diff[path][2] = 0xFE; | ||
1676 | } else { | ||
1677 | pwr5g->ofdm_diff[path][1] = (hwinfo[eadr] & 0xf0) >> 4; | ||
1678 | pwr5g->ofdm_diff[path][2] = (hwinfo[eadr] & 0x0f); | ||
1679 | } | ||
1680 | eadr++; | ||
1681 | |||
1682 | if (hwinfo[eadr] == 0xFF) | ||
1683 | pwr5g->ofdm_diff[path][3] = 0xFE; | ||
1684 | else | ||
1685 | pwr5g->ofdm_diff[path][3] = (hwinfo[eadr]&0x0f); | ||
1686 | eadr++; | ||
1687 | |||
1688 | for (i = 1; i < MAX_TX_COUNT; i++) { | ||
1689 | if (pwr5g->ofdm_diff[path][i] == 0xFF) | ||
1690 | pwr5g->ofdm_diff[path][i] = 0xFE; | ||
1691 | else if (pwr5g->ofdm_diff[path][i] & BIT(3)) | ||
1692 | pwr5g->ofdm_diff[path][i] |= 0xF0; | ||
1693 | } | ||
1694 | } | ||
1695 | } | ||
1696 | |||
1697 | static void _rtl88ee_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | ||
1698 | bool autoload_fail, | ||
1699 | u8 *hwinfo) | ||
1700 | { | ||
1701 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1702 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1703 | struct txpower_info_2g pwrinfo24g; | ||
1704 | struct txpower_info_5g pwrinfo5g; | ||
1705 | u8 rf_path, index; | ||
1706 | u8 i; | ||
1707 | int jj = EEPROM_RF_BOARD_OPTION_88E; | ||
1708 | int kk = EEPROM_THERMAL_METER_88E; | ||
1709 | |||
1710 | _rtl8188e_read_power_value_fromprom(hw, &pwrinfo24g, &pwrinfo5g, | ||
1711 | autoload_fail, hwinfo); | ||
1712 | |||
1713 | for (rf_path = 0; rf_path < 2; rf_path++) { | ||
1714 | for (i = 0; i < 14; i++) { | ||
1715 | index = get_chnl_group(i+1); | ||
1716 | |||
1717 | rtlefuse->txpwrlevel_cck[rf_path][i] = | ||
1718 | pwrinfo24g.index_cck_base[rf_path][index]; | ||
1719 | if (i == 13) | ||
1720 | rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = | ||
1721 | pwrinfo24g.index_bw40_base[rf_path][4]; | ||
1722 | else | ||
1723 | rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = | ||
1724 | pwrinfo24g.index_bw40_base[rf_path][index]; | ||
1725 | rtlefuse->txpwr_ht20diff[rf_path][i] = | ||
1726 | pwrinfo24g.bw20_diff[rf_path][0]; | ||
1727 | rtlefuse->txpwr_legacyhtdiff[rf_path][i] = | ||
1728 | pwrinfo24g.ofdm_diff[rf_path][0]; | ||
1729 | } | ||
1730 | |||
1731 | for (i = 0; i < 14; i++) { | ||
1732 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, | ||
1733 | "RF(%d)-Ch(%d) [CCK / HT40_1S ] = " | ||
1734 | "[0x%x / 0x%x ]\n", rf_path, i, | ||
1735 | rtlefuse->txpwrlevel_cck[rf_path][i], | ||
1736 | rtlefuse->txpwrlevel_ht40_1s[rf_path][i]); | ||
1737 | } | ||
1738 | } | ||
1739 | |||
1740 | if (!autoload_fail) | ||
1741 | rtlefuse->eeprom_thermalmeter = hwinfo[kk]; | ||
1742 | else | ||
1743 | rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER; | ||
1744 | |||
1745 | if (rtlefuse->eeprom_thermalmeter == 0xff || autoload_fail) { | ||
1746 | rtlefuse->apk_thermalmeterignore = true; | ||
1747 | rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER; | ||
1748 | } | ||
1749 | |||
1750 | rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; | ||
1751 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, | ||
1752 | "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); | ||
1753 | |||
1754 | if (!autoload_fail) { | ||
1755 | rtlefuse->eeprom_regulatory = hwinfo[jj] & 0x07;/*bit0~2*/ | ||
1756 | if (hwinfo[jj] == 0xFF) | ||
1757 | rtlefuse->eeprom_regulatory = 0; | ||
1758 | } else { | ||
1759 | rtlefuse->eeprom_regulatory = 0; | ||
1760 | } | ||
1761 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, | ||
1762 | "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); | ||
1763 | } | ||
1764 | |||
1765 | static void _rtl88ee_read_adapter_info(struct ieee80211_hw *hw) | ||
1766 | { | ||
1767 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1768 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1769 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1770 | struct rtl_pci_priv *rppriv = rtl_pcipriv(hw); | ||
1771 | u16 i, usvalue; | ||
1772 | u8 hwinfo[HWSET_MAX_SIZE]; | ||
1773 | u16 eeprom_id; | ||
1774 | int jj = EEPROM_RF_BOARD_OPTION_88E; | ||
1775 | int kk = EEPROM_RF_FEATURE_OPTION_88E; | ||
1776 | |||
1777 | if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { | ||
1778 | rtl_efuse_shadow_map_update(hw); | ||
1779 | |||
1780 | memcpy(hwinfo, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], | ||
1781 | HWSET_MAX_SIZE); | ||
1782 | } else if (rtlefuse->epromtype == EEPROM_93C46) { | ||
1783 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1784 | "RTL819X Not boot from eeprom, check it !!"); | ||
1785 | } | ||
1786 | |||
1787 | RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, ("MAP\n"), | ||
1788 | hwinfo, HWSET_MAX_SIZE); | ||
1789 | |||
1790 | eeprom_id = *((u16 *)&hwinfo[0]); | ||
1791 | if (eeprom_id != RTL8188E_EEPROM_ID) { | ||
1792 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
1793 | "EEPROM ID(%#x) is invalid!!\n", eeprom_id); | ||
1794 | rtlefuse->autoload_failflag = true; | ||
1795 | } else { | ||
1796 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); | ||
1797 | rtlefuse->autoload_failflag = false; | ||
1798 | } | ||
1799 | |||
1800 | if (rtlefuse->autoload_failflag == true) | ||
1801 | return; | ||
1802 | /*VID DID SVID SDID*/ | ||
1803 | rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; | ||
1804 | rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; | ||
1805 | rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; | ||
1806 | rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; | ||
1807 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1808 | "EEPROMId = 0x%4x\n", eeprom_id); | ||
1809 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1810 | "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid); | ||
1811 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1812 | "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did); | ||
1813 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1814 | "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid); | ||
1815 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1816 | "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid); | ||
1817 | /*customer ID*/ | ||
1818 | rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMER_ID]; | ||
1819 | if (rtlefuse->eeprom_oemid == 0xFF) | ||
1820 | rtlefuse->eeprom_oemid = 0; | ||
1821 | |||
1822 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1823 | "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid); | ||
1824 | /*EEPROM version*/ | ||
1825 | rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; | ||
1826 | /*mac address*/ | ||
1827 | for (i = 0; i < 6; i += 2) { | ||
1828 | usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; | ||
1829 | *((u16 *)(&rtlefuse->dev_addr[i])) = usvalue; | ||
1830 | } | ||
1831 | |||
1832 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | ||
1833 | "dev_addr: %pM\n", rtlefuse->dev_addr); | ||
1834 | /*channel plan */ | ||
1835 | rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN]; | ||
1836 | /* set channel paln to world wide 13 */ | ||
1837 | rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13; | ||
1838 | /*tx power*/ | ||
1839 | _rtl88ee_read_txpower_info_from_hwpg(hw, rtlefuse->autoload_failflag, | ||
1840 | hwinfo); | ||
1841 | rtlefuse->txpwr_fromeprom = true; | ||
1842 | |||
1843 | rtl8188ee_read_bt_coexist_info_from_hwpg(hw, | ||
1844 | rtlefuse->autoload_failflag, | ||
1845 | hwinfo); | ||
1846 | /*board type*/ | ||
1847 | rtlefuse->board_type = (((*(u8 *)&hwinfo[jj]) & 0xE0) >> 5); | ||
1848 | /*Wake on wlan*/ | ||
1849 | rtlefuse->wowlan_enable = ((hwinfo[kk] & 0x40) >> 6); | ||
1850 | /*parse xtal*/ | ||
1851 | rtlefuse->crystalcap = hwinfo[EEPROM_XTAL_88E]; | ||
1852 | if (hwinfo[EEPROM_XTAL_88E]) | ||
1853 | rtlefuse->crystalcap = 0x20; | ||
1854 | /*antenna diversity*/ | ||
1855 | rtlefuse->antenna_div_cfg = (hwinfo[jj] & 0x18) >> 3; | ||
1856 | if (hwinfo[jj] == 0xFF) | ||
1857 | rtlefuse->antenna_div_cfg = 0; | ||
1858 | if (rppriv->bt_coexist.eeprom_bt_coexist != 0 && | ||
1859 | rppriv->bt_coexist.eeprom_bt_ant_num == ANT_X1) | ||
1860 | rtlefuse->antenna_div_cfg = 0; | ||
1861 | |||
1862 | rtlefuse->antenna_div_type = hwinfo[EEPROM_RF_ANTENNA_OPT_88E]; | ||
1863 | if (rtlefuse->antenna_div_type == 0xFF) | ||
1864 | rtlefuse->antenna_div_type = 0x01; | ||
1865 | if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV || | ||
1866 | rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) | ||
1867 | rtlefuse->antenna_div_cfg = 1; | ||
1868 | |||
1869 | if (rtlhal->oem_id == RT_CID_DEFAULT) { | ||
1870 | switch (rtlefuse->eeprom_oemid) { | ||
1871 | case EEPROM_CID_DEFAULT: | ||
1872 | if (rtlefuse->eeprom_did == 0x8179) { | ||
1873 | if (rtlefuse->eeprom_svid == 0x1025) { | ||
1874 | rtlhal->oem_id = RT_CID_819x_Acer; | ||
1875 | } else if ((rtlefuse->eeprom_svid == 0x10EC && | ||
1876 | rtlefuse->eeprom_smid == 0x0179) || | ||
1877 | (rtlefuse->eeprom_svid == 0x17AA && | ||
1878 | rtlefuse->eeprom_smid == 0x0179)) { | ||
1879 | rtlhal->oem_id = RT_CID_819x_Lenovo; | ||
1880 | } else if (rtlefuse->eeprom_svid == 0x103c && | ||
1881 | rtlefuse->eeprom_smid == 0x197d) { | ||
1882 | rtlhal->oem_id = RT_CID_819x_HP; | ||
1883 | } else { | ||
1884 | rtlhal->oem_id = RT_CID_DEFAULT; | ||
1885 | } | ||
1886 | } else { | ||
1887 | rtlhal->oem_id = RT_CID_DEFAULT; | ||
1888 | } | ||
1889 | break; | ||
1890 | case EEPROM_CID_TOSHIBA: | ||
1891 | rtlhal->oem_id = RT_CID_TOSHIBA; | ||
1892 | break; | ||
1893 | case EEPROM_CID_QMI: | ||
1894 | rtlhal->oem_id = RT_CID_819x_QMI; | ||
1895 | break; | ||
1896 | case EEPROM_CID_WHQL: | ||
1897 | default: | ||
1898 | rtlhal->oem_id = RT_CID_DEFAULT; | ||
1899 | break; | ||
1900 | } | ||
1901 | } | ||
1902 | } | ||
1903 | |||
1904 | static void _rtl88ee_hal_customized_behavior(struct ieee80211_hw *hw) | ||
1905 | { | ||
1906 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1907 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
1908 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1909 | |||
1910 | pcipriv->ledctl.led_opendrain = true; | ||
1911 | |||
1912 | switch (rtlhal->oem_id) { | ||
1913 | case RT_CID_819x_HP: | ||
1914 | pcipriv->ledctl.led_opendrain = true; | ||
1915 | break; | ||
1916 | case RT_CID_819x_Lenovo: | ||
1917 | case RT_CID_DEFAULT: | ||
1918 | case RT_CID_TOSHIBA: | ||
1919 | case RT_CID_CCX: | ||
1920 | case RT_CID_819x_Acer: | ||
1921 | case RT_CID_WHQL: | ||
1922 | default: | ||
1923 | break; | ||
1924 | } | ||
1925 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | ||
1926 | "RT Customized ID: 0x%02X\n", rtlhal->oem_id); | ||
1927 | } | ||
1928 | |||
1929 | void rtl88ee_read_eeprom_info(struct ieee80211_hw *hw) | ||
1930 | { | ||
1931 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1932 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1933 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1934 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1935 | u8 tmp_u1b; | ||
1936 | |||
1937 | rtlhal->version = _rtl88ee_read_chip_version(hw); | ||
1938 | if (get_rf_type(rtlphy) == RF_1T1R) { | ||
1939 | rtlpriv->dm.rfpath_rxenable[0] = true; | ||
1940 | } else { | ||
1941 | rtlpriv->dm.rfpath_rxenable[0] = true; | ||
1942 | rtlpriv->dm.rfpath_rxenable[1] = true; | ||
1943 | } | ||
1944 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n", | ||
1945 | rtlhal->version); | ||
1946 | tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); | ||
1947 | if (tmp_u1b & BIT(4)) { | ||
1948 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n"); | ||
1949 | rtlefuse->epromtype = EEPROM_93C46; | ||
1950 | } else { | ||
1951 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n"); | ||
1952 | rtlefuse->epromtype = EEPROM_BOOT_EFUSE; | ||
1953 | } | ||
1954 | if (tmp_u1b & BIT(5)) { | ||
1955 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); | ||
1956 | rtlefuse->autoload_failflag = false; | ||
1957 | _rtl88ee_read_adapter_info(hw); | ||
1958 | } else { | ||
1959 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Autoload ERR!!\n"); | ||
1960 | } | ||
1961 | _rtl88ee_hal_customized_behavior(hw); | ||
1962 | } | ||
1963 | |||
1964 | static void rtl88ee_update_hal_rate_table(struct ieee80211_hw *hw, | ||
1965 | struct ieee80211_sta *sta) | ||
1966 | { | ||
1967 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1968 | struct rtl_pci_priv *rppriv = rtl_pcipriv(hw); | ||
1969 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1970 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1971 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1972 | u32 ratr_value; | ||
1973 | u8 ratr_index = 0; | ||
1974 | u8 nmode = mac->ht_enable; | ||
1975 | u8 mimo_ps = IEEE80211_SMPS_OFF; | ||
1976 | u16 shortgi_rate; | ||
1977 | u32 tmp_ratr_value; | ||
1978 | u8 ctx40 = mac->bw_40; | ||
1979 | u16 cap = sta->ht_cap.cap; | ||
1980 | u8 short40 = (cap & IEEE80211_HT_CAP_SGI_40) ? 1 : 0; | ||
1981 | u8 short20 = (cap & IEEE80211_HT_CAP_SGI_20) ? 1 : 0; | ||
1982 | enum wireless_mode wirelessmode = mac->mode; | ||
1983 | |||
1984 | if (rtlhal->current_bandtype == BAND_ON_5G) | ||
1985 | ratr_value = sta->supp_rates[1] << 4; | ||
1986 | else | ||
1987 | ratr_value = sta->supp_rates[0]; | ||
1988 | if (mac->opmode == NL80211_IFTYPE_ADHOC) | ||
1989 | ratr_value = 0xfff; | ||
1990 | ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | | ||
1991 | sta->ht_cap.mcs.rx_mask[0] << 12); | ||
1992 | switch (wirelessmode) { | ||
1993 | case WIRELESS_MODE_B: | ||
1994 | if (ratr_value & 0x0000000c) | ||
1995 | ratr_value &= 0x0000000d; | ||
1996 | else | ||
1997 | ratr_value &= 0x0000000f; | ||
1998 | break; | ||
1999 | case WIRELESS_MODE_G: | ||
2000 | ratr_value &= 0x00000FF5; | ||
2001 | break; | ||
2002 | case WIRELESS_MODE_N_24G: | ||
2003 | case WIRELESS_MODE_N_5G: | ||
2004 | nmode = 1; | ||
2005 | if (mimo_ps == IEEE80211_SMPS_STATIC) { | ||
2006 | ratr_value &= 0x0007F005; | ||
2007 | } else { | ||
2008 | u32 ratr_mask; | ||
2009 | |||
2010 | if (get_rf_type(rtlphy) == RF_1T2R || | ||
2011 | get_rf_type(rtlphy) == RF_1T1R) | ||
2012 | ratr_mask = 0x000ff005; | ||
2013 | else | ||
2014 | ratr_mask = 0x0f0ff005; | ||
2015 | |||
2016 | ratr_value &= ratr_mask; | ||
2017 | } | ||
2018 | break; | ||
2019 | default: | ||
2020 | if (rtlphy->rf_type == RF_1T2R) | ||
2021 | ratr_value &= 0x000ff0ff; | ||
2022 | else | ||
2023 | ratr_value &= 0x0f0ff0ff; | ||
2024 | |||
2025 | break; | ||
2026 | } | ||
2027 | |||
2028 | if ((rppriv->bt_coexist.bt_coexistence) && | ||
2029 | (rppriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) && | ||
2030 | (rppriv->bt_coexist.bt_cur_state) && | ||
2031 | (rppriv->bt_coexist.bt_ant_isolation) && | ||
2032 | ((rppriv->bt_coexist.bt_service == BT_SCO) || | ||
2033 | (rppriv->bt_coexist.bt_service == BT_BUSY))) | ||
2034 | ratr_value &= 0x0fffcfc0; | ||
2035 | else | ||
2036 | ratr_value &= 0x0FFFFFFF; | ||
2037 | |||
2038 | if (nmode && ((ctx40 && short40) || | ||
2039 | (!ctx40 && short20))) { | ||
2040 | ratr_value |= 0x10000000; | ||
2041 | tmp_ratr_value = (ratr_value >> 12); | ||
2042 | |||
2043 | for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { | ||
2044 | if ((1 << shortgi_rate) & tmp_ratr_value) | ||
2045 | break; | ||
2046 | } | ||
2047 | |||
2048 | shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | | ||
2049 | (shortgi_rate << 4) | (shortgi_rate); | ||
2050 | } | ||
2051 | |||
2052 | rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value); | ||
2053 | |||
2054 | RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, | ||
2055 | "%x\n", rtl_read_dword(rtlpriv, REG_ARFR0)); | ||
2056 | } | ||
2057 | |||
2058 | static void rtl88ee_update_hal_rate_mask(struct ieee80211_hw *hw, | ||
2059 | struct ieee80211_sta *sta, u8 rssi) | ||
2060 | { | ||
2061 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2062 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
2063 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
2064 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
2065 | struct rtl_sta_info *sta_entry = NULL; | ||
2066 | u32 ratr_bitmap; | ||
2067 | u8 ratr_index; | ||
2068 | u16 cap = sta->ht_cap.cap; | ||
2069 | u8 ctx40 = (cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1 : 0; | ||
2070 | u8 short40 = (cap & IEEE80211_HT_CAP_SGI_40) ? 1 : 0; | ||
2071 | u8 short20 = (cap & IEEE80211_HT_CAP_SGI_20) ? 1 : 0; | ||
2072 | enum wireless_mode wirelessmode = 0; | ||
2073 | bool shortgi = false; | ||
2074 | u8 rate_mask[5]; | ||
2075 | u8 macid = 0; | ||
2076 | u8 mimo_ps = IEEE80211_SMPS_OFF; | ||
2077 | |||
2078 | sta_entry = (struct rtl_sta_info *)sta->drv_priv; | ||
2079 | wirelessmode = sta_entry->wireless_mode; | ||
2080 | if (mac->opmode == NL80211_IFTYPE_STATION || | ||
2081 | mac->opmode == NL80211_IFTYPE_MESH_POINT) | ||
2082 | ctx40 = mac->bw_40; | ||
2083 | else if (mac->opmode == NL80211_IFTYPE_AP || | ||
2084 | mac->opmode == NL80211_IFTYPE_ADHOC) | ||
2085 | macid = sta->aid + 1; | ||
2086 | |||
2087 | if (rtlhal->current_bandtype == BAND_ON_5G) | ||
2088 | ratr_bitmap = sta->supp_rates[1] << 4; | ||
2089 | else | ||
2090 | ratr_bitmap = sta->supp_rates[0]; | ||
2091 | if (mac->opmode == NL80211_IFTYPE_ADHOC) | ||
2092 | ratr_bitmap = 0xfff; | ||
2093 | ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | | ||
2094 | sta->ht_cap.mcs.rx_mask[0] << 12); | ||
2095 | switch (wirelessmode) { | ||
2096 | case WIRELESS_MODE_B: | ||
2097 | ratr_index = RATR_INX_WIRELESS_B; | ||
2098 | if (ratr_bitmap & 0x0000000c) | ||
2099 | ratr_bitmap &= 0x0000000d; | ||
2100 | else | ||
2101 | ratr_bitmap &= 0x0000000f; | ||
2102 | break; | ||
2103 | case WIRELESS_MODE_G: | ||
2104 | ratr_index = RATR_INX_WIRELESS_GB; | ||
2105 | |||
2106 | if (rssi == 1) | ||
2107 | ratr_bitmap &= 0x00000f00; | ||
2108 | else if (rssi == 2) | ||
2109 | ratr_bitmap &= 0x00000ff0; | ||
2110 | else | ||
2111 | ratr_bitmap &= 0x00000ff5; | ||
2112 | break; | ||
2113 | case WIRELESS_MODE_A: | ||
2114 | ratr_index = RATR_INX_WIRELESS_A; | ||
2115 | ratr_bitmap &= 0x00000ff0; | ||
2116 | break; | ||
2117 | case WIRELESS_MODE_N_24G: | ||
2118 | case WIRELESS_MODE_N_5G: | ||
2119 | ratr_index = RATR_INX_WIRELESS_NGB; | ||
2120 | |||
2121 | if (mimo_ps == IEEE80211_SMPS_STATIC) { | ||
2122 | if (rssi == 1) | ||
2123 | ratr_bitmap &= 0x00070000; | ||
2124 | else if (rssi == 2) | ||
2125 | ratr_bitmap &= 0x0007f000; | ||
2126 | else | ||
2127 | ratr_bitmap &= 0x0007f005; | ||
2128 | } else { | ||
2129 | if (rtlphy->rf_type == RF_1T2R || | ||
2130 | rtlphy->rf_type == RF_1T1R) { | ||
2131 | if (ctx40) { | ||
2132 | if (rssi == 1) | ||
2133 | ratr_bitmap &= 0x000f0000; | ||
2134 | else if (rssi == 2) | ||
2135 | ratr_bitmap &= 0x000ff000; | ||
2136 | else | ||
2137 | ratr_bitmap &= 0x000ff015; | ||
2138 | } else { | ||
2139 | if (rssi == 1) | ||
2140 | ratr_bitmap &= 0x000f0000; | ||
2141 | else if (rssi == 2) | ||
2142 | ratr_bitmap &= 0x000ff000; | ||
2143 | else | ||
2144 | ratr_bitmap &= 0x000ff005; | ||
2145 | } | ||
2146 | } else { | ||
2147 | if (ctx40) { | ||
2148 | if (rssi == 1) | ||
2149 | ratr_bitmap &= 0x0f8f0000; | ||
2150 | else if (rssi == 2) | ||
2151 | ratr_bitmap &= 0x0f8ff000; | ||
2152 | else | ||
2153 | ratr_bitmap &= 0x0f8ff015; | ||
2154 | } else { | ||
2155 | if (rssi == 1) | ||
2156 | ratr_bitmap &= 0x0f8f0000; | ||
2157 | else if (rssi == 2) | ||
2158 | ratr_bitmap &= 0x0f8ff000; | ||
2159 | else | ||
2160 | ratr_bitmap &= 0x0f8ff005; | ||
2161 | } | ||
2162 | } | ||
2163 | } | ||
2164 | |||
2165 | if ((ctx40 && short40) || (!ctx40 && short20)) { | ||
2166 | if (macid == 0) | ||
2167 | shortgi = true; | ||
2168 | else if (macid == 1) | ||
2169 | shortgi = false; | ||
2170 | } | ||
2171 | break; | ||
2172 | default: | ||
2173 | ratr_index = RATR_INX_WIRELESS_NGB; | ||
2174 | |||
2175 | if (rtlphy->rf_type == RF_1T2R) | ||
2176 | ratr_bitmap &= 0x000ff0ff; | ||
2177 | else | ||
2178 | ratr_bitmap &= 0x0f0ff0ff; | ||
2179 | break; | ||
2180 | } | ||
2181 | sta_entry->ratr_index = ratr_index; | ||
2182 | |||
2183 | RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, | ||
2184 | "ratr_bitmap :%x\n", ratr_bitmap); | ||
2185 | *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) | | ||
2186 | (ratr_index << 28); | ||
2187 | rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80; | ||
2188 | RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, | ||
2189 | "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n", | ||
2190 | ratr_index, ratr_bitmap, rate_mask[0], rate_mask[1], | ||
2191 | rate_mask[2], rate_mask[3], rate_mask[4]); | ||
2192 | rtl88e_fill_h2c_cmd(hw, H2C_88E_RA_MASK, 5, rate_mask); | ||
2193 | _rtl88ee_set_bcn_ctrl_reg(hw, BIT(3), 0); | ||
2194 | } | ||
2195 | |||
2196 | void rtl88ee_update_hal_rate_tbl(struct ieee80211_hw *hw, | ||
2197 | struct ieee80211_sta *sta, u8 rssi) | ||
2198 | { | ||
2199 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2200 | |||
2201 | if (rtlpriv->dm.useramask) | ||
2202 | rtl88ee_update_hal_rate_mask(hw, sta, rssi); | ||
2203 | else | ||
2204 | rtl88ee_update_hal_rate_table(hw, sta); | ||
2205 | } | ||
2206 | |||
2207 | void rtl88ee_update_channel_access_setting(struct ieee80211_hw *hw) | ||
2208 | { | ||
2209 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2210 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
2211 | u16 sifs_timer; | ||
2212 | |||
2213 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, | ||
2214 | (u8 *)&mac->slot_time); | ||
2215 | if (!mac->ht_enable) | ||
2216 | sifs_timer = 0x0a0a; | ||
2217 | else | ||
2218 | sifs_timer = 0x0e0e; | ||
2219 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); | ||
2220 | } | ||
2221 | |||
2222 | bool rtl88ee_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) | ||
2223 | { | ||
2224 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2225 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
2226 | enum rf_pwrstate state_toset; | ||
2227 | u32 u4tmp; | ||
2228 | bool actuallyset = false; | ||
2229 | |||
2230 | if (rtlpriv->rtlhal.being_init_adapter) | ||
2231 | return false; | ||
2232 | |||
2233 | if (ppsc->swrf_processing) | ||
2234 | return false; | ||
2235 | |||
2236 | spin_lock(&rtlpriv->locks.rf_ps_lock); | ||
2237 | if (ppsc->rfchange_inprogress) { | ||
2238 | spin_unlock(&rtlpriv->locks.rf_ps_lock); | ||
2239 | return false; | ||
2240 | } else { | ||
2241 | ppsc->rfchange_inprogress = true; | ||
2242 | spin_unlock(&rtlpriv->locks.rf_ps_lock); | ||
2243 | } | ||
2244 | |||
2245 | u4tmp = rtl_read_dword(rtlpriv, REG_GPIO_OUTPUT); | ||
2246 | state_toset = (u4tmp & BIT(31)) ? ERFON : ERFOFF; | ||
2247 | |||
2248 | |||
2249 | if ((ppsc->hwradiooff == true) && (state_toset == ERFON)) { | ||
2250 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | ||
2251 | "GPIOChangeRF - HW Radio ON, RF ON\n"); | ||
2252 | |||
2253 | state_toset = ERFON; | ||
2254 | ppsc->hwradiooff = false; | ||
2255 | actuallyset = true; | ||
2256 | } else if ((ppsc->hwradiooff == false) && (state_toset == ERFOFF)) { | ||
2257 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | ||
2258 | "GPIOChangeRF - HW Radio OFF, RF OFF\n"); | ||
2259 | |||
2260 | state_toset = ERFOFF; | ||
2261 | ppsc->hwradiooff = true; | ||
2262 | actuallyset = true; | ||
2263 | } | ||
2264 | |||
2265 | if (actuallyset) { | ||
2266 | spin_lock(&rtlpriv->locks.rf_ps_lock); | ||
2267 | ppsc->rfchange_inprogress = false; | ||
2268 | spin_unlock(&rtlpriv->locks.rf_ps_lock); | ||
2269 | } else { | ||
2270 | if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) | ||
2271 | RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); | ||
2272 | |||
2273 | spin_lock(&rtlpriv->locks.rf_ps_lock); | ||
2274 | ppsc->rfchange_inprogress = false; | ||
2275 | spin_unlock(&rtlpriv->locks.rf_ps_lock); | ||
2276 | } | ||
2277 | |||
2278 | *valid = 1; | ||
2279 | return !ppsc->hwradiooff; | ||
2280 | } | ||
2281 | |||
2282 | static void add_one_key(struct ieee80211_hw *hw, u8 *macaddr, | ||
2283 | struct rtl_mac *mac, u32 key, u32 id, | ||
2284 | u8 enc_algo, bool is_pairwise) | ||
2285 | { | ||
2286 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2287 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
2288 | |||
2289 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "add one entry\n"); | ||
2290 | if (is_pairwise) { | ||
2291 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "set Pairwise key\n"); | ||
2292 | |||
2293 | rtl_cam_add_one_entry(hw, macaddr, key, id, enc_algo, | ||
2294 | CAM_CONFIG_NO_USEDK, | ||
2295 | rtlpriv->sec.key_buf[key]); | ||
2296 | } else { | ||
2297 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "set group key\n"); | ||
2298 | |||
2299 | if (mac->opmode == NL80211_IFTYPE_ADHOC) { | ||
2300 | rtl_cam_add_one_entry(hw, rtlefuse->dev_addr, | ||
2301 | PAIRWISE_KEYIDX, | ||
2302 | CAM_PAIRWISE_KEY_POSITION, | ||
2303 | enc_algo, | ||
2304 | CAM_CONFIG_NO_USEDK, | ||
2305 | rtlpriv->sec.key_buf[id]); | ||
2306 | } | ||
2307 | |||
2308 | rtl_cam_add_one_entry(hw, macaddr, key, id, enc_algo, | ||
2309 | CAM_CONFIG_NO_USEDK, | ||
2310 | rtlpriv->sec.key_buf[id]); | ||
2311 | } | ||
2312 | } | ||
2313 | |||
2314 | void rtl88ee_set_key(struct ieee80211_hw *hw, u32 key, | ||
2315 | u8 *mac_ad, bool is_group, u8 enc_algo, | ||
2316 | bool is_wepkey, bool clear_all) | ||
2317 | { | ||
2318 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2319 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
2320 | u8 *macaddr = mac_ad; | ||
2321 | u32 id = 0; | ||
2322 | bool is_pairwise = false; | ||
2323 | |||
2324 | static u8 cam_const_addr[4][6] = { | ||
2325 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, | ||
2326 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, | ||
2327 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, | ||
2328 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} | ||
2329 | }; | ||
2330 | static u8 cam_const_broad[] = { | ||
2331 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff | ||
2332 | }; | ||
2333 | |||
2334 | if (clear_all) { | ||
2335 | u8 idx = 0; | ||
2336 | u8 cam_offset = 0; | ||
2337 | u8 clear_number = 5; | ||
2338 | |||
2339 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n"); | ||
2340 | |||
2341 | for (idx = 0; idx < clear_number; idx++) { | ||
2342 | rtl_cam_mark_invalid(hw, cam_offset + idx); | ||
2343 | rtl_cam_empty_entry(hw, cam_offset + idx); | ||
2344 | |||
2345 | if (idx < 5) { | ||
2346 | memset(rtlpriv->sec.key_buf[idx], 0, | ||
2347 | MAX_KEY_LEN); | ||
2348 | rtlpriv->sec.key_len[idx] = 0; | ||
2349 | } | ||
2350 | } | ||
2351 | |||
2352 | } else { | ||
2353 | switch (enc_algo) { | ||
2354 | case WEP40_ENCRYPTION: | ||
2355 | enc_algo = CAM_WEP40; | ||
2356 | break; | ||
2357 | case WEP104_ENCRYPTION: | ||
2358 | enc_algo = CAM_WEP104; | ||
2359 | break; | ||
2360 | case TKIP_ENCRYPTION: | ||
2361 | enc_algo = CAM_TKIP; | ||
2362 | break; | ||
2363 | case AESCCMP_ENCRYPTION: | ||
2364 | enc_algo = CAM_AES; | ||
2365 | break; | ||
2366 | default: | ||
2367 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
2368 | "switch case not processed\n"); | ||
2369 | enc_algo = CAM_TKIP; | ||
2370 | break; | ||
2371 | } | ||
2372 | |||
2373 | if (is_wepkey || rtlpriv->sec.use_defaultkey) { | ||
2374 | macaddr = cam_const_addr[key]; | ||
2375 | id = key; | ||
2376 | } else { | ||
2377 | if (is_group) { | ||
2378 | macaddr = cam_const_broad; | ||
2379 | id = key; | ||
2380 | } else { | ||
2381 | if (mac->opmode == NL80211_IFTYPE_AP || | ||
2382 | mac->opmode == NL80211_IFTYPE_MESH_POINT) { | ||
2383 | id = rtl_cam_get_free_entry(hw, mac_ad); | ||
2384 | if (id >= TOTAL_CAM_ENTRY) { | ||
2385 | RT_TRACE(rtlpriv, COMP_SEC, | ||
2386 | DBG_EMERG, | ||
2387 | "Can not find free hw security cam entry\n"); | ||
2388 | return; | ||
2389 | } | ||
2390 | } else { | ||
2391 | id = CAM_PAIRWISE_KEY_POSITION; | ||
2392 | } | ||
2393 | |||
2394 | key = PAIRWISE_KEYIDX; | ||
2395 | is_pairwise = true; | ||
2396 | } | ||
2397 | } | ||
2398 | |||
2399 | if (rtlpriv->sec.key_len[key] == 0) { | ||
2400 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | ||
2401 | "delete one entry, id is %d\n", id); | ||
2402 | if (mac->opmode == NL80211_IFTYPE_AP || | ||
2403 | mac->opmode == NL80211_IFTYPE_MESH_POINT) | ||
2404 | rtl_cam_del_entry(hw, mac_ad); | ||
2405 | rtl_cam_delete_one_entry(hw, mac_ad, id); | ||
2406 | } else { | ||
2407 | add_one_key(hw, macaddr, mac, key, id, enc_algo, | ||
2408 | is_pairwise); | ||
2409 | } | ||
2410 | } | ||
2411 | } | ||
2412 | |||
2413 | static void rtl8188ee_bt_var_init(struct ieee80211_hw *hw) | ||
2414 | { | ||
2415 | struct rtl_pci_priv *rppriv = rtl_pcipriv(hw); | ||
2416 | struct bt_coexist_info coexist = rppriv->bt_coexist; | ||
2417 | |||
2418 | coexist.bt_coexistence = rppriv->bt_coexist.eeprom_bt_coexist; | ||
2419 | coexist.bt_ant_num = coexist.eeprom_bt_ant_num; | ||
2420 | coexist.bt_coexist_type = coexist.eeprom_bt_type; | ||
2421 | |||
2422 | if (coexist.reg_bt_iso == 2) | ||
2423 | coexist.bt_ant_isolation = coexist.eeprom_bt_ant_isol; | ||
2424 | else | ||
2425 | coexist.bt_ant_isolation = coexist.reg_bt_iso; | ||
2426 | |||
2427 | coexist.bt_radio_shared_type = coexist.eeprom_bt_radio_shared; | ||
2428 | |||
2429 | if (coexist.bt_coexistence) { | ||
2430 | if (coexist.reg_bt_sco == 1) | ||
2431 | coexist.bt_service = BT_OTHER_ACTION; | ||
2432 | else if (coexist.reg_bt_sco == 2) | ||
2433 | coexist.bt_service = BT_SCO; | ||
2434 | else if (coexist.reg_bt_sco == 4) | ||
2435 | coexist.bt_service = BT_BUSY; | ||
2436 | else if (coexist.reg_bt_sco == 5) | ||
2437 | coexist.bt_service = BT_OTHERBUSY; | ||
2438 | else | ||
2439 | coexist.bt_service = BT_IDLE; | ||
2440 | |||
2441 | coexist.bt_edca_ul = 0; | ||
2442 | coexist.bt_edca_dl = 0; | ||
2443 | coexist.bt_rssi_state = 0xff; | ||
2444 | } | ||
2445 | } | ||
2446 | |||
2447 | void rtl8188ee_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, | ||
2448 | bool auto_load_fail, u8 *hwinfo) | ||
2449 | { | ||
2450 | rtl8188ee_bt_var_init(hw); | ||
2451 | } | ||
2452 | |||
2453 | void rtl8188ee_bt_reg_init(struct ieee80211_hw *hw) | ||
2454 | { | ||
2455 | struct rtl_pci_priv *rppriv = rtl_pcipriv(hw); | ||
2456 | |||
2457 | /* 0:Low, 1:High, 2:From Efuse. */ | ||
2458 | rppriv->bt_coexist.reg_bt_iso = 2; | ||
2459 | /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */ | ||
2460 | rppriv->bt_coexist.reg_bt_sco = 3; | ||
2461 | /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ | ||
2462 | rppriv->bt_coexist.reg_bt_sco = 0; | ||
2463 | } | ||
2464 | |||
2465 | void rtl8188ee_bt_hw_init(struct ieee80211_hw *hw) | ||
2466 | { | ||
2467 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2468 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
2469 | struct rtl_pci_priv *rppriv = rtl_pcipriv(hw); | ||
2470 | struct bt_coexist_info coexist = rppriv->bt_coexist; | ||
2471 | u8 u1_tmp; | ||
2472 | |||
2473 | if (coexist.bt_coexistence && | ||
2474 | ((coexist.bt_coexist_type == BT_CSR_BC4) || | ||
2475 | coexist.bt_coexist_type == BT_CSR_BC8)) { | ||
2476 | if (coexist.bt_ant_isolation) | ||
2477 | rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); | ||
2478 | |||
2479 | u1_tmp = rtl_read_byte(rtlpriv, 0x4fd) & | ||
2480 | BIT_OFFSET_LEN_MASK_32(0, 1); | ||
2481 | u1_tmp = u1_tmp | ((coexist.bt_ant_isolation == 1) ? | ||
2482 | 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) | | ||
2483 | ((coexist.bt_service == BT_SCO) ? | ||
2484 | 0 : BIT_OFFSET_LEN_MASK_32(2, 1)); | ||
2485 | rtl_write_byte(rtlpriv, 0x4fd, u1_tmp); | ||
2486 | |||
2487 | rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+4, 0xaaaa9aaa); | ||
2488 | rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+8, 0xffbd0040); | ||
2489 | rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+0xc, 0x40000010); | ||
2490 | |||
2491 | /* Config to 1T1R. */ | ||
2492 | if (rtlphy->rf_type == RF_1T1R) { | ||
2493 | u1_tmp = rtl_read_byte(rtlpriv, ROFDM0_TRXPATHENABLE); | ||
2494 | u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1)); | ||
2495 | rtl_write_byte(rtlpriv, ROFDM0_TRXPATHENABLE, u1_tmp); | ||
2496 | |||
2497 | u1_tmp = rtl_read_byte(rtlpriv, ROFDM1_TRXPATHENABLE); | ||
2498 | u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1)); | ||
2499 | rtl_write_byte(rtlpriv, ROFDM1_TRXPATHENABLE, u1_tmp); | ||
2500 | } | ||
2501 | } | ||
2502 | } | ||
2503 | |||
2504 | void rtl88ee_suspend(struct ieee80211_hw *hw) | ||
2505 | { | ||
2506 | } | ||
2507 | |||
2508 | void rtl88ee_resume(struct ieee80211_hw *hw) | ||
2509 | { | ||
2510 | } | ||
2511 | |||
2512 | /* Turn on AAP (RCR:bit 0) for promicuous mode. */ | ||
2513 | void rtl88ee_allow_all_destaddr(struct ieee80211_hw *hw, | ||
2514 | bool allow_all_da, bool write_into_reg) | ||
2515 | { | ||
2516 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2517 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
2518 | |||
2519 | if (allow_all_da) /* Set BIT0 */ | ||
2520 | rtlpci->receive_config |= RCR_AAP; | ||
2521 | else /* Clear BIT0 */ | ||
2522 | rtlpci->receive_config &= ~RCR_AAP; | ||
2523 | |||
2524 | if (write_into_reg) | ||
2525 | rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); | ||
2526 | |||
2527 | RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD, | ||
2528 | "receive_config = 0x%08X, write_into_reg =%d\n", | ||
2529 | rtlpci->receive_config, write_into_reg); | ||
2530 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h new file mode 100644 index 000000000000..b4460a41bd01 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h | |||
@@ -0,0 +1,68 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #ifndef __RTL92CE_HW_H__ | ||
31 | #define __RTL92CE_HW_H__ | ||
32 | |||
33 | void rtl88ee_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); | ||
34 | void rtl88ee_read_eeprom_info(struct ieee80211_hw *hw); | ||
35 | void rtl88ee_interrupt_recognized(struct ieee80211_hw *hw, | ||
36 | u32 *p_inta, u32 *p_intb); | ||
37 | int rtl88ee_hw_init(struct ieee80211_hw *hw); | ||
38 | void rtl88ee_card_disable(struct ieee80211_hw *hw); | ||
39 | void rtl88ee_enable_interrupt(struct ieee80211_hw *hw); | ||
40 | void rtl88ee_disable_interrupt(struct ieee80211_hw *hw); | ||
41 | int rtl88ee_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type); | ||
42 | void rtl88ee_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); | ||
43 | void rtl88ee_set_qos(struct ieee80211_hw *hw, int aci); | ||
44 | void rtl88ee_set_beacon_related_registers(struct ieee80211_hw *hw); | ||
45 | void rtl88ee_set_beacon_interval(struct ieee80211_hw *hw); | ||
46 | void rtl88ee_update_interrupt_mask(struct ieee80211_hw *hw, | ||
47 | u32 add_msr, u32 rm_msr); | ||
48 | void rtl88ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); | ||
49 | void rtl88ee_update_hal_rate_tbl(struct ieee80211_hw *hw, | ||
50 | struct ieee80211_sta *sta, u8 rssi_level); | ||
51 | void rtl88ee_update_channel_access_setting(struct ieee80211_hw *hw); | ||
52 | bool rtl88ee_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); | ||
53 | void rtl88ee_enable_hw_security_config(struct ieee80211_hw *hw); | ||
54 | void rtl88ee_set_key(struct ieee80211_hw *hw, u32 key_index, | ||
55 | u8 *p_macaddr, bool is_group, u8 enc_algo, | ||
56 | bool is_wepkey, bool clear_all); | ||
57 | |||
58 | void rtl8188ee_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, | ||
59 | bool autoload_fail, u8 *hwinfo); | ||
60 | void rtl8188ee_bt_reg_init(struct ieee80211_hw *hw); | ||
61 | void rtl8188ee_bt_hw_init(struct ieee80211_hw *hw); | ||
62 | void rtl88ee_suspend(struct ieee80211_hw *hw); | ||
63 | void rtl88ee_resume(struct ieee80211_hw *hw); | ||
64 | void rtl88ee_allow_all_destaddr(struct ieee80211_hw *hw, | ||
65 | bool allow_all_da, bool write_into_reg); | ||
66 | void rtl88ee_fw_clk_off_timer_callback(unsigned long data); | ||
67 | |||
68 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/led.c b/drivers/net/wireless/rtlwifi/rtl8188ee/led.c new file mode 100644 index 000000000000..c81a9cb6894c --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/led.c | |||
@@ -0,0 +1,157 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "../wifi.h" | ||
31 | #include "../pci.h" | ||
32 | #include "reg.h" | ||
33 | #include "led.h" | ||
34 | |||
35 | static void rtl88ee_init_led(struct ieee80211_hw *hw, | ||
36 | struct rtl_led *pled, enum rtl_led_pin ledpin) | ||
37 | { | ||
38 | pled->hw = hw; | ||
39 | pled->ledpin = ledpin; | ||
40 | pled->ledon = false; | ||
41 | } | ||
42 | |||
43 | void rtl88ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) | ||
44 | { | ||
45 | u8 ledcfg; | ||
46 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
47 | |||
48 | RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, | ||
49 | "LedAddr:%X ledpin =%d\n", REG_LEDCFG2, pled->ledpin); | ||
50 | |||
51 | switch (pled->ledpin) { | ||
52 | case LED_PIN_GPIO0: | ||
53 | break; | ||
54 | case LED_PIN_LED0: | ||
55 | ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); | ||
56 | rtl_write_byte(rtlpriv, REG_LEDCFG2, | ||
57 | (ledcfg & 0xf0) | BIT(5) | BIT(6)); | ||
58 | break; | ||
59 | case LED_PIN_LED1: | ||
60 | ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1); | ||
61 | rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg & 0x10); | ||
62 | break; | ||
63 | default: | ||
64 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
65 | "switch case not processed\n"); | ||
66 | break; | ||
67 | } | ||
68 | pled->ledon = true; | ||
69 | } | ||
70 | |||
71 | void rtl88ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) | ||
72 | { | ||
73 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
74 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
75 | u8 ledcfg; | ||
76 | u8 val; | ||
77 | |||
78 | RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, | ||
79 | "LedAddr:%X ledpin =%d\n", REG_LEDCFG2, pled->ledpin); | ||
80 | |||
81 | switch (pled->ledpin) { | ||
82 | case LED_PIN_GPIO0: | ||
83 | break; | ||
84 | case LED_PIN_LED0: | ||
85 | ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); | ||
86 | ledcfg &= 0xf0; | ||
87 | val = ledcfg | BIT(3) | BIT(5) | BIT(6); | ||
88 | if (pcipriv->ledctl.led_opendrain == true) { | ||
89 | rtl_write_byte(rtlpriv, REG_LEDCFG2, val); | ||
90 | ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG); | ||
91 | val = ledcfg & 0xFE; | ||
92 | rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, val); | ||
93 | } else { | ||
94 | rtl_write_byte(rtlpriv, REG_LEDCFG2, val); | ||
95 | } | ||
96 | break; | ||
97 | case LED_PIN_LED1: | ||
98 | ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1); | ||
99 | ledcfg &= 0x10; | ||
100 | rtl_write_byte(rtlpriv, REG_LEDCFG1, (ledcfg | BIT(3))); | ||
101 | break; | ||
102 | default: | ||
103 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
104 | "switch case not processed\n"); | ||
105 | break; | ||
106 | } | ||
107 | pled->ledon = false; | ||
108 | } | ||
109 | |||
110 | void rtl88ee_init_sw_leds(struct ieee80211_hw *hw) | ||
111 | { | ||
112 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
113 | |||
114 | rtl88ee_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0); | ||
115 | rtl88ee_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1); | ||
116 | } | ||
117 | |||
118 | static void rtl88ee_sw_led_control(struct ieee80211_hw *hw, | ||
119 | enum led_ctl_mode ledaction) | ||
120 | { | ||
121 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
122 | struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); | ||
123 | |||
124 | switch (ledaction) { | ||
125 | case LED_CTL_POWER_ON: | ||
126 | case LED_CTL_LINK: | ||
127 | case LED_CTL_NO_LINK: | ||
128 | rtl88ee_sw_led_on(hw, pLed0); | ||
129 | break; | ||
130 | case LED_CTL_POWER_OFF: | ||
131 | rtl88ee_sw_led_off(hw, pLed0); | ||
132 | break; | ||
133 | default: | ||
134 | break; | ||
135 | } | ||
136 | } | ||
137 | |||
138 | void rtl88ee_led_control(struct ieee80211_hw *hw, | ||
139 | enum led_ctl_mode ledaction) | ||
140 | { | ||
141 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
142 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
143 | |||
144 | if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && | ||
145 | (ledaction == LED_CTL_TX || | ||
146 | ledaction == LED_CTL_RX || | ||
147 | ledaction == LED_CTL_SITE_SURVEY || | ||
148 | ledaction == LED_CTL_LINK || | ||
149 | ledaction == LED_CTL_NO_LINK || | ||
150 | ledaction == LED_CTL_START_TO_LINK || | ||
151 | ledaction == LED_CTL_POWER_ON)) { | ||
152 | return; | ||
153 | } | ||
154 | RT_TRACE(rtlpriv, COMP_LED, DBG_TRACE, "ledaction %d,\n", | ||
155 | ledaction); | ||
156 | rtl88ee_sw_led_control(hw, ledaction); | ||
157 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/led.h b/drivers/net/wireless/rtlwifi/rtl8188ee/led.h new file mode 100644 index 000000000000..4073f6f847b2 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/led.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #ifndef __RTL92CE_LED_H__ | ||
31 | #define __RTL92CE_LED_H__ | ||
32 | |||
33 | void rtl88ee_init_sw_leds(struct ieee80211_hw *hw); | ||
34 | void rtl88ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); | ||
35 | void rtl88ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); | ||
36 | void rtl88ee_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); | ||
37 | |||
38 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.c b/drivers/net/wireless/rtlwifi/rtl8188ee/phy.c new file mode 100644 index 000000000000..e655c0473225 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/phy.c | |||
@@ -0,0 +1,2202 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "../wifi.h" | ||
31 | #include "../pci.h" | ||
32 | #include "../ps.h" | ||
33 | #include "reg.h" | ||
34 | #include "def.h" | ||
35 | #include "phy.h" | ||
36 | #include "rf.h" | ||
37 | #include "dm.h" | ||
38 | #include "table.h" | ||
39 | |||
40 | static void set_baseband_phy_config(struct ieee80211_hw *hw); | ||
41 | static void set_baseband_agc_config(struct ieee80211_hw *hw); | ||
42 | static void store_pwrindex_offset(struct ieee80211_hw *hw, | ||
43 | u32 regaddr, u32 bitmask, | ||
44 | u32 data); | ||
45 | static bool check_cond(struct ieee80211_hw *hw, const u32 condition); | ||
46 | |||
47 | static u32 rf_serial_read(struct ieee80211_hw *hw, | ||
48 | enum radio_path rfpath, u32 offset) | ||
49 | { | ||
50 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
51 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
52 | struct bb_reg_def *phreg = &rtlphy->phyreg_def[rfpath]; | ||
53 | u32 newoffset; | ||
54 | u32 tmplong, tmplong2; | ||
55 | u8 rfpi_enable = 0; | ||
56 | u32 ret; | ||
57 | int jj = RF90_PATH_A; | ||
58 | int kk = RF90_PATH_B; | ||
59 | |||
60 | offset &= 0xff; | ||
61 | newoffset = offset; | ||
62 | if (RT_CANNOT_IO(hw)) { | ||
63 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "return all one\n"); | ||
64 | return 0xFFFFFFFF; | ||
65 | } | ||
66 | tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD); | ||
67 | if (rfpath == jj) | ||
68 | tmplong2 = tmplong; | ||
69 | else | ||
70 | tmplong2 = rtl_get_bbreg(hw, phreg->rfhssi_para2, MASKDWORD); | ||
71 | tmplong2 = (tmplong2 & (~BLSSIREADADDRESS)) | | ||
72 | (newoffset << 23) | BLSSIREADEDGE; | ||
73 | rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, | ||
74 | tmplong & (~BLSSIREADEDGE)); | ||
75 | mdelay(1); | ||
76 | rtl_set_bbreg(hw, phreg->rfhssi_para2, MASKDWORD, tmplong2); | ||
77 | mdelay(2); | ||
78 | if (rfpath == jj) | ||
79 | rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1, | ||
80 | BIT(8)); | ||
81 | else if (rfpath == kk) | ||
82 | rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1, | ||
83 | BIT(8)); | ||
84 | if (rfpi_enable) | ||
85 | ret = rtl_get_bbreg(hw, phreg->rf_rbpi, BLSSIREADBACKDATA); | ||
86 | else | ||
87 | ret = rtl_get_bbreg(hw, phreg->rf_rb, BLSSIREADBACKDATA); | ||
88 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFR-%d Addr[0x%x]= 0x%x\n", | ||
89 | rfpath, phreg->rf_rb, ret); | ||
90 | return ret; | ||
91 | } | ||
92 | |||
93 | static void rf_serial_write(struct ieee80211_hw *hw, | ||
94 | enum radio_path rfpath, u32 offset, | ||
95 | u32 data) | ||
96 | { | ||
97 | u32 data_and_addr; | ||
98 | u32 newoffset; | ||
99 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
100 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
101 | struct bb_reg_def *phreg = &rtlphy->phyreg_def[rfpath]; | ||
102 | |||
103 | if (RT_CANNOT_IO(hw)) { | ||
104 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "stop\n"); | ||
105 | return; | ||
106 | } | ||
107 | offset &= 0xff; | ||
108 | newoffset = offset; | ||
109 | data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff; | ||
110 | rtl_set_bbreg(hw, phreg->rf3wire_offset, MASKDWORD, data_and_addr); | ||
111 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFW-%d Addr[0x%x]= 0x%x\n", | ||
112 | rfpath, phreg->rf3wire_offset, data_and_addr); | ||
113 | } | ||
114 | |||
115 | static u32 cal_bit_shift(u32 bitmask) | ||
116 | { | ||
117 | u32 i; | ||
118 | |||
119 | for (i = 0; i <= 31; i++) { | ||
120 | if (((bitmask >> i) & 0x1) == 1) | ||
121 | break; | ||
122 | } | ||
123 | return i; | ||
124 | } | ||
125 | |||
126 | static bool config_bb_with_header(struct ieee80211_hw *hw, | ||
127 | u8 configtype) | ||
128 | { | ||
129 | if (configtype == BASEBAND_CONFIG_PHY_REG) | ||
130 | set_baseband_phy_config(hw); | ||
131 | else if (configtype == BASEBAND_CONFIG_AGC_TAB) | ||
132 | set_baseband_agc_config(hw); | ||
133 | return true; | ||
134 | } | ||
135 | |||
136 | static bool config_bb_with_pgheader(struct ieee80211_hw *hw, | ||
137 | u8 configtype) | ||
138 | { | ||
139 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
140 | int i; | ||
141 | u32 *table_pg; | ||
142 | u16 tbl_page_len; | ||
143 | u32 v1 = 0, v2 = 0; | ||
144 | |||
145 | tbl_page_len = RTL8188EEPHY_REG_ARRAY_PGLEN; | ||
146 | table_pg = RTL8188EEPHY_REG_ARRAY_PG; | ||
147 | |||
148 | if (configtype == BASEBAND_CONFIG_PHY_REG) { | ||
149 | for (i = 0; i < tbl_page_len; i = i + 3) { | ||
150 | v1 = table_pg[i]; | ||
151 | v2 = table_pg[i + 1]; | ||
152 | |||
153 | if (v1 < 0xcdcdcdcd) { | ||
154 | if (table_pg[i] == 0xfe) | ||
155 | mdelay(50); | ||
156 | else if (table_pg[i] == 0xfd) | ||
157 | mdelay(5); | ||
158 | else if (table_pg[i] == 0xfc) | ||
159 | mdelay(1); | ||
160 | else if (table_pg[i] == 0xfb) | ||
161 | udelay(50); | ||
162 | else if (table_pg[i] == 0xfa) | ||
163 | udelay(5); | ||
164 | else if (table_pg[i] == 0xf9) | ||
165 | udelay(1); | ||
166 | |||
167 | store_pwrindex_offset(hw, table_pg[i], | ||
168 | table_pg[i + 1], | ||
169 | table_pg[i + 2]); | ||
170 | continue; | ||
171 | } else { | ||
172 | if (!check_cond(hw, table_pg[i])) { | ||
173 | /*don't need the hw_body*/ | ||
174 | i += 2; /* skip the pair of expression*/ | ||
175 | v1 = table_pg[i]; | ||
176 | v2 = table_pg[i + 1]; | ||
177 | while (v2 != 0xDEAD) { | ||
178 | i += 3; | ||
179 | v1 = table_pg[i]; | ||
180 | v2 = table_pg[i + 1]; | ||
181 | } | ||
182 | } | ||
183 | } | ||
184 | } | ||
185 | } else { | ||
186 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, | ||
187 | "configtype != BaseBand_Config_PHY_REG\n"); | ||
188 | } | ||
189 | return true; | ||
190 | } | ||
191 | |||
192 | static bool config_parafile(struct ieee80211_hw *hw) | ||
193 | { | ||
194 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
195 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
196 | struct rtl_efuse *fuse = rtl_efuse(rtl_priv(hw)); | ||
197 | bool rtstatus; | ||
198 | |||
199 | rtstatus = config_bb_with_header(hw, BASEBAND_CONFIG_PHY_REG); | ||
200 | if (rtstatus != true) { | ||
201 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Write BB Reg Fail!!"); | ||
202 | return false; | ||
203 | } | ||
204 | |||
205 | if (fuse->autoload_failflag == false) { | ||
206 | rtlphy->pwrgroup_cnt = 0; | ||
207 | rtstatus = config_bb_with_pgheader(hw, BASEBAND_CONFIG_PHY_REG); | ||
208 | } | ||
209 | if (rtstatus != true) { | ||
210 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "BB_PG Reg Fail!!"); | ||
211 | return false; | ||
212 | } | ||
213 | rtstatus = config_bb_with_header(hw, BASEBAND_CONFIG_AGC_TAB); | ||
214 | if (rtstatus != true) { | ||
215 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "AGC Table Fail\n"); | ||
216 | return false; | ||
217 | } | ||
218 | rtlphy->cck_high_power = (bool) (rtl_get_bbreg(hw, | ||
219 | RFPGA0_XA_HSSIPARAMETER2, 0x200)); | ||
220 | |||
221 | return true; | ||
222 | } | ||
223 | |||
224 | static void rtl88e_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw) | ||
225 | { | ||
226 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
227 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
228 | int jj = RF90_PATH_A; | ||
229 | int kk = RF90_PATH_B; | ||
230 | |||
231 | rtlphy->phyreg_def[jj].rfintfs = RFPGA0_XAB_RFINTERFACESW; | ||
232 | rtlphy->phyreg_def[kk].rfintfs = RFPGA0_XAB_RFINTERFACESW; | ||
233 | rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW; | ||
234 | rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW; | ||
235 | |||
236 | rtlphy->phyreg_def[jj].rfintfi = RFPGA0_XAB_RFINTERFACERB; | ||
237 | rtlphy->phyreg_def[kk].rfintfi = RFPGA0_XAB_RFINTERFACERB; | ||
238 | rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB; | ||
239 | rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB; | ||
240 | |||
241 | rtlphy->phyreg_def[jj].rfintfo = RFPGA0_XA_RFINTERFACEOE; | ||
242 | rtlphy->phyreg_def[kk].rfintfo = RFPGA0_XB_RFINTERFACEOE; | ||
243 | |||
244 | rtlphy->phyreg_def[jj].rfintfe = RFPGA0_XA_RFINTERFACEOE; | ||
245 | rtlphy->phyreg_def[kk].rfintfe = RFPGA0_XB_RFINTERFACEOE; | ||
246 | |||
247 | rtlphy->phyreg_def[jj].rf3wire_offset = RFPGA0_XA_LSSIPARAMETER; | ||
248 | rtlphy->phyreg_def[kk].rf3wire_offset = RFPGA0_XB_LSSIPARAMETER; | ||
249 | |||
250 | rtlphy->phyreg_def[jj].rflssi_select = rFPGA0_XAB_RFPARAMETER; | ||
251 | rtlphy->phyreg_def[kk].rflssi_select = rFPGA0_XAB_RFPARAMETER; | ||
252 | rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = rFPGA0_XCD_RFPARAMETER; | ||
253 | rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = rFPGA0_XCD_RFPARAMETER; | ||
254 | |||
255 | rtlphy->phyreg_def[jj].rftxgain_stage = RFPGA0_TXGAINSTAGE; | ||
256 | rtlphy->phyreg_def[kk].rftxgain_stage = RFPGA0_TXGAINSTAGE; | ||
257 | rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE; | ||
258 | rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE; | ||
259 | |||
260 | rtlphy->phyreg_def[jj].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1; | ||
261 | rtlphy->phyreg_def[kk].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1; | ||
262 | |||
263 | rtlphy->phyreg_def[jj].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2; | ||
264 | rtlphy->phyreg_def[kk].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2; | ||
265 | |||
266 | rtlphy->phyreg_def[jj].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; | ||
267 | rtlphy->phyreg_def[kk].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; | ||
268 | rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; | ||
269 | rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; | ||
270 | |||
271 | rtlphy->phyreg_def[jj].rfagc_control1 = ROFDM0_XAAGCCORE1; | ||
272 | rtlphy->phyreg_def[kk].rfagc_control1 = ROFDM0_XBAGCCORE1; | ||
273 | rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1; | ||
274 | rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1; | ||
275 | |||
276 | rtlphy->phyreg_def[jj].rfagc_control2 = ROFDM0_XAAGCCORE2; | ||
277 | rtlphy->phyreg_def[kk].rfagc_control2 = ROFDM0_XBAGCCORE2; | ||
278 | rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2; | ||
279 | rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2; | ||
280 | |||
281 | rtlphy->phyreg_def[jj].rfrxiq_imbal = ROFDM0_XARXIQIMBAL; | ||
282 | rtlphy->phyreg_def[kk].rfrxiq_imbal = ROFDM0_XBRXIQIMBAL; | ||
283 | rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBAL; | ||
284 | rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBAL; | ||
285 | |||
286 | rtlphy->phyreg_def[jj].rfrx_afe = ROFDM0_XARXAFE; | ||
287 | rtlphy->phyreg_def[kk].rfrx_afe = ROFDM0_XBRXAFE; | ||
288 | rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE; | ||
289 | rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE; | ||
290 | |||
291 | rtlphy->phyreg_def[jj].rftxiq_imbal = ROFDM0_XATXIQIMBAL; | ||
292 | rtlphy->phyreg_def[kk].rftxiq_imbal = ROFDM0_XBTXIQIMBAL; | ||
293 | rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTXIQIMBAL; | ||
294 | rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTXIQIMBAL; | ||
295 | |||
296 | rtlphy->phyreg_def[jj].rftx_afe = ROFDM0_XATXAFE; | ||
297 | rtlphy->phyreg_def[kk].rftx_afe = ROFDM0_XBTXAFE; | ||
298 | |||
299 | rtlphy->phyreg_def[jj].rf_rb = RFPGA0_XA_LSSIREADBACK; | ||
300 | rtlphy->phyreg_def[kk].rf_rb = RFPGA0_XB_LSSIREADBACK; | ||
301 | |||
302 | rtlphy->phyreg_def[jj].rf_rbpi = TRANSCEIVEA_HSPI_READBACK; | ||
303 | rtlphy->phyreg_def[kk].rf_rbpi = TRANSCEIVEB_HSPI_READBACK; | ||
304 | } | ||
305 | |||
306 | static bool rtl88e_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, | ||
307 | u32 cmdtableidx, u32 cmdtablesz, | ||
308 | enum swchnlcmd_id cmdid, | ||
309 | u32 para1, u32 para2, u32 msdelay) | ||
310 | { | ||
311 | struct swchnlcmd *pcmd; | ||
312 | |||
313 | if (cmdtable == NULL) { | ||
314 | RT_ASSERT(false, "cmdtable cannot be NULL.\n"); | ||
315 | return false; | ||
316 | } | ||
317 | |||
318 | if (cmdtableidx >= cmdtablesz) | ||
319 | return false; | ||
320 | |||
321 | pcmd = cmdtable + cmdtableidx; | ||
322 | pcmd->cmdid = cmdid; | ||
323 | pcmd->para1 = para1; | ||
324 | pcmd->para2 = para2; | ||
325 | pcmd->msdelay = msdelay; | ||
326 | return true; | ||
327 | } | ||
328 | |||
329 | static bool chnl_step_by_step(struct ieee80211_hw *hw, | ||
330 | u8 channel, u8 *stage, u8 *step, | ||
331 | u32 *delay) | ||
332 | { | ||
333 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
334 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
335 | struct swchnlcmd precommoncmd[MAX_PRECMD_CNT]; | ||
336 | u32 precommoncmdcnt; | ||
337 | struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT]; | ||
338 | u32 postcommoncmdcnt; | ||
339 | struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT]; | ||
340 | u32 rfdependcmdcnt; | ||
341 | struct swchnlcmd *currentcmd = NULL; | ||
342 | u8 rfpath; | ||
343 | u8 num_total_rfpath = rtlphy->num_total_rfpath; | ||
344 | |||
345 | precommoncmdcnt = 0; | ||
346 | rtl88e_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, | ||
347 | MAX_PRECMD_CNT, | ||
348 | CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0); | ||
349 | rtl88e_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, | ||
350 | MAX_PRECMD_CNT, CMDID_END, 0, 0, 0); | ||
351 | |||
352 | postcommoncmdcnt = 0; | ||
353 | |||
354 | rtl88e_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++, | ||
355 | MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0); | ||
356 | |||
357 | rfdependcmdcnt = 0; | ||
358 | |||
359 | RT_ASSERT((channel >= 1 && channel <= 14), | ||
360 | "illegal channel for Zebra: %d\n", channel); | ||
361 | |||
362 | rtl88e_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, | ||
363 | MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG, | ||
364 | RF_CHNLBW, channel, 10); | ||
365 | |||
366 | rtl88e_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, | ||
367 | MAX_RFDEPENDCMD_CNT, CMDID_END, 0, 0, | ||
368 | 0); | ||
369 | |||
370 | do { | ||
371 | switch (*stage) { | ||
372 | case 0: | ||
373 | currentcmd = &precommoncmd[*step]; | ||
374 | break; | ||
375 | case 1: | ||
376 | currentcmd = &rfdependcmd[*step]; | ||
377 | break; | ||
378 | case 2: | ||
379 | currentcmd = &postcommoncmd[*step]; | ||
380 | break; | ||
381 | } | ||
382 | |||
383 | if (currentcmd->cmdid == CMDID_END) { | ||
384 | if ((*stage) == 2) { | ||
385 | return true; | ||
386 | } else { | ||
387 | (*stage)++; | ||
388 | (*step) = 0; | ||
389 | continue; | ||
390 | } | ||
391 | } | ||
392 | |||
393 | switch (currentcmd->cmdid) { | ||
394 | case CMDID_SET_TXPOWEROWER_LEVEL: | ||
395 | rtl88e_phy_set_txpower_level(hw, channel); | ||
396 | break; | ||
397 | case CMDID_WRITEPORT_ULONG: | ||
398 | rtl_write_dword(rtlpriv, currentcmd->para1, | ||
399 | currentcmd->para2); | ||
400 | break; | ||
401 | case CMDID_WRITEPORT_USHORT: | ||
402 | rtl_write_word(rtlpriv, currentcmd->para1, | ||
403 | (u16) currentcmd->para2); | ||
404 | break; | ||
405 | case CMDID_WRITEPORT_UCHAR: | ||
406 | rtl_write_byte(rtlpriv, currentcmd->para1, | ||
407 | (u8) currentcmd->para2); | ||
408 | break; | ||
409 | case CMDID_RF_WRITEREG: | ||
410 | for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) { | ||
411 | rtlphy->rfreg_chnlval[rfpath] = | ||
412 | ((rtlphy->rfreg_chnlval[rfpath] & | ||
413 | 0xfffffc00) | currentcmd->para2); | ||
414 | |||
415 | rtl_set_rfreg(hw, (enum radio_path)rfpath, | ||
416 | currentcmd->para1, | ||
417 | RFREG_OFFSET_MASK, | ||
418 | rtlphy->rfreg_chnlval[rfpath]); | ||
419 | } | ||
420 | break; | ||
421 | default: | ||
422 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
423 | "switch case not processed\n"); | ||
424 | break; | ||
425 | } | ||
426 | |||
427 | break; | ||
428 | } while (true); | ||
429 | |||
430 | (*delay) = currentcmd->msdelay; | ||
431 | (*step)++; | ||
432 | return false; | ||
433 | } | ||
434 | |||
435 | static long rtl88e_pwr_idx_dbm(struct ieee80211_hw *hw, | ||
436 | enum wireless_mode wirelessmode, | ||
437 | u8 txpwridx) | ||
438 | { | ||
439 | long offset; | ||
440 | long pwrout_dbm; | ||
441 | |||
442 | switch (wirelessmode) { | ||
443 | case WIRELESS_MODE_B: | ||
444 | offset = -7; | ||
445 | break; | ||
446 | case WIRELESS_MODE_G: | ||
447 | case WIRELESS_MODE_N_24G: | ||
448 | offset = -8; | ||
449 | break; | ||
450 | default: | ||
451 | offset = -8; | ||
452 | break; | ||
453 | } | ||
454 | pwrout_dbm = txpwridx / 2 + offset; | ||
455 | return pwrout_dbm; | ||
456 | } | ||
457 | |||
458 | static void rtl88e_phy_set_io(struct ieee80211_hw *hw) | ||
459 | { | ||
460 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
461 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
462 | struct dig_t *dm_digtable = &rtlpriv->dm_digtable; | ||
463 | |||
464 | RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, | ||
465 | "--->Cmd(%#x), set_io_inprogress(%d)\n", | ||
466 | rtlphy->current_io_type, rtlphy->set_io_inprogress); | ||
467 | switch (rtlphy->current_io_type) { | ||
468 | case IO_CMD_RESUME_DM_BY_SCAN: | ||
469 | dm_digtable->cur_igvalue = rtlphy->initgain_backup.xaagccore1; | ||
470 | /*rtl92c_dm_write_dig(hw);*/ | ||
471 | rtl88e_phy_set_txpower_level(hw, rtlphy->current_channel); | ||
472 | rtl_set_bbreg(hw, RCCK0_CCA, 0xff0000, 0x83); | ||
473 | break; | ||
474 | case IO_CMD_PAUSE_DM_BY_SCAN: | ||
475 | rtlphy->initgain_backup.xaagccore1 = dm_digtable->cur_igvalue; | ||
476 | dm_digtable->cur_igvalue = 0x17; | ||
477 | rtl_set_bbreg(hw, RCCK0_CCA, 0xff0000, 0x40); | ||
478 | break; | ||
479 | default: | ||
480 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
481 | "switch case not processed\n"); | ||
482 | break; | ||
483 | } | ||
484 | rtlphy->set_io_inprogress = false; | ||
485 | RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, | ||
486 | "(%#x)\n", rtlphy->current_io_type); | ||
487 | } | ||
488 | |||
489 | u32 rtl88e_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask) | ||
490 | { | ||
491 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
492 | u32 returnvalue, originalvalue, bitshift; | ||
493 | |||
494 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | ||
495 | "regaddr(%#x), bitmask(%#x)\n", regaddr, bitmask); | ||
496 | originalvalue = rtl_read_dword(rtlpriv, regaddr); | ||
497 | bitshift = cal_bit_shift(bitmask); | ||
498 | returnvalue = (originalvalue & bitmask) >> bitshift; | ||
499 | |||
500 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | ||
501 | "BBR MASK = 0x%x Addr[0x%x]= 0x%x\n", bitmask, | ||
502 | regaddr, originalvalue); | ||
503 | |||
504 | return returnvalue; | ||
505 | } | ||
506 | |||
507 | void rtl88e_phy_set_bb_reg(struct ieee80211_hw *hw, | ||
508 | u32 regaddr, u32 bitmask, u32 data) | ||
509 | { | ||
510 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
511 | u32 originalvalue, bitshift; | ||
512 | |||
513 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | ||
514 | "regaddr(%#x), bitmask(%#x),data(%#x)\n", | ||
515 | regaddr, bitmask, data); | ||
516 | |||
517 | if (bitmask != MASKDWORD) { | ||
518 | originalvalue = rtl_read_dword(rtlpriv, regaddr); | ||
519 | bitshift = cal_bit_shift(bitmask); | ||
520 | data = ((originalvalue & (~bitmask)) | (data << bitshift)); | ||
521 | } | ||
522 | |||
523 | rtl_write_dword(rtlpriv, regaddr, data); | ||
524 | |||
525 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | ||
526 | "regaddr(%#x), bitmask(%#x), data(%#x)\n", | ||
527 | regaddr, bitmask, data); | ||
528 | } | ||
529 | |||
530 | u32 rtl88e_phy_query_rf_reg(struct ieee80211_hw *hw, | ||
531 | enum radio_path rfpath, u32 regaddr, u32 bitmask) | ||
532 | { | ||
533 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
534 | u32 original_value, readback_value, bitshift; | ||
535 | unsigned long flags; | ||
536 | |||
537 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | ||
538 | "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n", | ||
539 | regaddr, rfpath, bitmask); | ||
540 | |||
541 | spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); | ||
542 | |||
543 | |||
544 | original_value = rf_serial_read(hw, rfpath, regaddr); | ||
545 | bitshift = cal_bit_shift(bitmask); | ||
546 | readback_value = (original_value & bitmask) >> bitshift; | ||
547 | |||
548 | spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); | ||
549 | |||
550 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | ||
551 | "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n", | ||
552 | regaddr, rfpath, bitmask, original_value); | ||
553 | |||
554 | return readback_value; | ||
555 | } | ||
556 | |||
557 | void rtl88e_phy_set_rf_reg(struct ieee80211_hw *hw, | ||
558 | enum radio_path rfpath, | ||
559 | u32 regaddr, u32 bitmask, u32 data) | ||
560 | { | ||
561 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
562 | u32 original_value, bitshift; | ||
563 | unsigned long flags; | ||
564 | |||
565 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | ||
566 | "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", | ||
567 | regaddr, bitmask, data, rfpath); | ||
568 | |||
569 | spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); | ||
570 | |||
571 | if (bitmask != RFREG_OFFSET_MASK) { | ||
572 | original_value = rf_serial_read(hw, rfpath, regaddr); | ||
573 | bitshift = cal_bit_shift(bitmask); | ||
574 | data = ((original_value & (~bitmask)) | | ||
575 | (data << bitshift)); | ||
576 | } | ||
577 | |||
578 | rf_serial_write(hw, rfpath, regaddr, data); | ||
579 | |||
580 | |||
581 | spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); | ||
582 | |||
583 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | ||
584 | "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", | ||
585 | regaddr, bitmask, data, rfpath); | ||
586 | } | ||
587 | |||
588 | static bool config_mac_with_header(struct ieee80211_hw *hw) | ||
589 | { | ||
590 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
591 | u32 i; | ||
592 | u32 arraylength; | ||
593 | u32 *ptrarray; | ||
594 | |||
595 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl8188EMACPHY_Array\n"); | ||
596 | arraylength = RTL8188EEMAC_1T_ARRAYLEN; | ||
597 | ptrarray = RTL8188EEMAC_1T_ARRAY; | ||
598 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
599 | "Img:RTL8188EEMAC_1T_ARRAY LEN %d\n", arraylength); | ||
600 | for (i = 0; i < arraylength; i = i + 2) | ||
601 | rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]); | ||
602 | return true; | ||
603 | } | ||
604 | |||
605 | bool rtl88e_phy_mac_config(struct ieee80211_hw *hw) | ||
606 | { | ||
607 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
608 | bool rtstatus = config_mac_with_header(hw); | ||
609 | |||
610 | rtl_write_byte(rtlpriv, 0x04CA, 0x0B); | ||
611 | return rtstatus; | ||
612 | } | ||
613 | |||
614 | bool rtl88e_phy_bb_config(struct ieee80211_hw *hw) | ||
615 | { | ||
616 | bool rtstatus = true; | ||
617 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
618 | u16 regval; | ||
619 | u8 reg_hwparafile = 1; | ||
620 | u32 tmp; | ||
621 | rtl88e_phy_init_bb_rf_register_definition(hw); | ||
622 | regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); | ||
623 | rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, | ||
624 | regval | BIT(13) | BIT(0) | BIT(1)); | ||
625 | |||
626 | rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); | ||
627 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, | ||
628 | FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE | | ||
629 | FEN_BB_GLB_RSTN | FEN_BBRSTB); | ||
630 | tmp = rtl_read_dword(rtlpriv, 0x4c); | ||
631 | rtl_write_dword(rtlpriv, 0x4c, tmp | BIT(23)); | ||
632 | if (reg_hwparafile == 1) | ||
633 | rtstatus = config_parafile(hw); | ||
634 | return rtstatus; | ||
635 | } | ||
636 | |||
637 | bool rtl88e_phy_rf_config(struct ieee80211_hw *hw) | ||
638 | { | ||
639 | return rtl88e_phy_rf6052_config(hw); | ||
640 | } | ||
641 | |||
642 | static bool check_cond(struct ieee80211_hw *hw, | ||
643 | const u32 condition) | ||
644 | { | ||
645 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
646 | struct rtl_efuse *fuse = rtl_efuse(rtl_priv(hw)); | ||
647 | u32 _board = fuse->board_type; /*need efuse define*/ | ||
648 | u32 _interface = rtlhal->interface; | ||
649 | u32 _platform = 0x08;/*SupportPlatform */ | ||
650 | u32 cond = condition; | ||
651 | |||
652 | if (condition == 0xCDCDCDCD) | ||
653 | return true; | ||
654 | |||
655 | cond = condition & 0xFF; | ||
656 | if ((_board & cond) == 0 && cond != 0x1F) | ||
657 | return false; | ||
658 | |||
659 | cond = condition & 0xFF00; | ||
660 | cond = cond >> 8; | ||
661 | if ((_interface & cond) == 0 && cond != 0x07) | ||
662 | return false; | ||
663 | |||
664 | cond = condition & 0xFF0000; | ||
665 | cond = cond >> 16; | ||
666 | if ((_platform & cond) == 0 && cond != 0x0F) | ||
667 | return false; | ||
668 | return true; | ||
669 | } | ||
670 | |||
671 | static void _rtl8188e_config_rf_reg(struct ieee80211_hw *hw, | ||
672 | u32 addr, u32 data, enum radio_path rfpath, | ||
673 | u32 regaddr) | ||
674 | { | ||
675 | if (addr == 0xffe) { | ||
676 | mdelay(50); | ||
677 | } else if (addr == 0xfd) { | ||
678 | mdelay(5); | ||
679 | } else if (addr == 0xfc) { | ||
680 | mdelay(1); | ||
681 | } else if (addr == 0xfb) { | ||
682 | udelay(50); | ||
683 | } else if (addr == 0xfa) { | ||
684 | udelay(5); | ||
685 | } else if (addr == 0xf9) { | ||
686 | udelay(1); | ||
687 | } else { | ||
688 | rtl_set_rfreg(hw, rfpath, regaddr, | ||
689 | RFREG_OFFSET_MASK, | ||
690 | data); | ||
691 | udelay(1); | ||
692 | } | ||
693 | } | ||
694 | |||
695 | static void rtl88_config_s(struct ieee80211_hw *hw, | ||
696 | u32 addr, u32 data) | ||
697 | { | ||
698 | u32 content = 0x1000; /*RF Content: radio_a_txt*/ | ||
699 | u32 maskforphyset = (u32)(content & 0xE000); | ||
700 | |||
701 | _rtl8188e_config_rf_reg(hw, addr, data, RF90_PATH_A, | ||
702 | addr | maskforphyset); | ||
703 | } | ||
704 | |||
705 | static void _rtl8188e_config_bb_reg(struct ieee80211_hw *hw, | ||
706 | u32 addr, u32 data) | ||
707 | { | ||
708 | if (addr == 0xfe) { | ||
709 | mdelay(50); | ||
710 | } else if (addr == 0xfd) { | ||
711 | mdelay(5); | ||
712 | } else if (addr == 0xfc) { | ||
713 | mdelay(1); | ||
714 | } else if (addr == 0xfb) { | ||
715 | udelay(50); | ||
716 | } else if (addr == 0xfa) { | ||
717 | udelay(5); | ||
718 | } else if (addr == 0xf9) { | ||
719 | udelay(1); | ||
720 | } else { | ||
721 | rtl_set_bbreg(hw, addr, MASKDWORD, data); | ||
722 | udelay(1); | ||
723 | } | ||
724 | } | ||
725 | |||
726 | |||
727 | #define NEXT_PAIR(v1, v2, i) \ | ||
728 | do { \ | ||
729 | i += 2; v1 = array_table[i]; \ | ||
730 | v2 = array_table[i + 1]; \ | ||
731 | } while (0) | ||
732 | |||
733 | static void set_baseband_agc_config(struct ieee80211_hw *hw) | ||
734 | { | ||
735 | int i; | ||
736 | u32 *array_table; | ||
737 | u16 arraylen; | ||
738 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
739 | u32 v1 = 0, v2 = 0; | ||
740 | |||
741 | arraylen = RTL8188EEAGCTAB_1TARRAYLEN; | ||
742 | array_table = RTL8188EEAGCTAB_1TARRAY; | ||
743 | |||
744 | for (i = 0; i < arraylen; i += 2) { | ||
745 | v1 = array_table[i]; | ||
746 | v2 = array_table[i + 1]; | ||
747 | if (v1 < 0xCDCDCDCD) { | ||
748 | rtl_set_bbreg(hw, array_table[i], MASKDWORD, | ||
749 | array_table[i + 1]); | ||
750 | udelay(1); | ||
751 | continue; | ||
752 | } else {/*This line is the start line of branch.*/ | ||
753 | if (!check_cond(hw, array_table[i])) { | ||
754 | /*Discard the following (offset, data) pairs*/ | ||
755 | NEXT_PAIR(v1, v2, i); | ||
756 | while (v2 != 0xDEAD && v2 != 0xCDEF && | ||
757 | v2 != 0xCDCD && i < arraylen - 2) { | ||
758 | NEXT_PAIR(v1, v2, i); | ||
759 | } | ||
760 | i -= 2; /* compensate for loop's += 2*/ | ||
761 | } else { | ||
762 | /* Configure matched pairs and skip to end */ | ||
763 | NEXT_PAIR(v1, v2, i); | ||
764 | while (v2 != 0xDEAD && v2 != 0xCDEF && | ||
765 | v2 != 0xCDCD && i < arraylen - 2) { | ||
766 | rtl_set_bbreg(hw, array_table[i], | ||
767 | MASKDWORD, | ||
768 | array_table[i + 1]); | ||
769 | udelay(1); | ||
770 | NEXT_PAIR(v1, v2, i); | ||
771 | } | ||
772 | |||
773 | while (v2 != 0xDEAD && i < arraylen - 2) | ||
774 | NEXT_PAIR(v1, v2, i); | ||
775 | } | ||
776 | } | ||
777 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
778 | "The agctab_array_table[0] is %x Rtl818EEPHY_REGArray[1] is %x\n", | ||
779 | array_table[i], | ||
780 | array_table[i + 1]); | ||
781 | } | ||
782 | } | ||
783 | |||
784 | static void set_baseband_phy_config(struct ieee80211_hw *hw) | ||
785 | { | ||
786 | int i; | ||
787 | u32 *array_table; | ||
788 | u16 arraylen; | ||
789 | u32 v1 = 0, v2 = 0; | ||
790 | |||
791 | arraylen = RTL8188EEPHY_REG_1TARRAYLEN; | ||
792 | array_table = RTL8188EEPHY_REG_1TARRAY; | ||
793 | |||
794 | for (i = 0; i < arraylen; i += 2) { | ||
795 | v1 = array_table[i]; | ||
796 | v2 = array_table[i + 1]; | ||
797 | if (v1 < 0xcdcdcdcd) { | ||
798 | _rtl8188e_config_bb_reg(hw, v1, v2); | ||
799 | } else {/*This line is the start line of branch.*/ | ||
800 | if (!check_cond(hw, array_table[i])) { | ||
801 | /*Discard the following (offset, data) pairs*/ | ||
802 | NEXT_PAIR(v1, v2, i); | ||
803 | while (v2 != 0xDEAD && | ||
804 | v2 != 0xCDEF && | ||
805 | v2 != 0xCDCD && i < arraylen - 2) | ||
806 | NEXT_PAIR(v1, v2, i); | ||
807 | i -= 2; /* prevent from for-loop += 2*/ | ||
808 | } else { | ||
809 | /* Configure matched pairs and skip to end */ | ||
810 | NEXT_PAIR(v1, v2, i); | ||
811 | while (v2 != 0xDEAD && | ||
812 | v2 != 0xCDEF && | ||
813 | v2 != 0xCDCD && i < arraylen - 2) { | ||
814 | _rtl8188e_config_bb_reg(hw, v1, v2); | ||
815 | NEXT_PAIR(v1, v2, i); | ||
816 | } | ||
817 | |||
818 | while (v2 != 0xDEAD && i < arraylen - 2) | ||
819 | NEXT_PAIR(v1, v2, i); | ||
820 | } | ||
821 | } | ||
822 | } | ||
823 | } | ||
824 | |||
825 | static void store_pwrindex_offset(struct ieee80211_hw *hw, | ||
826 | u32 regaddr, u32 bitmask, | ||
827 | u32 data) | ||
828 | { | ||
829 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
830 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
831 | |||
832 | if (regaddr == RTXAGC_A_RATE18_06) { | ||
833 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][0] = data; | ||
834 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
835 | "MCSTxPowerLevelOriginalOffset[%d][0] = 0x%x\n", | ||
836 | rtlphy->pwrgroup_cnt, | ||
837 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][0]); | ||
838 | } | ||
839 | if (regaddr == RTXAGC_A_RATE54_24) { | ||
840 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][1] = data; | ||
841 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
842 | "MCSTxPowerLevelOriginalOffset[%d][1] = 0x%x\n", | ||
843 | rtlphy->pwrgroup_cnt, | ||
844 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][1]); | ||
845 | } | ||
846 | if (regaddr == RTXAGC_A_CCK1_MCS32) { | ||
847 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][6] = data; | ||
848 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
849 | "MCSTxPowerLevelOriginalOffset[%d][6] = 0x%x\n", | ||
850 | rtlphy->pwrgroup_cnt, | ||
851 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][6]); | ||
852 | } | ||
853 | if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) { | ||
854 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][7] = data; | ||
855 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
856 | "MCSTxPowerLevelOriginalOffset[%d][7] = 0x%x\n", | ||
857 | rtlphy->pwrgroup_cnt, | ||
858 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][7]); | ||
859 | } | ||
860 | if (regaddr == RTXAGC_A_MCS03_MCS00) { | ||
861 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][2] = data; | ||
862 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
863 | "MCSTxPowerLevelOriginalOffset[%d][2] = 0x%x\n", | ||
864 | rtlphy->pwrgroup_cnt, | ||
865 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][2]); | ||
866 | } | ||
867 | if (regaddr == RTXAGC_A_MCS07_MCS04) { | ||
868 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][3] = data; | ||
869 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
870 | "MCSTxPowerLevelOriginalOffset[%d][3] = 0x%x\n", | ||
871 | rtlphy->pwrgroup_cnt, | ||
872 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][3]); | ||
873 | } | ||
874 | if (regaddr == RTXAGC_A_MCS11_MCS08) { | ||
875 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][4] = data; | ||
876 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
877 | "MCSTxPowerLevelOriginalOffset[%d][4] = 0x%x\n", | ||
878 | rtlphy->pwrgroup_cnt, | ||
879 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][4]); | ||
880 | } | ||
881 | if (regaddr == RTXAGC_A_MCS15_MCS12) { | ||
882 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][5] = data; | ||
883 | if (get_rf_type(rtlphy) == RF_1T1R) | ||
884 | rtlphy->pwrgroup_cnt++; | ||
885 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
886 | "MCSTxPowerLevelOriginalOffset[%d][5] = 0x%x\n", | ||
887 | rtlphy->pwrgroup_cnt, | ||
888 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][5]); | ||
889 | } | ||
890 | if (regaddr == RTXAGC_B_RATE18_06) { | ||
891 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][8] = data; | ||
892 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
893 | "MCSTxPowerLevelOriginalOffset[%d][8] = 0x%x\n", | ||
894 | rtlphy->pwrgroup_cnt, | ||
895 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][8]); | ||
896 | } | ||
897 | if (regaddr == RTXAGC_B_RATE54_24) { | ||
898 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][9] = data; | ||
899 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
900 | "MCSTxPowerLevelOriginalOffset[%d][9] = 0x%x\n", | ||
901 | rtlphy->pwrgroup_cnt, | ||
902 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][9]); | ||
903 | } | ||
904 | if (regaddr == RTXAGC_B_CCK1_55_MCS32) { | ||
905 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][14] = data; | ||
906 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
907 | "MCSTxPowerLevelOriginalOffset[%d][14] = 0x%x\n", | ||
908 | rtlphy->pwrgroup_cnt, | ||
909 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][14]); | ||
910 | } | ||
911 | if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) { | ||
912 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][15] = data; | ||
913 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
914 | "MCSTxPowerLevelOriginalOffset[%d][15] = 0x%x\n", | ||
915 | rtlphy->pwrgroup_cnt, | ||
916 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][15]); | ||
917 | } | ||
918 | if (regaddr == RTXAGC_B_MCS03_MCS00) { | ||
919 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][10] = data; | ||
920 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
921 | "MCSTxPowerLevelOriginalOffset[%d][10] = 0x%x\n", | ||
922 | rtlphy->pwrgroup_cnt, | ||
923 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][10]); | ||
924 | } | ||
925 | if (regaddr == RTXAGC_B_MCS07_MCS04) { | ||
926 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][11] = data; | ||
927 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
928 | "MCSTxPowerLevelOriginalOffset[%d][11] = 0x%x\n", | ||
929 | rtlphy->pwrgroup_cnt, | ||
930 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][11]); | ||
931 | } | ||
932 | if (regaddr == RTXAGC_B_MCS11_MCS08) { | ||
933 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][12] = data; | ||
934 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
935 | "MCSTxPowerLevelOriginalOffset[%d][12] = 0x%x\n", | ||
936 | rtlphy->pwrgroup_cnt, | ||
937 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][12]); | ||
938 | } | ||
939 | if (regaddr == RTXAGC_B_MCS15_MCS12) { | ||
940 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][13] = data; | ||
941 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
942 | "MCSTxPowerLevelOriginalOffset[%d][13] = 0x%x\n", | ||
943 | rtlphy->pwrgroup_cnt, | ||
944 | rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][13]); | ||
945 | if (get_rf_type(rtlphy) != RF_1T1R) | ||
946 | rtlphy->pwrgroup_cnt++; | ||
947 | } | ||
948 | } | ||
949 | |||
950 | #define READ_NEXT_RF_PAIR(v1, v2, i) \ | ||
951 | do { \ | ||
952 | i += 2; v1 = a_table[i]; \ | ||
953 | v2 = a_table[i + 1]; \ | ||
954 | } while (0) | ||
955 | |||
956 | bool rtl88e_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, | ||
957 | enum radio_path rfpath) | ||
958 | { | ||
959 | int i; | ||
960 | u32 *a_table; | ||
961 | u16 a_len; | ||
962 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
963 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
964 | u32 v1 = 0, v2 = 0; | ||
965 | |||
966 | a_len = RTL8188EE_RADIOA_1TARRAYLEN; | ||
967 | a_table = RTL8188EE_RADIOA_1TARRAY; | ||
968 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
969 | "Radio_A:RTL8188EE_RADIOA_1TARRAY %d\n", a_len); | ||
970 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Radio No %x\n", rfpath); | ||
971 | switch (rfpath) { | ||
972 | case RF90_PATH_A: | ||
973 | for (i = 0; i < a_len; i = i + 2) { | ||
974 | v1 = a_table[i]; | ||
975 | v2 = a_table[i + 1]; | ||
976 | if (v1 < 0xcdcdcdcd) { | ||
977 | rtl88_config_s(hw, v1, v2); | ||
978 | } else {/*This line is the start line of branch.*/ | ||
979 | if (!check_cond(hw, a_table[i])) { | ||
980 | /* Discard the following (offset, data) | ||
981 | * pairs | ||
982 | */ | ||
983 | READ_NEXT_RF_PAIR(v1, v2, i); | ||
984 | while (v2 != 0xDEAD && v2 != 0xCDEF && | ||
985 | v2 != 0xCDCD && i < a_len - 2) | ||
986 | READ_NEXT_RF_PAIR(v1, v2, i); | ||
987 | i -= 2; /* prevent from for-loop += 2*/ | ||
988 | } else { | ||
989 | /* Configure matched pairs and skip to | ||
990 | * end of if-else. | ||
991 | */ | ||
992 | READ_NEXT_RF_PAIR(v1, v2, i); | ||
993 | while (v2 != 0xDEAD && v2 != 0xCDEF && | ||
994 | v2 != 0xCDCD && i < a_len - 2) { | ||
995 | rtl88_config_s(hw, v1, v2); | ||
996 | READ_NEXT_RF_PAIR(v1, v2, i); | ||
997 | } | ||
998 | |||
999 | while (v2 != 0xDEAD && i < a_len - 2) | ||
1000 | READ_NEXT_RF_PAIR(v1, v2, i); | ||
1001 | } | ||
1002 | } | ||
1003 | } | ||
1004 | |||
1005 | if (rtlhal->oem_id == RT_CID_819x_HP) | ||
1006 | rtl88_config_s(hw, 0x52, 0x7E4BD); | ||
1007 | |||
1008 | break; | ||
1009 | |||
1010 | case RF90_PATH_B: | ||
1011 | case RF90_PATH_C: | ||
1012 | case RF90_PATH_D: | ||
1013 | default: | ||
1014 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1015 | "switch case not processed\n"); | ||
1016 | break; | ||
1017 | } | ||
1018 | return true; | ||
1019 | } | ||
1020 | |||
1021 | void rtl88e_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) | ||
1022 | { | ||
1023 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1024 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1025 | |||
1026 | rtlphy->default_initialgain[0] = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, | ||
1027 | MASKBYTE0); | ||
1028 | rtlphy->default_initialgain[1] = rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, | ||
1029 | MASKBYTE0); | ||
1030 | rtlphy->default_initialgain[2] = rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, | ||
1031 | MASKBYTE0); | ||
1032 | rtlphy->default_initialgain[3] = rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, | ||
1033 | MASKBYTE0); | ||
1034 | |||
1035 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1036 | "Default initial gain (c50 = 0x%x, c58 = 0x%x, c60 = 0x%x, c68 = 0x%x\n", | ||
1037 | rtlphy->default_initialgain[0], | ||
1038 | rtlphy->default_initialgain[1], | ||
1039 | rtlphy->default_initialgain[2], | ||
1040 | rtlphy->default_initialgain[3]); | ||
1041 | |||
1042 | rtlphy->framesync = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR3, | ||
1043 | MASKBYTE0); | ||
1044 | rtlphy->framesync_c34 = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR2, | ||
1045 | MASKDWORD); | ||
1046 | |||
1047 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1048 | "Default framesync (0x%x) = 0x%x\n", | ||
1049 | ROFDM0_RXDETECTOR3, rtlphy->framesync); | ||
1050 | } | ||
1051 | |||
1052 | void rtl88e_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel) | ||
1053 | { | ||
1054 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1055 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1056 | u8 level; | ||
1057 | long dbm; | ||
1058 | |||
1059 | level = rtlphy->cur_cck_txpwridx; | ||
1060 | dbm = rtl88e_pwr_idx_dbm(hw, WIRELESS_MODE_B, level); | ||
1061 | level = rtlphy->cur_ofdm24g_txpwridx; | ||
1062 | if (rtl88e_pwr_idx_dbm(hw, WIRELESS_MODE_G, level) > dbm) | ||
1063 | dbm = rtl88e_pwr_idx_dbm(hw, WIRELESS_MODE_G, level); | ||
1064 | level = rtlphy->cur_ofdm24g_txpwridx; | ||
1065 | if (rtl88e_pwr_idx_dbm(hw, WIRELESS_MODE_N_24G, level) > dbm) | ||
1066 | dbm = rtl88e_pwr_idx_dbm(hw, WIRELESS_MODE_N_24G, level); | ||
1067 | *powerlevel = dbm; | ||
1068 | } | ||
1069 | |||
1070 | static void _rtl88e_get_txpower_index(struct ieee80211_hw *hw, u8 channel, | ||
1071 | u8 *cckpower, u8 *ofdm, u8 *bw20_pwr, | ||
1072 | u8 *bw40_pwr) | ||
1073 | { | ||
1074 | struct rtl_efuse *fuse = rtl_efuse(rtl_priv(hw)); | ||
1075 | u8 i = (channel - 1); | ||
1076 | u8 rf_path = 0; | ||
1077 | int jj = RF90_PATH_A; | ||
1078 | int kk = RF90_PATH_B; | ||
1079 | |||
1080 | for (rf_path = 0; rf_path < 2; rf_path++) { | ||
1081 | if (rf_path == jj) { | ||
1082 | cckpower[jj] = fuse->txpwrlevel_cck[jj][i]; | ||
1083 | if (fuse->txpwr_ht20diff[jj][i] > 0x0f) /*-8~7 */ | ||
1084 | bw20_pwr[jj] = fuse->txpwrlevel_ht40_1s[jj][i] - | ||
1085 | (~(fuse->txpwr_ht20diff[jj][i]) + 1); | ||
1086 | else | ||
1087 | bw20_pwr[jj] = fuse->txpwrlevel_ht40_1s[jj][i] + | ||
1088 | fuse->txpwr_ht20diff[jj][i]; | ||
1089 | if (fuse->txpwr_legacyhtdiff[jj][i] > 0xf) | ||
1090 | ofdm[jj] = fuse->txpwrlevel_ht40_1s[jj][i] - | ||
1091 | (~(fuse->txpwr_legacyhtdiff[jj][i])+1); | ||
1092 | else | ||
1093 | ofdm[jj] = fuse->txpwrlevel_ht40_1s[jj][i] + | ||
1094 | fuse->txpwr_legacyhtdiff[jj][i]; | ||
1095 | bw40_pwr[jj] = fuse->txpwrlevel_ht40_1s[jj][i]; | ||
1096 | |||
1097 | } else if (rf_path == kk) { | ||
1098 | cckpower[kk] = fuse->txpwrlevel_cck[kk][i]; | ||
1099 | bw20_pwr[kk] = fuse->txpwrlevel_ht40_1s[kk][i] + | ||
1100 | fuse->txpwr_ht20diff[kk][i]; | ||
1101 | ofdm[kk] = fuse->txpwrlevel_ht40_1s[kk][i] + | ||
1102 | fuse->txpwr_legacyhtdiff[kk][i]; | ||
1103 | bw40_pwr[kk] = fuse->txpwrlevel_ht40_1s[kk][i]; | ||
1104 | } | ||
1105 | } | ||
1106 | } | ||
1107 | |||
1108 | static void _rtl88e_ccxpower_index_check(struct ieee80211_hw *hw, | ||
1109 | u8 channel, u8 *cckpower, | ||
1110 | u8 *ofdm, u8 *bw20_pwr, | ||
1111 | u8 *bw40_pwr) | ||
1112 | { | ||
1113 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1114 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1115 | |||
1116 | rtlphy->cur_cck_txpwridx = cckpower[0]; | ||
1117 | rtlphy->cur_ofdm24g_txpwridx = ofdm[0]; | ||
1118 | rtlphy->cur_bw20_txpwridx = bw20_pwr[0]; | ||
1119 | rtlphy->cur_bw40_txpwridx = bw40_pwr[0]; | ||
1120 | } | ||
1121 | |||
1122 | void rtl88e_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) | ||
1123 | { | ||
1124 | struct rtl_efuse *fuse = rtl_efuse(rtl_priv(hw)); | ||
1125 | u8 cckpower[MAX_TX_COUNT] = {0}, ofdm[MAX_TX_COUNT] = {0}; | ||
1126 | u8 bw20_pwr[MAX_TX_COUNT] = {0}, bw40_pwr[MAX_TX_COUNT] = {0}; | ||
1127 | |||
1128 | if (fuse->txpwr_fromeprom == false) | ||
1129 | return; | ||
1130 | _rtl88e_get_txpower_index(hw, channel, &cckpower[0], &ofdm[0], | ||
1131 | &bw20_pwr[0], &bw40_pwr[0]); | ||
1132 | _rtl88e_ccxpower_index_check(hw, channel, &cckpower[0], &ofdm[0], | ||
1133 | &bw20_pwr[0], &bw40_pwr[0]); | ||
1134 | rtl88e_phy_rf6052_set_cck_txpower(hw, &cckpower[0]); | ||
1135 | rtl88e_phy_rf6052_set_ofdm_txpower(hw, &ofdm[0], &bw20_pwr[0], | ||
1136 | &bw40_pwr[0], channel); | ||
1137 | } | ||
1138 | |||
1139 | void rtl88e_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) | ||
1140 | { | ||
1141 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1142 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1143 | enum io_type iotype; | ||
1144 | |||
1145 | if (!is_hal_stop(rtlhal)) { | ||
1146 | switch (operation) { | ||
1147 | case SCAN_OPT_BACKUP: | ||
1148 | iotype = IO_CMD_PAUSE_DM_BY_SCAN; | ||
1149 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
1150 | HW_VAR_IO_CMD, | ||
1151 | (u8 *)&iotype); | ||
1152 | break; | ||
1153 | case SCAN_OPT_RESTORE: | ||
1154 | iotype = IO_CMD_RESUME_DM_BY_SCAN; | ||
1155 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
1156 | HW_VAR_IO_CMD, | ||
1157 | (u8 *)&iotype); | ||
1158 | break; | ||
1159 | default: | ||
1160 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1161 | "Unknown Scan Backup operation.\n"); | ||
1162 | break; | ||
1163 | } | ||
1164 | } | ||
1165 | } | ||
1166 | |||
1167 | void rtl88e_phy_set_bw_mode_callback(struct ieee80211_hw *hw) | ||
1168 | { | ||
1169 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1170 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1171 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1172 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1173 | u8 reg_bw_opmode; | ||
1174 | u8 reg_prsr_rsc; | ||
1175 | |||
1176 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, | ||
1177 | "Switch to %s bandwidth\n", | ||
1178 | rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? | ||
1179 | "20MHz" : "40MHz"); | ||
1180 | |||
1181 | if (is_hal_stop(rtlhal)) { | ||
1182 | rtlphy->set_bwmode_inprogress = false; | ||
1183 | return; | ||
1184 | } | ||
1185 | |||
1186 | reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); | ||
1187 | reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); | ||
1188 | |||
1189 | switch (rtlphy->current_chan_bw) { | ||
1190 | case HT_CHANNEL_WIDTH_20: | ||
1191 | reg_bw_opmode |= BW_OPMODE_20MHZ; | ||
1192 | rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); | ||
1193 | break; | ||
1194 | case HT_CHANNEL_WIDTH_20_40: | ||
1195 | reg_bw_opmode &= ~BW_OPMODE_20MHZ; | ||
1196 | rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); | ||
1197 | reg_prsr_rsc = | ||
1198 | (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5); | ||
1199 | rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); | ||
1200 | break; | ||
1201 | default: | ||
1202 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1203 | "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); | ||
1204 | break; | ||
1205 | } | ||
1206 | |||
1207 | switch (rtlphy->current_chan_bw) { | ||
1208 | case HT_CHANNEL_WIDTH_20: | ||
1209 | rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); | ||
1210 | rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); | ||
1211 | /* rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1);*/ | ||
1212 | break; | ||
1213 | case HT_CHANNEL_WIDTH_20_40: | ||
1214 | rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); | ||
1215 | rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); | ||
1216 | |||
1217 | rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, | ||
1218 | (mac->cur_40_prime_sc >> 1)); | ||
1219 | rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); | ||
1220 | /*rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0);*/ | ||
1221 | |||
1222 | rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), | ||
1223 | (mac->cur_40_prime_sc == | ||
1224 | HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); | ||
1225 | break; | ||
1226 | default: | ||
1227 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1228 | "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); | ||
1229 | break; | ||
1230 | } | ||
1231 | rtl88e_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); | ||
1232 | rtlphy->set_bwmode_inprogress = false; | ||
1233 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, "\n"); | ||
1234 | } | ||
1235 | |||
1236 | void rtl88e_phy_set_bw_mode(struct ieee80211_hw *hw, | ||
1237 | enum nl80211_channel_type ch_type) | ||
1238 | { | ||
1239 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1240 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1241 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1242 | u8 tmp_bw = rtlphy->current_chan_bw; | ||
1243 | |||
1244 | if (rtlphy->set_bwmode_inprogress) | ||
1245 | return; | ||
1246 | rtlphy->set_bwmode_inprogress = true; | ||
1247 | if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { | ||
1248 | rtl88e_phy_set_bw_mode_callback(hw); | ||
1249 | } else { | ||
1250 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
1251 | "FALSE driver sleep or unload\n"); | ||
1252 | rtlphy->set_bwmode_inprogress = false; | ||
1253 | rtlphy->current_chan_bw = tmp_bw; | ||
1254 | } | ||
1255 | } | ||
1256 | |||
1257 | void rtl88e_phy_sw_chnl_callback(struct ieee80211_hw *hw) | ||
1258 | { | ||
1259 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1260 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1261 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1262 | u32 delay; | ||
1263 | |||
1264 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, | ||
1265 | "switch to channel%d\n", rtlphy->current_channel); | ||
1266 | if (is_hal_stop(rtlhal)) | ||
1267 | return; | ||
1268 | do { | ||
1269 | if (!rtlphy->sw_chnl_inprogress) | ||
1270 | break; | ||
1271 | if (!chnl_step_by_step(hw, rtlphy->current_channel, | ||
1272 | &rtlphy->sw_chnl_stage, | ||
1273 | &rtlphy->sw_chnl_step, &delay)) { | ||
1274 | if (delay > 0) | ||
1275 | mdelay(delay); | ||
1276 | else | ||
1277 | continue; | ||
1278 | } else { | ||
1279 | rtlphy->sw_chnl_inprogress = false; | ||
1280 | } | ||
1281 | break; | ||
1282 | } while (true); | ||
1283 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n"); | ||
1284 | } | ||
1285 | |||
1286 | u8 rtl88e_phy_sw_chnl(struct ieee80211_hw *hw) | ||
1287 | { | ||
1288 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1289 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1290 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1291 | |||
1292 | if (rtlphy->sw_chnl_inprogress) | ||
1293 | return 0; | ||
1294 | if (rtlphy->set_bwmode_inprogress) | ||
1295 | return 0; | ||
1296 | RT_ASSERT((rtlphy->current_channel <= 14), | ||
1297 | "WIRELESS_MODE_G but channel>14"); | ||
1298 | rtlphy->sw_chnl_inprogress = true; | ||
1299 | rtlphy->sw_chnl_stage = 0; | ||
1300 | rtlphy->sw_chnl_step = 0; | ||
1301 | if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { | ||
1302 | rtl88e_phy_sw_chnl_callback(hw); | ||
1303 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, | ||
1304 | "sw_chnl_inprogress false schdule workitem current channel %d\n", | ||
1305 | rtlphy->current_channel); | ||
1306 | rtlphy->sw_chnl_inprogress = false; | ||
1307 | } else { | ||
1308 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, | ||
1309 | "sw_chnl_inprogress false driver sleep or unload\n"); | ||
1310 | rtlphy->sw_chnl_inprogress = false; | ||
1311 | } | ||
1312 | return 1; | ||
1313 | } | ||
1314 | |||
1315 | static u8 _rtl88e_phy_path_a_iqk(struct ieee80211_hw *hw, bool config_pathb) | ||
1316 | { | ||
1317 | u32 reg_eac, reg_e94, reg_e9c; | ||
1318 | u8 result = 0x00; | ||
1319 | |||
1320 | rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c1c); | ||
1321 | rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x30008c1c); | ||
1322 | rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x8214032a); | ||
1323 | rtl_set_bbreg(hw, 0xe3c, MASKDWORD, 0x28160000); | ||
1324 | |||
1325 | rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x00462911); | ||
1326 | rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf9000000); | ||
1327 | rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf8000000); | ||
1328 | |||
1329 | mdelay(IQK_DELAY_TIME); | ||
1330 | |||
1331 | reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); | ||
1332 | reg_e94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD); | ||
1333 | reg_e9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD); | ||
1334 | |||
1335 | if (!(reg_eac & BIT(28)) && | ||
1336 | (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && | ||
1337 | (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) | ||
1338 | result |= 0x01; | ||
1339 | return result; | ||
1340 | } | ||
1341 | |||
1342 | static u8 _rtl88e_phy_path_b_iqk(struct ieee80211_hw *hw) | ||
1343 | { | ||
1344 | u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc; | ||
1345 | u8 result = 0x00; | ||
1346 | |||
1347 | rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000002); | ||
1348 | rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000000); | ||
1349 | mdelay(IQK_DELAY_TIME); | ||
1350 | reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); | ||
1351 | reg_eb4 = rtl_get_bbreg(hw, 0xeb4, MASKDWORD); | ||
1352 | reg_ebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD); | ||
1353 | reg_ec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD); | ||
1354 | reg_ecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD); | ||
1355 | |||
1356 | if (!(reg_eac & BIT(31)) && | ||
1357 | (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) && | ||
1358 | (((reg_ebc & 0x03FF0000) >> 16) != 0x42)) | ||
1359 | result |= 0x01; | ||
1360 | else | ||
1361 | return result; | ||
1362 | if (!(reg_eac & BIT(30)) && | ||
1363 | (((reg_ec4 & 0x03FF0000) >> 16) != 0x132) && | ||
1364 | (((reg_ecc & 0x03FF0000) >> 16) != 0x36)) | ||
1365 | result |= 0x02; | ||
1366 | return result; | ||
1367 | } | ||
1368 | |||
1369 | static u8 _rtl88e_phy_path_a_rx_iqk(struct ieee80211_hw *hw, bool config_pathb) | ||
1370 | { | ||
1371 | u32 reg_eac, reg_e94, reg_e9c, reg_ea4, u32temp; | ||
1372 | u8 result = 0x00; | ||
1373 | int jj = RF90_PATH_A; | ||
1374 | |||
1375 | /*Get TXIMR Setting*/ | ||
1376 | /*Modify RX IQK mode table*/ | ||
1377 | rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); | ||
1378 | rtl_set_rfreg(hw, jj, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0); | ||
1379 | rtl_set_rfreg(hw, jj, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000); | ||
1380 | rtl_set_rfreg(hw, jj, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0000f); | ||
1381 | rtl_set_rfreg(hw, jj, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf117b); | ||
1382 | rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); | ||
1383 | |||
1384 | /*IQK Setting*/ | ||
1385 | rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00); | ||
1386 | rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x81004800); | ||
1387 | |||
1388 | /*path a IQK setting*/ | ||
1389 | rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x10008c1c); | ||
1390 | rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x30008c1c); | ||
1391 | rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82160804); | ||
1392 | rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28160000); | ||
1393 | |||
1394 | /*LO calibration Setting*/ | ||
1395 | rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a911); | ||
1396 | /*one shot, path A LOK & iqk*/ | ||
1397 | rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000); | ||
1398 | rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); | ||
1399 | |||
1400 | mdelay(IQK_DELAY_TIME); | ||
1401 | |||
1402 | reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); | ||
1403 | reg_e94 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_A, MASKDWORD); | ||
1404 | reg_e9c = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, MASKDWORD); | ||
1405 | |||
1406 | |||
1407 | if (!(reg_eac & BIT(28)) && | ||
1408 | (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && | ||
1409 | (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) | ||
1410 | result |= 0x01; | ||
1411 | else | ||
1412 | return result; | ||
1413 | |||
1414 | u32temp = 0x80007C00 | (reg_e94&0x3FF0000) | | ||
1415 | ((reg_e9c&0x3FF0000) >> 16); | ||
1416 | rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, u32temp); | ||
1417 | /*RX IQK*/ | ||
1418 | /*Modify RX IQK mode table*/ | ||
1419 | rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); | ||
1420 | rtl_set_rfreg(hw, jj, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0); | ||
1421 | rtl_set_rfreg(hw, jj, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000); | ||
1422 | rtl_set_rfreg(hw, jj, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0000f); | ||
1423 | rtl_set_rfreg(hw, jj, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf7ffa); | ||
1424 | rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); | ||
1425 | |||
1426 | /*IQK Setting*/ | ||
1427 | rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); | ||
1428 | |||
1429 | /*path a IQK setting*/ | ||
1430 | rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x30008c1c); | ||
1431 | rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x10008c1c); | ||
1432 | rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82160c05); | ||
1433 | rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28160c05); | ||
1434 | |||
1435 | /*LO calibration Setting*/ | ||
1436 | rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a911); | ||
1437 | /*one shot, path A LOK & iqk*/ | ||
1438 | rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000); | ||
1439 | rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); | ||
1440 | |||
1441 | mdelay(IQK_DELAY_TIME); | ||
1442 | |||
1443 | reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); | ||
1444 | reg_e94 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_A, MASKDWORD); | ||
1445 | reg_e9c = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, MASKDWORD); | ||
1446 | reg_ea4 = rtl_get_bbreg(hw, RRX_POWER_BEFORE_IQK_A_2, MASKDWORD); | ||
1447 | |||
1448 | if (!(reg_eac & BIT(27)) && | ||
1449 | (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) && | ||
1450 | (((reg_eac & 0x03FF0000) >> 16) != 0x36)) | ||
1451 | result |= 0x02; | ||
1452 | return result; | ||
1453 | } | ||
1454 | |||
1455 | static void fill_iqk(struct ieee80211_hw *hw, bool iqk_ok, long result[][8], | ||
1456 | u8 final, bool btxonly) | ||
1457 | { | ||
1458 | u32 oldval_0, x, tx0_a, reg; | ||
1459 | long y, tx0_c; | ||
1460 | |||
1461 | if (final == 0xFF) { | ||
1462 | return; | ||
1463 | } else if (iqk_ok) { | ||
1464 | oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBAL, | ||
1465 | MASKDWORD) >> 22) & 0x3FF; | ||
1466 | x = result[final][0]; | ||
1467 | if ((x & 0x00000200) != 0) | ||
1468 | x = x | 0xFFFFFC00; | ||
1469 | tx0_a = (x * oldval_0) >> 8; | ||
1470 | rtl_set_bbreg(hw, ROFDM0_XATXIQIMBAL, 0x3FF, tx0_a); | ||
1471 | rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(31), | ||
1472 | ((x * oldval_0 >> 7) & 0x1)); | ||
1473 | y = result[final][1]; | ||
1474 | if ((y & 0x00000200) != 0) | ||
1475 | y |= 0xFFFFFC00; | ||
1476 | tx0_c = (y * oldval_0) >> 8; | ||
1477 | rtl_set_bbreg(hw, ROFDM0_XCTXAFE, 0xF0000000, | ||
1478 | ((tx0_c & 0x3C0) >> 6)); | ||
1479 | rtl_set_bbreg(hw, ROFDM0_XATXIQIMBAL, 0x003F0000, | ||
1480 | (tx0_c & 0x3F)); | ||
1481 | rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(29), | ||
1482 | ((y * oldval_0 >> 7) & 0x1)); | ||
1483 | if (btxonly) | ||
1484 | return; | ||
1485 | reg = result[final][2]; | ||
1486 | rtl_set_bbreg(hw, ROFDM0_XARXIQIMBAL, 0x3FF, reg); | ||
1487 | reg = result[final][3] & 0x3F; | ||
1488 | rtl_set_bbreg(hw, ROFDM0_XARXIQIMBAL, 0xFC00, reg); | ||
1489 | reg = (result[final][3] >> 6) & 0xF; | ||
1490 | rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg); | ||
1491 | } | ||
1492 | } | ||
1493 | |||
1494 | static void save_adda_reg(struct ieee80211_hw *hw, | ||
1495 | const u32 *addareg, u32 *backup, | ||
1496 | u32 registernum) | ||
1497 | { | ||
1498 | u32 i; | ||
1499 | |||
1500 | for (i = 0; i < registernum; i++) | ||
1501 | backup[i] = rtl_get_bbreg(hw, addareg[i], MASKDWORD); | ||
1502 | } | ||
1503 | |||
1504 | static void save_mac_reg(struct ieee80211_hw *hw, const u32 *macreg, | ||
1505 | u32 *macbackup) | ||
1506 | { | ||
1507 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1508 | u32 i; | ||
1509 | |||
1510 | for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) | ||
1511 | macbackup[i] = rtl_read_byte(rtlpriv, macreg[i]); | ||
1512 | macbackup[i] = rtl_read_dword(rtlpriv, macreg[i]); | ||
1513 | } | ||
1514 | |||
1515 | static void reload_adda(struct ieee80211_hw *hw, const u32 *addareg, | ||
1516 | u32 *backup, u32 reg_num) | ||
1517 | { | ||
1518 | u32 i; | ||
1519 | |||
1520 | for (i = 0; i < reg_num; i++) | ||
1521 | rtl_set_bbreg(hw, addareg[i], MASKDWORD, backup[i]); | ||
1522 | } | ||
1523 | |||
1524 | static void reload_mac(struct ieee80211_hw *hw, const u32 *macreg, | ||
1525 | u32 *macbackup) | ||
1526 | { | ||
1527 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1528 | u32 i; | ||
1529 | |||
1530 | for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) | ||
1531 | rtl_write_byte(rtlpriv, macreg[i], (u8) macbackup[i]); | ||
1532 | rtl_write_dword(rtlpriv, macreg[i], macbackup[i]); | ||
1533 | } | ||
1534 | |||
1535 | static void _rtl88e_phy_path_adda_on(struct ieee80211_hw *hw, | ||
1536 | const u32 *addareg, bool is_patha_on, | ||
1537 | bool is2t) | ||
1538 | { | ||
1539 | u32 pathon; | ||
1540 | u32 i; | ||
1541 | |||
1542 | pathon = is_patha_on ? 0x04db25a4 : 0x0b1b25a4; | ||
1543 | if (false == is2t) { | ||
1544 | pathon = 0x0bdb25a0; | ||
1545 | rtl_set_bbreg(hw, addareg[0], MASKDWORD, 0x0b1b25a0); | ||
1546 | } else { | ||
1547 | rtl_set_bbreg(hw, addareg[0], MASKDWORD, pathon); | ||
1548 | } | ||
1549 | |||
1550 | for (i = 1; i < IQK_ADDA_REG_NUM; i++) | ||
1551 | rtl_set_bbreg(hw, addareg[i], MASKDWORD, pathon); | ||
1552 | } | ||
1553 | |||
1554 | static void _rtl88e_phy_mac_setting_calibration(struct ieee80211_hw *hw, | ||
1555 | const u32 *macreg, | ||
1556 | u32 *macbackup) | ||
1557 | { | ||
1558 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1559 | u32 i = 0; | ||
1560 | |||
1561 | rtl_write_byte(rtlpriv, macreg[i], 0x3F); | ||
1562 | |||
1563 | for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++) | ||
1564 | rtl_write_byte(rtlpriv, macreg[i], | ||
1565 | (u8) (macbackup[i] & (~BIT(3)))); | ||
1566 | rtl_write_byte(rtlpriv, macreg[i], (u8) (macbackup[i] & (~BIT(5)))); | ||
1567 | } | ||
1568 | |||
1569 | static void _rtl88e_phy_path_a_standby(struct ieee80211_hw *hw) | ||
1570 | { | ||
1571 | rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x0); | ||
1572 | rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000); | ||
1573 | rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); | ||
1574 | } | ||
1575 | |||
1576 | static void _rtl88e_phy_pi_mode_switch(struct ieee80211_hw *hw, bool pi_mode) | ||
1577 | { | ||
1578 | u32 mode; | ||
1579 | |||
1580 | mode = pi_mode ? 0x01000100 : 0x01000000; | ||
1581 | rtl_set_bbreg(hw, 0x820, MASKDWORD, mode); | ||
1582 | rtl_set_bbreg(hw, 0x828, MASKDWORD, mode); | ||
1583 | } | ||
1584 | |||
1585 | static bool sim_comp(struct ieee80211_hw *hw, long result[][8], u8 c1, u8 c2) | ||
1586 | { | ||
1587 | u32 i, j, diff, bitmap, bound; | ||
1588 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1589 | |||
1590 | u8 final[2] = {0xFF, 0xFF}; | ||
1591 | bool bresult = true, is2t = IS_92C_SERIAL(rtlhal->version); | ||
1592 | |||
1593 | if (is2t) | ||
1594 | bound = 8; | ||
1595 | else | ||
1596 | bound = 4; | ||
1597 | |||
1598 | bitmap = 0; | ||
1599 | |||
1600 | for (i = 0; i < bound; i++) { | ||
1601 | diff = (result[c1][i] > result[c2][i]) ? | ||
1602 | (result[c1][i] - result[c2][i]) : | ||
1603 | (result[c2][i] - result[c1][i]); | ||
1604 | |||
1605 | if (diff > MAX_TOLERANCE) { | ||
1606 | if ((i == 2 || i == 6) && !bitmap) { | ||
1607 | if (result[c1][i] + result[c1][i + 1] == 0) | ||
1608 | final[(i / 4)] = c2; | ||
1609 | else if (result[c2][i] + result[c2][i + 1] == 0) | ||
1610 | final[(i / 4)] = c1; | ||
1611 | else | ||
1612 | bitmap = bitmap | (1 << i); | ||
1613 | } else { | ||
1614 | bitmap = bitmap | (1 << i); | ||
1615 | } | ||
1616 | } | ||
1617 | } | ||
1618 | |||
1619 | if (bitmap == 0) { | ||
1620 | for (i = 0; i < (bound / 4); i++) { | ||
1621 | if (final[i] != 0xFF) { | ||
1622 | for (j = i * 4; j < (i + 1) * 4 - 2; j++) | ||
1623 | result[3][j] = result[final[i]][j]; | ||
1624 | bresult = false; | ||
1625 | } | ||
1626 | } | ||
1627 | return bresult; | ||
1628 | } else if (!(bitmap & 0x0F)) { | ||
1629 | for (i = 0; i < 4; i++) | ||
1630 | result[3][i] = result[c1][i]; | ||
1631 | return false; | ||
1632 | } else if (!(bitmap & 0xF0) && is2t) { | ||
1633 | for (i = 4; i < 8; i++) | ||
1634 | result[3][i] = result[c1][i]; | ||
1635 | return false; | ||
1636 | } else { | ||
1637 | return false; | ||
1638 | } | ||
1639 | } | ||
1640 | |||
1641 | static void _rtl88e_phy_iq_calibrate(struct ieee80211_hw *hw, | ||
1642 | long result[][8], u8 t, bool is2t) | ||
1643 | { | ||
1644 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1645 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1646 | u32 i; | ||
1647 | u8 patha_ok, pathb_ok; | ||
1648 | const u32 adda_reg[IQK_ADDA_REG_NUM] = { | ||
1649 | 0x85c, 0xe6c, 0xe70, 0xe74, | ||
1650 | 0xe78, 0xe7c, 0xe80, 0xe84, | ||
1651 | 0xe88, 0xe8c, 0xed0, 0xed4, | ||
1652 | 0xed8, 0xedc, 0xee0, 0xeec | ||
1653 | }; | ||
1654 | const u32 iqk_mac_reg[IQK_MAC_REG_NUM] = { | ||
1655 | 0x522, 0x550, 0x551, 0x040 | ||
1656 | }; | ||
1657 | const u32 iqk_bb_reg[IQK_BB_REG_NUM] = { | ||
1658 | ROFDM0_TRXPATHENABLE, ROFDM0_TRMUXPAR, RFPGA0_XCD_RFINTERFACESW, | ||
1659 | 0xb68, 0xb6c, 0x870, 0x860, 0x864, 0x800 | ||
1660 | }; | ||
1661 | const u32 retrycount = 2; | ||
1662 | |||
1663 | if (t == 0) { | ||
1664 | save_adda_reg(hw, adda_reg, rtlphy->adda_backup, 16); | ||
1665 | save_mac_reg(hw, iqk_mac_reg, rtlphy->iqk_mac_backup); | ||
1666 | save_adda_reg(hw, iqk_bb_reg, rtlphy->iqk_bb_backup, | ||
1667 | IQK_BB_REG_NUM); | ||
1668 | } | ||
1669 | _rtl88e_phy_path_adda_on(hw, adda_reg, true, is2t); | ||
1670 | if (t == 0) { | ||
1671 | rtlphy->rfpi_enable = (u8) rtl_get_bbreg(hw, | ||
1672 | RFPGA0_XA_HSSIPARAMETER1, BIT(8)); | ||
1673 | } | ||
1674 | |||
1675 | if (!rtlphy->rfpi_enable) | ||
1676 | _rtl88e_phy_pi_mode_switch(hw, true); | ||
1677 | /*BB Setting*/ | ||
1678 | rtl_set_bbreg(hw, 0x800, BIT(24), 0x00); | ||
1679 | rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600); | ||
1680 | rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4); | ||
1681 | rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000); | ||
1682 | |||
1683 | rtl_set_bbreg(hw, 0x870, BIT(10), 0x01); | ||
1684 | rtl_set_bbreg(hw, 0x870, BIT(26), 0x01); | ||
1685 | rtl_set_bbreg(hw, 0x860, BIT(10), 0x00); | ||
1686 | rtl_set_bbreg(hw, 0x864, BIT(10), 0x00); | ||
1687 | |||
1688 | if (is2t) { | ||
1689 | rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000); | ||
1690 | rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00010000); | ||
1691 | } | ||
1692 | _rtl88e_phy_mac_setting_calibration(hw, iqk_mac_reg, | ||
1693 | rtlphy->iqk_mac_backup); | ||
1694 | rtl_set_bbreg(hw, 0xb68, MASKDWORD, 0x0f600000); | ||
1695 | if (is2t) | ||
1696 | rtl_set_bbreg(hw, 0xb6c, MASKDWORD, 0x0f600000); | ||
1697 | |||
1698 | rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); | ||
1699 | rtl_set_bbreg(hw, 0xe40, MASKDWORD, 0x01007c00); | ||
1700 | rtl_set_bbreg(hw, 0xe44, MASKDWORD, 0x81004800); | ||
1701 | for (i = 0; i < retrycount; i++) { | ||
1702 | patha_ok = _rtl88e_phy_path_a_iqk(hw, is2t); | ||
1703 | if (patha_ok == 0x01) { | ||
1704 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1705 | "Path A Tx IQK Success!!\n"); | ||
1706 | result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) & | ||
1707 | 0x3FF0000) >> 16; | ||
1708 | result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & | ||
1709 | 0x3FF0000) >> 16; | ||
1710 | break; | ||
1711 | } | ||
1712 | } | ||
1713 | |||
1714 | for (i = 0; i < retrycount; i++) { | ||
1715 | patha_ok = _rtl88e_phy_path_a_rx_iqk(hw, is2t); | ||
1716 | if (patha_ok == 0x03) { | ||
1717 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1718 | "Path A Rx IQK Success!!\n"); | ||
1719 | result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) & | ||
1720 | 0x3FF0000) >> 16; | ||
1721 | result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) & | ||
1722 | 0x3FF0000) >> 16; | ||
1723 | break; | ||
1724 | } else { | ||
1725 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1726 | "Path a RX iqk fail!!!\n"); | ||
1727 | } | ||
1728 | } | ||
1729 | |||
1730 | if (0 == patha_ok) { | ||
1731 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1732 | "Path A IQK Success!!\n"); | ||
1733 | } | ||
1734 | if (is2t) { | ||
1735 | _rtl88e_phy_path_a_standby(hw); | ||
1736 | _rtl88e_phy_path_adda_on(hw, adda_reg, false, is2t); | ||
1737 | for (i = 0; i < retrycount; i++) { | ||
1738 | pathb_ok = _rtl88e_phy_path_b_iqk(hw); | ||
1739 | if (pathb_ok == 0x03) { | ||
1740 | result[t][4] = (rtl_get_bbreg(hw, | ||
1741 | 0xeb4, MASKDWORD) & | ||
1742 | 0x3FF0000) >> 16; | ||
1743 | result[t][5] = | ||
1744 | (rtl_get_bbreg(hw, 0xebc, MASKDWORD) & | ||
1745 | 0x3FF0000) >> 16; | ||
1746 | result[t][6] = | ||
1747 | (rtl_get_bbreg(hw, 0xec4, MASKDWORD) & | ||
1748 | 0x3FF0000) >> 16; | ||
1749 | result[t][7] = | ||
1750 | (rtl_get_bbreg(hw, 0xecc, MASKDWORD) & | ||
1751 | 0x3FF0000) >> 16; | ||
1752 | break; | ||
1753 | } else if (i == (retrycount - 1) && pathb_ok == 0x01) { | ||
1754 | result[t][4] = (rtl_get_bbreg(hw, | ||
1755 | 0xeb4, MASKDWORD) & | ||
1756 | 0x3FF0000) >> 16; | ||
1757 | } | ||
1758 | result[t][5] = (rtl_get_bbreg(hw, 0xebc, MASKDWORD) & | ||
1759 | 0x3FF0000) >> 16; | ||
1760 | } | ||
1761 | } | ||
1762 | |||
1763 | rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0); | ||
1764 | |||
1765 | if (t != 0) { | ||
1766 | if (!rtlphy->rfpi_enable) | ||
1767 | _rtl88e_phy_pi_mode_switch(hw, false); | ||
1768 | reload_adda(hw, adda_reg, rtlphy->adda_backup, 16); | ||
1769 | reload_mac(hw, iqk_mac_reg, rtlphy->iqk_mac_backup); | ||
1770 | reload_adda(hw, iqk_bb_reg, rtlphy->iqk_bb_backup, | ||
1771 | IQK_BB_REG_NUM); | ||
1772 | |||
1773 | rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00032ed3); | ||
1774 | if (is2t) | ||
1775 | rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00032ed3); | ||
1776 | rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x01008c00); | ||
1777 | rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x01008c00); | ||
1778 | } | ||
1779 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "88ee IQK Finish!!\n"); | ||
1780 | } | ||
1781 | |||
1782 | static void _rtl88e_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) | ||
1783 | { | ||
1784 | u8 tmpreg; | ||
1785 | u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal; | ||
1786 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1787 | int jj = RF90_PATH_A; | ||
1788 | int kk = RF90_PATH_B; | ||
1789 | |||
1790 | tmpreg = rtl_read_byte(rtlpriv, 0xd03); | ||
1791 | |||
1792 | if ((tmpreg & 0x70) != 0) | ||
1793 | rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F); | ||
1794 | else | ||
1795 | rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); | ||
1796 | |||
1797 | if ((tmpreg & 0x70) != 0) { | ||
1798 | rf_a_mode = rtl_get_rfreg(hw, jj, 0x00, MASK12BITS); | ||
1799 | |||
1800 | if (is2t) | ||
1801 | rf_b_mode = rtl_get_rfreg(hw, kk, 0x00, | ||
1802 | MASK12BITS); | ||
1803 | |||
1804 | rtl_set_rfreg(hw, jj, 0x00, MASK12BITS, | ||
1805 | (rf_a_mode & 0x8FFFF) | 0x10000); | ||
1806 | |||
1807 | if (is2t) | ||
1808 | rtl_set_rfreg(hw, kk, 0x00, MASK12BITS, | ||
1809 | (rf_b_mode & 0x8FFFF) | 0x10000); | ||
1810 | } | ||
1811 | lc_cal = rtl_get_rfreg(hw, jj, 0x18, MASK12BITS); | ||
1812 | |||
1813 | rtl_set_rfreg(hw, jj, 0x18, MASK12BITS, lc_cal | 0x08000); | ||
1814 | |||
1815 | mdelay(100); | ||
1816 | |||
1817 | if ((tmpreg & 0x70) != 0) { | ||
1818 | rtl_write_byte(rtlpriv, 0xd03, tmpreg); | ||
1819 | rtl_set_rfreg(hw, jj, 0x00, MASK12BITS, rf_a_mode); | ||
1820 | |||
1821 | if (is2t) | ||
1822 | rtl_set_rfreg(hw, kk, 0x00, MASK12BITS, | ||
1823 | rf_b_mode); | ||
1824 | } else { | ||
1825 | rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); | ||
1826 | } | ||
1827 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n"); | ||
1828 | } | ||
1829 | |||
1830 | static void rfpath_switch(struct ieee80211_hw *hw, | ||
1831 | bool bmain, bool is2t) | ||
1832 | { | ||
1833 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1834 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1835 | struct rtl_efuse *fuse = rtl_efuse(rtl_priv(hw)); | ||
1836 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n"); | ||
1837 | |||
1838 | if (is_hal_stop(rtlhal)) { | ||
1839 | u8 u1btmp; | ||
1840 | u1btmp = rtl_read_byte(rtlpriv, REG_LEDCFG0); | ||
1841 | rtl_write_byte(rtlpriv, REG_LEDCFG0, u1btmp | BIT(7)); | ||
1842 | rtl_set_bbreg(hw, rFPGA0_XAB_RFPARAMETER, BIT(13), 0x01); | ||
1843 | } | ||
1844 | if (is2t) { | ||
1845 | if (bmain) | ||
1846 | rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, | ||
1847 | BIT(5) | BIT(6), 0x1); | ||
1848 | else | ||
1849 | rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, | ||
1850 | BIT(5) | BIT(6), 0x2); | ||
1851 | } else { | ||
1852 | rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BIT(8) | BIT(9), 0); | ||
1853 | rtl_set_bbreg(hw, 0x914, MASKLWORD, 0x0201); | ||
1854 | |||
1855 | /* We use the RF definition of MAIN and AUX, left antenna and | ||
1856 | * right antenna repectively. | ||
1857 | * Default output at AUX. | ||
1858 | */ | ||
1859 | if (bmain) { | ||
1860 | rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BIT(14) | | ||
1861 | BIT(13) | BIT(12), 0); | ||
1862 | rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, BIT(5) | | ||
1863 | BIT(4) | BIT(3), 0); | ||
1864 | if (fuse->antenna_div_type == CGCS_RX_HW_ANTDIV) | ||
1865 | rtl_set_bbreg(hw, RCONFIG_RAM64X16, BIT(31), 0); | ||
1866 | } else { | ||
1867 | rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BIT(14) | | ||
1868 | BIT(13) | BIT(12), 1); | ||
1869 | rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, BIT(5) | | ||
1870 | BIT(4) | BIT(3), 1); | ||
1871 | if (fuse->antenna_div_type == CGCS_RX_HW_ANTDIV) | ||
1872 | rtl_set_bbreg(hw, RCONFIG_RAM64X16, BIT(31), 1); | ||
1873 | } | ||
1874 | } | ||
1875 | } | ||
1876 | |||
1877 | #undef IQK_ADDA_REG_NUM | ||
1878 | #undef IQK_DELAY_TIME | ||
1879 | |||
1880 | void rtl88e_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery) | ||
1881 | { | ||
1882 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1883 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1884 | long result[4][8]; | ||
1885 | u8 i, final; | ||
1886 | bool patha_ok; | ||
1887 | long reg_e94, reg_e9c, reg_ea4, reg_eb4, reg_ebc, reg_tmp = 0; | ||
1888 | bool is12simular, is13simular, is23simular; | ||
1889 | u32 iqk_bb_reg[9] = { | ||
1890 | ROFDM0_XARXIQIMBAL, | ||
1891 | ROFDM0_XBRXIQIMBAL, | ||
1892 | ROFDM0_ECCATHRES, | ||
1893 | ROFDM0_AGCRSSITABLE, | ||
1894 | ROFDM0_XATXIQIMBAL, | ||
1895 | ROFDM0_XBTXIQIMBAL, | ||
1896 | ROFDM0_XCTXAFE, | ||
1897 | ROFDM0_XDTXAFE, | ||
1898 | ROFDM0_RXIQEXTANTA | ||
1899 | }; | ||
1900 | |||
1901 | if (recovery) { | ||
1902 | reload_adda(hw, iqk_bb_reg, rtlphy->iqk_bb_backup, 9); | ||
1903 | return; | ||
1904 | } | ||
1905 | |||
1906 | memset(result, 0, 32 * sizeof(long)); | ||
1907 | final = 0xff; | ||
1908 | patha_ok = false; | ||
1909 | is12simular = false; | ||
1910 | is23simular = false; | ||
1911 | is13simular = false; | ||
1912 | for (i = 0; i < 3; i++) { | ||
1913 | if (get_rf_type(rtlphy) == RF_2T2R) | ||
1914 | _rtl88e_phy_iq_calibrate(hw, result, i, true); | ||
1915 | else | ||
1916 | _rtl88e_phy_iq_calibrate(hw, result, i, false); | ||
1917 | if (i == 1) { | ||
1918 | is12simular = sim_comp(hw, result, 0, 1); | ||
1919 | if (is12simular) { | ||
1920 | final = 0; | ||
1921 | break; | ||
1922 | } | ||
1923 | } | ||
1924 | if (i == 2) { | ||
1925 | is13simular = sim_comp(hw, result, 0, 2); | ||
1926 | if (is13simular) { | ||
1927 | final = 0; | ||
1928 | break; | ||
1929 | } | ||
1930 | is23simular = sim_comp(hw, result, 1, 2); | ||
1931 | if (is23simular) { | ||
1932 | final = 1; | ||
1933 | } else { | ||
1934 | for (i = 0; i < 8; i++) | ||
1935 | reg_tmp += result[3][i]; | ||
1936 | |||
1937 | if (reg_tmp != 0) | ||
1938 | final = 3; | ||
1939 | else | ||
1940 | final = 0xFF; | ||
1941 | } | ||
1942 | } | ||
1943 | } | ||
1944 | for (i = 0; i < 4; i++) { | ||
1945 | reg_e94 = result[i][0]; | ||
1946 | reg_e9c = result[i][1]; | ||
1947 | reg_ea4 = result[i][2]; | ||
1948 | reg_eb4 = result[i][4]; | ||
1949 | reg_ebc = result[i][5]; | ||
1950 | } | ||
1951 | if (final != 0xff) { | ||
1952 | reg_e94 = result[final][0]; | ||
1953 | rtlphy->reg_e94 = reg_e94; | ||
1954 | reg_e9c = result[final][1]; | ||
1955 | rtlphy->reg_e9c = reg_e9c; | ||
1956 | reg_ea4 = result[final][2]; | ||
1957 | reg_eb4 = result[final][4]; | ||
1958 | rtlphy->reg_eb4 = reg_eb4; | ||
1959 | reg_ebc = result[final][5]; | ||
1960 | rtlphy->reg_ebc = reg_ebc; | ||
1961 | patha_ok = true; | ||
1962 | } else { | ||
1963 | rtlphy->reg_e94 = 0x100; | ||
1964 | rtlphy->reg_eb4 = 0x100; | ||
1965 | rtlphy->reg_ebc = 0x0; | ||
1966 | rtlphy->reg_e9c = 0x0; | ||
1967 | } | ||
1968 | if (reg_e94 != 0) /*&&(reg_ea4 != 0) */ | ||
1969 | fill_iqk(hw, patha_ok, result, final, (reg_ea4 == 0)); | ||
1970 | if (final != 0xFF) { | ||
1971 | for (i = 0; i < IQK_MATRIX_REG_NUM; i++) | ||
1972 | rtlphy->iqk_matrix[0].value[0][i] = result[final][i]; | ||
1973 | rtlphy->iqk_matrix[0].iqk_done = true; | ||
1974 | } | ||
1975 | save_adda_reg(hw, iqk_bb_reg, rtlphy->iqk_bb_backup, 9); | ||
1976 | } | ||
1977 | |||
1978 | void rtl88e_phy_lc_calibrate(struct ieee80211_hw *hw) | ||
1979 | { | ||
1980 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1981 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1982 | struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); | ||
1983 | bool start_conttx = false, singletone = false; | ||
1984 | u32 timeout = 2000, timecount = 0; | ||
1985 | |||
1986 | if (start_conttx || singletone) | ||
1987 | return; | ||
1988 | |||
1989 | while (rtlpriv->mac80211.act_scanning && timecount < timeout) { | ||
1990 | udelay(50); | ||
1991 | timecount += 50; | ||
1992 | } | ||
1993 | |||
1994 | rtlphy->lck_inprogress = true; | ||
1995 | RTPRINT(rtlpriv, FINIT, INIT_IQK, | ||
1996 | "LCK:Start!!! currentband %x delay %d ms\n", | ||
1997 | rtlhal->current_bandtype, timecount); | ||
1998 | |||
1999 | _rtl88e_phy_lc_calibrate(hw, false); | ||
2000 | |||
2001 | rtlphy->lck_inprogress = false; | ||
2002 | } | ||
2003 | |||
2004 | void rtl88e_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain) | ||
2005 | { | ||
2006 | rfpath_switch(hw, bmain, false); | ||
2007 | } | ||
2008 | |||
2009 | bool rtl88e_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype) | ||
2010 | { | ||
2011 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2012 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
2013 | bool postprocessing = false; | ||
2014 | |||
2015 | RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, | ||
2016 | "-->IO Cmd(%#x), set_io_inprogress(%d)\n", | ||
2017 | iotype, rtlphy->set_io_inprogress); | ||
2018 | do { | ||
2019 | switch (iotype) { | ||
2020 | case IO_CMD_RESUME_DM_BY_SCAN: | ||
2021 | RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, | ||
2022 | "[IO CMD] Resume DM after scan.\n"); | ||
2023 | postprocessing = true; | ||
2024 | break; | ||
2025 | case IO_CMD_PAUSE_DM_BY_SCAN: | ||
2026 | RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, | ||
2027 | "[IO CMD] Pause DM before scan.\n"); | ||
2028 | postprocessing = true; | ||
2029 | break; | ||
2030 | default: | ||
2031 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
2032 | "switch case not processed\n"); | ||
2033 | break; | ||
2034 | } | ||
2035 | } while (false); | ||
2036 | if (postprocessing && !rtlphy->set_io_inprogress) { | ||
2037 | rtlphy->set_io_inprogress = true; | ||
2038 | rtlphy->current_io_type = iotype; | ||
2039 | } else { | ||
2040 | return false; | ||
2041 | } | ||
2042 | rtl88e_phy_set_io(hw); | ||
2043 | RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "IO Type(%#x)\n", iotype); | ||
2044 | return true; | ||
2045 | } | ||
2046 | |||
2047 | static void rtl88ee_phy_set_rf_on(struct ieee80211_hw *hw) | ||
2048 | { | ||
2049 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2050 | |||
2051 | rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); | ||
2052 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); | ||
2053 | /*rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);*/ | ||
2054 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); | ||
2055 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); | ||
2056 | rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); | ||
2057 | } | ||
2058 | |||
2059 | static void _rtl88ee_phy_set_rf_sleep(struct ieee80211_hw *hw) | ||
2060 | { | ||
2061 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2062 | int jj = RF90_PATH_A; | ||
2063 | |||
2064 | rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); | ||
2065 | rtl_set_rfreg(hw, jj, 0x00, RFREG_OFFSET_MASK, 0x00); | ||
2066 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); | ||
2067 | rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); | ||
2068 | } | ||
2069 | |||
2070 | static bool _rtl88ee_phy_set_rf_power_state(struct ieee80211_hw *hw, | ||
2071 | enum rf_pwrstate rfpwr_state) | ||
2072 | { | ||
2073 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2074 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
2075 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
2076 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
2077 | struct rtl8192_tx_ring *ring = NULL; | ||
2078 | bool bresult = true; | ||
2079 | u8 i, queue_id; | ||
2080 | |||
2081 | switch (rfpwr_state) { | ||
2082 | case ERFON:{ | ||
2083 | if ((ppsc->rfpwr_state == ERFOFF) && | ||
2084 | RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { | ||
2085 | bool rtstatus; | ||
2086 | u32 init = 0; | ||
2087 | do { | ||
2088 | init++; | ||
2089 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | ||
2090 | "IPS Set eRf nic enable\n"); | ||
2091 | rtstatus = rtl_ps_enable_nic(hw); | ||
2092 | } while ((rtstatus != true) && (init < 10)); | ||
2093 | RT_CLEAR_PS_LEVEL(ppsc, | ||
2094 | RT_RF_OFF_LEVL_HALT_NIC); | ||
2095 | } else { | ||
2096 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | ||
2097 | "Set ERFON sleeped:%d ms\n", | ||
2098 | jiffies_to_msecs(jiffies - ppsc-> | ||
2099 | last_sleep_jiffies)); | ||
2100 | ppsc->last_awake_jiffies = jiffies; | ||
2101 | rtl88ee_phy_set_rf_on(hw); | ||
2102 | } | ||
2103 | if (mac->link_state == MAC80211_LINKED) | ||
2104 | rtlpriv->cfg->ops->led_control(hw, LED_CTL_LINK); | ||
2105 | else | ||
2106 | rtlpriv->cfg->ops->led_control(hw, LED_CTL_NO_LINK); | ||
2107 | break; } | ||
2108 | case ERFOFF:{ | ||
2109 | for (queue_id = 0, i = 0; | ||
2110 | queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { | ||
2111 | ring = &pcipriv->dev.tx_ring[queue_id]; | ||
2112 | if (skb_queue_len(&ring->queue) == 0) { | ||
2113 | queue_id++; | ||
2114 | continue; | ||
2115 | } else { | ||
2116 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
2117 | "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", | ||
2118 | (i + 1), queue_id, | ||
2119 | skb_queue_len(&ring->queue)); | ||
2120 | |||
2121 | udelay(10); | ||
2122 | i++; | ||
2123 | } | ||
2124 | if (i >= MAX_DOZE_WAITING_TIMES_9x) { | ||
2125 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
2126 | "\n ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", | ||
2127 | MAX_DOZE_WAITING_TIMES_9x, | ||
2128 | queue_id, | ||
2129 | skb_queue_len(&ring->queue)); | ||
2130 | break; | ||
2131 | } | ||
2132 | } | ||
2133 | if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { | ||
2134 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | ||
2135 | "IPS Set eRf nic disable\n"); | ||
2136 | rtl_ps_disable_nic(hw); | ||
2137 | RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); | ||
2138 | } else { | ||
2139 | if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) { | ||
2140 | rtlpriv->cfg->ops->led_control(hw, | ||
2141 | LED_CTL_NO_LINK); | ||
2142 | } else { | ||
2143 | rtlpriv->cfg->ops->led_control(hw, | ||
2144 | LED_CTL_POWER_OFF); | ||
2145 | } | ||
2146 | } | ||
2147 | break; } | ||
2148 | case ERFSLEEP:{ | ||
2149 | if (ppsc->rfpwr_state == ERFOFF) | ||
2150 | break; | ||
2151 | for (queue_id = 0, i = 0; | ||
2152 | queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { | ||
2153 | ring = &pcipriv->dev.tx_ring[queue_id]; | ||
2154 | if (skb_queue_len(&ring->queue) == 0) { | ||
2155 | queue_id++; | ||
2156 | continue; | ||
2157 | } else { | ||
2158 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
2159 | "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", | ||
2160 | (i + 1), queue_id, | ||
2161 | skb_queue_len(&ring->queue)); | ||
2162 | |||
2163 | udelay(10); | ||
2164 | i++; | ||
2165 | } | ||
2166 | if (i >= MAX_DOZE_WAITING_TIMES_9x) { | ||
2167 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
2168 | "\n ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", | ||
2169 | MAX_DOZE_WAITING_TIMES_9x, | ||
2170 | queue_id, | ||
2171 | skb_queue_len(&ring->queue)); | ||
2172 | break; | ||
2173 | } | ||
2174 | } | ||
2175 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | ||
2176 | "Set ERFSLEEP awaked:%d ms\n", | ||
2177 | jiffies_to_msecs(jiffies - ppsc->last_awake_jiffies)); | ||
2178 | ppsc->last_sleep_jiffies = jiffies; | ||
2179 | _rtl88ee_phy_set_rf_sleep(hw); | ||
2180 | break; } | ||
2181 | default: | ||
2182 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
2183 | "switch case not processed\n"); | ||
2184 | bresult = false; | ||
2185 | break; | ||
2186 | } | ||
2187 | if (bresult) | ||
2188 | ppsc->rfpwr_state = rfpwr_state; | ||
2189 | return bresult; | ||
2190 | } | ||
2191 | |||
2192 | bool rtl88e_phy_set_rf_power_state(struct ieee80211_hw *hw, | ||
2193 | enum rf_pwrstate rfpwr_state) | ||
2194 | { | ||
2195 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
2196 | bool bresult; | ||
2197 | |||
2198 | if (rfpwr_state == ppsc->rfpwr_state) | ||
2199 | return false; | ||
2200 | bresult = _rtl88ee_phy_set_rf_power_state(hw, rfpwr_state); | ||
2201 | return bresult; | ||
2202 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h b/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h new file mode 100644 index 000000000000..f1acd6d27e44 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h | |||
@@ -0,0 +1,236 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #ifndef __RTL92C_PHY_H__ | ||
31 | #define __RTL92C_PHY_H__ | ||
32 | |||
33 | /*It must always set to 4, otherwise read efuse table secquence will be wrong.*/ | ||
34 | #define MAX_TX_COUNT 4 | ||
35 | |||
36 | #define MAX_PRECMD_CNT 16 | ||
37 | #define MAX_RFDEPENDCMD_CNT 16 | ||
38 | #define MAX_POSTCMD_CNT 16 | ||
39 | |||
40 | #define MAX_DOZE_WAITING_TIMES_9x 64 | ||
41 | |||
42 | #define RT_CANNOT_IO(hw) false | ||
43 | #define HIGHPOWER_RADIOA_ARRAYLEN 22 | ||
44 | |||
45 | #define IQK_ADDA_REG_NUM 16 | ||
46 | #define IQK_BB_REG_NUM 9 | ||
47 | #define MAX_TOLERANCE 5 | ||
48 | #define IQK_DELAY_TIME 10 | ||
49 | #define IDX_MAP 15 | ||
50 | |||
51 | #define APK_BB_REG_NUM 5 | ||
52 | #define APK_AFE_REG_NUM 16 | ||
53 | #define APK_CURVE_REG_NUM 4 | ||
54 | #define PATH_NUM 2 | ||
55 | |||
56 | #define LOOP_LIMIT 5 | ||
57 | #define MAX_STALL_TIME 50 | ||
58 | #define ANTENNADIVERSITYVALUE 0x80 | ||
59 | #define MAX_TXPWR_IDX_NMODE_92S 63 | ||
60 | #define RESET_CNT_LIMIT 3 | ||
61 | |||
62 | #define IQK_ADDA_REG_NUM 16 | ||
63 | #define IQK_MAC_REG_NUM 4 | ||
64 | |||
65 | #define RF6052_MAX_PATH 2 | ||
66 | |||
67 | #define CT_OFFSET_MAC_ADDR 0X16 | ||
68 | |||
69 | #define CT_OFFSET_CCK_TX_PWR_IDX 0x5A | ||
70 | #define CT_OFFSET_HT401S_TX_PWR_IDX 0x60 | ||
71 | #define CT_OFFSET_HT402S_TX_PWR_IDX_DIFF 0x66 | ||
72 | #define CT_OFFSET_HT20_TX_PWR_IDX_DIFF 0x69 | ||
73 | #define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF 0x6C | ||
74 | |||
75 | #define CT_OFFSET_HT40_MAX_PWR_OFFSET 0x6F | ||
76 | #define CT_OFFSET_HT20_MAX_PWR_OFFSET 0x72 | ||
77 | |||
78 | #define CT_OFFSET_CHANNEL_PLAH 0x75 | ||
79 | #define CT_OFFSET_THERMAL_METER 0x78 | ||
80 | #define CT_OFFSET_RF_OPTION 0x79 | ||
81 | #define CT_OFFSET_VERSION 0x7E | ||
82 | #define CT_OFFSET_CUSTOMER_ID 0x7F | ||
83 | |||
84 | #define RTL92C_MAX_PATH_NUM 2 | ||
85 | |||
86 | enum swchnlcmd_id { | ||
87 | CMDID_END, | ||
88 | CMDID_SET_TXPOWEROWER_LEVEL, | ||
89 | CMDID_BBREGWRITE10, | ||
90 | CMDID_WRITEPORT_ULONG, | ||
91 | CMDID_WRITEPORT_USHORT, | ||
92 | CMDID_WRITEPORT_UCHAR, | ||
93 | CMDID_RF_WRITEREG, | ||
94 | }; | ||
95 | |||
96 | struct swchnlcmd { | ||
97 | enum swchnlcmd_id cmdid; | ||
98 | u32 para1; | ||
99 | u32 para2; | ||
100 | u32 msdelay; | ||
101 | }; | ||
102 | |||
103 | enum hw90_block_e { | ||
104 | HW90_BLOCK_MAC = 0, | ||
105 | HW90_BLOCK_PHY0 = 1, | ||
106 | HW90_BLOCK_PHY1 = 2, | ||
107 | HW90_BLOCK_RF = 3, | ||
108 | HW90_BLOCK_MAXIMUM = 4, | ||
109 | }; | ||
110 | |||
111 | enum baseband_config_type { | ||
112 | BASEBAND_CONFIG_PHY_REG = 0, | ||
113 | BASEBAND_CONFIG_AGC_TAB = 1, | ||
114 | }; | ||
115 | |||
116 | enum ra_offset_area { | ||
117 | RA_OFFSET_LEGACY_OFDM1, | ||
118 | RA_OFFSET_LEGACY_OFDM2, | ||
119 | RA_OFFSET_HT_OFDM1, | ||
120 | RA_OFFSET_HT_OFDM2, | ||
121 | RA_OFFSET_HT_OFDM3, | ||
122 | RA_OFFSET_HT_OFDM4, | ||
123 | RA_OFFSET_HT_CCK, | ||
124 | }; | ||
125 | |||
126 | enum antenna_path { | ||
127 | ANTENNA_NONE, | ||
128 | ANTENNA_D, | ||
129 | ANTENNA_C, | ||
130 | ANTENNA_CD, | ||
131 | ANTENNA_B, | ||
132 | ANTENNA_BD, | ||
133 | ANTENNA_BC, | ||
134 | ANTENNA_BCD, | ||
135 | ANTENNA_A, | ||
136 | ANTENNA_AD, | ||
137 | ANTENNA_AC, | ||
138 | ANTENNA_ACD, | ||
139 | ANTENNA_AB, | ||
140 | ANTENNA_ABD, | ||
141 | ANTENNA_ABC, | ||
142 | ANTENNA_ABCD | ||
143 | }; | ||
144 | |||
145 | struct r_antenna_select_ofdm { | ||
146 | u32 r_tx_antenna:4; | ||
147 | u32 r_ant_l:4; | ||
148 | u32 r_ant_non_ht:4; | ||
149 | u32 r_ant_ht1:4; | ||
150 | u32 r_ant_ht2:4; | ||
151 | u32 r_ant_ht_s1:4; | ||
152 | u32 r_ant_non_ht_s1:4; | ||
153 | u32 ofdm_txsc:2; | ||
154 | u32 reserved:2; | ||
155 | }; | ||
156 | |||
157 | struct r_antenna_select_cck { | ||
158 | u8 r_cckrx_enable_2:2; | ||
159 | u8 r_cckrx_enable:2; | ||
160 | u8 r_ccktx_enable:4; | ||
161 | }; | ||
162 | |||
163 | |||
164 | struct efuse_contents { | ||
165 | u8 mac_addr[ETH_ALEN]; | ||
166 | u8 cck_tx_power_idx[6]; | ||
167 | u8 ht40_1s_tx_power_idx[6]; | ||
168 | u8 ht40_2s_tx_power_idx_diff[3]; | ||
169 | u8 ht20_tx_power_idx_diff[3]; | ||
170 | u8 ofdm_tx_power_idx_diff[3]; | ||
171 | u8 ht40_max_power_offset[3]; | ||
172 | u8 ht20_max_power_offset[3]; | ||
173 | u8 channel_plan; | ||
174 | u8 thermal_meter; | ||
175 | u8 rf_option[5]; | ||
176 | u8 version; | ||
177 | u8 oem_id; | ||
178 | u8 regulatory; | ||
179 | }; | ||
180 | |||
181 | struct tx_power_struct { | ||
182 | u8 cck[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; | ||
183 | u8 ht40_1s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; | ||
184 | u8 ht40_2s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; | ||
185 | u8 ht20_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; | ||
186 | u8 legacy_ht_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; | ||
187 | u8 legacy_ht_txpowerdiff; | ||
188 | u8 groupht20[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; | ||
189 | u8 groupht40[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; | ||
190 | u8 pwrgroup_cnt; | ||
191 | u32 mcs_original_offset[4][16]; | ||
192 | }; | ||
193 | |||
194 | enum _ANT_DIV_TYPE { | ||
195 | NO_ANTDIV = 0xFF, | ||
196 | CG_TRX_HW_ANTDIV = 0x01, | ||
197 | CGCS_RX_HW_ANTDIV = 0x02, | ||
198 | FIXED_HW_ANTDIV = 0x03, | ||
199 | CG_TRX_SMART_ANTDIV = 0x04, | ||
200 | CGCS_RX_SW_ANTDIV = 0x05, | ||
201 | }; | ||
202 | |||
203 | extern u32 rtl88e_phy_query_bb_reg(struct ieee80211_hw *hw, | ||
204 | u32 regaddr, u32 bitmask); | ||
205 | extern void rtl88e_phy_set_bb_reg(struct ieee80211_hw *hw, | ||
206 | u32 regaddr, u32 bitmask, u32 data); | ||
207 | extern u32 rtl88e_phy_query_rf_reg(struct ieee80211_hw *hw, | ||
208 | enum radio_path rfpath, u32 regaddr, | ||
209 | u32 bitmask); | ||
210 | extern void rtl88e_phy_set_rf_reg(struct ieee80211_hw *hw, | ||
211 | enum radio_path rfpath, u32 regaddr, | ||
212 | u32 bitmask, u32 data); | ||
213 | extern bool rtl88e_phy_mac_config(struct ieee80211_hw *hw); | ||
214 | extern bool rtl88e_phy_bb_config(struct ieee80211_hw *hw); | ||
215 | extern bool rtl88e_phy_rf_config(struct ieee80211_hw *hw); | ||
216 | extern void rtl88e_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); | ||
217 | extern void rtl88e_phy_get_txpower_level(struct ieee80211_hw *hw, | ||
218 | long *powerlevel); | ||
219 | extern void rtl88e_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); | ||
220 | extern void rtl88e_phy_scan_operation_backup(struct ieee80211_hw *hw, | ||
221 | u8 operation); | ||
222 | extern void rtl88e_phy_set_bw_mode_callback(struct ieee80211_hw *hw); | ||
223 | extern void rtl88e_phy_set_bw_mode(struct ieee80211_hw *hw, | ||
224 | enum nl80211_channel_type ch_type); | ||
225 | extern void rtl88e_phy_sw_chnl_callback(struct ieee80211_hw *hw); | ||
226 | extern u8 rtl88e_phy_sw_chnl(struct ieee80211_hw *hw); | ||
227 | extern void rtl88e_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); | ||
228 | void rtl88e_phy_lc_calibrate(struct ieee80211_hw *hw); | ||
229 | void rtl88e_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); | ||
230 | bool rtl88e_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, | ||
231 | enum radio_path rfpath); | ||
232 | bool rtl88e_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); | ||
233 | extern bool rtl88e_phy_set_rf_power_state(struct ieee80211_hw *hw, | ||
234 | enum rf_pwrstate rfpwr_state); | ||
235 | |||
236 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c new file mode 100644 index 000000000000..6dc4e3a954f6 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c | |||
@@ -0,0 +1,109 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "pwrseqcmd.h" | ||
31 | #include "pwrseq.h" | ||
32 | |||
33 | /* drivers should parse below arrays and do the corresponding actions */ | ||
34 | /*3 Power on Array*/ | ||
35 | struct wlan_pwr_cfg rtl8188e_power_on_flow[RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS + | ||
36 | RTL8188E_TRANS_END_STEPS] = { | ||
37 | RTL8188E_TRANS_CARDEMU_TO_ACT | ||
38 | RTL8188E_TRANS_END | ||
39 | }; | ||
40 | |||
41 | /*3Radio off GPIO Array */ | ||
42 | struct wlan_pwr_cfg rtl8188e_radio_off_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS | ||
43 | + RTL8188E_TRANS_END_STEPS] = { | ||
44 | RTL8188E_TRANS_ACT_TO_CARDEMU | ||
45 | RTL8188E_TRANS_END | ||
46 | }; | ||
47 | |||
48 | /*3Card Disable Array*/ | ||
49 | struct wlan_pwr_cfg rtl8188e_card_disable_flow | ||
50 | [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + | ||
51 | RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS + | ||
52 | RTL8188E_TRANS_END_STEPS] = { | ||
53 | RTL8188E_TRANS_ACT_TO_CARDEMU | ||
54 | RTL8188E_TRANS_CARDEMU_TO_CARDDIS | ||
55 | RTL8188E_TRANS_END | ||
56 | }; | ||
57 | |||
58 | /*3 Card Enable Array*/ | ||
59 | struct wlan_pwr_cfg rtl8188e_card_enable_flow | ||
60 | [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + | ||
61 | RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS + | ||
62 | RTL8188E_TRANS_END_STEPS] = { | ||
63 | RTL8188E_TRANS_CARDDIS_TO_CARDEMU | ||
64 | RTL8188E_TRANS_CARDEMU_TO_ACT | ||
65 | RTL8188E_TRANS_END | ||
66 | }; | ||
67 | |||
68 | /*3Suspend Array*/ | ||
69 | struct wlan_pwr_cfg rtl8188e_suspend_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS | ||
70 | + RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS | ||
71 | + RTL8188E_TRANS_END_STEPS] = { | ||
72 | RTL8188E_TRANS_ACT_TO_CARDEMU | ||
73 | RTL8188E_TRANS_CARDEMU_TO_SUS | ||
74 | RTL8188E_TRANS_END | ||
75 | }; | ||
76 | |||
77 | /*3 Resume Array*/ | ||
78 | struct wlan_pwr_cfg rtl8188e_resume_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS | ||
79 | + RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS | ||
80 | + RTL8188E_TRANS_END_STEPS] = { | ||
81 | RTL8188E_TRANS_SUS_TO_CARDEMU | ||
82 | RTL8188E_TRANS_CARDEMU_TO_ACT | ||
83 | RTL8188E_TRANS_END | ||
84 | }; | ||
85 | |||
86 | /*3HWPDN Array*/ | ||
87 | struct wlan_pwr_cfg rtl8188e_hwpdn_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS | ||
88 | + RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS | ||
89 | + RTL8188E_TRANS_END_STEPS] = { | ||
90 | RTL8188E_TRANS_ACT_TO_CARDEMU | ||
91 | RTL8188E_TRANS_CARDEMU_TO_PDN | ||
92 | RTL8188E_TRANS_END | ||
93 | }; | ||
94 | |||
95 | /*3 Enter LPS */ | ||
96 | struct wlan_pwr_cfg rtl8188e_enter_lps_flow[RTL8188E_TRANS_ACT_TO_LPS_STEPS | ||
97 | + RTL8188E_TRANS_END_STEPS] = { | ||
98 | /*FW behavior*/ | ||
99 | RTL8188E_TRANS_ACT_TO_LPS | ||
100 | RTL8188E_TRANS_END | ||
101 | }; | ||
102 | |||
103 | /*3 Leave LPS */ | ||
104 | struct wlan_pwr_cfg rtl8188e_leave_lps_flow[RTL8188E_TRANS_LPS_TO_ACT_STEPS | ||
105 | + RTL8188E_TRANS_END_STEPS] = { | ||
106 | /*FW behavior*/ | ||
107 | RTL8188E_TRANS_LPS_TO_ACT | ||
108 | RTL8188E_TRANS_END | ||
109 | }; | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h new file mode 100644 index 000000000000..028ec6dd52b4 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h | |||
@@ -0,0 +1,327 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #ifndef __RTL8723E_PWRSEQ_H__ | ||
31 | #define __RTL8723E_PWRSEQ_H__ | ||
32 | |||
33 | #include "pwrseqcmd.h" | ||
34 | /* | ||
35 | Check document WM-20110607-Paul-RTL8188E_Power_Architecture-R02.vsd | ||
36 | There are 6 HW Power States: | ||
37 | 0: POFF--Power Off | ||
38 | 1: PDN--Power Down | ||
39 | 2: CARDEMU--Card Emulation | ||
40 | 3: ACT--Active Mode | ||
41 | 4: LPS--Low Power State | ||
42 | 5: SUS--Suspend | ||
43 | |||
44 | The transision from different states are defined below | ||
45 | TRANS_CARDEMU_TO_ACT | ||
46 | TRANS_ACT_TO_CARDEMU | ||
47 | TRANS_CARDEMU_TO_SUS | ||
48 | TRANS_SUS_TO_CARDEMU | ||
49 | TRANS_CARDEMU_TO_PDN | ||
50 | TRANS_ACT_TO_LPS | ||
51 | TRANS_LPS_TO_ACT | ||
52 | |||
53 | TRANS_END | ||
54 | PWR SEQ Version: rtl8188e_PwrSeq_V09.h | ||
55 | */ | ||
56 | |||
57 | #define RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS 10 | ||
58 | #define RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS 10 | ||
59 | #define RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS 10 | ||
60 | #define RTL8188E_TRANS_SUS_TO_CARDEMU_STEPS 10 | ||
61 | #define RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS 10 | ||
62 | #define RTL8188E_TRANS_PDN_TO_CARDEMU_STEPS 10 | ||
63 | #define RTL8188E_TRANS_ACT_TO_LPS_STEPS 15 | ||
64 | #define RTL8188E_TRANS_LPS_TO_ACT_STEPS 15 | ||
65 | #define RTL8188E_TRANS_END_STEPS 1 | ||
66 | |||
67 | |||
68 | #define RTL8188E_TRANS_CARDEMU_TO_ACT \ | ||
69 | /* format */ \ | ||
70 | /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ | ||
71 | {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
72 | /* wait till 0x04[17] = 1 power ready*/ \ | ||
73 | PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), BIT(1)}, \ | ||
74 | {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
75 | /* 0x02[1:0] = 0 reset BB*/ \ | ||
76 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0)|BIT(1), 0}, \ | ||
77 | {0x0026, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
78 | /*0x24[23] = 2b'01 schmit trigger */ \ | ||
79 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)}, \ | ||
80 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
81 | /* 0x04[15] = 0 disable HWPDN (control by DRV)*/ \ | ||
82 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0}, \ | ||
83 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
84 | /*0x04[12:11] = 2b'00 disable WL suspend*/ \ | ||
85 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4)|BIT(3), 0}, \ | ||
86 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
87 | /*0x04[8] = 1 polling until return 0*/ \ | ||
88 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, \ | ||
89 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
90 | /*wait till 0x04[8] = 0*/ \ | ||
91 | PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(0), 0}, \ | ||
92 | {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
93 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*LDO normal mode*/\ | ||
94 | {0x0074, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ | ||
95 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, /*SDIO Driving*/\ | ||
96 | |||
97 | #define RTL8188E_TRANS_ACT_TO_CARDEMU \ | ||
98 | /* format */ \ | ||
99 | /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ | ||
100 | {0x001F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
101 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0},/*0x1F[7:0] = 0 turn off RF*/\ | ||
102 | {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
103 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, /*LDO Sleep mode*/\ | ||
104 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
105 | /*0x04[9] = 1 turn off MAC by HW state machine*/ \ | ||
106 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, \ | ||
107 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
108 | /*wait till 0x04[9] = 0 polling until return 0 to disable*/ \ | ||
109 | PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), 0}, \ | ||
110 | |||
111 | |||
112 | #define RTL8188E_TRANS_CARDEMU_TO_SUS \ | ||
113 | /* format */ \ | ||
114 | /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ | ||
115 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ | ||
116 | PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ | ||
117 | /*0x04[12:11] = 2b'01enable WL suspend*/ \ | ||
118 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, \ | ||
119 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ | ||
120 | /*0x04[12:11] = 2b'11enable WL suspend for PCIe*/ \ | ||
121 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)|BIT(4)},\ | ||
122 | {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ | ||
123 | PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ | ||
124 | /* 0x04[31:30] = 2b'10 enable enable bandgap mbias in suspend */\ | ||
125 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, BIT(7)}, \ | ||
126 | {0x0041, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ | ||
127 | PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ | ||
128 | /*Clear SIC_EN register 0x40[12] = 1'b0 */ \ | ||
129 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, \ | ||
130 | {0xfe10, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ | ||
131 | PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ | ||
132 | /*Set USB suspend enable local register 0xfe10[4]= 1 */ \ | ||
133 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, \ | ||
134 | {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ | ||
135 | /*Set SDIO suspend local register*/ \ | ||
136 | PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)}, \ | ||
137 | {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ | ||
138 | /*wait power state to suspend*/ \ | ||
139 | PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0}, | ||
140 | |||
141 | #define RTL8188E_TRANS_SUS_TO_CARDEMU \ | ||
142 | /* format */ \ | ||
143 | /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ | ||
144 | {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ | ||
145 | /*Set SDIO suspend local register*/ \ | ||
146 | PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0}, \ | ||
147 | {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ | ||
148 | /*wait power state to suspend*/ \ | ||
149 | PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)}, \ | ||
150 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
151 | /*0x04[12:11] = 2b'01enable WL suspend*/ \ | ||
152 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, | ||
153 | |||
154 | #define RTL8188E_TRANS_CARDEMU_TO_CARDDIS \ | ||
155 | /* format */ \ | ||
156 | /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ | ||
157 | {0x0026, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
158 | /*0x24[23] = 2b'01 schmit trigger */ \ | ||
159 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)}, \ | ||
160 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ | ||
161 | PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ | ||
162 | /*0x04[12:11] = 2b'01 enable WL suspend*/ \ | ||
163 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, \ | ||
164 | {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ | ||
165 | PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ | ||
166 | /* 0x04[31:30] = 2b'10 enable enable bandgap mbias in suspend */\ | ||
167 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}, \ | ||
168 | {0x0041, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ | ||
169 | PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ | ||
170 | /*Clear SIC_EN register 0x40[12] = 1'b0 */ \ | ||
171 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, \ | ||
172 | {0xfe10, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, \ | ||
173 | /*Set USB suspend enable local register 0xfe10[4]= 1 */ \ | ||
174 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, \ | ||
175 | {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ | ||
176 | /*Set SDIO suspend local register*/ \ | ||
177 | PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)}, \ | ||
178 | {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ | ||
179 | PWR_CMD_POLLING, BIT(1), 0}, /*wait power state to suspend*/ | ||
180 | |||
181 | #define RTL8188E_TRANS_CARDDIS_TO_CARDEMU \ | ||
182 | /* format */ \ | ||
183 | /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ | ||
184 | {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ | ||
185 | PWR_BASEADDR_SDIO,\ | ||
186 | PWR_CMD_WRITE, BIT(0), 0}, /*Set SDIO suspend local register*/ \ | ||
187 | {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ | ||
188 | PWR_BASEADDR_SDIO,\ | ||
189 | PWR_CMD_POLLING, BIT(1), BIT(1)}, /*wait power state to suspend*/\ | ||
190 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
191 | PWR_BASEADDR_MAC, \ | ||
192 | PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, \ | ||
193 | /*0x04[12:11] = 2b'01enable WL suspend*/ | ||
194 | |||
195 | |||
196 | #define RTL8188E_TRANS_CARDEMU_TO_PDN \ | ||
197 | /* format */ \ | ||
198 | /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ | ||
199 | {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
200 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0},/* 0x04[16] = 0*/ \ | ||
201 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
202 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)},/* 0x04[15] = 1*/ | ||
203 | |||
204 | |||
205 | #define RTL8188E_TRANS_PDN_TO_CARDEMU \ | ||
206 | /* format */ \ | ||
207 | /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ | ||
208 | {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
209 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0},/* 0x04[15] = 0*/ | ||
210 | |||
211 | |||
212 | #define RTL8188E_TRANS_ACT_TO_LPS \ | ||
213 | /* format */ \ | ||
214 | /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ | ||
215 | {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
216 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x7F},/*Tx Pause*/ \ | ||
217 | {0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
218 | /*zero if no pkt is tx*/\ | ||
219 | PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \ | ||
220 | {0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
221 | /*Should be zero if no packet is transmitting*/ \ | ||
222 | PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \ | ||
223 | {0x05FA, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
224 | /*Should be zero if no packet is transmitting*/ \ | ||
225 | PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \ | ||
226 | {0x05FB, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
227 | /*Should be zero if no packet is transmitting*/ \ | ||
228 | PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \ | ||
229 | {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
230 | /*CCK and OFDM are disabled, and clock are gated*/ \ | ||
231 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, \ | ||
232 | {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
233 | PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US},/*Delay 1us*/\ | ||
234 | {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
235 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x3F},/*Reset MAC TRX*/ \ | ||
236 | {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
237 | /*check if removed later*/ \ | ||
238 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0}, \ | ||
239 | {0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
240 | /*Respond TxOK to scheduler*/ \ | ||
241 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), BIT(5)}, \ | ||
242 | |||
243 | |||
244 | #define RTL8188E_TRANS_LPS_TO_ACT \ | ||
245 | /* format */ \ | ||
246 | /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ | ||
247 | {0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ | ||
248 | PWR_BASEADDR_SDIO, PWR_CMD_WRITE, 0xFF, 0x84}, /*SDIO RPWM*/ \ | ||
249 | {0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, \ | ||
250 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, /*USB RPWM*/ \ | ||
251 | {0x0361, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ | ||
252 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, /*PCIe RPWM*/ \ | ||
253 | {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
254 | PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS}, /*Delay*/ \ | ||
255 | {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
256 | /*. 0x08[4] = 0 switch TSF to 40M*/ \ | ||
257 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, \ | ||
258 | {0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
259 | /*Polling 0x109[7]= 0 TSF in 40M*/ \ | ||
260 | PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(7), 0}, \ | ||
261 | {0x0029, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
262 | /*. 0x29[7:6] = 2b'00 enable BB clock*/ \ | ||
263 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(6)|BIT(7), 0}, \ | ||
264 | {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
265 | /*. 0x101[1] = 1*/\ | ||
266 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, \ | ||
267 | {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
268 | /*. 0x100[7:0] = 0xFF enable WMAC TRX*/\ | ||
269 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF}, \ | ||
270 | {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ | ||
271 | /*. 0x02[1:0] = 2b'11 enable BB macro*/\ | ||
272 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1)|BIT(0), BIT(1)|BIT(0)}, \ | ||
273 | {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ | ||
274 | PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}, /*. 0x522 = 0*/ | ||
275 | |||
276 | |||
277 | #define RTL8188E_TRANS_END \ | ||
278 | /* format */ \ | ||
279 | /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ | ||
280 | {0xFFFF, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ | ||
281 | 0, PWR_CMD_END, 0, 0} | ||
282 | |||
283 | extern struct wlan_pwr_cfg rtl8188e_power_on_flow | ||
284 | [RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS + | ||
285 | RTL8188E_TRANS_END_STEPS]; | ||
286 | extern struct wlan_pwr_cfg rtl8188e_radio_off_flow | ||
287 | [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + | ||
288 | RTL8188E_TRANS_END_STEPS]; | ||
289 | extern struct wlan_pwr_cfg rtl8188e_card_disable_flow | ||
290 | [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + | ||
291 | RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS + | ||
292 | RTL8188E_TRANS_END_STEPS]; | ||
293 | extern struct wlan_pwr_cfg rtl8188e_card_enable_flow | ||
294 | [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + | ||
295 | RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS + | ||
296 | RTL8188E_TRANS_END_STEPS]; | ||
297 | extern struct wlan_pwr_cfg rtl8188e_suspend_flow | ||
298 | [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + | ||
299 | RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS + | ||
300 | RTL8188E_TRANS_END_STEPS]; | ||
301 | extern struct wlan_pwr_cfg rtl8188e_resume_flow | ||
302 | [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + | ||
303 | RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS + | ||
304 | RTL8188E_TRANS_END_STEPS]; | ||
305 | extern struct wlan_pwr_cfg rtl8188e_hwpdn_flow | ||
306 | [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + | ||
307 | RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS + | ||
308 | RTL8188E_TRANS_END_STEPS]; | ||
309 | extern struct wlan_pwr_cfg rtl8188e_enter_lps_flow | ||
310 | [RTL8188E_TRANS_ACT_TO_LPS_STEPS + | ||
311 | RTL8188E_TRANS_END_STEPS]; | ||
312 | extern struct wlan_pwr_cfg rtl8188e_leave_lps_flow | ||
313 | [RTL8188E_TRANS_LPS_TO_ACT_STEPS + | ||
314 | RTL8188E_TRANS_END_STEPS]; | ||
315 | |||
316 | /* RTL8723 Power Configuration CMDs for PCIe interface */ | ||
317 | #define Rtl8188E_NIC_PWR_ON_FLOW rtl8188e_power_on_flow | ||
318 | #define Rtl8188E_NIC_RF_OFF_FLOW rtl8188e_radio_off_flow | ||
319 | #define Rtl8188E_NIC_DISABLE_FLOW rtl8188e_card_disable_flow | ||
320 | #define Rtl8188E_NIC_ENABLE_FLOW rtl8188e_card_enable_flow | ||
321 | #define Rtl8188E_NIC_SUSPEND_FLOW rtl8188e_suspend_flow | ||
322 | #define Rtl8188E_NIC_RESUME_FLOW rtl8188e_resume_flow | ||
323 | #define Rtl8188E_NIC_PDN_FLOW rtl8188e_hwpdn_flow | ||
324 | #define Rtl8188E_NIC_LPS_ENTER_FLOW rtl8188e_enter_lps_flow | ||
325 | #define Rtl8188E_NIC_LPS_LEAVE_FLOW rtl8188e_leave_lps_flow | ||
326 | |||
327 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.c b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.c new file mode 100644 index 000000000000..a9cfa13be3a8 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.c | |||
@@ -0,0 +1,140 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "pwrseq.h" | ||
31 | |||
32 | |||
33 | /* Description: | ||
34 | * This routine deal with the Power Configuration CMDs | ||
35 | * parsing for RTL8723/RTL8188E Series IC. | ||
36 | * Assumption: | ||
37 | * We should follow specific format which was released from HW SD. | ||
38 | * | ||
39 | * 2011.07.07, added by Roger. | ||
40 | */ | ||
41 | |||
42 | bool rtl88_hal_pwrseqcmdparsing(struct rtl_priv *rtlpriv, u8 cut_version, | ||
43 | u8 fab_version, u8 interface_type, | ||
44 | struct wlan_pwr_cfg pwrcfgcmd[]) | ||
45 | { | ||
46 | struct wlan_pwr_cfg cmd = {0}; | ||
47 | bool polling_bit = false; | ||
48 | u32 ary_idx = 0; | ||
49 | u8 val = 0; | ||
50 | u32 offset = 0; | ||
51 | u32 polling_count = 0; | ||
52 | u32 max_polling_cnt = 5000; | ||
53 | |||
54 | do { | ||
55 | cmd = pwrcfgcmd[ary_idx]; | ||
56 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
57 | "rtl88_hal_pwrseqcmdparsing(): offset(%#x), cut_msk(%#x), fab_msk(%#x)," | ||
58 | "interface_msk(%#x), base(%#x), cmd(%#x), msk(%#x), val(%#x)\n", | ||
59 | GET_PWR_CFG_OFFSET(cmd), | ||
60 | GET_PWR_CFG_CUT_MASK(cmd), | ||
61 | GET_PWR_CFG_FAB_MASK(cmd), | ||
62 | GET_PWR_CFG_INTF_MASK(cmd), | ||
63 | GET_PWR_CFG_BASE(cmd), | ||
64 | GET_PWR_CFG_CMD(cmd), | ||
65 | GET_PWR_CFG_MASK(cmd), | ||
66 | GET_PWR_CFG_VALUE(cmd)); | ||
67 | |||
68 | if ((GET_PWR_CFG_FAB_MASK(cmd) & fab_version) && | ||
69 | (GET_PWR_CFG_CUT_MASK(cmd) & cut_version) && | ||
70 | (GET_PWR_CFG_INTF_MASK(cmd) & interface_type)) { | ||
71 | switch (GET_PWR_CFG_CMD(cmd)) { | ||
72 | case PWR_CMD_READ: | ||
73 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
74 | "rtl88_hal_pwrseqcmdparsing(): PWR_CMD_READ\n"); | ||
75 | break; | ||
76 | case PWR_CMD_WRITE: { | ||
77 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
78 | "rtl88_hal_pwrseqcmdparsing(): PWR_CMD_WRITE\n"); | ||
79 | offset = GET_PWR_CFG_OFFSET(cmd); | ||
80 | |||
81 | /*Read the val from system register*/ | ||
82 | val = rtl_read_byte(rtlpriv, offset); | ||
83 | val &= (~(GET_PWR_CFG_MASK(cmd))); | ||
84 | val |= (GET_PWR_CFG_VALUE(cmd) & | ||
85 | GET_PWR_CFG_MASK(cmd)); | ||
86 | |||
87 | /*Write the val back to sytem register*/ | ||
88 | rtl_write_byte(rtlpriv, offset, val); | ||
89 | } | ||
90 | break; | ||
91 | case PWR_CMD_POLLING: | ||
92 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
93 | "rtl88_hal_pwrseqcmdparsing(): PWR_CMD_POLLING\n"); | ||
94 | polling_bit = false; | ||
95 | offset = GET_PWR_CFG_OFFSET(cmd); | ||
96 | |||
97 | do { | ||
98 | val = rtl_read_byte(rtlpriv, offset); | ||
99 | |||
100 | val = val & GET_PWR_CFG_MASK(cmd); | ||
101 | if (val == (GET_PWR_CFG_VALUE(cmd) & | ||
102 | GET_PWR_CFG_MASK(cmd))) | ||
103 | polling_bit = true; | ||
104 | else | ||
105 | udelay(10); | ||
106 | |||
107 | if (polling_count++ > max_polling_cnt) { | ||
108 | RT_TRACE(rtlpriv, COMP_INIT, | ||
109 | DBG_LOUD, | ||
110 | "polling fail in pwrseqcmd\n"); | ||
111 | return false; | ||
112 | } | ||
113 | } while (!polling_bit); | ||
114 | |||
115 | break; | ||
116 | case PWR_CMD_DELAY: | ||
117 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
118 | "rtl88_hal_pwrseqcmdparsing(): PWR_CMD_DELAY\n"); | ||
119 | if (GET_PWR_CFG_VALUE(cmd) == PWRSEQ_DELAY_US) | ||
120 | udelay(GET_PWR_CFG_OFFSET(cmd)); | ||
121 | else | ||
122 | mdelay(GET_PWR_CFG_OFFSET(cmd)); | ||
123 | break; | ||
124 | case PWR_CMD_END: | ||
125 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
126 | "rtl88_hal_pwrseqcmdparsing(): PWR_CMD_END\n"); | ||
127 | return true; | ||
128 | break; | ||
129 | default: | ||
130 | RT_ASSERT(false, | ||
131 | "rtl88_hal_pwrseqcmdparsing(): Unknown CMD!!\n"); | ||
132 | break; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | ary_idx++; | ||
137 | } while (1); | ||
138 | |||
139 | return true; | ||
140 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.h b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.h new file mode 100644 index 000000000000..d9ae280bb1a2 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.h | |||
@@ -0,0 +1,97 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #ifndef __RTL8723E_PWRSEQCMD_H__ | ||
31 | #define __RTL8723E_PWRSEQCMD_H__ | ||
32 | |||
33 | #include "../wifi.h" | ||
34 | /*---------------------------------------------*/ | ||
35 | /* The value of cmd: 4 bits */ | ||
36 | /*---------------------------------------------*/ | ||
37 | #define PWR_CMD_READ 0x00 | ||
38 | #define PWR_CMD_WRITE 0x01 | ||
39 | #define PWR_CMD_POLLING 0x02 | ||
40 | #define PWR_CMD_DELAY 0x03 | ||
41 | #define PWR_CMD_END 0x04 | ||
42 | |||
43 | /* define the base address of each block */ | ||
44 | #define PWR_BASEADDR_MAC 0x00 | ||
45 | #define PWR_BASEADDR_USB 0x01 | ||
46 | #define PWR_BASEADDR_PCIE 0x02 | ||
47 | #define PWR_BASEADDR_SDIO 0x03 | ||
48 | |||
49 | #define PWR_INTF_SDIO_MSK BIT(0) | ||
50 | #define PWR_INTF_USB_MSK BIT(1) | ||
51 | #define PWR_INTF_PCI_MSK BIT(2) | ||
52 | #define PWR_INTF_ALL_MSK (BIT(0)|BIT(1)|BIT(2)|BIT(3)) | ||
53 | |||
54 | #define PWR_FAB_TSMC_MSK BIT(0) | ||
55 | #define PWR_FAB_UMC_MSK BIT(1) | ||
56 | #define PWR_FAB_ALL_MSK (BIT(0)|BIT(1)|BIT(2)|BIT(3)) | ||
57 | |||
58 | #define PWR_CUT_TESTCHIP_MSK BIT(0) | ||
59 | #define PWR_CUT_A_MSK BIT(1) | ||
60 | #define PWR_CUT_B_MSK BIT(2) | ||
61 | #define PWR_CUT_C_MSK BIT(3) | ||
62 | #define PWR_CUT_D_MSK BIT(4) | ||
63 | #define PWR_CUT_E_MSK BIT(5) | ||
64 | #define PWR_CUT_F_MSK BIT(6) | ||
65 | #define PWR_CUT_G_MSK BIT(7) | ||
66 | #define PWR_CUT_ALL_MSK 0xFF | ||
67 | |||
68 | enum pwrseq_delay_unit { | ||
69 | PWRSEQ_DELAY_US, | ||
70 | PWRSEQ_DELAY_MS, | ||
71 | }; | ||
72 | |||
73 | struct wlan_pwr_cfg { | ||
74 | u16 offset; | ||
75 | u8 cut_msk; | ||
76 | u8 fab_msk:4; | ||
77 | u8 interface_msk:4; | ||
78 | u8 base:4; | ||
79 | u8 cmd:4; | ||
80 | u8 msk; | ||
81 | u8 value; | ||
82 | }; | ||
83 | |||
84 | #define GET_PWR_CFG_OFFSET(__PWR) (__PWR.offset) | ||
85 | #define GET_PWR_CFG_CUT_MASK(__PWR) (__PWR.cut_msk) | ||
86 | #define GET_PWR_CFG_FAB_MASK(__PWR) (__PWR.fab_msk) | ||
87 | #define GET_PWR_CFG_INTF_MASK(__PWR) (__PWR.interface_msk) | ||
88 | #define GET_PWR_CFG_BASE(__PWR) (__PWR.base) | ||
89 | #define GET_PWR_CFG_CMD(__PWR) (__PWR.cmd) | ||
90 | #define GET_PWR_CFG_MASK(__PWR) (__PWR.msk) | ||
91 | #define GET_PWR_CFG_VALUE(__PWR) (__PWR.value) | ||
92 | |||
93 | bool rtl88_hal_pwrseqcmdparsing(struct rtl_priv *rtlpriv, u8 cut_version, | ||
94 | u8 fab_version, u8 interface_type, | ||
95 | struct wlan_pwr_cfg pwrcfgcmd[]); | ||
96 | |||
97 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h b/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h new file mode 100644 index 000000000000..d849abf7d94a --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h | |||
@@ -0,0 +1,2258 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #ifndef __RTL92C_REG_H__ | ||
31 | #define __RTL92C_REG_H__ | ||
32 | |||
33 | #define TXPKT_BUF_SELECT 0x69 | ||
34 | #define RXPKT_BUF_SELECT 0xA5 | ||
35 | #define DISABLE_TRXPKT_BUF_ACCESS 0x0 | ||
36 | |||
37 | #define REG_SYS_ISO_CTRL 0x0000 | ||
38 | #define REG_SYS_FUNC_EN 0x0002 | ||
39 | #define REG_APS_FSMCO 0x0004 | ||
40 | #define REG_SYS_CLKR 0x0008 | ||
41 | #define REG_9346CR 0x000A | ||
42 | #define REG_EE_VPD 0x000C | ||
43 | #define REG_AFE_MISC 0x0010 | ||
44 | #define REG_SPS0_CTRL 0x0011 | ||
45 | #define REG_SPS_OCP_CFG 0x0018 | ||
46 | #define REG_RSV_CTRL 0x001C | ||
47 | #define REG_RF_CTRL 0x001F | ||
48 | #define REG_LDOA15_CTRL 0x0020 | ||
49 | #define REG_LDOV12D_CTRL 0x0021 | ||
50 | #define REG_LDOHCI12_CTRL 0x0022 | ||
51 | #define REG_LPLDO_CTRL 0x0023 | ||
52 | #define REG_AFE_XTAL_CTRL 0x0024 | ||
53 | #define REG_AFE_LDO_CTRL 0x0027 /* 1.5v for 8188EE test | ||
54 | * chip, 1.4v for MP chip | ||
55 | */ | ||
56 | #define REG_AFE_PLL_CTRL 0x0028 | ||
57 | #define REG_EFUSE_CTRL 0x0030 | ||
58 | #define REG_EFUSE_TEST 0x0034 | ||
59 | #define REG_PWR_DATA 0x0038 | ||
60 | #define REG_CAL_TIMER 0x003C | ||
61 | #define REG_ACLK_MON 0x003E | ||
62 | #define REG_GPIO_MUXCFG 0x0040 | ||
63 | #define REG_GPIO_IO_SEL 0x0042 | ||
64 | #define REG_MAC_PINMUX_CFG 0x0043 | ||
65 | #define REG_GPIO_PIN_CTRL 0x0044 | ||
66 | #define REG_GPIO_INTM 0x0048 | ||
67 | #define REG_LEDCFG0 0x004C | ||
68 | #define REG_LEDCFG1 0x004D | ||
69 | #define REG_LEDCFG2 0x004E | ||
70 | #define REG_LEDCFG3 0x004F | ||
71 | #define REG_FSIMR 0x0050 | ||
72 | #define REG_FSISR 0x0054 | ||
73 | #define REG_HSIMR 0x0058 | ||
74 | #define REG_HSISR 0x005c | ||
75 | #define REG_GPIO_PIN_CTRL_2 0x0060 | ||
76 | #define REG_GPIO_IO_SEL_2 0x0062 | ||
77 | #define REG_GPIO_OUTPUT 0x006c | ||
78 | #define REG_AFE_XTAL_CTRL_EXT 0x0078 | ||
79 | #define REG_XCK_OUT_CTRL 0x007c | ||
80 | #define REG_MCUFWDL 0x0080 | ||
81 | #define REG_WOL_EVENT 0x0081 | ||
82 | #define REG_MCUTSTCFG 0x0084 | ||
83 | |||
84 | |||
85 | #define REG_HIMR 0x00B0 | ||
86 | #define REG_HISR 0x00B4 | ||
87 | #define REG_HIMRE 0x00B8 | ||
88 | #define REG_HISRE 0x00BC | ||
89 | |||
90 | #define REG_EFUSE_ACCESS 0x00CF | ||
91 | |||
92 | #define REG_BIST_SCAN 0x00D0 | ||
93 | #define REG_BIST_RPT 0x00D4 | ||
94 | #define REG_BIST_ROM_RPT 0x00D8 | ||
95 | #define REG_USB_SIE_INTF 0x00E0 | ||
96 | #define REG_PCIE_MIO_INTF 0x00E4 | ||
97 | #define REG_PCIE_MIO_INTD 0x00E8 | ||
98 | #define REG_HPON_FSM 0x00EC | ||
99 | #define REG_SYS_CFG 0x00F0 | ||
100 | |||
101 | #define REG_CR 0x0100 | ||
102 | #define REG_PBP 0x0104 | ||
103 | #define REG_PKT_BUFF_ACCESS_CTRL 0x0106 | ||
104 | #define REG_TRXDMA_CTRL 0x010C | ||
105 | #define REG_TRXFF_BNDY 0x0114 | ||
106 | #define REG_TRXFF_STATUS 0x0118 | ||
107 | #define REG_RXFF_PTR 0x011C | ||
108 | |||
109 | #define REG_CPWM 0x012F | ||
110 | #define REG_FWIMR 0x0130 | ||
111 | #define REG_FWISR 0x0134 | ||
112 | #define REG_PKTBUF_DBG_CTRL 0x0140 | ||
113 | #define REG_PKTBUF_DBG_DATA_L 0x0144 | ||
114 | #define REG_PKTBUF_DBG_DATA_H 0x0148 | ||
115 | #define REG_RXPKTBUF_CTRL (REG_PKTBUF_DBG_CTRL+2) | ||
116 | |||
117 | #define REG_TC0_CTRL 0x0150 | ||
118 | #define REG_TC1_CTRL 0x0154 | ||
119 | #define REG_TC2_CTRL 0x0158 | ||
120 | #define REG_TC3_CTRL 0x015C | ||
121 | #define REG_TC4_CTRL 0x0160 | ||
122 | #define REG_TCUNIT_BASE 0x0164 | ||
123 | #define REG_MBIST_START 0x0174 | ||
124 | #define REG_MBIST_DONE 0x0178 | ||
125 | #define REG_MBIST_FAIL 0x017C | ||
126 | #define REG_32K_CTRL 0x0194 | ||
127 | #define REG_C2HEVT_MSG_NORMAL 0x01A0 | ||
128 | #define REG_C2HEVT_CLEAR 0x01AF | ||
129 | #define REG_C2HEVT_MSG_TEST 0x01B8 | ||
130 | #define REG_MCUTST_1 0x01c0 | ||
131 | #define REG_FMETHR 0x01C8 | ||
132 | #define REG_HMETFR 0x01CC | ||
133 | #define REG_HMEBOX_0 0x01D0 | ||
134 | #define REG_HMEBOX_1 0x01D4 | ||
135 | #define REG_HMEBOX_2 0x01D8 | ||
136 | #define REG_HMEBOX_3 0x01DC | ||
137 | |||
138 | #define REG_LLT_INIT 0x01E0 | ||
139 | #define REG_BB_ACCEESS_CTRL 0x01E8 | ||
140 | #define REG_BB_ACCESS_DATA 0x01EC | ||
141 | |||
142 | #define REG_HMEBOX_EXT_0 0x01F0 | ||
143 | #define REG_HMEBOX_EXT_1 0x01F4 | ||
144 | #define REG_HMEBOX_EXT_2 0x01F8 | ||
145 | #define REG_HMEBOX_EXT_3 0x01FC | ||
146 | |||
147 | #define REG_RQPN 0x0200 | ||
148 | #define REG_FIFOPAGE 0x0204 | ||
149 | #define REG_TDECTRL 0x0208 | ||
150 | #define REG_TXDMA_OFFSET_CHK 0x020C | ||
151 | #define REG_TXDMA_STATUS 0x0210 | ||
152 | #define REG_RQPN_NPQ 0x0214 | ||
153 | |||
154 | #define REG_RXDMA_AGG_PG_TH 0x0280 | ||
155 | #define REG_FW_UPD_RDPTR 0x0284 /* FW shall update this | ||
156 | * register before FW * write | ||
157 | * RXPKT_RELEASE_POLL to 1 | ||
158 | */ | ||
159 | #define REG_RXDMA_CONTROL 0x0286 /* Control the RX DMA.*/ | ||
160 | #define REG_RXPKT_NUM 0x0287 /* The number of packets | ||
161 | * in RXPKTBUF. | ||
162 | */ | ||
163 | #define REG_PCIE_CTRL_REG 0x0300 | ||
164 | #define REG_INT_MIG 0x0304 | ||
165 | #define REG_BCNQ_DESA 0x0308 | ||
166 | #define REG_HQ_DESA 0x0310 | ||
167 | #define REG_MGQ_DESA 0x0318 | ||
168 | #define REG_VOQ_DESA 0x0320 | ||
169 | #define REG_VIQ_DESA 0x0328 | ||
170 | #define REG_BEQ_DESA 0x0330 | ||
171 | #define REG_BKQ_DESA 0x0338 | ||
172 | #define REG_RX_DESA 0x0340 | ||
173 | |||
174 | #define REG_DBI 0x0348 | ||
175 | #define REG_MDIO 0x0354 | ||
176 | #define REG_DBG_SEL 0x0360 | ||
177 | #define REG_PCIE_HRPWM 0x0361 | ||
178 | #define REG_PCIE_HCPWM 0x0363 | ||
179 | #define REG_UART_CTRL 0x0364 | ||
180 | #define REG_WATCH_DOG 0x0368 | ||
181 | #define REG_UART_TX_DESA 0x0370 | ||
182 | #define REG_UART_RX_DESA 0x0378 | ||
183 | |||
184 | |||
185 | #define REG_HDAQ_DESA_NODEF 0x0000 | ||
186 | #define REG_CMDQ_DESA_NODEF 0x0000 | ||
187 | |||
188 | #define REG_VOQ_INFORMATION 0x0400 | ||
189 | #define REG_VIQ_INFORMATION 0x0404 | ||
190 | #define REG_BEQ_INFORMATION 0x0408 | ||
191 | #define REG_BKQ_INFORMATION 0x040C | ||
192 | #define REG_MGQ_INFORMATION 0x0410 | ||
193 | #define REG_HGQ_INFORMATION 0x0414 | ||
194 | #define REG_BCNQ_INFORMATION 0x0418 | ||
195 | #define REG_TXPKT_EMPTY 0x041A | ||
196 | |||
197 | |||
198 | #define REG_CPU_MGQ_INFORMATION 0x041C | ||
199 | #define REG_FWHW_TXQ_CTRL 0x0420 | ||
200 | #define REG_HWSEQ_CTRL 0x0423 | ||
201 | #define REG_TXPKTBUF_BCNQ_BDNY 0x0424 | ||
202 | #define REG_TXPKTBUF_MGQ_BDNY 0x0425 | ||
203 | #define REG_MULTI_BCNQ_EN 0x0426 | ||
204 | #define REG_MULTI_BCNQ_OFFSET 0x0427 | ||
205 | #define REG_SPEC_SIFS 0x0428 | ||
206 | #define REG_RL 0x042A | ||
207 | #define REG_DARFRC 0x0430 | ||
208 | #define REG_RARFRC 0x0438 | ||
209 | #define REG_RRSR 0x0440 | ||
210 | #define REG_ARFR0 0x0444 | ||
211 | #define REG_ARFR1 0x0448 | ||
212 | #define REG_ARFR2 0x044C | ||
213 | #define REG_ARFR3 0x0450 | ||
214 | #define REG_AGGLEN_LMT 0x0458 | ||
215 | #define REG_AMPDU_MIN_SPACE 0x045C | ||
216 | #define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D | ||
217 | #define REG_FAST_EDCA_CTRL 0x0460 | ||
218 | #define REG_RD_RESP_PKT_TH 0x0463 | ||
219 | #define REG_INIRTS_RATE_SEL 0x0480 | ||
220 | #define REG_INIDATA_RATE_SEL 0x0484 | ||
221 | #define REG_POWER_STATUS 0x04A4 | ||
222 | #define REG_POWER_STAGE1 0x04B4 | ||
223 | #define REG_POWER_STAGE2 0x04B8 | ||
224 | #define REG_PKT_LIFE_TIME 0x04C0 | ||
225 | #define REG_STBC_SETTING 0x04C4 | ||
226 | #define REG_PROT_MODE_CTRL 0x04C8 | ||
227 | #define REG_BAR_MODE_CTRL 0x04CC | ||
228 | #define REG_RA_TRY_RATE_AGG_LMT 0x04CF | ||
229 | #define REG_EARLY_MODE_CONTROL 0x04D0 | ||
230 | #define REG_NQOS_SEQ 0x04DC | ||
231 | #define REG_QOS_SEQ 0x04DE | ||
232 | #define REG_NEED_CPU_HANDLE 0x04E0 | ||
233 | #define REG_PKT_LOSE_RPT 0x04E1 | ||
234 | #define REG_PTCL_ERR_STATUS 0x04E2 | ||
235 | #define REG_TX_RPT_CTRL 0x04EC | ||
236 | #define REG_TX_RPT_TIME 0x04F0 | ||
237 | #define REG_DUMMY 0x04FC | ||
238 | |||
239 | #define REG_EDCA_VO_PARAM 0x0500 | ||
240 | #define REG_EDCA_VI_PARAM 0x0504 | ||
241 | #define REG_EDCA_BE_PARAM 0x0508 | ||
242 | #define REG_EDCA_BK_PARAM 0x050C | ||
243 | #define REG_BCNTCFG 0x0510 | ||
244 | #define REG_PIFS 0x0512 | ||
245 | #define REG_RDG_PIFS 0x0513 | ||
246 | #define REG_SIFS_CTX 0x0514 | ||
247 | #define REG_SIFS_TRX 0x0516 | ||
248 | #define REG_AGGR_BREAK_TIME 0x051A | ||
249 | #define REG_SLOT 0x051B | ||
250 | #define REG_TX_PTCL_CTRL 0x0520 | ||
251 | #define REG_TXPAUSE 0x0522 | ||
252 | #define REG_DIS_TXREQ_CLR 0x0523 | ||
253 | #define REG_RD_CTRL 0x0524 | ||
254 | #define REG_TBTT_PROHIBIT 0x0540 | ||
255 | #define REG_RD_NAV_NXT 0x0544 | ||
256 | #define REG_NAV_PROT_LEN 0x0546 | ||
257 | #define REG_BCN_CTRL 0x0550 | ||
258 | #define REG_USTIME_TSF 0x0551 | ||
259 | #define REG_MBID_NUM 0x0552 | ||
260 | #define REG_DUAL_TSF_RST 0x0553 | ||
261 | #define REG_BCN_INTERVAL 0x0554 | ||
262 | #define REG_MBSSID_BCN_SPACE 0x0554 | ||
263 | #define REG_DRVERLYINT 0x0558 | ||
264 | #define REG_BCNDMATIM 0x0559 | ||
265 | #define REG_ATIMWND 0x055A | ||
266 | #define REG_BCN_MAX_ERR 0x055D | ||
267 | #define REG_RXTSF_OFFSET_CCK 0x055E | ||
268 | #define REG_RXTSF_OFFSET_OFDM 0x055F | ||
269 | #define REG_TSFTR 0x0560 | ||
270 | #define REG_INIT_TSFTR 0x0564 | ||
271 | #define REG_PSTIMER 0x0580 | ||
272 | #define REG_TIMER0 0x0584 | ||
273 | #define REG_TIMER1 0x0588 | ||
274 | #define REG_ACMHWCTRL 0x05C0 | ||
275 | #define REG_ACMRSTCTRL 0x05C1 | ||
276 | #define REG_ACMAVG 0x05C2 | ||
277 | #define REG_VO_ADMTIME 0x05C4 | ||
278 | #define REG_VI_ADMTIME 0x05C6 | ||
279 | #define REG_BE_ADMTIME 0x05C8 | ||
280 | #define REG_EDCA_RANDOM_GEN 0x05CC | ||
281 | #define REG_SCH_TXCMD 0x05D0 | ||
282 | |||
283 | #define REG_APSD_CTRL 0x0600 | ||
284 | #define REG_BWOPMODE 0x0603 | ||
285 | #define REG_TCR 0x0604 | ||
286 | #define REG_RCR 0x0608 | ||
287 | #define REG_RX_PKT_LIMIT 0x060C | ||
288 | #define REG_RX_DLK_TIME 0x060D | ||
289 | #define REG_RX_DRVINFO_SZ 0x060F | ||
290 | |||
291 | #define REG_MACID 0x0610 | ||
292 | #define REG_BSSID 0x0618 | ||
293 | #define REG_MAR 0x0620 | ||
294 | #define REG_MBIDCAMCFG 0x0628 | ||
295 | |||
296 | #define REG_USTIME_EDCA 0x0638 | ||
297 | #define REG_MAC_SPEC_SIFS 0x063A | ||
298 | #define REG_RESP_SIFS_CCK 0x063C | ||
299 | #define REG_RESP_SIFS_OFDM 0x063E | ||
300 | #define REG_ACKTO 0x0640 | ||
301 | #define REG_CTS2TO 0x0641 | ||
302 | #define REG_EIFS 0x0642 | ||
303 | |||
304 | #define REG_NAV_CTRL 0x0650 | ||
305 | #define REG_BACAMCMD 0x0654 | ||
306 | #define REG_BACAMCONTENT 0x0658 | ||
307 | #define REG_LBDLY 0x0660 | ||
308 | #define REG_FWDLY 0x0661 | ||
309 | #define REG_RXERR_RPT 0x0664 | ||
310 | #define REG_TRXPTCL_CTL 0x0668 | ||
311 | |||
312 | #define REG_CAMCMD 0x0670 | ||
313 | #define REG_CAMWRITE 0x0674 | ||
314 | #define REG_CAMREAD 0x0678 | ||
315 | #define REG_CAMDBG 0x067C | ||
316 | #define REG_SECCFG 0x0680 | ||
317 | |||
318 | #define REG_WOW_CTRL 0x0690 | ||
319 | #define REG_PSSTATUS 0x0691 | ||
320 | #define REG_PS_RX_INFO 0x0692 | ||
321 | #define REG_UAPSD_TID 0x0693 | ||
322 | #define REG_LPNAV_CTRL 0x0694 | ||
323 | #define REG_WKFMCAM_NUM 0x0698 | ||
324 | #define REG_WKFMCAM_RWD 0x069C | ||
325 | #define REG_RXFLTMAP0 0x06A0 | ||
326 | #define REG_RXFLTMAP1 0x06A2 | ||
327 | #define REG_RXFLTMAP2 0x06A4 | ||
328 | #define REG_BCN_PSR_RPT 0x06A8 | ||
329 | #define REG_CALB32K_CTRL 0x06AC | ||
330 | #define REG_PKT_MON_CTRL 0x06B4 | ||
331 | #define REG_BT_COEX_TABLE 0x06C0 | ||
332 | #define REG_WMAC_RESP_TXINFO 0x06D8 | ||
333 | |||
334 | #define REG_USB_INFO 0xFE17 | ||
335 | #define REG_USB_SPECIAL_OPTION 0xFE55 | ||
336 | #define REG_USB_DMA_AGG_TO 0xFE5B | ||
337 | #define REG_USB_AGG_TO 0xFE5C | ||
338 | #define REG_USB_AGG_TH 0xFE5D | ||
339 | |||
340 | #define REG_TEST_USB_TXQS 0xFE48 | ||
341 | #define REG_TEST_SIE_VID 0xFE60 | ||
342 | #define REG_TEST_SIE_PID 0xFE62 | ||
343 | #define REG_TEST_SIE_OPTIONAL 0xFE64 | ||
344 | #define REG_TEST_SIE_CHIRP_K 0xFE65 | ||
345 | #define REG_TEST_SIE_PHY 0xFE66 | ||
346 | #define REG_TEST_SIE_MAC_ADDR 0xFE70 | ||
347 | #define REG_TEST_SIE_STRING 0xFE80 | ||
348 | |||
349 | #define REG_NORMAL_SIE_VID 0xFE60 | ||
350 | #define REG_NORMAL_SIE_PID 0xFE62 | ||
351 | #define REG_NORMAL_SIE_OPTIONAL 0xFE64 | ||
352 | #define REG_NORMAL_SIE_EP 0xFE65 | ||
353 | #define REG_NORMAL_SIE_PHY 0xFE68 | ||
354 | #define REG_NORMAL_SIE_MAC_ADDR 0xFE70 | ||
355 | #define REG_NORMAL_SIE_STRING 0xFE80 | ||
356 | |||
357 | #define CR9346 REG_9346CR | ||
358 | #define MSR (REG_CR + 2) | ||
359 | #define ISR REG_HISR | ||
360 | #define TSFR REG_TSFTR | ||
361 | |||
362 | #define MACIDR0 REG_MACID | ||
363 | #define MACIDR4 (REG_MACID + 4) | ||
364 | |||
365 | #define PBP REG_PBP | ||
366 | |||
367 | #define IDR0 MACIDR0 | ||
368 | #define IDR4 MACIDR4 | ||
369 | |||
370 | #define UNUSED_REGISTER 0x1BF | ||
371 | #define DCAM UNUSED_REGISTER | ||
372 | #define PSR UNUSED_REGISTER | ||
373 | #define BBADDR UNUSED_REGISTER | ||
374 | #define PHYDATAR UNUSED_REGISTER | ||
375 | |||
376 | #define INVALID_BBRF_VALUE 0x12345678 | ||
377 | |||
378 | #define MAX_MSS_DENSITY_2T 0x13 | ||
379 | #define MAX_MSS_DENSITY_1T 0x0A | ||
380 | |||
381 | #define CMDEEPROM_EN BIT(5) | ||
382 | #define CMDEEPROM_SEL BIT(4) | ||
383 | #define CMD9346CR_9356SEL BIT(4) | ||
384 | #define AUTOLOAD_EEPROM (CMDEEPROM_EN|CMDEEPROM_SEL) | ||
385 | #define AUTOLOAD_EFUSE CMDEEPROM_EN | ||
386 | |||
387 | #define GPIOSEL_GPIO 0 | ||
388 | #define GPIOSEL_ENBT BIT(5) | ||
389 | |||
390 | #define GPIO_IN REG_GPIO_PIN_CTRL | ||
391 | #define GPIO_OUT (REG_GPIO_PIN_CTRL+1) | ||
392 | #define GPIO_IO_SEL (REG_GPIO_PIN_CTRL+2) | ||
393 | #define GPIO_MOD (REG_GPIO_PIN_CTRL+3) | ||
394 | |||
395 | /* 8723/8188E Host System Interrupt Mask Register (offset 0x58, 32 byte) */ | ||
396 | #define HSIMR_GPIO12_0_INT_EN BIT(0) | ||
397 | #define HSIMR_SPS_OCP_INT_EN BIT(5) | ||
398 | #define HSIMR_RON_INT_EN BIT(6) | ||
399 | #define HSIMR_PDN_INT_EN BIT(7) | ||
400 | #define HSIMR_GPIO9_INT_EN BIT(25) | ||
401 | |||
402 | |||
403 | /* 8723/8188E Host System Interrupt Status Register (offset 0x5C, 32 byte) */ | ||
404 | #define HSISR_GPIO12_0_INT BIT(0) | ||
405 | #define HSISR_SPS_OCP_INT BIT(5) | ||
406 | #define HSISR_RON_INT_EN BIT(6) | ||
407 | #define HSISR_PDNINT BIT(7) | ||
408 | #define HSISR_GPIO9_INT BIT(25) | ||
409 | |||
410 | #define MSR_NOLINK 0x00 | ||
411 | #define MSR_ADHOC 0x01 | ||
412 | #define MSR_INFRA 0x02 | ||
413 | #define MSR_AP 0x03 | ||
414 | |||
415 | #define RRSR_RSC_OFFSET 21 | ||
416 | #define RRSR_SHORT_OFFSET 23 | ||
417 | #define RRSR_RSC_BW_40M 0x600000 | ||
418 | #define RRSR_RSC_UPSUBCHNL 0x400000 | ||
419 | #define RRSR_RSC_LOWSUBCHNL 0x200000 | ||
420 | #define RRSR_SHORT 0x800000 | ||
421 | #define RRSR_1M BIT(0) | ||
422 | #define RRSR_2M BIT(1) | ||
423 | #define RRSR_5_5M BIT(2) | ||
424 | #define RRSR_11M BIT(3) | ||
425 | #define RRSR_6M BIT(4) | ||
426 | #define RRSR_9M BIT(5) | ||
427 | #define RRSR_12M BIT(6) | ||
428 | #define RRSR_18M BIT(7) | ||
429 | #define RRSR_24M BIT(8) | ||
430 | #define RRSR_36M BIT(9) | ||
431 | #define RRSR_48M BIT(10) | ||
432 | #define RRSR_54M BIT(11) | ||
433 | #define RRSR_MCS0 BIT(12) | ||
434 | #define RRSR_MCS1 BIT(13) | ||
435 | #define RRSR_MCS2 BIT(14) | ||
436 | #define RRSR_MCS3 BIT(15) | ||
437 | #define RRSR_MCS4 BIT(16) | ||
438 | #define RRSR_MCS5 BIT(17) | ||
439 | #define RRSR_MCS6 BIT(18) | ||
440 | #define RRSR_MCS7 BIT(19) | ||
441 | #define BRSR_ACKSHORTPMB BIT(23) | ||
442 | |||
443 | #define RATR_1M 0x00000001 | ||
444 | #define RATR_2M 0x00000002 | ||
445 | #define RATR_55M 0x00000004 | ||
446 | #define RATR_11M 0x00000008 | ||
447 | #define RATR_6M 0x00000010 | ||
448 | #define RATR_9M 0x00000020 | ||
449 | #define RATR_12M 0x00000040 | ||
450 | #define RATR_18M 0x00000080 | ||
451 | #define RATR_24M 0x00000100 | ||
452 | #define RATR_36M 0x00000200 | ||
453 | #define RATR_48M 0x00000400 | ||
454 | #define RATR_54M 0x00000800 | ||
455 | #define RATR_MCS0 0x00001000 | ||
456 | #define RATR_MCS1 0x00002000 | ||
457 | #define RATR_MCS2 0x00004000 | ||
458 | #define RATR_MCS3 0x00008000 | ||
459 | #define RATR_MCS4 0x00010000 | ||
460 | #define RATR_MCS5 0x00020000 | ||
461 | #define RATR_MCS6 0x00040000 | ||
462 | #define RATR_MCS7 0x00080000 | ||
463 | #define RATR_MCS8 0x00100000 | ||
464 | #define RATR_MCS9 0x00200000 | ||
465 | #define RATR_MCS10 0x00400000 | ||
466 | #define RATR_MCS11 0x00800000 | ||
467 | #define RATR_MCS12 0x01000000 | ||
468 | #define RATR_MCS13 0x02000000 | ||
469 | #define RATR_MCS14 0x04000000 | ||
470 | #define RATR_MCS15 0x08000000 | ||
471 | |||
472 | #define RATE_1M BIT(0) | ||
473 | #define RATE_2M BIT(1) | ||
474 | #define RATE_5_5M BIT(2) | ||
475 | #define RATE_11M BIT(3) | ||
476 | #define RATE_6M BIT(4) | ||
477 | #define RATE_9M BIT(5) | ||
478 | #define RATE_12M BIT(6) | ||
479 | #define RATE_18M BIT(7) | ||
480 | #define RATE_24M BIT(8) | ||
481 | #define RATE_36M BIT(9) | ||
482 | #define RATE_48M BIT(10) | ||
483 | #define RATE_54M BIT(11) | ||
484 | #define RATE_MCS0 BIT(12) | ||
485 | #define RATE_MCS1 BIT(13) | ||
486 | #define RATE_MCS2 BIT(14) | ||
487 | #define RATE_MCS3 BIT(15) | ||
488 | #define RATE_MCS4 BIT(16) | ||
489 | #define RATE_MCS5 BIT(17) | ||
490 | #define RATE_MCS6 BIT(18) | ||
491 | #define RATE_MCS7 BIT(19) | ||
492 | #define RATE_MCS8 BIT(20) | ||
493 | #define RATE_MCS9 BIT(21) | ||
494 | #define RATE_MCS10 BIT(22) | ||
495 | #define RATE_MCS11 BIT(23) | ||
496 | #define RATE_MCS12 BIT(24) | ||
497 | #define RATE_MCS13 BIT(25) | ||
498 | #define RATE_MCS14 BIT(26) | ||
499 | #define RATE_MCS15 BIT(27) | ||
500 | |||
501 | #define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | RATR_11M) | ||
502 | #define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M | \ | ||
503 | RATR_24M | RATR_36M | RATR_48M | RATR_54M) | ||
504 | #define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 | \ | ||
505 | RATR_MCS3 | RATR_MCS4 | RATR_MCS5 | \ | ||
506 | RATR_MCS6 | RATR_MCS7) | ||
507 | #define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 | \ | ||
508 | RATR_MCS11 | RATR_MCS12 | RATR_MCS13 | \ | ||
509 | RATR_MCS14 | RATR_MCS15) | ||
510 | |||
511 | #define BW_OPMODE_20MHZ BIT(2) | ||
512 | #define BW_OPMODE_5G BIT(1) | ||
513 | #define BW_OPMODE_11J BIT(0) | ||
514 | |||
515 | #define CAM_VALID BIT(15) | ||
516 | #define CAM_NOTVALID 0x0000 | ||
517 | #define CAM_USEDK BIT(5) | ||
518 | |||
519 | #define CAM_NONE 0x0 | ||
520 | #define CAM_WEP40 0x01 | ||
521 | #define CAM_TKIP 0x02 | ||
522 | #define CAM_AES 0x04 | ||
523 | #define CAM_WEP104 0x05 | ||
524 | |||
525 | #define TOTAL_CAM_ENTRY 32 | ||
526 | #define HALF_CAM_ENTRY 16 | ||
527 | |||
528 | #define CAM_WRITE BIT(16) | ||
529 | #define CAM_READ 0x00000000 | ||
530 | #define CAM_POLLINIG BIT(31) | ||
531 | |||
532 | #define SCR_USEDK 0x01 | ||
533 | #define SCR_TXSEC_ENABLE 0x02 | ||
534 | #define SCR_RXSEC_ENABLE 0x04 | ||
535 | |||
536 | #define WOW_PMEN BIT(0) | ||
537 | #define WOW_WOMEN BIT(1) | ||
538 | #define WOW_MAGIC BIT(2) | ||
539 | #define WOW_UWF BIT(3) | ||
540 | |||
541 | /********************************************* | ||
542 | * 8188 IMR/ISR bits | ||
543 | **********************************************/ | ||
544 | #define IMR_DISABLED 0x0 | ||
545 | /* IMR DW0(0x0060-0063) Bit 0-31 */ | ||
546 | #define IMR_TXCCK BIT(30) /* TXRPT interrupt when CCX bit of | ||
547 | * the packet is set | ||
548 | */ | ||
549 | #define IMR_PSTIMEOUT BIT(29) /* Power Save Time Out Interrupt */ | ||
550 | #define IMR_GTINT4 BIT(28) /* When GTIMER4 expires, | ||
551 | * this bit is set to 1 | ||
552 | */ | ||
553 | #define IMR_GTINT3 BIT(27) /* When GTIMER3 expires, | ||
554 | * this bit is set to 1 | ||
555 | */ | ||
556 | #define IMR_TBDER BIT(26) /* Transmit Beacon0 Error */ | ||
557 | #define IMR_TBDOK BIT(25) /* Transmit Beacon0 OK */ | ||
558 | #define IMR_TSF_BIT32_TOGGLE BIT(24) /* TSF Timer BIT32 toggle ind int */ | ||
559 | #define IMR_BCNDMAINT0 BIT(20) /* Beacon DMA Interrupt 0 */ | ||
560 | #define IMR_BCNDOK0 BIT(16) /* Beacon Queue DMA OK0 */ | ||
561 | #define IMR_HSISR_IND_ON_INT BIT(15) /* HSISR Indicator (HSIMR & HSISR is | ||
562 | * true, this bit is set to 1) | ||
563 | */ | ||
564 | #define IMR_BCNDMAINT_E BIT(14) /* Beacon DMA Int Extension for Win7 */ | ||
565 | #define IMR_ATIMEND BIT(12) /* CTWidnow End or ATIM Window End */ | ||
566 | #define IMR_HISR1_IND_INT BIT(11) /* HISR1 Indicator (HISR1 & HIMR1 is | ||
567 | * true, this bit is set to 1) | ||
568 | */ | ||
569 | #define IMR_C2HCMD BIT(10) /* CPU to Host Command INT Status, | ||
570 | * Write 1 clear | ||
571 | */ | ||
572 | #define IMR_CPWM2 BIT(9) /* CPU power Mode exchange INT Status, | ||
573 | * Write 1 clear | ||
574 | */ | ||
575 | #define IMR_CPWM BIT(8) /* CPU power Mode exchange INT Status, | ||
576 | * Write 1 clear | ||
577 | */ | ||
578 | #define IMR_HIGHDOK BIT(7) /* High Queue DMA OK */ | ||
579 | #define IMR_MGNTDOK BIT(6) /* Management Queue DMA OK */ | ||
580 | #define IMR_BKDOK BIT(5) /* AC_BK DMA OK */ | ||
581 | #define IMR_BEDOK BIT(4) /* AC_BE DMA OK */ | ||
582 | #define IMR_VIDOK BIT(3) /* AC_VI DMA OK */ | ||
583 | #define IMR_VODOK BIT(2) /* AC_VO DMA OK */ | ||
584 | #define IMR_RDU BIT(1) /* Rx Descriptor Unavailable */ | ||
585 | #define IMR_ROK BIT(0) /* Receive DMA OK */ | ||
586 | |||
587 | /* IMR DW1(0x00B4-00B7) Bit 0-31 */ | ||
588 | #define IMR_BCNDMAINT7 BIT(27) /* Beacon DMA Interrupt 7 */ | ||
589 | #define IMR_BCNDMAINT6 BIT(26) /* Beacon DMA Interrupt 6 */ | ||
590 | #define IMR_BCNDMAINT5 BIT(25) /* Beacon DMA Interrupt 5 */ | ||
591 | #define IMR_BCNDMAINT4 BIT(24) /* Beacon DMA Interrupt 4 */ | ||
592 | #define IMR_BCNDMAINT3 BIT(23) /* Beacon DMA Interrupt 3 */ | ||
593 | #define IMR_BCNDMAINT2 BIT(22) /* Beacon DMA Interrupt 2 */ | ||
594 | #define IMR_BCNDMAINT1 BIT(21) /* Beacon DMA Interrupt 1 */ | ||
595 | #define IMR_BCNDOK7 BIT(20) /* Beacon Queue DMA OK Interrup 7 */ | ||
596 | #define IMR_BCNDOK6 BIT(19) /* Beacon Queue DMA OK Interrup 6 */ | ||
597 | #define IMR_BCNDOK5 BIT(18) /* Beacon Queue DMA OK Interrup 5 */ | ||
598 | #define IMR_BCNDOK4 BIT(17) /* Beacon Queue DMA OK Interrup 4 */ | ||
599 | #define IMR_BCNDOK3 BIT(16) /* Beacon Queue DMA OK Interrup 3 */ | ||
600 | #define IMR_BCNDOK2 BIT(15) /* Beacon Queue DMA OK Interrup 2 */ | ||
601 | #define IMR_BCNDOK1 BIT(14) /* Beacon Queue DMA OK Interrup 1 */ | ||
602 | #define IMR_ATIMEND_E BIT(13) /* ATIM Window End Extension for Win7 */ | ||
603 | #define IMR_TXERR BIT(11) /* Tx Err Flag Int Status, | ||
604 | * write 1 clear. | ||
605 | */ | ||
606 | #define IMR_RXERR BIT(10) /* Rx Err Flag INT Status, | ||
607 | * Write 1 clear | ||
608 | */ | ||
609 | #define IMR_TXFOVW BIT(9) /* Transmit FIFO Overflow */ | ||
610 | #define IMR_RXFOVW BIT(8) /* Receive FIFO Overflow */ | ||
611 | |||
612 | |||
613 | #define HWSET_MAX_SIZE 512 | ||
614 | #define EFUSE_MAX_SECTION 64 | ||
615 | #define EFUSE_REAL_CONTENT_LEN 256 | ||
616 | #define EFUSE_OOB_PROTECT_BYTES 18 /* PG data exclude header, | ||
617 | * dummy 7 bytes frome CP | ||
618 | * test and reserved 1byte. | ||
619 | */ | ||
620 | |||
621 | #define EEPROM_DEFAULT_TSSI 0x0 | ||
622 | #define EEPROM_DEFAULT_TXPOWERDIFF 0x0 | ||
623 | #define EEPROM_DEFAULT_CRYSTALCAP 0x5 | ||
624 | #define EEPROM_DEFAULT_BOARDTYPE 0x02 | ||
625 | #define EEPROM_DEFAULT_TXPOWER 0x1010 | ||
626 | #define EEPROM_DEFAULT_HT2T_TXPWR 0x10 | ||
627 | |||
628 | #define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 | ||
629 | #define EEPROM_DEFAULT_THERMALMETER 0x18 | ||
630 | #define EEPROM_DEFAULT_ANTTXPOWERDIFF 0x0 | ||
631 | #define EEPROM_DEFAULT_TXPWDIFF_CRYSTALCAP 0x5 | ||
632 | #define EEPROM_DEFAULT_TXPOWERLEVEL 0x22 | ||
633 | #define EEPROM_DEFAULT_HT40_2SDIFF 0x0 | ||
634 | #define EEPROM_DEFAULT_HT20_DIFF 2 | ||
635 | #define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 | ||
636 | #define EEPROM_DEFAULT_HT40_PWRMAXOFFSET 0 | ||
637 | #define EEPROM_DEFAULT_HT20_PWRMAXOFFSET 0 | ||
638 | |||
639 | #define RF_OPTION1 0x79 | ||
640 | #define RF_OPTION2 0x7A | ||
641 | #define RF_OPTION3 0x7B | ||
642 | #define RF_OPTION4 0x7C | ||
643 | |||
644 | #define EEPROM_DEFAULT_PID 0x1234 | ||
645 | #define EEPROM_DEFAULT_VID 0x5678 | ||
646 | #define EEPROM_DEFAULT_CUSTOMERID 0xAB | ||
647 | #define EEPROM_DEFAULT_SUBCUSTOMERID 0xCD | ||
648 | #define EEPROM_DEFAULT_VERSION 0 | ||
649 | |||
650 | #define EEPROM_CHANNEL_PLAN_FCC 0x0 | ||
651 | #define EEPROM_CHANNEL_PLAN_IC 0x1 | ||
652 | #define EEPROM_CHANNEL_PLAN_ETSI 0x2 | ||
653 | #define EEPROM_CHANNEL_PLAN_SPAIN 0x3 | ||
654 | #define EEPROM_CHANNEL_PLAN_FRANCE 0x4 | ||
655 | #define EEPROM_CHANNEL_PLAN_MKK 0x5 | ||
656 | #define EEPROM_CHANNEL_PLAN_MKK1 0x6 | ||
657 | #define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 | ||
658 | #define EEPROM_CHANNEL_PLAN_TELEC 0x8 | ||
659 | #define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 | ||
660 | #define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA | ||
661 | #define EEPROM_CHANNEL_PLAN_NCC 0xB | ||
662 | #define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 | ||
663 | |||
664 | #define EEPROM_CID_DEFAULT 0x0 | ||
665 | #define EEPROM_CID_TOSHIBA 0x4 | ||
666 | #define EEPROM_CID_CCX 0x10 | ||
667 | #define EEPROM_CID_QMI 0x0D | ||
668 | #define EEPROM_CID_WHQL 0xFE | ||
669 | |||
670 | #define RTL8188E_EEPROM_ID 0x8129 | ||
671 | |||
672 | #define EEPROM_HPON 0x02 | ||
673 | #define EEPROM_CLK 0x06 | ||
674 | #define EEPROM_TESTR 0x08 | ||
675 | |||
676 | #define EEPROM_TXPOWERCCK 0x10 | ||
677 | #define EEPROM_TXPOWERHT40_1S 0x16 | ||
678 | #define EEPROM_TXPOWERHT20DIFF 0x1B | ||
679 | #define EEPROM_TXPOWER_OFDMDIFF 0x1B | ||
680 | |||
681 | #define EEPROM_TX_PWR_INX 0x10 | ||
682 | |||
683 | #define EEPROM_CHANNELPLAN 0xB8 | ||
684 | #define EEPROM_XTAL_88E 0xB9 | ||
685 | #define EEPROM_THERMAL_METER_88E 0xBA | ||
686 | #define EEPROM_IQK_LCK_88E 0xBB | ||
687 | |||
688 | #define EEPROM_RF_BOARD_OPTION_88E 0xC1 | ||
689 | #define EEPROM_RF_FEATURE_OPTION_88E 0xC2 | ||
690 | #define EEPROM_RF_BT_SETTING_88E 0xC3 | ||
691 | #define EEPROM_VERSION 0xC4 | ||
692 | #define EEPROM_CUSTOMER_ID 0xC5 | ||
693 | #define EEPROM_RF_ANTENNA_OPT_88E 0xC9 | ||
694 | |||
695 | #define EEPROM_MAC_ADDR 0xD0 | ||
696 | #define EEPROM_VID 0xD6 | ||
697 | #define EEPROM_DID 0xD8 | ||
698 | #define EEPROM_SVID 0xDA | ||
699 | #define EEPROM_SMID 0xDC | ||
700 | |||
701 | #define STOPBECON BIT(6) | ||
702 | #define STOPHIGHT BIT(5) | ||
703 | #define STOPMGT BIT(4) | ||
704 | #define STOPVO BIT(3) | ||
705 | #define STOPVI BIT(2) | ||
706 | #define STOPBE BIT(1) | ||
707 | #define STOPBK BIT(0) | ||
708 | |||
709 | #define RCR_APPFCS BIT(31) | ||
710 | #define RCR_APP_MIC BIT(30) | ||
711 | #define RCR_APP_ICV BIT(29) | ||
712 | #define RCR_APP_PHYST_RXFF BIT(28) | ||
713 | #define RCR_APP_BA_SSN BIT(27) | ||
714 | #define RCR_ENMBID BIT(24) | ||
715 | #define RCR_LSIGEN BIT(23) | ||
716 | #define RCR_MFBEN BIT(22) | ||
717 | #define RCR_HTC_LOC_CTRL BIT(14) | ||
718 | #define RCR_AMF BIT(13) | ||
719 | #define RCR_ACF BIT(12) | ||
720 | #define RCR_ADF BIT(11) | ||
721 | #define RCR_AICV BIT(9) | ||
722 | #define RCR_ACRC32 BIT(8) | ||
723 | #define RCR_CBSSID_BCN BIT(7) | ||
724 | #define RCR_CBSSID_DATA BIT(6) | ||
725 | #define RCR_CBSSID RCR_CBSSID_DATA | ||
726 | #define RCR_APWRMGT BIT(5) | ||
727 | #define RCR_ADD3 BIT(4) | ||
728 | #define RCR_AB BIT(3) | ||
729 | #define RCR_AM BIT(2) | ||
730 | #define RCR_APM BIT(1) | ||
731 | #define RCR_AAP BIT(0) | ||
732 | #define RCR_MXDMA_OFFSET 8 | ||
733 | #define RCR_FIFO_OFFSET 13 | ||
734 | |||
735 | #define RSV_CTRL 0x001C | ||
736 | #define RD_CTRL 0x0524 | ||
737 | |||
738 | #define REG_USB_INFO 0xFE17 | ||
739 | #define REG_USB_SPECIAL_OPTION 0xFE55 | ||
740 | #define REG_USB_DMA_AGG_TO 0xFE5B | ||
741 | #define REG_USB_AGG_TO 0xFE5C | ||
742 | #define REG_USB_AGG_TH 0xFE5D | ||
743 | |||
744 | #define REG_USB_VID 0xFE60 | ||
745 | #define REG_USB_PID 0xFE62 | ||
746 | #define REG_USB_OPTIONAL 0xFE64 | ||
747 | #define REG_USB_CHIRP_K 0xFE65 | ||
748 | #define REG_USB_PHY 0xFE66 | ||
749 | #define REG_USB_MAC_ADDR 0xFE70 | ||
750 | #define REG_USB_HRPWM 0xFE58 | ||
751 | #define REG_USB_HCPWM 0xFE57 | ||
752 | |||
753 | #define SW18_FPWM BIT(3) | ||
754 | |||
755 | #define ISO_MD2PP BIT(0) | ||
756 | #define ISO_UA2USB BIT(1) | ||
757 | #define ISO_UD2CORE BIT(2) | ||
758 | #define ISO_PA2PCIE BIT(3) | ||
759 | #define ISO_PD2CORE BIT(4) | ||
760 | #define ISO_IP2MAC BIT(5) | ||
761 | #define ISO_DIOP BIT(6) | ||
762 | #define ISO_DIOE BIT(7) | ||
763 | #define ISO_EB2CORE BIT(8) | ||
764 | #define ISO_DIOR BIT(9) | ||
765 | |||
766 | #define PWC_EV25V BIT(14) | ||
767 | #define PWC_EV12V BIT(15) | ||
768 | |||
769 | #define FEN_BBRSTB BIT(0) | ||
770 | #define FEN_BB_GLB_RSTN BIT(1) | ||
771 | #define FEN_USBA BIT(2) | ||
772 | #define FEN_UPLL BIT(3) | ||
773 | #define FEN_USBD BIT(4) | ||
774 | #define FEN_DIO_PCIE BIT(5) | ||
775 | #define FEN_PCIEA BIT(6) | ||
776 | #define FEN_PPLL BIT(7) | ||
777 | #define FEN_PCIED BIT(8) | ||
778 | #define FEN_DIOE BIT(9) | ||
779 | #define FEN_CPUEN BIT(10) | ||
780 | #define FEN_DCORE BIT(11) | ||
781 | #define FEN_ELDR BIT(12) | ||
782 | #define FEN_DIO_RF BIT(13) | ||
783 | #define FEN_HWPDN BIT(14) | ||
784 | #define FEN_MREGEN BIT(15) | ||
785 | |||
786 | #define PFM_LDALL BIT(0) | ||
787 | #define PFM_ALDN BIT(1) | ||
788 | #define PFM_LDKP BIT(2) | ||
789 | #define PFM_WOWL BIT(3) | ||
790 | #define ENPDN BIT(4) | ||
791 | #define PDN_PL BIT(5) | ||
792 | #define APFM_ONMAC BIT(8) | ||
793 | #define APFM_OFF BIT(9) | ||
794 | #define APFM_RSM BIT(10) | ||
795 | #define AFSM_HSUS BIT(11) | ||
796 | #define AFSM_PCIE BIT(12) | ||
797 | #define APDM_MAC BIT(13) | ||
798 | #define APDM_HOST BIT(14) | ||
799 | #define APDM_HPDN BIT(15) | ||
800 | #define RDY_MACON BIT(16) | ||
801 | #define SUS_HOST BIT(17) | ||
802 | #define ROP_ALD BIT(20) | ||
803 | #define ROP_PWR BIT(21) | ||
804 | #define ROP_SPS BIT(22) | ||
805 | #define SOP_MRST BIT(25) | ||
806 | #define SOP_FUSE BIT(26) | ||
807 | #define SOP_ABG BIT(27) | ||
808 | #define SOP_AMB BIT(28) | ||
809 | #define SOP_RCK BIT(29) | ||
810 | #define SOP_A8M BIT(30) | ||
811 | #define XOP_BTCK BIT(31) | ||
812 | |||
813 | #define ANAD16V_EN BIT(0) | ||
814 | #define ANA8M BIT(1) | ||
815 | #define MACSLP BIT(4) | ||
816 | #define LOADER_CLK_EN BIT(5) | ||
817 | #define _80M_SSC_DIS BIT(7) | ||
818 | #define _80M_SSC_EN_HO BIT(8) | ||
819 | #define PHY_SSC_RSTB BIT(9) | ||
820 | #define SEC_CLK_EN BIT(10) | ||
821 | #define MAC_CLK_EN BIT(11) | ||
822 | #define SYS_CLK_EN BIT(12) | ||
823 | #define RING_CLK_EN BIT(13) | ||
824 | |||
825 | #define BOOT_FROM_EEPROM BIT(4) | ||
826 | #define EEPROM_EN BIT(5) | ||
827 | |||
828 | #define AFE_BGEN BIT(0) | ||
829 | #define AFE_MBEN BIT(1) | ||
830 | #define MAC_ID_EN BIT(7) | ||
831 | |||
832 | #define WLOCK_ALL BIT(0) | ||
833 | #define WLOCK_00 BIT(1) | ||
834 | #define WLOCK_04 BIT(2) | ||
835 | #define WLOCK_08 BIT(3) | ||
836 | #define WLOCK_40 BIT(4) | ||
837 | #define R_DIS_PRST_0 BIT(5) | ||
838 | #define R_DIS_PRST_1 BIT(6) | ||
839 | #define LOCK_ALL_EN BIT(7) | ||
840 | |||
841 | #define RF_EN BIT(0) | ||
842 | #define RF_RSTB BIT(1) | ||
843 | #define RF_SDMRSTB BIT(2) | ||
844 | |||
845 | #define LDA15_EN BIT(0) | ||
846 | #define LDA15_STBY BIT(1) | ||
847 | #define LDA15_OBUF BIT(2) | ||
848 | #define LDA15_REG_VOS BIT(3) | ||
849 | #define _LDA15_VOADJ(x) (((x) & 0x7) << 4) | ||
850 | |||
851 | #define LDV12_EN BIT(0) | ||
852 | #define LDV12_SDBY BIT(1) | ||
853 | #define LPLDO_HSM BIT(2) | ||
854 | #define LPLDO_LSM_DIS BIT(3) | ||
855 | #define _LDV12_VADJ(x) (((x) & 0xF) << 4) | ||
856 | |||
857 | #define XTAL_EN BIT(0) | ||
858 | #define XTAL_BSEL BIT(1) | ||
859 | #define _XTAL_BOSC(x) (((x) & 0x3) << 2) | ||
860 | #define _XTAL_CADJ(x) (((x) & 0xF) << 4) | ||
861 | #define XTAL_GATE_USB BIT(8) | ||
862 | #define _XTAL_USB_DRV(x) (((x) & 0x3) << 9) | ||
863 | #define XTAL_GATE_AFE BIT(11) | ||
864 | #define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12) | ||
865 | #define XTAL_RF_GATE BIT(14) | ||
866 | #define _XTAL_RF_DRV(x) (((x) & 0x3) << 15) | ||
867 | #define XTAL_GATE_DIG BIT(17) | ||
868 | #define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18) | ||
869 | #define XTAL_BT_GATE BIT(20) | ||
870 | #define _XTAL_BT_DRV(x) (((x) & 0x3) << 21) | ||
871 | #define _XTAL_GPIO(x) (((x) & 0x7) << 23) | ||
872 | |||
873 | #define CKDLY_AFE BIT(26) | ||
874 | #define CKDLY_USB BIT(27) | ||
875 | #define CKDLY_DIG BIT(28) | ||
876 | #define CKDLY_BT BIT(29) | ||
877 | |||
878 | #define APLL_EN BIT(0) | ||
879 | #define APLL_320_EN BIT(1) | ||
880 | #define APLL_FREF_SEL BIT(2) | ||
881 | #define APLL_EDGE_SEL BIT(3) | ||
882 | #define APLL_WDOGB BIT(4) | ||
883 | #define APLL_LPFEN BIT(5) | ||
884 | |||
885 | #define APLL_REF_CLK_13MHZ 0x1 | ||
886 | #define APLL_REF_CLK_19_2MHZ 0x2 | ||
887 | #define APLL_REF_CLK_20MHZ 0x3 | ||
888 | #define APLL_REF_CLK_25MHZ 0x4 | ||
889 | #define APLL_REF_CLK_26MHZ 0x5 | ||
890 | #define APLL_REF_CLK_38_4MHZ 0x6 | ||
891 | #define APLL_REF_CLK_40MHZ 0x7 | ||
892 | |||
893 | #define APLL_320EN BIT(14) | ||
894 | #define APLL_80EN BIT(15) | ||
895 | #define APLL_1MEN BIT(24) | ||
896 | |||
897 | #define ALD_EN BIT(18) | ||
898 | #define EF_PD BIT(19) | ||
899 | #define EF_FLAG BIT(31) | ||
900 | |||
901 | #define EF_TRPT BIT(7) | ||
902 | #define LDOE25_EN BIT(31) | ||
903 | |||
904 | #define RSM_EN BIT(0) | ||
905 | #define TIMER_EN BIT(4) | ||
906 | |||
907 | #define TRSW0EN BIT(2) | ||
908 | #define TRSW1EN BIT(3) | ||
909 | #define EROM_EN BIT(4) | ||
910 | #define ENBT BIT(5) | ||
911 | #define ENUART BIT(8) | ||
912 | #define UART_910 BIT(9) | ||
913 | #define ENPMAC BIT(10) | ||
914 | #define SIC_SWRST BIT(11) | ||
915 | #define ENSIC BIT(12) | ||
916 | #define SIC_23 BIT(13) | ||
917 | #define ENHDP BIT(14) | ||
918 | #define SIC_LBK BIT(15) | ||
919 | |||
920 | #define LED0PL BIT(4) | ||
921 | #define LED1PL BIT(12) | ||
922 | #define LED0DIS BIT(7) | ||
923 | |||
924 | #define MCUFWDL_EN BIT(0) | ||
925 | #define MCUFWDL_RDY BIT(1) | ||
926 | #define FWDL_CHKSUM_RPT BIT(2) | ||
927 | #define MACINI_RDY BIT(3) | ||
928 | #define BBINI_RDY BIT(4) | ||
929 | #define RFINI_RDY BIT(5) | ||
930 | #define WINTINI_RDY BIT(6) | ||
931 | #define CPRST BIT(23) | ||
932 | |||
933 | #define XCLK_VLD BIT(0) | ||
934 | #define ACLK_VLD BIT(1) | ||
935 | #define UCLK_VLD BIT(2) | ||
936 | #define PCLK_VLD BIT(3) | ||
937 | #define PCIRSTB BIT(4) | ||
938 | #define V15_VLD BIT(5) | ||
939 | #define TRP_B15V_EN BIT(7) | ||
940 | #define SIC_IDLE BIT(8) | ||
941 | #define BD_MAC2 BIT(9) | ||
942 | #define BD_MAC1 BIT(10) | ||
943 | #define IC_MACPHY_MODE BIT(11) | ||
944 | #define VENDOR_ID BIT(19) | ||
945 | #define PAD_HWPD_IDN BIT(22) | ||
946 | #define TRP_VAUX_EN BIT(23) | ||
947 | #define TRP_BT_EN BIT(24) | ||
948 | #define BD_PKG_SEL BIT(25) | ||
949 | #define BD_HCI_SEL BIT(26) | ||
950 | #define TYPE_ID BIT(27) | ||
951 | |||
952 | #define CHIP_VER_RTL_MASK 0xF000 | ||
953 | #define CHIP_VER_RTL_SHIFT 12 | ||
954 | |||
955 | #define REG_LBMODE (REG_CR + 3) | ||
956 | |||
957 | #define HCI_TXDMA_EN BIT(0) | ||
958 | #define HCI_RXDMA_EN BIT(1) | ||
959 | #define TXDMA_EN BIT(2) | ||
960 | #define RXDMA_EN BIT(3) | ||
961 | #define PROTOCOL_EN BIT(4) | ||
962 | #define SCHEDULE_EN BIT(5) | ||
963 | #define MACTXEN BIT(6) | ||
964 | #define MACRXEN BIT(7) | ||
965 | #define ENSWBCN BIT(8) | ||
966 | #define ENSEC BIT(9) | ||
967 | |||
968 | #define _NETTYPE(x) (((x) & 0x3) << 16) | ||
969 | #define MASK_NETTYPE 0x30000 | ||
970 | #define NT_NO_LINK 0x0 | ||
971 | #define NT_LINK_AD_HOC 0x1 | ||
972 | #define NT_LINK_AP 0x2 | ||
973 | #define NT_AS_AP 0x3 | ||
974 | |||
975 | #define _LBMODE(x) (((x) & 0xF) << 24) | ||
976 | #define MASK_LBMODE 0xF000000 | ||
977 | #define LOOPBACK_NORMAL 0x0 | ||
978 | #define LOOPBACK_IMMEDIATELY 0xB | ||
979 | #define LOOPBACK_MAC_DELAY 0x3 | ||
980 | #define LOOPBACK_PHY 0x1 | ||
981 | #define LOOPBACK_DMA 0x7 | ||
982 | |||
983 | #define GET_RX_PAGE_SIZE(value) ((value) & 0xF) | ||
984 | #define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4) | ||
985 | #define _PSRX_MASK 0xF | ||
986 | #define _PSTX_MASK 0xF0 | ||
987 | #define _PSRX(x) (x) | ||
988 | #define _PSTX(x) ((x) << 4) | ||
989 | |||
990 | #define PBP_64 0x0 | ||
991 | #define PBP_128 0x1 | ||
992 | #define PBP_256 0x2 | ||
993 | #define PBP_512 0x3 | ||
994 | #define PBP_1024 0x4 | ||
995 | |||
996 | #define RXDMA_ARBBW_EN BIT(0) | ||
997 | #define RXSHFT_EN BIT(1) | ||
998 | #define RXDMA_AGG_EN BIT(2) | ||
999 | #define QS_VO_QUEUE BIT(8) | ||
1000 | #define QS_VI_QUEUE BIT(9) | ||
1001 | #define QS_BE_QUEUE BIT(10) | ||
1002 | #define QS_BK_QUEUE BIT(11) | ||
1003 | #define QS_MANAGER_QUEUE BIT(12) | ||
1004 | #define QS_HIGH_QUEUE BIT(13) | ||
1005 | |||
1006 | #define HQSEL_VOQ BIT(0) | ||
1007 | #define HQSEL_VIQ BIT(1) | ||
1008 | #define HQSEL_BEQ BIT(2) | ||
1009 | #define HQSEL_BKQ BIT(3) | ||
1010 | #define HQSEL_MGTQ BIT(4) | ||
1011 | #define HQSEL_HIQ BIT(5) | ||
1012 | |||
1013 | #define _TXDMA_HIQ_MAP(x) (((x)&0x3) << 14) | ||
1014 | #define _TXDMA_MGQ_MAP(x) (((x)&0x3) << 12) | ||
1015 | #define _TXDMA_BKQ_MAP(x) (((x)&0x3) << 10) | ||
1016 | #define _TXDMA_BEQ_MAP(x) (((x)&0x3) << 8) | ||
1017 | #define _TXDMA_VIQ_MAP(x) (((x)&0x3) << 6) | ||
1018 | #define _TXDMA_VOQ_MAP(x) (((x)&0x3) << 4) | ||
1019 | |||
1020 | #define QUEUE_LOW 1 | ||
1021 | #define QUEUE_NORMAL 2 | ||
1022 | #define QUEUE_HIGH 3 | ||
1023 | |||
1024 | #define _LLT_NO_ACTIVE 0x0 | ||
1025 | #define _LLT_WRITE_ACCESS 0x1 | ||
1026 | #define _LLT_READ_ACCESS 0x2 | ||
1027 | |||
1028 | #define _LLT_INIT_DATA(x) ((x) & 0xFF) | ||
1029 | #define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8) | ||
1030 | #define _LLT_OP(x) (((x) & 0x3) << 30) | ||
1031 | #define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3) | ||
1032 | |||
1033 | #define BB_WRITE_READ_MASK (BIT(31) | BIT(30)) | ||
1034 | #define BB_WRITE_EN BIT(30) | ||
1035 | #define BB_READ_EN BIT(31) | ||
1036 | |||
1037 | #define _HPQ(x) ((x) & 0xFF) | ||
1038 | #define _LPQ(x) (((x) & 0xFF) << 8) | ||
1039 | #define _PUBQ(x) (((x) & 0xFF) << 16) | ||
1040 | #define _NPQ(x) ((x) & 0xFF) | ||
1041 | |||
1042 | #define HPQ_PUBLIC_DIS BIT(24) | ||
1043 | #define LPQ_PUBLIC_DIS BIT(25) | ||
1044 | #define LD_RQPN BIT(31) | ||
1045 | |||
1046 | #define BCN_VALID BIT(16) | ||
1047 | #define BCN_HEAD(x) (((x) & 0xFF) << 8) | ||
1048 | #define BCN_HEAD_MASK 0xFF00 | ||
1049 | |||
1050 | #define BLK_DESC_NUM_SHIFT 4 | ||
1051 | #define BLK_DESC_NUM_MASK 0xF | ||
1052 | |||
1053 | #define DROP_DATA_EN BIT(9) | ||
1054 | |||
1055 | #define EN_AMPDU_RTY_NEW BIT(7) | ||
1056 | |||
1057 | #define _INIRTSMCS_SEL(x) ((x) & 0x3F) | ||
1058 | |||
1059 | #define _SPEC_SIFS_CCK(x) ((x) & 0xFF) | ||
1060 | #define _SPEC_SIFS_OFDM(x) (((x) & 0xFF) << 8) | ||
1061 | |||
1062 | #define RATE_REG_BITMAP_ALL 0xFFFFF | ||
1063 | |||
1064 | #define _RRSC_BITMAP(x) ((x) & 0xFFFFF) | ||
1065 | |||
1066 | #define _RRSR_RSC(x) (((x) & 0x3) << 21) | ||
1067 | #define RRSR_RSC_RESERVED 0x0 | ||
1068 | #define RRSR_RSC_UPPER_SUBCHANNEL 0x1 | ||
1069 | #define RRSR_RSC_LOWER_SUBCHANNEL 0x2 | ||
1070 | #define RRSR_RSC_DUPLICATE_MODE 0x3 | ||
1071 | |||
1072 | #define USE_SHORT_G1 BIT(20) | ||
1073 | |||
1074 | #define _AGGLMT_MCS0(x) ((x) & 0xF) | ||
1075 | #define _AGGLMT_MCS1(x) (((x) & 0xF) << 4) | ||
1076 | #define _AGGLMT_MCS2(x) (((x) & 0xF) << 8) | ||
1077 | #define _AGGLMT_MCS3(x) (((x) & 0xF) << 12) | ||
1078 | #define _AGGLMT_MCS4(x) (((x) & 0xF) << 16) | ||
1079 | #define _AGGLMT_MCS5(x) (((x) & 0xF) << 20) | ||
1080 | #define _AGGLMT_MCS6(x) (((x) & 0xF) << 24) | ||
1081 | #define _AGGLMT_MCS7(x) (((x) & 0xF) << 28) | ||
1082 | |||
1083 | #define RETRY_LIMIT_SHORT_SHIFT 8 | ||
1084 | #define RETRY_LIMIT_LONG_SHIFT 0 | ||
1085 | |||
1086 | #define _DARF_RC1(x) ((x) & 0x1F) | ||
1087 | #define _DARF_RC2(x) (((x) & 0x1F) << 8) | ||
1088 | #define _DARF_RC3(x) (((x) & 0x1F) << 16) | ||
1089 | #define _DARF_RC4(x) (((x) & 0x1F) << 24) | ||
1090 | #define _DARF_RC5(x) ((x) & 0x1F) | ||
1091 | #define _DARF_RC6(x) (((x) & 0x1F) << 8) | ||
1092 | #define _DARF_RC7(x) (((x) & 0x1F) << 16) | ||
1093 | #define _DARF_RC8(x) (((x) & 0x1F) << 24) | ||
1094 | |||
1095 | #define _RARF_RC1(x) ((x) & 0x1F) | ||
1096 | #define _RARF_RC2(x) (((x) & 0x1F) << 8) | ||
1097 | #define _RARF_RC3(x) (((x) & 0x1F) << 16) | ||
1098 | #define _RARF_RC4(x) (((x) & 0x1F) << 24) | ||
1099 | #define _RARF_RC5(x) ((x) & 0x1F) | ||
1100 | #define _RARF_RC6(x) (((x) & 0x1F) << 8) | ||
1101 | #define _RARF_RC7(x) (((x) & 0x1F) << 16) | ||
1102 | #define _RARF_RC8(x) (((x) & 0x1F) << 24) | ||
1103 | |||
1104 | #define AC_PARAM_TXOP_LIMIT_OFFSET 16 | ||
1105 | #define AC_PARAM_ECW_MAX_OFFSET 12 | ||
1106 | #define AC_PARAM_ECW_MIN_OFFSET 8 | ||
1107 | #define AC_PARAM_AIFS_OFFSET 0 | ||
1108 | |||
1109 | #define _AIFS(x) (x) | ||
1110 | #define _ECW_MAX_MIN(x) ((x) << 8) | ||
1111 | #define _TXOP_LIMIT(x) ((x) << 16) | ||
1112 | |||
1113 | #define _BCNIFS(x) ((x) & 0xFF) | ||
1114 | #define _BCNECW(x) ((((x) & 0xF)) << 8) | ||
1115 | |||
1116 | #define _LRL(x) ((x) & 0x3F) | ||
1117 | #define _SRL(x) (((x) & 0x3F) << 8) | ||
1118 | |||
1119 | #define _SIFS_CCK_CTX(x) ((x) & 0xFF) | ||
1120 | #define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8); | ||
1121 | |||
1122 | #define _SIFS_OFDM_CTX(x) ((x) & 0xFF) | ||
1123 | #define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8); | ||
1124 | |||
1125 | #define _TBTT_PROHIBIT_HOLD(x) (((x) & 0xFF) << 8) | ||
1126 | |||
1127 | #define DIS_EDCA_CNT_DWN BIT(11) | ||
1128 | |||
1129 | #define EN_MBSSID BIT(1) | ||
1130 | #define EN_TXBCN_RPT BIT(2) | ||
1131 | #define EN_BCN_FUNCTION BIT(3) | ||
1132 | |||
1133 | #define TSFTR_RST BIT(0) | ||
1134 | #define TSFTR1_RST BIT(1) | ||
1135 | |||
1136 | #define STOP_BCNQ BIT(6) | ||
1137 | |||
1138 | #define DIS_TSF_UDT0_NORMAL_CHIP BIT(4) | ||
1139 | #define DIS_TSF_UDT0_TEST_CHIP BIT(5) | ||
1140 | |||
1141 | #define ACMHW_HWEN BIT(0) | ||
1142 | #define ACMHW_BEQEN BIT(1) | ||
1143 | #define ACMHW_VIQEN BIT(2) | ||
1144 | #define ACMHW_VOQEN BIT(3) | ||
1145 | #define ACMHW_BEQSTATUS BIT(4) | ||
1146 | #define ACMHW_VIQSTATUS BIT(5) | ||
1147 | #define ACMHW_VOQSTATUS BIT(6) | ||
1148 | |||
1149 | #define APSDOFF BIT(6) | ||
1150 | #define APSDOFF_STATUS BIT(7) | ||
1151 | |||
1152 | #define BW_20MHZ BIT(2) | ||
1153 | |||
1154 | #define RATE_BITMAP_ALL 0xFFFFF | ||
1155 | |||
1156 | #define RATE_RRSR_CCK_ONLY_1M 0xFFFF1 | ||
1157 | |||
1158 | #define TSFRST BIT(0) | ||
1159 | #define DIS_GCLK BIT(1) | ||
1160 | #define PAD_SEL BIT(2) | ||
1161 | #define PWR_ST BIT(6) | ||
1162 | #define PWRBIT_OW_EN BIT(7) | ||
1163 | #define ACRC BIT(8) | ||
1164 | #define CFENDFORM BIT(9) | ||
1165 | #define ICV BIT(10) | ||
1166 | |||
1167 | #define AAP BIT(0) | ||
1168 | #define APM BIT(1) | ||
1169 | #define AM BIT(2) | ||
1170 | #define AB BIT(3) | ||
1171 | #define ADD3 BIT(4) | ||
1172 | #define APWRMGT BIT(5) | ||
1173 | #define CBSSID BIT(6) | ||
1174 | #define CBSSID_DATA BIT(6) | ||
1175 | #define CBSSID_BCN BIT(7) | ||
1176 | #define ACRC32 BIT(8) | ||
1177 | #define AICV BIT(9) | ||
1178 | #define ADF BIT(11) | ||
1179 | #define ACF BIT(12) | ||
1180 | #define AMF BIT(13) | ||
1181 | #define HTC_LOC_CTRL BIT(14) | ||
1182 | #define UC_DATA_EN BIT(16) | ||
1183 | #define BM_DATA_EN BIT(17) | ||
1184 | #define MFBEN BIT(22) | ||
1185 | #define LSIGEN BIT(23) | ||
1186 | #define ENMBID BIT(24) | ||
1187 | #define APP_BASSN BIT(27) | ||
1188 | #define APP_PHYSTS BIT(28) | ||
1189 | #define APP_ICV BIT(29) | ||
1190 | #define APP_MIC BIT(30) | ||
1191 | #define APP_FCS BIT(31) | ||
1192 | |||
1193 | #define _MIN_SPACE(x) ((x) & 0x7) | ||
1194 | #define _SHORT_GI_PADDING(x) (((x) & 0x1F) << 3) | ||
1195 | |||
1196 | #define RXERR_TYPE_OFDM_PPDU 0 | ||
1197 | #define RXERR_TYPE_OFDM_FALSE_ALARM 1 | ||
1198 | #define RXERR_TYPE_OFDM_MPDU_OK 2 | ||
1199 | #define RXERR_TYPE_OFDM_MPDU_FAIL 3 | ||
1200 | #define RXERR_TYPE_CCK_PPDU 4 | ||
1201 | #define RXERR_TYPE_CCK_FALSE_ALARM 5 | ||
1202 | #define RXERR_TYPE_CCK_MPDU_OK 6 | ||
1203 | #define RXERR_TYPE_CCK_MPDU_FAIL 7 | ||
1204 | #define RXERR_TYPE_HT_PPDU 8 | ||
1205 | #define RXERR_TYPE_HT_FALSE_ALARM 9 | ||
1206 | #define RXERR_TYPE_HT_MPDU_TOTAL 10 | ||
1207 | #define RXERR_TYPE_HT_MPDU_OK 11 | ||
1208 | #define RXERR_TYPE_HT_MPDU_FAIL 12 | ||
1209 | #define RXERR_TYPE_RX_FULL_DROP 15 | ||
1210 | |||
1211 | #define RXERR_COUNTER_MASK 0xFFFFF | ||
1212 | #define RXERR_RPT_RST BIT(27) | ||
1213 | #define _RXERR_RPT_SEL(type) ((type) << 28) | ||
1214 | |||
1215 | #define SCR_TXUSEDK BIT(0) | ||
1216 | #define SCR_RXUSEDK BIT(1) | ||
1217 | #define SCR_TXENCENABLE BIT(2) | ||
1218 | #define SCR_RXDECENABLE BIT(3) | ||
1219 | #define SCR_SKBYA2 BIT(4) | ||
1220 | #define SCR_NOSKMC BIT(5) | ||
1221 | #define SCR_TXBCUSEDK BIT(6) | ||
1222 | #define SCR_RXBCUSEDK BIT(7) | ||
1223 | |||
1224 | #define USB_IS_HIGH_SPEED 0 | ||
1225 | #define USB_IS_FULL_SPEED 1 | ||
1226 | #define USB_SPEED_MASK BIT(5) | ||
1227 | |||
1228 | #define USB_NORMAL_SIE_EP_MASK 0xF | ||
1229 | #define USB_NORMAL_SIE_EP_SHIFT 4 | ||
1230 | |||
1231 | #define USB_TEST_EP_MASK 0x30 | ||
1232 | #define USB_TEST_EP_SHIFT 4 | ||
1233 | |||
1234 | #define USB_AGG_EN BIT(3) | ||
1235 | |||
1236 | #define MAC_ADDR_LEN 6 | ||
1237 | #define LAST_ENTRY_OF_TX_PKT_BUFFER 175/*255 88e*/ | ||
1238 | |||
1239 | #define POLLING_LLT_THRESHOLD 20 | ||
1240 | #define POLLING_READY_TIMEOUT_COUNT 3000 | ||
1241 | |||
1242 | #define MAX_MSS_DENSITY_2T 0x13 | ||
1243 | #define MAX_MSS_DENSITY_1T 0x0A | ||
1244 | |||
1245 | #define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6)) | ||
1246 | #define EPROM_CMD_CONFIG 0x3 | ||
1247 | #define EPROM_CMD_LOAD 1 | ||
1248 | |||
1249 | #define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE | ||
1250 | |||
1251 | #define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) | ||
1252 | |||
1253 | #define RPMAC_RESET 0x100 | ||
1254 | #define RPMAC_TXSTART 0x104 | ||
1255 | #define RPMAC_TXLEGACYSIG 0x108 | ||
1256 | #define RPMAC_TXHTSIG1 0x10c | ||
1257 | #define RPMAC_TXHTSIG2 0x110 | ||
1258 | #define RPMAC_PHYDEBUG 0x114 | ||
1259 | #define RPMAC_TXPACKETNUM 0x118 | ||
1260 | #define RPMAC_TXIDLE 0x11c | ||
1261 | #define RPMAC_TXMACHEADER0 0x120 | ||
1262 | #define RPMAC_TXMACHEADER1 0x124 | ||
1263 | #define RPMAC_TXMACHEADER2 0x128 | ||
1264 | #define RPMAC_TXMACHEADER3 0x12c | ||
1265 | #define RPMAC_TXMACHEADER4 0x130 | ||
1266 | #define RPMAC_TXMACHEADER5 0x134 | ||
1267 | #define RPMAC_TXDADATYPE 0x138 | ||
1268 | #define RPMAC_TXRANDOMSEED 0x13c | ||
1269 | #define RPMAC_CCKPLCPPREAMBLE 0x140 | ||
1270 | #define RPMAC_CCKPLCPHEADER 0x144 | ||
1271 | #define RPMAC_CCKCRC16 0x148 | ||
1272 | #define RPMAC_OFDMRXCRC32OK 0x170 | ||
1273 | #define RPMAC_OFDMRXCRC32Er 0x174 | ||
1274 | #define RPMAC_OFDMRXPARITYER 0x178 | ||
1275 | #define RPMAC_OFDMRXCRC8ER 0x17c | ||
1276 | #define RPMAC_CCKCRXRC16ER 0x180 | ||
1277 | #define RPMAC_CCKCRXRC32ER 0x184 | ||
1278 | #define RPMAC_CCKCRXRC32OK 0x188 | ||
1279 | #define RPMAC_TXSTATUS 0x18c | ||
1280 | |||
1281 | #define RFPGA0_RFMOD 0x800 | ||
1282 | |||
1283 | #define RFPGA0_TXINFO 0x804 | ||
1284 | #define RFPGA0_PSDFUNCTION 0x808 | ||
1285 | |||
1286 | #define RFPGA0_TXGAINSTAGE 0x80c | ||
1287 | |||
1288 | #define RFPGA0_RFTIMING1 0x810 | ||
1289 | #define RFPGA0_RFTIMING2 0x814 | ||
1290 | |||
1291 | #define RFPGA0_XA_HSSIPARAMETER1 0x820 | ||
1292 | #define RFPGA0_XA_HSSIPARAMETER2 0x824 | ||
1293 | #define RFPGA0_XB_HSSIPARAMETER1 0x828 | ||
1294 | #define RFPGA0_XB_HSSIPARAMETER2 0x82c | ||
1295 | |||
1296 | #define RFPGA0_XA_LSSIPARAMETER 0x840 | ||
1297 | #define RFPGA0_XB_LSSIPARAMETER 0x844 | ||
1298 | |||
1299 | #define RFPGA0_RFWAKEUPPARAMETER 0x850 | ||
1300 | #define RFPGA0_RFSLEEPUPPARAMETER 0x854 | ||
1301 | |||
1302 | #define RFPGA0_XAB_SWITCHCONTROL 0x858 | ||
1303 | #define RFPGA0_XCD_SWITCHCONTROL 0x85c | ||
1304 | |||
1305 | #define RFPGA0_XA_RFINTERFACEOE 0x860 | ||
1306 | #define RFPGA0_XB_RFINTERFACEOE 0x864 | ||
1307 | |||
1308 | #define RFPGA0_XAB_RFINTERFACESW 0x870 | ||
1309 | #define RFPGA0_XCD_RFINTERFACESW 0x874 | ||
1310 | |||
1311 | #define rFPGA0_XAB_RFPARAMETER 0x878 | ||
1312 | #define rFPGA0_XCD_RFPARAMETER 0x87c | ||
1313 | |||
1314 | #define RFPGA0_ANALOGPARAMETER1 0x880 | ||
1315 | #define RFPGA0_ANALOGPARAMETER2 0x884 | ||
1316 | #define RFPGA0_ANALOGPARAMETER3 0x888 | ||
1317 | #define RFPGA0_ANALOGPARAMETER4 0x88c | ||
1318 | |||
1319 | #define RFPGA0_XA_LSSIREADBACK 0x8a0 | ||
1320 | #define RFPGA0_XB_LSSIREADBACK 0x8a4 | ||
1321 | #define RFPGA0_XC_LSSIREADBACK 0x8a8 | ||
1322 | #define RFPGA0_XD_LSSIREADBACK 0x8ac | ||
1323 | |||
1324 | #define RFPGA0_PSDREPORT 0x8b4 | ||
1325 | #define TRANSCEIVEA_HSPI_READBACK 0x8b8 | ||
1326 | #define TRANSCEIVEB_HSPI_READBACK 0x8bc | ||
1327 | #define REG_SC_CNT 0x8c4 | ||
1328 | #define RFPGA0_XAB_RFINTERFACERB 0x8e0 | ||
1329 | #define RFPGA0_XCD_RFINTERFACERB 0x8e4 | ||
1330 | |||
1331 | #define RFPGA1_RFMOD 0x900 | ||
1332 | |||
1333 | #define RFPGA1_TXBLOCK 0x904 | ||
1334 | #define RFPGA1_DEBUGSELECT 0x908 | ||
1335 | #define RFPGA1_TXINFO 0x90c | ||
1336 | |||
1337 | #define RCCK0_SYSTEM 0xa00 | ||
1338 | |||
1339 | #define RCCK0_AFESETTING 0xa04 | ||
1340 | #define RCCK0_CCA 0xa08 | ||
1341 | |||
1342 | #define RCCK0_RXAGC1 0xa0c | ||
1343 | #define RCCK0_RXAGC2 0xa10 | ||
1344 | |||
1345 | #define RCCK0_RXHP 0xa14 | ||
1346 | |||
1347 | #define RCCK0_DSPPARAMETER1 0xa18 | ||
1348 | #define RCCK0_DSPPARAMETER2 0xa1c | ||
1349 | |||
1350 | #define RCCK0_TXFILTER1 0xa20 | ||
1351 | #define RCCK0_TXFILTER2 0xa24 | ||
1352 | #define RCCK0_DEBUGPORT 0xa28 | ||
1353 | #define RCCK0_FALSEALARMREPORT 0xa2c | ||
1354 | #define RCCK0_TRSSIREPORT 0xa50 | ||
1355 | #define RCCK0_RXREPORT 0xa54 | ||
1356 | #define RCCK0_FACOUNTERLOWER 0xa5c | ||
1357 | #define RCCK0_FACOUNTERUPPER 0xa58 | ||
1358 | #define RCCK0_CCA_CNT 0xa60 | ||
1359 | |||
1360 | |||
1361 | /* PageB(0xB00) */ | ||
1362 | #define RPDP_ANTA 0xb00 | ||
1363 | #define RPDP_ANTA_4 0xb04 | ||
1364 | #define RPDP_ANTA_8 0xb08 | ||
1365 | #define RPDP_ANTA_C 0xb0c | ||
1366 | #define RPDP_ANTA_10 0xb10 | ||
1367 | #define RPDP_ANTA_14 0xb14 | ||
1368 | #define RPDP_ANTA_18 0xb18 | ||
1369 | #define RPDP_ANTA_1C 0xb1c | ||
1370 | #define RPDP_ANTA_20 0xb20 | ||
1371 | #define RPDP_ANTA_24 0xb24 | ||
1372 | |||
1373 | #define RCONFIG_PMPD_ANTA 0xb28 | ||
1374 | #define RCONFIG_RAM64X16 0xb2c | ||
1375 | |||
1376 | #define RBNDA 0xb30 | ||
1377 | #define RHSSIPAR 0xb34 | ||
1378 | |||
1379 | #define RCONFIG_ANTA 0xb68 | ||
1380 | #define RCONFIG_ANTB 0xb6c | ||
1381 | |||
1382 | #define RPDP_ANTB 0xb70 | ||
1383 | #define RPDP_ANTB_4 0xb74 | ||
1384 | #define RPDP_ANTB_8 0xb78 | ||
1385 | #define RPDP_ANTB_C 0xb7c | ||
1386 | #define RPDP_ANTB_10 0xb80 | ||
1387 | #define RPDP_ANTB_14 0xb84 | ||
1388 | #define RPDP_ANTB_18 0xb88 | ||
1389 | #define RPDP_ANTB_1C 0xb8c | ||
1390 | #define RPDP_ANTB_20 0xb90 | ||
1391 | #define RPDP_ANTB_24 0xb94 | ||
1392 | |||
1393 | #define RCONFIG_PMPD_ANTB 0xb98 | ||
1394 | |||
1395 | #define RBNDB 0xba0 | ||
1396 | |||
1397 | #define RAPK 0xbd8 | ||
1398 | #define rPm_Rx0_AntA 0xbdc | ||
1399 | #define rPm_Rx1_AntA 0xbe0 | ||
1400 | #define rPm_Rx2_AntA 0xbe4 | ||
1401 | #define rPm_Rx3_AntA 0xbe8 | ||
1402 | #define rPm_Rx0_AntB 0xbec | ||
1403 | #define rPm_Rx1_AntB 0xbf0 | ||
1404 | #define rPm_Rx2_AntB 0xbf4 | ||
1405 | #define rPm_Rx3_AntB 0xbf8 | ||
1406 | |||
1407 | /*Page C*/ | ||
1408 | #define ROFDM0_LSTF 0xc00 | ||
1409 | |||
1410 | #define ROFDM0_TRXPATHENABLE 0xc04 | ||
1411 | #define ROFDM0_TRMUXPAR 0xc08 | ||
1412 | #define ROFDM0_TRSWISOLATION 0xc0c | ||
1413 | |||
1414 | #define ROFDM0_XARXAFE 0xc10 | ||
1415 | #define ROFDM0_XARXIQIMBAL 0xc14 | ||
1416 | #define ROFDM0_XBRXAFE 0xc18 | ||
1417 | #define ROFDM0_XBRXIQIMBAL 0xc1c | ||
1418 | #define ROFDM0_XCRXAFE 0xc20 | ||
1419 | #define ROFDM0_XCRXIQIMBAL 0xc24 | ||
1420 | #define ROFDM0_XDRXAFE 0xc28 | ||
1421 | #define ROFDM0_XDRXIQIMBAL 0xc2c | ||
1422 | |||
1423 | #define ROFDM0_RXDETECTOR1 0xc30 | ||
1424 | #define ROFDM0_RXDETECTOR2 0xc34 | ||
1425 | #define ROFDM0_RXDETECTOR3 0xc38 | ||
1426 | #define ROFDM0_RXDETECTOR4 0xc3c | ||
1427 | |||
1428 | #define ROFDM0_RXDSP 0xc40 | ||
1429 | #define ROFDM0_CFOANDDAGC 0xc44 | ||
1430 | #define ROFDM0_CCADROPTHRES 0xc48 | ||
1431 | #define ROFDM0_ECCATHRES 0xc4c | ||
1432 | |||
1433 | #define ROFDM0_XAAGCCORE1 0xc50 | ||
1434 | #define ROFDM0_XAAGCCORE2 0xc54 | ||
1435 | #define ROFDM0_XBAGCCORE1 0xc58 | ||
1436 | #define ROFDM0_XBAGCCORE2 0xc5c | ||
1437 | #define ROFDM0_XCAGCCORE1 0xc60 | ||
1438 | #define ROFDM0_XCAGCCORE2 0xc64 | ||
1439 | #define ROFDM0_XDAGCCORE1 0xc68 | ||
1440 | #define ROFDM0_XDAGCCORE2 0xc6c | ||
1441 | |||
1442 | #define ROFDM0_AGCPARAMETER1 0xc70 | ||
1443 | #define ROFDM0_AGCPARAMETER2 0xc74 | ||
1444 | #define ROFDM0_AGCRSSITABLE 0xc78 | ||
1445 | #define ROFDM0_HTSTFAGC 0xc7c | ||
1446 | |||
1447 | #define ROFDM0_XATXIQIMBAL 0xc80 | ||
1448 | #define ROFDM0_XATXAFE 0xc84 | ||
1449 | #define ROFDM0_XBTXIQIMBAL 0xc88 | ||
1450 | #define ROFDM0_XBTXAFE 0xc8c | ||
1451 | #define ROFDM0_XCTXIQIMBAL 0xc90 | ||
1452 | #define ROFDM0_XCTXAFE 0xc94 | ||
1453 | #define ROFDM0_XDTXIQIMBAL 0xc98 | ||
1454 | #define ROFDM0_XDTXAFE 0xc9c | ||
1455 | |||
1456 | #define ROFDM0_RXIQEXTANTA 0xca0 | ||
1457 | #define ROFDM0_TXCOEFF1 0xca4 | ||
1458 | #define ROFDM0_TXCOEFF2 0xca8 | ||
1459 | #define ROFDM0_TXCOEFF3 0xcac | ||
1460 | #define ROFDM0_TXCOEFF4 0xcb0 | ||
1461 | #define ROFDM0_TXCOEFF5 0xcb4 | ||
1462 | #define ROFDM0_TXCOEFF6 0xcb8 | ||
1463 | |||
1464 | #define ROFDM0_RXHPPARAMETER 0xce0 | ||
1465 | #define ROFDM0_TXPSEUDONOISEWGT 0xce4 | ||
1466 | #define ROFDM0_FRAMESYNC 0xcf0 | ||
1467 | #define ROFDM0_DFSREPORT 0xcf4 | ||
1468 | |||
1469 | |||
1470 | #define ROFDM1_LSTF 0xd00 | ||
1471 | #define ROFDM1_TRXPATHENABLE 0xd04 | ||
1472 | |||
1473 | #define ROFDM1_CF0 0xd08 | ||
1474 | #define ROFDM1_CSI1 0xd10 | ||
1475 | #define ROFDM1_SBD 0xd14 | ||
1476 | #define ROFDM1_CSI2 0xd18 | ||
1477 | #define ROFDM1_CFOTRACKING 0xd2c | ||
1478 | #define ROFDM1_TRXMESAURE1 0xd34 | ||
1479 | #define ROFDM1_INTFDET 0xd3c | ||
1480 | #define ROFDM1_PSEUDONOISESTATEAB 0xd50 | ||
1481 | #define ROFDM1_PSEUDONOISESTATECD 0xd54 | ||
1482 | #define ROFDM1_RXPSEUDONOISEWGT 0xd58 | ||
1483 | |||
1484 | #define ROFDM_PHYCOUNTER1 0xda0 | ||
1485 | #define ROFDM_PHYCOUNTER2 0xda4 | ||
1486 | #define ROFDM_PHYCOUNTER3 0xda8 | ||
1487 | |||
1488 | #define ROFDM_SHORTCFOAB 0xdac | ||
1489 | #define ROFDM_SHORTCFOCD 0xdb0 | ||
1490 | #define ROFDM_LONGCFOAB 0xdb4 | ||
1491 | #define ROFDM_LONGCFOCD 0xdb8 | ||
1492 | #define ROFDM_TAILCF0AB 0xdbc | ||
1493 | #define ROFDM_TAILCF0CD 0xdc0 | ||
1494 | #define ROFDM_PWMEASURE1 0xdc4 | ||
1495 | #define ROFDM_PWMEASURE2 0xdc8 | ||
1496 | #define ROFDM_BWREPORT 0xdcc | ||
1497 | #define ROFDM_AGCREPORT 0xdd0 | ||
1498 | #define ROFDM_RXSNR 0xdd4 | ||
1499 | #define ROFDM_RXEVMCSI 0xdd8 | ||
1500 | #define ROFDM_SIGREPORT 0xddc | ||
1501 | |||
1502 | #define RTXAGC_A_RATE18_06 0xe00 | ||
1503 | #define RTXAGC_A_RATE54_24 0xe04 | ||
1504 | #define RTXAGC_A_CCK1_MCS32 0xe08 | ||
1505 | #define RTXAGC_A_MCS03_MCS00 0xe10 | ||
1506 | #define RTXAGC_A_MCS07_MCS04 0xe14 | ||
1507 | #define RTXAGC_A_MCS11_MCS08 0xe18 | ||
1508 | #define RTXAGC_A_MCS15_MCS12 0xe1c | ||
1509 | |||
1510 | #define RTXAGC_B_RATE18_06 0x830 | ||
1511 | #define RTXAGC_B_RATE54_24 0x834 | ||
1512 | #define RTXAGC_B_CCK1_55_MCS32 0x838 | ||
1513 | #define RTXAGC_B_MCS03_MCS00 0x83c | ||
1514 | #define RTXAGC_B_MCS07_MCS04 0x848 | ||
1515 | #define RTXAGC_B_MCS11_MCS08 0x84c | ||
1516 | #define RTXAGC_B_MCS15_MCS12 0x868 | ||
1517 | #define RTXAGC_B_CCK11_A_CCK2_11 0x86c | ||
1518 | |||
1519 | #define RFPGA0_IQK 0xe28 | ||
1520 | #define RTX_IQK_TONE_A 0xe30 | ||
1521 | #define RRX_IQK_TONE_A 0xe34 | ||
1522 | #define RTX_IQK_PI_A 0xe38 | ||
1523 | #define RRX_IQK_PI_A 0xe3c | ||
1524 | |||
1525 | #define RTX_IQK 0xe40 | ||
1526 | #define RRX_IQK 0xe44 | ||
1527 | #define RIQK_AGC_PTS 0xe48 | ||
1528 | #define RIQK_AGC_RSP 0xe4c | ||
1529 | #define RTX_IQK_TONE_B 0xe50 | ||
1530 | #define RRX_IQK_TONE_B 0xe54 | ||
1531 | #define RTX_IQK_PI_B 0xe58 | ||
1532 | #define RRX_IQK_PI_B 0xe5c | ||
1533 | #define RIQK_AGC_CONT 0xe60 | ||
1534 | |||
1535 | #define RBLUE_TOOTH 0xe6c | ||
1536 | #define RRX_WAIT_CCA 0xe70 | ||
1537 | #define RTX_CCK_RFON 0xe74 | ||
1538 | #define RTX_CCK_BBON 0xe78 | ||
1539 | #define RTX_OFDM_RFON 0xe7c | ||
1540 | #define RTX_OFDM_BBON 0xe80 | ||
1541 | #define RTX_TO_RX 0xe84 | ||
1542 | #define RTX_TO_TX 0xe88 | ||
1543 | #define RRX_CCK 0xe8c | ||
1544 | |||
1545 | #define RTX_POWER_BEFORE_IQK_A 0xe94 | ||
1546 | #define RTX_POWER_AFTER_IQK_A 0xe9c | ||
1547 | |||
1548 | #define RRX_POWER_BEFORE_IQK_A 0xea0 | ||
1549 | #define RRX_POWER_BEFORE_IQK_A_2 0xea4 | ||
1550 | #define RRX_POWER_AFTER_IQK_A 0xea8 | ||
1551 | #define RRX_POWER_AFTER_IQK_A_2 0xeac | ||
1552 | |||
1553 | #define RTX_POWER_BEFORE_IQK_B 0xeb4 | ||
1554 | #define RTX_POWER_AFTER_IQK_B 0xebc | ||
1555 | |||
1556 | #define RRX_POWER_BEFORE_IQK_B 0xec0 | ||
1557 | #define RRX_POWER_BEFORE_IQK_B_2 0xec4 | ||
1558 | #define RRX_POWER_AFTER_IQK_B 0xec8 | ||
1559 | #define RRX_POWER_AFTER_IQK_B_2 0xecc | ||
1560 | |||
1561 | #define RRX_OFDM 0xed0 | ||
1562 | #define RRX_WAIT_RIFS 0xed4 | ||
1563 | #define RRX_TO_RX 0xed8 | ||
1564 | #define RSTANDBY 0xedc | ||
1565 | #define RSLEEP 0xee0 | ||
1566 | #define RPMPD_ANAEN 0xeec | ||
1567 | |||
1568 | #define RZEBRA1_HSSIENABLE 0x0 | ||
1569 | #define RZEBRA1_TRXENABLE1 0x1 | ||
1570 | #define RZEBRA1_TRXENABLE2 0x2 | ||
1571 | #define RZEBRA1_AGC 0x4 | ||
1572 | #define RZEBRA1_CHARGEPUMP 0x5 | ||
1573 | #define RZEBRA1_CHANNEL 0x7 | ||
1574 | |||
1575 | #define RZEBRA1_TXGAIN 0x8 | ||
1576 | #define RZEBRA1_TXLPF 0x9 | ||
1577 | #define RZEBRA1_RXLPF 0xb | ||
1578 | #define RZEBRA1_RXHPFCORNER 0xc | ||
1579 | |||
1580 | #define RGLOBALCTRL 0 | ||
1581 | #define RRTL8256_TXLPF 19 | ||
1582 | #define RRTL8256_RXLPF 11 | ||
1583 | #define RRTL8258_TXLPF 0x11 | ||
1584 | #define RRTL8258_RXLPF 0x13 | ||
1585 | #define RRTL8258_RSSILPF 0xa | ||
1586 | |||
1587 | #define RF_AC 0x00 | ||
1588 | |||
1589 | #define RF_IQADJ_G1 0x01 | ||
1590 | #define RF_IQADJ_G2 0x02 | ||
1591 | #define RF_POW_TRSW 0x05 | ||
1592 | |||
1593 | #define RF_GAIN_RX 0x06 | ||
1594 | #define RF_GAIN_TX 0x07 | ||
1595 | |||
1596 | #define RF_TXM_IDAC 0x08 | ||
1597 | #define RF_BS_IQGEN 0x0F | ||
1598 | |||
1599 | #define RF_MODE1 0x10 | ||
1600 | #define RF_MODE2 0x11 | ||
1601 | |||
1602 | #define RF_RX_AGC_HP 0x12 | ||
1603 | #define RF_TX_AGC 0x13 | ||
1604 | #define RF_BIAS 0x14 | ||
1605 | #define RF_IPA 0x15 | ||
1606 | #define RF_POW_ABILITY 0x17 | ||
1607 | #define RF_MODE_AG 0x18 | ||
1608 | #define RRFCHANNEL 0x18 | ||
1609 | #define RF_CHNLBW 0x18 | ||
1610 | #define RF_TOP 0x19 | ||
1611 | |||
1612 | #define RF_RX_G1 0x1A | ||
1613 | #define RF_RX_G2 0x1B | ||
1614 | |||
1615 | #define RF_RX_BB2 0x1C | ||
1616 | #define RF_RX_BB1 0x1D | ||
1617 | |||
1618 | #define RF_RCK1 0x1E | ||
1619 | #define RF_RCK2 0x1F | ||
1620 | |||
1621 | #define RF_TX_G1 0x20 | ||
1622 | #define RF_TX_G2 0x21 | ||
1623 | #define RF_TX_G3 0x22 | ||
1624 | |||
1625 | #define RF_TX_BB1 0x23 | ||
1626 | #define RF_T_METER 0x42 | ||
1627 | |||
1628 | #define RF_SYN_G1 0x25 | ||
1629 | #define RF_SYN_G2 0x26 | ||
1630 | #define RF_SYN_G3 0x27 | ||
1631 | #define RF_SYN_G4 0x28 | ||
1632 | #define RF_SYN_G5 0x29 | ||
1633 | #define RF_SYN_G6 0x2A | ||
1634 | #define RF_SYN_G7 0x2B | ||
1635 | #define RF_SYN_G8 0x2C | ||
1636 | |||
1637 | #define RF_RCK_OS 0x30 | ||
1638 | #define RF_TXPA_G1 0x31 | ||
1639 | #define RF_TXPA_G2 0x32 | ||
1640 | #define RF_TXPA_G3 0x33 | ||
1641 | |||
1642 | #define RF_TX_BIAS_A 0x35 | ||
1643 | #define RF_TX_BIAS_D 0x36 | ||
1644 | #define RF_LOBF_9 0x38 | ||
1645 | #define RF_RXRF_A3 0x3C | ||
1646 | #define RF_TRSW 0x3F | ||
1647 | |||
1648 | #define RF_TXRF_A2 0x41 | ||
1649 | #define RF_TXPA_G4 0x46 | ||
1650 | #define RF_TXPA_A4 0x4B | ||
1651 | |||
1652 | #define RF_WE_LUT 0xEF | ||
1653 | |||
1654 | #define BBBRESETB 0x100 | ||
1655 | #define BGLOBALRESETB 0x200 | ||
1656 | #define BOFDMTXSTART 0x4 | ||
1657 | #define BCCKTXSTART 0x8 | ||
1658 | #define BCRC32DEBUG 0x100 | ||
1659 | #define BPMACLOOPBACK 0x10 | ||
1660 | #define BTXLSIG 0xffffff | ||
1661 | #define BOFDMTXRATE 0xf | ||
1662 | #define BOFDMTXRESERVED 0x10 | ||
1663 | #define BOFDMTXLENGTH 0x1ffe0 | ||
1664 | #define BOFDMTXPARITY 0x20000 | ||
1665 | #define BTXHTSIG1 0xffffff | ||
1666 | #define BTXHTMCSRATE 0x7f | ||
1667 | #define BTXHTBW 0x80 | ||
1668 | #define BTXHTLENGTH 0xffff00 | ||
1669 | #define BTXHTSIG2 0xffffff | ||
1670 | #define BTXHTSMOOTHING 0x1 | ||
1671 | #define BTXHTSOUNDING 0x2 | ||
1672 | #define BTXHTRESERVED 0x4 | ||
1673 | #define BTXHTAGGREATION 0x8 | ||
1674 | #define BTXHTSTBC 0x30 | ||
1675 | #define BTXHTADVANCECODING 0x40 | ||
1676 | #define BTXHTSHORTGI 0x80 | ||
1677 | #define BTXHTNUMBERHT_LTF 0x300 | ||
1678 | #define BTXHTCRC8 0x3fc00 | ||
1679 | #define BCOUNTERRESET 0x10000 | ||
1680 | #define BNUMOFOFDMTX 0xffff | ||
1681 | #define BNUMOFCCKTX 0xffff0000 | ||
1682 | #define BTXIDLEINTERVAL 0xffff | ||
1683 | #define BOFDMSERVICE 0xffff0000 | ||
1684 | #define BTXMACHEADER 0xffffffff | ||
1685 | #define BTXDATAINIT 0xff | ||
1686 | #define BTXHTMODE 0x100 | ||
1687 | #define BTXDATATYPE 0x30000 | ||
1688 | #define BTXRANDOMSEED 0xffffffff | ||
1689 | #define BCCKTXPREAMBLE 0x1 | ||
1690 | #define BCCKTXSFD 0xffff0000 | ||
1691 | #define BCCKTXSIG 0xff | ||
1692 | #define BCCKTXSERVICE 0xff00 | ||
1693 | #define BCCKLENGTHEXT 0x8000 | ||
1694 | #define BCCKTXLENGHT 0xffff0000 | ||
1695 | #define BCCKTXCRC16 0xffff | ||
1696 | #define BCCKTXSTATUS 0x1 | ||
1697 | #define BOFDMTXSTATUS 0x2 | ||
1698 | #define IS_BB_REG_OFFSET_92S(_offset) \ | ||
1699 | ((_offset >= 0x800) && (_offset <= 0xfff)) | ||
1700 | |||
1701 | #define BRFMOD 0x1 | ||
1702 | #define BJAPANMODE 0x2 | ||
1703 | #define BCCKTXSC 0x30 | ||
1704 | #define BCCKEN 0x1000000 | ||
1705 | #define BOFDMEN 0x2000000 | ||
1706 | |||
1707 | #define BOFDMRXADCPHASE 0x10000 | ||
1708 | #define BOFDMTXDACPHASE 0x40000 | ||
1709 | #define BXATXAGC 0x3f | ||
1710 | |||
1711 | #define BXBTXAGC 0xf00 | ||
1712 | #define BXCTXAGC 0xf000 | ||
1713 | #define BXDTXAGC 0xf0000 | ||
1714 | |||
1715 | #define BPASTART 0xf0000000 | ||
1716 | #define BTRSTART 0x00f00000 | ||
1717 | #define BRFSTART 0x0000f000 | ||
1718 | #define BBBSTART 0x000000f0 | ||
1719 | #define BBBCCKSTART 0x0000000f | ||
1720 | #define BPAEND 0xf | ||
1721 | #define BTREND 0x0f000000 | ||
1722 | #define BRFEND 0x000f0000 | ||
1723 | #define BCCAMASK 0x000000f0 | ||
1724 | #define BR2RCCAMASK 0x00000f00 | ||
1725 | #define BHSSI_R2TDELAY 0xf8000000 | ||
1726 | #define BHSSI_T2RDELAY 0xf80000 | ||
1727 | #define BCONTXHSSI 0x400 | ||
1728 | #define BIGFROMCCK 0x200 | ||
1729 | #define BAGCADDRESS 0x3f | ||
1730 | #define BRXHPTX 0x7000 | ||
1731 | #define BRXHP2RX 0x38000 | ||
1732 | #define BRXHPCCKINI 0xc0000 | ||
1733 | #define BAGCTXCODE 0xc00000 | ||
1734 | #define BAGCRXCODE 0x300000 | ||
1735 | |||
1736 | #define B3WIREDATALENGTH 0x800 | ||
1737 | #define B3WIREADDREAALENGTH 0x400 | ||
1738 | |||
1739 | #define B3WIRERFPOWERDOWN 0x1 | ||
1740 | #define B5GPAPEPOLARITY 0x40000000 | ||
1741 | #define B2GPAPEPOLARITY 0x80000000 | ||
1742 | #define BRFSW_TXDEFAULTANT 0x3 | ||
1743 | #define BRFSW_TXOPTIONANT 0x30 | ||
1744 | #define BRFSW_RXDEFAULTANT 0x300 | ||
1745 | #define BRFSW_RXOPTIONANT 0x3000 | ||
1746 | #define BRFSI_3WIREDATA 0x1 | ||
1747 | #define BRFSI_3WIRECLOCK 0x2 | ||
1748 | #define BRFSI_3WIRELOAD 0x4 | ||
1749 | #define BRFSI_3WIRERW 0x8 | ||
1750 | #define BRFSI_3WIRE 0xf | ||
1751 | |||
1752 | #define BRFSI_RFENV 0x10 | ||
1753 | |||
1754 | #define BRFSI_TRSW 0x20 | ||
1755 | #define BRFSI_TRSWB 0x40 | ||
1756 | #define BRFSI_ANTSW 0x100 | ||
1757 | #define BRFSI_ANTSWB 0x200 | ||
1758 | #define BRFSI_PAPE 0x400 | ||
1759 | #define BRFSI_PAPE5G 0x800 | ||
1760 | #define BBANDSELECT 0x1 | ||
1761 | #define BHTSIG2_GI 0x80 | ||
1762 | #define BHTSIG2_SMOOTHING 0x01 | ||
1763 | #define BHTSIG2_SOUNDING 0x02 | ||
1764 | #define BHTSIG2_AGGREATON 0x08 | ||
1765 | #define BHTSIG2_STBC 0x30 | ||
1766 | #define BHTSIG2_ADVCODING 0x40 | ||
1767 | #define BHTSIG2_NUMOFHTLTF 0x300 | ||
1768 | #define BHTSIG2_CRC8 0x3fc | ||
1769 | #define BHTSIG1_MCS 0x7f | ||
1770 | #define BHTSIG1_BANDWIDTH 0x80 | ||
1771 | #define BHTSIG1_HTLENGTH 0xffff | ||
1772 | #define BLSIG_RATE 0xf | ||
1773 | #define BLSIG_RESERVED 0x10 | ||
1774 | #define BLSIG_LENGTH 0x1fffe | ||
1775 | #define BLSIG_PARITY 0x20 | ||
1776 | #define BCCKRXPHASE 0x4 | ||
1777 | |||
1778 | #define BLSSIREADADDRESS 0x7f800000 | ||
1779 | #define BLSSIREADEDGE 0x80000000 | ||
1780 | |||
1781 | #define BLSSIREADBACKDATA 0xfffff | ||
1782 | |||
1783 | #define BLSSIREADOKFLAG 0x1000 | ||
1784 | #define BCCKSAMPLERATE 0x8 | ||
1785 | #define BREGULATOR0STANDBY 0x1 | ||
1786 | #define BREGULATORPLLSTANDBY 0x2 | ||
1787 | #define BREGULATOR1STANDBY 0x4 | ||
1788 | #define BPLLPOWERUP 0x8 | ||
1789 | #define BDPLLPOWERUP 0x10 | ||
1790 | #define BDA10POWERUP 0x20 | ||
1791 | #define BAD7POWERUP 0x200 | ||
1792 | #define BDA6POWERUP 0x2000 | ||
1793 | #define BXTALPOWERUP 0x4000 | ||
1794 | #define B40MDCLKPOWERUP 0x8000 | ||
1795 | #define BDA6DEBUGMODE 0x20000 | ||
1796 | #define BDA6SWING 0x380000 | ||
1797 | |||
1798 | #define BADCLKPHASE 0x4000000 | ||
1799 | #define B80MCLKDELAY 0x18000000 | ||
1800 | #define BAFEWATCHDOGENABLE 0x20000000 | ||
1801 | |||
1802 | #define BXTALCAP01 0xc0000000 | ||
1803 | #define BXTALCAP23 0x3 | ||
1804 | #define BXTALCAP92X 0x0f000000 | ||
1805 | #define BXTALCAP 0x0f000000 | ||
1806 | |||
1807 | #define BINTDIFCLKENABLE 0x400 | ||
1808 | #define BEXTSIGCLKENABLE 0x800 | ||
1809 | #define BBANDGAP_MBIAS_POWERUP 0x10000 | ||
1810 | #define BAD11SH_GAIN 0xc0000 | ||
1811 | #define BAD11NPUT_RANGE 0x700000 | ||
1812 | #define BAD110P_CURRENT 0x3800000 | ||
1813 | #define BLPATH_LOOPBACK 0x4000000 | ||
1814 | #define BQPATH_LOOPBACK 0x8000000 | ||
1815 | #define BAFE_LOOPBACK 0x10000000 | ||
1816 | #define BDA10_SWING 0x7e0 | ||
1817 | #define BDA10_REVERSE 0x800 | ||
1818 | #define BDA_CLK_SOURCE 0x1000 | ||
1819 | #define BDA7INPUT_RANGE 0x6000 | ||
1820 | #define BDA7_GAIN 0x38000 | ||
1821 | #define BDA7OUTPUT_CM_MODE 0x40000 | ||
1822 | #define BDA7INPUT_CM_MODE 0x380000 | ||
1823 | #define BDA7CURRENT 0xc00000 | ||
1824 | #define BREGULATOR_ADJUST 0x7000000 | ||
1825 | #define BAD11POWERUP_ATTX 0x1 | ||
1826 | #define BDA10PS_ATTX 0x10 | ||
1827 | #define BAD11POWERUP_ATRX 0x100 | ||
1828 | #define BDA10PS_ATRX 0x1000 | ||
1829 | #define BCCKRX_AGC_FORMAT 0x200 | ||
1830 | #define BPSDFFT_SAMPLE_POINT 0xc000 | ||
1831 | #define BPSD_AVERAGE_NUM 0x3000 | ||
1832 | #define BIQPATH_CONTROL 0xc00 | ||
1833 | #define BPSD_FREQ 0x3ff | ||
1834 | #define BPSD_ANTENNA_PATH 0x30 | ||
1835 | #define BPSD_IQ_SWITCH 0x40 | ||
1836 | #define BPSD_RX_TRIGGER 0x400000 | ||
1837 | #define BPSD_TX_TRIGGERCW 0x80000000 | ||
1838 | #define BPSD_SINE_TONE_SCALE 0x7f000000 | ||
1839 | #define BPSD_REPORT 0xffff | ||
1840 | |||
1841 | #define BOFDM_TXSC 0x30000000 | ||
1842 | #define BCCK_TXON 0x1 | ||
1843 | #define BOFDM_TXON 0x2 | ||
1844 | #define BDEBUG_PAGE 0xfff | ||
1845 | #define BDEBUG_ITEM 0xff | ||
1846 | #define BANTL 0x10 | ||
1847 | #define BANT_NONHT 0x100 | ||
1848 | #define BANT_HT1 0x1000 | ||
1849 | #define BANT_HT2 0x10000 | ||
1850 | #define BANT_HT1S1 0x100000 | ||
1851 | #define BANT_NONHTS1 0x1000000 | ||
1852 | |||
1853 | #define BCCK_BBMODE 0x3 | ||
1854 | #define BCCK_TXPOWERSAVING 0x80 | ||
1855 | #define BCCK_RXPOWERSAVING 0x40 | ||
1856 | |||
1857 | #define BCCK_SIDEBAND 0x10 | ||
1858 | |||
1859 | #define BCCK_SCRAMBLE 0x8 | ||
1860 | #define BCCK_ANTDIVERSITY 0x8000 | ||
1861 | #define BCCK_CARRIER_RECOVERY 0x4000 | ||
1862 | #define BCCK_TXRATE 0x3000 | ||
1863 | #define BCCK_DCCANCEL 0x0800 | ||
1864 | #define BCCK_ISICANCEL 0x0400 | ||
1865 | #define BCCK_MATCH_FILTER 0x0200 | ||
1866 | #define BCCK_EQUALIZER 0x0100 | ||
1867 | #define BCCK_PREAMBLE_DETECT 0x800000 | ||
1868 | #define BCCK_FAST_FALSECCA 0x400000 | ||
1869 | #define BCCK_CH_ESTSTART 0x300000 | ||
1870 | #define BCCK_CCA_COUNT 0x080000 | ||
1871 | #define BCCK_CS_LIM 0x070000 | ||
1872 | #define BCCK_BIST_MODE 0x80000000 | ||
1873 | #define BCCK_CCAMASK 0x40000000 | ||
1874 | #define BCCK_TX_DAC_PHASE 0x4 | ||
1875 | #define BCCK_RX_ADC_PHASE 0x20000000 | ||
1876 | #define BCCKR_CP_MODE 0x0100 | ||
1877 | #define BCCK_TXDC_OFFSET 0xf0 | ||
1878 | #define BCCK_RXDC_OFFSET 0xf | ||
1879 | #define BCCK_CCA_MODE 0xc000 | ||
1880 | #define BCCK_FALSECS_LIM 0x3f00 | ||
1881 | #define BCCK_CS_RATIO 0xc00000 | ||
1882 | #define BCCK_CORGBIT_SEL 0x300000 | ||
1883 | #define BCCK_PD_LIM 0x0f0000 | ||
1884 | #define BCCK_NEWCCA 0x80000000 | ||
1885 | #define BCCK_RXHP_OF_IG 0x8000 | ||
1886 | #define BCCK_RXIG 0x7f00 | ||
1887 | #define BCCK_LNA_POLARITY 0x800000 | ||
1888 | #define BCCK_RX1ST_BAIN 0x7f0000 | ||
1889 | #define BCCK_RF_EXTEND 0x20000000 | ||
1890 | #define BCCK_RXAGC_SATLEVEL 0x1f000000 | ||
1891 | #define BCCK_RXAGC_SATCOUNT 0xe0 | ||
1892 | #define BCCKRXRFSETTLE 0x1f | ||
1893 | #define BCCK_FIXED_RXAGC 0x8000 | ||
1894 | #define BCCK_ANTENNA_POLARITY 0x2000 | ||
1895 | #define BCCK_TXFILTER_TYPE 0x0c00 | ||
1896 | #define BCCK_RXAGC_REPORTTYPE 0x0300 | ||
1897 | #define BCCK_RXDAGC_EN 0x80000000 | ||
1898 | #define BCCK_RXDAGC_PERIOD 0x20000000 | ||
1899 | #define BCCK_RXDAGC_SATLEVEL 0x1f000000 | ||
1900 | #define BCCK_TIMING_RECOVERY 0x800000 | ||
1901 | #define BCCK_TXC0 0x3f0000 | ||
1902 | #define BCCK_TXC1 0x3f000000 | ||
1903 | #define BCCK_TXC2 0x3f | ||
1904 | #define BCCK_TXC3 0x3f00 | ||
1905 | #define BCCK_TXC4 0x3f0000 | ||
1906 | #define BCCK_TXC5 0x3f000000 | ||
1907 | #define BCCK_TXC6 0x3f | ||
1908 | #define BCCK_TXC7 0x3f00 | ||
1909 | #define BCCK_DEBUGPORT 0xff0000 | ||
1910 | #define BCCK_DAC_DEBUG 0x0f000000 | ||
1911 | #define BCCK_FALSEALARM_ENABLE 0x8000 | ||
1912 | #define BCCK_FALSEALARM_READ 0x4000 | ||
1913 | #define BCCK_TRSSI 0x7f | ||
1914 | #define BCCK_RXAGC_REPORT 0xfe | ||
1915 | #define BCCK_RXREPORT_ANTSEL 0x80000000 | ||
1916 | #define BCCK_RXREPORT_MFOFF 0x40000000 | ||
1917 | #define BCCK_RXREPORT_SQLOSS 0x20000000 | ||
1918 | #define BCCK_RXREPORT_PKTLOSS 0x10000000 | ||
1919 | #define BCCK_RXREPORT_LOCKEDBIT 0x08000000 | ||
1920 | #define BCCK_RXREPORT_RATEERROR 0x04000000 | ||
1921 | #define BCCK_RXREPORT_RXRATE 0x03000000 | ||
1922 | #define BCCK_RXFA_COUNTER_LOWER 0xff | ||
1923 | #define BCCK_RXFA_COUNTER_UPPER 0xff000000 | ||
1924 | #define BCCK_RXHPAGC_START 0xe000 | ||
1925 | #define BCCK_RXHPAGC_FINAL 0x1c00 | ||
1926 | #define BCCK_RXFALSEALARM_ENABLE 0x8000 | ||
1927 | #define BCCK_FACOUNTER_FREEZE 0x4000 | ||
1928 | #define BCCK_TXPATH_SEL 0x10000000 | ||
1929 | #define BCCK_DEFAULT_RXPATH 0xc000000 | ||
1930 | #define BCCK_OPTION_RXPATH 0x3000000 | ||
1931 | |||
1932 | #define BNUM_OFSTF 0x3 | ||
1933 | #define BSHIFT_L 0xc0 | ||
1934 | #define BGI_TH 0xc | ||
1935 | #define BRXPATH_A 0x1 | ||
1936 | #define BRXPATH_B 0x2 | ||
1937 | #define BRXPATH_C 0x4 | ||
1938 | #define BRXPATH_D 0x8 | ||
1939 | #define BTXPATH_A 0x1 | ||
1940 | #define BTXPATH_B 0x2 | ||
1941 | #define BTXPATH_C 0x4 | ||
1942 | #define BTXPATH_D 0x8 | ||
1943 | #define BTRSSI_FREQ 0x200 | ||
1944 | #define BADC_BACKOFF 0x3000 | ||
1945 | #define BDFIR_BACKOFF 0xc000 | ||
1946 | #define BTRSSI_LATCH_PHASE 0x10000 | ||
1947 | #define BRX_LDC_OFFSET 0xff | ||
1948 | #define BRX_QDC_OFFSET 0xff00 | ||
1949 | #define BRX_DFIR_MODE 0x1800000 | ||
1950 | #define BRX_DCNF_TYPE 0xe000000 | ||
1951 | #define BRXIQIMB_A 0x3ff | ||
1952 | #define BRXIQIMB_B 0xfc00 | ||
1953 | #define BRXIQIMB_C 0x3f0000 | ||
1954 | #define BRXIQIMB_D 0xffc00000 | ||
1955 | #define BDC_DC_NOTCH 0x60000 | ||
1956 | #define BRXNB_NOTCH 0x1f000000 | ||
1957 | #define BPD_TH 0xf | ||
1958 | #define BPD_TH_OPT2 0xc000 | ||
1959 | #define BPWED_TH 0x700 | ||
1960 | #define BIFMF_WIN_L 0x800 | ||
1961 | #define BPD_OPTION 0x1000 | ||
1962 | #define BMF_WIN_L 0xe000 | ||
1963 | #define BBW_SEARCH_L 0x30000 | ||
1964 | #define BWIN_ENH_L 0xc0000 | ||
1965 | #define BBW_TH 0x700000 | ||
1966 | #define BED_TH2 0x3800000 | ||
1967 | #define BBW_OPTION 0x4000000 | ||
1968 | #define BRADIO_TH 0x18000000 | ||
1969 | #define BWINDOW_L 0xe0000000 | ||
1970 | #define BSBD_OPTION 0x1 | ||
1971 | #define BFRAME_TH 0x1c | ||
1972 | #define BFS_OPTION 0x60 | ||
1973 | #define BDC_SLOPE_CHECK 0x80 | ||
1974 | #define BFGUARD_COUNTER_DC_L 0xe00 | ||
1975 | #define BFRAME_WEIGHT_SHORT 0x7000 | ||
1976 | #define BSUB_TUNE 0xe00000 | ||
1977 | #define BFRAME_DC_LENGTH 0xe000000 | ||
1978 | #define BSBD_START_OFFSET 0x30000000 | ||
1979 | #define BFRAME_TH_2 0x7 | ||
1980 | #define BFRAME_GI2_TH 0x38 | ||
1981 | #define BGI2_SYNC_EN 0x40 | ||
1982 | #define BSARCH_SHORT_EARLY 0x300 | ||
1983 | #define BSARCH_SHORT_LATE 0xc00 | ||
1984 | #define BSARCH_GI2_LATE 0x70000 | ||
1985 | #define BCFOANTSUM 0x1 | ||
1986 | #define BCFOACC 0x2 | ||
1987 | #define BCFOSTARTOFFSET 0xc | ||
1988 | #define BCFOLOOPBACK 0x70 | ||
1989 | #define BCFOSUMWEIGHT 0x80 | ||
1990 | #define BDAGCENABLE 0x10000 | ||
1991 | #define BTXIQIMB_A 0x3ff | ||
1992 | #define BTXIQIMB_B 0xfc00 | ||
1993 | #define BTXIQIMB_C 0x3f0000 | ||
1994 | #define BTXIQIMB_D 0xffc00000 | ||
1995 | #define BTXIDCOFFSET 0xff | ||
1996 | #define BTXIQDCOFFSET 0xff00 | ||
1997 | #define BTXDFIRMODE 0x10000 | ||
1998 | #define BTXPESUDO_NOISEON 0x4000000 | ||
1999 | #define BTXPESUDO_NOISE_A 0xff | ||
2000 | #define BTXPESUDO_NOISE_B 0xff00 | ||
2001 | #define BTXPESUDO_NOISE_C 0xff0000 | ||
2002 | #define BTXPESUDO_NOISE_D 0xff000000 | ||
2003 | #define BCCA_DROPOPTION 0x20000 | ||
2004 | #define BCCA_DROPTHRES 0xfff00000 | ||
2005 | #define BEDCCA_H 0xf | ||
2006 | #define BEDCCA_L 0xf0 | ||
2007 | #define BLAMBDA_ED 0x300 | ||
2008 | #define BRX_INITIALGAIN 0x7f | ||
2009 | #define BRX_ANTDIV_EN 0x80 | ||
2010 | #define BRX_AGC_ADDRESS_FOR_LNA 0x7f00 | ||
2011 | #define BRX_HIGHPOWER_FLOW 0x8000 | ||
2012 | #define BRX_AGC_FREEZE_THRES 0xc0000 | ||
2013 | #define BRX_FREEZESTEP_AGC1 0x300000 | ||
2014 | #define BRX_FREEZESTEP_AGC2 0xc00000 | ||
2015 | #define BRX_FREEZESTEP_AGC3 0x3000000 | ||
2016 | #define BRX_FREEZESTEP_AGC0 0xc000000 | ||
2017 | #define BRXRSSI_CMP_EN 0x10000000 | ||
2018 | #define BRXQUICK_AGCEN 0x20000000 | ||
2019 | #define BRXAGC_FREEZE_THRES_MODE 0x40000000 | ||
2020 | #define BRX_OVERFLOW_CHECKTYPE 0x80000000 | ||
2021 | #define BRX_AGCSHIFT 0x7f | ||
2022 | #define BTRSW_TRI_ONLY 0x80 | ||
2023 | #define BPOWER_THRES 0x300 | ||
2024 | #define BRXAGC_EN 0x1 | ||
2025 | #define BRXAGC_TOGETHER_EN 0x2 | ||
2026 | #define BRXAGC_MIN 0x4 | ||
2027 | #define BRXHP_INI 0x7 | ||
2028 | #define BRXHP_TRLNA 0x70 | ||
2029 | #define BRXHP_RSSI 0x700 | ||
2030 | #define BRXHP_BBP1 0x7000 | ||
2031 | #define BRXHP_BBP2 0x70000 | ||
2032 | #define BRXHP_BBP3 0x700000 | ||
2033 | #define BRSSI_H 0x7f0000 | ||
2034 | #define BRSSI_GEN 0x7f000000 | ||
2035 | #define BRXSETTLE_TRSW 0x7 | ||
2036 | #define BRXSETTLE_LNA 0x38 | ||
2037 | #define BRXSETTLE_RSSI 0x1c0 | ||
2038 | #define BRXSETTLE_BBP 0xe00 | ||
2039 | #define BRXSETTLE_RXHP 0x7000 | ||
2040 | #define BRXSETTLE_ANTSW_RSSI 0x38000 | ||
2041 | #define BRXSETTLE_ANTSW 0xc0000 | ||
2042 | #define BRXPROCESS_TIME_DAGC 0x300000 | ||
2043 | #define BRXSETTLE_HSSI 0x400000 | ||
2044 | #define BRXPROCESS_TIME_BBPPW 0x800000 | ||
2045 | #define BRXANTENNA_POWER_SHIFT 0x3000000 | ||
2046 | #define BRSSI_TABLE_SELECT 0xc000000 | ||
2047 | #define BRXHP_FINAL 0x7000000 | ||
2048 | #define BRXHPSETTLE_BBP 0x7 | ||
2049 | #define BRXHTSETTLE_HSSI 0x8 | ||
2050 | #define BRXHTSETTLE_RXHP 0x70 | ||
2051 | #define BRXHTSETTLE_BBPPW 0x80 | ||
2052 | #define BRXHTSETTLE_IDLE 0x300 | ||
2053 | #define BRXHTSETTLE_RESERVED 0x1c00 | ||
2054 | #define BRXHT_RXHP_EN 0x8000 | ||
2055 | #define BRXAGC_FREEZE_THRES 0x30000 | ||
2056 | #define BRXAGC_TOGETHEREN 0x40000 | ||
2057 | #define BRXHTAGC_MIN 0x80000 | ||
2058 | #define BRXHTAGC_EN 0x100000 | ||
2059 | #define BRXHTDAGC_EN 0x200000 | ||
2060 | #define BRXHT_RXHP_BBP 0x1c00000 | ||
2061 | #define BRXHT_RXHP_FINAL 0xe0000000 | ||
2062 | #define BRXPW_RADIO_TH 0x3 | ||
2063 | #define BRXPW_RADIO_EN 0x4 | ||
2064 | #define BRXMF_HOLD 0x3800 | ||
2065 | #define BRXPD_DELAY_TH1 0x38 | ||
2066 | #define BRXPD_DELAY_TH2 0x1c0 | ||
2067 | #define BRXPD_DC_COUNT_MAX 0x600 | ||
2068 | #define BRXPD_DELAY_TH 0x8000 | ||
2069 | #define BRXPROCESS_DELAY 0xf0000 | ||
2070 | #define BRXSEARCHRANGE_GI2_EARLY 0x700000 | ||
2071 | #define BRXFRAME_FUARD_COUNTER_L 0x3800000 | ||
2072 | #define BRXSGI_GUARD_L 0xc000000 | ||
2073 | #define BRXSGI_SEARCH_L 0x30000000 | ||
2074 | #define BRXSGI_TH 0xc0000000 | ||
2075 | #define BDFSCNT0 0xff | ||
2076 | #define BDFSCNT1 0xff00 | ||
2077 | #define BDFSFLAG 0xf0000 | ||
2078 | #define BMF_WEIGHT_SUM 0x300000 | ||
2079 | #define BMINIDX_TH 0x7f000000 | ||
2080 | #define BDAFORMAT 0x40000 | ||
2081 | #define BTXCH_EMU_ENABLE 0x01000000 | ||
2082 | #define BTRSW_ISOLATION_A 0x7f | ||
2083 | #define BTRSW_ISOLATION_B 0x7f00 | ||
2084 | #define BTRSW_ISOLATION_C 0x7f0000 | ||
2085 | #define BTRSW_ISOLATION_D 0x7f000000 | ||
2086 | #define BEXT_LNA_GAIN 0x7c00 | ||
2087 | |||
2088 | #define BSTBC_EN 0x4 | ||
2089 | #define BANTENNA_MAPPING 0x10 | ||
2090 | #define BNSS 0x20 | ||
2091 | #define BCFO_ANTSUM_ID 0x200 | ||
2092 | #define BPHY_COUNTER_RESET 0x8000000 | ||
2093 | #define BCFO_REPORT_GET 0x4000000 | ||
2094 | #define BOFDM_CONTINUE_TX 0x10000000 | ||
2095 | #define BOFDM_SINGLE_CARRIER 0x20000000 | ||
2096 | #define BOFDM_SINGLE_TONE 0x40000000 | ||
2097 | #define BHT_DETECT 0x100 | ||
2098 | #define BCFOEN 0x10000 | ||
2099 | #define BCFOVALUE 0xfff00000 | ||
2100 | #define BSIGTONE_RE 0x3f | ||
2101 | #define BSIGTONE_IM 0x7f00 | ||
2102 | #define BCOUNTER_CCA 0xffff | ||
2103 | #define BCOUNTER_PARITYFAIL 0xffff0000 | ||
2104 | #define BCOUNTER_RATEILLEGAL 0xffff | ||
2105 | #define BCOUNTER_CRC8FAIL 0xffff0000 | ||
2106 | #define BCOUNTER_MCSNOSUPPORT 0xffff | ||
2107 | #define BCOUNTER_FASTSYNC 0xffff | ||
2108 | #define BSHORTCFO 0xfff | ||
2109 | #define BSHORTCFOT_LENGTH 12 | ||
2110 | #define BSHORTCFOF_LENGTH 11 | ||
2111 | #define BLONGCFO 0x7ff | ||
2112 | #define BLONGCFOT_LENGTH 11 | ||
2113 | #define BLONGCFOF_LENGTH 11 | ||
2114 | #define BTAILCFO 0x1fff | ||
2115 | #define BTAILCFOT_LENGTH 13 | ||
2116 | #define BTAILCFOF_LENGTH 12 | ||
2117 | #define BNOISE_EN_PWDB 0xffff | ||
2118 | #define BCC_POWER_DB 0xffff0000 | ||
2119 | #define BMOISE_PWDB 0xffff | ||
2120 | #define BPOWERMEAST_LENGTH 10 | ||
2121 | #define BPOWERMEASF_LENGTH 3 | ||
2122 | #define BRX_HT_BW 0x1 | ||
2123 | #define BRXSC 0x6 | ||
2124 | #define BRX_HT 0x8 | ||
2125 | #define BNB_INTF_DET_ON 0x1 | ||
2126 | #define BINTF_WIN_LEN_CFG 0x30 | ||
2127 | #define BNB_INTF_TH_CFG 0x1c0 | ||
2128 | #define BRFGAIN 0x3f | ||
2129 | #define BTABLESEL 0x40 | ||
2130 | #define BTRSW 0x80 | ||
2131 | #define BRXSNR_A 0xff | ||
2132 | #define BRXSNR_B 0xff00 | ||
2133 | #define BRXSNR_C 0xff0000 | ||
2134 | #define BRXSNR_D 0xff000000 | ||
2135 | #define BSNR_EVMT_LENGTH 8 | ||
2136 | #define BSNR_EVMF_LENGTH 1 | ||
2137 | #define BCSI1ST 0xff | ||
2138 | #define BCSI2ND 0xff00 | ||
2139 | #define BRXEVM1ST 0xff0000 | ||
2140 | #define BRXEVM2ND 0xff000000 | ||
2141 | #define BSIGEVM 0xff | ||
2142 | #define BPWDB 0xff00 | ||
2143 | #define BSGIEN 0x10000 | ||
2144 | |||
2145 | #define BSFACTOR_QMA1 0xf | ||
2146 | #define BSFACTOR_QMA2 0xf0 | ||
2147 | #define BSFACTOR_QMA3 0xf00 | ||
2148 | #define BSFACTOR_QMA4 0xf000 | ||
2149 | #define BSFACTOR_QMA5 0xf0000 | ||
2150 | #define BSFACTOR_QMA6 0xf0000 | ||
2151 | #define BSFACTOR_QMA7 0xf00000 | ||
2152 | #define BSFACTOR_QMA8 0xf000000 | ||
2153 | #define BSFACTOR_QMA9 0xf0000000 | ||
2154 | #define BCSI_SCHEME 0x100000 | ||
2155 | |||
2156 | #define BNOISE_LVL_TOP_SET 0x3 | ||
2157 | #define BCHSMOOTH 0x4 | ||
2158 | #define BCHSMOOTH_CFG1 0x38 | ||
2159 | #define BCHSMOOTH_CFG2 0x1c0 | ||
2160 | #define BCHSMOOTH_CFG3 0xe00 | ||
2161 | #define BCHSMOOTH_CFG4 0x7000 | ||
2162 | #define BMRCMODE 0x800000 | ||
2163 | #define BTHEVMCFG 0x7000000 | ||
2164 | |||
2165 | #define BLOOP_FIT_TYPE 0x1 | ||
2166 | #define BUPD_CFO 0x40 | ||
2167 | #define BUPD_CFO_OFFDATA 0x80 | ||
2168 | #define BADV_UPD_CFO 0x100 | ||
2169 | #define BADV_TIME_CTRL 0x800 | ||
2170 | #define BUPD_CLKO 0x1000 | ||
2171 | #define BFC 0x6000 | ||
2172 | #define BTRACKING_MODE 0x8000 | ||
2173 | #define BPHCMP_ENABLE 0x10000 | ||
2174 | #define BUPD_CLKO_LTF 0x20000 | ||
2175 | #define BCOM_CH_CFO 0x40000 | ||
2176 | #define BCSI_ESTI_MODE 0x80000 | ||
2177 | #define BADV_UPD_EQZ 0x100000 | ||
2178 | #define BUCHCFG 0x7000000 | ||
2179 | #define BUPDEQZ 0x8000000 | ||
2180 | |||
2181 | #define BRX_PESUDO_NOISE_ON 0x20000000 | ||
2182 | #define BRX_PESUDO_NOISE_A 0xff | ||
2183 | #define BRX_PESUDO_NOISE_B 0xff00 | ||
2184 | #define BRX_PESUDO_NOISE_C 0xff0000 | ||
2185 | #define BRX_PESUDO_NOISE_D 0xff000000 | ||
2186 | #define BRX_PESUDO_NOISESTATE_A 0xffff | ||
2187 | #define BRX_PESUDO_NOISESTATE_B 0xffff0000 | ||
2188 | #define BRX_PESUDO_NOISESTATE_C 0xffff | ||
2189 | #define BRX_PESUDO_NOISESTATE_D 0xffff0000 | ||
2190 | |||
2191 | #define BZEBRA1_HSSIENABLE 0x8 | ||
2192 | #define BZEBRA1_TRXCONTROL 0xc00 | ||
2193 | #define BZEBRA1_TRXGAINSETTING 0x07f | ||
2194 | #define BZEBRA1_RXCOUNTER 0xc00 | ||
2195 | #define BZEBRA1_TXCHANGEPUMP 0x38 | ||
2196 | #define BZEBRA1_RXCHANGEPUMP 0x7 | ||
2197 | #define BZEBRA1_CHANNEL_NUM 0xf80 | ||
2198 | #define BZEBRA1_TXLPFBW 0x400 | ||
2199 | #define BZEBRA1_RXLPFBW 0x600 | ||
2200 | |||
2201 | #define BRTL8256REG_MODE_CTRL1 0x100 | ||
2202 | #define BRTL8256REG_MODE_CTRL0 0x40 | ||
2203 | #define BRTL8256REG_TXLPFBW 0x18 | ||
2204 | #define BRTL8256REG_RXLPFBW 0x600 | ||
2205 | |||
2206 | #define BRTL8258_TXLPFBW 0xc | ||
2207 | #define BRTL8258_RXLPFBW 0xc00 | ||
2208 | #define BRTL8258_RSSILPFBW 0xc0 | ||
2209 | |||
2210 | #define BBYTE0 0x1 | ||
2211 | #define BBYTE1 0x2 | ||
2212 | #define BBYTE2 0x4 | ||
2213 | #define BBYTE3 0x8 | ||
2214 | #define BWORD0 0x3 | ||
2215 | #define BWORD1 0xc | ||
2216 | #define BWORD 0xf | ||
2217 | |||
2218 | #define MASKBYTE0 0xff | ||
2219 | #define MASKBYTE1 0xff00 | ||
2220 | #define MASKBYTE2 0xff0000 | ||
2221 | #define MASKBYTE3 0xff000000 | ||
2222 | #define MASKHWORD 0xffff0000 | ||
2223 | #define MASKLWORD 0x0000ffff | ||
2224 | #define MASKDWORD 0xffffffff | ||
2225 | #define MASK12BITS 0xfff | ||
2226 | #define MASKH4BITS 0xf0000000 | ||
2227 | #define MASKOFDM_D 0xffc00000 | ||
2228 | #define MASKCCK 0x3f3f3f3f | ||
2229 | |||
2230 | #define MASK4BITS 0x0f | ||
2231 | #define MASK20BITS 0xfffff | ||
2232 | #define RFREG_OFFSET_MASK 0xfffff | ||
2233 | |||
2234 | #define BENABLE 0x1 | ||
2235 | #define BDISABLE 0x0 | ||
2236 | |||
2237 | #define LEFT_ANTENNA 0x0 | ||
2238 | #define RIGHT_ANTENNA 0x1 | ||
2239 | |||
2240 | #define TCHECK_TXSTATUS 500 | ||
2241 | #define TUPDATE_RXCOUNTER 100 | ||
2242 | |||
2243 | #define REG_UN_USED_REGISTER 0x01bf | ||
2244 | |||
2245 | /* WOL bit information */ | ||
2246 | #define HAL92C_WOL_PTK_UPDATE_EVENT BIT(0) | ||
2247 | #define HAL92C_WOL_GTK_UPDATE_EVENT BIT(1) | ||
2248 | #define HAL92C_WOL_DISASSOC_EVENT BIT(2) | ||
2249 | #define HAL92C_WOL_DEAUTH_EVENT BIT(3) | ||
2250 | #define HAL92C_WOL_FW_DISCONNECT_EVENT BIT(4) | ||
2251 | |||
2252 | #define WOL_REASON_PTK_UPDATE BIT(0) | ||
2253 | #define WOL_REASON_GTK_UPDATE BIT(1) | ||
2254 | #define WOL_REASON_DISASSOC BIT(2) | ||
2255 | #define WOL_REASON_DEAUTH BIT(3) | ||
2256 | #define WOL_REASON_FW_DISCONNECT BIT(4) | ||
2257 | |||
2258 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/rf.c b/drivers/net/wireless/rtlwifi/rtl8188ee/rf.c new file mode 100644 index 000000000000..4faafdbab9c6 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/rf.c | |||
@@ -0,0 +1,467 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "../wifi.h" | ||
31 | #include "reg.h" | ||
32 | #include "def.h" | ||
33 | #include "phy.h" | ||
34 | #include "rf.h" | ||
35 | #include "dm.h" | ||
36 | |||
37 | void rtl88e_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) | ||
38 | { | ||
39 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
40 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
41 | |||
42 | switch (bandwidth) { | ||
43 | case HT_CHANNEL_WIDTH_20: | ||
44 | rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & | ||
45 | 0xfffff3ff) | BIT(10) | BIT(11)); | ||
46 | rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, | ||
47 | rtlphy->rfreg_chnlval[0]); | ||
48 | break; | ||
49 | case HT_CHANNEL_WIDTH_20_40: | ||
50 | rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & | ||
51 | 0xfffff3ff) | BIT(10)); | ||
52 | rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, | ||
53 | rtlphy->rfreg_chnlval[0]); | ||
54 | break; | ||
55 | default: | ||
56 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
57 | "unknown bandwidth: %#X\n", bandwidth); | ||
58 | break; | ||
59 | } | ||
60 | } | ||
61 | |||
62 | void rtl88e_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, | ||
63 | u8 *plevel) | ||
64 | { | ||
65 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
66 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
67 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
68 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
69 | u32 tx_agc[2] = {0, 0}, tmpval; | ||
70 | bool turbo_scanoff = false; | ||
71 | u8 idx1, idx2; | ||
72 | u8 *ptr; | ||
73 | u8 direction; | ||
74 | u32 pwrtrac_value; | ||
75 | |||
76 | if (rtlefuse->eeprom_regulatory != 0) | ||
77 | turbo_scanoff = true; | ||
78 | |||
79 | if (mac->act_scanning == true) { | ||
80 | tx_agc[RF90_PATH_A] = 0x3f3f3f3f; | ||
81 | tx_agc[RF90_PATH_B] = 0x3f3f3f3f; | ||
82 | |||
83 | if (turbo_scanoff) { | ||
84 | for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { | ||
85 | tx_agc[idx1] = plevel[idx1] | | ||
86 | (plevel[idx1] << 8) | | ||
87 | (plevel[idx1] << 16) | | ||
88 | (plevel[idx1] << 24); | ||
89 | } | ||
90 | } | ||
91 | } else { | ||
92 | for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { | ||
93 | tx_agc[idx1] = plevel[idx1] | (plevel[idx1] << 8) | | ||
94 | (plevel[idx1] << 16) | | ||
95 | (plevel[idx1] << 24); | ||
96 | } | ||
97 | |||
98 | if (rtlefuse->eeprom_regulatory == 0) { | ||
99 | tmpval = (rtlphy->mcs_offset[0][6]) + | ||
100 | (rtlphy->mcs_offset[0][7] << 8); | ||
101 | tx_agc[RF90_PATH_A] += tmpval; | ||
102 | |||
103 | tmpval = (rtlphy->mcs_offset[0][14]) + | ||
104 | (rtlphy->mcs_offset[0][15] << 24); | ||
105 | tx_agc[RF90_PATH_B] += tmpval; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { | ||
110 | ptr = (u8 *)(&(tx_agc[idx1])); | ||
111 | for (idx2 = 0; idx2 < 4; idx2++) { | ||
112 | if (*ptr > RF6052_MAX_TX_PWR) | ||
113 | *ptr = RF6052_MAX_TX_PWR; | ||
114 | ptr++; | ||
115 | } | ||
116 | } | ||
117 | rtl88e_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value); | ||
118 | if (direction == 1) { | ||
119 | tx_agc[0] += pwrtrac_value; | ||
120 | tx_agc[1] += pwrtrac_value; | ||
121 | } else if (direction == 2) { | ||
122 | tx_agc[0] -= pwrtrac_value; | ||
123 | tx_agc[1] -= pwrtrac_value; | ||
124 | } | ||
125 | tmpval = tx_agc[RF90_PATH_A] & 0xff; | ||
126 | rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval); | ||
127 | |||
128 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
129 | "CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, | ||
130 | RTXAGC_A_CCK1_MCS32); | ||
131 | |||
132 | tmpval = tx_agc[RF90_PATH_A] >> 8; | ||
133 | |||
134 | rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); | ||
135 | |||
136 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
137 | "CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, | ||
138 | RTXAGC_B_CCK11_A_CCK2_11); | ||
139 | |||
140 | tmpval = tx_agc[RF90_PATH_B] >> 24; | ||
141 | rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval); | ||
142 | |||
143 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
144 | "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, | ||
145 | RTXAGC_B_CCK11_A_CCK2_11); | ||
146 | |||
147 | tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff; | ||
148 | rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval); | ||
149 | |||
150 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
151 | "CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, | ||
152 | RTXAGC_B_CCK1_55_MCS32); | ||
153 | } | ||
154 | |||
155 | static void rtl88e_phy_get_power_base(struct ieee80211_hw *hw, | ||
156 | u8 *pwrlvlofdm, u8 *pwrlvlbw20, | ||
157 | u8 *pwrlvlbw40, u8 channel, | ||
158 | u32 *ofdmbase, u32 *mcsbase) | ||
159 | { | ||
160 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
161 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
162 | u32 base0, base1; | ||
163 | u8 i, powerlevel[2]; | ||
164 | |||
165 | for (i = 0; i < 2; i++) { | ||
166 | base0 = pwrlvlofdm[i]; | ||
167 | |||
168 | base0 = (base0 << 24) | (base0 << 16) | | ||
169 | (base0 << 8) | base0; | ||
170 | *(ofdmbase + i) = base0; | ||
171 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
172 | "[OFDM power base index rf(%c) = 0x%x]\n", | ||
173 | ((i == 0) ? 'A' : 'B'), *(ofdmbase + i)); | ||
174 | } | ||
175 | |||
176 | for (i = 0; i < 2; i++) { | ||
177 | if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) | ||
178 | powerlevel[i] = pwrlvlbw20[i]; | ||
179 | else | ||
180 | powerlevel[i] = pwrlvlbw40[i]; | ||
181 | base1 = powerlevel[i]; | ||
182 | base1 = (base1 << 24) | | ||
183 | (base1 << 16) | (base1 << 8) | base1; | ||
184 | |||
185 | *(mcsbase + i) = base1; | ||
186 | |||
187 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
188 | "[MCS power base index rf(%c) = 0x%x]\n", | ||
189 | ((i == 0) ? 'A' : 'B'), *(mcsbase + i)); | ||
190 | } | ||
191 | } | ||
192 | |||
193 | static void get_txpwr_by_reg(struct ieee80211_hw *hw, u8 chan, u8 index, | ||
194 | u32 *base0, u32 *base1, u32 *outval) | ||
195 | { | ||
196 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
197 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
198 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
199 | u8 i, chg = 0, pwr_lim[4], pwr_diff = 0, cust_pwr_dif; | ||
200 | u32 writeval, cust_lim, rf, tmp; | ||
201 | u8 ch = chan - 1; | ||
202 | u8 j; | ||
203 | |||
204 | for (rf = 0; rf < 2; rf++) { | ||
205 | j = index + (rf ? 8 : 0); | ||
206 | tmp = ((index < 2) ? base0[rf] : base1[rf]); | ||
207 | switch (rtlefuse->eeprom_regulatory) { | ||
208 | case 0: | ||
209 | chg = 0; | ||
210 | |||
211 | writeval = rtlphy->mcs_offset[chg][j] + tmp; | ||
212 | |||
213 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
214 | "RTK better performance, " | ||
215 | "writeval(%c) = 0x%x\n", | ||
216 | ((rf == 0) ? 'A' : 'B'), writeval); | ||
217 | break; | ||
218 | case 1: | ||
219 | if (rtlphy->pwrgroup_cnt == 1) { | ||
220 | chg = 0; | ||
221 | } else { | ||
222 | chg = chan / 3; | ||
223 | if (chan == 14) | ||
224 | chg = 5; | ||
225 | } | ||
226 | writeval = rtlphy->mcs_offset[chg][j] + tmp; | ||
227 | |||
228 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
229 | "Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n", | ||
230 | ((rf == 0) ? 'A' : 'B'), writeval); | ||
231 | break; | ||
232 | case 2: | ||
233 | writeval = ((index < 2) ? base0[rf] : base1[rf]); | ||
234 | |||
235 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
236 | "Better regulatory, writeval(%c) = 0x%x\n", | ||
237 | ((rf == 0) ? 'A' : 'B'), writeval); | ||
238 | break; | ||
239 | case 3: | ||
240 | chg = 0; | ||
241 | |||
242 | if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { | ||
243 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
244 | "customer's limit, 40MHz rf(%c) = 0x%x\n", | ||
245 | ((rf == 0) ? 'A' : 'B'), | ||
246 | rtlefuse->pwrgroup_ht40[rf][ch]); | ||
247 | } else { | ||
248 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
249 | "customer's limit, 20MHz rf(%c) = 0x%x\n", | ||
250 | ((rf == 0) ? 'A' : 'B'), | ||
251 | rtlefuse->pwrgroup_ht20[rf][ch]); | ||
252 | } | ||
253 | |||
254 | if (index < 2) | ||
255 | pwr_diff = rtlefuse->txpwr_legacyhtdiff[rf][ch]; | ||
256 | else if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) | ||
257 | pwr_diff = rtlefuse->txpwr_ht20diff[rf][ch]; | ||
258 | |||
259 | if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) | ||
260 | cust_pwr_dif = rtlefuse->pwrgroup_ht40[rf][ch]; | ||
261 | else | ||
262 | cust_pwr_dif = rtlefuse->pwrgroup_ht20[rf][ch]; | ||
263 | |||
264 | if (pwr_diff > cust_pwr_dif) | ||
265 | pwr_diff = 0; | ||
266 | else | ||
267 | pwr_diff = cust_pwr_dif - pwr_diff; | ||
268 | |||
269 | for (i = 0; i < 4; i++) { | ||
270 | pwr_lim[i] = (u8)((rtlphy->mcs_offset[chg][j] & | ||
271 | (0x7f << (i * 8))) >> (i * 8)); | ||
272 | |||
273 | if (pwr_lim[i] > pwr_diff) | ||
274 | pwr_lim[i] = pwr_diff; | ||
275 | } | ||
276 | |||
277 | cust_lim = (pwr_lim[3] << 24) | (pwr_lim[2] << 16) | | ||
278 | (pwr_lim[1] << 8) | (pwr_lim[0]); | ||
279 | |||
280 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
281 | "Customer's limit rf(%c) = 0x%x\n", | ||
282 | ((rf == 0) ? 'A' : 'B'), cust_lim); | ||
283 | |||
284 | writeval = cust_lim + tmp; | ||
285 | |||
286 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
287 | "Customer, writeval rf(%c) = 0x%x\n", | ||
288 | ((rf == 0) ? 'A' : 'B'), writeval); | ||
289 | break; | ||
290 | default: | ||
291 | chg = 0; | ||
292 | writeval = rtlphy->mcs_offset[chg][j] + tmp; | ||
293 | |||
294 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
295 | "RTK better performance, writeval " | ||
296 | "rf(%c) = 0x%x\n", | ||
297 | ((rf == 0) ? 'A' : 'B'), writeval); | ||
298 | break; | ||
299 | } | ||
300 | |||
301 | if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1) | ||
302 | writeval = writeval - 0x06060606; | ||
303 | else if (rtlpriv->dm.dynamic_txhighpower_lvl == | ||
304 | TXHIGHPWRLEVEL_BT2) | ||
305 | writeval -= 0x0c0c0c0c; | ||
306 | *(outval + rf) = writeval; | ||
307 | } | ||
308 | } | ||
309 | |||
310 | static void write_ofdm_pwr(struct ieee80211_hw *hw, u8 index, u32 *pvalue) | ||
311 | { | ||
312 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
313 | u16 regoffset_a[6] = { | ||
314 | RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24, | ||
315 | RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04, | ||
316 | RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12 | ||
317 | }; | ||
318 | u16 regoffset_b[6] = { | ||
319 | RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24, | ||
320 | RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04, | ||
321 | RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12 | ||
322 | }; | ||
323 | u8 i, rf, pwr_val[4]; | ||
324 | u32 writeval; | ||
325 | u16 regoffset; | ||
326 | |||
327 | for (rf = 0; rf < 2; rf++) { | ||
328 | writeval = pvalue[rf]; | ||
329 | for (i = 0; i < 4; i++) { | ||
330 | pwr_val[i] = (u8) ((writeval & (0x7f << | ||
331 | (i * 8))) >> (i * 8)); | ||
332 | |||
333 | if (pwr_val[i] > RF6052_MAX_TX_PWR) | ||
334 | pwr_val[i] = RF6052_MAX_TX_PWR; | ||
335 | } | ||
336 | writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) | | ||
337 | (pwr_val[1] << 8) | pwr_val[0]; | ||
338 | |||
339 | if (rf == 0) | ||
340 | regoffset = regoffset_a[index]; | ||
341 | else | ||
342 | regoffset = regoffset_b[index]; | ||
343 | rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval); | ||
344 | |||
345 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, | ||
346 | "Set 0x%x = %08x\n", regoffset, writeval); | ||
347 | } | ||
348 | } | ||
349 | |||
350 | void rtl88e_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, | ||
351 | u8 *pwrlvlofdm, | ||
352 | u8 *pwrlvlbw20, | ||
353 | u8 *pwrlvlbw40, u8 chan) | ||
354 | { | ||
355 | u32 writeval[2], base0[2], base1[2]; | ||
356 | u8 index; | ||
357 | u8 direction; | ||
358 | u32 pwrtrac_value; | ||
359 | |||
360 | rtl88e_phy_get_power_base(hw, pwrlvlofdm, pwrlvlbw20, | ||
361 | pwrlvlbw40, chan, &base0[0], | ||
362 | &base1[0]); | ||
363 | |||
364 | rtl88e_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value); | ||
365 | |||
366 | for (index = 0; index < 6; index++) { | ||
367 | get_txpwr_by_reg(hw, chan, index, &base0[0], &base1[0], | ||
368 | &writeval[0]); | ||
369 | if (direction == 1) { | ||
370 | writeval[0] += pwrtrac_value; | ||
371 | writeval[1] += pwrtrac_value; | ||
372 | } else if (direction == 2) { | ||
373 | writeval[0] -= pwrtrac_value; | ||
374 | writeval[1] -= pwrtrac_value; | ||
375 | } | ||
376 | write_ofdm_pwr(hw, index, &writeval[0]); | ||
377 | } | ||
378 | } | ||
379 | |||
380 | static bool rf6052_conf_para(struct ieee80211_hw *hw) | ||
381 | { | ||
382 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
383 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
384 | u32 u4val = 0; | ||
385 | u8 rfpath; | ||
386 | bool rtstatus = true; | ||
387 | struct bb_reg_def *pphyreg; | ||
388 | |||
389 | for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { | ||
390 | pphyreg = &rtlphy->phyreg_def[rfpath]; | ||
391 | |||
392 | switch (rfpath) { | ||
393 | case RF90_PATH_A: | ||
394 | case RF90_PATH_C: | ||
395 | u4val = rtl_get_bbreg(hw, pphyreg->rfintfs, | ||
396 | BRFSI_RFENV); | ||
397 | break; | ||
398 | case RF90_PATH_B: | ||
399 | case RF90_PATH_D: | ||
400 | u4val = rtl_get_bbreg(hw, pphyreg->rfintfs, | ||
401 | BRFSI_RFENV << 16); | ||
402 | break; | ||
403 | } | ||
404 | |||
405 | rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); | ||
406 | udelay(1); | ||
407 | |||
408 | rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); | ||
409 | udelay(1); | ||
410 | |||
411 | rtl_set_bbreg(hw, pphyreg->rfhssi_para2, | ||
412 | B3WIREADDREAALENGTH, 0x0); | ||
413 | udelay(1); | ||
414 | |||
415 | rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0); | ||
416 | udelay(1); | ||
417 | |||
418 | switch (rfpath) { | ||
419 | case RF90_PATH_A: | ||
420 | rtstatus = rtl88e_phy_config_rf_with_headerfile(hw, | ||
421 | (enum radio_path)rfpath); | ||
422 | break; | ||
423 | case RF90_PATH_B: | ||
424 | rtstatus = rtl88e_phy_config_rf_with_headerfile(hw, | ||
425 | (enum radio_path)rfpath); | ||
426 | break; | ||
427 | case RF90_PATH_C: | ||
428 | break; | ||
429 | case RF90_PATH_D: | ||
430 | break; | ||
431 | } | ||
432 | |||
433 | switch (rfpath) { | ||
434 | case RF90_PATH_A: | ||
435 | case RF90_PATH_C: | ||
436 | rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV, u4val); | ||
437 | break; | ||
438 | case RF90_PATH_B: | ||
439 | case RF90_PATH_D: | ||
440 | rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV << 16, | ||
441 | u4val); | ||
442 | break; | ||
443 | } | ||
444 | |||
445 | if (rtstatus != true) { | ||
446 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
447 | "Radio[%d] Fail!!", rfpath); | ||
448 | return false; | ||
449 | } | ||
450 | } | ||
451 | |||
452 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "\n"); | ||
453 | return rtstatus; | ||
454 | } | ||
455 | |||
456 | bool rtl88e_phy_rf6052_config(struct ieee80211_hw *hw) | ||
457 | { | ||
458 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
459 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
460 | |||
461 | if (rtlphy->rf_type == RF_1T1R) | ||
462 | rtlphy->num_total_rfpath = 1; | ||
463 | else | ||
464 | rtlphy->num_total_rfpath = 2; | ||
465 | |||
466 | return rf6052_conf_para(hw); | ||
467 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/rf.h b/drivers/net/wireless/rtlwifi/rtl8188ee/rf.h new file mode 100644 index 000000000000..a39a2a3dbcc9 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/rf.h | |||
@@ -0,0 +1,46 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #ifndef __RTL92C_RF_H__ | ||
31 | #define __RTL92C_RF_H__ | ||
32 | |||
33 | #define RF6052_MAX_TX_PWR 0x3F | ||
34 | #define RF6052_MAX_REG 0x3F | ||
35 | |||
36 | void rtl88e_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, | ||
37 | u8 bandwidth); | ||
38 | void rtl88e_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, | ||
39 | u8 *ppowerlevel); | ||
40 | void rtl88e_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, | ||
41 | u8 *ppowerlevel_ofdm, | ||
42 | u8 *ppowerlevel_bw20, | ||
43 | u8 *ppowerlevel_bw40, u8 channel); | ||
44 | bool rtl88e_phy_rf6052_config(struct ieee80211_hw *hw); | ||
45 | |||
46 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c new file mode 100644 index 000000000000..c254693a1e6a --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c | |||
@@ -0,0 +1,400 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "../wifi.h" | ||
31 | #include "../core.h" | ||
32 | #include "../pci.h" | ||
33 | #include "reg.h" | ||
34 | #include "def.h" | ||
35 | #include "phy.h" | ||
36 | #include "dm.h" | ||
37 | #include "hw.h" | ||
38 | #include "sw.h" | ||
39 | #include "trx.h" | ||
40 | #include "led.h" | ||
41 | #include "table.h" | ||
42 | |||
43 | #include <linux/vmalloc.h> | ||
44 | #include <linux/module.h> | ||
45 | |||
46 | static void rtl88e_init_aspm_vars(struct ieee80211_hw *hw) | ||
47 | { | ||
48 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
49 | |||
50 | /*close ASPM for AMD defaultly */ | ||
51 | rtlpci->const_amdpci_aspm = 0; | ||
52 | |||
53 | /* ASPM PS mode. | ||
54 | * 0 - Disable ASPM, | ||
55 | * 1 - Enable ASPM without Clock Req, | ||
56 | * 2 - Enable ASPM with Clock Req, | ||
57 | * 3 - Alwyas Enable ASPM with Clock Req, | ||
58 | * 4 - Always Enable ASPM without Clock Req. | ||
59 | * set defult to RTL8192CE:3 RTL8192E:2 | ||
60 | */ | ||
61 | rtlpci->const_pci_aspm = 3; | ||
62 | |||
63 | /*Setting for PCI-E device */ | ||
64 | rtlpci->const_devicepci_aspm_setting = 0x03; | ||
65 | |||
66 | /*Setting for PCI-E bridge */ | ||
67 | rtlpci->const_hostpci_aspm_setting = 0x02; | ||
68 | |||
69 | /* In Hw/Sw Radio Off situation. | ||
70 | * 0 - Default, | ||
71 | * 1 - From ASPM setting without low Mac Pwr, | ||
72 | * 2 - From ASPM setting with low Mac Pwr, | ||
73 | * 3 - Bus D3 | ||
74 | * set default to RTL8192CE:0 RTL8192SE:2 | ||
75 | */ | ||
76 | rtlpci->const_hwsw_rfoff_d3 = 0; | ||
77 | |||
78 | /* This setting works for those device with | ||
79 | * backdoor ASPM setting such as EPHY setting. | ||
80 | * 0 - Not support ASPM, | ||
81 | * 1 - Support ASPM, | ||
82 | * 2 - According to chipset. | ||
83 | */ | ||
84 | rtlpci->const_support_pciaspm = 1; | ||
85 | } | ||
86 | |||
87 | int rtl88e_init_sw_vars(struct ieee80211_hw *hw) | ||
88 | { | ||
89 | int err = 0; | ||
90 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
91 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
92 | u8 tid; | ||
93 | |||
94 | rtl8188ee_bt_reg_init(hw); | ||
95 | |||
96 | rtlpriv->dm.dm_initialgain_enable = 1; | ||
97 | rtlpriv->dm.dm_flag = 0; | ||
98 | rtlpriv->dm.disable_framebursting = 0; | ||
99 | rtlpriv->dm.thermalvalue = 0; | ||
100 | rtlpci->transmit_config = CFENDFORM | BIT(15); | ||
101 | |||
102 | /* compatible 5G band 88ce just 2.4G band & smsp */ | ||
103 | rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; | ||
104 | rtlpriv->rtlhal.bandset = BAND_ON_2_4G; | ||
105 | rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; | ||
106 | |||
107 | rtlpci->receive_config = (RCR_APPFCS | | ||
108 | RCR_APP_MIC | | ||
109 | RCR_APP_ICV | | ||
110 | RCR_APP_PHYST_RXFF | | ||
111 | RCR_HTC_LOC_CTRL | | ||
112 | RCR_AMF | | ||
113 | RCR_ACF | | ||
114 | RCR_ADF | | ||
115 | RCR_AICV | | ||
116 | RCR_ACRC32 | | ||
117 | RCR_AB | | ||
118 | RCR_AM | | ||
119 | RCR_APM | | ||
120 | 0); | ||
121 | |||
122 | rtlpci->irq_mask[0] = | ||
123 | (u32) (IMR_PSTIMEOUT | | ||
124 | IMR_HSISR_IND_ON_INT | | ||
125 | IMR_C2HCMD | | ||
126 | IMR_HIGHDOK | | ||
127 | IMR_MGNTDOK | | ||
128 | IMR_BKDOK | | ||
129 | IMR_BEDOK | | ||
130 | IMR_VIDOK | | ||
131 | IMR_VODOK | | ||
132 | IMR_RDU | | ||
133 | IMR_ROK | | ||
134 | 0); | ||
135 | rtlpci->irq_mask[1] = (u32) (IMR_RXFOVW | 0); | ||
136 | rtlpci->sys_irq_mask = (u32) (HSIMR_PDN_INT_EN | HSIMR_RON_INT_EN); | ||
137 | |||
138 | /* for debug level */ | ||
139 | rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; | ||
140 | /* for LPS & IPS */ | ||
141 | rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; | ||
142 | rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; | ||
143 | rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; | ||
144 | if (!rtlpriv->psc.inactiveps) | ||
145 | pr_info("rtl8188ee: Power Save off (module option)\n"); | ||
146 | if (!rtlpriv->psc.fwctrl_lps) | ||
147 | pr_info("rtl8188ee: FW Power Save off (module option)\n"); | ||
148 | rtlpriv->psc.reg_fwctrl_lps = 3; | ||
149 | rtlpriv->psc.reg_max_lps_awakeintvl = 5; | ||
150 | /* for ASPM, you can close aspm through | ||
151 | * set const_support_pciaspm = 0 | ||
152 | */ | ||
153 | rtl88e_init_aspm_vars(hw); | ||
154 | |||
155 | if (rtlpriv->psc.reg_fwctrl_lps == 1) | ||
156 | rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; | ||
157 | else if (rtlpriv->psc.reg_fwctrl_lps == 2) | ||
158 | rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; | ||
159 | else if (rtlpriv->psc.reg_fwctrl_lps == 3) | ||
160 | rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; | ||
161 | |||
162 | /* for firmware buf */ | ||
163 | rtlpriv->rtlhal.pfirmware = vmalloc(0x8000); | ||
164 | if (!rtlpriv->rtlhal.pfirmware) { | ||
165 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
166 | "Can't alloc buffer for fw.\n"); | ||
167 | return 1; | ||
168 | } | ||
169 | |||
170 | rtlpriv->cfg->fw_name = "rtlwifi/rtl8188efw.bin"; | ||
171 | rtlpriv->max_fw_size = 0x8000; | ||
172 | pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name); | ||
173 | err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, | ||
174 | rtlpriv->io.dev, GFP_KERNEL, hw, | ||
175 | rtl_fw_cb); | ||
176 | if (err) { | ||
177 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
178 | "Failed to request firmware!\n"); | ||
179 | return 1; | ||
180 | } | ||
181 | |||
182 | /* for early mode */ | ||
183 | rtlpriv->rtlhal.earlymode_enable = false; | ||
184 | rtlpriv->rtlhal.max_earlymode_num = 10; | ||
185 | for (tid = 0; tid < 8; tid++) | ||
186 | skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]); | ||
187 | |||
188 | /*low power */ | ||
189 | rtlpriv->psc.low_power_enable = false; | ||
190 | if (rtlpriv->psc.low_power_enable) { | ||
191 | init_timer(&rtlpriv->works.fw_clockoff_timer); | ||
192 | setup_timer(&rtlpriv->works.fw_clockoff_timer, | ||
193 | rtl88ee_fw_clk_off_timer_callback, | ||
194 | (unsigned long)hw); | ||
195 | } | ||
196 | |||
197 | init_timer(&rtlpriv->works.fast_antenna_training_timer); | ||
198 | setup_timer(&rtlpriv->works.fast_antenna_training_timer, | ||
199 | rtl88e_dm_fast_antenna_training_callback, | ||
200 | (unsigned long)hw); | ||
201 | return err; | ||
202 | } | ||
203 | |||
204 | void rtl88e_deinit_sw_vars(struct ieee80211_hw *hw) | ||
205 | { | ||
206 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
207 | |||
208 | if (rtlpriv->rtlhal.pfirmware) { | ||
209 | vfree(rtlpriv->rtlhal.pfirmware); | ||
210 | rtlpriv->rtlhal.pfirmware = NULL; | ||
211 | } | ||
212 | |||
213 | if (rtlpriv->psc.low_power_enable) | ||
214 | del_timer_sync(&rtlpriv->works.fw_clockoff_timer); | ||
215 | |||
216 | del_timer_sync(&rtlpriv->works.fast_antenna_training_timer); | ||
217 | } | ||
218 | |||
219 | static struct rtl_hal_ops rtl8188ee_hal_ops = { | ||
220 | .init_sw_vars = rtl88e_init_sw_vars, | ||
221 | .deinit_sw_vars = rtl88e_deinit_sw_vars, | ||
222 | .read_eeprom_info = rtl88ee_read_eeprom_info, | ||
223 | .interrupt_recognized = rtl88ee_interrupt_recognized,/*need check*/ | ||
224 | .hw_init = rtl88ee_hw_init, | ||
225 | .hw_disable = rtl88ee_card_disable, | ||
226 | .hw_suspend = rtl88ee_suspend, | ||
227 | .hw_resume = rtl88ee_resume, | ||
228 | .enable_interrupt = rtl88ee_enable_interrupt, | ||
229 | .disable_interrupt = rtl88ee_disable_interrupt, | ||
230 | .set_network_type = rtl88ee_set_network_type, | ||
231 | .set_chk_bssid = rtl88ee_set_check_bssid, | ||
232 | .set_qos = rtl88ee_set_qos, | ||
233 | .set_bcn_reg = rtl88ee_set_beacon_related_registers, | ||
234 | .set_bcn_intv = rtl88ee_set_beacon_interval, | ||
235 | .update_interrupt_mask = rtl88ee_update_interrupt_mask, | ||
236 | .get_hw_reg = rtl88ee_get_hw_reg, | ||
237 | .set_hw_reg = rtl88ee_set_hw_reg, | ||
238 | .update_rate_tbl = rtl88ee_update_hal_rate_tbl, | ||
239 | .fill_tx_desc = rtl88ee_tx_fill_desc, | ||
240 | .fill_tx_cmddesc = rtl88ee_tx_fill_cmddesc, | ||
241 | .query_rx_desc = rtl88ee_rx_query_desc, | ||
242 | .set_channel_access = rtl88ee_update_channel_access_setting, | ||
243 | .radio_onoff_checking = rtl88ee_gpio_radio_on_off_checking, | ||
244 | .set_bw_mode = rtl88e_phy_set_bw_mode, | ||
245 | .switch_channel = rtl88e_phy_sw_chnl, | ||
246 | .dm_watchdog = rtl88e_dm_watchdog, | ||
247 | .scan_operation_backup = rtl88e_phy_scan_operation_backup, | ||
248 | .set_rf_power_state = rtl88e_phy_set_rf_power_state, | ||
249 | .led_control = rtl88ee_led_control, | ||
250 | .set_desc = rtl88ee_set_desc, | ||
251 | .get_desc = rtl88ee_get_desc, | ||
252 | .tx_polling = rtl88ee_tx_polling, | ||
253 | .enable_hw_sec = rtl88ee_enable_hw_security_config, | ||
254 | .set_key = rtl88ee_set_key, | ||
255 | .init_sw_leds = rtl88ee_init_sw_leds, | ||
256 | .allow_all_destaddr = rtl88ee_allow_all_destaddr, | ||
257 | .get_bbreg = rtl88e_phy_query_bb_reg, | ||
258 | .set_bbreg = rtl88e_phy_set_bb_reg, | ||
259 | .get_rfreg = rtl88e_phy_query_rf_reg, | ||
260 | .set_rfreg = rtl88e_phy_set_rf_reg, | ||
261 | }; | ||
262 | |||
263 | static struct rtl_mod_params rtl88ee_mod_params = { | ||
264 | .sw_crypto = false, | ||
265 | .inactiveps = true, | ||
266 | .swctrl_lps = false, | ||
267 | .fwctrl_lps = true, | ||
268 | .debug = DBG_EMERG, | ||
269 | }; | ||
270 | |||
271 | static struct rtl_hal_cfg rtl88ee_hal_cfg = { | ||
272 | .bar_id = 2, | ||
273 | .write_readback = true, | ||
274 | .name = "rtl88e_pci", | ||
275 | .ops = &rtl8188ee_hal_ops, | ||
276 | .mod_params = &rtl88ee_mod_params, | ||
277 | |||
278 | .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, | ||
279 | .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, | ||
280 | .maps[SYS_CLK] = REG_SYS_CLKR, | ||
281 | .maps[MAC_RCR_AM] = AM, | ||
282 | .maps[MAC_RCR_AB] = AB, | ||
283 | .maps[MAC_RCR_ACRC32] = ACRC32, | ||
284 | .maps[MAC_RCR_ACF] = ACF, | ||
285 | .maps[MAC_RCR_AAP] = AAP, | ||
286 | |||
287 | .maps[EFUSE_ACCESS] = REG_EFUSE_ACCESS, | ||
288 | |||
289 | .maps[EFUSE_TEST] = REG_EFUSE_TEST, | ||
290 | .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, | ||
291 | .maps[EFUSE_CLK] = 0, | ||
292 | .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, | ||
293 | .maps[EFUSE_PWC_EV12V] = PWC_EV12V, | ||
294 | .maps[EFUSE_FEN_ELDR] = FEN_ELDR, | ||
295 | .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN, | ||
296 | .maps[EFUSE_ANA8M] = ANA8M, | ||
297 | .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, | ||
298 | .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, | ||
299 | .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, | ||
300 | .maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES, | ||
301 | |||
302 | .maps[RWCAM] = REG_CAMCMD, | ||
303 | .maps[WCAMI] = REG_CAMWRITE, | ||
304 | .maps[RCAMO] = REG_CAMREAD, | ||
305 | .maps[CAMDBG] = REG_CAMDBG, | ||
306 | .maps[SECR] = REG_SECCFG, | ||
307 | .maps[SEC_CAM_NONE] = CAM_NONE, | ||
308 | .maps[SEC_CAM_WEP40] = CAM_WEP40, | ||
309 | .maps[SEC_CAM_TKIP] = CAM_TKIP, | ||
310 | .maps[SEC_CAM_AES] = CAM_AES, | ||
311 | .maps[SEC_CAM_WEP104] = CAM_WEP104, | ||
312 | |||
313 | .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, | ||
314 | .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, | ||
315 | .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, | ||
316 | .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, | ||
317 | .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, | ||
318 | .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, | ||
319 | /* .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8, */ /*need check*/ | ||
320 | .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, | ||
321 | .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, | ||
322 | .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, | ||
323 | .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, | ||
324 | .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, | ||
325 | .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, | ||
326 | .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, | ||
327 | /* .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2,*/ | ||
328 | /* .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1,*/ | ||
329 | |||
330 | .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, | ||
331 | .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, | ||
332 | .maps[RTL_IMR_BCNINT] = IMR_BCNDMAINT0, | ||
333 | .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, | ||
334 | .maps[RTL_IMR_RDU] = IMR_RDU, | ||
335 | .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, | ||
336 | .maps[RTL_IMR_BDOK] = IMR_BCNDOK0, | ||
337 | .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK, | ||
338 | .maps[RTL_IMR_TBDER] = IMR_TBDER, | ||
339 | .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK, | ||
340 | .maps[RTL_IMR_TBDOK] = IMR_TBDOK, | ||
341 | .maps[RTL_IMR_BKDOK] = IMR_BKDOK, | ||
342 | .maps[RTL_IMR_BEDOK] = IMR_BEDOK, | ||
343 | .maps[RTL_IMR_VIDOK] = IMR_VIDOK, | ||
344 | .maps[RTL_IMR_VODOK] = IMR_VODOK, | ||
345 | .maps[RTL_IMR_ROK] = IMR_ROK, | ||
346 | .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNDMAINT0 | IMR_TBDOK | IMR_TBDER), | ||
347 | |||
348 | .maps[RTL_RC_CCK_RATE1M] = DESC92C_RATE1M, | ||
349 | .maps[RTL_RC_CCK_RATE2M] = DESC92C_RATE2M, | ||
350 | .maps[RTL_RC_CCK_RATE5_5M] = DESC92C_RATE5_5M, | ||
351 | .maps[RTL_RC_CCK_RATE11M] = DESC92C_RATE11M, | ||
352 | .maps[RTL_RC_OFDM_RATE6M] = DESC92C_RATE6M, | ||
353 | .maps[RTL_RC_OFDM_RATE9M] = DESC92C_RATE9M, | ||
354 | .maps[RTL_RC_OFDM_RATE12M] = DESC92C_RATE12M, | ||
355 | .maps[RTL_RC_OFDM_RATE18M] = DESC92C_RATE18M, | ||
356 | .maps[RTL_RC_OFDM_RATE24M] = DESC92C_RATE24M, | ||
357 | .maps[RTL_RC_OFDM_RATE36M] = DESC92C_RATE36M, | ||
358 | .maps[RTL_RC_OFDM_RATE48M] = DESC92C_RATE48M, | ||
359 | .maps[RTL_RC_OFDM_RATE54M] = DESC92C_RATE54M, | ||
360 | |||
361 | .maps[RTL_RC_HT_RATEMCS7] = DESC92C_RATEMCS7, | ||
362 | .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15, | ||
363 | }; | ||
364 | |||
365 | static DEFINE_PCI_DEVICE_TABLE(rtl88ee_pci_ids) = { | ||
366 | {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8179, rtl88ee_hal_cfg)}, | ||
367 | {}, | ||
368 | }; | ||
369 | |||
370 | MODULE_DEVICE_TABLE(pci, rtl88ee_pci_ids); | ||
371 | |||
372 | MODULE_AUTHOR("zhiyuan_yang <zhiyuan_yang@realsil.com.cn>"); | ||
373 | MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>"); | ||
374 | MODULE_AUTHOR("Larry Finger <Larry.Finger@lwfinger.net>"); | ||
375 | MODULE_LICENSE("GPL"); | ||
376 | MODULE_DESCRIPTION("Realtek 8188E 802.11n PCI wireless"); | ||
377 | MODULE_FIRMWARE("rtlwifi/rtl8188efw.bin"); | ||
378 | |||
379 | module_param_named(swenc, rtl88ee_mod_params.sw_crypto, bool, 0444); | ||
380 | module_param_named(debug, rtl88ee_mod_params.debug, int, 0444); | ||
381 | module_param_named(ips, rtl88ee_mod_params.inactiveps, bool, 0444); | ||
382 | module_param_named(swlps, rtl88ee_mod_params.swctrl_lps, bool, 0444); | ||
383 | module_param_named(fwlps, rtl88ee_mod_params.fwctrl_lps, bool, 0444); | ||
384 | MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n"); | ||
385 | MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n"); | ||
386 | MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n"); | ||
387 | MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); | ||
388 | MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); | ||
389 | |||
390 | static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); | ||
391 | |||
392 | static struct pci_driver rtl88ee_driver = { | ||
393 | .name = KBUILD_MODNAME, | ||
394 | .id_table = rtl88ee_pci_ids, | ||
395 | .probe = rtl_pci_probe, | ||
396 | .remove = rtl_pci_disconnect, | ||
397 | .driver.pm = &rtlwifi_pm_ops, | ||
398 | }; | ||
399 | |||
400 | module_pci_driver(rtl88ee_driver); | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.h b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.h new file mode 100644 index 000000000000..85e02b3bdff8 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #ifndef __RTL92CE_SW_H__ | ||
31 | #define __RTL92CE_SW_H__ | ||
32 | |||
33 | int rtl88e_init_sw_vars(struct ieee80211_hw *hw); | ||
34 | void rtl88e_deinit_sw_vars(struct ieee80211_hw *hw); | ||
35 | |||
36 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/table.c b/drivers/net/wireless/rtlwifi/rtl8188ee/table.c new file mode 100644 index 000000000000..fad373f97b2c --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/table.c | |||
@@ -0,0 +1,643 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Created on 2010/ 5/18, 1:41 | ||
27 | * | ||
28 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
29 | * | ||
30 | *****************************************************************************/ | ||
31 | |||
32 | #include "table.h" | ||
33 | |||
34 | u32 RTL8188EEPHY_REG_1TARRAY[] = { | ||
35 | 0x800, 0x80040000, | ||
36 | 0x804, 0x00000003, | ||
37 | 0x808, 0x0000FC00, | ||
38 | 0x80C, 0x0000000A, | ||
39 | 0x810, 0x10001331, | ||
40 | 0x814, 0x020C3D10, | ||
41 | 0x818, 0x02200385, | ||
42 | 0x81C, 0x00000000, | ||
43 | 0x820, 0x01000100, | ||
44 | 0x824, 0x00390204, | ||
45 | 0x828, 0x00000000, | ||
46 | 0x82C, 0x00000000, | ||
47 | 0x830, 0x00000000, | ||
48 | 0x834, 0x00000000, | ||
49 | 0x838, 0x00000000, | ||
50 | 0x83C, 0x00000000, | ||
51 | 0x840, 0x00010000, | ||
52 | 0x844, 0x00000000, | ||
53 | 0x848, 0x00000000, | ||
54 | 0x84C, 0x00000000, | ||
55 | 0x850, 0x00000000, | ||
56 | 0x854, 0x00000000, | ||
57 | 0x858, 0x569A11A9, | ||
58 | 0x85C, 0x01000014, | ||
59 | 0x860, 0x66F60110, | ||
60 | 0x864, 0x061F0649, | ||
61 | 0x868, 0x00000000, | ||
62 | 0x86C, 0x27272700, | ||
63 | 0x870, 0x07000760, | ||
64 | 0x874, 0x25004000, | ||
65 | 0x878, 0x00000808, | ||
66 | 0x87C, 0x00000000, | ||
67 | 0x880, 0xB0000C1C, | ||
68 | 0x884, 0x00000001, | ||
69 | 0x888, 0x00000000, | ||
70 | 0x88C, 0xCCC000C0, | ||
71 | 0x890, 0x00000800, | ||
72 | 0x894, 0xFFFFFFFE, | ||
73 | 0x898, 0x40302010, | ||
74 | 0x89C, 0x00706050, | ||
75 | 0x900, 0x00000000, | ||
76 | 0x904, 0x00000023, | ||
77 | 0x908, 0x00000000, | ||
78 | 0x90C, 0x81121111, | ||
79 | 0x910, 0x00000002, | ||
80 | 0x914, 0x00000201, | ||
81 | 0xA00, 0x00D047C8, | ||
82 | 0xA04, 0x80FF000C, | ||
83 | 0xA08, 0x8C838300, | ||
84 | 0xA0C, 0x2E7F120F, | ||
85 | 0xA10, 0x9500BB78, | ||
86 | 0xA14, 0x1114D028, | ||
87 | 0xA18, 0x00881117, | ||
88 | 0xA1C, 0x89140F00, | ||
89 | 0xA20, 0x1A1B0000, | ||
90 | 0xA24, 0x090E1317, | ||
91 | 0xA28, 0x00000204, | ||
92 | 0xA2C, 0x00D30000, | ||
93 | 0xA70, 0x101FBF00, | ||
94 | 0xA74, 0x00000007, | ||
95 | 0xA78, 0x00000900, | ||
96 | 0xA7C, 0x225B0606, | ||
97 | 0xA80, 0x218075B1, | ||
98 | 0xB2C, 0x80000000, | ||
99 | 0xC00, 0x48071D40, | ||
100 | 0xC04, 0x03A05611, | ||
101 | 0xC08, 0x000000E4, | ||
102 | 0xC0C, 0x6C6C6C6C, | ||
103 | 0xC10, 0x08800000, | ||
104 | 0xC14, 0x40000100, | ||
105 | 0xC18, 0x08800000, | ||
106 | 0xC1C, 0x40000100, | ||
107 | 0xC20, 0x00000000, | ||
108 | 0xC24, 0x00000000, | ||
109 | 0xC28, 0x00000000, | ||
110 | 0xC2C, 0x00000000, | ||
111 | 0xC30, 0x69E9AC47, | ||
112 | 0xC34, 0x469652AF, | ||
113 | 0xC38, 0x49795994, | ||
114 | 0xC3C, 0x0A97971C, | ||
115 | 0xC40, 0x1F7C403F, | ||
116 | 0xC44, 0x000100B7, | ||
117 | 0xC48, 0xEC020107, | ||
118 | 0xC4C, 0x007F037F, | ||
119 | 0xC50, 0x69553420, | ||
120 | 0xC54, 0x43BC0094, | ||
121 | 0xC58, 0x00013169, | ||
122 | 0xC5C, 0x00250492, | ||
123 | 0xC60, 0x00000000, | ||
124 | 0xC64, 0x7112848B, | ||
125 | 0xC68, 0x47C00BFF, | ||
126 | 0xC6C, 0x00000036, | ||
127 | 0xC70, 0x2C7F000D, | ||
128 | 0xC74, 0x020610DB, | ||
129 | 0xC78, 0x0000001F, | ||
130 | 0xC7C, 0x00B91612, | ||
131 | 0xC80, 0x390000E4, | ||
132 | 0xC84, 0x20F60000, | ||
133 | 0xC88, 0x40000100, | ||
134 | 0xC8C, 0x20200000, | ||
135 | 0xC90, 0x00091521, | ||
136 | 0xC94, 0x00000000, | ||
137 | 0xC98, 0x00121820, | ||
138 | 0xC9C, 0x00007F7F, | ||
139 | 0xCA0, 0x00000000, | ||
140 | 0xCA4, 0x000300A0, | ||
141 | 0xCA8, 0x00000000, | ||
142 | 0xCAC, 0x00000000, | ||
143 | 0xCB0, 0x00000000, | ||
144 | 0xCB4, 0x00000000, | ||
145 | 0xCB8, 0x00000000, | ||
146 | 0xCBC, 0x28000000, | ||
147 | 0xCC0, 0x00000000, | ||
148 | 0xCC4, 0x00000000, | ||
149 | 0xCC8, 0x00000000, | ||
150 | 0xCCC, 0x00000000, | ||
151 | 0xCD0, 0x00000000, | ||
152 | 0xCD4, 0x00000000, | ||
153 | 0xCD8, 0x64B22427, | ||
154 | 0xCDC, 0x00766932, | ||
155 | 0xCE0, 0x00222222, | ||
156 | 0xCE4, 0x00000000, | ||
157 | 0xCE8, 0x37644302, | ||
158 | 0xCEC, 0x2F97D40C, | ||
159 | 0xD00, 0x00000740, | ||
160 | 0xD04, 0x00020401, | ||
161 | 0xD08, 0x0000907F, | ||
162 | 0xD0C, 0x20010201, | ||
163 | 0xD10, 0xA0633333, | ||
164 | 0xD14, 0x3333BC43, | ||
165 | 0xD18, 0x7A8F5B6F, | ||
166 | 0xD2C, 0xCC979975, | ||
167 | 0xD30, 0x00000000, | ||
168 | 0xD34, 0x80608000, | ||
169 | 0xD38, 0x00000000, | ||
170 | 0xD3C, 0x00127353, | ||
171 | 0xD40, 0x00000000, | ||
172 | 0xD44, 0x00000000, | ||
173 | 0xD48, 0x00000000, | ||
174 | 0xD4C, 0x00000000, | ||
175 | 0xD50, 0x6437140A, | ||
176 | 0xD54, 0x00000000, | ||
177 | 0xD58, 0x00000282, | ||
178 | 0xD5C, 0x30032064, | ||
179 | 0xD60, 0x4653DE68, | ||
180 | 0xD64, 0x04518A3C, | ||
181 | 0xD68, 0x00002101, | ||
182 | 0xD6C, 0x2A201C16, | ||
183 | 0xD70, 0x1812362E, | ||
184 | 0xD74, 0x322C2220, | ||
185 | 0xD78, 0x000E3C24, | ||
186 | 0xE00, 0x2D2D2D2D, | ||
187 | 0xE04, 0x2D2D2D2D, | ||
188 | 0xE08, 0x0390272D, | ||
189 | 0xE10, 0x2D2D2D2D, | ||
190 | 0xE14, 0x2D2D2D2D, | ||
191 | 0xE18, 0x2D2D2D2D, | ||
192 | 0xE1C, 0x2D2D2D2D, | ||
193 | 0xE28, 0x00000000, | ||
194 | 0xE30, 0x1000DC1F, | ||
195 | 0xE34, 0x10008C1F, | ||
196 | 0xE38, 0x02140102, | ||
197 | 0xE3C, 0x681604C2, | ||
198 | 0xE40, 0x01007C00, | ||
199 | 0xE44, 0x01004800, | ||
200 | 0xE48, 0xFB000000, | ||
201 | 0xE4C, 0x000028D1, | ||
202 | 0xE50, 0x1000DC1F, | ||
203 | 0xE54, 0x10008C1F, | ||
204 | 0xE58, 0x02140102, | ||
205 | 0xE5C, 0x28160D05, | ||
206 | 0xE60, 0x00000008, | ||
207 | 0xE68, 0x001B25A4, | ||
208 | 0xE6C, 0x00C00014, | ||
209 | 0xE70, 0x00C00014, | ||
210 | 0xE74, 0x01000014, | ||
211 | 0xE78, 0x01000014, | ||
212 | 0xE7C, 0x01000014, | ||
213 | 0xE80, 0x01000014, | ||
214 | 0xE84, 0x00C00014, | ||
215 | 0xE88, 0x01000014, | ||
216 | 0xE8C, 0x00C00014, | ||
217 | 0xED0, 0x00C00014, | ||
218 | 0xED4, 0x00C00014, | ||
219 | 0xED8, 0x00C00014, | ||
220 | 0xEDC, 0x00000014, | ||
221 | 0xEE0, 0x00000014, | ||
222 | 0xEEC, 0x01C00014, | ||
223 | 0xF14, 0x00000003, | ||
224 | 0xF4C, 0x00000000, | ||
225 | 0xF00, 0x00000300, | ||
226 | |||
227 | }; | ||
228 | |||
229 | u32 RTL8188EEPHY_REG_ARRAY_PG[] = { | ||
230 | 0xE00, 0xFFFFFFFF, 0x06070809, | ||
231 | 0xE04, 0xFFFFFFFF, 0x02020405, | ||
232 | 0xE08, 0x0000FF00, 0x00000006, | ||
233 | 0x86C, 0xFFFFFF00, 0x00020400, | ||
234 | 0xE10, 0xFFFFFFFF, 0x08090A0B, | ||
235 | 0xE14, 0xFFFFFFFF, 0x01030607, | ||
236 | 0xE18, 0xFFFFFFFF, 0x08090A0B, | ||
237 | 0xE1C, 0xFFFFFFFF, 0x01030607, | ||
238 | 0xE00, 0xFFFFFFFF, 0x00000000, | ||
239 | 0xE04, 0xFFFFFFFF, 0x00000000, | ||
240 | 0xE08, 0x0000FF00, 0x00000000, | ||
241 | 0x86C, 0xFFFFFF00, 0x00000000, | ||
242 | 0xE10, 0xFFFFFFFF, 0x00000000, | ||
243 | 0xE14, 0xFFFFFFFF, 0x00000000, | ||
244 | 0xE18, 0xFFFFFFFF, 0x00000000, | ||
245 | 0xE1C, 0xFFFFFFFF, 0x00000000, | ||
246 | 0xE00, 0xFFFFFFFF, 0x02020202, | ||
247 | 0xE04, 0xFFFFFFFF, 0x00020202, | ||
248 | 0xE08, 0x0000FF00, 0x00000000, | ||
249 | 0x86C, 0xFFFFFF00, 0x00000000, | ||
250 | 0xE10, 0xFFFFFFFF, 0x04040404, | ||
251 | 0xE14, 0xFFFFFFFF, 0x00020404, | ||
252 | 0xE18, 0xFFFFFFFF, 0x00000000, | ||
253 | 0xE1C, 0xFFFFFFFF, 0x00000000, | ||
254 | 0xE00, 0xFFFFFFFF, 0x02020202, | ||
255 | 0xE04, 0xFFFFFFFF, 0x00020202, | ||
256 | 0xE08, 0x0000FF00, 0x00000000, | ||
257 | 0x86C, 0xFFFFFF00, 0x00000000, | ||
258 | 0xE10, 0xFFFFFFFF, 0x04040404, | ||
259 | 0xE14, 0xFFFFFFFF, 0x00020404, | ||
260 | 0xE18, 0xFFFFFFFF, 0x00000000, | ||
261 | 0xE1C, 0xFFFFFFFF, 0x00000000, | ||
262 | 0xE00, 0xFFFFFFFF, 0x00000000, | ||
263 | 0xE04, 0xFFFFFFFF, 0x00000000, | ||
264 | 0xE08, 0x0000FF00, 0x00000000, | ||
265 | 0x86C, 0xFFFFFF00, 0x00000000, | ||
266 | 0xE10, 0xFFFFFFFF, 0x00000000, | ||
267 | 0xE14, 0xFFFFFFFF, 0x00000000, | ||
268 | 0xE18, 0xFFFFFFFF, 0x00000000, | ||
269 | 0xE1C, 0xFFFFFFFF, 0x00000000, | ||
270 | 0xE00, 0xFFFFFFFF, 0x02020202, | ||
271 | 0xE04, 0xFFFFFFFF, 0x00020202, | ||
272 | 0xE08, 0x0000FF00, 0x00000000, | ||
273 | 0x86C, 0xFFFFFF00, 0x00000000, | ||
274 | 0xE10, 0xFFFFFFFF, 0x04040404, | ||
275 | 0xE14, 0xFFFFFFFF, 0x00020404, | ||
276 | 0xE18, 0xFFFFFFFF, 0x00000000, | ||
277 | 0xE1C, 0xFFFFFFFF, 0x00000000, | ||
278 | 0xE00, 0xFFFFFFFF, 0x00000000, | ||
279 | 0xE04, 0xFFFFFFFF, 0x00000000, | ||
280 | 0xE08, 0x0000FF00, 0x00000000, | ||
281 | 0x86C, 0xFFFFFF00, 0x00000000, | ||
282 | 0xE10, 0xFFFFFFFF, 0x00000000, | ||
283 | 0xE14, 0xFFFFFFFF, 0x00000000, | ||
284 | 0xE18, 0xFFFFFFFF, 0x00000000, | ||
285 | 0xE1C, 0xFFFFFFFF, 0x00000000, | ||
286 | 0xE00, 0xFFFFFFFF, 0x00000000, | ||
287 | 0xE04, 0xFFFFFFFF, 0x00000000, | ||
288 | 0xE08, 0x0000FF00, 0x00000000, | ||
289 | 0x86C, 0xFFFFFF00, 0x00000000, | ||
290 | 0xE10, 0xFFFFFFFF, 0x00000000, | ||
291 | 0xE14, 0xFFFFFFFF, 0x00000000, | ||
292 | 0xE18, 0xFFFFFFFF, 0x00000000, | ||
293 | 0xE1C, 0xFFFFFFFF, 0x00000000, | ||
294 | 0xE00, 0xFFFFFFFF, 0x00000000, | ||
295 | 0xE04, 0xFFFFFFFF, 0x00000000, | ||
296 | 0xE08, 0x0000FF00, 0x00000000, | ||
297 | 0x86C, 0xFFFFFF00, 0x00000000, | ||
298 | 0xE10, 0xFFFFFFFF, 0x00000000, | ||
299 | 0xE14, 0xFFFFFFFF, 0x00000000, | ||
300 | 0xE18, 0xFFFFFFFF, 0x00000000, | ||
301 | 0xE1C, 0xFFFFFFFF, 0x00000000, | ||
302 | 0xE00, 0xFFFFFFFF, 0x00000000, | ||
303 | 0xE04, 0xFFFFFFFF, 0x00000000, | ||
304 | 0xE08, 0x0000FF00, 0x00000000, | ||
305 | 0x86C, 0xFFFFFF00, 0x00000000, | ||
306 | 0xE10, 0xFFFFFFFF, 0x00000000, | ||
307 | 0xE14, 0xFFFFFFFF, 0x00000000, | ||
308 | 0xE18, 0xFFFFFFFF, 0x00000000, | ||
309 | 0xE1C, 0xFFFFFFFF, 0x00000000, | ||
310 | 0xE00, 0xFFFFFFFF, 0x00000000, | ||
311 | 0xE04, 0xFFFFFFFF, 0x00000000, | ||
312 | 0xE08, 0x0000FF00, 0x00000000, | ||
313 | 0x86C, 0xFFFFFF00, 0x00000000, | ||
314 | 0xE10, 0xFFFFFFFF, 0x00000000, | ||
315 | 0xE14, 0xFFFFFFFF, 0x00000000, | ||
316 | 0xE18, 0xFFFFFFFF, 0x00000000, | ||
317 | 0xE1C, 0xFFFFFFFF, 0x00000000, | ||
318 | |||
319 | }; | ||
320 | |||
321 | u32 RTL8188EE_RADIOA_1TARRAY[] = { | ||
322 | 0x000, 0x00030000, | ||
323 | 0x008, 0x00084000, | ||
324 | 0x018, 0x00000407, | ||
325 | 0x019, 0x00000012, | ||
326 | 0x01E, 0x00080009, | ||
327 | 0x01F, 0x00000880, | ||
328 | 0x02F, 0x0001A060, | ||
329 | 0x03F, 0x00000000, | ||
330 | 0x042, 0x000060C0, | ||
331 | 0x057, 0x000D0000, | ||
332 | 0x058, 0x000BE180, | ||
333 | 0x067, 0x00001552, | ||
334 | 0x083, 0x00000000, | ||
335 | 0x0B0, 0x000FF8FC, | ||
336 | 0x0B1, 0x00054400, | ||
337 | 0x0B2, 0x000CCC19, | ||
338 | 0x0B4, 0x00043003, | ||
339 | 0x0B6, 0x0004953E, | ||
340 | 0x0B7, 0x0001C718, | ||
341 | 0x0B8, 0x000060FF, | ||
342 | 0x0B9, 0x00080001, | ||
343 | 0x0BA, 0x00040000, | ||
344 | 0x0BB, 0x00000400, | ||
345 | 0x0BF, 0x000C0000, | ||
346 | 0x0C2, 0x00002400, | ||
347 | 0x0C3, 0x00000009, | ||
348 | 0x0C4, 0x00040C91, | ||
349 | 0x0C5, 0x00099999, | ||
350 | 0x0C6, 0x000000A3, | ||
351 | 0x0C7, 0x00088820, | ||
352 | 0x0C8, 0x00076C06, | ||
353 | 0x0C9, 0x00000000, | ||
354 | 0x0CA, 0x00080000, | ||
355 | 0x0DF, 0x00000180, | ||
356 | 0x0EF, 0x000001A0, | ||
357 | 0x051, 0x0006B27D, | ||
358 | 0x052, 0x0007E49D, | ||
359 | 0x053, 0x00000073, | ||
360 | 0x056, 0x00051FF3, | ||
361 | 0x035, 0x00000086, | ||
362 | 0x035, 0x00000186, | ||
363 | 0x035, 0x00000286, | ||
364 | 0x036, 0x00001C25, | ||
365 | 0x036, 0x00009C25, | ||
366 | 0x036, 0x00011C25, | ||
367 | 0x036, 0x00019C25, | ||
368 | 0x0B6, 0x00048538, | ||
369 | 0x018, 0x00000C07, | ||
370 | 0x05A, 0x0004BD00, | ||
371 | 0x019, 0x000739D0, | ||
372 | 0x034, 0x0000ADF3, | ||
373 | 0x034, 0x00009DF0, | ||
374 | 0x034, 0x00008DED, | ||
375 | 0x034, 0x00007DEA, | ||
376 | 0x034, 0x00006DE7, | ||
377 | 0x034, 0x000054EE, | ||
378 | 0x034, 0x000044EB, | ||
379 | 0x034, 0x000034E8, | ||
380 | 0x034, 0x0000246B, | ||
381 | 0x034, 0x00001468, | ||
382 | 0x034, 0x0000006D, | ||
383 | 0x000, 0x00030159, | ||
384 | 0x084, 0x00068200, | ||
385 | 0x086, 0x000000CE, | ||
386 | 0x087, 0x00048A00, | ||
387 | 0x08E, 0x00065540, | ||
388 | 0x08F, 0x00088000, | ||
389 | 0x0EF, 0x000020A0, | ||
390 | 0x03B, 0x000F02B0, | ||
391 | 0x03B, 0x000EF7B0, | ||
392 | 0x03B, 0x000D4FB0, | ||
393 | 0x03B, 0x000CF060, | ||
394 | 0x03B, 0x000B0090, | ||
395 | 0x03B, 0x000A0080, | ||
396 | 0x03B, 0x00090080, | ||
397 | 0x03B, 0x0008F780, | ||
398 | 0x03B, 0x000722B0, | ||
399 | 0x03B, 0x0006F7B0, | ||
400 | 0x03B, 0x00054FB0, | ||
401 | 0x03B, 0x0004F060, | ||
402 | 0x03B, 0x00030090, | ||
403 | 0x03B, 0x00020080, | ||
404 | 0x03B, 0x00010080, | ||
405 | 0x03B, 0x0000F780, | ||
406 | 0x0EF, 0x000000A0, | ||
407 | 0x000, 0x00010159, | ||
408 | 0x018, 0x0000F407, | ||
409 | 0xFFE, 0x00000000, | ||
410 | 0xFFE, 0x00000000, | ||
411 | 0x01F, 0x00080003, | ||
412 | 0xFFE, 0x00000000, | ||
413 | 0xFFE, 0x00000000, | ||
414 | 0x01E, 0x00000001, | ||
415 | 0x01F, 0x00080000, | ||
416 | 0x000, 0x00033E60, | ||
417 | |||
418 | }; | ||
419 | |||
420 | u32 RTL8188EEMAC_1T_ARRAY[] = { | ||
421 | 0x026, 0x00000041, | ||
422 | 0x027, 0x00000035, | ||
423 | 0x428, 0x0000000A, | ||
424 | 0x429, 0x00000010, | ||
425 | 0x430, 0x00000000, | ||
426 | 0x431, 0x00000001, | ||
427 | 0x432, 0x00000002, | ||
428 | 0x433, 0x00000004, | ||
429 | 0x434, 0x00000005, | ||
430 | 0x435, 0x00000006, | ||
431 | 0x436, 0x00000007, | ||
432 | 0x437, 0x00000008, | ||
433 | 0x438, 0x00000000, | ||
434 | 0x439, 0x00000000, | ||
435 | 0x43A, 0x00000001, | ||
436 | 0x43B, 0x00000002, | ||
437 | 0x43C, 0x00000004, | ||
438 | 0x43D, 0x00000005, | ||
439 | 0x43E, 0x00000006, | ||
440 | 0x43F, 0x00000007, | ||
441 | 0x440, 0x0000005D, | ||
442 | 0x441, 0x00000001, | ||
443 | 0x442, 0x00000000, | ||
444 | 0x444, 0x00000015, | ||
445 | 0x445, 0x000000F0, | ||
446 | 0x446, 0x0000000F, | ||
447 | 0x447, 0x00000000, | ||
448 | 0x458, 0x00000041, | ||
449 | 0x459, 0x000000A8, | ||
450 | 0x45A, 0x00000072, | ||
451 | 0x45B, 0x000000B9, | ||
452 | 0x460, 0x00000066, | ||
453 | 0x461, 0x00000066, | ||
454 | 0x480, 0x00000008, | ||
455 | 0x4C8, 0x000000FF, | ||
456 | 0x4C9, 0x00000008, | ||
457 | 0x4CC, 0x000000FF, | ||
458 | 0x4CD, 0x000000FF, | ||
459 | 0x4CE, 0x00000001, | ||
460 | 0x4D3, 0x00000001, | ||
461 | 0x500, 0x00000026, | ||
462 | 0x501, 0x000000A2, | ||
463 | 0x502, 0x0000002F, | ||
464 | 0x503, 0x00000000, | ||
465 | 0x504, 0x00000028, | ||
466 | 0x505, 0x000000A3, | ||
467 | 0x506, 0x0000005E, | ||
468 | 0x507, 0x00000000, | ||
469 | 0x508, 0x0000002B, | ||
470 | 0x509, 0x000000A4, | ||
471 | 0x50A, 0x0000005E, | ||
472 | 0x50B, 0x00000000, | ||
473 | 0x50C, 0x0000004F, | ||
474 | 0x50D, 0x000000A4, | ||
475 | 0x50E, 0x00000000, | ||
476 | 0x50F, 0x00000000, | ||
477 | 0x512, 0x0000001C, | ||
478 | 0x514, 0x0000000A, | ||
479 | 0x516, 0x0000000A, | ||
480 | 0x525, 0x0000004F, | ||
481 | 0x550, 0x00000010, | ||
482 | 0x551, 0x00000010, | ||
483 | 0x559, 0x00000002, | ||
484 | 0x55D, 0x000000FF, | ||
485 | 0x605, 0x00000030, | ||
486 | 0x608, 0x0000000E, | ||
487 | 0x609, 0x0000002A, | ||
488 | 0x620, 0x000000FF, | ||
489 | 0x621, 0x000000FF, | ||
490 | 0x622, 0x000000FF, | ||
491 | 0x623, 0x000000FF, | ||
492 | 0x624, 0x000000FF, | ||
493 | 0x625, 0x000000FF, | ||
494 | 0x626, 0x000000FF, | ||
495 | 0x627, 0x000000FF, | ||
496 | 0x652, 0x00000020, | ||
497 | 0x63C, 0x0000000A, | ||
498 | 0x63D, 0x0000000A, | ||
499 | 0x63E, 0x0000000E, | ||
500 | 0x63F, 0x0000000E, | ||
501 | 0x640, 0x00000040, | ||
502 | 0x66E, 0x00000005, | ||
503 | 0x700, 0x00000021, | ||
504 | 0x701, 0x00000043, | ||
505 | 0x702, 0x00000065, | ||
506 | 0x703, 0x00000087, | ||
507 | 0x708, 0x00000021, | ||
508 | 0x709, 0x00000043, | ||
509 | 0x70A, 0x00000065, | ||
510 | 0x70B, 0x00000087, | ||
511 | |||
512 | }; | ||
513 | |||
514 | u32 RTL8188EEAGCTAB_1TARRAY[] = { | ||
515 | 0xC78, 0xFB000001, | ||
516 | 0xC78, 0xFB010001, | ||
517 | 0xC78, 0xFB020001, | ||
518 | 0xC78, 0xFB030001, | ||
519 | 0xC78, 0xFB040001, | ||
520 | 0xC78, 0xFB050001, | ||
521 | 0xC78, 0xFA060001, | ||
522 | 0xC78, 0xF9070001, | ||
523 | 0xC78, 0xF8080001, | ||
524 | 0xC78, 0xF7090001, | ||
525 | 0xC78, 0xF60A0001, | ||
526 | 0xC78, 0xF50B0001, | ||
527 | 0xC78, 0xF40C0001, | ||
528 | 0xC78, 0xF30D0001, | ||
529 | 0xC78, 0xF20E0001, | ||
530 | 0xC78, 0xF10F0001, | ||
531 | 0xC78, 0xF0100001, | ||
532 | 0xC78, 0xEF110001, | ||
533 | 0xC78, 0xEE120001, | ||
534 | 0xC78, 0xED130001, | ||
535 | 0xC78, 0xEC140001, | ||
536 | 0xC78, 0xEB150001, | ||
537 | 0xC78, 0xEA160001, | ||
538 | 0xC78, 0xE9170001, | ||
539 | 0xC78, 0xE8180001, | ||
540 | 0xC78, 0xE7190001, | ||
541 | 0xC78, 0xE61A0001, | ||
542 | 0xC78, 0xE51B0001, | ||
543 | 0xC78, 0xE41C0001, | ||
544 | 0xC78, 0xE31D0001, | ||
545 | 0xC78, 0xE21E0001, | ||
546 | 0xC78, 0xE11F0001, | ||
547 | 0xC78, 0x8A200001, | ||
548 | 0xC78, 0x89210001, | ||
549 | 0xC78, 0x88220001, | ||
550 | 0xC78, 0x87230001, | ||
551 | 0xC78, 0x86240001, | ||
552 | 0xC78, 0x85250001, | ||
553 | 0xC78, 0x84260001, | ||
554 | 0xC78, 0x83270001, | ||
555 | 0xC78, 0x82280001, | ||
556 | 0xC78, 0x6B290001, | ||
557 | 0xC78, 0x6A2A0001, | ||
558 | 0xC78, 0x692B0001, | ||
559 | 0xC78, 0x682C0001, | ||
560 | 0xC78, 0x672D0001, | ||
561 | 0xC78, 0x662E0001, | ||
562 | 0xC78, 0x652F0001, | ||
563 | 0xC78, 0x64300001, | ||
564 | 0xC78, 0x63310001, | ||
565 | 0xC78, 0x62320001, | ||
566 | 0xC78, 0x61330001, | ||
567 | 0xC78, 0x46340001, | ||
568 | 0xC78, 0x45350001, | ||
569 | 0xC78, 0x44360001, | ||
570 | 0xC78, 0x43370001, | ||
571 | 0xC78, 0x42380001, | ||
572 | 0xC78, 0x41390001, | ||
573 | 0xC78, 0x403A0001, | ||
574 | 0xC78, 0x403B0001, | ||
575 | 0xC78, 0x403C0001, | ||
576 | 0xC78, 0x403D0001, | ||
577 | 0xC78, 0x403E0001, | ||
578 | 0xC78, 0x403F0001, | ||
579 | 0xC78, 0xFB400001, | ||
580 | 0xC78, 0xFB410001, | ||
581 | 0xC78, 0xFB420001, | ||
582 | 0xC78, 0xFB430001, | ||
583 | 0xC78, 0xFB440001, | ||
584 | 0xC78, 0xFB450001, | ||
585 | 0xC78, 0xFB460001, | ||
586 | 0xC78, 0xFB470001, | ||
587 | 0xC78, 0xFB480001, | ||
588 | 0xC78, 0xFA490001, | ||
589 | 0xC78, 0xF94A0001, | ||
590 | 0xC78, 0xF84B0001, | ||
591 | 0xC78, 0xF74C0001, | ||
592 | 0xC78, 0xF64D0001, | ||
593 | 0xC78, 0xF54E0001, | ||
594 | 0xC78, 0xF44F0001, | ||
595 | 0xC78, 0xF3500001, | ||
596 | 0xC78, 0xF2510001, | ||
597 | 0xC78, 0xF1520001, | ||
598 | 0xC78, 0xF0530001, | ||
599 | 0xC78, 0xEF540001, | ||
600 | 0xC78, 0xEE550001, | ||
601 | 0xC78, 0xED560001, | ||
602 | 0xC78, 0xEC570001, | ||
603 | 0xC78, 0xEB580001, | ||
604 | 0xC78, 0xEA590001, | ||
605 | 0xC78, 0xE95A0001, | ||
606 | 0xC78, 0xE85B0001, | ||
607 | 0xC78, 0xE75C0001, | ||
608 | 0xC78, 0xE65D0001, | ||
609 | 0xC78, 0xE55E0001, | ||
610 | 0xC78, 0xE45F0001, | ||
611 | 0xC78, 0xE3600001, | ||
612 | 0xC78, 0xE2610001, | ||
613 | 0xC78, 0xC3620001, | ||
614 | 0xC78, 0xC2630001, | ||
615 | 0xC78, 0xC1640001, | ||
616 | 0xC78, 0x8B650001, | ||
617 | 0xC78, 0x8A660001, | ||
618 | 0xC78, 0x89670001, | ||
619 | 0xC78, 0x88680001, | ||
620 | 0xC78, 0x87690001, | ||
621 | 0xC78, 0x866A0001, | ||
622 | 0xC78, 0x856B0001, | ||
623 | 0xC78, 0x846C0001, | ||
624 | 0xC78, 0x676D0001, | ||
625 | 0xC78, 0x666E0001, | ||
626 | 0xC78, 0x656F0001, | ||
627 | 0xC78, 0x64700001, | ||
628 | 0xC78, 0x63710001, | ||
629 | 0xC78, 0x62720001, | ||
630 | 0xC78, 0x61730001, | ||
631 | 0xC78, 0x60740001, | ||
632 | 0xC78, 0x46750001, | ||
633 | 0xC78, 0x45760001, | ||
634 | 0xC78, 0x44770001, | ||
635 | 0xC78, 0x43780001, | ||
636 | 0xC78, 0x42790001, | ||
637 | 0xC78, 0x417A0001, | ||
638 | 0xC78, 0x407B0001, | ||
639 | 0xC78, 0x407C0001, | ||
640 | 0xC78, 0x407D0001, | ||
641 | 0xC78, 0x407E0001, | ||
642 | 0xC78, 0x407F0001, | ||
643 | }; | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/table.h b/drivers/net/wireless/rtlwifi/rtl8188ee/table.h new file mode 100644 index 000000000000..c1218e835129 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/table.h | |||
@@ -0,0 +1,47 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Created on 2010/ 5/18, 1:41 | ||
27 | * | ||
28 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
29 | * | ||
30 | *****************************************************************************/ | ||
31 | |||
32 | #ifndef __RTL92CE_TABLE__H_ | ||
33 | #define __RTL92CE_TABLE__H_ | ||
34 | |||
35 | #include <linux/types.h> | ||
36 | #define RTL8188EEPHY_REG_1TARRAYLEN 382 | ||
37 | extern u32 RTL8188EEPHY_REG_1TARRAY[]; | ||
38 | #define RTL8188EEPHY_REG_ARRAY_PGLEN 264 | ||
39 | extern u32 RTL8188EEPHY_REG_ARRAY_PG[]; | ||
40 | #define RTL8188EE_RADIOA_1TARRAYLEN 190 | ||
41 | extern u32 RTL8188EE_RADIOA_1TARRAY[]; | ||
42 | #define RTL8188EEMAC_1T_ARRAYLEN 180 | ||
43 | extern u32 RTL8188EEMAC_1T_ARRAY[]; | ||
44 | #define RTL8188EEAGCTAB_1TARRAYLEN 256 | ||
45 | extern u32 RTL8188EEAGCTAB_1TARRAY[]; | ||
46 | |||
47 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c new file mode 100644 index 000000000000..d075237add51 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c | |||
@@ -0,0 +1,817 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "../wifi.h" | ||
31 | #include "../pci.h" | ||
32 | #include "../base.h" | ||
33 | #include "../stats.h" | ||
34 | #include "reg.h" | ||
35 | #include "def.h" | ||
36 | #include "phy.h" | ||
37 | #include "trx.h" | ||
38 | #include "led.h" | ||
39 | #include "dm.h" | ||
40 | |||
41 | static u8 _rtl88ee_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) | ||
42 | { | ||
43 | __le16 fc = rtl_get_fc(skb); | ||
44 | |||
45 | if (unlikely(ieee80211_is_beacon(fc))) | ||
46 | return QSLT_BEACON; | ||
47 | if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) | ||
48 | return QSLT_MGNT; | ||
49 | |||
50 | return skb->priority; | ||
51 | } | ||
52 | |||
53 | static void _rtl88ee_query_rxphystatus(struct ieee80211_hw *hw, | ||
54 | struct rtl_stats *pstatus, u8 *pdesc, | ||
55 | struct rx_fwinfo_88e *p_drvinfo, | ||
56 | bool bpacket_match_bssid, | ||
57 | bool bpacket_toself, bool packet_beacon) | ||
58 | { | ||
59 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
60 | struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); | ||
61 | struct phy_sts_cck_8192s_t *cck_buf; | ||
62 | struct phy_status_rpt *phystrpt = (struct phy_status_rpt *)p_drvinfo; | ||
63 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
64 | char rx_pwr_all = 0, rx_pwr[4]; | ||
65 | u8 rf_rx_num = 0, evm, pwdb_all; | ||
66 | u8 i, max_spatial_stream; | ||
67 | u32 rssi, total_rssi = 0; | ||
68 | bool is_cck = pstatus->is_cck; | ||
69 | u8 lan_idx, vga_idx; | ||
70 | |||
71 | /* Record it for next packet processing */ | ||
72 | pstatus->packet_matchbssid = bpacket_match_bssid; | ||
73 | pstatus->packet_toself = bpacket_toself; | ||
74 | pstatus->packet_beacon = packet_beacon; | ||
75 | pstatus->rx_mimo_sig_qual[0] = -1; | ||
76 | pstatus->rx_mimo_sig_qual[1] = -1; | ||
77 | |||
78 | if (is_cck) { | ||
79 | u8 cck_hipwr; | ||
80 | u8 cck_agc_rpt; | ||
81 | /* CCK Driver info Structure is not the same as OFDM packet. */ | ||
82 | cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; | ||
83 | cck_agc_rpt = cck_buf->cck_agc_rpt; | ||
84 | |||
85 | /* (1)Hardware does not provide RSSI for CCK | ||
86 | * (2)PWDB, Average PWDB cacluated by | ||
87 | * hardware (for rate adaptive) | ||
88 | */ | ||
89 | if (ppsc->rfpwr_state == ERFON) | ||
90 | cck_hipwr = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, | ||
91 | BIT(9)); | ||
92 | else | ||
93 | cck_hipwr = false; | ||
94 | |||
95 | lan_idx = ((cck_agc_rpt & 0xE0) >> 5); | ||
96 | vga_idx = (cck_agc_rpt & 0x1f); | ||
97 | switch (lan_idx) { | ||
98 | case 7: | ||
99 | if (vga_idx <= 27) | ||
100 | rx_pwr_all = -100 + 2 * (27 - vga_idx); | ||
101 | else | ||
102 | rx_pwr_all = -100; | ||
103 | break; | ||
104 | case 6: | ||
105 | rx_pwr_all = -48 + 2 * (2 - vga_idx); /*VGA_idx = 2~0*/ | ||
106 | break; | ||
107 | case 5: | ||
108 | rx_pwr_all = -42 + 2 * (7 - vga_idx); /*VGA_idx = 7~5*/ | ||
109 | break; | ||
110 | case 4: | ||
111 | rx_pwr_all = -36 + 2 * (7 - vga_idx); /*VGA_idx = 7~4*/ | ||
112 | break; | ||
113 | case 3: | ||
114 | rx_pwr_all = -24 + 2 * (7 - vga_idx); /*VGA_idx = 7~0*/ | ||
115 | break; | ||
116 | case 2: | ||
117 | if (cck_hipwr) | ||
118 | rx_pwr_all = -12 + 2 * (5 - vga_idx); | ||
119 | else | ||
120 | rx_pwr_all = -6 + 2 * (5 - vga_idx); | ||
121 | break; | ||
122 | case 1: | ||
123 | rx_pwr_all = 8 - 2 * vga_idx; | ||
124 | break; | ||
125 | case 0: | ||
126 | rx_pwr_all = 14 - 2 * vga_idx; | ||
127 | break; | ||
128 | default: | ||
129 | break; | ||
130 | } | ||
131 | rx_pwr_all += 6; | ||
132 | pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); | ||
133 | /* CCK gain is smaller than OFDM/MCS gain, | ||
134 | * so we add gain diff by experiences, | ||
135 | * the val is 6 | ||
136 | */ | ||
137 | pwdb_all += 6; | ||
138 | if (pwdb_all > 100) | ||
139 | pwdb_all = 100; | ||
140 | /* modify the offset to make the same | ||
141 | * gain index with OFDM. | ||
142 | */ | ||
143 | if (pwdb_all > 34 && pwdb_all <= 42) | ||
144 | pwdb_all -= 2; | ||
145 | else if (pwdb_all > 26 && pwdb_all <= 34) | ||
146 | pwdb_all -= 6; | ||
147 | else if (pwdb_all > 14 && pwdb_all <= 26) | ||
148 | pwdb_all -= 8; | ||
149 | else if (pwdb_all > 4 && pwdb_all <= 14) | ||
150 | pwdb_all -= 4; | ||
151 | if (cck_hipwr == false) { | ||
152 | if (pwdb_all >= 80) | ||
153 | pwdb_all = ((pwdb_all - 80)<<1) + | ||
154 | ((pwdb_all - 80)>>1) + 80; | ||
155 | else if ((pwdb_all <= 78) && (pwdb_all >= 20)) | ||
156 | pwdb_all += 3; | ||
157 | if (pwdb_all > 100) | ||
158 | pwdb_all = 100; | ||
159 | } | ||
160 | |||
161 | pstatus->rx_pwdb_all = pwdb_all; | ||
162 | pstatus->recvsignalpower = rx_pwr_all; | ||
163 | |||
164 | /* (3) Get Signal Quality (EVM) */ | ||
165 | if (bpacket_match_bssid) { | ||
166 | u8 sq; | ||
167 | |||
168 | if (pstatus->rx_pwdb_all > 40) { | ||
169 | sq = 100; | ||
170 | } else { | ||
171 | sq = cck_buf->sq_rpt; | ||
172 | if (sq > 64) | ||
173 | sq = 0; | ||
174 | else if (sq < 20) | ||
175 | sq = 100; | ||
176 | else | ||
177 | sq = ((64 - sq) * 100) / 44; | ||
178 | } | ||
179 | |||
180 | pstatus->signalquality = sq; | ||
181 | pstatus->rx_mimo_sig_qual[0] = sq; | ||
182 | pstatus->rx_mimo_sig_qual[1] = -1; | ||
183 | } | ||
184 | } else { | ||
185 | rtlpriv->dm.rfpath_rxenable[0] = | ||
186 | rtlpriv->dm.rfpath_rxenable[1] = true; | ||
187 | |||
188 | /* (1)Get RSSI for HT rate */ | ||
189 | for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) { | ||
190 | /* we will judge RF RX path now. */ | ||
191 | if (rtlpriv->dm.rfpath_rxenable[i]) | ||
192 | rf_rx_num++; | ||
193 | |||
194 | rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & 0x3f) * 2)-110; | ||
195 | |||
196 | /* Translate DBM to percentage. */ | ||
197 | rssi = rtl_query_rxpwrpercentage(rx_pwr[i]); | ||
198 | total_rssi += rssi; | ||
199 | |||
200 | /* Get Rx snr value in DB */ | ||
201 | rtlpriv->stats.rx_snr_db[i] = p_drvinfo->rxsnr[i] / 2; | ||
202 | |||
203 | /* Record Signal Strength for next packet */ | ||
204 | if (bpacket_match_bssid) | ||
205 | pstatus->rx_mimo_signalstrength[i] = (u8) rssi; | ||
206 | } | ||
207 | |||
208 | /* (2)PWDB, Average PWDB cacluated by | ||
209 | * hardware (for rate adaptive) | ||
210 | */ | ||
211 | rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; | ||
212 | |||
213 | pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); | ||
214 | pstatus->rx_pwdb_all = pwdb_all; | ||
215 | pstatus->rxpower = rx_pwr_all; | ||
216 | pstatus->recvsignalpower = rx_pwr_all; | ||
217 | |||
218 | /* (3)EVM of HT rate */ | ||
219 | if (pstatus->is_ht && pstatus->rate >= DESC92C_RATEMCS8 && | ||
220 | pstatus->rate <= DESC92C_RATEMCS15) | ||
221 | max_spatial_stream = 2; | ||
222 | else | ||
223 | max_spatial_stream = 1; | ||
224 | |||
225 | for (i = 0; i < max_spatial_stream; i++) { | ||
226 | evm = rtl_evm_db_to_percentage(p_drvinfo->rxevm[i]); | ||
227 | |||
228 | if (bpacket_match_bssid) { | ||
229 | /* Fill value in RFD, Get the first | ||
230 | * spatial stream only | ||
231 | */ | ||
232 | if (i == 0) | ||
233 | pstatus->signalquality = evm & 0xff; | ||
234 | pstatus->rx_mimo_sig_qual[i] = evm & 0xff; | ||
235 | } | ||
236 | } | ||
237 | } | ||
238 | |||
239 | /* UI BSS List signal strength(in percentage), | ||
240 | * make it good looking, from 0~100. | ||
241 | */ | ||
242 | if (is_cck) | ||
243 | pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw, | ||
244 | pwdb_all)); | ||
245 | else if (rf_rx_num != 0) | ||
246 | pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw, | ||
247 | total_rssi /= rf_rx_num)); | ||
248 | /*HW antenna diversity*/ | ||
249 | rtldm->fat_table.antsel_rx_keep_0 = phystrpt->ant_sel; | ||
250 | rtldm->fat_table.antsel_rx_keep_1 = phystrpt->ant_sel_b; | ||
251 | rtldm->fat_table.antsel_rx_keep_2 = phystrpt->antsel_rx_keep_2; | ||
252 | } | ||
253 | |||
254 | static void _rtl88ee_smart_antenna(struct ieee80211_hw *hw, | ||
255 | struct rtl_stats *pstatus) | ||
256 | { | ||
257 | struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); | ||
258 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
259 | u8 ant_mux; | ||
260 | struct fast_ant_training *pfat = &(rtldm->fat_table); | ||
261 | |||
262 | if (rtlefuse->antenna_div_type == CG_TRX_SMART_ANTDIV) { | ||
263 | if (pfat->fat_state == FAT_TRAINING_STATE) { | ||
264 | if (pstatus->packet_toself) { | ||
265 | ant_mux = (pfat->antsel_rx_keep_2 << 2) | | ||
266 | (pfat->antsel_rx_keep_1 << 1) | | ||
267 | pfat->antsel_rx_keep_0; | ||
268 | pfat->ant_sum[ant_mux] += pstatus->rx_pwdb_all; | ||
269 | pfat->ant_cnt[ant_mux]++; | ||
270 | } | ||
271 | } | ||
272 | } else if ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) || | ||
273 | (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV)) { | ||
274 | if (pstatus->packet_toself || pstatus->packet_matchbssid) { | ||
275 | ant_mux = (pfat->antsel_rx_keep_2 << 2) | | ||
276 | (pfat->antsel_rx_keep_1 << 1) | | ||
277 | pfat->antsel_rx_keep_0; | ||
278 | rtl88e_dm_ant_sel_statistics(hw, ant_mux, 0, | ||
279 | pstatus->rx_pwdb_all); | ||
280 | } | ||
281 | } | ||
282 | } | ||
283 | |||
284 | static void _rtl88ee_translate_rx_signal_stuff(struct ieee80211_hw *hw, | ||
285 | struct sk_buff *skb, struct rtl_stats *pstatus, | ||
286 | u8 *pdesc, struct rx_fwinfo_88e *p_drvinfo) | ||
287 | { | ||
288 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
289 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
290 | struct ieee80211_hdr *hdr; | ||
291 | u8 *tmp_buf; | ||
292 | u8 *praddr; | ||
293 | u8 *psaddr; | ||
294 | __le16 fc; | ||
295 | u16 type, ufc; | ||
296 | bool match_bssid, packet_toself, packet_beacon, addr; | ||
297 | |||
298 | tmp_buf = skb->data + pstatus->rx_drvinfo_size + pstatus->rx_bufshift; | ||
299 | |||
300 | hdr = (struct ieee80211_hdr *)tmp_buf; | ||
301 | fc = hdr->frame_control; | ||
302 | ufc = le16_to_cpu(fc); | ||
303 | type = WLAN_FC_GET_TYPE(fc); | ||
304 | praddr = hdr->addr1; | ||
305 | psaddr = ieee80211_get_SA(hdr); | ||
306 | memcpy(pstatus->psaddr, psaddr, ETH_ALEN); | ||
307 | |||
308 | addr = (!compare_ether_addr(mac->bssid, (ufc & IEEE80211_FCTL_TODS) ? | ||
309 | hdr->addr1 : (ufc & IEEE80211_FCTL_FROMDS) ? | ||
310 | hdr->addr2 : hdr->addr3)); | ||
311 | match_bssid = ((IEEE80211_FTYPE_CTL != type) && (!pstatus->hwerror) && | ||
312 | (!pstatus->crc) && (!pstatus->icv)) && addr; | ||
313 | |||
314 | addr = (!compare_ether_addr(praddr, rtlefuse->dev_addr)); | ||
315 | packet_toself = match_bssid && addr; | ||
316 | |||
317 | if (ieee80211_is_beacon(fc)) | ||
318 | packet_beacon = true; | ||
319 | |||
320 | _rtl88ee_query_rxphystatus(hw, pstatus, pdesc, p_drvinfo, | ||
321 | match_bssid, packet_toself, packet_beacon); | ||
322 | _rtl88ee_smart_antenna(hw, pstatus); | ||
323 | rtl_process_phyinfo(hw, tmp_buf, pstatus); | ||
324 | } | ||
325 | |||
326 | static void insert_em(struct rtl_tcb_desc *ptcb_desc, u8 *virtualaddress) | ||
327 | { | ||
328 | u32 dwtmp = 0; | ||
329 | |||
330 | memset(virtualaddress, 0, 8); | ||
331 | |||
332 | SET_EARLYMODE_PKTNUM(virtualaddress, ptcb_desc->empkt_num); | ||
333 | if (ptcb_desc->empkt_num == 1) { | ||
334 | dwtmp = ptcb_desc->empkt_len[0]; | ||
335 | } else { | ||
336 | dwtmp = ptcb_desc->empkt_len[0]; | ||
337 | dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; | ||
338 | dwtmp += ptcb_desc->empkt_len[1]; | ||
339 | } | ||
340 | SET_EARLYMODE_LEN0(virtualaddress, dwtmp); | ||
341 | |||
342 | if (ptcb_desc->empkt_num <= 3) { | ||
343 | dwtmp = ptcb_desc->empkt_len[2]; | ||
344 | } else { | ||
345 | dwtmp = ptcb_desc->empkt_len[2]; | ||
346 | dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; | ||
347 | dwtmp += ptcb_desc->empkt_len[3]; | ||
348 | } | ||
349 | SET_EARLYMODE_LEN1(virtualaddress, dwtmp); | ||
350 | if (ptcb_desc->empkt_num <= 5) { | ||
351 | dwtmp = ptcb_desc->empkt_len[4]; | ||
352 | } else { | ||
353 | dwtmp = ptcb_desc->empkt_len[4]; | ||
354 | dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; | ||
355 | dwtmp += ptcb_desc->empkt_len[5]; | ||
356 | } | ||
357 | SET_EARLYMODE_LEN2_1(virtualaddress, dwtmp & 0xF); | ||
358 | SET_EARLYMODE_LEN2_2(virtualaddress, dwtmp >> 4); | ||
359 | if (ptcb_desc->empkt_num <= 7) { | ||
360 | dwtmp = ptcb_desc->empkt_len[6]; | ||
361 | } else { | ||
362 | dwtmp = ptcb_desc->empkt_len[6]; | ||
363 | dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; | ||
364 | dwtmp += ptcb_desc->empkt_len[7]; | ||
365 | } | ||
366 | SET_EARLYMODE_LEN3(virtualaddress, dwtmp); | ||
367 | if (ptcb_desc->empkt_num <= 9) { | ||
368 | dwtmp = ptcb_desc->empkt_len[8]; | ||
369 | } else { | ||
370 | dwtmp = ptcb_desc->empkt_len[8]; | ||
371 | dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; | ||
372 | dwtmp += ptcb_desc->empkt_len[9]; | ||
373 | } | ||
374 | SET_EARLYMODE_LEN4(virtualaddress, dwtmp); | ||
375 | } | ||
376 | |||
377 | bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw, | ||
378 | struct rtl_stats *status, | ||
379 | struct ieee80211_rx_status *rx_status, | ||
380 | u8 *pdesc, struct sk_buff *skb) | ||
381 | { | ||
382 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
383 | struct rx_fwinfo_88e *p_drvinfo; | ||
384 | struct ieee80211_hdr *hdr; | ||
385 | |||
386 | u32 phystatus = GET_RX_DESC_PHYST(pdesc); | ||
387 | status->packet_report_type = (u8)GET_RX_STATUS_DESC_RPT_SEL(pdesc); | ||
388 | if (status->packet_report_type == TX_REPORT2) | ||
389 | status->length = (u16) GET_RX_RPT2_DESC_PKT_LEN(pdesc); | ||
390 | else | ||
391 | status->length = (u16) GET_RX_DESC_PKT_LEN(pdesc); | ||
392 | status->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) * | ||
393 | RX_DRV_INFO_SIZE_UNIT; | ||
394 | status->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03); | ||
395 | status->icv = (u16) GET_RX_DESC_ICV(pdesc); | ||
396 | status->crc = (u16) GET_RX_DESC_CRC32(pdesc); | ||
397 | status->hwerror = (status->crc | status->icv); | ||
398 | status->decrypted = !GET_RX_DESC_SWDEC(pdesc); | ||
399 | status->rate = (u8) GET_RX_DESC_RXMCS(pdesc); | ||
400 | status->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc); | ||
401 | status->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1); | ||
402 | status->isfirst_ampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1) && | ||
403 | (GET_RX_DESC_FAGGR(pdesc) == 1)); | ||
404 | if (status->packet_report_type == NORMAL_RX) | ||
405 | status->timestamp_low = GET_RX_DESC_TSFL(pdesc); | ||
406 | status->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); | ||
407 | status->is_ht = (bool)GET_RX_DESC_RXHT(pdesc); | ||
408 | |||
409 | status->is_cck = RTL8188_RX_HAL_IS_CCK_RATE(status->rate); | ||
410 | |||
411 | status->macid = GET_RX_DESC_MACID(pdesc); | ||
412 | if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) | ||
413 | status->wake_match = BIT(2); | ||
414 | else if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) | ||
415 | status->wake_match = BIT(1); | ||
416 | else if (GET_RX_STATUS_DESC_UNICAST_MATCH(pdesc)) | ||
417 | status->wake_match = BIT(0); | ||
418 | else | ||
419 | status->wake_match = 0; | ||
420 | if (status->wake_match) | ||
421 | RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD, | ||
422 | "Get Wakeup Packet!! WakeMatch =%d\n", | ||
423 | status->wake_match); | ||
424 | rx_status->freq = hw->conf.channel->center_freq; | ||
425 | rx_status->band = hw->conf.channel->band; | ||
426 | |||
427 | if (status->crc) | ||
428 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; | ||
429 | |||
430 | if (status->rx_is40Mhzpacket) | ||
431 | rx_status->flag |= RX_FLAG_40MHZ; | ||
432 | |||
433 | if (status->is_ht) | ||
434 | rx_status->flag |= RX_FLAG_HT; | ||
435 | |||
436 | rx_status->flag |= RX_FLAG_MACTIME_START; | ||
437 | |||
438 | /* hw will set status->decrypted true, if it finds the | ||
439 | * frame is open data frame or mgmt frame. | ||
440 | * So hw will not decryption robust managment frame | ||
441 | * for IEEE80211w but still set status->decrypted | ||
442 | * true, so here we should set it back to undecrypted | ||
443 | * for IEEE80211w frame, and mac80211 sw will help | ||
444 | * to decrypt it | ||
445 | */ | ||
446 | if (status->decrypted) { | ||
447 | hdr = (struct ieee80211_hdr *)(skb->data + | ||
448 | status->rx_drvinfo_size + status->rx_bufshift); | ||
449 | |||
450 | if (!hdr) { | ||
451 | /* During testing, hdr was NULL */ | ||
452 | return false; | ||
453 | } | ||
454 | if ((ieee80211_is_robust_mgmt_frame(hdr)) && | ||
455 | (ieee80211_has_protected(hdr->frame_control))) | ||
456 | rx_status->flag &= ~RX_FLAG_DECRYPTED; | ||
457 | else | ||
458 | rx_status->flag |= RX_FLAG_DECRYPTED; | ||
459 | } | ||
460 | |||
461 | /* rate_idx: index of data rate into band's | ||
462 | * supported rates or MCS index if HT rates | ||
463 | * are use (RX_FLAG_HT) | ||
464 | * Notice: this is diff with windows define | ||
465 | */ | ||
466 | rx_status->rate_idx = rtlwifi_rate_mapping(hw, status->is_ht, | ||
467 | status->rate, false); | ||
468 | |||
469 | rx_status->mactime = status->timestamp_low; | ||
470 | if (phystatus == true) { | ||
471 | p_drvinfo = (struct rx_fwinfo_88e *)(skb->data + | ||
472 | status->rx_bufshift); | ||
473 | |||
474 | _rtl88ee_translate_rx_signal_stuff(hw, skb, status, pdesc, | ||
475 | p_drvinfo); | ||
476 | } | ||
477 | |||
478 | /*rx_status->qual = status->signal; */ | ||
479 | rx_status->signal = status->recvsignalpower + 10; | ||
480 | /*rx_status->noise = -status->noise; */ | ||
481 | if (status->packet_report_type == TX_REPORT2) { | ||
482 | status->macid_valid_entry[0] = | ||
483 | GET_RX_RPT2_DESC_MACID_VALID_1(pdesc); | ||
484 | status->macid_valid_entry[1] = | ||
485 | GET_RX_RPT2_DESC_MACID_VALID_2(pdesc); | ||
486 | } | ||
487 | return true; | ||
488 | } | ||
489 | |||
490 | void rtl88ee_tx_fill_desc(struct ieee80211_hw *hw, | ||
491 | struct ieee80211_hdr *hdr, u8 *pdesc_tx, | ||
492 | struct ieee80211_tx_info *info, | ||
493 | struct ieee80211_sta *sta, | ||
494 | struct sk_buff *skb, | ||
495 | u8 hw_queue, struct rtl_tcb_desc *ptcb_desc) | ||
496 | { | ||
497 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
498 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
499 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
500 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); | ||
501 | u8 *pdesc = (u8 *)pdesc_tx; | ||
502 | u16 seq_number; | ||
503 | __le16 fc = hdr->frame_control; | ||
504 | unsigned int buf_len = 0; | ||
505 | unsigned int skb_len = skb->len; | ||
506 | u8 fw_qsel = _rtl88ee_map_hwqueue_to_fwqueue(skb, hw_queue); | ||
507 | bool firstseg = ((hdr->seq_ctrl & | ||
508 | cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); | ||
509 | bool lastseg = ((hdr->frame_control & | ||
510 | cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0); | ||
511 | dma_addr_t mapping; | ||
512 | u8 bw_40 = 0; | ||
513 | u8 short_gi = 0; | ||
514 | |||
515 | if (mac->opmode == NL80211_IFTYPE_STATION) { | ||
516 | bw_40 = mac->bw_40; | ||
517 | } else if (mac->opmode == NL80211_IFTYPE_AP || | ||
518 | mac->opmode == NL80211_IFTYPE_ADHOC) { | ||
519 | if (sta) | ||
520 | bw_40 = sta->ht_cap.cap & | ||
521 | IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
522 | } | ||
523 | seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; | ||
524 | rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc); | ||
525 | /* reserve 8 byte for AMPDU early mode */ | ||
526 | if (rtlhal->earlymode_enable) { | ||
527 | skb_push(skb, EM_HDR_LEN); | ||
528 | memset(skb->data, 0, EM_HDR_LEN); | ||
529 | } | ||
530 | buf_len = skb->len; | ||
531 | mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, | ||
532 | PCI_DMA_TODEVICE); | ||
533 | if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { | ||
534 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, | ||
535 | "DMA mapping error"); | ||
536 | return; | ||
537 | } | ||
538 | CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_88e)); | ||
539 | if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { | ||
540 | firstseg = true; | ||
541 | lastseg = true; | ||
542 | } | ||
543 | if (firstseg) { | ||
544 | if (rtlhal->earlymode_enable) { | ||
545 | SET_TX_DESC_PKT_OFFSET(pdesc, 1); | ||
546 | SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN + | ||
547 | EM_HDR_LEN); | ||
548 | if (ptcb_desc->empkt_num) { | ||
549 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, | ||
550 | "Insert 8 byte.pTcb->EMPktNum:%d\n", | ||
551 | ptcb_desc->empkt_num); | ||
552 | insert_em(ptcb_desc, (u8 *)(skb->data)); | ||
553 | } | ||
554 | } else { | ||
555 | SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); | ||
556 | } | ||
557 | |||
558 | ptcb_desc->use_driver_rate = true; | ||
559 | SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate); | ||
560 | if (ptcb_desc->hw_rate > DESC92C_RATEMCS0) | ||
561 | short_gi = (ptcb_desc->use_shortgi) ? 1 : 0; | ||
562 | else | ||
563 | short_gi = (ptcb_desc->use_shortpreamble) ? 1 : 0; | ||
564 | SET_TX_DESC_DATA_SHORTGI(pdesc, short_gi); | ||
565 | |||
566 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { | ||
567 | SET_TX_DESC_AGG_ENABLE(pdesc, 1); | ||
568 | SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14); | ||
569 | } | ||
570 | SET_TX_DESC_SEQ(pdesc, seq_number); | ||
571 | SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable && | ||
572 | !ptcb_desc->cts_enable) ? 1 : 0)); | ||
573 | SET_TX_DESC_HW_RTS_ENABLE(pdesc, 0); | ||
574 | SET_TX_DESC_CTS2SELF(pdesc, ((ptcb_desc->cts_enable) ? 1 : 0)); | ||
575 | SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0)); | ||
576 | |||
577 | SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate); | ||
578 | SET_TX_DESC_RTS_BW(pdesc, 0); | ||
579 | SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc); | ||
580 | SET_TX_DESC_RTS_SHORT(pdesc, | ||
581 | ((ptcb_desc->rts_rate <= DESC92C_RATE54M) ? | ||
582 | (ptcb_desc->rts_use_shortpreamble ? 1 : 0) : | ||
583 | (ptcb_desc->rts_use_shortgi ? 1 : 0))); | ||
584 | |||
585 | if (ptcb_desc->btx_enable_sw_calc_duration) | ||
586 | SET_TX_DESC_NAV_USE_HDR(pdesc, 1); | ||
587 | |||
588 | if (bw_40) { | ||
589 | if (ptcb_desc->packet_bw) { | ||
590 | SET_TX_DESC_DATA_BW(pdesc, 1); | ||
591 | SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3); | ||
592 | } else { | ||
593 | SET_TX_DESC_DATA_BW(pdesc, 0); | ||
594 | SET_TX_DESC_TX_SUB_CARRIER(pdesc, | ||
595 | mac->cur_40_prime_sc); | ||
596 | } | ||
597 | } else { | ||
598 | SET_TX_DESC_DATA_BW(pdesc, 0); | ||
599 | SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); | ||
600 | } | ||
601 | |||
602 | SET_TX_DESC_LINIP(pdesc, 0); | ||
603 | SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb_len); | ||
604 | if (sta) { | ||
605 | u8 ampdu_density = sta->ht_cap.ampdu_density; | ||
606 | SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); | ||
607 | } | ||
608 | if (info->control.hw_key) { | ||
609 | struct ieee80211_key_conf *keyconf; | ||
610 | keyconf = info->control.hw_key; | ||
611 | switch (keyconf->cipher) { | ||
612 | case WLAN_CIPHER_SUITE_WEP40: | ||
613 | case WLAN_CIPHER_SUITE_WEP104: | ||
614 | case WLAN_CIPHER_SUITE_TKIP: | ||
615 | SET_TX_DESC_SEC_TYPE(pdesc, 0x1); | ||
616 | break; | ||
617 | case WLAN_CIPHER_SUITE_CCMP: | ||
618 | SET_TX_DESC_SEC_TYPE(pdesc, 0x3); | ||
619 | break; | ||
620 | default: | ||
621 | SET_TX_DESC_SEC_TYPE(pdesc, 0x0); | ||
622 | break; | ||
623 | } | ||
624 | } | ||
625 | |||
626 | SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); | ||
627 | SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); | ||
628 | SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); | ||
629 | SET_TX_DESC_DISABLE_FB(pdesc, ptcb_desc->disable_ratefallback ? | ||
630 | 1 : 0); | ||
631 | SET_TX_DESC_USE_RATE(pdesc, ptcb_desc->use_driver_rate ? 1 : 0); | ||
632 | |||
633 | /* Set TxRate and RTSRate in TxDesc */ | ||
634 | /* This prevent Tx initial rate of new-coming packets */ | ||
635 | /* from being overwritten by retried packet rate.*/ | ||
636 | if (!ptcb_desc->use_driver_rate) { | ||
637 | /*SET_TX_DESC_RTS_RATE(pdesc, 0x08); */ | ||
638 | /* SET_TX_DESC_TX_RATE(pdesc, 0x0b); */ | ||
639 | } | ||
640 | if (ieee80211_is_data_qos(fc)) { | ||
641 | if (mac->rdg_en) { | ||
642 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, | ||
643 | "Enable RDG function.\n"); | ||
644 | SET_TX_DESC_RDG_ENABLE(pdesc, 1); | ||
645 | SET_TX_DESC_HTC(pdesc, 1); | ||
646 | } | ||
647 | } | ||
648 | } | ||
649 | |||
650 | SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); | ||
651 | SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); | ||
652 | SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) buf_len); | ||
653 | SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); | ||
654 | if (rtlpriv->dm.useramask) { | ||
655 | SET_TX_DESC_RATE_ID(pdesc, ptcb_desc->ratr_index); | ||
656 | SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); | ||
657 | } else { | ||
658 | SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcb_desc->ratr_index); | ||
659 | SET_TX_DESC_MACID(pdesc, ptcb_desc->ratr_index); | ||
660 | } | ||
661 | if (ieee80211_is_data_qos(fc)) | ||
662 | SET_TX_DESC_QOS(pdesc, 1); | ||
663 | |||
664 | if (!ieee80211_is_data_qos(fc)) | ||
665 | SET_TX_DESC_HWSEQ_EN(pdesc, 1); | ||
666 | SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1)); | ||
667 | if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || | ||
668 | is_broadcast_ether_addr(ieee80211_get_DA(hdr))) | ||
669 | SET_TX_DESC_BMC(pdesc, 1); | ||
670 | |||
671 | rtl88e_dm_set_tx_ant_by_tx_info(hw, pdesc, ptcb_desc->mac_id); | ||
672 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); | ||
673 | } | ||
674 | |||
675 | void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw, | ||
676 | u8 *pdesc, bool firstseg, | ||
677 | bool lastseg, struct sk_buff *skb) | ||
678 | { | ||
679 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
680 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
681 | u8 fw_queue = QSLT_BEACON; | ||
682 | |||
683 | dma_addr_t mapping = pci_map_single(rtlpci->pdev, | ||
684 | skb->data, skb->len, | ||
685 | PCI_DMA_TODEVICE); | ||
686 | |||
687 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); | ||
688 | __le16 fc = hdr->frame_control; | ||
689 | |||
690 | if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { | ||
691 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, | ||
692 | "DMA mapping error"); | ||
693 | return; | ||
694 | } | ||
695 | CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); | ||
696 | |||
697 | if (firstseg) | ||
698 | SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); | ||
699 | |||
700 | SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M); | ||
701 | |||
702 | SET_TX_DESC_SEQ(pdesc, 0); | ||
703 | |||
704 | SET_TX_DESC_LINIP(pdesc, 0); | ||
705 | |||
706 | SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); | ||
707 | |||
708 | SET_TX_DESC_FIRST_SEG(pdesc, 1); | ||
709 | SET_TX_DESC_LAST_SEG(pdesc, 1); | ||
710 | |||
711 | SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len)); | ||
712 | |||
713 | SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); | ||
714 | |||
715 | SET_TX_DESC_RATE_ID(pdesc, 7); | ||
716 | SET_TX_DESC_MACID(pdesc, 0); | ||
717 | |||
718 | SET_TX_DESC_OWN(pdesc, 1); | ||
719 | |||
720 | SET_TX_DESC_PKT_SIZE((u8 *)pdesc, (u16)(skb->len)); | ||
721 | |||
722 | SET_TX_DESC_FIRST_SEG(pdesc, 1); | ||
723 | SET_TX_DESC_LAST_SEG(pdesc, 1); | ||
724 | |||
725 | SET_TX_DESC_OFFSET(pdesc, 0x20); | ||
726 | |||
727 | SET_TX_DESC_USE_RATE(pdesc, 1); | ||
728 | |||
729 | if (!ieee80211_is_data_qos(fc)) | ||
730 | SET_TX_DESC_HWSEQ_EN(pdesc, 1); | ||
731 | |||
732 | RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, | ||
733 | "H2C Tx Cmd Content\n", | ||
734 | pdesc, TX_DESC_SIZE); | ||
735 | } | ||
736 | |||
737 | void rtl88ee_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val) | ||
738 | { | ||
739 | if (istx == true) { | ||
740 | switch (desc_name) { | ||
741 | case HW_DESC_OWN: | ||
742 | SET_TX_DESC_OWN(pdesc, 1); | ||
743 | break; | ||
744 | case HW_DESC_TX_NEXTDESC_ADDR: | ||
745 | SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *)val); | ||
746 | break; | ||
747 | default: | ||
748 | RT_ASSERT(false, "ERR txdesc :%d not processed\n", | ||
749 | desc_name); | ||
750 | break; | ||
751 | } | ||
752 | } else { | ||
753 | switch (desc_name) { | ||
754 | case HW_DESC_RXOWN: | ||
755 | SET_RX_DESC_OWN(pdesc, 1); | ||
756 | break; | ||
757 | case HW_DESC_RXBUFF_ADDR: | ||
758 | SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *)val); | ||
759 | break; | ||
760 | case HW_DESC_RXPKT_LEN: | ||
761 | SET_RX_DESC_PKT_LEN(pdesc, *(u32 *)val); | ||
762 | break; | ||
763 | case HW_DESC_RXERO: | ||
764 | SET_RX_DESC_EOR(pdesc, 1); | ||
765 | break; | ||
766 | default: | ||
767 | RT_ASSERT(false, "ERR rxdesc :%d not processed\n", | ||
768 | desc_name); | ||
769 | break; | ||
770 | } | ||
771 | } | ||
772 | } | ||
773 | |||
774 | u32 rtl88ee_get_desc(u8 *pdesc, bool istx, u8 desc_name) | ||
775 | { | ||
776 | u32 ret = 0; | ||
777 | |||
778 | if (istx == true) { | ||
779 | switch (desc_name) { | ||
780 | case HW_DESC_OWN: | ||
781 | ret = GET_TX_DESC_OWN(pdesc); | ||
782 | break; | ||
783 | case HW_DESC_TXBUFF_ADDR: | ||
784 | ret = GET_TX_DESC_TX_BUFFER_ADDRESS(pdesc); | ||
785 | break; | ||
786 | default: | ||
787 | RT_ASSERT(false, "ERR txdesc :%d not processed\n", | ||
788 | desc_name); | ||
789 | break; | ||
790 | } | ||
791 | } else { | ||
792 | switch (desc_name) { | ||
793 | case HW_DESC_OWN: | ||
794 | ret = GET_RX_DESC_OWN(pdesc); | ||
795 | break; | ||
796 | case HW_DESC_RXPKT_LEN: | ||
797 | ret = GET_RX_DESC_PKT_LEN(pdesc); | ||
798 | break; | ||
799 | default: | ||
800 | RT_ASSERT(false, "ERR rxdesc :%d not processed\n", | ||
801 | desc_name); | ||
802 | break; | ||
803 | } | ||
804 | } | ||
805 | return ret; | ||
806 | } | ||
807 | |||
808 | void rtl88ee_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) | ||
809 | { | ||
810 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
811 | if (hw_queue == BEACON_QUEUE) { | ||
812 | rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4)); | ||
813 | } else { | ||
814 | rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, | ||
815 | BIT(0) << (hw_queue)); | ||
816 | } | ||
817 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h new file mode 100644 index 000000000000..d3a02e73f53a --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h | |||
@@ -0,0 +1,795 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2013 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #ifndef __RTL92CE_TRX_H__ | ||
31 | #define __RTL92CE_TRX_H__ | ||
32 | |||
33 | #define TX_DESC_SIZE 64 | ||
34 | #define TX_DESC_AGGR_SUBFRAME_SIZE 32 | ||
35 | |||
36 | #define RX_DESC_SIZE 32 | ||
37 | #define RX_DRV_INFO_SIZE_UNIT 8 | ||
38 | |||
39 | #define TX_DESC_NEXT_DESC_OFFSET 40 | ||
40 | #define USB_HWDESC_HEADER_LEN 32 | ||
41 | #define CRCLENGTH 4 | ||
42 | |||
43 | #define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ | ||
44 | SET_BITS_TO_LE_4BYTE(__pdesc, 0, 16, __val) | ||
45 | #define SET_TX_DESC_OFFSET(__pdesc, __val) \ | ||
46 | SET_BITS_TO_LE_4BYTE(__pdesc, 16, 8, __val) | ||
47 | #define SET_TX_DESC_BMC(__pdesc, __val) \ | ||
48 | SET_BITS_TO_LE_4BYTE(__pdesc, 24, 1, __val) | ||
49 | #define SET_TX_DESC_HTC(__pdesc, __val) \ | ||
50 | SET_BITS_TO_LE_4BYTE(__pdesc, 25, 1, __val) | ||
51 | #define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ | ||
52 | SET_BITS_TO_LE_4BYTE(__pdesc, 26, 1, __val) | ||
53 | #define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ | ||
54 | SET_BITS_TO_LE_4BYTE(__pdesc, 27, 1, __val) | ||
55 | #define SET_TX_DESC_LINIP(__pdesc, __val) \ | ||
56 | SET_BITS_TO_LE_4BYTE(__pdesc, 28, 1, __val) | ||
57 | #define SET_TX_DESC_NO_ACM(__pdesc, __val) \ | ||
58 | SET_BITS_TO_LE_4BYTE(__pdesc, 29, 1, __val) | ||
59 | #define SET_TX_DESC_GF(__pdesc, __val) \ | ||
60 | SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) | ||
61 | #define SET_TX_DESC_OWN(__pdesc, __val) \ | ||
62 | SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) | ||
63 | |||
64 | #define GET_TX_DESC_PKT_SIZE(__pdesc) \ | ||
65 | LE_BITS_TO_4BYTE(__pdesc, 0, 16) | ||
66 | #define GET_TX_DESC_OFFSET(__pdesc) \ | ||
67 | LE_BITS_TO_4BYTE(__pdesc, 16, 8) | ||
68 | #define GET_TX_DESC_BMC(__pdesc) \ | ||
69 | LE_BITS_TO_4BYTE(__pdesc, 24, 1) | ||
70 | #define GET_TX_DESC_HTC(__pdesc) \ | ||
71 | LE_BITS_TO_4BYTE(__pdesc, 25, 1) | ||
72 | #define GET_TX_DESC_LAST_SEG(__pdesc) \ | ||
73 | LE_BITS_TO_4BYTE(__pdesc, 26, 1) | ||
74 | #define GET_TX_DESC_FIRST_SEG(__pdesc) \ | ||
75 | LE_BITS_TO_4BYTE(__pdesc, 27, 1) | ||
76 | #define GET_TX_DESC_LINIP(__pdesc) \ | ||
77 | LE_BITS_TO_4BYTE(__pdesc, 28, 1) | ||
78 | #define GET_TX_DESC_NO_ACM(__pdesc) \ | ||
79 | LE_BITS_TO_4BYTE(__pdesc, 29, 1) | ||
80 | #define GET_TX_DESC_GF(__pdesc) \ | ||
81 | LE_BITS_TO_4BYTE(__pdesc, 30, 1) | ||
82 | #define GET_TX_DESC_OWN(__pdesc) \ | ||
83 | LE_BITS_TO_4BYTE(__pdesc, 31, 1) | ||
84 | |||
85 | #define SET_TX_DESC_MACID(__pdesc, __val) \ | ||
86 | SET_BITS_TO_LE_4BYTE(__pdesc+4, 0, 6, __val) | ||
87 | #define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ | ||
88 | SET_BITS_TO_LE_4BYTE(__pdesc+4, 8, 5, __val) | ||
89 | #define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val) \ | ||
90 | SET_BITS_TO_LE_4BYTE(__pdesc+4, 13, 1, __val) | ||
91 | #define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val) \ | ||
92 | SET_BITS_TO_LE_4BYTE(__pdesc+4, 14, 1, __val) | ||
93 | #define SET_TX_DESC_PIFS(__pdesc, __val) \ | ||
94 | SET_BITS_TO_LE_4BYTE(__pdesc+4, 15, 1, __val) | ||
95 | #define SET_TX_DESC_RATE_ID(__pdesc, __val) \ | ||
96 | SET_BITS_TO_LE_4BYTE(__pdesc+4, 16, 4, __val) | ||
97 | #define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \ | ||
98 | SET_BITS_TO_LE_4BYTE(__pdesc+4, 20, 1, __val) | ||
99 | #define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \ | ||
100 | SET_BITS_TO_LE_4BYTE(__pdesc+4, 21, 1, __val) | ||
101 | #define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ | ||
102 | SET_BITS_TO_LE_4BYTE(__pdesc+4, 22, 2, __val) | ||
103 | #define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ | ||
104 | SET_BITS_TO_LE_4BYTE(__pdesc+4, 26, 5, __val) | ||
105 | #define SET_TX_DESC_PADDING_LEN(__pdesc, __val) \ | ||
106 | SET_BITS_TO_LE_4BYTE(__pdesc+4, 24, 8, __val) | ||
107 | |||
108 | #define GET_TX_DESC_MACID(__pdesc) \ | ||
109 | LE_BITS_TO_4BYTE(__pdesc+4, 0, 5) | ||
110 | #define GET_TX_DESC_AGG_ENABLE(__pdesc) \ | ||
111 | LE_BITS_TO_4BYTE(__pdesc+4, 5, 1) | ||
112 | #define GET_TX_DESC_AGG_BREAK(__pdesc) \ | ||
113 | LE_BITS_TO_4BYTE(__pdesc+4, 6, 1) | ||
114 | #define GET_TX_DESC_RDG_ENABLE(__pdesc) \ | ||
115 | LE_BITS_TO_4BYTE(__pdesc+4, 7, 1) | ||
116 | #define GET_TX_DESC_QUEUE_SEL(__pdesc) \ | ||
117 | LE_BITS_TO_4BYTE(__pdesc+4, 8, 5) | ||
118 | #define GET_TX_DESC_RDG_NAV_EXT(__pdesc) \ | ||
119 | LE_BITS_TO_4BYTE(__pdesc+4, 13, 1) | ||
120 | #define GET_TX_DESC_LSIG_TXOP_EN(__pdesc) \ | ||
121 | LE_BITS_TO_4BYTE(__pdesc+4, 14, 1) | ||
122 | #define GET_TX_DESC_PIFS(__pdesc) \ | ||
123 | LE_BITS_TO_4BYTE(__pdesc+4, 15, 1) | ||
124 | #define GET_TX_DESC_RATE_ID(__pdesc) \ | ||
125 | LE_BITS_TO_4BYTE(__pdesc+4, 16, 4) | ||
126 | #define GET_TX_DESC_NAV_USE_HDR(__pdesc) \ | ||
127 | LE_BITS_TO_4BYTE(__pdesc+4, 20, 1) | ||
128 | #define GET_TX_DESC_EN_DESC_ID(__pdesc) \ | ||
129 | LE_BITS_TO_4BYTE(__pdesc+4, 21, 1) | ||
130 | #define GET_TX_DESC_SEC_TYPE(__pdesc) \ | ||
131 | LE_BITS_TO_4BYTE(__pdesc+4, 22, 2) | ||
132 | #define GET_TX_DESC_PKT_OFFSET(__pdesc) \ | ||
133 | LE_BITS_TO_4BYTE(__pdesc+4, 24, 8) | ||
134 | |||
135 | #define SET_TX_DESC_RTS_RC(__pdesc, __val) \ | ||
136 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 0, 6, __val) | ||
137 | #define SET_TX_DESC_DATA_RC(__pdesc, __val) \ | ||
138 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 6, 6, __val) | ||
139 | #define SET_TX_DESC_AGG_ENABLE(__pdesc, __val) \ | ||
140 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 12, 1, __val) | ||
141 | #define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \ | ||
142 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 13, 1, __val) | ||
143 | #define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \ | ||
144 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 14, 2, __val) | ||
145 | #define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \ | ||
146 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 16, 1, __val) | ||
147 | #define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ | ||
148 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 17, 1, __val) | ||
149 | #define SET_TX_DESC_RAW(__pdesc, __val) \ | ||
150 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val) | ||
151 | #define SET_TX_DESC_CCX(__pdesc, __val) \ | ||
152 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val) | ||
153 | #define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \ | ||
154 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val) | ||
155 | #define SET_TX_DESC_BT_INT(__pdesc, __val) \ | ||
156 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 23, 1, __val) | ||
157 | #define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \ | ||
158 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 24, 1, __val) | ||
159 | #define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \ | ||
160 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 25, 1, __val) | ||
161 | #define SET_TX_DESC_TX_ANT_CCK(__pdesc, __val) \ | ||
162 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 26, 2, __val) | ||
163 | #define SET_TX_DESC_TX_ANTL(__pdesc, __val) \ | ||
164 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 28, 2, __val) | ||
165 | #define SET_TX_DESC_TX_ANT_HT(__pdesc, __val) \ | ||
166 | SET_BITS_TO_LE_4BYTE(__pdesc+8, 30, 2, __val) | ||
167 | |||
168 | #define GET_TX_DESC_RTS_RC(__pdesc) \ | ||
169 | LE_BITS_TO_4BYTE(__pdesc+8, 0, 6) | ||
170 | #define GET_TX_DESC_DATA_RC(__pdesc) \ | ||
171 | LE_BITS_TO_4BYTE(__pdesc+8, 6, 6) | ||
172 | #define GET_TX_DESC_BAR_RTY_TH(__pdesc) \ | ||
173 | LE_BITS_TO_4BYTE(__pdesc+8, 14, 2) | ||
174 | #define GET_TX_DESC_MORE_FRAG(__pdesc) \ | ||
175 | LE_BITS_TO_4BYTE(__pdesc+8, 17, 1) | ||
176 | #define GET_TX_DESC_RAW(__pdesc) \ | ||
177 | LE_BITS_TO_4BYTE(__pdesc+8, 18, 1) | ||
178 | #define GET_TX_DESC_CCX(__pdesc) \ | ||
179 | LE_BITS_TO_4BYTE(__pdesc+8, 19, 1) | ||
180 | #define GET_TX_DESC_AMPDU_DENSITY(__pdesc) \ | ||
181 | LE_BITS_TO_4BYTE(__pdesc+8, 20, 3) | ||
182 | #define GET_TX_DESC_ANTSEL_A(__pdesc) \ | ||
183 | LE_BITS_TO_4BYTE(__pdesc+8, 24, 1) | ||
184 | #define GET_TX_DESC_ANTSEL_B(__pdesc) \ | ||
185 | LE_BITS_TO_4BYTE(__pdesc+8, 25, 1) | ||
186 | #define GET_TX_DESC_TX_ANT_CCK(__pdesc) \ | ||
187 | LE_BITS_TO_4BYTE(__pdesc+8, 26, 2) | ||
188 | #define GET_TX_DESC_TX_ANTL(__pdesc) \ | ||
189 | LE_BITS_TO_4BYTE(__pdesc+8, 28, 2) | ||
190 | #define GET_TX_DESC_TX_ANT_HT(__pdesc) \ | ||
191 | LE_BITS_TO_4BYTE(__pdesc+8, 30, 2) | ||
192 | |||
193 | #define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val) \ | ||
194 | SET_BITS_TO_LE_4BYTE(__pdesc+12, 0, 8, __val) | ||
195 | #define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \ | ||
196 | SET_BITS_TO_LE_4BYTE(__pdesc+12, 8, 8, __val) | ||
197 | #define SET_TX_DESC_SEQ(__pdesc, __val) \ | ||
198 | SET_BITS_TO_LE_4BYTE(__pdesc+12, 16, 12, __val) | ||
199 | #define SET_TX_DESC_CPU_HANDLE(__pdesc, __val) \ | ||
200 | SET_BITS_TO_LE_4BYTE(__pdesc+12, 28, 1, __val) | ||
201 | #define SET_TX_DESC_TAG1(__pdesc, __val) \ | ||
202 | SET_BITS_TO_LE_4BYTE(__pdesc+12, 29, 1, __val) | ||
203 | #define SET_TX_DESC_TRIGGER_INT(__pdesc, __val) \ | ||
204 | SET_BITS_TO_LE_4BYTE(__pdesc+12, 30, 1, __val) | ||
205 | #define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \ | ||
206 | SET_BITS_TO_LE_4BYTE(__pdesc+12, 31, 1, __val) | ||
207 | |||
208 | |||
209 | #define GET_TX_DESC_NEXT_HEAP_PAGE(__pdesc) \ | ||
210 | LE_BITS_TO_4BYTE(__pdesc+12, 0, 8) | ||
211 | #define GET_TX_DESC_TAIL_PAGE(__pdesc) \ | ||
212 | LE_BITS_TO_4BYTE(__pdesc+12, 8, 8) | ||
213 | #define GET_TX_DESC_SEQ(__pdesc) \ | ||
214 | LE_BITS_TO_4BYTE(__pdesc+12, 16, 12) | ||
215 | |||
216 | |||
217 | #define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ | ||
218 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 5, __val) | ||
219 | #define SET_TX_DESC_AP_DCFE(__pdesc, __val) \ | ||
220 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 5, 1, __val) | ||
221 | #define SET_TX_DESC_QOS(__pdesc, __val) \ | ||
222 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 6, 1, __val) | ||
223 | #define SET_TX_DESC_HWSEQ_SSN(__pdesc, __val) \ | ||
224 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 7, 1, __val) | ||
225 | #define SET_TX_DESC_USE_RATE(__pdesc, __val) \ | ||
226 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 8, 1, __val) | ||
227 | #define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \ | ||
228 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 9, 1, __val) | ||
229 | #define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ | ||
230 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 10, 1, __val) | ||
231 | #define SET_TX_DESC_CTS2SELF(__pdesc, __val) \ | ||
232 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 11, 1, __val) | ||
233 | #define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ | ||
234 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 12, 1, __val) | ||
235 | #define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \ | ||
236 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 13, 1, __val) | ||
237 | #define SET_TX_DESC_PORT_ID(__pdesc, __val) \ | ||
238 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 14, 1, __val) | ||
239 | #define SET_TX_DESC_PWR_STATUS(__pdesc, __val) \ | ||
240 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 15, 3, __val) | ||
241 | #define SET_TX_DESC_WAIT_DCTS(__pdesc, __val) \ | ||
242 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 18, 1, __val) | ||
243 | #define SET_TX_DESC_CTS2AP_EN(__pdesc, __val) \ | ||
244 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 19, 1, __val) | ||
245 | #define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ | ||
246 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 20, 2, __val) | ||
247 | #define SET_TX_DESC_TX_STBC(__pdesc, __val) \ | ||
248 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 22, 2, __val) | ||
249 | #define SET_TX_DESC_DATA_SHORT(__pdesc, __val) \ | ||
250 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 24, 1, __val) | ||
251 | #define SET_TX_DESC_DATA_BW(__pdesc, __val) \ | ||
252 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 25, 1, __val) | ||
253 | #define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ | ||
254 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 26, 1, __val) | ||
255 | #define SET_TX_DESC_RTS_BW(__pdesc, __val) \ | ||
256 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 27, 1, __val) | ||
257 | #define SET_TX_DESC_RTS_SC(__pdesc, __val) \ | ||
258 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 28, 2, __val) | ||
259 | #define SET_TX_DESC_RTS_STBC(__pdesc, __val) \ | ||
260 | SET_BITS_TO_LE_4BYTE(__pdesc+16, 30, 2, __val) | ||
261 | |||
262 | #define GET_TX_DESC_RTS_RATE(__pdesc) \ | ||
263 | LE_BITS_TO_4BYTE(__pdesc+16, 0, 5) | ||
264 | #define GET_TX_DESC_AP_DCFE(__pdesc) \ | ||
265 | LE_BITS_TO_4BYTE(__pdesc+16, 5, 1) | ||
266 | #define GET_TX_DESC_QOS(__pdesc) \ | ||
267 | LE_BITS_TO_4BYTE(__pdesc+16, 6, 1) | ||
268 | #define GET_TX_DESC_HWSEQ_EN(__pdesc) \ | ||
269 | LE_BITS_TO_4BYTE(__pdesc+16, 7, 1) | ||
270 | #define GET_TX_DESC_USE_RATE(__pdesc) \ | ||
271 | LE_BITS_TO_4BYTE(__pdesc+16, 8, 1) | ||
272 | #define GET_TX_DESC_DISABLE_RTS_FB(__pdesc) \ | ||
273 | LE_BITS_TO_4BYTE(__pdesc+16, 9, 1) | ||
274 | #define GET_TX_DESC_DISABLE_FB(__pdesc) \ | ||
275 | LE_BITS_TO_4BYTE(__pdesc+16, 10, 1) | ||
276 | #define GET_TX_DESC_CTS2SELF(__pdesc) \ | ||
277 | LE_BITS_TO_4BYTE(__pdesc+16, 11, 1) | ||
278 | #define GET_TX_DESC_RTS_ENABLE(__pdesc) \ | ||
279 | LE_BITS_TO_4BYTE(__pdesc+16, 12, 1) | ||
280 | #define GET_TX_DESC_HW_RTS_ENABLE(__pdesc) \ | ||
281 | LE_BITS_TO_4BYTE(__pdesc+16, 13, 1) | ||
282 | #define GET_TX_DESC_PORT_ID(__pdesc) \ | ||
283 | LE_BITS_TO_4BYTE(__pdesc+16, 14, 1) | ||
284 | #define GET_TX_DESC_WAIT_DCTS(__pdesc) \ | ||
285 | LE_BITS_TO_4BYTE(__pdesc+16, 18, 1) | ||
286 | #define GET_TX_DESC_CTS2AP_EN(__pdesc) \ | ||
287 | LE_BITS_TO_4BYTE(__pdesc+16, 19, 1) | ||
288 | #define GET_TX_DESC_TX_SUB_CARRIER(__pdesc) \ | ||
289 | LE_BITS_TO_4BYTE(__pdesc+16, 20, 2) | ||
290 | #define GET_TX_DESC_TX_STBC(__pdesc) \ | ||
291 | LE_BITS_TO_4BYTE(__pdesc+16, 22, 2) | ||
292 | #define GET_TX_DESC_DATA_SHORT(__pdesc) \ | ||
293 | LE_BITS_TO_4BYTE(__pdesc+16, 24, 1) | ||
294 | #define GET_TX_DESC_DATA_BW(__pdesc) \ | ||
295 | LE_BITS_TO_4BYTE(__pdesc+16, 25, 1) | ||
296 | #define GET_TX_DESC_RTS_SHORT(__pdesc) \ | ||
297 | LE_BITS_TO_4BYTE(__pdesc+16, 26, 1) | ||
298 | #define GET_TX_DESC_RTS_BW(__pdesc) \ | ||
299 | LE_BITS_TO_4BYTE(__pdesc+16, 27, 1) | ||
300 | #define GET_TX_DESC_RTS_SC(__pdesc) \ | ||
301 | LE_BITS_TO_4BYTE(__pdesc+16, 28, 2) | ||
302 | #define GET_TX_DESC_RTS_STBC(__pdesc) \ | ||
303 | LE_BITS_TO_4BYTE(__pdesc+16, 30, 2) | ||
304 | |||
305 | #define SET_TX_DESC_TX_RATE(__pdesc, __val) \ | ||
306 | SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 6, __val) | ||
307 | #define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \ | ||
308 | SET_BITS_TO_LE_4BYTE(__pdesc+20, 6, 1, __val) | ||
309 | #define SET_TX_DESC_CCX_TAG(__pdesc, __val) \ | ||
310 | SET_BITS_TO_LE_4BYTE(__pdesc+20, 7, 1, __val) | ||
311 | #define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ | ||
312 | SET_BITS_TO_LE_4BYTE(__pdesc+20, 8, 5, __val) | ||
313 | #define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ | ||
314 | SET_BITS_TO_LE_4BYTE(__pdesc+20, 13, 4, __val) | ||
315 | #define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \ | ||
316 | SET_BITS_TO_LE_4BYTE(__pdesc+20, 17, 1, __val) | ||
317 | #define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \ | ||
318 | SET_BITS_TO_LE_4BYTE(__pdesc+20, 18, 6, __val) | ||
319 | #define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val) \ | ||
320 | SET_BITS_TO_LE_4BYTE(__pdesc+20, 24, 8, __val) | ||
321 | |||
322 | #define GET_TX_DESC_TX_RATE(__pdesc) \ | ||
323 | LE_BITS_TO_4BYTE(__pdesc+20, 0, 6) | ||
324 | #define GET_TX_DESC_DATA_SHORTGI(__pdesc) \ | ||
325 | LE_BITS_TO_4BYTE(__pdesc+20, 6, 1) | ||
326 | #define GET_TX_DESC_CCX_TAG(__pdesc) \ | ||
327 | LE_BITS_TO_4BYTE(__pdesc+20, 7, 1) | ||
328 | #define GET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc) \ | ||
329 | LE_BITS_TO_4BYTE(__pdesc+20, 8, 5) | ||
330 | #define GET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc) \ | ||
331 | LE_BITS_TO_4BYTE(__pdesc+20, 13, 4) | ||
332 | #define GET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc) \ | ||
333 | LE_BITS_TO_4BYTE(__pdesc+20, 17, 1) | ||
334 | #define GET_TX_DESC_DATA_RETRY_LIMIT(__pdesc) \ | ||
335 | LE_BITS_TO_4BYTE(__pdesc+20, 18, 6) | ||
336 | #define GET_TX_DESC_USB_TXAGG_NUM(__pdesc) \ | ||
337 | LE_BITS_TO_4BYTE(__pdesc+20, 24, 8) | ||
338 | |||
339 | #define SET_TX_DESC_TXAGC_A(__pdesc, __val) \ | ||
340 | SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 5, __val) | ||
341 | #define SET_TX_DESC_TXAGC_B(__pdesc, __val) \ | ||
342 | SET_BITS_TO_LE_4BYTE(__pdesc+24, 5, 5, __val) | ||
343 | #define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val) \ | ||
344 | SET_BITS_TO_LE_4BYTE(__pdesc+24, 10, 1, __val) | ||
345 | #define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \ | ||
346 | SET_BITS_TO_LE_4BYTE(__pdesc+24, 11, 5, __val) | ||
347 | #define SET_TX_DESC_MCSG1_MAX_LEN(__pdesc, __val) \ | ||
348 | SET_BITS_TO_LE_4BYTE(__pdesc+24, 16, 4, __val) | ||
349 | #define SET_TX_DESC_MCSG2_MAX_LEN(__pdesc, __val) \ | ||
350 | SET_BITS_TO_LE_4BYTE(__pdesc+24, 20, 4, __val) | ||
351 | #define SET_TX_DESC_MCSG3_MAX_LEN(__pdesc, __val) \ | ||
352 | SET_BITS_TO_LE_4BYTE(__pdesc+24, 24, 4, __val) | ||
353 | #define SET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc, __val) \ | ||
354 | SET_BITS_TO_LE_4BYTE(__pdesc+24, 28, 4, __val) | ||
355 | |||
356 | #define GET_TX_DESC_TXAGC_A(__pdesc) \ | ||
357 | LE_BITS_TO_4BYTE(__pdesc+24, 0, 5) | ||
358 | #define GET_TX_DESC_TXAGC_B(__pdesc) \ | ||
359 | LE_BITS_TO_4BYTE(__pdesc+24, 5, 5) | ||
360 | #define GET_TX_DESC_USE_MAX_LEN(__pdesc) \ | ||
361 | LE_BITS_TO_4BYTE(__pdesc+24, 10, 1) | ||
362 | #define GET_TX_DESC_MAX_AGG_NUM(__pdesc) \ | ||
363 | LE_BITS_TO_4BYTE(__pdesc+24, 11, 5) | ||
364 | #define GET_TX_DESC_MCSG1_MAX_LEN(__pdesc) \ | ||
365 | LE_BITS_TO_4BYTE(__pdesc+24, 16, 4) | ||
366 | #define GET_TX_DESC_MCSG2_MAX_LEN(__pdesc) \ | ||
367 | LE_BITS_TO_4BYTE(__pdesc+24, 20, 4) | ||
368 | #define GET_TX_DESC_MCSG3_MAX_LEN(__pdesc) \ | ||
369 | LE_BITS_TO_4BYTE(__pdesc+24, 24, 4) | ||
370 | #define GET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc) \ | ||
371 | LE_BITS_TO_4BYTE(__pdesc+24, 28, 4) | ||
372 | |||
373 | #define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ | ||
374 | SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val) | ||
375 | #define SET_TX_DESC_SW_OFFSET30(__pdesc, __val) \ | ||
376 | SET_BITS_TO_LE_4BYTE(__pdesc+28, 16, 8, __val) | ||
377 | #define SET_TX_DESC_SW_OFFSET31(__pdesc, __val) \ | ||
378 | SET_BITS_TO_LE_4BYTE(__pdesc+28, 24, 4, __val) | ||
379 | #define SET_TX_DESC_ANTSEL_C(__pdesc, __val) \ | ||
380 | SET_BITS_TO_LE_4BYTE(__pdesc+28, 29, 1, __val) | ||
381 | #define SET_TX_DESC_NULL_0(__pdesc, __val) \ | ||
382 | SET_BITS_TO_LE_4BYTE(__pdesc+28, 30, 1, __val) | ||
383 | #define SET_TX_DESC_NULL_1(__pdesc, __val) \ | ||
384 | SET_BITS_TO_LE_4BYTE(__pdesc+28, 30, 1, __val) | ||
385 | |||
386 | #define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \ | ||
387 | LE_BITS_TO_4BYTE(__pdesc+28, 0, 16) | ||
388 | |||
389 | |||
390 | #define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ | ||
391 | SET_BITS_TO_LE_4BYTE(__pdesc+32, 0, 32, __val) | ||
392 | #define SET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc, __val) \ | ||
393 | SET_BITS_TO_LE_4BYTE(__pdesc+36, 0, 32, __val) | ||
394 | |||
395 | #define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ | ||
396 | LE_BITS_TO_4BYTE(__pdesc+32, 0, 32) | ||
397 | #define GET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc) \ | ||
398 | LE_BITS_TO_4BYTE(__pdesc+36, 0, 32) | ||
399 | |||
400 | #define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ | ||
401 | SET_BITS_TO_LE_4BYTE(__pdesc+40, 0, 32, __val) | ||
402 | #define SET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc, __val) \ | ||
403 | SET_BITS_TO_LE_4BYTE(__pdesc+44, 0, 32, __val) | ||
404 | |||
405 | #define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc) \ | ||
406 | LE_BITS_TO_4BYTE(__pdesc+40, 0, 32) | ||
407 | #define GET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc) \ | ||
408 | LE_BITS_TO_4BYTE(__pdesc+44, 0, 32) | ||
409 | |||
410 | #define GET_RX_DESC_PKT_LEN(__pdesc) \ | ||
411 | LE_BITS_TO_4BYTE(__pdesc, 0, 14) | ||
412 | #define GET_RX_DESC_CRC32(__pdesc) \ | ||
413 | LE_BITS_TO_4BYTE(__pdesc, 14, 1) | ||
414 | #define GET_RX_DESC_ICV(__pdesc) \ | ||
415 | LE_BITS_TO_4BYTE(__pdesc, 15, 1) | ||
416 | #define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \ | ||
417 | LE_BITS_TO_4BYTE(__pdesc, 16, 4) | ||
418 | #define GET_RX_DESC_SECURITY(__pdesc) \ | ||
419 | LE_BITS_TO_4BYTE(__pdesc, 20, 3) | ||
420 | #define GET_RX_DESC_QOS(__pdesc) \ | ||
421 | LE_BITS_TO_4BYTE(__pdesc, 23, 1) | ||
422 | #define GET_RX_DESC_SHIFT(__pdesc) \ | ||
423 | LE_BITS_TO_4BYTE(__pdesc, 24, 2) | ||
424 | #define GET_RX_DESC_PHYST(__pdesc) \ | ||
425 | LE_BITS_TO_4BYTE(__pdesc, 26, 1) | ||
426 | #define GET_RX_DESC_SWDEC(__pdesc) \ | ||
427 | LE_BITS_TO_4BYTE(__pdesc, 27, 1) | ||
428 | #define GET_RX_DESC_LS(__pdesc) \ | ||
429 | LE_BITS_TO_4BYTE(__pdesc, 28, 1) | ||
430 | #define GET_RX_DESC_FS(__pdesc) \ | ||
431 | LE_BITS_TO_4BYTE(__pdesc, 29, 1) | ||
432 | #define GET_RX_DESC_EOR(__pdesc) \ | ||
433 | LE_BITS_TO_4BYTE(__pdesc, 30, 1) | ||
434 | #define GET_RX_DESC_OWN(__pdesc) \ | ||
435 | LE_BITS_TO_4BYTE(__pdesc, 31, 1) | ||
436 | |||
437 | #define SET_RX_DESC_PKT_LEN(__pdesc, __val) \ | ||
438 | SET_BITS_TO_LE_4BYTE(__pdesc, 0, 14, __val) | ||
439 | #define SET_RX_DESC_EOR(__pdesc, __val) \ | ||
440 | SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) | ||
441 | #define SET_RX_DESC_OWN(__pdesc, __val) \ | ||
442 | SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) | ||
443 | |||
444 | #define GET_RX_DESC_MACID(__pdesc) \ | ||
445 | LE_BITS_TO_4BYTE(__pdesc+4, 0, 6) | ||
446 | #define GET_RX_DESC_PAGGR(__pdesc) \ | ||
447 | LE_BITS_TO_4BYTE(__pdesc+4, 14, 1) | ||
448 | #define GET_RX_DESC_FAGGR(__pdesc) \ | ||
449 | LE_BITS_TO_4BYTE(__pdesc+4, 15, 1) | ||
450 | #define GET_RX_DESC_A1_FIT(__pdesc) \ | ||
451 | LE_BITS_TO_4BYTE(__pdesc+4, 16, 4) | ||
452 | #define GET_RX_DESC_A2_FIT(__pdesc) \ | ||
453 | LE_BITS_TO_4BYTE(__pdesc+4, 20, 4) | ||
454 | #define GET_RX_DESC_PAM(__pdesc) \ | ||
455 | LE_BITS_TO_4BYTE(__pdesc+4, 24, 1) | ||
456 | #define GET_RX_DESC_PWR(__pdesc) \ | ||
457 | LE_BITS_TO_4BYTE(__pdesc+4, 25, 1) | ||
458 | #define GET_RX_DESC_MD(__pdesc) \ | ||
459 | LE_BITS_TO_4BYTE(__pdesc+4, 26, 1) | ||
460 | #define GET_RX_DESC_MF(__pdesc) \ | ||
461 | LE_BITS_TO_4BYTE(__pdesc+4, 27, 1) | ||
462 | #define GET_RX_DESC_TYPE(__pdesc) \ | ||
463 | LE_BITS_TO_4BYTE(__pdesc+4, 28, 2) | ||
464 | #define GET_RX_DESC_MC(__pdesc) \ | ||
465 | LE_BITS_TO_4BYTE(__pdesc+4, 30, 1) | ||
466 | #define GET_RX_DESC_BC(__pdesc) \ | ||
467 | LE_BITS_TO_4BYTE(__pdesc+4, 31, 1) | ||
468 | #define GET_RX_DESC_SEQ(__pdesc) \ | ||
469 | LE_BITS_TO_4BYTE(__pdesc+8, 0, 12) | ||
470 | #define GET_RX_DESC_FRAG(__pdesc) \ | ||
471 | LE_BITS_TO_4BYTE(__pdesc+8, 12, 4) | ||
472 | |||
473 | #define GET_RX_DESC_RXMCS(__pdesc) \ | ||
474 | LE_BITS_TO_4BYTE(__pdesc+12, 0, 6) | ||
475 | #define GET_RX_DESC_RXHT(__pdesc) \ | ||
476 | LE_BITS_TO_4BYTE(__pdesc+12, 6, 1) | ||
477 | #define GET_RX_STATUS_DESC_RX_GF(__pdesc) \ | ||
478 | LE_BITS_TO_4BYTE(__pdesc+12, 7, 1) | ||
479 | #define GET_RX_DESC_SPLCP(__pdesc) \ | ||
480 | LE_BITS_TO_4BYTE(__pdesc+12, 8, 1) | ||
481 | #define GET_RX_DESC_BW(__pdesc) \ | ||
482 | LE_BITS_TO_4BYTE(__pdesc+12, 9, 1) | ||
483 | #define GET_RX_DESC_HTC(__pdesc) \ | ||
484 | LE_BITS_TO_4BYTE(__pdesc+12, 10, 1) | ||
485 | #define GET_RX_STATUS_DESC_EOSP(__pdesc) \ | ||
486 | LE_BITS_TO_4BYTE(__pdesc+12, 11, 1) | ||
487 | #define GET_RX_STATUS_DESC_BSSID_FIT(__pdesc) \ | ||
488 | LE_BITS_TO_4BYTE(__pdesc+12, 12, 2) | ||
489 | #define GET_RX_STATUS_DESC_RPT_SEL(__pdesc) \ | ||
490 | LE_BITS_TO_4BYTE(__pdesc+12, 14, 2) | ||
491 | |||
492 | #define GET_RX_STATUS_DESC_PATTERN_MATCH(__pdesc) \ | ||
493 | LE_BITS_TO_4BYTE(__pdesc+12, 29, 1) | ||
494 | #define GET_RX_STATUS_DESC_UNICAST_MATCH(__pdesc) \ | ||
495 | LE_BITS_TO_4BYTE(__pdesc+12, 30, 1) | ||
496 | #define GET_RX_STATUS_DESC_MAGIC_MATCH(__pdesc) \ | ||
497 | LE_BITS_TO_4BYTE(__pdesc+12, 31, 1) | ||
498 | |||
499 | #define GET_RX_DESC_IV1(__pdesc) \ | ||
500 | LE_BITS_TO_4BYTE(__pdesc+16, 0, 32) | ||
501 | #define GET_RX_DESC_TSFL(__pdesc) \ | ||
502 | LE_BITS_TO_4BYTE(__pdesc+20, 0, 32) | ||
503 | |||
504 | #define GET_RX_DESC_BUFF_ADDR(__pdesc) \ | ||
505 | LE_BITS_TO_4BYTE(__pdesc+24, 0, 32) | ||
506 | #define GET_RX_DESC_BUFF_ADDR64(__pdesc) \ | ||
507 | LE_BITS_TO_4BYTE(__pdesc+28, 0, 32) | ||
508 | |||
509 | #define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \ | ||
510 | SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 32, __val) | ||
511 | #define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \ | ||
512 | SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 32, __val) | ||
513 | |||
514 | /* TX report 2 format in Rx desc*/ | ||
515 | |||
516 | #define GET_RX_RPT2_DESC_PKT_LEN(__status) \ | ||
517 | LE_BITS_TO_4BYTE(__status, 0, 9) | ||
518 | #define GET_RX_RPT2_DESC_MACID_VALID_1(__status) \ | ||
519 | LE_BITS_TO_4BYTE(__status+16, 0, 32) | ||
520 | #define GET_RX_RPT2_DESC_MACID_VALID_2(__status) \ | ||
521 | LE_BITS_TO_4BYTE(__status+20, 0, 32) | ||
522 | |||
523 | #define SET_EARLYMODE_PKTNUM(__paddr, __value) \ | ||
524 | SET_BITS_TO_LE_4BYTE(__paddr, 0, 4, __value) | ||
525 | #define SET_EARLYMODE_LEN0(__paddr, __value) \ | ||
526 | SET_BITS_TO_LE_4BYTE(__paddr, 4, 12, __value) | ||
527 | #define SET_EARLYMODE_LEN1(__paddr, __value) \ | ||
528 | SET_BITS_TO_LE_4BYTE(__paddr, 16, 12, __value) | ||
529 | #define SET_EARLYMODE_LEN2_1(__paddr, __value) \ | ||
530 | SET_BITS_TO_LE_4BYTE(__paddr, 28, 4, __value) | ||
531 | #define SET_EARLYMODE_LEN2_2(__paddr, __value) \ | ||
532 | SET_BITS_TO_LE_4BYTE(__paddr+4, 0, 8, __value) | ||
533 | #define SET_EARLYMODE_LEN3(__paddr, __value) \ | ||
534 | SET_BITS_TO_LE_4BYTE(__paddr+4, 8, 12, __value) | ||
535 | #define SET_EARLYMODE_LEN4(__paddr, __value) \ | ||
536 | SET_BITS_TO_LE_4BYTE(__paddr+4, 20, 12, __value) | ||
537 | |||
538 | #define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ | ||
539 | do { \ | ||
540 | if (_size > TX_DESC_NEXT_DESC_OFFSET) \ | ||
541 | memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ | ||
542 | else \ | ||
543 | memset(__pdesc, 0, _size); \ | ||
544 | } while (0) | ||
545 | |||
546 | #define RTL8188_RX_HAL_IS_CCK_RATE(rxmcs)\ | ||
547 | (rxmcs == DESC92C_RATE1M ||\ | ||
548 | rxmcs == DESC92C_RATE2M ||\ | ||
549 | rxmcs == DESC92C_RATE5_5M ||\ | ||
550 | rxmcs == DESC92C_RATE11M) | ||
551 | |||
552 | struct phy_rx_agc_info_t { | ||
553 | #if __LITTLE_ENDIAN | ||
554 | u8 gain:7, trsw:1; | ||
555 | #else | ||
556 | u8 trsw:1, gain:7; | ||
557 | #endif | ||
558 | }; | ||
559 | struct phy_status_rpt { | ||
560 | struct phy_rx_agc_info_t path_agc[2]; | ||
561 | u8 ch_corr[2]; | ||
562 | u8 cck_sig_qual_ofdm_pwdb_all; | ||
563 | u8 cck_agc_rpt_ofdm_cfosho_a; | ||
564 | u8 cck_rpt_b_ofdm_cfosho_b; | ||
565 | u8 rsvd_1; | ||
566 | u8 noise_power_db_msb; | ||
567 | u8 path_cfotail[2]; | ||
568 | u8 pcts_mask[2]; | ||
569 | u8 stream_rxevm[2]; | ||
570 | u8 path_rxsnr[2]; | ||
571 | u8 noise_power_db_lsb; | ||
572 | u8 rsvd_2[3]; | ||
573 | u8 stream_csi[2]; | ||
574 | u8 stream_target_csi[2]; | ||
575 | u8 sig_evm; | ||
576 | u8 rsvd_3; | ||
577 | #if __LITTLE_ENDIAN | ||
578 | u8 antsel_rx_keep_2:1; /*ex_intf_flg:1;*/ | ||
579 | u8 sgi_en:1; | ||
580 | u8 rxsc:2; | ||
581 | u8 idle_long:1; | ||
582 | u8 r_ant_train_en:1; | ||
583 | u8 ant_sel_b:1; | ||
584 | u8 ant_sel:1; | ||
585 | #else /* _BIG_ENDIAN_ */ | ||
586 | u8 ant_sel:1; | ||
587 | u8 ant_sel_b:1; | ||
588 | u8 r_ant_train_en:1; | ||
589 | u8 idle_long:1; | ||
590 | u8 rxsc:2; | ||
591 | u8 sgi_en:1; | ||
592 | u8 antsel_rx_keep_2:1; /*ex_intf_flg:1;*/ | ||
593 | #endif | ||
594 | } __packed; | ||
595 | |||
596 | struct rx_fwinfo_88e { | ||
597 | u8 gain_trsw[4]; | ||
598 | u8 pwdb_all; | ||
599 | u8 cfosho[4]; | ||
600 | u8 cfotail[4]; | ||
601 | char rxevm[2]; | ||
602 | char rxsnr[4]; | ||
603 | u8 pdsnr[2]; | ||
604 | u8 csi_current[2]; | ||
605 | u8 csi_target[2]; | ||
606 | u8 sigevm; | ||
607 | u8 max_ex_pwr; | ||
608 | u8 ex_intf_flag:1; | ||
609 | u8 sgi_en:1; | ||
610 | u8 rxsc:2; | ||
611 | u8 reserve:4; | ||
612 | } __packed; | ||
613 | |||
614 | struct tx_desc_88e { | ||
615 | u32 pktsize:16; | ||
616 | u32 offset:8; | ||
617 | u32 bmc:1; | ||
618 | u32 htc:1; | ||
619 | u32 lastseg:1; | ||
620 | u32 firstseg:1; | ||
621 | u32 linip:1; | ||
622 | u32 noacm:1; | ||
623 | u32 gf:1; | ||
624 | u32 own:1; | ||
625 | |||
626 | u32 macid:6; | ||
627 | u32 rsvd0:2; | ||
628 | u32 queuesel:5; | ||
629 | u32 rd_nav_ext:1; | ||
630 | u32 lsig_txop_en:1; | ||
631 | u32 pifs:1; | ||
632 | u32 rateid:4; | ||
633 | u32 nav_usehdr:1; | ||
634 | u32 en_descid:1; | ||
635 | u32 sectype:2; | ||
636 | u32 pktoffset:8; | ||
637 | |||
638 | u32 rts_rc:6; | ||
639 | u32 data_rc:6; | ||
640 | u32 agg_en:1; | ||
641 | u32 rdg_en:1; | ||
642 | u32 bar_retryht:2; | ||
643 | u32 agg_break:1; | ||
644 | u32 morefrag:1; | ||
645 | u32 raw:1; | ||
646 | u32 ccx:1; | ||
647 | u32 ampdudensity:3; | ||
648 | u32 bt_int:1; | ||
649 | u32 ant_sela:1; | ||
650 | u32 ant_selb:1; | ||
651 | u32 txant_cck:2; | ||
652 | u32 txant_l:2; | ||
653 | u32 txant_ht:2; | ||
654 | |||
655 | u32 nextheadpage:8; | ||
656 | u32 tailpage:8; | ||
657 | u32 seq:12; | ||
658 | u32 cpu_handle:1; | ||
659 | u32 tag1:1; | ||
660 | u32 trigger_int:1; | ||
661 | u32 hwseq_en:1; | ||
662 | |||
663 | u32 rtsrate:5; | ||
664 | u32 apdcfe:1; | ||
665 | u32 qos:1; | ||
666 | u32 hwseq_ssn:1; | ||
667 | u32 userrate:1; | ||
668 | u32 dis_rtsfb:1; | ||
669 | u32 dis_datafb:1; | ||
670 | u32 cts2self:1; | ||
671 | u32 rts_en:1; | ||
672 | u32 hwrts_en:1; | ||
673 | u32 portid:1; | ||
674 | u32 pwr_status:3; | ||
675 | u32 waitdcts:1; | ||
676 | u32 cts2ap_en:1; | ||
677 | u32 txsc:2; | ||
678 | u32 stbc:2; | ||
679 | u32 txshort:1; | ||
680 | u32 txbw:1; | ||
681 | u32 rtsshort:1; | ||
682 | u32 rtsbw:1; | ||
683 | u32 rtssc:2; | ||
684 | u32 rtsstbc:2; | ||
685 | |||
686 | u32 txrate:6; | ||
687 | u32 shortgi:1; | ||
688 | u32 ccxt:1; | ||
689 | u32 txrate_fb_lmt:5; | ||
690 | u32 rtsrate_fb_lmt:4; | ||
691 | u32 retrylmt_en:1; | ||
692 | u32 txretrylmt:6; | ||
693 | u32 usb_txaggnum:8; | ||
694 | |||
695 | u32 txagca:5; | ||
696 | u32 txagcb:5; | ||
697 | u32 usemaxlen:1; | ||
698 | u32 maxaggnum:5; | ||
699 | u32 mcsg1maxlen:4; | ||
700 | u32 mcsg2maxlen:4; | ||
701 | u32 mcsg3maxlen:4; | ||
702 | u32 mcs7sgimaxlen:4; | ||
703 | |||
704 | u32 txbuffersize:16; | ||
705 | u32 sw_offset30:8; | ||
706 | u32 sw_offset31:4; | ||
707 | u32 rsvd1:1; | ||
708 | u32 antsel_c:1; | ||
709 | u32 null_0:1; | ||
710 | u32 null_1:1; | ||
711 | |||
712 | u32 txbuffaddr; | ||
713 | u32 txbufferaddr64; | ||
714 | u32 nextdescaddress; | ||
715 | u32 nextdescaddress64; | ||
716 | |||
717 | u32 reserve_pass_pcie_mm_limit[4]; | ||
718 | } __packed; | ||
719 | |||
720 | struct rx_desc_88e { | ||
721 | u32 length:14; | ||
722 | u32 crc32:1; | ||
723 | u32 icverror:1; | ||
724 | u32 drv_infosize:4; | ||
725 | u32 security:3; | ||
726 | u32 qos:1; | ||
727 | u32 shift:2; | ||
728 | u32 phystatus:1; | ||
729 | u32 swdec:1; | ||
730 | u32 lastseg:1; | ||
731 | u32 firstseg:1; | ||
732 | u32 eor:1; | ||
733 | u32 own:1; | ||
734 | |||
735 | u32 macid:6; | ||
736 | u32 tid:4; | ||
737 | u32 hwrsvd:5; | ||
738 | u32 paggr:1; | ||
739 | u32 faggr:1; | ||
740 | u32 a1_fit:4; | ||
741 | u32 a2_fit:4; | ||
742 | u32 pam:1; | ||
743 | u32 pwr:1; | ||
744 | u32 moredata:1; | ||
745 | u32 morefrag:1; | ||
746 | u32 type:2; | ||
747 | u32 mc:1; | ||
748 | u32 bc:1; | ||
749 | |||
750 | u32 seq:12; | ||
751 | u32 frag:4; | ||
752 | u32 nextpktlen:14; | ||
753 | u32 nextind:1; | ||
754 | u32 rsvd:1; | ||
755 | |||
756 | u32 rxmcs:6; | ||
757 | u32 rxht:1; | ||
758 | u32 amsdu:1; | ||
759 | u32 splcp:1; | ||
760 | u32 bandwidth:1; | ||
761 | u32 htc:1; | ||
762 | u32 tcpchk_rpt:1; | ||
763 | u32 ipcchk_rpt:1; | ||
764 | u32 tcpchk_valid:1; | ||
765 | u32 hwpcerr:1; | ||
766 | u32 hwpcind:1; | ||
767 | u32 iv0:16; | ||
768 | |||
769 | u32 iv1; | ||
770 | |||
771 | u32 tsfl; | ||
772 | |||
773 | u32 bufferaddress; | ||
774 | u32 bufferaddress64; | ||
775 | |||
776 | } __packed; | ||
777 | |||
778 | void rtl88ee_tx_fill_desc(struct ieee80211_hw *hw, | ||
779 | struct ieee80211_hdr *hdr, u8 *pdesc_tx, | ||
780 | struct ieee80211_tx_info *info, | ||
781 | struct ieee80211_sta *sta, | ||
782 | struct sk_buff *skb, | ||
783 | u8 hw_queue, struct rtl_tcb_desc *ptcb_desc); | ||
784 | bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw, | ||
785 | struct rtl_stats *status, | ||
786 | struct ieee80211_rx_status *rx_status, | ||
787 | u8 *pdesc, struct sk_buff *skb); | ||
788 | void rtl88ee_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val); | ||
789 | u32 rtl88ee_get_desc(u8 *pdesc, bool istx, u8 desc_name); | ||
790 | void rtl88ee_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); | ||
791 | void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, | ||
792 | bool b_firstseg, bool b_lastseg, | ||
793 | struct sk_buff *skb); | ||
794 | |||
795 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c index b793a659a465..926e2a34c766 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c | |||
@@ -174,8 +174,8 @@ static void rtl92c_dm_diginit(struct ieee80211_hw *hw) | |||
174 | dm_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH; | 174 | dm_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH; |
175 | dm_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW; | 175 | dm_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW; |
176 | dm_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH; | 176 | dm_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH; |
177 | dm_digtable->rx_gain_range_max = DM_DIG_MAX; | 177 | dm_digtable->rx_gain_max = DM_DIG_MAX; |
178 | dm_digtable->rx_gain_range_min = DM_DIG_MIN; | 178 | dm_digtable->rx_gain_min = DM_DIG_MIN; |
179 | dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT; | 179 | dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT; |
180 | dm_digtable->back_range_max = DM_DIG_BACKOFF_MAX; | 180 | dm_digtable->back_range_max = DM_DIG_BACKOFF_MAX; |
181 | dm_digtable->back_range_min = DM_DIG_BACKOFF_MIN; | 181 | dm_digtable->back_range_min = DM_DIG_BACKOFF_MIN; |
@@ -300,11 +300,11 @@ static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw) | |||
300 | } | 300 | } |
301 | 301 | ||
302 | if ((digtable->rssi_val_min + 10 - digtable->back_val) > | 302 | if ((digtable->rssi_val_min + 10 - digtable->back_val) > |
303 | digtable->rx_gain_range_max) | 303 | digtable->rx_gain_max) |
304 | digtable->cur_igvalue = digtable->rx_gain_range_max; | 304 | digtable->cur_igvalue = digtable->rx_gain_max; |
305 | else if ((digtable->rssi_val_min + 10 - | 305 | else if ((digtable->rssi_val_min + 10 - |
306 | digtable->back_val) < digtable->rx_gain_range_min) | 306 | digtable->back_val) < digtable->rx_gain_min) |
307 | digtable->cur_igvalue = digtable->rx_gain_range_min; | 307 | digtable->cur_igvalue = digtable->rx_gain_min; |
308 | else | 308 | else |
309 | digtable->cur_igvalue = digtable->rssi_val_min + 10 - | 309 | digtable->cur_igvalue = digtable->rssi_val_min + 10 - |
310 | digtable->back_val; | 310 | digtable->back_val; |
@@ -1147,75 +1147,6 @@ void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) | |||
1147 | } | 1147 | } |
1148 | EXPORT_SYMBOL(rtl92c_dm_init_rate_adaptive_mask); | 1148 | EXPORT_SYMBOL(rtl92c_dm_init_rate_adaptive_mask); |
1149 | 1149 | ||
1150 | static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) | ||
1151 | { | ||
1152 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1153 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1154 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1155 | struct rate_adaptive *p_ra = &(rtlpriv->ra); | ||
1156 | u32 low_rssi_thresh, high_rssi_thresh; | ||
1157 | struct ieee80211_sta *sta = NULL; | ||
1158 | |||
1159 | if (is_hal_stop(rtlhal)) { | ||
1160 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
1161 | "<---- driver is going to unload\n"); | ||
1162 | return; | ||
1163 | } | ||
1164 | |||
1165 | if (!rtlpriv->dm.useramask) { | ||
1166 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
1167 | "<---- driver does not control rate adaptive mask\n"); | ||
1168 | return; | ||
1169 | } | ||
1170 | |||
1171 | if (mac->link_state == MAC80211_LINKED && | ||
1172 | mac->opmode == NL80211_IFTYPE_STATION) { | ||
1173 | switch (p_ra->pre_ratr_state) { | ||
1174 | case DM_RATR_STA_HIGH: | ||
1175 | high_rssi_thresh = 50; | ||
1176 | low_rssi_thresh = 20; | ||
1177 | break; | ||
1178 | case DM_RATR_STA_MIDDLE: | ||
1179 | high_rssi_thresh = 55; | ||
1180 | low_rssi_thresh = 20; | ||
1181 | break; | ||
1182 | case DM_RATR_STA_LOW: | ||
1183 | high_rssi_thresh = 50; | ||
1184 | low_rssi_thresh = 25; | ||
1185 | break; | ||
1186 | default: | ||
1187 | high_rssi_thresh = 50; | ||
1188 | low_rssi_thresh = 20; | ||
1189 | break; | ||
1190 | } | ||
1191 | |||
1192 | if (rtlpriv->dm.undec_sm_pwdb > (long)high_rssi_thresh) | ||
1193 | p_ra->ratr_state = DM_RATR_STA_HIGH; | ||
1194 | else if (rtlpriv->dm.undec_sm_pwdb > (long)low_rssi_thresh) | ||
1195 | p_ra->ratr_state = DM_RATR_STA_MIDDLE; | ||
1196 | else | ||
1197 | p_ra->ratr_state = DM_RATR_STA_LOW; | ||
1198 | |||
1199 | if (p_ra->pre_ratr_state != p_ra->ratr_state) { | ||
1200 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, "RSSI = %ld\n", | ||
1201 | rtlpriv->dm.undec_sm_pwdb); | ||
1202 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
1203 | "RSSI_LEVEL = %d\n", p_ra->ratr_state); | ||
1204 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
1205 | "PreState = %d, CurState = %d\n", | ||
1206 | p_ra->pre_ratr_state, p_ra->ratr_state); | ||
1207 | |||
1208 | rcu_read_lock(); | ||
1209 | sta = ieee80211_find_sta(mac->vif, mac->bssid); | ||
1210 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, | ||
1211 | p_ra->ratr_state); | ||
1212 | |||
1213 | p_ra->pre_ratr_state = p_ra->ratr_state; | ||
1214 | rcu_read_unlock(); | ||
1215 | } | ||
1216 | } | ||
1217 | } | ||
1218 | |||
1219 | static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw) | 1150 | static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw) |
1220 | { | 1151 | { |
1221 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1152 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -1437,6 +1368,9 @@ void rtl92c_dm_watchdog(struct ieee80211_hw *hw) | |||
1437 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, | 1368 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, |
1438 | (u8 *) (&fw_ps_awake)); | 1369 | (u8 *) (&fw_ps_awake)); |
1439 | 1370 | ||
1371 | if (ppsc->p2p_ps_info.p2p_ps_mode) | ||
1372 | fw_ps_awake = false; | ||
1373 | |||
1440 | if ((ppsc->rfpwr_state == ERFON) && ((!fw_current_inpsmode) && | 1374 | if ((ppsc->rfpwr_state == ERFON) && ((!fw_current_inpsmode) && |
1441 | fw_ps_awake) | 1375 | fw_ps_awake) |
1442 | && (!ppsc->rfchange_inprogress)) { | 1376 | && (!ppsc->rfchange_inprogress)) { |
@@ -1446,7 +1380,7 @@ void rtl92c_dm_watchdog(struct ieee80211_hw *hw) | |||
1446 | rtl92c_dm_dynamic_bb_powersaving(hw); | 1380 | rtl92c_dm_dynamic_bb_powersaving(hw); |
1447 | rtl92c_dm_dynamic_txpower(hw); | 1381 | rtl92c_dm_dynamic_txpower(hw); |
1448 | rtl92c_dm_check_txpower_tracking(hw); | 1382 | rtl92c_dm_check_txpower_tracking(hw); |
1449 | rtl92c_dm_refresh_rate_adaptive_mask(hw); | 1383 | /* rtl92c_dm_refresh_rate_adaptive_mask(hw); */ |
1450 | rtl92c_dm_bt_coexist(hw); | 1384 | rtl92c_dm_bt_coexist(hw); |
1451 | rtl92c_dm_check_edca_turbo(hw); | 1385 | rtl92c_dm_check_edca_turbo(hw); |
1452 | } | 1386 | } |
@@ -1651,7 +1585,7 @@ static void rtl92c_bt_set_normal(struct ieee80211_hw *hw) | |||
1651 | } | 1585 | } |
1652 | } | 1586 | } |
1653 | 1587 | ||
1654 | static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw) | 1588 | static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw, u8 tmp1byte) |
1655 | { | 1589 | { |
1656 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1590 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1657 | struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); | 1591 | struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); |
@@ -1673,9 +1607,9 @@ static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw) | |||
1673 | BT_RSSI_STATE_SPECIAL_LOW)) { | 1607 | BT_RSSI_STATE_SPECIAL_LOW)) { |
1674 | rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); | 1608 | rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); |
1675 | } else if (rtlpcipriv->bt_coexist.bt_service == BT_PAN) { | 1609 | } else if (rtlpcipriv->bt_coexist.bt_service == BT_PAN) { |
1676 | rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0x00); | 1610 | rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte); |
1677 | } else { | 1611 | } else { |
1678 | rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0x00); | 1612 | rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte); |
1679 | } | 1613 | } |
1680 | } | 1614 | } |
1681 | 1615 | ||
@@ -1726,12 +1660,17 @@ static void rtl92c_check_bt_change(struct ieee80211_hw *hw) | |||
1726 | { | 1660 | { |
1727 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1661 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1728 | struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); | 1662 | struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); |
1663 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1664 | u8 tmp1byte = 0; | ||
1729 | 1665 | ||
1666 | if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version) && | ||
1667 | rtlpcipriv->bt_coexist.bt_coexistence) | ||
1668 | tmp1byte |= BIT(5); | ||
1730 | if (rtlpcipriv->bt_coexist.bt_cur_state) { | 1669 | if (rtlpcipriv->bt_coexist.bt_cur_state) { |
1731 | if (rtlpcipriv->bt_coexist.bt_ant_isolation) | 1670 | if (rtlpcipriv->bt_coexist.bt_ant_isolation) |
1732 | rtl92c_bt_ant_isolation(hw); | 1671 | rtl92c_bt_ant_isolation(hw, tmp1byte); |
1733 | } else { | 1672 | } else { |
1734 | rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0x00); | 1673 | rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte); |
1735 | rtlpriv->cfg->ops->set_rfreg(hw, RF90_PATH_A, 0x1e, 0xf0, | 1674 | rtlpriv->cfg->ops->set_rfreg(hw, RF90_PATH_A, 0x1e, 0xf0, |
1736 | rtlpcipriv->bt_coexist.bt_rfreg_origin_1e); | 1675 | rtlpcipriv->bt_coexist.bt_rfreg_origin_1e); |
1737 | 1676 | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c index 883f23ae9519..04a41628ceed 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | |||
@@ -552,7 +552,9 @@ void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) | |||
552 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); | 552 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); |
553 | 553 | ||
554 | SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode); | 554 | SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode); |
555 | SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 1); | 555 | SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, |
556 | (rtlpriv->mac80211.p2p) ? | ||
557 | ppsc->smart_ps : 1); | ||
556 | SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode, | 558 | SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode, |
557 | ppsc->reg_max_lps_awakeintvl); | 559 | ppsc->reg_max_lps_awakeintvl); |
558 | 560 | ||
@@ -808,3 +810,98 @@ void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus) | |||
808 | rtl92c_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm); | 810 | rtl92c_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm); |
809 | } | 811 | } |
810 | EXPORT_SYMBOL(rtl92c_set_fw_joinbss_report_cmd); | 812 | EXPORT_SYMBOL(rtl92c_set_fw_joinbss_report_cmd); |
813 | |||
814 | static void rtl92c_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow) | ||
815 | { | ||
816 | u8 u1_ctwindow_period[1] = {ctwindow}; | ||
817 | |||
818 | rtl92c_fill_h2c_cmd(hw, H2C_P2P_PS_CTW_CMD, 1, u1_ctwindow_period); | ||
819 | } | ||
820 | |||
821 | void rtl92c_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) | ||
822 | { | ||
823 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
824 | struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); | ||
825 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
826 | struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info); | ||
827 | struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; | ||
828 | u8 i; | ||
829 | u16 ctwindow; | ||
830 | u32 start_time, tsf_low; | ||
831 | |||
832 | switch (p2p_ps_state) { | ||
833 | case P2P_PS_DISABLE: | ||
834 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n"); | ||
835 | memset(p2p_ps_offload, 0, sizeof(struct p2p_ps_offload_t)); | ||
836 | break; | ||
837 | case P2P_PS_ENABLE: | ||
838 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n"); | ||
839 | /* update CTWindow value. */ | ||
840 | if (p2pinfo->ctwindow > 0) { | ||
841 | p2p_ps_offload->ctwindow_en = 1; | ||
842 | ctwindow = p2pinfo->ctwindow; | ||
843 | rtl92c_set_p2p_ctw_period_cmd(hw, ctwindow); | ||
844 | } | ||
845 | /* hw only support 2 set of NoA */ | ||
846 | for (i = 0; i < p2pinfo->noa_num; i++) { | ||
847 | /* To control the register setting for which NOA*/ | ||
848 | rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); | ||
849 | if (i == 0) | ||
850 | p2p_ps_offload->noa0_en = 1; | ||
851 | else | ||
852 | p2p_ps_offload->noa1_en = 1; | ||
853 | |||
854 | /* config P2P NoA Descriptor Register */ | ||
855 | rtl_write_dword(rtlpriv, 0x5E0, | ||
856 | p2pinfo->noa_duration[i]); | ||
857 | rtl_write_dword(rtlpriv, 0x5E4, | ||
858 | p2pinfo->noa_interval[i]); | ||
859 | |||
860 | /*Get Current TSF value */ | ||
861 | tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); | ||
862 | |||
863 | start_time = p2pinfo->noa_start_time[i]; | ||
864 | if (p2pinfo->noa_count_type[i] != 1) { | ||
865 | while (start_time <= (tsf_low+(50*1024))) { | ||
866 | start_time += p2pinfo->noa_interval[i]; | ||
867 | if (p2pinfo->noa_count_type[i] != 255) | ||
868 | p2pinfo->noa_count_type[i]--; | ||
869 | } | ||
870 | } | ||
871 | rtl_write_dword(rtlpriv, 0x5E8, start_time); | ||
872 | rtl_write_dword(rtlpriv, 0x5EC, | ||
873 | p2pinfo->noa_count_type[i]); | ||
874 | } | ||
875 | |||
876 | if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) { | ||
877 | /* rst p2p circuit */ | ||
878 | rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); | ||
879 | |||
880 | p2p_ps_offload->offload_en = 1; | ||
881 | |||
882 | if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { | ||
883 | p2p_ps_offload->role = 1; | ||
884 | p2p_ps_offload->allstasleep = 0; | ||
885 | } else { | ||
886 | p2p_ps_offload->role = 0; | ||
887 | } | ||
888 | |||
889 | p2p_ps_offload->discovery = 0; | ||
890 | } | ||
891 | break; | ||
892 | case P2P_PS_SCAN: | ||
893 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n"); | ||
894 | p2p_ps_offload->discovery = 1; | ||
895 | break; | ||
896 | case P2P_PS_SCAN_DONE: | ||
897 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n"); | ||
898 | p2p_ps_offload->discovery = 0; | ||
899 | p2pinfo->p2p_ps_state = P2P_PS_ENABLE; | ||
900 | break; | ||
901 | default: | ||
902 | break; | ||
903 | } | ||
904 | |||
905 | rtl92c_fill_h2c_cmd(hw, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload); | ||
906 | } | ||
907 | EXPORT_SYMBOL_GPL(rtl92c_set_p2p_ps_offload_cmd); | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h index 780ea5b1e24c..15b2055e6212 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h +++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h | |||
@@ -67,6 +67,9 @@ enum rtl8192c_h2c_cmd { | |||
67 | H2C_RSVDPAGE = 3, | 67 | H2C_RSVDPAGE = 3, |
68 | H2C_RSSI_REPORT = 5, | 68 | H2C_RSSI_REPORT = 5, |
69 | H2C_RA_MASK = 6, | 69 | H2C_RA_MASK = 6, |
70 | H2C_MACID_PS_MODE = 7, | ||
71 | H2C_P2P_PS_OFFLOAD = 8, | ||
72 | H2C_P2P_PS_CTW_CMD = 32, | ||
70 | MAX_H2CCMD | 73 | MAX_H2CCMD |
71 | }; | 74 | }; |
72 | 75 | ||
@@ -95,5 +98,6 @@ void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); | |||
95 | void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); | 98 | void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); |
96 | void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); | 99 | void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); |
97 | void usb_writeN_async(struct rtl_priv *rtlpriv, u32 addr, void *data, u16 len); | 100 | void usb_writeN_async(struct rtl_priv *rtlpriv, u32 addr, void *data, u16 len); |
101 | void rtl92c_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state); | ||
98 | 102 | ||
99 | #endif | 103 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index 1b65db7fd651..a82b30a1996c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c | |||
@@ -475,6 +475,9 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | |||
475 | 475 | ||
476 | break; | 476 | break; |
477 | } | 477 | } |
478 | case HW_VAR_H2C_FW_P2P_PS_OFFLOAD: | ||
479 | rtl92c_set_p2p_ps_offload_cmd(hw, (*(u8 *)val)); | ||
480 | break; | ||
478 | case HW_VAR_AID:{ | 481 | case HW_VAR_AID:{ |
479 | u16 u2btmp; | 482 | u16 u2btmp; |
480 | u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); | 483 | u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); |
@@ -505,6 +508,40 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | |||
505 | break; | 508 | break; |
506 | 509 | ||
507 | } | 510 | } |
511 | case HW_VAR_FW_LPS_ACTION: { | ||
512 | bool enter_fwlps = *((bool *)val); | ||
513 | u8 rpwm_val, fw_pwrmode; | ||
514 | bool fw_current_inps; | ||
515 | |||
516 | if (enter_fwlps) { | ||
517 | rpwm_val = 0x02; /* RF off */ | ||
518 | fw_current_inps = true; | ||
519 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
520 | HW_VAR_FW_PSMODE_STATUS, | ||
521 | (u8 *)(&fw_current_inps)); | ||
522 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
523 | HW_VAR_H2C_FW_PWRMODE, | ||
524 | (u8 *)(&ppsc->fwctrl_psmode)); | ||
525 | |||
526 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
527 | HW_VAR_SET_RPWM, | ||
528 | (u8 *)(&rpwm_val)); | ||
529 | } else { | ||
530 | rpwm_val = 0x0C; /* RF on */ | ||
531 | fw_pwrmode = FW_PS_ACTIVE_MODE; | ||
532 | fw_current_inps = false; | ||
533 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
534 | HW_VAR_SET_RPWM, | ||
535 | (u8 *)(&rpwm_val)); | ||
536 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
537 | HW_VAR_H2C_FW_PWRMODE, | ||
538 | (u8 *)(&fw_pwrmode)); | ||
539 | |||
540 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
541 | HW_VAR_FW_PSMODE_STATUS, | ||
542 | (u8 *)(&fw_current_inps)); | ||
543 | } | ||
544 | break; } | ||
508 | default: | 545 | default: |
509 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 546 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
510 | "switch case not processed\n"); | 547 | "switch case not processed\n"); |
@@ -1105,7 +1142,8 @@ static int _rtl92ce_set_media_status(struct ieee80211_hw *hw, | |||
1105 | type == NL80211_IFTYPE_STATION) { | 1142 | type == NL80211_IFTYPE_STATION) { |
1106 | _rtl92ce_stop_tx_beacon(hw); | 1143 | _rtl92ce_stop_tx_beacon(hw); |
1107 | _rtl92ce_enable_bcn_sub_func(hw); | 1144 | _rtl92ce_enable_bcn_sub_func(hw); |
1108 | } else if (type == NL80211_IFTYPE_ADHOC || type == NL80211_IFTYPE_AP) { | 1145 | } else if (type == NL80211_IFTYPE_ADHOC || type == NL80211_IFTYPE_AP || |
1146 | type == NL80211_IFTYPE_MESH_POINT) { | ||
1109 | _rtl92ce_resume_tx_beacon(hw); | 1147 | _rtl92ce_resume_tx_beacon(hw); |
1110 | _rtl92ce_disable_bcn_sub_func(hw); | 1148 | _rtl92ce_disable_bcn_sub_func(hw); |
1111 | } else { | 1149 | } else { |
@@ -1137,6 +1175,11 @@ static int _rtl92ce_set_media_status(struct ieee80211_hw *hw, | |||
1137 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | 1175 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
1138 | "Set Network type to AP!\n"); | 1176 | "Set Network type to AP!\n"); |
1139 | break; | 1177 | break; |
1178 | case NL80211_IFTYPE_MESH_POINT: | ||
1179 | bt_msr |= MSR_ADHOC; | ||
1180 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1181 | "Set Network type to Mesh Point!\n"); | ||
1182 | break; | ||
1140 | default: | 1183 | default: |
1141 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 1184 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
1142 | "Network type %d not supported!\n", type); | 1185 | "Network type %d not supported!\n", type); |
@@ -1184,7 +1227,8 @@ int rtl92ce_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) | |||
1184 | return -EOPNOTSUPP; | 1227 | return -EOPNOTSUPP; |
1185 | 1228 | ||
1186 | if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { | 1229 | if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { |
1187 | if (type != NL80211_IFTYPE_AP) | 1230 | if (type != NL80211_IFTYPE_AP && |
1231 | type != NL80211_IFTYPE_MESH_POINT) | ||
1188 | rtl92ce_set_check_bssid(hw, true); | 1232 | rtl92ce_set_check_bssid(hw, true); |
1189 | } else { | 1233 | } else { |
1190 | rtl92ce_set_check_bssid(hw, false); | 1234 | rtl92ce_set_check_bssid(hw, false); |
@@ -1459,7 +1503,7 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
1459 | } | 1503 | } |
1460 | 1504 | ||
1461 | for (i = 0; i < 14; i++) { | 1505 | for (i = 0; i < 14; i++) { |
1462 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1506 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1463 | "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n", | 1507 | "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n", |
1464 | rf_path, i, | 1508 | rf_path, i, |
1465 | rtlefuse->txpwrlevel_cck[rf_path][i], | 1509 | rtlefuse->txpwrlevel_cck[rf_path][i], |
@@ -1500,11 +1544,11 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
1500 | & 0xf0) >> 4); | 1544 | & 0xf0) >> 4); |
1501 | } | 1545 | } |
1502 | 1546 | ||
1503 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1547 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1504 | "RF-%d pwrgroup_ht20[%d] = 0x%x\n", | 1548 | "RF-%d pwrgroup_ht20[%d] = 0x%x\n", |
1505 | rf_path, i, | 1549 | rf_path, i, |
1506 | rtlefuse->pwrgroup_ht20[rf_path][i]); | 1550 | rtlefuse->pwrgroup_ht20[rf_path][i]); |
1507 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1551 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1508 | "RF-%d pwrgroup_ht40[%d] = 0x%x\n", | 1552 | "RF-%d pwrgroup_ht40[%d] = 0x%x\n", |
1509 | rf_path, i, | 1553 | rf_path, i, |
1510 | rtlefuse->pwrgroup_ht40[rf_path][i]); | 1554 | rtlefuse->pwrgroup_ht40[rf_path][i]); |
@@ -1545,19 +1589,19 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
1545 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7]; | 1589 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7]; |
1546 | 1590 | ||
1547 | for (i = 0; i < 14; i++) | 1591 | for (i = 0; i < 14; i++) |
1548 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1592 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1549 | "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", | 1593 | "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", |
1550 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); | 1594 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); |
1551 | for (i = 0; i < 14; i++) | 1595 | for (i = 0; i < 14; i++) |
1552 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1596 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1553 | "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", | 1597 | "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", |
1554 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); | 1598 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); |
1555 | for (i = 0; i < 14; i++) | 1599 | for (i = 0; i < 14; i++) |
1556 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1600 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1557 | "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", | 1601 | "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", |
1558 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); | 1602 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); |
1559 | for (i = 0; i < 14; i++) | 1603 | for (i = 0; i < 14; i++) |
1560 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1604 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1561 | "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", | 1605 | "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", |
1562 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); | 1606 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); |
1563 | 1607 | ||
@@ -1565,7 +1609,7 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
1565 | rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7); | 1609 | rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7); |
1566 | else | 1610 | else |
1567 | rtlefuse->eeprom_regulatory = 0; | 1611 | rtlefuse->eeprom_regulatory = 0; |
1568 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1612 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1569 | "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); | 1613 | "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); |
1570 | 1614 | ||
1571 | if (!autoload_fail) { | 1615 | if (!autoload_fail) { |
@@ -1575,7 +1619,7 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
1575 | rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI; | 1619 | rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI; |
1576 | rtlefuse->eeprom_tssi[RF90_PATH_B] = EEPROM_DEFAULT_TSSI; | 1620 | rtlefuse->eeprom_tssi[RF90_PATH_B] = EEPROM_DEFAULT_TSSI; |
1577 | } | 1621 | } |
1578 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, "TSSI_A = 0x%x, TSSI_B = 0x%x\n", | 1622 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, "TSSI_A = 0x%x, TSSI_B = 0x%x\n", |
1579 | rtlefuse->eeprom_tssi[RF90_PATH_A], | 1623 | rtlefuse->eeprom_tssi[RF90_PATH_A], |
1580 | rtlefuse->eeprom_tssi[RF90_PATH_B]); | 1624 | rtlefuse->eeprom_tssi[RF90_PATH_B]); |
1581 | 1625 | ||
@@ -1589,7 +1633,7 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
1589 | rtlefuse->apk_thermalmeterignore = true; | 1633 | rtlefuse->apk_thermalmeterignore = true; |
1590 | 1634 | ||
1591 | rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; | 1635 | rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; |
1592 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1636 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1593 | "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); | 1637 | "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); |
1594 | } | 1638 | } |
1595 | 1639 | ||
@@ -1629,6 +1673,21 @@ static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw) | |||
1629 | if (rtlefuse->autoload_failflag) | 1673 | if (rtlefuse->autoload_failflag) |
1630 | return; | 1674 | return; |
1631 | 1675 | ||
1676 | rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; | ||
1677 | rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; | ||
1678 | rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; | ||
1679 | rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; | ||
1680 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1681 | "EEPROMId = 0x%4x\n", eeprom_id); | ||
1682 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1683 | "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid); | ||
1684 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1685 | "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did); | ||
1686 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1687 | "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid); | ||
1688 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1689 | "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid); | ||
1690 | |||
1632 | for (i = 0; i < 6; i += 2) { | 1691 | for (i = 0; i < 6; i += 2) { |
1633 | usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; | 1692 | usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; |
1634 | *((u16 *) (&rtlefuse->dev_addr[i])) = usvalue; | 1693 | *((u16 *) (&rtlefuse->dev_addr[i])) = usvalue; |
@@ -1766,6 +1825,9 @@ static void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw, | |||
1766 | ratr_value = sta->supp_rates[1] << 4; | 1825 | ratr_value = sta->supp_rates[1] << 4; |
1767 | else | 1826 | else |
1768 | ratr_value = sta->supp_rates[0]; | 1827 | ratr_value = sta->supp_rates[0]; |
1828 | if (mac->opmode == NL80211_IFTYPE_ADHOC) | ||
1829 | ratr_value = 0xfff; | ||
1830 | |||
1769 | ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | | 1831 | ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | |
1770 | sta->ht_cap.mcs.rx_mask[0] << 12); | 1832 | sta->ht_cap.mcs.rx_mask[0] << 12); |
1771 | switch (wirelessmode) { | 1833 | switch (wirelessmode) { |
@@ -1860,7 +1922,8 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, | |||
1860 | 1922 | ||
1861 | sta_entry = (struct rtl_sta_info *) sta->drv_priv; | 1923 | sta_entry = (struct rtl_sta_info *) sta->drv_priv; |
1862 | wirelessmode = sta_entry->wireless_mode; | 1924 | wirelessmode = sta_entry->wireless_mode; |
1863 | if (mac->opmode == NL80211_IFTYPE_STATION) | 1925 | if (mac->opmode == NL80211_IFTYPE_STATION || |
1926 | mac->opmode == NL80211_IFTYPE_MESH_POINT) | ||
1864 | curtxbw_40mhz = mac->bw_40; | 1927 | curtxbw_40mhz = mac->bw_40; |
1865 | else if (mac->opmode == NL80211_IFTYPE_AP || | 1928 | else if (mac->opmode == NL80211_IFTYPE_AP || |
1866 | mac->opmode == NL80211_IFTYPE_ADHOC) | 1929 | mac->opmode == NL80211_IFTYPE_ADHOC) |
@@ -1870,6 +1933,8 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, | |||
1870 | ratr_bitmap = sta->supp_rates[1] << 4; | 1933 | ratr_bitmap = sta->supp_rates[1] << 4; |
1871 | else | 1934 | else |
1872 | ratr_bitmap = sta->supp_rates[0]; | 1935 | ratr_bitmap = sta->supp_rates[0]; |
1936 | if (mac->opmode == NL80211_IFTYPE_ADHOC) | ||
1937 | ratr_bitmap = 0xfff; | ||
1873 | ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | | 1938 | ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | |
1874 | sta->ht_cap.mcs.rx_mask[0] << 12); | 1939 | sta->ht_cap.mcs.rx_mask[0] << 12); |
1875 | switch (wirelessmode) { | 1940 | switch (wirelessmode) { |
@@ -2135,7 +2200,8 @@ void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index, | |||
2135 | macaddr = cam_const_broad; | 2200 | macaddr = cam_const_broad; |
2136 | entry_id = key_index; | 2201 | entry_id = key_index; |
2137 | } else { | 2202 | } else { |
2138 | if (mac->opmode == NL80211_IFTYPE_AP) { | 2203 | if (mac->opmode == NL80211_IFTYPE_AP || |
2204 | mac->opmode == NL80211_IFTYPE_MESH_POINT) { | ||
2139 | entry_id = rtl_cam_get_free_entry(hw, | 2205 | entry_id = rtl_cam_get_free_entry(hw, |
2140 | p_macaddr); | 2206 | p_macaddr); |
2141 | if (entry_id >= TOTAL_CAM_ENTRY) { | 2207 | if (entry_id >= TOTAL_CAM_ENTRY) { |
@@ -2157,7 +2223,8 @@ void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index, | |||
2157 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | 2223 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, |
2158 | "delete one entry, entry_id is %d\n", | 2224 | "delete one entry, entry_id is %d\n", |
2159 | entry_id); | 2225 | entry_id); |
2160 | if (mac->opmode == NL80211_IFTYPE_AP) | 2226 | if (mac->opmode == NL80211_IFTYPE_AP || |
2227 | mac->opmode == NL80211_IFTYPE_MESH_POINT) | ||
2161 | rtl_cam_del_entry(hw, p_macaddr); | 2228 | rtl_cam_del_entry(hw, p_macaddr); |
2162 | rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); | 2229 | rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); |
2163 | } else { | 2230 | } else { |
@@ -2338,3 +2405,24 @@ void rtl92ce_suspend(struct ieee80211_hw *hw) | |||
2338 | void rtl92ce_resume(struct ieee80211_hw *hw) | 2405 | void rtl92ce_resume(struct ieee80211_hw *hw) |
2339 | { | 2406 | { |
2340 | } | 2407 | } |
2408 | |||
2409 | /* Turn on AAP (RCR:bit 0) for promicuous mode. */ | ||
2410 | void rtl92ce_allow_all_destaddr(struct ieee80211_hw *hw, | ||
2411 | bool allow_all_da, bool write_into_reg) | ||
2412 | { | ||
2413 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2414 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
2415 | |||
2416 | if (allow_all_da) {/* Set BIT0 */ | ||
2417 | rtlpci->receive_config |= RCR_AAP; | ||
2418 | } else {/* Clear BIT0 */ | ||
2419 | rtlpci->receive_config &= ~RCR_AAP; | ||
2420 | } | ||
2421 | |||
2422 | if (write_into_reg) | ||
2423 | rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); | ||
2424 | |||
2425 | RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD, | ||
2426 | "receive_config=0x%08X, write_into_reg=%d\n", | ||
2427 | rtlpci->receive_config, write_into_reg); | ||
2428 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h index 52a3aea9b3de..2d063b0c7760 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h | |||
@@ -61,6 +61,8 @@ void rtl92ce_update_interrupt_mask(struct ieee80211_hw *hw, | |||
61 | void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); | 61 | void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); |
62 | void rtl92ce_update_hal_rate_tbl(struct ieee80211_hw *hw, | 62 | void rtl92ce_update_hal_rate_tbl(struct ieee80211_hw *hw, |
63 | struct ieee80211_sta *sta, u8 rssi_level); | 63 | struct ieee80211_sta *sta, u8 rssi_level); |
64 | void rtl92ce_update_hal_rate_tbl(struct ieee80211_hw *hw, | ||
65 | struct ieee80211_sta *sta, u8 rssi_level); | ||
64 | void rtl92ce_update_channel_access_setting(struct ieee80211_hw *hw); | 66 | void rtl92ce_update_channel_access_setting(struct ieee80211_hw *hw); |
65 | bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); | 67 | bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); |
66 | void rtl92ce_enable_hw_security_config(struct ieee80211_hw *hw); | 68 | void rtl92ce_enable_hw_security_config(struct ieee80211_hw *hw); |
@@ -74,5 +76,7 @@ void rtl8192ce_bt_reg_init(struct ieee80211_hw *hw); | |||
74 | void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw); | 76 | void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw); |
75 | void rtl92ce_suspend(struct ieee80211_hw *hw); | 77 | void rtl92ce_suspend(struct ieee80211_hw *hw); |
76 | void rtl92ce_resume(struct ieee80211_hw *hw); | 78 | void rtl92ce_resume(struct ieee80211_hw *hw); |
79 | void rtl92ce_allow_all_destaddr(struct ieee80211_hw *hw, | ||
80 | bool allow_all_da, bool write_into_reg); | ||
77 | 81 | ||
78 | #endif | 82 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h index e4d738f6166d..bd4aef74c056 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h | |||
@@ -544,6 +544,7 @@ | |||
544 | #define IMR_WLANOFF BIT(0) | 544 | #define IMR_WLANOFF BIT(0) |
545 | 545 | ||
546 | #define EFUSE_REAL_CONTENT_LEN 512 | 546 | #define EFUSE_REAL_CONTENT_LEN 512 |
547 | #define EFUSE_OOB_PROTECT_BYTES 15 | ||
547 | 548 | ||
548 | #define EEPROM_DEFAULT_TSSI 0x0 | 549 | #define EEPROM_DEFAULT_TSSI 0x0 |
549 | #define EEPROM_DEFAULT_TXPOWERDIFF 0x0 | 550 | #define EEPROM_DEFAULT_TXPOWERDIFF 0x0 |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 49f663bd93ff..14203561b6ee 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | |||
@@ -228,6 +228,7 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = { | |||
228 | .enable_hw_sec = rtl92ce_enable_hw_security_config, | 228 | .enable_hw_sec = rtl92ce_enable_hw_security_config, |
229 | .set_key = rtl92ce_set_key, | 229 | .set_key = rtl92ce_set_key, |
230 | .init_sw_leds = rtl92ce_init_sw_leds, | 230 | .init_sw_leds = rtl92ce_init_sw_leds, |
231 | .allow_all_destaddr = rtl92ce_allow_all_destaddr, | ||
231 | .get_bbreg = rtl92c_phy_query_bb_reg, | 232 | .get_bbreg = rtl92c_phy_query_bb_reg, |
232 | .set_bbreg = rtl92c_phy_set_bb_reg, | 233 | .set_bbreg = rtl92c_phy_set_bb_reg, |
233 | .set_rfreg = rtl92ce_phy_set_rf_reg, | 234 | .set_rfreg = rtl92ce_phy_set_rf_reg, |
@@ -278,6 +279,7 @@ static struct rtl_hal_cfg rtl92ce_hal_cfg = { | |||
278 | .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, | 279 | .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, |
279 | .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, | 280 | .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, |
280 | .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, | 281 | .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, |
282 | .maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES, | ||
281 | 283 | ||
282 | .maps[RWCAM] = REG_CAMCMD, | 284 | .maps[RWCAM] = REG_CAMCMD, |
283 | .maps[WCAMI] = REG_CAMWRITE, | 285 | .maps[WCAMI] = REG_CAMWRITE, |
@@ -309,7 +311,7 @@ static struct rtl_hal_cfg rtl92ce_hal_cfg = { | |||
309 | 311 | ||
310 | .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, | 312 | .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, |
311 | .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, | 313 | .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, |
312 | .maps[RTL_IMR_BcnInt] = IMR_BCNINT, | 314 | .maps[RTL_IMR_BCNINT] = IMR_BCNINT, |
313 | .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, | 315 | .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, |
314 | .maps[RTL_IMR_RDU] = IMR_RDU, | 316 | .maps[RTL_IMR_RDU] = IMR_RDU, |
315 | .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, | 317 | .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c index b9b1a6e0b16e..65bf5fb97002 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "../wifi.h" | 30 | #include "../wifi.h" |
31 | #include "../pci.h" | 31 | #include "../pci.h" |
32 | #include "../base.h" | 32 | #include "../base.h" |
33 | #include "../stats.h" | ||
33 | #include "reg.h" | 34 | #include "reg.h" |
34 | #include "def.h" | 35 | #include "def.h" |
35 | #include "phy.h" | 36 | #include "phy.h" |
@@ -42,7 +43,7 @@ static u8 _rtl92ce_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) | |||
42 | 43 | ||
43 | if (unlikely(ieee80211_is_beacon(fc))) | 44 | if (unlikely(ieee80211_is_beacon(fc))) |
44 | return QSLT_BEACON; | 45 | return QSLT_BEACON; |
45 | if (ieee80211_is_mgmt(fc)) | 46 | if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) |
46 | return QSLT_MGNT; | 47 | return QSLT_MGNT; |
47 | 48 | ||
48 | return skb->priority; | 49 | return skb->priority; |
@@ -78,16 +79,6 @@ static u8 _rtl92c_evm_db_to_percentage(char value) | |||
78 | return ret_val; | 79 | return ret_val; |
79 | } | 80 | } |
80 | 81 | ||
81 | static long _rtl92ce_translate_todbm(struct ieee80211_hw *hw, | ||
82 | u8 signal_strength_index) | ||
83 | { | ||
84 | long signal_power; | ||
85 | |||
86 | signal_power = (long)((signal_strength_index + 1) >> 1); | ||
87 | signal_power -= 95; | ||
88 | return signal_power; | ||
89 | } | ||
90 | |||
91 | static long _rtl92ce_signal_scale_mapping(struct ieee80211_hw *hw, | 82 | static long _rtl92ce_signal_scale_mapping(struct ieee80211_hw *hw, |
92 | long currsig) | 83 | long currsig) |
93 | { | 84 | { |
@@ -139,7 +130,6 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, | |||
139 | pstats->packet_toself = packet_toself; | 130 | pstats->packet_toself = packet_toself; |
140 | pstats->is_cck = is_cck_rate; | 131 | pstats->is_cck = is_cck_rate; |
141 | pstats->packet_beacon = packet_beacon; | 132 | pstats->packet_beacon = packet_beacon; |
142 | pstats->is_cck = is_cck_rate; | ||
143 | pstats->rx_mimo_sig_qual[0] = -1; | 133 | pstats->rx_mimo_sig_qual[0] = -1; |
144 | pstats->rx_mimo_sig_qual[1] = -1; | 134 | pstats->rx_mimo_sig_qual[1] = -1; |
145 | 135 | ||
@@ -192,10 +182,30 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, | |||
192 | } | 182 | } |
193 | } | 183 | } |
194 | 184 | ||
195 | pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all); | 185 | pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); |
186 | /* CCK gain is smaller than OFDM/MCS gain, | ||
187 | * so we add gain diff by experiences, | ||
188 | * the val is 6 | ||
189 | */ | ||
190 | pwdb_all += 6; | ||
191 | if (pwdb_all > 100) | ||
192 | pwdb_all = 100; | ||
193 | /* modify the offset to make the same | ||
194 | * gain index with OFDM. | ||
195 | */ | ||
196 | if (pwdb_all > 34 && pwdb_all <= 42) | ||
197 | pwdb_all -= 2; | ||
198 | else if (pwdb_all > 26 && pwdb_all <= 34) | ||
199 | pwdb_all -= 6; | ||
200 | else if (pwdb_all > 14 && pwdb_all <= 26) | ||
201 | pwdb_all -= 8; | ||
202 | else if (pwdb_all > 4 && pwdb_all <= 14) | ||
203 | pwdb_all -= 4; | ||
204 | |||
196 | pstats->rx_pwdb_all = pwdb_all; | 205 | pstats->rx_pwdb_all = pwdb_all; |
197 | pstats->recvsignalpower = rx_pwr_all; | 206 | pstats->recvsignalpower = rx_pwr_all; |
198 | 207 | ||
208 | /* (3) Get Signal Quality (EVM) */ | ||
199 | if (packet_match_bssid) { | 209 | if (packet_match_bssid) { |
200 | u8 sq; | 210 | u8 sq; |
201 | if (pstats->rx_pwdb_all > 40) | 211 | if (pstats->rx_pwdb_all > 40) |
@@ -217,29 +227,38 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, | |||
217 | } else { | 227 | } else { |
218 | rtlpriv->dm.rfpath_rxenable[0] = | 228 | rtlpriv->dm.rfpath_rxenable[0] = |
219 | rtlpriv->dm.rfpath_rxenable[1] = true; | 229 | rtlpriv->dm.rfpath_rxenable[1] = true; |
230 | /* (1)Get RSSI for HT rate */ | ||
220 | for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) { | 231 | for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) { |
232 | /* we will judge RF RX path now. */ | ||
221 | if (rtlpriv->dm.rfpath_rxenable[i]) | 233 | if (rtlpriv->dm.rfpath_rxenable[i]) |
222 | rf_rx_num++; | 234 | rf_rx_num++; |
223 | 235 | ||
224 | rx_pwr[i] = | 236 | rx_pwr[i] = |
225 | ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) - 110; | 237 | ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) - 110; |
238 | /* Translate DBM to percentage. */ | ||
226 | rssi = _rtl92c_query_rxpwrpercentage(rx_pwr[i]); | 239 | rssi = _rtl92c_query_rxpwrpercentage(rx_pwr[i]); |
227 | total_rssi += rssi; | 240 | total_rssi += rssi; |
241 | /* Get Rx snr value in DB */ | ||
228 | rtlpriv->stats.rx_snr_db[i] = | 242 | rtlpriv->stats.rx_snr_db[i] = |
229 | (long)(p_drvinfo->rxsnr[i] / 2); | 243 | (long)(p_drvinfo->rxsnr[i] / 2); |
230 | 244 | ||
245 | /* Record Signal Strength for next packet */ | ||
231 | if (packet_match_bssid) | 246 | if (packet_match_bssid) |
232 | pstats->rx_mimo_signalstrength[i] = (u8) rssi; | 247 | pstats->rx_mimo_signalstrength[i] = (u8) rssi; |
233 | } | 248 | } |
234 | 249 | ||
250 | /* (2)PWDB, Average PWDB cacluated by | ||
251 | * hardware (for rate adaptive) | ||
252 | */ | ||
235 | rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; | 253 | rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; |
236 | pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all); | 254 | pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all); |
237 | pstats->rx_pwdb_all = pwdb_all; | 255 | pstats->rx_pwdb_all = pwdb_all; |
238 | pstats->rxpower = rx_pwr_all; | 256 | pstats->rxpower = rx_pwr_all; |
239 | pstats->recvsignalpower = rx_pwr_all; | 257 | pstats->recvsignalpower = rx_pwr_all; |
240 | 258 | ||
241 | if (pdesc->rxht && pdesc->rxmcs >= DESC92_RATEMCS8 && | 259 | /* (3)EVM of HT rate */ |
242 | pdesc->rxmcs <= DESC92_RATEMCS15) | 260 | if (pstats->is_ht && pstats->rate >= DESC92_RATEMCS8 && |
261 | pstats->rate <= DESC92_RATEMCS15) | ||
243 | max_spatial_stream = 2; | 262 | max_spatial_stream = 2; |
244 | else | 263 | else |
245 | max_spatial_stream = 1; | 264 | max_spatial_stream = 1; |
@@ -248,6 +267,9 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, | |||
248 | evm = _rtl92c_evm_db_to_percentage(p_drvinfo->rxevm[i]); | 267 | evm = _rtl92c_evm_db_to_percentage(p_drvinfo->rxevm[i]); |
249 | 268 | ||
250 | if (packet_match_bssid) { | 269 | if (packet_match_bssid) { |
270 | /* Fill value in RFD, Get the first | ||
271 | * spatial stream only | ||
272 | */ | ||
251 | if (i == 0) | 273 | if (i == 0) |
252 | pstats->signalquality = | 274 | pstats->signalquality = |
253 | (u8) (evm & 0xff); | 275 | (u8) (evm & 0xff); |
@@ -256,6 +278,9 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, | |||
256 | } | 278 | } |
257 | } | 279 | } |
258 | 280 | ||
281 | /* UI BSS List signal strength(in percentage), | ||
282 | * make it good looking, from 0~100. | ||
283 | */ | ||
259 | if (is_cck_rate) | 284 | if (is_cck_rate) |
260 | pstats->signalstrength = | 285 | pstats->signalstrength = |
261 | (u8) (_rtl92ce_signal_scale_mapping(hw, pwdb_all)); | 286 | (u8) (_rtl92ce_signal_scale_mapping(hw, pwdb_all)); |
@@ -265,215 +290,6 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, | |||
265 | (hw, total_rssi /= rf_rx_num)); | 290 | (hw, total_rssi /= rf_rx_num)); |
266 | } | 291 | } |
267 | 292 | ||
268 | static void _rtl92ce_process_ui_rssi(struct ieee80211_hw *hw, | ||
269 | struct rtl_stats *pstats) | ||
270 | { | ||
271 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
272 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
273 | u8 rfpath; | ||
274 | u32 last_rssi, tmpval; | ||
275 | |||
276 | if (pstats->packet_toself || pstats->packet_beacon) { | ||
277 | rtlpriv->stats.rssi_calculate_cnt++; | ||
278 | |||
279 | if (rtlpriv->stats.ui_rssi.total_num++ >= | ||
280 | PHY_RSSI_SLID_WIN_MAX) { | ||
281 | |||
282 | rtlpriv->stats.ui_rssi.total_num = | ||
283 | PHY_RSSI_SLID_WIN_MAX; | ||
284 | last_rssi = | ||
285 | rtlpriv->stats.ui_rssi.elements[rtlpriv-> | ||
286 | stats.ui_rssi.index]; | ||
287 | rtlpriv->stats.ui_rssi.total_val -= last_rssi; | ||
288 | } | ||
289 | |||
290 | rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength; | ||
291 | rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi. | ||
292 | index++] = | ||
293 | pstats->signalstrength; | ||
294 | |||
295 | if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX) | ||
296 | rtlpriv->stats.ui_rssi.index = 0; | ||
297 | |||
298 | tmpval = rtlpriv->stats.ui_rssi.total_val / | ||
299 | rtlpriv->stats.ui_rssi.total_num; | ||
300 | rtlpriv->stats.signal_strength = | ||
301 | _rtl92ce_translate_todbm(hw, (u8) tmpval); | ||
302 | pstats->rssi = rtlpriv->stats.signal_strength; | ||
303 | } | ||
304 | |||
305 | if (!pstats->is_cck && pstats->packet_toself) { | ||
306 | for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; | ||
307 | rfpath++) { | ||
308 | if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) { | ||
309 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
310 | pstats->rx_mimo_signalstrength[rfpath]; | ||
311 | |||
312 | } | ||
313 | |||
314 | if (pstats->rx_mimo_signalstrength[rfpath] > | ||
315 | rtlpriv->stats.rx_rssi_percentage[rfpath]) { | ||
316 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
317 | ((rtlpriv->stats. | ||
318 | rx_rssi_percentage[rfpath] * | ||
319 | (RX_SMOOTH_FACTOR - 1)) + | ||
320 | (pstats->rx_mimo_signalstrength[rfpath])) / | ||
321 | (RX_SMOOTH_FACTOR); | ||
322 | |||
323 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
324 | rtlpriv->stats.rx_rssi_percentage[rfpath] + | ||
325 | 1; | ||
326 | } else { | ||
327 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
328 | ((rtlpriv->stats. | ||
329 | rx_rssi_percentage[rfpath] * | ||
330 | (RX_SMOOTH_FACTOR - 1)) + | ||
331 | (pstats->rx_mimo_signalstrength[rfpath])) / | ||
332 | (RX_SMOOTH_FACTOR); | ||
333 | } | ||
334 | |||
335 | } | ||
336 | } | ||
337 | } | ||
338 | |||
339 | static void _rtl92ce_update_rxsignalstatistics(struct ieee80211_hw *hw, | ||
340 | struct rtl_stats *pstats) | ||
341 | { | ||
342 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
343 | int weighting = 0; | ||
344 | |||
345 | if (rtlpriv->stats.recv_signal_power == 0) | ||
346 | rtlpriv->stats.recv_signal_power = pstats->recvsignalpower; | ||
347 | |||
348 | if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power) | ||
349 | weighting = 5; | ||
350 | |||
351 | else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power) | ||
352 | weighting = (-5); | ||
353 | |||
354 | rtlpriv->stats.recv_signal_power = | ||
355 | (rtlpriv->stats.recv_signal_power * 5 + | ||
356 | pstats->recvsignalpower + weighting) / 6; | ||
357 | } | ||
358 | |||
359 | static void _rtl92ce_process_pwdb(struct ieee80211_hw *hw, | ||
360 | struct rtl_stats *pstats) | ||
361 | { | ||
362 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
363 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
364 | long undec_sm_pwdb; | ||
365 | |||
366 | if (mac->opmode == NL80211_IFTYPE_ADHOC) { | ||
367 | return; | ||
368 | } else { | ||
369 | undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; | ||
370 | } | ||
371 | |||
372 | if (pstats->packet_toself || pstats->packet_beacon) { | ||
373 | if (undec_sm_pwdb < 0) | ||
374 | undec_sm_pwdb = pstats->rx_pwdb_all; | ||
375 | |||
376 | if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) { | ||
377 | undec_sm_pwdb = (((undec_sm_pwdb) * | ||
378 | (RX_SMOOTH_FACTOR - 1)) + | ||
379 | (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); | ||
380 | |||
381 | undec_sm_pwdb += 1; | ||
382 | } else { | ||
383 | undec_sm_pwdb = (((undec_sm_pwdb) * | ||
384 | (RX_SMOOTH_FACTOR - 1)) + | ||
385 | (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); | ||
386 | } | ||
387 | |||
388 | rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb; | ||
389 | _rtl92ce_update_rxsignalstatistics(hw, pstats); | ||
390 | } | ||
391 | } | ||
392 | |||
393 | static void _rtl92ce_process_ui_link_quality(struct ieee80211_hw *hw, | ||
394 | struct rtl_stats *pstats) | ||
395 | { | ||
396 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
397 | u32 last_evm, n_spatialstream, tmpval; | ||
398 | |||
399 | if (pstats->signalquality != 0) { | ||
400 | if (pstats->packet_toself || pstats->packet_beacon) { | ||
401 | |||
402 | if (rtlpriv->stats.ui_link_quality.total_num++ >= | ||
403 | PHY_LINKQUALITY_SLID_WIN_MAX) { | ||
404 | rtlpriv->stats.ui_link_quality.total_num = | ||
405 | PHY_LINKQUALITY_SLID_WIN_MAX; | ||
406 | last_evm = | ||
407 | rtlpriv->stats. | ||
408 | ui_link_quality.elements[rtlpriv-> | ||
409 | stats.ui_link_quality. | ||
410 | index]; | ||
411 | rtlpriv->stats.ui_link_quality.total_val -= | ||
412 | last_evm; | ||
413 | } | ||
414 | |||
415 | rtlpriv->stats.ui_link_quality.total_val += | ||
416 | pstats->signalquality; | ||
417 | rtlpriv->stats.ui_link_quality.elements[rtlpriv->stats. | ||
418 | ui_link_quality. | ||
419 | index++] = | ||
420 | pstats->signalquality; | ||
421 | |||
422 | if (rtlpriv->stats.ui_link_quality.index >= | ||
423 | PHY_LINKQUALITY_SLID_WIN_MAX) | ||
424 | rtlpriv->stats.ui_link_quality.index = 0; | ||
425 | |||
426 | tmpval = rtlpriv->stats.ui_link_quality.total_val / | ||
427 | rtlpriv->stats.ui_link_quality.total_num; | ||
428 | rtlpriv->stats.signal_quality = tmpval; | ||
429 | |||
430 | rtlpriv->stats.last_sigstrength_inpercent = tmpval; | ||
431 | |||
432 | for (n_spatialstream = 0; n_spatialstream < 2; | ||
433 | n_spatialstream++) { | ||
434 | if (pstats-> | ||
435 | rx_mimo_sig_qual[n_spatialstream] != -1) { | ||
436 | if (rtlpriv->stats. | ||
437 | rx_evm_percentage[n_spatialstream] | ||
438 | == 0) { | ||
439 | rtlpriv->stats. | ||
440 | rx_evm_percentage | ||
441 | [n_spatialstream] = | ||
442 | pstats->rx_mimo_sig_qual | ||
443 | [n_spatialstream]; | ||
444 | } | ||
445 | |||
446 | rtlpriv->stats. | ||
447 | rx_evm_percentage[n_spatialstream] = | ||
448 | ((rtlpriv-> | ||
449 | stats.rx_evm_percentage | ||
450 | [n_spatialstream] * | ||
451 | (RX_SMOOTH_FACTOR - 1)) + | ||
452 | (pstats->rx_mimo_sig_qual | ||
453 | [n_spatialstream] * 1)) / | ||
454 | (RX_SMOOTH_FACTOR); | ||
455 | } | ||
456 | } | ||
457 | } | ||
458 | } else { | ||
459 | ; | ||
460 | } | ||
461 | } | ||
462 | |||
463 | static void _rtl92ce_process_phyinfo(struct ieee80211_hw *hw, | ||
464 | u8 *buffer, | ||
465 | struct rtl_stats *pcurrent_stats) | ||
466 | { | ||
467 | |||
468 | if (!pcurrent_stats->packet_matchbssid && | ||
469 | !pcurrent_stats->packet_beacon) | ||
470 | return; | ||
471 | |||
472 | _rtl92ce_process_ui_rssi(hw, pcurrent_stats); | ||
473 | _rtl92ce_process_pwdb(hw, pcurrent_stats); | ||
474 | _rtl92ce_process_ui_link_quality(hw, pcurrent_stats); | ||
475 | } | ||
476 | |||
477 | static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw, | 293 | static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw, |
478 | struct sk_buff *skb, | 294 | struct sk_buff *skb, |
479 | struct rtl_stats *pstats, | 295 | struct rtl_stats *pstats, |
@@ -516,7 +332,7 @@ static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw, | |||
516 | packet_matchbssid, packet_toself, | 332 | packet_matchbssid, packet_toself, |
517 | packet_beacon); | 333 | packet_beacon); |
518 | 334 | ||
519 | _rtl92ce_process_phyinfo(hw, tmp_buf, pstats); | 335 | rtl_process_phyinfo(hw, tmp_buf, pstats); |
520 | } | 336 | } |
521 | 337 | ||
522 | bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, | 338 | bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, |
@@ -526,7 +342,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, | |||
526 | { | 342 | { |
527 | struct rx_fwinfo_92c *p_drvinfo; | 343 | struct rx_fwinfo_92c *p_drvinfo; |
528 | struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc; | 344 | struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc; |
529 | 345 | struct ieee80211_hdr *hdr; | |
530 | u32 phystatus = GET_RX_DESC_PHYST(pdesc); | 346 | u32 phystatus = GET_RX_DESC_PHYST(pdesc); |
531 | stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc); | 347 | stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc); |
532 | stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) * | 348 | stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) * |
@@ -539,37 +355,60 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, | |||
539 | stats->rate = (u8) GET_RX_DESC_RXMCS(pdesc); | 355 | stats->rate = (u8) GET_RX_DESC_RXMCS(pdesc); |
540 | stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc); | 356 | stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc); |
541 | stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1); | 357 | stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1); |
542 | stats->isampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1) | 358 | stats->isfirst_ampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1) |
543 | && (GET_RX_DESC_FAGGR(pdesc) == 1)); | 359 | && (GET_RX_DESC_FAGGR(pdesc) == 1)); |
544 | stats->timestamp_low = GET_RX_DESC_TSFL(pdesc); | 360 | stats->timestamp_low = GET_RX_DESC_TSFL(pdesc); |
545 | stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); | 361 | stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); |
362 | stats->is_ht = (bool)GET_RX_DESC_RXHT(pdesc); | ||
363 | |||
364 | stats->is_cck = RX_HAL_IS_CCK_RATE(pdesc); | ||
546 | 365 | ||
547 | rx_status->freq = hw->conf.channel->center_freq; | 366 | rx_status->freq = hw->conf.channel->center_freq; |
548 | rx_status->band = hw->conf.channel->band; | 367 | rx_status->band = hw->conf.channel->band; |
549 | 368 | ||
550 | if (GET_RX_DESC_CRC32(pdesc)) | 369 | hdr = (struct ieee80211_hdr *)(skb->data + stats->rx_drvinfo_size |
551 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; | 370 | + stats->rx_bufshift); |
552 | 371 | ||
553 | if (!GET_RX_DESC_SWDEC(pdesc)) | 372 | if (stats->crc) |
554 | rx_status->flag |= RX_FLAG_DECRYPTED; | 373 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; |
555 | 374 | ||
556 | if (GET_RX_DESC_BW(pdesc)) | 375 | if (stats->rx_is40Mhzpacket) |
557 | rx_status->flag |= RX_FLAG_40MHZ; | 376 | rx_status->flag |= RX_FLAG_40MHZ; |
558 | 377 | ||
559 | if (GET_RX_DESC_RXHT(pdesc)) | 378 | if (stats->is_ht) |
560 | rx_status->flag |= RX_FLAG_HT; | 379 | rx_status->flag |= RX_FLAG_HT; |
561 | 380 | ||
562 | rx_status->flag |= RX_FLAG_MACTIME_START; | 381 | rx_status->flag |= RX_FLAG_MACTIME_START; |
563 | 382 | ||
564 | if (stats->decrypted) | 383 | /* hw will set stats->decrypted true, if it finds the |
565 | rx_status->flag |= RX_FLAG_DECRYPTED; | 384 | * frame is open data frame or mgmt frame. |
566 | 385 | * So hw will not decryption robust managment frame | |
386 | * for IEEE80211w but still set status->decrypted | ||
387 | * true, so here we should set it back to undecrypted | ||
388 | * for IEEE80211w frame, and mac80211 sw will help | ||
389 | * to decrypt it | ||
390 | */ | ||
391 | if (stats->decrypted) { | ||
392 | if (!hdr) { | ||
393 | /* In testing, hdr was NULL here */ | ||
394 | return false; | ||
395 | } | ||
396 | if ((ieee80211_is_robust_mgmt_frame(hdr)) && | ||
397 | (ieee80211_has_protected(hdr->frame_control))) | ||
398 | rx_status->flag &= ~RX_FLAG_DECRYPTED; | ||
399 | else | ||
400 | rx_status->flag |= RX_FLAG_DECRYPTED; | ||
401 | } | ||
402 | /* rate_idx: index of data rate into band's | ||
403 | * supported rates or MCS index if HT rates | ||
404 | * are use (RX_FLAG_HT) | ||
405 | * Notice: this is diff with windows define | ||
406 | */ | ||
567 | rx_status->rate_idx = rtlwifi_rate_mapping(hw, | 407 | rx_status->rate_idx = rtlwifi_rate_mapping(hw, |
568 | (bool)GET_RX_DESC_RXHT(pdesc), | 408 | stats->is_ht, stats->rate, |
569 | (u8)GET_RX_DESC_RXMCS(pdesc), | 409 | stats->isfirst_ampdu); |
570 | (bool)GET_RX_DESC_PAGGR(pdesc)); | ||
571 | 410 | ||
572 | rx_status->mactime = GET_RX_DESC_TSFL(pdesc); | 411 | rx_status->mactime = stats->timestamp_low; |
573 | if (phystatus) { | 412 | if (phystatus) { |
574 | p_drvinfo = (struct rx_fwinfo_92c *)(skb->data + | 413 | p_drvinfo = (struct rx_fwinfo_92c *)(skb->data + |
575 | stats->rx_bufshift); | 414 | stats->rx_bufshift); |
@@ -580,7 +419,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, | |||
580 | } | 419 | } |
581 | 420 | ||
582 | /*rx_status->qual = stats->signal; */ | 421 | /*rx_status->qual = stats->signal; */ |
583 | rx_status->signal = stats->rssi + 10; | 422 | rx_status->signal = stats->recvsignalpower + 10; |
584 | /*rx_status->noise = -stats->noise; */ | 423 | /*rx_status->noise = -stats->noise; */ |
585 | 424 | ||
586 | return true; | 425 | return true; |
@@ -624,7 +463,8 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, | |||
624 | if (mac->opmode == NL80211_IFTYPE_STATION) { | 463 | if (mac->opmode == NL80211_IFTYPE_STATION) { |
625 | bw_40 = mac->bw_40; | 464 | bw_40 = mac->bw_40; |
626 | } else if (mac->opmode == NL80211_IFTYPE_AP || | 465 | } else if (mac->opmode == NL80211_IFTYPE_AP || |
627 | mac->opmode == NL80211_IFTYPE_ADHOC) { | 466 | mac->opmode == NL80211_IFTYPE_ADHOC || |
467 | mac->opmode == NL80211_IFTYPE_MESH_POINT) { | ||
628 | if (sta) | 468 | if (sta) |
629 | bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40; | 469 | bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40; |
630 | } | 470 | } |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index c08d0f4c5f3d..3d0498e69c8c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c | |||
@@ -202,7 +202,7 @@ static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
202 | } | 202 | } |
203 | } | 203 | } |
204 | for (i = 0; i < 14; i++) { | 204 | for (i = 0; i < 14; i++) { |
205 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 205 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
206 | "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n", rf_path, i, | 206 | "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n", rf_path, i, |
207 | rtlefuse->txpwrlevel_cck[rf_path][i], | 207 | rtlefuse->txpwrlevel_cck[rf_path][i], |
208 | rtlefuse->txpwrlevel_ht40_1s[rf_path][i], | 208 | rtlefuse->txpwrlevel_ht40_1s[rf_path][i], |
@@ -238,11 +238,11 @@ static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
238 | ((rtlefuse->eeprom_pwrlimit_ht40[index] | 238 | ((rtlefuse->eeprom_pwrlimit_ht40[index] |
239 | & 0xf0) >> 4); | 239 | & 0xf0) >> 4); |
240 | } | 240 | } |
241 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 241 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
242 | "RF-%d pwrgroup_ht20[%d] = 0x%x\n", | 242 | "RF-%d pwrgroup_ht20[%d] = 0x%x\n", |
243 | rf_path, i, | 243 | rf_path, i, |
244 | rtlefuse->pwrgroup_ht20[rf_path][i]); | 244 | rtlefuse->pwrgroup_ht20[rf_path][i]); |
245 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 245 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
246 | "RF-%d pwrgroup_ht40[%d] = 0x%x\n", | 246 | "RF-%d pwrgroup_ht40[%d] = 0x%x\n", |
247 | rf_path, i, | 247 | rf_path, i, |
248 | rtlefuse->pwrgroup_ht40[rf_path][i]); | 248 | rtlefuse->pwrgroup_ht40[rf_path][i]); |
@@ -273,26 +273,26 @@ static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
273 | rtlefuse->legacy_ht_txpowerdiff = | 273 | rtlefuse->legacy_ht_txpowerdiff = |
274 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7]; | 274 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7]; |
275 | for (i = 0; i < 14; i++) | 275 | for (i = 0; i < 14; i++) |
276 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 276 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
277 | "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", | 277 | "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", |
278 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); | 278 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); |
279 | for (i = 0; i < 14; i++) | 279 | for (i = 0; i < 14; i++) |
280 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 280 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
281 | "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", | 281 | "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", |
282 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); | 282 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); |
283 | for (i = 0; i < 14; i++) | 283 | for (i = 0; i < 14; i++) |
284 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 284 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
285 | "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", | 285 | "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", |
286 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); | 286 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); |
287 | for (i = 0; i < 14; i++) | 287 | for (i = 0; i < 14; i++) |
288 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 288 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
289 | "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", | 289 | "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", |
290 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); | 290 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); |
291 | if (!autoload_fail) | 291 | if (!autoload_fail) |
292 | rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7); | 292 | rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7); |
293 | else | 293 | else |
294 | rtlefuse->eeprom_regulatory = 0; | 294 | rtlefuse->eeprom_regulatory = 0; |
295 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 295 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
296 | "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); | 296 | "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); |
297 | if (!autoload_fail) { | 297 | if (!autoload_fail) { |
298 | rtlefuse->eeprom_tssi[RF90_PATH_A] = hwinfo[EEPROM_TSSI_A]; | 298 | rtlefuse->eeprom_tssi[RF90_PATH_A] = hwinfo[EEPROM_TSSI_A]; |
@@ -301,7 +301,7 @@ static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
301 | rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI; | 301 | rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI; |
302 | rtlefuse->eeprom_tssi[RF90_PATH_B] = EEPROM_DEFAULT_TSSI; | 302 | rtlefuse->eeprom_tssi[RF90_PATH_B] = EEPROM_DEFAULT_TSSI; |
303 | } | 303 | } |
304 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 304 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
305 | "TSSI_A = 0x%x, TSSI_B = 0x%x\n", | 305 | "TSSI_A = 0x%x, TSSI_B = 0x%x\n", |
306 | rtlefuse->eeprom_tssi[RF90_PATH_A], | 306 | rtlefuse->eeprom_tssi[RF90_PATH_A], |
307 | rtlefuse->eeprom_tssi[RF90_PATH_B]); | 307 | rtlefuse->eeprom_tssi[RF90_PATH_B]); |
@@ -316,7 +316,7 @@ static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
316 | if (rtlefuse->eeprom_thermalmeter == 0x1f || autoload_fail) | 316 | if (rtlefuse->eeprom_thermalmeter == 0x1f || autoload_fail) |
317 | rtlefuse->apk_thermalmeterignore = true; | 317 | rtlefuse->apk_thermalmeterignore = true; |
318 | rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; | 318 | rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; |
319 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 319 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
320 | "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); | 320 | "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); |
321 | } | 321 | } |
322 | 322 | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index a73a17bc56dd..23d640a4debd 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | |||
@@ -223,7 +223,7 @@ static struct rtl_hal_cfg rtl92cu_hal_cfg = { | |||
223 | 223 | ||
224 | .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, | 224 | .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, |
225 | .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, | 225 | .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, |
226 | .maps[RTL_IMR_BcnInt] = IMR_BCNINT, | 226 | .maps[RTL_IMR_BCNINT] = IMR_BCNINT, |
227 | .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, | 227 | .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, |
228 | .maps[RTL_IMR_RDU] = IMR_RDU, | 228 | .maps[RTL_IMR_RDU] = IMR_RDU, |
229 | .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, | 229 | .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index b6222eedb835..710f7904ecdf 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c | |||
@@ -434,7 +434,7 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
434 | (u32)hdr->addr1[2], (u32)hdr->addr1[3], | 434 | (u32)hdr->addr1[2], (u32)hdr->addr1[3], |
435 | (u32)hdr->addr1[4], (u32)hdr->addr1[5]); | 435 | (u32)hdr->addr1[4], (u32)hdr->addr1[5]); |
436 | memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status)); | 436 | memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status)); |
437 | ieee80211_rx_irqsafe(hw, skb); | 437 | ieee80211_rx(hw, skb); |
438 | } | 438 | } |
439 | 439 | ||
440 | void rtl8192cu_rx_hdl(struct ieee80211_hw *hw, struct sk_buff * skb) | 440 | void rtl8192cu_rx_hdl(struct ieee80211_hw *hw, struct sk_buff * skb) |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c index 5251fb8a111e..19a765532603 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c | |||
@@ -171,8 +171,8 @@ static void rtl92d_dm_diginit(struct ieee80211_hw *hw) | |||
171 | de_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH; | 171 | de_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH; |
172 | de_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW; | 172 | de_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW; |
173 | de_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH; | 173 | de_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH; |
174 | de_digtable->rx_gain_range_max = DM_DIG_FA_UPPER; | 174 | de_digtable->rx_gain_max = DM_DIG_FA_UPPER; |
175 | de_digtable->rx_gain_range_min = DM_DIG_FA_LOWER; | 175 | de_digtable->rx_gain_min = DM_DIG_FA_LOWER; |
176 | de_digtable->back_val = DM_DIG_BACKOFF_DEFAULT; | 176 | de_digtable->back_val = DM_DIG_BACKOFF_DEFAULT; |
177 | de_digtable->back_range_max = DM_DIG_BACKOFF_MAX; | 177 | de_digtable->back_range_max = DM_DIG_BACKOFF_MAX; |
178 | de_digtable->back_range_min = DM_DIG_BACKOFF_MIN; | 178 | de_digtable->back_range_min = DM_DIG_BACKOFF_MIN; |
@@ -444,8 +444,8 @@ static void rtl92d_dm_dig(struct ieee80211_hw *hw) | |||
444 | "dm_DIG() Before: large_fa_hit=%d, forbidden_igi=%x\n", | 444 | "dm_DIG() Before: large_fa_hit=%d, forbidden_igi=%x\n", |
445 | de_digtable->large_fa_hit, de_digtable->forbidden_igi); | 445 | de_digtable->large_fa_hit, de_digtable->forbidden_igi); |
446 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, | 446 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, |
447 | "dm_DIG() Before: Recover_cnt=%d, rx_gain_range_min=%x\n", | 447 | "dm_DIG() Before: Recover_cnt=%d, rx_gain_min=%x\n", |
448 | de_digtable->recover_cnt, de_digtable->rx_gain_range_min); | 448 | de_digtable->recover_cnt, de_digtable->rx_gain_min); |
449 | 449 | ||
450 | /* deal with abnorally large false alarm */ | 450 | /* deal with abnorally large false alarm */ |
451 | if (falsealm_cnt->cnt_all > 10000) { | 451 | if (falsealm_cnt->cnt_all > 10000) { |
@@ -459,9 +459,9 @@ static void rtl92d_dm_dig(struct ieee80211_hw *hw) | |||
459 | } | 459 | } |
460 | if (de_digtable->large_fa_hit >= 3) { | 460 | if (de_digtable->large_fa_hit >= 3) { |
461 | if ((de_digtable->forbidden_igi + 1) > DM_DIG_MAX) | 461 | if ((de_digtable->forbidden_igi + 1) > DM_DIG_MAX) |
462 | de_digtable->rx_gain_range_min = DM_DIG_MAX; | 462 | de_digtable->rx_gain_min = DM_DIG_MAX; |
463 | else | 463 | else |
464 | de_digtable->rx_gain_range_min = | 464 | de_digtable->rx_gain_min = |
465 | (de_digtable->forbidden_igi + 1); | 465 | (de_digtable->forbidden_igi + 1); |
466 | de_digtable->recover_cnt = 3600; /* 3600=2hr */ | 466 | de_digtable->recover_cnt = 3600; /* 3600=2hr */ |
467 | } | 467 | } |
@@ -475,12 +475,12 @@ static void rtl92d_dm_dig(struct ieee80211_hw *hw) | |||
475 | DM_DIG_FA_LOWER) { | 475 | DM_DIG_FA_LOWER) { |
476 | de_digtable->forbidden_igi = | 476 | de_digtable->forbidden_igi = |
477 | DM_DIG_FA_LOWER; | 477 | DM_DIG_FA_LOWER; |
478 | de_digtable->rx_gain_range_min = | 478 | de_digtable->rx_gain_min = |
479 | DM_DIG_FA_LOWER; | 479 | DM_DIG_FA_LOWER; |
480 | 480 | ||
481 | } else { | 481 | } else { |
482 | de_digtable->forbidden_igi--; | 482 | de_digtable->forbidden_igi--; |
483 | de_digtable->rx_gain_range_min = | 483 | de_digtable->rx_gain_min = |
484 | (de_digtable->forbidden_igi + 1); | 484 | (de_digtable->forbidden_igi + 1); |
485 | } | 485 | } |
486 | } else if (de_digtable->large_fa_hit == 3) { | 486 | } else if (de_digtable->large_fa_hit == 3) { |
@@ -492,13 +492,13 @@ static void rtl92d_dm_dig(struct ieee80211_hw *hw) | |||
492 | "dm_DIG() After: large_fa_hit=%d, forbidden_igi=%x\n", | 492 | "dm_DIG() After: large_fa_hit=%d, forbidden_igi=%x\n", |
493 | de_digtable->large_fa_hit, de_digtable->forbidden_igi); | 493 | de_digtable->large_fa_hit, de_digtable->forbidden_igi); |
494 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, | 494 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, |
495 | "dm_DIG() After: recover_cnt=%d, rx_gain_range_min=%x\n", | 495 | "dm_DIG() After: recover_cnt=%d, rx_gain_min=%x\n", |
496 | de_digtable->recover_cnt, de_digtable->rx_gain_range_min); | 496 | de_digtable->recover_cnt, de_digtable->rx_gain_min); |
497 | 497 | ||
498 | if (value_igi > DM_DIG_MAX) | 498 | if (value_igi > DM_DIG_MAX) |
499 | value_igi = DM_DIG_MAX; | 499 | value_igi = DM_DIG_MAX; |
500 | else if (value_igi < de_digtable->rx_gain_range_min) | 500 | else if (value_igi < de_digtable->rx_gain_min) |
501 | value_igi = de_digtable->rx_gain_range_min; | 501 | value_igi = de_digtable->rx_gain_min; |
502 | de_digtable->cur_igvalue = value_igi; | 502 | de_digtable->cur_igvalue = value_igi; |
503 | rtl92d_dm_write_dig(hw); | 503 | rtl92d_dm_write_dig(hw); |
504 | if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G) | 504 | if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G) |
@@ -1071,9 +1071,9 @@ static void rtl92d_dm_txpower_tracking_callback_thermalmeter( | |||
1071 | } | 1071 | } |
1072 | ele_d = (ofdmswing_table[(u8) ofdm_index[0]] & | 1072 | ele_d = (ofdmswing_table[(u8) ofdm_index[0]] & |
1073 | 0xFFC00000) >> 22; | 1073 | 0xFFC00000) >> 22; |
1074 | val_x = rtlphy->iqk_matrix_regsetting | 1074 | val_x = rtlphy->iqk_matrix |
1075 | [indexforchannel].value[0][0]; | 1075 | [indexforchannel].value[0][0]; |
1076 | val_y = rtlphy->iqk_matrix_regsetting | 1076 | val_y = rtlphy->iqk_matrix |
1077 | [indexforchannel].value[0][1]; | 1077 | [indexforchannel].value[0][1]; |
1078 | if (val_x != 0) { | 1078 | if (val_x != 0) { |
1079 | if ((val_x & 0x00000200) != 0) | 1079 | if ((val_x & 0x00000200) != 0) |
@@ -1175,9 +1175,9 @@ static void rtl92d_dm_txpower_tracking_callback_thermalmeter( | |||
1175 | if (is2t) { | 1175 | if (is2t) { |
1176 | ele_d = (ofdmswing_table[(u8) ofdm_index[1]] & | 1176 | ele_d = (ofdmswing_table[(u8) ofdm_index[1]] & |
1177 | 0xFFC00000) >> 22; | 1177 | 0xFFC00000) >> 22; |
1178 | val_x = rtlphy->iqk_matrix_regsetting | 1178 | val_x = rtlphy->iqk_matrix |
1179 | [indexforchannel].value[0][4]; | 1179 | [indexforchannel].value[0][4]; |
1180 | val_y = rtlphy->iqk_matrix_regsetting | 1180 | val_y = rtlphy->iqk_matrix |
1181 | [indexforchannel].value[0][5]; | 1181 | [indexforchannel].value[0][5]; |
1182 | if (val_x != 0) { | 1182 | if (val_x != 0) { |
1183 | if ((val_x & 0x00000200) != 0) | 1183 | if ((val_x & 0x00000200) != 0) |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c index aa5b42521bb4..7dd8f6de0550 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c | |||
@@ -1183,7 +1183,7 @@ void rtl92d_linked_set_reg(struct ieee80211_hw *hw) | |||
1183 | u8 channel = rtlphy->current_channel; | 1183 | u8 channel = rtlphy->current_channel; |
1184 | 1184 | ||
1185 | indexforchannel = rtl92d_get_rightchnlplace_for_iqk(channel); | 1185 | indexforchannel = rtl92d_get_rightchnlplace_for_iqk(channel); |
1186 | if (!rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done) { | 1186 | if (!rtlphy->iqk_matrix[indexforchannel].iqk_done) { |
1187 | RT_TRACE(rtlpriv, COMP_SCAN | COMP_INIT, DBG_DMESG, | 1187 | RT_TRACE(rtlpriv, COMP_SCAN | COMP_INIT, DBG_DMESG, |
1188 | "Do IQK for channel:%d\n", channel); | 1188 | "Do IQK for channel:%d\n", channel); |
1189 | rtl92d_phy_iq_calibrate(hw); | 1189 | rtl92d_phy_iq_calibrate(hw); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c index 33041bd4da81..840bac5fa2f8 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c | |||
@@ -2479,9 +2479,9 @@ void rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw) | |||
2479 | rtlphy->current_channel); | 2479 | rtlphy->current_channel); |
2480 | 2480 | ||
2481 | for (i = 0; i < IQK_MATRIX_REG_NUM; i++) | 2481 | for (i = 0; i < IQK_MATRIX_REG_NUM; i++) |
2482 | rtlphy->iqk_matrix_regsetting[indexforchannel]. | 2482 | rtlphy->iqk_matrix[indexforchannel]. |
2483 | value[0][i] = result[final_candidate][i]; | 2483 | value[0][i] = result[final_candidate][i]; |
2484 | rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done = | 2484 | rtlphy->iqk_matrix[indexforchannel].iqk_done = |
2485 | true; | 2485 | true; |
2486 | 2486 | ||
2487 | RT_TRACE(rtlpriv, COMP_SCAN | COMP_MLME, DBG_LOUD, | 2487 | RT_TRACE(rtlpriv, COMP_SCAN | COMP_MLME, DBG_LOUD, |
@@ -2501,8 +2501,8 @@ void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel) | |||
2501 | indexforchannel = rtl92d_get_rightchnlplace_for_iqk(channel); | 2501 | indexforchannel = rtl92d_get_rightchnlplace_for_iqk(channel); |
2502 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "indexforchannel %d done %d\n", | 2502 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "indexforchannel %d done %d\n", |
2503 | indexforchannel, | 2503 | indexforchannel, |
2504 | rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done); | 2504 | rtlphy->iqk_matrix[indexforchannel].iqk_done); |
2505 | if (0 && !rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done && | 2505 | if (0 && !rtlphy->iqk_matrix[indexforchannel].iqk_done && |
2506 | rtlphy->need_iqk) { | 2506 | rtlphy->need_iqk) { |
2507 | /* Re Do IQK. */ | 2507 | /* Re Do IQK. */ |
2508 | RT_TRACE(rtlpriv, COMP_SCAN | COMP_INIT, DBG_LOUD, | 2508 | RT_TRACE(rtlpriv, COMP_SCAN | COMP_INIT, DBG_LOUD, |
@@ -2516,23 +2516,23 @@ void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel) | |||
2516 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, | 2516 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, |
2517 | "Just Read IQK Matrix reg for channel:%d....\n", | 2517 | "Just Read IQK Matrix reg for channel:%d....\n", |
2518 | channel); | 2518 | channel); |
2519 | if ((rtlphy->iqk_matrix_regsetting[indexforchannel]. | 2519 | if ((rtlphy->iqk_matrix[indexforchannel]. |
2520 | value[0] != NULL) | 2520 | value[0] != NULL) |
2521 | /*&&(regea4 != 0) */) | 2521 | /*&&(regea4 != 0) */) |
2522 | _rtl92d_phy_patha_fill_iqk_matrix(hw, true, | 2522 | _rtl92d_phy_patha_fill_iqk_matrix(hw, true, |
2523 | rtlphy->iqk_matrix_regsetting[ | 2523 | rtlphy->iqk_matrix[ |
2524 | indexforchannel].value, 0, | 2524 | indexforchannel].value, 0, |
2525 | (rtlphy->iqk_matrix_regsetting[ | 2525 | (rtlphy->iqk_matrix[ |
2526 | indexforchannel].value[0][2] == 0)); | 2526 | indexforchannel].value[0][2] == 0)); |
2527 | if (IS_92D_SINGLEPHY(rtlhal->version)) { | 2527 | if (IS_92D_SINGLEPHY(rtlhal->version)) { |
2528 | if ((rtlphy->iqk_matrix_regsetting[ | 2528 | if ((rtlphy->iqk_matrix[ |
2529 | indexforchannel].value[0][4] != 0) | 2529 | indexforchannel].value[0][4] != 0) |
2530 | /*&&(regec4 != 0) */) | 2530 | /*&&(regec4 != 0) */) |
2531 | _rtl92d_phy_pathb_fill_iqk_matrix(hw, | 2531 | _rtl92d_phy_pathb_fill_iqk_matrix(hw, |
2532 | true, | 2532 | true, |
2533 | rtlphy->iqk_matrix_regsetting[ | 2533 | rtlphy->iqk_matrix[ |
2534 | indexforchannel].value, 0, | 2534 | indexforchannel].value, 0, |
2535 | (rtlphy->iqk_matrix_regsetting[ | 2535 | (rtlphy->iqk_matrix[ |
2536 | indexforchannel].value[0][6] | 2536 | indexforchannel].value[0][6] |
2537 | == 0)); | 2537 | == 0)); |
2538 | } | 2538 | } |
@@ -2830,20 +2830,20 @@ void rtl92d_phy_reset_iqk_result(struct ieee80211_hw *hw) | |||
2830 | 2830 | ||
2831 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | 2831 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, |
2832 | "settings regs %d default regs %d\n", | 2832 | "settings regs %d default regs %d\n", |
2833 | (int)(sizeof(rtlphy->iqk_matrix_regsetting) / | 2833 | (int)(sizeof(rtlphy->iqk_matrix) / |
2834 | sizeof(struct iqk_matrix_regs)), | 2834 | sizeof(struct iqk_matrix_regs)), |
2835 | IQK_MATRIX_REG_NUM); | 2835 | IQK_MATRIX_REG_NUM); |
2836 | /* 0xe94, 0xe9c, 0xea4, 0xeac, 0xeb4, 0xebc, 0xec4, 0xecc */ | 2836 | /* 0xe94, 0xe9c, 0xea4, 0xeac, 0xeb4, 0xebc, 0xec4, 0xecc */ |
2837 | for (i = 0; i < IQK_MATRIX_SETTINGS_NUM; i++) { | 2837 | for (i = 0; i < IQK_MATRIX_SETTINGS_NUM; i++) { |
2838 | rtlphy->iqk_matrix_regsetting[i].value[0][0] = 0x100; | 2838 | rtlphy->iqk_matrix[i].value[0][0] = 0x100; |
2839 | rtlphy->iqk_matrix_regsetting[i].value[0][2] = 0x100; | 2839 | rtlphy->iqk_matrix[i].value[0][2] = 0x100; |
2840 | rtlphy->iqk_matrix_regsetting[i].value[0][4] = 0x100; | 2840 | rtlphy->iqk_matrix[i].value[0][4] = 0x100; |
2841 | rtlphy->iqk_matrix_regsetting[i].value[0][6] = 0x100; | 2841 | rtlphy->iqk_matrix[i].value[0][6] = 0x100; |
2842 | rtlphy->iqk_matrix_regsetting[i].value[0][1] = 0x0; | 2842 | rtlphy->iqk_matrix[i].value[0][1] = 0x0; |
2843 | rtlphy->iqk_matrix_regsetting[i].value[0][3] = 0x0; | 2843 | rtlphy->iqk_matrix[i].value[0][3] = 0x0; |
2844 | rtlphy->iqk_matrix_regsetting[i].value[0][5] = 0x0; | 2844 | rtlphy->iqk_matrix[i].value[0][5] = 0x0; |
2845 | rtlphy->iqk_matrix_regsetting[i].value[0][7] = 0x0; | 2845 | rtlphy->iqk_matrix[i].value[0][7] = 0x0; |
2846 | rtlphy->iqk_matrix_regsetting[i].iqk_done = false; | 2846 | rtlphy->iqk_matrix[i].iqk_done = false; |
2847 | } | 2847 | } |
2848 | } | 2848 | } |
2849 | 2849 | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/reg.h b/drivers/net/wireless/rtlwifi/rtl8192de/reg.h index ebb1d5f5e7b5..b7498c5bafc5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/reg.h +++ b/drivers/net/wireless/rtlwifi/rtl8192de/reg.h | |||
@@ -543,7 +543,7 @@ | |||
543 | #define IMR_TIMEOUT1 BIT(16) | 543 | #define IMR_TIMEOUT1 BIT(16) |
544 | #define IMR_TXFOVW BIT(15) | 544 | #define IMR_TXFOVW BIT(15) |
545 | #define IMR_PSTIMEOUT BIT(14) | 545 | #define IMR_PSTIMEOUT BIT(14) |
546 | #define IMR_BcnInt BIT(13) | 546 | #define IMR_BCNINT BIT(13) |
547 | #define IMR_RXFOVW BIT(12) | 547 | #define IMR_RXFOVW BIT(12) |
548 | #define IMR_RDU BIT(11) | 548 | #define IMR_RDU BIT(11) |
549 | #define IMR_ATIMEND BIT(10) | 549 | #define IMR_ATIMEND BIT(10) |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c index 03c6d18b2e07..c18c04bf0c13 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c | |||
@@ -166,7 +166,7 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw) | |||
166 | rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; | 166 | rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; |
167 | 167 | ||
168 | /* for early mode */ | 168 | /* for early mode */ |
169 | rtlpriv->rtlhal.earlymode_enable = true; | 169 | rtlpriv->rtlhal.earlymode_enable = false; |
170 | for (tid = 0; tid < 8; tid++) | 170 | for (tid = 0; tid < 8; tid++) |
171 | skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]); | 171 | skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]); |
172 | 172 | ||
@@ -319,7 +319,7 @@ static struct rtl_hal_cfg rtl92de_hal_cfg = { | |||
319 | 319 | ||
320 | .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, | 320 | .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, |
321 | .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, | 321 | .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, |
322 | .maps[RTL_IMR_BcnInt] = IMR_BcnInt, | 322 | .maps[RTL_IMR_BCNINT] = IMR_BCNINT, |
323 | .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, | 323 | .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, |
324 | .maps[RTL_IMR_RDU] = IMR_RDU, | 324 | .maps[RTL_IMR_RDU] = IMR_RDU, |
325 | .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, | 325 | .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, |
@@ -333,7 +333,7 @@ static struct rtl_hal_cfg rtl92de_hal_cfg = { | |||
333 | .maps[RTL_IMR_VIDOK] = IMR_VIDOK, | 333 | .maps[RTL_IMR_VIDOK] = IMR_VIDOK, |
334 | .maps[RTL_IMR_VODOK] = IMR_VODOK, | 334 | .maps[RTL_IMR_VODOK] = IMR_VODOK, |
335 | .maps[RTL_IMR_ROK] = IMR_ROK, | 335 | .maps[RTL_IMR_ROK] = IMR_ROK, |
336 | .maps[RTL_IBSS_INT_MASKS] = (IMR_BcnInt | IMR_TBDOK | IMR_TBDER), | 336 | .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER), |
337 | 337 | ||
338 | .maps[RTL_RC_CCK_RATE1M] = DESC92_RATE1M, | 338 | .maps[RTL_RC_CCK_RATE1M] = DESC92_RATE1M, |
339 | .maps[RTL_RC_CCK_RATE2M] = DESC92_RATE2M, | 339 | .maps[RTL_RC_CCK_RATE2M] = DESC92_RATE2M, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/def.h b/drivers/net/wireless/rtlwifi/rtl8192se/def.h index 2d255e02d795..83c98674bfd3 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/def.h +++ b/drivers/net/wireless/rtlwifi/rtl8192se/def.h | |||
@@ -36,9 +36,6 @@ | |||
36 | #define SHORT_SLOT_TIME 9 | 36 | #define SHORT_SLOT_TIME 9 |
37 | #define NON_SHORT_SLOT_TIME 20 | 37 | #define NON_SHORT_SLOT_TIME 20 |
38 | 38 | ||
39 | /* Rx smooth factor */ | ||
40 | #define RX_SMOOTH_FACTOR 20 | ||
41 | |||
42 | /* Queue Select Value in TxDesc */ | 39 | /* Queue Select Value in TxDesc */ |
43 | #define QSLT_BK 0x2 | 40 | #define QSLT_BK 0x2 |
44 | #define QSLT_BE 0x0 | 41 | #define QSLT_BE 0x0 |
@@ -49,10 +46,6 @@ | |||
49 | #define QSLT_MGNT 0x12 | 46 | #define QSLT_MGNT 0x12 |
50 | #define QSLT_CMD 0x13 | 47 | #define QSLT_CMD 0x13 |
51 | 48 | ||
52 | #define PHY_RSSI_SLID_WIN_MAX 100 | ||
53 | #define PHY_LINKQUALITY_SLID_WIN_MAX 20 | ||
54 | #define PHY_BEACON_RSSI_SLID_WIN_MAX 10 | ||
55 | |||
56 | /* Tx Desc */ | 49 | /* Tx Desc */ |
57 | #define TX_DESC_SIZE_RTL8192S (16 * 4) | 50 | #define TX_DESC_SIZE_RTL8192S (16 * 4) |
58 | #define TX_CMDDESC_SIZE_RTL8192S (16 * 4) | 51 | #define TX_CMDDESC_SIZE_RTL8192S (16 * 4) |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c index e551fe5f9ccd..b3a2d5ec59e6 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c | |||
@@ -163,6 +163,7 @@ static void _rtl92s_dm_txpowertracking_callback_thermalmeter( | |||
163 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 163 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
164 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | 164 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); |
165 | u8 thermalvalue = 0; | 165 | u8 thermalvalue = 0; |
166 | u32 fw_cmd = 0; | ||
166 | 167 | ||
167 | rtlpriv->dm.txpower_trackinginit = true; | 168 | rtlpriv->dm.txpower_trackinginit = true; |
168 | 169 | ||
@@ -175,7 +176,19 @@ static void _rtl92s_dm_txpowertracking_callback_thermalmeter( | |||
175 | 176 | ||
176 | if (thermalvalue) { | 177 | if (thermalvalue) { |
177 | rtlpriv->dm.thermalvalue = thermalvalue; | 178 | rtlpriv->dm.thermalvalue = thermalvalue; |
178 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_TXPWR_TRACK_THERMAL); | 179 | if (hal_get_firmwareversion(rtlpriv) >= 0x35) { |
180 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_TXPWR_TRACK_THERMAL); | ||
181 | } else { | ||
182 | fw_cmd = (FW_TXPWR_TRACK_THERMAL | | ||
183 | (rtlpriv->efuse.thermalmeter[0] << 8) | | ||
184 | (thermalvalue << 16)); | ||
185 | |||
186 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | ||
187 | "Write to FW Thermal Val = 0x%x\n", fw_cmd); | ||
188 | |||
189 | rtl_write_dword(rtlpriv, WFM5, fw_cmd); | ||
190 | rtl92s_phy_chk_fwcmd_iodone(hw); | ||
191 | } | ||
179 | } | 192 | } |
180 | 193 | ||
181 | rtlpriv->dm.txpowercount = 0; | 194 | rtlpriv->dm.txpowercount = 0; |
@@ -217,11 +230,10 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw) | |||
217 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 230 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
218 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 231 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
219 | struct rate_adaptive *ra = &(rtlpriv->ra); | 232 | struct rate_adaptive *ra = &(rtlpriv->ra); |
220 | 233 | struct ieee80211_sta *sta = NULL; | |
221 | u32 low_rssi_thresh = 0; | 234 | u32 low_rssi_thresh = 0; |
222 | u32 middle_rssi_thresh = 0; | 235 | u32 middle_rssi_thresh = 0; |
223 | u32 high_rssi_thresh = 0; | 236 | u32 high_rssi_thresh = 0; |
224 | struct ieee80211_sta *sta = NULL; | ||
225 | 237 | ||
226 | if (is_hal_stop(rtlhal)) | 238 | if (is_hal_stop(rtlhal)) |
227 | return; | 239 | return; |
@@ -229,14 +241,12 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw) | |||
229 | if (!rtlpriv->dm.useramask) | 241 | if (!rtlpriv->dm.useramask) |
230 | return; | 242 | return; |
231 | 243 | ||
232 | if (!rtlpriv->dm.inform_fw_driverctrldm) { | 244 | if (hal_get_firmwareversion(rtlpriv) >= 61 && |
245 | !rtlpriv->dm.inform_fw_driverctrldm) { | ||
233 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_CTRL_DM_BY_DRIVER); | 246 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_CTRL_DM_BY_DRIVER); |
234 | rtlpriv->dm.inform_fw_driverctrldm = true; | 247 | rtlpriv->dm.inform_fw_driverctrldm = true; |
235 | } | 248 | } |
236 | 249 | ||
237 | rcu_read_lock(); | ||
238 | if (mac->opmode == NL80211_IFTYPE_STATION) | ||
239 | sta = get_sta(hw, mac->vif, mac->bssid); | ||
240 | if ((mac->link_state == MAC80211_LINKED) && | 250 | if ((mac->link_state == MAC80211_LINKED) && |
241 | (mac->opmode == NL80211_IFTYPE_STATION)) { | 251 | (mac->opmode == NL80211_IFTYPE_STATION)) { |
242 | switch (ra->pre_ratr_state) { | 252 | switch (ra->pre_ratr_state) { |
@@ -285,12 +295,16 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw) | |||
285 | rtlpriv->dm.undec_sm_pwdb, ra->ratr_state, | 295 | rtlpriv->dm.undec_sm_pwdb, ra->ratr_state, |
286 | ra->pre_ratr_state, ra->ratr_state); | 296 | ra->pre_ratr_state, ra->ratr_state); |
287 | 297 | ||
288 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, | 298 | rcu_read_lock(); |
299 | sta = rtl_find_sta(hw, mac->bssid); | ||
300 | if (sta) | ||
301 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, | ||
289 | ra->ratr_state); | 302 | ra->ratr_state); |
303 | rcu_read_unlock(); | ||
304 | |||
290 | ra->pre_ratr_state = ra->ratr_state; | 305 | ra->pre_ratr_state = ra->ratr_state; |
291 | } | 306 | } |
292 | } | 307 | } |
293 | rcu_read_unlock(); | ||
294 | } | 308 | } |
295 | 309 | ||
296 | static void _rtl92s_dm_switch_baseband_mrc(struct ieee80211_hw *hw) | 310 | static void _rtl92s_dm_switch_baseband_mrc(struct ieee80211_hw *hw) |
@@ -370,7 +384,8 @@ static void _rtl92s_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) | |||
370 | ra->ratr_state = DM_RATR_STA_MAX; | 384 | ra->ratr_state = DM_RATR_STA_MAX; |
371 | ra->pre_ratr_state = DM_RATR_STA_MAX; | 385 | ra->pre_ratr_state = DM_RATR_STA_MAX; |
372 | 386 | ||
373 | if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) | 387 | if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER && |
388 | hal_get_firmwareversion(rtlpriv) >= 60) | ||
374 | rtlpriv->dm.useramask = true; | 389 | rtlpriv->dm.useramask = true; |
375 | else | 390 | else |
376 | rtlpriv->dm.useramask = false; | 391 | rtlpriv->dm.useramask = false; |
@@ -457,13 +472,13 @@ static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw) | |||
457 | digtable->back_val = DM_DIG_BACKOFF; | 472 | digtable->back_val = DM_DIG_BACKOFF; |
458 | 473 | ||
459 | if ((digtable->rssi_val + 10 - digtable->back_val) > | 474 | if ((digtable->rssi_val + 10 - digtable->back_val) > |
460 | digtable->rx_gain_range_max) | 475 | digtable->rx_gain_max) |
461 | digtable->cur_igvalue = | 476 | digtable->cur_igvalue = |
462 | digtable->rx_gain_range_max; | 477 | digtable->rx_gain_max; |
463 | else if ((digtable->rssi_val + 10 - digtable->back_val) | 478 | else if ((digtable->rssi_val + 10 - digtable->back_val) |
464 | < digtable->rx_gain_range_min) | 479 | < digtable->rx_gain_min) |
465 | digtable->cur_igvalue = | 480 | digtable->cur_igvalue = |
466 | digtable->rx_gain_range_min; | 481 | digtable->rx_gain_min; |
467 | else | 482 | else |
468 | digtable->cur_igvalue = digtable->rssi_val + 10 | 483 | digtable->cur_igvalue = digtable->rssi_val + 10 |
469 | - digtable->back_val; | 484 | - digtable->back_val; |
@@ -475,7 +490,7 @@ static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw) | |||
475 | 490 | ||
476 | if (falsealm_cnt->cnt_all > 16000) | 491 | if (falsealm_cnt->cnt_all > 16000) |
477 | digtable->cur_igvalue = | 492 | digtable->cur_igvalue = |
478 | digtable->rx_gain_range_max; | 493 | digtable->rx_gain_max; |
479 | /* connected -> connected or disconnected -> disconnected */ | 494 | /* connected -> connected or disconnected -> disconnected */ |
480 | } else { | 495 | } else { |
481 | /* Firmware control DIG, do nothing in driver dm */ | 496 | /* Firmware control DIG, do nothing in driver dm */ |
@@ -677,9 +692,9 @@ static void _rtl92s_dm_init_dig(struct ieee80211_hw *hw) | |||
677 | /* for dig debug rssi value */ | 692 | /* for dig debug rssi value */ |
678 | digtable->rssi_val = 50; | 693 | digtable->rssi_val = 50; |
679 | digtable->back_val = DM_DIG_BACKOFF; | 694 | digtable->back_val = DM_DIG_BACKOFF; |
680 | digtable->rx_gain_range_max = DM_DIG_MAX; | 695 | digtable->rx_gain_max = DM_DIG_MAX; |
681 | 696 | ||
682 | digtable->rx_gain_range_min = DM_DIG_MIN; | 697 | digtable->rx_gain_min = DM_DIG_MIN; |
683 | 698 | ||
684 | digtable->backoffval_range_max = DM_DIG_BACKOFF_MAX; | 699 | digtable->backoffval_range_max = DM_DIG_BACKOFF_MAX; |
685 | digtable->backoffval_range_min = DM_DIG_BACKOFF_MIN; | 700 | digtable->backoffval_range_min = DM_DIG_BACKOFF_MIN; |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c index 084e7773bce2..4f461786a7eb 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c | |||
@@ -400,6 +400,39 @@ void rtl92se_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | |||
400 | 400 | ||
401 | break; | 401 | break; |
402 | } | 402 | } |
403 | case HW_VAR_FW_LPS_ACTION: { | ||
404 | bool enter_fwlps = *((bool *)val); | ||
405 | u8 rpwm_val, fw_pwrmode; | ||
406 | bool fw_current_inps; | ||
407 | |||
408 | if (enter_fwlps) { | ||
409 | rpwm_val = 0x02; /* RF off */ | ||
410 | fw_current_inps = true; | ||
411 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
412 | HW_VAR_FW_PSMODE_STATUS, | ||
413 | (u8 *)(&fw_current_inps)); | ||
414 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
415 | HW_VAR_H2C_FW_PWRMODE, | ||
416 | (u8 *)(&ppsc->fwctrl_psmode)); | ||
417 | |||
418 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
419 | HW_VAR_SET_RPWM, | ||
420 | (u8 *)(&rpwm_val)); | ||
421 | } else { | ||
422 | rpwm_val = 0x0C; /* RF on */ | ||
423 | fw_pwrmode = FW_PS_ACTIVE_MODE; | ||
424 | fw_current_inps = false; | ||
425 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, | ||
426 | (u8 *)(&rpwm_val)); | ||
427 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
428 | HW_VAR_H2C_FW_PWRMODE, | ||
429 | (u8 *)(&fw_pwrmode)); | ||
430 | |||
431 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
432 | HW_VAR_FW_PSMODE_STATUS, | ||
433 | (u8 *)(&fw_current_inps)); | ||
434 | } | ||
435 | break; } | ||
403 | default: | 436 | default: |
404 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 437 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
405 | "switch case not processed\n"); | 438 | "switch case not processed\n"); |
@@ -438,7 +471,7 @@ void rtl92se_enable_hw_security_config(struct ieee80211_hw *hw) | |||
438 | 471 | ||
439 | } | 472 | } |
440 | 473 | ||
441 | static u8 _rtl92ce_halset_sysclk(struct ieee80211_hw *hw, u8 data) | 474 | static u8 _rtl92se_halset_sysclk(struct ieee80211_hw *hw, u8 data) |
442 | { | 475 | { |
443 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 476 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
444 | u8 waitcount = 100; | 477 | u8 waitcount = 100; |
@@ -547,7 +580,7 @@ static void _rtl92se_macconfig_before_fwdownload(struct ieee80211_hw *hw) | |||
547 | tmpu1b &= ~(BIT(6) | BIT(7)); | 580 | tmpu1b &= ~(BIT(6) | BIT(7)); |
548 | 581 | ||
549 | /* Set failed, return to prevent hang. */ | 582 | /* Set failed, return to prevent hang. */ |
550 | if (!_rtl92ce_halset_sysclk(hw, tmpu1b)) | 583 | if (!_rtl92se_halset_sysclk(hw, tmpu1b)) |
551 | return; | 584 | return; |
552 | } | 585 | } |
553 | 586 | ||
@@ -650,7 +683,7 @@ static void _rtl92se_macconfig_before_fwdownload(struct ieee80211_hw *hw) | |||
650 | 683 | ||
651 | tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); | 684 | tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); |
652 | tmpu1b = ((tmpu1b | BIT(7)) & (~BIT(6))); | 685 | tmpu1b = ((tmpu1b | BIT(7)) & (~BIT(6))); |
653 | if (!_rtl92ce_halset_sysclk(hw, tmpu1b)) | 686 | if (!_rtl92se_halset_sysclk(hw, tmpu1b)) |
654 | return; /* Set failed, return to prevent hang. */ | 687 | return; /* Set failed, return to prevent hang. */ |
655 | 688 | ||
656 | rtl_write_word(rtlpriv, CMDR, 0x07FC); | 689 | rtl_write_word(rtlpriv, CMDR, 0x07FC); |
@@ -967,6 +1000,15 @@ int rtl92se_hw_init(struct ieee80211_hw *hw) | |||
967 | return rtstatus; | 1000 | return rtstatus; |
968 | } | 1001 | } |
969 | 1002 | ||
1003 | /* because last function modify RCR, so we update | ||
1004 | * rcr var here, or TP will unstable for receive_config | ||
1005 | * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx | ||
1006 | * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252 | ||
1007 | */ | ||
1008 | rtlpci->receive_config = rtl_read_dword(rtlpriv, RCR); | ||
1009 | rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV); | ||
1010 | rtl_write_dword(rtlpriv, RCR, rtlpci->receive_config); | ||
1011 | |||
970 | /* Make sure BB/RF write OK. We should prevent enter IPS. radio off. */ | 1012 | /* Make sure BB/RF write OK. We should prevent enter IPS. radio off. */ |
971 | /* We must set flag avoid BB/RF config period later!! */ | 1013 | /* We must set flag avoid BB/RF config period later!! */ |
972 | rtl_write_dword(rtlpriv, CMDR, 0x37FC); | 1014 | rtl_write_dword(rtlpriv, CMDR, 0x37FC); |
@@ -982,25 +1024,6 @@ int rtl92se_hw_init(struct ieee80211_hw *hw) | |||
982 | 1024 | ||
983 | rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; | 1025 | rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; |
984 | 1026 | ||
985 | /* RF Power Save */ | ||
986 | #if 0 | ||
987 | /* H/W or S/W RF OFF before sleep. */ | ||
988 | if (rtlpriv->psc.rfoff_reason > RF_CHANGE_BY_PS) { | ||
989 | u32 rfoffreason = rtlpriv->psc.rfoff_reason; | ||
990 | |||
991 | rtlpriv->psc.rfoff_reason = RF_CHANGE_BY_INIT; | ||
992 | rtlpriv->psc.rfpwr_state = ERFON; | ||
993 | /* FIXME: check spinlocks if this block is uncommented */ | ||
994 | rtl_ps_set_rf_state(hw, ERFOFF, rfoffreason); | ||
995 | } else { | ||
996 | /* gpio radio on/off is out of adapter start */ | ||
997 | if (rtlpriv->psc.hwradiooff == false) { | ||
998 | rtlpriv->psc.rfpwr_state = ERFON; | ||
999 | rtlpriv->psc.rfoff_reason = 0; | ||
1000 | } | ||
1001 | } | ||
1002 | #endif | ||
1003 | |||
1004 | /* Before RF-R/W we must execute the IO from Scott's suggestion. */ | 1027 | /* Before RF-R/W we must execute the IO from Scott's suggestion. */ |
1005 | rtl_write_byte(rtlpriv, AFE_XTAL_CTRL + 1, 0xDB); | 1028 | rtl_write_byte(rtlpriv, AFE_XTAL_CTRL + 1, 0xDB); |
1006 | if (rtlhal->version == VERSION_8192S_ACUT) | 1029 | if (rtlhal->version == VERSION_8192S_ACUT) |
@@ -1058,7 +1081,22 @@ int rtl92se_hw_init(struct ieee80211_hw *hw) | |||
1058 | 1081 | ||
1059 | /* We enable high power and RA related mechanism after NIC | 1082 | /* We enable high power and RA related mechanism after NIC |
1060 | * initialized. */ | 1083 | * initialized. */ |
1061 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_INIT); | 1084 | if (hal_get_firmwareversion(rtlpriv) >= 0x35) { |
1085 | /* Fw v.53 and later. */ | ||
1086 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_INIT); | ||
1087 | } else if (hal_get_firmwareversion(rtlpriv) == 0x34) { | ||
1088 | /* Fw v.52. */ | ||
1089 | rtl_write_dword(rtlpriv, WFM5, FW_RA_INIT); | ||
1090 | rtl92s_phy_chk_fwcmd_iodone(hw); | ||
1091 | } else { | ||
1092 | /* Compatible earlier FW version. */ | ||
1093 | rtl_write_dword(rtlpriv, WFM5, FW_RA_RESET); | ||
1094 | rtl92s_phy_chk_fwcmd_iodone(hw); | ||
1095 | rtl_write_dword(rtlpriv, WFM5, FW_RA_ACTIVE); | ||
1096 | rtl92s_phy_chk_fwcmd_iodone(hw); | ||
1097 | rtl_write_dword(rtlpriv, WFM5, FW_RA_REFRESH); | ||
1098 | rtl92s_phy_chk_fwcmd_iodone(hw); | ||
1099 | } | ||
1062 | 1100 | ||
1063 | /* Add to prevent ASPM bug. */ | 1101 | /* Add to prevent ASPM bug. */ |
1064 | /* Always enable hst and NIC clock request. */ | 1102 | /* Always enable hst and NIC clock request. */ |
@@ -1229,7 +1267,6 @@ void rtl92se_disable_interrupt(struct ieee80211_hw *hw) | |||
1229 | synchronize_irq(rtlpci->pdev->irq); | 1267 | synchronize_irq(rtlpci->pdev->irq); |
1230 | } | 1268 | } |
1231 | 1269 | ||
1232 | |||
1233 | static u8 _rtl92s_set_sysclk(struct ieee80211_hw *hw, u8 data) | 1270 | static u8 _rtl92s_set_sysclk(struct ieee80211_hw *hw, u8 data) |
1234 | { | 1271 | { |
1235 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1272 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -1754,7 +1791,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw) | |||
1754 | } | 1791 | } |
1755 | 1792 | ||
1756 | for (i = 0; i < 14; i++) { | 1793 | for (i = 0; i < 14; i++) { |
1757 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1794 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1758 | "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n", | 1795 | "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n", |
1759 | rf_path, i, | 1796 | rf_path, i, |
1760 | rtlefuse->txpwrlevel_cck[rf_path][i], | 1797 | rtlefuse->txpwrlevel_cck[rf_path][i], |
@@ -1791,11 +1828,11 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw) | |||
1791 | ((rtlefuse->eeprom_pwrgroup[rf_path][index] & | 1828 | ((rtlefuse->eeprom_pwrgroup[rf_path][index] & |
1792 | 0xf0) >> 4); | 1829 | 0xf0) >> 4); |
1793 | 1830 | ||
1794 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1831 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1795 | "RF-%d pwrgroup_ht20[%d] = 0x%x\n", | 1832 | "RF-%d pwrgroup_ht20[%d] = 0x%x\n", |
1796 | rf_path, i, | 1833 | rf_path, i, |
1797 | rtlefuse->pwrgroup_ht20[rf_path][i]); | 1834 | rtlefuse->pwrgroup_ht20[rf_path][i]); |
1798 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1835 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1799 | "RF-%d pwrgroup_ht40[%d] = 0x%x\n", | 1836 | "RF-%d pwrgroup_ht40[%d] = 0x%x\n", |
1800 | rf_path, i, | 1837 | rf_path, i, |
1801 | rtlefuse->pwrgroup_ht40[rf_path][i]); | 1838 | rtlefuse->pwrgroup_ht40[rf_path][i]); |
@@ -1850,27 +1887,27 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw) | |||
1850 | rtlefuse->eeprom_regulatory = | 1887 | rtlefuse->eeprom_regulatory = |
1851 | (hwinfo[EEPROM_REGULATORY] & 0x1); | 1888 | (hwinfo[EEPROM_REGULATORY] & 0x1); |
1852 | } | 1889 | } |
1853 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1890 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1854 | "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); | 1891 | "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); |
1855 | 1892 | ||
1856 | for (i = 0; i < 14; i++) | 1893 | for (i = 0; i < 14; i++) |
1857 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1894 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1858 | "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", | 1895 | "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", |
1859 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); | 1896 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); |
1860 | for (i = 0; i < 14; i++) | 1897 | for (i = 0; i < 14; i++) |
1861 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1898 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1862 | "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", | 1899 | "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", |
1863 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); | 1900 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); |
1864 | for (i = 0; i < 14; i++) | 1901 | for (i = 0; i < 14; i++) |
1865 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1902 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1866 | "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", | 1903 | "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", |
1867 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); | 1904 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); |
1868 | for (i = 0; i < 14; i++) | 1905 | for (i = 0; i < 14; i++) |
1869 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1906 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1870 | "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", | 1907 | "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", |
1871 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); | 1908 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); |
1872 | 1909 | ||
1873 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1910 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1874 | "TxPwrSafetyFlag = %d\n", rtlefuse->txpwr_safetyflag); | 1911 | "TxPwrSafetyFlag = %d\n", rtlefuse->txpwr_safetyflag); |
1875 | 1912 | ||
1876 | /* Read RF-indication and Tx Power gain | 1913 | /* Read RF-indication and Tx Power gain |
@@ -1880,7 +1917,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw) | |||
1880 | rtlefuse->legacy_httxpowerdiff = | 1917 | rtlefuse->legacy_httxpowerdiff = |
1881 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][0]; | 1918 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][0]; |
1882 | 1919 | ||
1883 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1920 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1884 | "TxPowerDiff = %#x\n", rtlefuse->eeprom_txpowerdiff); | 1921 | "TxPowerDiff = %#x\n", rtlefuse->eeprom_txpowerdiff); |
1885 | 1922 | ||
1886 | /* Get TSSI value for each path. */ | 1923 | /* Get TSSI value for each path. */ |
@@ -1889,7 +1926,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw) | |||
1889 | usvalue = hwinfo[EEPROM_TSSI_B]; | 1926 | usvalue = hwinfo[EEPROM_TSSI_B]; |
1890 | rtlefuse->eeprom_tssi[RF90_PATH_B] = (u8)(usvalue & 0xff); | 1927 | rtlefuse->eeprom_tssi[RF90_PATH_B] = (u8)(usvalue & 0xff); |
1891 | 1928 | ||
1892 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, "TSSI_A = 0x%x, TSSI_B = 0x%x\n", | 1929 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, "TSSI_A = 0x%x, TSSI_B = 0x%x\n", |
1893 | rtlefuse->eeprom_tssi[RF90_PATH_A], | 1930 | rtlefuse->eeprom_tssi[RF90_PATH_A], |
1894 | rtlefuse->eeprom_tssi[RF90_PATH_B]); | 1931 | rtlefuse->eeprom_tssi[RF90_PATH_B]); |
1895 | 1932 | ||
@@ -1897,7 +1934,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw) | |||
1897 | /* and read ThermalMeter from EEPROM */ | 1934 | /* and read ThermalMeter from EEPROM */ |
1898 | tempval = hwinfo[EEPROM_THERMALMETER]; | 1935 | tempval = hwinfo[EEPROM_THERMALMETER]; |
1899 | rtlefuse->eeprom_thermalmeter = tempval; | 1936 | rtlefuse->eeprom_thermalmeter = tempval; |
1900 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1937 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1901 | "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); | 1938 | "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); |
1902 | 1939 | ||
1903 | /* ThermalMeter, BIT(0)~3 for RFIC1, BIT(4)~7 for RFIC2 */ | 1940 | /* ThermalMeter, BIT(0)~3 for RFIC1, BIT(4)~7 for RFIC2 */ |
@@ -1914,7 +1951,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw) | |||
1914 | /* Version ID, Channel plan */ | 1951 | /* Version ID, Channel plan */ |
1915 | rtlefuse->eeprom_channelplan = hwinfo[EEPROM_CHANNELPLAN]; | 1952 | rtlefuse->eeprom_channelplan = hwinfo[EEPROM_CHANNELPLAN]; |
1916 | rtlefuse->txpwr_fromeprom = true; | 1953 | rtlefuse->txpwr_fromeprom = true; |
1917 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1954 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1918 | "EEPROM ChannelPlan = 0x%4x\n", rtlefuse->eeprom_channelplan); | 1955 | "EEPROM ChannelPlan = 0x%4x\n", rtlefuse->eeprom_channelplan); |
1919 | 1956 | ||
1920 | /* Read Customer ID or Board Type!!! */ | 1957 | /* Read Customer ID or Board Type!!! */ |
@@ -1999,6 +2036,8 @@ static void rtl92se_update_hal_rate_table(struct ieee80211_hw *hw, | |||
1999 | ratr_value = sta->supp_rates[1] << 4; | 2036 | ratr_value = sta->supp_rates[1] << 4; |
2000 | else | 2037 | else |
2001 | ratr_value = sta->supp_rates[0]; | 2038 | ratr_value = sta->supp_rates[0]; |
2039 | if (mac->opmode == NL80211_IFTYPE_ADHOC) | ||
2040 | ratr_value = 0xfff; | ||
2002 | ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | | 2041 | ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | |
2003 | sta->ht_cap.mcs.rx_mask[0] << 12); | 2042 | sta->ht_cap.mcs.rx_mask[0] << 12); |
2004 | switch (wirelessmode) { | 2043 | switch (wirelessmode) { |
@@ -2112,6 +2151,8 @@ static void rtl92se_update_hal_rate_mask(struct ieee80211_hw *hw, | |||
2112 | ratr_bitmap = sta->supp_rates[1] << 4; | 2151 | ratr_bitmap = sta->supp_rates[1] << 4; |
2113 | else | 2152 | else |
2114 | ratr_bitmap = sta->supp_rates[0]; | 2153 | ratr_bitmap = sta->supp_rates[0]; |
2154 | if (mac->opmode == NL80211_IFTYPE_ADHOC) | ||
2155 | ratr_bitmap = 0xfff; | ||
2115 | ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | | 2156 | ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | |
2116 | sta->ht_cap.mcs.rx_mask[0] << 12); | 2157 | sta->ht_cap.mcs.rx_mask[0] << 12); |
2117 | switch (wirelessmode) { | 2158 | switch (wirelessmode) { |
@@ -2200,6 +2241,7 @@ static void rtl92se_update_hal_rate_mask(struct ieee80211_hw *hw, | |||
2200 | ratr_bitmap &= 0x0f8ff0ff; | 2241 | ratr_bitmap &= 0x0f8ff0ff; |
2201 | break; | 2242 | break; |
2202 | } | 2243 | } |
2244 | sta_entry->ratr_index = ratr_index; | ||
2203 | 2245 | ||
2204 | if (rtlpriv->rtlhal.version >= VERSION_8192S_BCUT) | 2246 | if (rtlpriv->rtlhal.version >= VERSION_8192S_BCUT) |
2205 | ratr_bitmap &= 0x0FFFFFFF; | 2247 | ratr_bitmap &= 0x0FFFFFFF; |
@@ -2438,23 +2480,9 @@ void rtl92se_set_key(struct ieee80211_hw *hw, u32 key_index, u8 *p_macaddr, | |||
2438 | rtl_cam_del_entry(hw, p_macaddr); | 2480 | rtl_cam_del_entry(hw, p_macaddr); |
2439 | rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); | 2481 | rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); |
2440 | } else { | 2482 | } else { |
2441 | RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, | ||
2442 | "The insert KEY length is %d\n", | ||
2443 | rtlpriv->sec.key_len[PAIRWISE_KEYIDX]); | ||
2444 | RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, | ||
2445 | "The insert KEY is %x %x\n", | ||
2446 | rtlpriv->sec.key_buf[0][0], | ||
2447 | rtlpriv->sec.key_buf[0][1]); | ||
2448 | |||
2449 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | 2483 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, |
2450 | "add one entry\n"); | 2484 | "add one entry\n"); |
2451 | if (is_pairwise) { | 2485 | if (is_pairwise) { |
2452 | RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD, | ||
2453 | "Pairwise Key content", | ||
2454 | rtlpriv->sec.pairwise_key, | ||
2455 | rtlpriv->sec. | ||
2456 | key_len[PAIRWISE_KEYIDX]); | ||
2457 | |||
2458 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | 2486 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, |
2459 | "set Pairwise key\n"); | 2487 | "set Pairwise key\n"); |
2460 | 2488 | ||
@@ -2502,3 +2530,23 @@ void rtl92se_resume(struct ieee80211_hw *hw) | |||
2502 | pci_write_config_dword(rtlpci->pdev, 0x40, | 2530 | pci_write_config_dword(rtlpci->pdev, 0x40, |
2503 | val & 0xffff00ff); | 2531 | val & 0xffff00ff); |
2504 | } | 2532 | } |
2533 | |||
2534 | /* Turn on AAP (RCR:bit 0) for promicuous mode. */ | ||
2535 | void rtl92se_allow_all_destaddr(struct ieee80211_hw *hw, | ||
2536 | bool allow_all_da, bool write_into_reg) | ||
2537 | { | ||
2538 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2539 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
2540 | |||
2541 | if (allow_all_da) /* Set BIT0 */ | ||
2542 | rtlpci->receive_config |= RCR_AAP; | ||
2543 | else /* Clear BIT0 */ | ||
2544 | rtlpci->receive_config &= ~RCR_AAP; | ||
2545 | |||
2546 | if (write_into_reg) | ||
2547 | rtl_write_dword(rtlpriv, RCR, rtlpci->receive_config); | ||
2548 | |||
2549 | RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD, | ||
2550 | "receive_config=0x%08X, write_into_reg=%d\n", | ||
2551 | rtlpci->receive_config, write_into_reg); | ||
2552 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.h b/drivers/net/wireless/rtlwifi/rtl8192se/hw.h index a8e068c76e47..da48aa8cbe6f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.h +++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.h | |||
@@ -74,6 +74,7 @@ void rtl92se_set_key(struct ieee80211_hw *hw, | |||
74 | u8 enc_algo, bool is_wepkey, bool clear_all); | 74 | u8 enc_algo, bool is_wepkey, bool clear_all); |
75 | void rtl92se_suspend(struct ieee80211_hw *hw); | 75 | void rtl92se_suspend(struct ieee80211_hw *hw); |
76 | void rtl92se_resume(struct ieee80211_hw *hw); | 76 | void rtl92se_resume(struct ieee80211_hw *hw); |
77 | void rtl92se_allow_all_destaddr(struct ieee80211_hw *hw, | ||
78 | bool allow_all_da, bool write_into_reg); | ||
77 | 79 | ||
78 | #endif | 80 | #endif |
79 | |||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c index 67404975e00b..9c092e6eb3fe 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c | |||
@@ -1307,6 +1307,8 @@ static void _rtl92s_phy_set_fwcmd_io(struct ieee80211_hw *hw) | |||
1307 | if (is_hal_stop(rtlhal)) | 1307 | if (is_hal_stop(rtlhal)) |
1308 | return; | 1308 | return; |
1309 | 1309 | ||
1310 | if (hal_get_firmwareversion(rtlpriv) < 0x34) | ||
1311 | goto skip; | ||
1310 | /* We re-map RA related CMD IO to combinational ones */ | 1312 | /* We re-map RA related CMD IO to combinational ones */ |
1311 | /* if FW version is v.52 or later. */ | 1313 | /* if FW version is v.52 or later. */ |
1312 | switch (rtlhal->current_fwcmd_io) { | 1314 | switch (rtlhal->current_fwcmd_io) { |
@@ -1320,6 +1322,7 @@ static void _rtl92s_phy_set_fwcmd_io(struct ieee80211_hw *hw) | |||
1320 | break; | 1322 | break; |
1321 | } | 1323 | } |
1322 | 1324 | ||
1325 | skip: | ||
1323 | switch (rtlhal->current_fwcmd_io) { | 1326 | switch (rtlhal->current_fwcmd_io) { |
1324 | case FW_CMD_RA_RESET: | 1327 | case FW_CMD_RA_RESET: |
1325 | RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_RA_RESET\n"); | 1328 | RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_RA_RESET\n"); |
@@ -1440,7 +1443,7 @@ bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio) | |||
1440 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | 1443 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); |
1441 | u32 fw_param = FW_CMD_IO_PARA_QUERY(rtlpriv); | 1444 | u32 fw_param = FW_CMD_IO_PARA_QUERY(rtlpriv); |
1442 | u16 fw_cmdmap = FW_CMD_IO_QUERY(rtlpriv); | 1445 | u16 fw_cmdmap = FW_CMD_IO_QUERY(rtlpriv); |
1443 | bool bPostProcessing = false; | 1446 | bool postprocessing = false; |
1444 | 1447 | ||
1445 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | 1448 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, |
1446 | "Set FW Cmd(%#x), set_fwcmd_inprogress(%d)\n", | 1449 | "Set FW Cmd(%#x), set_fwcmd_inprogress(%d)\n", |
@@ -1449,15 +1452,24 @@ bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio) | |||
1449 | do { | 1452 | do { |
1450 | /* We re-map to combined FW CMD ones if firmware version */ | 1453 | /* We re-map to combined FW CMD ones if firmware version */ |
1451 | /* is v.53 or later. */ | 1454 | /* is v.53 or later. */ |
1452 | switch (fw_cmdio) { | 1455 | if (hal_get_firmwareversion(rtlpriv) >= 0x35) { |
1453 | case FW_CMD_RA_REFRESH_N: | 1456 | switch (fw_cmdio) { |
1454 | fw_cmdio = FW_CMD_RA_REFRESH_N_COMB; | 1457 | case FW_CMD_RA_REFRESH_N: |
1455 | break; | 1458 | fw_cmdio = FW_CMD_RA_REFRESH_N_COMB; |
1456 | case FW_CMD_RA_REFRESH_BG: | 1459 | break; |
1457 | fw_cmdio = FW_CMD_RA_REFRESH_BG_COMB; | 1460 | case FW_CMD_RA_REFRESH_BG: |
1458 | break; | 1461 | fw_cmdio = FW_CMD_RA_REFRESH_BG_COMB; |
1459 | default: | 1462 | break; |
1460 | break; | 1463 | default: |
1464 | break; | ||
1465 | } | ||
1466 | } else { | ||
1467 | if ((fw_cmdio == FW_CMD_IQK_ENABLE) || | ||
1468 | (fw_cmdio == FW_CMD_RA_REFRESH_N) || | ||
1469 | (fw_cmdio == FW_CMD_RA_REFRESH_BG)) { | ||
1470 | postprocessing = true; | ||
1471 | break; | ||
1472 | } | ||
1461 | } | 1473 | } |
1462 | 1474 | ||
1463 | /* If firmware version is v.62 or later, | 1475 | /* If firmware version is v.62 or later, |
@@ -1588,19 +1600,19 @@ bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio) | |||
1588 | fw_cmdmap &= ~FW_DIG_ENABLE_CTL; | 1600 | fw_cmdmap &= ~FW_DIG_ENABLE_CTL; |
1589 | 1601 | ||
1590 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); | 1602 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); |
1591 | bPostProcessing = true; | 1603 | postprocessing = true; |
1592 | break; | 1604 | break; |
1593 | case FW_CMD_PAUSE_DM_BY_SCAN: | 1605 | case FW_CMD_PAUSE_DM_BY_SCAN: |
1594 | fw_cmdmap &= ~(FW_DIG_ENABLE_CTL | | 1606 | fw_cmdmap &= ~(FW_DIG_ENABLE_CTL | |
1595 | FW_HIGH_PWR_ENABLE_CTL | | 1607 | FW_HIGH_PWR_ENABLE_CTL | |
1596 | FW_SS_CTL); | 1608 | FW_SS_CTL); |
1597 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); | 1609 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); |
1598 | bPostProcessing = true; | 1610 | postprocessing = true; |
1599 | break; | 1611 | break; |
1600 | case FW_CMD_HIGH_PWR_DISABLE: | 1612 | case FW_CMD_HIGH_PWR_DISABLE: |
1601 | fw_cmdmap &= ~FW_HIGH_PWR_ENABLE_CTL; | 1613 | fw_cmdmap &= ~FW_HIGH_PWR_ENABLE_CTL; |
1602 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); | 1614 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); |
1603 | bPostProcessing = true; | 1615 | postprocessing = true; |
1604 | break; | 1616 | break; |
1605 | case FW_CMD_HIGH_PWR_ENABLE: | 1617 | case FW_CMD_HIGH_PWR_ENABLE: |
1606 | if (!(rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) && | 1618 | if (!(rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) && |
@@ -1608,7 +1620,7 @@ bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio) | |||
1608 | fw_cmdmap |= (FW_HIGH_PWR_ENABLE_CTL | | 1620 | fw_cmdmap |= (FW_HIGH_PWR_ENABLE_CTL | |
1609 | FW_SS_CTL); | 1621 | FW_SS_CTL); |
1610 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); | 1622 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); |
1611 | bPostProcessing = true; | 1623 | postprocessing = true; |
1612 | } | 1624 | } |
1613 | break; | 1625 | break; |
1614 | case FW_CMD_DIG_MODE_FA: | 1626 | case FW_CMD_DIG_MODE_FA: |
@@ -1629,14 +1641,15 @@ bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio) | |||
1629 | default: | 1641 | default: |
1630 | /* Pass to original FW CMD processing callback | 1642 | /* Pass to original FW CMD processing callback |
1631 | * routine. */ | 1643 | * routine. */ |
1632 | bPostProcessing = true; | 1644 | postprocessing = true; |
1633 | break; | 1645 | break; |
1634 | } | 1646 | } |
1635 | } while (false); | 1647 | } while (false); |
1636 | 1648 | ||
1637 | /* We shall post processing these FW CMD if | 1649 | /* We shall post processing these FW CMD if |
1638 | * variable bPostProcessing is set. */ | 1650 | * variable postprocessing is set. |
1639 | if (bPostProcessing && !rtlhal->set_fwcmd_inprogress) { | 1651 | */ |
1652 | if (postprocessing && !rtlhal->set_fwcmd_inprogress) { | ||
1640 | rtlhal->set_fwcmd_inprogress = true; | 1653 | rtlhal->set_fwcmd_inprogress = true; |
1641 | /* Update current FW Cmd for callback use. */ | 1654 | /* Update current FW Cmd for callback use. */ |
1642 | rtlhal->current_fwcmd_io = fw_cmdio; | 1655 | rtlhal->current_fwcmd_io = fw_cmdio; |
@@ -1697,8 +1710,18 @@ void rtl92s_phy_switch_ephy_parameter(struct ieee80211_hw *hw) | |||
1697 | 1710 | ||
1698 | } | 1711 | } |
1699 | 1712 | ||
1700 | void rtl92s_phy_set_beacon_hwreg(struct ieee80211_hw *hw, u16 BeaconInterval) | 1713 | void rtl92s_phy_set_beacon_hwreg(struct ieee80211_hw *hw, u16 beaconinterval) |
1701 | { | 1714 | { |
1702 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1715 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1703 | rtl_write_dword(rtlpriv, WFM5, 0xF1000000 | (BeaconInterval << 8)); | 1716 | u32 new_bcn_num = 0; |
1717 | |||
1718 | if (hal_get_firmwareversion(rtlpriv) >= 0x33) { | ||
1719 | /* Fw v.51 and later. */ | ||
1720 | rtl_write_dword(rtlpriv, WFM5, 0xF1000000 | | ||
1721 | (beaconinterval << 8)); | ||
1722 | } else { | ||
1723 | new_bcn_num = beaconinterval * 32 - 64; | ||
1724 | rtl_write_dword(rtlpriv, WFM3 + 4, new_bcn_num); | ||
1725 | rtl_write_dword(rtlpriv, WFM3, 0xB026007C); | ||
1726 | } | ||
1704 | } | 1727 | } |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.h b/drivers/net/wireless/rtlwifi/rtl8192se/phy.h index ac0387770630..8acf4765a7a6 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.h +++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.h | |||
@@ -39,6 +39,7 @@ | |||
39 | #define MAX_POSTCMD_CNT 16 | 39 | #define MAX_POSTCMD_CNT 16 |
40 | 40 | ||
41 | #define RF90_PATH_MAX 4 | 41 | #define RF90_PATH_MAX 4 |
42 | #define RF6052_MAX_PATH 2 | ||
42 | 43 | ||
43 | enum version_8192s { | 44 | enum version_8192s { |
44 | VERSION_8192S_ACUT, | 45 | VERSION_8192S_ACUT, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c index cecc377e9e61..2e8e6f8d2d51 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c | |||
@@ -290,6 +290,7 @@ static struct rtl_hal_ops rtl8192se_hal_ops = { | |||
290 | .enable_hw_sec = rtl92se_enable_hw_security_config, | 290 | .enable_hw_sec = rtl92se_enable_hw_security_config, |
291 | .set_key = rtl92se_set_key, | 291 | .set_key = rtl92se_set_key, |
292 | .init_sw_leds = rtl92se_init_sw_leds, | 292 | .init_sw_leds = rtl92se_init_sw_leds, |
293 | .allow_all_destaddr = rtl92se_allow_all_destaddr, | ||
293 | .get_bbreg = rtl92s_phy_query_bb_reg, | 294 | .get_bbreg = rtl92s_phy_query_bb_reg, |
294 | .set_bbreg = rtl92s_phy_set_bb_reg, | 295 | .set_bbreg = rtl92s_phy_set_bb_reg, |
295 | .get_rfreg = rtl92s_phy_query_rf_reg, | 296 | .get_rfreg = rtl92s_phy_query_rf_reg, |
@@ -366,7 +367,7 @@ static struct rtl_hal_cfg rtl92se_hal_cfg = { | |||
366 | 367 | ||
367 | .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, | 368 | .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, |
368 | .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, | 369 | .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, |
369 | .maps[RTL_IMR_BcnInt] = IMR_BCNINT, | 370 | .maps[RTL_IMR_BCNINT] = IMR_BCNINT, |
370 | .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, | 371 | .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, |
371 | .maps[RTL_IMR_RDU] = IMR_RDU, | 372 | .maps[RTL_IMR_RDU] = IMR_RDU, |
372 | .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, | 373 | .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c index 7b0a2e75b8b8..960bc28cc51e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "../wifi.h" | 30 | #include "../wifi.h" |
31 | #include "../pci.h" | 31 | #include "../pci.h" |
32 | #include "../base.h" | 32 | #include "../base.h" |
33 | #include "../stats.h" | ||
33 | #include "reg.h" | 34 | #include "reg.h" |
34 | #include "def.h" | 35 | #include "def.h" |
35 | #include "phy.h" | 36 | #include "phy.h" |
@@ -43,7 +44,7 @@ static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 skb_queue) | |||
43 | 44 | ||
44 | if (unlikely(ieee80211_is_beacon(fc))) | 45 | if (unlikely(ieee80211_is_beacon(fc))) |
45 | return QSLT_BEACON; | 46 | return QSLT_BEACON; |
46 | if (ieee80211_is_mgmt(fc)) | 47 | if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) |
47 | return QSLT_MGNT; | 48 | return QSLT_MGNT; |
48 | if (ieee80211_is_nullfunc(fc)) | 49 | if (ieee80211_is_nullfunc(fc)) |
49 | return QSLT_HIGH; | 50 | return QSLT_HIGH; |
@@ -51,65 +52,6 @@ static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 skb_queue) | |||
51 | return skb->priority; | 52 | return skb->priority; |
52 | } | 53 | } |
53 | 54 | ||
54 | static u8 _rtl92s_query_rxpwrpercentage(char antpower) | ||
55 | { | ||
56 | if ((antpower <= -100) || (antpower >= 20)) | ||
57 | return 0; | ||
58 | else if (antpower >= 0) | ||
59 | return 100; | ||
60 | else | ||
61 | return 100 + antpower; | ||
62 | } | ||
63 | |||
64 | static u8 _rtl92s_evm_db_to_percentage(char value) | ||
65 | { | ||
66 | char ret_val; | ||
67 | ret_val = value; | ||
68 | |||
69 | if (ret_val >= 0) | ||
70 | ret_val = 0; | ||
71 | |||
72 | if (ret_val <= -33) | ||
73 | ret_val = -33; | ||
74 | |||
75 | ret_val = 0 - ret_val; | ||
76 | ret_val *= 3; | ||
77 | |||
78 | if (ret_val == 99) | ||
79 | ret_val = 100; | ||
80 | |||
81 | return ret_val; | ||
82 | } | ||
83 | |||
84 | static long _rtl92se_translate_todbm(struct ieee80211_hw *hw, | ||
85 | u8 signal_strength_index) | ||
86 | { | ||
87 | long signal_power; | ||
88 | |||
89 | signal_power = (long)((signal_strength_index + 1) >> 1); | ||
90 | signal_power -= 95; | ||
91 | return signal_power; | ||
92 | } | ||
93 | |||
94 | static long _rtl92se_signal_scale_mapping(struct ieee80211_hw *hw, | ||
95 | long currsig) | ||
96 | { | ||
97 | long retsig = 0; | ||
98 | |||
99 | /* Step 1. Scale mapping. */ | ||
100 | if (currsig > 47) | ||
101 | retsig = 100; | ||
102 | else if (currsig > 14 && currsig <= 47) | ||
103 | retsig = 100 - ((47 - currsig) * 3) / 2; | ||
104 | else if (currsig > 2 && currsig <= 14) | ||
105 | retsig = 48 - ((14 - currsig) * 15) / 7; | ||
106 | else if (currsig >= 0) | ||
107 | retsig = currsig * 9 + 1; | ||
108 | |||
109 | return retsig; | ||
110 | } | ||
111 | |||
112 | |||
113 | static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, | 55 | static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, |
114 | struct rtl_stats *pstats, u8 *pdesc, | 56 | struct rtl_stats *pstats, u8 *pdesc, |
115 | struct rx_fwinfo *p_drvinfo, | 57 | struct rx_fwinfo *p_drvinfo, |
@@ -119,11 +61,11 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, | |||
119 | { | 61 | { |
120 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 62 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
121 | struct phy_sts_cck_8192s_t *cck_buf; | 63 | struct phy_sts_cck_8192s_t *cck_buf; |
64 | struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); | ||
122 | s8 rx_pwr_all = 0, rx_pwr[4]; | 65 | s8 rx_pwr_all = 0, rx_pwr[4]; |
123 | u8 rf_rx_num = 0, evm, pwdb_all; | 66 | u8 rf_rx_num = 0, evm, pwdb_all; |
124 | u8 i, max_spatial_stream; | 67 | u8 i, max_spatial_stream; |
125 | u32 rssi, total_rssi = 0; | 68 | u32 rssi, total_rssi = 0; |
126 | bool in_powersavemode = false; | ||
127 | bool is_cck = pstats->is_cck; | 69 | bool is_cck = pstats->is_cck; |
128 | 70 | ||
129 | pstats->packet_matchbssid = packet_match_bssid; | 71 | pstats->packet_matchbssid = packet_match_bssid; |
@@ -136,7 +78,7 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, | |||
136 | u8 report, cck_highpwr; | 78 | u8 report, cck_highpwr; |
137 | cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; | 79 | cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; |
138 | 80 | ||
139 | if (!in_powersavemode) | 81 | if (ppsc->rfpwr_state == ERFON) |
140 | cck_highpwr = (u8) rtl_get_bbreg(hw, | 82 | cck_highpwr = (u8) rtl_get_bbreg(hw, |
141 | RFPGA0_XA_HSSIPARAMETER2, | 83 | RFPGA0_XA_HSSIPARAMETER2, |
142 | 0x200); | 84 | 0x200); |
@@ -181,7 +123,7 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, | |||
181 | } | 123 | } |
182 | } | 124 | } |
183 | 125 | ||
184 | pwdb_all = _rtl92s_query_rxpwrpercentage(rx_pwr_all); | 126 | pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); |
185 | 127 | ||
186 | /* CCK gain is smaller than OFDM/MCS gain, */ | 128 | /* CCK gain is smaller than OFDM/MCS gain, */ |
187 | /* so we add gain diff by experiences, the val is 6 */ | 129 | /* so we add gain diff by experiences, the val is 6 */ |
@@ -222,13 +164,13 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, | |||
222 | } else { | 164 | } else { |
223 | rtlpriv->dm.rfpath_rxenable[0] = | 165 | rtlpriv->dm.rfpath_rxenable[0] = |
224 | rtlpriv->dm.rfpath_rxenable[1] = true; | 166 | rtlpriv->dm.rfpath_rxenable[1] = true; |
225 | for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) { | 167 | for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) { |
226 | if (rtlpriv->dm.rfpath_rxenable[i]) | 168 | if (rtlpriv->dm.rfpath_rxenable[i]) |
227 | rf_rx_num++; | 169 | rf_rx_num++; |
228 | 170 | ||
229 | rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & | 171 | rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & |
230 | 0x3f) * 2) - 110; | 172 | 0x3f) * 2) - 110; |
231 | rssi = _rtl92s_query_rxpwrpercentage(rx_pwr[i]); | 173 | rssi = rtl_query_rxpwrpercentage(rx_pwr[i]); |
232 | total_rssi += rssi; | 174 | total_rssi += rssi; |
233 | rtlpriv->stats.rx_snr_db[i] = | 175 | rtlpriv->stats.rx_snr_db[i] = |
234 | (long)(p_drvinfo->rxsnr[i] / 2); | 176 | (long)(p_drvinfo->rxsnr[i] / 2); |
@@ -238,7 +180,7 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, | |||
238 | } | 180 | } |
239 | 181 | ||
240 | rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; | 182 | rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; |
241 | pwdb_all = _rtl92s_query_rxpwrpercentage(rx_pwr_all); | 183 | pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); |
242 | pstats->rx_pwdb_all = pwdb_all; | 184 | pstats->rx_pwdb_all = pwdb_all; |
243 | pstats->rxpower = rx_pwr_all; | 185 | pstats->rxpower = rx_pwr_all; |
244 | pstats->recvsignalpower = rx_pwr_all; | 186 | pstats->recvsignalpower = rx_pwr_all; |
@@ -250,7 +192,7 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, | |||
250 | max_spatial_stream = 1; | 192 | max_spatial_stream = 1; |
251 | 193 | ||
252 | for (i = 0; i < max_spatial_stream; i++) { | 194 | for (i = 0; i < max_spatial_stream; i++) { |
253 | evm = _rtl92s_evm_db_to_percentage(p_drvinfo->rxevm[i]); | 195 | evm = rtl_evm_db_to_percentage(p_drvinfo->rxevm[i]); |
254 | 196 | ||
255 | if (packet_match_bssid) { | 197 | if (packet_match_bssid) { |
256 | if (i == 0) | 198 | if (i == 0) |
@@ -262,212 +204,13 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, | |||
262 | } | 204 | } |
263 | 205 | ||
264 | if (is_cck) | 206 | if (is_cck) |
265 | pstats->signalstrength = (u8)(_rtl92se_signal_scale_mapping(hw, | 207 | pstats->signalstrength = (u8)(rtl_signal_scale_mapping(hw, |
266 | pwdb_all)); | 208 | pwdb_all)); |
267 | else if (rf_rx_num != 0) | 209 | else if (rf_rx_num != 0) |
268 | pstats->signalstrength = (u8) (_rtl92se_signal_scale_mapping(hw, | 210 | pstats->signalstrength = (u8) (rtl_signal_scale_mapping(hw, |
269 | total_rssi /= rf_rx_num)); | 211 | total_rssi /= rf_rx_num)); |
270 | } | 212 | } |
271 | 213 | ||
272 | static void _rtl92se_process_ui_rssi(struct ieee80211_hw *hw, | ||
273 | struct rtl_stats *pstats) | ||
274 | { | ||
275 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
276 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
277 | u8 rfpath; | ||
278 | u32 last_rssi, tmpval; | ||
279 | |||
280 | if (pstats->packet_toself || pstats->packet_beacon) { | ||
281 | rtlpriv->stats.rssi_calculate_cnt++; | ||
282 | |||
283 | if (rtlpriv->stats.ui_rssi.total_num++ >= | ||
284 | PHY_RSSI_SLID_WIN_MAX) { | ||
285 | rtlpriv->stats.ui_rssi.total_num = | ||
286 | PHY_RSSI_SLID_WIN_MAX; | ||
287 | last_rssi = rtlpriv->stats.ui_rssi.elements[ | ||
288 | rtlpriv->stats.ui_rssi.index]; | ||
289 | rtlpriv->stats.ui_rssi.total_val -= last_rssi; | ||
290 | } | ||
291 | |||
292 | rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength; | ||
293 | rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi.index++] | ||
294 | = pstats->signalstrength; | ||
295 | |||
296 | if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX) | ||
297 | rtlpriv->stats.ui_rssi.index = 0; | ||
298 | |||
299 | tmpval = rtlpriv->stats.ui_rssi.total_val / | ||
300 | rtlpriv->stats.ui_rssi.total_num; | ||
301 | rtlpriv->stats.signal_strength = _rtl92se_translate_todbm(hw, | ||
302 | (u8) tmpval); | ||
303 | pstats->rssi = rtlpriv->stats.signal_strength; | ||
304 | } | ||
305 | |||
306 | if (!pstats->is_cck && pstats->packet_toself) { | ||
307 | for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; | ||
308 | rfpath++) { | ||
309 | if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) { | ||
310 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
311 | pstats->rx_mimo_signalstrength[rfpath]; | ||
312 | |||
313 | } | ||
314 | |||
315 | if (pstats->rx_mimo_signalstrength[rfpath] > | ||
316 | rtlpriv->stats.rx_rssi_percentage[rfpath]) { | ||
317 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
318 | ((rtlpriv->stats.rx_rssi_percentage[rfpath] | ||
319 | * (RX_SMOOTH_FACTOR - 1)) + | ||
320 | (pstats->rx_mimo_signalstrength[rfpath])) / | ||
321 | (RX_SMOOTH_FACTOR); | ||
322 | |||
323 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
324 | rtlpriv->stats.rx_rssi_percentage[rfpath] | ||
325 | + 1; | ||
326 | } else { | ||
327 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
328 | ((rtlpriv->stats.rx_rssi_percentage[rfpath] | ||
329 | * (RX_SMOOTH_FACTOR - 1)) + | ||
330 | (pstats->rx_mimo_signalstrength[rfpath])) / | ||
331 | (RX_SMOOTH_FACTOR); | ||
332 | } | ||
333 | |||
334 | } | ||
335 | } | ||
336 | } | ||
337 | |||
338 | static void _rtl92se_update_rxsignalstatistics(struct ieee80211_hw *hw, | ||
339 | struct rtl_stats *pstats) | ||
340 | { | ||
341 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
342 | int weighting = 0; | ||
343 | |||
344 | if (rtlpriv->stats.recv_signal_power == 0) | ||
345 | rtlpriv->stats.recv_signal_power = pstats->recvsignalpower; | ||
346 | |||
347 | if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power) | ||
348 | weighting = 5; | ||
349 | else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power) | ||
350 | weighting = (-5); | ||
351 | |||
352 | rtlpriv->stats.recv_signal_power = (rtlpriv->stats.recv_signal_power * 5 | ||
353 | + pstats->recvsignalpower + | ||
354 | weighting) / 6; | ||
355 | } | ||
356 | |||
357 | static void _rtl92se_process_pwdb(struct ieee80211_hw *hw, | ||
358 | struct rtl_stats *pstats) | ||
359 | { | ||
360 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
361 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
362 | long undec_sm_pwdb = 0; | ||
363 | |||
364 | if (mac->opmode == NL80211_IFTYPE_ADHOC) { | ||
365 | return; | ||
366 | } else { | ||
367 | undec_sm_pwdb = | ||
368 | rtlpriv->dm.undec_sm_pwdb; | ||
369 | } | ||
370 | |||
371 | if (pstats->packet_toself || pstats->packet_beacon) { | ||
372 | if (undec_sm_pwdb < 0) | ||
373 | undec_sm_pwdb = pstats->rx_pwdb_all; | ||
374 | |||
375 | if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) { | ||
376 | undec_sm_pwdb = | ||
377 | (((undec_sm_pwdb) * | ||
378 | (RX_SMOOTH_FACTOR - 1)) + | ||
379 | (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); | ||
380 | |||
381 | undec_sm_pwdb = undec_sm_pwdb + 1; | ||
382 | } else { | ||
383 | undec_sm_pwdb = (((undec_sm_pwdb) * | ||
384 | (RX_SMOOTH_FACTOR - 1)) + (pstats->rx_pwdb_all)) / | ||
385 | (RX_SMOOTH_FACTOR); | ||
386 | } | ||
387 | |||
388 | rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb; | ||
389 | _rtl92se_update_rxsignalstatistics(hw, pstats); | ||
390 | } | ||
391 | } | ||
392 | |||
393 | static void rtl_92s_process_streams(struct ieee80211_hw *hw, | ||
394 | struct rtl_stats *pstats) | ||
395 | { | ||
396 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
397 | u32 stream; | ||
398 | |||
399 | for (stream = 0; stream < 2; stream++) { | ||
400 | if (pstats->rx_mimo_sig_qual[stream] != -1) { | ||
401 | if (rtlpriv->stats.rx_evm_percentage[stream] == 0) { | ||
402 | rtlpriv->stats.rx_evm_percentage[stream] = | ||
403 | pstats->rx_mimo_sig_qual[stream]; | ||
404 | } | ||
405 | |||
406 | rtlpriv->stats.rx_evm_percentage[stream] = | ||
407 | ((rtlpriv->stats.rx_evm_percentage[stream] * | ||
408 | (RX_SMOOTH_FACTOR - 1)) + | ||
409 | (pstats->rx_mimo_sig_qual[stream] * | ||
410 | 1)) / (RX_SMOOTH_FACTOR); | ||
411 | } | ||
412 | } | ||
413 | } | ||
414 | |||
415 | static void _rtl92se_process_ui_link_quality(struct ieee80211_hw *hw, | ||
416 | struct rtl_stats *pstats) | ||
417 | { | ||
418 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
419 | u32 last_evm = 0, tmpval; | ||
420 | |||
421 | if (pstats->signalquality != 0) { | ||
422 | if (pstats->packet_toself || pstats->packet_beacon) { | ||
423 | |||
424 | if (rtlpriv->stats.ui_link_quality.total_num++ >= | ||
425 | PHY_LINKQUALITY_SLID_WIN_MAX) { | ||
426 | rtlpriv->stats.ui_link_quality.total_num = | ||
427 | PHY_LINKQUALITY_SLID_WIN_MAX; | ||
428 | last_evm = | ||
429 | rtlpriv->stats.ui_link_quality.elements[ | ||
430 | rtlpriv->stats.ui_link_quality.index]; | ||
431 | rtlpriv->stats.ui_link_quality.total_val -= | ||
432 | last_evm; | ||
433 | } | ||
434 | |||
435 | rtlpriv->stats.ui_link_quality.total_val += | ||
436 | pstats->signalquality; | ||
437 | rtlpriv->stats.ui_link_quality.elements[ | ||
438 | rtlpriv->stats.ui_link_quality.index++] = | ||
439 | pstats->signalquality; | ||
440 | |||
441 | if (rtlpriv->stats.ui_link_quality.index >= | ||
442 | PHY_LINKQUALITY_SLID_WIN_MAX) | ||
443 | rtlpriv->stats.ui_link_quality.index = 0; | ||
444 | |||
445 | tmpval = rtlpriv->stats.ui_link_quality.total_val / | ||
446 | rtlpriv->stats.ui_link_quality.total_num; | ||
447 | rtlpriv->stats.signal_quality = tmpval; | ||
448 | |||
449 | rtlpriv->stats.last_sigstrength_inpercent = tmpval; | ||
450 | |||
451 | rtl_92s_process_streams(hw, pstats); | ||
452 | |||
453 | } | ||
454 | } | ||
455 | } | ||
456 | |||
457 | static void _rtl92se_process_phyinfo(struct ieee80211_hw *hw, | ||
458 | u8 *buffer, | ||
459 | struct rtl_stats *pcurrent_stats) | ||
460 | { | ||
461 | |||
462 | if (!pcurrent_stats->packet_matchbssid && | ||
463 | !pcurrent_stats->packet_beacon) | ||
464 | return; | ||
465 | |||
466 | _rtl92se_process_ui_rssi(hw, pcurrent_stats); | ||
467 | _rtl92se_process_pwdb(hw, pcurrent_stats); | ||
468 | _rtl92se_process_ui_link_quality(hw, pcurrent_stats); | ||
469 | } | ||
470 | |||
471 | static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw, | 214 | static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw, |
472 | struct sk_buff *skb, struct rtl_stats *pstats, | 215 | struct sk_buff *skb, struct rtl_stats *pstats, |
473 | u8 *pdesc, struct rx_fwinfo *p_drvinfo) | 216 | u8 *pdesc, struct rx_fwinfo *p_drvinfo) |
@@ -505,7 +248,7 @@ static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw, | |||
505 | 248 | ||
506 | _rtl92se_query_rxphystatus(hw, pstats, pdesc, p_drvinfo, | 249 | _rtl92se_query_rxphystatus(hw, pstats, pdesc, p_drvinfo, |
507 | packet_matchbssid, packet_toself, packet_beacon); | 250 | packet_matchbssid, packet_toself, packet_beacon); |
508 | _rtl92se_process_phyinfo(hw, tmp_buf, pstats); | 251 | rtl_process_phyinfo(hw, tmp_buf, pstats); |
509 | } | 252 | } |
510 | 253 | ||
511 | bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, | 254 | bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, |
@@ -541,9 +284,6 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, | |||
541 | rx_status->freq = hw->conf.channel->center_freq; | 284 | rx_status->freq = hw->conf.channel->center_freq; |
542 | rx_status->band = hw->conf.channel->band; | 285 | rx_status->band = hw->conf.channel->band; |
543 | 286 | ||
544 | hdr = (struct ieee80211_hdr *)(skb->data + stats->rx_drvinfo_size | ||
545 | + stats->rx_bufshift); | ||
546 | |||
547 | if (stats->crc) | 287 | if (stats->crc) |
548 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; | 288 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; |
549 | 289 | ||
@@ -563,6 +303,13 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, | |||
563 | * for IEEE80211w frame, and mac80211 sw will help | 303 | * for IEEE80211w frame, and mac80211 sw will help |
564 | * to decrypt it */ | 304 | * to decrypt it */ |
565 | if (stats->decrypted) { | 305 | if (stats->decrypted) { |
306 | hdr = (struct ieee80211_hdr *)(skb->data + | ||
307 | stats->rx_drvinfo_size + stats->rx_bufshift); | ||
308 | |||
309 | if (!hdr) { | ||
310 | /* during testing, hdr was NULL here */ | ||
311 | return false; | ||
312 | } | ||
566 | if ((ieee80211_is_robust_mgmt_frame(hdr)) && | 313 | if ((ieee80211_is_robust_mgmt_frame(hdr)) && |
567 | (ieee80211_has_protected(hdr->frame_control))) | 314 | (ieee80211_has_protected(hdr->frame_control))) |
568 | rx_status->flag &= ~RX_FLAG_DECRYPTED; | 315 | rx_status->flag &= ~RX_FLAG_DECRYPTED; |
@@ -630,6 +377,11 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, | |||
630 | 377 | ||
631 | CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE_RTL8192S); | 378 | CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE_RTL8192S); |
632 | 379 | ||
380 | if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { | ||
381 | firstseg = true; | ||
382 | lastseg = true; | ||
383 | } | ||
384 | |||
633 | if (firstseg) { | 385 | if (firstseg) { |
634 | if (rtlpriv->dm.useramask) { | 386 | if (rtlpriv->dm.useramask) { |
635 | /* set txdesc macId */ | 387 | /* set txdesc macId */ |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c b/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c index 12e2a3cb0701..a36eee28f9e7 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c | |||
@@ -166,8 +166,8 @@ static void rtl8723ae_dm_diginit(struct ieee80211_hw *hw) | |||
166 | dm_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH; | 166 | dm_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH; |
167 | dm_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW; | 167 | dm_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW; |
168 | dm_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH; | 168 | dm_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH; |
169 | dm_digtable->rx_gain_range_max = DM_DIG_MAX; | 169 | dm_digtable->rx_gain_max = DM_DIG_MAX; |
170 | dm_digtable->rx_gain_range_min = DM_DIG_MIN; | 170 | dm_digtable->rx_gain_min = DM_DIG_MIN; |
171 | dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT; | 171 | dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT; |
172 | dm_digtable->back_range_max = DM_DIG_BACKOFF_MAX; | 172 | dm_digtable->back_range_max = DM_DIG_BACKOFF_MAX; |
173 | dm_digtable->back_range_min = DM_DIG_BACKOFF_MIN; | 173 | dm_digtable->back_range_min = DM_DIG_BACKOFF_MIN; |
@@ -291,11 +291,11 @@ static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw) | |||
291 | } | 291 | } |
292 | 292 | ||
293 | if ((dgtbl->rssi_val_min + 10 - dgtbl->back_val) > | 293 | if ((dgtbl->rssi_val_min + 10 - dgtbl->back_val) > |
294 | dgtbl->rx_gain_range_max) | 294 | dgtbl->rx_gain_max) |
295 | dgtbl->cur_igvalue = dgtbl->rx_gain_range_max; | 295 | dgtbl->cur_igvalue = dgtbl->rx_gain_max; |
296 | else if ((dgtbl->rssi_val_min + 10 - | 296 | else if ((dgtbl->rssi_val_min + 10 - |
297 | dgtbl->back_val) < dgtbl->rx_gain_range_min) | 297 | dgtbl->back_val) < dgtbl->rx_gain_min) |
298 | dgtbl->cur_igvalue = dgtbl->rx_gain_range_min; | 298 | dgtbl->cur_igvalue = dgtbl->rx_gain_min; |
299 | else | 299 | else |
300 | dgtbl->cur_igvalue = dgtbl->rssi_val_min + 10 - dgtbl->back_val; | 300 | dgtbl->cur_igvalue = dgtbl->rssi_val_min + 10 - dgtbl->back_val; |
301 | 301 | ||
@@ -707,6 +707,77 @@ void rtl8723ae_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) | |||
707 | rtlpriv->dm.useramask = false; | 707 | rtlpriv->dm.useramask = false; |
708 | } | 708 | } |
709 | 709 | ||
710 | static void rtl8723ae_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) | ||
711 | { | ||
712 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
713 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
714 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
715 | struct rate_adaptive *p_ra = &(rtlpriv->ra); | ||
716 | u32 low_rssithresh_for_ra, high_rssithresh_for_ra; | ||
717 | struct ieee80211_sta *sta = NULL; | ||
718 | |||
719 | if (is_hal_stop(rtlhal)) { | ||
720 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
721 | " driver is going to unload\n"); | ||
722 | return; | ||
723 | } | ||
724 | |||
725 | if (!rtlpriv->dm.useramask) { | ||
726 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
727 | " driver does not control rate adaptive mask\n"); | ||
728 | return; | ||
729 | } | ||
730 | |||
731 | if (mac->link_state == MAC80211_LINKED && | ||
732 | mac->opmode == NL80211_IFTYPE_STATION) { | ||
733 | switch (p_ra->pre_ratr_state) { | ||
734 | case DM_RATR_STA_HIGH: | ||
735 | high_rssithresh_for_ra = 50; | ||
736 | low_rssithresh_for_ra = 20; | ||
737 | break; | ||
738 | case DM_RATR_STA_MIDDLE: | ||
739 | high_rssithresh_for_ra = 55; | ||
740 | low_rssithresh_for_ra = 20; | ||
741 | break; | ||
742 | case DM_RATR_STA_LOW: | ||
743 | high_rssithresh_for_ra = 50; | ||
744 | low_rssithresh_for_ra = 25; | ||
745 | break; | ||
746 | default: | ||
747 | high_rssithresh_for_ra = 50; | ||
748 | low_rssithresh_for_ra = 20; | ||
749 | break; | ||
750 | } | ||
751 | |||
752 | if (rtlpriv->dm.undec_sm_pwdb > high_rssithresh_for_ra) | ||
753 | p_ra->ratr_state = DM_RATR_STA_HIGH; | ||
754 | else if (rtlpriv->dm.undec_sm_pwdb > low_rssithresh_for_ra) | ||
755 | p_ra->ratr_state = DM_RATR_STA_MIDDLE; | ||
756 | else | ||
757 | p_ra->ratr_state = DM_RATR_STA_LOW; | ||
758 | |||
759 | if (p_ra->pre_ratr_state != p_ra->ratr_state) { | ||
760 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
761 | "RSSI = %ld\n", | ||
762 | rtlpriv->dm.undec_sm_pwdb); | ||
763 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
764 | "RSSI_LEVEL = %d\n", p_ra->ratr_state); | ||
765 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, | ||
766 | "PreState = %d, CurState = %d\n", | ||
767 | p_ra->pre_ratr_state, p_ra->ratr_state); | ||
768 | |||
769 | rcu_read_lock(); | ||
770 | sta = rtl_find_sta(hw, mac->bssid); | ||
771 | if (sta) | ||
772 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, | ||
773 | p_ra->ratr_state); | ||
774 | rcu_read_unlock(); | ||
775 | |||
776 | p_ra->pre_ratr_state = p_ra->ratr_state; | ||
777 | } | ||
778 | } | ||
779 | } | ||
780 | |||
710 | static void rtl8723ae_dm_init_dynamic_bpowersaving(struct ieee80211_hw *hw) | 781 | static void rtl8723ae_dm_init_dynamic_bpowersaving(struct ieee80211_hw *hw) |
711 | { | 782 | { |
712 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 783 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -853,6 +924,9 @@ void rtl8723ae_dm_watchdog(struct ieee80211_hw *hw) | |||
853 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, | 924 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, |
854 | (u8 *) (&fw_ps_awake)); | 925 | (u8 *) (&fw_ps_awake)); |
855 | 926 | ||
927 | if (ppsc->p2p_ps_info.p2p_ps_mode) | ||
928 | fw_ps_awake = false; | ||
929 | |||
856 | if ((ppsc->rfpwr_state == ERFON) && | 930 | if ((ppsc->rfpwr_state == ERFON) && |
857 | ((!fw_current_inpsmode) && fw_ps_awake) && | 931 | ((!fw_current_inpsmode) && fw_ps_awake) && |
858 | (!ppsc->rfchange_inprogress)) { | 932 | (!ppsc->rfchange_inprogress)) { |
@@ -861,7 +935,7 @@ void rtl8723ae_dm_watchdog(struct ieee80211_hw *hw) | |||
861 | rtl8723ae_dm_false_alarm_counter_statistics(hw); | 935 | rtl8723ae_dm_false_alarm_counter_statistics(hw); |
862 | rtl8723ae_dm_dynamic_bpowersaving(hw); | 936 | rtl8723ae_dm_dynamic_bpowersaving(hw); |
863 | rtl8723ae_dm_dynamic_txpower(hw); | 937 | rtl8723ae_dm_dynamic_txpower(hw); |
864 | /* rtl92c_dm_refresh_rate_adaptive_mask(hw); */ | 938 | rtl8723ae_dm_refresh_rate_adaptive_mask(hw); |
865 | rtl8723ae_dm_bt_coexist(hw); | 939 | rtl8723ae_dm_bt_coexist(hw); |
866 | rtl8723ae_dm_check_edca_turbo(hw); | 940 | rtl8723ae_dm_check_edca_turbo(hw); |
867 | } | 941 | } |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h b/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h index 39d246196247..a372b0204456 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h | |||
@@ -55,7 +55,13 @@ | |||
55 | #define DM_DIG_BACKOFF_MIN -4 | 55 | #define DM_DIG_BACKOFF_MIN -4 |
56 | #define DM_DIG_BACKOFF_DEFAULT 10 | 56 | #define DM_DIG_BACKOFF_DEFAULT 10 |
57 | 57 | ||
58 | #define RXPATHSELECTION_SS_TH_LOW 30 | ||
59 | #define RXPATHSELECTION_DIFF_TH 18 | ||
60 | |||
58 | #define DM_RATR_STA_INIT 0 | 61 | #define DM_RATR_STA_INIT 0 |
62 | #define DM_RATR_STA_HIGH 1 | ||
63 | #define DM_RATR_STA_MIDDLE 2 | ||
64 | #define DM_RATR_STA_LOW 3 | ||
59 | 65 | ||
60 | #define TXHIGHPWRLEVEL_NORMAL 0 | 66 | #define TXHIGHPWRLEVEL_NORMAL 0 |
61 | #define TXHIGHPWRLEVEL_LEVEL1 1 | 67 | #define TXHIGHPWRLEVEL_LEVEL1 1 |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c index 35cb8f83eed4..dedfa1ed3e02 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c | |||
@@ -494,7 +494,9 @@ void rtl8723ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) | |||
494 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); | 494 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); |
495 | 495 | ||
496 | SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode); | 496 | SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode); |
497 | SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 1); | 497 | SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, |
498 | (rtlpriv->mac80211.p2p) ? | ||
499 | ppsc->smart_ps : 1); | ||
498 | SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode, | 500 | SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode, |
499 | ppsc->reg_max_lps_awakeintvl); | 501 | ppsc->reg_max_lps_awakeintvl); |
500 | 502 | ||
@@ -741,3 +743,96 @@ void rtl8723ae_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus) | |||
741 | 743 | ||
742 | rtl8723ae_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm); | 744 | rtl8723ae_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm); |
743 | } | 745 | } |
746 | |||
747 | static void rtl8723e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, | ||
748 | u8 ctwindow) | ||
749 | { | ||
750 | u8 u1_ctwindow_period[1] = {ctwindow}; | ||
751 | |||
752 | rtl8723ae_fill_h2c_cmd(hw, H2C_P2P_PS_CTW_CMD, 1, u1_ctwindow_period); | ||
753 | } | ||
754 | |||
755 | void rtl8723ae_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) | ||
756 | { | ||
757 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
758 | struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); | ||
759 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
760 | struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info); | ||
761 | struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; | ||
762 | u8 i; | ||
763 | u16 ctwindow; | ||
764 | u32 start_time, tsf_low; | ||
765 | |||
766 | switch (p2p_ps_state) { | ||
767 | case P2P_PS_DISABLE: | ||
768 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n"); | ||
769 | memset(p2p_ps_offload, 0, sizeof(struct p2p_ps_offload_t)); | ||
770 | break; | ||
771 | case P2P_PS_ENABLE: | ||
772 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n"); | ||
773 | /* update CTWindow value. */ | ||
774 | if (p2pinfo->ctwindow > 0) { | ||
775 | p2p_ps_offload->ctwindow_en = 1; | ||
776 | ctwindow = p2pinfo->ctwindow; | ||
777 | rtl8723e_set_p2p_ctw_period_cmd(hw, ctwindow); | ||
778 | } | ||
779 | |||
780 | /* hw only support 2 set of NoA */ | ||
781 | for (i = 0; i < p2pinfo->noa_num; i++) { | ||
782 | /* To control the register setting for which NOA*/ | ||
783 | rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); | ||
784 | if (i == 0) | ||
785 | p2p_ps_offload->noa0_en = 1; | ||
786 | else | ||
787 | p2p_ps_offload->noa1_en = 1; | ||
788 | |||
789 | /* config P2P NoA Descriptor Register */ | ||
790 | rtl_write_dword(rtlpriv, 0x5E0, | ||
791 | p2pinfo->noa_duration[i]); | ||
792 | rtl_write_dword(rtlpriv, 0x5E4, | ||
793 | p2pinfo->noa_interval[i]); | ||
794 | |||
795 | /*Get Current TSF value */ | ||
796 | tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); | ||
797 | |||
798 | start_time = p2pinfo->noa_start_time[i]; | ||
799 | if (p2pinfo->noa_count_type[i] != 1) { | ||
800 | while (start_time <= (tsf_low+(50*1024))) { | ||
801 | start_time += p2pinfo->noa_interval[i]; | ||
802 | if (p2pinfo->noa_count_type[i] != 255) | ||
803 | p2pinfo->noa_count_type[i]--; | ||
804 | } | ||
805 | } | ||
806 | rtl_write_dword(rtlpriv, 0x5E8, start_time); | ||
807 | rtl_write_dword(rtlpriv, 0x5EC, | ||
808 | p2pinfo->noa_count_type[i]); | ||
809 | } | ||
810 | if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) { | ||
811 | /* rst p2p circuit */ | ||
812 | rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); | ||
813 | |||
814 | p2p_ps_offload->offload_en = 1; | ||
815 | |||
816 | if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { | ||
817 | p2p_ps_offload->role = 1; | ||
818 | p2p_ps_offload->allstasleep = 0; | ||
819 | } else { | ||
820 | p2p_ps_offload->role = 0; | ||
821 | } | ||
822 | p2p_ps_offload->discovery = 0; | ||
823 | } | ||
824 | break; | ||
825 | case P2P_PS_SCAN: | ||
826 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n"); | ||
827 | p2p_ps_offload->discovery = 1; | ||
828 | break; | ||
829 | case P2P_PS_SCAN_DONE: | ||
830 | RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n"); | ||
831 | p2p_ps_offload->discovery = 0; | ||
832 | p2pinfo->p2p_ps_state = P2P_PS_ENABLE; | ||
833 | break; | ||
834 | default: | ||
835 | break; | ||
836 | } | ||
837 | rtl8723ae_fill_h2c_cmd(hw, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload); | ||
838 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h b/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h index 89994e16dc83..ed3b795e6980 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h | |||
@@ -70,8 +70,10 @@ enum rtl8192c_h2c_cmd { | |||
70 | H2C_SETPWRMODE = 1, | 70 | H2C_SETPWRMODE = 1, |
71 | H2C_JOINBSSRPT = 2, | 71 | H2C_JOINBSSRPT = 2, |
72 | H2C_RSVDPAGE = 3, | 72 | H2C_RSVDPAGE = 3, |
73 | H2C_RSSI_REPORT = 5, | 73 | H2C_RSSI_REPORT = 4, |
74 | H2C_RA_MASK = 6, | 74 | H2C_P2P_PS_CTW_CMD = 5, |
75 | H2C_P2P_PS_OFFLOAD = 6, | ||
76 | H2C_RA_MASK = 7, | ||
75 | MAX_H2CCMD | 77 | MAX_H2CCMD |
76 | }; | 78 | }; |
77 | 79 | ||
@@ -97,5 +99,6 @@ void rtl8723ae_firmware_selfreset(struct ieee80211_hw *hw); | |||
97 | void rtl8723ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); | 99 | void rtl8723ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); |
98 | void rtl8723ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); | 100 | void rtl8723ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); |
99 | void rtl8723ae_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); | 101 | void rtl8723ae_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); |
102 | void rtl8723ae_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state); | ||
100 | 103 | ||
101 | #endif | 104 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c index 9a0c71c2e15e..c333dfd116b8 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c | |||
@@ -449,6 +449,9 @@ void rtl8723ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | |||
449 | rtl8723ae_set_fw_joinbss_report_cmd(hw, (*(u8 *) val)); | 449 | rtl8723ae_set_fw_joinbss_report_cmd(hw, (*(u8 *) val)); |
450 | 450 | ||
451 | break; } | 451 | break; } |
452 | case HW_VAR_H2C_FW_P2P_PS_OFFLOAD: | ||
453 | rtl8723ae_set_p2p_ps_offload_cmd(hw, (*(u8 *)val)); | ||
454 | break; | ||
452 | case HW_VAR_AID:{ | 455 | case HW_VAR_AID:{ |
453 | u16 u2btmp; | 456 | u16 u2btmp; |
454 | u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); | 457 | u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); |
@@ -474,6 +477,39 @@ void rtl8723ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | |||
474 | if (btype_ibss == true) | 477 | if (btype_ibss == true) |
475 | _rtl8723ae_resume_tx_beacon(hw); | 478 | _rtl8723ae_resume_tx_beacon(hw); |
476 | break; } | 479 | break; } |
480 | case HW_VAR_FW_LPS_ACTION: { | ||
481 | bool enter_fwlps = *((bool *)val); | ||
482 | u8 rpwm_val, fw_pwrmode; | ||
483 | bool fw_current_inps; | ||
484 | |||
485 | if (enter_fwlps) { | ||
486 | rpwm_val = 0x02; /* RF off */ | ||
487 | fw_current_inps = true; | ||
488 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
489 | HW_VAR_FW_PSMODE_STATUS, | ||
490 | (u8 *)(&fw_current_inps)); | ||
491 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
492 | HW_VAR_H2C_FW_PWRMODE, | ||
493 | (u8 *)(&ppsc->fwctrl_psmode)); | ||
494 | |||
495 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
496 | HW_VAR_SET_RPWM, | ||
497 | (u8 *)(&rpwm_val)); | ||
498 | } else { | ||
499 | rpwm_val = 0x0C; /* RF on */ | ||
500 | fw_pwrmode = FW_PS_ACTIVE_MODE; | ||
501 | fw_current_inps = false; | ||
502 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, | ||
503 | (u8 *)(&rpwm_val)); | ||
504 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
505 | HW_VAR_H2C_FW_PWRMODE, | ||
506 | (u8 *)(&fw_pwrmode)); | ||
507 | |||
508 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
509 | HW_VAR_FW_PSMODE_STATUS, | ||
510 | (u8 *)(&fw_current_inps)); | ||
511 | } | ||
512 | break; } | ||
477 | default: | 513 | default: |
478 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 514 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
479 | "switch case not processed\n"); | 515 | "switch case not processed\n"); |
@@ -1379,7 +1415,7 @@ static void _rtl8723ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
1379 | } | 1415 | } |
1380 | 1416 | ||
1381 | for (i = 0; i < 14; i++) { | 1417 | for (i = 0; i < 14; i++) { |
1382 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1418 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1383 | "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = " | 1419 | "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = " |
1384 | "[0x%x / 0x%x / 0x%x]\n", rf_path, i, | 1420 | "[0x%x / 0x%x / 0x%x]\n", rf_path, i, |
1385 | rtlefuse->txpwrlevel_cck[rf_path][i], | 1421 | rtlefuse->txpwrlevel_cck[rf_path][i], |
@@ -1420,10 +1456,10 @@ static void _rtl8723ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
1420 | 0xf0) >> 4); | 1456 | 0xf0) >> 4); |
1421 | } | 1457 | } |
1422 | 1458 | ||
1423 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1459 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1424 | "RF-%d pwrgroup_ht20[%d] = 0x%x\n", rf_path, i, | 1460 | "RF-%d pwrgroup_ht20[%d] = 0x%x\n", rf_path, i, |
1425 | rtlefuse->pwrgroup_ht20[rf_path][i]); | 1461 | rtlefuse->pwrgroup_ht20[rf_path][i]); |
1426 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1462 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1427 | "RF-%d pwrgroup_ht40[%d] = 0x%x\n", rf_path, i, | 1463 | "RF-%d pwrgroup_ht40[%d] = 0x%x\n", rf_path, i, |
1428 | rtlefuse->pwrgroup_ht40[rf_path][i]); | 1464 | rtlefuse->pwrgroup_ht40[rf_path][i]); |
1429 | } | 1465 | } |
@@ -1463,19 +1499,19 @@ static void _rtl8723ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
1463 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7]; | 1499 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7]; |
1464 | 1500 | ||
1465 | for (i = 0; i < 14; i++) | 1501 | for (i = 0; i < 14; i++) |
1466 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1502 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1467 | "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", i, | 1503 | "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", i, |
1468 | rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); | 1504 | rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); |
1469 | for (i = 0; i < 14; i++) | 1505 | for (i = 0; i < 14; i++) |
1470 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1506 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1471 | "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", i, | 1507 | "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", i, |
1472 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); | 1508 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); |
1473 | for (i = 0; i < 14; i++) | 1509 | for (i = 0; i < 14; i++) |
1474 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1510 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1475 | "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", i, | 1511 | "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", i, |
1476 | rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); | 1512 | rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); |
1477 | for (i = 0; i < 14; i++) | 1513 | for (i = 0; i < 14; i++) |
1478 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1514 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1479 | "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", i, | 1515 | "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", i, |
1480 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); | 1516 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); |
1481 | 1517 | ||
@@ -1483,14 +1519,14 @@ static void _rtl8723ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
1483 | rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7); | 1519 | rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7); |
1484 | else | 1520 | else |
1485 | rtlefuse->eeprom_regulatory = 0; | 1521 | rtlefuse->eeprom_regulatory = 0; |
1486 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1522 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1487 | "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); | 1523 | "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); |
1488 | 1524 | ||
1489 | if (!autoload_fail) | 1525 | if (!autoload_fail) |
1490 | rtlefuse->eeprom_tssi[RF90_PATH_A] = hwinfo[EEPROM_TSSI_A]; | 1526 | rtlefuse->eeprom_tssi[RF90_PATH_A] = hwinfo[EEPROM_TSSI_A]; |
1491 | else | 1527 | else |
1492 | rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI; | 1528 | rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI; |
1493 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1529 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1494 | "TSSI_A = 0x%x, TSSI_B = 0x%x\n", | 1530 | "TSSI_A = 0x%x, TSSI_B = 0x%x\n", |
1495 | rtlefuse->eeprom_tssi[RF90_PATH_A], | 1531 | rtlefuse->eeprom_tssi[RF90_PATH_A], |
1496 | rtlefuse->eeprom_tssi[RF90_PATH_B]); | 1532 | rtlefuse->eeprom_tssi[RF90_PATH_B]); |
@@ -1505,7 +1541,7 @@ static void _rtl8723ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, | |||
1505 | rtlefuse->apk_thermalmeterignore = true; | 1541 | rtlefuse->apk_thermalmeterignore = true; |
1506 | 1542 | ||
1507 | rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; | 1543 | rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; |
1508 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | 1544 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
1509 | "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); | 1545 | "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); |
1510 | } | 1546 | } |
1511 | 1547 | ||
@@ -1713,19 +1749,7 @@ static void _rtl8723ae_hal_customized_behavior(struct ieee80211_hw *hw) | |||
1713 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | 1749 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); |
1714 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 1750 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
1715 | 1751 | ||
1716 | switch (rtlhal->oem_id) { | 1752 | pcipriv->ledctl.led_opendrain = true; |
1717 | case RT_CID_819x_HP: | ||
1718 | pcipriv->ledctl.led_opendrain = true; | ||
1719 | break; | ||
1720 | case RT_CID_819x_Lenovo: | ||
1721 | case RT_CID_DEFAULT: | ||
1722 | case RT_CID_TOSHIBA: | ||
1723 | case RT_CID_CCX: | ||
1724 | case RT_CID_819x_Acer: | ||
1725 | case RT_CID_WHQL: | ||
1726 | default: | ||
1727 | break; | ||
1728 | } | ||
1729 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | 1753 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, |
1730 | "RT Customized ID: 0x%02X\n", rtlhal->oem_id); | 1754 | "RT Customized ID: 0x%02X\n", rtlhal->oem_id); |
1731 | } | 1755 | } |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/led.c b/drivers/net/wireless/rtlwifi/rtl8723ae/led.c index 9c4e1d811187..061526fe6e2d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/led.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/led.c | |||
@@ -54,8 +54,9 @@ void rtl8723ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) | |||
54 | case LED_PIN_GPIO0: | 54 | case LED_PIN_GPIO0: |
55 | break; | 55 | break; |
56 | case LED_PIN_LED0: | 56 | case LED_PIN_LED0: |
57 | ledcfg &= ~BIT(6); | ||
57 | rtl_write_byte(rtlpriv, | 58 | rtl_write_byte(rtlpriv, |
58 | REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5) | BIT(6)); | 59 | REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5)); |
59 | break; | 60 | break; |
60 | case LED_PIN_LED1: | 61 | case LED_PIN_LED1: |
61 | rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5)); | 62 | rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5)); |
@@ -84,16 +85,21 @@ void rtl8723ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) | |||
84 | break; | 85 | break; |
85 | case LED_PIN_LED0: | 86 | case LED_PIN_LED0: |
86 | ledcfg &= 0xf0; | 87 | ledcfg &= 0xf0; |
87 | if (pcipriv->ledctl.led_opendrain) | 88 | if (pcipriv->ledctl.led_opendrain) { |
89 | ledcfg &= 0x90; | ||
90 | rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg|BIT(3))); | ||
91 | ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG); | ||
92 | ledcfg &= 0xFE; | ||
93 | rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, ledcfg); | ||
94 | } else { | ||
95 | ledcfg &= ~BIT(6); | ||
88 | rtl_write_byte(rtlpriv, REG_LEDCFG2, | 96 | rtl_write_byte(rtlpriv, REG_LEDCFG2, |
89 | (ledcfg | BIT(1) | BIT(5) | BIT(6))); | 97 | (ledcfg | BIT(3) | BIT(5))); |
90 | else | 98 | } |
91 | rtl_write_byte(rtlpriv, REG_LEDCFG2, | ||
92 | (ledcfg | BIT(3) | BIT(5) | BIT(6))); | ||
93 | break; | 99 | break; |
94 | case LED_PIN_LED1: | 100 | case LED_PIN_LED1: |
95 | ledcfg &= 0x0f; | 101 | ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1) & 0x10; |
96 | rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3))); | 102 | rtl_write_byte(rtlpriv, REG_LEDCFG1, (ledcfg | BIT(3))); |
97 | break; | 103 | break; |
98 | default: | 104 | default: |
99 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 105 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c index bb7cc90bafb2..e4c4cdc3eb67 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c | |||
@@ -305,7 +305,7 @@ static struct rtl_hal_cfg rtl8723ae_hal_cfg = { | |||
305 | 305 | ||
306 | .maps[RTL_IMR_TXFOVW] = PHIMR_TXFOVW, | 306 | .maps[RTL_IMR_TXFOVW] = PHIMR_TXFOVW, |
307 | .maps[RTL_IMR_PSTIMEOUT] = PHIMR_PSTIMEOUT, | 307 | .maps[RTL_IMR_PSTIMEOUT] = PHIMR_PSTIMEOUT, |
308 | .maps[RTL_IMR_BcnInt] = PHIMR_BCNDMAINT0, | 308 | .maps[RTL_IMR_BCNINT] = PHIMR_BCNDMAINT0, |
309 | .maps[RTL_IMR_RXFOVW] = PHIMR_RXFOVW, | 309 | .maps[RTL_IMR_RXFOVW] = PHIMR_RXFOVW, |
310 | .maps[RTL_IMR_RDU] = PHIMR_RDU, | 310 | .maps[RTL_IMR_RDU] = PHIMR_RDU, |
311 | .maps[RTL_IMR_ATIMEND] = PHIMR_ATIMEND_E, | 311 | .maps[RTL_IMR_ATIMEND] = PHIMR_ATIMEND_E, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c index ac081297db50..6c64365308d3 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c | |||
@@ -307,9 +307,6 @@ bool rtl8723ae_rx_query_desc(struct ieee80211_hw *hw, | |||
307 | rx_status->freq = hw->conf.channel->center_freq; | 307 | rx_status->freq = hw->conf.channel->center_freq; |
308 | rx_status->band = hw->conf.channel->band; | 308 | rx_status->band = hw->conf.channel->band; |
309 | 309 | ||
310 | hdr = (struct ieee80211_hdr *)(skb->data + status->rx_drvinfo_size | ||
311 | + status->rx_bufshift); | ||
312 | |||
313 | if (status->crc) | 310 | if (status->crc) |
314 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; | 311 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; |
315 | 312 | ||
@@ -330,6 +327,13 @@ bool rtl8723ae_rx_query_desc(struct ieee80211_hw *hw, | |||
330 | * to decrypt it | 327 | * to decrypt it |
331 | */ | 328 | */ |
332 | if (status->decrypted) { | 329 | if (status->decrypted) { |
330 | hdr = (struct ieee80211_hdr *)(skb->data + | ||
331 | status->rx_drvinfo_size + status->rx_bufshift); | ||
332 | |||
333 | if (!hdr) { | ||
334 | /* during testing, hdr could be NULL here */ | ||
335 | return false; | ||
336 | } | ||
333 | if ((ieee80211_is_robust_mgmt_frame(hdr)) && | 337 | if ((ieee80211_is_robust_mgmt_frame(hdr)) && |
334 | (ieee80211_has_protected(hdr->frame_control))) | 338 | (ieee80211_has_protected(hdr->frame_control))) |
335 | rx_status->flag &= ~RX_FLAG_DECRYPTED; | 339 | rx_status->flag &= ~RX_FLAG_DECRYPTED; |
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 41dce83ff41a..83915dcd0e58 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c | |||
@@ -308,6 +308,8 @@ static int _rtl_usb_init_tx(struct ieee80211_hw *hw) | |||
308 | return 0; | 308 | return 0; |
309 | } | 309 | } |
310 | 310 | ||
311 | static void _rtl_rx_work(unsigned long param); | ||
312 | |||
311 | static int _rtl_usb_init_rx(struct ieee80211_hw *hw) | 313 | static int _rtl_usb_init_rx(struct ieee80211_hw *hw) |
312 | { | 314 | { |
313 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 315 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -324,6 +326,12 @@ static int _rtl_usb_init_rx(struct ieee80211_hw *hw) | |||
324 | pr_info("rx_max_size %d, rx_urb_num %d, in_ep %d\n", | 326 | pr_info("rx_max_size %d, rx_urb_num %d, in_ep %d\n", |
325 | rtlusb->rx_max_size, rtlusb->rx_urb_num, rtlusb->in_ep); | 327 | rtlusb->rx_max_size, rtlusb->rx_urb_num, rtlusb->in_ep); |
326 | init_usb_anchor(&rtlusb->rx_submitted); | 328 | init_usb_anchor(&rtlusb->rx_submitted); |
329 | init_usb_anchor(&rtlusb->rx_cleanup_urbs); | ||
330 | |||
331 | skb_queue_head_init(&rtlusb->rx_queue); | ||
332 | rtlusb->rx_work_tasklet.func = _rtl_rx_work; | ||
333 | rtlusb->rx_work_tasklet.data = (unsigned long)rtlusb; | ||
334 | |||
327 | return 0; | 335 | return 0; |
328 | } | 336 | } |
329 | 337 | ||
@@ -405,40 +413,30 @@ static void rtl_usb_init_sw(struct ieee80211_hw *hw) | |||
405 | rtlusb->disableHWSM = true; | 413 | rtlusb->disableHWSM = true; |
406 | } | 414 | } |
407 | 415 | ||
408 | #define __RADIO_TAP_SIZE_RSV 32 | ||
409 | |||
410 | static void _rtl_rx_completed(struct urb *urb); | 416 | static void _rtl_rx_completed(struct urb *urb); |
411 | 417 | ||
412 | static struct sk_buff *_rtl_prep_rx_urb(struct ieee80211_hw *hw, | 418 | static int _rtl_prep_rx_urb(struct ieee80211_hw *hw, struct rtl_usb *rtlusb, |
413 | struct rtl_usb *rtlusb, | 419 | struct urb *urb, gfp_t gfp_mask) |
414 | struct urb *urb, | ||
415 | gfp_t gfp_mask) | ||
416 | { | 420 | { |
417 | struct sk_buff *skb; | ||
418 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 421 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
422 | void *buf; | ||
419 | 423 | ||
420 | skb = __dev_alloc_skb((rtlusb->rx_max_size + __RADIO_TAP_SIZE_RSV), | 424 | buf = usb_alloc_coherent(rtlusb->udev, rtlusb->rx_max_size, gfp_mask, |
421 | gfp_mask); | 425 | &urb->transfer_dma); |
422 | if (!skb) { | 426 | if (!buf) { |
423 | RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, | 427 | RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, |
424 | "Failed to __dev_alloc_skb!!\n"); | 428 | "Failed to usb_alloc_coherent!!\n"); |
425 | return ERR_PTR(-ENOMEM); | 429 | return -ENOMEM; |
426 | } | 430 | } |
427 | 431 | ||
428 | /* reserve some space for mac80211's radiotap */ | ||
429 | skb_reserve(skb, __RADIO_TAP_SIZE_RSV); | ||
430 | usb_fill_bulk_urb(urb, rtlusb->udev, | 432 | usb_fill_bulk_urb(urb, rtlusb->udev, |
431 | usb_rcvbulkpipe(rtlusb->udev, rtlusb->in_ep), | 433 | usb_rcvbulkpipe(rtlusb->udev, rtlusb->in_ep), |
432 | skb->data, min(skb_tailroom(skb), | 434 | buf, rtlusb->rx_max_size, _rtl_rx_completed, rtlusb); |
433 | (int)rtlusb->rx_max_size), | 435 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
434 | _rtl_rx_completed, skb); | ||
435 | 436 | ||
436 | _rtl_install_trx_info(rtlusb, skb, rtlusb->in_ep); | 437 | return 0; |
437 | return skb; | ||
438 | } | 438 | } |
439 | 439 | ||
440 | #undef __RADIO_TAP_SIZE_RSV | ||
441 | |||
442 | static void _rtl_usb_rx_process_agg(struct ieee80211_hw *hw, | 440 | static void _rtl_usb_rx_process_agg(struct ieee80211_hw *hw, |
443 | struct sk_buff *skb) | 441 | struct sk_buff *skb) |
444 | { | 442 | { |
@@ -522,22 +520,11 @@ static void _rtl_usb_rx_process_noagg(struct ieee80211_hw *hw, | |||
522 | if (unicast) | 520 | if (unicast) |
523 | rtlpriv->link_info.num_rx_inperiod++; | 521 | rtlpriv->link_info.num_rx_inperiod++; |
524 | } | 522 | } |
525 | if (likely(rtl_action_proc(hw, skb, false))) { | 523 | |
526 | struct sk_buff *uskb = NULL; | 524 | if (likely(rtl_action_proc(hw, skb, false))) |
527 | u8 *pdata; | 525 | ieee80211_rx(hw, skb); |
528 | 526 | else | |
529 | uskb = dev_alloc_skb(skb->len + 128); | ||
530 | if (uskb) { /* drop packet on allocation failure */ | ||
531 | memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status, | ||
532 | sizeof(rx_status)); | ||
533 | pdata = (u8 *)skb_put(uskb, skb->len); | ||
534 | memcpy(pdata, skb->data, skb->len); | ||
535 | ieee80211_rx_irqsafe(hw, uskb); | ||
536 | } | ||
537 | dev_kfree_skb_any(skb); | ||
538 | } else { | ||
539 | dev_kfree_skb_any(skb); | 527 | dev_kfree_skb_any(skb); |
540 | } | ||
541 | } | 528 | } |
542 | } | 529 | } |
543 | 530 | ||
@@ -554,15 +541,70 @@ static void _rtl_rx_pre_process(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
554 | while (!skb_queue_empty(&rx_queue)) { | 541 | while (!skb_queue_empty(&rx_queue)) { |
555 | _skb = skb_dequeue(&rx_queue); | 542 | _skb = skb_dequeue(&rx_queue); |
556 | _rtl_usb_rx_process_agg(hw, _skb); | 543 | _rtl_usb_rx_process_agg(hw, _skb); |
557 | ieee80211_rx_irqsafe(hw, _skb); | 544 | ieee80211_rx(hw, _skb); |
558 | } | 545 | } |
559 | } | 546 | } |
560 | 547 | ||
548 | #define __RX_SKB_MAX_QUEUED 32 | ||
549 | |||
550 | static void _rtl_rx_work(unsigned long param) | ||
551 | { | ||
552 | struct rtl_usb *rtlusb = (struct rtl_usb *)param; | ||
553 | struct ieee80211_hw *hw = usb_get_intfdata(rtlusb->intf); | ||
554 | struct sk_buff *skb; | ||
555 | |||
556 | while ((skb = skb_dequeue(&rtlusb->rx_queue))) { | ||
557 | if (unlikely(IS_USB_STOP(rtlusb))) { | ||
558 | dev_kfree_skb_any(skb); | ||
559 | continue; | ||
560 | } | ||
561 | |||
562 | if (likely(!rtlusb->usb_rx_segregate_hdl)) { | ||
563 | _rtl_usb_rx_process_noagg(hw, skb); | ||
564 | } else { | ||
565 | /* TO DO */ | ||
566 | _rtl_rx_pre_process(hw, skb); | ||
567 | pr_err("rx agg not supported\n"); | ||
568 | } | ||
569 | } | ||
570 | } | ||
571 | |||
572 | static unsigned int _rtl_rx_get_padding(struct ieee80211_hdr *hdr, | ||
573 | unsigned int len) | ||
574 | { | ||
575 | unsigned int padding = 0; | ||
576 | |||
577 | /* make function no-op when possible */ | ||
578 | if (NET_IP_ALIGN == 0 || len < sizeof(*hdr)) | ||
579 | return 0; | ||
580 | |||
581 | /* alignment calculation as in lbtf_rx() / carl9170_rx_copy_data() */ | ||
582 | /* TODO: deduplicate common code, define helper function instead? */ | ||
583 | |||
584 | if (ieee80211_is_data_qos(hdr->frame_control)) { | ||
585 | u8 *qc = ieee80211_get_qos_ctl(hdr); | ||
586 | |||
587 | padding ^= NET_IP_ALIGN; | ||
588 | |||
589 | /* Input might be invalid, avoid accessing memory outside | ||
590 | * the buffer. | ||
591 | */ | ||
592 | if ((unsigned long)qc - (unsigned long)hdr < len && | ||
593 | *qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT) | ||
594 | padding ^= NET_IP_ALIGN; | ||
595 | } | ||
596 | |||
597 | if (ieee80211_has_a4(hdr->frame_control)) | ||
598 | padding ^= NET_IP_ALIGN; | ||
599 | |||
600 | return padding; | ||
601 | } | ||
602 | |||
603 | #define __RADIO_TAP_SIZE_RSV 32 | ||
604 | |||
561 | static void _rtl_rx_completed(struct urb *_urb) | 605 | static void _rtl_rx_completed(struct urb *_urb) |
562 | { | 606 | { |
563 | struct sk_buff *skb = (struct sk_buff *)_urb->context; | 607 | struct rtl_usb *rtlusb = (struct rtl_usb *)_urb->context; |
564 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
565 | struct rtl_usb *rtlusb = (struct rtl_usb *)info->rate_driver_data[0]; | ||
566 | struct ieee80211_hw *hw = usb_get_intfdata(rtlusb->intf); | 608 | struct ieee80211_hw *hw = usb_get_intfdata(rtlusb->intf); |
567 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 609 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
568 | int err = 0; | 610 | int err = 0; |
@@ -571,28 +613,50 @@ static void _rtl_rx_completed(struct urb *_urb) | |||
571 | goto free; | 613 | goto free; |
572 | 614 | ||
573 | if (likely(0 == _urb->status)) { | 615 | if (likely(0 == _urb->status)) { |
574 | /* If this code were moved to work queue, would CPU | 616 | unsigned int padding; |
575 | * utilization be improved? NOTE: We shall allocate another skb | 617 | struct sk_buff *skb; |
576 | * and reuse the original one. | 618 | unsigned int qlen; |
577 | */ | 619 | unsigned int size = _urb->actual_length; |
578 | skb_put(skb, _urb->actual_length); | 620 | struct ieee80211_hdr *hdr; |
579 | 621 | ||
580 | if (likely(!rtlusb->usb_rx_segregate_hdl)) { | 622 | if (size < RTL_RX_DESC_SIZE + sizeof(struct ieee80211_hdr)) { |
581 | struct sk_buff *_skb; | 623 | RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, |
582 | _rtl_usb_rx_process_noagg(hw, skb); | 624 | "Too short packet from bulk IN! (len: %d)\n", |
583 | _skb = _rtl_prep_rx_urb(hw, rtlusb, _urb, GFP_ATOMIC); | 625 | size); |
584 | if (IS_ERR(_skb)) { | 626 | goto resubmit; |
585 | err = PTR_ERR(_skb); | 627 | } |
586 | RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, | 628 | |
587 | "Can't allocate skb for bulk IN!\n"); | 629 | qlen = skb_queue_len(&rtlusb->rx_queue); |
588 | return; | 630 | if (qlen >= __RX_SKB_MAX_QUEUED) { |
589 | } | 631 | RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, |
590 | skb = _skb; | 632 | "Pending RX skbuff queue full! (qlen: %d)\n", |
591 | } else{ | 633 | qlen); |
592 | /* TO DO */ | 634 | goto resubmit; |
593 | _rtl_rx_pre_process(hw, skb); | ||
594 | pr_err("rx agg not supported\n"); | ||
595 | } | 635 | } |
636 | |||
637 | hdr = (void *)(_urb->transfer_buffer + RTL_RX_DESC_SIZE); | ||
638 | padding = _rtl_rx_get_padding(hdr, size - RTL_RX_DESC_SIZE); | ||
639 | |||
640 | skb = dev_alloc_skb(size + __RADIO_TAP_SIZE_RSV + padding); | ||
641 | if (!skb) { | ||
642 | RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, | ||
643 | "Can't allocate skb for bulk IN!\n"); | ||
644 | goto resubmit; | ||
645 | } | ||
646 | |||
647 | _rtl_install_trx_info(rtlusb, skb, rtlusb->in_ep); | ||
648 | |||
649 | /* Make sure the payload data is 4 byte aligned. */ | ||
650 | skb_reserve(skb, padding); | ||
651 | |||
652 | /* reserve some space for mac80211's radiotap */ | ||
653 | skb_reserve(skb, __RADIO_TAP_SIZE_RSV); | ||
654 | |||
655 | memcpy(skb_put(skb, size), _urb->transfer_buffer, size); | ||
656 | |||
657 | skb_queue_tail(&rtlusb->rx_queue, skb); | ||
658 | tasklet_schedule(&rtlusb->rx_work_tasklet); | ||
659 | |||
596 | goto resubmit; | 660 | goto resubmit; |
597 | } | 661 | } |
598 | 662 | ||
@@ -608,9 +672,6 @@ static void _rtl_rx_completed(struct urb *_urb) | |||
608 | } | 672 | } |
609 | 673 | ||
610 | resubmit: | 674 | resubmit: |
611 | skb_reset_tail_pointer(skb); | ||
612 | skb_trim(skb, 0); | ||
613 | |||
614 | usb_anchor_urb(_urb, &rtlusb->rx_submitted); | 675 | usb_anchor_urb(_urb, &rtlusb->rx_submitted); |
615 | err = usb_submit_urb(_urb, GFP_ATOMIC); | 676 | err = usb_submit_urb(_urb, GFP_ATOMIC); |
616 | if (unlikely(err)) { | 677 | if (unlikely(err)) { |
@@ -620,13 +681,34 @@ resubmit: | |||
620 | return; | 681 | return; |
621 | 682 | ||
622 | free: | 683 | free: |
623 | dev_kfree_skb_irq(skb); | 684 | /* On some architectures, usb_free_coherent must not be called from |
685 | * hardirq context. Queue urb to cleanup list. | ||
686 | */ | ||
687 | usb_anchor_urb(_urb, &rtlusb->rx_cleanup_urbs); | ||
688 | } | ||
689 | |||
690 | #undef __RADIO_TAP_SIZE_RSV | ||
691 | |||
692 | static void _rtl_usb_cleanup_rx(struct ieee80211_hw *hw) | ||
693 | { | ||
694 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); | ||
695 | struct urb *urb; | ||
696 | |||
697 | usb_kill_anchored_urbs(&rtlusb->rx_submitted); | ||
698 | |||
699 | tasklet_kill(&rtlusb->rx_work_tasklet); | ||
700 | skb_queue_purge(&rtlusb->rx_queue); | ||
701 | |||
702 | while ((urb = usb_get_from_anchor(&rtlusb->rx_cleanup_urbs))) { | ||
703 | usb_free_coherent(urb->dev, urb->transfer_buffer_length, | ||
704 | urb->transfer_buffer, urb->transfer_dma); | ||
705 | usb_free_urb(urb); | ||
706 | } | ||
624 | } | 707 | } |
625 | 708 | ||
626 | static int _rtl_usb_receive(struct ieee80211_hw *hw) | 709 | static int _rtl_usb_receive(struct ieee80211_hw *hw) |
627 | { | 710 | { |
628 | struct urb *urb; | 711 | struct urb *urb; |
629 | struct sk_buff *skb; | ||
630 | int err; | 712 | int err; |
631 | int i; | 713 | int i; |
632 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 714 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -645,11 +727,10 @@ static int _rtl_usb_receive(struct ieee80211_hw *hw) | |||
645 | goto err_out; | 727 | goto err_out; |
646 | } | 728 | } |
647 | 729 | ||
648 | skb = _rtl_prep_rx_urb(hw, rtlusb, urb, GFP_KERNEL); | 730 | err = _rtl_prep_rx_urb(hw, rtlusb, urb, GFP_KERNEL); |
649 | if (IS_ERR(skb)) { | 731 | if (err < 0) { |
650 | RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, | 732 | RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, |
651 | "Failed to prep_rx_urb!!\n"); | 733 | "Failed to prep_rx_urb!!\n"); |
652 | err = PTR_ERR(skb); | ||
653 | usb_free_urb(urb); | 734 | usb_free_urb(urb); |
654 | goto err_out; | 735 | goto err_out; |
655 | } | 736 | } |
@@ -664,6 +745,7 @@ static int _rtl_usb_receive(struct ieee80211_hw *hw) | |||
664 | 745 | ||
665 | err_out: | 746 | err_out: |
666 | usb_kill_anchored_urbs(&rtlusb->rx_submitted); | 747 | usb_kill_anchored_urbs(&rtlusb->rx_submitted); |
748 | _rtl_usb_cleanup_rx(hw); | ||
667 | return err; | 749 | return err; |
668 | } | 750 | } |
669 | 751 | ||
@@ -705,7 +787,7 @@ static void rtl_usb_cleanup(struct ieee80211_hw *hw) | |||
705 | SET_USB_STOP(rtlusb); | 787 | SET_USB_STOP(rtlusb); |
706 | 788 | ||
707 | /* clean up rx stuff. */ | 789 | /* clean up rx stuff. */ |
708 | usb_kill_anchored_urbs(&rtlusb->rx_submitted); | 790 | _rtl_usb_cleanup_rx(hw); |
709 | 791 | ||
710 | /* clean up tx stuff */ | 792 | /* clean up tx stuff */ |
711 | for (i = 0; i < RTL_USB_MAX_EP_NUM; i++) { | 793 | for (i = 0; i < RTL_USB_MAX_EP_NUM; i++) { |
diff --git a/drivers/net/wireless/rtlwifi/usb.h b/drivers/net/wireless/rtlwifi/usb.h index fb986f98d1df..685273ca9561 100644 --- a/drivers/net/wireless/rtlwifi/usb.h +++ b/drivers/net/wireless/rtlwifi/usb.h | |||
@@ -136,11 +136,14 @@ struct rtl_usb { | |||
136 | void (*usb_tx_cleanup)(struct ieee80211_hw *, struct sk_buff *); | 136 | void (*usb_tx_cleanup)(struct ieee80211_hw *, struct sk_buff *); |
137 | 137 | ||
138 | /* Rx */ | 138 | /* Rx */ |
139 | u8 in_ep_nums ; | 139 | u8 in_ep_nums; |
140 | u32 in_ep; /* Bulk IN endpoint number */ | 140 | u32 in_ep; /* Bulk IN endpoint number */ |
141 | u32 rx_max_size; /* Bulk IN max buffer size */ | 141 | u32 rx_max_size; /* Bulk IN max buffer size */ |
142 | u32 rx_urb_num; /* How many Bulk INs are submitted to host. */ | 142 | u32 rx_urb_num; /* How many Bulk INs are submitted to host. */ |
143 | struct usb_anchor rx_submitted; | 143 | struct usb_anchor rx_submitted; |
144 | struct usb_anchor rx_cleanup_urbs; | ||
145 | struct tasklet_struct rx_work_tasklet; | ||
146 | struct sk_buff_head rx_queue; | ||
144 | void (*usb_rx_segregate_hdl)(struct ieee80211_hw *, struct sk_buff *, | 147 | void (*usb_rx_segregate_hdl)(struct ieee80211_hw *, struct sk_buff *, |
145 | struct sk_buff_head *); | 148 | struct sk_buff_head *); |
146 | void (*usb_rx_hdl)(struct ieee80211_hw *, struct sk_buff *); | 149 | void (*usb_rx_hdl)(struct ieee80211_hw *, struct sk_buff *); |
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index c3eff32acf6c..44328baa6389 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h | |||
@@ -99,11 +99,36 @@ | |||
99 | #define CHANNEL_GROUP_MAX_5G 9 | 99 | #define CHANNEL_GROUP_MAX_5G 9 |
100 | #define CHANNEL_MAX_NUMBER_2G 14 | 100 | #define CHANNEL_MAX_NUMBER_2G 14 |
101 | #define AVG_THERMAL_NUM 8 | 101 | #define AVG_THERMAL_NUM 8 |
102 | #define AVG_THERMAL_NUM_88E 4 | ||
102 | #define MAX_TID_COUNT 9 | 103 | #define MAX_TID_COUNT 9 |
103 | 104 | ||
104 | /* for early mode */ | 105 | /* for early mode */ |
105 | #define FCS_LEN 4 | 106 | #define FCS_LEN 4 |
106 | #define EM_HDR_LEN 8 | 107 | #define EM_HDR_LEN 8 |
108 | |||
109 | #define MAX_TX_COUNT 4 | ||
110 | #define MAX_RF_PATH 4 | ||
111 | #define MAX_CHNL_GROUP_24G 6 | ||
112 | #define MAX_CHNL_GROUP_5G 14 | ||
113 | |||
114 | struct txpower_info_2g { | ||
115 | u8 index_cck_base[MAX_RF_PATH][MAX_CHNL_GROUP_24G]; | ||
116 | u8 index_bw40_base[MAX_RF_PATH][MAX_CHNL_GROUP_24G]; | ||
117 | /*If only one tx, only BW20 and OFDM are used.*/ | ||
118 | u8 cck_diff[MAX_RF_PATH][MAX_TX_COUNT]; | ||
119 | u8 ofdm_diff[MAX_RF_PATH][MAX_TX_COUNT]; | ||
120 | u8 bw20_diff[MAX_RF_PATH][MAX_TX_COUNT]; | ||
121 | u8 bw40_diff[MAX_RF_PATH][MAX_TX_COUNT]; | ||
122 | }; | ||
123 | |||
124 | struct txpower_info_5g { | ||
125 | u8 index_bw40_base[MAX_RF_PATH][MAX_CHNL_GROUP_5G]; | ||
126 | /*If only one tx, only BW20, OFDM, BW80 and BW160 are used.*/ | ||
127 | u8 ofdm_diff[MAX_RF_PATH][MAX_TX_COUNT]; | ||
128 | u8 bw20_diff[MAX_RF_PATH][MAX_TX_COUNT]; | ||
129 | u8 bw40_diff[MAX_RF_PATH][MAX_TX_COUNT]; | ||
130 | }; | ||
131 | |||
107 | enum intf_type { | 132 | enum intf_type { |
108 | INTF_PCI = 0, | 133 | INTF_PCI = 0, |
109 | INTF_USB = 1, | 134 | INTF_USB = 1, |
@@ -137,6 +162,7 @@ enum hardware_type { | |||
137 | HARDWARE_TYPE_RTL8192DU, | 162 | HARDWARE_TYPE_RTL8192DU, |
138 | HARDWARE_TYPE_RTL8723AE, | 163 | HARDWARE_TYPE_RTL8723AE, |
139 | HARDWARE_TYPE_RTL8723U, | 164 | HARDWARE_TYPE_RTL8723U, |
165 | HARDWARE_TYPE_RTL8188EE, | ||
140 | 166 | ||
141 | /* keep it last */ | 167 | /* keep it last */ |
142 | HARDWARE_TYPE_NUM | 168 | HARDWARE_TYPE_NUM |
@@ -263,7 +289,7 @@ enum hw_variables { | |||
263 | HW_VAR_RATR_0, | 289 | HW_VAR_RATR_0, |
264 | HW_VAR_RRSR, | 290 | HW_VAR_RRSR, |
265 | HW_VAR_CPU_RST, | 291 | HW_VAR_CPU_RST, |
266 | HW_VAR_CECHK_BSSID, | 292 | HW_VAR_CHECK_BSSID, |
267 | HW_VAR_LBK_MODE, | 293 | HW_VAR_LBK_MODE, |
268 | HW_VAR_AES_11N_FIX, | 294 | HW_VAR_AES_11N_FIX, |
269 | HW_VAR_USB_RX_AGGR, | 295 | HW_VAR_USB_RX_AGGR, |
@@ -278,7 +304,10 @@ enum hw_variables { | |||
278 | HW_VAR_SET_RPWM, | 304 | HW_VAR_SET_RPWM, |
279 | HW_VAR_H2C_FW_PWRMODE, | 305 | HW_VAR_H2C_FW_PWRMODE, |
280 | HW_VAR_H2C_FW_JOINBSSRPT, | 306 | HW_VAR_H2C_FW_JOINBSSRPT, |
307 | HW_VAR_H2C_FW_P2P_PS_OFFLOAD, | ||
281 | HW_VAR_FW_PSMODE_STATUS, | 308 | HW_VAR_FW_PSMODE_STATUS, |
309 | HW_VAR_RESUME_CLK_ON, | ||
310 | HW_VAR_FW_LPS_ACTION, | ||
282 | HW_VAR_1X1_RECV_COMBINE, | 311 | HW_VAR_1X1_RECV_COMBINE, |
283 | HW_VAR_STOP_SEND_BEACON, | 312 | HW_VAR_STOP_SEND_BEACON, |
284 | HW_VAR_TSF_TIMER, | 313 | HW_VAR_TSF_TIMER, |
@@ -305,6 +334,7 @@ enum hw_variables { | |||
305 | HW_VAR_INT_AC, | 334 | HW_VAR_INT_AC, |
306 | HW_VAR_RF_TIMING, | 335 | HW_VAR_RF_TIMING, |
307 | 336 | ||
337 | HAL_DEF_WOWLAN, | ||
308 | HW_VAR_MRC, | 338 | HW_VAR_MRC, |
309 | 339 | ||
310 | HW_VAR_MGT_FILTER, | 340 | HW_VAR_MGT_FILTER, |
@@ -461,6 +491,7 @@ enum rtl_var_map { | |||
461 | EFUSE_MAX_SECTION_MAP, | 491 | EFUSE_MAX_SECTION_MAP, |
462 | EFUSE_REAL_CONTENT_SIZE, | 492 | EFUSE_REAL_CONTENT_SIZE, |
463 | EFUSE_OOB_PROTECT_BYTES_LEN, | 493 | EFUSE_OOB_PROTECT_BYTES_LEN, |
494 | EFUSE_ACCESS, | ||
464 | 495 | ||
465 | /*CAM map */ | 496 | /*CAM map */ |
466 | RWCAM, | 497 | RWCAM, |
@@ -493,7 +524,7 @@ enum rtl_var_map { | |||
493 | RTL_IMR_TIMEOUT1, /*Timeout interrupt 1 */ | 524 | RTL_IMR_TIMEOUT1, /*Timeout interrupt 1 */ |
494 | RTL_IMR_TXFOVW, /*Transmit FIFO Overflow */ | 525 | RTL_IMR_TXFOVW, /*Transmit FIFO Overflow */ |
495 | RTL_IMR_PSTIMEOUT, /*Power save time out interrupt */ | 526 | RTL_IMR_PSTIMEOUT, /*Power save time out interrupt */ |
496 | RTL_IMR_BcnInt, /*Beacon DMA Interrupt 0 */ | 527 | RTL_IMR_BCNINT, /*Beacon DMA Interrupt 0 */ |
497 | RTL_IMR_RXFOVW, /*Receive FIFO Overflow */ | 528 | RTL_IMR_RXFOVW, /*Receive FIFO Overflow */ |
498 | RTL_IMR_RDU, /*Receive Descriptor Unavailable */ | 529 | RTL_IMR_RDU, /*Receive Descriptor Unavailable */ |
499 | RTL_IMR_ATIMEND, /*For 92C,ATIM Window End Interrupt */ | 530 | RTL_IMR_ATIMEND, /*For 92C,ATIM Window End Interrupt */ |
@@ -508,7 +539,7 @@ enum rtl_var_map { | |||
508 | RTL_IMR_VIDOK, /*AC_VI DMA OK Interrupt */ | 539 | RTL_IMR_VIDOK, /*AC_VI DMA OK Interrupt */ |
509 | RTL_IMR_VODOK, /*AC_VO DMA Interrupt */ | 540 | RTL_IMR_VODOK, /*AC_VO DMA Interrupt */ |
510 | RTL_IMR_ROK, /*Receive DMA OK Interrupt */ | 541 | RTL_IMR_ROK, /*Receive DMA OK Interrupt */ |
511 | RTL_IBSS_INT_MASKS, /*(RTL_IMR_BcnInt | RTL_IMR_TBDOK | | 542 | RTL_IBSS_INT_MASKS, /*(RTL_IMR_BCNINT | RTL_IMR_TBDOK | |
512 | * RTL_IMR_TBDER) */ | 543 | * RTL_IMR_TBDER) */ |
513 | RTL_IMR_C2HCMD, /*fw interrupt*/ | 544 | RTL_IMR_C2HCMD, /*fw interrupt*/ |
514 | 545 | ||
@@ -742,6 +773,11 @@ struct false_alarm_statistics { | |||
742 | u32 cnt_ofdm_fail; | 773 | u32 cnt_ofdm_fail; |
743 | u32 cnt_cck_fail; | 774 | u32 cnt_cck_fail; |
744 | u32 cnt_all; | 775 | u32 cnt_all; |
776 | u32 cnt_ofdm_cca; | ||
777 | u32 cnt_cck_cca; | ||
778 | u32 cnt_cca_all; | ||
779 | u32 cnt_bw_usc; | ||
780 | u32 cnt_bw_lsc; | ||
745 | }; | 781 | }; |
746 | 782 | ||
747 | struct init_gain { | 783 | struct init_gain { |
@@ -826,8 +862,67 @@ struct rtl_rfkill { | |||
826 | bool rfkill_state; /*0 is off, 1 is on */ | 862 | bool rfkill_state; /*0 is off, 1 is on */ |
827 | }; | 863 | }; |
828 | 864 | ||
865 | /*for P2P PS**/ | ||
866 | #define P2P_MAX_NOA_NUM 2 | ||
867 | |||
868 | enum p2p_role { | ||
869 | P2P_ROLE_DISABLE = 0, | ||
870 | P2P_ROLE_DEVICE = 1, | ||
871 | P2P_ROLE_CLIENT = 2, | ||
872 | P2P_ROLE_GO = 3 | ||
873 | }; | ||
874 | |||
875 | enum p2p_ps_state { | ||
876 | P2P_PS_DISABLE = 0, | ||
877 | P2P_PS_ENABLE = 1, | ||
878 | P2P_PS_SCAN = 2, | ||
879 | P2P_PS_SCAN_DONE = 3, | ||
880 | P2P_PS_ALLSTASLEEP = 4, /* for P2P GO */ | ||
881 | }; | ||
882 | |||
883 | enum p2p_ps_mode { | ||
884 | P2P_PS_NONE = 0, | ||
885 | P2P_PS_CTWINDOW = 1, | ||
886 | P2P_PS_NOA = 2, | ||
887 | P2P_PS_MIX = 3, /* CTWindow and NoA */ | ||
888 | }; | ||
889 | |||
890 | struct rtl_p2p_ps_info { | ||
891 | enum p2p_ps_mode p2p_ps_mode; /* indicate p2p ps mode */ | ||
892 | enum p2p_ps_state p2p_ps_state; /* indicate p2p ps state */ | ||
893 | u8 noa_index; /* Identifies instance of Notice of Absence timing. */ | ||
894 | /* Client traffic window. A period of time in TU after TBTT. */ | ||
895 | u8 ctwindow; | ||
896 | u8 opp_ps; /* opportunistic power save. */ | ||
897 | u8 noa_num; /* number of NoA descriptor in P2P IE. */ | ||
898 | /* Count for owner, Type of client. */ | ||
899 | u8 noa_count_type[P2P_MAX_NOA_NUM]; | ||
900 | /* Max duration for owner, preferred or min acceptable duration | ||
901 | * for client. | ||
902 | */ | ||
903 | u32 noa_duration[P2P_MAX_NOA_NUM]; | ||
904 | /* Length of interval for owner, preferred or max acceptable intervali | ||
905 | * of client. | ||
906 | */ | ||
907 | u32 noa_interval[P2P_MAX_NOA_NUM]; | ||
908 | /* schedule in terms of the lower 4 bytes of the TSF timer. */ | ||
909 | u32 noa_start_time[P2P_MAX_NOA_NUM]; | ||
910 | }; | ||
911 | |||
912 | struct p2p_ps_offload_t { | ||
913 | u8 offload_en:1; | ||
914 | u8 role:1; /* 1: Owner, 0: Client */ | ||
915 | u8 ctwindow_en:1; | ||
916 | u8 noa0_en:1; | ||
917 | u8 noa1_en:1; | ||
918 | u8 allstasleep:1; | ||
919 | u8 discovery:1; | ||
920 | u8 reserved:1; | ||
921 | }; | ||
922 | |||
829 | #define IQK_MATRIX_REG_NUM 8 | 923 | #define IQK_MATRIX_REG_NUM 8 |
830 | #define IQK_MATRIX_SETTINGS_NUM (1 + 24 + 21) | 924 | #define IQK_MATRIX_SETTINGS_NUM (1 + 24 + 21) |
925 | |||
831 | struct iqk_matrix_regs { | 926 | struct iqk_matrix_regs { |
832 | bool iqk_done; | 927 | bool iqk_done; |
833 | long value[1][IQK_MATRIX_REG_NUM]; | 928 | long value[1][IQK_MATRIX_REG_NUM]; |
@@ -889,7 +984,7 @@ struct rtl_phy { | |||
889 | 984 | ||
890 | /* Dual mac */ | 985 | /* Dual mac */ |
891 | bool need_iqk; | 986 | bool need_iqk; |
892 | struct iqk_matrix_regs iqk_matrix_regsetting[IQK_MATRIX_SETTINGS_NUM]; | 987 | struct iqk_matrix_regs iqk_matrix[IQK_MATRIX_SETTINGS_NUM]; |
893 | 988 | ||
894 | bool rfpi_enable; | 989 | bool rfpi_enable; |
895 | 990 | ||
@@ -902,6 +997,8 @@ struct rtl_phy { | |||
902 | /* the current Tx power level */ | 997 | /* the current Tx power level */ |
903 | u8 cur_cck_txpwridx; | 998 | u8 cur_cck_txpwridx; |
904 | u8 cur_ofdm24g_txpwridx; | 999 | u8 cur_ofdm24g_txpwridx; |
1000 | u8 cur_bw20_txpwridx; | ||
1001 | u8 cur_bw40_txpwridx; | ||
905 | 1002 | ||
906 | u32 rfreg_chnlval[2]; | 1003 | u32 rfreg_chnlval[2]; |
907 | bool apk_done; | 1004 | bool apk_done; |
@@ -940,20 +1037,21 @@ struct rtl_ht_agg { | |||
940 | u8 rx_agg_state; | 1037 | u8 rx_agg_state; |
941 | }; | 1038 | }; |
942 | 1039 | ||
1040 | struct rssi_sta { | ||
1041 | long undec_sm_pwdb; | ||
1042 | }; | ||
1043 | |||
943 | struct rtl_tid_data { | 1044 | struct rtl_tid_data { |
944 | u16 seq_number; | 1045 | u16 seq_number; |
945 | struct rtl_ht_agg agg; | 1046 | struct rtl_ht_agg agg; |
946 | }; | 1047 | }; |
947 | 1048 | ||
948 | struct rssi_sta { | ||
949 | long undec_sm_pwdb; | ||
950 | }; | ||
951 | |||
952 | struct rtl_sta_info { | 1049 | struct rtl_sta_info { |
953 | struct list_head list; | 1050 | struct list_head list; |
954 | u8 ratr_index; | 1051 | u8 ratr_index; |
955 | u8 wireless_mode; | 1052 | u8 wireless_mode; |
956 | u8 mimo_ps; | 1053 | u8 mimo_ps; |
1054 | u8 mac_addr[ETH_ALEN]; | ||
957 | struct rtl_tid_data tids[MAX_TID_COUNT]; | 1055 | struct rtl_tid_data tids[MAX_TID_COUNT]; |
958 | 1056 | ||
959 | /* just used for ap adhoc or mesh*/ | 1057 | /* just used for ap adhoc or mesh*/ |
@@ -1005,6 +1103,8 @@ struct rtl_mac { | |||
1005 | int n_bitrates; | 1103 | int n_bitrates; |
1006 | 1104 | ||
1007 | bool offchan_delay; | 1105 | bool offchan_delay; |
1106 | u8 p2p; /*using p2p role*/ | ||
1107 | bool p2p_in_use; | ||
1008 | 1108 | ||
1009 | /*filters */ | 1109 | /*filters */ |
1010 | u32 rx_conf; | 1110 | u32 rx_conf; |
@@ -1014,11 +1114,11 @@ struct rtl_mac { | |||
1014 | 1114 | ||
1015 | bool act_scanning; | 1115 | bool act_scanning; |
1016 | u8 cnt_after_linked; | 1116 | u8 cnt_after_linked; |
1117 | bool skip_scan; | ||
1017 | 1118 | ||
1018 | /* early mode */ | 1119 | /* early mode */ |
1019 | /* skb wait queue */ | 1120 | /* skb wait queue */ |
1020 | struct sk_buff_head skb_waitq[MAX_TID_COUNT]; | 1121 | struct sk_buff_head skb_waitq[MAX_TID_COUNT]; |
1021 | u8 earlymode_threshold; | ||
1022 | 1122 | ||
1023 | /*RDG*/ | 1123 | /*RDG*/ |
1024 | bool rdg_en; | 1124 | bool rdg_en; |
@@ -1042,6 +1142,7 @@ struct rtl_mac { | |||
1042 | u8 retry_short; | 1142 | u8 retry_short; |
1043 | u8 retry_long; | 1143 | u8 retry_long; |
1044 | u16 assoc_id; | 1144 | u16 assoc_id; |
1145 | bool hiddenssid; | ||
1045 | 1146 | ||
1046 | /*IBSS*/ | 1147 | /*IBSS*/ |
1047 | int beacon_interval; | 1148 | int beacon_interval; |
@@ -1111,10 +1212,13 @@ struct bt_coexist_8723 { | |||
1111 | 1212 | ||
1112 | struct rtl_hal { | 1213 | struct rtl_hal { |
1113 | struct ieee80211_hw *hw; | 1214 | struct ieee80211_hw *hw; |
1114 | struct bt_coexist_8723 hal_coex_8723; | 1215 | bool driver_is_goingto_unload; |
1115 | bool up_first_time; | 1216 | bool up_first_time; |
1217 | bool first_init; | ||
1116 | bool being_init_adapter; | 1218 | bool being_init_adapter; |
1117 | bool bbrf_ready; | 1219 | bool bbrf_ready; |
1220 | bool mac_func_enable; | ||
1221 | struct bt_coexist_8723 hal_coex_8723; | ||
1118 | 1222 | ||
1119 | enum intf_type interface; | 1223 | enum intf_type interface; |
1120 | u16 hw_type; /*92c or 92d or 92s and so on */ | 1224 | u16 hw_type; /*92c or 92d or 92s and so on */ |
@@ -1122,6 +1226,7 @@ struct rtl_hal { | |||
1122 | u8 oem_id; | 1226 | u8 oem_id; |
1123 | u32 version; /*version of chip */ | 1227 | u32 version; /*version of chip */ |
1124 | u8 state; /*stop 0, start 1 */ | 1228 | u8 state; /*stop 0, start 1 */ |
1229 | u8 board_type; | ||
1125 | 1230 | ||
1126 | /*firmware */ | 1231 | /*firmware */ |
1127 | u32 fwsize; | 1232 | u32 fwsize; |
@@ -1141,6 +1246,10 @@ struct rtl_hal { | |||
1141 | bool set_fwcmd_inprogress; | 1246 | bool set_fwcmd_inprogress; |
1142 | u8 current_fwcmd_io; | 1247 | u8 current_fwcmd_io; |
1143 | 1248 | ||
1249 | struct p2p_ps_offload_t p2p_ps_offload; | ||
1250 | bool fw_clk_change_in_progress; | ||
1251 | bool allow_sw_to_change_hwclc; | ||
1252 | u8 fw_ps_state; | ||
1144 | /**/ | 1253 | /**/ |
1145 | bool driver_going2unload; | 1254 | bool driver_going2unload; |
1146 | 1255 | ||
@@ -1157,6 +1266,7 @@ struct rtl_hal { | |||
1157 | /* just for DualMac S3S4 */ | 1266 | /* just for DualMac S3S4 */ |
1158 | u8 macphyctl_reg; | 1267 | u8 macphyctl_reg; |
1159 | bool earlymode_enable; | 1268 | bool earlymode_enable; |
1269 | u8 max_earlymode_num; | ||
1160 | /* Dual mac*/ | 1270 | /* Dual mac*/ |
1161 | bool during_mac0init_radiob; | 1271 | bool during_mac0init_radiob; |
1162 | bool during_mac1init_radioa; | 1272 | bool during_mac1init_radioa; |
@@ -1193,6 +1303,29 @@ struct rtl_security { | |||
1193 | u8 *pairwise_key; | 1303 | u8 *pairwise_key; |
1194 | }; | 1304 | }; |
1195 | 1305 | ||
1306 | #define ASSOCIATE_ENTRY_NUM 33 | ||
1307 | |||
1308 | struct fast_ant_training { | ||
1309 | u8 bssid[6]; | ||
1310 | u8 antsel_rx_keep_0; | ||
1311 | u8 antsel_rx_keep_1; | ||
1312 | u8 antsel_rx_keep_2; | ||
1313 | u32 ant_sum[7]; | ||
1314 | u32 ant_cnt[7]; | ||
1315 | u32 ant_ave[7]; | ||
1316 | u8 fat_state; | ||
1317 | u32 train_idx; | ||
1318 | u8 antsel_a[ASSOCIATE_ENTRY_NUM]; | ||
1319 | u8 antsel_b[ASSOCIATE_ENTRY_NUM]; | ||
1320 | u8 antsel_c[ASSOCIATE_ENTRY_NUM]; | ||
1321 | u32 main_ant_sum[ASSOCIATE_ENTRY_NUM]; | ||
1322 | u32 aux_ant_sum[ASSOCIATE_ENTRY_NUM]; | ||
1323 | u32 main_ant_cnt[ASSOCIATE_ENTRY_NUM]; | ||
1324 | u32 aux_ant_cnt[ASSOCIATE_ENTRY_NUM]; | ||
1325 | u8 rx_idle_ant; | ||
1326 | bool becomelinked; | ||
1327 | }; | ||
1328 | |||
1196 | struct rtl_dm { | 1329 | struct rtl_dm { |
1197 | /*PHY status for Dynamic Management */ | 1330 | /*PHY status for Dynamic Management */ |
1198 | long entry_min_undec_sm_pwdb; | 1331 | long entry_min_undec_sm_pwdb; |
@@ -1229,9 +1362,24 @@ struct rtl_dm { | |||
1229 | bool disable_tx_int; | 1362 | bool disable_tx_int; |
1230 | char ofdm_index[2]; | 1363 | char ofdm_index[2]; |
1231 | char cck_index; | 1364 | char cck_index; |
1365 | char delta_power_index; | ||
1366 | char delta_power_index_last; | ||
1367 | char power_index_offset; | ||
1368 | |||
1369 | /*88e tx power tracking*/ | ||
1370 | u8 swing_idx_ofdm[2]; | ||
1371 | u8 swing_idx_ofdm_cur; | ||
1372 | u8 swing_idx_ofdm_base; | ||
1373 | bool swing_flag_ofdm; | ||
1374 | u8 swing_idx_cck; | ||
1375 | u8 swing_idx_cck_cur; | ||
1376 | u8 swing_idx_cck_base; | ||
1377 | bool swing_flag_cck; | ||
1232 | 1378 | ||
1233 | /* DMSP */ | 1379 | /* DMSP */ |
1234 | bool supp_phymode_switch; | 1380 | bool supp_phymode_switch; |
1381 | |||
1382 | struct fast_ant_training fat_table; | ||
1235 | }; | 1383 | }; |
1236 | 1384 | ||
1237 | #define EFUSE_MAX_LOGICAL_SIZE 256 | 1385 | #define EFUSE_MAX_LOGICAL_SIZE 256 |
@@ -1264,6 +1412,9 @@ struct rtl_efuse { | |||
1264 | u8 external_pa; | 1412 | u8 external_pa; |
1265 | 1413 | ||
1266 | u8 dev_addr[6]; | 1414 | u8 dev_addr[6]; |
1415 | u8 wowlan_enable; | ||
1416 | u8 antenna_div_cfg; | ||
1417 | u8 antenna_div_type; | ||
1267 | 1418 | ||
1268 | bool txpwr_fromeprom; | 1419 | bool txpwr_fromeprom; |
1269 | u8 eeprom_crystalcap; | 1420 | u8 eeprom_crystalcap; |
@@ -1319,14 +1470,12 @@ struct rtl_ps_ctl { | |||
1319 | bool rfchange_inprogress; | 1470 | bool rfchange_inprogress; |
1320 | bool swrf_processing; | 1471 | bool swrf_processing; |
1321 | bool hwradiooff; | 1472 | bool hwradiooff; |
1322 | |||
1323 | /* | 1473 | /* |
1324 | * just for PCIE ASPM | 1474 | * just for PCIE ASPM |
1325 | * If it supports ASPM, Offset[560h] = 0x40, | 1475 | * If it supports ASPM, Offset[560h] = 0x40, |
1326 | * otherwise Offset[560h] = 0x00. | 1476 | * otherwise Offset[560h] = 0x00. |
1327 | * */ | 1477 | * */ |
1328 | bool support_aspm; | 1478 | bool support_aspm; |
1329 | |||
1330 | bool support_backdoor; | 1479 | bool support_backdoor; |
1331 | 1480 | ||
1332 | /*for LPS */ | 1481 | /*for LPS */ |
@@ -1341,6 +1490,7 @@ struct rtl_ps_ctl { | |||
1341 | bool fw_current_inpsmode; | 1490 | bool fw_current_inpsmode; |
1342 | u8 reg_max_lps_awakeintvl; | 1491 | u8 reg_max_lps_awakeintvl; |
1343 | bool report_linked; | 1492 | bool report_linked; |
1493 | bool low_power_enable;/*for 32k*/ | ||
1344 | 1494 | ||
1345 | /*for IPS */ | 1495 | /*for IPS */ |
1346 | bool inactiveps; | 1496 | bool inactiveps; |
@@ -1373,6 +1523,11 @@ struct rtl_ps_ctl { | |||
1373 | unsigned long last_beacon; | 1523 | unsigned long last_beacon; |
1374 | unsigned long last_action; | 1524 | unsigned long last_action; |
1375 | unsigned long last_slept; | 1525 | unsigned long last_slept; |
1526 | |||
1527 | /*For P2P PS */ | ||
1528 | struct rtl_p2p_ps_info p2p_ps_info; | ||
1529 | u8 pwr_mode; | ||
1530 | u8 smart_ps; | ||
1376 | }; | 1531 | }; |
1377 | 1532 | ||
1378 | struct rtl_stats { | 1533 | struct rtl_stats { |
@@ -1381,7 +1536,7 @@ struct rtl_stats { | |||
1381 | s8 rssi; | 1536 | s8 rssi; |
1382 | u8 signal; | 1537 | u8 signal; |
1383 | u8 noise; | 1538 | u8 noise; |
1384 | u16 rate; /*in 100 kbps */ | 1539 | u8 rate; /* hw desc rate */ |
1385 | u8 received_channel; | 1540 | u8 received_channel; |
1386 | u8 control; | 1541 | u8 control; |
1387 | u8 mask; | 1542 | u8 mask; |
@@ -1423,8 +1578,16 @@ struct rtl_stats { | |||
1423 | bool packet_toself; | 1578 | bool packet_toself; |
1424 | bool packet_beacon; /*for rssi */ | 1579 | bool packet_beacon; /*for rssi */ |
1425 | char cck_adc_pwdb[4]; /*for rx path selection */ | 1580 | char cck_adc_pwdb[4]; /*for rx path selection */ |
1581 | |||
1582 | u8 packet_report_type; | ||
1583 | |||
1584 | u32 macid; | ||
1585 | u8 wake_match; | ||
1586 | u32 bt_rx_rssi_percentage; | ||
1587 | u32 macid_valid_entry[2]; | ||
1426 | }; | 1588 | }; |
1427 | 1589 | ||
1590 | |||
1428 | struct rt_link_detect { | 1591 | struct rt_link_detect { |
1429 | /* count for roaming */ | 1592 | /* count for roaming */ |
1430 | u32 bcn_rx_inperiod; | 1593 | u32 bcn_rx_inperiod; |
@@ -1477,7 +1640,8 @@ struct rtl_tcb_desc { | |||
1477 | /* early mode */ | 1640 | /* early mode */ |
1478 | u8 empkt_num; | 1641 | u8 empkt_num; |
1479 | /* The max value by HW */ | 1642 | /* The max value by HW */ |
1480 | u32 empkt_len[5]; | 1643 | u32 empkt_len[10]; |
1644 | bool btx_enable_sw_calc_duration; | ||
1481 | }; | 1645 | }; |
1482 | 1646 | ||
1483 | struct rtl_hal_ops { | 1647 | struct rtl_hal_ops { |
@@ -1553,7 +1717,7 @@ struct rtl_hal_ops { | |||
1553 | void (*allow_all_destaddr)(struct ieee80211_hw *hw, | 1717 | void (*allow_all_destaddr)(struct ieee80211_hw *hw, |
1554 | bool allow_all_da, bool write_into_reg); | 1718 | bool allow_all_da, bool write_into_reg); |
1555 | void (*linked_set_reg) (struct ieee80211_hw *hw); | 1719 | void (*linked_set_reg) (struct ieee80211_hw *hw); |
1556 | void (*check_switch_to_dmdp) (struct ieee80211_hw *hw); | 1720 | void (*chk_switch_dmdp) (struct ieee80211_hw *hw); |
1557 | void (*dualmac_easy_concurrent) (struct ieee80211_hw *hw); | 1721 | void (*dualmac_easy_concurrent) (struct ieee80211_hw *hw); |
1558 | void (*dualmac_switch_to_dmdp) (struct ieee80211_hw *hw); | 1722 | void (*dualmac_switch_to_dmdp) (struct ieee80211_hw *hw); |
1559 | bool (*phy_rf6052_config) (struct ieee80211_hw *hw); | 1723 | bool (*phy_rf6052_config) (struct ieee80211_hw *hw); |
@@ -1662,6 +1826,8 @@ struct rtl_locks { | |||
1662 | /*spin lock */ | 1826 | /*spin lock */ |
1663 | spinlock_t ips_lock; | 1827 | spinlock_t ips_lock; |
1664 | spinlock_t irq_th_lock; | 1828 | spinlock_t irq_th_lock; |
1829 | spinlock_t irq_pci_lock; | ||
1830 | spinlock_t tx_lock; | ||
1665 | spinlock_t h2c_lock; | 1831 | spinlock_t h2c_lock; |
1666 | spinlock_t rf_ps_lock; | 1832 | spinlock_t rf_ps_lock; |
1667 | spinlock_t rf_lock; | 1833 | spinlock_t rf_lock; |
@@ -1670,6 +1836,9 @@ struct rtl_locks { | |||
1670 | spinlock_t entry_list_lock; | 1836 | spinlock_t entry_list_lock; |
1671 | spinlock_t usb_lock; | 1837 | spinlock_t usb_lock; |
1672 | 1838 | ||
1839 | /*FW clock change */ | ||
1840 | spinlock_t fw_ps_lock; | ||
1841 | |||
1673 | /*Dual mac*/ | 1842 | /*Dual mac*/ |
1674 | spinlock_t cck_and_rw_pagea_lock; | 1843 | spinlock_t cck_and_rw_pagea_lock; |
1675 | 1844 | ||
@@ -1683,7 +1852,8 @@ struct rtl_works { | |||
1683 | /*timer */ | 1852 | /*timer */ |
1684 | struct timer_list watchdog_timer; | 1853 | struct timer_list watchdog_timer; |
1685 | struct timer_list dualmac_easyconcurrent_retrytimer; | 1854 | struct timer_list dualmac_easyconcurrent_retrytimer; |
1686 | 1855 | struct timer_list fw_clockoff_timer; | |
1856 | struct timer_list fast_antenna_training_timer; | ||
1687 | /*task */ | 1857 | /*task */ |
1688 | struct tasklet_struct irq_tasklet; | 1858 | struct tasklet_struct irq_tasklet; |
1689 | struct tasklet_struct irq_prepare_bcn_tasklet; | 1859 | struct tasklet_struct irq_prepare_bcn_tasklet; |
@@ -1696,8 +1866,9 @@ struct rtl_works { | |||
1696 | /* For SW LPS */ | 1866 | /* For SW LPS */ |
1697 | struct delayed_work ps_work; | 1867 | struct delayed_work ps_work; |
1698 | struct delayed_work ps_rfon_wq; | 1868 | struct delayed_work ps_rfon_wq; |
1869 | struct delayed_work fwevt_wq; | ||
1699 | 1870 | ||
1700 | struct work_struct lps_leave_work; | 1871 | struct work_struct lps_change_work; |
1701 | }; | 1872 | }; |
1702 | 1873 | ||
1703 | struct rtl_debug { | 1874 | struct rtl_debug { |
@@ -1767,10 +1938,12 @@ struct dig_t { | |||
1767 | char back_val; | 1938 | char back_val; |
1768 | char back_range_max; | 1939 | char back_range_max; |
1769 | char back_range_min; | 1940 | char back_range_min; |
1770 | u8 rx_gain_range_max; | 1941 | u8 rx_gain_max; |
1771 | u8 rx_gain_range_min; | 1942 | u8 rx_gain_min; |
1772 | u8 min_undec_pwdb_for_dm; | 1943 | u8 min_undec_pwdb_for_dm; |
1773 | u8 rssi_val_min; | 1944 | u8 rssi_val_min; |
1945 | u8 pre_cck_cca_thres; | ||
1946 | u8 cur_cck_cca_thres; | ||
1774 | u8 pre_cck_pd_state; | 1947 | u8 pre_cck_pd_state; |
1775 | u8 cur_cck_pd_state; | 1948 | u8 cur_cck_pd_state; |
1776 | u8 pre_cck_fa_state; | 1949 | u8 pre_cck_fa_state; |
@@ -1792,6 +1965,13 @@ struct dig_t { | |||
1792 | u8 backoff_enable_flag; | 1965 | u8 backoff_enable_flag; |
1793 | char backoffval_range_max; | 1966 | char backoffval_range_max; |
1794 | char backoffval_range_min; | 1967 | char backoffval_range_min; |
1968 | u8 dig_min_0; | ||
1969 | u8 dig_min_1; | ||
1970 | bool media_connect_0; | ||
1971 | bool media_connect_1; | ||
1972 | |||
1973 | u32 antdiv_rssi_max; | ||
1974 | u32 rssi_max; | ||
1795 | }; | 1975 | }; |
1796 | 1976 | ||
1797 | struct rtl_global_var { | 1977 | struct rtl_global_var { |
@@ -1802,6 +1982,7 @@ struct rtl_global_var { | |||
1802 | }; | 1982 | }; |
1803 | 1983 | ||
1804 | struct rtl_priv { | 1984 | struct rtl_priv { |
1985 | struct ieee80211_hw *hw; | ||
1805 | struct completion firmware_loading_complete; | 1986 | struct completion firmware_loading_complete; |
1806 | struct list_head list; | 1987 | struct list_head list; |
1807 | struct rtl_priv *buddy_priv; | 1988 | struct rtl_priv *buddy_priv; |
@@ -1866,6 +2047,7 @@ struct rtl_priv { | |||
1866 | bool bt_operation_on; | 2047 | bool bt_operation_on; |
1867 | }; | 2048 | }; |
1868 | }; | 2049 | }; |
2050 | bool enter_ps; /* true when entering PS */ | ||
1869 | 2051 | ||
1870 | /*This must be the last item so | 2052 | /*This must be the last item so |
1871 | that it points to the data allocated | 2053 | that it points to the data allocated |
@@ -2127,6 +2309,7 @@ value to host byte ordering.*/ | |||
2127 | #define WLAN_FC_GET_TYPE(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) | 2309 | #define WLAN_FC_GET_TYPE(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) |
2128 | #define WLAN_FC_GET_STYPE(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) | 2310 | #define WLAN_FC_GET_STYPE(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) |
2129 | #define WLAN_FC_MORE_DATA(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_MOREDATA) | 2311 | #define WLAN_FC_MORE_DATA(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_MOREDATA) |
2312 | #define rtl_dm(rtlpriv) (&((rtlpriv)->dm)) | ||
2130 | 2313 | ||
2131 | #define RT_RF_OFF_LEVL_ASPM BIT(0) /*PCI ASPM */ | 2314 | #define RT_RF_OFF_LEVL_ASPM BIT(0) /*PCI ASPM */ |
2132 | #define RT_RF_OFF_LEVL_CLK_REQ BIT(1) /*PCI clock request */ | 2315 | #define RT_RF_OFF_LEVL_CLK_REQ BIT(1) /*PCI clock request */ |
diff --git a/drivers/net/wireless/ti/wl1251/sdio.c b/drivers/net/wireless/ti/wl1251/sdio.c index e57ee48edff6..e2b3d9c541e8 100644 --- a/drivers/net/wireless/ti/wl1251/sdio.c +++ b/drivers/net/wireless/ti/wl1251/sdio.c | |||
@@ -186,8 +186,10 @@ static int wl1251_sdio_set_power(struct wl1251 *wl, bool enable) | |||
186 | wl->set_power(true); | 186 | wl->set_power(true); |
187 | 187 | ||
188 | ret = pm_runtime_get_sync(&func->dev); | 188 | ret = pm_runtime_get_sync(&func->dev); |
189 | if (ret < 0) | 189 | if (ret < 0) { |
190 | pm_runtime_put_sync(&func->dev); | ||
190 | goto out; | 191 | goto out; |
192 | } | ||
191 | 193 | ||
192 | sdio_claim_host(func); | 194 | sdio_claim_host(func); |
193 | sdio_enable_func(func); | 195 | sdio_enable_func(func); |
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index 09694e39bb14..1c627da85083 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c | |||
@@ -723,6 +723,7 @@ static int wl12xx_identify_chip(struct wl1271 *wl) | |||
723 | wl->sched_scan_templ_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4; | 723 | wl->sched_scan_templ_id_2_4 = CMD_TEMPL_CFG_PROBE_REQ_2_4; |
724 | wl->sched_scan_templ_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5; | 724 | wl->sched_scan_templ_id_5 = CMD_TEMPL_CFG_PROBE_REQ_5; |
725 | wl->max_channels_5 = WL12XX_MAX_CHANNELS_5GHZ; | 725 | wl->max_channels_5 = WL12XX_MAX_CHANNELS_5GHZ; |
726 | wl->ba_rx_session_count_max = WL12XX_RX_BA_MAX_SESSIONS; | ||
726 | out: | 727 | out: |
727 | return ret; | 728 | return ret; |
728 | } | 729 | } |
diff --git a/drivers/net/wireless/ti/wl12xx/wl12xx.h b/drivers/net/wireless/ti/wl12xx/wl12xx.h index d4552857480c..222d03540200 100644 --- a/drivers/net/wireless/ti/wl12xx/wl12xx.h +++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h | |||
@@ -63,6 +63,8 @@ | |||
63 | 63 | ||
64 | #define WL12XX_NUM_MAC_ADDRESSES 2 | 64 | #define WL12XX_NUM_MAC_ADDRESSES 2 |
65 | 65 | ||
66 | #define WL12XX_RX_BA_MAX_SESSIONS 3 | ||
67 | |||
66 | struct wl127x_rx_mem_pool_addr { | 68 | struct wl127x_rx_mem_pool_addr { |
67 | u32 addr; | 69 | u32 addr; |
68 | u32 addr_extra; | 70 | u32 addr_extra; |
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index da3ef1b10a9c..9fa692d11025 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c | |||
@@ -678,6 +678,7 @@ static int wl18xx_identify_chip(struct wl1271 *wl) | |||
678 | wl->sched_scan_templ_id_2_4 = CMD_TEMPL_PROBE_REQ_2_4_PERIODIC; | 678 | wl->sched_scan_templ_id_2_4 = CMD_TEMPL_PROBE_REQ_2_4_PERIODIC; |
679 | wl->sched_scan_templ_id_5 = CMD_TEMPL_PROBE_REQ_5_PERIODIC; | 679 | wl->sched_scan_templ_id_5 = CMD_TEMPL_PROBE_REQ_5_PERIODIC; |
680 | wl->max_channels_5 = WL18XX_MAX_CHANNELS_5GHZ; | 680 | wl->max_channels_5 = WL18XX_MAX_CHANNELS_5GHZ; |
681 | wl->ba_rx_session_count_max = WL18XX_RX_BA_MAX_SESSIONS; | ||
681 | out: | 682 | out: |
682 | return ret; | 683 | return ret; |
683 | } | 684 | } |
@@ -1144,6 +1145,7 @@ static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl, | |||
1144 | static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver) | 1145 | static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver) |
1145 | { | 1146 | { |
1146 | u32 fuse; | 1147 | u32 fuse; |
1148 | s8 rom = 0, metal = 0, pg_ver = 0, rdl_ver = 0; | ||
1147 | int ret; | 1149 | int ret; |
1148 | 1150 | ||
1149 | ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); | 1151 | ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); |
@@ -1154,8 +1156,29 @@ static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver) | |||
1154 | if (ret < 0) | 1156 | if (ret < 0) |
1155 | goto out; | 1157 | goto out; |
1156 | 1158 | ||
1159 | pg_ver = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET; | ||
1160 | rom = (fuse & WL18XX_ROM_VER_MASK) >> WL18XX_ROM_VER_OFFSET; | ||
1161 | |||
1162 | if (rom <= 0xE) | ||
1163 | metal = (fuse & WL18XX_METAL_VER_MASK) >> | ||
1164 | WL18XX_METAL_VER_OFFSET; | ||
1165 | else | ||
1166 | metal = (fuse & WL18XX_NEW_METAL_VER_MASK) >> | ||
1167 | WL18XX_NEW_METAL_VER_OFFSET; | ||
1168 | |||
1169 | ret = wlcore_read32(wl, WL18XX_REG_FUSE_DATA_2_3, &fuse); | ||
1170 | if (ret < 0) | ||
1171 | goto out; | ||
1172 | |||
1173 | rdl_ver = (fuse & WL18XX_RDL_VER_MASK) >> WL18XX_RDL_VER_OFFSET; | ||
1174 | if (rdl_ver > RDL_MAX) | ||
1175 | rdl_ver = RDL_NONE; | ||
1176 | |||
1177 | wl1271_info("wl18xx HW: RDL %d, %s, PG %x.%x (ROM %x)", | ||
1178 | rdl_ver, rdl_names[rdl_ver], pg_ver, metal, rom); | ||
1179 | |||
1157 | if (ver) | 1180 | if (ver) |
1158 | *ver = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET; | 1181 | *ver = pg_ver; |
1159 | 1182 | ||
1160 | ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | 1183 | ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); |
1161 | 1184 | ||
diff --git a/drivers/net/wireless/ti/wl18xx/reg.h b/drivers/net/wireless/ti/wl18xx/reg.h index 937b71d8783f..6306e04cd258 100644 --- a/drivers/net/wireless/ti/wl18xx/reg.h +++ b/drivers/net/wireless/ti/wl18xx/reg.h | |||
@@ -131,6 +131,16 @@ | |||
131 | #define WL18XX_REG_FUSE_DATA_1_3 0xA0260C | 131 | #define WL18XX_REG_FUSE_DATA_1_3 0xA0260C |
132 | #define WL18XX_PG_VER_MASK 0x70 | 132 | #define WL18XX_PG_VER_MASK 0x70 |
133 | #define WL18XX_PG_VER_OFFSET 4 | 133 | #define WL18XX_PG_VER_OFFSET 4 |
134 | #define WL18XX_ROM_VER_MASK 0x3 | ||
135 | #define WL18XX_ROM_VER_OFFSET 0 | ||
136 | #define WL18XX_METAL_VER_MASK 0xC | ||
137 | #define WL18XX_METAL_VER_OFFSET 2 | ||
138 | #define WL18XX_NEW_METAL_VER_MASK 0x180 | ||
139 | #define WL18XX_NEW_METAL_VER_OFFSET 7 | ||
140 | |||
141 | #define WL18XX_REG_FUSE_DATA_2_3 0xA02614 | ||
142 | #define WL18XX_RDL_VER_MASK 0x1f00 | ||
143 | #define WL18XX_RDL_VER_OFFSET 8 | ||
134 | 144 | ||
135 | #define WL18XX_REG_FUSE_BD_ADDR_1 0xA02602 | 145 | #define WL18XX_REG_FUSE_BD_ADDR_1 0xA02602 |
136 | #define WL18XX_REG_FUSE_BD_ADDR_2 0xA02606 | 146 | #define WL18XX_REG_FUSE_BD_ADDR_2 0xA02606 |
@@ -188,4 +198,23 @@ enum { | |||
188 | NUM_BOARD_TYPES, | 198 | NUM_BOARD_TYPES, |
189 | }; | 199 | }; |
190 | 200 | ||
201 | enum { | ||
202 | RDL_NONE = 0, | ||
203 | RDL_1_HP = 1, | ||
204 | RDL_2_SP = 2, | ||
205 | RDL_3_HP = 3, | ||
206 | RDL_4_SP = 4, | ||
207 | |||
208 | _RDL_LAST, | ||
209 | RDL_MAX = _RDL_LAST - 1, | ||
210 | }; | ||
211 | |||
212 | static const char * const rdl_names[] = { | ||
213 | [RDL_NONE] = "", | ||
214 | [RDL_1_HP] = "1853 SISO", | ||
215 | [RDL_2_SP] = "1857 MIMO", | ||
216 | [RDL_3_HP] = "1893 SISO", | ||
217 | [RDL_4_SP] = "1897 MIMO", | ||
218 | }; | ||
219 | |||
191 | #endif /* __REG_H__ */ | 220 | #endif /* __REG_H__ */ |
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h index b6739e79efcf..9204e07ee432 100644 --- a/drivers/net/wireless/ti/wl18xx/wl18xx.h +++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h | |||
@@ -29,7 +29,7 @@ | |||
29 | #define WL18XX_IFTYPE_VER 5 | 29 | #define WL18XX_IFTYPE_VER 5 |
30 | #define WL18XX_MAJOR_VER WLCORE_FW_VER_IGNORE | 30 | #define WL18XX_MAJOR_VER WLCORE_FW_VER_IGNORE |
31 | #define WL18XX_SUBTYPE_VER WLCORE_FW_VER_IGNORE | 31 | #define WL18XX_SUBTYPE_VER WLCORE_FW_VER_IGNORE |
32 | #define WL18XX_MINOR_VER 28 | 32 | #define WL18XX_MINOR_VER 39 |
33 | 33 | ||
34 | #define WL18XX_CMD_MAX_SIZE 740 | 34 | #define WL18XX_CMD_MAX_SIZE 740 |
35 | 35 | ||
@@ -40,6 +40,8 @@ | |||
40 | 40 | ||
41 | #define WL18XX_NUM_MAC_ADDRESSES 3 | 41 | #define WL18XX_NUM_MAC_ADDRESSES 3 |
42 | 42 | ||
43 | #define WL18XX_RX_BA_MAX_SESSIONS 5 | ||
44 | |||
43 | struct wl18xx_priv { | 45 | struct wl18xx_priv { |
44 | /* buffer for sending commands to FW */ | 46 | /* buffer for sending commands to FW */ |
45 | u8 cmd_buf[WL18XX_CMD_MAX_SIZE]; | 47 | u8 cmd_buf[WL18XX_CMD_MAX_SIZE]; |
diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c index c79654323396..7a970cd9c555 100644 --- a/drivers/net/wireless/ti/wlcore/acx.c +++ b/drivers/net/wireless/ti/wlcore/acx.c | |||
@@ -1736,6 +1736,35 @@ out: | |||
1736 | 1736 | ||
1737 | } | 1737 | } |
1738 | 1738 | ||
1739 | int wlcore_acx_average_rssi(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
1740 | s8 *avg_rssi) | ||
1741 | { | ||
1742 | struct acx_roaming_stats *acx; | ||
1743 | int ret = 0; | ||
1744 | |||
1745 | wl1271_debug(DEBUG_ACX, "acx roaming statistics"); | ||
1746 | |||
1747 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1748 | if (!acx) { | ||
1749 | ret = -ENOMEM; | ||
1750 | goto out; | ||
1751 | } | ||
1752 | |||
1753 | acx->role_id = wlvif->role_id; | ||
1754 | ret = wl1271_cmd_interrogate(wl, ACX_ROAMING_STATISTICS_TBL, | ||
1755 | acx, sizeof(*acx)); | ||
1756 | if (ret < 0) { | ||
1757 | wl1271_warning("acx roaming statistics failed: %d", ret); | ||
1758 | ret = -ENOMEM; | ||
1759 | goto out; | ||
1760 | } | ||
1761 | |||
1762 | *avg_rssi = acx->rssi_beacon; | ||
1763 | out: | ||
1764 | kfree(acx); | ||
1765 | return ret; | ||
1766 | } | ||
1767 | |||
1739 | #ifdef CONFIG_PM | 1768 | #ifdef CONFIG_PM |
1740 | /* Set the global behaviour of RX filters - On/Off + default action */ | 1769 | /* Set the global behaviour of RX filters - On/Off + default action */ |
1741 | int wl1271_acx_default_rx_filter_enable(struct wl1271 *wl, bool enable, | 1770 | int wl1271_acx_default_rx_filter_enable(struct wl1271 *wl, bool enable, |
diff --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h index 126536c6a393..6dcfad9b0472 100644 --- a/drivers/net/wireless/ti/wlcore/acx.h +++ b/drivers/net/wireless/ti/wlcore/acx.h | |||
@@ -728,8 +728,6 @@ struct wl1271_acx_ht_information { | |||
728 | u8 padding[2]; | 728 | u8 padding[2]; |
729 | } __packed; | 729 | } __packed; |
730 | 730 | ||
731 | #define RX_BA_MAX_SESSIONS 3 | ||
732 | |||
733 | struct wl1271_acx_ba_initiator_policy { | 731 | struct wl1271_acx_ba_initiator_policy { |
734 | struct acx_header header; | 732 | struct acx_header header; |
735 | 733 | ||
@@ -955,6 +953,18 @@ struct acx_rx_filter_cfg { | |||
955 | u8 fields[0]; | 953 | u8 fields[0]; |
956 | } __packed; | 954 | } __packed; |
957 | 955 | ||
956 | struct acx_roaming_stats { | ||
957 | struct acx_header header; | ||
958 | |||
959 | u8 role_id; | ||
960 | u8 pad[3]; | ||
961 | u32 missed_beacons; | ||
962 | u8 snr_data; | ||
963 | u8 snr_bacon; | ||
964 | s8 rssi_data; | ||
965 | s8 rssi_beacon; | ||
966 | } __packed; | ||
967 | |||
958 | enum { | 968 | enum { |
959 | ACX_WAKE_UP_CONDITIONS = 0x0000, | 969 | ACX_WAKE_UP_CONDITIONS = 0x0000, |
960 | ACX_MEM_CFG = 0x0001, | 970 | ACX_MEM_CFG = 0x0001, |
@@ -1112,6 +1122,8 @@ int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); | |||
1112 | int wl1271_acx_fm_coex(struct wl1271 *wl); | 1122 | int wl1271_acx_fm_coex(struct wl1271 *wl); |
1113 | int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl); | 1123 | int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl); |
1114 | int wl12xx_acx_config_hangover(struct wl1271 *wl); | 1124 | int wl12xx_acx_config_hangover(struct wl1271 *wl); |
1125 | int wlcore_acx_average_rssi(struct wl1271 *wl, struct wl12xx_vif *wlvif, | ||
1126 | s8 *avg_rssi); | ||
1115 | 1127 | ||
1116 | #ifdef CONFIG_PM | 1128 | #ifdef CONFIG_PM |
1117 | int wl1271_acx_default_rx_filter_enable(struct wl1271 *wl, bool enable, | 1129 | int wl1271_acx_default_rx_filter_enable(struct wl1271 *wl, bool enable, |
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 6331f9e1cb39..c9e060795d13 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c | |||
@@ -327,6 +327,14 @@ int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) | |||
327 | wl->links[link].prev_freed_pkts = | 327 | wl->links[link].prev_freed_pkts = |
328 | wl->fw_status_2->counters.tx_lnk_free_pkts[link]; | 328 | wl->fw_status_2->counters.tx_lnk_free_pkts[link]; |
329 | wl->links[link].wlvif = wlvif; | 329 | wl->links[link].wlvif = wlvif; |
330 | |||
331 | /* | ||
332 | * Take saved value for total freed packets from wlvif, in case this is | ||
333 | * recovery/resume | ||
334 | */ | ||
335 | if (wlvif->bss_type != BSS_TYPE_AP_BSS) | ||
336 | wl->links[link].total_freed_pkts = wlvif->total_freed_pkts; | ||
337 | |||
330 | *hlid = link; | 338 | *hlid = link; |
331 | 339 | ||
332 | wl->active_link_count++; | 340 | wl->active_link_count++; |
@@ -358,6 +366,26 @@ void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) | |||
358 | wl1271_tx_reset_link_queues(wl, *hlid); | 366 | wl1271_tx_reset_link_queues(wl, *hlid); |
359 | wl->links[*hlid].wlvif = NULL; | 367 | wl->links[*hlid].wlvif = NULL; |
360 | 368 | ||
369 | if (wlvif->bss_type == BSS_TYPE_STA_BSS || | ||
370 | (wlvif->bss_type == BSS_TYPE_AP_BSS && | ||
371 | *hlid == wlvif->ap.bcast_hlid)) { | ||
372 | /* | ||
373 | * save the total freed packets in the wlvif, in case this is | ||
374 | * recovery or suspend | ||
375 | */ | ||
376 | wlvif->total_freed_pkts = wl->links[*hlid].total_freed_pkts; | ||
377 | |||
378 | /* | ||
379 | * increment the initial seq number on recovery to account for | ||
380 | * transmitted packets that we haven't yet got in the FW status | ||
381 | */ | ||
382 | if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) | ||
383 | wlvif->total_freed_pkts += | ||
384 | WL1271_TX_SQN_POST_RECOVERY_PADDING; | ||
385 | } | ||
386 | |||
387 | wl->links[*hlid].total_freed_pkts = 0; | ||
388 | |||
361 | *hlid = WL12XX_INVALID_LINK_ID; | 389 | *hlid = WL12XX_INVALID_LINK_ID; |
362 | wl->active_link_count--; | 390 | wl->active_link_count--; |
363 | WARN_ON_ONCE(wl->active_link_count < 0); | 391 | WARN_ON_ONCE(wl->active_link_count < 0); |
@@ -609,6 +637,10 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
609 | if (ret < 0) | 637 | if (ret < 0) |
610 | goto out_free_global; | 638 | goto out_free_global; |
611 | 639 | ||
640 | /* use the previous security seq, if this is a recovery/resume */ | ||
641 | wl->links[wlvif->ap.bcast_hlid].total_freed_pkts = | ||
642 | wlvif->total_freed_pkts; | ||
643 | |||
612 | cmd->role_id = wlvif->role_id; | 644 | cmd->role_id = wlvif->role_id; |
613 | cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); | 645 | cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); |
614 | cmd->ap.bss_index = WL1271_AP_BSS_INDEX; | 646 | cmd->ap.bss_index = WL1271_AP_BSS_INDEX; |
diff --git a/drivers/net/wireless/ti/wlcore/debug.h b/drivers/net/wireless/ti/wlcore/debug.h index db4bf5a68ce2..0420bd45e4ee 100644 --- a/drivers/net/wireless/ti/wlcore/debug.h +++ b/drivers/net/wireless/ti/wlcore/debug.h | |||
@@ -89,25 +89,24 @@ extern u32 wl12xx_debug_level; | |||
89 | } while (0) | 89 | } while (0) |
90 | #endif | 90 | #endif |
91 | 91 | ||
92 | /* TODO: use pr_debug_hex_dump when it becomes available */ | 92 | #define wl1271_dump(level, prefix, buf, len) \ |
93 | #define wl1271_dump(level, prefix, buf, len) \ | 93 | do { \ |
94 | do { \ | 94 | if (level & wl12xx_debug_level) \ |
95 | if (level & wl12xx_debug_level) \ | 95 | print_hex_dump_debug(DRIVER_PREFIX prefix, \ |
96 | print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ | 96 | DUMP_PREFIX_OFFSET, 16, 1, \ |
97 | DUMP_PREFIX_OFFSET, 16, 1, \ | 97 | buf, \ |
98 | buf, \ | 98 | min_t(size_t, len, DEBUG_DUMP_LIMIT), \ |
99 | min_t(size_t, len, DEBUG_DUMP_LIMIT), \ | 99 | 0); \ |
100 | 0); \ | ||
101 | } while (0) | 100 | } while (0) |
102 | 101 | ||
103 | #define wl1271_dump_ascii(level, prefix, buf, len) \ | 102 | #define wl1271_dump_ascii(level, prefix, buf, len) \ |
104 | do { \ | 103 | do { \ |
105 | if (level & wl12xx_debug_level) \ | 104 | if (level & wl12xx_debug_level) \ |
106 | print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ | 105 | print_hex_dump_debug(DRIVER_PREFIX prefix, \ |
107 | DUMP_PREFIX_OFFSET, 16, 1, \ | 106 | DUMP_PREFIX_OFFSET, 16, 1, \ |
108 | buf, \ | 107 | buf, \ |
109 | min_t(size_t, len, DEBUG_DUMP_LIMIT), \ | 108 | min_t(size_t, len, DEBUG_DUMP_LIMIT), \ |
110 | true); \ | 109 | true); \ |
111 | } while (0) | 110 | } while (0) |
112 | 111 | ||
113 | #endif /* __DEBUG_H__ */ | 112 | #endif /* __DEBUG_H__ */ |
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c index e70a7c864865..c3e1f79c7856 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.c +++ b/drivers/net/wireless/ti/wlcore/debugfs.c | |||
@@ -598,8 +598,7 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf, | |||
598 | VIF_STATE_PRINT_INT(last_rssi_event); | 598 | VIF_STATE_PRINT_INT(last_rssi_event); |
599 | VIF_STATE_PRINT_INT(ba_support); | 599 | VIF_STATE_PRINT_INT(ba_support); |
600 | VIF_STATE_PRINT_INT(ba_allowed); | 600 | VIF_STATE_PRINT_INT(ba_allowed); |
601 | VIF_STATE_PRINT_LLHEX(tx_security_seq); | 601 | VIF_STATE_PRINT_LLHEX(total_freed_pkts); |
602 | VIF_STATE_PRINT_INT(tx_security_last_seq_lsb); | ||
603 | } | 602 | } |
604 | 603 | ||
605 | #undef VIF_STATE_PRINT_INT | 604 | #undef VIF_STATE_PRINT_INT |
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c index 70f289aa1bc6..67f61689b49e 100644 --- a/drivers/net/wireless/ti/wlcore/event.c +++ b/drivers/net/wireless/ti/wlcore/event.c | |||
@@ -237,6 +237,14 @@ void wlcore_event_beacon_loss(struct wl1271 *wl, unsigned long roles_bitmap) | |||
237 | !test_bit(wlvif->role_id , &roles_bitmap)) | 237 | !test_bit(wlvif->role_id , &roles_bitmap)) |
238 | continue; | 238 | continue; |
239 | 239 | ||
240 | vif = wl12xx_wlvif_to_vif(wlvif); | ||
241 | |||
242 | /* don't attempt roaming in case of p2p */ | ||
243 | if (wlvif->p2p) { | ||
244 | ieee80211_connection_loss(vif); | ||
245 | continue; | ||
246 | } | ||
247 | |||
240 | /* | 248 | /* |
241 | * if the work is already queued, it should take place. | 249 | * if the work is already queued, it should take place. |
242 | * We don't want to delay the connection loss | 250 | * We don't want to delay the connection loss |
@@ -246,7 +254,6 @@ void wlcore_event_beacon_loss(struct wl1271 *wl, unsigned long roles_bitmap) | |||
246 | &wlvif->connection_loss_work, | 254 | &wlvif->connection_loss_work, |
247 | msecs_to_jiffies(delay)); | 255 | msecs_to_jiffies(delay)); |
248 | 256 | ||
249 | vif = wl12xx_wlvif_to_vif(wlvif); | ||
250 | ieee80211_cqm_rssi_notify( | 257 | ieee80211_cqm_rssi_notify( |
251 | vif, | 258 | vif, |
252 | NL80211_CQM_RSSI_BEACON_LOSS_EVENT, | 259 | NL80211_CQM_RSSI_BEACON_LOSS_EVENT, |
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index d7e306333f6c..d10954c0c181 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
@@ -108,8 +108,7 @@ static void wl1271_reg_notify(struct wiphy *wiphy, | |||
108 | 108 | ||
109 | } | 109 | } |
110 | 110 | ||
111 | if (likely(wl->state == WLCORE_STATE_ON)) | 111 | wlcore_regdomain_config(wl); |
112 | wlcore_regdomain_config(wl); | ||
113 | } | 112 | } |
114 | 113 | ||
115 | static int wl1271_set_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 114 | static int wl1271_set_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
@@ -332,10 +331,9 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, | |||
332 | struct wl12xx_vif *wlvif, | 331 | struct wl12xx_vif *wlvif, |
333 | u8 hlid, u8 tx_pkts) | 332 | u8 hlid, u8 tx_pkts) |
334 | { | 333 | { |
335 | bool fw_ps, single_link; | 334 | bool fw_ps; |
336 | 335 | ||
337 | fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); | 336 | fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); |
338 | single_link = (wl->active_link_count == 1); | ||
339 | 337 | ||
340 | /* | 338 | /* |
341 | * Wake up from high level PS if the STA is asleep with too little | 339 | * Wake up from high level PS if the STA is asleep with too little |
@@ -348,8 +346,13 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, | |||
348 | * Start high-level PS if the STA is asleep with enough blocks in FW. | 346 | * Start high-level PS if the STA is asleep with enough blocks in FW. |
349 | * Make an exception if this is the only connected link. In this | 347 | * Make an exception if this is the only connected link. In this |
350 | * case FW-memory congestion is less of a problem. | 348 | * case FW-memory congestion is less of a problem. |
349 | * Note that a single connected STA means 3 active links, since we must | ||
350 | * account for the global and broadcast AP links. The "fw_ps" check | ||
351 | * assures us the third link is a STA connected to the AP. Otherwise | ||
352 | * the FW would not set the PSM bit. | ||
351 | */ | 353 | */ |
352 | else if (!single_link && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS) | 354 | else if (wl->active_link_count > 3 && fw_ps && |
355 | tx_pkts >= WL1271_PS_STA_MAX_PACKETS) | ||
353 | wl12xx_ps_link_start(wl, wlvif, hlid, true); | 356 | wl12xx_ps_link_start(wl, wlvif, hlid, true); |
354 | } | 357 | } |
355 | 358 | ||
@@ -414,13 +417,21 @@ static int wlcore_fw_status(struct wl1271 *wl, | |||
414 | 417 | ||
415 | 418 | ||
416 | for_each_set_bit(i, wl->links_map, WL12XX_MAX_LINKS) { | 419 | for_each_set_bit(i, wl->links_map, WL12XX_MAX_LINKS) { |
420 | u8 diff; | ||
417 | lnk = &wl->links[i]; | 421 | lnk = &wl->links[i]; |
422 | |||
418 | /* prevent wrap-around in freed-packets counter */ | 423 | /* prevent wrap-around in freed-packets counter */ |
419 | lnk->allocated_pkts -= | 424 | diff = (status_2->counters.tx_lnk_free_pkts[i] - |
420 | (status_2->counters.tx_lnk_free_pkts[i] - | 425 | lnk->prev_freed_pkts) & 0xff; |
421 | lnk->prev_freed_pkts) & 0xff; | 426 | |
427 | if (diff == 0) | ||
428 | continue; | ||
422 | 429 | ||
430 | lnk->allocated_pkts -= diff; | ||
423 | lnk->prev_freed_pkts = status_2->counters.tx_lnk_free_pkts[i]; | 431 | lnk->prev_freed_pkts = status_2->counters.tx_lnk_free_pkts[i]; |
432 | |||
433 | /* accumulate the prev_freed_pkts counter */ | ||
434 | lnk->total_freed_pkts += diff; | ||
424 | } | 435 | } |
425 | 436 | ||
426 | /* prevent wrap-around in total blocks counter */ | 437 | /* prevent wrap-around in total blocks counter */ |
@@ -640,6 +651,25 @@ static irqreturn_t wlcore_irq(int irq, void *cookie) | |||
640 | unsigned long flags; | 651 | unsigned long flags; |
641 | struct wl1271 *wl = cookie; | 652 | struct wl1271 *wl = cookie; |
642 | 653 | ||
654 | /* complete the ELP completion */ | ||
655 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
656 | set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); | ||
657 | if (wl->elp_compl) { | ||
658 | complete(wl->elp_compl); | ||
659 | wl->elp_compl = NULL; | ||
660 | } | ||
661 | |||
662 | if (test_bit(WL1271_FLAG_SUSPENDED, &wl->flags)) { | ||
663 | /* don't enqueue a work right now. mark it as pending */ | ||
664 | set_bit(WL1271_FLAG_PENDING_WORK, &wl->flags); | ||
665 | wl1271_debug(DEBUG_IRQ, "should not enqueue work"); | ||
666 | disable_irq_nosync(wl->irq); | ||
667 | pm_wakeup_event(wl->dev, 0); | ||
668 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
669 | return IRQ_HANDLED; | ||
670 | } | ||
671 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
672 | |||
643 | /* TX might be handled here, avoid redundant work */ | 673 | /* TX might be handled here, avoid redundant work */ |
644 | set_bit(WL1271_FLAG_TX_PENDING, &wl->flags); | 674 | set_bit(WL1271_FLAG_TX_PENDING, &wl->flags); |
645 | cancel_work_sync(&wl->tx_work); | 675 | cancel_work_sync(&wl->tx_work); |
@@ -919,18 +949,6 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
919 | goto out_unlock; | 949 | goto out_unlock; |
920 | } | 950 | } |
921 | 951 | ||
922 | /* | ||
923 | * Advance security sequence number to overcome potential progress | ||
924 | * in the firmware during recovery. This doens't hurt if the network is | ||
925 | * not encrypted. | ||
926 | */ | ||
927 | wl12xx_for_each_wlvif(wl, wlvif) { | ||
928 | if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) || | ||
929 | test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) | ||
930 | wlvif->tx_security_seq += | ||
931 | WL1271_TX_SQN_POST_RECOVERY_PADDING; | ||
932 | } | ||
933 | |||
934 | /* Prevent spurious TX during FW restart */ | 952 | /* Prevent spurious TX during FW restart */ |
935 | wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_FW_RESTART); | 953 | wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_FW_RESTART); |
936 | 954 | ||
@@ -2523,6 +2541,8 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, | |||
2523 | wl1271_ps_elp_sleep(wl); | 2541 | wl1271_ps_elp_sleep(wl); |
2524 | } | 2542 | } |
2525 | deinit: | 2543 | deinit: |
2544 | wl12xx_tx_reset_wlvif(wl, wlvif); | ||
2545 | |||
2526 | /* clear all hlids (except system_hlid) */ | 2546 | /* clear all hlids (except system_hlid) */ |
2527 | wlvif->dev_hlid = WL12XX_INVALID_LINK_ID; | 2547 | wlvif->dev_hlid = WL12XX_INVALID_LINK_ID; |
2528 | 2548 | ||
@@ -2546,7 +2566,6 @@ deinit: | |||
2546 | 2566 | ||
2547 | dev_kfree_skb(wlvif->probereq); | 2567 | dev_kfree_skb(wlvif->probereq); |
2548 | wlvif->probereq = NULL; | 2568 | wlvif->probereq = NULL; |
2549 | wl12xx_tx_reset_wlvif(wl, wlvif); | ||
2550 | if (wl->last_wlvif == wlvif) | 2569 | if (wl->last_wlvif == wlvif) |
2551 | wl->last_wlvif = NULL; | 2570 | wl->last_wlvif = NULL; |
2552 | list_del(&wlvif->list); | 2571 | list_del(&wlvif->list); |
@@ -2860,10 +2879,6 @@ static int wlcore_unset_assoc(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
2860 | wlvif->sta.klv_template_id, | 2879 | wlvif->sta.klv_template_id, |
2861 | ACX_KEEP_ALIVE_TPL_INVALID); | 2880 | ACX_KEEP_ALIVE_TPL_INVALID); |
2862 | 2881 | ||
2863 | /* reset TX security counters on a clean disconnect */ | ||
2864 | wlvif->tx_security_last_seq_lsb = 0; | ||
2865 | wlvif->tx_security_seq = 0; | ||
2866 | |||
2867 | return 0; | 2882 | return 0; |
2868 | } | 2883 | } |
2869 | 2884 | ||
@@ -3262,6 +3277,7 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, | |||
3262 | u32 tx_seq_32 = 0; | 3277 | u32 tx_seq_32 = 0; |
3263 | u16 tx_seq_16 = 0; | 3278 | u16 tx_seq_16 = 0; |
3264 | u8 key_type; | 3279 | u8 key_type; |
3280 | u8 hlid; | ||
3265 | 3281 | ||
3266 | wl1271_debug(DEBUG_MAC80211, "mac80211 set key"); | 3282 | wl1271_debug(DEBUG_MAC80211, "mac80211 set key"); |
3267 | 3283 | ||
@@ -3271,6 +3287,22 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, | |||
3271 | key_conf->keylen, key_conf->flags); | 3287 | key_conf->keylen, key_conf->flags); |
3272 | wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen); | 3288 | wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen); |
3273 | 3289 | ||
3290 | if (wlvif->bss_type == BSS_TYPE_AP_BSS) | ||
3291 | if (sta) { | ||
3292 | struct wl1271_station *wl_sta = (void *)sta->drv_priv; | ||
3293 | hlid = wl_sta->hlid; | ||
3294 | } else { | ||
3295 | hlid = wlvif->ap.bcast_hlid; | ||
3296 | } | ||
3297 | else | ||
3298 | hlid = wlvif->sta.hlid; | ||
3299 | |||
3300 | if (hlid != WL12XX_INVALID_LINK_ID) { | ||
3301 | u64 tx_seq = wl->links[hlid].total_freed_pkts; | ||
3302 | tx_seq_32 = WL1271_TX_SECURITY_HI32(tx_seq); | ||
3303 | tx_seq_16 = WL1271_TX_SECURITY_LO16(tx_seq); | ||
3304 | } | ||
3305 | |||
3274 | switch (key_conf->cipher) { | 3306 | switch (key_conf->cipher) { |
3275 | case WLAN_CIPHER_SUITE_WEP40: | 3307 | case WLAN_CIPHER_SUITE_WEP40: |
3276 | case WLAN_CIPHER_SUITE_WEP104: | 3308 | case WLAN_CIPHER_SUITE_WEP104: |
@@ -3280,22 +3312,14 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, | |||
3280 | break; | 3312 | break; |
3281 | case WLAN_CIPHER_SUITE_TKIP: | 3313 | case WLAN_CIPHER_SUITE_TKIP: |
3282 | key_type = KEY_TKIP; | 3314 | key_type = KEY_TKIP; |
3283 | |||
3284 | key_conf->hw_key_idx = key_conf->keyidx; | 3315 | key_conf->hw_key_idx = key_conf->keyidx; |
3285 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq); | ||
3286 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq); | ||
3287 | break; | 3316 | break; |
3288 | case WLAN_CIPHER_SUITE_CCMP: | 3317 | case WLAN_CIPHER_SUITE_CCMP: |
3289 | key_type = KEY_AES; | 3318 | key_type = KEY_AES; |
3290 | |||
3291 | key_conf->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE; | 3319 | key_conf->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE; |
3292 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq); | ||
3293 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq); | ||
3294 | break; | 3320 | break; |
3295 | case WL1271_CIPHER_SUITE_GEM: | 3321 | case WL1271_CIPHER_SUITE_GEM: |
3296 | key_type = KEY_GEM; | 3322 | key_type = KEY_GEM; |
3297 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq); | ||
3298 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq); | ||
3299 | break; | 3323 | break; |
3300 | default: | 3324 | default: |
3301 | wl1271_error("Unknown key algo 0x%x", key_conf->cipher); | 3325 | wl1271_error("Unknown key algo 0x%x", key_conf->cipher); |
@@ -3358,6 +3382,10 @@ void wlcore_regdomain_config(struct wl1271 *wl) | |||
3358 | return; | 3382 | return; |
3359 | 3383 | ||
3360 | mutex_lock(&wl->mutex); | 3384 | mutex_lock(&wl->mutex); |
3385 | |||
3386 | if (unlikely(wl->state != WLCORE_STATE_ON)) | ||
3387 | goto out; | ||
3388 | |||
3361 | ret = wl1271_ps_elp_wakeup(wl); | 3389 | ret = wl1271_ps_elp_wakeup(wl); |
3362 | if (ret < 0) | 3390 | if (ret < 0) |
3363 | goto out; | 3391 | goto out; |
@@ -4499,6 +4527,9 @@ static int wl1271_allocate_sta(struct wl1271 *wl, | |||
4499 | return -EBUSY; | 4527 | return -EBUSY; |
4500 | } | 4528 | } |
4501 | 4529 | ||
4530 | /* use the previous security seq, if this is a recovery/resume */ | ||
4531 | wl->links[wl_sta->hlid].total_freed_pkts = wl_sta->total_freed_pkts; | ||
4532 | |||
4502 | set_bit(wl_sta->hlid, wlvif->ap.sta_hlid_map); | 4533 | set_bit(wl_sta->hlid, wlvif->ap.sta_hlid_map); |
4503 | memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN); | 4534 | memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN); |
4504 | wl->active_sta_count++; | 4535 | wl->active_sta_count++; |
@@ -4507,12 +4538,37 @@ static int wl1271_allocate_sta(struct wl1271 *wl, | |||
4507 | 4538 | ||
4508 | void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid) | 4539 | void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid) |
4509 | { | 4540 | { |
4541 | struct wl1271_station *wl_sta; | ||
4542 | struct ieee80211_sta *sta; | ||
4543 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); | ||
4544 | |||
4510 | if (!test_bit(hlid, wlvif->ap.sta_hlid_map)) | 4545 | if (!test_bit(hlid, wlvif->ap.sta_hlid_map)) |
4511 | return; | 4546 | return; |
4512 | 4547 | ||
4513 | clear_bit(hlid, wlvif->ap.sta_hlid_map); | 4548 | clear_bit(hlid, wlvif->ap.sta_hlid_map); |
4514 | __clear_bit(hlid, &wl->ap_ps_map); | 4549 | __clear_bit(hlid, &wl->ap_ps_map); |
4515 | __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); | 4550 | __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); |
4551 | |||
4552 | /* | ||
4553 | * save the last used PN in the private part of iee80211_sta, | ||
4554 | * in case of recovery/suspend | ||
4555 | */ | ||
4556 | rcu_read_lock(); | ||
4557 | sta = ieee80211_find_sta(vif, wl->links[hlid].addr); | ||
4558 | if (sta) { | ||
4559 | wl_sta = (void *)sta->drv_priv; | ||
4560 | wl_sta->total_freed_pkts = wl->links[hlid].total_freed_pkts; | ||
4561 | |||
4562 | /* | ||
4563 | * increment the initial seq number on recovery to account for | ||
4564 | * transmitted packets that we haven't yet got in the FW status | ||
4565 | */ | ||
4566 | if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) | ||
4567 | wl_sta->total_freed_pkts += | ||
4568 | WL1271_TX_SQN_POST_RECOVERY_PADDING; | ||
4569 | } | ||
4570 | rcu_read_unlock(); | ||
4571 | |||
4516 | wl12xx_free_link(wl, wlvif, &hlid); | 4572 | wl12xx_free_link(wl, wlvif, &hlid); |
4517 | wl->active_sta_count--; | 4573 | wl->active_sta_count--; |
4518 | 4574 | ||
@@ -4616,13 +4672,11 @@ static int wl12xx_update_sta_state(struct wl1271 *wl, | |||
4616 | enum ieee80211_sta_state new_state) | 4672 | enum ieee80211_sta_state new_state) |
4617 | { | 4673 | { |
4618 | struct wl1271_station *wl_sta; | 4674 | struct wl1271_station *wl_sta; |
4619 | u8 hlid; | ||
4620 | bool is_ap = wlvif->bss_type == BSS_TYPE_AP_BSS; | 4675 | bool is_ap = wlvif->bss_type == BSS_TYPE_AP_BSS; |
4621 | bool is_sta = wlvif->bss_type == BSS_TYPE_STA_BSS; | 4676 | bool is_sta = wlvif->bss_type == BSS_TYPE_STA_BSS; |
4622 | int ret; | 4677 | int ret; |
4623 | 4678 | ||
4624 | wl_sta = (struct wl1271_station *)sta->drv_priv; | 4679 | wl_sta = (struct wl1271_station *)sta->drv_priv; |
4625 | hlid = wl_sta->hlid; | ||
4626 | 4680 | ||
4627 | /* Add station (AP mode) */ | 4681 | /* Add station (AP mode) */ |
4628 | if (is_ap && | 4682 | if (is_ap && |
@@ -4648,12 +4702,12 @@ static int wl12xx_update_sta_state(struct wl1271 *wl, | |||
4648 | /* Authorize station (AP mode) */ | 4702 | /* Authorize station (AP mode) */ |
4649 | if (is_ap && | 4703 | if (is_ap && |
4650 | new_state == IEEE80211_STA_AUTHORIZED) { | 4704 | new_state == IEEE80211_STA_AUTHORIZED) { |
4651 | ret = wl12xx_cmd_set_peer_state(wl, wlvif, hlid); | 4705 | ret = wl12xx_cmd_set_peer_state(wl, wlvif, wl_sta->hlid); |
4652 | if (ret < 0) | 4706 | if (ret < 0) |
4653 | return ret; | 4707 | return ret; |
4654 | 4708 | ||
4655 | ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true, | 4709 | ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true, |
4656 | hlid); | 4710 | wl_sta->hlid); |
4657 | if (ret) | 4711 | if (ret) |
4658 | return ret; | 4712 | return ret; |
4659 | 4713 | ||
@@ -4784,7 +4838,7 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, | |||
4784 | break; | 4838 | break; |
4785 | } | 4839 | } |
4786 | 4840 | ||
4787 | if (wl->ba_rx_session_count >= RX_BA_MAX_SESSIONS) { | 4841 | if (wl->ba_rx_session_count >= wl->ba_rx_session_count_max) { |
4788 | ret = -EBUSY; | 4842 | ret = -EBUSY; |
4789 | wl1271_error("exceeded max RX BA sessions"); | 4843 | wl1271_error("exceeded max RX BA sessions"); |
4790 | break; | 4844 | break; |
@@ -4946,7 +5000,7 @@ out: | |||
4946 | mutex_unlock(&wl->mutex); | 5000 | mutex_unlock(&wl->mutex); |
4947 | } | 5001 | } |
4948 | 5002 | ||
4949 | static void wlcore_op_flush(struct ieee80211_hw *hw, bool drop) | 5003 | static void wlcore_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop) |
4950 | { | 5004 | { |
4951 | struct wl1271 *wl = hw->priv; | 5005 | struct wl1271 *wl = hw->priv; |
4952 | 5006 | ||
@@ -5092,6 +5146,39 @@ static void wlcore_op_sta_rc_update(struct ieee80211_hw *hw, | |||
5092 | wlcore_hw_sta_rc_update(wl, wlvif, sta, changed); | 5146 | wlcore_hw_sta_rc_update(wl, wlvif, sta, changed); |
5093 | } | 5147 | } |
5094 | 5148 | ||
5149 | static int wlcore_op_get_rssi(struct ieee80211_hw *hw, | ||
5150 | struct ieee80211_vif *vif, | ||
5151 | struct ieee80211_sta *sta, | ||
5152 | s8 *rssi_dbm) | ||
5153 | { | ||
5154 | struct wl1271 *wl = hw->priv; | ||
5155 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
5156 | int ret = 0; | ||
5157 | |||
5158 | wl1271_debug(DEBUG_MAC80211, "mac80211 get_rssi"); | ||
5159 | |||
5160 | mutex_lock(&wl->mutex); | ||
5161 | |||
5162 | if (unlikely(wl->state != WLCORE_STATE_ON)) | ||
5163 | goto out; | ||
5164 | |||
5165 | ret = wl1271_ps_elp_wakeup(wl); | ||
5166 | if (ret < 0) | ||
5167 | goto out_sleep; | ||
5168 | |||
5169 | ret = wlcore_acx_average_rssi(wl, wlvif, rssi_dbm); | ||
5170 | if (ret < 0) | ||
5171 | goto out_sleep; | ||
5172 | |||
5173 | out_sleep: | ||
5174 | wl1271_ps_elp_sleep(wl); | ||
5175 | |||
5176 | out: | ||
5177 | mutex_unlock(&wl->mutex); | ||
5178 | |||
5179 | return ret; | ||
5180 | } | ||
5181 | |||
5095 | static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) | 5182 | static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) |
5096 | { | 5183 | { |
5097 | struct wl1271 *wl = hw->priv; | 5184 | struct wl1271 *wl = hw->priv; |
@@ -5291,6 +5378,7 @@ static const struct ieee80211_ops wl1271_ops = { | |||
5291 | .assign_vif_chanctx = wlcore_op_assign_vif_chanctx, | 5378 | .assign_vif_chanctx = wlcore_op_assign_vif_chanctx, |
5292 | .unassign_vif_chanctx = wlcore_op_unassign_vif_chanctx, | 5379 | .unassign_vif_chanctx = wlcore_op_unassign_vif_chanctx, |
5293 | .sta_rc_update = wlcore_op_sta_rc_update, | 5380 | .sta_rc_update = wlcore_op_sta_rc_update, |
5381 | .get_rssi = wlcore_op_get_rssi, | ||
5294 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) | 5382 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) |
5295 | }; | 5383 | }; |
5296 | 5384 | ||
@@ -5930,35 +6018,6 @@ int wlcore_free_hw(struct wl1271 *wl) | |||
5930 | } | 6018 | } |
5931 | EXPORT_SYMBOL_GPL(wlcore_free_hw); | 6019 | EXPORT_SYMBOL_GPL(wlcore_free_hw); |
5932 | 6020 | ||
5933 | static irqreturn_t wl12xx_hardirq(int irq, void *cookie) | ||
5934 | { | ||
5935 | struct wl1271 *wl = cookie; | ||
5936 | unsigned long flags; | ||
5937 | |||
5938 | wl1271_debug(DEBUG_IRQ, "IRQ"); | ||
5939 | |||
5940 | /* complete the ELP completion */ | ||
5941 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
5942 | set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); | ||
5943 | if (wl->elp_compl) { | ||
5944 | complete(wl->elp_compl); | ||
5945 | wl->elp_compl = NULL; | ||
5946 | } | ||
5947 | |||
5948 | if (test_bit(WL1271_FLAG_SUSPENDED, &wl->flags)) { | ||
5949 | /* don't enqueue a work right now. mark it as pending */ | ||
5950 | set_bit(WL1271_FLAG_PENDING_WORK, &wl->flags); | ||
5951 | wl1271_debug(DEBUG_IRQ, "should not enqueue work"); | ||
5952 | disable_irq_nosync(wl->irq); | ||
5953 | pm_wakeup_event(wl->dev, 0); | ||
5954 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
5955 | return IRQ_HANDLED; | ||
5956 | } | ||
5957 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
5958 | |||
5959 | return IRQ_WAKE_THREAD; | ||
5960 | } | ||
5961 | |||
5962 | static void wlcore_nvs_cb(const struct firmware *fw, void *context) | 6021 | static void wlcore_nvs_cb(const struct firmware *fw, void *context) |
5963 | { | 6022 | { |
5964 | struct wl1271 *wl = context; | 6023 | struct wl1271 *wl = context; |
@@ -6000,9 +6059,8 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context) | |||
6000 | else | 6059 | else |
6001 | irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; | 6060 | irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; |
6002 | 6061 | ||
6003 | ret = request_threaded_irq(wl->irq, wl12xx_hardirq, wlcore_irq, | 6062 | ret = request_threaded_irq(wl->irq, NULL, wlcore_irq, |
6004 | irqflags, | 6063 | irqflags, pdev->name, wl); |
6005 | pdev->name, wl); | ||
6006 | if (ret < 0) { | 6064 | if (ret < 0) { |
6007 | wl1271_error("request_irq() failed: %d", ret); | 6065 | wl1271_error("request_irq() failed: %d", ret); |
6008 | goto out_free_nvs; | 6066 | goto out_free_nvs; |
diff --git a/drivers/net/wireless/ti/wlcore/ps.c b/drivers/net/wireless/ti/wlcore/ps.c index 9b7b6e2e4fbc..9654577efd01 100644 --- a/drivers/net/wireless/ti/wlcore/ps.c +++ b/drivers/net/wireless/ti/wlcore/ps.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #define WL1271_WAKEUP_TIMEOUT 500 | 29 | #define WL1271_WAKEUP_TIMEOUT 500 |
30 | 30 | ||
31 | #define ELP_ENTRY_DELAY 30 | 31 | #define ELP_ENTRY_DELAY 30 |
32 | #define ELP_ENTRY_DELAY_FORCE_PS 5 | ||
32 | 33 | ||
33 | void wl1271_elp_work(struct work_struct *work) | 34 | void wl1271_elp_work(struct work_struct *work) |
34 | { | 35 | { |
@@ -98,7 +99,8 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl) | |||
98 | return; | 99 | return; |
99 | } | 100 | } |
100 | 101 | ||
101 | timeout = ELP_ENTRY_DELAY; | 102 | timeout = wl->conf.conn.forced_ps ? |
103 | ELP_ENTRY_DELAY_FORCE_PS : ELP_ENTRY_DELAY; | ||
102 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, | 104 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, |
103 | msecs_to_jiffies(timeout)); | 105 | msecs_to_jiffies(timeout)); |
104 | } | 106 | } |
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index ece392c54d9c..004d02e71f01 100644 --- a/drivers/net/wireless/ti/wlcore/tx.c +++ b/drivers/net/wireless/ti/wlcore/tx.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/etherdevice.h> | 26 | #include <linux/etherdevice.h> |
27 | #include <linux/spinlock.h> | ||
27 | 28 | ||
28 | #include "wlcore.h" | 29 | #include "wlcore.h" |
29 | #include "debug.h" | 30 | #include "debug.h" |
@@ -104,7 +105,7 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl, | |||
104 | struct wl12xx_vif *wlvif, | 105 | struct wl12xx_vif *wlvif, |
105 | u8 hlid) | 106 | u8 hlid) |
106 | { | 107 | { |
107 | bool fw_ps, single_link; | 108 | bool fw_ps; |
108 | u8 tx_pkts; | 109 | u8 tx_pkts; |
109 | 110 | ||
110 | if (WARN_ON(!test_bit(hlid, wlvif->links_map))) | 111 | if (WARN_ON(!test_bit(hlid, wlvif->links_map))) |
@@ -112,15 +113,19 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl, | |||
112 | 113 | ||
113 | fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); | 114 | fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); |
114 | tx_pkts = wl->links[hlid].allocated_pkts; | 115 | tx_pkts = wl->links[hlid].allocated_pkts; |
115 | single_link = (wl->active_link_count == 1); | ||
116 | 116 | ||
117 | /* | 117 | /* |
118 | * if in FW PS and there is enough data in FW we can put the link | 118 | * if in FW PS and there is enough data in FW we can put the link |
119 | * into high-level PS and clean out its TX queues. | 119 | * into high-level PS and clean out its TX queues. |
120 | * Make an exception if this is the only connected link. In this | 120 | * Make an exception if this is the only connected link. In this |
121 | * case FW-memory congestion is less of a problem. | 121 | * case FW-memory congestion is less of a problem. |
122 | * Note that a single connected STA means 3 active links, since we must | ||
123 | * account for the global and broadcast AP links. The "fw_ps" check | ||
124 | * assures us the third link is a STA connected to the AP. Otherwise | ||
125 | * the FW would not set the PSM bit. | ||
122 | */ | 126 | */ |
123 | if (!single_link && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS) | 127 | if (wl->active_link_count > 3 && fw_ps && |
128 | tx_pkts >= WL1271_PS_STA_MAX_PACKETS) | ||
124 | wl12xx_ps_link_start(wl, wlvif, hlid, true); | 129 | wl12xx_ps_link_start(wl, wlvif, hlid, true); |
125 | } | 130 | } |
126 | 131 | ||
@@ -639,6 +644,7 @@ next: | |||
639 | 644 | ||
640 | } | 645 | } |
641 | 646 | ||
647 | out: | ||
642 | if (!skb && | 648 | if (!skb && |
643 | test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) { | 649 | test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) { |
644 | int q; | 650 | int q; |
@@ -652,7 +658,6 @@ next: | |||
652 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 658 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
653 | } | 659 | } |
654 | 660 | ||
655 | out: | ||
656 | return skb; | 661 | return skb; |
657 | } | 662 | } |
658 | 663 | ||
@@ -928,25 +933,6 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
928 | 933 | ||
929 | wl->stats.retry_count += result->ack_failures; | 934 | wl->stats.retry_count += result->ack_failures; |
930 | 935 | ||
931 | /* | ||
932 | * update sequence number only when relevant, i.e. only in | ||
933 | * sessions of TKIP, AES and GEM (not in open or WEP sessions) | ||
934 | */ | ||
935 | if (info->control.hw_key && | ||
936 | (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP || | ||
937 | info->control.hw_key->cipher == WLAN_CIPHER_SUITE_CCMP || | ||
938 | info->control.hw_key->cipher == WL1271_CIPHER_SUITE_GEM)) { | ||
939 | u8 fw_lsb = result->tx_security_sequence_number_lsb; | ||
940 | u8 cur_lsb = wlvif->tx_security_last_seq_lsb; | ||
941 | |||
942 | /* | ||
943 | * update security sequence number, taking care of potential | ||
944 | * wrap-around | ||
945 | */ | ||
946 | wlvif->tx_security_seq += (fw_lsb - cur_lsb) & 0xff; | ||
947 | wlvif->tx_security_last_seq_lsb = fw_lsb; | ||
948 | } | ||
949 | |||
950 | /* remove private header from packet */ | 936 | /* remove private header from packet */ |
951 | skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); | 937 | skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); |
952 | 938 | ||
@@ -1061,7 +1047,8 @@ void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
1061 | 1047 | ||
1062 | /* TX failure */ | 1048 | /* TX failure */ |
1063 | for_each_set_bit(i, wlvif->links_map, WL12XX_MAX_LINKS) { | 1049 | for_each_set_bit(i, wlvif->links_map, WL12XX_MAX_LINKS) { |
1064 | if (wlvif->bss_type == BSS_TYPE_AP_BSS) { | 1050 | if (wlvif->bss_type == BSS_TYPE_AP_BSS && |
1051 | i != wlvif->ap.bcast_hlid && i != wlvif->ap.global_hlid) { | ||
1065 | /* this calls wl12xx_free_link */ | 1052 | /* this calls wl12xx_free_link */ |
1066 | wl1271_free_sta(wl, wlvif, i); | 1053 | wl1271_free_sta(wl, wlvif, i); |
1067 | } else { | 1054 | } else { |
@@ -1304,7 +1291,7 @@ bool wlcore_is_queue_stopped_by_reason_locked(struct wl1271 *wl, | |||
1304 | { | 1291 | { |
1305 | int hwq = wlcore_tx_get_mac80211_queue(wlvif, queue); | 1292 | int hwq = wlcore_tx_get_mac80211_queue(wlvif, queue); |
1306 | 1293 | ||
1307 | WARN_ON_ONCE(!spin_is_locked(&wl->wl_lock)); | 1294 | assert_spin_locked(&wl->wl_lock); |
1308 | return test_bit(reason, &wl->queue_stop_reasons[hwq]); | 1295 | return test_bit(reason, &wl->queue_stop_reasons[hwq]); |
1309 | } | 1296 | } |
1310 | 1297 | ||
@@ -1313,6 +1300,6 @@ bool wlcore_is_queue_stopped_locked(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
1313 | { | 1300 | { |
1314 | int hwq = wlcore_tx_get_mac80211_queue(wlvif, queue); | 1301 | int hwq = wlcore_tx_get_mac80211_queue(wlvif, queue); |
1315 | 1302 | ||
1316 | WARN_ON_ONCE(!spin_is_locked(&wl->wl_lock)); | 1303 | assert_spin_locked(&wl->wl_lock); |
1317 | return !!wl->queue_stop_reasons[hwq]; | 1304 | return !!wl->queue_stop_reasons[hwq]; |
1318 | } | 1305 | } |
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index af9fecaefc30..0034979e97cb 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h | |||
@@ -390,6 +390,9 @@ struct wl1271 { | |||
390 | /* number of currently active RX BA sessions */ | 390 | /* number of currently active RX BA sessions */ |
391 | int ba_rx_session_count; | 391 | int ba_rx_session_count; |
392 | 392 | ||
393 | /* Maximum number of supported RX BA sessions */ | ||
394 | int ba_rx_session_count_max; | ||
395 | |||
393 | /* AP-mode - number of currently connected stations */ | 396 | /* AP-mode - number of currently connected stations */ |
394 | int active_sta_count; | 397 | int active_sta_count; |
395 | 398 | ||
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h index 508f5b0f8a70..e5e146435fe7 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h | |||
@@ -274,6 +274,13 @@ struct wl1271_link { | |||
274 | 274 | ||
275 | /* The wlvif this link belongs to. Might be null for global links */ | 275 | /* The wlvif this link belongs to. Might be null for global links */ |
276 | struct wl12xx_vif *wlvif; | 276 | struct wl12xx_vif *wlvif; |
277 | |||
278 | /* | ||
279 | * total freed FW packets on the link - used for tracking the | ||
280 | * AES/TKIP PN across recoveries. Re-initialized each time | ||
281 | * from the wl1271_station structure. | ||
282 | */ | ||
283 | u64 total_freed_pkts; | ||
277 | }; | 284 | }; |
278 | 285 | ||
279 | #define WL1271_MAX_RX_FILTERS 5 | 286 | #define WL1271_MAX_RX_FILTERS 5 |
@@ -318,6 +325,13 @@ struct wl12xx_rx_filter { | |||
318 | struct wl1271_station { | 325 | struct wl1271_station { |
319 | u8 hlid; | 326 | u8 hlid; |
320 | bool in_connection; | 327 | bool in_connection; |
328 | |||
329 | /* | ||
330 | * total freed FW packets on the link to the STA - used for tracking the | ||
331 | * AES/TKIP PN across recoveries. Re-initialized each time from the | ||
332 | * wl1271_station structure. | ||
333 | */ | ||
334 | u64 total_freed_pkts; | ||
321 | }; | 335 | }; |
322 | 336 | ||
323 | struct wl12xx_vif { | 337 | struct wl12xx_vif { |
@@ -449,16 +463,15 @@ struct wl12xx_vif { | |||
449 | */ | 463 | */ |
450 | struct { | 464 | struct { |
451 | u8 persistent[0]; | 465 | u8 persistent[0]; |
466 | |||
452 | /* | 467 | /* |
453 | * Security sequence number | 468 | * total freed FW packets on the link - used for |
454 | * bits 0-15: lower 16 bits part of sequence number | 469 | * storing the AES/TKIP PN during recovery, as this |
455 | * bits 16-47: higher 32 bits part of sequence number | 470 | * structure is not zeroed out. |
456 | * bits 48-63: not in use | 471 | * For STA this holds the PN of the link to the AP. |
472 | * For AP this holds the PN of the broadcast link. | ||
457 | */ | 473 | */ |
458 | u64 tx_security_seq; | 474 | u64 total_freed_pkts; |
459 | |||
460 | /* 8 bits of the last sequence number in use */ | ||
461 | u8 tx_security_last_seq_lsb; | ||
462 | }; | 475 | }; |
463 | }; | 476 | }; |
464 | 477 | ||
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c index 63ff69f9d3eb..a8dc95ebf2d6 100644 --- a/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c | |||
@@ -347,6 +347,21 @@ static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in, | |||
347 | return (s8)gain; | 347 | return (s8)gain; |
348 | } | 348 | } |
349 | 349 | ||
350 | static void sprom_extract_r23(struct ssb_sprom *out, const u16 *in) | ||
351 | { | ||
352 | SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0); | ||
353 | SPEX(opo, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0); | ||
354 | SPEX(pa1lob0, SSB_SPROM2_PA1LOB0, 0xFFFF, 0); | ||
355 | SPEX(pa1lob1, SSB_SPROM2_PA1LOB1, 0xFFFF, 0); | ||
356 | SPEX(pa1lob2, SSB_SPROM2_PA1LOB2, 0xFFFF, 0); | ||
357 | SPEX(pa1hib0, SSB_SPROM2_PA1HIB0, 0xFFFF, 0); | ||
358 | SPEX(pa1hib1, SSB_SPROM2_PA1HIB1, 0xFFFF, 0); | ||
359 | SPEX(pa1hib2, SSB_SPROM2_PA1HIB2, 0xFFFF, 0); | ||
360 | SPEX(maxpwr_ah, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_HI, 0); | ||
361 | SPEX(maxpwr_al, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_LO, | ||
362 | SSB_SPROM2_MAXP_A_LO_SHIFT); | ||
363 | } | ||
364 | |||
350 | static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) | 365 | static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) |
351 | { | 366 | { |
352 | u16 loc[3]; | 367 | u16 loc[3]; |
@@ -369,6 +384,7 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) | |||
369 | SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14); | 384 | SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14); |
370 | SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15); | 385 | SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15); |
371 | SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0); | 386 | SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0); |
387 | SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0); | ||
372 | if (out->revision == 1) | 388 | if (out->revision == 1) |
373 | SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE, | 389 | SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE, |
374 | SSB_SPROM1_BINF_CCODE_SHIFT); | 390 | SSB_SPROM1_BINF_CCODE_SHIFT); |
@@ -395,8 +411,7 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) | |||
395 | SSB_SPROM1_ITSSI_A_SHIFT); | 411 | SSB_SPROM1_ITSSI_A_SHIFT); |
396 | SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0); | 412 | SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0); |
397 | SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0); | 413 | SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0); |
398 | if (out->revision >= 2) | 414 | |
399 | SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0); | ||
400 | SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8); | 415 | SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8); |
401 | SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0); | 416 | SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0); |
402 | 417 | ||
@@ -407,6 +422,8 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) | |||
407 | out->antenna_gain.a1 = r123_extract_antgain(out->revision, in, | 422 | out->antenna_gain.a1 = r123_extract_antgain(out->revision, in, |
408 | SSB_SPROM1_AGAIN_A, | 423 | SSB_SPROM1_AGAIN_A, |
409 | SSB_SPROM1_AGAIN_A_SHIFT); | 424 | SSB_SPROM1_AGAIN_A_SHIFT); |
425 | if (out->revision >= 2) | ||
426 | sprom_extract_r23(out, in); | ||
410 | } | 427 | } |
411 | 428 | ||
412 | /* Revs 4 5 and 8 have partially shared layout */ | 429 | /* Revs 4 5 and 8 have partially shared layout */ |
@@ -464,6 +481,7 @@ static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) | |||
464 | SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A, | 481 | SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A, |
465 | SSB_SPROM4_ETHPHY_ET1A_SHIFT); | 482 | SSB_SPROM4_ETHPHY_ET1A_SHIFT); |
466 | SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0); | 483 | SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0); |
484 | SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0); | ||
467 | if (out->revision == 4) { | 485 | if (out->revision == 4) { |
468 | SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8); | 486 | SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8); |
469 | SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0); | 487 | SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0); |
@@ -535,6 +553,7 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) | |||
535 | sprom_get_mac(out->il0mac, &in[SPOFF(SSB_SPROM8_IL0MAC)]); | 553 | sprom_get_mac(out->il0mac, &in[SPOFF(SSB_SPROM8_IL0MAC)]); |
536 | 554 | ||
537 | SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0); | 555 | SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0); |
556 | SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0); | ||
538 | SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8); | 557 | SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8); |
539 | SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0); | 558 | SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0); |
540 | SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0); | 559 | SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0); |
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index e0ce311011c0..0ab6712fd76b 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h | |||
@@ -173,6 +173,60 @@ struct bcma_host_ops { | |||
173 | #define BCMA_CHIP_ID_BCM53572 53572 | 173 | #define BCMA_CHIP_ID_BCM53572 53572 |
174 | #define BCMA_PKG_ID_BCM47188 9 | 174 | #define BCMA_PKG_ID_BCM47188 9 |
175 | 175 | ||
176 | /* Board types (on PCI usually equals to the subsystem dev id) */ | ||
177 | /* BCM4313 */ | ||
178 | #define BCMA_BOARD_TYPE_BCM94313BU 0X050F | ||
179 | #define BCMA_BOARD_TYPE_BCM94313HM 0X0510 | ||
180 | #define BCMA_BOARD_TYPE_BCM94313EPA 0X0511 | ||
181 | #define BCMA_BOARD_TYPE_BCM94313HMG 0X051C | ||
182 | /* BCM4716 */ | ||
183 | #define BCMA_BOARD_TYPE_BCM94716NR2 0X04CD | ||
184 | /* BCM43224 */ | ||
185 | #define BCMA_BOARD_TYPE_BCM943224X21 0X056E | ||
186 | #define BCMA_BOARD_TYPE_BCM943224X21_FCC 0X00D1 | ||
187 | #define BCMA_BOARD_TYPE_BCM943224X21B 0X00E9 | ||
188 | #define BCMA_BOARD_TYPE_BCM943224M93 0X008B | ||
189 | #define BCMA_BOARD_TYPE_BCM943224M93A 0X0090 | ||
190 | #define BCMA_BOARD_TYPE_BCM943224X16 0X0093 | ||
191 | #define BCMA_BOARD_TYPE_BCM94322X9 0X008D | ||
192 | #define BCMA_BOARD_TYPE_BCM94322M35E 0X008E | ||
193 | /* BCM43228 */ | ||
194 | #define BCMA_BOARD_TYPE_BCM943228BU8 0X0540 | ||
195 | #define BCMA_BOARD_TYPE_BCM943228BU9 0X0541 | ||
196 | #define BCMA_BOARD_TYPE_BCM943228BU 0X0542 | ||
197 | #define BCMA_BOARD_TYPE_BCM943227HM4L 0X0543 | ||
198 | #define BCMA_BOARD_TYPE_BCM943227HMB 0X0544 | ||
199 | #define BCMA_BOARD_TYPE_BCM943228HM4L 0X0545 | ||
200 | #define BCMA_BOARD_TYPE_BCM943228SD 0X0573 | ||
201 | /* BCM4331 */ | ||
202 | #define BCMA_BOARD_TYPE_BCM94331X19 0X00D6 | ||
203 | #define BCMA_BOARD_TYPE_BCM94331X28 0X00E4 | ||
204 | #define BCMA_BOARD_TYPE_BCM94331X28B 0X010E | ||
205 | #define BCMA_BOARD_TYPE_BCM94331PCIEBT3AX 0X00E4 | ||
206 | #define BCMA_BOARD_TYPE_BCM94331X12_2G 0X00EC | ||
207 | #define BCMA_BOARD_TYPE_BCM94331X12_5G 0X00ED | ||
208 | #define BCMA_BOARD_TYPE_BCM94331X29B 0X00EF | ||
209 | #define BCMA_BOARD_TYPE_BCM94331CSAX 0X00EF | ||
210 | #define BCMA_BOARD_TYPE_BCM94331X19C 0X00F5 | ||
211 | #define BCMA_BOARD_TYPE_BCM94331X33 0X00F4 | ||
212 | #define BCMA_BOARD_TYPE_BCM94331BU 0X0523 | ||
213 | #define BCMA_BOARD_TYPE_BCM94331S9BU 0X0524 | ||
214 | #define BCMA_BOARD_TYPE_BCM94331MC 0X0525 | ||
215 | #define BCMA_BOARD_TYPE_BCM94331MCI 0X0526 | ||
216 | #define BCMA_BOARD_TYPE_BCM94331PCIEBT4 0X0527 | ||
217 | #define BCMA_BOARD_TYPE_BCM94331HM 0X0574 | ||
218 | #define BCMA_BOARD_TYPE_BCM94331PCIEDUAL 0X059B | ||
219 | #define BCMA_BOARD_TYPE_BCM94331MCH5 0X05A9 | ||
220 | #define BCMA_BOARD_TYPE_BCM94331CS 0X05C6 | ||
221 | #define BCMA_BOARD_TYPE_BCM94331CD 0X05DA | ||
222 | /* BCM53572 */ | ||
223 | #define BCMA_BOARD_TYPE_BCM953572BU 0X058D | ||
224 | #define BCMA_BOARD_TYPE_BCM953572NR2 0X058E | ||
225 | #define BCMA_BOARD_TYPE_BCM947188NR2 0X058F | ||
226 | #define BCMA_BOARD_TYPE_BCM953572SDRNR2 0X0590 | ||
227 | /* BCM43142 */ | ||
228 | #define BCMA_BOARD_TYPE_BCM943142HM 0X05E0 | ||
229 | |||
176 | struct bcma_device { | 230 | struct bcma_device { |
177 | struct bcma_bus *bus; | 231 | struct bcma_bus *bus; |
178 | struct bcma_device_id id; | 232 | struct bcma_device_id id; |
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index 8390c474f69a..453fcc914683 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h | |||
@@ -104,6 +104,7 @@ | |||
104 | #define BCMA_CC_CHIPST_4706_MIPS_BENDIAN BIT(3) /* 0: little, 1: big endian */ | 104 | #define BCMA_CC_CHIPST_4706_MIPS_BENDIAN BIT(3) /* 0: little, 1: big endian */ |
105 | #define BCMA_CC_CHIPST_4706_PCIE1_DISABLE BIT(5) /* PCIE1 enable strap pin */ | 105 | #define BCMA_CC_CHIPST_4706_PCIE1_DISABLE BIT(5) /* PCIE1 enable strap pin */ |
106 | #define BCMA_CC_CHIPST_5357_NAND_BOOT BIT(4) /* NAND boot, valid for CC rev 38 and/or BCM5357 */ | 106 | #define BCMA_CC_CHIPST_5357_NAND_BOOT BIT(4) /* NAND boot, valid for CC rev 38 and/or BCM5357 */ |
107 | #define BCMA_CC_CHIPST_4360_XTAL_40MZ 0x00000001 | ||
107 | #define BCMA_CC_JCMD 0x0030 /* Rev >= 10 only */ | 108 | #define BCMA_CC_JCMD 0x0030 /* Rev >= 10 only */ |
108 | #define BCMA_CC_JCMD_START 0x80000000 | 109 | #define BCMA_CC_JCMD_START 0x80000000 |
109 | #define BCMA_CC_JCMD_BUSY 0x80000000 | 110 | #define BCMA_CC_JCMD_BUSY 0x80000000 |
@@ -607,6 +608,8 @@ void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable); | |||
607 | 608 | ||
608 | extern u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks); | 609 | extern u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks); |
609 | 610 | ||
611 | extern u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc); | ||
612 | |||
610 | void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value); | 613 | void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value); |
611 | 614 | ||
612 | u32 bcma_chipco_irq_status(struct bcma_drv_cc *cc, u32 mask); | 615 | u32 bcma_chipco_irq_status(struct bcma_drv_cc *cc, u32 mask); |
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index 8b1322296fed..c64999fd1660 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h | |||
@@ -340,13 +340,61 @@ enum ssb_bustype { | |||
340 | #define SSB_BOARDVENDOR_DELL 0x1028 /* Dell */ | 340 | #define SSB_BOARDVENDOR_DELL 0x1028 /* Dell */ |
341 | #define SSB_BOARDVENDOR_HP 0x0E11 /* HP */ | 341 | #define SSB_BOARDVENDOR_HP 0x0E11 /* HP */ |
342 | /* board_type */ | 342 | /* board_type */ |
343 | #define SSB_BOARD_BCM94301CB 0x0406 | ||
344 | #define SSB_BOARD_BCM94301MP 0x0407 | ||
345 | #define SSB_BOARD_BU4309 0x040A | ||
346 | #define SSB_BOARD_BCM94309CB 0x040B | ||
347 | #define SSB_BOARD_BCM4309MP 0x040C | ||
348 | #define SSB_BOARD_BU4306 0x0416 | ||
343 | #define SSB_BOARD_BCM94306MP 0x0418 | 349 | #define SSB_BOARD_BCM94306MP 0x0418 |
344 | #define SSB_BOARD_BCM4309G 0x0421 | 350 | #define SSB_BOARD_BCM4309G 0x0421 |
345 | #define SSB_BOARD_BCM4306CB 0x0417 | 351 | #define SSB_BOARD_BCM4306CB 0x0417 |
346 | #define SSB_BOARD_BCM4309MP 0x040C | 352 | #define SSB_BOARD_BCM94306PC 0x0425 /* pcmcia 3.3v 4306 card */ |
353 | #define SSB_BOARD_BCM94306CBSG 0x042B /* with SiGe PA */ | ||
354 | #define SSB_BOARD_PCSG94306 0x042D /* with SiGe PA */ | ||
355 | #define SSB_BOARD_BU4704SD 0x042E /* with sdram */ | ||
356 | #define SSB_BOARD_BCM94704AGR 0x042F /* dual 11a/11g Router */ | ||
357 | #define SSB_BOARD_BCM94308MP 0x0430 /* 11a-only minipci */ | ||
358 | #define SSB_BOARD_BU4318 0x0447 | ||
359 | #define SSB_BOARD_CB4318 0x0448 | ||
360 | #define SSB_BOARD_MPG4318 0x0449 | ||
347 | #define SSB_BOARD_MP4318 0x044A | 361 | #define SSB_BOARD_MP4318 0x044A |
348 | #define SSB_BOARD_BU4306 0x0416 | 362 | #define SSB_BOARD_SD4318 0x044B |
349 | #define SSB_BOARD_BU4309 0x040A | 363 | #define SSB_BOARD_BCM94306P 0x044C /* with SiGe */ |
364 | #define SSB_BOARD_BCM94303MP 0x044E | ||
365 | #define SSB_BOARD_BCM94306MPM 0x0450 | ||
366 | #define SSB_BOARD_BCM94306MPL 0x0453 | ||
367 | #define SSB_BOARD_PC4303 0x0454 /* pcmcia */ | ||
368 | #define SSB_BOARD_BCM94306MPLNA 0x0457 | ||
369 | #define SSB_BOARD_BCM94306MPH 0x045B | ||
370 | #define SSB_BOARD_BCM94306PCIV 0x045C | ||
371 | #define SSB_BOARD_BCM94318MPGH 0x0463 | ||
372 | #define SSB_BOARD_BU4311 0x0464 | ||
373 | #define SSB_BOARD_BCM94311MC 0x0465 | ||
374 | #define SSB_BOARD_BCM94311MCAG 0x0466 | ||
375 | /* 4321 boards */ | ||
376 | #define SSB_BOARD_BU4321 0x046B | ||
377 | #define SSB_BOARD_BU4321E 0x047C | ||
378 | #define SSB_BOARD_MP4321 0x046C | ||
379 | #define SSB_BOARD_CB2_4321 0x046D | ||
380 | #define SSB_BOARD_CB2_4321_AG 0x0066 | ||
381 | #define SSB_BOARD_MC4321 0x046E | ||
382 | /* 4325 boards */ | ||
383 | #define SSB_BOARD_BCM94325DEVBU 0x0490 | ||
384 | #define SSB_BOARD_BCM94325BGABU 0x0491 | ||
385 | #define SSB_BOARD_BCM94325SDGWB 0x0492 | ||
386 | #define SSB_BOARD_BCM94325SDGMDL 0x04AA | ||
387 | #define SSB_BOARD_BCM94325SDGMDL2 0x04C6 | ||
388 | #define SSB_BOARD_BCM94325SDGMDL3 0x04C9 | ||
389 | #define SSB_BOARD_BCM94325SDABGWBA 0x04E1 | ||
390 | /* 4322 boards */ | ||
391 | #define SSB_BOARD_BCM94322MC 0x04A4 | ||
392 | #define SSB_BOARD_BCM94322USB 0x04A8 /* dualband */ | ||
393 | #define SSB_BOARD_BCM94322HM 0x04B0 | ||
394 | #define SSB_BOARD_BCM94322USB2D 0x04Bf /* single band discrete front end */ | ||
395 | /* 4312 boards */ | ||
396 | #define SSB_BOARD_BU4312 0x048A | ||
397 | #define SSB_BOARD_BCM4312MCGSG 0x04B5 | ||
350 | /* chip_package */ | 398 | /* chip_package */ |
351 | #define SSB_CHIPPACK_BCM4712S 1 /* Small 200pin 4712 */ | 399 | #define SSB_CHIPPACK_BCM4712S 1 /* Small 200pin 4712 */ |
352 | #define SSB_CHIPPACK_BCM4712M 2 /* Medium 225pin 4712 */ | 400 | #define SSB_CHIPPACK_BCM4712M 2 /* Medium 225pin 4712 */ |
diff --git a/include/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h index 6ecfa02ddbac..3a7256955b10 100644 --- a/include/linux/ssb/ssb_regs.h +++ b/include/linux/ssb/ssb_regs.h | |||
@@ -289,11 +289,11 @@ | |||
289 | #define SSB_SPROM4_ETHPHY_ET1A_SHIFT 5 | 289 | #define SSB_SPROM4_ETHPHY_ET1A_SHIFT 5 |
290 | #define SSB_SPROM4_ETHPHY_ET0M (1<<14) /* MDIO for enet0 */ | 290 | #define SSB_SPROM4_ETHPHY_ET0M (1<<14) /* MDIO for enet0 */ |
291 | #define SSB_SPROM4_ETHPHY_ET1M (1<<15) /* MDIO for enet1 */ | 291 | #define SSB_SPROM4_ETHPHY_ET1M (1<<15) /* MDIO for enet1 */ |
292 | #define SSB_SPROM4_ANTAVAIL 0x005D /* Antenna available bitfields */ | 292 | #define SSB_SPROM4_ANTAVAIL 0x005C /* Antenna available bitfields */ |
293 | #define SSB_SPROM4_ANTAVAIL_A 0x00FF /* A-PHY bitfield */ | 293 | #define SSB_SPROM4_ANTAVAIL_BG 0x00FF /* B-PHY and G-PHY bitfield */ |
294 | #define SSB_SPROM4_ANTAVAIL_A_SHIFT 0 | 294 | #define SSB_SPROM4_ANTAVAIL_BG_SHIFT 0 |
295 | #define SSB_SPROM4_ANTAVAIL_BG 0xFF00 /* B-PHY and G-PHY bitfield */ | 295 | #define SSB_SPROM4_ANTAVAIL_A 0xFF00 /* A-PHY bitfield */ |
296 | #define SSB_SPROM4_ANTAVAIL_BG_SHIFT 8 | 296 | #define SSB_SPROM4_ANTAVAIL_A_SHIFT 8 |
297 | #define SSB_SPROM4_AGAIN01 0x005E /* Antenna Gain (in dBm Q5.2) */ | 297 | #define SSB_SPROM4_AGAIN01 0x005E /* Antenna Gain (in dBm Q5.2) */ |
298 | #define SSB_SPROM4_AGAIN0 0x00FF /* Antenna 0 */ | 298 | #define SSB_SPROM4_AGAIN0 0x00FF /* Antenna 0 */ |
299 | #define SSB_SPROM4_AGAIN0_SHIFT 0 | 299 | #define SSB_SPROM4_AGAIN0_SHIFT 0 |
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 9531beee09b5..ed6e9552252e 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h | |||
@@ -232,7 +232,7 @@ struct bt_sock_list { | |||
232 | }; | 232 | }; |
233 | 233 | ||
234 | int bt_sock_register(int proto, const struct net_proto_family *ops); | 234 | int bt_sock_register(int proto, const struct net_proto_family *ops); |
235 | int bt_sock_unregister(int proto); | 235 | void bt_sock_unregister(int proto); |
236 | void bt_sock_link(struct bt_sock_list *l, struct sock *s); | 236 | void bt_sock_link(struct bt_sock_list *l, struct sock *s); |
237 | void bt_sock_unlink(struct bt_sock_list *l, struct sock *s); | 237 | void bt_sock_unlink(struct bt_sock_list *l, struct sock *s); |
238 | int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, | 238 | int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, |
@@ -260,12 +260,22 @@ struct l2cap_ctrl { | |||
260 | __u8 retries; | 260 | __u8 retries; |
261 | }; | 261 | }; |
262 | 262 | ||
263 | struct hci_dev; | ||
264 | |||
265 | typedef void (*hci_req_complete_t)(struct hci_dev *hdev, u8 status); | ||
266 | |||
267 | struct hci_req_ctrl { | ||
268 | bool start; | ||
269 | hci_req_complete_t complete; | ||
270 | }; | ||
271 | |||
263 | struct bt_skb_cb { | 272 | struct bt_skb_cb { |
264 | __u8 pkt_type; | 273 | __u8 pkt_type; |
265 | __u8 incoming; | 274 | __u8 incoming; |
266 | __u16 expect; | 275 | __u16 expect; |
267 | __u8 force_active; | 276 | __u8 force_active; |
268 | struct l2cap_ctrl control; | 277 | struct l2cap_ctrl control; |
278 | struct hci_req_ctrl req; | ||
269 | }; | 279 | }; |
270 | #define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb)) | 280 | #define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb)) |
271 | 281 | ||
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 7f12c25f1fca..b3308927a0a1 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h | |||
@@ -119,10 +119,16 @@ enum { | |||
119 | HCI_CONNECTABLE, | 119 | HCI_CONNECTABLE, |
120 | HCI_DISCOVERABLE, | 120 | HCI_DISCOVERABLE, |
121 | HCI_LINK_SECURITY, | 121 | HCI_LINK_SECURITY, |
122 | HCI_PENDING_CLASS, | ||
123 | HCI_PERIODIC_INQ, | 122 | HCI_PERIODIC_INQ, |
123 | HCI_FAST_CONNECTABLE, | ||
124 | }; | 124 | }; |
125 | 125 | ||
126 | /* A mask for the flags that are supposed to remain when a reset happens | ||
127 | * or the HCI device is closed. | ||
128 | */ | ||
129 | #define HCI_PERSISTENT_MASK (BIT(HCI_LE_SCAN) | BIT(HCI_PERIODIC_INQ) | \ | ||
130 | BIT(HCI_FAST_CONNECTABLE)) | ||
131 | |||
126 | /* HCI ioctl defines */ | 132 | /* HCI ioctl defines */ |
127 | #define HCIDEVUP _IOW('H', 201, int) | 133 | #define HCIDEVUP _IOW('H', 201, int) |
128 | #define HCIDEVDOWN _IOW('H', 202, int) | 134 | #define HCIDEVDOWN _IOW('H', 202, int) |
@@ -881,12 +887,25 @@ struct hci_rp_read_data_block_size { | |||
881 | __le16 num_blocks; | 887 | __le16 num_blocks; |
882 | } __packed; | 888 | } __packed; |
883 | 889 | ||
890 | #define HCI_OP_READ_PAGE_SCAN_ACTIVITY 0x0c1b | ||
891 | struct hci_rp_read_page_scan_activity { | ||
892 | __u8 status; | ||
893 | __le16 interval; | ||
894 | __le16 window; | ||
895 | } __packed; | ||
896 | |||
884 | #define HCI_OP_WRITE_PAGE_SCAN_ACTIVITY 0x0c1c | 897 | #define HCI_OP_WRITE_PAGE_SCAN_ACTIVITY 0x0c1c |
885 | struct hci_cp_write_page_scan_activity { | 898 | struct hci_cp_write_page_scan_activity { |
886 | __le16 interval; | 899 | __le16 interval; |
887 | __le16 window; | 900 | __le16 window; |
888 | } __packed; | 901 | } __packed; |
889 | 902 | ||
903 | #define HCI_OP_READ_PAGE_SCAN_TYPE 0x0c46 | ||
904 | struct hci_rp_read_page_scan_type { | ||
905 | __u8 status; | ||
906 | __u8 type; | ||
907 | } __packed; | ||
908 | |||
890 | #define HCI_OP_WRITE_PAGE_SCAN_TYPE 0x0c47 | 909 | #define HCI_OP_WRITE_PAGE_SCAN_TYPE 0x0c47 |
891 | #define PAGE_SCAN_TYPE_STANDARD 0x00 | 910 | #define PAGE_SCAN_TYPE_STANDARD 0x00 |
892 | #define PAGE_SCAN_TYPE_INTERLACED 0x01 | 911 | #define PAGE_SCAN_TYPE_INTERLACED 0x01 |
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 90cf75afcb02..358a6983d3bb 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -165,6 +165,10 @@ struct hci_dev { | |||
165 | __u16 voice_setting; | 165 | __u16 voice_setting; |
166 | __u8 io_capability; | 166 | __u8 io_capability; |
167 | __s8 inq_tx_power; | 167 | __s8 inq_tx_power; |
168 | __u16 page_scan_interval; | ||
169 | __u16 page_scan_window; | ||
170 | __u8 page_scan_type; | ||
171 | |||
168 | __u16 devid_source; | 172 | __u16 devid_source; |
169 | __u16 devid_vendor; | 173 | __u16 devid_vendor; |
170 | __u16 devid_product; | 174 | __u16 devid_product; |
@@ -248,8 +252,6 @@ struct hci_dev { | |||
248 | __u32 req_status; | 252 | __u32 req_status; |
249 | __u32 req_result; | 253 | __u32 req_result; |
250 | 254 | ||
251 | __u16 init_last_cmd; | ||
252 | |||
253 | struct list_head mgmt_pending; | 255 | struct list_head mgmt_pending; |
254 | 256 | ||
255 | struct discovery_state discovery; | 257 | struct discovery_state discovery; |
@@ -574,7 +576,7 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev, | |||
574 | return NULL; | 576 | return NULL; |
575 | } | 577 | } |
576 | 578 | ||
577 | void hci_acl_disconn(struct hci_conn *conn, __u8 reason); | 579 | void hci_disconnect(struct hci_conn *conn, __u8 reason); |
578 | void hci_setup_sync(struct hci_conn *conn, __u16 handle); | 580 | void hci_setup_sync(struct hci_conn *conn, __u16 handle); |
579 | void hci_sco_setup(struct hci_conn *conn, __u8 status); | 581 | void hci_sco_setup(struct hci_conn *conn, __u8 status); |
580 | 582 | ||
@@ -742,8 +744,6 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash, | |||
742 | u8 *randomizer); | 744 | u8 *randomizer); |
743 | int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr); | 745 | int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr); |
744 | 746 | ||
745 | int hci_update_ad(struct hci_dev *hdev); | ||
746 | |||
747 | void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); | 747 | void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); |
748 | 748 | ||
749 | int hci_recv_frame(struct sk_buff *skb); | 749 | int hci_recv_frame(struct sk_buff *skb); |
@@ -1041,6 +1041,22 @@ static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data, | |||
1041 | int hci_register_cb(struct hci_cb *hcb); | 1041 | int hci_register_cb(struct hci_cb *hcb); |
1042 | int hci_unregister_cb(struct hci_cb *hcb); | 1042 | int hci_unregister_cb(struct hci_cb *hcb); |
1043 | 1043 | ||
1044 | struct hci_request { | ||
1045 | struct hci_dev *hdev; | ||
1046 | struct sk_buff_head cmd_q; | ||
1047 | |||
1048 | /* If something goes wrong when building the HCI request, the error | ||
1049 | * value is stored in this field. | ||
1050 | */ | ||
1051 | int err; | ||
1052 | }; | ||
1053 | |||
1054 | void hci_req_init(struct hci_request *req, struct hci_dev *hdev); | ||
1055 | int hci_req_run(struct hci_request *req, hci_req_complete_t complete); | ||
1056 | void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param); | ||
1057 | void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status); | ||
1058 | void hci_req_cmd_status(struct hci_dev *hdev, u16 opcode, u8 status); | ||
1059 | |||
1044 | int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param); | 1060 | int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param); |
1045 | void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags); | 1061 | void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags); |
1046 | void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb); | 1062 | void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb); |
@@ -1153,7 +1169,7 @@ struct hci_sec_filter { | |||
1153 | #define hci_req_lock(d) mutex_lock(&d->req_lock) | 1169 | #define hci_req_lock(d) mutex_lock(&d->req_lock) |
1154 | #define hci_req_unlock(d) mutex_unlock(&d->req_lock) | 1170 | #define hci_req_unlock(d) mutex_unlock(&d->req_lock) |
1155 | 1171 | ||
1156 | void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result); | 1172 | void hci_update_ad(struct hci_request *req); |
1157 | 1173 | ||
1158 | void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, | 1174 | void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, |
1159 | u16 latency, u16 to_multiplier); | 1175 | u16 latency, u16 to_multiplier); |
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h index e2e3ecad1008..7afd4199d6b6 100644 --- a/include/net/bluetooth/rfcomm.h +++ b/include/net/bluetooth/rfcomm.h | |||
@@ -158,7 +158,6 @@ struct rfcomm_session { | |||
158 | struct timer_list timer; | 158 | struct timer_list timer; |
159 | unsigned long state; | 159 | unsigned long state; |
160 | unsigned long flags; | 160 | unsigned long flags; |
161 | atomic_t refcnt; | ||
162 | int initiator; | 161 | int initiator; |
163 | 162 | ||
164 | /* Default DLC parameters */ | 163 | /* Default DLC parameters */ |
@@ -276,11 +275,6 @@ static inline void rfcomm_dlc_unthrottle(struct rfcomm_dlc *d) | |||
276 | void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src, | 275 | void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src, |
277 | bdaddr_t *dst); | 276 | bdaddr_t *dst); |
278 | 277 | ||
279 | static inline void rfcomm_session_hold(struct rfcomm_session *s) | ||
280 | { | ||
281 | atomic_inc(&s->refcnt); | ||
282 | } | ||
283 | |||
284 | /* ---- RFCOMM sockets ---- */ | 278 | /* ---- RFCOMM sockets ---- */ |
285 | struct sockaddr_rc { | 279 | struct sockaddr_rc { |
286 | sa_family_t rc_family; | 280 | sa_family_t rc_family; |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index cdd7cea1fd4c..dd73b8c6746b 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -93,9 +93,11 @@ struct device; | |||
93 | * enum ieee80211_max_queues - maximum number of queues | 93 | * enum ieee80211_max_queues - maximum number of queues |
94 | * | 94 | * |
95 | * @IEEE80211_MAX_QUEUES: Maximum number of regular device queues. | 95 | * @IEEE80211_MAX_QUEUES: Maximum number of regular device queues. |
96 | * @IEEE80211_MAX_QUEUE_MAP: bitmap with maximum queues set | ||
96 | */ | 97 | */ |
97 | enum ieee80211_max_queues { | 98 | enum ieee80211_max_queues { |
98 | IEEE80211_MAX_QUEUES = 16, | 99 | IEEE80211_MAX_QUEUES = 16, |
100 | IEEE80211_MAX_QUEUE_MAP = BIT(IEEE80211_MAX_QUEUES) - 1, | ||
99 | }; | 101 | }; |
100 | 102 | ||
101 | #define IEEE80211_INVAL_HW_QUEUE 0xff | 103 | #define IEEE80211_INVAL_HW_QUEUE 0xff |
@@ -1067,6 +1069,9 @@ enum ieee80211_vif_flags { | |||
1067 | * path needing to access it; even though the netdev carrier will always | 1069 | * path needing to access it; even though the netdev carrier will always |
1068 | * be off when it is %NULL there can still be races and packets could be | 1070 | * be off when it is %NULL there can still be races and packets could be |
1069 | * processed after it switches back to %NULL. | 1071 | * processed after it switches back to %NULL. |
1072 | * @debugfs_dir: debugfs dentry, can be used by drivers to create own per | ||
1073 | * interface debug files. Note that it will be NULL for the virtual | ||
1074 | * monitor interface (if that is requested.) | ||
1070 | * @drv_priv: data area for driver use, will always be aligned to | 1075 | * @drv_priv: data area for driver use, will always be aligned to |
1071 | * sizeof(void *). | 1076 | * sizeof(void *). |
1072 | */ | 1077 | */ |
@@ -1083,6 +1088,10 @@ struct ieee80211_vif { | |||
1083 | 1088 | ||
1084 | u32 driver_flags; | 1089 | u32 driver_flags; |
1085 | 1090 | ||
1091 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
1092 | struct dentry *debugfs_dir; | ||
1093 | #endif | ||
1094 | |||
1086 | /* must be last */ | 1095 | /* must be last */ |
1087 | u8 drv_priv[0] __aligned(sizeof(void *)); | 1096 | u8 drv_priv[0] __aligned(sizeof(void *)); |
1088 | }; | 1097 | }; |
@@ -1946,14 +1955,14 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb); | |||
1946 | * filter those response frames except in the case of frames that | 1955 | * filter those response frames except in the case of frames that |
1947 | * are buffered in the driver -- those must remain buffered to avoid | 1956 | * are buffered in the driver -- those must remain buffered to avoid |
1948 | * reordering. Because it is possible that no frames are released | 1957 | * reordering. Because it is possible that no frames are released |
1949 | * in this case, the driver must call ieee80211_sta_eosp_irqsafe() | 1958 | * in this case, the driver must call ieee80211_sta_eosp() |
1950 | * to indicate to mac80211 that the service period ended anyway. | 1959 | * to indicate to mac80211 that the service period ended anyway. |
1951 | * | 1960 | * |
1952 | * Finally, if frames from multiple TIDs are released from mac80211 | 1961 | * Finally, if frames from multiple TIDs are released from mac80211 |
1953 | * but the driver might reorder them, it must clear & set the flags | 1962 | * but the driver might reorder them, it must clear & set the flags |
1954 | * appropriately (only the last frame may have %IEEE80211_TX_STATUS_EOSP) | 1963 | * appropriately (only the last frame may have %IEEE80211_TX_STATUS_EOSP) |
1955 | * and also take care of the EOSP and MORE_DATA bits in the frame. | 1964 | * and also take care of the EOSP and MORE_DATA bits in the frame. |
1956 | * The driver may also use ieee80211_sta_eosp_irqsafe() in this case. | 1965 | * The driver may also use ieee80211_sta_eosp() in this case. |
1957 | */ | 1966 | */ |
1958 | 1967 | ||
1959 | /** | 1968 | /** |
@@ -2226,18 +2235,6 @@ enum ieee80211_roc_type { | |||
2226 | * MAC address of the device going away. | 2235 | * MAC address of the device going away. |
2227 | * Hence, this callback must be implemented. It can sleep. | 2236 | * Hence, this callback must be implemented. It can sleep. |
2228 | * | 2237 | * |
2229 | * @add_interface_debugfs: Drivers can use this callback to add debugfs files | ||
2230 | * when a vif is added to mac80211. This callback and | ||
2231 | * @remove_interface_debugfs should be within a CONFIG_MAC80211_DEBUGFS | ||
2232 | * conditional. @remove_interface_debugfs must be provided for cleanup. | ||
2233 | * This callback can sleep. | ||
2234 | * | ||
2235 | * @remove_interface_debugfs: Remove the debugfs files which were added using | ||
2236 | * @add_interface_debugfs. This callback must remove all debugfs entries | ||
2237 | * that were added because mac80211 only removes interface debugfs when the | ||
2238 | * interface is destroyed, not when it is removed from the driver. | ||
2239 | * This callback can sleep. | ||
2240 | * | ||
2241 | * @config: Handler for configuration requests. IEEE 802.11 code calls this | 2238 | * @config: Handler for configuration requests. IEEE 802.11 code calls this |
2242 | * function to change hardware configuration, e.g., channel. | 2239 | * function to change hardware configuration, e.g., channel. |
2243 | * This function should never fail but returns a negative error code | 2240 | * This function should never fail but returns a negative error code |
@@ -2259,6 +2256,9 @@ enum ieee80211_roc_type { | |||
2259 | * See the section "Frame filtering" for more information. | 2256 | * See the section "Frame filtering" for more information. |
2260 | * This callback must be implemented and can sleep. | 2257 | * This callback must be implemented and can sleep. |
2261 | * | 2258 | * |
2259 | * @set_multicast_list: Configure the device's interface specific RX multicast | ||
2260 | * filter. This callback is optional. This callback must be atomic. | ||
2261 | * | ||
2262 | * @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit | 2262 | * @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit |
2263 | * must be set or cleared for a given STA. Must be atomic. | 2263 | * must be set or cleared for a given STA. Must be atomic. |
2264 | * | 2264 | * |
@@ -2440,8 +2440,11 @@ enum ieee80211_roc_type { | |||
2440 | * @testmode_dump: Implement a cfg80211 test mode dump. The callback can sleep. | 2440 | * @testmode_dump: Implement a cfg80211 test mode dump. The callback can sleep. |
2441 | * | 2441 | * |
2442 | * @flush: Flush all pending frames from the hardware queue, making sure | 2442 | * @flush: Flush all pending frames from the hardware queue, making sure |
2443 | * that the hardware queues are empty. If the parameter @drop is set | 2443 | * that the hardware queues are empty. The @queues parameter is a bitmap |
2444 | * to %true, pending frames may be dropped. The callback can sleep. | 2444 | * of queues to flush, which is useful if different virtual interfaces |
2445 | * use different hardware queues; it may also indicate all queues. | ||
2446 | * If the parameter @drop is set to %true, pending frames may be dropped. | ||
2447 | * The callback can sleep. | ||
2445 | * | 2448 | * |
2446 | * @channel_switch: Drivers that need (or want) to offload the channel | 2449 | * @channel_switch: Drivers that need (or want) to offload the channel |
2447 | * switch operation for CSAs received from the AP may implement this | 2450 | * switch operation for CSAs received from the AP may implement this |
@@ -2506,7 +2509,7 @@ enum ieee80211_roc_type { | |||
2506 | * setting the EOSP flag in the QoS header of the frames. Also, when the | 2509 | * setting the EOSP flag in the QoS header of the frames. Also, when the |
2507 | * service period ends, the driver must set %IEEE80211_TX_STATUS_EOSP | 2510 | * service period ends, the driver must set %IEEE80211_TX_STATUS_EOSP |
2508 | * on the last frame in the SP. Alternatively, it may call the function | 2511 | * on the last frame in the SP. Alternatively, it may call the function |
2509 | * ieee80211_sta_eosp_irqsafe() to inform mac80211 of the end of the SP. | 2512 | * ieee80211_sta_eosp() to inform mac80211 of the end of the SP. |
2510 | * This callback must be atomic. | 2513 | * This callback must be atomic. |
2511 | * @allow_buffered_frames: Prepare device to allow the given number of frames | 2514 | * @allow_buffered_frames: Prepare device to allow the given number of frames |
2512 | * to go out to the given station. The frames will be sent by mac80211 | 2515 | * to go out to the given station. The frames will be sent by mac80211 |
@@ -2517,7 +2520,7 @@ enum ieee80211_roc_type { | |||
2517 | * them between the TIDs, it must set the %IEEE80211_TX_STATUS_EOSP flag | 2520 | * them between the TIDs, it must set the %IEEE80211_TX_STATUS_EOSP flag |
2518 | * on the last frame and clear it on all others and also handle the EOSP | 2521 | * on the last frame and clear it on all others and also handle the EOSP |
2519 | * bit in the QoS header correctly. Alternatively, it can also call the | 2522 | * bit in the QoS header correctly. Alternatively, it can also call the |
2520 | * ieee80211_sta_eosp_irqsafe() function. | 2523 | * ieee80211_sta_eosp() function. |
2521 | * The @tids parameter is a bitmap and tells the driver which TIDs the | 2524 | * The @tids parameter is a bitmap and tells the driver which TIDs the |
2522 | * frames will be on; it will at most have two bits set. | 2525 | * frames will be on; it will at most have two bits set. |
2523 | * This callback must be atomic. | 2526 | * This callback must be atomic. |
@@ -2605,6 +2608,10 @@ struct ieee80211_ops { | |||
2605 | unsigned int changed_flags, | 2608 | unsigned int changed_flags, |
2606 | unsigned int *total_flags, | 2609 | unsigned int *total_flags, |
2607 | u64 multicast); | 2610 | u64 multicast); |
2611 | void (*set_multicast_list)(struct ieee80211_hw *hw, | ||
2612 | struct ieee80211_vif *vif, bool allmulti, | ||
2613 | struct netdev_hw_addr_list *mc_list); | ||
2614 | |||
2608 | int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | 2615 | int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta, |
2609 | bool set); | 2616 | bool set); |
2610 | int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 2617 | int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
@@ -2651,12 +2658,6 @@ struct ieee80211_ops { | |||
2651 | struct ieee80211_vif *vif, | 2658 | struct ieee80211_vif *vif, |
2652 | struct ieee80211_sta *sta, | 2659 | struct ieee80211_sta *sta, |
2653 | struct dentry *dir); | 2660 | struct dentry *dir); |
2654 | void (*add_interface_debugfs)(struct ieee80211_hw *hw, | ||
2655 | struct ieee80211_vif *vif, | ||
2656 | struct dentry *dir); | ||
2657 | void (*remove_interface_debugfs)(struct ieee80211_hw *hw, | ||
2658 | struct ieee80211_vif *vif, | ||
2659 | struct dentry *dir); | ||
2660 | #endif | 2661 | #endif |
2661 | void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 2662 | void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
2662 | enum sta_notify_cmd, struct ieee80211_sta *sta); | 2663 | enum sta_notify_cmd, struct ieee80211_sta *sta); |
@@ -2691,7 +2692,7 @@ struct ieee80211_ops { | |||
2691 | struct netlink_callback *cb, | 2692 | struct netlink_callback *cb, |
2692 | void *data, int len); | 2693 | void *data, int len); |
2693 | #endif | 2694 | #endif |
2694 | void (*flush)(struct ieee80211_hw *hw, bool drop); | 2695 | void (*flush)(struct ieee80211_hw *hw, u32 queues, bool drop); |
2695 | void (*channel_switch)(struct ieee80211_hw *hw, | 2696 | void (*channel_switch)(struct ieee80211_hw *hw, |
2696 | struct ieee80211_channel_switch *ch_switch); | 2697 | struct ieee80211_channel_switch *ch_switch); |
2697 | int (*napi_poll)(struct ieee80211_hw *hw, int budget); | 2698 | int (*napi_poll)(struct ieee80211_hw *hw, int budget); |
@@ -3857,14 +3858,17 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw, | |||
3857 | * %IEEE80211_TX_STATUS_EOSP bit and call this function instead. | 3858 | * %IEEE80211_TX_STATUS_EOSP bit and call this function instead. |
3858 | * This applies for PS-Poll as well as uAPSD. | 3859 | * This applies for PS-Poll as well as uAPSD. |
3859 | * | 3860 | * |
3860 | * Note that there is no non-_irqsafe version right now as | 3861 | * Note that just like with _tx_status() and _rx() drivers must |
3861 | * it wasn't needed, but just like _tx_status() and _rx() | 3862 | * not mix calls to irqsafe/non-irqsafe versions, this function |
3862 | * must not be mixed in irqsafe/non-irqsafe versions, this | 3863 | * must not be mixed with those either. Use the all irqsafe, or |
3863 | * function must not be mixed with those either. Use the | 3864 | * all non-irqsafe, don't mix! |
3864 | * all irqsafe, or all non-irqsafe, don't mix! If you need | 3865 | * |
3865 | * the non-irqsafe version of this, you need to add it. | 3866 | * NB: the _irqsafe version of this function doesn't exist, no |
3867 | * driver needs it right now. Don't call this function if | ||
3868 | * you'd need the _irqsafe version, look at the git history | ||
3869 | * and restore the _irqsafe version! | ||
3866 | */ | 3870 | */ |
3867 | void ieee80211_sta_eosp_irqsafe(struct ieee80211_sta *pubsta); | 3871 | void ieee80211_sta_eosp(struct ieee80211_sta *pubsta); |
3868 | 3872 | ||
3869 | /** | 3873 | /** |
3870 | * ieee80211_iter_keys - iterate keys programmed into the device | 3874 | * ieee80211_iter_keys - iterate keys programmed into the device |
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index eb0f4b16ff09..17f33a62f6db 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c | |||
@@ -397,13 +397,12 @@ static int a2mp_getampassoc_rsp(struct amp_mgr *mgr, struct sk_buff *skb, | |||
397 | if (ctrl) { | 397 | if (ctrl) { |
398 | u8 *assoc; | 398 | u8 *assoc; |
399 | 399 | ||
400 | assoc = kzalloc(assoc_len, GFP_KERNEL); | 400 | assoc = kmemdup(rsp->amp_assoc, assoc_len, GFP_KERNEL); |
401 | if (!assoc) { | 401 | if (!assoc) { |
402 | amp_ctrl_put(ctrl); | 402 | amp_ctrl_put(ctrl); |
403 | return -ENOMEM; | 403 | return -ENOMEM; |
404 | } | 404 | } |
405 | 405 | ||
406 | memcpy(assoc, rsp->amp_assoc, assoc_len); | ||
407 | ctrl->assoc = assoc; | 406 | ctrl->assoc = assoc; |
408 | ctrl->assoc_len = assoc_len; | 407 | ctrl->assoc_len = assoc_len; |
409 | ctrl->assoc_rem_len = assoc_len; | 408 | ctrl->assoc_rem_len = assoc_len; |
@@ -472,13 +471,12 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, | |||
472 | size_t assoc_len = le16_to_cpu(hdr->len) - sizeof(*req); | 471 | size_t assoc_len = le16_to_cpu(hdr->len) - sizeof(*req); |
473 | u8 *assoc; | 472 | u8 *assoc; |
474 | 473 | ||
475 | assoc = kzalloc(assoc_len, GFP_KERNEL); | 474 | assoc = kmemdup(req->amp_assoc, assoc_len, GFP_KERNEL); |
476 | if (!assoc) { | 475 | if (!assoc) { |
477 | amp_ctrl_put(ctrl); | 476 | amp_ctrl_put(ctrl); |
478 | return -ENOMEM; | 477 | return -ENOMEM; |
479 | } | 478 | } |
480 | 479 | ||
481 | memcpy(assoc, req->amp_assoc, assoc_len); | ||
482 | ctrl->assoc = assoc; | 480 | ctrl->assoc = assoc; |
483 | ctrl->assoc_len = assoc_len; | 481 | ctrl->assoc_len = assoc_len; |
484 | ctrl->assoc_rem_len = assoc_len; | 482 | ctrl->assoc_rem_len = assoc_len; |
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index d5a973bf8a6f..e5338f787d68 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -92,23 +92,14 @@ int bt_sock_register(int proto, const struct net_proto_family *ops) | |||
92 | } | 92 | } |
93 | EXPORT_SYMBOL(bt_sock_register); | 93 | EXPORT_SYMBOL(bt_sock_register); |
94 | 94 | ||
95 | int bt_sock_unregister(int proto) | 95 | void bt_sock_unregister(int proto) |
96 | { | 96 | { |
97 | int err = 0; | ||
98 | |||
99 | if (proto < 0 || proto >= BT_MAX_PROTO) | 97 | if (proto < 0 || proto >= BT_MAX_PROTO) |
100 | return -EINVAL; | 98 | return; |
101 | 99 | ||
102 | write_lock(&bt_proto_lock); | 100 | write_lock(&bt_proto_lock); |
103 | 101 | bt_proto[proto] = NULL; | |
104 | if (!bt_proto[proto]) | ||
105 | err = -ENOENT; | ||
106 | else | ||
107 | bt_proto[proto] = NULL; | ||
108 | |||
109 | write_unlock(&bt_proto_lock); | 102 | write_unlock(&bt_proto_lock); |
110 | |||
111 | return err; | ||
112 | } | 103 | } |
113 | EXPORT_SYMBOL(bt_sock_unregister); | 104 | EXPORT_SYMBOL(bt_sock_unregister); |
114 | 105 | ||
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c index e7154a58465f..5b1c04e28821 100644 --- a/net/bluetooth/bnep/sock.c +++ b/net/bluetooth/bnep/sock.c | |||
@@ -253,8 +253,6 @@ error: | |||
253 | void __exit bnep_sock_cleanup(void) | 253 | void __exit bnep_sock_cleanup(void) |
254 | { | 254 | { |
255 | bt_procfs_cleanup(&init_net, "bnep"); | 255 | bt_procfs_cleanup(&init_net, "bnep"); |
256 | if (bt_sock_unregister(BTPROTO_BNEP) < 0) | 256 | bt_sock_unregister(BTPROTO_BNEP); |
257 | BT_ERR("Can't unregister BNEP socket"); | ||
258 | |||
259 | proto_unregister(&bnep_proto); | 257 | proto_unregister(&bnep_proto); |
260 | } | 258 | } |
diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c index 1c57482112b6..58d9edebab4b 100644 --- a/net/bluetooth/cmtp/sock.c +++ b/net/bluetooth/cmtp/sock.c | |||
@@ -264,8 +264,6 @@ error: | |||
264 | void cmtp_cleanup_sockets(void) | 264 | void cmtp_cleanup_sockets(void) |
265 | { | 265 | { |
266 | bt_procfs_cleanup(&init_net, "cmtp"); | 266 | bt_procfs_cleanup(&init_net, "cmtp"); |
267 | if (bt_sock_unregister(BTPROTO_CMTP) < 0) | 267 | bt_sock_unregister(BTPROTO_CMTP); |
268 | BT_ERR("Can't unregister CMTP socket"); | ||
269 | |||
270 | proto_unregister(&cmtp_proto); | 268 | proto_unregister(&cmtp_proto); |
271 | } | 269 | } |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 4925a02ae7e4..b9f90169940b 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -117,7 +117,7 @@ static void hci_acl_create_connection_cancel(struct hci_conn *conn) | |||
117 | hci_send_cmd(conn->hdev, HCI_OP_CREATE_CONN_CANCEL, sizeof(cp), &cp); | 117 | hci_send_cmd(conn->hdev, HCI_OP_CREATE_CONN_CANCEL, sizeof(cp), &cp); |
118 | } | 118 | } |
119 | 119 | ||
120 | void hci_acl_disconn(struct hci_conn *conn, __u8 reason) | 120 | void hci_disconnect(struct hci_conn *conn, __u8 reason) |
121 | { | 121 | { |
122 | struct hci_cp_disconnect cp; | 122 | struct hci_cp_disconnect cp; |
123 | 123 | ||
@@ -253,7 +253,7 @@ static void hci_conn_disconnect(struct hci_conn *conn) | |||
253 | hci_amp_disconn(conn, reason); | 253 | hci_amp_disconn(conn, reason); |
254 | break; | 254 | break; |
255 | default: | 255 | default: |
256 | hci_acl_disconn(conn, reason); | 256 | hci_disconnect(conn, reason); |
257 | break; | 257 | break; |
258 | } | 258 | } |
259 | } | 259 | } |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 60793e7b768b..cfcad5423f1c 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -57,36 +57,9 @@ static void hci_notify(struct hci_dev *hdev, int event) | |||
57 | 57 | ||
58 | /* ---- HCI requests ---- */ | 58 | /* ---- HCI requests ---- */ |
59 | 59 | ||
60 | void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result) | 60 | static void hci_req_sync_complete(struct hci_dev *hdev, u8 result) |
61 | { | 61 | { |
62 | BT_DBG("%s command 0x%4.4x result 0x%2.2x", hdev->name, cmd, result); | 62 | BT_DBG("%s result 0x%2.2x", hdev->name, result); |
63 | |||
64 | /* If this is the init phase check if the completed command matches | ||
65 | * the last init command, and if not just return. | ||
66 | */ | ||
67 | if (test_bit(HCI_INIT, &hdev->flags) && hdev->init_last_cmd != cmd) { | ||
68 | struct hci_command_hdr *sent = (void *) hdev->sent_cmd->data; | ||
69 | u16 opcode = __le16_to_cpu(sent->opcode); | ||
70 | struct sk_buff *skb; | ||
71 | |||
72 | /* Some CSR based controllers generate a spontaneous | ||
73 | * reset complete event during init and any pending | ||
74 | * command will never be completed. In such a case we | ||
75 | * need to resend whatever was the last sent | ||
76 | * command. | ||
77 | */ | ||
78 | |||
79 | if (cmd != HCI_OP_RESET || opcode == HCI_OP_RESET) | ||
80 | return; | ||
81 | |||
82 | skb = skb_clone(hdev->sent_cmd, GFP_ATOMIC); | ||
83 | if (skb) { | ||
84 | skb_queue_head(&hdev->cmd_q, skb); | ||
85 | queue_work(hdev->workqueue, &hdev->cmd_work); | ||
86 | } | ||
87 | |||
88 | return; | ||
89 | } | ||
90 | 63 | ||
91 | if (hdev->req_status == HCI_REQ_PEND) { | 64 | if (hdev->req_status == HCI_REQ_PEND) { |
92 | hdev->req_result = result; | 65 | hdev->req_result = result; |
@@ -107,21 +80,41 @@ static void hci_req_cancel(struct hci_dev *hdev, int err) | |||
107 | } | 80 | } |
108 | 81 | ||
109 | /* Execute request and wait for completion. */ | 82 | /* Execute request and wait for completion. */ |
110 | static int __hci_request(struct hci_dev *hdev, | 83 | static int __hci_req_sync(struct hci_dev *hdev, |
111 | void (*req)(struct hci_dev *hdev, unsigned long opt), | 84 | void (*func)(struct hci_request *req, |
112 | unsigned long opt, __u32 timeout) | 85 | unsigned long opt), |
86 | unsigned long opt, __u32 timeout) | ||
113 | { | 87 | { |
88 | struct hci_request req; | ||
114 | DECLARE_WAITQUEUE(wait, current); | 89 | DECLARE_WAITQUEUE(wait, current); |
115 | int err = 0; | 90 | int err = 0; |
116 | 91 | ||
117 | BT_DBG("%s start", hdev->name); | 92 | BT_DBG("%s start", hdev->name); |
118 | 93 | ||
94 | hci_req_init(&req, hdev); | ||
95 | |||
119 | hdev->req_status = HCI_REQ_PEND; | 96 | hdev->req_status = HCI_REQ_PEND; |
120 | 97 | ||
98 | func(&req, opt); | ||
99 | |||
100 | err = hci_req_run(&req, hci_req_sync_complete); | ||
101 | if (err < 0) { | ||
102 | hdev->req_status = 0; | ||
103 | |||
104 | /* ENODATA means the HCI request command queue is empty. | ||
105 | * This can happen when a request with conditionals doesn't | ||
106 | * trigger any commands to be sent. This is normal behavior | ||
107 | * and should not trigger an error return. | ||
108 | */ | ||
109 | if (err == -ENODATA) | ||
110 | return 0; | ||
111 | |||
112 | return err; | ||
113 | } | ||
114 | |||
121 | add_wait_queue(&hdev->req_wait_q, &wait); | 115 | add_wait_queue(&hdev->req_wait_q, &wait); |
122 | set_current_state(TASK_INTERRUPTIBLE); | 116 | set_current_state(TASK_INTERRUPTIBLE); |
123 | 117 | ||
124 | req(hdev, opt); | ||
125 | schedule_timeout(timeout); | 118 | schedule_timeout(timeout); |
126 | 119 | ||
127 | remove_wait_queue(&hdev->req_wait_q, &wait); | 120 | remove_wait_queue(&hdev->req_wait_q, &wait); |
@@ -150,9 +143,10 @@ static int __hci_request(struct hci_dev *hdev, | |||
150 | return err; | 143 | return err; |
151 | } | 144 | } |
152 | 145 | ||
153 | static int hci_request(struct hci_dev *hdev, | 146 | static int hci_req_sync(struct hci_dev *hdev, |
154 | void (*req)(struct hci_dev *hdev, unsigned long opt), | 147 | void (*req)(struct hci_request *req, |
155 | unsigned long opt, __u32 timeout) | 148 | unsigned long opt), |
149 | unsigned long opt, __u32 timeout) | ||
156 | { | 150 | { |
157 | int ret; | 151 | int ret; |
158 | 152 | ||
@@ -161,75 +155,86 @@ static int hci_request(struct hci_dev *hdev, | |||
161 | 155 | ||
162 | /* Serialize all requests */ | 156 | /* Serialize all requests */ |
163 | hci_req_lock(hdev); | 157 | hci_req_lock(hdev); |
164 | ret = __hci_request(hdev, req, opt, timeout); | 158 | ret = __hci_req_sync(hdev, req, opt, timeout); |
165 | hci_req_unlock(hdev); | 159 | hci_req_unlock(hdev); |
166 | 160 | ||
167 | return ret; | 161 | return ret; |
168 | } | 162 | } |
169 | 163 | ||
170 | static void hci_reset_req(struct hci_dev *hdev, unsigned long opt) | 164 | static void hci_reset_req(struct hci_request *req, unsigned long opt) |
171 | { | 165 | { |
172 | BT_DBG("%s %ld", hdev->name, opt); | 166 | BT_DBG("%s %ld", req->hdev->name, opt); |
173 | 167 | ||
174 | /* Reset device */ | 168 | /* Reset device */ |
175 | set_bit(HCI_RESET, &hdev->flags); | 169 | set_bit(HCI_RESET, &req->hdev->flags); |
176 | hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL); | 170 | hci_req_add(req, HCI_OP_RESET, 0, NULL); |
177 | } | 171 | } |
178 | 172 | ||
179 | static void bredr_init(struct hci_dev *hdev) | 173 | static void bredr_init(struct hci_request *req) |
180 | { | 174 | { |
181 | hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_PACKET_BASED; | 175 | req->hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_PACKET_BASED; |
182 | 176 | ||
183 | /* Read Local Supported Features */ | 177 | /* Read Local Supported Features */ |
184 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_FEATURES, 0, NULL); | 178 | hci_req_add(req, HCI_OP_READ_LOCAL_FEATURES, 0, NULL); |
185 | 179 | ||
186 | /* Read Local Version */ | 180 | /* Read Local Version */ |
187 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL); | 181 | hci_req_add(req, HCI_OP_READ_LOCAL_VERSION, 0, NULL); |
182 | |||
183 | /* Read BD Address */ | ||
184 | hci_req_add(req, HCI_OP_READ_BD_ADDR, 0, NULL); | ||
188 | } | 185 | } |
189 | 186 | ||
190 | static void amp_init(struct hci_dev *hdev) | 187 | static void amp_init(struct hci_request *req) |
191 | { | 188 | { |
192 | hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_BLOCK_BASED; | 189 | req->hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_BLOCK_BASED; |
193 | 190 | ||
194 | /* Read Local Version */ | 191 | /* Read Local Version */ |
195 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL); | 192 | hci_req_add(req, HCI_OP_READ_LOCAL_VERSION, 0, NULL); |
196 | 193 | ||
197 | /* Read Local AMP Info */ | 194 | /* Read Local AMP Info */ |
198 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL); | 195 | hci_req_add(req, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL); |
199 | 196 | ||
200 | /* Read Data Blk size */ | 197 | /* Read Data Blk size */ |
201 | hci_send_cmd(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, 0, NULL); | 198 | hci_req_add(req, HCI_OP_READ_DATA_BLOCK_SIZE, 0, NULL); |
202 | } | 199 | } |
203 | 200 | ||
204 | static void hci_init_req(struct hci_dev *hdev, unsigned long opt) | 201 | static void hci_init1_req(struct hci_request *req, unsigned long opt) |
205 | { | 202 | { |
203 | struct hci_dev *hdev = req->hdev; | ||
204 | struct hci_request init_req; | ||
206 | struct sk_buff *skb; | 205 | struct sk_buff *skb; |
207 | 206 | ||
208 | BT_DBG("%s %ld", hdev->name, opt); | 207 | BT_DBG("%s %ld", hdev->name, opt); |
209 | 208 | ||
210 | /* Driver initialization */ | 209 | /* Driver initialization */ |
211 | 210 | ||
211 | hci_req_init(&init_req, hdev); | ||
212 | |||
212 | /* Special commands */ | 213 | /* Special commands */ |
213 | while ((skb = skb_dequeue(&hdev->driver_init))) { | 214 | while ((skb = skb_dequeue(&hdev->driver_init))) { |
214 | bt_cb(skb)->pkt_type = HCI_COMMAND_PKT; | 215 | bt_cb(skb)->pkt_type = HCI_COMMAND_PKT; |
215 | skb->dev = (void *) hdev; | 216 | skb->dev = (void *) hdev; |
216 | 217 | ||
217 | skb_queue_tail(&hdev->cmd_q, skb); | 218 | if (skb_queue_empty(&init_req.cmd_q)) |
218 | queue_work(hdev->workqueue, &hdev->cmd_work); | 219 | bt_cb(skb)->req.start = true; |
220 | |||
221 | skb_queue_tail(&init_req.cmd_q, skb); | ||
219 | } | 222 | } |
220 | skb_queue_purge(&hdev->driver_init); | 223 | skb_queue_purge(&hdev->driver_init); |
221 | 224 | ||
225 | hci_req_run(&init_req, NULL); | ||
226 | |||
222 | /* Reset */ | 227 | /* Reset */ |
223 | if (!test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) | 228 | if (!test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) |
224 | hci_reset_req(hdev, 0); | 229 | hci_reset_req(req, 0); |
225 | 230 | ||
226 | switch (hdev->dev_type) { | 231 | switch (hdev->dev_type) { |
227 | case HCI_BREDR: | 232 | case HCI_BREDR: |
228 | bredr_init(hdev); | 233 | bredr_init(req); |
229 | break; | 234 | break; |
230 | 235 | ||
231 | case HCI_AMP: | 236 | case HCI_AMP: |
232 | amp_init(hdev); | 237 | amp_init(req); |
233 | break; | 238 | break; |
234 | 239 | ||
235 | default: | 240 | default: |
@@ -238,44 +243,327 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt) | |||
238 | } | 243 | } |
239 | } | 244 | } |
240 | 245 | ||
241 | static void hci_scan_req(struct hci_dev *hdev, unsigned long opt) | 246 | static void bredr_setup(struct hci_request *req) |
247 | { | ||
248 | struct hci_cp_delete_stored_link_key cp; | ||
249 | __le16 param; | ||
250 | __u8 flt_type; | ||
251 | |||
252 | /* Read Buffer Size (ACL mtu, max pkt, etc.) */ | ||
253 | hci_req_add(req, HCI_OP_READ_BUFFER_SIZE, 0, NULL); | ||
254 | |||
255 | /* Read Class of Device */ | ||
256 | hci_req_add(req, HCI_OP_READ_CLASS_OF_DEV, 0, NULL); | ||
257 | |||
258 | /* Read Local Name */ | ||
259 | hci_req_add(req, HCI_OP_READ_LOCAL_NAME, 0, NULL); | ||
260 | |||
261 | /* Read Voice Setting */ | ||
262 | hci_req_add(req, HCI_OP_READ_VOICE_SETTING, 0, NULL); | ||
263 | |||
264 | /* Clear Event Filters */ | ||
265 | flt_type = HCI_FLT_CLEAR_ALL; | ||
266 | hci_req_add(req, HCI_OP_SET_EVENT_FLT, 1, &flt_type); | ||
267 | |||
268 | /* Connection accept timeout ~20 secs */ | ||
269 | param = __constant_cpu_to_le16(0x7d00); | ||
270 | hci_req_add(req, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); | ||
271 | |||
272 | bacpy(&cp.bdaddr, BDADDR_ANY); | ||
273 | cp.delete_all = 0x01; | ||
274 | hci_req_add(req, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp); | ||
275 | |||
276 | /* Read page scan parameters */ | ||
277 | if (req->hdev->hci_ver > BLUETOOTH_VER_1_1) { | ||
278 | hci_req_add(req, HCI_OP_READ_PAGE_SCAN_ACTIVITY, 0, NULL); | ||
279 | hci_req_add(req, HCI_OP_READ_PAGE_SCAN_TYPE, 0, NULL); | ||
280 | } | ||
281 | } | ||
282 | |||
283 | static void le_setup(struct hci_request *req) | ||
284 | { | ||
285 | /* Read LE Buffer Size */ | ||
286 | hci_req_add(req, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL); | ||
287 | |||
288 | /* Read LE Local Supported Features */ | ||
289 | hci_req_add(req, HCI_OP_LE_READ_LOCAL_FEATURES, 0, NULL); | ||
290 | |||
291 | /* Read LE Advertising Channel TX Power */ | ||
292 | hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL); | ||
293 | |||
294 | /* Read LE White List Size */ | ||
295 | hci_req_add(req, HCI_OP_LE_READ_WHITE_LIST_SIZE, 0, NULL); | ||
296 | |||
297 | /* Read LE Supported States */ | ||
298 | hci_req_add(req, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL); | ||
299 | } | ||
300 | |||
301 | static u8 hci_get_inquiry_mode(struct hci_dev *hdev) | ||
302 | { | ||
303 | if (lmp_ext_inq_capable(hdev)) | ||
304 | return 0x02; | ||
305 | |||
306 | if (lmp_inq_rssi_capable(hdev)) | ||
307 | return 0x01; | ||
308 | |||
309 | if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && | ||
310 | hdev->lmp_subver == 0x0757) | ||
311 | return 0x01; | ||
312 | |||
313 | if (hdev->manufacturer == 15) { | ||
314 | if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963) | ||
315 | return 0x01; | ||
316 | if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963) | ||
317 | return 0x01; | ||
318 | if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965) | ||
319 | return 0x01; | ||
320 | } | ||
321 | |||
322 | if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 && | ||
323 | hdev->lmp_subver == 0x1805) | ||
324 | return 0x01; | ||
325 | |||
326 | return 0x00; | ||
327 | } | ||
328 | |||
329 | static void hci_setup_inquiry_mode(struct hci_request *req) | ||
330 | { | ||
331 | u8 mode; | ||
332 | |||
333 | mode = hci_get_inquiry_mode(req->hdev); | ||
334 | |||
335 | hci_req_add(req, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode); | ||
336 | } | ||
337 | |||
338 | static void hci_setup_event_mask(struct hci_request *req) | ||
339 | { | ||
340 | struct hci_dev *hdev = req->hdev; | ||
341 | |||
342 | /* The second byte is 0xff instead of 0x9f (two reserved bits | ||
343 | * disabled) since a Broadcom 1.2 dongle doesn't respond to the | ||
344 | * command otherwise. | ||
345 | */ | ||
346 | u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; | ||
347 | |||
348 | /* CSR 1.1 dongles does not accept any bitfield so don't try to set | ||
349 | * any event mask for pre 1.2 devices. | ||
350 | */ | ||
351 | if (hdev->hci_ver < BLUETOOTH_VER_1_2) | ||
352 | return; | ||
353 | |||
354 | if (lmp_bredr_capable(hdev)) { | ||
355 | events[4] |= 0x01; /* Flow Specification Complete */ | ||
356 | events[4] |= 0x02; /* Inquiry Result with RSSI */ | ||
357 | events[4] |= 0x04; /* Read Remote Extended Features Complete */ | ||
358 | events[5] |= 0x08; /* Synchronous Connection Complete */ | ||
359 | events[5] |= 0x10; /* Synchronous Connection Changed */ | ||
360 | } | ||
361 | |||
362 | if (lmp_inq_rssi_capable(hdev)) | ||
363 | events[4] |= 0x02; /* Inquiry Result with RSSI */ | ||
364 | |||
365 | if (lmp_sniffsubr_capable(hdev)) | ||
366 | events[5] |= 0x20; /* Sniff Subrating */ | ||
367 | |||
368 | if (lmp_pause_enc_capable(hdev)) | ||
369 | events[5] |= 0x80; /* Encryption Key Refresh Complete */ | ||
370 | |||
371 | if (lmp_ext_inq_capable(hdev)) | ||
372 | events[5] |= 0x40; /* Extended Inquiry Result */ | ||
373 | |||
374 | if (lmp_no_flush_capable(hdev)) | ||
375 | events[7] |= 0x01; /* Enhanced Flush Complete */ | ||
376 | |||
377 | if (lmp_lsto_capable(hdev)) | ||
378 | events[6] |= 0x80; /* Link Supervision Timeout Changed */ | ||
379 | |||
380 | if (lmp_ssp_capable(hdev)) { | ||
381 | events[6] |= 0x01; /* IO Capability Request */ | ||
382 | events[6] |= 0x02; /* IO Capability Response */ | ||
383 | events[6] |= 0x04; /* User Confirmation Request */ | ||
384 | events[6] |= 0x08; /* User Passkey Request */ | ||
385 | events[6] |= 0x10; /* Remote OOB Data Request */ | ||
386 | events[6] |= 0x20; /* Simple Pairing Complete */ | ||
387 | events[7] |= 0x04; /* User Passkey Notification */ | ||
388 | events[7] |= 0x08; /* Keypress Notification */ | ||
389 | events[7] |= 0x10; /* Remote Host Supported | ||
390 | * Features Notification | ||
391 | */ | ||
392 | } | ||
393 | |||
394 | if (lmp_le_capable(hdev)) | ||
395 | events[7] |= 0x20; /* LE Meta-Event */ | ||
396 | |||
397 | hci_req_add(req, HCI_OP_SET_EVENT_MASK, sizeof(events), events); | ||
398 | |||
399 | if (lmp_le_capable(hdev)) { | ||
400 | memset(events, 0, sizeof(events)); | ||
401 | events[0] = 0x1f; | ||
402 | hci_req_add(req, HCI_OP_LE_SET_EVENT_MASK, | ||
403 | sizeof(events), events); | ||
404 | } | ||
405 | } | ||
406 | |||
407 | static void hci_init2_req(struct hci_request *req, unsigned long opt) | ||
408 | { | ||
409 | struct hci_dev *hdev = req->hdev; | ||
410 | |||
411 | if (lmp_bredr_capable(hdev)) | ||
412 | bredr_setup(req); | ||
413 | |||
414 | if (lmp_le_capable(hdev)) | ||
415 | le_setup(req); | ||
416 | |||
417 | hci_setup_event_mask(req); | ||
418 | |||
419 | if (hdev->hci_ver > BLUETOOTH_VER_1_1) | ||
420 | hci_req_add(req, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); | ||
421 | |||
422 | if (lmp_ssp_capable(hdev)) { | ||
423 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { | ||
424 | u8 mode = 0x01; | ||
425 | hci_req_add(req, HCI_OP_WRITE_SSP_MODE, | ||
426 | sizeof(mode), &mode); | ||
427 | } else { | ||
428 | struct hci_cp_write_eir cp; | ||
429 | |||
430 | memset(hdev->eir, 0, sizeof(hdev->eir)); | ||
431 | memset(&cp, 0, sizeof(cp)); | ||
432 | |||
433 | hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp); | ||
434 | } | ||
435 | } | ||
436 | |||
437 | if (lmp_inq_rssi_capable(hdev)) | ||
438 | hci_setup_inquiry_mode(req); | ||
439 | |||
440 | if (lmp_inq_tx_pwr_capable(hdev)) | ||
441 | hci_req_add(req, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); | ||
442 | |||
443 | if (lmp_ext_feat_capable(hdev)) { | ||
444 | struct hci_cp_read_local_ext_features cp; | ||
445 | |||
446 | cp.page = 0x01; | ||
447 | hci_req_add(req, HCI_OP_READ_LOCAL_EXT_FEATURES, | ||
448 | sizeof(cp), &cp); | ||
449 | } | ||
450 | |||
451 | if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) { | ||
452 | u8 enable = 1; | ||
453 | hci_req_add(req, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable), | ||
454 | &enable); | ||
455 | } | ||
456 | } | ||
457 | |||
458 | static void hci_setup_link_policy(struct hci_request *req) | ||
459 | { | ||
460 | struct hci_dev *hdev = req->hdev; | ||
461 | struct hci_cp_write_def_link_policy cp; | ||
462 | u16 link_policy = 0; | ||
463 | |||
464 | if (lmp_rswitch_capable(hdev)) | ||
465 | link_policy |= HCI_LP_RSWITCH; | ||
466 | if (lmp_hold_capable(hdev)) | ||
467 | link_policy |= HCI_LP_HOLD; | ||
468 | if (lmp_sniff_capable(hdev)) | ||
469 | link_policy |= HCI_LP_SNIFF; | ||
470 | if (lmp_park_capable(hdev)) | ||
471 | link_policy |= HCI_LP_PARK; | ||
472 | |||
473 | cp.policy = cpu_to_le16(link_policy); | ||
474 | hci_req_add(req, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp); | ||
475 | } | ||
476 | |||
477 | static void hci_set_le_support(struct hci_request *req) | ||
478 | { | ||
479 | struct hci_dev *hdev = req->hdev; | ||
480 | struct hci_cp_write_le_host_supported cp; | ||
481 | |||
482 | memset(&cp, 0, sizeof(cp)); | ||
483 | |||
484 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { | ||
485 | cp.le = 0x01; | ||
486 | cp.simul = lmp_le_br_capable(hdev); | ||
487 | } | ||
488 | |||
489 | if (cp.le != lmp_host_le_capable(hdev)) | ||
490 | hci_req_add(req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), | ||
491 | &cp); | ||
492 | } | ||
493 | |||
494 | static void hci_init3_req(struct hci_request *req, unsigned long opt) | ||
495 | { | ||
496 | struct hci_dev *hdev = req->hdev; | ||
497 | |||
498 | if (hdev->commands[5] & 0x10) | ||
499 | hci_setup_link_policy(req); | ||
500 | |||
501 | if (lmp_le_capable(hdev)) { | ||
502 | hci_set_le_support(req); | ||
503 | hci_update_ad(req); | ||
504 | } | ||
505 | } | ||
506 | |||
507 | static int __hci_init(struct hci_dev *hdev) | ||
508 | { | ||
509 | int err; | ||
510 | |||
511 | err = __hci_req_sync(hdev, hci_init1_req, 0, HCI_INIT_TIMEOUT); | ||
512 | if (err < 0) | ||
513 | return err; | ||
514 | |||
515 | /* HCI_BREDR covers both single-mode LE, BR/EDR and dual-mode | ||
516 | * BR/EDR/LE type controllers. AMP controllers only need the | ||
517 | * first stage init. | ||
518 | */ | ||
519 | if (hdev->dev_type != HCI_BREDR) | ||
520 | return 0; | ||
521 | |||
522 | err = __hci_req_sync(hdev, hci_init2_req, 0, HCI_INIT_TIMEOUT); | ||
523 | if (err < 0) | ||
524 | return err; | ||
525 | |||
526 | return __hci_req_sync(hdev, hci_init3_req, 0, HCI_INIT_TIMEOUT); | ||
527 | } | ||
528 | |||
529 | static void hci_scan_req(struct hci_request *req, unsigned long opt) | ||
242 | { | 530 | { |
243 | __u8 scan = opt; | 531 | __u8 scan = opt; |
244 | 532 | ||
245 | BT_DBG("%s %x", hdev->name, scan); | 533 | BT_DBG("%s %x", req->hdev->name, scan); |
246 | 534 | ||
247 | /* Inquiry and Page scans */ | 535 | /* Inquiry and Page scans */ |
248 | hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | 536 | hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); |
249 | } | 537 | } |
250 | 538 | ||
251 | static void hci_auth_req(struct hci_dev *hdev, unsigned long opt) | 539 | static void hci_auth_req(struct hci_request *req, unsigned long opt) |
252 | { | 540 | { |
253 | __u8 auth = opt; | 541 | __u8 auth = opt; |
254 | 542 | ||
255 | BT_DBG("%s %x", hdev->name, auth); | 543 | BT_DBG("%s %x", req->hdev->name, auth); |
256 | 544 | ||
257 | /* Authentication */ | 545 | /* Authentication */ |
258 | hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, 1, &auth); | 546 | hci_req_add(req, HCI_OP_WRITE_AUTH_ENABLE, 1, &auth); |
259 | } | 547 | } |
260 | 548 | ||
261 | static void hci_encrypt_req(struct hci_dev *hdev, unsigned long opt) | 549 | static void hci_encrypt_req(struct hci_request *req, unsigned long opt) |
262 | { | 550 | { |
263 | __u8 encrypt = opt; | 551 | __u8 encrypt = opt; |
264 | 552 | ||
265 | BT_DBG("%s %x", hdev->name, encrypt); | 553 | BT_DBG("%s %x", req->hdev->name, encrypt); |
266 | 554 | ||
267 | /* Encryption */ | 555 | /* Encryption */ |
268 | hci_send_cmd(hdev, HCI_OP_WRITE_ENCRYPT_MODE, 1, &encrypt); | 556 | hci_req_add(req, HCI_OP_WRITE_ENCRYPT_MODE, 1, &encrypt); |
269 | } | 557 | } |
270 | 558 | ||
271 | static void hci_linkpol_req(struct hci_dev *hdev, unsigned long opt) | 559 | static void hci_linkpol_req(struct hci_request *req, unsigned long opt) |
272 | { | 560 | { |
273 | __le16 policy = cpu_to_le16(opt); | 561 | __le16 policy = cpu_to_le16(opt); |
274 | 562 | ||
275 | BT_DBG("%s %x", hdev->name, policy); | 563 | BT_DBG("%s %x", req->hdev->name, policy); |
276 | 564 | ||
277 | /* Default link policy */ | 565 | /* Default link policy */ |
278 | hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, 2, &policy); | 566 | hci_req_add(req, HCI_OP_WRITE_DEF_LINK_POLICY, 2, &policy); |
279 | } | 567 | } |
280 | 568 | ||
281 | /* Get HCI device by index. | 569 | /* Get HCI device by index. |
@@ -512,9 +800,10 @@ static int inquiry_cache_dump(struct hci_dev *hdev, int num, __u8 *buf) | |||
512 | return copied; | 800 | return copied; |
513 | } | 801 | } |
514 | 802 | ||
515 | static void hci_inq_req(struct hci_dev *hdev, unsigned long opt) | 803 | static void hci_inq_req(struct hci_request *req, unsigned long opt) |
516 | { | 804 | { |
517 | struct hci_inquiry_req *ir = (struct hci_inquiry_req *) opt; | 805 | struct hci_inquiry_req *ir = (struct hci_inquiry_req *) opt; |
806 | struct hci_dev *hdev = req->hdev; | ||
518 | struct hci_cp_inquiry cp; | 807 | struct hci_cp_inquiry cp; |
519 | 808 | ||
520 | BT_DBG("%s", hdev->name); | 809 | BT_DBG("%s", hdev->name); |
@@ -526,7 +815,7 @@ static void hci_inq_req(struct hci_dev *hdev, unsigned long opt) | |||
526 | memcpy(&cp.lap, &ir->lap, 3); | 815 | memcpy(&cp.lap, &ir->lap, 3); |
527 | cp.length = ir->length; | 816 | cp.length = ir->length; |
528 | cp.num_rsp = ir->num_rsp; | 817 | cp.num_rsp = ir->num_rsp; |
529 | hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp); | 818 | hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp); |
530 | } | 819 | } |
531 | 820 | ||
532 | int hci_inquiry(void __user *arg) | 821 | int hci_inquiry(void __user *arg) |
@@ -556,7 +845,8 @@ int hci_inquiry(void __user *arg) | |||
556 | timeo = ir.length * msecs_to_jiffies(2000); | 845 | timeo = ir.length * msecs_to_jiffies(2000); |
557 | 846 | ||
558 | if (do_inquiry) { | 847 | if (do_inquiry) { |
559 | err = hci_request(hdev, hci_inq_req, (unsigned long)&ir, timeo); | 848 | err = hci_req_sync(hdev, hci_inq_req, (unsigned long) &ir, |
849 | timeo); | ||
560 | if (err < 0) | 850 | if (err < 0) |
561 | goto done; | 851 | goto done; |
562 | } | 852 | } |
@@ -654,39 +944,29 @@ static u8 create_ad(struct hci_dev *hdev, u8 *ptr) | |||
654 | return ad_len; | 944 | return ad_len; |
655 | } | 945 | } |
656 | 946 | ||
657 | int hci_update_ad(struct hci_dev *hdev) | 947 | void hci_update_ad(struct hci_request *req) |
658 | { | 948 | { |
949 | struct hci_dev *hdev = req->hdev; | ||
659 | struct hci_cp_le_set_adv_data cp; | 950 | struct hci_cp_le_set_adv_data cp; |
660 | u8 len; | 951 | u8 len; |
661 | int err; | ||
662 | 952 | ||
663 | hci_dev_lock(hdev); | 953 | if (!lmp_le_capable(hdev)) |
664 | 954 | return; | |
665 | if (!lmp_le_capable(hdev)) { | ||
666 | err = -EINVAL; | ||
667 | goto unlock; | ||
668 | } | ||
669 | 955 | ||
670 | memset(&cp, 0, sizeof(cp)); | 956 | memset(&cp, 0, sizeof(cp)); |
671 | 957 | ||
672 | len = create_ad(hdev, cp.data); | 958 | len = create_ad(hdev, cp.data); |
673 | 959 | ||
674 | if (hdev->adv_data_len == len && | 960 | if (hdev->adv_data_len == len && |
675 | memcmp(cp.data, hdev->adv_data, len) == 0) { | 961 | memcmp(cp.data, hdev->adv_data, len) == 0) |
676 | err = 0; | 962 | return; |
677 | goto unlock; | ||
678 | } | ||
679 | 963 | ||
680 | memcpy(hdev->adv_data, cp.data, sizeof(cp.data)); | 964 | memcpy(hdev->adv_data, cp.data, sizeof(cp.data)); |
681 | hdev->adv_data_len = len; | 965 | hdev->adv_data_len = len; |
682 | 966 | ||
683 | cp.length = len; | 967 | cp.length = len; |
684 | err = hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); | ||
685 | 968 | ||
686 | unlock: | 969 | hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); |
687 | hci_dev_unlock(hdev); | ||
688 | |||
689 | return err; | ||
690 | } | 970 | } |
691 | 971 | ||
692 | /* ---- HCI ioctl helpers ---- */ | 972 | /* ---- HCI ioctl helpers ---- */ |
@@ -735,10 +1015,7 @@ int hci_dev_open(__u16 dev) | |||
735 | if (!test_bit(HCI_RAW, &hdev->flags)) { | 1015 | if (!test_bit(HCI_RAW, &hdev->flags)) { |
736 | atomic_set(&hdev->cmd_cnt, 1); | 1016 | atomic_set(&hdev->cmd_cnt, 1); |
737 | set_bit(HCI_INIT, &hdev->flags); | 1017 | set_bit(HCI_INIT, &hdev->flags); |
738 | hdev->init_last_cmd = 0; | 1018 | ret = __hci_init(hdev); |
739 | |||
740 | ret = __hci_request(hdev, hci_init_req, 0, HCI_INIT_TIMEOUT); | ||
741 | |||
742 | clear_bit(HCI_INIT, &hdev->flags); | 1019 | clear_bit(HCI_INIT, &hdev->flags); |
743 | } | 1020 | } |
744 | 1021 | ||
@@ -746,7 +1023,6 @@ int hci_dev_open(__u16 dev) | |||
746 | hci_dev_hold(hdev); | 1023 | hci_dev_hold(hdev); |
747 | set_bit(HCI_UP, &hdev->flags); | 1024 | set_bit(HCI_UP, &hdev->flags); |
748 | hci_notify(hdev, HCI_DEV_UP); | 1025 | hci_notify(hdev, HCI_DEV_UP); |
749 | hci_update_ad(hdev); | ||
750 | if (!test_bit(HCI_SETUP, &hdev->dev_flags) && | 1026 | if (!test_bit(HCI_SETUP, &hdev->dev_flags) && |
751 | mgmt_valid_hdev(hdev)) { | 1027 | mgmt_valid_hdev(hdev)) { |
752 | hci_dev_lock(hdev); | 1028 | hci_dev_lock(hdev); |
@@ -828,7 +1104,7 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
828 | if (!test_bit(HCI_RAW, &hdev->flags) && | 1104 | if (!test_bit(HCI_RAW, &hdev->flags) && |
829 | test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) { | 1105 | test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) { |
830 | set_bit(HCI_INIT, &hdev->flags); | 1106 | set_bit(HCI_INIT, &hdev->flags); |
831 | __hci_request(hdev, hci_reset_req, 0, HCI_CMD_TIMEOUT); | 1107 | __hci_req_sync(hdev, hci_reset_req, 0, HCI_CMD_TIMEOUT); |
832 | clear_bit(HCI_INIT, &hdev->flags); | 1108 | clear_bit(HCI_INIT, &hdev->flags); |
833 | } | 1109 | } |
834 | 1110 | ||
@@ -851,6 +1127,10 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
851 | * and no tasks are scheduled. */ | 1127 | * and no tasks are scheduled. */ |
852 | hdev->close(hdev); | 1128 | hdev->close(hdev); |
853 | 1129 | ||
1130 | /* Clear flags */ | ||
1131 | hdev->flags = 0; | ||
1132 | hdev->dev_flags &= ~HCI_PERSISTENT_MASK; | ||
1133 | |||
854 | if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags) && | 1134 | if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags) && |
855 | mgmt_valid_hdev(hdev)) { | 1135 | mgmt_valid_hdev(hdev)) { |
856 | hci_dev_lock(hdev); | 1136 | hci_dev_lock(hdev); |
@@ -858,9 +1138,6 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
858 | hci_dev_unlock(hdev); | 1138 | hci_dev_unlock(hdev); |
859 | } | 1139 | } |
860 | 1140 | ||
861 | /* Clear flags */ | ||
862 | hdev->flags = 0; | ||
863 | |||
864 | /* Controller radio is available but is currently powered down */ | 1141 | /* Controller radio is available but is currently powered down */ |
865 | hdev->amp_status = 0; | 1142 | hdev->amp_status = 0; |
866 | 1143 | ||
@@ -921,7 +1198,7 @@ int hci_dev_reset(__u16 dev) | |||
921 | hdev->acl_cnt = 0; hdev->sco_cnt = 0; hdev->le_cnt = 0; | 1198 | hdev->acl_cnt = 0; hdev->sco_cnt = 0; hdev->le_cnt = 0; |
922 | 1199 | ||
923 | if (!test_bit(HCI_RAW, &hdev->flags)) | 1200 | if (!test_bit(HCI_RAW, &hdev->flags)) |
924 | ret = __hci_request(hdev, hci_reset_req, 0, HCI_INIT_TIMEOUT); | 1201 | ret = __hci_req_sync(hdev, hci_reset_req, 0, HCI_INIT_TIMEOUT); |
925 | 1202 | ||
926 | done: | 1203 | done: |
927 | hci_req_unlock(hdev); | 1204 | hci_req_unlock(hdev); |
@@ -960,8 +1237,8 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) | |||
960 | 1237 | ||
961 | switch (cmd) { | 1238 | switch (cmd) { |
962 | case HCISETAUTH: | 1239 | case HCISETAUTH: |
963 | err = hci_request(hdev, hci_auth_req, dr.dev_opt, | 1240 | err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt, |
964 | HCI_INIT_TIMEOUT); | 1241 | HCI_INIT_TIMEOUT); |
965 | break; | 1242 | break; |
966 | 1243 | ||
967 | case HCISETENCRYPT: | 1244 | case HCISETENCRYPT: |
@@ -972,24 +1249,24 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) | |||
972 | 1249 | ||
973 | if (!test_bit(HCI_AUTH, &hdev->flags)) { | 1250 | if (!test_bit(HCI_AUTH, &hdev->flags)) { |
974 | /* Auth must be enabled first */ | 1251 | /* Auth must be enabled first */ |
975 | err = hci_request(hdev, hci_auth_req, dr.dev_opt, | 1252 | err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt, |
976 | HCI_INIT_TIMEOUT); | 1253 | HCI_INIT_TIMEOUT); |
977 | if (err) | 1254 | if (err) |
978 | break; | 1255 | break; |
979 | } | 1256 | } |
980 | 1257 | ||
981 | err = hci_request(hdev, hci_encrypt_req, dr.dev_opt, | 1258 | err = hci_req_sync(hdev, hci_encrypt_req, dr.dev_opt, |
982 | HCI_INIT_TIMEOUT); | 1259 | HCI_INIT_TIMEOUT); |
983 | break; | 1260 | break; |
984 | 1261 | ||
985 | case HCISETSCAN: | 1262 | case HCISETSCAN: |
986 | err = hci_request(hdev, hci_scan_req, dr.dev_opt, | 1263 | err = hci_req_sync(hdev, hci_scan_req, dr.dev_opt, |
987 | HCI_INIT_TIMEOUT); | 1264 | HCI_INIT_TIMEOUT); |
988 | break; | 1265 | break; |
989 | 1266 | ||
990 | case HCISETLINKPOL: | 1267 | case HCISETLINKPOL: |
991 | err = hci_request(hdev, hci_linkpol_req, dr.dev_opt, | 1268 | err = hci_req_sync(hdev, hci_linkpol_req, dr.dev_opt, |
992 | HCI_INIT_TIMEOUT); | 1269 | HCI_INIT_TIMEOUT); |
993 | break; | 1270 | break; |
994 | 1271 | ||
995 | case HCISETLINKMODE: | 1272 | case HCISETLINKMODE: |
@@ -1566,7 +1843,7 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | |||
1566 | return mgmt_device_unblocked(hdev, bdaddr, type); | 1843 | return mgmt_device_unblocked(hdev, bdaddr, type); |
1567 | } | 1844 | } |
1568 | 1845 | ||
1569 | static void le_scan_param_req(struct hci_dev *hdev, unsigned long opt) | 1846 | static void le_scan_param_req(struct hci_request *req, unsigned long opt) |
1570 | { | 1847 | { |
1571 | struct le_scan_params *param = (struct le_scan_params *) opt; | 1848 | struct le_scan_params *param = (struct le_scan_params *) opt; |
1572 | struct hci_cp_le_set_scan_param cp; | 1849 | struct hci_cp_le_set_scan_param cp; |
@@ -1576,10 +1853,10 @@ static void le_scan_param_req(struct hci_dev *hdev, unsigned long opt) | |||
1576 | cp.interval = cpu_to_le16(param->interval); | 1853 | cp.interval = cpu_to_le16(param->interval); |
1577 | cp.window = cpu_to_le16(param->window); | 1854 | cp.window = cpu_to_le16(param->window); |
1578 | 1855 | ||
1579 | hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_PARAM, sizeof(cp), &cp); | 1856 | hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(cp), &cp); |
1580 | } | 1857 | } |
1581 | 1858 | ||
1582 | static void le_scan_enable_req(struct hci_dev *hdev, unsigned long opt) | 1859 | static void le_scan_enable_req(struct hci_request *req, unsigned long opt) |
1583 | { | 1860 | { |
1584 | struct hci_cp_le_set_scan_enable cp; | 1861 | struct hci_cp_le_set_scan_enable cp; |
1585 | 1862 | ||
@@ -1587,7 +1864,7 @@ static void le_scan_enable_req(struct hci_dev *hdev, unsigned long opt) | |||
1587 | cp.enable = 1; | 1864 | cp.enable = 1; |
1588 | cp.filter_dup = 1; | 1865 | cp.filter_dup = 1; |
1589 | 1866 | ||
1590 | hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); | 1867 | hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); |
1591 | } | 1868 | } |
1592 | 1869 | ||
1593 | static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval, | 1870 | static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval, |
@@ -1608,10 +1885,10 @@ static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval, | |||
1608 | 1885 | ||
1609 | hci_req_lock(hdev); | 1886 | hci_req_lock(hdev); |
1610 | 1887 | ||
1611 | err = __hci_request(hdev, le_scan_param_req, (unsigned long) ¶m, | 1888 | err = __hci_req_sync(hdev, le_scan_param_req, (unsigned long) ¶m, |
1612 | timeo); | 1889 | timeo); |
1613 | if (!err) | 1890 | if (!err) |
1614 | err = __hci_request(hdev, le_scan_enable_req, 0, timeo); | 1891 | err = __hci_req_sync(hdev, le_scan_enable_req, 0, timeo); |
1615 | 1892 | ||
1616 | hci_req_unlock(hdev); | 1893 | hci_req_unlock(hdev); |
1617 | 1894 | ||
@@ -2160,20 +2437,55 @@ static int hci_send_frame(struct sk_buff *skb) | |||
2160 | return hdev->send(skb); | 2437 | return hdev->send(skb); |
2161 | } | 2438 | } |
2162 | 2439 | ||
2163 | /* Send HCI command */ | 2440 | void hci_req_init(struct hci_request *req, struct hci_dev *hdev) |
2164 | int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param) | 2441 | { |
2442 | skb_queue_head_init(&req->cmd_q); | ||
2443 | req->hdev = hdev; | ||
2444 | req->err = 0; | ||
2445 | } | ||
2446 | |||
2447 | int hci_req_run(struct hci_request *req, hci_req_complete_t complete) | ||
2448 | { | ||
2449 | struct hci_dev *hdev = req->hdev; | ||
2450 | struct sk_buff *skb; | ||
2451 | unsigned long flags; | ||
2452 | |||
2453 | BT_DBG("length %u", skb_queue_len(&req->cmd_q)); | ||
2454 | |||
2455 | /* If an error occured during request building, remove all HCI | ||
2456 | * commands queued on the HCI request queue. | ||
2457 | */ | ||
2458 | if (req->err) { | ||
2459 | skb_queue_purge(&req->cmd_q); | ||
2460 | return req->err; | ||
2461 | } | ||
2462 | |||
2463 | /* Do not allow empty requests */ | ||
2464 | if (skb_queue_empty(&req->cmd_q)) | ||
2465 | return -ENODATA; | ||
2466 | |||
2467 | skb = skb_peek_tail(&req->cmd_q); | ||
2468 | bt_cb(skb)->req.complete = complete; | ||
2469 | |||
2470 | spin_lock_irqsave(&hdev->cmd_q.lock, flags); | ||
2471 | skb_queue_splice_tail(&req->cmd_q, &hdev->cmd_q); | ||
2472 | spin_unlock_irqrestore(&hdev->cmd_q.lock, flags); | ||
2473 | |||
2474 | queue_work(hdev->workqueue, &hdev->cmd_work); | ||
2475 | |||
2476 | return 0; | ||
2477 | } | ||
2478 | |||
2479 | static struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, | ||
2480 | u32 plen, void *param) | ||
2165 | { | 2481 | { |
2166 | int len = HCI_COMMAND_HDR_SIZE + plen; | 2482 | int len = HCI_COMMAND_HDR_SIZE + plen; |
2167 | struct hci_command_hdr *hdr; | 2483 | struct hci_command_hdr *hdr; |
2168 | struct sk_buff *skb; | 2484 | struct sk_buff *skb; |
2169 | 2485 | ||
2170 | BT_DBG("%s opcode 0x%4.4x plen %d", hdev->name, opcode, plen); | ||
2171 | |||
2172 | skb = bt_skb_alloc(len, GFP_ATOMIC); | 2486 | skb = bt_skb_alloc(len, GFP_ATOMIC); |
2173 | if (!skb) { | 2487 | if (!skb) |
2174 | BT_ERR("%s no memory for command", hdev->name); | 2488 | return NULL; |
2175 | return -ENOMEM; | ||
2176 | } | ||
2177 | 2489 | ||
2178 | hdr = (struct hci_command_hdr *) skb_put(skb, HCI_COMMAND_HDR_SIZE); | 2490 | hdr = (struct hci_command_hdr *) skb_put(skb, HCI_COMMAND_HDR_SIZE); |
2179 | hdr->opcode = cpu_to_le16(opcode); | 2491 | hdr->opcode = cpu_to_le16(opcode); |
@@ -2187,8 +2499,26 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param) | |||
2187 | bt_cb(skb)->pkt_type = HCI_COMMAND_PKT; | 2499 | bt_cb(skb)->pkt_type = HCI_COMMAND_PKT; |
2188 | skb->dev = (void *) hdev; | 2500 | skb->dev = (void *) hdev; |
2189 | 2501 | ||
2190 | if (test_bit(HCI_INIT, &hdev->flags)) | 2502 | return skb; |
2191 | hdev->init_last_cmd = opcode; | 2503 | } |
2504 | |||
2505 | /* Send HCI command */ | ||
2506 | int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param) | ||
2507 | { | ||
2508 | struct sk_buff *skb; | ||
2509 | |||
2510 | BT_DBG("%s opcode 0x%4.4x plen %d", hdev->name, opcode, plen); | ||
2511 | |||
2512 | skb = hci_prepare_cmd(hdev, opcode, plen, param); | ||
2513 | if (!skb) { | ||
2514 | BT_ERR("%s no memory for command", hdev->name); | ||
2515 | return -ENOMEM; | ||
2516 | } | ||
2517 | |||
2518 | /* Stand-alone HCI commands must be flaged as | ||
2519 | * single-command requests. | ||
2520 | */ | ||
2521 | bt_cb(skb)->req.start = true; | ||
2192 | 2522 | ||
2193 | skb_queue_tail(&hdev->cmd_q, skb); | 2523 | skb_queue_tail(&hdev->cmd_q, skb); |
2194 | queue_work(hdev->workqueue, &hdev->cmd_work); | 2524 | queue_work(hdev->workqueue, &hdev->cmd_work); |
@@ -2196,6 +2526,34 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param) | |||
2196 | return 0; | 2526 | return 0; |
2197 | } | 2527 | } |
2198 | 2528 | ||
2529 | /* Queue a command to an asynchronous HCI request */ | ||
2530 | void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param) | ||
2531 | { | ||
2532 | struct hci_dev *hdev = req->hdev; | ||
2533 | struct sk_buff *skb; | ||
2534 | |||
2535 | BT_DBG("%s opcode 0x%4.4x plen %d", hdev->name, opcode, plen); | ||
2536 | |||
2537 | /* If an error occured during request building, there is no point in | ||
2538 | * queueing the HCI command. We can simply return. | ||
2539 | */ | ||
2540 | if (req->err) | ||
2541 | return; | ||
2542 | |||
2543 | skb = hci_prepare_cmd(hdev, opcode, plen, param); | ||
2544 | if (!skb) { | ||
2545 | BT_ERR("%s no memory for command (opcode 0x%4.4x)", | ||
2546 | hdev->name, opcode); | ||
2547 | req->err = -ENOMEM; | ||
2548 | return; | ||
2549 | } | ||
2550 | |||
2551 | if (skb_queue_empty(&req->cmd_q)) | ||
2552 | bt_cb(skb)->req.start = true; | ||
2553 | |||
2554 | skb_queue_tail(&req->cmd_q, skb); | ||
2555 | } | ||
2556 | |||
2199 | /* Get data from the previously sent command */ | 2557 | /* Get data from the previously sent command */ |
2200 | void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode) | 2558 | void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode) |
2201 | { | 2559 | { |
@@ -2398,7 +2756,7 @@ static void hci_link_tx_to(struct hci_dev *hdev, __u8 type) | |||
2398 | if (c->type == type && c->sent) { | 2756 | if (c->type == type && c->sent) { |
2399 | BT_ERR("%s killing stalled connection %pMR", | 2757 | BT_ERR("%s killing stalled connection %pMR", |
2400 | hdev->name, &c->dst); | 2758 | hdev->name, &c->dst); |
2401 | hci_acl_disconn(c, HCI_ERROR_REMOTE_USER_TERM); | 2759 | hci_disconnect(c, HCI_ERROR_REMOTE_USER_TERM); |
2402 | } | 2760 | } |
2403 | } | 2761 | } |
2404 | 2762 | ||
@@ -2860,6 +3218,123 @@ static void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
2860 | kfree_skb(skb); | 3218 | kfree_skb(skb); |
2861 | } | 3219 | } |
2862 | 3220 | ||
3221 | static bool hci_req_is_complete(struct hci_dev *hdev) | ||
3222 | { | ||
3223 | struct sk_buff *skb; | ||
3224 | |||
3225 | skb = skb_peek(&hdev->cmd_q); | ||
3226 | if (!skb) | ||
3227 | return true; | ||
3228 | |||
3229 | return bt_cb(skb)->req.start; | ||
3230 | } | ||
3231 | |||
3232 | static void hci_resend_last(struct hci_dev *hdev) | ||
3233 | { | ||
3234 | struct hci_command_hdr *sent; | ||
3235 | struct sk_buff *skb; | ||
3236 | u16 opcode; | ||
3237 | |||
3238 | if (!hdev->sent_cmd) | ||
3239 | return; | ||
3240 | |||
3241 | sent = (void *) hdev->sent_cmd->data; | ||
3242 | opcode = __le16_to_cpu(sent->opcode); | ||
3243 | if (opcode == HCI_OP_RESET) | ||
3244 | return; | ||
3245 | |||
3246 | skb = skb_clone(hdev->sent_cmd, GFP_KERNEL); | ||
3247 | if (!skb) | ||
3248 | return; | ||
3249 | |||
3250 | skb_queue_head(&hdev->cmd_q, skb); | ||
3251 | queue_work(hdev->workqueue, &hdev->cmd_work); | ||
3252 | } | ||
3253 | |||
3254 | void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status) | ||
3255 | { | ||
3256 | hci_req_complete_t req_complete = NULL; | ||
3257 | struct sk_buff *skb; | ||
3258 | unsigned long flags; | ||
3259 | |||
3260 | BT_DBG("opcode 0x%04x status 0x%02x", opcode, status); | ||
3261 | |||
3262 | /* If the completed command doesn't match the last one that was | ||
3263 | * sent we need to do special handling of it. | ||
3264 | */ | ||
3265 | if (!hci_sent_cmd_data(hdev, opcode)) { | ||
3266 | /* Some CSR based controllers generate a spontaneous | ||
3267 | * reset complete event during init and any pending | ||
3268 | * command will never be completed. In such a case we | ||
3269 | * need to resend whatever was the last sent | ||
3270 | * command. | ||
3271 | */ | ||
3272 | if (test_bit(HCI_INIT, &hdev->flags) && opcode == HCI_OP_RESET) | ||
3273 | hci_resend_last(hdev); | ||
3274 | |||
3275 | return; | ||
3276 | } | ||
3277 | |||
3278 | /* If the command succeeded and there's still more commands in | ||
3279 | * this request the request is not yet complete. | ||
3280 | */ | ||
3281 | if (!status && !hci_req_is_complete(hdev)) | ||
3282 | return; | ||
3283 | |||
3284 | /* If this was the last command in a request the complete | ||
3285 | * callback would be found in hdev->sent_cmd instead of the | ||
3286 | * command queue (hdev->cmd_q). | ||
3287 | */ | ||
3288 | if (hdev->sent_cmd) { | ||
3289 | req_complete = bt_cb(hdev->sent_cmd)->req.complete; | ||
3290 | if (req_complete) | ||
3291 | goto call_complete; | ||
3292 | } | ||
3293 | |||
3294 | /* Remove all pending commands belonging to this request */ | ||
3295 | spin_lock_irqsave(&hdev->cmd_q.lock, flags); | ||
3296 | while ((skb = __skb_dequeue(&hdev->cmd_q))) { | ||
3297 | if (bt_cb(skb)->req.start) { | ||
3298 | __skb_queue_head(&hdev->cmd_q, skb); | ||
3299 | break; | ||
3300 | } | ||
3301 | |||
3302 | req_complete = bt_cb(skb)->req.complete; | ||
3303 | kfree_skb(skb); | ||
3304 | } | ||
3305 | spin_unlock_irqrestore(&hdev->cmd_q.lock, flags); | ||
3306 | |||
3307 | call_complete: | ||
3308 | if (req_complete) | ||
3309 | req_complete(hdev, status); | ||
3310 | } | ||
3311 | |||
3312 | void hci_req_cmd_status(struct hci_dev *hdev, u16 opcode, u8 status) | ||
3313 | { | ||
3314 | hci_req_complete_t req_complete = NULL; | ||
3315 | |||
3316 | BT_DBG("opcode 0x%04x status 0x%02x", opcode, status); | ||
3317 | |||
3318 | if (status) { | ||
3319 | hci_req_cmd_complete(hdev, opcode, status); | ||
3320 | return; | ||
3321 | } | ||
3322 | |||
3323 | /* No need to handle success status if there are more commands */ | ||
3324 | if (!hci_req_is_complete(hdev)) | ||
3325 | return; | ||
3326 | |||
3327 | if (hdev->sent_cmd) | ||
3328 | req_complete = bt_cb(hdev->sent_cmd)->req.complete; | ||
3329 | |||
3330 | /* If the request doesn't have a complete callback or there | ||
3331 | * are other commands/requests in the hdev queue we consider | ||
3332 | * this request as completed. | ||
3333 | */ | ||
3334 | if (!req_complete || !skb_queue_empty(&hdev->cmd_q)) | ||
3335 | hci_req_cmd_complete(hdev, opcode, status); | ||
3336 | } | ||
3337 | |||
2863 | static void hci_rx_work(struct work_struct *work) | 3338 | static void hci_rx_work(struct work_struct *work) |
2864 | { | 3339 | { |
2865 | struct hci_dev *hdev = container_of(work, struct hci_dev, rx_work); | 3340 | struct hci_dev *hdev = container_of(work, struct hci_dev, rx_work); |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 477726a63512..138580745c2c 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -53,7 +53,7 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) | |||
53 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | 53 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); |
54 | hci_dev_unlock(hdev); | 54 | hci_dev_unlock(hdev); |
55 | 55 | ||
56 | hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status); | 56 | hci_req_cmd_complete(hdev, HCI_OP_INQUIRY, status); |
57 | 57 | ||
58 | hci_conn_check_pending(hdev); | 58 | hci_conn_check_pending(hdev); |
59 | } | 59 | } |
@@ -183,8 +183,6 @@ static void hci_cc_write_def_link_policy(struct hci_dev *hdev, | |||
183 | 183 | ||
184 | if (!status) | 184 | if (!status) |
185 | hdev->link_policy = get_unaligned_le16(sent); | 185 | hdev->link_policy = get_unaligned_le16(sent); |
186 | |||
187 | hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status); | ||
188 | } | 186 | } |
189 | 187 | ||
190 | static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) | 188 | static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -195,11 +193,8 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) | |||
195 | 193 | ||
196 | clear_bit(HCI_RESET, &hdev->flags); | 194 | clear_bit(HCI_RESET, &hdev->flags); |
197 | 195 | ||
198 | hci_req_complete(hdev, HCI_OP_RESET, status); | ||
199 | |||
200 | /* Reset all non-persistent flags */ | 196 | /* Reset all non-persistent flags */ |
201 | hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS) | | 197 | hdev->dev_flags &= ~HCI_PERSISTENT_MASK; |
202 | BIT(HCI_PERIODIC_INQ)); | ||
203 | 198 | ||
204 | hdev->discovery.state = DISCOVERY_STOPPED; | 199 | hdev->discovery.state = DISCOVERY_STOPPED; |
205 | hdev->inq_tx_power = HCI_TX_POWER_INVALID; | 200 | hdev->inq_tx_power = HCI_TX_POWER_INVALID; |
@@ -228,11 +223,6 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) | |||
228 | memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); | 223 | memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); |
229 | 224 | ||
230 | hci_dev_unlock(hdev); | 225 | hci_dev_unlock(hdev); |
231 | |||
232 | if (!status && !test_bit(HCI_INIT, &hdev->flags)) | ||
233 | hci_update_ad(hdev); | ||
234 | |||
235 | hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status); | ||
236 | } | 226 | } |
237 | 227 | ||
238 | static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) | 228 | static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -270,8 +260,6 @@ static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) | |||
270 | 260 | ||
271 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) | 261 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) |
272 | mgmt_auth_enable_complete(hdev, status); | 262 | mgmt_auth_enable_complete(hdev, status); |
273 | |||
274 | hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status); | ||
275 | } | 263 | } |
276 | 264 | ||
277 | static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) | 265 | static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -293,8 +281,6 @@ static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) | |||
293 | else | 281 | else |
294 | clear_bit(HCI_ENCRYPT, &hdev->flags); | 282 | clear_bit(HCI_ENCRYPT, &hdev->flags); |
295 | } | 283 | } |
296 | |||
297 | hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status); | ||
298 | } | 284 | } |
299 | 285 | ||
300 | static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) | 286 | static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -343,7 +329,6 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) | |||
343 | 329 | ||
344 | done: | 330 | done: |
345 | hci_dev_unlock(hdev); | 331 | hci_dev_unlock(hdev); |
346 | hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status); | ||
347 | } | 332 | } |
348 | 333 | ||
349 | static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) | 334 | static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -435,15 +420,6 @@ static void hci_cc_write_voice_setting(struct hci_dev *hdev, | |||
435 | hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); | 420 | hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); |
436 | } | 421 | } |
437 | 422 | ||
438 | static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) | ||
439 | { | ||
440 | __u8 status = *((__u8 *) skb->data); | ||
441 | |||
442 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
443 | |||
444 | hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status); | ||
445 | } | ||
446 | |||
447 | static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) | 423 | static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) |
448 | { | 424 | { |
449 | __u8 status = *((__u8 *) skb->data); | 425 | __u8 status = *((__u8 *) skb->data); |
@@ -472,211 +448,6 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) | |||
472 | } | 448 | } |
473 | } | 449 | } |
474 | 450 | ||
475 | static u8 hci_get_inquiry_mode(struct hci_dev *hdev) | ||
476 | { | ||
477 | if (lmp_ext_inq_capable(hdev)) | ||
478 | return 2; | ||
479 | |||
480 | if (lmp_inq_rssi_capable(hdev)) | ||
481 | return 1; | ||
482 | |||
483 | if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && | ||
484 | hdev->lmp_subver == 0x0757) | ||
485 | return 1; | ||
486 | |||
487 | if (hdev->manufacturer == 15) { | ||
488 | if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963) | ||
489 | return 1; | ||
490 | if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963) | ||
491 | return 1; | ||
492 | if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965) | ||
493 | return 1; | ||
494 | } | ||
495 | |||
496 | if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 && | ||
497 | hdev->lmp_subver == 0x1805) | ||
498 | return 1; | ||
499 | |||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | static void hci_setup_inquiry_mode(struct hci_dev *hdev) | ||
504 | { | ||
505 | u8 mode; | ||
506 | |||
507 | mode = hci_get_inquiry_mode(hdev); | ||
508 | |||
509 | hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode); | ||
510 | } | ||
511 | |||
512 | static void hci_setup_event_mask(struct hci_dev *hdev) | ||
513 | { | ||
514 | /* The second byte is 0xff instead of 0x9f (two reserved bits | ||
515 | * disabled) since a Broadcom 1.2 dongle doesn't respond to the | ||
516 | * command otherwise */ | ||
517 | u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; | ||
518 | |||
519 | /* CSR 1.1 dongles does not accept any bitfield so don't try to set | ||
520 | * any event mask for pre 1.2 devices */ | ||
521 | if (hdev->hci_ver < BLUETOOTH_VER_1_2) | ||
522 | return; | ||
523 | |||
524 | if (lmp_bredr_capable(hdev)) { | ||
525 | events[4] |= 0x01; /* Flow Specification Complete */ | ||
526 | events[4] |= 0x02; /* Inquiry Result with RSSI */ | ||
527 | events[4] |= 0x04; /* Read Remote Extended Features Complete */ | ||
528 | events[5] |= 0x08; /* Synchronous Connection Complete */ | ||
529 | events[5] |= 0x10; /* Synchronous Connection Changed */ | ||
530 | } | ||
531 | |||
532 | if (lmp_inq_rssi_capable(hdev)) | ||
533 | events[4] |= 0x02; /* Inquiry Result with RSSI */ | ||
534 | |||
535 | if (lmp_sniffsubr_capable(hdev)) | ||
536 | events[5] |= 0x20; /* Sniff Subrating */ | ||
537 | |||
538 | if (lmp_pause_enc_capable(hdev)) | ||
539 | events[5] |= 0x80; /* Encryption Key Refresh Complete */ | ||
540 | |||
541 | if (lmp_ext_inq_capable(hdev)) | ||
542 | events[5] |= 0x40; /* Extended Inquiry Result */ | ||
543 | |||
544 | if (lmp_no_flush_capable(hdev)) | ||
545 | events[7] |= 0x01; /* Enhanced Flush Complete */ | ||
546 | |||
547 | if (lmp_lsto_capable(hdev)) | ||
548 | events[6] |= 0x80; /* Link Supervision Timeout Changed */ | ||
549 | |||
550 | if (lmp_ssp_capable(hdev)) { | ||
551 | events[6] |= 0x01; /* IO Capability Request */ | ||
552 | events[6] |= 0x02; /* IO Capability Response */ | ||
553 | events[6] |= 0x04; /* User Confirmation Request */ | ||
554 | events[6] |= 0x08; /* User Passkey Request */ | ||
555 | events[6] |= 0x10; /* Remote OOB Data Request */ | ||
556 | events[6] |= 0x20; /* Simple Pairing Complete */ | ||
557 | events[7] |= 0x04; /* User Passkey Notification */ | ||
558 | events[7] |= 0x08; /* Keypress Notification */ | ||
559 | events[7] |= 0x10; /* Remote Host Supported | ||
560 | * Features Notification */ | ||
561 | } | ||
562 | |||
563 | if (lmp_le_capable(hdev)) | ||
564 | events[7] |= 0x20; /* LE Meta-Event */ | ||
565 | |||
566 | hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); | ||
567 | |||
568 | if (lmp_le_capable(hdev)) { | ||
569 | memset(events, 0, sizeof(events)); | ||
570 | events[0] = 0x1f; | ||
571 | hci_send_cmd(hdev, HCI_OP_LE_SET_EVENT_MASK, | ||
572 | sizeof(events), events); | ||
573 | } | ||
574 | } | ||
575 | |||
576 | static void bredr_setup(struct hci_dev *hdev) | ||
577 | { | ||
578 | struct hci_cp_delete_stored_link_key cp; | ||
579 | __le16 param; | ||
580 | __u8 flt_type; | ||
581 | |||
582 | /* Read Buffer Size (ACL mtu, max pkt, etc.) */ | ||
583 | hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL); | ||
584 | |||
585 | /* Read Class of Device */ | ||
586 | hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL); | ||
587 | |||
588 | /* Read Local Name */ | ||
589 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL); | ||
590 | |||
591 | /* Read Voice Setting */ | ||
592 | hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL); | ||
593 | |||
594 | /* Clear Event Filters */ | ||
595 | flt_type = HCI_FLT_CLEAR_ALL; | ||
596 | hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type); | ||
597 | |||
598 | /* Connection accept timeout ~20 secs */ | ||
599 | param = __constant_cpu_to_le16(0x7d00); | ||
600 | hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); | ||
601 | |||
602 | bacpy(&cp.bdaddr, BDADDR_ANY); | ||
603 | cp.delete_all = 1; | ||
604 | hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp); | ||
605 | } | ||
606 | |||
607 | static void le_setup(struct hci_dev *hdev) | ||
608 | { | ||
609 | /* Read LE Buffer Size */ | ||
610 | hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL); | ||
611 | |||
612 | /* Read LE Local Supported Features */ | ||
613 | hci_send_cmd(hdev, HCI_OP_LE_READ_LOCAL_FEATURES, 0, NULL); | ||
614 | |||
615 | /* Read LE Advertising Channel TX Power */ | ||
616 | hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL); | ||
617 | |||
618 | /* Read LE White List Size */ | ||
619 | hci_send_cmd(hdev, HCI_OP_LE_READ_WHITE_LIST_SIZE, 0, NULL); | ||
620 | |||
621 | /* Read LE Supported States */ | ||
622 | hci_send_cmd(hdev, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL); | ||
623 | } | ||
624 | |||
625 | static void hci_setup(struct hci_dev *hdev) | ||
626 | { | ||
627 | if (hdev->dev_type != HCI_BREDR) | ||
628 | return; | ||
629 | |||
630 | /* Read BD Address */ | ||
631 | hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL); | ||
632 | |||
633 | if (lmp_bredr_capable(hdev)) | ||
634 | bredr_setup(hdev); | ||
635 | |||
636 | if (lmp_le_capable(hdev)) | ||
637 | le_setup(hdev); | ||
638 | |||
639 | hci_setup_event_mask(hdev); | ||
640 | |||
641 | if (hdev->hci_ver > BLUETOOTH_VER_1_1) | ||
642 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); | ||
643 | |||
644 | if (lmp_ssp_capable(hdev)) { | ||
645 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { | ||
646 | u8 mode = 0x01; | ||
647 | hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, | ||
648 | sizeof(mode), &mode); | ||
649 | } else { | ||
650 | struct hci_cp_write_eir cp; | ||
651 | |||
652 | memset(hdev->eir, 0, sizeof(hdev->eir)); | ||
653 | memset(&cp, 0, sizeof(cp)); | ||
654 | |||
655 | hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp); | ||
656 | } | ||
657 | } | ||
658 | |||
659 | if (lmp_inq_rssi_capable(hdev)) | ||
660 | hci_setup_inquiry_mode(hdev); | ||
661 | |||
662 | if (lmp_inq_tx_pwr_capable(hdev)) | ||
663 | hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); | ||
664 | |||
665 | if (lmp_ext_feat_capable(hdev)) { | ||
666 | struct hci_cp_read_local_ext_features cp; | ||
667 | |||
668 | cp.page = 0x01; | ||
669 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), | ||
670 | &cp); | ||
671 | } | ||
672 | |||
673 | if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) { | ||
674 | u8 enable = 1; | ||
675 | hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable), | ||
676 | &enable); | ||
677 | } | ||
678 | } | ||
679 | |||
680 | static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) | 451 | static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) |
681 | { | 452 | { |
682 | struct hci_rp_read_local_version *rp = (void *) skb->data; | 453 | struct hci_rp_read_local_version *rp = (void *) skb->data; |
@@ -684,7 +455,7 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) | |||
684 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | 455 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); |
685 | 456 | ||
686 | if (rp->status) | 457 | if (rp->status) |
687 | goto done; | 458 | return; |
688 | 459 | ||
689 | hdev->hci_ver = rp->hci_ver; | 460 | hdev->hci_ver = rp->hci_ver; |
690 | hdev->hci_rev = __le16_to_cpu(rp->hci_rev); | 461 | hdev->hci_rev = __le16_to_cpu(rp->hci_rev); |
@@ -694,30 +465,6 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) | |||
694 | 465 | ||
695 | BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name, | 466 | BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name, |
696 | hdev->manufacturer, hdev->hci_ver, hdev->hci_rev); | 467 | hdev->manufacturer, hdev->hci_ver, hdev->hci_rev); |
697 | |||
698 | if (test_bit(HCI_INIT, &hdev->flags)) | ||
699 | hci_setup(hdev); | ||
700 | |||
701 | done: | ||
702 | hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status); | ||
703 | } | ||
704 | |||
705 | static void hci_setup_link_policy(struct hci_dev *hdev) | ||
706 | { | ||
707 | struct hci_cp_write_def_link_policy cp; | ||
708 | u16 link_policy = 0; | ||
709 | |||
710 | if (lmp_rswitch_capable(hdev)) | ||
711 | link_policy |= HCI_LP_RSWITCH; | ||
712 | if (lmp_hold_capable(hdev)) | ||
713 | link_policy |= HCI_LP_HOLD; | ||
714 | if (lmp_sniff_capable(hdev)) | ||
715 | link_policy |= HCI_LP_SNIFF; | ||
716 | if (lmp_park_capable(hdev)) | ||
717 | link_policy |= HCI_LP_PARK; | ||
718 | |||
719 | cp.policy = cpu_to_le16(link_policy); | ||
720 | hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp); | ||
721 | } | 468 | } |
722 | 469 | ||
723 | static void hci_cc_read_local_commands(struct hci_dev *hdev, | 470 | static void hci_cc_read_local_commands(struct hci_dev *hdev, |
@@ -727,16 +474,8 @@ static void hci_cc_read_local_commands(struct hci_dev *hdev, | |||
727 | 474 | ||
728 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | 475 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); |
729 | 476 | ||
730 | if (rp->status) | 477 | if (!rp->status) |
731 | goto done; | 478 | memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); |
732 | |||
733 | memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); | ||
734 | |||
735 | if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10)) | ||
736 | hci_setup_link_policy(hdev); | ||
737 | |||
738 | done: | ||
739 | hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status); | ||
740 | } | 479 | } |
741 | 480 | ||
742 | static void hci_cc_read_local_features(struct hci_dev *hdev, | 481 | static void hci_cc_read_local_features(struct hci_dev *hdev, |
@@ -795,22 +534,6 @@ static void hci_cc_read_local_features(struct hci_dev *hdev, | |||
795 | hdev->features[6], hdev->features[7]); | 534 | hdev->features[6], hdev->features[7]); |
796 | } | 535 | } |
797 | 536 | ||
798 | static void hci_set_le_support(struct hci_dev *hdev) | ||
799 | { | ||
800 | struct hci_cp_write_le_host_supported cp; | ||
801 | |||
802 | memset(&cp, 0, sizeof(cp)); | ||
803 | |||
804 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { | ||
805 | cp.le = 1; | ||
806 | cp.simul = lmp_le_br_capable(hdev); | ||
807 | } | ||
808 | |||
809 | if (cp.le != lmp_host_le_capable(hdev)) | ||
810 | hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), | ||
811 | &cp); | ||
812 | } | ||
813 | |||
814 | static void hci_cc_read_local_ext_features(struct hci_dev *hdev, | 537 | static void hci_cc_read_local_ext_features(struct hci_dev *hdev, |
815 | struct sk_buff *skb) | 538 | struct sk_buff *skb) |
816 | { | 539 | { |
@@ -819,7 +542,7 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev, | |||
819 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | 542 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); |
820 | 543 | ||
821 | if (rp->status) | 544 | if (rp->status) |
822 | goto done; | 545 | return; |
823 | 546 | ||
824 | switch (rp->page) { | 547 | switch (rp->page) { |
825 | case 0: | 548 | case 0: |
@@ -829,12 +552,6 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev, | |||
829 | memcpy(hdev->host_features, rp->features, 8); | 552 | memcpy(hdev->host_features, rp->features, 8); |
830 | break; | 553 | break; |
831 | } | 554 | } |
832 | |||
833 | if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev)) | ||
834 | hci_set_le_support(hdev); | ||
835 | |||
836 | done: | ||
837 | hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); | ||
838 | } | 555 | } |
839 | 556 | ||
840 | static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, | 557 | static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, |
@@ -844,12 +561,8 @@ static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, | |||
844 | 561 | ||
845 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | 562 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); |
846 | 563 | ||
847 | if (rp->status) | 564 | if (!rp->status) |
848 | return; | 565 | hdev->flow_ctl_mode = rp->mode; |
849 | |||
850 | hdev->flow_ctl_mode = rp->mode; | ||
851 | |||
852 | hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status); | ||
853 | } | 566 | } |
854 | 567 | ||
855 | static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) | 568 | static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -886,8 +599,65 @@ static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) | |||
886 | 599 | ||
887 | if (!rp->status) | 600 | if (!rp->status) |
888 | bacpy(&hdev->bdaddr, &rp->bdaddr); | 601 | bacpy(&hdev->bdaddr, &rp->bdaddr); |
602 | } | ||
603 | |||
604 | static void hci_cc_read_page_scan_activity(struct hci_dev *hdev, | ||
605 | struct sk_buff *skb) | ||
606 | { | ||
607 | struct hci_rp_read_page_scan_activity *rp = (void *) skb->data; | ||
608 | |||
609 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | ||
610 | |||
611 | if (test_bit(HCI_INIT, &hdev->flags) && !rp->status) { | ||
612 | hdev->page_scan_interval = __le16_to_cpu(rp->interval); | ||
613 | hdev->page_scan_window = __le16_to_cpu(rp->window); | ||
614 | } | ||
615 | } | ||
616 | |||
617 | static void hci_cc_write_page_scan_activity(struct hci_dev *hdev, | ||
618 | struct sk_buff *skb) | ||
619 | { | ||
620 | u8 status = *((u8 *) skb->data); | ||
621 | struct hci_cp_write_page_scan_activity *sent; | ||
622 | |||
623 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
624 | |||
625 | if (status) | ||
626 | return; | ||
627 | |||
628 | sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY); | ||
629 | if (!sent) | ||
630 | return; | ||
631 | |||
632 | hdev->page_scan_interval = __le16_to_cpu(sent->interval); | ||
633 | hdev->page_scan_window = __le16_to_cpu(sent->window); | ||
634 | } | ||
635 | |||
636 | static void hci_cc_read_page_scan_type(struct hci_dev *hdev, | ||
637 | struct sk_buff *skb) | ||
638 | { | ||
639 | struct hci_rp_read_page_scan_type *rp = (void *) skb->data; | ||
640 | |||
641 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | ||
642 | |||
643 | if (test_bit(HCI_INIT, &hdev->flags) && !rp->status) | ||
644 | hdev->page_scan_type = rp->type; | ||
645 | } | ||
646 | |||
647 | static void hci_cc_write_page_scan_type(struct hci_dev *hdev, | ||
648 | struct sk_buff *skb) | ||
649 | { | ||
650 | u8 status = *((u8 *) skb->data); | ||
651 | u8 *type; | ||
889 | 652 | ||
890 | hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); | 653 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
654 | |||
655 | if (status) | ||
656 | return; | ||
657 | |||
658 | type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE); | ||
659 | if (type) | ||
660 | hdev->page_scan_type = *type; | ||
891 | } | 661 | } |
892 | 662 | ||
893 | static void hci_cc_read_data_block_size(struct hci_dev *hdev, | 663 | static void hci_cc_read_data_block_size(struct hci_dev *hdev, |
@@ -908,17 +678,6 @@ static void hci_cc_read_data_block_size(struct hci_dev *hdev, | |||
908 | 678 | ||
909 | BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, | 679 | BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, |
910 | hdev->block_cnt, hdev->block_len); | 680 | hdev->block_cnt, hdev->block_len); |
911 | |||
912 | hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status); | ||
913 | } | ||
914 | |||
915 | static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) | ||
916 | { | ||
917 | __u8 status = *((__u8 *) skb->data); | ||
918 | |||
919 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
920 | |||
921 | hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status); | ||
922 | } | 681 | } |
923 | 682 | ||
924 | static void hci_cc_read_local_amp_info(struct hci_dev *hdev, | 683 | static void hci_cc_read_local_amp_info(struct hci_dev *hdev, |
@@ -942,8 +701,6 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev, | |||
942 | hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); | 701 | hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); |
943 | hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); | 702 | hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); |
944 | 703 | ||
945 | hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status); | ||
946 | |||
947 | a2mp_rsp: | 704 | a2mp_rsp: |
948 | a2mp_send_getinfo_rsp(hdev); | 705 | a2mp_send_getinfo_rsp(hdev); |
949 | } | 706 | } |
@@ -985,35 +742,6 @@ a2mp_rsp: | |||
985 | a2mp_send_create_phy_link_req(hdev, rp->status); | 742 | a2mp_send_create_phy_link_req(hdev, rp->status); |
986 | } | 743 | } |
987 | 744 | ||
988 | static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, | ||
989 | struct sk_buff *skb) | ||
990 | { | ||
991 | __u8 status = *((__u8 *) skb->data); | ||
992 | |||
993 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
994 | |||
995 | hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status); | ||
996 | } | ||
997 | |||
998 | static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) | ||
999 | { | ||
1000 | __u8 status = *((__u8 *) skb->data); | ||
1001 | |||
1002 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
1003 | |||
1004 | hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status); | ||
1005 | } | ||
1006 | |||
1007 | static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, | ||
1008 | struct sk_buff *skb) | ||
1009 | { | ||
1010 | __u8 status = *((__u8 *) skb->data); | ||
1011 | |||
1012 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
1013 | |||
1014 | hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status); | ||
1015 | } | ||
1016 | |||
1017 | static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, | 745 | static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, |
1018 | struct sk_buff *skb) | 746 | struct sk_buff *skb) |
1019 | { | 747 | { |
@@ -1023,17 +751,6 @@ static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, | |||
1023 | 751 | ||
1024 | if (!rp->status) | 752 | if (!rp->status) |
1025 | hdev->inq_tx_power = rp->tx_power; | 753 | hdev->inq_tx_power = rp->tx_power; |
1026 | |||
1027 | hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status); | ||
1028 | } | ||
1029 | |||
1030 | static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb) | ||
1031 | { | ||
1032 | __u8 status = *((__u8 *) skb->data); | ||
1033 | |||
1034 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
1035 | |||
1036 | hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status); | ||
1037 | } | 754 | } |
1038 | 755 | ||
1039 | static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) | 756 | static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -1095,8 +812,6 @@ static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, | |||
1095 | hdev->le_cnt = hdev->le_pkts; | 812 | hdev->le_cnt = hdev->le_pkts; |
1096 | 813 | ||
1097 | BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); | 814 | BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); |
1098 | |||
1099 | hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); | ||
1100 | } | 815 | } |
1101 | 816 | ||
1102 | static void hci_cc_le_read_local_features(struct hci_dev *hdev, | 817 | static void hci_cc_le_read_local_features(struct hci_dev *hdev, |
@@ -1108,8 +823,6 @@ static void hci_cc_le_read_local_features(struct hci_dev *hdev, | |||
1108 | 823 | ||
1109 | if (!rp->status) | 824 | if (!rp->status) |
1110 | memcpy(hdev->le_features, rp->features, 8); | 825 | memcpy(hdev->le_features, rp->features, 8); |
1111 | |||
1112 | hci_req_complete(hdev, HCI_OP_LE_READ_LOCAL_FEATURES, rp->status); | ||
1113 | } | 826 | } |
1114 | 827 | ||
1115 | static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, | 828 | static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, |
@@ -1119,22 +832,8 @@ static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, | |||
1119 | 832 | ||
1120 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | 833 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); |
1121 | 834 | ||
1122 | if (!rp->status) { | 835 | if (!rp->status) |
1123 | hdev->adv_tx_power = rp->tx_power; | 836 | hdev->adv_tx_power = rp->tx_power; |
1124 | if (!test_bit(HCI_INIT, &hdev->flags)) | ||
1125 | hci_update_ad(hdev); | ||
1126 | } | ||
1127 | |||
1128 | hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status); | ||
1129 | } | ||
1130 | |||
1131 | static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) | ||
1132 | { | ||
1133 | __u8 status = *((__u8 *) skb->data); | ||
1134 | |||
1135 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
1136 | |||
1137 | hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status); | ||
1138 | } | 837 | } |
1139 | 838 | ||
1140 | static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) | 839 | static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -1231,12 +930,15 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) | |||
1231 | clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); | 930 | clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); |
1232 | } | 931 | } |
1233 | 932 | ||
1234 | hci_dev_unlock(hdev); | 933 | if (!test_bit(HCI_INIT, &hdev->flags)) { |
934 | struct hci_request req; | ||
1235 | 935 | ||
1236 | if (!test_bit(HCI_INIT, &hdev->flags)) | 936 | hci_req_init(&req, hdev); |
1237 | hci_update_ad(hdev); | 937 | hci_update_ad(&req); |
938 | hci_req_run(&req, NULL); | ||
939 | } | ||
1238 | 940 | ||
1239 | hci_req_complete(hdev, HCI_OP_LE_SET_ADV_ENABLE, status); | 941 | hci_dev_unlock(hdev); |
1240 | } | 942 | } |
1241 | 943 | ||
1242 | static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) | 944 | static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -1245,8 +947,6 @@ static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) | |||
1245 | 947 | ||
1246 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 948 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
1247 | 949 | ||
1248 | hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status); | ||
1249 | |||
1250 | if (status) { | 950 | if (status) { |
1251 | hci_dev_lock(hdev); | 951 | hci_dev_lock(hdev); |
1252 | mgmt_start_discovery_failed(hdev, status); | 952 | mgmt_start_discovery_failed(hdev, status); |
@@ -1269,8 +969,6 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, | |||
1269 | 969 | ||
1270 | switch (cp->enable) { | 970 | switch (cp->enable) { |
1271 | case LE_SCANNING_ENABLED: | 971 | case LE_SCANNING_ENABLED: |
1272 | hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status); | ||
1273 | |||
1274 | if (status) { | 972 | if (status) { |
1275 | hci_dev_lock(hdev); | 973 | hci_dev_lock(hdev); |
1276 | mgmt_start_discovery_failed(hdev, status); | 974 | mgmt_start_discovery_failed(hdev, status); |
@@ -1321,32 +1019,6 @@ static void hci_cc_le_read_white_list_size(struct hci_dev *hdev, | |||
1321 | 1019 | ||
1322 | if (!rp->status) | 1020 | if (!rp->status) |
1323 | hdev->le_white_list_size = rp->size; | 1021 | hdev->le_white_list_size = rp->size; |
1324 | |||
1325 | hci_req_complete(hdev, HCI_OP_LE_READ_WHITE_LIST_SIZE, rp->status); | ||
1326 | } | ||
1327 | |||
1328 | static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) | ||
1329 | { | ||
1330 | struct hci_rp_le_ltk_reply *rp = (void *) skb->data; | ||
1331 | |||
1332 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | ||
1333 | |||
1334 | if (rp->status) | ||
1335 | return; | ||
1336 | |||
1337 | hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status); | ||
1338 | } | ||
1339 | |||
1340 | static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) | ||
1341 | { | ||
1342 | struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data; | ||
1343 | |||
1344 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | ||
1345 | |||
1346 | if (rp->status) | ||
1347 | return; | ||
1348 | |||
1349 | hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); | ||
1350 | } | 1022 | } |
1351 | 1023 | ||
1352 | static void hci_cc_le_read_supported_states(struct hci_dev *hdev, | 1024 | static void hci_cc_le_read_supported_states(struct hci_dev *hdev, |
@@ -1358,8 +1030,6 @@ static void hci_cc_le_read_supported_states(struct hci_dev *hdev, | |||
1358 | 1030 | ||
1359 | if (!rp->status) | 1031 | if (!rp->status) |
1360 | memcpy(hdev->le_states, rp->le_states, 8); | 1032 | memcpy(hdev->le_states, rp->le_states, 8); |
1361 | |||
1362 | hci_req_complete(hdev, HCI_OP_LE_READ_SUPPORTED_STATES, rp->status); | ||
1363 | } | 1033 | } |
1364 | 1034 | ||
1365 | static void hci_cc_write_le_host_supported(struct hci_dev *hdev, | 1035 | static void hci_cc_write_le_host_supported(struct hci_dev *hdev, |
@@ -1389,8 +1059,6 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev, | |||
1389 | if (test_bit(HCI_MGMT, &hdev->dev_flags) && | 1059 | if (test_bit(HCI_MGMT, &hdev->dev_flags) && |
1390 | !test_bit(HCI_INIT, &hdev->flags)) | 1060 | !test_bit(HCI_INIT, &hdev->flags)) |
1391 | mgmt_le_enable_complete(hdev, sent->le, status); | 1061 | mgmt_le_enable_complete(hdev, sent->le, status); |
1392 | |||
1393 | hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status); | ||
1394 | } | 1062 | } |
1395 | 1063 | ||
1396 | static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev, | 1064 | static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev, |
@@ -1412,7 +1080,6 @@ static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) | |||
1412 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 1080 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
1413 | 1081 | ||
1414 | if (status) { | 1082 | if (status) { |
1415 | hci_req_complete(hdev, HCI_OP_INQUIRY, status); | ||
1416 | hci_conn_check_pending(hdev); | 1083 | hci_conn_check_pending(hdev); |
1417 | hci_dev_lock(hdev); | 1084 | hci_dev_lock(hdev); |
1418 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) | 1085 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) |
@@ -1884,11 +1551,6 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) | |||
1884 | } | 1551 | } |
1885 | } | 1552 | } |
1886 | 1553 | ||
1887 | static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) | ||
1888 | { | ||
1889 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
1890 | } | ||
1891 | |||
1892 | static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) | 1554 | static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) |
1893 | { | 1555 | { |
1894 | struct hci_cp_create_phy_link *cp; | 1556 | struct hci_cp_create_phy_link *cp; |
@@ -1930,11 +1592,6 @@ static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status) | |||
1930 | amp_write_remote_assoc(hdev, cp->phy_handle); | 1592 | amp_write_remote_assoc(hdev, cp->phy_handle); |
1931 | } | 1593 | } |
1932 | 1594 | ||
1933 | static void hci_cs_create_logical_link(struct hci_dev *hdev, u8 status) | ||
1934 | { | ||
1935 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
1936 | } | ||
1937 | |||
1938 | static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1595 | static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1939 | { | 1596 | { |
1940 | __u8 status = *((__u8 *) skb->data); | 1597 | __u8 status = *((__u8 *) skb->data); |
@@ -1943,7 +1600,7 @@ static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
1943 | 1600 | ||
1944 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 1601 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
1945 | 1602 | ||
1946 | hci_req_complete(hdev, HCI_OP_INQUIRY, status); | 1603 | hci_req_cmd_complete(hdev, HCI_OP_INQUIRY, status); |
1947 | 1604 | ||
1948 | hci_conn_check_pending(hdev); | 1605 | hci_conn_check_pending(hdev); |
1949 | 1606 | ||
@@ -2399,7 +2056,7 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2399 | clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); | 2056 | clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); |
2400 | 2057 | ||
2401 | if (ev->status && conn->state == BT_CONNECTED) { | 2058 | if (ev->status && conn->state == BT_CONNECTED) { |
2402 | hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE); | 2059 | hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); |
2403 | hci_conn_put(conn); | 2060 | hci_conn_put(conn); |
2404 | goto unlock; | 2061 | goto unlock; |
2405 | } | 2062 | } |
@@ -2491,20 +2148,10 @@ unlock: | |||
2491 | hci_dev_unlock(hdev); | 2148 | hci_dev_unlock(hdev); |
2492 | } | 2149 | } |
2493 | 2150 | ||
2494 | static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
2495 | { | ||
2496 | BT_DBG("%s", hdev->name); | ||
2497 | } | ||
2498 | |||
2499 | static void hci_qos_setup_complete_evt(struct hci_dev *hdev, | ||
2500 | struct sk_buff *skb) | ||
2501 | { | ||
2502 | BT_DBG("%s", hdev->name); | ||
2503 | } | ||
2504 | |||
2505 | static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2151 | static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2506 | { | 2152 | { |
2507 | struct hci_ev_cmd_complete *ev = (void *) skb->data; | 2153 | struct hci_ev_cmd_complete *ev = (void *) skb->data; |
2154 | u8 status = skb->data[sizeof(*ev)]; | ||
2508 | __u16 opcode; | 2155 | __u16 opcode; |
2509 | 2156 | ||
2510 | skb_pull(skb, sizeof(*ev)); | 2157 | skb_pull(skb, sizeof(*ev)); |
@@ -2588,10 +2235,6 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2588 | hci_cc_write_voice_setting(hdev, skb); | 2235 | hci_cc_write_voice_setting(hdev, skb); |
2589 | break; | 2236 | break; |
2590 | 2237 | ||
2591 | case HCI_OP_HOST_BUFFER_SIZE: | ||
2592 | hci_cc_host_buffer_size(hdev, skb); | ||
2593 | break; | ||
2594 | |||
2595 | case HCI_OP_WRITE_SSP_MODE: | 2238 | case HCI_OP_WRITE_SSP_MODE: |
2596 | hci_cc_write_ssp_mode(hdev, skb); | 2239 | hci_cc_write_ssp_mode(hdev, skb); |
2597 | break; | 2240 | break; |
@@ -2620,46 +2263,42 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2620 | hci_cc_read_bd_addr(hdev, skb); | 2263 | hci_cc_read_bd_addr(hdev, skb); |
2621 | break; | 2264 | break; |
2622 | 2265 | ||
2623 | case HCI_OP_READ_DATA_BLOCK_SIZE: | 2266 | case HCI_OP_READ_PAGE_SCAN_ACTIVITY: |
2624 | hci_cc_read_data_block_size(hdev, skb); | 2267 | hci_cc_read_page_scan_activity(hdev, skb); |
2625 | break; | 2268 | break; |
2626 | 2269 | ||
2627 | case HCI_OP_WRITE_CA_TIMEOUT: | 2270 | case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY: |
2628 | hci_cc_write_ca_timeout(hdev, skb); | 2271 | hci_cc_write_page_scan_activity(hdev, skb); |
2629 | break; | 2272 | break; |
2630 | 2273 | ||
2631 | case HCI_OP_READ_FLOW_CONTROL_MODE: | 2274 | case HCI_OP_READ_PAGE_SCAN_TYPE: |
2632 | hci_cc_read_flow_control_mode(hdev, skb); | 2275 | hci_cc_read_page_scan_type(hdev, skb); |
2633 | break; | 2276 | break; |
2634 | 2277 | ||
2635 | case HCI_OP_READ_LOCAL_AMP_INFO: | 2278 | case HCI_OP_WRITE_PAGE_SCAN_TYPE: |
2636 | hci_cc_read_local_amp_info(hdev, skb); | 2279 | hci_cc_write_page_scan_type(hdev, skb); |
2637 | break; | 2280 | break; |
2638 | 2281 | ||
2639 | case HCI_OP_READ_LOCAL_AMP_ASSOC: | 2282 | case HCI_OP_READ_DATA_BLOCK_SIZE: |
2640 | hci_cc_read_local_amp_assoc(hdev, skb); | 2283 | hci_cc_read_data_block_size(hdev, skb); |
2641 | break; | 2284 | break; |
2642 | 2285 | ||
2643 | case HCI_OP_DELETE_STORED_LINK_KEY: | 2286 | case HCI_OP_READ_FLOW_CONTROL_MODE: |
2644 | hci_cc_delete_stored_link_key(hdev, skb); | 2287 | hci_cc_read_flow_control_mode(hdev, skb); |
2645 | break; | 2288 | break; |
2646 | 2289 | ||
2647 | case HCI_OP_SET_EVENT_MASK: | 2290 | case HCI_OP_READ_LOCAL_AMP_INFO: |
2648 | hci_cc_set_event_mask(hdev, skb); | 2291 | hci_cc_read_local_amp_info(hdev, skb); |
2649 | break; | 2292 | break; |
2650 | 2293 | ||
2651 | case HCI_OP_WRITE_INQUIRY_MODE: | 2294 | case HCI_OP_READ_LOCAL_AMP_ASSOC: |
2652 | hci_cc_write_inquiry_mode(hdev, skb); | 2295 | hci_cc_read_local_amp_assoc(hdev, skb); |
2653 | break; | 2296 | break; |
2654 | 2297 | ||
2655 | case HCI_OP_READ_INQ_RSP_TX_POWER: | 2298 | case HCI_OP_READ_INQ_RSP_TX_POWER: |
2656 | hci_cc_read_inq_rsp_tx_power(hdev, skb); | 2299 | hci_cc_read_inq_rsp_tx_power(hdev, skb); |
2657 | break; | 2300 | break; |
2658 | 2301 | ||
2659 | case HCI_OP_SET_EVENT_FLT: | ||
2660 | hci_cc_set_event_flt(hdev, skb); | ||
2661 | break; | ||
2662 | |||
2663 | case HCI_OP_PIN_CODE_REPLY: | 2302 | case HCI_OP_PIN_CODE_REPLY: |
2664 | hci_cc_pin_code_reply(hdev, skb); | 2303 | hci_cc_pin_code_reply(hdev, skb); |
2665 | break; | 2304 | break; |
@@ -2684,10 +2323,6 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2684 | hci_cc_le_read_adv_tx_power(hdev, skb); | 2323 | hci_cc_le_read_adv_tx_power(hdev, skb); |
2685 | break; | 2324 | break; |
2686 | 2325 | ||
2687 | case HCI_OP_LE_SET_EVENT_MASK: | ||
2688 | hci_cc_le_set_event_mask(hdev, skb); | ||
2689 | break; | ||
2690 | |||
2691 | case HCI_OP_USER_CONFIRM_REPLY: | 2326 | case HCI_OP_USER_CONFIRM_REPLY: |
2692 | hci_cc_user_confirm_reply(hdev, skb); | 2327 | hci_cc_user_confirm_reply(hdev, skb); |
2693 | break; | 2328 | break; |
@@ -2720,14 +2355,6 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2720 | hci_cc_le_read_white_list_size(hdev, skb); | 2355 | hci_cc_le_read_white_list_size(hdev, skb); |
2721 | break; | 2356 | break; |
2722 | 2357 | ||
2723 | case HCI_OP_LE_LTK_REPLY: | ||
2724 | hci_cc_le_ltk_reply(hdev, skb); | ||
2725 | break; | ||
2726 | |||
2727 | case HCI_OP_LE_LTK_NEG_REPLY: | ||
2728 | hci_cc_le_ltk_neg_reply(hdev, skb); | ||
2729 | break; | ||
2730 | |||
2731 | case HCI_OP_LE_READ_SUPPORTED_STATES: | 2358 | case HCI_OP_LE_READ_SUPPORTED_STATES: |
2732 | hci_cc_le_read_supported_states(hdev, skb); | 2359 | hci_cc_le_read_supported_states(hdev, skb); |
2733 | break; | 2360 | break; |
@@ -2745,9 +2372,11 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2745 | break; | 2372 | break; |
2746 | } | 2373 | } |
2747 | 2374 | ||
2748 | if (ev->opcode != HCI_OP_NOP) | 2375 | if (opcode != HCI_OP_NOP) |
2749 | del_timer(&hdev->cmd_timer); | 2376 | del_timer(&hdev->cmd_timer); |
2750 | 2377 | ||
2378 | hci_req_cmd_complete(hdev, opcode, status); | ||
2379 | |||
2751 | if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { | 2380 | if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { |
2752 | atomic_set(&hdev->cmd_cnt, 1); | 2381 | atomic_set(&hdev->cmd_cnt, 1); |
2753 | if (!skb_queue_empty(&hdev->cmd_q)) | 2382 | if (!skb_queue_empty(&hdev->cmd_q)) |
@@ -2817,10 +2446,6 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2817 | hci_cs_le_create_conn(hdev, ev->status); | 2446 | hci_cs_le_create_conn(hdev, ev->status); |
2818 | break; | 2447 | break; |
2819 | 2448 | ||
2820 | case HCI_OP_LE_START_ENC: | ||
2821 | hci_cs_le_start_enc(hdev, ev->status); | ||
2822 | break; | ||
2823 | |||
2824 | case HCI_OP_CREATE_PHY_LINK: | 2449 | case HCI_OP_CREATE_PHY_LINK: |
2825 | hci_cs_create_phylink(hdev, ev->status); | 2450 | hci_cs_create_phylink(hdev, ev->status); |
2826 | break; | 2451 | break; |
@@ -2829,18 +2454,16 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2829 | hci_cs_accept_phylink(hdev, ev->status); | 2454 | hci_cs_accept_phylink(hdev, ev->status); |
2830 | break; | 2455 | break; |
2831 | 2456 | ||
2832 | case HCI_OP_CREATE_LOGICAL_LINK: | ||
2833 | hci_cs_create_logical_link(hdev, ev->status); | ||
2834 | break; | ||
2835 | |||
2836 | default: | 2457 | default: |
2837 | BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); | 2458 | BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); |
2838 | break; | 2459 | break; |
2839 | } | 2460 | } |
2840 | 2461 | ||
2841 | if (ev->opcode != HCI_OP_NOP) | 2462 | if (opcode != HCI_OP_NOP) |
2842 | del_timer(&hdev->cmd_timer); | 2463 | del_timer(&hdev->cmd_timer); |
2843 | 2464 | ||
2465 | hci_req_cmd_status(hdev, opcode, ev->status); | ||
2466 | |||
2844 | if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { | 2467 | if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { |
2845 | atomic_set(&hdev->cmd_cnt, 1); | 2468 | atomic_set(&hdev->cmd_cnt, 1); |
2846 | if (!skb_queue_empty(&hdev->cmd_q)) | 2469 | if (!skb_queue_empty(&hdev->cmd_q)) |
@@ -3391,18 +3014,6 @@ unlock: | |||
3391 | hci_dev_unlock(hdev); | 3014 | hci_dev_unlock(hdev); |
3392 | } | 3015 | } |
3393 | 3016 | ||
3394 | static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
3395 | { | ||
3396 | BT_DBG("%s", hdev->name); | ||
3397 | } | ||
3398 | |||
3399 | static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
3400 | { | ||
3401 | struct hci_ev_sniff_subrate *ev = (void *) skb->data; | ||
3402 | |||
3403 | BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); | ||
3404 | } | ||
3405 | |||
3406 | static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, | 3017 | static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, |
3407 | struct sk_buff *skb) | 3018 | struct sk_buff *skb) |
3408 | { | 3019 | { |
@@ -3472,7 +3083,7 @@ static void hci_key_refresh_complete_evt(struct hci_dev *hdev, | |||
3472 | clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); | 3083 | clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); |
3473 | 3084 | ||
3474 | if (ev->status && conn->state == BT_CONNECTED) { | 3085 | if (ev->status && conn->state == BT_CONNECTED) { |
3475 | hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE); | 3086 | hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); |
3476 | hci_conn_put(conn); | 3087 | hci_conn_put(conn); |
3477 | goto unlock; | 3088 | goto unlock; |
3478 | } | 3089 | } |
@@ -4130,14 +3741,6 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
4130 | hci_remote_features_evt(hdev, skb); | 3741 | hci_remote_features_evt(hdev, skb); |
4131 | break; | 3742 | break; |
4132 | 3743 | ||
4133 | case HCI_EV_REMOTE_VERSION: | ||
4134 | hci_remote_version_evt(hdev, skb); | ||
4135 | break; | ||
4136 | |||
4137 | case HCI_EV_QOS_SETUP_COMPLETE: | ||
4138 | hci_qos_setup_complete_evt(hdev, skb); | ||
4139 | break; | ||
4140 | |||
4141 | case HCI_EV_CMD_COMPLETE: | 3744 | case HCI_EV_CMD_COMPLETE: |
4142 | hci_cmd_complete_evt(hdev, skb); | 3745 | hci_cmd_complete_evt(hdev, skb); |
4143 | break; | 3746 | break; |
@@ -4194,14 +3797,6 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
4194 | hci_sync_conn_complete_evt(hdev, skb); | 3797 | hci_sync_conn_complete_evt(hdev, skb); |
4195 | break; | 3798 | break; |
4196 | 3799 | ||
4197 | case HCI_EV_SYNC_CONN_CHANGED: | ||
4198 | hci_sync_conn_changed_evt(hdev, skb); | ||
4199 | break; | ||
4200 | |||
4201 | case HCI_EV_SNIFF_SUBRATE: | ||
4202 | hci_sniff_subrate_evt(hdev, skb); | ||
4203 | break; | ||
4204 | |||
4205 | case HCI_EV_EXTENDED_INQUIRY_RESULT: | 3800 | case HCI_EV_EXTENDED_INQUIRY_RESULT: |
4206 | hci_extended_inquiry_result_evt(hdev, skb); | 3801 | hci_extended_inquiry_result_evt(hdev, skb); |
4207 | break; | 3802 | break; |
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 6a93614f2c49..aa4354fca77c 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
@@ -854,6 +854,11 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
854 | skb_queue_tail(&hdev->raw_q, skb); | 854 | skb_queue_tail(&hdev->raw_q, skb); |
855 | queue_work(hdev->workqueue, &hdev->tx_work); | 855 | queue_work(hdev->workqueue, &hdev->tx_work); |
856 | } else { | 856 | } else { |
857 | /* Stand-alone HCI commands must be flaged as | ||
858 | * single-command requests. | ||
859 | */ | ||
860 | bt_cb(skb)->req.start = true; | ||
861 | |||
857 | skb_queue_tail(&hdev->cmd_q, skb); | 862 | skb_queue_tail(&hdev->cmd_q, skb); |
858 | queue_work(hdev->workqueue, &hdev->cmd_work); | 863 | queue_work(hdev->workqueue, &hdev->cmd_work); |
859 | } | 864 | } |
@@ -1121,8 +1126,6 @@ error: | |||
1121 | void hci_sock_cleanup(void) | 1126 | void hci_sock_cleanup(void) |
1122 | { | 1127 | { |
1123 | bt_procfs_cleanup(&init_net, "hci"); | 1128 | bt_procfs_cleanup(&init_net, "hci"); |
1124 | if (bt_sock_unregister(BTPROTO_HCI) < 0) | 1129 | bt_sock_unregister(BTPROTO_HCI); |
1125 | BT_ERR("HCI socket unregistration failed"); | ||
1126 | |||
1127 | proto_unregister(&hci_sk_proto); | 1130 | proto_unregister(&hci_sk_proto); |
1128 | } | 1131 | } |
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 23b4e242a31a..ff38561385de 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c | |||
@@ -590,10 +590,8 @@ int __init bt_sysfs_init(void) | |||
590 | bt_debugfs = debugfs_create_dir("bluetooth", NULL); | 590 | bt_debugfs = debugfs_create_dir("bluetooth", NULL); |
591 | 591 | ||
592 | bt_class = class_create(THIS_MODULE, "bluetooth"); | 592 | bt_class = class_create(THIS_MODULE, "bluetooth"); |
593 | if (IS_ERR(bt_class)) | ||
594 | return PTR_ERR(bt_class); | ||
595 | 593 | ||
596 | return 0; | 594 | return PTR_RET(bt_class); |
597 | } | 595 | } |
598 | 596 | ||
599 | void bt_sysfs_cleanup(void) | 597 | void bt_sysfs_cleanup(void) |
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index a7352ff3fd1e..2342327f3335 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
@@ -311,6 +311,9 @@ static int hidp_get_raw_report(struct hid_device *hid, | |||
311 | int numbered_reports = hid->report_enum[report_type].numbered; | 311 | int numbered_reports = hid->report_enum[report_type].numbered; |
312 | int ret; | 312 | int ret; |
313 | 313 | ||
314 | if (atomic_read(&session->terminate)) | ||
315 | return -EIO; | ||
316 | |||
314 | switch (report_type) { | 317 | switch (report_type) { |
315 | case HID_FEATURE_REPORT: | 318 | case HID_FEATURE_REPORT: |
316 | report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_FEATURE; | 319 | report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_FEATURE; |
@@ -722,6 +725,7 @@ static int hidp_session(void *arg) | |||
722 | set_current_state(TASK_INTERRUPTIBLE); | 725 | set_current_state(TASK_INTERRUPTIBLE); |
723 | } | 726 | } |
724 | set_current_state(TASK_RUNNING); | 727 | set_current_state(TASK_RUNNING); |
728 | atomic_inc(&session->terminate); | ||
725 | remove_wait_queue(sk_sleep(intr_sk), &intr_wait); | 729 | remove_wait_queue(sk_sleep(intr_sk), &intr_wait); |
726 | remove_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait); | 730 | remove_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait); |
727 | 731 | ||
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c index 82a829d90b0f..5d0f1ca0a314 100644 --- a/net/bluetooth/hidp/sock.c +++ b/net/bluetooth/hidp/sock.c | |||
@@ -304,8 +304,6 @@ error: | |||
304 | void __exit hidp_cleanup_sockets(void) | 304 | void __exit hidp_cleanup_sockets(void) |
305 | { | 305 | { |
306 | bt_procfs_cleanup(&init_net, "hidp"); | 306 | bt_procfs_cleanup(&init_net, "hidp"); |
307 | if (bt_sock_unregister(BTPROTO_HIDP) < 0) | 307 | bt_sock_unregister(BTPROTO_HIDP); |
308 | BT_ERR("Can't unregister HIDP socket"); | ||
309 | |||
310 | proto_unregister(&hidp_proto); | 308 | proto_unregister(&hidp_proto); |
311 | } | 309 | } |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 1bcfb8422fdc..7f9704993b74 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -1312,8 +1312,6 @@ error: | |||
1312 | void l2cap_cleanup_sockets(void) | 1312 | void l2cap_cleanup_sockets(void) |
1313 | { | 1313 | { |
1314 | bt_procfs_cleanup(&init_net, "l2cap"); | 1314 | bt_procfs_cleanup(&init_net, "l2cap"); |
1315 | if (bt_sock_unregister(BTPROTO_L2CAP) < 0) | 1315 | bt_sock_unregister(BTPROTO_L2CAP); |
1316 | BT_ERR("L2CAP socket unregistration failed"); | ||
1317 | |||
1318 | proto_unregister(&l2cap_proto); | 1316 | proto_unregister(&l2cap_proto); |
1319 | } | 1317 | } |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 39395c7144aa..03e7e732215f 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -384,7 +384,8 @@ static u32 get_supported_settings(struct hci_dev *hdev) | |||
384 | 384 | ||
385 | if (lmp_bredr_capable(hdev)) { | 385 | if (lmp_bredr_capable(hdev)) { |
386 | settings |= MGMT_SETTING_CONNECTABLE; | 386 | settings |= MGMT_SETTING_CONNECTABLE; |
387 | settings |= MGMT_SETTING_FAST_CONNECTABLE; | 387 | if (hdev->hci_ver >= BLUETOOTH_VER_1_2) |
388 | settings |= MGMT_SETTING_FAST_CONNECTABLE; | ||
388 | settings |= MGMT_SETTING_DISCOVERABLE; | 389 | settings |= MGMT_SETTING_DISCOVERABLE; |
389 | settings |= MGMT_SETTING_BREDR; | 390 | settings |= MGMT_SETTING_BREDR; |
390 | settings |= MGMT_SETTING_LINK_SECURITY; | 391 | settings |= MGMT_SETTING_LINK_SECURITY; |
@@ -409,6 +410,9 @@ static u32 get_current_settings(struct hci_dev *hdev) | |||
409 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) | 410 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) |
410 | settings |= MGMT_SETTING_CONNECTABLE; | 411 | settings |= MGMT_SETTING_CONNECTABLE; |
411 | 412 | ||
413 | if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) | ||
414 | settings |= MGMT_SETTING_FAST_CONNECTABLE; | ||
415 | |||
412 | if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) | 416 | if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) |
413 | settings |= MGMT_SETTING_DISCOVERABLE; | 417 | settings |= MGMT_SETTING_DISCOVERABLE; |
414 | 418 | ||
@@ -591,32 +595,33 @@ static void create_eir(struct hci_dev *hdev, u8 *data) | |||
591 | ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data)); | 595 | ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data)); |
592 | } | 596 | } |
593 | 597 | ||
594 | static int update_eir(struct hci_dev *hdev) | 598 | static void update_eir(struct hci_request *req) |
595 | { | 599 | { |
600 | struct hci_dev *hdev = req->hdev; | ||
596 | struct hci_cp_write_eir cp; | 601 | struct hci_cp_write_eir cp; |
597 | 602 | ||
598 | if (!hdev_is_powered(hdev)) | 603 | if (!hdev_is_powered(hdev)) |
599 | return 0; | 604 | return; |
600 | 605 | ||
601 | if (!lmp_ext_inq_capable(hdev)) | 606 | if (!lmp_ext_inq_capable(hdev)) |
602 | return 0; | 607 | return; |
603 | 608 | ||
604 | if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) | 609 | if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) |
605 | return 0; | 610 | return; |
606 | 611 | ||
607 | if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) | 612 | if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) |
608 | return 0; | 613 | return; |
609 | 614 | ||
610 | memset(&cp, 0, sizeof(cp)); | 615 | memset(&cp, 0, sizeof(cp)); |
611 | 616 | ||
612 | create_eir(hdev, cp.data); | 617 | create_eir(hdev, cp.data); |
613 | 618 | ||
614 | if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0) | 619 | if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0) |
615 | return 0; | 620 | return; |
616 | 621 | ||
617 | memcpy(hdev->eir, cp.data, sizeof(cp.data)); | 622 | memcpy(hdev->eir, cp.data, sizeof(cp.data)); |
618 | 623 | ||
619 | return hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp); | 624 | hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp); |
620 | } | 625 | } |
621 | 626 | ||
622 | static u8 get_service_classes(struct hci_dev *hdev) | 627 | static u8 get_service_classes(struct hci_dev *hdev) |
@@ -630,47 +635,48 @@ static u8 get_service_classes(struct hci_dev *hdev) | |||
630 | return val; | 635 | return val; |
631 | } | 636 | } |
632 | 637 | ||
633 | static int update_class(struct hci_dev *hdev) | 638 | static void update_class(struct hci_request *req) |
634 | { | 639 | { |
640 | struct hci_dev *hdev = req->hdev; | ||
635 | u8 cod[3]; | 641 | u8 cod[3]; |
636 | int err; | ||
637 | 642 | ||
638 | BT_DBG("%s", hdev->name); | 643 | BT_DBG("%s", hdev->name); |
639 | 644 | ||
640 | if (!hdev_is_powered(hdev)) | 645 | if (!hdev_is_powered(hdev)) |
641 | return 0; | 646 | return; |
642 | 647 | ||
643 | if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) | 648 | if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) |
644 | return 0; | 649 | return; |
645 | 650 | ||
646 | cod[0] = hdev->minor_class; | 651 | cod[0] = hdev->minor_class; |
647 | cod[1] = hdev->major_class; | 652 | cod[1] = hdev->major_class; |
648 | cod[2] = get_service_classes(hdev); | 653 | cod[2] = get_service_classes(hdev); |
649 | 654 | ||
650 | if (memcmp(cod, hdev->dev_class, 3) == 0) | 655 | if (memcmp(cod, hdev->dev_class, 3) == 0) |
651 | return 0; | 656 | return; |
652 | |||
653 | err = hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod); | ||
654 | if (err == 0) | ||
655 | set_bit(HCI_PENDING_CLASS, &hdev->dev_flags); | ||
656 | 657 | ||
657 | return err; | 658 | hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod); |
658 | } | 659 | } |
659 | 660 | ||
660 | static void service_cache_off(struct work_struct *work) | 661 | static void service_cache_off(struct work_struct *work) |
661 | { | 662 | { |
662 | struct hci_dev *hdev = container_of(work, struct hci_dev, | 663 | struct hci_dev *hdev = container_of(work, struct hci_dev, |
663 | service_cache.work); | 664 | service_cache.work); |
665 | struct hci_request req; | ||
664 | 666 | ||
665 | if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) | 667 | if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) |
666 | return; | 668 | return; |
667 | 669 | ||
670 | hci_req_init(&req, hdev); | ||
671 | |||
668 | hci_dev_lock(hdev); | 672 | hci_dev_lock(hdev); |
669 | 673 | ||
670 | update_eir(hdev); | 674 | update_eir(&req); |
671 | update_class(hdev); | 675 | update_class(&req); |
672 | 676 | ||
673 | hci_dev_unlock(hdev); | 677 | hci_dev_unlock(hdev); |
678 | |||
679 | hci_req_run(&req, NULL); | ||
674 | } | 680 | } |
675 | 681 | ||
676 | static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev) | 682 | static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev) |
@@ -994,11 +1000,64 @@ failed: | |||
994 | return err; | 1000 | return err; |
995 | } | 1001 | } |
996 | 1002 | ||
1003 | static void write_fast_connectable(struct hci_request *req, bool enable) | ||
1004 | { | ||
1005 | struct hci_dev *hdev = req->hdev; | ||
1006 | struct hci_cp_write_page_scan_activity acp; | ||
1007 | u8 type; | ||
1008 | |||
1009 | if (hdev->hci_ver < BLUETOOTH_VER_1_2) | ||
1010 | return; | ||
1011 | |||
1012 | if (enable) { | ||
1013 | type = PAGE_SCAN_TYPE_INTERLACED; | ||
1014 | |||
1015 | /* 160 msec page scan interval */ | ||
1016 | acp.interval = __constant_cpu_to_le16(0x0100); | ||
1017 | } else { | ||
1018 | type = PAGE_SCAN_TYPE_STANDARD; /* default */ | ||
1019 | |||
1020 | /* default 1.28 sec page scan */ | ||
1021 | acp.interval = __constant_cpu_to_le16(0x0800); | ||
1022 | } | ||
1023 | |||
1024 | acp.window = __constant_cpu_to_le16(0x0012); | ||
1025 | |||
1026 | if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval || | ||
1027 | __cpu_to_le16(hdev->page_scan_window) != acp.window) | ||
1028 | hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, | ||
1029 | sizeof(acp), &acp); | ||
1030 | |||
1031 | if (hdev->page_scan_type != type) | ||
1032 | hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type); | ||
1033 | } | ||
1034 | |||
1035 | static void set_connectable_complete(struct hci_dev *hdev, u8 status) | ||
1036 | { | ||
1037 | struct pending_cmd *cmd; | ||
1038 | |||
1039 | BT_DBG("status 0x%02x", status); | ||
1040 | |||
1041 | hci_dev_lock(hdev); | ||
1042 | |||
1043 | cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev); | ||
1044 | if (!cmd) | ||
1045 | goto unlock; | ||
1046 | |||
1047 | send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev); | ||
1048 | |||
1049 | mgmt_pending_remove(cmd); | ||
1050 | |||
1051 | unlock: | ||
1052 | hci_dev_unlock(hdev); | ||
1053 | } | ||
1054 | |||
997 | static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | 1055 | static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, |
998 | u16 len) | 1056 | u16 len) |
999 | { | 1057 | { |
1000 | struct mgmt_mode *cp = data; | 1058 | struct mgmt_mode *cp = data; |
1001 | struct pending_cmd *cmd; | 1059 | struct pending_cmd *cmd; |
1060 | struct hci_request req; | ||
1002 | u8 scan; | 1061 | u8 scan; |
1003 | int err; | 1062 | int err; |
1004 | 1063 | ||
@@ -1065,7 +1124,20 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1065 | cancel_delayed_work(&hdev->discov_off); | 1124 | cancel_delayed_work(&hdev->discov_off); |
1066 | } | 1125 | } |
1067 | 1126 | ||
1068 | err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | 1127 | hci_req_init(&req, hdev); |
1128 | |||
1129 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | ||
1130 | |||
1131 | /* If we're going from non-connectable to connectable or | ||
1132 | * vice-versa when fast connectable is enabled ensure that fast | ||
1133 | * connectable gets disabled. write_fast_connectable won't do | ||
1134 | * anything if the page scan parameters are already what they | ||
1135 | * should be. | ||
1136 | */ | ||
1137 | if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) | ||
1138 | write_fast_connectable(&req, false); | ||
1139 | |||
1140 | err = hci_req_run(&req, set_connectable_complete); | ||
1069 | if (err < 0) | 1141 | if (err < 0) |
1070 | mgmt_pending_remove(cmd); | 1142 | mgmt_pending_remove(cmd); |
1071 | 1143 | ||
@@ -1332,6 +1404,29 @@ unlock: | |||
1332 | return err; | 1404 | return err; |
1333 | } | 1405 | } |
1334 | 1406 | ||
1407 | /* This is a helper function to test for pending mgmt commands that can | ||
1408 | * cause CoD or EIR HCI commands. We can only allow one such pending | ||
1409 | * mgmt command at a time since otherwise we cannot easily track what | ||
1410 | * the current values are, will be, and based on that calculate if a new | ||
1411 | * HCI command needs to be sent and if yes with what value. | ||
1412 | */ | ||
1413 | static bool pending_eir_or_class(struct hci_dev *hdev) | ||
1414 | { | ||
1415 | struct pending_cmd *cmd; | ||
1416 | |||
1417 | list_for_each_entry(cmd, &hdev->mgmt_pending, list) { | ||
1418 | switch (cmd->opcode) { | ||
1419 | case MGMT_OP_ADD_UUID: | ||
1420 | case MGMT_OP_REMOVE_UUID: | ||
1421 | case MGMT_OP_SET_DEV_CLASS: | ||
1422 | case MGMT_OP_SET_POWERED: | ||
1423 | return true; | ||
1424 | } | ||
1425 | } | ||
1426 | |||
1427 | return false; | ||
1428 | } | ||
1429 | |||
1335 | static const u8 bluetooth_base_uuid[] = { | 1430 | static const u8 bluetooth_base_uuid[] = { |
1336 | 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, | 1431 | 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, |
1337 | 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 1432 | 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
@@ -1351,10 +1446,37 @@ static u8 get_uuid_size(const u8 *uuid) | |||
1351 | return 16; | 1446 | return 16; |
1352 | } | 1447 | } |
1353 | 1448 | ||
1449 | static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status) | ||
1450 | { | ||
1451 | struct pending_cmd *cmd; | ||
1452 | |||
1453 | hci_dev_lock(hdev); | ||
1454 | |||
1455 | cmd = mgmt_pending_find(mgmt_op, hdev); | ||
1456 | if (!cmd) | ||
1457 | goto unlock; | ||
1458 | |||
1459 | cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status), | ||
1460 | hdev->dev_class, 3); | ||
1461 | |||
1462 | mgmt_pending_remove(cmd); | ||
1463 | |||
1464 | unlock: | ||
1465 | hci_dev_unlock(hdev); | ||
1466 | } | ||
1467 | |||
1468 | static void add_uuid_complete(struct hci_dev *hdev, u8 status) | ||
1469 | { | ||
1470 | BT_DBG("status 0x%02x", status); | ||
1471 | |||
1472 | mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status); | ||
1473 | } | ||
1474 | |||
1354 | static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | 1475 | static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) |
1355 | { | 1476 | { |
1356 | struct mgmt_cp_add_uuid *cp = data; | 1477 | struct mgmt_cp_add_uuid *cp = data; |
1357 | struct pending_cmd *cmd; | 1478 | struct pending_cmd *cmd; |
1479 | struct hci_request req; | ||
1358 | struct bt_uuid *uuid; | 1480 | struct bt_uuid *uuid; |
1359 | int err; | 1481 | int err; |
1360 | 1482 | ||
@@ -1362,7 +1484,7 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1362 | 1484 | ||
1363 | hci_dev_lock(hdev); | 1485 | hci_dev_lock(hdev); |
1364 | 1486 | ||
1365 | if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) { | 1487 | if (pending_eir_or_class(hdev)) { |
1366 | err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID, | 1488 | err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID, |
1367 | MGMT_STATUS_BUSY); | 1489 | MGMT_STATUS_BUSY); |
1368 | goto failed; | 1490 | goto failed; |
@@ -1380,23 +1502,28 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1380 | 1502 | ||
1381 | list_add_tail(&uuid->list, &hdev->uuids); | 1503 | list_add_tail(&uuid->list, &hdev->uuids); |
1382 | 1504 | ||
1383 | err = update_class(hdev); | 1505 | hci_req_init(&req, hdev); |
1384 | if (err < 0) | ||
1385 | goto failed; | ||
1386 | 1506 | ||
1387 | err = update_eir(hdev); | 1507 | update_class(&req); |
1388 | if (err < 0) | 1508 | update_eir(&req); |
1389 | goto failed; | 1509 | |
1510 | err = hci_req_run(&req, add_uuid_complete); | ||
1511 | if (err < 0) { | ||
1512 | if (err != -ENODATA) | ||
1513 | goto failed; | ||
1390 | 1514 | ||
1391 | if (!test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) { | ||
1392 | err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0, | 1515 | err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0, |
1393 | hdev->dev_class, 3); | 1516 | hdev->dev_class, 3); |
1394 | goto failed; | 1517 | goto failed; |
1395 | } | 1518 | } |
1396 | 1519 | ||
1397 | cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len); | 1520 | cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len); |
1398 | if (!cmd) | 1521 | if (!cmd) { |
1399 | err = -ENOMEM; | 1522 | err = -ENOMEM; |
1523 | goto failed; | ||
1524 | } | ||
1525 | |||
1526 | err = 0; | ||
1400 | 1527 | ||
1401 | failed: | 1528 | failed: |
1402 | hci_dev_unlock(hdev); | 1529 | hci_dev_unlock(hdev); |
@@ -1417,6 +1544,13 @@ static bool enable_service_cache(struct hci_dev *hdev) | |||
1417 | return false; | 1544 | return false; |
1418 | } | 1545 | } |
1419 | 1546 | ||
1547 | static void remove_uuid_complete(struct hci_dev *hdev, u8 status) | ||
1548 | { | ||
1549 | BT_DBG("status 0x%02x", status); | ||
1550 | |||
1551 | mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status); | ||
1552 | } | ||
1553 | |||
1420 | static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, | 1554 | static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, |
1421 | u16 len) | 1555 | u16 len) |
1422 | { | 1556 | { |
@@ -1424,13 +1558,14 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1424 | struct pending_cmd *cmd; | 1558 | struct pending_cmd *cmd; |
1425 | struct bt_uuid *match, *tmp; | 1559 | struct bt_uuid *match, *tmp; |
1426 | u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | 1560 | u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
1561 | struct hci_request req; | ||
1427 | int err, found; | 1562 | int err, found; |
1428 | 1563 | ||
1429 | BT_DBG("request for %s", hdev->name); | 1564 | BT_DBG("request for %s", hdev->name); |
1430 | 1565 | ||
1431 | hci_dev_lock(hdev); | 1566 | hci_dev_lock(hdev); |
1432 | 1567 | ||
1433 | if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) { | 1568 | if (pending_eir_or_class(hdev)) { |
1434 | err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID, | 1569 | err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID, |
1435 | MGMT_STATUS_BUSY); | 1570 | MGMT_STATUS_BUSY); |
1436 | goto unlock; | 1571 | goto unlock; |
@@ -1466,34 +1601,47 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1466 | } | 1601 | } |
1467 | 1602 | ||
1468 | update_class: | 1603 | update_class: |
1469 | err = update_class(hdev); | 1604 | hci_req_init(&req, hdev); |
1470 | if (err < 0) | ||
1471 | goto unlock; | ||
1472 | 1605 | ||
1473 | err = update_eir(hdev); | 1606 | update_class(&req); |
1474 | if (err < 0) | 1607 | update_eir(&req); |
1475 | goto unlock; | 1608 | |
1609 | err = hci_req_run(&req, remove_uuid_complete); | ||
1610 | if (err < 0) { | ||
1611 | if (err != -ENODATA) | ||
1612 | goto unlock; | ||
1476 | 1613 | ||
1477 | if (!test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) { | ||
1478 | err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0, | 1614 | err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0, |
1479 | hdev->dev_class, 3); | 1615 | hdev->dev_class, 3); |
1480 | goto unlock; | 1616 | goto unlock; |
1481 | } | 1617 | } |
1482 | 1618 | ||
1483 | cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len); | 1619 | cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len); |
1484 | if (!cmd) | 1620 | if (!cmd) { |
1485 | err = -ENOMEM; | 1621 | err = -ENOMEM; |
1622 | goto unlock; | ||
1623 | } | ||
1624 | |||
1625 | err = 0; | ||
1486 | 1626 | ||
1487 | unlock: | 1627 | unlock: |
1488 | hci_dev_unlock(hdev); | 1628 | hci_dev_unlock(hdev); |
1489 | return err; | 1629 | return err; |
1490 | } | 1630 | } |
1491 | 1631 | ||
1632 | static void set_class_complete(struct hci_dev *hdev, u8 status) | ||
1633 | { | ||
1634 | BT_DBG("status 0x%02x", status); | ||
1635 | |||
1636 | mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status); | ||
1637 | } | ||
1638 | |||
1492 | static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data, | 1639 | static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data, |
1493 | u16 len) | 1640 | u16 len) |
1494 | { | 1641 | { |
1495 | struct mgmt_cp_set_dev_class *cp = data; | 1642 | struct mgmt_cp_set_dev_class *cp = data; |
1496 | struct pending_cmd *cmd; | 1643 | struct pending_cmd *cmd; |
1644 | struct hci_request req; | ||
1497 | int err; | 1645 | int err; |
1498 | 1646 | ||
1499 | BT_DBG("request for %s", hdev->name); | 1647 | BT_DBG("request for %s", hdev->name); |
@@ -1502,15 +1650,19 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1502 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, | 1650 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, |
1503 | MGMT_STATUS_NOT_SUPPORTED); | 1651 | MGMT_STATUS_NOT_SUPPORTED); |
1504 | 1652 | ||
1505 | if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) | 1653 | hci_dev_lock(hdev); |
1506 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, | ||
1507 | MGMT_STATUS_BUSY); | ||
1508 | 1654 | ||
1509 | if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) | 1655 | if (pending_eir_or_class(hdev)) { |
1510 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, | 1656 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, |
1511 | MGMT_STATUS_INVALID_PARAMS); | 1657 | MGMT_STATUS_BUSY); |
1658 | goto unlock; | ||
1659 | } | ||
1512 | 1660 | ||
1513 | hci_dev_lock(hdev); | 1661 | if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) { |
1662 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, | ||
1663 | MGMT_STATUS_INVALID_PARAMS); | ||
1664 | goto unlock; | ||
1665 | } | ||
1514 | 1666 | ||
1515 | hdev->major_class = cp->major; | 1667 | hdev->major_class = cp->major; |
1516 | hdev->minor_class = cp->minor; | 1668 | hdev->minor_class = cp->minor; |
@@ -1521,26 +1673,34 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1521 | goto unlock; | 1673 | goto unlock; |
1522 | } | 1674 | } |
1523 | 1675 | ||
1676 | hci_req_init(&req, hdev); | ||
1677 | |||
1524 | if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) { | 1678 | if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) { |
1525 | hci_dev_unlock(hdev); | 1679 | hci_dev_unlock(hdev); |
1526 | cancel_delayed_work_sync(&hdev->service_cache); | 1680 | cancel_delayed_work_sync(&hdev->service_cache); |
1527 | hci_dev_lock(hdev); | 1681 | hci_dev_lock(hdev); |
1528 | update_eir(hdev); | 1682 | update_eir(&req); |
1529 | } | 1683 | } |
1530 | 1684 | ||
1531 | err = update_class(hdev); | 1685 | update_class(&req); |
1532 | if (err < 0) | 1686 | |
1533 | goto unlock; | 1687 | err = hci_req_run(&req, set_class_complete); |
1688 | if (err < 0) { | ||
1689 | if (err != -ENODATA) | ||
1690 | goto unlock; | ||
1534 | 1691 | ||
1535 | if (!test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) { | ||
1536 | err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0, | 1692 | err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0, |
1537 | hdev->dev_class, 3); | 1693 | hdev->dev_class, 3); |
1538 | goto unlock; | 1694 | goto unlock; |
1539 | } | 1695 | } |
1540 | 1696 | ||
1541 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len); | 1697 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len); |
1542 | if (!cmd) | 1698 | if (!cmd) { |
1543 | err = -ENOMEM; | 1699 | err = -ENOMEM; |
1700 | goto unlock; | ||
1701 | } | ||
1702 | |||
1703 | err = 0; | ||
1544 | 1704 | ||
1545 | unlock: | 1705 | unlock: |
1546 | hci_dev_unlock(hdev); | 1706 | hci_dev_unlock(hdev); |
@@ -2140,7 +2300,7 @@ unlock: | |||
2140 | } | 2300 | } |
2141 | 2301 | ||
2142 | static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev, | 2302 | static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev, |
2143 | bdaddr_t *bdaddr, u8 type, u16 mgmt_op, | 2303 | struct mgmt_addr_info *addr, u16 mgmt_op, |
2144 | u16 hci_op, __le32 passkey) | 2304 | u16 hci_op, __le32 passkey) |
2145 | { | 2305 | { |
2146 | struct pending_cmd *cmd; | 2306 | struct pending_cmd *cmd; |
@@ -2150,37 +2310,41 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev, | |||
2150 | hci_dev_lock(hdev); | 2310 | hci_dev_lock(hdev); |
2151 | 2311 | ||
2152 | if (!hdev_is_powered(hdev)) { | 2312 | if (!hdev_is_powered(hdev)) { |
2153 | err = cmd_status(sk, hdev->id, mgmt_op, | 2313 | err = cmd_complete(sk, hdev->id, mgmt_op, |
2154 | MGMT_STATUS_NOT_POWERED); | 2314 | MGMT_STATUS_NOT_POWERED, addr, |
2315 | sizeof(*addr)); | ||
2155 | goto done; | 2316 | goto done; |
2156 | } | 2317 | } |
2157 | 2318 | ||
2158 | if (type == BDADDR_BREDR) | 2319 | if (addr->type == BDADDR_BREDR) |
2159 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, bdaddr); | 2320 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr); |
2160 | else | 2321 | else |
2161 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, bdaddr); | 2322 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr); |
2162 | 2323 | ||
2163 | if (!conn) { | 2324 | if (!conn) { |
2164 | err = cmd_status(sk, hdev->id, mgmt_op, | 2325 | err = cmd_complete(sk, hdev->id, mgmt_op, |
2165 | MGMT_STATUS_NOT_CONNECTED); | 2326 | MGMT_STATUS_NOT_CONNECTED, addr, |
2327 | sizeof(*addr)); | ||
2166 | goto done; | 2328 | goto done; |
2167 | } | 2329 | } |
2168 | 2330 | ||
2169 | if (type == BDADDR_LE_PUBLIC || type == BDADDR_LE_RANDOM) { | 2331 | if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) { |
2170 | /* Continue with pairing via SMP */ | 2332 | /* Continue with pairing via SMP */ |
2171 | err = smp_user_confirm_reply(conn, mgmt_op, passkey); | 2333 | err = smp_user_confirm_reply(conn, mgmt_op, passkey); |
2172 | 2334 | ||
2173 | if (!err) | 2335 | if (!err) |
2174 | err = cmd_status(sk, hdev->id, mgmt_op, | 2336 | err = cmd_complete(sk, hdev->id, mgmt_op, |
2175 | MGMT_STATUS_SUCCESS); | 2337 | MGMT_STATUS_SUCCESS, addr, |
2338 | sizeof(*addr)); | ||
2176 | else | 2339 | else |
2177 | err = cmd_status(sk, hdev->id, mgmt_op, | 2340 | err = cmd_complete(sk, hdev->id, mgmt_op, |
2178 | MGMT_STATUS_FAILED); | 2341 | MGMT_STATUS_FAILED, addr, |
2342 | sizeof(*addr)); | ||
2179 | 2343 | ||
2180 | goto done; | 2344 | goto done; |
2181 | } | 2345 | } |
2182 | 2346 | ||
2183 | cmd = mgmt_pending_add(sk, mgmt_op, hdev, bdaddr, sizeof(*bdaddr)); | 2347 | cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr)); |
2184 | if (!cmd) { | 2348 | if (!cmd) { |
2185 | err = -ENOMEM; | 2349 | err = -ENOMEM; |
2186 | goto done; | 2350 | goto done; |
@@ -2190,11 +2354,12 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev, | |||
2190 | if (hci_op == HCI_OP_USER_PASSKEY_REPLY) { | 2354 | if (hci_op == HCI_OP_USER_PASSKEY_REPLY) { |
2191 | struct hci_cp_user_passkey_reply cp; | 2355 | struct hci_cp_user_passkey_reply cp; |
2192 | 2356 | ||
2193 | bacpy(&cp.bdaddr, bdaddr); | 2357 | bacpy(&cp.bdaddr, &addr->bdaddr); |
2194 | cp.passkey = passkey; | 2358 | cp.passkey = passkey; |
2195 | err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp); | 2359 | err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp); |
2196 | } else | 2360 | } else |
2197 | err = hci_send_cmd(hdev, hci_op, sizeof(*bdaddr), bdaddr); | 2361 | err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr), |
2362 | &addr->bdaddr); | ||
2198 | 2363 | ||
2199 | if (err < 0) | 2364 | if (err < 0) |
2200 | mgmt_pending_remove(cmd); | 2365 | mgmt_pending_remove(cmd); |
@@ -2211,7 +2376,7 @@ static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev, | |||
2211 | 2376 | ||
2212 | BT_DBG(""); | 2377 | BT_DBG(""); |
2213 | 2378 | ||
2214 | return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type, | 2379 | return user_pairing_resp(sk, hdev, &cp->addr, |
2215 | MGMT_OP_PIN_CODE_NEG_REPLY, | 2380 | MGMT_OP_PIN_CODE_NEG_REPLY, |
2216 | HCI_OP_PIN_CODE_NEG_REPLY, 0); | 2381 | HCI_OP_PIN_CODE_NEG_REPLY, 0); |
2217 | } | 2382 | } |
@@ -2227,7 +2392,7 @@ static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2227 | return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY, | 2392 | return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY, |
2228 | MGMT_STATUS_INVALID_PARAMS); | 2393 | MGMT_STATUS_INVALID_PARAMS); |
2229 | 2394 | ||
2230 | return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type, | 2395 | return user_pairing_resp(sk, hdev, &cp->addr, |
2231 | MGMT_OP_USER_CONFIRM_REPLY, | 2396 | MGMT_OP_USER_CONFIRM_REPLY, |
2232 | HCI_OP_USER_CONFIRM_REPLY, 0); | 2397 | HCI_OP_USER_CONFIRM_REPLY, 0); |
2233 | } | 2398 | } |
@@ -2239,7 +2404,7 @@ static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev, | |||
2239 | 2404 | ||
2240 | BT_DBG(""); | 2405 | BT_DBG(""); |
2241 | 2406 | ||
2242 | return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type, | 2407 | return user_pairing_resp(sk, hdev, &cp->addr, |
2243 | MGMT_OP_USER_CONFIRM_NEG_REPLY, | 2408 | MGMT_OP_USER_CONFIRM_NEG_REPLY, |
2244 | HCI_OP_USER_CONFIRM_NEG_REPLY, 0); | 2409 | HCI_OP_USER_CONFIRM_NEG_REPLY, 0); |
2245 | } | 2410 | } |
@@ -2251,7 +2416,7 @@ static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2251 | 2416 | ||
2252 | BT_DBG(""); | 2417 | BT_DBG(""); |
2253 | 2418 | ||
2254 | return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type, | 2419 | return user_pairing_resp(sk, hdev, &cp->addr, |
2255 | MGMT_OP_USER_PASSKEY_REPLY, | 2420 | MGMT_OP_USER_PASSKEY_REPLY, |
2256 | HCI_OP_USER_PASSKEY_REPLY, cp->passkey); | 2421 | HCI_OP_USER_PASSKEY_REPLY, cp->passkey); |
2257 | } | 2422 | } |
@@ -2263,18 +2428,47 @@ static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev, | |||
2263 | 2428 | ||
2264 | BT_DBG(""); | 2429 | BT_DBG(""); |
2265 | 2430 | ||
2266 | return user_pairing_resp(sk, hdev, &cp->addr.bdaddr, cp->addr.type, | 2431 | return user_pairing_resp(sk, hdev, &cp->addr, |
2267 | MGMT_OP_USER_PASSKEY_NEG_REPLY, | 2432 | MGMT_OP_USER_PASSKEY_NEG_REPLY, |
2268 | HCI_OP_USER_PASSKEY_NEG_REPLY, 0); | 2433 | HCI_OP_USER_PASSKEY_NEG_REPLY, 0); |
2269 | } | 2434 | } |
2270 | 2435 | ||
2271 | static int update_name(struct hci_dev *hdev, const char *name) | 2436 | static void update_name(struct hci_request *req) |
2272 | { | 2437 | { |
2438 | struct hci_dev *hdev = req->hdev; | ||
2273 | struct hci_cp_write_local_name cp; | 2439 | struct hci_cp_write_local_name cp; |
2274 | 2440 | ||
2275 | memcpy(cp.name, name, sizeof(cp.name)); | 2441 | memcpy(cp.name, hdev->dev_name, sizeof(cp.name)); |
2442 | |||
2443 | hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp); | ||
2444 | } | ||
2445 | |||
2446 | static void set_name_complete(struct hci_dev *hdev, u8 status) | ||
2447 | { | ||
2448 | struct mgmt_cp_set_local_name *cp; | ||
2449 | struct pending_cmd *cmd; | ||
2450 | |||
2451 | BT_DBG("status 0x%02x", status); | ||
2452 | |||
2453 | hci_dev_lock(hdev); | ||
2454 | |||
2455 | cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev); | ||
2456 | if (!cmd) | ||
2457 | goto unlock; | ||
2458 | |||
2459 | cp = cmd->param; | ||
2276 | 2460 | ||
2277 | return hci_send_cmd(hdev, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp); | 2461 | if (status) |
2462 | cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, | ||
2463 | mgmt_status(status)); | ||
2464 | else | ||
2465 | cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0, | ||
2466 | cp, sizeof(*cp)); | ||
2467 | |||
2468 | mgmt_pending_remove(cmd); | ||
2469 | |||
2470 | unlock: | ||
2471 | hci_dev_unlock(hdev); | ||
2278 | } | 2472 | } |
2279 | 2473 | ||
2280 | static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data, | 2474 | static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data, |
@@ -2282,12 +2476,24 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2282 | { | 2476 | { |
2283 | struct mgmt_cp_set_local_name *cp = data; | 2477 | struct mgmt_cp_set_local_name *cp = data; |
2284 | struct pending_cmd *cmd; | 2478 | struct pending_cmd *cmd; |
2479 | struct hci_request req; | ||
2285 | int err; | 2480 | int err; |
2286 | 2481 | ||
2287 | BT_DBG(""); | 2482 | BT_DBG(""); |
2288 | 2483 | ||
2289 | hci_dev_lock(hdev); | 2484 | hci_dev_lock(hdev); |
2290 | 2485 | ||
2486 | /* If the old values are the same as the new ones just return a | ||
2487 | * direct command complete event. | ||
2488 | */ | ||
2489 | if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) && | ||
2490 | !memcmp(hdev->short_name, cp->short_name, | ||
2491 | sizeof(hdev->short_name))) { | ||
2492 | err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0, | ||
2493 | data, len); | ||
2494 | goto failed; | ||
2495 | } | ||
2496 | |||
2291 | memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name)); | 2497 | memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name)); |
2292 | 2498 | ||
2293 | if (!hdev_is_powered(hdev)) { | 2499 | if (!hdev_is_powered(hdev)) { |
@@ -2310,7 +2516,19 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2310 | goto failed; | 2516 | goto failed; |
2311 | } | 2517 | } |
2312 | 2518 | ||
2313 | err = update_name(hdev, cp->name); | 2519 | memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name)); |
2520 | |||
2521 | hci_req_init(&req, hdev); | ||
2522 | |||
2523 | if (lmp_bredr_capable(hdev)) { | ||
2524 | update_name(&req); | ||
2525 | update_eir(&req); | ||
2526 | } | ||
2527 | |||
2528 | if (lmp_le_capable(hdev)) | ||
2529 | hci_update_ad(&req); | ||
2530 | |||
2531 | err = hci_req_run(&req, set_name_complete); | ||
2314 | if (err < 0) | 2532 | if (err < 0) |
2315 | mgmt_pending_remove(cmd); | 2533 | mgmt_pending_remove(cmd); |
2316 | 2534 | ||
@@ -2698,6 +2916,7 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2698 | u16 len) | 2916 | u16 len) |
2699 | { | 2917 | { |
2700 | struct mgmt_cp_set_device_id *cp = data; | 2918 | struct mgmt_cp_set_device_id *cp = data; |
2919 | struct hci_request req; | ||
2701 | int err; | 2920 | int err; |
2702 | __u16 source; | 2921 | __u16 source; |
2703 | 2922 | ||
@@ -2718,24 +2937,59 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2718 | 2937 | ||
2719 | err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0); | 2938 | err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0); |
2720 | 2939 | ||
2721 | update_eir(hdev); | 2940 | hci_req_init(&req, hdev); |
2941 | update_eir(&req); | ||
2942 | hci_req_run(&req, NULL); | ||
2722 | 2943 | ||
2723 | hci_dev_unlock(hdev); | 2944 | hci_dev_unlock(hdev); |
2724 | 2945 | ||
2725 | return err; | 2946 | return err; |
2726 | } | 2947 | } |
2727 | 2948 | ||
2949 | static void fast_connectable_complete(struct hci_dev *hdev, u8 status) | ||
2950 | { | ||
2951 | struct pending_cmd *cmd; | ||
2952 | |||
2953 | BT_DBG("status 0x%02x", status); | ||
2954 | |||
2955 | hci_dev_lock(hdev); | ||
2956 | |||
2957 | cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev); | ||
2958 | if (!cmd) | ||
2959 | goto unlock; | ||
2960 | |||
2961 | if (status) { | ||
2962 | cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, | ||
2963 | mgmt_status(status)); | ||
2964 | } else { | ||
2965 | struct mgmt_mode *cp = cmd->param; | ||
2966 | |||
2967 | if (cp->val) | ||
2968 | set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags); | ||
2969 | else | ||
2970 | clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags); | ||
2971 | |||
2972 | send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev); | ||
2973 | new_settings(hdev, cmd->sk); | ||
2974 | } | ||
2975 | |||
2976 | mgmt_pending_remove(cmd); | ||
2977 | |||
2978 | unlock: | ||
2979 | hci_dev_unlock(hdev); | ||
2980 | } | ||
2981 | |||
2728 | static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev, | 2982 | static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev, |
2729 | void *data, u16 len) | 2983 | void *data, u16 len) |
2730 | { | 2984 | { |
2731 | struct mgmt_mode *cp = data; | 2985 | struct mgmt_mode *cp = data; |
2732 | struct hci_cp_write_page_scan_activity acp; | 2986 | struct pending_cmd *cmd; |
2733 | u8 type; | 2987 | struct hci_request req; |
2734 | int err; | 2988 | int err; |
2735 | 2989 | ||
2736 | BT_DBG("%s", hdev->name); | 2990 | BT_DBG("%s", hdev->name); |
2737 | 2991 | ||
2738 | if (!lmp_bredr_capable(hdev)) | 2992 | if (!lmp_bredr_capable(hdev) || hdev->hci_ver < BLUETOOTH_VER_1_2) |
2739 | return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, | 2993 | return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, |
2740 | MGMT_STATUS_NOT_SUPPORTED); | 2994 | MGMT_STATUS_NOT_SUPPORTED); |
2741 | 2995 | ||
@@ -2753,40 +3007,39 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev, | |||
2753 | 3007 | ||
2754 | hci_dev_lock(hdev); | 3008 | hci_dev_lock(hdev); |
2755 | 3009 | ||
2756 | if (cp->val) { | 3010 | if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) { |
2757 | type = PAGE_SCAN_TYPE_INTERLACED; | 3011 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, |
3012 | MGMT_STATUS_BUSY); | ||
3013 | goto unlock; | ||
3014 | } | ||
2758 | 3015 | ||
2759 | /* 160 msec page scan interval */ | 3016 | if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) { |
2760 | acp.interval = __constant_cpu_to_le16(0x0100); | 3017 | err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE, |
2761 | } else { | 3018 | hdev); |
2762 | type = PAGE_SCAN_TYPE_STANDARD; /* default */ | 3019 | goto unlock; |
3020 | } | ||
2763 | 3021 | ||
2764 | /* default 1.28 sec page scan */ | 3022 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev, |
2765 | acp.interval = __constant_cpu_to_le16(0x0800); | 3023 | data, len); |
3024 | if (!cmd) { | ||
3025 | err = -ENOMEM; | ||
3026 | goto unlock; | ||
2766 | } | 3027 | } |
2767 | 3028 | ||
2768 | /* default 11.25 msec page scan window */ | 3029 | hci_req_init(&req, hdev); |
2769 | acp.window = __constant_cpu_to_le16(0x0012); | ||
2770 | 3030 | ||
2771 | err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, sizeof(acp), | 3031 | write_fast_connectable(&req, cp->val); |
2772 | &acp); | ||
2773 | if (err < 0) { | ||
2774 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, | ||
2775 | MGMT_STATUS_FAILED); | ||
2776 | goto done; | ||
2777 | } | ||
2778 | 3032 | ||
2779 | err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type); | 3033 | err = hci_req_run(&req, fast_connectable_complete); |
2780 | if (err < 0) { | 3034 | if (err < 0) { |
2781 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, | 3035 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, |
2782 | MGMT_STATUS_FAILED); | 3036 | MGMT_STATUS_FAILED); |
2783 | goto done; | 3037 | mgmt_pending_remove(cmd); |
2784 | } | 3038 | } |
2785 | 3039 | ||
2786 | err = cmd_complete(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE, 0, | 3040 | unlock: |
2787 | NULL, 0); | ||
2788 | done: | ||
2789 | hci_dev_unlock(hdev); | 3041 | hci_dev_unlock(hdev); |
3042 | |||
2790 | return err; | 3043 | return err; |
2791 | } | 3044 | } |
2792 | 3045 | ||
@@ -3043,79 +3296,115 @@ static void settings_rsp(struct pending_cmd *cmd, void *data) | |||
3043 | mgmt_pending_free(cmd); | 3296 | mgmt_pending_free(cmd); |
3044 | } | 3297 | } |
3045 | 3298 | ||
3046 | static int set_bredr_scan(struct hci_dev *hdev) | 3299 | static void set_bredr_scan(struct hci_request *req) |
3047 | { | 3300 | { |
3301 | struct hci_dev *hdev = req->hdev; | ||
3048 | u8 scan = 0; | 3302 | u8 scan = 0; |
3049 | 3303 | ||
3304 | /* Ensure that fast connectable is disabled. This function will | ||
3305 | * not do anything if the page scan parameters are already what | ||
3306 | * they should be. | ||
3307 | */ | ||
3308 | write_fast_connectable(req, false); | ||
3309 | |||
3050 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) | 3310 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) |
3051 | scan |= SCAN_PAGE; | 3311 | scan |= SCAN_PAGE; |
3052 | if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) | 3312 | if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) |
3053 | scan |= SCAN_INQUIRY; | 3313 | scan |= SCAN_INQUIRY; |
3054 | 3314 | ||
3055 | if (!scan) | 3315 | if (scan) |
3056 | return 0; | 3316 | hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); |
3057 | |||
3058 | return hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | ||
3059 | } | 3317 | } |
3060 | 3318 | ||
3061 | int mgmt_powered(struct hci_dev *hdev, u8 powered) | 3319 | static void powered_complete(struct hci_dev *hdev, u8 status) |
3062 | { | 3320 | { |
3063 | struct cmd_lookup match = { NULL, hdev }; | 3321 | struct cmd_lookup match = { NULL, hdev }; |
3064 | int err; | ||
3065 | 3322 | ||
3066 | if (!test_bit(HCI_MGMT, &hdev->dev_flags)) | 3323 | BT_DBG("status 0x%02x", status); |
3067 | return 0; | 3324 | |
3325 | hci_dev_lock(hdev); | ||
3068 | 3326 | ||
3069 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); | 3327 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); |
3070 | 3328 | ||
3071 | if (powered) { | 3329 | new_settings(hdev, match.sk); |
3072 | u8 link_sec; | ||
3073 | 3330 | ||
3074 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) && | 3331 | hci_dev_unlock(hdev); |
3075 | !lmp_host_ssp_capable(hdev)) { | ||
3076 | u8 ssp = 1; | ||
3077 | 3332 | ||
3078 | hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &ssp); | 3333 | if (match.sk) |
3079 | } | 3334 | sock_put(match.sk); |
3335 | } | ||
3080 | 3336 | ||
3081 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { | 3337 | static int powered_update_hci(struct hci_dev *hdev) |
3082 | struct hci_cp_write_le_host_supported cp; | 3338 | { |
3339 | struct hci_request req; | ||
3340 | u8 link_sec; | ||
3083 | 3341 | ||
3084 | cp.le = 1; | 3342 | hci_req_init(&req, hdev); |
3085 | cp.simul = lmp_le_br_capable(hdev); | ||
3086 | 3343 | ||
3087 | /* Check first if we already have the right | 3344 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) && |
3088 | * host state (host features set) | 3345 | !lmp_host_ssp_capable(hdev)) { |
3089 | */ | 3346 | u8 ssp = 1; |
3090 | if (cp.le != lmp_host_le_capable(hdev) || | ||
3091 | cp.simul != lmp_host_le_br_capable(hdev)) | ||
3092 | hci_send_cmd(hdev, | ||
3093 | HCI_OP_WRITE_LE_HOST_SUPPORTED, | ||
3094 | sizeof(cp), &cp); | ||
3095 | } | ||
3096 | 3347 | ||
3097 | link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags); | 3348 | hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp); |
3098 | if (link_sec != test_bit(HCI_AUTH, &hdev->flags)) | 3349 | } |
3099 | hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, | ||
3100 | sizeof(link_sec), &link_sec); | ||
3101 | 3350 | ||
3102 | if (lmp_bredr_capable(hdev)) { | 3351 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { |
3103 | set_bredr_scan(hdev); | 3352 | struct hci_cp_write_le_host_supported cp; |
3104 | update_class(hdev); | ||
3105 | update_name(hdev, hdev->dev_name); | ||
3106 | update_eir(hdev); | ||
3107 | } | ||
3108 | } else { | ||
3109 | u8 status = MGMT_STATUS_NOT_POWERED; | ||
3110 | u8 zero_cod[] = { 0, 0, 0 }; | ||
3111 | 3353 | ||
3112 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); | 3354 | cp.le = 1; |
3355 | cp.simul = lmp_le_br_capable(hdev); | ||
3113 | 3356 | ||
3114 | if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0) | 3357 | /* Check first if we already have the right |
3115 | mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, | 3358 | * host state (host features set) |
3116 | zero_cod, sizeof(zero_cod), NULL); | 3359 | */ |
3360 | if (cp.le != lmp_host_le_capable(hdev) || | ||
3361 | cp.simul != lmp_host_le_br_capable(hdev)) | ||
3362 | hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, | ||
3363 | sizeof(cp), &cp); | ||
3117 | } | 3364 | } |
3118 | 3365 | ||
3366 | link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags); | ||
3367 | if (link_sec != test_bit(HCI_AUTH, &hdev->flags)) | ||
3368 | hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE, | ||
3369 | sizeof(link_sec), &link_sec); | ||
3370 | |||
3371 | if (lmp_bredr_capable(hdev)) { | ||
3372 | set_bredr_scan(&req); | ||
3373 | update_class(&req); | ||
3374 | update_name(&req); | ||
3375 | update_eir(&req); | ||
3376 | } | ||
3377 | |||
3378 | return hci_req_run(&req, powered_complete); | ||
3379 | } | ||
3380 | |||
3381 | int mgmt_powered(struct hci_dev *hdev, u8 powered) | ||
3382 | { | ||
3383 | struct cmd_lookup match = { NULL, hdev }; | ||
3384 | u8 status_not_powered = MGMT_STATUS_NOT_POWERED; | ||
3385 | u8 zero_cod[] = { 0, 0, 0 }; | ||
3386 | int err; | ||
3387 | |||
3388 | if (!test_bit(HCI_MGMT, &hdev->dev_flags)) | ||
3389 | return 0; | ||
3390 | |||
3391 | if (powered) { | ||
3392 | if (powered_update_hci(hdev) == 0) | ||
3393 | return 0; | ||
3394 | |||
3395 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, | ||
3396 | &match); | ||
3397 | goto new_settings; | ||
3398 | } | ||
3399 | |||
3400 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); | ||
3401 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered); | ||
3402 | |||
3403 | if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0) | ||
3404 | mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, | ||
3405 | zero_cod, sizeof(zero_cod), NULL); | ||
3406 | |||
3407 | new_settings: | ||
3119 | err = new_settings(hdev, match.sk); | 3408 | err = new_settings(hdev, match.sk); |
3120 | 3409 | ||
3121 | if (match.sk) | 3410 | if (match.sk) |
@@ -3152,7 +3441,7 @@ int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) | |||
3152 | 3441 | ||
3153 | int mgmt_connectable(struct hci_dev *hdev, u8 connectable) | 3442 | int mgmt_connectable(struct hci_dev *hdev, u8 connectable) |
3154 | { | 3443 | { |
3155 | struct cmd_lookup match = { NULL, hdev }; | 3444 | struct pending_cmd *cmd; |
3156 | bool changed = false; | 3445 | bool changed = false; |
3157 | int err = 0; | 3446 | int err = 0; |
3158 | 3447 | ||
@@ -3164,14 +3453,10 @@ int mgmt_connectable(struct hci_dev *hdev, u8 connectable) | |||
3164 | changed = true; | 3453 | changed = true; |
3165 | } | 3454 | } |
3166 | 3455 | ||
3167 | mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, settings_rsp, | 3456 | cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev); |
3168 | &match); | ||
3169 | 3457 | ||
3170 | if (changed) | 3458 | if (changed) |
3171 | err = new_settings(hdev, match.sk); | 3459 | err = new_settings(hdev, cmd ? cmd->sk : NULL); |
3172 | |||
3173 | if (match.sk) | ||
3174 | sock_put(match.sk); | ||
3175 | 3460 | ||
3176 | return err; | 3461 | return err; |
3177 | } | 3462 | } |
@@ -3555,23 +3840,25 @@ int mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status) | |||
3555 | return err; | 3840 | return err; |
3556 | } | 3841 | } |
3557 | 3842 | ||
3558 | static int clear_eir(struct hci_dev *hdev) | 3843 | static void clear_eir(struct hci_request *req) |
3559 | { | 3844 | { |
3845 | struct hci_dev *hdev = req->hdev; | ||
3560 | struct hci_cp_write_eir cp; | 3846 | struct hci_cp_write_eir cp; |
3561 | 3847 | ||
3562 | if (!lmp_ext_inq_capable(hdev)) | 3848 | if (!lmp_ext_inq_capable(hdev)) |
3563 | return 0; | 3849 | return; |
3564 | 3850 | ||
3565 | memset(hdev->eir, 0, sizeof(hdev->eir)); | 3851 | memset(hdev->eir, 0, sizeof(hdev->eir)); |
3566 | 3852 | ||
3567 | memset(&cp, 0, sizeof(cp)); | 3853 | memset(&cp, 0, sizeof(cp)); |
3568 | 3854 | ||
3569 | return hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp); | 3855 | hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp); |
3570 | } | 3856 | } |
3571 | 3857 | ||
3572 | int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) | 3858 | int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) |
3573 | { | 3859 | { |
3574 | struct cmd_lookup match = { NULL, hdev }; | 3860 | struct cmd_lookup match = { NULL, hdev }; |
3861 | struct hci_request req; | ||
3575 | bool changed = false; | 3862 | bool changed = false; |
3576 | int err = 0; | 3863 | int err = 0; |
3577 | 3864 | ||
@@ -3604,29 +3891,26 @@ int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) | |||
3604 | if (match.sk) | 3891 | if (match.sk) |
3605 | sock_put(match.sk); | 3892 | sock_put(match.sk); |
3606 | 3893 | ||
3894 | hci_req_init(&req, hdev); | ||
3895 | |||
3607 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) | 3896 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) |
3608 | update_eir(hdev); | 3897 | update_eir(&req); |
3609 | else | 3898 | else |
3610 | clear_eir(hdev); | 3899 | clear_eir(&req); |
3900 | |||
3901 | hci_req_run(&req, NULL); | ||
3611 | 3902 | ||
3612 | return err; | 3903 | return err; |
3613 | } | 3904 | } |
3614 | 3905 | ||
3615 | static void class_rsp(struct pending_cmd *cmd, void *data) | 3906 | static void sk_lookup(struct pending_cmd *cmd, void *data) |
3616 | { | 3907 | { |
3617 | struct cmd_lookup *match = data; | 3908 | struct cmd_lookup *match = data; |
3618 | 3909 | ||
3619 | cmd_complete(cmd->sk, cmd->index, cmd->opcode, match->mgmt_status, | ||
3620 | match->hdev->dev_class, 3); | ||
3621 | |||
3622 | list_del(&cmd->list); | ||
3623 | |||
3624 | if (match->sk == NULL) { | 3910 | if (match->sk == NULL) { |
3625 | match->sk = cmd->sk; | 3911 | match->sk = cmd->sk; |
3626 | sock_hold(match->sk); | 3912 | sock_hold(match->sk); |
3627 | } | 3913 | } |
3628 | |||
3629 | mgmt_pending_free(cmd); | ||
3630 | } | 3914 | } |
3631 | 3915 | ||
3632 | int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, | 3916 | int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, |
@@ -3635,11 +3919,9 @@ int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, | |||
3635 | struct cmd_lookup match = { NULL, hdev, mgmt_status(status) }; | 3919 | struct cmd_lookup match = { NULL, hdev, mgmt_status(status) }; |
3636 | int err = 0; | 3920 | int err = 0; |
3637 | 3921 | ||
3638 | clear_bit(HCI_PENDING_CLASS, &hdev->dev_flags); | 3922 | mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match); |
3639 | 3923 | mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match); | |
3640 | mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, class_rsp, &match); | 3924 | mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match); |
3641 | mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, class_rsp, &match); | ||
3642 | mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, class_rsp, &match); | ||
3643 | 3925 | ||
3644 | if (!status) | 3926 | if (!status) |
3645 | err = mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, | 3927 | err = mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, |
@@ -3653,55 +3935,29 @@ int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, | |||
3653 | 3935 | ||
3654 | int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status) | 3936 | int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status) |
3655 | { | 3937 | { |
3656 | struct pending_cmd *cmd; | ||
3657 | struct mgmt_cp_set_local_name ev; | 3938 | struct mgmt_cp_set_local_name ev; |
3658 | bool changed = false; | 3939 | struct pending_cmd *cmd; |
3659 | int err = 0; | ||
3660 | 3940 | ||
3661 | if (memcmp(name, hdev->dev_name, sizeof(hdev->dev_name)) != 0) { | 3941 | if (status) |
3662 | memcpy(hdev->dev_name, name, sizeof(hdev->dev_name)); | 3942 | return 0; |
3663 | changed = true; | ||
3664 | } | ||
3665 | 3943 | ||
3666 | memset(&ev, 0, sizeof(ev)); | 3944 | memset(&ev, 0, sizeof(ev)); |
3667 | memcpy(ev.name, name, HCI_MAX_NAME_LENGTH); | 3945 | memcpy(ev.name, name, HCI_MAX_NAME_LENGTH); |
3668 | memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH); | 3946 | memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH); |
3669 | 3947 | ||
3670 | cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev); | 3948 | cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev); |
3671 | if (!cmd) | 3949 | if (!cmd) { |
3672 | goto send_event; | 3950 | memcpy(hdev->dev_name, name, sizeof(hdev->dev_name)); |
3673 | |||
3674 | /* Always assume that either the short or the complete name has | ||
3675 | * changed if there was a pending mgmt command */ | ||
3676 | changed = true; | ||
3677 | 3951 | ||
3678 | if (status) { | 3952 | /* If this is a HCI command related to powering on the |
3679 | err = cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, | 3953 | * HCI dev don't send any mgmt signals. |
3680 | mgmt_status(status)); | 3954 | */ |
3681 | goto failed; | 3955 | if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) |
3956 | return 0; | ||
3682 | } | 3957 | } |
3683 | 3958 | ||
3684 | err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0, &ev, | 3959 | return mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev), |
3685 | sizeof(ev)); | 3960 | cmd ? cmd->sk : NULL); |
3686 | if (err < 0) | ||
3687 | goto failed; | ||
3688 | |||
3689 | send_event: | ||
3690 | if (changed) | ||
3691 | err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, | ||
3692 | sizeof(ev), cmd ? cmd->sk : NULL); | ||
3693 | |||
3694 | /* EIR is taken care of separately when powering on the | ||
3695 | * adapter so only update them here if this is a name change | ||
3696 | * unrelated to power on. | ||
3697 | */ | ||
3698 | if (!test_bit(HCI_INIT, &hdev->flags)) | ||
3699 | update_eir(hdev); | ||
3700 | |||
3701 | failed: | ||
3702 | if (cmd) | ||
3703 | mgmt_pending_remove(cmd); | ||
3704 | return err; | ||
3705 | } | 3961 | } |
3706 | 3962 | ||
3707 | int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, | 3963 | int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index b23e2713fea8..ca957d34b0c8 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -69,7 +69,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, | |||
69 | u8 sec_level, | 69 | u8 sec_level, |
70 | int *err); | 70 | int *err); |
71 | static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst); | 71 | static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst); |
72 | static void rfcomm_session_del(struct rfcomm_session *s); | 72 | static struct rfcomm_session *rfcomm_session_del(struct rfcomm_session *s); |
73 | 73 | ||
74 | /* ---- RFCOMM frame parsing macros ---- */ | 74 | /* ---- RFCOMM frame parsing macros ---- */ |
75 | #define __get_dlci(b) ((b & 0xfc) >> 2) | 75 | #define __get_dlci(b) ((b & 0xfc) >> 2) |
@@ -108,12 +108,6 @@ static void rfcomm_schedule(void) | |||
108 | wake_up_process(rfcomm_thread); | 108 | wake_up_process(rfcomm_thread); |
109 | } | 109 | } |
110 | 110 | ||
111 | static void rfcomm_session_put(struct rfcomm_session *s) | ||
112 | { | ||
113 | if (atomic_dec_and_test(&s->refcnt)) | ||
114 | rfcomm_session_del(s); | ||
115 | } | ||
116 | |||
117 | /* ---- RFCOMM FCS computation ---- */ | 111 | /* ---- RFCOMM FCS computation ---- */ |
118 | 112 | ||
119 | /* reversed, 8-bit, poly=0x07 */ | 113 | /* reversed, 8-bit, poly=0x07 */ |
@@ -249,16 +243,14 @@ static void rfcomm_session_set_timer(struct rfcomm_session *s, long timeout) | |||
249 | { | 243 | { |
250 | BT_DBG("session %p state %ld timeout %ld", s, s->state, timeout); | 244 | BT_DBG("session %p state %ld timeout %ld", s, s->state, timeout); |
251 | 245 | ||
252 | if (!mod_timer(&s->timer, jiffies + timeout)) | 246 | mod_timer(&s->timer, jiffies + timeout); |
253 | rfcomm_session_hold(s); | ||
254 | } | 247 | } |
255 | 248 | ||
256 | static void rfcomm_session_clear_timer(struct rfcomm_session *s) | 249 | static void rfcomm_session_clear_timer(struct rfcomm_session *s) |
257 | { | 250 | { |
258 | BT_DBG("session %p state %ld", s, s->state); | 251 | BT_DBG("session %p state %ld", s, s->state); |
259 | 252 | ||
260 | if (del_timer(&s->timer)) | 253 | del_timer_sync(&s->timer); |
261 | rfcomm_session_put(s); | ||
262 | } | 254 | } |
263 | 255 | ||
264 | /* ---- RFCOMM DLCs ---- */ | 256 | /* ---- RFCOMM DLCs ---- */ |
@@ -336,8 +328,6 @@ static void rfcomm_dlc_link(struct rfcomm_session *s, struct rfcomm_dlc *d) | |||
336 | { | 328 | { |
337 | BT_DBG("dlc %p session %p", d, s); | 329 | BT_DBG("dlc %p session %p", d, s); |
338 | 330 | ||
339 | rfcomm_session_hold(s); | ||
340 | |||
341 | rfcomm_session_clear_timer(s); | 331 | rfcomm_session_clear_timer(s); |
342 | rfcomm_dlc_hold(d); | 332 | rfcomm_dlc_hold(d); |
343 | list_add(&d->list, &s->dlcs); | 333 | list_add(&d->list, &s->dlcs); |
@@ -356,8 +346,6 @@ static void rfcomm_dlc_unlink(struct rfcomm_dlc *d) | |||
356 | 346 | ||
357 | if (list_empty(&s->dlcs)) | 347 | if (list_empty(&s->dlcs)) |
358 | rfcomm_session_set_timer(s, RFCOMM_IDLE_TIMEOUT); | 348 | rfcomm_session_set_timer(s, RFCOMM_IDLE_TIMEOUT); |
359 | |||
360 | rfcomm_session_put(s); | ||
361 | } | 349 | } |
362 | 350 | ||
363 | static struct rfcomm_dlc *rfcomm_dlc_get(struct rfcomm_session *s, u8 dlci) | 351 | static struct rfcomm_dlc *rfcomm_dlc_get(struct rfcomm_session *s, u8 dlci) |
@@ -493,12 +481,34 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err) | |||
493 | 481 | ||
494 | int rfcomm_dlc_close(struct rfcomm_dlc *d, int err) | 482 | int rfcomm_dlc_close(struct rfcomm_dlc *d, int err) |
495 | { | 483 | { |
496 | int r; | 484 | int r = 0; |
485 | struct rfcomm_dlc *d_list; | ||
486 | struct rfcomm_session *s, *s_list; | ||
487 | |||
488 | BT_DBG("dlc %p state %ld dlci %d err %d", d, d->state, d->dlci, err); | ||
497 | 489 | ||
498 | rfcomm_lock(); | 490 | rfcomm_lock(); |
499 | 491 | ||
500 | r = __rfcomm_dlc_close(d, err); | 492 | s = d->session; |
493 | if (!s) | ||
494 | goto no_session; | ||
495 | |||
496 | /* after waiting on the mutex check the session still exists | ||
497 | * then check the dlc still exists | ||
498 | */ | ||
499 | list_for_each_entry(s_list, &session_list, list) { | ||
500 | if (s_list == s) { | ||
501 | list_for_each_entry(d_list, &s->dlcs, list) { | ||
502 | if (d_list == d) { | ||
503 | r = __rfcomm_dlc_close(d, err); | ||
504 | break; | ||
505 | } | ||
506 | } | ||
507 | break; | ||
508 | } | ||
509 | } | ||
501 | 510 | ||
511 | no_session: | ||
502 | rfcomm_unlock(); | 512 | rfcomm_unlock(); |
503 | return r; | 513 | return r; |
504 | } | 514 | } |
@@ -609,7 +619,7 @@ static struct rfcomm_session *rfcomm_session_add(struct socket *sock, int state) | |||
609 | return s; | 619 | return s; |
610 | } | 620 | } |
611 | 621 | ||
612 | static void rfcomm_session_del(struct rfcomm_session *s) | 622 | static struct rfcomm_session *rfcomm_session_del(struct rfcomm_session *s) |
613 | { | 623 | { |
614 | int state = s->state; | 624 | int state = s->state; |
615 | 625 | ||
@@ -617,15 +627,14 @@ static void rfcomm_session_del(struct rfcomm_session *s) | |||
617 | 627 | ||
618 | list_del(&s->list); | 628 | list_del(&s->list); |
619 | 629 | ||
620 | if (state == BT_CONNECTED) | ||
621 | rfcomm_send_disc(s, 0); | ||
622 | |||
623 | rfcomm_session_clear_timer(s); | 630 | rfcomm_session_clear_timer(s); |
624 | sock_release(s->sock); | 631 | sock_release(s->sock); |
625 | kfree(s); | 632 | kfree(s); |
626 | 633 | ||
627 | if (state != BT_LISTEN) | 634 | if (state != BT_LISTEN) |
628 | module_put(THIS_MODULE); | 635 | module_put(THIS_MODULE); |
636 | |||
637 | return NULL; | ||
629 | } | 638 | } |
630 | 639 | ||
631 | static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst) | 640 | static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst) |
@@ -644,17 +653,16 @@ static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst) | |||
644 | return NULL; | 653 | return NULL; |
645 | } | 654 | } |
646 | 655 | ||
647 | static void rfcomm_session_close(struct rfcomm_session *s, int err) | 656 | static struct rfcomm_session *rfcomm_session_close(struct rfcomm_session *s, |
657 | int err) | ||
648 | { | 658 | { |
649 | struct rfcomm_dlc *d; | 659 | struct rfcomm_dlc *d; |
650 | struct list_head *p, *n; | 660 | struct list_head *p, *n; |
651 | 661 | ||
652 | BT_DBG("session %p state %ld err %d", s, s->state, err); | ||
653 | |||
654 | rfcomm_session_hold(s); | ||
655 | |||
656 | s->state = BT_CLOSED; | 662 | s->state = BT_CLOSED; |
657 | 663 | ||
664 | BT_DBG("session %p state %ld err %d", s, s->state, err); | ||
665 | |||
658 | /* Close all dlcs */ | 666 | /* Close all dlcs */ |
659 | list_for_each_safe(p, n, &s->dlcs) { | 667 | list_for_each_safe(p, n, &s->dlcs) { |
660 | d = list_entry(p, struct rfcomm_dlc, list); | 668 | d = list_entry(p, struct rfcomm_dlc, list); |
@@ -663,7 +671,7 @@ static void rfcomm_session_close(struct rfcomm_session *s, int err) | |||
663 | } | 671 | } |
664 | 672 | ||
665 | rfcomm_session_clear_timer(s); | 673 | rfcomm_session_clear_timer(s); |
666 | rfcomm_session_put(s); | 674 | return rfcomm_session_del(s); |
667 | } | 675 | } |
668 | 676 | ||
669 | static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, | 677 | static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, |
@@ -715,8 +723,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, | |||
715 | if (*err == 0 || *err == -EINPROGRESS) | 723 | if (*err == 0 || *err == -EINPROGRESS) |
716 | return s; | 724 | return s; |
717 | 725 | ||
718 | rfcomm_session_del(s); | 726 | return rfcomm_session_del(s); |
719 | return NULL; | ||
720 | 727 | ||
721 | failed: | 728 | failed: |
722 | sock_release(sock); | 729 | sock_release(sock); |
@@ -1105,7 +1112,7 @@ static void rfcomm_make_uih(struct sk_buff *skb, u8 addr) | |||
1105 | } | 1112 | } |
1106 | 1113 | ||
1107 | /* ---- RFCOMM frame reception ---- */ | 1114 | /* ---- RFCOMM frame reception ---- */ |
1108 | static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci) | 1115 | static struct rfcomm_session *rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci) |
1109 | { | 1116 | { |
1110 | BT_DBG("session %p state %ld dlci %d", s, s->state, dlci); | 1117 | BT_DBG("session %p state %ld dlci %d", s, s->state, dlci); |
1111 | 1118 | ||
@@ -1114,7 +1121,7 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci) | |||
1114 | struct rfcomm_dlc *d = rfcomm_dlc_get(s, dlci); | 1121 | struct rfcomm_dlc *d = rfcomm_dlc_get(s, dlci); |
1115 | if (!d) { | 1122 | if (!d) { |
1116 | rfcomm_send_dm(s, dlci); | 1123 | rfcomm_send_dm(s, dlci); |
1117 | return 0; | 1124 | return s; |
1118 | } | 1125 | } |
1119 | 1126 | ||
1120 | switch (d->state) { | 1127 | switch (d->state) { |
@@ -1150,25 +1157,14 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci) | |||
1150 | break; | 1157 | break; |
1151 | 1158 | ||
1152 | case BT_DISCONN: | 1159 | case BT_DISCONN: |
1153 | /* rfcomm_session_put is called later so don't do | 1160 | s = rfcomm_session_close(s, ECONNRESET); |
1154 | * anything here otherwise we will mess up the session | ||
1155 | * reference counter: | ||
1156 | * | ||
1157 | * (a) when we are the initiator dlc_unlink will drive | ||
1158 | * the reference counter to 0 (there is no initial put | ||
1159 | * after session_add) | ||
1160 | * | ||
1161 | * (b) when we are not the initiator rfcomm_rx_process | ||
1162 | * will explicitly call put to balance the initial hold | ||
1163 | * done after session add. | ||
1164 | */ | ||
1165 | break; | 1161 | break; |
1166 | } | 1162 | } |
1167 | } | 1163 | } |
1168 | return 0; | 1164 | return s; |
1169 | } | 1165 | } |
1170 | 1166 | ||
1171 | static int rfcomm_recv_dm(struct rfcomm_session *s, u8 dlci) | 1167 | static struct rfcomm_session *rfcomm_recv_dm(struct rfcomm_session *s, u8 dlci) |
1172 | { | 1168 | { |
1173 | int err = 0; | 1169 | int err = 0; |
1174 | 1170 | ||
@@ -1192,13 +1188,13 @@ static int rfcomm_recv_dm(struct rfcomm_session *s, u8 dlci) | |||
1192 | else | 1188 | else |
1193 | err = ECONNRESET; | 1189 | err = ECONNRESET; |
1194 | 1190 | ||
1195 | s->state = BT_CLOSED; | 1191 | s = rfcomm_session_close(s, err); |
1196 | rfcomm_session_close(s, err); | ||
1197 | } | 1192 | } |
1198 | return 0; | 1193 | return s; |
1199 | } | 1194 | } |
1200 | 1195 | ||
1201 | static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci) | 1196 | static struct rfcomm_session *rfcomm_recv_disc(struct rfcomm_session *s, |
1197 | u8 dlci) | ||
1202 | { | 1198 | { |
1203 | int err = 0; | 1199 | int err = 0; |
1204 | 1200 | ||
@@ -1227,11 +1223,9 @@ static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci) | |||
1227 | else | 1223 | else |
1228 | err = ECONNRESET; | 1224 | err = ECONNRESET; |
1229 | 1225 | ||
1230 | s->state = BT_CLOSED; | 1226 | s = rfcomm_session_close(s, err); |
1231 | rfcomm_session_close(s, err); | ||
1232 | } | 1227 | } |
1233 | 1228 | return s; | |
1234 | return 0; | ||
1235 | } | 1229 | } |
1236 | 1230 | ||
1237 | void rfcomm_dlc_accept(struct rfcomm_dlc *d) | 1231 | void rfcomm_dlc_accept(struct rfcomm_dlc *d) |
@@ -1652,11 +1646,18 @@ drop: | |||
1652 | return 0; | 1646 | return 0; |
1653 | } | 1647 | } |
1654 | 1648 | ||
1655 | static int rfcomm_recv_frame(struct rfcomm_session *s, struct sk_buff *skb) | 1649 | static struct rfcomm_session *rfcomm_recv_frame(struct rfcomm_session *s, |
1650 | struct sk_buff *skb) | ||
1656 | { | 1651 | { |
1657 | struct rfcomm_hdr *hdr = (void *) skb->data; | 1652 | struct rfcomm_hdr *hdr = (void *) skb->data; |
1658 | u8 type, dlci, fcs; | 1653 | u8 type, dlci, fcs; |
1659 | 1654 | ||
1655 | if (!s) { | ||
1656 | /* no session, so free socket data */ | ||
1657 | kfree_skb(skb); | ||
1658 | return s; | ||
1659 | } | ||
1660 | |||
1660 | dlci = __get_dlci(hdr->addr); | 1661 | dlci = __get_dlci(hdr->addr); |
1661 | type = __get_type(hdr->ctrl); | 1662 | type = __get_type(hdr->ctrl); |
1662 | 1663 | ||
@@ -1667,7 +1668,7 @@ static int rfcomm_recv_frame(struct rfcomm_session *s, struct sk_buff *skb) | |||
1667 | if (__check_fcs(skb->data, type, fcs)) { | 1668 | if (__check_fcs(skb->data, type, fcs)) { |
1668 | BT_ERR("bad checksum in packet"); | 1669 | BT_ERR("bad checksum in packet"); |
1669 | kfree_skb(skb); | 1670 | kfree_skb(skb); |
1670 | return -EILSEQ; | 1671 | return s; |
1671 | } | 1672 | } |
1672 | 1673 | ||
1673 | if (__test_ea(hdr->len)) | 1674 | if (__test_ea(hdr->len)) |
@@ -1683,22 +1684,23 @@ static int rfcomm_recv_frame(struct rfcomm_session *s, struct sk_buff *skb) | |||
1683 | 1684 | ||
1684 | case RFCOMM_DISC: | 1685 | case RFCOMM_DISC: |
1685 | if (__test_pf(hdr->ctrl)) | 1686 | if (__test_pf(hdr->ctrl)) |
1686 | rfcomm_recv_disc(s, dlci); | 1687 | s = rfcomm_recv_disc(s, dlci); |
1687 | break; | 1688 | break; |
1688 | 1689 | ||
1689 | case RFCOMM_UA: | 1690 | case RFCOMM_UA: |
1690 | if (__test_pf(hdr->ctrl)) | 1691 | if (__test_pf(hdr->ctrl)) |
1691 | rfcomm_recv_ua(s, dlci); | 1692 | s = rfcomm_recv_ua(s, dlci); |
1692 | break; | 1693 | break; |
1693 | 1694 | ||
1694 | case RFCOMM_DM: | 1695 | case RFCOMM_DM: |
1695 | rfcomm_recv_dm(s, dlci); | 1696 | s = rfcomm_recv_dm(s, dlci); |
1696 | break; | 1697 | break; |
1697 | 1698 | ||
1698 | case RFCOMM_UIH: | 1699 | case RFCOMM_UIH: |
1699 | if (dlci) | 1700 | if (dlci) { |
1700 | return rfcomm_recv_data(s, dlci, __test_pf(hdr->ctrl), skb); | 1701 | rfcomm_recv_data(s, dlci, __test_pf(hdr->ctrl), skb); |
1701 | 1702 | return s; | |
1703 | } | ||
1702 | rfcomm_recv_mcc(s, skb); | 1704 | rfcomm_recv_mcc(s, skb); |
1703 | break; | 1705 | break; |
1704 | 1706 | ||
@@ -1707,7 +1709,7 @@ static int rfcomm_recv_frame(struct rfcomm_session *s, struct sk_buff *skb) | |||
1707 | break; | 1709 | break; |
1708 | } | 1710 | } |
1709 | kfree_skb(skb); | 1711 | kfree_skb(skb); |
1710 | return 0; | 1712 | return s; |
1711 | } | 1713 | } |
1712 | 1714 | ||
1713 | /* ---- Connection and data processing ---- */ | 1715 | /* ---- Connection and data processing ---- */ |
@@ -1844,7 +1846,7 @@ static void rfcomm_process_dlcs(struct rfcomm_session *s) | |||
1844 | } | 1846 | } |
1845 | } | 1847 | } |
1846 | 1848 | ||
1847 | static void rfcomm_process_rx(struct rfcomm_session *s) | 1849 | static struct rfcomm_session *rfcomm_process_rx(struct rfcomm_session *s) |
1848 | { | 1850 | { |
1849 | struct socket *sock = s->sock; | 1851 | struct socket *sock = s->sock; |
1850 | struct sock *sk = sock->sk; | 1852 | struct sock *sk = sock->sk; |
@@ -1856,17 +1858,15 @@ static void rfcomm_process_rx(struct rfcomm_session *s) | |||
1856 | while ((skb = skb_dequeue(&sk->sk_receive_queue))) { | 1858 | while ((skb = skb_dequeue(&sk->sk_receive_queue))) { |
1857 | skb_orphan(skb); | 1859 | skb_orphan(skb); |
1858 | if (!skb_linearize(skb)) | 1860 | if (!skb_linearize(skb)) |
1859 | rfcomm_recv_frame(s, skb); | 1861 | s = rfcomm_recv_frame(s, skb); |
1860 | else | 1862 | else |
1861 | kfree_skb(skb); | 1863 | kfree_skb(skb); |
1862 | } | 1864 | } |
1863 | 1865 | ||
1864 | if (sk->sk_state == BT_CLOSED) { | 1866 | if (s && (sk->sk_state == BT_CLOSED)) |
1865 | if (!s->initiator) | 1867 | s = rfcomm_session_close(s, sk->sk_err); |
1866 | rfcomm_session_put(s); | ||
1867 | 1868 | ||
1868 | rfcomm_session_close(s, sk->sk_err); | 1869 | return s; |
1869 | } | ||
1870 | } | 1870 | } |
1871 | 1871 | ||
1872 | static void rfcomm_accept_connection(struct rfcomm_session *s) | 1872 | static void rfcomm_accept_connection(struct rfcomm_session *s) |
@@ -1891,8 +1891,6 @@ static void rfcomm_accept_connection(struct rfcomm_session *s) | |||
1891 | 1891 | ||
1892 | s = rfcomm_session_add(nsock, BT_OPEN); | 1892 | s = rfcomm_session_add(nsock, BT_OPEN); |
1893 | if (s) { | 1893 | if (s) { |
1894 | rfcomm_session_hold(s); | ||
1895 | |||
1896 | /* We should adjust MTU on incoming sessions. | 1894 | /* We should adjust MTU on incoming sessions. |
1897 | * L2CAP MTU minus UIH header and FCS. */ | 1895 | * L2CAP MTU minus UIH header and FCS. */ |
1898 | s->mtu = min(l2cap_pi(nsock->sk)->chan->omtu, | 1896 | s->mtu = min(l2cap_pi(nsock->sk)->chan->omtu, |
@@ -1903,7 +1901,7 @@ static void rfcomm_accept_connection(struct rfcomm_session *s) | |||
1903 | sock_release(nsock); | 1901 | sock_release(nsock); |
1904 | } | 1902 | } |
1905 | 1903 | ||
1906 | static void rfcomm_check_connection(struct rfcomm_session *s) | 1904 | static struct rfcomm_session *rfcomm_check_connection(struct rfcomm_session *s) |
1907 | { | 1905 | { |
1908 | struct sock *sk = s->sock->sk; | 1906 | struct sock *sk = s->sock->sk; |
1909 | 1907 | ||
@@ -1921,10 +1919,10 @@ static void rfcomm_check_connection(struct rfcomm_session *s) | |||
1921 | break; | 1919 | break; |
1922 | 1920 | ||
1923 | case BT_CLOSED: | 1921 | case BT_CLOSED: |
1924 | s->state = BT_CLOSED; | 1922 | s = rfcomm_session_close(s, sk->sk_err); |
1925 | rfcomm_session_close(s, sk->sk_err); | ||
1926 | break; | 1923 | break; |
1927 | } | 1924 | } |
1925 | return s; | ||
1928 | } | 1926 | } |
1929 | 1927 | ||
1930 | static void rfcomm_process_sessions(void) | 1928 | static void rfcomm_process_sessions(void) |
@@ -1940,7 +1938,6 @@ static void rfcomm_process_sessions(void) | |||
1940 | if (test_and_clear_bit(RFCOMM_TIMED_OUT, &s->flags)) { | 1938 | if (test_and_clear_bit(RFCOMM_TIMED_OUT, &s->flags)) { |
1941 | s->state = BT_DISCONN; | 1939 | s->state = BT_DISCONN; |
1942 | rfcomm_send_disc(s, 0); | 1940 | rfcomm_send_disc(s, 0); |
1943 | rfcomm_session_put(s); | ||
1944 | continue; | 1941 | continue; |
1945 | } | 1942 | } |
1946 | 1943 | ||
@@ -1949,21 +1946,18 @@ static void rfcomm_process_sessions(void) | |||
1949 | continue; | 1946 | continue; |
1950 | } | 1947 | } |
1951 | 1948 | ||
1952 | rfcomm_session_hold(s); | ||
1953 | |||
1954 | switch (s->state) { | 1949 | switch (s->state) { |
1955 | case BT_BOUND: | 1950 | case BT_BOUND: |
1956 | rfcomm_check_connection(s); | 1951 | s = rfcomm_check_connection(s); |
1957 | break; | 1952 | break; |
1958 | 1953 | ||
1959 | default: | 1954 | default: |
1960 | rfcomm_process_rx(s); | 1955 | s = rfcomm_process_rx(s); |
1961 | break; | 1956 | break; |
1962 | } | 1957 | } |
1963 | 1958 | ||
1964 | rfcomm_process_dlcs(s); | 1959 | if (s) |
1965 | 1960 | rfcomm_process_dlcs(s); | |
1966 | rfcomm_session_put(s); | ||
1967 | } | 1961 | } |
1968 | 1962 | ||
1969 | rfcomm_unlock(); | 1963 | rfcomm_unlock(); |
@@ -2010,10 +2004,11 @@ static int rfcomm_add_listener(bdaddr_t *ba) | |||
2010 | 2004 | ||
2011 | /* Add listening session */ | 2005 | /* Add listening session */ |
2012 | s = rfcomm_session_add(sock, BT_LISTEN); | 2006 | s = rfcomm_session_add(sock, BT_LISTEN); |
2013 | if (!s) | 2007 | if (!s) { |
2008 | err = -ENOMEM; | ||
2014 | goto failed; | 2009 | goto failed; |
2010 | } | ||
2015 | 2011 | ||
2016 | rfcomm_session_hold(s); | ||
2017 | return 0; | 2012 | return 0; |
2018 | failed: | 2013 | failed: |
2019 | sock_release(sock); | 2014 | sock_release(sock); |
@@ -2071,8 +2066,6 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt) | |||
2071 | if (!s) | 2066 | if (!s) |
2072 | return; | 2067 | return; |
2073 | 2068 | ||
2074 | rfcomm_session_hold(s); | ||
2075 | |||
2076 | list_for_each_safe(p, n, &s->dlcs) { | 2069 | list_for_each_safe(p, n, &s->dlcs) { |
2077 | d = list_entry(p, struct rfcomm_dlc, list); | 2070 | d = list_entry(p, struct rfcomm_dlc, list); |
2078 | 2071 | ||
@@ -2104,8 +2097,6 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt) | |||
2104 | set_bit(RFCOMM_AUTH_REJECT, &d->flags); | 2097 | set_bit(RFCOMM_AUTH_REJECT, &d->flags); |
2105 | } | 2098 | } |
2106 | 2099 | ||
2107 | rfcomm_session_put(s); | ||
2108 | |||
2109 | rfcomm_schedule(); | 2100 | rfcomm_schedule(); |
2110 | } | 2101 | } |
2111 | 2102 | ||
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 7c9224bcce17..a8638b58c4bf 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
@@ -1066,8 +1066,7 @@ void __exit rfcomm_cleanup_sockets(void) | |||
1066 | 1066 | ||
1067 | debugfs_remove(rfcomm_sock_debugfs); | 1067 | debugfs_remove(rfcomm_sock_debugfs); |
1068 | 1068 | ||
1069 | if (bt_sock_unregister(BTPROTO_RFCOMM) < 0) | 1069 | bt_sock_unregister(BTPROTO_RFCOMM); |
1070 | BT_ERR("RFCOMM socket layer unregistration failed"); | ||
1071 | 1070 | ||
1072 | proto_unregister(&rfcomm_proto); | 1071 | proto_unregister(&rfcomm_proto); |
1073 | } | 1072 | } |
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index fb6192c9812e..2c8055350510 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -1113,8 +1113,7 @@ void __exit sco_exit(void) | |||
1113 | 1113 | ||
1114 | debugfs_remove(sco_debugfs); | 1114 | debugfs_remove(sco_debugfs); |
1115 | 1115 | ||
1116 | if (bt_sock_unregister(BTPROTO_SCO) < 0) | 1116 | bt_sock_unregister(BTPROTO_SCO); |
1117 | BT_ERR("SCO socket unregistration failed"); | ||
1118 | 1117 | ||
1119 | proto_unregister(&sco_proto); | 1118 | proto_unregister(&sco_proto); |
1120 | } | 1119 | } |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index c34e6d78a592..c50c19402588 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -175,7 +175,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
175 | * add it to the device after the station. | 175 | * add it to the device after the station. |
176 | */ | 176 | */ |
177 | if (!sta || !test_sta_flag(sta, WLAN_STA_ASSOC)) { | 177 | if (!sta || !test_sta_flag(sta, WLAN_STA_ASSOC)) { |
178 | ieee80211_key_free(sdata->local, key); | 178 | ieee80211_key_free_unused(key); |
179 | err = -ENOENT; | 179 | err = -ENOENT; |
180 | goto out_unlock; | 180 | goto out_unlock; |
181 | } | 181 | } |
@@ -214,8 +214,6 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
214 | } | 214 | } |
215 | 215 | ||
216 | err = ieee80211_key_link(key, sdata, sta); | 216 | err = ieee80211_key_link(key, sdata, sta); |
217 | if (err) | ||
218 | ieee80211_key_free(sdata->local, key); | ||
219 | 217 | ||
220 | out_unlock: | 218 | out_unlock: |
221 | mutex_unlock(&sdata->local->sta_mtx); | 219 | mutex_unlock(&sdata->local->sta_mtx); |
@@ -254,7 +252,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | |||
254 | goto out_unlock; | 252 | goto out_unlock; |
255 | } | 253 | } |
256 | 254 | ||
257 | __ieee80211_key_free(key, true); | 255 | ieee80211_key_free(key, true); |
258 | 256 | ||
259 | ret = 0; | 257 | ret = 0; |
260 | out_unlock: | 258 | out_unlock: |
@@ -445,12 +443,14 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
445 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 443 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
446 | struct ieee80211_local *local = sdata->local; | 444 | struct ieee80211_local *local = sdata->local; |
447 | struct timespec uptime; | 445 | struct timespec uptime; |
446 | u64 packets = 0; | ||
447 | int ac; | ||
448 | 448 | ||
449 | sinfo->generation = sdata->local->sta_generation; | 449 | sinfo->generation = sdata->local->sta_generation; |
450 | 450 | ||
451 | sinfo->filled = STATION_INFO_INACTIVE_TIME | | 451 | sinfo->filled = STATION_INFO_INACTIVE_TIME | |
452 | STATION_INFO_RX_BYTES | | 452 | STATION_INFO_RX_BYTES64 | |
453 | STATION_INFO_TX_BYTES | | 453 | STATION_INFO_TX_BYTES64 | |
454 | STATION_INFO_RX_PACKETS | | 454 | STATION_INFO_RX_PACKETS | |
455 | STATION_INFO_TX_PACKETS | | 455 | STATION_INFO_TX_PACKETS | |
456 | STATION_INFO_TX_RETRIES | | 456 | STATION_INFO_TX_RETRIES | |
@@ -467,10 +467,14 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
467 | sinfo->connected_time = uptime.tv_sec - sta->last_connected; | 467 | sinfo->connected_time = uptime.tv_sec - sta->last_connected; |
468 | 468 | ||
469 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); | 469 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); |
470 | sinfo->tx_bytes = 0; | ||
471 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | ||
472 | sinfo->tx_bytes += sta->tx_bytes[ac]; | ||
473 | packets += sta->tx_packets[ac]; | ||
474 | } | ||
475 | sinfo->tx_packets = packets; | ||
470 | sinfo->rx_bytes = sta->rx_bytes; | 476 | sinfo->rx_bytes = sta->rx_bytes; |
471 | sinfo->tx_bytes = sta->tx_bytes; | ||
472 | sinfo->rx_packets = sta->rx_packets; | 477 | sinfo->rx_packets = sta->rx_packets; |
473 | sinfo->tx_packets = sta->tx_packets; | ||
474 | sinfo->tx_retries = sta->tx_retry_count; | 478 | sinfo->tx_retries = sta->tx_retry_count; |
475 | sinfo->tx_failed = sta->tx_retry_failed; | 479 | sinfo->tx_failed = sta->tx_retry_failed; |
476 | sinfo->rx_dropped_misc = sta->rx_dropped; | 480 | sinfo->rx_dropped_misc = sta->rx_dropped; |
@@ -598,8 +602,8 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy, | |||
598 | data[i++] += sta->rx_fragments; \ | 602 | data[i++] += sta->rx_fragments; \ |
599 | data[i++] += sta->rx_dropped; \ | 603 | data[i++] += sta->rx_dropped; \ |
600 | \ | 604 | \ |
601 | data[i++] += sta->tx_packets; \ | 605 | data[i++] += sinfo.tx_packets; \ |
602 | data[i++] += sta->tx_bytes; \ | 606 | data[i++] += sinfo.tx_bytes; \ |
603 | data[i++] += sta->tx_fragments; \ | 607 | data[i++] += sta->tx_fragments; \ |
604 | data[i++] += sta->tx_filtered_count; \ | 608 | data[i++] += sta->tx_filtered_count; \ |
605 | data[i++] += sta->tx_retry_failed; \ | 609 | data[i++] += sta->tx_retry_failed; \ |
@@ -621,13 +625,14 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy, | |||
621 | if (!(sta && !WARN_ON(sta->sdata->dev != dev))) | 625 | if (!(sta && !WARN_ON(sta->sdata->dev != dev))) |
622 | goto do_survey; | 626 | goto do_survey; |
623 | 627 | ||
628 | sinfo.filled = 0; | ||
629 | sta_set_sinfo(sta, &sinfo); | ||
630 | |||
624 | i = 0; | 631 | i = 0; |
625 | ADD_STA_STATS(sta); | 632 | ADD_STA_STATS(sta); |
626 | 633 | ||
627 | data[i++] = sta->sta_state; | 634 | data[i++] = sta->sta_state; |
628 | 635 | ||
629 | sinfo.filled = 0; | ||
630 | sta_set_sinfo(sta, &sinfo); | ||
631 | 636 | ||
632 | if (sinfo.filled & STATION_INFO_TX_BITRATE) | 637 | if (sinfo.filled & STATION_INFO_TX_BITRATE) |
633 | data[i] = 100000 * | 638 | data[i] = 100000 * |
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index c3a3082b72e5..1521cabad3d6 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c | |||
@@ -295,7 +295,7 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) | |||
295 | char buf[50]; | 295 | char buf[50]; |
296 | struct ieee80211_key *key; | 296 | struct ieee80211_key *key; |
297 | 297 | ||
298 | if (!sdata->debugfs.dir) | 298 | if (!sdata->vif.debugfs_dir) |
299 | return; | 299 | return; |
300 | 300 | ||
301 | lockdep_assert_held(&sdata->local->key_mtx); | 301 | lockdep_assert_held(&sdata->local->key_mtx); |
@@ -311,7 +311,7 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) | |||
311 | sprintf(buf, "../keys/%d", key->debugfs.cnt); | 311 | sprintf(buf, "../keys/%d", key->debugfs.cnt); |
312 | sdata->debugfs.default_unicast_key = | 312 | sdata->debugfs.default_unicast_key = |
313 | debugfs_create_symlink("default_unicast_key", | 313 | debugfs_create_symlink("default_unicast_key", |
314 | sdata->debugfs.dir, buf); | 314 | sdata->vif.debugfs_dir, buf); |
315 | } | 315 | } |
316 | 316 | ||
317 | if (sdata->debugfs.default_multicast_key) { | 317 | if (sdata->debugfs.default_multicast_key) { |
@@ -325,7 +325,7 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) | |||
325 | sprintf(buf, "../keys/%d", key->debugfs.cnt); | 325 | sprintf(buf, "../keys/%d", key->debugfs.cnt); |
326 | sdata->debugfs.default_multicast_key = | 326 | sdata->debugfs.default_multicast_key = |
327 | debugfs_create_symlink("default_multicast_key", | 327 | debugfs_create_symlink("default_multicast_key", |
328 | sdata->debugfs.dir, buf); | 328 | sdata->vif.debugfs_dir, buf); |
329 | } | 329 | } |
330 | } | 330 | } |
331 | 331 | ||
@@ -334,7 +334,7 @@ void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata) | |||
334 | char buf[50]; | 334 | char buf[50]; |
335 | struct ieee80211_key *key; | 335 | struct ieee80211_key *key; |
336 | 336 | ||
337 | if (!sdata->debugfs.dir) | 337 | if (!sdata->vif.debugfs_dir) |
338 | return; | 338 | return; |
339 | 339 | ||
340 | key = key_mtx_dereference(sdata->local, | 340 | key = key_mtx_dereference(sdata->local, |
@@ -343,7 +343,7 @@ void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata) | |||
343 | sprintf(buf, "../keys/%d", key->debugfs.cnt); | 343 | sprintf(buf, "../keys/%d", key->debugfs.cnt); |
344 | sdata->debugfs.default_mgmt_key = | 344 | sdata->debugfs.default_mgmt_key = |
345 | debugfs_create_symlink("default_mgmt_key", | 345 | debugfs_create_symlink("default_mgmt_key", |
346 | sdata->debugfs.dir, buf); | 346 | sdata->vif.debugfs_dir, buf); |
347 | } else | 347 | } else |
348 | ieee80211_debugfs_key_remove_mgmt_default(sdata); | 348 | ieee80211_debugfs_key_remove_mgmt_default(sdata); |
349 | } | 349 | } |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 059bbb82e84f..ddb426867904 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -521,7 +521,7 @@ IEEE80211_IF_FILE(dot11MeshAwakeWindowDuration, | |||
521 | #endif | 521 | #endif |
522 | 522 | ||
523 | #define DEBUGFS_ADD_MODE(name, mode) \ | 523 | #define DEBUGFS_ADD_MODE(name, mode) \ |
524 | debugfs_create_file(#name, mode, sdata->debugfs.dir, \ | 524 | debugfs_create_file(#name, mode, sdata->vif.debugfs_dir, \ |
525 | sdata, &name##_ops); | 525 | sdata, &name##_ops); |
526 | 526 | ||
527 | #define DEBUGFS_ADD(name) DEBUGFS_ADD_MODE(name, 0400) | 527 | #define DEBUGFS_ADD(name) DEBUGFS_ADD_MODE(name, 0400) |
@@ -577,7 +577,7 @@ static void add_mesh_files(struct ieee80211_sub_if_data *sdata) | |||
577 | static void add_mesh_stats(struct ieee80211_sub_if_data *sdata) | 577 | static void add_mesh_stats(struct ieee80211_sub_if_data *sdata) |
578 | { | 578 | { |
579 | struct dentry *dir = debugfs_create_dir("mesh_stats", | 579 | struct dentry *dir = debugfs_create_dir("mesh_stats", |
580 | sdata->debugfs.dir); | 580 | sdata->vif.debugfs_dir); |
581 | #define MESHSTATS_ADD(name)\ | 581 | #define MESHSTATS_ADD(name)\ |
582 | debugfs_create_file(#name, 0400, dir, sdata, &name##_ops); | 582 | debugfs_create_file(#name, 0400, dir, sdata, &name##_ops); |
583 | 583 | ||
@@ -594,7 +594,7 @@ static void add_mesh_stats(struct ieee80211_sub_if_data *sdata) | |||
594 | static void add_mesh_config(struct ieee80211_sub_if_data *sdata) | 594 | static void add_mesh_config(struct ieee80211_sub_if_data *sdata) |
595 | { | 595 | { |
596 | struct dentry *dir = debugfs_create_dir("mesh_config", | 596 | struct dentry *dir = debugfs_create_dir("mesh_config", |
597 | sdata->debugfs.dir); | 597 | sdata->vif.debugfs_dir); |
598 | 598 | ||
599 | #define MESHPARAMS_ADD(name) \ | 599 | #define MESHPARAMS_ADD(name) \ |
600 | debugfs_create_file(#name, 0600, dir, sdata, &name##_ops); | 600 | debugfs_create_file(#name, 0600, dir, sdata, &name##_ops); |
@@ -631,7 +631,7 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata) | |||
631 | 631 | ||
632 | static void add_files(struct ieee80211_sub_if_data *sdata) | 632 | static void add_files(struct ieee80211_sub_if_data *sdata) |
633 | { | 633 | { |
634 | if (!sdata->debugfs.dir) | 634 | if (!sdata->vif.debugfs_dir) |
635 | return; | 635 | return; |
636 | 636 | ||
637 | DEBUGFS_ADD(flags); | 637 | DEBUGFS_ADD(flags); |
@@ -673,21 +673,21 @@ void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata) | |||
673 | char buf[10+IFNAMSIZ]; | 673 | char buf[10+IFNAMSIZ]; |
674 | 674 | ||
675 | sprintf(buf, "netdev:%s", sdata->name); | 675 | sprintf(buf, "netdev:%s", sdata->name); |
676 | sdata->debugfs.dir = debugfs_create_dir(buf, | 676 | sdata->vif.debugfs_dir = debugfs_create_dir(buf, |
677 | sdata->local->hw.wiphy->debugfsdir); | 677 | sdata->local->hw.wiphy->debugfsdir); |
678 | if (sdata->debugfs.dir) | 678 | if (sdata->vif.debugfs_dir) |
679 | sdata->debugfs.subdir_stations = debugfs_create_dir("stations", | 679 | sdata->debugfs.subdir_stations = debugfs_create_dir("stations", |
680 | sdata->debugfs.dir); | 680 | sdata->vif.debugfs_dir); |
681 | add_files(sdata); | 681 | add_files(sdata); |
682 | } | 682 | } |
683 | 683 | ||
684 | void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata) | 684 | void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata) |
685 | { | 685 | { |
686 | if (!sdata->debugfs.dir) | 686 | if (!sdata->vif.debugfs_dir) |
687 | return; | 687 | return; |
688 | 688 | ||
689 | debugfs_remove_recursive(sdata->debugfs.dir); | 689 | debugfs_remove_recursive(sdata->vif.debugfs_dir); |
690 | sdata->debugfs.dir = NULL; | 690 | sdata->vif.debugfs_dir = NULL; |
691 | } | 691 | } |
692 | 692 | ||
693 | void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata) | 693 | void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata) |
@@ -695,7 +695,7 @@ void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata) | |||
695 | struct dentry *dir; | 695 | struct dentry *dir; |
696 | char buf[10 + IFNAMSIZ]; | 696 | char buf[10 + IFNAMSIZ]; |
697 | 697 | ||
698 | dir = sdata->debugfs.dir; | 698 | dir = sdata->vif.debugfs_dir; |
699 | 699 | ||
700 | if (!dir) | 700 | if (!dir) |
701 | return; | 701 | return; |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 832acea4a5cb..169664c122e2 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -241,6 +241,22 @@ static inline u64 drv_prepare_multicast(struct ieee80211_local *local, | |||
241 | return ret; | 241 | return ret; |
242 | } | 242 | } |
243 | 243 | ||
244 | static inline void drv_set_multicast_list(struct ieee80211_local *local, | ||
245 | struct ieee80211_sub_if_data *sdata, | ||
246 | struct netdev_hw_addr_list *mc_list) | ||
247 | { | ||
248 | bool allmulti = sdata->flags & IEEE80211_SDATA_ALLMULTI; | ||
249 | |||
250 | trace_drv_set_multicast_list(local, sdata, mc_list->count); | ||
251 | |||
252 | check_sdata_in_driver(sdata); | ||
253 | |||
254 | if (local->ops->set_multicast_list) | ||
255 | local->ops->set_multicast_list(&local->hw, &sdata->vif, | ||
256 | allmulti, mc_list); | ||
257 | trace_drv_return_void(local); | ||
258 | } | ||
259 | |||
244 | static inline void drv_configure_filter(struct ieee80211_local *local, | 260 | static inline void drv_configure_filter(struct ieee80211_local *local, |
245 | unsigned int changed_flags, | 261 | unsigned int changed_flags, |
246 | unsigned int *total_flags, | 262 | unsigned int *total_flags, |
@@ -531,43 +547,6 @@ static inline void drv_sta_remove_debugfs(struct ieee80211_local *local, | |||
531 | local->ops->sta_remove_debugfs(&local->hw, &sdata->vif, | 547 | local->ops->sta_remove_debugfs(&local->hw, &sdata->vif, |
532 | sta, dir); | 548 | sta, dir); |
533 | } | 549 | } |
534 | |||
535 | static inline | ||
536 | void drv_add_interface_debugfs(struct ieee80211_local *local, | ||
537 | struct ieee80211_sub_if_data *sdata) | ||
538 | { | ||
539 | might_sleep(); | ||
540 | |||
541 | check_sdata_in_driver(sdata); | ||
542 | |||
543 | if (!local->ops->add_interface_debugfs) | ||
544 | return; | ||
545 | |||
546 | local->ops->add_interface_debugfs(&local->hw, &sdata->vif, | ||
547 | sdata->debugfs.dir); | ||
548 | } | ||
549 | |||
550 | static inline | ||
551 | void drv_remove_interface_debugfs(struct ieee80211_local *local, | ||
552 | struct ieee80211_sub_if_data *sdata) | ||
553 | { | ||
554 | might_sleep(); | ||
555 | |||
556 | check_sdata_in_driver(sdata); | ||
557 | |||
558 | if (!local->ops->remove_interface_debugfs) | ||
559 | return; | ||
560 | |||
561 | local->ops->remove_interface_debugfs(&local->hw, &sdata->vif, | ||
562 | sdata->debugfs.dir); | ||
563 | } | ||
564 | #else | ||
565 | static inline | ||
566 | void drv_add_interface_debugfs(struct ieee80211_local *local, | ||
567 | struct ieee80211_sub_if_data *sdata) {} | ||
568 | static inline | ||
569 | void drv_remove_interface_debugfs(struct ieee80211_local *local, | ||
570 | struct ieee80211_sub_if_data *sdata) {} | ||
571 | #endif | 550 | #endif |
572 | 551 | ||
573 | static inline __must_check | 552 | static inline __must_check |
@@ -741,13 +720,14 @@ static inline void drv_rfkill_poll(struct ieee80211_local *local) | |||
741 | local->ops->rfkill_poll(&local->hw); | 720 | local->ops->rfkill_poll(&local->hw); |
742 | } | 721 | } |
743 | 722 | ||
744 | static inline void drv_flush(struct ieee80211_local *local, bool drop) | 723 | static inline void drv_flush(struct ieee80211_local *local, |
724 | u32 queues, bool drop) | ||
745 | { | 725 | { |
746 | might_sleep(); | 726 | might_sleep(); |
747 | 727 | ||
748 | trace_drv_flush(local, drop); | 728 | trace_drv_flush(local, queues, drop); |
749 | if (local->ops->flush) | 729 | if (local->ops->flush) |
750 | local->ops->flush(&local->hw, drop); | 730 | local->ops->flush(&local->hw, queues, drop); |
751 | trace_drv_return_void(local); | 731 | trace_drv_return_void(local); |
752 | } | 732 | } |
753 | 733 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index e140184c28ce..0b09716d22ad 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -759,7 +759,6 @@ struct ieee80211_sub_if_data { | |||
759 | 759 | ||
760 | #ifdef CONFIG_MAC80211_DEBUGFS | 760 | #ifdef CONFIG_MAC80211_DEBUGFS |
761 | struct { | 761 | struct { |
762 | struct dentry *dir; | ||
763 | struct dentry *subdir_stations; | 762 | struct dentry *subdir_stations; |
764 | struct dentry *default_unicast_key; | 763 | struct dentry *default_unicast_key; |
765 | struct dentry *default_multicast_key; | 764 | struct dentry *default_multicast_key; |
@@ -801,11 +800,6 @@ enum sdata_queue_type { | |||
801 | enum { | 800 | enum { |
802 | IEEE80211_RX_MSG = 1, | 801 | IEEE80211_RX_MSG = 1, |
803 | IEEE80211_TX_STATUS_MSG = 2, | 802 | IEEE80211_TX_STATUS_MSG = 2, |
804 | IEEE80211_EOSP_MSG = 3, | ||
805 | }; | ||
806 | |||
807 | struct skb_eosp_msg_data { | ||
808 | u8 sta[ETH_ALEN], iface[ETH_ALEN]; | ||
809 | }; | 803 | }; |
810 | 804 | ||
811 | enum queue_stop_reason { | 805 | enum queue_stop_reason { |
@@ -816,6 +810,7 @@ enum queue_stop_reason { | |||
816 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, | 810 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, |
817 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, | 811 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, |
818 | IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL, | 812 | IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL, |
813 | IEEE80211_QUEUE_STOP_REASON_FLUSH, | ||
819 | }; | 814 | }; |
820 | 815 | ||
821 | #ifdef CONFIG_MAC80211_LEDS | 816 | #ifdef CONFIG_MAC80211_LEDS |
@@ -1530,8 +1525,10 @@ void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, | |||
1530 | struct ieee80211_hdr *hdr, bool ack); | 1525 | struct ieee80211_hdr *hdr, bool ack); |
1531 | 1526 | ||
1532 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | 1527 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, |
1528 | unsigned long queues, | ||
1533 | enum queue_stop_reason reason); | 1529 | enum queue_stop_reason reason); |
1534 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, | 1530 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, |
1531 | unsigned long queues, | ||
1535 | enum queue_stop_reason reason); | 1532 | enum queue_stop_reason reason); |
1536 | void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, | 1533 | void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, |
1537 | enum queue_stop_reason reason); | 1534 | enum queue_stop_reason reason); |
@@ -1548,6 +1545,8 @@ static inline void ieee80211_add_pending_skbs(struct ieee80211_local *local, | |||
1548 | { | 1545 | { |
1549 | ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL); | 1546 | ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL); |
1550 | } | 1547 | } |
1548 | void ieee80211_flush_queues(struct ieee80211_local *local, | ||
1549 | struct ieee80211_sub_if_data *sdata); | ||
1551 | 1550 | ||
1552 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | 1551 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, |
1553 | u16 transaction, u16 auth_alg, u16 status, | 1552 | u16 transaction, u16 auth_alg, u16 status, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index a2b5e17036bb..69aaba79a9f7 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -92,7 +92,7 @@ static u32 ieee80211_idle_on(struct ieee80211_local *local) | |||
92 | if (local->hw.conf.flags & IEEE80211_CONF_IDLE) | 92 | if (local->hw.conf.flags & IEEE80211_CONF_IDLE) |
93 | return 0; | 93 | return 0; |
94 | 94 | ||
95 | drv_flush(local, false); | 95 | ieee80211_flush_queues(local, NULL); |
96 | 96 | ||
97 | local->hw.conf.flags |= IEEE80211_CONF_IDLE; | 97 | local->hw.conf.flags |= IEEE80211_CONF_IDLE; |
98 | return IEEE80211_CONF_CHANGE_IDLE; | 98 | return IEEE80211_CONF_CHANGE_IDLE; |
@@ -560,8 +560,6 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
560 | goto err_del_interface; | 560 | goto err_del_interface; |
561 | } | 561 | } |
562 | 562 | ||
563 | drv_add_interface_debugfs(local, sdata); | ||
564 | |||
565 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | 563 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
566 | local->fif_pspoll++; | 564 | local->fif_pspoll++; |
567 | local->fif_probe_req++; | 565 | local->fif_probe_req++; |
@@ -849,8 +847,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
849 | case NL80211_IFTYPE_AP: | 847 | case NL80211_IFTYPE_AP: |
850 | skb_queue_purge(&sdata->skb_queue); | 848 | skb_queue_purge(&sdata->skb_queue); |
851 | 849 | ||
852 | drv_remove_interface_debugfs(local, sdata); | ||
853 | |||
854 | if (going_down) | 850 | if (going_down) |
855 | drv_remove_interface(local, sdata); | 851 | drv_remove_interface(local, sdata); |
856 | } | 852 | } |
@@ -922,6 +918,17 @@ static void ieee80211_set_multicast_list(struct net_device *dev) | |||
922 | atomic_dec(&local->iff_promiscs); | 918 | atomic_dec(&local->iff_promiscs); |
923 | sdata->flags ^= IEEE80211_SDATA_PROMISC; | 919 | sdata->flags ^= IEEE80211_SDATA_PROMISC; |
924 | } | 920 | } |
921 | |||
922 | /* | ||
923 | * TODO: If somebody needs this on AP interfaces, | ||
924 | * it can be enabled easily but multicast | ||
925 | * addresses from VLANs need to be synced. | ||
926 | */ | ||
927 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR && | ||
928 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | ||
929 | sdata->vif.type != NL80211_IFTYPE_AP) | ||
930 | drv_set_multicast_list(local, sdata, &dev->mc); | ||
931 | |||
925 | spin_lock_bh(&local->filter_lock); | 932 | spin_lock_bh(&local->filter_lock); |
926 | __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len); | 933 | __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len); |
927 | spin_unlock_bh(&local->filter_lock); | 934 | spin_unlock_bh(&local->filter_lock); |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 99e9f6ae6a54..67059b88fea5 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -248,11 +248,11 @@ void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, | |||
248 | } | 248 | } |
249 | 249 | ||
250 | 250 | ||
251 | static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | 251 | static void ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, |
252 | struct sta_info *sta, | 252 | struct sta_info *sta, |
253 | bool pairwise, | 253 | bool pairwise, |
254 | struct ieee80211_key *old, | 254 | struct ieee80211_key *old, |
255 | struct ieee80211_key *new) | 255 | struct ieee80211_key *new) |
256 | { | 256 | { |
257 | int idx; | 257 | int idx; |
258 | bool defunikey, defmultikey, defmgmtkey; | 258 | bool defunikey, defmultikey, defmgmtkey; |
@@ -397,25 +397,21 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, | |||
397 | return key; | 397 | return key; |
398 | } | 398 | } |
399 | 399 | ||
400 | static void ieee80211_key_free_common(struct ieee80211_key *key) | ||
401 | { | ||
402 | if (key->conf.cipher == WLAN_CIPHER_SUITE_CCMP) | ||
403 | ieee80211_aes_key_free(key->u.ccmp.tfm); | ||
404 | if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) | ||
405 | ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); | ||
406 | kfree(key); | ||
407 | } | ||
408 | |||
400 | static void __ieee80211_key_destroy(struct ieee80211_key *key, | 409 | static void __ieee80211_key_destroy(struct ieee80211_key *key, |
401 | bool delay_tailroom) | 410 | bool delay_tailroom) |
402 | { | 411 | { |
403 | if (!key) | ||
404 | return; | ||
405 | |||
406 | /* | ||
407 | * Synchronize so the TX path can no longer be using | ||
408 | * this key before we free/remove it. | ||
409 | */ | ||
410 | synchronize_net(); | ||
411 | |||
412 | if (key->local) | 412 | if (key->local) |
413 | ieee80211_key_disable_hw_accel(key); | 413 | ieee80211_key_disable_hw_accel(key); |
414 | 414 | ||
415 | if (key->conf.cipher == WLAN_CIPHER_SUITE_CCMP) | ||
416 | ieee80211_aes_key_free(key->u.ccmp.tfm); | ||
417 | if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) | ||
418 | ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); | ||
419 | if (key->local) { | 415 | if (key->local) { |
420 | struct ieee80211_sub_if_data *sdata = key->sdata; | 416 | struct ieee80211_sub_if_data *sdata = key->sdata; |
421 | 417 | ||
@@ -431,7 +427,28 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key, | |||
431 | } | 427 | } |
432 | } | 428 | } |
433 | 429 | ||
434 | kfree(key); | 430 | ieee80211_key_free_common(key); |
431 | } | ||
432 | |||
433 | static void ieee80211_key_destroy(struct ieee80211_key *key, | ||
434 | bool delay_tailroom) | ||
435 | { | ||
436 | if (!key) | ||
437 | return; | ||
438 | |||
439 | /* | ||
440 | * Synchronize so the TX path can no longer be using | ||
441 | * this key before we free/remove it. | ||
442 | */ | ||
443 | synchronize_net(); | ||
444 | |||
445 | __ieee80211_key_destroy(key, delay_tailroom); | ||
446 | } | ||
447 | |||
448 | void ieee80211_key_free_unused(struct ieee80211_key *key) | ||
449 | { | ||
450 | WARN_ON(key->sdata || key->local); | ||
451 | ieee80211_key_free_common(key); | ||
435 | } | 452 | } |
436 | 453 | ||
437 | int ieee80211_key_link(struct ieee80211_key *key, | 454 | int ieee80211_key_link(struct ieee80211_key *key, |
@@ -462,19 +479,22 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
462 | 479 | ||
463 | increment_tailroom_need_count(sdata); | 480 | increment_tailroom_need_count(sdata); |
464 | 481 | ||
465 | __ieee80211_key_replace(sdata, sta, pairwise, old_key, key); | 482 | ieee80211_key_replace(sdata, sta, pairwise, old_key, key); |
466 | __ieee80211_key_destroy(old_key, true); | 483 | ieee80211_key_destroy(old_key, true); |
467 | 484 | ||
468 | ieee80211_debugfs_key_add(key); | 485 | ieee80211_debugfs_key_add(key); |
469 | 486 | ||
470 | ret = ieee80211_key_enable_hw_accel(key); | 487 | ret = ieee80211_key_enable_hw_accel(key); |
471 | 488 | ||
489 | if (ret) | ||
490 | ieee80211_key_free(key, true); | ||
491 | |||
472 | mutex_unlock(&sdata->local->key_mtx); | 492 | mutex_unlock(&sdata->local->key_mtx); |
473 | 493 | ||
474 | return ret; | 494 | return ret; |
475 | } | 495 | } |
476 | 496 | ||
477 | void __ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom) | 497 | void ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom) |
478 | { | 498 | { |
479 | if (!key) | 499 | if (!key) |
480 | return; | 500 | return; |
@@ -483,18 +503,10 @@ void __ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom) | |||
483 | * Replace key with nothingness if it was ever used. | 503 | * Replace key with nothingness if it was ever used. |
484 | */ | 504 | */ |
485 | if (key->sdata) | 505 | if (key->sdata) |
486 | __ieee80211_key_replace(key->sdata, key->sta, | 506 | ieee80211_key_replace(key->sdata, key->sta, |
487 | key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, | 507 | key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, |
488 | key, NULL); | 508 | key, NULL); |
489 | __ieee80211_key_destroy(key, delay_tailroom); | 509 | ieee80211_key_destroy(key, delay_tailroom); |
490 | } | ||
491 | |||
492 | void ieee80211_key_free(struct ieee80211_local *local, | ||
493 | struct ieee80211_key *key) | ||
494 | { | ||
495 | mutex_lock(&local->key_mtx); | ||
496 | __ieee80211_key_free(key, true); | ||
497 | mutex_unlock(&local->key_mtx); | ||
498 | } | 510 | } |
499 | 511 | ||
500 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) | 512 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) |
@@ -554,6 +566,7 @@ EXPORT_SYMBOL(ieee80211_iter_keys); | |||
554 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) | 566 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) |
555 | { | 567 | { |
556 | struct ieee80211_key *key, *tmp; | 568 | struct ieee80211_key *key, *tmp; |
569 | LIST_HEAD(keys); | ||
557 | 570 | ||
558 | cancel_delayed_work_sync(&sdata->dec_tailroom_needed_wk); | 571 | cancel_delayed_work_sync(&sdata->dec_tailroom_needed_wk); |
559 | 572 | ||
@@ -565,17 +578,65 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) | |||
565 | 578 | ||
566 | ieee80211_debugfs_key_remove_mgmt_default(sdata); | 579 | ieee80211_debugfs_key_remove_mgmt_default(sdata); |
567 | 580 | ||
568 | list_for_each_entry_safe(key, tmp, &sdata->key_list, list) | 581 | list_for_each_entry_safe(key, tmp, &sdata->key_list, list) { |
569 | __ieee80211_key_free(key, false); | 582 | ieee80211_key_replace(key->sdata, key->sta, |
583 | key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, | ||
584 | key, NULL); | ||
585 | list_add_tail(&key->list, &keys); | ||
586 | } | ||
570 | 587 | ||
571 | ieee80211_debugfs_key_update_default(sdata); | 588 | ieee80211_debugfs_key_update_default(sdata); |
572 | 589 | ||
590 | if (!list_empty(&keys)) { | ||
591 | synchronize_net(); | ||
592 | list_for_each_entry_safe(key, tmp, &keys, list) | ||
593 | __ieee80211_key_destroy(key, false); | ||
594 | } | ||
595 | |||
573 | WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt || | 596 | WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt || |
574 | sdata->crypto_tx_tailroom_pending_dec); | 597 | sdata->crypto_tx_tailroom_pending_dec); |
575 | 598 | ||
576 | mutex_unlock(&sdata->local->key_mtx); | 599 | mutex_unlock(&sdata->local->key_mtx); |
577 | } | 600 | } |
578 | 601 | ||
602 | void ieee80211_free_sta_keys(struct ieee80211_local *local, | ||
603 | struct sta_info *sta) | ||
604 | { | ||
605 | struct ieee80211_key *key, *tmp; | ||
606 | LIST_HEAD(keys); | ||
607 | int i; | ||
608 | |||
609 | mutex_lock(&local->key_mtx); | ||
610 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | ||
611 | key = key_mtx_dereference(local, sta->gtk[i]); | ||
612 | if (!key) | ||
613 | continue; | ||
614 | ieee80211_key_replace(key->sdata, key->sta, | ||
615 | key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, | ||
616 | key, NULL); | ||
617 | list_add(&key->list, &keys); | ||
618 | } | ||
619 | |||
620 | key = key_mtx_dereference(local, sta->ptk); | ||
621 | if (key) { | ||
622 | ieee80211_key_replace(key->sdata, key->sta, | ||
623 | key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE, | ||
624 | key, NULL); | ||
625 | list_add(&key->list, &keys); | ||
626 | } | ||
627 | |||
628 | /* | ||
629 | * NB: the station code relies on this being | ||
630 | * done even if there aren't any keys | ||
631 | */ | ||
632 | synchronize_net(); | ||
633 | |||
634 | list_for_each_entry_safe(key, tmp, &keys, list) | ||
635 | __ieee80211_key_destroy(key, true); | ||
636 | |||
637 | mutex_unlock(&local->key_mtx); | ||
638 | } | ||
639 | |||
579 | void ieee80211_delayed_tailroom_dec(struct work_struct *wk) | 640 | void ieee80211_delayed_tailroom_dec(struct work_struct *wk) |
580 | { | 641 | { |
581 | struct ieee80211_sub_if_data *sdata; | 642 | struct ieee80211_sub_if_data *sdata; |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 2a682d81cee9..e8de3e6d7804 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -129,19 +129,20 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, | |||
129 | size_t seq_len, const u8 *seq); | 129 | size_t seq_len, const u8 *seq); |
130 | /* | 130 | /* |
131 | * Insert a key into data structures (sdata, sta if necessary) | 131 | * Insert a key into data structures (sdata, sta if necessary) |
132 | * to make it used, free old key. | 132 | * to make it used, free old key. On failure, also free the new key. |
133 | */ | 133 | */ |
134 | int __must_check ieee80211_key_link(struct ieee80211_key *key, | 134 | int ieee80211_key_link(struct ieee80211_key *key, |
135 | struct ieee80211_sub_if_data *sdata, | 135 | struct ieee80211_sub_if_data *sdata, |
136 | struct sta_info *sta); | 136 | struct sta_info *sta); |
137 | void __ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom); | 137 | void ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom); |
138 | void ieee80211_key_free(struct ieee80211_local *local, | 138 | void ieee80211_key_free_unused(struct ieee80211_key *key); |
139 | struct ieee80211_key *key); | ||
140 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, | 139 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, |
141 | bool uni, bool multi); | 140 | bool uni, bool multi); |
142 | void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, | 141 | void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, |
143 | int idx); | 142 | int idx); |
144 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); | 143 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); |
144 | void ieee80211_free_sta_keys(struct ieee80211_local *local, | ||
145 | struct sta_info *sta); | ||
145 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); | 146 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); |
146 | 147 | ||
147 | #define key_mtx_dereference(local, ref) \ | 148 | #define key_mtx_dereference(local, ref) \ |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 5a53aa5ede80..c6f81ecc36a1 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -100,7 +100,6 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) | |||
100 | int power; | 100 | int power; |
101 | enum nl80211_channel_type channel_type; | 101 | enum nl80211_channel_type channel_type; |
102 | u32 offchannel_flag; | 102 | u32 offchannel_flag; |
103 | bool scanning = false; | ||
104 | 103 | ||
105 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | 104 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; |
106 | if (local->scan_channel) { | 105 | if (local->scan_channel) { |
@@ -147,9 +146,6 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) | |||
147 | changed |= IEEE80211_CONF_CHANGE_SMPS; | 146 | changed |= IEEE80211_CONF_CHANGE_SMPS; |
148 | } | 147 | } |
149 | 148 | ||
150 | scanning = test_bit(SCAN_SW_SCANNING, &local->scanning) || | ||
151 | test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) || | ||
152 | test_bit(SCAN_HW_SCANNING, &local->scanning); | ||
153 | power = chan->max_power; | 149 | power = chan->max_power; |
154 | 150 | ||
155 | rcu_read_lock(); | 151 | rcu_read_lock(); |
@@ -226,8 +222,6 @@ u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) | |||
226 | static void ieee80211_tasklet_handler(unsigned long data) | 222 | static void ieee80211_tasklet_handler(unsigned long data) |
227 | { | 223 | { |
228 | struct ieee80211_local *local = (struct ieee80211_local *) data; | 224 | struct ieee80211_local *local = (struct ieee80211_local *) data; |
229 | struct sta_info *sta, *tmp; | ||
230 | struct skb_eosp_msg_data *eosp_data; | ||
231 | struct sk_buff *skb; | 225 | struct sk_buff *skb; |
232 | 226 | ||
233 | while ((skb = skb_dequeue(&local->skb_queue)) || | 227 | while ((skb = skb_dequeue(&local->skb_queue)) || |
@@ -243,18 +237,6 @@ static void ieee80211_tasklet_handler(unsigned long data) | |||
243 | skb->pkt_type = 0; | 237 | skb->pkt_type = 0; |
244 | ieee80211_tx_status(&local->hw, skb); | 238 | ieee80211_tx_status(&local->hw, skb); |
245 | break; | 239 | break; |
246 | case IEEE80211_EOSP_MSG: | ||
247 | eosp_data = (void *)skb->cb; | ||
248 | for_each_sta_info(local, eosp_data->sta, sta, tmp) { | ||
249 | /* skip wrong virtual interface */ | ||
250 | if (memcmp(eosp_data->iface, | ||
251 | sta->sdata->vif.addr, ETH_ALEN)) | ||
252 | continue; | ||
253 | clear_sta_flag(sta, WLAN_STA_SP); | ||
254 | break; | ||
255 | } | ||
256 | dev_kfree_skb(skb); | ||
257 | break; | ||
258 | default: | 240 | default: |
259 | WARN(1, "mac80211: Packet is of unknown type %d\n", | 241 | WARN(1, "mac80211: Packet is of unknown type %d\n", |
260 | skb->pkt_type); | 242 | skb->pkt_type); |
@@ -295,8 +277,8 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw) | |||
295 | "Hardware restart was requested\n"); | 277 | "Hardware restart was requested\n"); |
296 | 278 | ||
297 | /* use this reason, ieee80211_reconfig will unblock it */ | 279 | /* use this reason, ieee80211_reconfig will unblock it */ |
298 | ieee80211_stop_queues_by_reason(hw, | 280 | ieee80211_stop_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP, |
299 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 281 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); |
300 | 282 | ||
301 | /* | 283 | /* |
302 | * Stop all Rx during the reconfig. We don't want state changes | 284 | * Stop all Rx during the reconfig. We don't want state changes |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 77b5710db241..123a300cef57 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -699,10 +699,8 @@ out_free: | |||
699 | static int | 699 | static int |
700 | ieee80211_mesh_rebuild_beacon(struct ieee80211_if_mesh *ifmsh) | 700 | ieee80211_mesh_rebuild_beacon(struct ieee80211_if_mesh *ifmsh) |
701 | { | 701 | { |
702 | struct ieee80211_sub_if_data *sdata; | ||
703 | struct beacon_data *old_bcn; | 702 | struct beacon_data *old_bcn; |
704 | int ret; | 703 | int ret; |
705 | sdata = container_of(ifmsh, struct ieee80211_sub_if_data, u.mesh); | ||
706 | 704 | ||
707 | mutex_lock(&ifmsh->mtx); | 705 | mutex_lock(&ifmsh->mtx); |
708 | 706 | ||
@@ -833,9 +831,8 @@ ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata, | |||
833 | struct ieee80211_mgmt *hdr; | 831 | struct ieee80211_mgmt *hdr; |
834 | struct ieee802_11_elems elems; | 832 | struct ieee802_11_elems elems; |
835 | size_t baselen; | 833 | size_t baselen; |
836 | u8 *pos, *end; | 834 | u8 *pos; |
837 | 835 | ||
838 | end = ((u8 *) mgmt) + len; | ||
839 | pos = mgmt->u.probe_req.variable; | 836 | pos = mgmt->u.probe_req.variable; |
840 | baselen = (u8 *) pos - (u8 *) mgmt; | 837 | baselen = (u8 *) pos - (u8 *) mgmt; |
841 | if (baselen > len) | 838 | if (baselen > len) |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 167158646593..e06dbbf8cb4c 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1009,6 +1009,7 @@ static void ieee80211_chswitch_work(struct work_struct *work) | |||
1009 | 1009 | ||
1010 | /* XXX: wait for a beacon first? */ | 1010 | /* XXX: wait for a beacon first? */ |
1011 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | 1011 | ieee80211_wake_queues_by_reason(&sdata->local->hw, |
1012 | IEEE80211_MAX_QUEUE_MAP, | ||
1012 | IEEE80211_QUEUE_STOP_REASON_CSA); | 1013 | IEEE80211_QUEUE_STOP_REASON_CSA); |
1013 | out: | 1014 | out: |
1014 | ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; | 1015 | ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; |
@@ -1108,6 +1109,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1108 | 1109 | ||
1109 | if (sw_elem->mode) | 1110 | if (sw_elem->mode) |
1110 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | 1111 | ieee80211_stop_queues_by_reason(&sdata->local->hw, |
1112 | IEEE80211_MAX_QUEUE_MAP, | ||
1111 | IEEE80211_QUEUE_STOP_REASON_CSA); | 1113 | IEEE80211_QUEUE_STOP_REASON_CSA); |
1112 | 1114 | ||
1113 | if (sdata->local->ops->channel_switch) { | 1115 | if (sdata->local->ops->channel_switch) { |
@@ -1375,6 +1377,7 @@ void ieee80211_dynamic_ps_disable_work(struct work_struct *work) | |||
1375 | } | 1377 | } |
1376 | 1378 | ||
1377 | ieee80211_wake_queues_by_reason(&local->hw, | 1379 | ieee80211_wake_queues_by_reason(&local->hw, |
1380 | IEEE80211_MAX_QUEUE_MAP, | ||
1378 | IEEE80211_QUEUE_STOP_REASON_PS); | 1381 | IEEE80211_QUEUE_STOP_REASON_PS); |
1379 | } | 1382 | } |
1380 | 1383 | ||
@@ -1436,7 +1439,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | |||
1436 | else { | 1439 | else { |
1437 | ieee80211_send_nullfunc(local, sdata, 1); | 1440 | ieee80211_send_nullfunc(local, sdata, 1); |
1438 | /* Flush to get the tx status of nullfunc frame */ | 1441 | /* Flush to get the tx status of nullfunc frame */ |
1439 | drv_flush(local, false); | 1442 | ieee80211_flush_queues(local, sdata); |
1440 | } | 1443 | } |
1441 | } | 1444 | } |
1442 | 1445 | ||
@@ -1767,7 +1770,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1767 | 1770 | ||
1768 | /* flush out any pending frame (e.g. DELBA) before deauth/disassoc */ | 1771 | /* flush out any pending frame (e.g. DELBA) before deauth/disassoc */ |
1769 | if (tx) | 1772 | if (tx) |
1770 | drv_flush(local, false); | 1773 | ieee80211_flush_queues(local, sdata); |
1771 | 1774 | ||
1772 | /* deauthenticate/disassociate now */ | 1775 | /* deauthenticate/disassociate now */ |
1773 | if (tx || frame_buf) | 1776 | if (tx || frame_buf) |
@@ -1776,7 +1779,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1776 | 1779 | ||
1777 | /* flush out frame */ | 1780 | /* flush out frame */ |
1778 | if (tx) | 1781 | if (tx) |
1779 | drv_flush(local, false); | 1782 | ieee80211_flush_queues(local, sdata); |
1780 | 1783 | ||
1781 | /* clear bssid only after building the needed mgmt frames */ | 1784 | /* clear bssid only after building the needed mgmt frames */ |
1782 | memset(ifmgd->bssid, 0, ETH_ALEN); | 1785 | memset(ifmgd->bssid, 0, ETH_ALEN); |
@@ -1948,7 +1951,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | |||
1948 | ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); | 1951 | ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); |
1949 | run_again(ifmgd, ifmgd->probe_timeout); | 1952 | run_again(ifmgd, ifmgd->probe_timeout); |
1950 | if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) | 1953 | if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) |
1951 | drv_flush(sdata->local, false); | 1954 | ieee80211_flush_queues(sdata->local, sdata); |
1952 | } | 1955 | } |
1953 | 1956 | ||
1954 | static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, | 1957 | static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, |
@@ -2071,6 +2074,7 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) | |||
2071 | true, frame_buf); | 2074 | true, frame_buf); |
2072 | ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; | 2075 | ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; |
2073 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | 2076 | ieee80211_wake_queues_by_reason(&sdata->local->hw, |
2077 | IEEE80211_MAX_QUEUE_MAP, | ||
2074 | IEEE80211_QUEUE_STOP_REASON_CSA); | 2078 | IEEE80211_QUEUE_STOP_REASON_CSA); |
2075 | mutex_unlock(&ifmgd->mtx); | 2079 | mutex_unlock(&ifmgd->mtx); |
2076 | 2080 | ||
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 950c95bec13d..cce795871ab1 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -118,9 +118,9 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local) | |||
118 | * Stop queues and transmit all frames queued by the driver | 118 | * Stop queues and transmit all frames queued by the driver |
119 | * before sending nullfunc to enable powersave at the AP. | 119 | * before sending nullfunc to enable powersave at the AP. |
120 | */ | 120 | */ |
121 | ieee80211_stop_queues_by_reason(&local->hw, | 121 | ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP, |
122 | IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL); | 122 | IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL); |
123 | drv_flush(local, false); | 123 | ieee80211_flush_queues(local, NULL); |
124 | 124 | ||
125 | mutex_lock(&local->iflist_mtx); | 125 | mutex_lock(&local->iflist_mtx); |
126 | list_for_each_entry(sdata, &local->interfaces, list) { | 126 | list_for_each_entry(sdata, &local->interfaces, list) { |
@@ -181,7 +181,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local) | |||
181 | } | 181 | } |
182 | mutex_unlock(&local->iflist_mtx); | 182 | mutex_unlock(&local->iflist_mtx); |
183 | 183 | ||
184 | ieee80211_wake_queues_by_reason(&local->hw, | 184 | ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP, |
185 | IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL); | 185 | IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL); |
186 | } | 186 | } |
187 | 187 | ||
@@ -382,7 +382,7 @@ void ieee80211_sw_roc_work(struct work_struct *work) | |||
382 | ieee80211_roc_notify_destroy(roc, !roc->abort); | 382 | ieee80211_roc_notify_destroy(roc, !roc->abort); |
383 | 383 | ||
384 | if (started) { | 384 | if (started) { |
385 | drv_flush(local, false); | 385 | ieee80211_flush_queues(local, NULL); |
386 | 386 | ||
387 | local->tmp_channel = NULL; | 387 | local->tmp_channel = NULL; |
388 | ieee80211_hw_config(local, 0); | 388 | ieee80211_hw_config(local, 0); |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index b471a67f224d..3d16f4e61743 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -30,12 +30,13 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
30 | } | 30 | } |
31 | 31 | ||
32 | ieee80211_stop_queues_by_reason(hw, | 32 | ieee80211_stop_queues_by_reason(hw, |
33 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 33 | IEEE80211_MAX_QUEUE_MAP, |
34 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | ||
34 | 35 | ||
35 | /* flush out all packets */ | 36 | /* flush out all packets */ |
36 | synchronize_net(); | 37 | synchronize_net(); |
37 | 38 | ||
38 | drv_flush(local, false); | 39 | ieee80211_flush_queues(local, NULL); |
39 | 40 | ||
40 | local->quiescing = true; | 41 | local->quiescing = true; |
41 | /* make quiescing visible to timers everywhere */ | 42 | /* make quiescing visible to timers everywhere */ |
@@ -68,6 +69,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
68 | mutex_unlock(&local->sta_mtx); | 69 | mutex_unlock(&local->sta_mtx); |
69 | } | 70 | } |
70 | ieee80211_wake_queues_by_reason(hw, | 71 | ieee80211_wake_queues_by_reason(hw, |
72 | IEEE80211_MAX_QUEUE_MAP, | ||
71 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 73 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); |
72 | return err; | 74 | return err; |
73 | } else if (err > 0) { | 75 | } else if (err > 0) { |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 749552bdcfe1..d2b264d1311d 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -202,14 +202,23 @@ minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate) | |||
202 | struct minstrel_rate_stats *mr; | 202 | struct minstrel_rate_stats *mr; |
203 | unsigned int nsecs = 0; | 203 | unsigned int nsecs = 0; |
204 | unsigned int tp; | 204 | unsigned int tp; |
205 | unsigned int prob; | ||
205 | 206 | ||
206 | mr = &mi->groups[group].rates[rate]; | 207 | mr = &mi->groups[group].rates[rate]; |
208 | prob = mr->probability; | ||
207 | 209 | ||
208 | if (mr->probability < MINSTREL_FRAC(1, 10)) { | 210 | if (prob < MINSTREL_FRAC(1, 10)) { |
209 | mr->cur_tp = 0; | 211 | mr->cur_tp = 0; |
210 | return; | 212 | return; |
211 | } | 213 | } |
212 | 214 | ||
215 | /* | ||
216 | * For the throughput calculation, limit the probability value to 90% to | ||
217 | * account for collision related packet error rate fluctuation | ||
218 | */ | ||
219 | if (prob > MINSTREL_FRAC(9, 10)) | ||
220 | prob = MINSTREL_FRAC(9, 10); | ||
221 | |||
213 | if (group != MINSTREL_CCK_GROUP) | 222 | if (group != MINSTREL_CCK_GROUP) |
214 | nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len); | 223 | nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len); |
215 | 224 | ||
@@ -639,15 +648,18 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
639 | /* | 648 | /* |
640 | * Sampling might add some overhead (RTS, no aggregation) | 649 | * Sampling might add some overhead (RTS, no aggregation) |
641 | * to the frame. Hence, don't use sampling for the currently | 650 | * to the frame. Hence, don't use sampling for the currently |
642 | * used max TP rate. | 651 | * used rates. |
643 | */ | 652 | */ |
644 | if (sample_idx == mi->max_tp_rate) | 653 | if (sample_idx == mi->max_tp_rate || |
654 | sample_idx == mi->max_tp_rate2 || | ||
655 | sample_idx == mi->max_prob_rate) | ||
645 | return -1; | 656 | return -1; |
657 | |||
646 | /* | 658 | /* |
647 | * When not using MRR, do not sample if the probability is already | 659 | * Do not sample if the probability is already higher than 95% |
648 | * higher than 95% to avoid wasting airtime | 660 | * to avoid wasting airtime. |
649 | */ | 661 | */ |
650 | if (!mp->has_mrr && (mr->probability > MINSTREL_FRAC(95, 100))) | 662 | if (mr->probability > MINSTREL_FRAC(95, 100)) |
651 | return -1; | 663 | return -1; |
652 | 664 | ||
653 | /* | 665 | /* |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 43a45cf00e06..cb34cbbaa20c 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -153,7 +153,6 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) | |||
153 | u8 *elements; | 153 | u8 *elements; |
154 | struct ieee80211_channel *channel; | 154 | struct ieee80211_channel *channel; |
155 | size_t baselen; | 155 | size_t baselen; |
156 | bool beacon; | ||
157 | struct ieee802_11_elems elems; | 156 | struct ieee802_11_elems elems; |
158 | 157 | ||
159 | if (skb->len < 24 || | 158 | if (skb->len < 24 || |
@@ -175,11 +174,9 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) | |||
175 | 174 | ||
176 | elements = mgmt->u.probe_resp.variable; | 175 | elements = mgmt->u.probe_resp.variable; |
177 | baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); | 176 | baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); |
178 | beacon = false; | ||
179 | } else { | 177 | } else { |
180 | baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable); | 178 | baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable); |
181 | elements = mgmt->u.beacon.variable; | 179 | elements = mgmt->u.beacon.variable; |
182 | beacon = true; | ||
183 | } | 180 | } |
184 | 181 | ||
185 | if (baselen > skb->len) | 182 | if (baselen > skb->len) |
@@ -335,7 +332,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) | |||
335 | ieee80211_offchannel_stop_vifs(local); | 332 | ieee80211_offchannel_stop_vifs(local); |
336 | 333 | ||
337 | /* ensure nullfunc is transmitted before leaving operating channel */ | 334 | /* ensure nullfunc is transmitted before leaving operating channel */ |
338 | drv_flush(local, false); | 335 | ieee80211_flush_queues(local, NULL); |
339 | 336 | ||
340 | ieee80211_configure_filter(local); | 337 | ieee80211_configure_filter(local); |
341 | 338 | ||
@@ -671,7 +668,7 @@ static void ieee80211_scan_state_resume(struct ieee80211_local *local, | |||
671 | ieee80211_offchannel_stop_vifs(local); | 668 | ieee80211_offchannel_stop_vifs(local); |
672 | 669 | ||
673 | if (local->ops->flush) { | 670 | if (local->ops->flush) { |
674 | drv_flush(local, false); | 671 | ieee80211_flush_queues(local, NULL); |
675 | *next_delay = 0; | 672 | *next_delay = 0; |
676 | } else | 673 | } else |
677 | *next_delay = HZ / 10; | 674 | *next_delay = HZ / 10; |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 85458a28ffa0..11216bc13b27 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -556,6 +556,15 @@ static inline void __bss_tim_clear(u8 *tim, u16 id) | |||
556 | tim[id / 8] &= ~(1 << (id % 8)); | 556 | tim[id / 8] &= ~(1 << (id % 8)); |
557 | } | 557 | } |
558 | 558 | ||
559 | static inline bool __bss_tim_get(u8 *tim, u16 id) | ||
560 | { | ||
561 | /* | ||
562 | * This format has been mandated by the IEEE specifications, | ||
563 | * so this line may not be changed to use the test_bit() format. | ||
564 | */ | ||
565 | return tim[id / 8] & (1 << (id % 8)); | ||
566 | } | ||
567 | |||
559 | static unsigned long ieee80211_tids_for_ac(int ac) | 568 | static unsigned long ieee80211_tids_for_ac(int ac) |
560 | { | 569 | { |
561 | /* If we ever support TIDs > 7, this obviously needs to be adjusted */ | 570 | /* If we ever support TIDs > 7, this obviously needs to be adjusted */ |
@@ -636,6 +645,9 @@ void sta_info_recalc_tim(struct sta_info *sta) | |||
636 | done: | 645 | done: |
637 | spin_lock_bh(&local->tim_lock); | 646 | spin_lock_bh(&local->tim_lock); |
638 | 647 | ||
648 | if (indicate_tim == __bss_tim_get(ps->tim, id)) | ||
649 | goto out_unlock; | ||
650 | |||
639 | if (indicate_tim) | 651 | if (indicate_tim) |
640 | __bss_tim_set(ps->tim, id); | 652 | __bss_tim_set(ps->tim, id); |
641 | else | 653 | else |
@@ -647,6 +659,7 @@ void sta_info_recalc_tim(struct sta_info *sta) | |||
647 | local->tim_in_locked_section = false; | 659 | local->tim_in_locked_section = false; |
648 | } | 660 | } |
649 | 661 | ||
662 | out_unlock: | ||
650 | spin_unlock_bh(&local->tim_lock); | 663 | spin_unlock_bh(&local->tim_lock); |
651 | } | 664 | } |
652 | 665 | ||
@@ -770,8 +783,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta) | |||
770 | { | 783 | { |
771 | struct ieee80211_local *local; | 784 | struct ieee80211_local *local; |
772 | struct ieee80211_sub_if_data *sdata; | 785 | struct ieee80211_sub_if_data *sdata; |
773 | int ret, i; | 786 | int ret; |
774 | bool have_key = false; | ||
775 | 787 | ||
776 | might_sleep(); | 788 | might_sleep(); |
777 | 789 | ||
@@ -798,22 +810,8 @@ int __must_check __sta_info_destroy(struct sta_info *sta) | |||
798 | 810 | ||
799 | list_del_rcu(&sta->list); | 811 | list_del_rcu(&sta->list); |
800 | 812 | ||
801 | mutex_lock(&local->key_mtx); | 813 | /* this always calls synchronize_net() */ |
802 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | 814 | ieee80211_free_sta_keys(local, sta); |
803 | __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i]), | ||
804 | true); | ||
805 | have_key = true; | ||
806 | } | ||
807 | if (sta->ptk) { | ||
808 | __ieee80211_key_free(key_mtx_dereference(local, sta->ptk), | ||
809 | true); | ||
810 | have_key = true; | ||
811 | } | ||
812 | |||
813 | mutex_unlock(&local->key_mtx); | ||
814 | |||
815 | if (!have_key) | ||
816 | synchronize_net(); | ||
817 | 815 | ||
818 | sta->dead = true; | 816 | sta->dead = true; |
819 | 817 | ||
@@ -1399,30 +1397,16 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw, | |||
1399 | } | 1397 | } |
1400 | EXPORT_SYMBOL(ieee80211_sta_block_awake); | 1398 | EXPORT_SYMBOL(ieee80211_sta_block_awake); |
1401 | 1399 | ||
1402 | void ieee80211_sta_eosp_irqsafe(struct ieee80211_sta *pubsta) | 1400 | void ieee80211_sta_eosp(struct ieee80211_sta *pubsta) |
1403 | { | 1401 | { |
1404 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); | 1402 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); |
1405 | struct ieee80211_local *local = sta->local; | 1403 | struct ieee80211_local *local = sta->local; |
1406 | struct sk_buff *skb; | ||
1407 | struct skb_eosp_msg_data *data; | ||
1408 | 1404 | ||
1409 | trace_api_eosp(local, pubsta); | 1405 | trace_api_eosp(local, pubsta); |
1410 | 1406 | ||
1411 | skb = alloc_skb(0, GFP_ATOMIC); | 1407 | clear_sta_flag(sta, WLAN_STA_SP); |
1412 | if (!skb) { | ||
1413 | /* too bad ... but race is better than loss */ | ||
1414 | clear_sta_flag(sta, WLAN_STA_SP); | ||
1415 | return; | ||
1416 | } | ||
1417 | |||
1418 | data = (void *)skb->cb; | ||
1419 | memcpy(data->sta, pubsta->addr, ETH_ALEN); | ||
1420 | memcpy(data->iface, sta->sdata->vif.addr, ETH_ALEN); | ||
1421 | skb->pkt_type = IEEE80211_EOSP_MSG; | ||
1422 | skb_queue_tail(&local->skb_queue, skb); | ||
1423 | tasklet_schedule(&local->tasklet); | ||
1424 | } | 1408 | } |
1425 | EXPORT_SYMBOL(ieee80211_sta_eosp_irqsafe); | 1409 | EXPORT_SYMBOL(ieee80211_sta_eosp); |
1426 | 1410 | ||
1427 | void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta, | 1411 | void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta, |
1428 | u8 tid, bool buffered) | 1412 | u8 tid, bool buffered) |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index e5868c32d1a3..adc30045f99e 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -333,7 +333,8 @@ struct sta_info { | |||
333 | unsigned long driver_buffered_tids; | 333 | unsigned long driver_buffered_tids; |
334 | 334 | ||
335 | /* Updated from RX path only, no locking requirements */ | 335 | /* Updated from RX path only, no locking requirements */ |
336 | unsigned long rx_packets, rx_bytes; | 336 | unsigned long rx_packets; |
337 | u64 rx_bytes; | ||
337 | unsigned long wep_weak_iv_count; | 338 | unsigned long wep_weak_iv_count; |
338 | unsigned long last_rx; | 339 | unsigned long last_rx; |
339 | long last_connected; | 340 | long last_connected; |
@@ -353,9 +354,9 @@ struct sta_info { | |||
353 | unsigned int fail_avg; | 354 | unsigned int fail_avg; |
354 | 355 | ||
355 | /* Updated from TX path only, no locking requirements */ | 356 | /* Updated from TX path only, no locking requirements */ |
356 | unsigned long tx_packets; | 357 | u32 tx_fragments; |
357 | unsigned long tx_bytes; | 358 | u64 tx_packets[IEEE80211_NUM_ACS]; |
358 | unsigned long tx_fragments; | 359 | u64 tx_bytes[IEEE80211_NUM_ACS]; |
359 | struct ieee80211_tx_rate last_tx_rate; | 360 | struct ieee80211_tx_rate last_tx_rate; |
360 | int last_rx_rate_idx; | 361 | int last_rx_rate_idx; |
361 | u32 last_rx_rate_flag; | 362 | u32 last_rx_rate_flag; |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index e7db2b804e0c..c5899797a8d4 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -431,6 +431,30 @@ TRACE_EVENT(drv_prepare_multicast, | |||
431 | ) | 431 | ) |
432 | ); | 432 | ); |
433 | 433 | ||
434 | TRACE_EVENT(drv_set_multicast_list, | ||
435 | TP_PROTO(struct ieee80211_local *local, | ||
436 | struct ieee80211_sub_if_data *sdata, int mc_count), | ||
437 | |||
438 | TP_ARGS(local, sdata, mc_count), | ||
439 | |||
440 | TP_STRUCT__entry( | ||
441 | LOCAL_ENTRY | ||
442 | __field(bool, allmulti) | ||
443 | __field(int, mc_count) | ||
444 | ), | ||
445 | |||
446 | TP_fast_assign( | ||
447 | LOCAL_ASSIGN; | ||
448 | __entry->allmulti = sdata->flags & IEEE80211_SDATA_ALLMULTI; | ||
449 | __entry->mc_count = mc_count; | ||
450 | ), | ||
451 | |||
452 | TP_printk( | ||
453 | LOCAL_PR_FMT " configure mc filter, count=%d, allmulti=%d", | ||
454 | LOCAL_PR_ARG, __entry->mc_count, __entry->allmulti | ||
455 | ) | ||
456 | ); | ||
457 | |||
434 | TRACE_EVENT(drv_configure_filter, | 458 | TRACE_EVENT(drv_configure_filter, |
435 | TP_PROTO(struct ieee80211_local *local, | 459 | TP_PROTO(struct ieee80211_local *local, |
436 | unsigned int changed_flags, | 460 | unsigned int changed_flags, |
@@ -940,23 +964,26 @@ TRACE_EVENT(drv_get_survey, | |||
940 | ); | 964 | ); |
941 | 965 | ||
942 | TRACE_EVENT(drv_flush, | 966 | TRACE_EVENT(drv_flush, |
943 | TP_PROTO(struct ieee80211_local *local, bool drop), | 967 | TP_PROTO(struct ieee80211_local *local, |
968 | u32 queues, bool drop), | ||
944 | 969 | ||
945 | TP_ARGS(local, drop), | 970 | TP_ARGS(local, queues, drop), |
946 | 971 | ||
947 | TP_STRUCT__entry( | 972 | TP_STRUCT__entry( |
948 | LOCAL_ENTRY | 973 | LOCAL_ENTRY |
949 | __field(bool, drop) | 974 | __field(bool, drop) |
975 | __field(u32, queues) | ||
950 | ), | 976 | ), |
951 | 977 | ||
952 | TP_fast_assign( | 978 | TP_fast_assign( |
953 | LOCAL_ASSIGN; | 979 | LOCAL_ASSIGN; |
954 | __entry->drop = drop; | 980 | __entry->drop = drop; |
981 | __entry->queues = queues; | ||
955 | ), | 982 | ), |
956 | 983 | ||
957 | TP_printk( | 984 | TP_printk( |
958 | LOCAL_PR_FMT " drop:%d", | 985 | LOCAL_PR_FMT " queues:0x%x drop:%d", |
959 | LOCAL_PR_ARG, __entry->drop | 986 | LOCAL_PR_ARG, __entry->queues, __entry->drop |
960 | ) | 987 | ) |
961 | ); | 988 | ); |
962 | 989 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 4e8a86163fc7..9e67cc97b87b 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -233,6 +233,7 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx) | |||
233 | 233 | ||
234 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | 234 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { |
235 | ieee80211_stop_queues_by_reason(&local->hw, | 235 | ieee80211_stop_queues_by_reason(&local->hw, |
236 | IEEE80211_MAX_QUEUE_MAP, | ||
236 | IEEE80211_QUEUE_STOP_REASON_PS); | 237 | IEEE80211_QUEUE_STOP_REASON_PS); |
237 | ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; | 238 | ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; |
238 | ieee80211_queue_work(&local->hw, | 239 | ieee80211_queue_work(&local->hw, |
@@ -991,15 +992,18 @@ static ieee80211_tx_result debug_noinline | |||
991 | ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) | 992 | ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) |
992 | { | 993 | { |
993 | struct sk_buff *skb; | 994 | struct sk_buff *skb; |
995 | int ac = -1; | ||
994 | 996 | ||
995 | if (!tx->sta) | 997 | if (!tx->sta) |
996 | return TX_CONTINUE; | 998 | return TX_CONTINUE; |
997 | 999 | ||
998 | tx->sta->tx_packets++; | ||
999 | skb_queue_walk(&tx->skbs, skb) { | 1000 | skb_queue_walk(&tx->skbs, skb) { |
1001 | ac = skb_get_queue_mapping(skb); | ||
1000 | tx->sta->tx_fragments++; | 1002 | tx->sta->tx_fragments++; |
1001 | tx->sta->tx_bytes += skb->len; | 1003 | tx->sta->tx_bytes[ac] += skb->len; |
1002 | } | 1004 | } |
1005 | if (ac >= 0) | ||
1006 | tx->sta->tx_packets[ac]++; | ||
1003 | 1007 | ||
1004 | return TX_CONTINUE; | 1008 | return TX_CONTINUE; |
1005 | } | 1009 | } |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index b7a856e3281b..a7368870c8ee 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -453,7 +453,8 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, | |||
453 | } | 453 | } |
454 | 454 | ||
455 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, | 455 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, |
456 | enum queue_stop_reason reason) | 456 | unsigned long queues, |
457 | enum queue_stop_reason reason) | ||
457 | { | 458 | { |
458 | struct ieee80211_local *local = hw_to_local(hw); | 459 | struct ieee80211_local *local = hw_to_local(hw); |
459 | unsigned long flags; | 460 | unsigned long flags; |
@@ -461,7 +462,7 @@ void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, | |||
461 | 462 | ||
462 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 463 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
463 | 464 | ||
464 | for (i = 0; i < hw->queues; i++) | 465 | for_each_set_bit(i, &queues, hw->queues) |
465 | __ieee80211_stop_queue(hw, i, reason); | 466 | __ieee80211_stop_queue(hw, i, reason); |
466 | 467 | ||
467 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 468 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
@@ -469,7 +470,7 @@ void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, | |||
469 | 470 | ||
470 | void ieee80211_stop_queues(struct ieee80211_hw *hw) | 471 | void ieee80211_stop_queues(struct ieee80211_hw *hw) |
471 | { | 472 | { |
472 | ieee80211_stop_queues_by_reason(hw, | 473 | ieee80211_stop_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP, |
473 | IEEE80211_QUEUE_STOP_REASON_DRIVER); | 474 | IEEE80211_QUEUE_STOP_REASON_DRIVER); |
474 | } | 475 | } |
475 | EXPORT_SYMBOL(ieee80211_stop_queues); | 476 | EXPORT_SYMBOL(ieee80211_stop_queues); |
@@ -491,6 +492,7 @@ int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue) | |||
491 | EXPORT_SYMBOL(ieee80211_queue_stopped); | 492 | EXPORT_SYMBOL(ieee80211_queue_stopped); |
492 | 493 | ||
493 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | 494 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, |
495 | unsigned long queues, | ||
494 | enum queue_stop_reason reason) | 496 | enum queue_stop_reason reason) |
495 | { | 497 | { |
496 | struct ieee80211_local *local = hw_to_local(hw); | 498 | struct ieee80211_local *local = hw_to_local(hw); |
@@ -499,7 +501,7 @@ void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | |||
499 | 501 | ||
500 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 502 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
501 | 503 | ||
502 | for (i = 0; i < hw->queues; i++) | 504 | for_each_set_bit(i, &queues, hw->queues) |
503 | __ieee80211_wake_queue(hw, i, reason); | 505 | __ieee80211_wake_queue(hw, i, reason); |
504 | 506 | ||
505 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 507 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
@@ -507,10 +509,42 @@ void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | |||
507 | 509 | ||
508 | void ieee80211_wake_queues(struct ieee80211_hw *hw) | 510 | void ieee80211_wake_queues(struct ieee80211_hw *hw) |
509 | { | 511 | { |
510 | ieee80211_wake_queues_by_reason(hw, IEEE80211_QUEUE_STOP_REASON_DRIVER); | 512 | ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP, |
513 | IEEE80211_QUEUE_STOP_REASON_DRIVER); | ||
511 | } | 514 | } |
512 | EXPORT_SYMBOL(ieee80211_wake_queues); | 515 | EXPORT_SYMBOL(ieee80211_wake_queues); |
513 | 516 | ||
517 | void ieee80211_flush_queues(struct ieee80211_local *local, | ||
518 | struct ieee80211_sub_if_data *sdata) | ||
519 | { | ||
520 | u32 queues; | ||
521 | |||
522 | if (!local->ops->flush) | ||
523 | return; | ||
524 | |||
525 | if (sdata && local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) { | ||
526 | int ac; | ||
527 | |||
528 | queues = 0; | ||
529 | |||
530 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | ||
531 | queues |= BIT(sdata->vif.hw_queue[ac]); | ||
532 | if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE) | ||
533 | queues |= BIT(sdata->vif.cab_queue); | ||
534 | } else { | ||
535 | /* all queues */ | ||
536 | queues = BIT(local->hw.queues) - 1; | ||
537 | } | ||
538 | |||
539 | ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP, | ||
540 | IEEE80211_QUEUE_STOP_REASON_FLUSH); | ||
541 | |||
542 | drv_flush(local, queues, false); | ||
543 | |||
544 | ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP, | ||
545 | IEEE80211_QUEUE_STOP_REASON_FLUSH); | ||
546 | } | ||
547 | |||
514 | void ieee80211_iterate_active_interfaces( | 548 | void ieee80211_iterate_active_interfaces( |
515 | struct ieee80211_hw *hw, u32 iter_flags, | 549 | struct ieee80211_hw *hw, u32 iter_flags, |
516 | void (*iterator)(void *data, u8 *mac, | 550 | void (*iterator)(void *data, u8 *mac, |
@@ -1651,8 +1685,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1651 | mutex_unlock(&local->sta_mtx); | 1685 | mutex_unlock(&local->sta_mtx); |
1652 | } | 1686 | } |
1653 | 1687 | ||
1654 | ieee80211_wake_queues_by_reason(hw, | 1688 | ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP, |
1655 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 1689 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); |
1656 | 1690 | ||
1657 | /* | 1691 | /* |
1658 | * If this is for hw restart things are still running. | 1692 | * If this is for hw restart things are still running. |
diff --git a/net/wireless/core.c b/net/wireless/core.c index 00be55530a32..84c9ad7e1dca 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -1126,8 +1126,10 @@ static int __init cfg80211_init(void) | |||
1126 | goto out_fail_reg; | 1126 | goto out_fail_reg; |
1127 | 1127 | ||
1128 | cfg80211_wq = create_singlethread_workqueue("cfg80211"); | 1128 | cfg80211_wq = create_singlethread_workqueue("cfg80211"); |
1129 | if (!cfg80211_wq) | 1129 | if (!cfg80211_wq) { |
1130 | err = -ENOMEM; | ||
1130 | goto out_fail_wq; | 1131 | goto out_fail_wq; |
1132 | } | ||
1131 | 1133 | ||
1132 | return 0; | 1134 | return 0; |
1133 | 1135 | ||
diff --git a/net/wireless/core.h b/net/wireless/core.h index b5174f65cc9a..124e5e773fbc 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -500,14 +500,12 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, | |||
500 | void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, | 500 | void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, |
501 | enum nl80211_iftype iftype, int num); | 501 | enum nl80211_iftype iftype, int num); |
502 | 502 | ||
503 | |||
504 | void cfg80211_leave(struct cfg80211_registered_device *rdev, | 503 | void cfg80211_leave(struct cfg80211_registered_device *rdev, |
505 | struct wireless_dev *wdev); | 504 | struct wireless_dev *wdev); |
506 | 505 | ||
507 | void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, | 506 | void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, |
508 | struct wireless_dev *wdev); | 507 | struct wireless_dev *wdev); |
509 | 508 | ||
510 | |||
511 | #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 | 509 | #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 |
512 | 510 | ||
513 | #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS | 511 | #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index ff6f7ae35586..a9dc5c736df0 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -228,6 +228,7 @@ void cfg80211_conn_work(struct work_struct *work) | |||
228 | rtnl_lock(); | 228 | rtnl_lock(); |
229 | cfg80211_lock_rdev(rdev); | 229 | cfg80211_lock_rdev(rdev); |
230 | mutex_lock(&rdev->devlist_mtx); | 230 | mutex_lock(&rdev->devlist_mtx); |
231 | mutex_lock(&rdev->sched_scan_mtx); | ||
231 | 232 | ||
232 | list_for_each_entry(wdev, &rdev->wdev_list, list) { | 233 | list_for_each_entry(wdev, &rdev->wdev_list, list) { |
233 | wdev_lock(wdev); | 234 | wdev_lock(wdev); |
@@ -235,7 +236,7 @@ void cfg80211_conn_work(struct work_struct *work) | |||
235 | wdev_unlock(wdev); | 236 | wdev_unlock(wdev); |
236 | continue; | 237 | continue; |
237 | } | 238 | } |
238 | if (wdev->sme_state != CFG80211_SME_CONNECTING) { | 239 | if (wdev->sme_state != CFG80211_SME_CONNECTING || !wdev->conn) { |
239 | wdev_unlock(wdev); | 240 | wdev_unlock(wdev); |
240 | continue; | 241 | continue; |
241 | } | 242 | } |
@@ -252,6 +253,7 @@ void cfg80211_conn_work(struct work_struct *work) | |||
252 | wdev_unlock(wdev); | 253 | wdev_unlock(wdev); |
253 | } | 254 | } |
254 | 255 | ||
256 | mutex_unlock(&rdev->sched_scan_mtx); | ||
255 | mutex_unlock(&rdev->devlist_mtx); | 257 | mutex_unlock(&rdev->devlist_mtx); |
256 | cfg80211_unlock_rdev(rdev); | 258 | cfg80211_unlock_rdev(rdev); |
257 | rtnl_unlock(); | 259 | rtnl_unlock(); |