diff options
Diffstat (limited to 'drivers/net')
132 files changed, 4370 insertions, 1298 deletions
diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c index f92050617ae6..5147ebe4cd05 100644 --- a/drivers/net/wireless/ath/ar5523/ar5523.c +++ b/drivers/net/wireless/ath/ar5523/ar5523.c | |||
@@ -779,8 +779,6 @@ static void ar5523_tx(struct ieee80211_hw *hw, | |||
779 | ieee80211_stop_queues(hw); | 779 | ieee80211_stop_queues(hw); |
780 | } | 780 | } |
781 | 781 | ||
782 | data->skb = skb; | ||
783 | |||
784 | spin_lock_irqsave(&ar->tx_data_list_lock, flags); | 782 | spin_lock_irqsave(&ar->tx_data_list_lock, flags); |
785 | list_add_tail(&data->list, &ar->tx_queue_pending); | 783 | list_add_tail(&data->list, &ar->tx_queue_pending); |
786 | spin_unlock_irqrestore(&ar->tx_data_list_lock, flags); | 784 | spin_unlock_irqrestore(&ar->tx_data_list_lock, flags); |
@@ -817,10 +815,13 @@ static void ar5523_tx_work_locked(struct ar5523 *ar) | |||
817 | if (!data) | 815 | if (!data) |
818 | break; | 816 | break; |
819 | 817 | ||
820 | skb = data->skb; | 818 | txi = container_of((void *)data, struct ieee80211_tx_info, |
819 | driver_data); | ||
821 | txqid = 0; | 820 | txqid = 0; |
822 | txi = IEEE80211_SKB_CB(skb); | 821 | |
822 | skb = container_of((void *)txi, struct sk_buff, cb); | ||
823 | paylen = skb->len; | 823 | paylen = skb->len; |
824 | |||
824 | urb = usb_alloc_urb(0, GFP_KERNEL); | 825 | urb = usb_alloc_urb(0, GFP_KERNEL); |
825 | if (!urb) { | 826 | if (!urb) { |
826 | ar5523_err(ar, "Failed to allocate TX urb\n"); | 827 | ar5523_err(ar, "Failed to allocate TX urb\n"); |
diff --git a/drivers/net/wireless/ath/ar5523/ar5523.h b/drivers/net/wireless/ath/ar5523/ar5523.h index 00c6fd346d48..9a322a65cdb5 100644 --- a/drivers/net/wireless/ath/ar5523/ar5523.h +++ b/drivers/net/wireless/ath/ar5523/ar5523.h | |||
@@ -74,7 +74,6 @@ struct ar5523_tx_cmd { | |||
74 | struct ar5523_tx_data { | 74 | struct ar5523_tx_data { |
75 | struct list_head list; | 75 | struct list_head list; |
76 | struct ar5523 *ar; | 76 | struct ar5523 *ar; |
77 | struct sk_buff *skb; | ||
78 | struct urb *urb; | 77 | struct urb *urb; |
79 | }; | 78 | }; |
80 | 79 | ||
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index 1eebe2ea3dfb..7e9481099a8e 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h | |||
@@ -131,6 +131,9 @@ struct ath_ops { | |||
131 | void (*enable_write_buffer)(void *); | 131 | void (*enable_write_buffer)(void *); |
132 | void (*write_flush) (void *); | 132 | void (*write_flush) (void *); |
133 | u32 (*rmw)(void *, u32 reg_offset, u32 set, u32 clr); | 133 | u32 (*rmw)(void *, u32 reg_offset, u32 set, u32 clr); |
134 | void (*enable_rmw_buffer)(void *); | ||
135 | void (*rmw_flush) (void *); | ||
136 | |||
134 | }; | 137 | }; |
135 | 138 | ||
136 | struct ath_common; | 139 | struct ath_common; |
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 1ed7a88aeea9..7ca0d6f930fd 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -1283,6 +1283,7 @@ struct ath5k_hw { | |||
1283 | #define ATH_STAT_PROMISC 1 | 1283 | #define ATH_STAT_PROMISC 1 |
1284 | #define ATH_STAT_LEDSOFT 2 /* enable LED gpio status */ | 1284 | #define ATH_STAT_LEDSOFT 2 /* enable LED gpio status */ |
1285 | #define ATH_STAT_STARTED 3 /* opened & irqs enabled */ | 1285 | #define ATH_STAT_STARTED 3 /* opened & irqs enabled */ |
1286 | #define ATH_STAT_RESET 4 /* hw reset */ | ||
1286 | 1287 | ||
1287 | unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */ | 1288 | unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */ |
1288 | unsigned int fif_filter_flags; /* Current FIF_* filter flags */ | 1289 | unsigned int fif_filter_flags; /* Current FIF_* filter flags */ |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 57a80e89822d..a6131825c9f6 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -1523,6 +1523,9 @@ ath5k_set_current_imask(struct ath5k_hw *ah) | |||
1523 | enum ath5k_int imask; | 1523 | enum ath5k_int imask; |
1524 | unsigned long flags; | 1524 | unsigned long flags; |
1525 | 1525 | ||
1526 | if (test_bit(ATH_STAT_RESET, ah->status)) | ||
1527 | return; | ||
1528 | |||
1526 | spin_lock_irqsave(&ah->irqlock, flags); | 1529 | spin_lock_irqsave(&ah->irqlock, flags); |
1527 | imask = ah->imask; | 1530 | imask = ah->imask; |
1528 | if (ah->rx_pending) | 1531 | if (ah->rx_pending) |
@@ -2858,10 +2861,12 @@ ath5k_reset(struct ath5k_hw *ah, struct ieee80211_channel *chan, | |||
2858 | { | 2861 | { |
2859 | struct ath_common *common = ath5k_hw_common(ah); | 2862 | struct ath_common *common = ath5k_hw_common(ah); |
2860 | int ret, ani_mode; | 2863 | int ret, ani_mode; |
2861 | bool fast; | 2864 | bool fast = chan && modparam_fastchanswitch ? 1 : 0; |
2862 | 2865 | ||
2863 | ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "resetting\n"); | 2866 | ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "resetting\n"); |
2864 | 2867 | ||
2868 | __set_bit(ATH_STAT_RESET, ah->status); | ||
2869 | |||
2865 | ath5k_hw_set_imr(ah, 0); | 2870 | ath5k_hw_set_imr(ah, 0); |
2866 | synchronize_irq(ah->irq); | 2871 | synchronize_irq(ah->irq); |
2867 | ath5k_stop_tasklets(ah); | 2872 | ath5k_stop_tasklets(ah); |
@@ -2876,11 +2881,29 @@ ath5k_reset(struct ath5k_hw *ah, struct ieee80211_channel *chan, | |||
2876 | * so we should also free any remaining | 2881 | * so we should also free any remaining |
2877 | * tx buffers */ | 2882 | * tx buffers */ |
2878 | ath5k_drain_tx_buffs(ah); | 2883 | ath5k_drain_tx_buffs(ah); |
2884 | |||
2885 | /* Stop PCU */ | ||
2886 | ath5k_hw_stop_rx_pcu(ah); | ||
2887 | |||
2888 | /* Stop DMA | ||
2889 | * | ||
2890 | * Note: If DMA didn't stop continue | ||
2891 | * since only a reset will fix it. | ||
2892 | */ | ||
2893 | ret = ath5k_hw_dma_stop(ah); | ||
2894 | |||
2895 | /* RF Bus grant won't work if we have pending | ||
2896 | * frames | ||
2897 | */ | ||
2898 | if (ret && fast) { | ||
2899 | ATH5K_DBG(ah, ATH5K_DEBUG_RESET, | ||
2900 | "DMA didn't stop, falling back to normal reset\n"); | ||
2901 | fast = false; | ||
2902 | } | ||
2903 | |||
2879 | if (chan) | 2904 | if (chan) |
2880 | ah->curchan = chan; | 2905 | ah->curchan = chan; |
2881 | 2906 | ||
2882 | fast = ((chan != NULL) && modparam_fastchanswitch) ? 1 : 0; | ||
2883 | |||
2884 | ret = ath5k_hw_reset(ah, ah->opmode, ah->curchan, fast, skip_pcu); | 2907 | ret = ath5k_hw_reset(ah, ah->opmode, ah->curchan, fast, skip_pcu); |
2885 | if (ret) { | 2908 | if (ret) { |
2886 | ATH5K_ERR(ah, "can't reset hardware (%d)\n", ret); | 2909 | ATH5K_ERR(ah, "can't reset hardware (%d)\n", ret); |
@@ -2934,6 +2957,8 @@ ath5k_reset(struct ath5k_hw *ah, struct ieee80211_channel *chan, | |||
2934 | */ | 2957 | */ |
2935 | /* ath5k_chan_change(ah, c); */ | 2958 | /* ath5k_chan_change(ah, c); */ |
2936 | 2959 | ||
2960 | __clear_bit(ATH_STAT_RESET, ah->status); | ||
2961 | |||
2937 | ath5k_beacon_config(ah); | 2962 | ath5k_beacon_config(ah); |
2938 | /* intrs are enabled by ath5k_beacon_config */ | 2963 | /* intrs are enabled by ath5k_beacon_config */ |
2939 | 2964 | ||
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index b9b651ea9851..99e62f99a182 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c | |||
@@ -1169,30 +1169,6 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1169 | if (ah->ah_version == AR5K_AR5212) | 1169 | if (ah->ah_version == AR5K_AR5212) |
1170 | ath5k_hw_set_sleep_clock(ah, false); | 1170 | ath5k_hw_set_sleep_clock(ah, false); |
1171 | 1171 | ||
1172 | /* | ||
1173 | * Stop PCU | ||
1174 | */ | ||
1175 | ath5k_hw_stop_rx_pcu(ah); | ||
1176 | |||
1177 | /* | ||
1178 | * Stop DMA | ||
1179 | * | ||
1180 | * Note: If DMA didn't stop continue | ||
1181 | * since only a reset will fix it. | ||
1182 | */ | ||
1183 | ret = ath5k_hw_dma_stop(ah); | ||
1184 | |||
1185 | /* RF Bus grant won't work if we have pending | ||
1186 | * frames */ | ||
1187 | if (ret && fast) { | ||
1188 | ATH5K_DBG(ah, ATH5K_DEBUG_RESET, | ||
1189 | "DMA didn't stop, falling back to normal reset\n"); | ||
1190 | fast = false; | ||
1191 | /* Non fatal, just continue with | ||
1192 | * normal reset */ | ||
1193 | ret = 0; | ||
1194 | } | ||
1195 | |||
1196 | mode = channel->hw_value; | 1172 | mode = channel->hw_value; |
1197 | switch (mode) { | 1173 | switch (mode) { |
1198 | case AR5K_MODE_11A: | 1174 | case AR5K_MODE_11A: |
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 473972288a84..ecda613c2d54 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -46,7 +46,8 @@ ath9k_hw-y:= \ | |||
46 | ath9k_hw-$(CONFIG_ATH9K_WOW) += ar9003_wow.o | 46 | ath9k_hw-$(CONFIG_ATH9K_WOW) += ar9003_wow.o |
47 | 47 | ||
48 | ath9k_hw-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += btcoex.o \ | 48 | ath9k_hw-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += btcoex.o \ |
49 | ar9003_mci.o | 49 | ar9003_mci.o \ |
50 | ar9003_aic.o | ||
50 | 51 | ||
51 | ath9k_hw-$(CONFIG_ATH9K_PCOEM) += ar9003_rtt.o | 52 | ath9k_hw-$(CONFIG_ATH9K_PCOEM) += ar9003_rtt.o |
52 | 53 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index ca01d17d130f..25e45e4d1a60 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
@@ -107,11 +107,21 @@ static const struct ani_cck_level_entry cck_level_table[] = { | |||
107 | static void ath9k_hw_update_mibstats(struct ath_hw *ah, | 107 | static void ath9k_hw_update_mibstats(struct ath_hw *ah, |
108 | struct ath9k_mib_stats *stats) | 108 | struct ath9k_mib_stats *stats) |
109 | { | 109 | { |
110 | stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL); | 110 | u32 addr[5] = {AR_RTS_OK, AR_RTS_FAIL, AR_ACK_FAIL, |
111 | stats->rts_bad += REG_READ(ah, AR_RTS_FAIL); | 111 | AR_FCS_FAIL, AR_BEACON_CNT}; |
112 | stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL); | 112 | u32 data[5]; |
113 | stats->rts_good += REG_READ(ah, AR_RTS_OK); | 113 | |
114 | stats->beacons += REG_READ(ah, AR_BEACON_CNT); | 114 | REG_READ_MULTI(ah, &addr[0], &data[0], 5); |
115 | /* AR_RTS_OK */ | ||
116 | stats->rts_good += data[0]; | ||
117 | /* AR_RTS_FAIL */ | ||
118 | stats->rts_bad += data[1]; | ||
119 | /* AR_ACK_FAIL */ | ||
120 | stats->ackrcv_bad += data[2]; | ||
121 | /* AR_FCS_FAIL */ | ||
122 | stats->fcs_bad += data[3]; | ||
123 | /* AR_BEACON_CNT */ | ||
124 | stats->beacons += data[4]; | ||
115 | } | 125 | } |
116 | 126 | ||
117 | static void ath9k_ani_restart(struct ath_hw *ah) | 127 | static void ath9k_ani_restart(struct ath_hw *ah) |
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index f273427fdd29..6c23d279525f 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c | |||
@@ -681,12 +681,13 @@ static void ar5008_hw_set_channel_regs(struct ath_hw *ah, | |||
681 | phymode |= AR_PHY_FC_DYN2040_PRI_CH; | 681 | phymode |= AR_PHY_FC_DYN2040_PRI_CH; |
682 | 682 | ||
683 | } | 683 | } |
684 | ENABLE_REGWRITE_BUFFER(ah); | ||
684 | REG_WRITE(ah, AR_PHY_TURBO, phymode); | 685 | REG_WRITE(ah, AR_PHY_TURBO, phymode); |
685 | 686 | ||
687 | /* This function do only REG_WRITE, so | ||
688 | * we can include it to REGWRITE_BUFFER. */ | ||
686 | ath9k_hw_set11nmac2040(ah, chan); | 689 | ath9k_hw_set11nmac2040(ah, chan); |
687 | 690 | ||
688 | ENABLE_REGWRITE_BUFFER(ah); | ||
689 | |||
690 | REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S); | 691 | REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S); |
691 | REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S); | 692 | REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S); |
692 | 693 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index 42190b67c671..50fcd343c41a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c | |||
@@ -430,46 +430,43 @@ static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset) | |||
430 | u32 regVal; | 430 | u32 regVal; |
431 | unsigned int i; | 431 | unsigned int i; |
432 | u32 regList[][2] = { | 432 | u32 regList[][2] = { |
433 | { 0x786c, 0 }, | 433 | { AR9285_AN_TOP3, 0 }, |
434 | { 0x7854, 0 }, | 434 | { AR9285_AN_RXTXBB1, 0 }, |
435 | { 0x7820, 0 }, | 435 | { AR9285_AN_RF2G1, 0 }, |
436 | { 0x7824, 0 }, | 436 | { AR9285_AN_RF2G2, 0 }, |
437 | { 0x7868, 0 }, | 437 | { AR9285_AN_TOP2, 0 }, |
438 | { 0x783c, 0 }, | 438 | { AR9285_AN_RF2G8, 0 }, |
439 | { 0x7838, 0 } , | 439 | { AR9285_AN_RF2G7, 0 }, |
440 | { 0x7828, 0 } , | 440 | { AR9285_AN_RF2G3, 0 }, |
441 | }; | 441 | }; |
442 | 442 | ||
443 | for (i = 0; i < ARRAY_SIZE(regList); i++) | 443 | REG_READ_ARRAY(ah, regList, ARRAY_SIZE(regList)); |
444 | regList[i][1] = REG_READ(ah, regList[i][0]); | ||
445 | |||
446 | regVal = REG_READ(ah, 0x7834); | ||
447 | regVal &= (~(0x1)); | ||
448 | REG_WRITE(ah, 0x7834, regVal); | ||
449 | regVal = REG_READ(ah, 0x9808); | ||
450 | regVal |= (0x1 << 27); | ||
451 | REG_WRITE(ah, 0x9808, regVal); | ||
452 | 444 | ||
445 | ENABLE_REG_RMW_BUFFER(ah); | ||
446 | /* 7834, b1=0 */ | ||
447 | REG_CLR_BIT(ah, AR9285_AN_RF2G6, 1 << 0); | ||
448 | /* 9808, b27=1 */ | ||
449 | REG_SET_BIT(ah, 0x9808, 1 << 27); | ||
453 | /* 786c,b23,1, pwddac=1 */ | 450 | /* 786c,b23,1, pwddac=1 */ |
454 | REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); | 451 | REG_SET_BIT(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC); |
455 | /* 7854, b5,1, pdrxtxbb=1 */ | 452 | /* 7854, b5,1, pdrxtxbb=1 */ |
456 | REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); | 453 | REG_SET_BIT(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1); |
457 | /* 7854, b7,1, pdv2i=1 */ | 454 | /* 7854, b7,1, pdv2i=1 */ |
458 | REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); | 455 | REG_SET_BIT(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I); |
459 | /* 7854, b8,1, pddacinterface=1 */ | 456 | /* 7854, b8,1, pddacinterface=1 */ |
460 | REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); | 457 | REG_SET_BIT(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF); |
461 | /* 7824,b12,0, offcal=0 */ | 458 | /* 7824,b12,0, offcal=0 */ |
462 | REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); | 459 | REG_CLR_BIT(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL); |
463 | /* 7838, b1,0, pwddb=0 */ | 460 | /* 7838, b1,0, pwddb=0 */ |
464 | REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); | 461 | REG_CLR_BIT(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB); |
465 | /* 7820,b11,0, enpacal=0 */ | 462 | /* 7820,b11,0, enpacal=0 */ |
466 | REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); | 463 | REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL); |
467 | /* 7820,b25,1, pdpadrv1=0 */ | 464 | /* 7820,b25,1, pdpadrv1=0 */ |
468 | REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); | 465 | REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1); |
469 | /* 7820,b24,0, pdpadrv2=0 */ | 466 | /* 7820,b24,0, pdpadrv2=0 */ |
470 | REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0); | 467 | REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2); |
471 | /* 7820,b23,0, pdpaout=0 */ | 468 | /* 7820,b23,0, pdpaout=0 */ |
472 | REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); | 469 | REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT); |
473 | /* 783c,b14-16,7, padrvgn2tab_0=7 */ | 470 | /* 783c,b14-16,7, padrvgn2tab_0=7 */ |
474 | REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); | 471 | REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); |
475 | /* | 472 | /* |
@@ -477,8 +474,9 @@ static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset) | |||
477 | * does not matter since we turn it off | 474 | * does not matter since we turn it off |
478 | */ | 475 | */ |
479 | REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); | 476 | REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); |
480 | 477 | /* 7828, b0-11, ccom=fff */ | |
481 | REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff); | 478 | REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff); |
479 | REG_RMW_BUFFER_FLUSH(ah); | ||
482 | 480 | ||
483 | /* Set: | 481 | /* Set: |
484 | * localmode=1,bmode=1,bmoderxtx=1,synthon=1, | 482 | * localmode=1,bmode=1,bmoderxtx=1,synthon=1, |
@@ -490,15 +488,16 @@ static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset) | |||
490 | 488 | ||
491 | /* find off_6_1; */ | 489 | /* find off_6_1; */ |
492 | for (i = 6; i > 0; i--) { | 490 | for (i = 6; i > 0; i--) { |
493 | regVal = REG_READ(ah, 0x7834); | 491 | regVal = REG_READ(ah, AR9285_AN_RF2G6); |
494 | regVal |= (1 << (20 + i)); | 492 | regVal |= (1 << (20 + i)); |
495 | REG_WRITE(ah, 0x7834, regVal); | 493 | REG_WRITE(ah, AR9285_AN_RF2G6, regVal); |
496 | udelay(1); | 494 | udelay(1); |
497 | /* regVal = REG_READ(ah, 0x7834); */ | 495 | /* regVal = REG_READ(ah, 0x7834); */ |
498 | regVal &= (~(0x1 << (20 + i))); | 496 | regVal &= (~(0x1 << (20 + i))); |
499 | regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9) | 497 | regVal |= (MS(REG_READ(ah, AR9285_AN_RF2G9), |
498 | AR9285_AN_RXTXBB1_SPARE9) | ||
500 | << (20 + i)); | 499 | << (20 + i)); |
501 | REG_WRITE(ah, 0x7834, regVal); | 500 | REG_WRITE(ah, AR9285_AN_RF2G6, regVal); |
502 | } | 501 | } |
503 | 502 | ||
504 | regVal = (regVal >> 20) & 0x7f; | 503 | regVal = (regVal >> 20) & 0x7f; |
@@ -515,15 +514,15 @@ static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset) | |||
515 | ah->pacal_info.prev_offset = regVal; | 514 | ah->pacal_info.prev_offset = regVal; |
516 | } | 515 | } |
517 | 516 | ||
518 | ENABLE_REGWRITE_BUFFER(ah); | ||
519 | 517 | ||
520 | regVal = REG_READ(ah, 0x7834); | 518 | ENABLE_REG_RMW_BUFFER(ah); |
521 | regVal |= 0x1; | 519 | /* 7834, b1=1 */ |
522 | REG_WRITE(ah, 0x7834, regVal); | 520 | REG_SET_BIT(ah, AR9285_AN_RF2G6, 1 << 0); |
523 | regVal = REG_READ(ah, 0x9808); | 521 | /* 9808, b27=0 */ |
524 | regVal &= (~(0x1 << 27)); | 522 | REG_CLR_BIT(ah, 0x9808, 1 << 27); |
525 | REG_WRITE(ah, 0x9808, regVal); | 523 | REG_RMW_BUFFER_FLUSH(ah); |
526 | 524 | ||
525 | ENABLE_REGWRITE_BUFFER(ah); | ||
527 | for (i = 0; i < ARRAY_SIZE(regList); i++) | 526 | for (i = 0; i < ARRAY_SIZE(regList); i++) |
528 | REG_WRITE(ah, regList[i][0], regList[i][1]); | 527 | REG_WRITE(ah, regList[i][0], regList[i][1]); |
529 | 528 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_aic.c b/drivers/net/wireless/ath/ath9k/ar9003_aic.c new file mode 100644 index 000000000000..1db119d77783 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_aic.c | |||
@@ -0,0 +1,599 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015 Qualcomm Atheros Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "hw.h" | ||
18 | #include "hw-ops.h" | ||
19 | #include "ar9003_mci.h" | ||
20 | #include "ar9003_aic.h" | ||
21 | #include "ar9003_phy.h" | ||
22 | #include "reg_aic.h" | ||
23 | |||
24 | static const u8 com_att_db_table[ATH_AIC_MAX_COM_ATT_DB_TABLE] = { | ||
25 | 0, 3, 9, 15, 21, 27 | ||
26 | }; | ||
27 | |||
28 | static const u16 aic_lin_table[ATH_AIC_MAX_AIC_LIN_TABLE] = { | ||
29 | 8191, 7300, 6506, 5799, 5168, 4606, 4105, 3659, | ||
30 | 3261, 2906, 2590, 2309, 2057, 1834, 1634, 1457, | ||
31 | 1298, 1157, 1031, 919, 819, 730, 651, 580, | ||
32 | 517, 461, 411, 366, 326, 291, 259, 231, | ||
33 | 206, 183, 163, 146, 130, 116, 103, 92, | ||
34 | 82, 73, 65, 58, 52, 46, 41, 37, | ||
35 | 33, 29, 26, 23, 21, 18, 16, 15, | ||
36 | 13, 12, 10, 9, 8, 7, 7, 6, | ||
37 | 5, 5, 4, 4, 3 | ||
38 | }; | ||
39 | |||
40 | static bool ar9003_hw_is_aic_enabled(struct ath_hw *ah) | ||
41 | { | ||
42 | struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; | ||
43 | |||
44 | /* | ||
45 | * Disable AIC for now, until we have all the | ||
46 | * HW code and the driver-layer support ready. | ||
47 | */ | ||
48 | return false; | ||
49 | |||
50 | if (mci_hw->config & ATH_MCI_CONFIG_DISABLE_AIC) | ||
51 | return false; | ||
52 | |||
53 | return true; | ||
54 | } | ||
55 | |||
56 | static int16_t ar9003_aic_find_valid(struct ath_aic_sram_info *cal_sram, | ||
57 | bool dir, u8 index) | ||
58 | { | ||
59 | int16_t i; | ||
60 | |||
61 | if (dir) { | ||
62 | for (i = index + 1; i < ATH_AIC_MAX_BT_CHANNEL; i++) { | ||
63 | if (cal_sram[i].valid) | ||
64 | break; | ||
65 | } | ||
66 | } else { | ||
67 | for (i = index - 1; i >= 0; i--) { | ||
68 | if (cal_sram[i].valid) | ||
69 | break; | ||
70 | } | ||
71 | } | ||
72 | |||
73 | if ((i >= ATH_AIC_MAX_BT_CHANNEL) || (i < 0)) | ||
74 | i = -1; | ||
75 | |||
76 | return i; | ||
77 | } | ||
78 | |||
79 | /* | ||
80 | * type 0: aic_lin_table, 1: com_att_db_table | ||
81 | */ | ||
82 | static int16_t ar9003_aic_find_index(u8 type, int16_t value) | ||
83 | { | ||
84 | int16_t i = -1; | ||
85 | |||
86 | if (type == 0) { | ||
87 | for (i = ATH_AIC_MAX_AIC_LIN_TABLE - 1; i >= 0; i--) { | ||
88 | if (aic_lin_table[i] >= value) | ||
89 | break; | ||
90 | } | ||
91 | } else if (type == 1) { | ||
92 | for (i = 0; i < ATH_AIC_MAX_COM_ATT_DB_TABLE; i++) { | ||
93 | if (com_att_db_table[i] > value) { | ||
94 | i--; | ||
95 | break; | ||
96 | } | ||
97 | } | ||
98 | |||
99 | if (i >= ATH_AIC_MAX_COM_ATT_DB_TABLE) | ||
100 | i = -1; | ||
101 | } | ||
102 | |||
103 | return i; | ||
104 | } | ||
105 | |||
106 | static void ar9003_aic_gain_table(struct ath_hw *ah) | ||
107 | { | ||
108 | u32 aic_atten_word[19], i; | ||
109 | |||
110 | /* Config LNA gain difference */ | ||
111 | REG_WRITE(ah, AR_PHY_BT_COEX_4, 0x2c200a00); | ||
112 | REG_WRITE(ah, AR_PHY_BT_COEX_5, 0x5c4e4438); | ||
113 | |||
114 | /* Program gain table */ | ||
115 | aic_atten_word[0] = (0x1 & 0xf) << 14 | (0x1f & 0x1f) << 9 | (0x0 & 0xf) << 5 | | ||
116 | (0x1f & 0x1f); /* -01 dB: 4'd1, 5'd31, 00 dB: 4'd0, 5'd31 */ | ||
117 | aic_atten_word[1] = (0x3 & 0xf) << 14 | (0x1f & 0x1f) << 9 | (0x2 & 0xf) << 5 | | ||
118 | (0x1f & 0x1f); /* -03 dB: 4'd3, 5'd31, -02 dB: 4'd2, 5'd31 */ | ||
119 | aic_atten_word[2] = (0x5 & 0xf) << 14 | (0x1f & 0x1f) << 9 | (0x4 & 0xf) << 5 | | ||
120 | (0x1f & 0x1f); /* -05 dB: 4'd5, 5'd31, -04 dB: 4'd4, 5'd31 */ | ||
121 | aic_atten_word[3] = (0x1 & 0xf) << 14 | (0x1e & 0x1f) << 9 | (0x0 & 0xf) << 5 | | ||
122 | (0x1e & 0x1f); /* -07 dB: 4'd1, 5'd30, -06 dB: 4'd0, 5'd30 */ | ||
123 | aic_atten_word[4] = (0x3 & 0xf) << 14 | (0x1e & 0x1f) << 9 | (0x2 & 0xf) << 5 | | ||
124 | (0x1e & 0x1f); /* -09 dB: 4'd3, 5'd30, -08 dB: 4'd2, 5'd30 */ | ||
125 | aic_atten_word[5] = (0x5 & 0xf) << 14 | (0x1e & 0x1f) << 9 | (0x4 & 0xf) << 5 | | ||
126 | (0x1e & 0x1f); /* -11 dB: 4'd5, 5'd30, -10 dB: 4'd4, 5'd30 */ | ||
127 | aic_atten_word[6] = (0x1 & 0xf) << 14 | (0xf & 0x1f) << 9 | (0x0 & 0xf) << 5 | | ||
128 | (0xf & 0x1f); /* -13 dB: 4'd1, 5'd15, -12 dB: 4'd0, 5'd15 */ | ||
129 | aic_atten_word[7] = (0x3 & 0xf) << 14 | (0xf & 0x1f) << 9 | (0x2 & 0xf) << 5 | | ||
130 | (0xf & 0x1f); /* -15 dB: 4'd3, 5'd15, -14 dB: 4'd2, 5'd15 */ | ||
131 | aic_atten_word[8] = (0x5 & 0xf) << 14 | (0xf & 0x1f) << 9 | (0x4 & 0xf) << 5 | | ||
132 | (0xf & 0x1f); /* -17 dB: 4'd5, 5'd15, -16 dB: 4'd4, 5'd15 */ | ||
133 | aic_atten_word[9] = (0x1 & 0xf) << 14 | (0x7 & 0x1f) << 9 | (0x0 & 0xf) << 5 | | ||
134 | (0x7 & 0x1f); /* -19 dB: 4'd1, 5'd07, -18 dB: 4'd0, 5'd07 */ | ||
135 | aic_atten_word[10] = (0x3 & 0xf) << 14 | (0x7 & 0x1f) << 9 | (0x2 & 0xf) << 5 | | ||
136 | (0x7 & 0x1f); /* -21 dB: 4'd3, 5'd07, -20 dB: 4'd2, 5'd07 */ | ||
137 | aic_atten_word[11] = (0x5 & 0xf) << 14 | (0x7 & 0x1f) << 9 | (0x4 & 0xf) << 5 | | ||
138 | (0x7 & 0x1f); /* -23 dB: 4'd5, 5'd07, -22 dB: 4'd4, 5'd07 */ | ||
139 | aic_atten_word[12] = (0x7 & 0xf) << 14 | (0x7 & 0x1f) << 9 | (0x6 & 0xf) << 5 | | ||
140 | (0x7 & 0x1f); /* -25 dB: 4'd7, 5'd07, -24 dB: 4'd6, 5'd07 */ | ||
141 | aic_atten_word[13] = (0x3 & 0xf) << 14 | (0x3 & 0x1f) << 9 | (0x2 & 0xf) << 5 | | ||
142 | (0x3 & 0x1f); /* -27 dB: 4'd3, 5'd03, -26 dB: 4'd2, 5'd03 */ | ||
143 | aic_atten_word[14] = (0x5 & 0xf) << 14 | (0x3 & 0x1f) << 9 | (0x4 & 0xf) << 5 | | ||
144 | (0x3 & 0x1f); /* -29 dB: 4'd5, 5'd03, -28 dB: 4'd4, 5'd03 */ | ||
145 | aic_atten_word[15] = (0x1 & 0xf) << 14 | (0x1 & 0x1f) << 9 | (0x0 & 0xf) << 5 | | ||
146 | (0x1 & 0x1f); /* -31 dB: 4'd1, 5'd01, -30 dB: 4'd0, 5'd01 */ | ||
147 | aic_atten_word[16] = (0x3 & 0xf) << 14 | (0x1 & 0x1f) << 9 | (0x2 & 0xf) << 5 | | ||
148 | (0x1 & 0x1f); /* -33 dB: 4'd3, 5'd01, -32 dB: 4'd2, 5'd01 */ | ||
149 | aic_atten_word[17] = (0x5 & 0xf) << 14 | (0x1 & 0x1f) << 9 | (0x4 & 0xf) << 5 | | ||
150 | (0x1 & 0x1f); /* -35 dB: 4'd5, 5'd01, -34 dB: 4'd4, 5'd01 */ | ||
151 | aic_atten_word[18] = (0x7 & 0xf) << 14 | (0x1 & 0x1f) << 9 | (0x6 & 0xf) << 5 | | ||
152 | (0x1 & 0x1f); /* -37 dB: 4'd7, 5'd01, -36 dB: 4'd6, 5'd01 */ | ||
153 | |||
154 | /* Write to Gain table with auto increment enabled. */ | ||
155 | REG_WRITE(ah, (AR_PHY_AIC_SRAM_ADDR_B0 + 0x3000), | ||
156 | (ATH_AIC_SRAM_AUTO_INCREMENT | | ||
157 | ATH_AIC_SRAM_GAIN_TABLE_OFFSET)); | ||
158 | |||
159 | for (i = 0; i < 19; i++) { | ||
160 | REG_WRITE(ah, (AR_PHY_AIC_SRAM_DATA_B0 + 0x3000), | ||
161 | aic_atten_word[i]); | ||
162 | } | ||
163 | } | ||
164 | |||
165 | static u8 ar9003_aic_cal_start(struct ath_hw *ah, u8 min_valid_count) | ||
166 | { | ||
167 | struct ath9k_hw_aic *aic = &ah->btcoex_hw.aic; | ||
168 | int i; | ||
169 | |||
170 | /* Write to Gain table with auto increment enabled. */ | ||
171 | REG_WRITE(ah, (AR_PHY_AIC_SRAM_ADDR_B0 + 0x3000), | ||
172 | (ATH_AIC_SRAM_AUTO_INCREMENT | | ||
173 | ATH_AIC_SRAM_CAL_OFFSET)); | ||
174 | |||
175 | for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) { | ||
176 | REG_WRITE(ah, (AR_PHY_AIC_SRAM_DATA_B0 + 0x3000), 0); | ||
177 | aic->aic_sram[i] = 0; | ||
178 | } | ||
179 | |||
180 | REG_WRITE(ah, AR_PHY_AIC_CTRL_0_B0, | ||
181 | (SM(0, AR_PHY_AIC_MON_ENABLE) | | ||
182 | SM(127, AR_PHY_AIC_CAL_MAX_HOP_COUNT) | | ||
183 | SM(min_valid_count, AR_PHY_AIC_CAL_MIN_VALID_COUNT) | | ||
184 | SM(37, AR_PHY_AIC_F_WLAN) | | ||
185 | SM(1, AR_PHY_AIC_CAL_CH_VALID_RESET) | | ||
186 | SM(0, AR_PHY_AIC_CAL_ENABLE) | | ||
187 | SM(0x40, AR_PHY_AIC_BTTX_PWR_THR) | | ||
188 | SM(0, AR_PHY_AIC_ENABLE))); | ||
189 | |||
190 | REG_WRITE(ah, AR_PHY_AIC_CTRL_0_B1, | ||
191 | (SM(0, AR_PHY_AIC_MON_ENABLE) | | ||
192 | SM(1, AR_PHY_AIC_CAL_CH_VALID_RESET) | | ||
193 | SM(0, AR_PHY_AIC_CAL_ENABLE) | | ||
194 | SM(0x40, AR_PHY_AIC_BTTX_PWR_THR) | | ||
195 | SM(0, AR_PHY_AIC_ENABLE))); | ||
196 | |||
197 | REG_WRITE(ah, AR_PHY_AIC_CTRL_1_B0, | ||
198 | (SM(8, AR_PHY_AIC_CAL_BT_REF_DELAY) | | ||
199 | SM(0, AR_PHY_AIC_BT_IDLE_CFG) | | ||
200 | SM(1, AR_PHY_AIC_STDBY_COND) | | ||
201 | SM(37, AR_PHY_AIC_STDBY_ROT_ATT_DB) | | ||
202 | SM(5, AR_PHY_AIC_STDBY_COM_ATT_DB) | | ||
203 | SM(15, AR_PHY_AIC_RSSI_MAX) | | ||
204 | SM(0, AR_PHY_AIC_RSSI_MIN))); | ||
205 | |||
206 | REG_WRITE(ah, AR_PHY_AIC_CTRL_1_B1, | ||
207 | (SM(15, AR_PHY_AIC_RSSI_MAX) | | ||
208 | SM(0, AR_PHY_AIC_RSSI_MIN))); | ||
209 | |||
210 | REG_WRITE(ah, AR_PHY_AIC_CTRL_2_B0, | ||
211 | (SM(44, AR_PHY_AIC_RADIO_DELAY) | | ||
212 | SM(8, AR_PHY_AIC_CAL_STEP_SIZE_CORR) | | ||
213 | SM(12, AR_PHY_AIC_CAL_ROT_IDX_CORR) | | ||
214 | SM(2, AR_PHY_AIC_CAL_CONV_CHECK_FACTOR) | | ||
215 | SM(5, AR_PHY_AIC_ROT_IDX_COUNT_MAX) | | ||
216 | SM(0, AR_PHY_AIC_CAL_SYNTH_TOGGLE) | | ||
217 | SM(0, AR_PHY_AIC_CAL_SYNTH_AFTER_BTRX) | | ||
218 | SM(200, AR_PHY_AIC_CAL_SYNTH_SETTLING))); | ||
219 | |||
220 | REG_WRITE(ah, AR_PHY_AIC_CTRL_3_B0, | ||
221 | (SM(2, AR_PHY_AIC_MON_MAX_HOP_COUNT) | | ||
222 | SM(1, AR_PHY_AIC_MON_MIN_STALE_COUNT) | | ||
223 | SM(1, AR_PHY_AIC_MON_PWR_EST_LONG) | | ||
224 | SM(2, AR_PHY_AIC_MON_PD_TALLY_SCALING) | | ||
225 | SM(10, AR_PHY_AIC_MON_PERF_THR) | | ||
226 | SM(2, AR_PHY_AIC_CAL_TARGET_MAG_SETTING) | | ||
227 | SM(1, AR_PHY_AIC_CAL_PERF_CHECK_FACTOR) | | ||
228 | SM(1, AR_PHY_AIC_CAL_PWR_EST_LONG))); | ||
229 | |||
230 | REG_WRITE(ah, AR_PHY_AIC_CTRL_4_B0, | ||
231 | (SM(2, AR_PHY_AIC_CAL_ROT_ATT_DB_EST_ISO) | | ||
232 | SM(3, AR_PHY_AIC_CAL_COM_ATT_DB_EST_ISO) | | ||
233 | SM(0, AR_PHY_AIC_CAL_ISO_EST_INIT_SETTING) | | ||
234 | SM(2, AR_PHY_AIC_CAL_COM_ATT_DB_BACKOFF) | | ||
235 | SM(1, AR_PHY_AIC_CAL_COM_ATT_DB_FIXED))); | ||
236 | |||
237 | REG_WRITE(ah, AR_PHY_AIC_CTRL_4_B1, | ||
238 | (SM(2, AR_PHY_AIC_CAL_ROT_ATT_DB_EST_ISO) | | ||
239 | SM(3, AR_PHY_AIC_CAL_COM_ATT_DB_EST_ISO) | | ||
240 | SM(0, AR_PHY_AIC_CAL_ISO_EST_INIT_SETTING) | | ||
241 | SM(2, AR_PHY_AIC_CAL_COM_ATT_DB_BACKOFF) | | ||
242 | SM(1, AR_PHY_AIC_CAL_COM_ATT_DB_FIXED))); | ||
243 | |||
244 | ar9003_aic_gain_table(ah); | ||
245 | |||
246 | /* Need to enable AIC reference signal in BT modem. */ | ||
247 | REG_WRITE(ah, ATH_AIC_BT_JUPITER_CTRL, | ||
248 | (REG_READ(ah, ATH_AIC_BT_JUPITER_CTRL) | | ||
249 | ATH_AIC_BT_AIC_ENABLE)); | ||
250 | |||
251 | aic->aic_cal_start_time = REG_READ(ah, AR_TSF_L32); | ||
252 | |||
253 | /* Start calibration */ | ||
254 | REG_CLR_BIT(ah, AR_PHY_AIC_CTRL_0_B1, AR_PHY_AIC_CAL_ENABLE); | ||
255 | REG_SET_BIT(ah, AR_PHY_AIC_CTRL_0_B1, AR_PHY_AIC_CAL_CH_VALID_RESET); | ||
256 | REG_SET_BIT(ah, AR_PHY_AIC_CTRL_0_B1, AR_PHY_AIC_CAL_ENABLE); | ||
257 | |||
258 | aic->aic_caled_chan = 0; | ||
259 | aic->aic_cal_state = AIC_CAL_STATE_STARTED; | ||
260 | |||
261 | return aic->aic_cal_state; | ||
262 | } | ||
263 | |||
264 | static bool ar9003_aic_cal_post_process(struct ath_hw *ah) | ||
265 | { | ||
266 | struct ath9k_hw_aic *aic = &ah->btcoex_hw.aic; | ||
267 | struct ath_aic_sram_info cal_sram[ATH_AIC_MAX_BT_CHANNEL]; | ||
268 | struct ath_aic_out_info aic_sram[ATH_AIC_MAX_BT_CHANNEL]; | ||
269 | u32 dir_path_gain_idx, quad_path_gain_idx, value; | ||
270 | u32 fixed_com_att_db; | ||
271 | int8_t dir_path_sign, quad_path_sign; | ||
272 | int16_t i; | ||
273 | bool ret = true; | ||
274 | |||
275 | memset(&cal_sram, 0, sizeof(cal_sram)); | ||
276 | memset(&aic_sram, 0, sizeof(aic_sram)); | ||
277 | |||
278 | for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) { | ||
279 | value = aic->aic_sram[i]; | ||
280 | |||
281 | cal_sram[i].valid = | ||
282 | MS(value, AR_PHY_AIC_SRAM_VALID); | ||
283 | cal_sram[i].rot_quad_att_db = | ||
284 | MS(value, AR_PHY_AIC_SRAM_ROT_QUAD_ATT_DB); | ||
285 | cal_sram[i].vga_quad_sign = | ||
286 | MS(value, AR_PHY_AIC_SRAM_VGA_QUAD_SIGN); | ||
287 | cal_sram[i].rot_dir_att_db = | ||
288 | MS(value, AR_PHY_AIC_SRAM_ROT_DIR_ATT_DB); | ||
289 | cal_sram[i].vga_dir_sign = | ||
290 | MS(value, AR_PHY_AIC_SRAM_VGA_DIR_SIGN); | ||
291 | cal_sram[i].com_att_6db = | ||
292 | MS(value, AR_PHY_AIC_SRAM_COM_ATT_6DB); | ||
293 | |||
294 | if (cal_sram[i].valid) { | ||
295 | dir_path_gain_idx = cal_sram[i].rot_dir_att_db + | ||
296 | com_att_db_table[cal_sram[i].com_att_6db]; | ||
297 | quad_path_gain_idx = cal_sram[i].rot_quad_att_db + | ||
298 | com_att_db_table[cal_sram[i].com_att_6db]; | ||
299 | |||
300 | dir_path_sign = (cal_sram[i].vga_dir_sign) ? 1 : -1; | ||
301 | quad_path_sign = (cal_sram[i].vga_quad_sign) ? 1 : -1; | ||
302 | |||
303 | aic_sram[i].dir_path_gain_lin = dir_path_sign * | ||
304 | aic_lin_table[dir_path_gain_idx]; | ||
305 | aic_sram[i].quad_path_gain_lin = quad_path_sign * | ||
306 | aic_lin_table[quad_path_gain_idx]; | ||
307 | } | ||
308 | } | ||
309 | |||
310 | for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) { | ||
311 | int16_t start_idx, end_idx; | ||
312 | |||
313 | if (cal_sram[i].valid) | ||
314 | continue; | ||
315 | |||
316 | start_idx = ar9003_aic_find_valid(cal_sram, 0, i); | ||
317 | end_idx = ar9003_aic_find_valid(cal_sram, 1, i); | ||
318 | |||
319 | if (start_idx < 0) { | ||
320 | /* extrapolation */ | ||
321 | start_idx = end_idx; | ||
322 | end_idx = ar9003_aic_find_valid(cal_sram, 1, start_idx); | ||
323 | |||
324 | if (end_idx < 0) { | ||
325 | ret = false; | ||
326 | break; | ||
327 | } | ||
328 | |||
329 | aic_sram[i].dir_path_gain_lin = | ||
330 | ((aic_sram[start_idx].dir_path_gain_lin - | ||
331 | aic_sram[end_idx].dir_path_gain_lin) * | ||
332 | (start_idx - i) + ((end_idx - i) >> 1)) / | ||
333 | (end_idx - i) + | ||
334 | aic_sram[start_idx].dir_path_gain_lin; | ||
335 | aic_sram[i].quad_path_gain_lin = | ||
336 | ((aic_sram[start_idx].quad_path_gain_lin - | ||
337 | aic_sram[end_idx].quad_path_gain_lin) * | ||
338 | (start_idx - i) + ((end_idx - i) >> 1)) / | ||
339 | (end_idx - i) + | ||
340 | aic_sram[start_idx].quad_path_gain_lin; | ||
341 | } | ||
342 | |||
343 | if (end_idx < 0) { | ||
344 | /* extrapolation */ | ||
345 | end_idx = ar9003_aic_find_valid(cal_sram, 0, start_idx); | ||
346 | |||
347 | if (end_idx < 0) { | ||
348 | ret = false; | ||
349 | break; | ||
350 | } | ||
351 | |||
352 | aic_sram[i].dir_path_gain_lin = | ||
353 | ((aic_sram[start_idx].dir_path_gain_lin - | ||
354 | aic_sram[end_idx].dir_path_gain_lin) * | ||
355 | (i - start_idx) + ((start_idx - end_idx) >> 1)) / | ||
356 | (start_idx - end_idx) + | ||
357 | aic_sram[start_idx].dir_path_gain_lin; | ||
358 | aic_sram[i].quad_path_gain_lin = | ||
359 | ((aic_sram[start_idx].quad_path_gain_lin - | ||
360 | aic_sram[end_idx].quad_path_gain_lin) * | ||
361 | (i - start_idx) + ((start_idx - end_idx) >> 1)) / | ||
362 | (start_idx - end_idx) + | ||
363 | aic_sram[start_idx].quad_path_gain_lin; | ||
364 | |||
365 | } else if (start_idx >= 0){ | ||
366 | /* interpolation */ | ||
367 | aic_sram[i].dir_path_gain_lin = | ||
368 | (((end_idx - i) * aic_sram[start_idx].dir_path_gain_lin) + | ||
369 | ((i - start_idx) * aic_sram[end_idx].dir_path_gain_lin) + | ||
370 | ((end_idx - start_idx) >> 1)) / | ||
371 | (end_idx - start_idx); | ||
372 | aic_sram[i].quad_path_gain_lin = | ||
373 | (((end_idx - i) * aic_sram[start_idx].quad_path_gain_lin) + | ||
374 | ((i - start_idx) * aic_sram[end_idx].quad_path_gain_lin) + | ||
375 | ((end_idx - start_idx) >> 1))/ | ||
376 | (end_idx - start_idx); | ||
377 | } | ||
378 | } | ||
379 | |||
380 | /* From dir/quad_path_gain_lin to sram. */ | ||
381 | i = ar9003_aic_find_valid(cal_sram, 1, 0); | ||
382 | if (i < 0) { | ||
383 | i = 0; | ||
384 | ret = false; | ||
385 | } | ||
386 | fixed_com_att_db = com_att_db_table[cal_sram[i].com_att_6db]; | ||
387 | |||
388 | for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) { | ||
389 | int16_t rot_dir_path_att_db, rot_quad_path_att_db; | ||
390 | |||
391 | aic_sram[i].sram.vga_dir_sign = | ||
392 | (aic_sram[i].dir_path_gain_lin >= 0) ? 1 : 0; | ||
393 | aic_sram[i].sram.vga_quad_sign= | ||
394 | (aic_sram[i].quad_path_gain_lin >= 0) ? 1 : 0; | ||
395 | |||
396 | rot_dir_path_att_db = | ||
397 | ar9003_aic_find_index(0, abs(aic_sram[i].dir_path_gain_lin)) - | ||
398 | fixed_com_att_db; | ||
399 | rot_quad_path_att_db = | ||
400 | ar9003_aic_find_index(0, abs(aic_sram[i].quad_path_gain_lin)) - | ||
401 | fixed_com_att_db; | ||
402 | |||
403 | aic_sram[i].sram.com_att_6db = | ||
404 | ar9003_aic_find_index(1, fixed_com_att_db); | ||
405 | |||
406 | aic_sram[i].sram.valid = 1; | ||
407 | |||
408 | aic_sram[i].sram.rot_dir_att_db = | ||
409 | min(max(rot_dir_path_att_db, | ||
410 | (int16_t)ATH_AIC_MIN_ROT_DIR_ATT_DB), | ||
411 | ATH_AIC_MAX_ROT_DIR_ATT_DB); | ||
412 | aic_sram[i].sram.rot_quad_att_db = | ||
413 | min(max(rot_quad_path_att_db, | ||
414 | (int16_t)ATH_AIC_MIN_ROT_QUAD_ATT_DB), | ||
415 | ATH_AIC_MAX_ROT_QUAD_ATT_DB); | ||
416 | } | ||
417 | |||
418 | for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) { | ||
419 | aic->aic_sram[i] = (SM(aic_sram[i].sram.vga_dir_sign, | ||
420 | AR_PHY_AIC_SRAM_VGA_DIR_SIGN) | | ||
421 | SM(aic_sram[i].sram.vga_quad_sign, | ||
422 | AR_PHY_AIC_SRAM_VGA_QUAD_SIGN) | | ||
423 | SM(aic_sram[i].sram.com_att_6db, | ||
424 | AR_PHY_AIC_SRAM_COM_ATT_6DB) | | ||
425 | SM(aic_sram[i].sram.valid, | ||
426 | AR_PHY_AIC_SRAM_VALID) | | ||
427 | SM(aic_sram[i].sram.rot_dir_att_db, | ||
428 | AR_PHY_AIC_SRAM_ROT_DIR_ATT_DB) | | ||
429 | SM(aic_sram[i].sram.rot_quad_att_db, | ||
430 | AR_PHY_AIC_SRAM_ROT_QUAD_ATT_DB)); | ||
431 | } | ||
432 | |||
433 | return ret; | ||
434 | } | ||
435 | |||
436 | static void ar9003_aic_cal_done(struct ath_hw *ah) | ||
437 | { | ||
438 | struct ath9k_hw_aic *aic = &ah->btcoex_hw.aic; | ||
439 | |||
440 | /* Disable AIC reference signal in BT modem. */ | ||
441 | REG_WRITE(ah, ATH_AIC_BT_JUPITER_CTRL, | ||
442 | (REG_READ(ah, ATH_AIC_BT_JUPITER_CTRL) & | ||
443 | ~ATH_AIC_BT_AIC_ENABLE)); | ||
444 | |||
445 | if (ar9003_aic_cal_post_process(ah)) | ||
446 | aic->aic_cal_state = AIC_CAL_STATE_DONE; | ||
447 | else | ||
448 | aic->aic_cal_state = AIC_CAL_STATE_ERROR; | ||
449 | } | ||
450 | |||
451 | static u8 ar9003_aic_cal_continue(struct ath_hw *ah, bool cal_once) | ||
452 | { | ||
453 | struct ath_common *common = ath9k_hw_common(ah); | ||
454 | struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; | ||
455 | struct ath9k_hw_aic *aic = &ah->btcoex_hw.aic; | ||
456 | int i, num_chan; | ||
457 | |||
458 | num_chan = MS(mci_hw->config, ATH_MCI_CONFIG_AIC_CAL_NUM_CHAN); | ||
459 | |||
460 | if (!num_chan) { | ||
461 | aic->aic_cal_state = AIC_CAL_STATE_ERROR; | ||
462 | return aic->aic_cal_state; | ||
463 | } | ||
464 | |||
465 | if (cal_once) { | ||
466 | for (i = 0; i < 10000; i++) { | ||
467 | if ((REG_READ(ah, AR_PHY_AIC_CTRL_0_B1) & | ||
468 | AR_PHY_AIC_CAL_ENABLE) == 0) | ||
469 | break; | ||
470 | |||
471 | udelay(100); | ||
472 | } | ||
473 | } | ||
474 | |||
475 | /* | ||
476 | * Use AR_PHY_AIC_CAL_ENABLE bit instead of AR_PHY_AIC_CAL_DONE. | ||
477 | * Sometimes CAL_DONE bit is not asserted. | ||
478 | */ | ||
479 | if ((REG_READ(ah, AR_PHY_AIC_CTRL_0_B1) & | ||
480 | AR_PHY_AIC_CAL_ENABLE) != 0) { | ||
481 | ath_dbg(common, MCI, "AIC cal is not done after 40ms"); | ||
482 | goto exit; | ||
483 | } | ||
484 | |||
485 | REG_WRITE(ah, AR_PHY_AIC_SRAM_ADDR_B1, | ||
486 | (ATH_AIC_SRAM_CAL_OFFSET | ATH_AIC_SRAM_AUTO_INCREMENT)); | ||
487 | |||
488 | for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) { | ||
489 | u32 value; | ||
490 | |||
491 | value = REG_READ(ah, AR_PHY_AIC_SRAM_DATA_B1); | ||
492 | |||
493 | if (value & 0x01) { | ||
494 | if (aic->aic_sram[i] == 0) | ||
495 | aic->aic_caled_chan++; | ||
496 | |||
497 | aic->aic_sram[i] = value; | ||
498 | |||
499 | if (!cal_once) | ||
500 | break; | ||
501 | } | ||
502 | } | ||
503 | |||
504 | if ((aic->aic_caled_chan >= num_chan) || cal_once) { | ||
505 | ar9003_aic_cal_done(ah); | ||
506 | } else { | ||
507 | /* Start calibration */ | ||
508 | REG_CLR_BIT(ah, AR_PHY_AIC_CTRL_0_B1, AR_PHY_AIC_CAL_ENABLE); | ||
509 | REG_SET_BIT(ah, AR_PHY_AIC_CTRL_0_B1, | ||
510 | AR_PHY_AIC_CAL_CH_VALID_RESET); | ||
511 | REG_SET_BIT(ah, AR_PHY_AIC_CTRL_0_B1, AR_PHY_AIC_CAL_ENABLE); | ||
512 | } | ||
513 | exit: | ||
514 | return aic->aic_cal_state; | ||
515 | |||
516 | } | ||
517 | |||
518 | u8 ar9003_aic_calibration(struct ath_hw *ah) | ||
519 | { | ||
520 | struct ath9k_hw_aic *aic = &ah->btcoex_hw.aic; | ||
521 | u8 cal_ret = AIC_CAL_STATE_ERROR; | ||
522 | |||
523 | switch (aic->aic_cal_state) { | ||
524 | case AIC_CAL_STATE_IDLE: | ||
525 | cal_ret = ar9003_aic_cal_start(ah, 1); | ||
526 | break; | ||
527 | case AIC_CAL_STATE_STARTED: | ||
528 | cal_ret = ar9003_aic_cal_continue(ah, false); | ||
529 | break; | ||
530 | case AIC_CAL_STATE_DONE: | ||
531 | cal_ret = AIC_CAL_STATE_DONE; | ||
532 | break; | ||
533 | default: | ||
534 | break; | ||
535 | } | ||
536 | |||
537 | return cal_ret; | ||
538 | } | ||
539 | |||
540 | u8 ar9003_aic_start_normal(struct ath_hw *ah) | ||
541 | { | ||
542 | struct ath9k_hw_aic *aic = &ah->btcoex_hw.aic; | ||
543 | int16_t i; | ||
544 | |||
545 | if (aic->aic_cal_state != AIC_CAL_STATE_DONE) | ||
546 | return 1; | ||
547 | |||
548 | ar9003_aic_gain_table(ah); | ||
549 | |||
550 | REG_WRITE(ah, AR_PHY_AIC_SRAM_ADDR_B1, ATH_AIC_SRAM_AUTO_INCREMENT); | ||
551 | |||
552 | for (i = 0; i < ATH_AIC_MAX_BT_CHANNEL; i++) { | ||
553 | REG_WRITE(ah, AR_PHY_AIC_SRAM_DATA_B1, aic->aic_sram[i]); | ||
554 | } | ||
555 | |||
556 | /* FIXME: Replace these with proper register names */ | ||
557 | REG_WRITE(ah, 0xa6b0, 0x80); | ||
558 | REG_WRITE(ah, 0xa6b4, 0x5b2df0); | ||
559 | REG_WRITE(ah, 0xa6b8, 0x10762cc8); | ||
560 | REG_WRITE(ah, 0xa6bc, 0x1219a4b); | ||
561 | REG_WRITE(ah, 0xa6c0, 0x1e01); | ||
562 | REG_WRITE(ah, 0xb6b4, 0xf0); | ||
563 | REG_WRITE(ah, 0xb6c0, 0x1e01); | ||
564 | REG_WRITE(ah, 0xb6b0, 0x81); | ||
565 | REG_WRITE(ah, AR_PHY_65NM_CH1_RXTX4, 0x40000000); | ||
566 | |||
567 | aic->aic_enabled = true; | ||
568 | |||
569 | return 0; | ||
570 | } | ||
571 | |||
572 | u8 ar9003_aic_cal_reset(struct ath_hw *ah) | ||
573 | { | ||
574 | struct ath9k_hw_aic *aic = &ah->btcoex_hw.aic; | ||
575 | |||
576 | aic->aic_cal_state = AIC_CAL_STATE_IDLE; | ||
577 | return aic->aic_cal_state; | ||
578 | } | ||
579 | |||
580 | u8 ar9003_aic_calibration_single(struct ath_hw *ah) | ||
581 | { | ||
582 | struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; | ||
583 | u8 cal_ret; | ||
584 | int num_chan; | ||
585 | |||
586 | num_chan = MS(mci_hw->config, ATH_MCI_CONFIG_AIC_CAL_NUM_CHAN); | ||
587 | |||
588 | (void) ar9003_aic_cal_start(ah, num_chan); | ||
589 | cal_ret = ar9003_aic_cal_continue(ah, true); | ||
590 | |||
591 | return cal_ret; | ||
592 | } | ||
593 | |||
594 | void ar9003_hw_attach_aic_ops(struct ath_hw *ah) | ||
595 | { | ||
596 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | ||
597 | |||
598 | priv_ops->is_aic_enabled = ar9003_hw_is_aic_enabled; | ||
599 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_aic.h b/drivers/net/wireless/ath/ath9k/ar9003_aic.h new file mode 100644 index 000000000000..86f40644be43 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_aic.h | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015 Qualcomm Atheros Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef AR9003_AIC_H | ||
18 | #define AR9003_AIC_H | ||
19 | |||
20 | #define ATH_AIC_MAX_COM_ATT_DB_TABLE 6 | ||
21 | #define ATH_AIC_MAX_AIC_LIN_TABLE 69 | ||
22 | #define ATH_AIC_MIN_ROT_DIR_ATT_DB 0 | ||
23 | #define ATH_AIC_MIN_ROT_QUAD_ATT_DB 0 | ||
24 | #define ATH_AIC_MAX_ROT_DIR_ATT_DB 37 | ||
25 | #define ATH_AIC_MAX_ROT_QUAD_ATT_DB 37 | ||
26 | #define ATH_AIC_SRAM_AUTO_INCREMENT 0x80000000 | ||
27 | #define ATH_AIC_SRAM_GAIN_TABLE_OFFSET 0x280 | ||
28 | #define ATH_AIC_SRAM_CAL_OFFSET 0x140 | ||
29 | #define ATH_AIC_SRAM_OFFSET 0x00 | ||
30 | #define ATH_AIC_MEAS_MAG_THRESH 20 | ||
31 | #define ATH_AIC_BT_JUPITER_CTRL 0x66820 | ||
32 | #define ATH_AIC_BT_AIC_ENABLE 0x02 | ||
33 | |||
34 | enum aic_cal_state { | ||
35 | AIC_CAL_STATE_IDLE = 0, | ||
36 | AIC_CAL_STATE_STARTED, | ||
37 | AIC_CAL_STATE_DONE, | ||
38 | AIC_CAL_STATE_ERROR | ||
39 | }; | ||
40 | |||
41 | struct ath_aic_sram_info { | ||
42 | bool valid:1; | ||
43 | bool vga_quad_sign:1; | ||
44 | bool vga_dir_sign:1; | ||
45 | u8 rot_quad_att_db; | ||
46 | u8 rot_dir_att_db; | ||
47 | u8 com_att_6db; | ||
48 | }; | ||
49 | |||
50 | struct ath_aic_out_info { | ||
51 | int16_t dir_path_gain_lin; | ||
52 | int16_t quad_path_gain_lin; | ||
53 | struct ath_aic_sram_info sram; | ||
54 | }; | ||
55 | |||
56 | u8 ar9003_aic_calibration(struct ath_hw *ah); | ||
57 | u8 ar9003_aic_start_normal(struct ath_hw *ah); | ||
58 | u8 ar9003_aic_cal_reset(struct ath_hw *ah); | ||
59 | u8 ar9003_aic_calibration_single(struct ath_hw *ah); | ||
60 | |||
61 | #endif /* AR9003_AIC_H */ | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 4335ccbe7d7e..79fd3b2dcbde 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c | |||
@@ -195,16 +195,16 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) | |||
195 | INIT_INI_ARRAY(&ah->iniCckfirJapan2484, | 195 | INIT_INI_ARRAY(&ah->iniCckfirJapan2484, |
196 | ar9485_1_1_baseband_core_txfir_coeff_japan_2484); | 196 | ar9485_1_1_baseband_core_txfir_coeff_japan_2484); |
197 | 197 | ||
198 | if (ah->config.no_pll_pwrsave) { | 198 | if (ah->config.pll_pwrsave & AR_PCIE_PLL_PWRSAVE_CONTROL) { |
199 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | 199 | INIT_INI_ARRAY(&ah->iniPcieSerdes, |
200 | ar9485_1_1_pcie_phy_clkreq_disable_L1); | 200 | ar9485_1_1_pll_on_cdr_on_clkreq_disable_L1); |
201 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, | 201 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, |
202 | ar9485_1_1_pcie_phy_clkreq_disable_L1); | 202 | ar9485_1_1_pll_on_cdr_on_clkreq_disable_L1); |
203 | } else { | 203 | } else { |
204 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | 204 | INIT_INI_ARRAY(&ah->iniPcieSerdes, |
205 | ar9485_1_1_pll_on_cdr_on_clkreq_disable_L1); | 205 | ar9485_1_1_pcie_phy_clkreq_disable_L1); |
206 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, | 206 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, |
207 | ar9485_1_1_pll_on_cdr_on_clkreq_disable_L1); | 207 | ar9485_1_1_pcie_phy_clkreq_disable_L1); |
208 | } | 208 | } |
209 | } else if (AR_SREV_9462_21(ah)) { | 209 | } else if (AR_SREV_9462_21(ah)) { |
210 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], | 210 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], |
@@ -231,10 +231,20 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) | |||
231 | ar9462_2p1_modes_fast_clock); | 231 | ar9462_2p1_modes_fast_clock); |
232 | INIT_INI_ARRAY(&ah->iniCckfirJapan2484, | 232 | INIT_INI_ARRAY(&ah->iniCckfirJapan2484, |
233 | ar9462_2p1_baseband_core_txfir_coeff_japan_2484); | 233 | ar9462_2p1_baseband_core_txfir_coeff_japan_2484); |
234 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | 234 | |
235 | ar9462_2p1_pciephy_clkreq_disable_L1); | 235 | /* Awake -> Sleep Setting */ |
236 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, | 236 | if ((ah->config.pll_pwrsave & AR_PCIE_PLL_PWRSAVE_CONTROL) && |
237 | ar9462_2p1_pciephy_clkreq_disable_L1); | 237 | (ah->config.pll_pwrsave & AR_PCIE_PLL_PWRSAVE_ON_D3)) { |
238 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | ||
239 | ar9462_2p1_pciephy_clkreq_disable_L1); | ||
240 | } | ||
241 | |||
242 | /* Sleep -> Awake Setting */ | ||
243 | if ((ah->config.pll_pwrsave & AR_PCIE_PLL_PWRSAVE_CONTROL) && | ||
244 | (ah->config.pll_pwrsave & AR_PCIE_PLL_PWRSAVE_ON_D0)) { | ||
245 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, | ||
246 | ar9462_2p1_pciephy_clkreq_disable_L1); | ||
247 | } | ||
238 | } else if (AR_SREV_9462_20(ah)) { | 248 | } else if (AR_SREV_9462_20(ah)) { |
239 | 249 | ||
240 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], ar9462_2p0_mac_core); | 250 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], ar9462_2p0_mac_core); |
@@ -262,11 +272,18 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) | |||
262 | ar9462_2p0_common_rx_gain); | 272 | ar9462_2p0_common_rx_gain); |
263 | 273 | ||
264 | /* Awake -> Sleep Setting */ | 274 | /* Awake -> Sleep Setting */ |
265 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | 275 | if ((ah->config.pll_pwrsave & AR_PCIE_PLL_PWRSAVE_CONTROL) && |
266 | ar9462_2p0_pciephy_clkreq_disable_L1); | 276 | (ah->config.pll_pwrsave & AR_PCIE_PLL_PWRSAVE_ON_D3)) { |
277 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | ||
278 | ar9462_2p0_pciephy_clkreq_disable_L1); | ||
279 | } | ||
280 | |||
267 | /* Sleep -> Awake Setting */ | 281 | /* Sleep -> Awake Setting */ |
268 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, | 282 | if ((ah->config.pll_pwrsave & AR_PCIE_PLL_PWRSAVE_CONTROL) && |
269 | ar9462_2p0_pciephy_clkreq_disable_L1); | 283 | (ah->config.pll_pwrsave & AR_PCIE_PLL_PWRSAVE_ON_D0)) { |
284 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, | ||
285 | ar9462_2p0_pciephy_clkreq_disable_L1); | ||
286 | } | ||
270 | 287 | ||
271 | /* Fast clock modal settings */ | 288 | /* Fast clock modal settings */ |
272 | INIT_INI_ARRAY(&ah->iniModesFastClock, | 289 | INIT_INI_ARRAY(&ah->iniModesFastClock, |
@@ -456,10 +473,19 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) | |||
456 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 473 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
457 | ar9565_1p1_Modes_lowest_ob_db_tx_gain_table); | 474 | ar9565_1p1_Modes_lowest_ob_db_tx_gain_table); |
458 | 475 | ||
459 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | 476 | /* Awake -> Sleep Setting */ |
460 | ar9565_1p1_pciephy_clkreq_disable_L1); | 477 | if ((ah->config.pll_pwrsave & AR_PCIE_PLL_PWRSAVE_CONTROL) && |
461 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, | 478 | (ah->config.pll_pwrsave & AR_PCIE_PLL_PWRSAVE_ON_D3)) { |
462 | ar9565_1p1_pciephy_clkreq_disable_L1); | 479 | INIT_INI_ARRAY(&ah->iniPcieSerdes, |
480 | ar9565_1p1_pciephy_clkreq_disable_L1); | ||
481 | } | ||
482 | |||
483 | /* Sleep -> Awake Setting */ | ||
484 | if ((ah->config.pll_pwrsave & AR_PCIE_PLL_PWRSAVE_CONTROL) && | ||
485 | (ah->config.pll_pwrsave & AR_PCIE_PLL_PWRSAVE_ON_D0)) { | ||
486 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, | ||
487 | ar9565_1p1_pciephy_clkreq_disable_L1); | ||
488 | } | ||
463 | 489 | ||
464 | INIT_INI_ARRAY(&ah->iniModesFastClock, | 490 | INIT_INI_ARRAY(&ah->iniModesFastClock, |
465 | ar9565_1p1_modes_fast_clock); | 491 | ar9565_1p1_modes_fast_clock); |
@@ -491,10 +517,19 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) | |||
491 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 517 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
492 | ar9565_1p0_Modes_lowest_ob_db_tx_gain_table); | 518 | ar9565_1p0_Modes_lowest_ob_db_tx_gain_table); |
493 | 519 | ||
494 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | 520 | /* Awake -> Sleep Setting */ |
495 | ar9565_1p0_pciephy_clkreq_disable_L1); | 521 | if ((ah->config.pll_pwrsave & AR_PCIE_PLL_PWRSAVE_CONTROL) && |
496 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, | 522 | (ah->config.pll_pwrsave & AR_PCIE_PLL_PWRSAVE_ON_D3)) { |
497 | ar9565_1p0_pciephy_clkreq_disable_L1); | 523 | INIT_INI_ARRAY(&ah->iniPcieSerdes, |
524 | ar9565_1p0_pciephy_clkreq_disable_L1); | ||
525 | } | ||
526 | |||
527 | /* Sleep -> Awake Setting */ | ||
528 | if ((ah->config.pll_pwrsave & AR_PCIE_PLL_PWRSAVE_CONTROL) && | ||
529 | (ah->config.pll_pwrsave & AR_PCIE_PLL_PWRSAVE_ON_D0)) { | ||
530 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, | ||
531 | ar9565_1p0_pciephy_clkreq_disable_L1); | ||
532 | } | ||
498 | 533 | ||
499 | INIT_INI_ARRAY(&ah->iniModesFastClock, | 534 | INIT_INI_ARRAY(&ah->iniModesFastClock, |
500 | ar9565_1p0_modes_fast_clock); | 535 | ar9565_1p0_modes_fast_clock); |
@@ -1130,6 +1165,12 @@ void ar9003_hw_attach_ops(struct ath_hw *ah) | |||
1130 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); | 1165 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); |
1131 | 1166 | ||
1132 | ar9003_hw_init_mode_regs(ah); | 1167 | ar9003_hw_init_mode_regs(ah); |
1168 | |||
1169 | if (AR_SREV_9003_PCOEM(ah)) { | ||
1170 | WARN_ON(!ah->iniPcieSerdes.ia_array); | ||
1171 | WARN_ON(!ah->iniPcieSerdesLowPower.ia_array); | ||
1172 | } | ||
1173 | |||
1133 | priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs; | 1174 | priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs; |
1134 | priv_ops->init_hang_checks = ar9003_hw_init_hang_checks; | 1175 | priv_ops->init_hang_checks = ar9003_hw_init_hang_checks; |
1135 | priv_ops->detect_mac_hang = ar9003_hw_detect_mac_hang; | 1176 | priv_ops->detect_mac_hang = ar9003_hw_detect_mac_hang; |
@@ -1139,4 +1180,5 @@ void ar9003_hw_attach_ops(struct ath_hw *ah) | |||
1139 | ar9003_hw_attach_phy_ops(ah); | 1180 | ar9003_hw_attach_phy_ops(ah); |
1140 | ar9003_hw_attach_calib_ops(ah); | 1181 | ar9003_hw_attach_calib_ops(ah); |
1141 | ar9003_hw_attach_mac_ops(ah); | 1182 | ar9003_hw_attach_mac_ops(ah); |
1183 | ar9003_hw_attach_aic_ops(ah); | ||
1142 | } | 1184 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/drivers/net/wireless/ath/ath9k/ar9003_mci.c index bd169fae32a1..af5ee416a560 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mci.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include "hw-ops.h" | 19 | #include "hw-ops.h" |
20 | #include "ar9003_phy.h" | 20 | #include "ar9003_phy.h" |
21 | #include "ar9003_mci.h" | 21 | #include "ar9003_mci.h" |
22 | #include "ar9003_aic.h" | ||
22 | 23 | ||
23 | static void ar9003_mci_reset_req_wakeup(struct ath_hw *ah) | 24 | static void ar9003_mci_reset_req_wakeup(struct ath_hw *ah) |
24 | { | 25 | { |
@@ -1016,6 +1017,9 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, | |||
1016 | if (en_int) | 1017 | if (en_int) |
1017 | ar9003_mci_enable_interrupt(ah); | 1018 | ar9003_mci_enable_interrupt(ah); |
1018 | 1019 | ||
1020 | if (ath9k_hw_is_aic_enabled(ah)) | ||
1021 | ar9003_aic_start_normal(ah); | ||
1022 | |||
1019 | return 0; | 1023 | return 0; |
1020 | } | 1024 | } |
1021 | 1025 | ||
@@ -1362,6 +1366,22 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type) | |||
1362 | value = (!mci->unhalt_bt_gpm && mci->need_flush_btinfo) ? 1 : 0; | 1366 | value = (!mci->unhalt_bt_gpm && mci->need_flush_btinfo) ? 1 : 0; |
1363 | mci->need_flush_btinfo = false; | 1367 | mci->need_flush_btinfo = false; |
1364 | break; | 1368 | break; |
1369 | case MCI_STATE_AIC_CAL: | ||
1370 | if (ath9k_hw_is_aic_enabled(ah)) | ||
1371 | value = ar9003_aic_calibration(ah); | ||
1372 | break; | ||
1373 | case MCI_STATE_AIC_START: | ||
1374 | if (ath9k_hw_is_aic_enabled(ah)) | ||
1375 | ar9003_aic_start_normal(ah); | ||
1376 | break; | ||
1377 | case MCI_STATE_AIC_CAL_RESET: | ||
1378 | if (ath9k_hw_is_aic_enabled(ah)) | ||
1379 | value = ar9003_aic_cal_reset(ah); | ||
1380 | break; | ||
1381 | case MCI_STATE_AIC_CAL_SINGLE: | ||
1382 | if (ath9k_hw_is_aic_enabled(ah)) | ||
1383 | value = ar9003_aic_calibration_single(ah); | ||
1384 | break; | ||
1365 | default: | 1385 | default: |
1366 | break; | 1386 | break; |
1367 | } | 1387 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index c311b2bfdb00..fc595b92ac56 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h | |||
@@ -640,16 +640,6 @@ | |||
640 | #define AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE 0x0000ff00 | 640 | #define AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE 0x0000ff00 |
641 | #define AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE_S 8 | 641 | #define AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE_S 8 |
642 | 642 | ||
643 | /* AIC Registers */ | ||
644 | #define AR_PHY_AIC_CTRL_0_B0 (AR_SM_BASE + 0x4b0) | ||
645 | #define AR_PHY_AIC_CTRL_1_B0 (AR_SM_BASE + 0x4b4) | ||
646 | #define AR_PHY_AIC_CTRL_2_B0 (AR_SM_BASE + 0x4b8) | ||
647 | #define AR_PHY_AIC_CTRL_3_B0 (AR_SM_BASE + 0x4bc) | ||
648 | #define AR_PHY_AIC_STAT_0_B0 (AR_SM_BASE + 0x4c4)) | ||
649 | #define AR_PHY_AIC_STAT_1_B0 (AR_SM_BASE + 0x4c8)) | ||
650 | #define AR_PHY_AIC_CTRL_4_B0 (AR_SM_BASE + 0x4c0) | ||
651 | #define AR_PHY_AIC_STAT_2_B0 (AR_SM_BASE + 0x4cc) | ||
652 | |||
653 | #define AR_PHY_65NM_CH0_TXRF3 0x16048 | 643 | #define AR_PHY_65NM_CH0_TXRF3 0x16048 |
654 | #define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G 0x0000001e | 644 | #define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G 0x0000001e |
655 | #define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G_S 1 | 645 | #define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G_S 1 |
@@ -989,21 +979,6 @@ | |||
989 | #define AR_PHY_TX_IQCAL_STATUS_B1 (AR_SM1_BASE + 0x48c) | 979 | #define AR_PHY_TX_IQCAL_STATUS_B1 (AR_SM1_BASE + 0x48c) |
990 | #define AR_PHY_TX_IQCAL_CORR_COEFF_B1(_i) (AR_SM1_BASE + 0x450 + ((_i) << 2)) | 980 | #define AR_PHY_TX_IQCAL_CORR_COEFF_B1(_i) (AR_SM1_BASE + 0x450 + ((_i) << 2)) |
991 | 981 | ||
992 | /* SM 1 AIC Registers */ | ||
993 | |||
994 | #define AR_PHY_AIC_CTRL_0_B1 (AR_SM1_BASE + 0x4b0) | ||
995 | #define AR_PHY_AIC_CTRL_1_B1 (AR_SM1_BASE + 0x4b4) | ||
996 | #define AR_PHY_AIC_CTRL_2_B1 (AR_SM1_BASE + 0x4b8) | ||
997 | #define AR_PHY_AIC_STAT_0_B1 (AR_SM1_BASE + (AR_SREV_9462_10(ah) ? \ | ||
998 | 0x4c0 : 0x4c4)) | ||
999 | #define AR_PHY_AIC_STAT_1_B1 (AR_SM1_BASE + (AR_SREV_9462_10(ah) ? \ | ||
1000 | 0x4c4 : 0x4c8)) | ||
1001 | #define AR_PHY_AIC_CTRL_4_B1 (AR_SM1_BASE + 0x4c0) | ||
1002 | #define AR_PHY_AIC_STAT_2_B1 (AR_SM1_BASE + 0x4cc) | ||
1003 | |||
1004 | #define AR_PHY_AIC_SRAM_ADDR_B1 (AR_SM1_BASE + 0x5f0) | ||
1005 | #define AR_PHY_AIC_SRAM_DATA_B1 (AR_SM1_BASE + 0x5f4) | ||
1006 | |||
1007 | #define AR_PHY_RTT_TABLE_SW_INTF_B(i) (0x384 + ((i) ? \ | 982 | #define AR_PHY_RTT_TABLE_SW_INTF_B(i) (0x384 + ((i) ? \ |
1008 | AR_SM1_BASE : AR_SM_BASE)) | 983 | AR_SM1_BASE : AR_SM_BASE)) |
1009 | #define AR_PHY_RTT_TABLE_SW_INTF_1_B(i) (0x388 + ((i) ? \ | 984 | #define AR_PHY_RTT_TABLE_SW_INTF_1_B(i) (0x388 + ((i) ? \ |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_rtt.c b/drivers/net/wireless/ath/ath9k/ar9003_rtt.c index 934418872e8e..e4d11fa7fe8c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_rtt.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_rtt.c | |||
@@ -106,7 +106,7 @@ void ar9003_hw_rtt_load_hist(struct ath_hw *ah) | |||
106 | int chain, i; | 106 | int chain, i; |
107 | 107 | ||
108 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { | 108 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { |
109 | if (!(ah->rxchainmask & (1 << chain))) | 109 | if (!(ah->caps.rx_chainmask & (1 << chain))) |
110 | continue; | 110 | continue; |
111 | for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) { | 111 | for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) { |
112 | ar9003_hw_rtt_load_hist_entry(ah, chain, i, | 112 | ar9003_hw_rtt_load_hist_entry(ah, chain, i, |
@@ -171,7 +171,7 @@ void ar9003_hw_rtt_fill_hist(struct ath_hw *ah) | |||
171 | int chain, i; | 171 | int chain, i; |
172 | 172 | ||
173 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { | 173 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { |
174 | if (!(ah->rxchainmask & (1 << chain))) | 174 | if (!(ah->caps.rx_chainmask & (1 << chain))) |
175 | continue; | 175 | continue; |
176 | for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) { | 176 | for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) { |
177 | ah->caldata->rtt_table[chain][i] = | 177 | ah->caldata->rtt_table[chain][i] = |
@@ -193,7 +193,7 @@ void ar9003_hw_rtt_clear_hist(struct ath_hw *ah) | |||
193 | int chain, i; | 193 | int chain, i; |
194 | 194 | ||
195 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { | 195 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { |
196 | if (!(ah->rxchainmask & (1 << chain))) | 196 | if (!(ah->caps.rx_chainmask & (1 << chain))) |
197 | continue; | 197 | continue; |
198 | for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) | 198 | for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) |
199 | ar9003_hw_rtt_load_hist_entry(ah, chain, i, 0); | 199 | ar9003_hw_rtt_load_hist_entry(ah, chain, i, 0); |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 7e89236c0e13..a7a81b3969ce 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -184,12 +184,12 @@ struct ath_frame_info { | |||
184 | struct ath_buf *bf; | 184 | struct ath_buf *bf; |
185 | u16 framelen; | 185 | u16 framelen; |
186 | s8 txq; | 186 | s8 txq; |
187 | enum ath9k_key_type keytype; | ||
188 | u8 keyix; | 187 | u8 keyix; |
189 | u8 rtscts_rate; | 188 | u8 rtscts_rate; |
190 | u8 retries : 7; | 189 | u8 retries : 7; |
191 | u8 baw_tracked : 1; | 190 | u8 baw_tracked : 1; |
192 | u8 tx_power; | 191 | u8 tx_power; |
192 | enum ath9k_key_type keytype:2; | ||
193 | }; | 193 | }; |
194 | 194 | ||
195 | struct ath_rxbuf { | 195 | struct ath_rxbuf { |
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h index 5fe62ff2223b..cd2f0a2373cb 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/drivers/net/wireless/ath/ath9k/btcoex.h | |||
@@ -44,6 +44,9 @@ | |||
44 | 44 | ||
45 | #define AR9300_NUM_BT_WEIGHTS 4 | 45 | #define AR9300_NUM_BT_WEIGHTS 4 |
46 | #define AR9300_NUM_WLAN_WEIGHTS 4 | 46 | #define AR9300_NUM_WLAN_WEIGHTS 4 |
47 | |||
48 | #define ATH_AIC_MAX_BT_CHANNEL 79 | ||
49 | |||
47 | /* Defines the BT AR_BT_COEX_WGHT used */ | 50 | /* Defines the BT AR_BT_COEX_WGHT used */ |
48 | enum ath_stomp_type { | 51 | enum ath_stomp_type { |
49 | ATH_BTCOEX_STOMP_ALL, | 52 | ATH_BTCOEX_STOMP_ALL, |
@@ -93,9 +96,18 @@ struct ath9k_hw_mci { | |||
93 | u32 last_recovery; | 96 | u32 last_recovery; |
94 | }; | 97 | }; |
95 | 98 | ||
99 | struct ath9k_hw_aic { | ||
100 | bool aic_enabled; | ||
101 | u8 aic_cal_state; | ||
102 | u8 aic_caled_chan; | ||
103 | u32 aic_sram[ATH_AIC_MAX_BT_CHANNEL]; | ||
104 | u32 aic_cal_start_time; | ||
105 | }; | ||
106 | |||
96 | struct ath_btcoex_hw { | 107 | struct ath_btcoex_hw { |
97 | enum ath_btcoex_scheme scheme; | 108 | enum ath_btcoex_scheme scheme; |
98 | struct ath9k_hw_mci mci; | 109 | struct ath9k_hw_mci mci; |
110 | struct ath9k_hw_aic aic; | ||
99 | bool enabled; | 111 | bool enabled; |
100 | u8 wlanactive_gpio; | 112 | u8 wlanactive_gpio; |
101 | u8 btactive_gpio; | 113 | u8 btactive_gpio; |
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index e200a6e3aca5..3e2e24e4843f 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -238,7 +238,6 @@ int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
238 | { | 238 | { |
239 | struct ath9k_nfcal_hist *h = NULL; | 239 | struct ath9k_nfcal_hist *h = NULL; |
240 | unsigned i, j; | 240 | unsigned i, j; |
241 | int32_t val; | ||
242 | u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; | 241 | u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; |
243 | struct ath_common *common = ath9k_hw_common(ah); | 242 | struct ath_common *common = ath9k_hw_common(ah); |
244 | s16 default_nf = ath9k_hw_get_default_nf(ah, chan); | 243 | s16 default_nf = ath9k_hw_get_default_nf(ah, chan); |
@@ -246,6 +245,7 @@ int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
246 | if (ah->caldata) | 245 | if (ah->caldata) |
247 | h = ah->caldata->nfCalHist; | 246 | h = ah->caldata->nfCalHist; |
248 | 247 | ||
248 | ENABLE_REG_RMW_BUFFER(ah); | ||
249 | for (i = 0; i < NUM_NF_READINGS; i++) { | 249 | for (i = 0; i < NUM_NF_READINGS; i++) { |
250 | if (chainmask & (1 << i)) { | 250 | if (chainmask & (1 << i)) { |
251 | s16 nfval; | 251 | s16 nfval; |
@@ -258,10 +258,8 @@ int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
258 | else | 258 | else |
259 | nfval = default_nf; | 259 | nfval = default_nf; |
260 | 260 | ||
261 | val = REG_READ(ah, ah->nf_regs[i]); | 261 | REG_RMW(ah, ah->nf_regs[i], |
262 | val &= 0xFFFFFE00; | 262 | (((u32) nfval << 1) & 0x1ff), 0x1ff); |
263 | val |= (((u32) nfval << 1) & 0x1ff); | ||
264 | REG_WRITE(ah, ah->nf_regs[i], val); | ||
265 | } | 263 | } |
266 | } | 264 | } |
267 | 265 | ||
@@ -274,6 +272,7 @@ int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
274 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, | 272 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, |
275 | AR_PHY_AGC_CONTROL_NO_UPDATE_NF); | 273 | AR_PHY_AGC_CONTROL_NO_UPDATE_NF); |
276 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); | 274 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); |
275 | REG_RMW_BUFFER_FLUSH(ah); | ||
277 | 276 | ||
278 | /* | 277 | /* |
279 | * Wait for load to complete, should be fast, a few 10s of us. | 278 | * Wait for load to complete, should be fast, a few 10s of us. |
@@ -309,19 +308,17 @@ int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
309 | * by the median we just loaded. This will be initial (and max) value | 308 | * by the median we just loaded. This will be initial (and max) value |
310 | * of next noise floor calibration the baseband does. | 309 | * of next noise floor calibration the baseband does. |
311 | */ | 310 | */ |
312 | ENABLE_REGWRITE_BUFFER(ah); | 311 | ENABLE_REG_RMW_BUFFER(ah); |
313 | for (i = 0; i < NUM_NF_READINGS; i++) { | 312 | for (i = 0; i < NUM_NF_READINGS; i++) { |
314 | if (chainmask & (1 << i)) { | 313 | if (chainmask & (1 << i)) { |
315 | if ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(chan)) | 314 | if ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(chan)) |
316 | continue; | 315 | continue; |
317 | 316 | ||
318 | val = REG_READ(ah, ah->nf_regs[i]); | 317 | REG_RMW(ah, ah->nf_regs[i], |
319 | val &= 0xFFFFFE00; | 318 | (((u32) (-50) << 1) & 0x1ff), 0x1ff); |
320 | val |= (((u32) (-50) << 1) & 0x1ff); | ||
321 | REG_WRITE(ah, ah->nf_regs[i], val); | ||
322 | } | 319 | } |
323 | } | 320 | } |
324 | REGWRITE_BUFFER_FLUSH(ah); | 321 | REG_RMW_BUFFER_FLUSH(ah); |
325 | 322 | ||
326 | return 0; | 323 | return 0; |
327 | } | 324 | } |
diff --git a/drivers/net/wireless/ath/ath9k/dfs.c b/drivers/net/wireless/ath/ath9k/dfs.c index 726271c7c330..e98a9eaba7ff 100644 --- a/drivers/net/wireless/ath/ath9k/dfs.c +++ b/drivers/net/wireless/ath/ath9k/dfs.c | |||
@@ -126,8 +126,19 @@ ath9k_postprocess_radar_event(struct ath_softc *sc, | |||
126 | DFS_STAT_INC(sc, pulses_detected); | 126 | DFS_STAT_INC(sc, pulses_detected); |
127 | return true; | 127 | return true; |
128 | } | 128 | } |
129 | #undef PRI_CH_RADAR_FOUND | 129 | |
130 | #undef EXT_CH_RADAR_FOUND | 130 | static void |
131 | ath9k_dfs_process_radar_pulse(struct ath_softc *sc, struct pulse_event *pe) | ||
132 | { | ||
133 | struct dfs_pattern_detector *pd = sc->dfs_detector; | ||
134 | DFS_STAT_INC(sc, pulses_processed); | ||
135 | if (pd == NULL) | ||
136 | return; | ||
137 | if (!pd->add_pulse(pd, pe)) | ||
138 | return; | ||
139 | DFS_STAT_INC(sc, radar_detected); | ||
140 | ieee80211_radar_detected(sc->hw); | ||
141 | } | ||
131 | 142 | ||
132 | /* | 143 | /* |
133 | * DFS: check PHY-error for radar pulse and feed the detector | 144 | * DFS: check PHY-error for radar pulse and feed the detector |
@@ -176,18 +187,21 @@ void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data, | |||
176 | ard.pulse_length_pri = vdata_end[-3]; | 187 | ard.pulse_length_pri = vdata_end[-3]; |
177 | pe.freq = ah->curchan->channel; | 188 | pe.freq = ah->curchan->channel; |
178 | pe.ts = mactime; | 189 | pe.ts = mactime; |
179 | if (ath9k_postprocess_radar_event(sc, &ard, &pe)) { | 190 | if (!ath9k_postprocess_radar_event(sc, &ard, &pe)) |
180 | struct dfs_pattern_detector *pd = sc->dfs_detector; | 191 | return; |
181 | ath_dbg(common, DFS, | 192 | |
182 | "ath9k_dfs_process_phyerr: channel=%d, ts=%llu, " | 193 | ath_dbg(common, DFS, |
183 | "width=%d, rssi=%d, delta_ts=%llu\n", | 194 | "ath9k_dfs_process_phyerr: type=%d, freq=%d, ts=%llu, " |
184 | pe.freq, pe.ts, pe.width, pe.rssi, | 195 | "width=%d, rssi=%d, delta_ts=%llu\n", |
185 | pe.ts - sc->dfs_prev_pulse_ts); | 196 | ard.pulse_bw_info, pe.freq, pe.ts, pe.width, pe.rssi, |
186 | sc->dfs_prev_pulse_ts = pe.ts; | 197 | pe.ts - sc->dfs_prev_pulse_ts); |
187 | DFS_STAT_INC(sc, pulses_processed); | 198 | sc->dfs_prev_pulse_ts = pe.ts; |
188 | if (pd != NULL && pd->add_pulse(pd, &pe)) { | 199 | if (ard.pulse_bw_info & PRI_CH_RADAR_FOUND) |
189 | DFS_STAT_INC(sc, radar_detected); | 200 | ath9k_dfs_process_radar_pulse(sc, &pe); |
190 | ieee80211_radar_detected(sc->hw); | 201 | if (ard.pulse_bw_info & EXT_CH_RADAR_FOUND) { |
191 | } | 202 | pe.freq += IS_CHAN_HT40PLUS(ah->curchan) ? 20 : -20; |
203 | ath9k_dfs_process_radar_pulse(sc, &pe); | ||
192 | } | 204 | } |
193 | } | 205 | } |
206 | #undef PRI_CH_RADAR_FOUND | ||
207 | #undef EXT_CH_RADAR_FOUND | ||
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index 971d770722cf..cc81482c934d 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c | |||
@@ -27,12 +27,7 @@ void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val) | |||
27 | void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask, | 27 | void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask, |
28 | u32 shift, u32 val) | 28 | u32 shift, u32 val) |
29 | { | 29 | { |
30 | u32 regVal; | 30 | REG_RMW(ah, reg, ((val << shift) & mask), mask); |
31 | |||
32 | regVal = REG_READ(ah, reg) & ~mask; | ||
33 | regVal |= (val << shift) & mask; | ||
34 | |||
35 | REG_WRITE(ah, reg, regVal); | ||
36 | 31 | ||
37 | if (ah->config.analog_shiftreg) | 32 | if (ah->config.analog_shiftreg) |
38 | udelay(100); | 33 | udelay(100); |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index e5a78d4fd66e..4773da6dc6f2 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c | |||
@@ -389,6 +389,7 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, | |||
389 | } | 389 | } |
390 | } | 390 | } |
391 | 391 | ||
392 | ENABLE_REG_RMW_BUFFER(ah); | ||
392 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, | 393 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, |
393 | (numXpdGain - 1) & 0x3); | 394 | (numXpdGain - 1) & 0x3); |
394 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, | 395 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, |
@@ -396,6 +397,7 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, | |||
396 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, | 397 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, |
397 | xpdGainValues[1]); | 398 | xpdGainValues[1]); |
398 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0); | 399 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0); |
400 | REG_RMW_BUFFER_FLUSH(ah); | ||
399 | 401 | ||
400 | for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) { | 402 | for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) { |
401 | regChainOffset = i * 0x1000; | 403 | regChainOffset = i * 0x1000; |
@@ -770,15 +772,14 @@ static void ath9k_hw_4k_set_gain(struct ath_hw *ah, | |||
770 | struct ar5416_eeprom_4k *eep, | 772 | struct ar5416_eeprom_4k *eep, |
771 | u8 txRxAttenLocal) | 773 | u8 txRxAttenLocal) |
772 | { | 774 | { |
773 | REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0, | 775 | ENABLE_REG_RMW_BUFFER(ah); |
774 | pModal->antCtrlChain[0]); | 776 | REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, |
777 | pModal->antCtrlChain[0], 0); | ||
775 | 778 | ||
776 | REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), | 779 | REG_RMW(ah, AR_PHY_TIMING_CTRL4(0), |
777 | (REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) & | 780 | SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | |
778 | ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | | 781 | SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF), |
779 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | | 782 | AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF); |
780 | SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | | ||
781 | SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); | ||
782 | 783 | ||
783 | if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | 784 | if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= |
784 | AR5416_EEP_MINOR_VER_3) { | 785 | AR5416_EEP_MINOR_VER_3) { |
@@ -817,6 +818,7 @@ static void ath9k_hw_4k_set_gain(struct ath_hw *ah, | |||
817 | AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); | 818 | AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); |
818 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, | 819 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, |
819 | AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); | 820 | AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); |
821 | REG_RMW_BUFFER_FLUSH(ah); | ||
820 | } | 822 | } |
821 | 823 | ||
822 | /* | 824 | /* |
@@ -928,6 +930,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, | |||
928 | } | 930 | } |
929 | } | 931 | } |
930 | 932 | ||
933 | ENABLE_REG_RMW_BUFFER(ah); | ||
931 | if (AR_SREV_9271(ah)) { | 934 | if (AR_SREV_9271(ah)) { |
932 | ath9k_hw_analog_shift_rmw(ah, | 935 | ath9k_hw_analog_shift_rmw(ah, |
933 | AR9285_AN_RF2G3, | 936 | AR9285_AN_RF2G3, |
@@ -1032,18 +1035,19 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, | |||
1032 | AR9285_AN_RF2G4_DB2_4_S, | 1035 | AR9285_AN_RF2G4_DB2_4_S, |
1033 | db2[4]); | 1036 | db2[4]); |
1034 | } | 1037 | } |
1038 | REG_RMW_BUFFER_FLUSH(ah); | ||
1035 | 1039 | ||
1036 | 1040 | ENABLE_REG_RMW_BUFFER(ah); | |
1037 | REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, | 1041 | REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, |
1038 | pModal->switchSettling); | 1042 | pModal->switchSettling); |
1039 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, | 1043 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, |
1040 | pModal->adcDesiredSize); | 1044 | pModal->adcDesiredSize); |
1041 | 1045 | ||
1042 | REG_WRITE(ah, AR_PHY_RF_CTL4, | 1046 | REG_RMW(ah, AR_PHY_RF_CTL4, |
1043 | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) | | 1047 | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) | |
1044 | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) | | 1048 | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) | |
1045 | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) | | 1049 | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) | |
1046 | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON)); | 1050 | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON), 0); |
1047 | 1051 | ||
1048 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, | 1052 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, |
1049 | pModal->txEndToRxOn); | 1053 | pModal->txEndToRxOn); |
@@ -1072,6 +1076,8 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, | |||
1072 | pModal->swSettleHt40); | 1076 | pModal->swSettleHt40); |
1073 | } | 1077 | } |
1074 | 1078 | ||
1079 | REG_RMW_BUFFER_FLUSH(ah); | ||
1080 | |||
1075 | bb_desired_scale = (pModal->bb_scale_smrt_antenna & | 1081 | bb_desired_scale = (pModal->bb_scale_smrt_antenna & |
1076 | EEP_4K_BB_DESIRED_SCALE_MASK); | 1082 | EEP_4K_BB_DESIRED_SCALE_MASK); |
1077 | if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) { | 1083 | if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) { |
@@ -1080,6 +1086,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, | |||
1080 | mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25); | 1086 | mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25); |
1081 | pwrctrl = mask * bb_desired_scale; | 1087 | pwrctrl = mask * bb_desired_scale; |
1082 | clr = mask * 0x1f; | 1088 | clr = mask * 0x1f; |
1089 | ENABLE_REG_RMW_BUFFER(ah); | ||
1083 | REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr); | 1090 | REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr); |
1084 | REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr); | 1091 | REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr); |
1085 | REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr); | 1092 | REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr); |
@@ -1094,6 +1101,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, | |||
1094 | clr = mask * 0x1f; | 1101 | clr = mask * 0x1f; |
1095 | REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr); | 1102 | REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr); |
1096 | REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr); | 1103 | REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr); |
1104 | REG_RMW_BUFFER_FLUSH(ah); | ||
1097 | } | 1105 | } |
1098 | } | 1106 | } |
1099 | 1107 | ||
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 098059039351..056f516bf017 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c | |||
@@ -466,6 +466,7 @@ static void ath9k_hw_def_set_gain(struct ath_hw *ah, | |||
466 | struct ar5416_eeprom_def *eep, | 466 | struct ar5416_eeprom_def *eep, |
467 | u8 txRxAttenLocal, int regChainOffset, int i) | 467 | u8 txRxAttenLocal, int regChainOffset, int i) |
468 | { | 468 | { |
469 | ENABLE_REG_RMW_BUFFER(ah); | ||
469 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { | 470 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { |
470 | txRxAttenLocal = pModal->txRxAttenCh[i]; | 471 | txRxAttenLocal = pModal->txRxAttenCh[i]; |
471 | 472 | ||
@@ -483,16 +484,12 @@ static void ath9k_hw_def_set_gain(struct ath_hw *ah, | |||
483 | AR_PHY_GAIN_2GHZ_XATTEN2_DB, | 484 | AR_PHY_GAIN_2GHZ_XATTEN2_DB, |
484 | pModal->xatten2Db[i]); | 485 | pModal->xatten2Db[i]); |
485 | } else { | 486 | } else { |
486 | REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | 487 | REG_RMW(ah, AR_PHY_GAIN_2GHZ + regChainOffset, |
487 | (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & | 488 | SM(pModal-> bswMargin[i], AR_PHY_GAIN_2GHZ_BSW_MARGIN), |
488 | ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) | 489 | AR_PHY_GAIN_2GHZ_BSW_MARGIN); |
489 | | SM(pModal-> bswMargin[i], | 490 | REG_RMW(ah, AR_PHY_GAIN_2GHZ + regChainOffset, |
490 | AR_PHY_GAIN_2GHZ_BSW_MARGIN)); | 491 | SM(pModal->bswAtten[i], AR_PHY_GAIN_2GHZ_BSW_ATTEN), |
491 | REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | 492 | AR_PHY_GAIN_2GHZ_BSW_ATTEN); |
492 | (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & | ||
493 | ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) | ||
494 | | SM(pModal->bswAtten[i], | ||
495 | AR_PHY_GAIN_2GHZ_BSW_ATTEN)); | ||
496 | } | 493 | } |
497 | } | 494 | } |
498 | 495 | ||
@@ -504,17 +501,14 @@ static void ath9k_hw_def_set_gain(struct ath_hw *ah, | |||
504 | AR_PHY_RXGAIN + regChainOffset, | 501 | AR_PHY_RXGAIN + regChainOffset, |
505 | AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]); | 502 | AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]); |
506 | } else { | 503 | } else { |
507 | REG_WRITE(ah, | 504 | REG_RMW(ah, AR_PHY_RXGAIN + regChainOffset, |
508 | AR_PHY_RXGAIN + regChainOffset, | 505 | SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN), |
509 | (REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) & | 506 | AR_PHY_RXGAIN_TXRX_ATTEN); |
510 | ~AR_PHY_RXGAIN_TXRX_ATTEN) | 507 | REG_RMW(ah, AR_PHY_GAIN_2GHZ + regChainOffset, |
511 | | SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN)); | 508 | SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN), |
512 | REG_WRITE(ah, | 509 | AR_PHY_GAIN_2GHZ_RXTX_MARGIN); |
513 | AR_PHY_GAIN_2GHZ + regChainOffset, | ||
514 | (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & | ||
515 | ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) | | ||
516 | SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN)); | ||
517 | } | 510 | } |
511 | REG_RMW_BUFFER_FLUSH(ah); | ||
518 | } | 512 | } |
519 | 513 | ||
520 | static void ath9k_hw_def_set_board_values(struct ath_hw *ah, | 514 | static void ath9k_hw_def_set_board_values(struct ath_hw *ah, |
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 300d3671d0ef..e82a0d4ce23f 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -444,6 +444,10 @@ static inline void ath9k_htc_stop_btcoex(struct ath9k_htc_priv *priv) | |||
444 | #define OP_BT_SCAN BIT(4) | 444 | #define OP_BT_SCAN BIT(4) |
445 | #define OP_TSF_RESET BIT(6) | 445 | #define OP_TSF_RESET BIT(6) |
446 | 446 | ||
447 | enum htc_op_flags { | ||
448 | HTC_FWFLAG_NO_RMW, | ||
449 | }; | ||
450 | |||
447 | struct ath9k_htc_priv { | 451 | struct ath9k_htc_priv { |
448 | struct device *dev; | 452 | struct device *dev; |
449 | struct ieee80211_hw *hw; | 453 | struct ieee80211_hw *hw; |
@@ -482,6 +486,7 @@ struct ath9k_htc_priv { | |||
482 | bool reconfig_beacon; | 486 | bool reconfig_beacon; |
483 | unsigned int rxfilter; | 487 | unsigned int rxfilter; |
484 | unsigned long op_flags; | 488 | unsigned long op_flags; |
489 | unsigned long fw_flags; | ||
485 | 490 | ||
486 | struct ath9k_hw_cal_data caldata; | 491 | struct ath9k_hw_cal_data caldata; |
487 | struct ath_spec_scan_priv spec_priv; | 492 | struct ath_spec_scan_priv spec_priv; |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index fd229409f676..d7beefe60683 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -376,17 +376,139 @@ static void ath9k_regwrite_flush(void *hw_priv) | |||
376 | mutex_unlock(&priv->wmi->multi_write_mutex); | 376 | mutex_unlock(&priv->wmi->multi_write_mutex); |
377 | } | 377 | } |
378 | 378 | ||
379 | static u32 ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr) | 379 | static void ath9k_reg_rmw_buffer(void *hw_priv, |
380 | u32 reg_offset, u32 set, u32 clr) | ||
381 | { | ||
382 | struct ath_hw *ah = (struct ath_hw *) hw_priv; | ||
383 | struct ath_common *common = ath9k_hw_common(ah); | ||
384 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; | ||
385 | u32 rsp_status; | ||
386 | int r; | ||
387 | |||
388 | mutex_lock(&priv->wmi->multi_rmw_mutex); | ||
389 | |||
390 | /* Store the register/value */ | ||
391 | priv->wmi->multi_rmw[priv->wmi->multi_rmw_idx].reg = | ||
392 | cpu_to_be32(reg_offset); | ||
393 | priv->wmi->multi_rmw[priv->wmi->multi_rmw_idx].set = | ||
394 | cpu_to_be32(set); | ||
395 | priv->wmi->multi_rmw[priv->wmi->multi_rmw_idx].clr = | ||
396 | cpu_to_be32(clr); | ||
397 | |||
398 | priv->wmi->multi_rmw_idx++; | ||
399 | |||
400 | /* If the buffer is full, send it out. */ | ||
401 | if (priv->wmi->multi_rmw_idx == MAX_RMW_CMD_NUMBER) { | ||
402 | r = ath9k_wmi_cmd(priv->wmi, WMI_REG_RMW_CMDID, | ||
403 | (u8 *) &priv->wmi->multi_rmw, | ||
404 | sizeof(struct register_write) * priv->wmi->multi_rmw_idx, | ||
405 | (u8 *) &rsp_status, sizeof(rsp_status), | ||
406 | 100); | ||
407 | if (unlikely(r)) { | ||
408 | ath_dbg(common, WMI, | ||
409 | "REGISTER RMW FAILED, multi len: %d\n", | ||
410 | priv->wmi->multi_rmw_idx); | ||
411 | } | ||
412 | priv->wmi->multi_rmw_idx = 0; | ||
413 | } | ||
414 | |||
415 | mutex_unlock(&priv->wmi->multi_rmw_mutex); | ||
416 | } | ||
417 | |||
418 | static void ath9k_reg_rmw_flush(void *hw_priv) | ||
380 | { | 419 | { |
381 | u32 val; | 420 | struct ath_hw *ah = (struct ath_hw *) hw_priv; |
421 | struct ath_common *common = ath9k_hw_common(ah); | ||
422 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; | ||
423 | u32 rsp_status; | ||
424 | int r; | ||
425 | |||
426 | if (test_bit(HTC_FWFLAG_NO_RMW, &priv->fw_flags)) | ||
427 | return; | ||
428 | |||
429 | atomic_dec(&priv->wmi->m_rmw_cnt); | ||
382 | 430 | ||
383 | val = ath9k_regread(hw_priv, reg_offset); | 431 | mutex_lock(&priv->wmi->multi_rmw_mutex); |
384 | val &= ~clr; | 432 | |
385 | val |= set; | 433 | if (priv->wmi->multi_rmw_idx) { |
386 | ath9k_regwrite(hw_priv, val, reg_offset); | 434 | r = ath9k_wmi_cmd(priv->wmi, WMI_REG_RMW_CMDID, |
435 | (u8 *) &priv->wmi->multi_rmw, | ||
436 | sizeof(struct register_rmw) * priv->wmi->multi_rmw_idx, | ||
437 | (u8 *) &rsp_status, sizeof(rsp_status), | ||
438 | 100); | ||
439 | if (unlikely(r)) { | ||
440 | ath_dbg(common, WMI, | ||
441 | "REGISTER RMW FAILED, multi len: %d\n", | ||
442 | priv->wmi->multi_rmw_idx); | ||
443 | } | ||
444 | priv->wmi->multi_rmw_idx = 0; | ||
445 | } | ||
446 | |||
447 | mutex_unlock(&priv->wmi->multi_rmw_mutex); | ||
448 | } | ||
449 | |||
450 | static void ath9k_enable_rmw_buffer(void *hw_priv) | ||
451 | { | ||
452 | struct ath_hw *ah = (struct ath_hw *) hw_priv; | ||
453 | struct ath_common *common = ath9k_hw_common(ah); | ||
454 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; | ||
455 | |||
456 | if (test_bit(HTC_FWFLAG_NO_RMW, &priv->fw_flags)) | ||
457 | return; | ||
458 | |||
459 | atomic_inc(&priv->wmi->m_rmw_cnt); | ||
460 | } | ||
461 | |||
462 | static u32 ath9k_reg_rmw_single(void *hw_priv, | ||
463 | u32 reg_offset, u32 set, u32 clr) | ||
464 | { | ||
465 | struct ath_hw *ah = (struct ath_hw *) hw_priv; | ||
466 | struct ath_common *common = ath9k_hw_common(ah); | ||
467 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; | ||
468 | struct register_rmw buf, buf_ret; | ||
469 | int ret; | ||
470 | u32 val = 0; | ||
471 | |||
472 | buf.reg = cpu_to_be32(reg_offset); | ||
473 | buf.set = cpu_to_be32(set); | ||
474 | buf.clr = cpu_to_be32(clr); | ||
475 | |||
476 | ret = ath9k_wmi_cmd(priv->wmi, WMI_REG_RMW_CMDID, | ||
477 | (u8 *) &buf, sizeof(buf), | ||
478 | (u8 *) &buf_ret, sizeof(buf_ret), | ||
479 | 100); | ||
480 | if (unlikely(ret)) { | ||
481 | ath_dbg(common, WMI, "REGISTER RMW FAILED:(0x%04x, %d)\n", | ||
482 | reg_offset, ret); | ||
483 | } | ||
387 | return val; | 484 | return val; |
388 | } | 485 | } |
389 | 486 | ||
487 | static u32 ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr) | ||
488 | { | ||
489 | struct ath_hw *ah = (struct ath_hw *) hw_priv; | ||
490 | struct ath_common *common = ath9k_hw_common(ah); | ||
491 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; | ||
492 | |||
493 | if (test_bit(HTC_FWFLAG_NO_RMW, &priv->fw_flags)) { | ||
494 | u32 val; | ||
495 | |||
496 | val = REG_READ(ah, reg_offset); | ||
497 | val &= ~clr; | ||
498 | val |= set; | ||
499 | REG_WRITE(ah, reg_offset, val); | ||
500 | |||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | if (atomic_read(&priv->wmi->m_rmw_cnt)) | ||
505 | ath9k_reg_rmw_buffer(hw_priv, reg_offset, set, clr); | ||
506 | else | ||
507 | ath9k_reg_rmw_single(hw_priv, reg_offset, set, clr); | ||
508 | |||
509 | return 0; | ||
510 | } | ||
511 | |||
390 | static void ath_usb_read_cachesize(struct ath_common *common, int *csz) | 512 | static void ath_usb_read_cachesize(struct ath_common *common, int *csz) |
391 | { | 513 | { |
392 | *csz = L1_CACHE_BYTES >> 2; | 514 | *csz = L1_CACHE_BYTES >> 2; |
@@ -501,6 +623,8 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, | |||
501 | ah->reg_ops.write = ath9k_regwrite; | 623 | ah->reg_ops.write = ath9k_regwrite; |
502 | ah->reg_ops.enable_write_buffer = ath9k_enable_regwrite_buffer; | 624 | ah->reg_ops.enable_write_buffer = ath9k_enable_regwrite_buffer; |
503 | ah->reg_ops.write_flush = ath9k_regwrite_flush; | 625 | ah->reg_ops.write_flush = ath9k_regwrite_flush; |
626 | ah->reg_ops.enable_rmw_buffer = ath9k_enable_rmw_buffer; | ||
627 | ah->reg_ops.rmw_flush = ath9k_reg_rmw_flush; | ||
504 | ah->reg_ops.rmw = ath9k_reg_rmw; | 628 | ah->reg_ops.rmw = ath9k_reg_rmw; |
505 | priv->ah = ah; | 629 | priv->ah = ah; |
506 | 630 | ||
@@ -686,6 +810,12 @@ static int ath9k_init_firmware_version(struct ath9k_htc_priv *priv) | |||
686 | return -EINVAL; | 810 | return -EINVAL; |
687 | } | 811 | } |
688 | 812 | ||
813 | if (priv->fw_version_major == 1 && priv->fw_version_minor < 4) | ||
814 | set_bit(HTC_FWFLAG_NO_RMW, &priv->fw_flags); | ||
815 | |||
816 | dev_info(priv->dev, "FW RMW support: %s\n", | ||
817 | test_bit(HTC_FWFLAG_NO_RMW, &priv->fw_flags) ? "Off" : "On"); | ||
818 | |||
689 | return 0; | 819 | return 0; |
690 | } | 820 | } |
691 | 821 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 88769b64b20b..232339b05540 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h | |||
@@ -108,6 +108,14 @@ static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable) | |||
108 | ath9k_hw_ops(ah)->set_bt_ant_diversity(ah, enable); | 108 | ath9k_hw_ops(ah)->set_bt_ant_diversity(ah, enable); |
109 | } | 109 | } |
110 | 110 | ||
111 | static inline bool ath9k_hw_is_aic_enabled(struct ath_hw *ah) | ||
112 | { | ||
113 | if (ath9k_hw_private_ops(ah)->is_aic_enabled) | ||
114 | return ath9k_hw_private_ops(ah)->is_aic_enabled(ah); | ||
115 | |||
116 | return false; | ||
117 | } | ||
118 | |||
111 | #endif | 119 | #endif |
112 | 120 | ||
113 | /* Private hardware call ops */ | 121 | /* Private hardware call ops */ |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 60aa8d71e753..1d9ad5bfe0c8 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -121,6 +121,36 @@ void ath9k_hw_write_array(struct ath_hw *ah, const struct ar5416IniArray *array, | |||
121 | REGWRITE_BUFFER_FLUSH(ah); | 121 | REGWRITE_BUFFER_FLUSH(ah); |
122 | } | 122 | } |
123 | 123 | ||
124 | void ath9k_hw_read_array(struct ath_hw *ah, u32 array[][2], int size) | ||
125 | { | ||
126 | u32 *tmp_reg_list, *tmp_data; | ||
127 | int i; | ||
128 | |||
129 | tmp_reg_list = kmalloc(size * sizeof(u32), GFP_KERNEL); | ||
130 | if (!tmp_reg_list) { | ||
131 | dev_err(ah->dev, "%s: tmp_reg_list: alloc filed\n", __func__); | ||
132 | return; | ||
133 | } | ||
134 | |||
135 | tmp_data = kmalloc(size * sizeof(u32), GFP_KERNEL); | ||
136 | if (!tmp_data) { | ||
137 | dev_err(ah->dev, "%s tmp_data: alloc filed\n", __func__); | ||
138 | goto error_tmp_data; | ||
139 | } | ||
140 | |||
141 | for (i = 0; i < size; i++) | ||
142 | tmp_reg_list[i] = array[i][0]; | ||
143 | |||
144 | REG_READ_MULTI(ah, tmp_reg_list, tmp_data, size); | ||
145 | |||
146 | for (i = 0; i < size; i++) | ||
147 | array[i][1] = tmp_data[i]; | ||
148 | |||
149 | kfree(tmp_data); | ||
150 | error_tmp_data: | ||
151 | kfree(tmp_reg_list); | ||
152 | } | ||
153 | |||
124 | u32 ath9k_hw_reverse_bits(u32 val, u32 n) | 154 | u32 ath9k_hw_reverse_bits(u32 val, u32 n) |
125 | { | 155 | { |
126 | u32 retval; | 156 | u32 retval; |
@@ -366,6 +396,9 @@ static void ath9k_hw_init_config(struct ath_hw *ah) | |||
366 | ah->config.rimt_first = 700; | 396 | ah->config.rimt_first = 700; |
367 | } | 397 | } |
368 | 398 | ||
399 | if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) | ||
400 | ah->config.pll_pwrsave = 7; | ||
401 | |||
369 | /* | 402 | /* |
370 | * We need this for PCI devices only (Cardbus, PCI, miniPCI) | 403 | * We need this for PCI devices only (Cardbus, PCI, miniPCI) |
371 | * _and_ if on non-uniprocessor systems (Multiprocessor/HT). | 404 | * _and_ if on non-uniprocessor systems (Multiprocessor/HT). |
@@ -1197,6 +1230,7 @@ static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode) | |||
1197 | u32 mask = AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC; | 1230 | u32 mask = AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC; |
1198 | u32 set = AR_STA_ID1_KSRCH_MODE; | 1231 | u32 set = AR_STA_ID1_KSRCH_MODE; |
1199 | 1232 | ||
1233 | ENABLE_REG_RMW_BUFFER(ah); | ||
1200 | switch (opmode) { | 1234 | switch (opmode) { |
1201 | case NL80211_IFTYPE_ADHOC: | 1235 | case NL80211_IFTYPE_ADHOC: |
1202 | if (!AR_SREV_9340_13(ah)) { | 1236 | if (!AR_SREV_9340_13(ah)) { |
@@ -1218,6 +1252,7 @@ static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode) | |||
1218 | break; | 1252 | break; |
1219 | } | 1253 | } |
1220 | REG_RMW(ah, AR_STA_ID1, set, mask); | 1254 | REG_RMW(ah, AR_STA_ID1, set, mask); |
1255 | REG_RMW_BUFFER_FLUSH(ah); | ||
1221 | } | 1256 | } |
1222 | 1257 | ||
1223 | void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, | 1258 | void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, |
@@ -1930,6 +1965,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1930 | if (!ath9k_hw_mci_is_enabled(ah)) | 1965 | if (!ath9k_hw_mci_is_enabled(ah)) |
1931 | REG_WRITE(ah, AR_OBS, 8); | 1966 | REG_WRITE(ah, AR_OBS, 8); |
1932 | 1967 | ||
1968 | ENABLE_REG_RMW_BUFFER(ah); | ||
1933 | if (ah->config.rx_intr_mitigation) { | 1969 | if (ah->config.rx_intr_mitigation) { |
1934 | REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, ah->config.rimt_last); | 1970 | REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, ah->config.rimt_last); |
1935 | REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, ah->config.rimt_first); | 1971 | REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, ah->config.rimt_first); |
@@ -1939,6 +1975,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1939 | REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_LAST, 300); | 1975 | REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_LAST, 300); |
1940 | REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_FIRST, 750); | 1976 | REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_FIRST, 750); |
1941 | } | 1977 | } |
1978 | REG_RMW_BUFFER_FLUSH(ah); | ||
1942 | 1979 | ||
1943 | ath9k_hw_init_bb(ah, chan); | 1980 | ath9k_hw_init_bb(ah, chan); |
1944 | 1981 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 29a25d92add7..92fab1a54697 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -100,6 +100,18 @@ | |||
100 | (_ah)->reg_ops.write_flush((_ah)); \ | 100 | (_ah)->reg_ops.write_flush((_ah)); \ |
101 | } while (0) | 101 | } while (0) |
102 | 102 | ||
103 | #define ENABLE_REG_RMW_BUFFER(_ah) \ | ||
104 | do { \ | ||
105 | if ((_ah)->reg_ops.enable_rmw_buffer) \ | ||
106 | (_ah)->reg_ops.enable_rmw_buffer((_ah)); \ | ||
107 | } while (0) | ||
108 | |||
109 | #define REG_RMW_BUFFER_FLUSH(_ah) \ | ||
110 | do { \ | ||
111 | if ((_ah)->reg_ops.rmw_flush) \ | ||
112 | (_ah)->reg_ops.rmw_flush((_ah)); \ | ||
113 | } while (0) | ||
114 | |||
103 | #define PR_EEP(_s, _val) \ | 115 | #define PR_EEP(_s, _val) \ |
104 | do { \ | 116 | do { \ |
105 | len += scnprintf(buf + len, size - len, "%20s : %10d\n",\ | 117 | len += scnprintf(buf + len, size - len, "%20s : %10d\n",\ |
@@ -126,6 +138,8 @@ | |||
126 | 138 | ||
127 | #define REG_WRITE_ARRAY(iniarray, column, regWr) \ | 139 | #define REG_WRITE_ARRAY(iniarray, column, regWr) \ |
128 | ath9k_hw_write_array(ah, iniarray, column, &(regWr)) | 140 | ath9k_hw_write_array(ah, iniarray, column, &(regWr)) |
141 | #define REG_READ_ARRAY(ah, array, size) \ | ||
142 | ath9k_hw_read_array(ah, array, size) | ||
129 | 143 | ||
130 | #define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0 | 144 | #define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0 |
131 | #define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1 | 145 | #define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1 |
@@ -309,6 +323,12 @@ enum ath9k_hw_hang_checks { | |||
309 | HW_MAC_HANG = BIT(5), | 323 | HW_MAC_HANG = BIT(5), |
310 | }; | 324 | }; |
311 | 325 | ||
326 | #define AR_PCIE_PLL_PWRSAVE_CONTROL BIT(0) | ||
327 | #define AR_PCIE_PLL_PWRSAVE_ON_D3 BIT(1) | ||
328 | #define AR_PCIE_PLL_PWRSAVE_ON_D0 BIT(2) | ||
329 | #define AR_PCIE_CDR_PWRSAVE_ON_D3 BIT(3) | ||
330 | #define AR_PCIE_CDR_PWRSAVE_ON_D0 BIT(4) | ||
331 | |||
312 | struct ath9k_ops_config { | 332 | struct ath9k_ops_config { |
313 | int dma_beacon_response_time; | 333 | int dma_beacon_response_time; |
314 | int sw_beacon_response_time; | 334 | int sw_beacon_response_time; |
@@ -335,7 +355,7 @@ struct ath9k_ops_config { | |||
335 | u32 ant_ctrl_comm2g_switch_enable; | 355 | u32 ant_ctrl_comm2g_switch_enable; |
336 | bool xatten_margin_cfg; | 356 | bool xatten_margin_cfg; |
337 | bool alt_mingainidx; | 357 | bool alt_mingainidx; |
338 | bool no_pll_pwrsave; | 358 | u8 pll_pwrsave; |
339 | bool tx_gain_buffalo; | 359 | bool tx_gain_buffalo; |
340 | bool led_active_high; | 360 | bool led_active_high; |
341 | }; | 361 | }; |
@@ -647,6 +667,10 @@ struct ath_hw_private_ops { | |||
647 | 667 | ||
648 | /* ANI */ | 668 | /* ANI */ |
649 | void (*ani_cache_ini_regs)(struct ath_hw *ah); | 669 | void (*ani_cache_ini_regs)(struct ath_hw *ah); |
670 | |||
671 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | ||
672 | bool (*is_aic_enabled)(struct ath_hw *ah); | ||
673 | #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ | ||
650 | }; | 674 | }; |
651 | 675 | ||
652 | /** | 676 | /** |
@@ -1008,6 +1032,7 @@ void ath9k_hw_synth_delay(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1008 | bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); | 1032 | bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); |
1009 | void ath9k_hw_write_array(struct ath_hw *ah, const struct ar5416IniArray *array, | 1033 | void ath9k_hw_write_array(struct ath_hw *ah, const struct ar5416IniArray *array, |
1010 | int column, unsigned int *writecnt); | 1034 | int column, unsigned int *writecnt); |
1035 | void ath9k_hw_read_array(struct ath_hw *ah, u32 array[][2], int size); | ||
1011 | u32 ath9k_hw_reverse_bits(u32 val, u32 n); | 1036 | u32 ath9k_hw_reverse_bits(u32 val, u32 n); |
1012 | u16 ath9k_hw_computetxtime(struct ath_hw *ah, | 1037 | u16 ath9k_hw_computetxtime(struct ath_hw *ah, |
1013 | u8 phy, int kbps, | 1038 | u8 phy, int kbps, |
@@ -1117,6 +1142,7 @@ void ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us); | |||
1117 | void ath9k_hw_setslottime(struct ath_hw *ah, u32 us); | 1142 | void ath9k_hw_setslottime(struct ath_hw *ah, u32 us); |
1118 | 1143 | ||
1119 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | 1144 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT |
1145 | void ar9003_hw_attach_aic_ops(struct ath_hw *ah); | ||
1120 | static inline bool ath9k_hw_btcoex_is_enabled(struct ath_hw *ah) | 1146 | static inline bool ath9k_hw_btcoex_is_enabled(struct ath_hw *ah) |
1121 | { | 1147 | { |
1122 | return ah->btcoex_hw.enabled; | 1148 | return ah->btcoex_hw.enabled; |
@@ -1134,6 +1160,9 @@ ath9k_hw_get_btcoex_scheme(struct ath_hw *ah) | |||
1134 | return ah->btcoex_hw.scheme; | 1160 | return ah->btcoex_hw.scheme; |
1135 | } | 1161 | } |
1136 | #else | 1162 | #else |
1163 | static inline void ar9003_hw_attach_aic_ops(struct ath_hw *ah) | ||
1164 | { | ||
1165 | } | ||
1137 | static inline bool ath9k_hw_btcoex_is_enabled(struct ath_hw *ah) | 1166 | static inline bool ath9k_hw_btcoex_is_enabled(struct ath_hw *ah) |
1138 | { | 1167 | { |
1139 | return false; | 1168 | return false; |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 6c6e88495394..f8d11efa7b0f 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -141,6 +141,16 @@ static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset) | |||
141 | return val; | 141 | return val; |
142 | } | 142 | } |
143 | 143 | ||
144 | static void ath9k_multi_ioread32(void *hw_priv, u32 *addr, | ||
145 | u32 *val, u16 count) | ||
146 | { | ||
147 | int i; | ||
148 | |||
149 | for (i = 0; i < count; i++) | ||
150 | val[i] = ath9k_ioread32(hw_priv, addr[i]); | ||
151 | } | ||
152 | |||
153 | |||
144 | static unsigned int __ath9k_reg_rmw(struct ath_softc *sc, u32 reg_offset, | 154 | static unsigned int __ath9k_reg_rmw(struct ath_softc *sc, u32 reg_offset, |
145 | u32 set, u32 clr) | 155 | u32 set, u32 clr) |
146 | { | 156 | { |
@@ -437,8 +447,15 @@ static void ath9k_init_pcoem_platform(struct ath_softc *sc) | |||
437 | ath_info(common, "Enable WAR for ASPM D3/L1\n"); | 447 | ath_info(common, "Enable WAR for ASPM D3/L1\n"); |
438 | } | 448 | } |
439 | 449 | ||
450 | /* | ||
451 | * The default value of pll_pwrsave is 1. | ||
452 | * For certain AR9485 cards, it is set to 0. | ||
453 | * For AR9462, AR9565 it's set to 7. | ||
454 | */ | ||
455 | ah->config.pll_pwrsave = 1; | ||
456 | |||
440 | if (sc->driver_data & ATH9K_PCI_NO_PLL_PWRSAVE) { | 457 | if (sc->driver_data & ATH9K_PCI_NO_PLL_PWRSAVE) { |
441 | ah->config.no_pll_pwrsave = true; | 458 | ah->config.pll_pwrsave = 0; |
442 | ath_info(common, "Disable PLL PowerSave\n"); | 459 | ath_info(common, "Disable PLL PowerSave\n"); |
443 | } | 460 | } |
444 | 461 | ||
@@ -530,6 +547,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, | |||
530 | ah->hw = sc->hw; | 547 | ah->hw = sc->hw; |
531 | ah->hw_version.devid = devid; | 548 | ah->hw_version.devid = devid; |
532 | ah->reg_ops.read = ath9k_ioread32; | 549 | ah->reg_ops.read = ath9k_ioread32; |
550 | ah->reg_ops.multi_read = ath9k_multi_ioread32; | ||
533 | ah->reg_ops.write = ath9k_iowrite32; | 551 | ah->reg_ops.write = ath9k_iowrite32; |
534 | ah->reg_ops.rmw = ath9k_reg_rmw; | 552 | ah->reg_ops.rmw = ath9k_reg_rmw; |
535 | pCap = &ah->caps; | 553 | pCap = &ah->caps; |
@@ -763,7 +781,8 @@ static const struct ieee80211_iface_combination if_comb[] = { | |||
763 | .num_different_channels = 1, | 781 | .num_different_channels = 1, |
764 | .beacon_int_infra_match = true, | 782 | .beacon_int_infra_match = true, |
765 | .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | | 783 | .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | |
766 | BIT(NL80211_CHAN_WIDTH_20), | 784 | BIT(NL80211_CHAN_WIDTH_20) | |
785 | BIT(NL80211_CHAN_WIDTH_40), | ||
767 | } | 786 | } |
768 | #endif | 787 | #endif |
769 | }; | 788 | }; |
diff --git a/drivers/net/wireless/ath/ath9k/reg_aic.h b/drivers/net/wireless/ath/ath9k/reg_aic.h new file mode 100644 index 000000000000..955147ab48a2 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/reg_aic.h | |||
@@ -0,0 +1,168 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015 Qualcomm Atheros Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef REG_AIC_H | ||
18 | #define REG_AIC_H | ||
19 | |||
20 | #define AR_SM_BASE 0xa200 | ||
21 | #define AR_SM1_BASE 0xb200 | ||
22 | #define AR_AGC_BASE 0x9e00 | ||
23 | |||
24 | #define AR_PHY_AIC_CTRL_0_B0 (AR_SM_BASE + 0x4b0) | ||
25 | #define AR_PHY_AIC_CTRL_1_B0 (AR_SM_BASE + 0x4b4) | ||
26 | #define AR_PHY_AIC_CTRL_2_B0 (AR_SM_BASE + 0x4b8) | ||
27 | #define AR_PHY_AIC_CTRL_3_B0 (AR_SM_BASE + 0x4bc) | ||
28 | #define AR_PHY_AIC_CTRL_4_B0 (AR_SM_BASE + 0x4c0) | ||
29 | |||
30 | #define AR_PHY_AIC_STAT_0_B0 (AR_SM_BASE + 0x4c4) | ||
31 | #define AR_PHY_AIC_STAT_1_B0 (AR_SM_BASE + 0x4c8) | ||
32 | #define AR_PHY_AIC_STAT_2_B0 (AR_SM_BASE + 0x4cc) | ||
33 | |||
34 | #define AR_PHY_AIC_CTRL_0_B1 (AR_SM1_BASE + 0x4b0) | ||
35 | #define AR_PHY_AIC_CTRL_1_B1 (AR_SM1_BASE + 0x4b4) | ||
36 | #define AR_PHY_AIC_CTRL_4_B1 (AR_SM1_BASE + 0x4c0) | ||
37 | |||
38 | #define AR_PHY_AIC_STAT_0_B1 (AR_SM1_BASE + 0x4c4) | ||
39 | #define AR_PHY_AIC_STAT_1_B1 (AR_SM1_BASE + 0x4c8) | ||
40 | #define AR_PHY_AIC_STAT_2_B1 (AR_SM1_BASE + 0x4cc) | ||
41 | |||
42 | #define AR_PHY_AIC_SRAM_ADDR_B0 (AR_SM_BASE + 0x5f0) | ||
43 | #define AR_PHY_AIC_SRAM_DATA_B0 (AR_SM_BASE + 0x5f4) | ||
44 | |||
45 | #define AR_PHY_AIC_SRAM_ADDR_B1 (AR_SM1_BASE + 0x5f0) | ||
46 | #define AR_PHY_AIC_SRAM_DATA_B1 (AR_SM1_BASE + 0x5f4) | ||
47 | |||
48 | #define AR_PHY_BT_COEX_4 (AR_AGC_BASE + 0x60) | ||
49 | #define AR_PHY_BT_COEX_5 (AR_AGC_BASE + 0x64) | ||
50 | |||
51 | /* AIC fields */ | ||
52 | #define AR_PHY_AIC_MON_ENABLE 0x80000000 | ||
53 | #define AR_PHY_AIC_MON_ENABLE_S 31 | ||
54 | #define AR_PHY_AIC_CAL_MAX_HOP_COUNT 0x7F000000 | ||
55 | #define AR_PHY_AIC_CAL_MAX_HOP_COUNT_S 24 | ||
56 | #define AR_PHY_AIC_CAL_MIN_VALID_COUNT 0x00FE0000 | ||
57 | #define AR_PHY_AIC_CAL_MIN_VALID_COUNT_S 17 | ||
58 | #define AR_PHY_AIC_F_WLAN 0x0001FC00 | ||
59 | #define AR_PHY_AIC_F_WLAN_S 10 | ||
60 | #define AR_PHY_AIC_CAL_CH_VALID_RESET 0x00000200 | ||
61 | #define AR_PHY_AIC_CAL_CH_VALID_RESET_S 9 | ||
62 | #define AR_PHY_AIC_CAL_ENABLE 0x00000100 | ||
63 | #define AR_PHY_AIC_CAL_ENABLE_S 8 | ||
64 | #define AR_PHY_AIC_BTTX_PWR_THR 0x000000FE | ||
65 | #define AR_PHY_AIC_BTTX_PWR_THR_S 1 | ||
66 | #define AR_PHY_AIC_ENABLE 0x00000001 | ||
67 | #define AR_PHY_AIC_ENABLE_S 0 | ||
68 | #define AR_PHY_AIC_CAL_BT_REF_DELAY 0x00F00000 | ||
69 | #define AR_PHY_AIC_CAL_BT_REF_DELAY_S 20 | ||
70 | #define AR_PHY_AIC_BT_IDLE_CFG 0x00080000 | ||
71 | #define AR_PHY_AIC_BT_IDLE_CFG_S 19 | ||
72 | #define AR_PHY_AIC_STDBY_COND 0x00060000 | ||
73 | #define AR_PHY_AIC_STDBY_COND_S 17 | ||
74 | #define AR_PHY_AIC_STDBY_ROT_ATT_DB 0x0001F800 | ||
75 | #define AR_PHY_AIC_STDBY_ROT_ATT_DB_S 11 | ||
76 | #define AR_PHY_AIC_STDBY_COM_ATT_DB 0x00000700 | ||
77 | #define AR_PHY_AIC_STDBY_COM_ATT_DB_S 8 | ||
78 | #define AR_PHY_AIC_RSSI_MAX 0x000000F0 | ||
79 | #define AR_PHY_AIC_RSSI_MAX_S 4 | ||
80 | #define AR_PHY_AIC_RSSI_MIN 0x0000000F | ||
81 | #define AR_PHY_AIC_RSSI_MIN_S 0 | ||
82 | #define AR_PHY_AIC_RADIO_DELAY 0x7F000000 | ||
83 | #define AR_PHY_AIC_RADIO_DELAY_S 24 | ||
84 | #define AR_PHY_AIC_CAL_STEP_SIZE_CORR 0x00F00000 | ||
85 | #define AR_PHY_AIC_CAL_STEP_SIZE_CORR_S 20 | ||
86 | #define AR_PHY_AIC_CAL_ROT_IDX_CORR 0x000F8000 | ||
87 | #define AR_PHY_AIC_CAL_ROT_IDX_CORR_S 15 | ||
88 | #define AR_PHY_AIC_CAL_CONV_CHECK_FACTOR 0x00006000 | ||
89 | #define AR_PHY_AIC_CAL_CONV_CHECK_FACTOR_S 13 | ||
90 | #define AR_PHY_AIC_ROT_IDX_COUNT_MAX 0x00001C00 | ||
91 | #define AR_PHY_AIC_ROT_IDX_COUNT_MAX_S 10 | ||
92 | #define AR_PHY_AIC_CAL_SYNTH_TOGGLE 0x00000200 | ||
93 | #define AR_PHY_AIC_CAL_SYNTH_TOGGLE_S 9 | ||
94 | #define AR_PHY_AIC_CAL_SYNTH_AFTER_BTRX 0x00000100 | ||
95 | #define AR_PHY_AIC_CAL_SYNTH_AFTER_BTRX_S 8 | ||
96 | #define AR_PHY_AIC_CAL_SYNTH_SETTLING 0x000000FF | ||
97 | #define AR_PHY_AIC_CAL_SYNTH_SETTLING_S 0 | ||
98 | #define AR_PHY_AIC_MON_MAX_HOP_COUNT 0x07F00000 | ||
99 | #define AR_PHY_AIC_MON_MAX_HOP_COUNT_S 20 | ||
100 | #define AR_PHY_AIC_MON_MIN_STALE_COUNT 0x000FE000 | ||
101 | #define AR_PHY_AIC_MON_MIN_STALE_COUNT_S 13 | ||
102 | #define AR_PHY_AIC_MON_PWR_EST_LONG 0x00001000 | ||
103 | #define AR_PHY_AIC_MON_PWR_EST_LONG_S 12 | ||
104 | #define AR_PHY_AIC_MON_PD_TALLY_SCALING 0x00000C00 | ||
105 | #define AR_PHY_AIC_MON_PD_TALLY_SCALING_S 10 | ||
106 | #define AR_PHY_AIC_MON_PERF_THR 0x000003E0 | ||
107 | #define AR_PHY_AIC_MON_PERF_THR_S 5 | ||
108 | #define AR_PHY_AIC_CAL_TARGET_MAG_SETTING 0x00000018 | ||
109 | #define AR_PHY_AIC_CAL_TARGET_MAG_SETTING_S 3 | ||
110 | #define AR_PHY_AIC_CAL_PERF_CHECK_FACTOR 0x00000006 | ||
111 | #define AR_PHY_AIC_CAL_PERF_CHECK_FACTOR_S 1 | ||
112 | #define AR_PHY_AIC_CAL_PWR_EST_LONG 0x00000001 | ||
113 | #define AR_PHY_AIC_CAL_PWR_EST_LONG_S 0 | ||
114 | #define AR_PHY_AIC_MON_DONE 0x80000000 | ||
115 | #define AR_PHY_AIC_MON_DONE_S 31 | ||
116 | #define AR_PHY_AIC_MON_ACTIVE 0x40000000 | ||
117 | #define AR_PHY_AIC_MON_ACTIVE_S 30 | ||
118 | #define AR_PHY_AIC_MEAS_COUNT 0x3F000000 | ||
119 | #define AR_PHY_AIC_MEAS_COUNT_S 24 | ||
120 | #define AR_PHY_AIC_CAL_ANT_ISO_EST 0x00FC0000 | ||
121 | #define AR_PHY_AIC_CAL_ANT_ISO_EST_S 18 | ||
122 | #define AR_PHY_AIC_CAL_HOP_COUNT 0x0003F800 | ||
123 | #define AR_PHY_AIC_CAL_HOP_COUNT_S 11 | ||
124 | #define AR_PHY_AIC_CAL_VALID_COUNT 0x000007F0 | ||
125 | #define AR_PHY_AIC_CAL_VALID_COUNT_S 4 | ||
126 | #define AR_PHY_AIC_CAL_BT_TOO_WEAK_ERR 0x00000008 | ||
127 | #define AR_PHY_AIC_CAL_BT_TOO_WEAK_ERR_S 3 | ||
128 | #define AR_PHY_AIC_CAL_BT_TOO_STRONG_ERR 0x00000004 | ||
129 | #define AR_PHY_AIC_CAL_BT_TOO_STRONG_ERR_S 2 | ||
130 | #define AR_PHY_AIC_CAL_DONE 0x00000002 | ||
131 | #define AR_PHY_AIC_CAL_DONE_S 1 | ||
132 | #define AR_PHY_AIC_CAL_ACTIVE 0x00000001 | ||
133 | #define AR_PHY_AIC_CAL_ACTIVE_S 0 | ||
134 | |||
135 | #define AR_PHY_AIC_MEAS_MAG_MIN 0xFFC00000 | ||
136 | #define AR_PHY_AIC_MEAS_MAG_MIN_S 22 | ||
137 | #define AR_PHY_AIC_MON_STALE_COUNT 0x003F8000 | ||
138 | #define AR_PHY_AIC_MON_STALE_COUNT_S 15 | ||
139 | #define AR_PHY_AIC_MON_HOP_COUNT 0x00007F00 | ||
140 | #define AR_PHY_AIC_MON_HOP_COUNT_S 8 | ||
141 | #define AR_PHY_AIC_CAL_AIC_SM 0x000000F8 | ||
142 | #define AR_PHY_AIC_CAL_AIC_SM_S 3 | ||
143 | #define AR_PHY_AIC_SM 0x00000007 | ||
144 | #define AR_PHY_AIC_SM_S 0 | ||
145 | #define AR_PHY_AIC_SRAM_VALID 0x00000001 | ||
146 | #define AR_PHY_AIC_SRAM_VALID_S 0 | ||
147 | #define AR_PHY_AIC_SRAM_ROT_QUAD_ATT_DB 0x0000007E | ||
148 | #define AR_PHY_AIC_SRAM_ROT_QUAD_ATT_DB_S 1 | ||
149 | #define AR_PHY_AIC_SRAM_VGA_QUAD_SIGN 0x00000080 | ||
150 | #define AR_PHY_AIC_SRAM_VGA_QUAD_SIGN_S 7 | ||
151 | #define AR_PHY_AIC_SRAM_ROT_DIR_ATT_DB 0x00003F00 | ||
152 | #define AR_PHY_AIC_SRAM_ROT_DIR_ATT_DB_S 8 | ||
153 | #define AR_PHY_AIC_SRAM_VGA_DIR_SIGN 0x00004000 | ||
154 | #define AR_PHY_AIC_SRAM_VGA_DIR_SIGN_S 14 | ||
155 | #define AR_PHY_AIC_SRAM_COM_ATT_6DB 0x00038000 | ||
156 | #define AR_PHY_AIC_SRAM_COM_ATT_6DB_S 15 | ||
157 | #define AR_PHY_AIC_CAL_ROT_ATT_DB_EST_ISO 0x0000E000 | ||
158 | #define AR_PHY_AIC_CAL_ROT_ATT_DB_EST_ISO_S 13 | ||
159 | #define AR_PHY_AIC_CAL_COM_ATT_DB_EST_ISO 0x00001E00 | ||
160 | #define AR_PHY_AIC_CAL_COM_ATT_DB_EST_ISO_S 9 | ||
161 | #define AR_PHY_AIC_CAL_ISO_EST_INIT_SETTING 0x000001F8 | ||
162 | #define AR_PHY_AIC_CAL_ISO_EST_INIT_SETTING_S 3 | ||
163 | #define AR_PHY_AIC_CAL_COM_ATT_DB_BACKOFF 0x00000006 | ||
164 | #define AR_PHY_AIC_CAL_COM_ATT_DB_BACKOFF_S 1 | ||
165 | #define AR_PHY_AIC_CAL_COM_ATT_DB_FIXED 0x00000001 | ||
166 | #define AR_PHY_AIC_CAL_COM_ATT_DB_FIXED_S 0 | ||
167 | |||
168 | #endif /* REG_AIC_H */ | ||
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 65c8894c5f81..67a2f8c88829 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c | |||
@@ -61,6 +61,8 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) | |||
61 | return "WMI_REG_READ_CMDID"; | 61 | return "WMI_REG_READ_CMDID"; |
62 | case WMI_REG_WRITE_CMDID: | 62 | case WMI_REG_WRITE_CMDID: |
63 | return "WMI_REG_WRITE_CMDID"; | 63 | return "WMI_REG_WRITE_CMDID"; |
64 | case WMI_REG_RMW_CMDID: | ||
65 | return "WMI_REG_RMW_CMDID"; | ||
64 | case WMI_RC_STATE_CHANGE_CMDID: | 66 | case WMI_RC_STATE_CHANGE_CMDID: |
65 | return "WMI_RC_STATE_CHANGE_CMDID"; | 67 | return "WMI_RC_STATE_CHANGE_CMDID"; |
66 | case WMI_RC_RATE_UPDATE_CMDID: | 68 | case WMI_RC_RATE_UPDATE_CMDID: |
@@ -101,6 +103,7 @@ struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv) | |||
101 | spin_lock_init(&wmi->event_lock); | 103 | spin_lock_init(&wmi->event_lock); |
102 | mutex_init(&wmi->op_mutex); | 104 | mutex_init(&wmi->op_mutex); |
103 | mutex_init(&wmi->multi_write_mutex); | 105 | mutex_init(&wmi->multi_write_mutex); |
106 | mutex_init(&wmi->multi_rmw_mutex); | ||
104 | init_completion(&wmi->cmd_wait); | 107 | init_completion(&wmi->cmd_wait); |
105 | INIT_LIST_HEAD(&wmi->pending_tx_events); | 108 | INIT_LIST_HEAD(&wmi->pending_tx_events); |
106 | tasklet_init(&wmi->wmi_event_tasklet, ath9k_wmi_event_tasklet, | 109 | tasklet_init(&wmi->wmi_event_tasklet, ath9k_wmi_event_tasklet, |
diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index 0db37f230018..aa84a335289a 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h | |||
@@ -112,6 +112,7 @@ enum wmi_cmd_id { | |||
112 | WMI_TX_STATS_CMDID, | 112 | WMI_TX_STATS_CMDID, |
113 | WMI_RX_STATS_CMDID, | 113 | WMI_RX_STATS_CMDID, |
114 | WMI_BITRATE_MASK_CMDID, | 114 | WMI_BITRATE_MASK_CMDID, |
115 | WMI_REG_RMW_CMDID, | ||
115 | }; | 116 | }; |
116 | 117 | ||
117 | enum wmi_event_id { | 118 | enum wmi_event_id { |
@@ -125,12 +126,19 @@ enum wmi_event_id { | |||
125 | }; | 126 | }; |
126 | 127 | ||
127 | #define MAX_CMD_NUMBER 62 | 128 | #define MAX_CMD_NUMBER 62 |
129 | #define MAX_RMW_CMD_NUMBER 15 | ||
128 | 130 | ||
129 | struct register_write { | 131 | struct register_write { |
130 | __be32 reg; | 132 | __be32 reg; |
131 | __be32 val; | 133 | __be32 val; |
132 | }; | 134 | }; |
133 | 135 | ||
136 | struct register_rmw { | ||
137 | __be32 reg; | ||
138 | __be32 set; | ||
139 | __be32 clr; | ||
140 | } __packed; | ||
141 | |||
134 | struct ath9k_htc_tx_event { | 142 | struct ath9k_htc_tx_event { |
135 | int count; | 143 | int count; |
136 | struct __wmi_event_txstatus txs; | 144 | struct __wmi_event_txstatus txs; |
@@ -156,10 +164,18 @@ struct wmi { | |||
156 | 164 | ||
157 | spinlock_t wmi_lock; | 165 | spinlock_t wmi_lock; |
158 | 166 | ||
167 | /* multi write section */ | ||
159 | atomic_t mwrite_cnt; | 168 | atomic_t mwrite_cnt; |
160 | struct register_write multi_write[MAX_CMD_NUMBER]; | 169 | struct register_write multi_write[MAX_CMD_NUMBER]; |
161 | u32 multi_write_idx; | 170 | u32 multi_write_idx; |
162 | struct mutex multi_write_mutex; | 171 | struct mutex multi_write_mutex; |
172 | |||
173 | /* multi rmw section */ | ||
174 | atomic_t m_rmw_cnt; | ||
175 | struct register_rmw multi_rmw[MAX_RMW_CMD_NUMBER]; | ||
176 | u32 multi_rmw_idx; | ||
177 | struct mutex multi_rmw_mutex; | ||
178 | |||
163 | }; | 179 | }; |
164 | 180 | ||
165 | struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv); | 181 | struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv); |
diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.c b/drivers/net/wireless/ath/dfs_pattern_detector.c index 3d57f8772389..c657ca26a71a 100644 --- a/drivers/net/wireless/ath/dfs_pattern_detector.c +++ b/drivers/net/wireless/ath/dfs_pattern_detector.c | |||
@@ -289,7 +289,7 @@ dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event) | |||
289 | "count=%d, count_false=%d\n", | 289 | "count=%d, count_false=%d\n", |
290 | event->freq, pd->rs->type_id, | 290 | event->freq, pd->rs->type_id, |
291 | ps->pri, ps->count, ps->count_falses); | 291 | ps->pri, ps->count, ps->count_falses); |
292 | channel_detector_reset(dpd, cd); | 292 | pd->reset(pd, dpd->last_pulse_ts); |
293 | return true; | 293 | return true; |
294 | } | 294 | } |
295 | } | 295 | } |
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 47d14db59b93..b97172667bc7 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c | |||
@@ -14,6 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/etherdevice.h> | ||
17 | #include "wil6210.h" | 18 | #include "wil6210.h" |
18 | #include "wmi.h" | 19 | #include "wmi.h" |
19 | 20 | ||
@@ -217,7 +218,7 @@ static int wil_cfg80211_dump_station(struct wiphy *wiphy, | |||
217 | if (cid < 0) | 218 | if (cid < 0) |
218 | return -ENOENT; | 219 | return -ENOENT; |
219 | 220 | ||
220 | memcpy(mac, wil->sta[cid].addr, ETH_ALEN); | 221 | ether_addr_copy(mac, wil->sta[cid].addr); |
221 | wil_dbg_misc(wil, "%s(%pM) CID %d\n", __func__, mac, cid); | 222 | wil_dbg_misc(wil, "%s(%pM) CID %d\n", __func__, mac, cid); |
222 | 223 | ||
223 | rc = wil_cid_fill_sinfo(wil, cid, sinfo); | 224 | rc = wil_cid_fill_sinfo(wil, cid, sinfo); |
@@ -478,8 +479,8 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, | |||
478 | } | 479 | } |
479 | conn.channel = ch - 1; | 480 | conn.channel = ch - 1; |
480 | 481 | ||
481 | memcpy(conn.bssid, bss->bssid, ETH_ALEN); | 482 | ether_addr_copy(conn.bssid, bss->bssid); |
482 | memcpy(conn.dst_mac, bss->bssid, ETH_ALEN); | 483 | ether_addr_copy(conn.dst_mac, bss->bssid); |
483 | 484 | ||
484 | set_bit(wil_status_fwconnecting, wil->status); | 485 | set_bit(wil_status_fwconnecting, wil->status); |
485 | 486 | ||
@@ -782,8 +783,17 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, | |||
782 | rc = wmi_pcp_start(wil, info->beacon_interval, wmi_nettype, | 783 | rc = wmi_pcp_start(wil, info->beacon_interval, wmi_nettype, |
783 | channel->hw_value); | 784 | channel->hw_value); |
784 | if (rc) | 785 | if (rc) |
785 | netif_carrier_off(ndev); | 786 | goto err_pcp_start; |
786 | 787 | ||
788 | rc = wil_bcast_init(wil); | ||
789 | if (rc) | ||
790 | goto err_bcast; | ||
791 | |||
792 | goto out; /* success */ | ||
793 | err_bcast: | ||
794 | wmi_pcp_stop(wil); | ||
795 | err_pcp_start: | ||
796 | netif_carrier_off(ndev); | ||
787 | out: | 797 | out: |
788 | mutex_unlock(&wil->mutex); | 798 | mutex_unlock(&wil->mutex); |
789 | return rc; | 799 | return rc; |
@@ -917,6 +927,21 @@ static int wil_cfg80211_probe_client(struct wiphy *wiphy, | |||
917 | return 0; | 927 | return 0; |
918 | } | 928 | } |
919 | 929 | ||
930 | static int wil_cfg80211_change_bss(struct wiphy *wiphy, | ||
931 | struct net_device *dev, | ||
932 | struct bss_parameters *params) | ||
933 | { | ||
934 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
935 | |||
936 | if (params->ap_isolate >= 0) { | ||
937 | wil_dbg_misc(wil, "%s(ap_isolate %d => %d)\n", __func__, | ||
938 | wil->ap_isolate, params->ap_isolate); | ||
939 | wil->ap_isolate = params->ap_isolate; | ||
940 | } | ||
941 | |||
942 | return 0; | ||
943 | } | ||
944 | |||
920 | static struct cfg80211_ops wil_cfg80211_ops = { | 945 | static struct cfg80211_ops wil_cfg80211_ops = { |
921 | .scan = wil_cfg80211_scan, | 946 | .scan = wil_cfg80211_scan, |
922 | .connect = wil_cfg80211_connect, | 947 | .connect = wil_cfg80211_connect, |
@@ -937,6 +962,7 @@ static struct cfg80211_ops wil_cfg80211_ops = { | |||
937 | .stop_ap = wil_cfg80211_stop_ap, | 962 | .stop_ap = wil_cfg80211_stop_ap, |
938 | .del_station = wil_cfg80211_del_station, | 963 | .del_station = wil_cfg80211_del_station, |
939 | .probe_client = wil_cfg80211_probe_client, | 964 | .probe_client = wil_cfg80211_probe_client, |
965 | .change_bss = wil_cfg80211_change_bss, | ||
940 | }; | 966 | }; |
941 | 967 | ||
942 | static void wil_wiphy_init(struct wiphy *wiphy) | 968 | static void wil_wiphy_init(struct wiphy *wiphy) |
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 3830cc20d4fa..bbc22d88f78f 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c | |||
@@ -121,12 +121,18 @@ static int wil_vring_debugfs_show(struct seq_file *s, void *data) | |||
121 | 121 | ||
122 | snprintf(name, sizeof(name), "tx_%2d", i); | 122 | snprintf(name, sizeof(name), "tx_%2d", i); |
123 | 123 | ||
124 | seq_printf(s, | 124 | if (cid < WIL6210_MAX_CID) |
125 | "\n%pM CID %d TID %d BACK([%d] %d TU A%s) [%3d|%3d] idle %s\n", | 125 | seq_printf(s, |
126 | wil->sta[cid].addr, cid, tid, | 126 | "\n%pM CID %d TID %d BACK([%u] %u TU A%s) [%3d|%3d] idle %s\n", |
127 | txdata->agg_wsize, txdata->agg_timeout, | 127 | wil->sta[cid].addr, cid, tid, |
128 | txdata->agg_amsdu ? "+" : "-", | 128 | txdata->agg_wsize, |
129 | used, avail, sidle); | 129 | txdata->agg_timeout, |
130 | txdata->agg_amsdu ? "+" : "-", | ||
131 | used, avail, sidle); | ||
132 | else | ||
133 | seq_printf(s, | ||
134 | "\nBroadcast [%3d|%3d] idle %s\n", | ||
135 | used, avail, sidle); | ||
130 | 136 | ||
131 | wil_print_vring(s, wil, name, vring, '_', 'H'); | 137 | wil_print_vring(s, wil, name, vring, '_', 'H'); |
132 | } | 138 | } |
@@ -1405,6 +1411,7 @@ static const struct dbg_off dbg_wil_off[] = { | |||
1405 | WIL_FIELD(fw_version, S_IRUGO, doff_u32), | 1411 | WIL_FIELD(fw_version, S_IRUGO, doff_u32), |
1406 | WIL_FIELD(hw_version, S_IRUGO, doff_x32), | 1412 | WIL_FIELD(hw_version, S_IRUGO, doff_x32), |
1407 | WIL_FIELD(recovery_count, S_IRUGO, doff_u32), | 1413 | WIL_FIELD(recovery_count, S_IRUGO, doff_u32), |
1414 | WIL_FIELD(ap_isolate, S_IRUGO, doff_u32), | ||
1408 | {}, | 1415 | {}, |
1409 | }; | 1416 | }; |
1410 | 1417 | ||
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index db74e811f5c4..c2a238426425 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c | |||
@@ -68,6 +68,7 @@ MODULE_PARM_DESC(mtu_max, " Max MTU value."); | |||
68 | 68 | ||
69 | static uint rx_ring_order = WIL_RX_RING_SIZE_ORDER_DEFAULT; | 69 | static uint rx_ring_order = WIL_RX_RING_SIZE_ORDER_DEFAULT; |
70 | static uint tx_ring_order = WIL_TX_RING_SIZE_ORDER_DEFAULT; | 70 | static uint tx_ring_order = WIL_TX_RING_SIZE_ORDER_DEFAULT; |
71 | static uint bcast_ring_order = WIL_BCAST_RING_SIZE_ORDER_DEFAULT; | ||
71 | 72 | ||
72 | static int ring_order_set(const char *val, const struct kernel_param *kp) | 73 | static int ring_order_set(const char *val, const struct kernel_param *kp) |
73 | { | 74 | { |
@@ -216,6 +217,7 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, | |||
216 | switch (wdev->iftype) { | 217 | switch (wdev->iftype) { |
217 | case NL80211_IFTYPE_STATION: | 218 | case NL80211_IFTYPE_STATION: |
218 | case NL80211_IFTYPE_P2P_CLIENT: | 219 | case NL80211_IFTYPE_P2P_CLIENT: |
220 | wil_bcast_fini(wil); | ||
219 | netif_tx_stop_all_queues(ndev); | 221 | netif_tx_stop_all_queues(ndev); |
220 | netif_carrier_off(ndev); | 222 | netif_carrier_off(ndev); |
221 | 223 | ||
@@ -360,6 +362,35 @@ static int wil_find_free_vring(struct wil6210_priv *wil) | |||
360 | return -EINVAL; | 362 | return -EINVAL; |
361 | } | 363 | } |
362 | 364 | ||
365 | int wil_bcast_init(struct wil6210_priv *wil) | ||
366 | { | ||
367 | int ri = wil->bcast_vring, rc; | ||
368 | |||
369 | if ((ri >= 0) && wil->vring_tx[ri].va) | ||
370 | return 0; | ||
371 | |||
372 | ri = wil_find_free_vring(wil); | ||
373 | if (ri < 0) | ||
374 | return ri; | ||
375 | |||
376 | rc = wil_vring_init_bcast(wil, ri, 1 << bcast_ring_order); | ||
377 | if (rc == 0) | ||
378 | wil->bcast_vring = ri; | ||
379 | |||
380 | return rc; | ||
381 | } | ||
382 | |||
383 | void wil_bcast_fini(struct wil6210_priv *wil) | ||
384 | { | ||
385 | int ri = wil->bcast_vring; | ||
386 | |||
387 | if (ri < 0) | ||
388 | return; | ||
389 | |||
390 | wil->bcast_vring = -1; | ||
391 | wil_vring_fini_tx(wil, ri); | ||
392 | } | ||
393 | |||
363 | static void wil_connect_worker(struct work_struct *work) | 394 | static void wil_connect_worker(struct work_struct *work) |
364 | { | 395 | { |
365 | int rc; | 396 | int rc; |
@@ -407,6 +438,7 @@ int wil_priv_init(struct wil6210_priv *wil) | |||
407 | init_completion(&wil->wmi_call); | 438 | init_completion(&wil->wmi_call); |
408 | 439 | ||
409 | wil->pending_connect_cid = -1; | 440 | wil->pending_connect_cid = -1; |
441 | wil->bcast_vring = -1; | ||
410 | setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil); | 442 | setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil); |
411 | setup_timer(&wil->scan_timer, wil_scan_timer_fn, (ulong)wil); | 443 | setup_timer(&wil->scan_timer, wil_scan_timer_fn, (ulong)wil); |
412 | 444 | ||
@@ -656,6 +688,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) | |||
656 | 688 | ||
657 | cancel_work_sync(&wil->disconnect_worker); | 689 | cancel_work_sync(&wil->disconnect_worker); |
658 | wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false); | 690 | wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false); |
691 | wil_bcast_fini(wil); | ||
659 | 692 | ||
660 | /* prevent NAPI from being scheduled */ | 693 | /* prevent NAPI from being scheduled */ |
661 | bitmap_zero(wil->status, wil_status_last); | 694 | bitmap_zero(wil->status, wil_status_last); |
@@ -714,6 +747,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) | |||
714 | 747 | ||
715 | /* init after reset */ | 748 | /* init after reset */ |
716 | wil->pending_connect_cid = -1; | 749 | wil->pending_connect_cid = -1; |
750 | wil->ap_isolate = 0; | ||
717 | reinit_completion(&wil->wmi_ready); | 751 | reinit_completion(&wil->wmi_ready); |
718 | reinit_completion(&wil->wmi_call); | 752 | reinit_completion(&wil->wmi_call); |
719 | 753 | ||
@@ -723,6 +757,8 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) | |||
723 | 757 | ||
724 | /* we just started MAC, wait for FW ready */ | 758 | /* we just started MAC, wait for FW ready */ |
725 | rc = wil_wait_for_fw_ready(wil); | 759 | rc = wil_wait_for_fw_ready(wil); |
760 | if (rc == 0) /* check FW is responsive */ | ||
761 | rc = wmi_echo(wil); | ||
726 | } | 762 | } |
727 | 763 | ||
728 | return rc; | 764 | return rc; |
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index ace30c1b5c64..f2f7ea29558e 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c | |||
@@ -82,7 +82,7 @@ static int wil6210_netdev_poll_rx(struct napi_struct *napi, int budget) | |||
82 | wil_rx_handle(wil, "a); | 82 | wil_rx_handle(wil, "a); |
83 | done = budget - quota; | 83 | done = budget - quota; |
84 | 84 | ||
85 | if (done <= 1) { /* burst ends - only one packet processed */ | 85 | if (done < budget) { |
86 | napi_complete(napi); | 86 | napi_complete(napi); |
87 | wil6210_unmask_irq_rx(wil); | 87 | wil6210_unmask_irq_rx(wil); |
88 | wil_dbg_txrx(wil, "NAPI RX complete\n"); | 88 | wil_dbg_txrx(wil, "NAPI RX complete\n"); |
@@ -110,7 +110,7 @@ static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget) | |||
110 | tx_done += wil_tx_complete(wil, i); | 110 | tx_done += wil_tx_complete(wil, i); |
111 | } | 111 | } |
112 | 112 | ||
113 | if (tx_done <= 1) { /* burst ends - only one packet processed */ | 113 | if (tx_done < budget) { |
114 | napi_complete(napi); | 114 | napi_complete(napi); |
115 | wil6210_unmask_irq_tx(wil); | 115 | wil6210_unmask_irq_tx(wil); |
116 | wil_dbg_txrx(wil, "NAPI TX complete\n"); | 116 | wil_dbg_txrx(wil, "NAPI TX complete\n"); |
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c index 25343cffe229..109986114abf 100644 --- a/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c | |||
@@ -246,8 +246,6 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
246 | 246 | ||
247 | wil6210_debugfs_init(wil); | 247 | wil6210_debugfs_init(wil); |
248 | 248 | ||
249 | /* check FW is alive */ | ||
250 | wmi_echo(wil); | ||
251 | 249 | ||
252 | return 0; | 250 | return 0; |
253 | 251 | ||
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 7f2f560b8638..e8bd512d81a9 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c | |||
@@ -33,6 +33,15 @@ module_param(rtap_include_phy_info, bool, S_IRUGO); | |||
33 | MODULE_PARM_DESC(rtap_include_phy_info, | 33 | MODULE_PARM_DESC(rtap_include_phy_info, |
34 | " Include PHY info in the radiotap header, default - no"); | 34 | " Include PHY info in the radiotap header, default - no"); |
35 | 35 | ||
36 | bool rx_align_2; | ||
37 | module_param(rx_align_2, bool, S_IRUGO); | ||
38 | MODULE_PARM_DESC(rx_align_2, " align Rx buffers on 4*n+2, default - no"); | ||
39 | |||
40 | static inline uint wil_rx_snaplen(void) | ||
41 | { | ||
42 | return rx_align_2 ? 6 : 0; | ||
43 | } | ||
44 | |||
36 | static inline int wil_vring_is_empty(struct vring *vring) | 45 | static inline int wil_vring_is_empty(struct vring *vring) |
37 | { | 46 | { |
38 | return vring->swhead == vring->swtail; | 47 | return vring->swhead == vring->swtail; |
@@ -209,7 +218,7 @@ static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring, | |||
209 | u32 i, int headroom) | 218 | u32 i, int headroom) |
210 | { | 219 | { |
211 | struct device *dev = wil_to_dev(wil); | 220 | struct device *dev = wil_to_dev(wil); |
212 | unsigned int sz = mtu_max + ETH_HLEN; | 221 | unsigned int sz = mtu_max + ETH_HLEN + wil_rx_snaplen(); |
213 | struct vring_rx_desc dd, *d = ⅆ | 222 | struct vring_rx_desc dd, *d = ⅆ |
214 | volatile struct vring_rx_desc *_d = &vring->va[i].rx; | 223 | volatile struct vring_rx_desc *_d = &vring->va[i].rx; |
215 | dma_addr_t pa; | 224 | dma_addr_t pa; |
@@ -365,10 +374,12 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, | |||
365 | struct vring_rx_desc *d; | 374 | struct vring_rx_desc *d; |
366 | struct sk_buff *skb; | 375 | struct sk_buff *skb; |
367 | dma_addr_t pa; | 376 | dma_addr_t pa; |
368 | unsigned int sz = mtu_max + ETH_HLEN; | 377 | unsigned int snaplen = wil_rx_snaplen(); |
378 | unsigned int sz = mtu_max + ETH_HLEN + snaplen; | ||
369 | u16 dmalen; | 379 | u16 dmalen; |
370 | u8 ftype; | 380 | u8 ftype; |
371 | int cid; | 381 | int cid; |
382 | int i = (int)vring->swhead; | ||
372 | struct wil_net_stats *stats; | 383 | struct wil_net_stats *stats; |
373 | 384 | ||
374 | BUILD_BUG_ON(sizeof(struct vring_rx_desc) > sizeof(skb->cb)); | 385 | BUILD_BUG_ON(sizeof(struct vring_rx_desc) > sizeof(skb->cb)); |
@@ -376,24 +387,28 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, | |||
376 | if (unlikely(wil_vring_is_empty(vring))) | 387 | if (unlikely(wil_vring_is_empty(vring))) |
377 | return NULL; | 388 | return NULL; |
378 | 389 | ||
379 | _d = &vring->va[vring->swhead].rx; | 390 | _d = &vring->va[i].rx; |
380 | if (unlikely(!(_d->dma.status & RX_DMA_STATUS_DU))) { | 391 | if (unlikely(!(_d->dma.status & RX_DMA_STATUS_DU))) { |
381 | /* it is not error, we just reached end of Rx done area */ | 392 | /* it is not error, we just reached end of Rx done area */ |
382 | return NULL; | 393 | return NULL; |
383 | } | 394 | } |
384 | 395 | ||
385 | skb = vring->ctx[vring->swhead].skb; | 396 | skb = vring->ctx[i].skb; |
397 | vring->ctx[i].skb = NULL; | ||
398 | wil_vring_advance_head(vring, 1); | ||
399 | if (!skb) { | ||
400 | wil_err(wil, "No Rx skb at [%d]\n", i); | ||
401 | return NULL; | ||
402 | } | ||
386 | d = wil_skb_rxdesc(skb); | 403 | d = wil_skb_rxdesc(skb); |
387 | *d = *_d; | 404 | *d = *_d; |
388 | pa = wil_desc_addr(&d->dma.addr); | 405 | pa = wil_desc_addr(&d->dma.addr); |
389 | vring->ctx[vring->swhead].skb = NULL; | ||
390 | wil_vring_advance_head(vring, 1); | ||
391 | 406 | ||
392 | dma_unmap_single(dev, pa, sz, DMA_FROM_DEVICE); | 407 | dma_unmap_single(dev, pa, sz, DMA_FROM_DEVICE); |
393 | dmalen = le16_to_cpu(d->dma.length); | 408 | dmalen = le16_to_cpu(d->dma.length); |
394 | 409 | ||
395 | trace_wil6210_rx(vring->swhead, d); | 410 | trace_wil6210_rx(i, d); |
396 | wil_dbg_txrx(wil, "Rx[%3d] : %d bytes\n", vring->swhead, dmalen); | 411 | wil_dbg_txrx(wil, "Rx[%3d] : %d bytes\n", i, dmalen); |
397 | wil_hex_dump_txrx("Rx ", DUMP_PREFIX_NONE, 32, 4, | 412 | wil_hex_dump_txrx("Rx ", DUMP_PREFIX_NONE, 32, 4, |
398 | (const void *)d, sizeof(*d), false); | 413 | (const void *)d, sizeof(*d), false); |
399 | 414 | ||
@@ -433,7 +448,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, | |||
433 | return NULL; | 448 | return NULL; |
434 | } | 449 | } |
435 | 450 | ||
436 | if (unlikely(skb->len < ETH_HLEN)) { | 451 | if (unlikely(skb->len < ETH_HLEN + snaplen)) { |
437 | wil_err(wil, "Short frame, len = %d\n", skb->len); | 452 | wil_err(wil, "Short frame, len = %d\n", skb->len); |
438 | /* TODO: process it (i.e. BAR) */ | 453 | /* TODO: process it (i.e. BAR) */ |
439 | kfree_skb(skb); | 454 | kfree_skb(skb); |
@@ -455,6 +470,17 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, | |||
455 | */ | 470 | */ |
456 | } | 471 | } |
457 | 472 | ||
473 | if (snaplen) { | ||
474 | /* Packet layout | ||
475 | * +-------+-------+---------+------------+------+ | ||
476 | * | SA(6) | DA(6) | SNAP(6) | ETHTYPE(2) | DATA | | ||
477 | * +-------+-------+---------+------------+------+ | ||
478 | * Need to remove SNAP, shifting SA and DA forward | ||
479 | */ | ||
480 | memmove(skb->data + snaplen, skb->data, 2 * ETH_ALEN); | ||
481 | skb_pull(skb, snaplen); | ||
482 | } | ||
483 | |||
458 | return skb; | 484 | return skb; |
459 | } | 485 | } |
460 | 486 | ||
@@ -492,17 +518,71 @@ static int wil_rx_refill(struct wil6210_priv *wil, int count) | |||
492 | */ | 518 | */ |
493 | void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) | 519 | void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) |
494 | { | 520 | { |
495 | gro_result_t rc; | 521 | gro_result_t rc = GRO_NORMAL; |
496 | struct wil6210_priv *wil = ndev_to_wil(ndev); | 522 | struct wil6210_priv *wil = ndev_to_wil(ndev); |
523 | struct wireless_dev *wdev = wil_to_wdev(wil); | ||
497 | unsigned int len = skb->len; | 524 | unsigned int len = skb->len; |
498 | struct vring_rx_desc *d = wil_skb_rxdesc(skb); | 525 | struct vring_rx_desc *d = wil_skb_rxdesc(skb); |
499 | int cid = wil_rxdesc_cid(d); | 526 | int cid = wil_rxdesc_cid(d); /* always 0..7, no need to check */ |
527 | struct ethhdr *eth = (void *)skb->data; | ||
528 | /* here looking for DA, not A1, thus Rxdesc's 'mcast' indication | ||
529 | * is not suitable, need to look at data | ||
530 | */ | ||
531 | int mcast = is_multicast_ether_addr(eth->h_dest); | ||
500 | struct wil_net_stats *stats = &wil->sta[cid].stats; | 532 | struct wil_net_stats *stats = &wil->sta[cid].stats; |
533 | struct sk_buff *xmit_skb = NULL; | ||
534 | static const char * const gro_res_str[] = { | ||
535 | [GRO_MERGED] = "GRO_MERGED", | ||
536 | [GRO_MERGED_FREE] = "GRO_MERGED_FREE", | ||
537 | [GRO_HELD] = "GRO_HELD", | ||
538 | [GRO_NORMAL] = "GRO_NORMAL", | ||
539 | [GRO_DROP] = "GRO_DROP", | ||
540 | }; | ||
501 | 541 | ||
502 | skb_orphan(skb); | 542 | skb_orphan(skb); |
503 | 543 | ||
504 | rc = napi_gro_receive(&wil->napi_rx, skb); | 544 | if (wdev->iftype == NL80211_IFTYPE_AP && !wil->ap_isolate) { |
545 | if (mcast) { | ||
546 | /* send multicast frames both to higher layers in | ||
547 | * local net stack and back to the wireless medium | ||
548 | */ | ||
549 | xmit_skb = skb_copy(skb, GFP_ATOMIC); | ||
550 | } else { | ||
551 | int xmit_cid = wil_find_cid(wil, eth->h_dest); | ||
552 | |||
553 | if (xmit_cid >= 0) { | ||
554 | /* The destination station is associated to | ||
555 | * this AP (in this VLAN), so send the frame | ||
556 | * directly to it and do not pass it to local | ||
557 | * net stack. | ||
558 | */ | ||
559 | xmit_skb = skb; | ||
560 | skb = NULL; | ||
561 | } | ||
562 | } | ||
563 | } | ||
564 | if (xmit_skb) { | ||
565 | /* Send to wireless media and increase priority by 256 to | ||
566 | * keep the received priority instead of reclassifying | ||
567 | * the frame (see cfg80211_classify8021d). | ||
568 | */ | ||
569 | xmit_skb->dev = ndev; | ||
570 | xmit_skb->priority += 256; | ||
571 | xmit_skb->protocol = htons(ETH_P_802_3); | ||
572 | skb_reset_network_header(xmit_skb); | ||
573 | skb_reset_mac_header(xmit_skb); | ||
574 | wil_dbg_txrx(wil, "Rx -> Tx %d bytes\n", len); | ||
575 | dev_queue_xmit(xmit_skb); | ||
576 | } | ||
505 | 577 | ||
578 | if (skb) { /* deliver to local stack */ | ||
579 | |||
580 | skb->protocol = eth_type_trans(skb, ndev); | ||
581 | rc = napi_gro_receive(&wil->napi_rx, skb); | ||
582 | wil_dbg_txrx(wil, "Rx complete %d bytes => %s\n", | ||
583 | len, gro_res_str[rc]); | ||
584 | } | ||
585 | /* statistics. rc set to GRO_NORMAL for AP bridging */ | ||
506 | if (unlikely(rc == GRO_DROP)) { | 586 | if (unlikely(rc == GRO_DROP)) { |
507 | ndev->stats.rx_dropped++; | 587 | ndev->stats.rx_dropped++; |
508 | stats->rx_dropped++; | 588 | stats->rx_dropped++; |
@@ -512,17 +592,8 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) | |||
512 | stats->rx_packets++; | 592 | stats->rx_packets++; |
513 | ndev->stats.rx_bytes += len; | 593 | ndev->stats.rx_bytes += len; |
514 | stats->rx_bytes += len; | 594 | stats->rx_bytes += len; |
515 | } | 595 | if (mcast) |
516 | { | 596 | ndev->stats.multicast++; |
517 | static const char * const gro_res_str[] = { | ||
518 | [GRO_MERGED] = "GRO_MERGED", | ||
519 | [GRO_MERGED_FREE] = "GRO_MERGED_FREE", | ||
520 | [GRO_HELD] = "GRO_HELD", | ||
521 | [GRO_NORMAL] = "GRO_NORMAL", | ||
522 | [GRO_DROP] = "GRO_DROP", | ||
523 | }; | ||
524 | wil_dbg_txrx(wil, "Rx complete %d bytes => %s\n", | ||
525 | len, gro_res_str[rc]); | ||
526 | } | 597 | } |
527 | } | 598 | } |
528 | 599 | ||
@@ -553,7 +624,6 @@ void wil_rx_handle(struct wil6210_priv *wil, int *quota) | |||
553 | skb->protocol = htons(ETH_P_802_2); | 624 | skb->protocol = htons(ETH_P_802_2); |
554 | wil_netif_rx_any(skb, ndev); | 625 | wil_netif_rx_any(skb, ndev); |
555 | } else { | 626 | } else { |
556 | skb->protocol = eth_type_trans(skb, ndev); | ||
557 | wil_rx_reorder(wil, skb); | 627 | wil_rx_reorder(wil, skb); |
558 | } | 628 | } |
559 | } | 629 | } |
@@ -679,6 +749,72 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | |||
679 | return rc; | 749 | return rc; |
680 | } | 750 | } |
681 | 751 | ||
752 | int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size) | ||
753 | { | ||
754 | int rc; | ||
755 | struct wmi_bcast_vring_cfg_cmd cmd = { | ||
756 | .action = cpu_to_le32(WMI_VRING_CMD_ADD), | ||
757 | .vring_cfg = { | ||
758 | .tx_sw_ring = { | ||
759 | .max_mpdu_size = | ||
760 | cpu_to_le16(wil_mtu2macbuf(mtu_max)), | ||
761 | .ring_size = cpu_to_le16(size), | ||
762 | }, | ||
763 | .ringid = id, | ||
764 | .encap_trans_type = WMI_VRING_ENC_TYPE_802_3, | ||
765 | }, | ||
766 | }; | ||
767 | struct { | ||
768 | struct wil6210_mbox_hdr_wmi wmi; | ||
769 | struct wmi_vring_cfg_done_event cmd; | ||
770 | } __packed reply; | ||
771 | struct vring *vring = &wil->vring_tx[id]; | ||
772 | struct vring_tx_data *txdata = &wil->vring_tx_data[id]; | ||
773 | |||
774 | wil_dbg_misc(wil, "%s() max_mpdu_size %d\n", __func__, | ||
775 | cmd.vring_cfg.tx_sw_ring.max_mpdu_size); | ||
776 | |||
777 | if (vring->va) { | ||
778 | wil_err(wil, "Tx ring [%d] already allocated\n", id); | ||
779 | rc = -EINVAL; | ||
780 | goto out; | ||
781 | } | ||
782 | |||
783 | memset(txdata, 0, sizeof(*txdata)); | ||
784 | spin_lock_init(&txdata->lock); | ||
785 | vring->size = size; | ||
786 | rc = wil_vring_alloc(wil, vring); | ||
787 | if (rc) | ||
788 | goto out; | ||
789 | |||
790 | wil->vring2cid_tid[id][0] = WIL6210_MAX_CID; /* CID */ | ||
791 | wil->vring2cid_tid[id][1] = 0; /* TID */ | ||
792 | |||
793 | cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); | ||
794 | |||
795 | rc = wmi_call(wil, WMI_BCAST_VRING_CFG_CMDID, &cmd, sizeof(cmd), | ||
796 | WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100); | ||
797 | if (rc) | ||
798 | goto out_free; | ||
799 | |||
800 | if (reply.cmd.status != WMI_FW_STATUS_SUCCESS) { | ||
801 | wil_err(wil, "Tx config failed, status 0x%02x\n", | ||
802 | reply.cmd.status); | ||
803 | rc = -EINVAL; | ||
804 | goto out_free; | ||
805 | } | ||
806 | vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr); | ||
807 | |||
808 | txdata->enabled = 1; | ||
809 | |||
810 | return 0; | ||
811 | out_free: | ||
812 | wil_vring_free(wil, vring, 1); | ||
813 | out: | ||
814 | |||
815 | return rc; | ||
816 | } | ||
817 | |||
682 | void wil_vring_fini_tx(struct wil6210_priv *wil, int id) | 818 | void wil_vring_fini_tx(struct wil6210_priv *wil, int id) |
683 | { | 819 | { |
684 | struct vring *vring = &wil->vring_tx[id]; | 820 | struct vring *vring = &wil->vring_tx[id]; |
@@ -702,7 +838,7 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id) | |||
702 | memset(txdata, 0, sizeof(*txdata)); | 838 | memset(txdata, 0, sizeof(*txdata)); |
703 | } | 839 | } |
704 | 840 | ||
705 | static struct vring *wil_find_tx_vring(struct wil6210_priv *wil, | 841 | static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil, |
706 | struct sk_buff *skb) | 842 | struct sk_buff *skb) |
707 | { | 843 | { |
708 | int i; | 844 | int i; |
@@ -735,15 +871,6 @@ static struct vring *wil_find_tx_vring(struct wil6210_priv *wil, | |||
735 | return NULL; | 871 | return NULL; |
736 | } | 872 | } |
737 | 873 | ||
738 | static void wil_set_da_for_vring(struct wil6210_priv *wil, | ||
739 | struct sk_buff *skb, int vring_index) | ||
740 | { | ||
741 | struct ethhdr *eth = (void *)skb->data; | ||
742 | int cid = wil->vring2cid_tid[vring_index][0]; | ||
743 | |||
744 | memcpy(eth->h_dest, wil->sta[cid].addr, ETH_ALEN); | ||
745 | } | ||
746 | |||
747 | static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | 874 | static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, |
748 | struct sk_buff *skb); | 875 | struct sk_buff *skb); |
749 | 876 | ||
@@ -764,6 +891,9 @@ static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil, | |||
764 | continue; | 891 | continue; |
765 | 892 | ||
766 | cid = wil->vring2cid_tid[i][0]; | 893 | cid = wil->vring2cid_tid[i][0]; |
894 | if (cid >= WIL6210_MAX_CID) /* skip BCAST */ | ||
895 | continue; | ||
896 | |||
767 | if (!wil->sta[cid].data_port_open && | 897 | if (!wil->sta[cid].data_port_open && |
768 | (skb->protocol != cpu_to_be16(ETH_P_PAE))) | 898 | (skb->protocol != cpu_to_be16(ETH_P_PAE))) |
769 | break; | 899 | break; |
@@ -778,17 +908,51 @@ static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil, | |||
778 | return NULL; | 908 | return NULL; |
779 | } | 909 | } |
780 | 910 | ||
781 | /* | 911 | /* Use one of 2 strategies: |
782 | * Find 1-st vring and return it; set dest address for this vring in skb | 912 | * |
783 | * duplicate skb and send it to other active vrings | 913 | * 1. New (real broadcast): |
914 | * use dedicated broadcast vring | ||
915 | * 2. Old (pseudo-DMS): | ||
916 | * Find 1-st vring and return it; | ||
917 | * duplicate skb and send it to other active vrings; | ||
918 | * in all cases override dest address to unicast peer's address | ||
919 | * Use old strategy when new is not supported yet: | ||
920 | * - for PBSS | ||
921 | * - for secure link | ||
784 | */ | 922 | */ |
785 | static struct vring *wil_tx_bcast(struct wil6210_priv *wil, | 923 | static struct vring *wil_find_tx_bcast_1(struct wil6210_priv *wil, |
786 | struct sk_buff *skb) | 924 | struct sk_buff *skb) |
925 | { | ||
926 | struct vring *v; | ||
927 | int i = wil->bcast_vring; | ||
928 | |||
929 | if (i < 0) | ||
930 | return NULL; | ||
931 | v = &wil->vring_tx[i]; | ||
932 | if (!v->va) | ||
933 | return NULL; | ||
934 | |||
935 | return v; | ||
936 | } | ||
937 | |||
938 | static void wil_set_da_for_vring(struct wil6210_priv *wil, | ||
939 | struct sk_buff *skb, int vring_index) | ||
940 | { | ||
941 | struct ethhdr *eth = (void *)skb->data; | ||
942 | int cid = wil->vring2cid_tid[vring_index][0]; | ||
943 | |||
944 | ether_addr_copy(eth->h_dest, wil->sta[cid].addr); | ||
945 | } | ||
946 | |||
947 | static struct vring *wil_find_tx_bcast_2(struct wil6210_priv *wil, | ||
948 | struct sk_buff *skb) | ||
787 | { | 949 | { |
788 | struct vring *v, *v2; | 950 | struct vring *v, *v2; |
789 | struct sk_buff *skb2; | 951 | struct sk_buff *skb2; |
790 | int i; | 952 | int i; |
791 | u8 cid; | 953 | u8 cid; |
954 | struct ethhdr *eth = (void *)skb->data; | ||
955 | char *src = eth->h_source; | ||
792 | 956 | ||
793 | /* find 1-st vring eligible for data */ | 957 | /* find 1-st vring eligible for data */ |
794 | for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { | 958 | for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { |
@@ -797,9 +961,15 @@ static struct vring *wil_tx_bcast(struct wil6210_priv *wil, | |||
797 | continue; | 961 | continue; |
798 | 962 | ||
799 | cid = wil->vring2cid_tid[i][0]; | 963 | cid = wil->vring2cid_tid[i][0]; |
964 | if (cid >= WIL6210_MAX_CID) /* skip BCAST */ | ||
965 | continue; | ||
800 | if (!wil->sta[cid].data_port_open) | 966 | if (!wil->sta[cid].data_port_open) |
801 | continue; | 967 | continue; |
802 | 968 | ||
969 | /* don't Tx back to source when re-routing Rx->Tx at the AP */ | ||
970 | if (0 == memcmp(wil->sta[cid].addr, src, ETH_ALEN)) | ||
971 | continue; | ||
972 | |||
803 | goto found; | 973 | goto found; |
804 | } | 974 | } |
805 | 975 | ||
@@ -817,9 +987,14 @@ found: | |||
817 | if (!v2->va) | 987 | if (!v2->va) |
818 | continue; | 988 | continue; |
819 | cid = wil->vring2cid_tid[i][0]; | 989 | cid = wil->vring2cid_tid[i][0]; |
990 | if (cid >= WIL6210_MAX_CID) /* skip BCAST */ | ||
991 | continue; | ||
820 | if (!wil->sta[cid].data_port_open) | 992 | if (!wil->sta[cid].data_port_open) |
821 | continue; | 993 | continue; |
822 | 994 | ||
995 | if (0 == memcmp(wil->sta[cid].addr, src, ETH_ALEN)) | ||
996 | continue; | ||
997 | |||
823 | skb2 = skb_copy(skb, GFP_ATOMIC); | 998 | skb2 = skb_copy(skb, GFP_ATOMIC); |
824 | if (skb2) { | 999 | if (skb2) { |
825 | wil_dbg_txrx(wil, "BCAST DUP -> ring %d\n", i); | 1000 | wil_dbg_txrx(wil, "BCAST DUP -> ring %d\n", i); |
@@ -833,6 +1008,20 @@ found: | |||
833 | return v; | 1008 | return v; |
834 | } | 1009 | } |
835 | 1010 | ||
1011 | static struct vring *wil_find_tx_bcast(struct wil6210_priv *wil, | ||
1012 | struct sk_buff *skb) | ||
1013 | { | ||
1014 | struct wireless_dev *wdev = wil->wdev; | ||
1015 | |||
1016 | if (wdev->iftype != NL80211_IFTYPE_AP) | ||
1017 | return wil_find_tx_bcast_2(wil, skb); | ||
1018 | |||
1019 | if (wil->privacy) | ||
1020 | return wil_find_tx_bcast_2(wil, skb); | ||
1021 | |||
1022 | return wil_find_tx_bcast_1(wil, skb); | ||
1023 | } | ||
1024 | |||
836 | static int wil_tx_desc_map(struct vring_tx_desc *d, dma_addr_t pa, u32 len, | 1025 | static int wil_tx_desc_map(struct vring_tx_desc *d, dma_addr_t pa, u32 len, |
837 | int vring_index) | 1026 | int vring_index) |
838 | { | 1027 | { |
@@ -925,6 +1114,8 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
925 | uint i = swhead; | 1114 | uint i = swhead; |
926 | dma_addr_t pa; | 1115 | dma_addr_t pa; |
927 | int used; | 1116 | int used; |
1117 | bool mcast = (vring_index == wil->bcast_vring); | ||
1118 | uint len = skb_headlen(skb); | ||
928 | 1119 | ||
929 | wil_dbg_txrx(wil, "%s()\n", __func__); | 1120 | wil_dbg_txrx(wil, "%s()\n", __func__); |
930 | 1121 | ||
@@ -950,7 +1141,17 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
950 | return -EINVAL; | 1141 | return -EINVAL; |
951 | vring->ctx[i].mapped_as = wil_mapped_as_single; | 1142 | vring->ctx[i].mapped_as = wil_mapped_as_single; |
952 | /* 1-st segment */ | 1143 | /* 1-st segment */ |
953 | wil_tx_desc_map(d, pa, skb_headlen(skb), vring_index); | 1144 | wil_tx_desc_map(d, pa, len, vring_index); |
1145 | if (unlikely(mcast)) { | ||
1146 | d->mac.d[0] |= BIT(MAC_CFG_DESC_TX_0_MCS_EN_POS); /* MCS 0 */ | ||
1147 | if (unlikely(len > WIL_BCAST_MCS0_LIMIT)) { | ||
1148 | /* set MCS 1 */ | ||
1149 | d->mac.d[0] |= (1 << MAC_CFG_DESC_TX_0_MCS_INDEX_POS); | ||
1150 | /* packet mode 2 */ | ||
1151 | d->mac.d[1] |= BIT(MAC_CFG_DESC_TX_1_PKT_MODE_EN_POS) | | ||
1152 | (2 << MAC_CFG_DESC_TX_1_PKT_MODE_POS); | ||
1153 | } | ||
1154 | } | ||
954 | /* Process TCP/UDP checksum offloading */ | 1155 | /* Process TCP/UDP checksum offloading */ |
955 | if (unlikely(wil_tx_desc_offload_cksum_set(wil, d, skb))) { | 1156 | if (unlikely(wil_tx_desc_offload_cksum_set(wil, d, skb))) { |
956 | wil_err(wil, "Tx[%2d] Failed to set cksum, drop packet\n", | 1157 | wil_err(wil, "Tx[%2d] Failed to set cksum, drop packet\n", |
@@ -1056,6 +1257,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
1056 | { | 1257 | { |
1057 | struct wil6210_priv *wil = ndev_to_wil(ndev); | 1258 | struct wil6210_priv *wil = ndev_to_wil(ndev); |
1058 | struct ethhdr *eth = (void *)skb->data; | 1259 | struct ethhdr *eth = (void *)skb->data; |
1260 | bool bcast = is_multicast_ether_addr(eth->h_dest); | ||
1059 | struct vring *vring; | 1261 | struct vring *vring; |
1060 | static bool pr_once_fw; | 1262 | static bool pr_once_fw; |
1061 | int rc; | 1263 | int rc; |
@@ -1083,10 +1285,8 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
1083 | /* in STA mode (ESS), all to same VRING */ | 1285 | /* in STA mode (ESS), all to same VRING */ |
1084 | vring = wil_find_tx_vring_sta(wil, skb); | 1286 | vring = wil_find_tx_vring_sta(wil, skb); |
1085 | } else { /* direct communication, find matching VRING */ | 1287 | } else { /* direct communication, find matching VRING */ |
1086 | if (is_unicast_ether_addr(eth->h_dest)) | 1288 | vring = bcast ? wil_find_tx_bcast(wil, skb) : |
1087 | vring = wil_find_tx_vring(wil, skb); | 1289 | wil_find_tx_ucast(wil, skb); |
1088 | else | ||
1089 | vring = wil_tx_bcast(wil, skb); | ||
1090 | } | 1290 | } |
1091 | if (unlikely(!vring)) { | 1291 | if (unlikely(!vring)) { |
1092 | wil_dbg_txrx(wil, "No Tx VRING found for %pM\n", eth->h_dest); | 1292 | wil_dbg_txrx(wil, "No Tx VRING found for %pM\n", eth->h_dest); |
@@ -1149,7 +1349,7 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid) | |||
1149 | struct vring_tx_data *txdata = &wil->vring_tx_data[ringid]; | 1349 | struct vring_tx_data *txdata = &wil->vring_tx_data[ringid]; |
1150 | int done = 0; | 1350 | int done = 0; |
1151 | int cid = wil->vring2cid_tid[ringid][0]; | 1351 | int cid = wil->vring2cid_tid[ringid][0]; |
1152 | struct wil_net_stats *stats = &wil->sta[cid].stats; | 1352 | struct wil_net_stats *stats = NULL; |
1153 | volatile struct vring_tx_desc *_d; | 1353 | volatile struct vring_tx_desc *_d; |
1154 | int used_before_complete; | 1354 | int used_before_complete; |
1155 | int used_new; | 1355 | int used_new; |
@@ -1168,6 +1368,9 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid) | |||
1168 | 1368 | ||
1169 | used_before_complete = wil_vring_used_tx(vring); | 1369 | used_before_complete = wil_vring_used_tx(vring); |
1170 | 1370 | ||
1371 | if (cid < WIL6210_MAX_CID) | ||
1372 | stats = &wil->sta[cid].stats; | ||
1373 | |||
1171 | while (!wil_vring_is_empty(vring)) { | 1374 | while (!wil_vring_is_empty(vring)) { |
1172 | int new_swtail; | 1375 | int new_swtail; |
1173 | struct wil_ctx *ctx = &vring->ctx[vring->swtail]; | 1376 | struct wil_ctx *ctx = &vring->ctx[vring->swtail]; |
@@ -1209,12 +1412,15 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid) | |||
1209 | if (skb) { | 1412 | if (skb) { |
1210 | if (likely(d->dma.error == 0)) { | 1413 | if (likely(d->dma.error == 0)) { |
1211 | ndev->stats.tx_packets++; | 1414 | ndev->stats.tx_packets++; |
1212 | stats->tx_packets++; | ||
1213 | ndev->stats.tx_bytes += skb->len; | 1415 | ndev->stats.tx_bytes += skb->len; |
1214 | stats->tx_bytes += skb->len; | 1416 | if (stats) { |
1417 | stats->tx_packets++; | ||
1418 | stats->tx_bytes += skb->len; | ||
1419 | } | ||
1215 | } else { | 1420 | } else { |
1216 | ndev->stats.tx_errors++; | 1421 | ndev->stats.tx_errors++; |
1217 | stats->tx_errors++; | 1422 | if (stats) |
1423 | stats->tx_errors++; | ||
1218 | } | 1424 | } |
1219 | wil_consume_skb(skb, d->dma.error == 0); | 1425 | wil_consume_skb(skb, d->dma.error == 0); |
1220 | } | 1426 | } |
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index b6e65c37d410..4310972c9e16 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h | |||
@@ -28,6 +28,7 @@ extern unsigned int mtu_max; | |||
28 | extern unsigned short rx_ring_overflow_thrsh; | 28 | extern unsigned short rx_ring_overflow_thrsh; |
29 | extern int agg_wsize; | 29 | extern int agg_wsize; |
30 | extern u32 vring_idle_trsh; | 30 | extern u32 vring_idle_trsh; |
31 | extern bool rx_align_2; | ||
31 | 32 | ||
32 | #define WIL_NAME "wil6210" | 33 | #define WIL_NAME "wil6210" |
33 | #define WIL_FW_NAME "wil6210.fw" /* code */ | 34 | #define WIL_FW_NAME "wil6210.fw" /* code */ |
@@ -49,6 +50,8 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1) | |||
49 | #define WIL_TX_Q_LEN_DEFAULT (4000) | 50 | #define WIL_TX_Q_LEN_DEFAULT (4000) |
50 | #define WIL_RX_RING_SIZE_ORDER_DEFAULT (10) | 51 | #define WIL_RX_RING_SIZE_ORDER_DEFAULT (10) |
51 | #define WIL_TX_RING_SIZE_ORDER_DEFAULT (10) | 52 | #define WIL_TX_RING_SIZE_ORDER_DEFAULT (10) |
53 | #define WIL_BCAST_RING_SIZE_ORDER_DEFAULT (7) | ||
54 | #define WIL_BCAST_MCS0_LIMIT (1024) /* limit for MCS0 frame size */ | ||
52 | /* limit ring size in range [32..32k] */ | 55 | /* limit ring size in range [32..32k] */ |
53 | #define WIL_RING_SIZE_ORDER_MIN (5) | 56 | #define WIL_RING_SIZE_ORDER_MIN (5) |
54 | #define WIL_RING_SIZE_ORDER_MAX (15) | 57 | #define WIL_RING_SIZE_ORDER_MAX (15) |
@@ -542,6 +545,7 @@ struct wil6210_priv { | |||
542 | u32 monitor_flags; | 545 | u32 monitor_flags; |
543 | u32 privacy; /* secure connection? */ | 546 | u32 privacy; /* secure connection? */ |
544 | int sinfo_gen; | 547 | int sinfo_gen; |
548 | u32 ap_isolate; /* no intra-BSS communication */ | ||
545 | /* interrupt moderation */ | 549 | /* interrupt moderation */ |
546 | u32 tx_max_burst_duration; | 550 | u32 tx_max_burst_duration; |
547 | u32 tx_interframe_timeout; | 551 | u32 tx_interframe_timeout; |
@@ -593,6 +597,7 @@ struct wil6210_priv { | |||
593 | struct vring_tx_data vring_tx_data[WIL6210_MAX_TX_RINGS]; | 597 | struct vring_tx_data vring_tx_data[WIL6210_MAX_TX_RINGS]; |
594 | u8 vring2cid_tid[WIL6210_MAX_TX_RINGS][2]; /* [0] - CID, [1] - TID */ | 598 | u8 vring2cid_tid[WIL6210_MAX_TX_RINGS][2]; /* [0] - CID, [1] - TID */ |
595 | struct wil_sta_info sta[WIL6210_MAX_CID]; | 599 | struct wil_sta_info sta[WIL6210_MAX_CID]; |
600 | int bcast_vring; | ||
596 | /* scan */ | 601 | /* scan */ |
597 | struct cfg80211_scan_request *scan_request; | 602 | struct cfg80211_scan_request *scan_request; |
598 | 603 | ||
@@ -755,6 +760,9 @@ void wil_rx_fini(struct wil6210_priv *wil); | |||
755 | int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | 760 | int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, |
756 | int cid, int tid); | 761 | int cid, int tid); |
757 | void wil_vring_fini_tx(struct wil6210_priv *wil, int id); | 762 | void wil_vring_fini_tx(struct wil6210_priv *wil, int id); |
763 | int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size); | ||
764 | int wil_bcast_init(struct wil6210_priv *wil); | ||
765 | void wil_bcast_fini(struct wil6210_priv *wil); | ||
758 | 766 | ||
759 | netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev); | 767 | netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev); |
760 | int wil_tx_complete(struct wil6210_priv *wil, int ringid); | 768 | int wil_tx_complete(struct wil6210_priv *wil, int ringid); |
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 021313524913..9fe2085be2c5 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c | |||
@@ -466,7 +466,7 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) | |||
466 | 466 | ||
467 | /* FIXME FW can transmit only ucast frames to peer */ | 467 | /* FIXME FW can transmit only ucast frames to peer */ |
468 | /* FIXME real ring_id instead of hard coded 0 */ | 468 | /* FIXME real ring_id instead of hard coded 0 */ |
469 | memcpy(wil->sta[evt->cid].addr, evt->bssid, ETH_ALEN); | 469 | ether_addr_copy(wil->sta[evt->cid].addr, evt->bssid); |
470 | wil->sta[evt->cid].status = wil_sta_conn_pending; | 470 | wil->sta[evt->cid].status = wil_sta_conn_pending; |
471 | 471 | ||
472 | wil->pending_connect_cid = evt->cid; | 472 | wil->pending_connect_cid = evt->cid; |
@@ -524,8 +524,8 @@ static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id, | |||
524 | } | 524 | } |
525 | 525 | ||
526 | eth = (struct ethhdr *)skb_put(skb, ETH_HLEN); | 526 | eth = (struct ethhdr *)skb_put(skb, ETH_HLEN); |
527 | memcpy(eth->h_dest, ndev->dev_addr, ETH_ALEN); | 527 | ether_addr_copy(eth->h_dest, ndev->dev_addr); |
528 | memcpy(eth->h_source, evt->src_mac, ETH_ALEN); | 528 | ether_addr_copy(eth->h_source, evt->src_mac); |
529 | eth->h_proto = cpu_to_be16(ETH_P_PAE); | 529 | eth->h_proto = cpu_to_be16(ETH_P_PAE); |
530 | memcpy(skb_put(skb, eapol_len), evt->eapol, eapol_len); | 530 | memcpy(skb_put(skb, eapol_len), evt->eapol, eapol_len); |
531 | skb->protocol = eth_type_trans(skb, ndev); | 531 | skb->protocol = eth_type_trans(skb, ndev); |
@@ -851,7 +851,7 @@ int wmi_set_mac_address(struct wil6210_priv *wil, void *addr) | |||
851 | { | 851 | { |
852 | struct wmi_set_mac_address_cmd cmd; | 852 | struct wmi_set_mac_address_cmd cmd; |
853 | 853 | ||
854 | memcpy(cmd.mac, addr, ETH_ALEN); | 854 | ether_addr_copy(cmd.mac, addr); |
855 | 855 | ||
856 | wil_dbg_wmi(wil, "Set MAC %pM\n", addr); | 856 | wil_dbg_wmi(wil, "Set MAC %pM\n", addr); |
857 | 857 | ||
@@ -1109,6 +1109,11 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) | |||
1109 | */ | 1109 | */ |
1110 | cmd.l3_l4_ctrl |= (1 << L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS); | 1110 | cmd.l3_l4_ctrl |= (1 << L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS); |
1111 | } | 1111 | } |
1112 | |||
1113 | if (rx_align_2) | ||
1114 | cmd.l2_802_3_offload_ctrl |= | ||
1115 | L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_MSK; | ||
1116 | |||
1112 | /* typical time for secure PCP is 840ms */ | 1117 | /* typical time for secure PCP is 840ms */ |
1113 | rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd), | 1118 | rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd), |
1114 | WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000); | 1119 | WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000); |
@@ -1157,7 +1162,8 @@ int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason) | |||
1157 | struct wmi_disconnect_sta_cmd cmd = { | 1162 | struct wmi_disconnect_sta_cmd cmd = { |
1158 | .disconnect_reason = cpu_to_le16(reason), | 1163 | .disconnect_reason = cpu_to_le16(reason), |
1159 | }; | 1164 | }; |
1160 | memcpy(cmd.dst_mac, mac, ETH_ALEN); | 1165 | |
1166 | ether_addr_copy(cmd.dst_mac, mac); | ||
1161 | 1167 | ||
1162 | wil_dbg_wmi(wil, "%s(%pM, reason %d)\n", __func__, mac, reason); | 1168 | wil_dbg_wmi(wil, "%s(%pM, reason %d)\n", __func__, mac, reason); |
1163 | 1169 | ||
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h index 8a4af613e191..b29055315350 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.h +++ b/drivers/net/wireless/ath/wil6210/wmi.h | |||
@@ -70,7 +70,6 @@ enum wmi_command_id { | |||
70 | WMI_SET_UCODE_IDLE_CMDID = 0x0813, | 70 | WMI_SET_UCODE_IDLE_CMDID = 0x0813, |
71 | WMI_SET_WORK_MODE_CMDID = 0x0815, | 71 | WMI_SET_WORK_MODE_CMDID = 0x0815, |
72 | WMI_LO_LEAKAGE_CALIB_CMDID = 0x0816, | 72 | WMI_LO_LEAKAGE_CALIB_CMDID = 0x0816, |
73 | WMI_MARLON_R_ACTIVATE_CMDID = 0x0817, | ||
74 | WMI_MARLON_R_READ_CMDID = 0x0818, | 73 | WMI_MARLON_R_READ_CMDID = 0x0818, |
75 | WMI_MARLON_R_WRITE_CMDID = 0x0819, | 74 | WMI_MARLON_R_WRITE_CMDID = 0x0819, |
76 | WMI_MARLON_R_TXRX_SEL_CMDID = 0x081a, | 75 | WMI_MARLON_R_TXRX_SEL_CMDID = 0x081a, |
@@ -80,6 +79,7 @@ enum wmi_command_id { | |||
80 | WMI_RF_RX_TEST_CMDID = 0x081e, | 79 | WMI_RF_RX_TEST_CMDID = 0x081e, |
81 | WMI_CFG_RX_CHAIN_CMDID = 0x0820, | 80 | WMI_CFG_RX_CHAIN_CMDID = 0x0820, |
82 | WMI_VRING_CFG_CMDID = 0x0821, | 81 | WMI_VRING_CFG_CMDID = 0x0821, |
82 | WMI_BCAST_VRING_CFG_CMDID = 0x0822, | ||
83 | WMI_VRING_BA_EN_CMDID = 0x0823, | 83 | WMI_VRING_BA_EN_CMDID = 0x0823, |
84 | WMI_VRING_BA_DIS_CMDID = 0x0824, | 84 | WMI_VRING_BA_DIS_CMDID = 0x0824, |
85 | WMI_RCP_ADDBA_RESP_CMDID = 0x0825, | 85 | WMI_RCP_ADDBA_RESP_CMDID = 0x0825, |
@@ -99,6 +99,7 @@ enum wmi_command_id { | |||
99 | WMI_BF_TXSS_MGMT_CMDID = 0x0837, | 99 | WMI_BF_TXSS_MGMT_CMDID = 0x0837, |
100 | WMI_BF_SM_MGMT_CMDID = 0x0838, | 100 | WMI_BF_SM_MGMT_CMDID = 0x0838, |
101 | WMI_BF_RXSS_MGMT_CMDID = 0x0839, | 101 | WMI_BF_RXSS_MGMT_CMDID = 0x0839, |
102 | WMI_BF_TRIG_CMDID = 0x083A, | ||
102 | WMI_SET_SECTORS_CMDID = 0x0849, | 103 | WMI_SET_SECTORS_CMDID = 0x0849, |
103 | WMI_MAINTAIN_PAUSE_CMDID = 0x0850, | 104 | WMI_MAINTAIN_PAUSE_CMDID = 0x0850, |
104 | WMI_MAINTAIN_RESUME_CMDID = 0x0851, | 105 | WMI_MAINTAIN_RESUME_CMDID = 0x0851, |
@@ -596,6 +597,22 @@ struct wmi_vring_cfg_cmd { | |||
596 | } __packed; | 597 | } __packed; |
597 | 598 | ||
598 | /* | 599 | /* |
600 | * WMI_BCAST_VRING_CFG_CMDID | ||
601 | */ | ||
602 | struct wmi_bcast_vring_cfg { | ||
603 | struct wmi_sw_ring_cfg tx_sw_ring; | ||
604 | u8 ringid; /* 0-23 vrings */ | ||
605 | u8 encap_trans_type; | ||
606 | u8 ds_cfg; /* 802.3 DS cfg */ | ||
607 | u8 nwifi_ds_trans_type; | ||
608 | } __packed; | ||
609 | |||
610 | struct wmi_bcast_vring_cfg_cmd { | ||
611 | __le32 action; | ||
612 | struct wmi_bcast_vring_cfg vring_cfg; | ||
613 | } __packed; | ||
614 | |||
615 | /* | ||
599 | * WMI_VRING_BA_EN_CMDID | 616 | * WMI_VRING_BA_EN_CMDID |
600 | */ | 617 | */ |
601 | struct wmi_vring_ba_en_cmd { | 618 | struct wmi_vring_ba_en_cmd { |
@@ -687,6 +704,9 @@ struct wmi_cfg_rx_chain_cmd { | |||
687 | #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_POS (0) | 704 | #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_POS (0) |
688 | #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_LEN (1) | 705 | #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_LEN (1) |
689 | #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_MSK (0x1) | 706 | #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_MSK (0x1) |
707 | #define L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_POS (1) | ||
708 | #define L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_LEN (1) | ||
709 | #define L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_MSK (0x2) | ||
690 | u8 l2_802_3_offload_ctrl; | 710 | u8 l2_802_3_offload_ctrl; |
691 | 711 | ||
692 | #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_POS (0) | 712 | #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_POS (0) |
@@ -841,7 +861,6 @@ enum wmi_event_id { | |||
841 | WMI_IQ_RX_CALIB_DONE_EVENTID = 0x1812, | 861 | WMI_IQ_RX_CALIB_DONE_EVENTID = 0x1812, |
842 | WMI_SET_WORK_MODE_DONE_EVENTID = 0x1815, | 862 | WMI_SET_WORK_MODE_DONE_EVENTID = 0x1815, |
843 | WMI_LO_LEAKAGE_CALIB_DONE_EVENTID = 0x1816, | 863 | WMI_LO_LEAKAGE_CALIB_DONE_EVENTID = 0x1816, |
844 | WMI_MARLON_R_ACTIVATE_DONE_EVENTID = 0x1817, | ||
845 | WMI_MARLON_R_READ_DONE_EVENTID = 0x1818, | 864 | WMI_MARLON_R_READ_DONE_EVENTID = 0x1818, |
846 | WMI_MARLON_R_WRITE_DONE_EVENTID = 0x1819, | 865 | WMI_MARLON_R_WRITE_DONE_EVENTID = 0x1819, |
847 | WMI_MARLON_R_TXRX_SEL_DONE_EVENTID = 0x181a, | 866 | WMI_MARLON_R_TXRX_SEL_DONE_EVENTID = 0x181a, |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index ea4843be773c..b2f9521fe551 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -4866,7 +4866,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev) | |||
4866 | switch (dev->dev->bus_type) { | 4866 | switch (dev->dev->bus_type) { |
4867 | #ifdef CONFIG_B43_BCMA | 4867 | #ifdef CONFIG_B43_BCMA |
4868 | case B43_BUS_BCMA: | 4868 | case B43_BUS_BCMA: |
4869 | bcma_core_pci_irq_ctl(dev->dev->bdev->bus, | 4869 | bcma_host_pci_irq_ctl(dev->dev->bdev->bus, |
4870 | dev->dev->bdev, true); | 4870 | dev->dev->bdev, true); |
4871 | bcma_host_pci_up(dev->dev->bdev->bus); | 4871 | bcma_host_pci_up(dev->dev->bdev->bus); |
4872 | break; | 4872 | break; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index c438ccdb6ed8..9b508bd3b839 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/mmc/host.h> | 29 | #include <linux/mmc/host.h> |
30 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
31 | #include <linux/platform_data/brcmfmac-sdio.h> | 31 | #include <linux/platform_data/brcmfmac-sdio.h> |
32 | #include <linux/pm_runtime.h> | ||
32 | #include <linux/suspend.h> | 33 | #include <linux/suspend.h> |
33 | #include <linux/errno.h> | 34 | #include <linux/errno.h> |
34 | #include <linux/module.h> | 35 | #include <linux/module.h> |
@@ -1006,6 +1007,7 @@ static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev) | |||
1006 | sg_free_table(&sdiodev->sgtable); | 1007 | sg_free_table(&sdiodev->sgtable); |
1007 | sdiodev->sbwad = 0; | 1008 | sdiodev->sbwad = 0; |
1008 | 1009 | ||
1010 | pm_runtime_allow(sdiodev->func[1]->card->host->parent); | ||
1009 | return 0; | 1011 | return 0; |
1010 | } | 1012 | } |
1011 | 1013 | ||
@@ -1074,7 +1076,7 @@ static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev) | |||
1074 | ret = -ENODEV; | 1076 | ret = -ENODEV; |
1075 | goto out; | 1077 | goto out; |
1076 | } | 1078 | } |
1077 | 1079 | pm_runtime_forbid(host->parent); | |
1078 | out: | 1080 | out: |
1079 | if (ret) | 1081 | if (ret) |
1080 | brcmf_sdiod_remove(sdiodev); | 1082 | brcmf_sdiod_remove(sdiodev); |
@@ -1096,6 +1098,8 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = { | |||
1096 | BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43341), | 1098 | BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43341), |
1097 | BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43362), | 1099 | BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43362), |
1098 | BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4335_4339), | 1100 | BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4335_4339), |
1101 | BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43430), | ||
1102 | BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4345), | ||
1099 | BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354), | 1103 | BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354), |
1100 | { /* end: all zeroes */ } | 1104 | { /* end: all zeroes */ } |
1101 | }; | 1105 | }; |
@@ -1194,7 +1198,7 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func) | |||
1194 | brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device); | 1198 | brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device); |
1195 | brcmf_dbg(SDIO, "Function: %d\n", func->num); | 1199 | brcmf_dbg(SDIO, "Function: %d\n", func->num); |
1196 | 1200 | ||
1197 | if (func->num != 1 && func->num != 2) | 1201 | if (func->num != 1) |
1198 | return; | 1202 | return; |
1199 | 1203 | ||
1200 | bus_if = dev_get_drvdata(&func->dev); | 1204 | bus_if = dev_get_drvdata(&func->dev); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/brcm80211/brcmfmac/chip.c index 04d2ca0d87d6..ab2fac8b2760 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c | |||
@@ -100,9 +100,6 @@ | |||
100 | #define BCM4329_CORE_SOCRAM_BASE 0x18003000 | 100 | #define BCM4329_CORE_SOCRAM_BASE 0x18003000 |
101 | /* ARM Cortex M3 core, ID 0x82a */ | 101 | /* ARM Cortex M3 core, ID 0x82a */ |
102 | #define BCM4329_CORE_ARM_BASE 0x18002000 | 102 | #define BCM4329_CORE_ARM_BASE 0x18002000 |
103 | #define BCM4329_RAMSIZE 0x48000 | ||
104 | /* bcm43143 */ | ||
105 | #define BCM43143_RAMSIZE 0x70000 | ||
106 | 103 | ||
107 | #define CORE_SB(base, field) \ | 104 | #define CORE_SB(base, field) \ |
108 | (base + SBCONFIGOFF + offsetof(struct sbconfig, field)) | 105 | (base + SBCONFIGOFF + offsetof(struct sbconfig, field)) |
@@ -150,6 +147,78 @@ struct sbconfig { | |||
150 | u32 sbidhigh; /* identification */ | 147 | u32 sbidhigh; /* identification */ |
151 | }; | 148 | }; |
152 | 149 | ||
150 | /* bankidx and bankinfo reg defines corerev >= 8 */ | ||
151 | #define SOCRAM_BANKINFO_RETNTRAM_MASK 0x00010000 | ||
152 | #define SOCRAM_BANKINFO_SZMASK 0x0000007f | ||
153 | #define SOCRAM_BANKIDX_ROM_MASK 0x00000100 | ||
154 | |||
155 | #define SOCRAM_BANKIDX_MEMTYPE_SHIFT 8 | ||
156 | /* socram bankinfo memtype */ | ||
157 | #define SOCRAM_MEMTYPE_RAM 0 | ||
158 | #define SOCRAM_MEMTYPE_R0M 1 | ||
159 | #define SOCRAM_MEMTYPE_DEVRAM 2 | ||
160 | |||
161 | #define SOCRAM_BANKINFO_SZBASE 8192 | ||
162 | #define SRCI_LSS_MASK 0x00f00000 | ||
163 | #define SRCI_LSS_SHIFT 20 | ||
164 | #define SRCI_SRNB_MASK 0xf0 | ||
165 | #define SRCI_SRNB_SHIFT 4 | ||
166 | #define SRCI_SRBSZ_MASK 0xf | ||
167 | #define SRCI_SRBSZ_SHIFT 0 | ||
168 | #define SR_BSZ_BASE 14 | ||
169 | |||
170 | struct sbsocramregs { | ||
171 | u32 coreinfo; | ||
172 | u32 bwalloc; | ||
173 | u32 extracoreinfo; | ||
174 | u32 biststat; | ||
175 | u32 bankidx; | ||
176 | u32 standbyctrl; | ||
177 | |||
178 | u32 errlogstatus; /* rev 6 */ | ||
179 | u32 errlogaddr; /* rev 6 */ | ||
180 | /* used for patching rev 3 & 5 */ | ||
181 | u32 cambankidx; | ||
182 | u32 cambankstandbyctrl; | ||
183 | u32 cambankpatchctrl; | ||
184 | u32 cambankpatchtblbaseaddr; | ||
185 | u32 cambankcmdreg; | ||
186 | u32 cambankdatareg; | ||
187 | u32 cambankmaskreg; | ||
188 | u32 PAD[1]; | ||
189 | u32 bankinfo; /* corev 8 */ | ||
190 | u32 bankpda; | ||
191 | u32 PAD[14]; | ||
192 | u32 extmemconfig; | ||
193 | u32 extmemparitycsr; | ||
194 | u32 extmemparityerrdata; | ||
195 | u32 extmemparityerrcnt; | ||
196 | u32 extmemwrctrlandsize; | ||
197 | u32 PAD[84]; | ||
198 | u32 workaround; | ||
199 | u32 pwrctl; /* corerev >= 2 */ | ||
200 | u32 PAD[133]; | ||
201 | u32 sr_control; /* corerev >= 15 */ | ||
202 | u32 sr_status; /* corerev >= 15 */ | ||
203 | u32 sr_address; /* corerev >= 15 */ | ||
204 | u32 sr_data; /* corerev >= 15 */ | ||
205 | }; | ||
206 | |||
207 | #define SOCRAMREGOFFS(_f) offsetof(struct sbsocramregs, _f) | ||
208 | |||
209 | #define ARMCR4_CAP (0x04) | ||
210 | #define ARMCR4_BANKIDX (0x40) | ||
211 | #define ARMCR4_BANKINFO (0x44) | ||
212 | #define ARMCR4_BANKPDA (0x4C) | ||
213 | |||
214 | #define ARMCR4_TCBBNB_MASK 0xf0 | ||
215 | #define ARMCR4_TCBBNB_SHIFT 4 | ||
216 | #define ARMCR4_TCBANB_MASK 0xf | ||
217 | #define ARMCR4_TCBANB_SHIFT 0 | ||
218 | |||
219 | #define ARMCR4_BSZ_MASK 0x3f | ||
220 | #define ARMCR4_BSZ_MULT 8192 | ||
221 | |||
153 | struct brcmf_core_priv { | 222 | struct brcmf_core_priv { |
154 | struct brcmf_core pub; | 223 | struct brcmf_core pub; |
155 | u32 wrapbase; | 224 | u32 wrapbase; |
@@ -419,13 +488,13 @@ static struct brcmf_core *brcmf_chip_add_core(struct brcmf_chip_priv *ci, | |||
419 | return &core->pub; | 488 | return &core->pub; |
420 | } | 489 | } |
421 | 490 | ||
422 | #ifdef DEBUG | ||
423 | /* safety check for chipinfo */ | 491 | /* safety check for chipinfo */ |
424 | static int brcmf_chip_cores_check(struct brcmf_chip_priv *ci) | 492 | static int brcmf_chip_cores_check(struct brcmf_chip_priv *ci) |
425 | { | 493 | { |
426 | struct brcmf_core_priv *core; | 494 | struct brcmf_core_priv *core; |
427 | bool need_socram = false; | 495 | bool need_socram = false; |
428 | bool has_socram = false; | 496 | bool has_socram = false; |
497 | bool cpu_found = false; | ||
429 | int idx = 1; | 498 | int idx = 1; |
430 | 499 | ||
431 | list_for_each_entry(core, &ci->cores, list) { | 500 | list_for_each_entry(core, &ci->cores, list) { |
@@ -435,22 +504,24 @@ static int brcmf_chip_cores_check(struct brcmf_chip_priv *ci) | |||
435 | 504 | ||
436 | switch (core->pub.id) { | 505 | switch (core->pub.id) { |
437 | case BCMA_CORE_ARM_CM3: | 506 | case BCMA_CORE_ARM_CM3: |
507 | cpu_found = true; | ||
438 | need_socram = true; | 508 | need_socram = true; |
439 | break; | 509 | break; |
440 | case BCMA_CORE_INTERNAL_MEM: | 510 | case BCMA_CORE_INTERNAL_MEM: |
441 | has_socram = true; | 511 | has_socram = true; |
442 | break; | 512 | break; |
443 | case BCMA_CORE_ARM_CR4: | 513 | case BCMA_CORE_ARM_CR4: |
444 | if (ci->pub.rambase == 0) { | 514 | cpu_found = true; |
445 | brcmf_err("RAM base not provided with ARM CR4 core\n"); | ||
446 | return -ENOMEM; | ||
447 | } | ||
448 | break; | 515 | break; |
449 | default: | 516 | default: |
450 | break; | 517 | break; |
451 | } | 518 | } |
452 | } | 519 | } |
453 | 520 | ||
521 | if (!cpu_found) { | ||
522 | brcmf_err("CPU core not detected\n"); | ||
523 | return -ENXIO; | ||
524 | } | ||
454 | /* check RAM core presence for ARM CM3 core */ | 525 | /* check RAM core presence for ARM CM3 core */ |
455 | if (need_socram && !has_socram) { | 526 | if (need_socram && !has_socram) { |
456 | brcmf_err("RAM core not provided with ARM CM3 core\n"); | 527 | brcmf_err("RAM core not provided with ARM CM3 core\n"); |
@@ -458,56 +529,164 @@ static int brcmf_chip_cores_check(struct brcmf_chip_priv *ci) | |||
458 | } | 529 | } |
459 | return 0; | 530 | return 0; |
460 | } | 531 | } |
461 | #else /* DEBUG */ | 532 | |
462 | static inline int brcmf_chip_cores_check(struct brcmf_chip_priv *ci) | 533 | static u32 brcmf_chip_core_read32(struct brcmf_core_priv *core, u16 reg) |
463 | { | 534 | { |
464 | return 0; | 535 | return core->chip->ops->read32(core->chip->ctx, core->pub.base + reg); |
465 | } | 536 | } |
466 | #endif | ||
467 | 537 | ||
468 | static void brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci) | 538 | static void brcmf_chip_core_write32(struct brcmf_core_priv *core, |
539 | u16 reg, u32 val) | ||
469 | { | 540 | { |
470 | switch (ci->pub.chip) { | 541 | core->chip->ops->write32(core->chip->ctx, core->pub.base + reg, val); |
471 | case BRCM_CC_4329_CHIP_ID: | 542 | } |
472 | ci->pub.ramsize = BCM4329_RAMSIZE; | 543 | |
473 | break; | 544 | static bool brcmf_chip_socram_banksize(struct brcmf_core_priv *core, u8 idx, |
474 | case BRCM_CC_43143_CHIP_ID: | 545 | u32 *banksize) |
475 | ci->pub.ramsize = BCM43143_RAMSIZE; | 546 | { |
476 | break; | 547 | u32 bankinfo; |
477 | case BRCM_CC_43241_CHIP_ID: | 548 | u32 bankidx = (SOCRAM_MEMTYPE_RAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT); |
478 | ci->pub.ramsize = 0x90000; | 549 | |
479 | break; | 550 | bankidx |= idx; |
480 | case BRCM_CC_4330_CHIP_ID: | 551 | brcmf_chip_core_write32(core, SOCRAMREGOFFS(bankidx), bankidx); |
481 | ci->pub.ramsize = 0x48000; | 552 | bankinfo = brcmf_chip_core_read32(core, SOCRAMREGOFFS(bankinfo)); |
482 | break; | 553 | *banksize = (bankinfo & SOCRAM_BANKINFO_SZMASK) + 1; |
554 | *banksize *= SOCRAM_BANKINFO_SZBASE; | ||
555 | return !!(bankinfo & SOCRAM_BANKINFO_RETNTRAM_MASK); | ||
556 | } | ||
557 | |||
558 | static void brcmf_chip_socram_ramsize(struct brcmf_core_priv *sr, u32 *ramsize, | ||
559 | u32 *srsize) | ||
560 | { | ||
561 | u32 coreinfo; | ||
562 | uint nb, banksize, lss; | ||
563 | bool retent; | ||
564 | int i; | ||
565 | |||
566 | *ramsize = 0; | ||
567 | *srsize = 0; | ||
568 | |||
569 | if (WARN_ON(sr->pub.rev < 4)) | ||
570 | return; | ||
571 | |||
572 | if (!brcmf_chip_iscoreup(&sr->pub)) | ||
573 | brcmf_chip_resetcore(&sr->pub, 0, 0, 0); | ||
574 | |||
575 | /* Get info for determining size */ | ||
576 | coreinfo = brcmf_chip_core_read32(sr, SOCRAMREGOFFS(coreinfo)); | ||
577 | nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; | ||
578 | |||
579 | if ((sr->pub.rev <= 7) || (sr->pub.rev == 12)) { | ||
580 | banksize = (coreinfo & SRCI_SRBSZ_MASK); | ||
581 | lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT; | ||
582 | if (lss != 0) | ||
583 | nb--; | ||
584 | *ramsize = nb * (1 << (banksize + SR_BSZ_BASE)); | ||
585 | if (lss != 0) | ||
586 | *ramsize += (1 << ((lss - 1) + SR_BSZ_BASE)); | ||
587 | } else { | ||
588 | nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; | ||
589 | for (i = 0; i < nb; i++) { | ||
590 | retent = brcmf_chip_socram_banksize(sr, i, &banksize); | ||
591 | *ramsize += banksize; | ||
592 | if (retent) | ||
593 | *srsize += banksize; | ||
594 | } | ||
595 | } | ||
596 | |||
597 | /* hardcoded save&restore memory sizes */ | ||
598 | switch (sr->chip->pub.chip) { | ||
483 | case BRCM_CC_4334_CHIP_ID: | 599 | case BRCM_CC_4334_CHIP_ID: |
484 | case BRCM_CC_43340_CHIP_ID: | 600 | if (sr->chip->pub.chiprev < 2) |
485 | ci->pub.ramsize = 0x80000; | 601 | *srsize = (32 * 1024); |
486 | break; | 602 | break; |
487 | case BRCM_CC_4335_CHIP_ID: | 603 | case BRCM_CC_43430_CHIP_ID: |
488 | ci->pub.ramsize = 0xc0000; | 604 | /* assume sr for now as we can not check |
489 | ci->pub.rambase = 0x180000; | 605 | * firmware sr capability at this point. |
606 | */ | ||
607 | *srsize = (64 * 1024); | ||
490 | break; | 608 | break; |
491 | case BRCM_CC_43362_CHIP_ID: | 609 | default: |
492 | ci->pub.ramsize = 0x3c000; | ||
493 | break; | 610 | break; |
611 | } | ||
612 | } | ||
613 | |||
614 | /** Return the TCM-RAM size of the ARMCR4 core. */ | ||
615 | static u32 brcmf_chip_tcm_ramsize(struct brcmf_core_priv *cr4) | ||
616 | { | ||
617 | u32 corecap; | ||
618 | u32 memsize = 0; | ||
619 | u32 nab; | ||
620 | u32 nbb; | ||
621 | u32 totb; | ||
622 | u32 bxinfo; | ||
623 | u32 idx; | ||
624 | |||
625 | corecap = brcmf_chip_core_read32(cr4, ARMCR4_CAP); | ||
626 | |||
627 | nab = (corecap & ARMCR4_TCBANB_MASK) >> ARMCR4_TCBANB_SHIFT; | ||
628 | nbb = (corecap & ARMCR4_TCBBNB_MASK) >> ARMCR4_TCBBNB_SHIFT; | ||
629 | totb = nab + nbb; | ||
630 | |||
631 | for (idx = 0; idx < totb; idx++) { | ||
632 | brcmf_chip_core_write32(cr4, ARMCR4_BANKIDX, idx); | ||
633 | bxinfo = brcmf_chip_core_read32(cr4, ARMCR4_BANKINFO); | ||
634 | memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * ARMCR4_BSZ_MULT; | ||
635 | } | ||
636 | |||
637 | return memsize; | ||
638 | } | ||
639 | |||
640 | static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci) | ||
641 | { | ||
642 | switch (ci->pub.chip) { | ||
643 | case BRCM_CC_4345_CHIP_ID: | ||
644 | return 0x198000; | ||
645 | case BRCM_CC_4335_CHIP_ID: | ||
494 | case BRCM_CC_4339_CHIP_ID: | 646 | case BRCM_CC_4339_CHIP_ID: |
495 | case BRCM_CC_4354_CHIP_ID: | 647 | case BRCM_CC_4354_CHIP_ID: |
496 | case BRCM_CC_4356_CHIP_ID: | 648 | case BRCM_CC_4356_CHIP_ID: |
497 | case BRCM_CC_43567_CHIP_ID: | 649 | case BRCM_CC_43567_CHIP_ID: |
498 | case BRCM_CC_43569_CHIP_ID: | 650 | case BRCM_CC_43569_CHIP_ID: |
499 | case BRCM_CC_43570_CHIP_ID: | 651 | case BRCM_CC_43570_CHIP_ID: |
500 | ci->pub.ramsize = 0xc0000; | ||
501 | ci->pub.rambase = 0x180000; | ||
502 | break; | ||
503 | case BRCM_CC_43602_CHIP_ID: | 652 | case BRCM_CC_43602_CHIP_ID: |
504 | ci->pub.ramsize = 0xf0000; | 653 | return 0x180000; |
505 | ci->pub.rambase = 0x180000; | ||
506 | break; | ||
507 | default: | 654 | default: |
508 | brcmf_err("unknown chip: %s\n", ci->pub.name); | 655 | brcmf_err("unknown chip: %s\n", ci->pub.name); |
509 | break; | 656 | break; |
510 | } | 657 | } |
658 | return 0; | ||
659 | } | ||
660 | |||
661 | static int brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci) | ||
662 | { | ||
663 | struct brcmf_core_priv *mem_core; | ||
664 | struct brcmf_core *mem; | ||
665 | |||
666 | mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_ARM_CR4); | ||
667 | if (mem) { | ||
668 | mem_core = container_of(mem, struct brcmf_core_priv, pub); | ||
669 | ci->pub.ramsize = brcmf_chip_tcm_ramsize(mem_core); | ||
670 | ci->pub.rambase = brcmf_chip_tcm_rambase(ci); | ||
671 | if (!ci->pub.rambase) { | ||
672 | brcmf_err("RAM base not provided with ARM CR4 core\n"); | ||
673 | return -EINVAL; | ||
674 | } | ||
675 | } else { | ||
676 | mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_INTERNAL_MEM); | ||
677 | mem_core = container_of(mem, struct brcmf_core_priv, pub); | ||
678 | brcmf_chip_socram_ramsize(mem_core, &ci->pub.ramsize, | ||
679 | &ci->pub.srsize); | ||
680 | } | ||
681 | brcmf_dbg(INFO, "RAM: base=0x%x size=%d (0x%x) sr=%d (0x%x)\n", | ||
682 | ci->pub.rambase, ci->pub.ramsize, ci->pub.ramsize, | ||
683 | ci->pub.srsize, ci->pub.srsize); | ||
684 | |||
685 | if (!ci->pub.ramsize) { | ||
686 | brcmf_err("RAM size is undetermined\n"); | ||
687 | return -ENOMEM; | ||
688 | } | ||
689 | return 0; | ||
511 | } | 690 | } |
512 | 691 | ||
513 | static u32 brcmf_chip_dmp_get_desc(struct brcmf_chip_priv *ci, u32 *eromaddr, | 692 | static u32 brcmf_chip_dmp_get_desc(struct brcmf_chip_priv *ci, u32 *eromaddr, |
@@ -660,6 +839,7 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci) | |||
660 | struct brcmf_core *core; | 839 | struct brcmf_core *core; |
661 | u32 regdata; | 840 | u32 regdata; |
662 | u32 socitype; | 841 | u32 socitype; |
842 | int ret; | ||
663 | 843 | ||
664 | /* Get CC core rev | 844 | /* Get CC core rev |
665 | * Chipid is assume to be at offset 0 from SI_ENUM_BASE | 845 | * Chipid is assume to be at offset 0 from SI_ENUM_BASE |
@@ -712,9 +892,13 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci) | |||
712 | return -ENODEV; | 892 | return -ENODEV; |
713 | } | 893 | } |
714 | 894 | ||
715 | brcmf_chip_get_raminfo(ci); | 895 | ret = brcmf_chip_cores_check(ci); |
896 | if (ret) | ||
897 | return ret; | ||
716 | 898 | ||
717 | return brcmf_chip_cores_check(ci); | 899 | /* assure chip is passive for core access */ |
900 | brcmf_chip_set_passive(&ci->pub); | ||
901 | return brcmf_chip_get_raminfo(ci); | ||
718 | } | 902 | } |
719 | 903 | ||
720 | static void brcmf_chip_disable_arm(struct brcmf_chip_priv *chip, u16 id) | 904 | static void brcmf_chip_disable_arm(struct brcmf_chip_priv *chip, u16 id) |
@@ -778,12 +962,6 @@ static int brcmf_chip_setup(struct brcmf_chip_priv *chip) | |||
778 | if (chip->ops->setup) | 962 | if (chip->ops->setup) |
779 | ret = chip->ops->setup(chip->ctx, pub); | 963 | ret = chip->ops->setup(chip->ctx, pub); |
780 | 964 | ||
781 | /* | ||
782 | * Make sure any on-chip ARM is off (in case strapping is wrong), | ||
783 | * or downloaded code was already running. | ||
784 | */ | ||
785 | brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CM3); | ||
786 | brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CR4); | ||
787 | return ret; | 965 | return ret; |
788 | } | 966 | } |
789 | 967 | ||
@@ -799,7 +977,7 @@ struct brcmf_chip *brcmf_chip_attach(void *ctx, | |||
799 | err = -EINVAL; | 977 | err = -EINVAL; |
800 | if (WARN_ON(!ops->prepare)) | 978 | if (WARN_ON(!ops->prepare)) |
801 | err = -EINVAL; | 979 | err = -EINVAL; |
802 | if (WARN_ON(!ops->exit_dl)) | 980 | if (WARN_ON(!ops->activate)) |
803 | err = -EINVAL; | 981 | err = -EINVAL; |
804 | if (err < 0) | 982 | if (err < 0) |
805 | return ERR_PTR(-EINVAL); | 983 | return ERR_PTR(-EINVAL); |
@@ -897,9 +1075,10 @@ void brcmf_chip_resetcore(struct brcmf_core *pub, u32 prereset, u32 reset, | |||
897 | } | 1075 | } |
898 | 1076 | ||
899 | static void | 1077 | static void |
900 | brcmf_chip_cm3_enterdl(struct brcmf_chip_priv *chip) | 1078 | brcmf_chip_cm3_set_passive(struct brcmf_chip_priv *chip) |
901 | { | 1079 | { |
902 | struct brcmf_core *core; | 1080 | struct brcmf_core *core; |
1081 | struct brcmf_core_priv *sr; | ||
903 | 1082 | ||
904 | brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CM3); | 1083 | brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CM3); |
905 | core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211); | 1084 | core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211); |
@@ -909,9 +1088,16 @@ brcmf_chip_cm3_enterdl(struct brcmf_chip_priv *chip) | |||
909 | D11_BCMA_IOCTL_PHYCLOCKEN); | 1088 | D11_BCMA_IOCTL_PHYCLOCKEN); |
910 | core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_INTERNAL_MEM); | 1089 | core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_INTERNAL_MEM); |
911 | brcmf_chip_resetcore(core, 0, 0, 0); | 1090 | brcmf_chip_resetcore(core, 0, 0, 0); |
1091 | |||
1092 | /* disable bank #3 remap for this device */ | ||
1093 | if (chip->pub.chip == BRCM_CC_43430_CHIP_ID) { | ||
1094 | sr = container_of(core, struct brcmf_core_priv, pub); | ||
1095 | brcmf_chip_core_write32(sr, SOCRAMREGOFFS(bankidx), 3); | ||
1096 | brcmf_chip_core_write32(sr, SOCRAMREGOFFS(bankpda), 0); | ||
1097 | } | ||
912 | } | 1098 | } |
913 | 1099 | ||
914 | static bool brcmf_chip_cm3_exitdl(struct brcmf_chip_priv *chip) | 1100 | static bool brcmf_chip_cm3_set_active(struct brcmf_chip_priv *chip) |
915 | { | 1101 | { |
916 | struct brcmf_core *core; | 1102 | struct brcmf_core *core; |
917 | 1103 | ||
@@ -921,7 +1107,7 @@ static bool brcmf_chip_cm3_exitdl(struct brcmf_chip_priv *chip) | |||
921 | return false; | 1107 | return false; |
922 | } | 1108 | } |
923 | 1109 | ||
924 | chip->ops->exit_dl(chip->ctx, &chip->pub, 0); | 1110 | chip->ops->activate(chip->ctx, &chip->pub, 0); |
925 | 1111 | ||
926 | core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CM3); | 1112 | core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CM3); |
927 | brcmf_chip_resetcore(core, 0, 0, 0); | 1113 | brcmf_chip_resetcore(core, 0, 0, 0); |
@@ -930,7 +1116,7 @@ static bool brcmf_chip_cm3_exitdl(struct brcmf_chip_priv *chip) | |||
930 | } | 1116 | } |
931 | 1117 | ||
932 | static inline void | 1118 | static inline void |
933 | brcmf_chip_cr4_enterdl(struct brcmf_chip_priv *chip) | 1119 | brcmf_chip_cr4_set_passive(struct brcmf_chip_priv *chip) |
934 | { | 1120 | { |
935 | struct brcmf_core *core; | 1121 | struct brcmf_core *core; |
936 | 1122 | ||
@@ -943,11 +1129,11 @@ brcmf_chip_cr4_enterdl(struct brcmf_chip_priv *chip) | |||
943 | D11_BCMA_IOCTL_PHYCLOCKEN); | 1129 | D11_BCMA_IOCTL_PHYCLOCKEN); |
944 | } | 1130 | } |
945 | 1131 | ||
946 | static bool brcmf_chip_cr4_exitdl(struct brcmf_chip_priv *chip, u32 rstvec) | 1132 | static bool brcmf_chip_cr4_set_active(struct brcmf_chip_priv *chip, u32 rstvec) |
947 | { | 1133 | { |
948 | struct brcmf_core *core; | 1134 | struct brcmf_core *core; |
949 | 1135 | ||
950 | chip->ops->exit_dl(chip->ctx, &chip->pub, rstvec); | 1136 | chip->ops->activate(chip->ctx, &chip->pub, rstvec); |
951 | 1137 | ||
952 | /* restore ARM */ | 1138 | /* restore ARM */ |
953 | core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CR4); | 1139 | core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CR4); |
@@ -956,7 +1142,7 @@ static bool brcmf_chip_cr4_exitdl(struct brcmf_chip_priv *chip, u32 rstvec) | |||
956 | return true; | 1142 | return true; |
957 | } | 1143 | } |
958 | 1144 | ||
959 | void brcmf_chip_enter_download(struct brcmf_chip *pub) | 1145 | void brcmf_chip_set_passive(struct brcmf_chip *pub) |
960 | { | 1146 | { |
961 | struct brcmf_chip_priv *chip; | 1147 | struct brcmf_chip_priv *chip; |
962 | struct brcmf_core *arm; | 1148 | struct brcmf_core *arm; |
@@ -966,14 +1152,14 @@ void brcmf_chip_enter_download(struct brcmf_chip *pub) | |||
966 | chip = container_of(pub, struct brcmf_chip_priv, pub); | 1152 | chip = container_of(pub, struct brcmf_chip_priv, pub); |
967 | arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4); | 1153 | arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4); |
968 | if (arm) { | 1154 | if (arm) { |
969 | brcmf_chip_cr4_enterdl(chip); | 1155 | brcmf_chip_cr4_set_passive(chip); |
970 | return; | 1156 | return; |
971 | } | 1157 | } |
972 | 1158 | ||
973 | brcmf_chip_cm3_enterdl(chip); | 1159 | brcmf_chip_cm3_set_passive(chip); |
974 | } | 1160 | } |
975 | 1161 | ||
976 | bool brcmf_chip_exit_download(struct brcmf_chip *pub, u32 rstvec) | 1162 | bool brcmf_chip_set_active(struct brcmf_chip *pub, u32 rstvec) |
977 | { | 1163 | { |
978 | struct brcmf_chip_priv *chip; | 1164 | struct brcmf_chip_priv *chip; |
979 | struct brcmf_core *arm; | 1165 | struct brcmf_core *arm; |
@@ -983,9 +1169,9 @@ bool brcmf_chip_exit_download(struct brcmf_chip *pub, u32 rstvec) | |||
983 | chip = container_of(pub, struct brcmf_chip_priv, pub); | 1169 | chip = container_of(pub, struct brcmf_chip_priv, pub); |
984 | arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4); | 1170 | arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4); |
985 | if (arm) | 1171 | if (arm) |
986 | return brcmf_chip_cr4_exitdl(chip, rstvec); | 1172 | return brcmf_chip_cr4_set_active(chip, rstvec); |
987 | 1173 | ||
988 | return brcmf_chip_cm3_exitdl(chip); | 1174 | return brcmf_chip_cm3_set_active(chip); |
989 | } | 1175 | } |
990 | 1176 | ||
991 | bool brcmf_chip_sr_capable(struct brcmf_chip *pub) | 1177 | bool brcmf_chip_sr_capable(struct brcmf_chip *pub) |
@@ -1016,6 +1202,10 @@ bool brcmf_chip_sr_capable(struct brcmf_chip *pub) | |||
1016 | addr = CORE_CC_REG(base, chipcontrol_data); | 1202 | addr = CORE_CC_REG(base, chipcontrol_data); |
1017 | reg = chip->ops->read32(chip->ctx, addr); | 1203 | reg = chip->ops->read32(chip->ctx, addr); |
1018 | return (reg & pmu_cc3_mask) != 0; | 1204 | return (reg & pmu_cc3_mask) != 0; |
1205 | case BRCM_CC_43430_CHIP_ID: | ||
1206 | addr = CORE_CC_REG(base, sr_control1); | ||
1207 | reg = chip->ops->read32(chip->ctx, addr); | ||
1208 | return reg != 0; | ||
1019 | default: | 1209 | default: |
1020 | addr = CORE_CC_REG(base, pmucapabilities_ext); | 1210 | addr = CORE_CC_REG(base, pmucapabilities_ext); |
1021 | reg = chip->ops->read32(chip->ctx, addr); | 1211 | reg = chip->ops->read32(chip->ctx, addr); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.h b/drivers/net/wireless/brcm80211/brcmfmac/chip.h index c32908da90c8..60dcb38fc77a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/chip.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.h | |||
@@ -30,7 +30,8 @@ | |||
30 | * @pmucaps: PMU capabilities. | 30 | * @pmucaps: PMU capabilities. |
31 | * @pmurev: PMU revision. | 31 | * @pmurev: PMU revision. |
32 | * @rambase: RAM base address (only applicable for ARM CR4 chips). | 32 | * @rambase: RAM base address (only applicable for ARM CR4 chips). |
33 | * @ramsize: amount of RAM on chip. | 33 | * @ramsize: amount of RAM on chip including retention. |
34 | * @srsize: amount of retention RAM on chip. | ||
34 | * @name: string representation of the chip identifier. | 35 | * @name: string representation of the chip identifier. |
35 | */ | 36 | */ |
36 | struct brcmf_chip { | 37 | struct brcmf_chip { |
@@ -41,6 +42,7 @@ struct brcmf_chip { | |||
41 | u32 pmurev; | 42 | u32 pmurev; |
42 | u32 rambase; | 43 | u32 rambase; |
43 | u32 ramsize; | 44 | u32 ramsize; |
45 | u32 srsize; | ||
44 | char name[8]; | 46 | char name[8]; |
45 | }; | 47 | }; |
46 | 48 | ||
@@ -64,7 +66,7 @@ struct brcmf_core { | |||
64 | * @write32: write 32-bit value over bus. | 66 | * @write32: write 32-bit value over bus. |
65 | * @prepare: prepare bus for core configuration. | 67 | * @prepare: prepare bus for core configuration. |
66 | * @setup: bus-specific core setup. | 68 | * @setup: bus-specific core setup. |
67 | * @exit_dl: exit download state. | 69 | * @active: chip becomes active. |
68 | * The callback should use the provided @rstvec when non-zero. | 70 | * The callback should use the provided @rstvec when non-zero. |
69 | */ | 71 | */ |
70 | struct brcmf_buscore_ops { | 72 | struct brcmf_buscore_ops { |
@@ -72,7 +74,7 @@ struct brcmf_buscore_ops { | |||
72 | void (*write32)(void *ctx, u32 addr, u32 value); | 74 | void (*write32)(void *ctx, u32 addr, u32 value); |
73 | int (*prepare)(void *ctx); | 75 | int (*prepare)(void *ctx); |
74 | int (*setup)(void *ctx, struct brcmf_chip *chip); | 76 | int (*setup)(void *ctx, struct brcmf_chip *chip); |
75 | void (*exit_dl)(void *ctx, struct brcmf_chip *chip, u32 rstvec); | 77 | void (*activate)(void *ctx, struct brcmf_chip *chip, u32 rstvec); |
76 | }; | 78 | }; |
77 | 79 | ||
78 | struct brcmf_chip *brcmf_chip_attach(void *ctx, | 80 | struct brcmf_chip *brcmf_chip_attach(void *ctx, |
@@ -84,8 +86,8 @@ bool brcmf_chip_iscoreup(struct brcmf_core *core); | |||
84 | void brcmf_chip_coredisable(struct brcmf_core *core, u32 prereset, u32 reset); | 86 | void brcmf_chip_coredisable(struct brcmf_core *core, u32 prereset, u32 reset); |
85 | void brcmf_chip_resetcore(struct brcmf_core *core, u32 prereset, u32 reset, | 87 | void brcmf_chip_resetcore(struct brcmf_core *core, u32 prereset, u32 reset, |
86 | u32 postreset); | 88 | u32 postreset); |
87 | void brcmf_chip_enter_download(struct brcmf_chip *ci); | 89 | void brcmf_chip_set_passive(struct brcmf_chip *ci); |
88 | bool brcmf_chip_exit_download(struct brcmf_chip *ci, u32 rstvec); | 90 | bool brcmf_chip_set_active(struct brcmf_chip *ci, u32 rstvec); |
89 | bool brcmf_chip_sr_capable(struct brcmf_chip *pub); | 91 | bool brcmf_chip_sr_capable(struct brcmf_chip *pub); |
90 | 92 | ||
91 | #endif /* BRCMF_AXIDMP_H */ | 93 | #endif /* BRCMF_AXIDMP_H */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c index 6262612dec45..4ec9811f49c8 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c | |||
@@ -481,10 +481,9 @@ static int brcmf_msgbuf_ioctl_resp_wait(struct brcmf_msgbuf *msgbuf) | |||
481 | 481 | ||
482 | static void brcmf_msgbuf_ioctl_resp_wake(struct brcmf_msgbuf *msgbuf) | 482 | static void brcmf_msgbuf_ioctl_resp_wake(struct brcmf_msgbuf *msgbuf) |
483 | { | 483 | { |
484 | if (waitqueue_active(&msgbuf->ioctl_resp_wait)) { | 484 | msgbuf->ctl_completed = true; |
485 | msgbuf->ctl_completed = true; | 485 | if (waitqueue_active(&msgbuf->ioctl_resp_wait)) |
486 | wake_up(&msgbuf->ioctl_resp_wait); | 486 | wake_up(&msgbuf->ioctl_resp_wait); |
487 | } | ||
488 | } | 487 | } |
489 | 488 | ||
490 | 489 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.h b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.h index 77a51b8c1e12..3d513e407e3d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.h | |||
@@ -17,11 +17,11 @@ | |||
17 | 17 | ||
18 | #ifdef CONFIG_BRCMFMAC_PROTO_MSGBUF | 18 | #ifdef CONFIG_BRCMFMAC_PROTO_MSGBUF |
19 | 19 | ||
20 | #define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM 20 | 20 | #define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM 64 |
21 | #define BRCMF_H2D_MSGRING_RXPOST_SUBMIT_MAX_ITEM 256 | 21 | #define BRCMF_H2D_MSGRING_RXPOST_SUBMIT_MAX_ITEM 512 |
22 | #define BRCMF_D2H_MSGRING_CONTROL_COMPLETE_MAX_ITEM 20 | 22 | #define BRCMF_D2H_MSGRING_CONTROL_COMPLETE_MAX_ITEM 64 |
23 | #define BRCMF_D2H_MSGRING_TX_COMPLETE_MAX_ITEM 1024 | 23 | #define BRCMF_D2H_MSGRING_TX_COMPLETE_MAX_ITEM 1024 |
24 | #define BRCMF_D2H_MSGRING_RX_COMPLETE_MAX_ITEM 256 | 24 | #define BRCMF_D2H_MSGRING_RX_COMPLETE_MAX_ITEM 512 |
25 | #define BRCMF_H2D_TXFLOWRING_MAX_ITEM 512 | 25 | #define BRCMF_H2D_TXFLOWRING_MAX_ITEM 512 |
26 | 26 | ||
27 | #define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_ITEMSIZE 40 | 27 | #define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_ITEMSIZE 40 |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c index 61c053a729be..1831ecd0813e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c | |||
@@ -47,8 +47,6 @@ enum brcmf_pcie_state { | |||
47 | 47 | ||
48 | #define BRCMF_PCIE_43602_FW_NAME "brcm/brcmfmac43602-pcie.bin" | 48 | #define BRCMF_PCIE_43602_FW_NAME "brcm/brcmfmac43602-pcie.bin" |
49 | #define BRCMF_PCIE_43602_NVRAM_NAME "brcm/brcmfmac43602-pcie.txt" | 49 | #define BRCMF_PCIE_43602_NVRAM_NAME "brcm/brcmfmac43602-pcie.txt" |
50 | #define BRCMF_PCIE_4354_FW_NAME "brcm/brcmfmac4354-pcie.bin" | ||
51 | #define BRCMF_PCIE_4354_NVRAM_NAME "brcm/brcmfmac4354-pcie.txt" | ||
52 | #define BRCMF_PCIE_4356_FW_NAME "brcm/brcmfmac4356-pcie.bin" | 50 | #define BRCMF_PCIE_4356_FW_NAME "brcm/brcmfmac4356-pcie.bin" |
53 | #define BRCMF_PCIE_4356_NVRAM_NAME "brcm/brcmfmac4356-pcie.txt" | 51 | #define BRCMF_PCIE_4356_NVRAM_NAME "brcm/brcmfmac4356-pcie.txt" |
54 | #define BRCMF_PCIE_43570_FW_NAME "brcm/brcmfmac43570-pcie.bin" | 52 | #define BRCMF_PCIE_43570_FW_NAME "brcm/brcmfmac43570-pcie.bin" |
@@ -187,8 +185,8 @@ enum brcmf_pcie_state { | |||
187 | 185 | ||
188 | MODULE_FIRMWARE(BRCMF_PCIE_43602_FW_NAME); | 186 | MODULE_FIRMWARE(BRCMF_PCIE_43602_FW_NAME); |
189 | MODULE_FIRMWARE(BRCMF_PCIE_43602_NVRAM_NAME); | 187 | MODULE_FIRMWARE(BRCMF_PCIE_43602_NVRAM_NAME); |
190 | MODULE_FIRMWARE(BRCMF_PCIE_4354_FW_NAME); | 188 | MODULE_FIRMWARE(BRCMF_PCIE_4356_FW_NAME); |
191 | MODULE_FIRMWARE(BRCMF_PCIE_4354_NVRAM_NAME); | 189 | MODULE_FIRMWARE(BRCMF_PCIE_4356_NVRAM_NAME); |
192 | MODULE_FIRMWARE(BRCMF_PCIE_43570_FW_NAME); | 190 | MODULE_FIRMWARE(BRCMF_PCIE_43570_FW_NAME); |
193 | MODULE_FIRMWARE(BRCMF_PCIE_43570_NVRAM_NAME); | 191 | MODULE_FIRMWARE(BRCMF_PCIE_43570_NVRAM_NAME); |
194 | 192 | ||
@@ -509,8 +507,6 @@ static void brcmf_pcie_attach(struct brcmf_pciedev_info *devinfo) | |||
509 | 507 | ||
510 | static int brcmf_pcie_enter_download_state(struct brcmf_pciedev_info *devinfo) | 508 | static int brcmf_pcie_enter_download_state(struct brcmf_pciedev_info *devinfo) |
511 | { | 509 | { |
512 | brcmf_chip_enter_download(devinfo->ci); | ||
513 | |||
514 | if (devinfo->ci->chip == BRCM_CC_43602_CHIP_ID) { | 510 | if (devinfo->ci->chip == BRCM_CC_43602_CHIP_ID) { |
515 | brcmf_pcie_select_core(devinfo, BCMA_CORE_ARM_CR4); | 511 | brcmf_pcie_select_core(devinfo, BCMA_CORE_ARM_CR4); |
516 | brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKIDX, | 512 | brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKIDX, |
@@ -536,7 +532,7 @@ static int brcmf_pcie_exit_download_state(struct brcmf_pciedev_info *devinfo, | |||
536 | brcmf_chip_resetcore(core, 0, 0, 0); | 532 | brcmf_chip_resetcore(core, 0, 0, 0); |
537 | } | 533 | } |
538 | 534 | ||
539 | return !brcmf_chip_exit_download(devinfo->ci, resetintr); | 535 | return !brcmf_chip_set_active(devinfo->ci, resetintr); |
540 | } | 536 | } |
541 | 537 | ||
542 | 538 | ||
@@ -653,10 +649,9 @@ static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo) | |||
653 | console->log_str[console->log_idx] = ch; | 649 | console->log_str[console->log_idx] = ch; |
654 | console->log_idx++; | 650 | console->log_idx++; |
655 | } | 651 | } |
656 | |||
657 | if (ch == '\n') { | 652 | if (ch == '\n') { |
658 | console->log_str[console->log_idx] = 0; | 653 | console->log_str[console->log_idx] = 0; |
659 | brcmf_dbg(PCIE, "CONSOLE: %s\n", console->log_str); | 654 | brcmf_dbg(PCIE, "CONSOLE: %s", console->log_str); |
660 | console->log_idx = 0; | 655 | console->log_idx = 0; |
661 | } | 656 | } |
662 | } | 657 | } |
@@ -1328,10 +1323,6 @@ static int brcmf_pcie_get_fwnames(struct brcmf_pciedev_info *devinfo) | |||
1328 | fw_name = BRCMF_PCIE_43602_FW_NAME; | 1323 | fw_name = BRCMF_PCIE_43602_FW_NAME; |
1329 | nvram_name = BRCMF_PCIE_43602_NVRAM_NAME; | 1324 | nvram_name = BRCMF_PCIE_43602_NVRAM_NAME; |
1330 | break; | 1325 | break; |
1331 | case BRCM_CC_4354_CHIP_ID: | ||
1332 | fw_name = BRCMF_PCIE_4354_FW_NAME; | ||
1333 | nvram_name = BRCMF_PCIE_4354_NVRAM_NAME; | ||
1334 | break; | ||
1335 | case BRCM_CC_4356_CHIP_ID: | 1326 | case BRCM_CC_4356_CHIP_ID: |
1336 | fw_name = BRCMF_PCIE_4356_FW_NAME; | 1327 | fw_name = BRCMF_PCIE_4356_FW_NAME; |
1337 | nvram_name = BRCMF_PCIE_4356_NVRAM_NAME; | 1328 | nvram_name = BRCMF_PCIE_4356_NVRAM_NAME; |
@@ -1566,8 +1557,8 @@ static int brcmf_pcie_buscoreprep(void *ctx) | |||
1566 | } | 1557 | } |
1567 | 1558 | ||
1568 | 1559 | ||
1569 | static void brcmf_pcie_buscore_exitdl(void *ctx, struct brcmf_chip *chip, | 1560 | static void brcmf_pcie_buscore_activate(void *ctx, struct brcmf_chip *chip, |
1570 | u32 rstvec) | 1561 | u32 rstvec) |
1571 | { | 1562 | { |
1572 | struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx; | 1563 | struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx; |
1573 | 1564 | ||
@@ -1577,7 +1568,7 @@ static void brcmf_pcie_buscore_exitdl(void *ctx, struct brcmf_chip *chip, | |||
1577 | 1568 | ||
1578 | static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = { | 1569 | static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = { |
1579 | .prepare = brcmf_pcie_buscoreprep, | 1570 | .prepare = brcmf_pcie_buscoreprep, |
1580 | .exit_dl = brcmf_pcie_buscore_exitdl, | 1571 | .activate = brcmf_pcie_buscore_activate, |
1581 | .read32 = brcmf_pcie_buscore_read32, | 1572 | .read32 = brcmf_pcie_buscore_read32, |
1582 | .write32 = brcmf_pcie_buscore_write32, | 1573 | .write32 = brcmf_pcie_buscore_write32, |
1583 | }; | 1574 | }; |
@@ -1856,7 +1847,6 @@ cleanup: | |||
1856 | PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 } | 1847 | PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 } |
1857 | 1848 | ||
1858 | static struct pci_device_id brcmf_pcie_devid_table[] = { | 1849 | static struct pci_device_id brcmf_pcie_devid_table[] = { |
1859 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4354_DEVICE_ID), | ||
1860 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4356_DEVICE_ID), | 1850 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4356_DEVICE_ID), |
1861 | BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID), | 1851 | BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID), |
1862 | BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID), | 1852 | BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID), |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c index 257ee70feb5b..ab0c89833013 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c | |||
@@ -432,8 +432,6 @@ struct brcmf_sdio { | |||
432 | struct brcmf_sdio_dev *sdiodev; /* sdio device handler */ | 432 | struct brcmf_sdio_dev *sdiodev; /* sdio device handler */ |
433 | struct brcmf_chip *ci; /* Chip info struct */ | 433 | struct brcmf_chip *ci; /* Chip info struct */ |
434 | 434 | ||
435 | u32 ramsize; /* Size of RAM in SOCRAM (bytes) */ | ||
436 | |||
437 | u32 hostintmask; /* Copy of Host Interrupt Mask */ | 435 | u32 hostintmask; /* Copy of Host Interrupt Mask */ |
438 | atomic_t intstatus; /* Intstatus bits (events) pending */ | 436 | atomic_t intstatus; /* Intstatus bits (events) pending */ |
439 | atomic_t fcstate; /* State of dongle flow-control */ | 437 | atomic_t fcstate; /* State of dongle flow-control */ |
@@ -485,10 +483,9 @@ struct brcmf_sdio { | |||
485 | #endif /* DEBUG */ | 483 | #endif /* DEBUG */ |
486 | 484 | ||
487 | uint clkstate; /* State of sd and backplane clock(s) */ | 485 | uint clkstate; /* State of sd and backplane clock(s) */ |
488 | bool activity; /* Activity flag for clock down */ | ||
489 | s32 idletime; /* Control for activity timeout */ | 486 | s32 idletime; /* Control for activity timeout */ |
490 | s32 idlecount; /* Activity timeout counter */ | 487 | s32 idlecount; /* Activity timeout counter */ |
491 | s32 idleclock; /* How to set bus driver when idle */ | 488 | s32 idleclock; /* How to set bus driver when idle */ |
492 | bool rxflow_mode; /* Rx flow control mode */ | 489 | bool rxflow_mode; /* Rx flow control mode */ |
493 | bool rxflow; /* Is rx flow control on */ | 490 | bool rxflow; /* Is rx flow control on */ |
494 | bool alp_only; /* Don't use HT clock (ALP only) */ | 491 | bool alp_only; /* Don't use HT clock (ALP only) */ |
@@ -510,7 +507,8 @@ struct brcmf_sdio { | |||
510 | 507 | ||
511 | struct workqueue_struct *brcmf_wq; | 508 | struct workqueue_struct *brcmf_wq; |
512 | struct work_struct datawork; | 509 | struct work_struct datawork; |
513 | atomic_t dpc_tskcnt; | 510 | bool dpc_triggered; |
511 | bool dpc_running; | ||
514 | 512 | ||
515 | bool txoff; /* Transmit flow-controlled */ | 513 | bool txoff; /* Transmit flow-controlled */ |
516 | struct brcmf_sdio_count sdcnt; | 514 | struct brcmf_sdio_count sdcnt; |
@@ -617,6 +615,10 @@ static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3[] = { | |||
617 | #define BCM43362_NVRAM_NAME "brcm/brcmfmac43362-sdio.txt" | 615 | #define BCM43362_NVRAM_NAME "brcm/brcmfmac43362-sdio.txt" |
618 | #define BCM4339_FIRMWARE_NAME "brcm/brcmfmac4339-sdio.bin" | 616 | #define BCM4339_FIRMWARE_NAME "brcm/brcmfmac4339-sdio.bin" |
619 | #define BCM4339_NVRAM_NAME "brcm/brcmfmac4339-sdio.txt" | 617 | #define BCM4339_NVRAM_NAME "brcm/brcmfmac4339-sdio.txt" |
618 | #define BCM43430_FIRMWARE_NAME "brcm/brcmfmac43430-sdio.bin" | ||
619 | #define BCM43430_NVRAM_NAME "brcm/brcmfmac43430-sdio.txt" | ||
620 | #define BCM43455_FIRMWARE_NAME "brcm/brcmfmac43455-sdio.bin" | ||
621 | #define BCM43455_NVRAM_NAME "brcm/brcmfmac43455-sdio.txt" | ||
620 | #define BCM4354_FIRMWARE_NAME "brcm/brcmfmac4354-sdio.bin" | 622 | #define BCM4354_FIRMWARE_NAME "brcm/brcmfmac4354-sdio.bin" |
621 | #define BCM4354_NVRAM_NAME "brcm/brcmfmac4354-sdio.txt" | 623 | #define BCM4354_NVRAM_NAME "brcm/brcmfmac4354-sdio.txt" |
622 | 624 | ||
@@ -640,6 +642,10 @@ MODULE_FIRMWARE(BCM43362_FIRMWARE_NAME); | |||
640 | MODULE_FIRMWARE(BCM43362_NVRAM_NAME); | 642 | MODULE_FIRMWARE(BCM43362_NVRAM_NAME); |
641 | MODULE_FIRMWARE(BCM4339_FIRMWARE_NAME); | 643 | MODULE_FIRMWARE(BCM4339_FIRMWARE_NAME); |
642 | MODULE_FIRMWARE(BCM4339_NVRAM_NAME); | 644 | MODULE_FIRMWARE(BCM4339_NVRAM_NAME); |
645 | MODULE_FIRMWARE(BCM43430_FIRMWARE_NAME); | ||
646 | MODULE_FIRMWARE(BCM43430_NVRAM_NAME); | ||
647 | MODULE_FIRMWARE(BCM43455_FIRMWARE_NAME); | ||
648 | MODULE_FIRMWARE(BCM43455_NVRAM_NAME); | ||
643 | MODULE_FIRMWARE(BCM4354_FIRMWARE_NAME); | 649 | MODULE_FIRMWARE(BCM4354_FIRMWARE_NAME); |
644 | MODULE_FIRMWARE(BCM4354_NVRAM_NAME); | 650 | MODULE_FIRMWARE(BCM4354_NVRAM_NAME); |
645 | 651 | ||
@@ -669,6 +675,8 @@ static const struct brcmf_firmware_names brcmf_fwname_data[] = { | |||
669 | { BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) }, | 675 | { BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) }, |
670 | { BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) }, | 676 | { BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) }, |
671 | { BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) }, | 677 | { BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) }, |
678 | { BRCM_CC_43430_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43430) }, | ||
679 | { BRCM_CC_4345_CHIP_ID, 0xFFFFFFC0, BRCMF_FIRMWARE_NVRAM(BCM43455) }, | ||
672 | { BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) } | 680 | { BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) } |
673 | }; | 681 | }; |
674 | 682 | ||
@@ -959,13 +967,8 @@ static int brcmf_sdio_clkctl(struct brcmf_sdio *bus, uint target, bool pendok) | |||
959 | brcmf_dbg(SDIO, "Enter\n"); | 967 | brcmf_dbg(SDIO, "Enter\n"); |
960 | 968 | ||
961 | /* Early exit if we're already there */ | 969 | /* Early exit if we're already there */ |
962 | if (bus->clkstate == target) { | 970 | if (bus->clkstate == target) |
963 | if (target == CLK_AVAIL) { | ||
964 | brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); | ||
965 | bus->activity = true; | ||
966 | } | ||
967 | return 0; | 971 | return 0; |
968 | } | ||
969 | 972 | ||
970 | switch (target) { | 973 | switch (target) { |
971 | case CLK_AVAIL: | 974 | case CLK_AVAIL: |
@@ -974,8 +977,6 @@ static int brcmf_sdio_clkctl(struct brcmf_sdio *bus, uint target, bool pendok) | |||
974 | brcmf_sdio_sdclk(bus, true); | 977 | brcmf_sdio_sdclk(bus, true); |
975 | /* Now request HT Avail on the backplane */ | 978 | /* Now request HT Avail on the backplane */ |
976 | brcmf_sdio_htclk(bus, true, pendok); | 979 | brcmf_sdio_htclk(bus, true, pendok); |
977 | brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); | ||
978 | bus->activity = true; | ||
979 | break; | 980 | break; |
980 | 981 | ||
981 | case CLK_SDONLY: | 982 | case CLK_SDONLY: |
@@ -987,7 +988,6 @@ static int brcmf_sdio_clkctl(struct brcmf_sdio *bus, uint target, bool pendok) | |||
987 | else | 988 | else |
988 | brcmf_err("request for %d -> %d\n", | 989 | brcmf_err("request for %d -> %d\n", |
989 | bus->clkstate, target); | 990 | bus->clkstate, target); |
990 | brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); | ||
991 | break; | 991 | break; |
992 | 992 | ||
993 | case CLK_NONE: | 993 | case CLK_NONE: |
@@ -996,7 +996,6 @@ static int brcmf_sdio_clkctl(struct brcmf_sdio *bus, uint target, bool pendok) | |||
996 | brcmf_sdio_htclk(bus, false, false); | 996 | brcmf_sdio_htclk(bus, false, false); |
997 | /* Now remove the SD clock */ | 997 | /* Now remove the SD clock */ |
998 | brcmf_sdio_sdclk(bus, false); | 998 | brcmf_sdio_sdclk(bus, false); |
999 | brcmf_sdio_wd_timer(bus, 0); | ||
1000 | break; | 999 | break; |
1001 | } | 1000 | } |
1002 | #ifdef DEBUG | 1001 | #ifdef DEBUG |
@@ -1024,17 +1023,6 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok) | |||
1024 | 1023 | ||
1025 | /* Going to sleep */ | 1024 | /* Going to sleep */ |
1026 | if (sleep) { | 1025 | if (sleep) { |
1027 | /* Don't sleep if something is pending */ | ||
1028 | if (atomic_read(&bus->intstatus) || | ||
1029 | atomic_read(&bus->ipend) > 0 || | ||
1030 | bus->ctrl_frame_stat || | ||
1031 | (!atomic_read(&bus->fcstate) && | ||
1032 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && | ||
1033 | data_ok(bus))) { | ||
1034 | err = -EBUSY; | ||
1035 | goto done; | ||
1036 | } | ||
1037 | |||
1038 | clkcsr = brcmf_sdiod_regrb(bus->sdiodev, | 1026 | clkcsr = brcmf_sdiod_regrb(bus->sdiodev, |
1039 | SBSDIO_FUNC1_CHIPCLKCSR, | 1027 | SBSDIO_FUNC1_CHIPCLKCSR, |
1040 | &err); | 1028 | &err); |
@@ -1045,11 +1033,7 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok) | |||
1045 | SBSDIO_ALP_AVAIL_REQ, &err); | 1033 | SBSDIO_ALP_AVAIL_REQ, &err); |
1046 | } | 1034 | } |
1047 | err = brcmf_sdio_kso_control(bus, false); | 1035 | err = brcmf_sdio_kso_control(bus, false); |
1048 | /* disable watchdog */ | ||
1049 | if (!err) | ||
1050 | brcmf_sdio_wd_timer(bus, 0); | ||
1051 | } else { | 1036 | } else { |
1052 | bus->idlecount = 0; | ||
1053 | err = brcmf_sdio_kso_control(bus, true); | 1037 | err = brcmf_sdio_kso_control(bus, true); |
1054 | } | 1038 | } |
1055 | if (err) { | 1039 | if (err) { |
@@ -1066,6 +1050,7 @@ end: | |||
1066 | brcmf_sdio_clkctl(bus, CLK_NONE, pendok); | 1050 | brcmf_sdio_clkctl(bus, CLK_NONE, pendok); |
1067 | } else { | 1051 | } else { |
1068 | brcmf_sdio_clkctl(bus, CLK_AVAIL, pendok); | 1052 | brcmf_sdio_clkctl(bus, CLK_AVAIL, pendok); |
1053 | brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); | ||
1069 | } | 1054 | } |
1070 | bus->sleeping = sleep; | 1055 | bus->sleeping = sleep; |
1071 | brcmf_dbg(SDIO, "new state %s\n", | 1056 | brcmf_dbg(SDIO, "new state %s\n", |
@@ -1085,44 +1070,47 @@ static inline bool brcmf_sdio_valid_shared_address(u32 addr) | |||
1085 | static int brcmf_sdio_readshared(struct brcmf_sdio *bus, | 1070 | static int brcmf_sdio_readshared(struct brcmf_sdio *bus, |
1086 | struct sdpcm_shared *sh) | 1071 | struct sdpcm_shared *sh) |
1087 | { | 1072 | { |
1088 | u32 addr; | 1073 | u32 addr = 0; |
1089 | int rv; | 1074 | int rv; |
1090 | u32 shaddr = 0; | 1075 | u32 shaddr = 0; |
1091 | struct sdpcm_shared_le sh_le; | 1076 | struct sdpcm_shared_le sh_le; |
1092 | __le32 addr_le; | 1077 | __le32 addr_le; |
1093 | 1078 | ||
1094 | shaddr = bus->ci->rambase + bus->ramsize - 4; | 1079 | sdio_claim_host(bus->sdiodev->func[1]); |
1080 | brcmf_sdio_bus_sleep(bus, false, false); | ||
1095 | 1081 | ||
1096 | /* | 1082 | /* |
1097 | * Read last word in socram to determine | 1083 | * Read last word in socram to determine |
1098 | * address of sdpcm_shared structure | 1084 | * address of sdpcm_shared structure |
1099 | */ | 1085 | */ |
1100 | sdio_claim_host(bus->sdiodev->func[1]); | 1086 | shaddr = bus->ci->rambase + bus->ci->ramsize - 4; |
1101 | brcmf_sdio_bus_sleep(bus, false, false); | 1087 | if (!bus->ci->rambase && brcmf_chip_sr_capable(bus->ci)) |
1102 | rv = brcmf_sdiod_ramrw(bus->sdiodev, false, shaddr, (u8 *)&addr_le, 4); | 1088 | shaddr -= bus->ci->srsize; |
1103 | sdio_release_host(bus->sdiodev->func[1]); | 1089 | rv = brcmf_sdiod_ramrw(bus->sdiodev, false, shaddr, |
1090 | (u8 *)&addr_le, 4); | ||
1104 | if (rv < 0) | 1091 | if (rv < 0) |
1105 | return rv; | 1092 | goto fail; |
1106 | |||
1107 | addr = le32_to_cpu(addr_le); | ||
1108 | |||
1109 | brcmf_dbg(SDIO, "sdpcm_shared address 0x%08X\n", addr); | ||
1110 | 1093 | ||
1111 | /* | 1094 | /* |
1112 | * Check if addr is valid. | 1095 | * Check if addr is valid. |
1113 | * NVRAM length at the end of memory should have been overwritten. | 1096 | * NVRAM length at the end of memory should have been overwritten. |
1114 | */ | 1097 | */ |
1098 | addr = le32_to_cpu(addr_le); | ||
1115 | if (!brcmf_sdio_valid_shared_address(addr)) { | 1099 | if (!brcmf_sdio_valid_shared_address(addr)) { |
1116 | brcmf_err("invalid sdpcm_shared address 0x%08X\n", | 1100 | brcmf_err("invalid sdpcm_shared address 0x%08X\n", addr); |
1117 | addr); | 1101 | rv = -EINVAL; |
1118 | return -EINVAL; | 1102 | goto fail; |
1119 | } | 1103 | } |
1120 | 1104 | ||
1105 | brcmf_dbg(INFO, "sdpcm_shared address 0x%08X\n", addr); | ||
1106 | |||
1121 | /* Read hndrte_shared structure */ | 1107 | /* Read hndrte_shared structure */ |
1122 | rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr, (u8 *)&sh_le, | 1108 | rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr, (u8 *)&sh_le, |
1123 | sizeof(struct sdpcm_shared_le)); | 1109 | sizeof(struct sdpcm_shared_le)); |
1124 | if (rv < 0) | 1110 | if (rv < 0) |
1125 | return rv; | 1111 | goto fail; |
1112 | |||
1113 | sdio_release_host(bus->sdiodev->func[1]); | ||
1126 | 1114 | ||
1127 | /* Endianness */ | 1115 | /* Endianness */ |
1128 | sh->flags = le32_to_cpu(sh_le.flags); | 1116 | sh->flags = le32_to_cpu(sh_le.flags); |
@@ -1139,8 +1127,13 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus, | |||
1139 | sh->flags & SDPCM_SHARED_VERSION_MASK); | 1127 | sh->flags & SDPCM_SHARED_VERSION_MASK); |
1140 | return -EPROTO; | 1128 | return -EPROTO; |
1141 | } | 1129 | } |
1142 | |||
1143 | return 0; | 1130 | return 0; |
1131 | |||
1132 | fail: | ||
1133 | brcmf_err("unable to obtain sdpcm_shared info: rv=%d (addr=0x%x)\n", | ||
1134 | rv, addr); | ||
1135 | sdio_release_host(bus->sdiodev->func[1]); | ||
1136 | return rv; | ||
1144 | } | 1137 | } |
1145 | 1138 | ||
1146 | static void brcmf_sdio_get_console_addr(struct brcmf_sdio *bus) | 1139 | static void brcmf_sdio_get_console_addr(struct brcmf_sdio *bus) |
@@ -2721,11 +2714,14 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus) | |||
2721 | if (bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL) && | 2714 | if (bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL) && |
2722 | data_ok(bus)) { | 2715 | data_ok(bus)) { |
2723 | sdio_claim_host(bus->sdiodev->func[1]); | 2716 | sdio_claim_host(bus->sdiodev->func[1]); |
2724 | err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf, | 2717 | if (bus->ctrl_frame_stat) { |
2725 | bus->ctrl_frame_len); | 2718 | err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf, |
2719 | bus->ctrl_frame_len); | ||
2720 | bus->ctrl_frame_err = err; | ||
2721 | wmb(); | ||
2722 | bus->ctrl_frame_stat = false; | ||
2723 | } | ||
2726 | sdio_release_host(bus->sdiodev->func[1]); | 2724 | sdio_release_host(bus->sdiodev->func[1]); |
2727 | bus->ctrl_frame_err = err; | ||
2728 | bus->ctrl_frame_stat = false; | ||
2729 | brcmf_sdio_wait_event_wakeup(bus); | 2725 | brcmf_sdio_wait_event_wakeup(bus); |
2730 | } | 2726 | } |
2731 | /* Send queued frames (limit 1 if rx may still be pending) */ | 2727 | /* Send queued frames (limit 1 if rx may still be pending) */ |
@@ -2740,12 +2736,22 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus) | |||
2740 | if ((bus->sdiodev->state != BRCMF_SDIOD_DATA) || (err != 0)) { | 2736 | if ((bus->sdiodev->state != BRCMF_SDIOD_DATA) || (err != 0)) { |
2741 | brcmf_err("failed backplane access over SDIO, halting operation\n"); | 2737 | brcmf_err("failed backplane access over SDIO, halting operation\n"); |
2742 | atomic_set(&bus->intstatus, 0); | 2738 | atomic_set(&bus->intstatus, 0); |
2739 | if (bus->ctrl_frame_stat) { | ||
2740 | sdio_claim_host(bus->sdiodev->func[1]); | ||
2741 | if (bus->ctrl_frame_stat) { | ||
2742 | bus->ctrl_frame_err = -ENODEV; | ||
2743 | wmb(); | ||
2744 | bus->ctrl_frame_stat = false; | ||
2745 | brcmf_sdio_wait_event_wakeup(bus); | ||
2746 | } | ||
2747 | sdio_release_host(bus->sdiodev->func[1]); | ||
2748 | } | ||
2743 | } else if (atomic_read(&bus->intstatus) || | 2749 | } else if (atomic_read(&bus->intstatus) || |
2744 | atomic_read(&bus->ipend) > 0 || | 2750 | atomic_read(&bus->ipend) > 0 || |
2745 | (!atomic_read(&bus->fcstate) && | 2751 | (!atomic_read(&bus->fcstate) && |
2746 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && | 2752 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && |
2747 | data_ok(bus))) { | 2753 | data_ok(bus))) { |
2748 | atomic_inc(&bus->dpc_tskcnt); | 2754 | bus->dpc_triggered = true; |
2749 | } | 2755 | } |
2750 | } | 2756 | } |
2751 | 2757 | ||
@@ -2941,20 +2947,27 @@ brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2941 | /* Send from dpc */ | 2947 | /* Send from dpc */ |
2942 | bus->ctrl_frame_buf = msg; | 2948 | bus->ctrl_frame_buf = msg; |
2943 | bus->ctrl_frame_len = msglen; | 2949 | bus->ctrl_frame_len = msglen; |
2950 | wmb(); | ||
2944 | bus->ctrl_frame_stat = true; | 2951 | bus->ctrl_frame_stat = true; |
2945 | 2952 | ||
2946 | brcmf_sdio_trigger_dpc(bus); | 2953 | brcmf_sdio_trigger_dpc(bus); |
2947 | wait_event_interruptible_timeout(bus->ctrl_wait, !bus->ctrl_frame_stat, | 2954 | wait_event_interruptible_timeout(bus->ctrl_wait, !bus->ctrl_frame_stat, |
2948 | msecs_to_jiffies(CTL_DONE_TIMEOUT)); | 2955 | msecs_to_jiffies(CTL_DONE_TIMEOUT)); |
2949 | 2956 | ret = 0; | |
2950 | if (!bus->ctrl_frame_stat) { | 2957 | if (bus->ctrl_frame_stat) { |
2958 | sdio_claim_host(bus->sdiodev->func[1]); | ||
2959 | if (bus->ctrl_frame_stat) { | ||
2960 | brcmf_dbg(SDIO, "ctrl_frame timeout\n"); | ||
2961 | bus->ctrl_frame_stat = false; | ||
2962 | ret = -ETIMEDOUT; | ||
2963 | } | ||
2964 | sdio_release_host(bus->sdiodev->func[1]); | ||
2965 | } | ||
2966 | if (!ret) { | ||
2951 | brcmf_dbg(SDIO, "ctrl_frame complete, err=%d\n", | 2967 | brcmf_dbg(SDIO, "ctrl_frame complete, err=%d\n", |
2952 | bus->ctrl_frame_err); | 2968 | bus->ctrl_frame_err); |
2969 | rmb(); | ||
2953 | ret = bus->ctrl_frame_err; | 2970 | ret = bus->ctrl_frame_err; |
2954 | } else { | ||
2955 | brcmf_dbg(SDIO, "ctrl_frame timeout\n"); | ||
2956 | bus->ctrl_frame_stat = false; | ||
2957 | ret = -ETIMEDOUT; | ||
2958 | } | 2971 | } |
2959 | 2972 | ||
2960 | if (ret) | 2973 | if (ret) |
@@ -3358,9 +3371,6 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus, | |||
3358 | sdio_claim_host(bus->sdiodev->func[1]); | 3371 | sdio_claim_host(bus->sdiodev->func[1]); |
3359 | brcmf_sdio_clkctl(bus, CLK_AVAIL, false); | 3372 | brcmf_sdio_clkctl(bus, CLK_AVAIL, false); |
3360 | 3373 | ||
3361 | /* Keep arm in reset */ | ||
3362 | brcmf_chip_enter_download(bus->ci); | ||
3363 | |||
3364 | rstvec = get_unaligned_le32(fw->data); | 3374 | rstvec = get_unaligned_le32(fw->data); |
3365 | brcmf_dbg(SDIO, "firmware rstvec: %x\n", rstvec); | 3375 | brcmf_dbg(SDIO, "firmware rstvec: %x\n", rstvec); |
3366 | 3376 | ||
@@ -3380,7 +3390,7 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus, | |||
3380 | } | 3390 | } |
3381 | 3391 | ||
3382 | /* Take arm out of reset */ | 3392 | /* Take arm out of reset */ |
3383 | if (!brcmf_chip_exit_download(bus->ci, rstvec)) { | 3393 | if (!brcmf_chip_set_active(bus->ci, rstvec)) { |
3384 | brcmf_err("error getting out of ARM core reset\n"); | 3394 | brcmf_err("error getting out of ARM core reset\n"); |
3385 | goto err; | 3395 | goto err; |
3386 | } | 3396 | } |
@@ -3525,8 +3535,8 @@ done: | |||
3525 | 3535 | ||
3526 | void brcmf_sdio_trigger_dpc(struct brcmf_sdio *bus) | 3536 | void brcmf_sdio_trigger_dpc(struct brcmf_sdio *bus) |
3527 | { | 3537 | { |
3528 | if (atomic_read(&bus->dpc_tskcnt) == 0) { | 3538 | if (!bus->dpc_triggered) { |
3529 | atomic_inc(&bus->dpc_tskcnt); | 3539 | bus->dpc_triggered = true; |
3530 | queue_work(bus->brcmf_wq, &bus->datawork); | 3540 | queue_work(bus->brcmf_wq, &bus->datawork); |
3531 | } | 3541 | } |
3532 | } | 3542 | } |
@@ -3557,11 +3567,11 @@ void brcmf_sdio_isr(struct brcmf_sdio *bus) | |||
3557 | if (!bus->intr) | 3567 | if (!bus->intr) |
3558 | brcmf_err("isr w/o interrupt configured!\n"); | 3568 | brcmf_err("isr w/o interrupt configured!\n"); |
3559 | 3569 | ||
3560 | atomic_inc(&bus->dpc_tskcnt); | 3570 | bus->dpc_triggered = true; |
3561 | queue_work(bus->brcmf_wq, &bus->datawork); | 3571 | queue_work(bus->brcmf_wq, &bus->datawork); |
3562 | } | 3572 | } |
3563 | 3573 | ||
3564 | static bool brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus) | 3574 | static void brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus) |
3565 | { | 3575 | { |
3566 | brcmf_dbg(TIMER, "Enter\n"); | 3576 | brcmf_dbg(TIMER, "Enter\n"); |
3567 | 3577 | ||
@@ -3577,7 +3587,7 @@ static bool brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus) | |||
3577 | if (!bus->intr || | 3587 | if (!bus->intr || |
3578 | (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) { | 3588 | (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) { |
3579 | 3589 | ||
3580 | if (atomic_read(&bus->dpc_tskcnt) == 0) { | 3590 | if (!bus->dpc_triggered) { |
3581 | u8 devpend; | 3591 | u8 devpend; |
3582 | 3592 | ||
3583 | sdio_claim_host(bus->sdiodev->func[1]); | 3593 | sdio_claim_host(bus->sdiodev->func[1]); |
@@ -3595,7 +3605,7 @@ static bool brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus) | |||
3595 | bus->sdcnt.pollcnt++; | 3605 | bus->sdcnt.pollcnt++; |
3596 | atomic_set(&bus->ipend, 1); | 3606 | atomic_set(&bus->ipend, 1); |
3597 | 3607 | ||
3598 | atomic_inc(&bus->dpc_tskcnt); | 3608 | bus->dpc_triggered = true; |
3599 | queue_work(bus->brcmf_wq, &bus->datawork); | 3609 | queue_work(bus->brcmf_wq, &bus->datawork); |
3600 | } | 3610 | } |
3601 | } | 3611 | } |
@@ -3622,22 +3632,25 @@ static bool brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus) | |||
3622 | #endif /* DEBUG */ | 3632 | #endif /* DEBUG */ |
3623 | 3633 | ||
3624 | /* On idle timeout clear activity flag and/or turn off clock */ | 3634 | /* On idle timeout clear activity flag and/or turn off clock */ |
3625 | if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) { | 3635 | if (!bus->dpc_triggered) { |
3626 | if (++bus->idlecount >= bus->idletime) { | 3636 | rmb(); |
3627 | bus->idlecount = 0; | 3637 | if ((!bus->dpc_running) && (bus->idletime > 0) && |
3628 | if (bus->activity) { | 3638 | (bus->clkstate == CLK_AVAIL)) { |
3629 | bus->activity = false; | 3639 | bus->idlecount++; |
3630 | brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); | 3640 | if (bus->idlecount > bus->idletime) { |
3631 | } else { | ||
3632 | brcmf_dbg(SDIO, "idle\n"); | 3641 | brcmf_dbg(SDIO, "idle\n"); |
3633 | sdio_claim_host(bus->sdiodev->func[1]); | 3642 | sdio_claim_host(bus->sdiodev->func[1]); |
3643 | brcmf_sdio_wd_timer(bus, 0); | ||
3644 | bus->idlecount = 0; | ||
3634 | brcmf_sdio_bus_sleep(bus, true, false); | 3645 | brcmf_sdio_bus_sleep(bus, true, false); |
3635 | sdio_release_host(bus->sdiodev->func[1]); | 3646 | sdio_release_host(bus->sdiodev->func[1]); |
3636 | } | 3647 | } |
3648 | } else { | ||
3649 | bus->idlecount = 0; | ||
3637 | } | 3650 | } |
3651 | } else { | ||
3652 | bus->idlecount = 0; | ||
3638 | } | 3653 | } |
3639 | |||
3640 | return (atomic_read(&bus->ipend) > 0); | ||
3641 | } | 3654 | } |
3642 | 3655 | ||
3643 | static void brcmf_sdio_dataworker(struct work_struct *work) | 3656 | static void brcmf_sdio_dataworker(struct work_struct *work) |
@@ -3645,10 +3658,14 @@ static void brcmf_sdio_dataworker(struct work_struct *work) | |||
3645 | struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio, | 3658 | struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio, |
3646 | datawork); | 3659 | datawork); |
3647 | 3660 | ||
3648 | while (atomic_read(&bus->dpc_tskcnt)) { | 3661 | bus->dpc_running = true; |
3649 | atomic_set(&bus->dpc_tskcnt, 0); | 3662 | wmb(); |
3663 | while (ACCESS_ONCE(bus->dpc_triggered)) { | ||
3664 | bus->dpc_triggered = false; | ||
3650 | brcmf_sdio_dpc(bus); | 3665 | brcmf_sdio_dpc(bus); |
3666 | bus->idlecount = 0; | ||
3651 | } | 3667 | } |
3668 | bus->dpc_running = false; | ||
3652 | if (brcmf_sdiod_freezing(bus->sdiodev)) { | 3669 | if (brcmf_sdiod_freezing(bus->sdiodev)) { |
3653 | brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DOWN); | 3670 | brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DOWN); |
3654 | brcmf_sdiod_try_freeze(bus->sdiodev); | 3671 | brcmf_sdiod_try_freeze(bus->sdiodev); |
@@ -3771,8 +3788,8 @@ static int brcmf_sdio_buscoreprep(void *ctx) | |||
3771 | return 0; | 3788 | return 0; |
3772 | } | 3789 | } |
3773 | 3790 | ||
3774 | static void brcmf_sdio_buscore_exitdl(void *ctx, struct brcmf_chip *chip, | 3791 | static void brcmf_sdio_buscore_activate(void *ctx, struct brcmf_chip *chip, |
3775 | u32 rstvec) | 3792 | u32 rstvec) |
3776 | { | 3793 | { |
3777 | struct brcmf_sdio_dev *sdiodev = ctx; | 3794 | struct brcmf_sdio_dev *sdiodev = ctx; |
3778 | struct brcmf_core *core; | 3795 | struct brcmf_core *core; |
@@ -3815,7 +3832,7 @@ static void brcmf_sdio_buscore_write32(void *ctx, u32 addr, u32 val) | |||
3815 | 3832 | ||
3816 | static const struct brcmf_buscore_ops brcmf_sdio_buscore_ops = { | 3833 | static const struct brcmf_buscore_ops brcmf_sdio_buscore_ops = { |
3817 | .prepare = brcmf_sdio_buscoreprep, | 3834 | .prepare = brcmf_sdio_buscoreprep, |
3818 | .exit_dl = brcmf_sdio_buscore_exitdl, | 3835 | .activate = brcmf_sdio_buscore_activate, |
3819 | .read32 = brcmf_sdio_buscore_read32, | 3836 | .read32 = brcmf_sdio_buscore_read32, |
3820 | .write32 = brcmf_sdio_buscore_write32, | 3837 | .write32 = brcmf_sdio_buscore_write32, |
3821 | }; | 3838 | }; |
@@ -3869,13 +3886,6 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus) | |||
3869 | drivestrength = DEFAULT_SDIO_DRIVE_STRENGTH; | 3886 | drivestrength = DEFAULT_SDIO_DRIVE_STRENGTH; |
3870 | brcmf_sdio_drivestrengthinit(bus->sdiodev, bus->ci, drivestrength); | 3887 | brcmf_sdio_drivestrengthinit(bus->sdiodev, bus->ci, drivestrength); |
3871 | 3888 | ||
3872 | /* Get info on the SOCRAM cores... */ | ||
3873 | bus->ramsize = bus->ci->ramsize; | ||
3874 | if (!(bus->ramsize)) { | ||
3875 | brcmf_err("failed to find SOCRAM memory!\n"); | ||
3876 | goto fail; | ||
3877 | } | ||
3878 | |||
3879 | /* Set card control so an SDIO card reset does a WLAN backplane reset */ | 3889 | /* Set card control so an SDIO card reset does a WLAN backplane reset */ |
3880 | reg_val = brcmf_sdiod_regrb(bus->sdiodev, | 3890 | reg_val = brcmf_sdiod_regrb(bus->sdiodev, |
3881 | SDIO_CCCR_BRCM_CARDCTRL, &err); | 3891 | SDIO_CCCR_BRCM_CARDCTRL, &err); |
@@ -4148,7 +4158,8 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) | |||
4148 | bus->watchdog_tsk = NULL; | 4158 | bus->watchdog_tsk = NULL; |
4149 | } | 4159 | } |
4150 | /* Initialize DPC thread */ | 4160 | /* Initialize DPC thread */ |
4151 | atomic_set(&bus->dpc_tskcnt, 0); | 4161 | bus->dpc_triggered = false; |
4162 | bus->dpc_running = false; | ||
4152 | 4163 | ||
4153 | /* Assign bus interface call back */ | 4164 | /* Assign bus interface call back */ |
4154 | bus->sdiodev->bus_if->dev = bus->sdiodev->dev; | 4165 | bus->sdiodev->bus_if->dev = bus->sdiodev->dev; |
@@ -4243,14 +4254,14 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus) | |||
4243 | if (bus->ci) { | 4254 | if (bus->ci) { |
4244 | if (bus->sdiodev->state != BRCMF_SDIOD_NOMEDIUM) { | 4255 | if (bus->sdiodev->state != BRCMF_SDIOD_NOMEDIUM) { |
4245 | sdio_claim_host(bus->sdiodev->func[1]); | 4256 | sdio_claim_host(bus->sdiodev->func[1]); |
4257 | brcmf_sdio_wd_timer(bus, 0); | ||
4246 | brcmf_sdio_clkctl(bus, CLK_AVAIL, false); | 4258 | brcmf_sdio_clkctl(bus, CLK_AVAIL, false); |
4247 | /* Leave the device in state where it is | 4259 | /* Leave the device in state where it is |
4248 | * 'quiet'. This is done by putting it in | 4260 | * 'passive'. This is done by resetting all |
4249 | * download_state which essentially resets | 4261 | * necessary cores. |
4250 | * all necessary cores. | ||
4251 | */ | 4262 | */ |
4252 | msleep(20); | 4263 | msleep(20); |
4253 | brcmf_chip_enter_download(bus->ci); | 4264 | brcmf_chip_set_passive(bus->ci); |
4254 | brcmf_sdio_clkctl(bus, CLK_NONE, false); | 4265 | brcmf_sdio_clkctl(bus, CLK_NONE, false); |
4255 | sdio_release_host(bus->sdiodev->func[1]); | 4266 | sdio_release_host(bus->sdiodev->func[1]); |
4256 | } | 4267 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index c84af1dfc88f..369527e27689 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c | |||
@@ -4959,7 +4959,7 @@ static int brcms_b_up_prep(struct brcms_hardware *wlc_hw) | |||
4959 | * Configure pci/pcmcia here instead of in brcms_c_attach() | 4959 | * Configure pci/pcmcia here instead of in brcms_c_attach() |
4960 | * to allow mfg hotswap: down, hotswap (chip power cycle), up. | 4960 | * to allow mfg hotswap: down, hotswap (chip power cycle), up. |
4961 | */ | 4961 | */ |
4962 | bcma_core_pci_irq_ctl(wlc_hw->d11core->bus, wlc_hw->d11core, | 4962 | bcma_host_pci_irq_ctl(wlc_hw->d11core->bus, wlc_hw->d11core, |
4963 | true); | 4963 | true); |
4964 | 4964 | ||
4965 | /* | 4965 | /* |
diff --git a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h index 2124a17d0bfd..4efdd51af9c8 100644 --- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h | |||
@@ -37,6 +37,8 @@ | |||
37 | #define BRCM_CC_43362_CHIP_ID 43362 | 37 | #define BRCM_CC_43362_CHIP_ID 43362 |
38 | #define BRCM_CC_4335_CHIP_ID 0x4335 | 38 | #define BRCM_CC_4335_CHIP_ID 0x4335 |
39 | #define BRCM_CC_4339_CHIP_ID 0x4339 | 39 | #define BRCM_CC_4339_CHIP_ID 0x4339 |
40 | #define BRCM_CC_43430_CHIP_ID 43430 | ||
41 | #define BRCM_CC_4345_CHIP_ID 0x4345 | ||
40 | #define BRCM_CC_4354_CHIP_ID 0x4354 | 42 | #define BRCM_CC_4354_CHIP_ID 0x4354 |
41 | #define BRCM_CC_4356_CHIP_ID 0x4356 | 43 | #define BRCM_CC_4356_CHIP_ID 0x4356 |
42 | #define BRCM_CC_43566_CHIP_ID 43566 | 44 | #define BRCM_CC_43566_CHIP_ID 43566 |
diff --git a/drivers/net/wireless/brcm80211/include/chipcommon.h b/drivers/net/wireless/brcm80211/include/chipcommon.h index d242333b7559..e1fd499930a0 100644 --- a/drivers/net/wireless/brcm80211/include/chipcommon.h +++ b/drivers/net/wireless/brcm80211/include/chipcommon.h | |||
@@ -183,7 +183,14 @@ struct chipcregs { | |||
183 | u8 uart1lsr; | 183 | u8 uart1lsr; |
184 | u8 uart1msr; | 184 | u8 uart1msr; |
185 | u8 uart1scratch; | 185 | u8 uart1scratch; |
186 | u32 PAD[126]; | 186 | u32 PAD[62]; |
187 | |||
188 | /* save/restore, corerev >= 48 */ | ||
189 | u32 sr_capability; /* 0x500 */ | ||
190 | u32 sr_control0; /* 0x504 */ | ||
191 | u32 sr_control1; /* 0x508 */ | ||
192 | u32 gpio_control; /* 0x50C */ | ||
193 | u32 PAD[60]; | ||
187 | 194 | ||
188 | /* PMU registers (corerev >= 20) */ | 195 | /* PMU registers (corerev >= 20) */ |
189 | u32 pmucontrol; /* 0x600 */ | 196 | u32 pmucontrol; /* 0x600 */ |
diff --git a/drivers/net/wireless/cw1200/cw1200_spi.c b/drivers/net/wireless/cw1200/cw1200_spi.c index 964b64ab7fe3..7603546d2de3 100644 --- a/drivers/net/wireless/cw1200/cw1200_spi.c +++ b/drivers/net/wireless/cw1200/cw1200_spi.c | |||
@@ -447,7 +447,7 @@ static int cw1200_spi_disconnect(struct spi_device *func) | |||
447 | } | 447 | } |
448 | 448 | ||
449 | #ifdef CONFIG_PM | 449 | #ifdef CONFIG_PM |
450 | static int cw1200_spi_suspend(struct device *dev, pm_message_t state) | 450 | static int cw1200_spi_suspend(struct device *dev) |
451 | { | 451 | { |
452 | struct hwbus_priv *self = spi_get_drvdata(to_spi_device(dev)); | 452 | struct hwbus_priv *self = spi_get_drvdata(to_spi_device(dev)); |
453 | 453 | ||
@@ -458,10 +458,8 @@ static int cw1200_spi_suspend(struct device *dev, pm_message_t state) | |||
458 | return 0; | 458 | return 0; |
459 | } | 459 | } |
460 | 460 | ||
461 | static int cw1200_spi_resume(struct device *dev) | 461 | static SIMPLE_DEV_PM_OPS(cw1200_pm_ops, cw1200_spi_suspend, NULL); |
462 | { | 462 | |
463 | return 0; | ||
464 | } | ||
465 | #endif | 463 | #endif |
466 | 464 | ||
467 | static struct spi_driver spi_driver = { | 465 | static struct spi_driver spi_driver = { |
@@ -472,8 +470,7 @@ static struct spi_driver spi_driver = { | |||
472 | .bus = &spi_bus_type, | 470 | .bus = &spi_bus_type, |
473 | .owner = THIS_MODULE, | 471 | .owner = THIS_MODULE, |
474 | #ifdef CONFIG_PM | 472 | #ifdef CONFIG_PM |
475 | .suspend = cw1200_spi_suspend, | 473 | .pm = &cw1200_pm_ops, |
476 | .resume = cw1200_spi_resume, | ||
477 | #endif | 474 | #endif |
478 | }, | 475 | }, |
479 | }; | 476 | }; |
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index 5707ba5ce23f..5abd62ed8cb4 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c | |||
@@ -1114,16 +1114,17 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
1114 | scd_queues &= ~(BIT(IWL_IPAN_CMD_QUEUE_NUM) | | 1114 | scd_queues &= ~(BIT(IWL_IPAN_CMD_QUEUE_NUM) | |
1115 | BIT(IWL_DEFAULT_CMD_QUEUE_NUM)); | 1115 | BIT(IWL_DEFAULT_CMD_QUEUE_NUM)); |
1116 | 1116 | ||
1117 | if (vif) | 1117 | if (drop) { |
1118 | scd_queues &= ~BIT(vif->hw_queue[IEEE80211_AC_VO]); | 1118 | IWL_DEBUG_TX_QUEUES(priv, "Flushing SCD queues: 0x%x\n", |
1119 | 1119 | scd_queues); | |
1120 | IWL_DEBUG_TX_QUEUES(priv, "Flushing SCD queues: 0x%x\n", scd_queues); | 1120 | if (iwlagn_txfifo_flush(priv, scd_queues)) { |
1121 | if (iwlagn_txfifo_flush(priv, scd_queues)) { | 1121 | IWL_ERR(priv, "flush request fail\n"); |
1122 | IWL_ERR(priv, "flush request fail\n"); | 1122 | goto done; |
1123 | goto done; | 1123 | } |
1124 | } | 1124 | } |
1125 | |||
1125 | IWL_DEBUG_TX_QUEUES(priv, "wait transmit/flush all frames\n"); | 1126 | IWL_DEBUG_TX_QUEUES(priv, "wait transmit/flush all frames\n"); |
1126 | iwl_trans_wait_tx_queue_empty(priv->trans, 0xffffffff); | 1127 | iwl_trans_wait_tx_queue_empty(priv->trans, scd_queues); |
1127 | done: | 1128 | done: |
1128 | mutex_unlock(&priv->mutex); | 1129 | mutex_unlock(&priv->mutex); |
1129 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 1130 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.c b/drivers/net/wireless/iwlwifi/dvm/rs.c index 32b78a66536d..3bd7c86e90d9 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rs.c +++ b/drivers/net/wireless/iwlwifi/dvm/rs.c | |||
@@ -3153,12 +3153,13 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | |||
3153 | desc += sprintf(buff+desc, "lq type %s\n", | 3153 | desc += sprintf(buff+desc, "lq type %s\n", |
3154 | (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); | 3154 | (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); |
3155 | if (is_Ht(tbl->lq_type)) { | 3155 | if (is_Ht(tbl->lq_type)) { |
3156 | desc += sprintf(buff+desc, " %s", | 3156 | desc += sprintf(buff + desc, " %s", |
3157 | (is_siso(tbl->lq_type)) ? "SISO" : | 3157 | (is_siso(tbl->lq_type)) ? "SISO" : |
3158 | ((is_mimo2(tbl->lq_type)) ? "MIMO2" : "MIMO3")); | 3158 | ((is_mimo2(tbl->lq_type)) ? "MIMO2" : "MIMO3")); |
3159 | desc += sprintf(buff+desc, " %s", | 3159 | desc += sprintf(buff + desc, " %s", |
3160 | (tbl->is_ht40) ? "40MHz" : "20MHz"); | 3160 | (tbl->is_ht40) ? "40MHz" : "20MHz"); |
3161 | desc += sprintf(buff+desc, " %s %s %s\n", (tbl->is_SGI) ? "SGI" : "", | 3161 | desc += sprintf(buff + desc, " %s %s %s\n", |
3162 | (tbl->is_SGI) ? "SGI" : "", | ||
3162 | (lq_sta->is_green) ? "GF enabled" : "", | 3163 | (lq_sta->is_green) ? "GF enabled" : "", |
3163 | (lq_sta->is_agg) ? "AGG on" : ""); | 3164 | (lq_sta->is_agg) ? "AGG on" : ""); |
3164 | } | 3165 | } |
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index 1e40a12de077..275df12a6045 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c | |||
@@ -189,9 +189,9 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, | |||
189 | rate_flags |= RATE_MCS_CCK_MSK; | 189 | rate_flags |= RATE_MCS_CCK_MSK; |
190 | 190 | ||
191 | /* Set up antennas */ | 191 | /* Set up antennas */ |
192 | if (priv->lib->bt_params && | 192 | if (priv->lib->bt_params && |
193 | priv->lib->bt_params->advanced_bt_coexist && | 193 | priv->lib->bt_params->advanced_bt_coexist && |
194 | priv->bt_full_concurrent) { | 194 | priv->bt_full_concurrent) { |
195 | /* operated as 1x1 in full concurrency mode */ | 195 | /* operated as 1x1 in full concurrency mode */ |
196 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | 196 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, |
197 | first_antenna(priv->nvm_data->valid_tx_ant)); | 197 | first_antenna(priv->nvm_data->valid_tx_ant)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index 0597a9cfd2f6..36e786f0387b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c | |||
@@ -69,12 +69,12 @@ | |||
69 | #include "iwl-agn-hw.h" | 69 | #include "iwl-agn-hw.h" |
70 | 70 | ||
71 | /* Highest firmware API version supported */ | 71 | /* Highest firmware API version supported */ |
72 | #define IWL7260_UCODE_API_MAX 12 | 72 | #define IWL7260_UCODE_API_MAX 13 |
73 | #define IWL3160_UCODE_API_MAX 12 | 73 | #define IWL3160_UCODE_API_MAX 13 |
74 | 74 | ||
75 | /* Oldest version we won't warn about */ | 75 | /* Oldest version we won't warn about */ |
76 | #define IWL7260_UCODE_API_OK 10 | 76 | #define IWL7260_UCODE_API_OK 12 |
77 | #define IWL3160_UCODE_API_OK 10 | 77 | #define IWL3160_UCODE_API_OK 12 |
78 | 78 | ||
79 | /* Lowest firmware API version supported */ | 79 | /* Lowest firmware API version supported */ |
80 | #define IWL7260_UCODE_API_MIN 10 | 80 | #define IWL7260_UCODE_API_MIN 10 |
diff --git a/drivers/net/wireless/iwlwifi/iwl-8000.c b/drivers/net/wireless/iwlwifi/iwl-8000.c index d8dfa6da6307..9c396a42aec8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-8000.c +++ b/drivers/net/wireless/iwlwifi/iwl-8000.c | |||
@@ -69,10 +69,10 @@ | |||
69 | #include "iwl-agn-hw.h" | 69 | #include "iwl-agn-hw.h" |
70 | 70 | ||
71 | /* Highest firmware API version supported */ | 71 | /* Highest firmware API version supported */ |
72 | #define IWL8000_UCODE_API_MAX 12 | 72 | #define IWL8000_UCODE_API_MAX 13 |
73 | 73 | ||
74 | /* Oldest version we won't warn about */ | 74 | /* Oldest version we won't warn about */ |
75 | #define IWL8000_UCODE_API_OK 10 | 75 | #define IWL8000_UCODE_API_OK 12 |
76 | 76 | ||
77 | /* Lowest firmware API version supported */ | 77 | /* Lowest firmware API version supported */ |
78 | #define IWL8000_UCODE_API_MIN 10 | 78 | #define IWL8000_UCODE_API_MIN 10 |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 684254553558..9bb36d79c2bd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h | |||
@@ -157,6 +157,7 @@ do { \ | |||
157 | /* 0x0000F000 - 0x00001000 */ | 157 | /* 0x0000F000 - 0x00001000 */ |
158 | #define IWL_DL_ASSOC 0x00001000 | 158 | #define IWL_DL_ASSOC 0x00001000 |
159 | #define IWL_DL_DROP 0x00002000 | 159 | #define IWL_DL_DROP 0x00002000 |
160 | #define IWL_DL_LAR 0x00004000 | ||
160 | #define IWL_DL_COEX 0x00008000 | 161 | #define IWL_DL_COEX 0x00008000 |
161 | /* 0x000F0000 - 0x00010000 */ | 162 | /* 0x000F0000 - 0x00010000 */ |
162 | #define IWL_DL_FW 0x00010000 | 163 | #define IWL_DL_FW 0x00010000 |
@@ -219,5 +220,6 @@ do { \ | |||
219 | #define IWL_DEBUG_POWER(p, f, a...) IWL_DEBUG(p, IWL_DL_POWER, f, ## a) | 220 | #define IWL_DEBUG_POWER(p, f, a...) IWL_DEBUG(p, IWL_DL_POWER, f, ## a) |
220 | #define IWL_DEBUG_11H(p, f, a...) IWL_DEBUG(p, IWL_DL_11H, f, ## a) | 221 | #define IWL_DEBUG_11H(p, f, a...) IWL_DEBUG(p, IWL_DL_11H, f, ## a) |
221 | #define IWL_DEBUG_RPM(p, f, a...) IWL_DEBUG(p, IWL_DL_RPM, f, ## a) | 222 | #define IWL_DEBUG_RPM(p, f, a...) IWL_DEBUG(p, IWL_DL_RPM, f, ## a) |
223 | #define IWL_DEBUG_LAR(p, f, a...) IWL_DEBUG(p, IWL_DL_LAR, f, ## a) | ||
222 | 224 | ||
223 | #endif | 225 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 141331d41abf..66ca000f0da1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
@@ -1014,34 +1014,34 @@ static int validate_sec_sizes(struct iwl_drv *drv, | |||
1014 | 1014 | ||
1015 | /* Verify that uCode images will fit in card's SRAM. */ | 1015 | /* Verify that uCode images will fit in card's SRAM. */ |
1016 | if (get_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_INST) > | 1016 | if (get_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_INST) > |
1017 | cfg->max_inst_size) { | 1017 | cfg->max_inst_size) { |
1018 | IWL_ERR(drv, "uCode instr len %Zd too large to fit in\n", | 1018 | IWL_ERR(drv, "uCode instr len %Zd too large to fit in\n", |
1019 | get_sec_size(pieces, IWL_UCODE_REGULAR, | 1019 | get_sec_size(pieces, IWL_UCODE_REGULAR, |
1020 | IWL_UCODE_SECTION_INST)); | 1020 | IWL_UCODE_SECTION_INST)); |
1021 | return -1; | 1021 | return -1; |
1022 | } | 1022 | } |
1023 | 1023 | ||
1024 | if (get_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_DATA) > | 1024 | if (get_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_DATA) > |
1025 | cfg->max_data_size) { | 1025 | cfg->max_data_size) { |
1026 | IWL_ERR(drv, "uCode data len %Zd too large to fit in\n", | 1026 | IWL_ERR(drv, "uCode data len %Zd too large to fit in\n", |
1027 | get_sec_size(pieces, IWL_UCODE_REGULAR, | 1027 | get_sec_size(pieces, IWL_UCODE_REGULAR, |
1028 | IWL_UCODE_SECTION_DATA)); | 1028 | IWL_UCODE_SECTION_DATA)); |
1029 | return -1; | 1029 | return -1; |
1030 | } | 1030 | } |
1031 | 1031 | ||
1032 | if (get_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST) > | 1032 | if (get_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST) > |
1033 | cfg->max_inst_size) { | 1033 | cfg->max_inst_size) { |
1034 | IWL_ERR(drv, "uCode init instr len %Zd too large to fit in\n", | 1034 | IWL_ERR(drv, "uCode init instr len %Zd too large to fit in\n", |
1035 | get_sec_size(pieces, IWL_UCODE_INIT, | 1035 | get_sec_size(pieces, IWL_UCODE_INIT, |
1036 | IWL_UCODE_SECTION_INST)); | 1036 | IWL_UCODE_SECTION_INST)); |
1037 | return -1; | 1037 | return -1; |
1038 | } | 1038 | } |
1039 | 1039 | ||
1040 | if (get_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA) > | 1040 | if (get_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA) > |
1041 | cfg->max_data_size) { | 1041 | cfg->max_data_size) { |
1042 | IWL_ERR(drv, "uCode init data len %Zd too large to fit in\n", | 1042 | IWL_ERR(drv, "uCode init data len %Zd too large to fit in\n", |
1043 | get_sec_size(pieces, IWL_UCODE_REGULAR, | 1043 | get_sec_size(pieces, IWL_UCODE_REGULAR, |
1044 | IWL_UCODE_SECTION_DATA)); | 1044 | IWL_UCODE_SECTION_DATA)); |
1045 | return -1; | 1045 | return -1; |
1046 | } | 1046 | } |
1047 | return 0; | 1047 | return 0; |
@@ -1546,6 +1546,10 @@ module_param_named(d0i3_disable, iwlwifi_mod_params.d0i3_disable, | |||
1546 | bool, S_IRUGO); | 1546 | bool, S_IRUGO); |
1547 | MODULE_PARM_DESC(d0i3_disable, "disable d0i3 functionality (default: Y)"); | 1547 | MODULE_PARM_DESC(d0i3_disable, "disable d0i3 functionality (default: Y)"); |
1548 | 1548 | ||
1549 | module_param_named(lar_disable, iwlwifi_mod_params.lar_disable, | ||
1550 | bool, S_IRUGO); | ||
1551 | MODULE_PARM_DESC(lar_disable, "disable LAR functionality (default: N)"); | ||
1552 | |||
1549 | module_param_named(uapsd_disable, iwlwifi_mod_params.uapsd_disable, | 1553 | module_param_named(uapsd_disable, iwlwifi_mod_params.uapsd_disable, |
1550 | bool, S_IRUGO | S_IWUSR); | 1554 | bool, S_IRUGO | S_IWUSR); |
1551 | #ifdef CONFIG_IWLWIFI_UAPSD | 1555 | #ifdef CONFIG_IWLWIFI_UAPSD |
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.h b/drivers/net/wireless/iwlwifi/iwl-drv.h index adf522c756e6..67a3a241b331 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.h +++ b/drivers/net/wireless/iwlwifi/iwl-drv.h | |||
@@ -68,7 +68,7 @@ | |||
68 | 68 | ||
69 | /* for all modules */ | 69 | /* for all modules */ |
70 | #define DRV_NAME "iwlwifi" | 70 | #define DRV_NAME "iwlwifi" |
71 | #define DRV_COPYRIGHT "Copyright(c) 2003- 2014 Intel Corporation" | 71 | #define DRV_COPYRIGHT "Copyright(c) 2003- 2015 Intel Corporation" |
72 | #define DRV_AUTHOR "<ilw@linux.intel.com>" | 72 | #define DRV_AUTHOR "<ilw@linux.intel.com>" |
73 | 73 | ||
74 | /* radio config bits (actual values from NVM definition) */ | 74 | /* radio config bits (actual values from NVM definition) */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h index f0548b8a64b0..5234a0bf11e4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h | |||
@@ -94,6 +94,7 @@ struct iwl_nvm_data { | |||
94 | u32 nvm_version; | 94 | u32 nvm_version; |
95 | s8 max_tx_pwr_half_dbm; | 95 | s8 max_tx_pwr_half_dbm; |
96 | 96 | ||
97 | bool lar_enabled; | ||
97 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; | 98 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; |
98 | struct ieee80211_channel channels[]; | 99 | struct ieee80211_channel channels[]; |
99 | }; | 100 | }; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index 5ea381861d5d..291a3382aa3f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h | |||
@@ -240,10 +240,9 @@ enum iwl_ucode_tlv_flag { | |||
240 | /** | 240 | /** |
241 | * enum iwl_ucode_tlv_api - ucode api | 241 | * enum iwl_ucode_tlv_api - ucode api |
242 | * @IWL_UCODE_TLV_API_BT_COEX_SPLIT: new API for BT Coex | 242 | * @IWL_UCODE_TLV_API_BT_COEX_SPLIT: new API for BT Coex |
243 | * @IWL_UCODE_TLV_API_DISABLE_STA_TX: ucode supports tx_disable bit. | ||
244 | * @IWL_UCODE_TLV_API_SF_NO_DUMMY_NOTIF: ucode supports disabling dummy notif. | ||
245 | * @IWL_UCODE_TLV_API_FRAGMENTED_SCAN: This ucode supports active dwell time | 243 | * @IWL_UCODE_TLV_API_FRAGMENTED_SCAN: This ucode supports active dwell time |
246 | * longer than the passive one, which is essential for fragmented scan. | 244 | * longer than the passive one, which is essential for fragmented scan. |
245 | * @IWL_UCODE_TLV_API_WIFI_MCC_UPDATE: ucode supports MCC updates with source. | ||
247 | * IWL_UCODE_TLV_API_HDC_PHASE_0: ucode supports finer configuration of LTR | 246 | * IWL_UCODE_TLV_API_HDC_PHASE_0: ucode supports finer configuration of LTR |
248 | * @IWL_UCODE_TLV_API_BASIC_DWELL: use only basic dwell time in scan command, | 247 | * @IWL_UCODE_TLV_API_BASIC_DWELL: use only basic dwell time in scan command, |
249 | * regardless of the band or the number of the probes. FW will calculate | 248 | * regardless of the band or the number of the probes. FW will calculate |
@@ -258,9 +257,8 @@ enum iwl_ucode_tlv_flag { | |||
258 | */ | 257 | */ |
259 | enum iwl_ucode_tlv_api { | 258 | enum iwl_ucode_tlv_api { |
260 | IWL_UCODE_TLV_API_BT_COEX_SPLIT = BIT(3), | 259 | IWL_UCODE_TLV_API_BT_COEX_SPLIT = BIT(3), |
261 | IWL_UCODE_TLV_API_DISABLE_STA_TX = BIT(5), | ||
262 | IWL_UCODE_TLV_API_SF_NO_DUMMY_NOTIF = BIT(7), | ||
263 | IWL_UCODE_TLV_API_FRAGMENTED_SCAN = BIT(8), | 260 | IWL_UCODE_TLV_API_FRAGMENTED_SCAN = BIT(8), |
261 | IWL_UCODE_TLV_API_WIFI_MCC_UPDATE = BIT(9), | ||
264 | IWL_UCODE_TLV_API_HDC_PHASE_0 = BIT(10), | 262 | IWL_UCODE_TLV_API_HDC_PHASE_0 = BIT(10), |
265 | IWL_UCODE_TLV_API_BASIC_DWELL = BIT(13), | 263 | IWL_UCODE_TLV_API_BASIC_DWELL = BIT(13), |
266 | IWL_UCODE_TLV_API_SCD_CFG = BIT(15), | 264 | IWL_UCODE_TLV_API_SCD_CFG = BIT(15), |
@@ -292,6 +290,7 @@ enum iwl_ucode_tlv_api { | |||
292 | * @IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT: supports Hot Spot Command | 290 | * @IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT: supports Hot Spot Command |
293 | * @IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS: support radio and beacon statistics | 291 | * @IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS: support radio and beacon statistics |
294 | * @IWL_UCODE_TLV_CAPA_BT_COEX_PLCR: enabled BT Coex packet level co-running | 292 | * @IWL_UCODE_TLV_CAPA_BT_COEX_PLCR: enabled BT Coex packet level co-running |
293 | * @IWL_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC | ||
295 | */ | 294 | */ |
296 | enum iwl_ucode_tlv_capa { | 295 | enum iwl_ucode_tlv_capa { |
297 | IWL_UCODE_TLV_CAPA_D0I3_SUPPORT = BIT(0), | 296 | IWL_UCODE_TLV_CAPA_D0I3_SUPPORT = BIT(0), |
@@ -308,6 +307,7 @@ enum iwl_ucode_tlv_capa { | |||
308 | IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT = BIT(18), | 307 | IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT = BIT(18), |
309 | IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS = BIT(22), | 308 | IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS = BIT(22), |
310 | IWL_UCODE_TLV_CAPA_BT_COEX_PLCR = BIT(28), | 309 | IWL_UCODE_TLV_CAPA_BT_COEX_PLCR = BIT(28), |
310 | IWL_UCODE_TLV_CAPA_BT_COEX_RRC = BIT(30), | ||
311 | }; | 311 | }; |
312 | 312 | ||
313 | /* The default calibrate table size if not specified by firmware file */ | 313 | /* The default calibrate table size if not specified by firmware file */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index 03250a45272e..78cac43e2bcd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c | |||
@@ -201,6 +201,8 @@ void iwl_force_nmi(struct iwl_trans *trans) | |||
201 | } else { | 201 | } else { |
202 | iwl_write_prph(trans, DEVICE_SET_NMI_8000B_REG, | 202 | iwl_write_prph(trans, DEVICE_SET_NMI_8000B_REG, |
203 | DEVICE_SET_NMI_8000B_VAL); | 203 | DEVICE_SET_NMI_8000B_VAL); |
204 | iwl_write_prph(trans, DEVICE_SET_NMI_REG, | ||
205 | DEVICE_SET_NMI_VAL_DRV); | ||
204 | } | 206 | } |
205 | } | 207 | } |
206 | IWL_EXPORT_SYMBOL(iwl_force_nmi); | 208 | IWL_EXPORT_SYMBOL(iwl_force_nmi); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h index e8eabd21ccfe..ac2b90df8413 100644 --- a/drivers/net/wireless/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h | |||
@@ -103,6 +103,7 @@ enum iwl_disable_11n { | |||
103 | * @debug_level: levels are IWL_DL_* | 103 | * @debug_level: levels are IWL_DL_* |
104 | * @ant_coupling: antenna coupling in dB, default = 0 | 104 | * @ant_coupling: antenna coupling in dB, default = 0 |
105 | * @d0i3_disable: disable d0i3, default = 1, | 105 | * @d0i3_disable: disable d0i3, default = 1, |
106 | * @lar_disable: disable LAR (regulatory), default = 0 | ||
106 | * @fw_monitor: allow to use firmware monitor | 107 | * @fw_monitor: allow to use firmware monitor |
107 | */ | 108 | */ |
108 | struct iwl_mod_params { | 109 | struct iwl_mod_params { |
@@ -121,6 +122,7 @@ struct iwl_mod_params { | |||
121 | char *nvm_file; | 122 | char *nvm_file; |
122 | bool uapsd_disable; | 123 | bool uapsd_disable; |
123 | bool d0i3_disable; | 124 | bool d0i3_disable; |
125 | bool lar_disable; | ||
124 | bool fw_monitor; | 126 | bool fw_monitor; |
125 | }; | 127 | }; |
126 | 128 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index c74f1a4edf23..774637746427 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | |||
@@ -103,8 +103,16 @@ enum family_8000_nvm_offsets { | |||
103 | SKU_FAMILY_8000 = 4, | 103 | SKU_FAMILY_8000 = 4, |
104 | N_HW_ADDRS_FAMILY_8000 = 5, | 104 | N_HW_ADDRS_FAMILY_8000 = 5, |
105 | 105 | ||
106 | /* NVM PHY-SKU-Section offset (in words) for B0 */ | ||
107 | RADIO_CFG_FAMILY_8000_B0 = 0, | ||
108 | SKU_FAMILY_8000_B0 = 2, | ||
109 | N_HW_ADDRS_FAMILY_8000_B0 = 3, | ||
110 | |||
106 | /* NVM REGULATORY -Section offset (in words) definitions */ | 111 | /* NVM REGULATORY -Section offset (in words) definitions */ |
107 | NVM_CHANNELS_FAMILY_8000 = 0, | 112 | NVM_CHANNELS_FAMILY_8000 = 0, |
113 | NVM_LAR_OFFSET_FAMILY_8000_OLD = 0x4C7, | ||
114 | NVM_LAR_OFFSET_FAMILY_8000 = 0x507, | ||
115 | NVM_LAR_ENABLED_FAMILY_8000 = 0x7, | ||
108 | 116 | ||
109 | /* NVM calibration section offset (in words) definitions */ | 117 | /* NVM calibration section offset (in words) definitions */ |
110 | NVM_CALIB_SECTION_FAMILY_8000 = 0x2B8, | 118 | NVM_CALIB_SECTION_FAMILY_8000 = 0x2B8, |
@@ -146,7 +154,9 @@ static const u8 iwl_nvm_channels_family_8000[] = { | |||
146 | #define NUM_2GHZ_CHANNELS_FAMILY_8000 14 | 154 | #define NUM_2GHZ_CHANNELS_FAMILY_8000 14 |
147 | #define FIRST_2GHZ_HT_MINUS 5 | 155 | #define FIRST_2GHZ_HT_MINUS 5 |
148 | #define LAST_2GHZ_HT_PLUS 9 | 156 | #define LAST_2GHZ_HT_PLUS 9 |
149 | #define LAST_5GHZ_HT 161 | 157 | #define LAST_5GHZ_HT 165 |
158 | #define LAST_5GHZ_HT_FAMILY_8000 181 | ||
159 | #define N_HW_ADDR_MASK 0xF | ||
150 | 160 | ||
151 | /* rate data (static) */ | 161 | /* rate data (static) */ |
152 | static struct ieee80211_rate iwl_cfg80211_rates[] = { | 162 | static struct ieee80211_rate iwl_cfg80211_rates[] = { |
@@ -201,9 +211,57 @@ enum iwl_nvm_channel_flags { | |||
201 | #define CHECK_AND_PRINT_I(x) \ | 211 | #define CHECK_AND_PRINT_I(x) \ |
202 | ((ch_flags & NVM_CHANNEL_##x) ? # x " " : "") | 212 | ((ch_flags & NVM_CHANNEL_##x) ? # x " " : "") |
203 | 213 | ||
214 | static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz, | ||
215 | u16 nvm_flags, const struct iwl_cfg *cfg) | ||
216 | { | ||
217 | u32 flags = IEEE80211_CHAN_NO_HT40; | ||
218 | u32 last_5ghz_ht = LAST_5GHZ_HT; | ||
219 | |||
220 | if (cfg->device_family == IWL_DEVICE_FAMILY_8000) | ||
221 | last_5ghz_ht = LAST_5GHZ_HT_FAMILY_8000; | ||
222 | |||
223 | if (!is_5ghz && (nvm_flags & NVM_CHANNEL_40MHZ)) { | ||
224 | if (ch_num <= LAST_2GHZ_HT_PLUS) | ||
225 | flags &= ~IEEE80211_CHAN_NO_HT40PLUS; | ||
226 | if (ch_num >= FIRST_2GHZ_HT_MINUS) | ||
227 | flags &= ~IEEE80211_CHAN_NO_HT40MINUS; | ||
228 | } else if (ch_num <= last_5ghz_ht && (nvm_flags & NVM_CHANNEL_40MHZ)) { | ||
229 | if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0) | ||
230 | flags &= ~IEEE80211_CHAN_NO_HT40PLUS; | ||
231 | else | ||
232 | flags &= ~IEEE80211_CHAN_NO_HT40MINUS; | ||
233 | } | ||
234 | if (!(nvm_flags & NVM_CHANNEL_80MHZ)) | ||
235 | flags |= IEEE80211_CHAN_NO_80MHZ; | ||
236 | if (!(nvm_flags & NVM_CHANNEL_160MHZ)) | ||
237 | flags |= IEEE80211_CHAN_NO_160MHZ; | ||
238 | |||
239 | if (!(nvm_flags & NVM_CHANNEL_IBSS)) | ||
240 | flags |= IEEE80211_CHAN_NO_IR; | ||
241 | |||
242 | if (!(nvm_flags & NVM_CHANNEL_ACTIVE)) | ||
243 | flags |= IEEE80211_CHAN_NO_IR; | ||
244 | |||
245 | if (nvm_flags & NVM_CHANNEL_RADAR) | ||
246 | flags |= IEEE80211_CHAN_RADAR; | ||
247 | |||
248 | if (nvm_flags & NVM_CHANNEL_INDOOR_ONLY) | ||
249 | flags |= IEEE80211_CHAN_INDOOR_ONLY; | ||
250 | |||
251 | /* Set the GO concurrent flag only in case that NO_IR is set. | ||
252 | * Otherwise it is meaningless | ||
253 | */ | ||
254 | if ((nvm_flags & NVM_CHANNEL_GO_CONCURRENT) && | ||
255 | (flags & IEEE80211_CHAN_NO_IR)) | ||
256 | flags |= IEEE80211_CHAN_GO_CONCURRENT; | ||
257 | |||
258 | return flags; | ||
259 | } | ||
260 | |||
204 | static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | 261 | static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, |
205 | struct iwl_nvm_data *data, | 262 | struct iwl_nvm_data *data, |
206 | const __le16 * const nvm_ch_flags) | 263 | const __le16 * const nvm_ch_flags, |
264 | bool lar_supported) | ||
207 | { | 265 | { |
208 | int ch_idx; | 266 | int ch_idx; |
209 | int n_channels = 0; | 267 | int n_channels = 0; |
@@ -228,9 +286,14 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
228 | 286 | ||
229 | if (ch_idx >= num_2ghz_channels && | 287 | if (ch_idx >= num_2ghz_channels && |
230 | !data->sku_cap_band_52GHz_enable) | 288 | !data->sku_cap_band_52GHz_enable) |
231 | ch_flags &= ~NVM_CHANNEL_VALID; | 289 | continue; |
232 | 290 | ||
233 | if (!(ch_flags & NVM_CHANNEL_VALID)) { | 291 | if (!lar_supported && !(ch_flags & NVM_CHANNEL_VALID)) { |
292 | /* | ||
293 | * Channels might become valid later if lar is | ||
294 | * supported, hence we still want to add them to | ||
295 | * the list of supported channels to cfg80211. | ||
296 | */ | ||
234 | IWL_DEBUG_EEPROM(dev, | 297 | IWL_DEBUG_EEPROM(dev, |
235 | "Ch. %d Flags %x [%sGHz] - No traffic\n", | 298 | "Ch. %d Flags %x [%sGHz] - No traffic\n", |
236 | nvm_chan[ch_idx], | 299 | nvm_chan[ch_idx], |
@@ -250,45 +313,6 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
250 | ieee80211_channel_to_frequency( | 313 | ieee80211_channel_to_frequency( |
251 | channel->hw_value, channel->band); | 314 | channel->hw_value, channel->band); |
252 | 315 | ||
253 | /* TODO: Need to be dependent to the NVM */ | ||
254 | channel->flags = IEEE80211_CHAN_NO_HT40; | ||
255 | if (ch_idx < num_2ghz_channels && | ||
256 | (ch_flags & NVM_CHANNEL_40MHZ)) { | ||
257 | if (nvm_chan[ch_idx] <= LAST_2GHZ_HT_PLUS) | ||
258 | channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS; | ||
259 | if (nvm_chan[ch_idx] >= FIRST_2GHZ_HT_MINUS) | ||
260 | channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS; | ||
261 | } else if (nvm_chan[ch_idx] <= LAST_5GHZ_HT && | ||
262 | (ch_flags & NVM_CHANNEL_40MHZ)) { | ||
263 | if ((ch_idx - num_2ghz_channels) % 2 == 0) | ||
264 | channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS; | ||
265 | else | ||
266 | channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS; | ||
267 | } | ||
268 | if (!(ch_flags & NVM_CHANNEL_80MHZ)) | ||
269 | channel->flags |= IEEE80211_CHAN_NO_80MHZ; | ||
270 | if (!(ch_flags & NVM_CHANNEL_160MHZ)) | ||
271 | channel->flags |= IEEE80211_CHAN_NO_160MHZ; | ||
272 | |||
273 | if (!(ch_flags & NVM_CHANNEL_IBSS)) | ||
274 | channel->flags |= IEEE80211_CHAN_NO_IR; | ||
275 | |||
276 | if (!(ch_flags & NVM_CHANNEL_ACTIVE)) | ||
277 | channel->flags |= IEEE80211_CHAN_NO_IR; | ||
278 | |||
279 | if (ch_flags & NVM_CHANNEL_RADAR) | ||
280 | channel->flags |= IEEE80211_CHAN_RADAR; | ||
281 | |||
282 | if (ch_flags & NVM_CHANNEL_INDOOR_ONLY) | ||
283 | channel->flags |= IEEE80211_CHAN_INDOOR_ONLY; | ||
284 | |||
285 | /* Set the GO concurrent flag only in case that NO_IR is set. | ||
286 | * Otherwise it is meaningless | ||
287 | */ | ||
288 | if ((ch_flags & NVM_CHANNEL_GO_CONCURRENT) && | ||
289 | (channel->flags & IEEE80211_CHAN_NO_IR)) | ||
290 | channel->flags |= IEEE80211_CHAN_GO_CONCURRENT; | ||
291 | |||
292 | /* Initialize regulatory-based run-time data */ | 316 | /* Initialize regulatory-based run-time data */ |
293 | 317 | ||
294 | /* | 318 | /* |
@@ -297,6 +321,15 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
297 | */ | 321 | */ |
298 | channel->max_power = IWL_DEFAULT_MAX_TX_POWER; | 322 | channel->max_power = IWL_DEFAULT_MAX_TX_POWER; |
299 | is_5ghz = channel->band == IEEE80211_BAND_5GHZ; | 323 | is_5ghz = channel->band == IEEE80211_BAND_5GHZ; |
324 | |||
325 | /* don't put limitations in case we're using LAR */ | ||
326 | if (!lar_supported) | ||
327 | channel->flags = iwl_get_channel_flags(nvm_chan[ch_idx], | ||
328 | ch_idx, is_5ghz, | ||
329 | ch_flags, cfg); | ||
330 | else | ||
331 | channel->flags = 0; | ||
332 | |||
300 | IWL_DEBUG_EEPROM(dev, | 333 | IWL_DEBUG_EEPROM(dev, |
301 | "Ch. %d [%sGHz] %s%s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n", | 334 | "Ch. %d [%sGHz] %s%s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n", |
302 | channel->hw_value, | 335 | channel->hw_value, |
@@ -370,8 +403,8 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, | |||
370 | 403 | ||
371 | static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | 404 | static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, |
372 | struct iwl_nvm_data *data, | 405 | struct iwl_nvm_data *data, |
373 | const __le16 *ch_section, bool enable_vht, | 406 | const __le16 *ch_section, |
374 | u8 tx_chains, u8 rx_chains) | 407 | u8 tx_chains, u8 rx_chains, bool lar_supported) |
375 | { | 408 | { |
376 | int n_channels; | 409 | int n_channels; |
377 | int n_used = 0; | 410 | int n_used = 0; |
@@ -380,11 +413,12 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | |||
380 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) | 413 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) |
381 | n_channels = iwl_init_channel_map( | 414 | n_channels = iwl_init_channel_map( |
382 | dev, cfg, data, | 415 | dev, cfg, data, |
383 | &ch_section[NVM_CHANNELS]); | 416 | &ch_section[NVM_CHANNELS], lar_supported); |
384 | else | 417 | else |
385 | n_channels = iwl_init_channel_map( | 418 | n_channels = iwl_init_channel_map( |
386 | dev, cfg, data, | 419 | dev, cfg, data, |
387 | &ch_section[NVM_CHANNELS_FAMILY_8000]); | 420 | &ch_section[NVM_CHANNELS_FAMILY_8000], |
421 | lar_supported); | ||
388 | 422 | ||
389 | sband = &data->bands[IEEE80211_BAND_2GHZ]; | 423 | sband = &data->bands[IEEE80211_BAND_2GHZ]; |
390 | sband->band = IEEE80211_BAND_2GHZ; | 424 | sband->band = IEEE80211_BAND_2GHZ; |
@@ -403,7 +437,7 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | |||
403 | IEEE80211_BAND_5GHZ); | 437 | IEEE80211_BAND_5GHZ); |
404 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ, | 438 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ, |
405 | tx_chains, rx_chains); | 439 | tx_chains, rx_chains); |
406 | if (enable_vht) | 440 | if (data->sku_cap_11ac_enable) |
407 | iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap, | 441 | iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap, |
408 | tx_chains, rx_chains); | 442 | tx_chains, rx_chains); |
409 | 443 | ||
@@ -413,10 +447,15 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | |||
413 | } | 447 | } |
414 | 448 | ||
415 | static int iwl_get_sku(const struct iwl_cfg *cfg, | 449 | static int iwl_get_sku(const struct iwl_cfg *cfg, |
416 | const __le16 *nvm_sw) | 450 | const __le16 *nvm_sw, const __le16 *phy_sku, |
451 | bool is_family_8000_a_step) | ||
417 | { | 452 | { |
418 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) | 453 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) |
419 | return le16_to_cpup(nvm_sw + SKU); | 454 | return le16_to_cpup(nvm_sw + SKU); |
455 | |||
456 | if (!is_family_8000_a_step) | ||
457 | return le32_to_cpup((__le32 *)(phy_sku + | ||
458 | SKU_FAMILY_8000_B0)); | ||
420 | else | 459 | else |
421 | return le32_to_cpup((__le32 *)(nvm_sw + SKU_FAMILY_8000)); | 460 | return le32_to_cpup((__le32 *)(nvm_sw + SKU_FAMILY_8000)); |
422 | } | 461 | } |
@@ -432,23 +471,36 @@ static int iwl_get_nvm_version(const struct iwl_cfg *cfg, | |||
432 | } | 471 | } |
433 | 472 | ||
434 | static int iwl_get_radio_cfg(const struct iwl_cfg *cfg, | 473 | static int iwl_get_radio_cfg(const struct iwl_cfg *cfg, |
435 | const __le16 *nvm_sw) | 474 | const __le16 *nvm_sw, const __le16 *phy_sku, |
475 | bool is_family_8000_a_step) | ||
436 | { | 476 | { |
437 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) | 477 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) |
438 | return le16_to_cpup(nvm_sw + RADIO_CFG); | 478 | return le16_to_cpup(nvm_sw + RADIO_CFG); |
479 | |||
480 | if (!is_family_8000_a_step) | ||
481 | return le32_to_cpup((__le32 *)(phy_sku + | ||
482 | RADIO_CFG_FAMILY_8000_B0)); | ||
439 | else | 483 | else |
440 | return le32_to_cpup((__le32 *)(nvm_sw + RADIO_CFG_FAMILY_8000)); | 484 | return le32_to_cpup((__le32 *)(nvm_sw + RADIO_CFG_FAMILY_8000)); |
485 | |||
441 | } | 486 | } |
442 | 487 | ||
443 | #define N_HW_ADDRS_MASK_FAMILY_8000 0xF | ||
444 | static int iwl_get_n_hw_addrs(const struct iwl_cfg *cfg, | 488 | static int iwl_get_n_hw_addrs(const struct iwl_cfg *cfg, |
445 | const __le16 *nvm_sw) | 489 | const __le16 *nvm_sw, bool is_family_8000_a_step) |
446 | { | 490 | { |
491 | int n_hw_addr; | ||
492 | |||
447 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) | 493 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) |
448 | return le16_to_cpup(nvm_sw + N_HW_ADDRS); | 494 | return le16_to_cpup(nvm_sw + N_HW_ADDRS); |
495 | |||
496 | if (!is_family_8000_a_step) | ||
497 | n_hw_addr = le32_to_cpup((__le32 *)(nvm_sw + | ||
498 | N_HW_ADDRS_FAMILY_8000_B0)); | ||
449 | else | 499 | else |
450 | return le32_to_cpup((__le32 *)(nvm_sw + N_HW_ADDRS_FAMILY_8000)) | 500 | n_hw_addr = le32_to_cpup((__le32 *)(nvm_sw + |
451 | & N_HW_ADDRS_MASK_FAMILY_8000; | 501 | N_HW_ADDRS_FAMILY_8000)); |
502 | |||
503 | return n_hw_addr & N_HW_ADDR_MASK; | ||
452 | } | 504 | } |
453 | 505 | ||
454 | static void iwl_set_radio_cfg(const struct iwl_cfg *cfg, | 506 | static void iwl_set_radio_cfg(const struct iwl_cfg *cfg, |
@@ -491,7 +543,8 @@ static void iwl_set_hw_address_family_8000(struct device *dev, | |||
491 | const struct iwl_cfg *cfg, | 543 | const struct iwl_cfg *cfg, |
492 | struct iwl_nvm_data *data, | 544 | struct iwl_nvm_data *data, |
493 | const __le16 *mac_override, | 545 | const __le16 *mac_override, |
494 | const __le16 *nvm_hw) | 546 | const __le16 *nvm_hw, |
547 | u32 mac_addr0, u32 mac_addr1) | ||
495 | { | 548 | { |
496 | const u8 *hw_addr; | 549 | const u8 *hw_addr; |
497 | 550 | ||
@@ -515,48 +568,17 @@ static void iwl_set_hw_address_family_8000(struct device *dev, | |||
515 | } | 568 | } |
516 | 569 | ||
517 | if (nvm_hw) { | 570 | if (nvm_hw) { |
518 | /* read the MAC address from OTP */ | 571 | /* read the MAC address from HW resisters */ |
519 | if (!dev_is_pci(dev) || (data->nvm_version < 0xE08)) { | 572 | hw_addr = (const u8 *)&mac_addr0; |
520 | /* read the mac address from the WFPM location */ | 573 | data->hw_addr[0] = hw_addr[3]; |
521 | hw_addr = (const u8 *)(nvm_hw + | 574 | data->hw_addr[1] = hw_addr[2]; |
522 | HW_ADDR0_WFPM_FAMILY_8000); | 575 | data->hw_addr[2] = hw_addr[1]; |
523 | data->hw_addr[0] = hw_addr[3]; | 576 | data->hw_addr[3] = hw_addr[0]; |
524 | data->hw_addr[1] = hw_addr[2]; | 577 | |
525 | data->hw_addr[2] = hw_addr[1]; | 578 | hw_addr = (const u8 *)&mac_addr1; |
526 | data->hw_addr[3] = hw_addr[0]; | 579 | data->hw_addr[4] = hw_addr[1]; |
527 | 580 | data->hw_addr[5] = hw_addr[0]; | |
528 | hw_addr = (const u8 *)(nvm_hw + | 581 | |
529 | HW_ADDR1_WFPM_FAMILY_8000); | ||
530 | data->hw_addr[4] = hw_addr[1]; | ||
531 | data->hw_addr[5] = hw_addr[0]; | ||
532 | } else if ((data->nvm_version >= 0xE08) && | ||
533 | (data->nvm_version < 0xE0B)) { | ||
534 | /* read "reverse order" from the PCIe location */ | ||
535 | hw_addr = (const u8 *)(nvm_hw + | ||
536 | HW_ADDR0_PCIE_FAMILY_8000); | ||
537 | data->hw_addr[5] = hw_addr[2]; | ||
538 | data->hw_addr[4] = hw_addr[1]; | ||
539 | data->hw_addr[3] = hw_addr[0]; | ||
540 | |||
541 | hw_addr = (const u8 *)(nvm_hw + | ||
542 | HW_ADDR1_PCIE_FAMILY_8000); | ||
543 | data->hw_addr[2] = hw_addr[3]; | ||
544 | data->hw_addr[1] = hw_addr[2]; | ||
545 | data->hw_addr[0] = hw_addr[1]; | ||
546 | } else { | ||
547 | /* read from the PCIe location */ | ||
548 | hw_addr = (const u8 *)(nvm_hw + | ||
549 | HW_ADDR0_PCIE_FAMILY_8000); | ||
550 | data->hw_addr[5] = hw_addr[0]; | ||
551 | data->hw_addr[4] = hw_addr[1]; | ||
552 | data->hw_addr[3] = hw_addr[2]; | ||
553 | |||
554 | hw_addr = (const u8 *)(nvm_hw + | ||
555 | HW_ADDR1_PCIE_FAMILY_8000); | ||
556 | data->hw_addr[2] = hw_addr[1]; | ||
557 | data->hw_addr[1] = hw_addr[2]; | ||
558 | data->hw_addr[0] = hw_addr[3]; | ||
559 | } | ||
560 | if (!is_valid_ether_addr(data->hw_addr)) | 582 | if (!is_valid_ether_addr(data->hw_addr)) |
561 | IWL_ERR_DEV(dev, | 583 | IWL_ERR_DEV(dev, |
562 | "mac address from hw section is not valid\n"); | 584 | "mac address from hw section is not valid\n"); |
@@ -571,11 +593,15 @@ struct iwl_nvm_data * | |||
571 | iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, | 593 | iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, |
572 | const __le16 *nvm_hw, const __le16 *nvm_sw, | 594 | const __le16 *nvm_hw, const __le16 *nvm_sw, |
573 | const __le16 *nvm_calib, const __le16 *regulatory, | 595 | const __le16 *nvm_calib, const __le16 *regulatory, |
574 | const __le16 *mac_override, u8 tx_chains, u8 rx_chains) | 596 | const __le16 *mac_override, const __le16 *phy_sku, |
597 | u8 tx_chains, u8 rx_chains, | ||
598 | bool lar_fw_supported, bool is_family_8000_a_step, | ||
599 | u32 mac_addr0, u32 mac_addr1) | ||
575 | { | 600 | { |
576 | struct iwl_nvm_data *data; | 601 | struct iwl_nvm_data *data; |
577 | u32 sku; | 602 | u32 sku; |
578 | u32 radio_cfg; | 603 | u32 radio_cfg; |
604 | u16 lar_config; | ||
579 | 605 | ||
580 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) | 606 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) |
581 | data = kzalloc(sizeof(*data) + | 607 | data = kzalloc(sizeof(*data) + |
@@ -592,22 +618,25 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, | |||
592 | 618 | ||
593 | data->nvm_version = iwl_get_nvm_version(cfg, nvm_sw); | 619 | data->nvm_version = iwl_get_nvm_version(cfg, nvm_sw); |
594 | 620 | ||
595 | radio_cfg = iwl_get_radio_cfg(cfg, nvm_sw); | 621 | radio_cfg = |
622 | iwl_get_radio_cfg(cfg, nvm_sw, phy_sku, is_family_8000_a_step); | ||
596 | iwl_set_radio_cfg(cfg, data, radio_cfg); | 623 | iwl_set_radio_cfg(cfg, data, radio_cfg); |
597 | if (data->valid_tx_ant) | 624 | if (data->valid_tx_ant) |
598 | tx_chains &= data->valid_tx_ant; | 625 | tx_chains &= data->valid_tx_ant; |
599 | if (data->valid_rx_ant) | 626 | if (data->valid_rx_ant) |
600 | rx_chains &= data->valid_rx_ant; | 627 | rx_chains &= data->valid_rx_ant; |
601 | 628 | ||
602 | sku = iwl_get_sku(cfg, nvm_sw); | 629 | sku = iwl_get_sku(cfg, nvm_sw, phy_sku, is_family_8000_a_step); |
603 | data->sku_cap_band_24GHz_enable = sku & NVM_SKU_CAP_BAND_24GHZ; | 630 | data->sku_cap_band_24GHz_enable = sku & NVM_SKU_CAP_BAND_24GHZ; |
604 | data->sku_cap_band_52GHz_enable = sku & NVM_SKU_CAP_BAND_52GHZ; | 631 | data->sku_cap_band_52GHz_enable = sku & NVM_SKU_CAP_BAND_52GHZ; |
605 | data->sku_cap_11n_enable = sku & NVM_SKU_CAP_11N_ENABLE; | 632 | data->sku_cap_11n_enable = sku & NVM_SKU_CAP_11N_ENABLE; |
606 | data->sku_cap_11ac_enable = sku & NVM_SKU_CAP_11AC_ENABLE; | ||
607 | if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL) | 633 | if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL) |
608 | data->sku_cap_11n_enable = false; | 634 | data->sku_cap_11n_enable = false; |
635 | data->sku_cap_11ac_enable = data->sku_cap_11n_enable && | ||
636 | (sku & NVM_SKU_CAP_11AC_ENABLE); | ||
609 | 637 | ||
610 | data->n_hw_addrs = iwl_get_n_hw_addrs(cfg, nvm_sw); | 638 | data->n_hw_addrs = |
639 | iwl_get_n_hw_addrs(cfg, nvm_sw, is_family_8000_a_step); | ||
611 | 640 | ||
612 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) { | 641 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) { |
613 | /* Checking for required sections */ | 642 | /* Checking for required sections */ |
@@ -626,16 +655,23 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, | |||
626 | iwl_set_hw_address(cfg, data, nvm_hw); | 655 | iwl_set_hw_address(cfg, data, nvm_hw); |
627 | 656 | ||
628 | iwl_init_sbands(dev, cfg, data, nvm_sw, | 657 | iwl_init_sbands(dev, cfg, data, nvm_sw, |
629 | sku & NVM_SKU_CAP_11AC_ENABLE, tx_chains, | 658 | tx_chains, rx_chains, lar_fw_supported); |
630 | rx_chains); | ||
631 | } else { | 659 | } else { |
660 | u16 lar_offset = data->nvm_version < 0xE39 ? | ||
661 | NVM_LAR_OFFSET_FAMILY_8000_OLD : | ||
662 | NVM_LAR_OFFSET_FAMILY_8000; | ||
663 | |||
664 | lar_config = le16_to_cpup(regulatory + lar_offset); | ||
665 | data->lar_enabled = !!(lar_config & | ||
666 | NVM_LAR_ENABLED_FAMILY_8000); | ||
667 | |||
632 | /* MAC address in family 8000 */ | 668 | /* MAC address in family 8000 */ |
633 | iwl_set_hw_address_family_8000(dev, cfg, data, mac_override, | 669 | iwl_set_hw_address_family_8000(dev, cfg, data, mac_override, |
634 | nvm_hw); | 670 | nvm_hw, mac_addr0, mac_addr1); |
635 | 671 | ||
636 | iwl_init_sbands(dev, cfg, data, regulatory, | 672 | iwl_init_sbands(dev, cfg, data, regulatory, |
637 | sku & NVM_SKU_CAP_11AC_ENABLE, tx_chains, | 673 | tx_chains, rx_chains, |
638 | rx_chains); | 674 | lar_fw_supported && data->lar_enabled); |
639 | } | 675 | } |
640 | 676 | ||
641 | data->calib_version = 255; | 677 | data->calib_version = 255; |
@@ -643,3 +679,164 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, | |||
643 | return data; | 679 | return data; |
644 | } | 680 | } |
645 | IWL_EXPORT_SYMBOL(iwl_parse_nvm_data); | 681 | IWL_EXPORT_SYMBOL(iwl_parse_nvm_data); |
682 | |||
683 | static u32 iwl_nvm_get_regdom_bw_flags(const u8 *nvm_chan, | ||
684 | int ch_idx, u16 nvm_flags, | ||
685 | const struct iwl_cfg *cfg) | ||
686 | { | ||
687 | u32 flags = NL80211_RRF_NO_HT40; | ||
688 | u32 last_5ghz_ht = LAST_5GHZ_HT; | ||
689 | |||
690 | if (cfg->device_family == IWL_DEVICE_FAMILY_8000) | ||
691 | last_5ghz_ht = LAST_5GHZ_HT_FAMILY_8000; | ||
692 | |||
693 | if (ch_idx < NUM_2GHZ_CHANNELS && | ||
694 | (nvm_flags & NVM_CHANNEL_40MHZ)) { | ||
695 | if (nvm_chan[ch_idx] <= LAST_2GHZ_HT_PLUS) | ||
696 | flags &= ~NL80211_RRF_NO_HT40PLUS; | ||
697 | if (nvm_chan[ch_idx] >= FIRST_2GHZ_HT_MINUS) | ||
698 | flags &= ~NL80211_RRF_NO_HT40MINUS; | ||
699 | } else if (nvm_chan[ch_idx] <= last_5ghz_ht && | ||
700 | (nvm_flags & NVM_CHANNEL_40MHZ)) { | ||
701 | if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0) | ||
702 | flags &= ~NL80211_RRF_NO_HT40PLUS; | ||
703 | else | ||
704 | flags &= ~NL80211_RRF_NO_HT40MINUS; | ||
705 | } | ||
706 | |||
707 | if (!(nvm_flags & NVM_CHANNEL_80MHZ)) | ||
708 | flags |= NL80211_RRF_NO_80MHZ; | ||
709 | if (!(nvm_flags & NVM_CHANNEL_160MHZ)) | ||
710 | flags |= NL80211_RRF_NO_160MHZ; | ||
711 | |||
712 | if (!(nvm_flags & NVM_CHANNEL_ACTIVE)) | ||
713 | flags |= NL80211_RRF_NO_IR; | ||
714 | |||
715 | if (nvm_flags & NVM_CHANNEL_RADAR) | ||
716 | flags |= NL80211_RRF_DFS; | ||
717 | |||
718 | if (nvm_flags & NVM_CHANNEL_INDOOR_ONLY) | ||
719 | flags |= NL80211_RRF_NO_OUTDOOR; | ||
720 | |||
721 | /* Set the GO concurrent flag only in case that NO_IR is set. | ||
722 | * Otherwise it is meaningless | ||
723 | */ | ||
724 | if ((nvm_flags & NVM_CHANNEL_GO_CONCURRENT) && | ||
725 | (flags & NL80211_RRF_NO_IR)) | ||
726 | flags |= NL80211_RRF_GO_CONCURRENT; | ||
727 | |||
728 | return flags; | ||
729 | } | ||
730 | |||
731 | struct ieee80211_regdomain * | ||
732 | iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, | ||
733 | int num_of_ch, __le32 *channels, u16 fw_mcc) | ||
734 | { | ||
735 | int ch_idx; | ||
736 | u16 ch_flags, prev_ch_flags = 0; | ||
737 | const u8 *nvm_chan = cfg->device_family == IWL_DEVICE_FAMILY_8000 ? | ||
738 | iwl_nvm_channels_family_8000 : iwl_nvm_channels; | ||
739 | struct ieee80211_regdomain *regd; | ||
740 | int size_of_regd; | ||
741 | struct ieee80211_reg_rule *rule; | ||
742 | enum ieee80211_band band; | ||
743 | int center_freq, prev_center_freq = 0; | ||
744 | int valid_rules = 0; | ||
745 | bool new_rule; | ||
746 | int max_num_ch = cfg->device_family == IWL_DEVICE_FAMILY_8000 ? | ||
747 | IWL_NUM_CHANNELS_FAMILY_8000 : IWL_NUM_CHANNELS; | ||
748 | |||
749 | if (WARN_ON_ONCE(num_of_ch > NL80211_MAX_SUPP_REG_RULES)) | ||
750 | return ERR_PTR(-EINVAL); | ||
751 | |||
752 | if (WARN_ON(num_of_ch > max_num_ch)) | ||
753 | num_of_ch = max_num_ch; | ||
754 | |||
755 | IWL_DEBUG_DEV(dev, IWL_DL_LAR, "building regdom for %d channels\n", | ||
756 | num_of_ch); | ||
757 | |||
758 | /* build a regdomain rule for every valid channel */ | ||
759 | size_of_regd = | ||
760 | sizeof(struct ieee80211_regdomain) + | ||
761 | num_of_ch * sizeof(struct ieee80211_reg_rule); | ||
762 | |||
763 | regd = kzalloc(size_of_regd, GFP_KERNEL); | ||
764 | if (!regd) | ||
765 | return ERR_PTR(-ENOMEM); | ||
766 | |||
767 | for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) { | ||
768 | ch_flags = (u16)__le32_to_cpup(channels + ch_idx); | ||
769 | band = (ch_idx < NUM_2GHZ_CHANNELS) ? | ||
770 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | ||
771 | center_freq = ieee80211_channel_to_frequency(nvm_chan[ch_idx], | ||
772 | band); | ||
773 | new_rule = false; | ||
774 | |||
775 | if (!(ch_flags & NVM_CHANNEL_VALID)) { | ||
776 | IWL_DEBUG_DEV(dev, IWL_DL_LAR, | ||
777 | "Ch. %d Flags %x [%sGHz] - No traffic\n", | ||
778 | nvm_chan[ch_idx], | ||
779 | ch_flags, | ||
780 | (ch_idx >= NUM_2GHZ_CHANNELS) ? | ||
781 | "5.2" : "2.4"); | ||
782 | continue; | ||
783 | } | ||
784 | |||
785 | /* we can't continue the same rule */ | ||
786 | if (ch_idx == 0 || prev_ch_flags != ch_flags || | ||
787 | center_freq - prev_center_freq > 20) { | ||
788 | valid_rules++; | ||
789 | new_rule = true; | ||
790 | } | ||
791 | |||
792 | rule = ®d->reg_rules[valid_rules - 1]; | ||
793 | |||
794 | if (new_rule) | ||
795 | rule->freq_range.start_freq_khz = | ||
796 | MHZ_TO_KHZ(center_freq - 10); | ||
797 | |||
798 | rule->freq_range.end_freq_khz = MHZ_TO_KHZ(center_freq + 10); | ||
799 | |||
800 | /* this doesn't matter - not used by FW */ | ||
801 | rule->power_rule.max_antenna_gain = DBI_TO_MBI(6); | ||
802 | rule->power_rule.max_eirp = | ||
803 | DBM_TO_MBM(IWL_DEFAULT_MAX_TX_POWER); | ||
804 | |||
805 | rule->flags = iwl_nvm_get_regdom_bw_flags(nvm_chan, ch_idx, | ||
806 | ch_flags, cfg); | ||
807 | |||
808 | /* rely on auto-calculation to merge BW of contiguous chans */ | ||
809 | rule->flags |= NL80211_RRF_AUTO_BW; | ||
810 | rule->freq_range.max_bandwidth_khz = 0; | ||
811 | |||
812 | prev_ch_flags = ch_flags; | ||
813 | prev_center_freq = center_freq; | ||
814 | |||
815 | IWL_DEBUG_DEV(dev, IWL_DL_LAR, | ||
816 | "Ch. %d [%sGHz] %s%s%s%s%s%s%s%s%s(0x%02x): Ad-Hoc %ssupported\n", | ||
817 | center_freq, | ||
818 | band == IEEE80211_BAND_5GHZ ? "5.2" : "2.4", | ||
819 | CHECK_AND_PRINT_I(VALID), | ||
820 | CHECK_AND_PRINT_I(ACTIVE), | ||
821 | CHECK_AND_PRINT_I(RADAR), | ||
822 | CHECK_AND_PRINT_I(WIDE), | ||
823 | CHECK_AND_PRINT_I(40MHZ), | ||
824 | CHECK_AND_PRINT_I(80MHZ), | ||
825 | CHECK_AND_PRINT_I(160MHZ), | ||
826 | CHECK_AND_PRINT_I(INDOOR_ONLY), | ||
827 | CHECK_AND_PRINT_I(GO_CONCURRENT), | ||
828 | ch_flags, | ||
829 | ((ch_flags & NVM_CHANNEL_ACTIVE) && | ||
830 | !(ch_flags & NVM_CHANNEL_RADAR)) | ||
831 | ? "" : "not "); | ||
832 | } | ||
833 | |||
834 | regd->n_reg_rules = valid_rules; | ||
835 | |||
836 | /* set alpha2 from FW. */ | ||
837 | regd->alpha2[0] = fw_mcc >> 8; | ||
838 | regd->alpha2[1] = fw_mcc & 0xff; | ||
839 | |||
840 | return regd; | ||
841 | } | ||
842 | IWL_EXPORT_SYMBOL(iwl_parse_nvm_mcc_info); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h index c9c45a39d212..c995d2cee3f6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h | |||
@@ -62,6 +62,7 @@ | |||
62 | #ifndef __iwl_nvm_parse_h__ | 62 | #ifndef __iwl_nvm_parse_h__ |
63 | #define __iwl_nvm_parse_h__ | 63 | #define __iwl_nvm_parse_h__ |
64 | 64 | ||
65 | #include <net/cfg80211.h> | ||
65 | #include "iwl-eeprom-parse.h" | 66 | #include "iwl-eeprom-parse.h" |
66 | 67 | ||
67 | /** | 68 | /** |
@@ -76,6 +77,22 @@ struct iwl_nvm_data * | |||
76 | iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, | 77 | iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, |
77 | const __le16 *nvm_hw, const __le16 *nvm_sw, | 78 | const __le16 *nvm_hw, const __le16 *nvm_sw, |
78 | const __le16 *nvm_calib, const __le16 *regulatory, | 79 | const __le16 *nvm_calib, const __le16 *regulatory, |
79 | const __le16 *mac_override, u8 tx_chains, u8 rx_chains); | 80 | const __le16 *mac_override, const __le16 *phy_sku, |
81 | u8 tx_chains, u8 rx_chains, | ||
82 | bool lar_fw_supported, bool is_family_8000_a_step, | ||
83 | u32 mac_addr0, u32 mac_addr1); | ||
84 | |||
85 | /** | ||
86 | * iwl_parse_mcc_info - parse MCC (mobile country code) info coming from FW | ||
87 | * | ||
88 | * This function parses the regulatory channel data received as a | ||
89 | * MCC_UPDATE_CMD command. It returns a newly allocation regulatory domain, | ||
90 | * to be fed into the regulatory core. An ERR_PTR is returned on error. | ||
91 | * If not given to the regulatory core, the user is responsible for freeing | ||
92 | * the regdomain returned here with kfree. | ||
93 | */ | ||
94 | struct ieee80211_regdomain * | ||
95 | iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, | ||
96 | int num_of_ch, __le32 *channels, u16 fw_mcc); | ||
80 | 97 | ||
81 | #endif /* __iwl_nvm_parse_h__ */ | 98 | #endif /* __iwl_nvm_parse_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 6095088b88d9..bc962888c583 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h | |||
@@ -371,6 +371,33 @@ enum secure_load_status_reg { | |||
371 | 371 | ||
372 | #define DBGC_IN_SAMPLE (0xa03c00) | 372 | #define DBGC_IN_SAMPLE (0xa03c00) |
373 | 373 | ||
374 | /* enable the ID buf for read */ | ||
375 | #define WFPM_PS_CTL_CLR 0xA0300C | ||
376 | #define WFMP_MAC_ADDR_0 0xA03080 | ||
377 | #define WFMP_MAC_ADDR_1 0xA03084 | ||
378 | #define LMPM_PMG_EN 0xA01CEC | ||
379 | #define RADIO_REG_SYS_MANUAL_DFT_0 0xAD4078 | ||
380 | #define RFIC_REG_RD 0xAD0470 | ||
381 | #define WFPM_CTRL_REG 0xA03030 | ||
382 | enum { | ||
383 | ENABLE_WFPM = BIT(31), | ||
384 | WFPM_AUX_CTL_AUX_IF_MAC_OWNER_MSK = 0x80000000, | ||
385 | }; | ||
386 | |||
387 | #define AUX_MISC_REG 0xA200B0 | ||
388 | enum { | ||
389 | HW_STEP_LOCATION_BITS = 24, | ||
390 | }; | ||
391 | |||
392 | #define AUX_MISC_MASTER1_EN 0xA20818 | ||
393 | enum aux_misc_master1_en { | ||
394 | AUX_MISC_MASTER1_EN_SBE_MSK = 0x1, | ||
395 | }; | ||
396 | |||
397 | #define AUX_MISC_MASTER1_SMPHR_STATUS 0xA20800 | ||
398 | #define RSA_ENABLE 0xA24B08 | ||
399 | #define PREG_AUX_BUS_WPROT_0 0xA04CC0 | ||
400 | |||
374 | /* FW chicken bits */ | 401 | /* FW chicken bits */ |
375 | #define LMPM_CHICK 0xA01FF8 | 402 | #define LMPM_CHICK 0xA01FF8 |
376 | enum { | 403 | enum { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 542a6810c81c..11ac5c58527f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -458,6 +458,8 @@ struct iwl_trans_txq_scd_cfg { | |||
458 | * @txq_disable: de-configure a Tx queue to send AMPDUs | 458 | * @txq_disable: de-configure a Tx queue to send AMPDUs |
459 | * Must be atomic | 459 | * Must be atomic |
460 | * @wait_tx_queue_empty: wait until tx queues are empty. May sleep. | 460 | * @wait_tx_queue_empty: wait until tx queues are empty. May sleep. |
461 | * @freeze_txq_timer: prevents the timer of the queue from firing until the | ||
462 | * queue is set to awake. Must be atomic. | ||
461 | * @dbgfs_register: add the dbgfs files under this directory. Files will be | 463 | * @dbgfs_register: add the dbgfs files under this directory. Files will be |
462 | * automatically deleted. | 464 | * automatically deleted. |
463 | * @write8: write a u8 to a register at offset ofs from the BAR | 465 | * @write8: write a u8 to a register at offset ofs from the BAR |
@@ -517,6 +519,8 @@ struct iwl_trans_ops { | |||
517 | 519 | ||
518 | int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); | 520 | int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); |
519 | int (*wait_tx_queue_empty)(struct iwl_trans *trans, u32 txq_bm); | 521 | int (*wait_tx_queue_empty)(struct iwl_trans *trans, u32 txq_bm); |
522 | void (*freeze_txq_timer)(struct iwl_trans *trans, unsigned long txqs, | ||
523 | bool freeze); | ||
520 | 524 | ||
521 | void (*write8)(struct iwl_trans *trans, u32 ofs, u8 val); | 525 | void (*write8)(struct iwl_trans *trans, u32 ofs, u8 val); |
522 | void (*write32)(struct iwl_trans *trans, u32 ofs, u32 val); | 526 | void (*write32)(struct iwl_trans *trans, u32 ofs, u32 val); |
@@ -873,6 +877,17 @@ void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue, int fifo, | |||
873 | iwl_trans_txq_enable_cfg(trans, queue, 0, &cfg, queue_wdg_timeout); | 877 | iwl_trans_txq_enable_cfg(trans, queue, 0, &cfg, queue_wdg_timeout); |
874 | } | 878 | } |
875 | 879 | ||
880 | static inline void iwl_trans_freeze_txq_timer(struct iwl_trans *trans, | ||
881 | unsigned long txqs, | ||
882 | bool freeze) | ||
883 | { | ||
884 | if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) | ||
885 | IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state); | ||
886 | |||
887 | if (trans->ops->freeze_txq_timer) | ||
888 | trans->ops->freeze_txq_timer(trans, txqs, freeze); | ||
889 | } | ||
890 | |||
876 | static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans, | 891 | static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans, |
877 | u32 txqs) | 892 | u32 txqs) |
878 | { | 893 | { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c index 877f19bbae7e..13a0a03158de 100644 --- a/drivers/net/wireless/iwlwifi/mvm/coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/coex.c | |||
@@ -72,158 +72,6 @@ | |||
72 | #include "mvm.h" | 72 | #include "mvm.h" |
73 | #include "iwl-debug.h" | 73 | #include "iwl-debug.h" |
74 | 74 | ||
75 | const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX] = { | ||
76 | [BT_KILL_MSK_DEFAULT] = 0xfffffc00, | ||
77 | [BT_KILL_MSK_NEVER] = 0xffffffff, | ||
78 | [BT_KILL_MSK_ALWAYS] = 0, | ||
79 | }; | ||
80 | |||
81 | const u8 iwl_bt_cts_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT] = { | ||
82 | { | ||
83 | BT_KILL_MSK_ALWAYS, | ||
84 | BT_KILL_MSK_ALWAYS, | ||
85 | BT_KILL_MSK_ALWAYS, | ||
86 | }, | ||
87 | { | ||
88 | BT_KILL_MSK_NEVER, | ||
89 | BT_KILL_MSK_NEVER, | ||
90 | BT_KILL_MSK_NEVER, | ||
91 | }, | ||
92 | { | ||
93 | BT_KILL_MSK_NEVER, | ||
94 | BT_KILL_MSK_NEVER, | ||
95 | BT_KILL_MSK_NEVER, | ||
96 | }, | ||
97 | { | ||
98 | BT_KILL_MSK_DEFAULT, | ||
99 | BT_KILL_MSK_NEVER, | ||
100 | BT_KILL_MSK_DEFAULT, | ||
101 | }, | ||
102 | }; | ||
103 | |||
104 | const u8 iwl_bt_ack_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT] = { | ||
105 | { | ||
106 | BT_KILL_MSK_ALWAYS, | ||
107 | BT_KILL_MSK_ALWAYS, | ||
108 | BT_KILL_MSK_ALWAYS, | ||
109 | }, | ||
110 | { | ||
111 | BT_KILL_MSK_ALWAYS, | ||
112 | BT_KILL_MSK_ALWAYS, | ||
113 | BT_KILL_MSK_ALWAYS, | ||
114 | }, | ||
115 | { | ||
116 | BT_KILL_MSK_ALWAYS, | ||
117 | BT_KILL_MSK_ALWAYS, | ||
118 | BT_KILL_MSK_ALWAYS, | ||
119 | }, | ||
120 | { | ||
121 | BT_KILL_MSK_DEFAULT, | ||
122 | BT_KILL_MSK_ALWAYS, | ||
123 | BT_KILL_MSK_DEFAULT, | ||
124 | }, | ||
125 | }; | ||
126 | |||
127 | static const __le32 iwl_bt_prio_boost[BT_COEX_BOOST_SIZE] = { | ||
128 | cpu_to_le32(0xf0f0f0f0), /* 50% */ | ||
129 | cpu_to_le32(0xc0c0c0c0), /* 25% */ | ||
130 | cpu_to_le32(0xfcfcfcfc), /* 75% */ | ||
131 | cpu_to_le32(0xfefefefe), /* 87.5% */ | ||
132 | }; | ||
133 | |||
134 | static const __le32 iwl_single_shared_ant[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = { | ||
135 | { | ||
136 | cpu_to_le32(0x40000000), | ||
137 | cpu_to_le32(0x00000000), | ||
138 | cpu_to_le32(0x44000000), | ||
139 | cpu_to_le32(0x00000000), | ||
140 | cpu_to_le32(0x40000000), | ||
141 | cpu_to_le32(0x00000000), | ||
142 | cpu_to_le32(0x44000000), | ||
143 | cpu_to_le32(0x00000000), | ||
144 | cpu_to_le32(0xc0004000), | ||
145 | cpu_to_le32(0xf0005000), | ||
146 | cpu_to_le32(0xc0004000), | ||
147 | cpu_to_le32(0xf0005000), | ||
148 | }, | ||
149 | { | ||
150 | cpu_to_le32(0x40000000), | ||
151 | cpu_to_le32(0x00000000), | ||
152 | cpu_to_le32(0x44000000), | ||
153 | cpu_to_le32(0x00000000), | ||
154 | cpu_to_le32(0x40000000), | ||
155 | cpu_to_le32(0x00000000), | ||
156 | cpu_to_le32(0x44000000), | ||
157 | cpu_to_le32(0x00000000), | ||
158 | cpu_to_le32(0xc0004000), | ||
159 | cpu_to_le32(0xf0005000), | ||
160 | cpu_to_le32(0xc0004000), | ||
161 | cpu_to_le32(0xf0005000), | ||
162 | }, | ||
163 | { | ||
164 | cpu_to_le32(0x40000000), | ||
165 | cpu_to_le32(0x00000000), | ||
166 | cpu_to_le32(0x44000000), | ||
167 | cpu_to_le32(0x00000000), | ||
168 | cpu_to_le32(0x40000000), | ||
169 | cpu_to_le32(0x00000000), | ||
170 | cpu_to_le32(0x44000000), | ||
171 | cpu_to_le32(0x00000000), | ||
172 | cpu_to_le32(0xc0004000), | ||
173 | cpu_to_le32(0xf0005000), | ||
174 | cpu_to_le32(0xc0004000), | ||
175 | cpu_to_le32(0xf0005000), | ||
176 | }, | ||
177 | }; | ||
178 | |||
179 | static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = { | ||
180 | { | ||
181 | /* Tight */ | ||
182 | cpu_to_le32(0xaaaaaaaa), | ||
183 | cpu_to_le32(0xaaaaaaaa), | ||
184 | cpu_to_le32(0xaeaaaaaa), | ||
185 | cpu_to_le32(0xaaaaaaaa), | ||
186 | cpu_to_le32(0xcc00ff28), | ||
187 | cpu_to_le32(0x0000aaaa), | ||
188 | cpu_to_le32(0xcc00aaaa), | ||
189 | cpu_to_le32(0x0000aaaa), | ||
190 | cpu_to_le32(0xc0004000), | ||
191 | cpu_to_le32(0x00004000), | ||
192 | cpu_to_le32(0xf0005000), | ||
193 | cpu_to_le32(0xf0005000), | ||
194 | }, | ||
195 | { | ||
196 | /* Loose */ | ||
197 | cpu_to_le32(0xaaaaaaaa), | ||
198 | cpu_to_le32(0xaaaaaaaa), | ||
199 | cpu_to_le32(0xaaaaaaaa), | ||
200 | cpu_to_le32(0xaaaaaaaa), | ||
201 | cpu_to_le32(0xcc00ff28), | ||
202 | cpu_to_le32(0x0000aaaa), | ||
203 | cpu_to_le32(0xcc00aaaa), | ||
204 | cpu_to_le32(0x0000aaaa), | ||
205 | cpu_to_le32(0x00000000), | ||
206 | cpu_to_le32(0x00000000), | ||
207 | cpu_to_le32(0xf0005000), | ||
208 | cpu_to_le32(0xf0005000), | ||
209 | }, | ||
210 | { | ||
211 | /* Tx Tx disabled */ | ||
212 | cpu_to_le32(0xaaaaaaaa), | ||
213 | cpu_to_le32(0xaaaaaaaa), | ||
214 | cpu_to_le32(0xeeaaaaaa), | ||
215 | cpu_to_le32(0xaaaaaaaa), | ||
216 | cpu_to_le32(0xcc00ff28), | ||
217 | cpu_to_le32(0x0000aaaa), | ||
218 | cpu_to_le32(0xcc00aaaa), | ||
219 | cpu_to_le32(0x0000aaaa), | ||
220 | cpu_to_le32(0xc0004000), | ||
221 | cpu_to_le32(0xc0004000), | ||
222 | cpu_to_le32(0xf0005000), | ||
223 | cpu_to_le32(0xf0005000), | ||
224 | }, | ||
225 | }; | ||
226 | |||
227 | /* 20MHz / 40MHz below / 40Mhz above*/ | 75 | /* 20MHz / 40MHz below / 40Mhz above*/ |
228 | static const __le64 iwl_ci_mask[][3] = { | 76 | static const __le64 iwl_ci_mask[][3] = { |
229 | /* dummy entry for channel 0 */ | 77 | /* dummy entry for channel 0 */ |
@@ -596,14 +444,6 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | |||
596 | goto send_cmd; | 444 | goto send_cmd; |
597 | } | 445 | } |
598 | 446 | ||
599 | bt_cmd->max_kill = cpu_to_le32(5); | ||
600 | bt_cmd->bt4_antenna_isolation_thr = | ||
601 | cpu_to_le32(IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS); | ||
602 | bt_cmd->bt4_tx_tx_delta_freq_thr = cpu_to_le32(15); | ||
603 | bt_cmd->bt4_tx_rx_max_freq0 = cpu_to_le32(15); | ||
604 | bt_cmd->override_primary_lut = cpu_to_le32(BT_COEX_INVALID_LUT); | ||
605 | bt_cmd->override_secondary_lut = cpu_to_le32(BT_COEX_INVALID_LUT); | ||
606 | |||
607 | mode = iwlwifi_mod_params.bt_coex_active ? BT_COEX_NW : BT_COEX_DISABLE; | 447 | mode = iwlwifi_mod_params.bt_coex_active ? BT_COEX_NW : BT_COEX_DISABLE; |
608 | bt_cmd->mode = cpu_to_le32(mode); | 448 | bt_cmd->mode = cpu_to_le32(mode); |
609 | 449 | ||
@@ -622,18 +462,6 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | |||
622 | 462 | ||
623 | bt_cmd->enabled_modules |= cpu_to_le32(BT_COEX_HIGH_BAND_RET); | 463 | bt_cmd->enabled_modules |= cpu_to_le32(BT_COEX_HIGH_BAND_RET); |
624 | 464 | ||
625 | if (mvm->cfg->bt_shared_single_ant) | ||
626 | memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant, | ||
627 | sizeof(iwl_single_shared_ant)); | ||
628 | else | ||
629 | memcpy(&bt_cmd->decision_lut, iwl_combined_lookup, | ||
630 | sizeof(iwl_combined_lookup)); | ||
631 | |||
632 | memcpy(&bt_cmd->mplut_prio_boost, iwl_bt_prio_boost, | ||
633 | sizeof(iwl_bt_prio_boost)); | ||
634 | bt_cmd->multiprio_lut[0] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG0); | ||
635 | bt_cmd->multiprio_lut[1] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG1); | ||
636 | |||
637 | send_cmd: | 465 | send_cmd: |
638 | memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); | 466 | memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); |
639 | memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd)); | 467 | memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd)); |
@@ -644,48 +472,6 @@ send_cmd: | |||
644 | return ret; | 472 | return ret; |
645 | } | 473 | } |
646 | 474 | ||
647 | static int iwl_mvm_bt_udpate_sw_boost(struct iwl_mvm *mvm) | ||
648 | { | ||
649 | struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif; | ||
650 | u32 primary_lut = le32_to_cpu(notif->primary_ch_lut); | ||
651 | u32 secondary_lut = le32_to_cpu(notif->secondary_ch_lut); | ||
652 | u32 ag = le32_to_cpu(notif->bt_activity_grading); | ||
653 | struct iwl_bt_coex_sw_boost_update_cmd cmd = {}; | ||
654 | u8 ack_kill_msk[NUM_PHY_CTX] = {}; | ||
655 | u8 cts_kill_msk[NUM_PHY_CTX] = {}; | ||
656 | int i; | ||
657 | |||
658 | lockdep_assert_held(&mvm->mutex); | ||
659 | |||
660 | ack_kill_msk[0] = iwl_bt_ack_kill_msk[ag][primary_lut]; | ||
661 | cts_kill_msk[0] = iwl_bt_cts_kill_msk[ag][primary_lut]; | ||
662 | |||
663 | ack_kill_msk[1] = iwl_bt_ack_kill_msk[ag][secondary_lut]; | ||
664 | cts_kill_msk[1] = iwl_bt_cts_kill_msk[ag][secondary_lut]; | ||
665 | |||
666 | /* Don't send HCMD if there is no update */ | ||
667 | if (!memcmp(ack_kill_msk, mvm->bt_ack_kill_msk, sizeof(ack_kill_msk)) || | ||
668 | !memcmp(cts_kill_msk, mvm->bt_cts_kill_msk, sizeof(cts_kill_msk))) | ||
669 | return 0; | ||
670 | |||
671 | memcpy(mvm->bt_ack_kill_msk, ack_kill_msk, | ||
672 | sizeof(mvm->bt_ack_kill_msk)); | ||
673 | memcpy(mvm->bt_cts_kill_msk, cts_kill_msk, | ||
674 | sizeof(mvm->bt_cts_kill_msk)); | ||
675 | |||
676 | BUILD_BUG_ON(ARRAY_SIZE(ack_kill_msk) < ARRAY_SIZE(cmd.boost_values)); | ||
677 | |||
678 | for (i = 0; i < ARRAY_SIZE(cmd.boost_values); i++) { | ||
679 | cmd.boost_values[i].kill_ack_msk = | ||
680 | cpu_to_le32(iwl_bt_ctl_kill_msk[ack_kill_msk[i]]); | ||
681 | cmd.boost_values[i].kill_cts_msk = | ||
682 | cpu_to_le32(iwl_bt_ctl_kill_msk[cts_kill_msk[i]]); | ||
683 | } | ||
684 | |||
685 | return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_SW_BOOST, 0, | ||
686 | sizeof(cmd), &cmd); | ||
687 | } | ||
688 | |||
689 | static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, | 475 | static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, |
690 | bool enable) | 476 | bool enable) |
691 | { | 477 | { |
@@ -951,9 +737,6 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm) | |||
951 | IWL_ERR(mvm, "Failed to send BT_CI cmd\n"); | 737 | IWL_ERR(mvm, "Failed to send BT_CI cmd\n"); |
952 | memcpy(&mvm->last_bt_ci_cmd, &cmd, sizeof(cmd)); | 738 | memcpy(&mvm->last_bt_ci_cmd, &cmd, sizeof(cmd)); |
953 | } | 739 | } |
954 | |||
955 | if (iwl_mvm_bt_udpate_sw_boost(mvm)) | ||
956 | IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); | ||
957 | } | 740 | } |
958 | 741 | ||
959 | int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, | 742 | int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, |
@@ -1074,9 +857,6 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1074 | ieee80211_iterate_active_interfaces_atomic( | 857 | ieee80211_iterate_active_interfaces_atomic( |
1075 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | 858 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, |
1076 | iwl_mvm_bt_rssi_iterator, &data); | 859 | iwl_mvm_bt_rssi_iterator, &data); |
1077 | |||
1078 | if (iwl_mvm_bt_udpate_sw_boost(mvm)) | ||
1079 | IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); | ||
1080 | } | 860 | } |
1081 | 861 | ||
1082 | #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) | 862 | #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c index 5535ec9766cb..d954591e0be5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c +++ b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c | |||
@@ -288,6 +288,65 @@ static const __le64 iwl_ci_mask[][3] = { | |||
288 | }, | 288 | }, |
289 | }; | 289 | }; |
290 | 290 | ||
291 | enum iwl_bt_kill_msk { | ||
292 | BT_KILL_MSK_DEFAULT, | ||
293 | BT_KILL_MSK_NEVER, | ||
294 | BT_KILL_MSK_ALWAYS, | ||
295 | BT_KILL_MSK_MAX, | ||
296 | }; | ||
297 | |||
298 | static const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX] = { | ||
299 | [BT_KILL_MSK_DEFAULT] = 0xfffffc00, | ||
300 | [BT_KILL_MSK_NEVER] = 0xffffffff, | ||
301 | [BT_KILL_MSK_ALWAYS] = 0, | ||
302 | }; | ||
303 | |||
304 | static const u8 iwl_bt_cts_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT] = { | ||
305 | { | ||
306 | BT_KILL_MSK_ALWAYS, | ||
307 | BT_KILL_MSK_ALWAYS, | ||
308 | BT_KILL_MSK_ALWAYS, | ||
309 | }, | ||
310 | { | ||
311 | BT_KILL_MSK_NEVER, | ||
312 | BT_KILL_MSK_NEVER, | ||
313 | BT_KILL_MSK_NEVER, | ||
314 | }, | ||
315 | { | ||
316 | BT_KILL_MSK_NEVER, | ||
317 | BT_KILL_MSK_NEVER, | ||
318 | BT_KILL_MSK_NEVER, | ||
319 | }, | ||
320 | { | ||
321 | BT_KILL_MSK_DEFAULT, | ||
322 | BT_KILL_MSK_NEVER, | ||
323 | BT_KILL_MSK_DEFAULT, | ||
324 | }, | ||
325 | }; | ||
326 | |||
327 | static const u8 iwl_bt_ack_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT] = { | ||
328 | { | ||
329 | BT_KILL_MSK_ALWAYS, | ||
330 | BT_KILL_MSK_ALWAYS, | ||
331 | BT_KILL_MSK_ALWAYS, | ||
332 | }, | ||
333 | { | ||
334 | BT_KILL_MSK_ALWAYS, | ||
335 | BT_KILL_MSK_ALWAYS, | ||
336 | BT_KILL_MSK_ALWAYS, | ||
337 | }, | ||
338 | { | ||
339 | BT_KILL_MSK_ALWAYS, | ||
340 | BT_KILL_MSK_ALWAYS, | ||
341 | BT_KILL_MSK_ALWAYS, | ||
342 | }, | ||
343 | { | ||
344 | BT_KILL_MSK_DEFAULT, | ||
345 | BT_KILL_MSK_ALWAYS, | ||
346 | BT_KILL_MSK_DEFAULT, | ||
347 | }, | ||
348 | }; | ||
349 | |||
291 | struct corunning_block_luts { | 350 | struct corunning_block_luts { |
292 | u8 range; | 351 | u8 range; |
293 | __le32 lut20[BT_COEX_CORUN_LUT_SIZE]; | 352 | __le32 lut20[BT_COEX_CORUN_LUT_SIZE]; |
@@ -633,7 +692,7 @@ int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm) | |||
633 | if (IWL_MVM_BT_COEX_TTC) | 692 | if (IWL_MVM_BT_COEX_TTC) |
634 | bt_cmd->flags |= cpu_to_le32(BT_COEX_TTC); | 693 | bt_cmd->flags |= cpu_to_le32(BT_COEX_TTC); |
635 | 694 | ||
636 | if (IWL_MVM_BT_COEX_RRC) | 695 | if (iwl_mvm_bt_is_rrc_supported(mvm)) |
637 | bt_cmd->flags |= cpu_to_le32(BT_COEX_RRC); | 696 | bt_cmd->flags |= cpu_to_le32(BT_COEX_RRC); |
638 | 697 | ||
639 | if (mvm->cfg->bt_shared_single_ant) | 698 | if (mvm->cfg->bt_shared_single_ant) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index 9bdfa95d6ce7..5f8afa5f11a3 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c | |||
@@ -694,6 +694,9 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
694 | if (ret) | 694 | if (ret) |
695 | IWL_ERR(mvm, "Failed to send quota: %d\n", ret); | 695 | IWL_ERR(mvm, "Failed to send quota: %d\n", ret); |
696 | 696 | ||
697 | if (iwl_mvm_is_lar_supported(mvm) && iwl_mvm_init_fw_regd(mvm)) | ||
698 | IWL_ERR(mvm, "Failed to initialize D3 LAR information\n"); | ||
699 | |||
697 | return 0; | 700 | return 0; |
698 | } | 701 | } |
699 | 702 | ||
@@ -1596,7 +1599,7 @@ iwl_mvm_get_wakeup_status(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
1596 | 1599 | ||
1597 | /* RF-kill already asserted again... */ | 1600 | /* RF-kill already asserted again... */ |
1598 | if (!cmd.resp_pkt) { | 1601 | if (!cmd.resp_pkt) { |
1599 | ret = -ERFKILL; | 1602 | fw_status = ERR_PTR(-ERFKILL); |
1600 | goto out_free_resp; | 1603 | goto out_free_resp; |
1601 | } | 1604 | } |
1602 | 1605 | ||
@@ -1605,7 +1608,7 @@ iwl_mvm_get_wakeup_status(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
1605 | len = iwl_rx_packet_payload_len(cmd.resp_pkt); | 1608 | len = iwl_rx_packet_payload_len(cmd.resp_pkt); |
1606 | if (len < status_size) { | 1609 | if (len < status_size) { |
1607 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); | 1610 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); |
1608 | ret = -EIO; | 1611 | fw_status = ERR_PTR(-EIO); |
1609 | goto out_free_resp; | 1612 | goto out_free_resp; |
1610 | } | 1613 | } |
1611 | 1614 | ||
@@ -1613,7 +1616,7 @@ iwl_mvm_get_wakeup_status(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
1613 | if (len != (status_size + | 1616 | if (len != (status_size + |
1614 | ALIGN(le32_to_cpu(status->wake_packet_bufsize), 4))) { | 1617 | ALIGN(le32_to_cpu(status->wake_packet_bufsize), 4))) { |
1615 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); | 1618 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); |
1616 | ret = -EIO; | 1619 | fw_status = ERR_PTR(-EIO); |
1617 | goto out_free_resp; | 1620 | goto out_free_resp; |
1618 | } | 1621 | } |
1619 | 1622 | ||
@@ -1621,7 +1624,7 @@ iwl_mvm_get_wakeup_status(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
1621 | 1624 | ||
1622 | out_free_resp: | 1625 | out_free_resp: |
1623 | iwl_free_resp(&cmd); | 1626 | iwl_free_resp(&cmd); |
1624 | return ret ? ERR_PTR(ret) : fw_status; | 1627 | return fw_status; |
1625 | } | 1628 | } |
1626 | 1629 | ||
1627 | /* releases the MVM mutex */ | 1630 | /* releases the MVM mutex */ |
@@ -1874,6 +1877,12 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) | |||
1874 | /* query SRAM first in case we want event logging */ | 1877 | /* query SRAM first in case we want event logging */ |
1875 | iwl_mvm_read_d3_sram(mvm); | 1878 | iwl_mvm_read_d3_sram(mvm); |
1876 | 1879 | ||
1880 | /* | ||
1881 | * Query the current location and source from the D3 firmware so we | ||
1882 | * can play it back when we re-intiailize the D0 firmware | ||
1883 | */ | ||
1884 | iwl_mvm_update_changed_regdom(mvm); | ||
1885 | |||
1877 | if (mvm->net_detect) { | 1886 | if (mvm->net_detect) { |
1878 | iwl_mvm_query_netdetect_reasons(mvm, vif); | 1887 | iwl_mvm_query_netdetect_reasons(mvm, vif); |
1879 | /* has unlocked the mutex, so skip that */ | 1888 | /* has unlocked the mutex, so skip that */ |
@@ -1883,9 +1892,9 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) | |||
1883 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 1892 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
1884 | if (keep) | 1893 | if (keep) |
1885 | mvm->keep_vif = vif; | 1894 | mvm->keep_vif = vif; |
1895 | #endif | ||
1886 | /* has unlocked the mutex, so skip that */ | 1896 | /* has unlocked the mutex, so skip that */ |
1887 | goto out_iterate; | 1897 | goto out_iterate; |
1888 | #endif | ||
1889 | } | 1898 | } |
1890 | 1899 | ||
1891 | out_unlock: | 1900 | out_unlock: |
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 8cbe77dc1dbb..8c5229892e57 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c | |||
@@ -562,11 +562,12 @@ static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf, | |||
562 | "\tSecondary Channel Bitmap 0x%016llx\n", | 562 | "\tSecondary Channel Bitmap 0x%016llx\n", |
563 | le64_to_cpu(cmd->bt_secondary_ci)); | 563 | le64_to_cpu(cmd->bt_secondary_ci)); |
564 | 564 | ||
565 | pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n"); | 565 | pos += scnprintf(buf+pos, bufsz-pos, |
566 | pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill Mask 0x%08x\n", | 566 | "BT Configuration CMD - 0=default, 1=never, 2=always\n"); |
567 | iwl_bt_ctl_kill_msk[mvm->bt_ack_kill_msk[0]]); | 567 | pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill msk idx %d\n", |
568 | pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill Mask 0x%08x\n", | 568 | mvm->bt_ack_kill_msk[0]); |
569 | iwl_bt_ctl_kill_msk[mvm->bt_cts_kill_msk[0]]); | 569 | pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill msk idx %d\n", |
570 | mvm->bt_cts_kill_msk[0]); | ||
570 | 571 | ||
571 | } else { | 572 | } else { |
572 | struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd; | 573 | struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd; |
@@ -579,21 +580,6 @@ static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf, | |||
579 | pos += scnprintf(buf+pos, bufsz-pos, | 580 | pos += scnprintf(buf+pos, bufsz-pos, |
580 | "\tSecondary Channel Bitmap 0x%016llx\n", | 581 | "\tSecondary Channel Bitmap 0x%016llx\n", |
581 | le64_to_cpu(cmd->bt_secondary_ci)); | 582 | le64_to_cpu(cmd->bt_secondary_ci)); |
582 | |||
583 | pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n"); | ||
584 | pos += scnprintf(buf+pos, bufsz-pos, | ||
585 | "\tPrimary: ACK Kill Mask 0x%08x\n", | ||
586 | iwl_bt_ctl_kill_msk[mvm->bt_ack_kill_msk[0]]); | ||
587 | pos += scnprintf(buf+pos, bufsz-pos, | ||
588 | "\tPrimary: CTS Kill Mask 0x%08x\n", | ||
589 | iwl_bt_ctl_kill_msk[mvm->bt_cts_kill_msk[0]]); | ||
590 | pos += scnprintf(buf+pos, bufsz-pos, | ||
591 | "\tSecondary: ACK Kill Mask 0x%08x\n", | ||
592 | iwl_bt_ctl_kill_msk[mvm->bt_ack_kill_msk[1]]); | ||
593 | pos += scnprintf(buf+pos, bufsz-pos, | ||
594 | "\tSecondary: CTS Kill Mask 0x%08x\n", | ||
595 | iwl_bt_ctl_kill_msk[mvm->bt_cts_kill_msk[1]]); | ||
596 | |||
597 | } | 583 | } |
598 | 584 | ||
599 | mutex_unlock(&mvm->mutex); | 585 | mutex_unlock(&mvm->mutex); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h index f3b11897991e..d398a6102805 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h | |||
@@ -235,36 +235,12 @@ enum iwl_bt_coex_enabled_modules { | |||
235 | * struct iwl_bt_coex_cmd - bt coex configuration command | 235 | * struct iwl_bt_coex_cmd - bt coex configuration command |
236 | * @mode: enum %iwl_bt_coex_mode | 236 | * @mode: enum %iwl_bt_coex_mode |
237 | * @enabled_modules: enum %iwl_bt_coex_enabled_modules | 237 | * @enabled_modules: enum %iwl_bt_coex_enabled_modules |
238 | * @max_kill: max count of Tx retries due to kill from PTA | ||
239 | * @override_primary_lut: enum %iwl_bt_coex_lut_type: BT_COEX_INVALID_LUT | ||
240 | * should be set by default | ||
241 | * @override_secondary_lut: enum %iwl_bt_coex_lut_type: BT_COEX_INVALID_LUT | ||
242 | * should be set by default | ||
243 | * @bt4_antenna_isolation_thr: antenna threshold value | ||
244 | * @bt4_tx_tx_delta_freq_thr: TxTx delta frequency | ||
245 | * @bt4_tx_rx_max_freq0: TxRx max frequency | ||
246 | * @multiprio_lut: multi priority LUT configuration | ||
247 | * @mplut_prio_boost: BT priority boost registers | ||
248 | * @decision_lut: PTA decision LUT, per Prio-Ch | ||
249 | * | 238 | * |
250 | * The structure is used for the BT_COEX command. | 239 | * The structure is used for the BT_COEX command. |
251 | */ | 240 | */ |
252 | struct iwl_bt_coex_cmd { | 241 | struct iwl_bt_coex_cmd { |
253 | __le32 mode; | 242 | __le32 mode; |
254 | __le32 enabled_modules; | 243 | __le32 enabled_modules; |
255 | |||
256 | __le32 max_kill; | ||
257 | __le32 override_primary_lut; | ||
258 | __le32 override_secondary_lut; | ||
259 | __le32 bt4_antenna_isolation_thr; | ||
260 | |||
261 | __le32 bt4_tx_tx_delta_freq_thr; | ||
262 | __le32 bt4_tx_rx_max_freq0; | ||
263 | |||
264 | __le32 multiprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE]; | ||
265 | __le32 mplut_prio_boost[BT_COEX_BOOST_SIZE]; | ||
266 | |||
267 | __le32 decision_lut[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE]; | ||
268 | } __packed; /* BT_COEX_CMD_API_S_VER_6 */ | 244 | } __packed; /* BT_COEX_CMD_API_S_VER_6 */ |
269 | 245 | ||
270 | /** | 246 | /** |
@@ -280,29 +256,6 @@ struct iwl_bt_coex_corun_lut_update_cmd { | |||
280 | } __packed; /* BT_COEX_UPDATE_CORUN_LUT_API_S_VER_1 */ | 256 | } __packed; /* BT_COEX_UPDATE_CORUN_LUT_API_S_VER_1 */ |
281 | 257 | ||
282 | /** | 258 | /** |
283 | * struct iwl_bt_coex_sw_boost - SW boost values | ||
284 | * @wifi_tx_prio_boost: SW boost of wifi tx priority | ||
285 | * @wifi_rx_prio_boost: SW boost of wifi rx priority | ||
286 | * @kill_ack_msk: kill ACK mask. 1 - Tx ACK, 0 - kill Tx of ACK. | ||
287 | * @kill_cts_msk: kill CTS mask. 1 - Tx CTS, 0 - kill Tx of CTS. | ||
288 | */ | ||
289 | struct iwl_bt_coex_sw_boost { | ||
290 | __le32 wifi_tx_prio_boost; | ||
291 | __le32 wifi_rx_prio_boost; | ||
292 | __le32 kill_ack_msk; | ||
293 | __le32 kill_cts_msk; | ||
294 | }; | ||
295 | |||
296 | /** | ||
297 | * struct iwl_bt_coex_sw_boost_update_cmd - command to update the SW boost | ||
298 | * @boost_values: check struct %iwl_bt_coex_sw_boost - one for each channel | ||
299 | * primary / secondary / low priority | ||
300 | */ | ||
301 | struct iwl_bt_coex_sw_boost_update_cmd { | ||
302 | struct iwl_bt_coex_sw_boost boost_values[3]; | ||
303 | } __packed; /* BT_COEX_UPDATE_SW_BOOST_S_VER_1 */ | ||
304 | |||
305 | /** | ||
306 | * struct iwl_bt_coex_reduced_txp_update_cmd | 259 | * struct iwl_bt_coex_reduced_txp_update_cmd |
307 | * @reduced_txp: bit BT_REDUCED_TX_POWER_BIT to enable / disable, rest of the | 260 | * @reduced_txp: bit BT_REDUCED_TX_POWER_BIT to enable / disable, rest of the |
308 | * bits are the sta_id (value) | 261 | * bits are the sta_id (value) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index d95b47213731..aab68cbae754 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h | |||
@@ -212,6 +212,10 @@ enum { | |||
212 | REPLY_RX_MPDU_CMD = 0xc1, | 212 | REPLY_RX_MPDU_CMD = 0xc1, |
213 | BA_NOTIF = 0xc5, | 213 | BA_NOTIF = 0xc5, |
214 | 214 | ||
215 | /* Location Aware Regulatory */ | ||
216 | MCC_UPDATE_CMD = 0xc8, | ||
217 | MCC_CHUB_UPDATE_CMD = 0xc9, | ||
218 | |||
215 | MARKER_CMD = 0xcb, | 219 | MARKER_CMD = 0xcb, |
216 | 220 | ||
217 | /* BT Coex */ | 221 | /* BT Coex */ |
@@ -362,7 +366,8 @@ enum { | |||
362 | NVM_SECTION_TYPE_CALIBRATION = 4, | 366 | NVM_SECTION_TYPE_CALIBRATION = 4, |
363 | NVM_SECTION_TYPE_PRODUCTION = 5, | 367 | NVM_SECTION_TYPE_PRODUCTION = 5, |
364 | NVM_SECTION_TYPE_MAC_OVERRIDE = 11, | 368 | NVM_SECTION_TYPE_MAC_OVERRIDE = 11, |
365 | NVM_MAX_NUM_SECTIONS = 12, | 369 | NVM_SECTION_TYPE_PHY_SKU = 12, |
370 | NVM_MAX_NUM_SECTIONS = 13, | ||
366 | }; | 371 | }; |
367 | 372 | ||
368 | /** | 373 | /** |
@@ -1442,7 +1447,19 @@ enum iwl_sf_scenario { | |||
1442 | #define SF_W_MARK_LEGACY 4096 | 1447 | #define SF_W_MARK_LEGACY 4096 |
1443 | #define SF_W_MARK_SCAN 4096 | 1448 | #define SF_W_MARK_SCAN 4096 |
1444 | 1449 | ||
1445 | /* SF Scenarios timers for FULL_ON state (aligned to 32 uSec) */ | 1450 | /* SF Scenarios timers for default configuration (aligned to 32 uSec) */ |
1451 | #define SF_SINGLE_UNICAST_IDLE_TIMER_DEF 160 /* 150 uSec */ | ||
1452 | #define SF_SINGLE_UNICAST_AGING_TIMER_DEF 400 /* 0.4 mSec */ | ||
1453 | #define SF_AGG_UNICAST_IDLE_TIMER_DEF 160 /* 150 uSec */ | ||
1454 | #define SF_AGG_UNICAST_AGING_TIMER_DEF 400 /* 0.4 mSec */ | ||
1455 | #define SF_MCAST_IDLE_TIMER_DEF 160 /* 150 mSec */ | ||
1456 | #define SF_MCAST_AGING_TIMER_DEF 400 /* 0.4 mSec */ | ||
1457 | #define SF_BA_IDLE_TIMER_DEF 160 /* 150 uSec */ | ||
1458 | #define SF_BA_AGING_TIMER_DEF 400 /* 0.4 mSec */ | ||
1459 | #define SF_TX_RE_IDLE_TIMER_DEF 160 /* 150 uSec */ | ||
1460 | #define SF_TX_RE_AGING_TIMER_DEF 400 /* 0.4 mSec */ | ||
1461 | |||
1462 | /* SF Scenarios timers for BSS MAC configuration (aligned to 32 uSec) */ | ||
1446 | #define SF_SINGLE_UNICAST_IDLE_TIMER 320 /* 300 uSec */ | 1463 | #define SF_SINGLE_UNICAST_IDLE_TIMER 320 /* 300 uSec */ |
1447 | #define SF_SINGLE_UNICAST_AGING_TIMER 2016 /* 2 mSec */ | 1464 | #define SF_SINGLE_UNICAST_AGING_TIMER 2016 /* 2 mSec */ |
1448 | #define SF_AGG_UNICAST_IDLE_TIMER 320 /* 300 uSec */ | 1465 | #define SF_AGG_UNICAST_IDLE_TIMER 320 /* 300 uSec */ |
@@ -1473,6 +1490,92 @@ struct iwl_sf_cfg_cmd { | |||
1473 | __le32 full_on_timeouts[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES]; | 1490 | __le32 full_on_timeouts[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES]; |
1474 | } __packed; /* SF_CFG_API_S_VER_2 */ | 1491 | } __packed; /* SF_CFG_API_S_VER_2 */ |
1475 | 1492 | ||
1493 | /*********************************** | ||
1494 | * Location Aware Regulatory (LAR) API - MCC updates | ||
1495 | ***********************************/ | ||
1496 | |||
1497 | /** | ||
1498 | * struct iwl_mcc_update_cmd - Request the device to update geographic | ||
1499 | * regulatory profile according to the given MCC (Mobile Country Code). | ||
1500 | * The MCC is two letter-code, ascii upper case[A-Z] or '00' for world domain. | ||
1501 | * 'ZZ' MCC will be used to switch to NVM default profile; in this case, the | ||
1502 | * MCC in the cmd response will be the relevant MCC in the NVM. | ||
1503 | * @mcc: given mobile country code | ||
1504 | * @source_id: the source from where we got the MCC, see iwl_mcc_source | ||
1505 | * @reserved: reserved for alignment | ||
1506 | */ | ||
1507 | struct iwl_mcc_update_cmd { | ||
1508 | __le16 mcc; | ||
1509 | u8 source_id; | ||
1510 | u8 reserved; | ||
1511 | } __packed; /* LAR_UPDATE_MCC_CMD_API_S */ | ||
1512 | |||
1513 | /** | ||
1514 | * iwl_mcc_update_resp - response to MCC_UPDATE_CMD. | ||
1515 | * Contains the new channel control profile map, if changed, and the new MCC | ||
1516 | * (mobile country code). | ||
1517 | * The new MCC may be different than what was requested in MCC_UPDATE_CMD. | ||
1518 | * @status: see &enum iwl_mcc_update_status | ||
1519 | * @mcc: the new applied MCC | ||
1520 | * @cap: capabilities for all channels which matches the MCC | ||
1521 | * @source_id: the MCC source, see iwl_mcc_source | ||
1522 | * @n_channels: number of channels in @channels_data (may be 14, 39, 50 or 51 | ||
1523 | * channels, depending on platform) | ||
1524 | * @channels: channel control data map, DWORD for each channel. Only the first | ||
1525 | * 16bits are used. | ||
1526 | */ | ||
1527 | struct iwl_mcc_update_resp { | ||
1528 | __le32 status; | ||
1529 | __le16 mcc; | ||
1530 | u8 cap; | ||
1531 | u8 source_id; | ||
1532 | __le32 n_channels; | ||
1533 | __le32 channels[0]; | ||
1534 | } __packed; /* LAR_UPDATE_MCC_CMD_RESP_S */ | ||
1535 | |||
1536 | /** | ||
1537 | * struct iwl_mcc_chub_notif - chub notifies of mcc change | ||
1538 | * (MCC_CHUB_UPDATE_CMD = 0xc9) | ||
1539 | * The Chub (Communication Hub, CommsHUB) is a HW component that connects to | ||
1540 | * the cellular and connectivity cores that gets updates of the mcc, and | ||
1541 | * notifies the ucode directly of any mcc change. | ||
1542 | * The ucode requests the driver to request the device to update geographic | ||
1543 | * regulatory profile according to the given MCC (Mobile Country Code). | ||
1544 | * The MCC is two letter-code, ascii upper case[A-Z] or '00' for world domain. | ||
1545 | * 'ZZ' MCC will be used to switch to NVM default profile; in this case, the | ||
1546 | * MCC in the cmd response will be the relevant MCC in the NVM. | ||
1547 | * @mcc: given mobile country code | ||
1548 | * @source_id: identity of the change originator, see iwl_mcc_source | ||
1549 | * @reserved1: reserved for alignment | ||
1550 | */ | ||
1551 | struct iwl_mcc_chub_notif { | ||
1552 | u16 mcc; | ||
1553 | u8 source_id; | ||
1554 | u8 reserved1; | ||
1555 | } __packed; /* LAR_MCC_NOTIFY_S */ | ||
1556 | |||
1557 | enum iwl_mcc_update_status { | ||
1558 | MCC_RESP_NEW_CHAN_PROFILE, | ||
1559 | MCC_RESP_SAME_CHAN_PROFILE, | ||
1560 | MCC_RESP_INVALID, | ||
1561 | MCC_RESP_NVM_DISABLED, | ||
1562 | MCC_RESP_ILLEGAL, | ||
1563 | MCC_RESP_LOW_PRIORITY, | ||
1564 | }; | ||
1565 | |||
1566 | enum iwl_mcc_source { | ||
1567 | MCC_SOURCE_OLD_FW = 0, | ||
1568 | MCC_SOURCE_ME = 1, | ||
1569 | MCC_SOURCE_BIOS = 2, | ||
1570 | MCC_SOURCE_3G_LTE_HOST = 3, | ||
1571 | MCC_SOURCE_3G_LTE_DEVICE = 4, | ||
1572 | MCC_SOURCE_WIFI = 5, | ||
1573 | MCC_SOURCE_RESERVED = 6, | ||
1574 | MCC_SOURCE_DEFAULT = 7, | ||
1575 | MCC_SOURCE_UNINITIALIZED = 8, | ||
1576 | MCC_SOURCE_GET_CURRENT = 0x10 | ||
1577 | }; | ||
1578 | |||
1476 | /* DTS measurements */ | 1579 | /* DTS measurements */ |
1477 | 1580 | ||
1478 | enum iwl_dts_measurement_flags { | 1581 | enum iwl_dts_measurement_flags { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index a81da4cde643..6cf7d9837ca5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c | |||
@@ -739,6 +739,16 @@ int iwl_mvm_up(struct iwl_mvm *mvm) | |||
739 | if (ret) | 739 | if (ret) |
740 | goto error; | 740 | goto error; |
741 | 741 | ||
742 | /* | ||
743 | * RTNL is not taken during Ct-kill, but we don't need to scan/Tx | ||
744 | * anyway, so don't init MCC. | ||
745 | */ | ||
746 | if (!test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status)) { | ||
747 | ret = iwl_mvm_init_mcc(mvm); | ||
748 | if (ret) | ||
749 | goto error; | ||
750 | } | ||
751 | |||
742 | if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) { | 752 | if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) { |
743 | ret = iwl_mvm_config_scan(mvm); | 753 | ret = iwl_mvm_config_scan(mvm); |
744 | if (ret) | 754 | if (ret) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 7396b52262b5..302c8cc50f25 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -86,6 +86,7 @@ | |||
86 | #include "iwl-fw-error-dump.h" | 86 | #include "iwl-fw-error-dump.h" |
87 | #include "iwl-prph.h" | 87 | #include "iwl-prph.h" |
88 | #include "iwl-csr.h" | 88 | #include "iwl-csr.h" |
89 | #include "iwl-nvm-parse.h" | ||
89 | 90 | ||
90 | static const struct ieee80211_iface_limit iwl_mvm_limits[] = { | 91 | static const struct ieee80211_iface_limit iwl_mvm_limits[] = { |
91 | { | 92 | { |
@@ -301,6 +302,109 @@ static void iwl_mvm_reset_phy_ctxts(struct iwl_mvm *mvm) | |||
301 | } | 302 | } |
302 | } | 303 | } |
303 | 304 | ||
305 | struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy, | ||
306 | const char *alpha2, | ||
307 | enum iwl_mcc_source src_id, | ||
308 | bool *changed) | ||
309 | { | ||
310 | struct ieee80211_regdomain *regd = NULL; | ||
311 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | ||
312 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
313 | struct iwl_mcc_update_resp *resp; | ||
314 | |||
315 | IWL_DEBUG_LAR(mvm, "Getting regdomain data for %s from FW\n", alpha2); | ||
316 | |||
317 | lockdep_assert_held(&mvm->mutex); | ||
318 | |||
319 | resp = iwl_mvm_update_mcc(mvm, alpha2, src_id); | ||
320 | if (IS_ERR_OR_NULL(resp)) { | ||
321 | IWL_DEBUG_LAR(mvm, "Could not get update from FW %d\n", | ||
322 | PTR_RET(resp)); | ||
323 | goto out; | ||
324 | } | ||
325 | |||
326 | if (changed) | ||
327 | *changed = (resp->status == MCC_RESP_NEW_CHAN_PROFILE); | ||
328 | |||
329 | regd = iwl_parse_nvm_mcc_info(mvm->trans->dev, mvm->cfg, | ||
330 | __le32_to_cpu(resp->n_channels), | ||
331 | resp->channels, | ||
332 | __le16_to_cpu(resp->mcc)); | ||
333 | /* Store the return source id */ | ||
334 | src_id = resp->source_id; | ||
335 | kfree(resp); | ||
336 | if (IS_ERR_OR_NULL(regd)) { | ||
337 | IWL_DEBUG_LAR(mvm, "Could not get parse update from FW %d\n", | ||
338 | PTR_RET(regd)); | ||
339 | goto out; | ||
340 | } | ||
341 | |||
342 | IWL_DEBUG_LAR(mvm, "setting alpha2 from FW to %s (0x%x, 0x%x) src=%d\n", | ||
343 | regd->alpha2, regd->alpha2[0], regd->alpha2[1], src_id); | ||
344 | mvm->lar_regdom_set = true; | ||
345 | mvm->mcc_src = src_id; | ||
346 | |||
347 | out: | ||
348 | return regd; | ||
349 | } | ||
350 | |||
351 | void iwl_mvm_update_changed_regdom(struct iwl_mvm *mvm) | ||
352 | { | ||
353 | bool changed; | ||
354 | struct ieee80211_regdomain *regd; | ||
355 | |||
356 | if (!iwl_mvm_is_lar_supported(mvm)) | ||
357 | return; | ||
358 | |||
359 | regd = iwl_mvm_get_current_regdomain(mvm, &changed); | ||
360 | if (!IS_ERR_OR_NULL(regd)) { | ||
361 | /* only update the regulatory core if changed */ | ||
362 | if (changed) | ||
363 | regulatory_set_wiphy_regd(mvm->hw->wiphy, regd); | ||
364 | |||
365 | kfree(regd); | ||
366 | } | ||
367 | } | ||
368 | |||
369 | struct ieee80211_regdomain *iwl_mvm_get_current_regdomain(struct iwl_mvm *mvm, | ||
370 | bool *changed) | ||
371 | { | ||
372 | return iwl_mvm_get_regdomain(mvm->hw->wiphy, "ZZ", | ||
373 | iwl_mvm_is_wifi_mcc_supported(mvm) ? | ||
374 | MCC_SOURCE_GET_CURRENT : | ||
375 | MCC_SOURCE_OLD_FW, changed); | ||
376 | } | ||
377 | |||
378 | int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm) | ||
379 | { | ||
380 | enum iwl_mcc_source used_src; | ||
381 | struct ieee80211_regdomain *regd; | ||
382 | const struct ieee80211_regdomain *r = | ||
383 | rtnl_dereference(mvm->hw->wiphy->regd); | ||
384 | |||
385 | if (!r) | ||
386 | return 0; | ||
387 | |||
388 | /* save the last source in case we overwrite it below */ | ||
389 | used_src = mvm->mcc_src; | ||
390 | if (iwl_mvm_is_wifi_mcc_supported(mvm)) { | ||
391 | /* Notify the firmware we support wifi location updates */ | ||
392 | regd = iwl_mvm_get_current_regdomain(mvm, NULL); | ||
393 | if (!IS_ERR_OR_NULL(regd)) | ||
394 | kfree(regd); | ||
395 | } | ||
396 | |||
397 | /* Now set our last stored MCC and source */ | ||
398 | regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, r->alpha2, used_src, NULL); | ||
399 | if (IS_ERR_OR_NULL(regd)) | ||
400 | return -EIO; | ||
401 | |||
402 | regulatory_set_wiphy_regd(mvm->hw->wiphy, regd); | ||
403 | kfree(regd); | ||
404 | |||
405 | return 0; | ||
406 | } | ||
407 | |||
304 | int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | 408 | int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) |
305 | { | 409 | { |
306 | struct ieee80211_hw *hw = mvm->hw; | 410 | struct ieee80211_hw *hw = mvm->hw; |
@@ -356,8 +460,12 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
356 | BIT(NL80211_IFTYPE_ADHOC); | 460 | BIT(NL80211_IFTYPE_ADHOC); |
357 | 461 | ||
358 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | 462 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; |
359 | hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG | | 463 | hw->wiphy->regulatory_flags |= REGULATORY_ENABLE_RELAX_NO_IR; |
360 | REGULATORY_DISABLE_BEACON_HINTS; | 464 | if (iwl_mvm_is_lar_supported(mvm)) |
465 | hw->wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED; | ||
466 | else | ||
467 | hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG | | ||
468 | REGULATORY_DISABLE_BEACON_HINTS; | ||
361 | 469 | ||
362 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_GO_UAPSD) | 470 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_GO_UAPSD) |
363 | hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; | 471 | hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; |
@@ -1193,7 +1301,7 @@ static void iwl_mvm_restart_complete(struct iwl_mvm *mvm) | |||
1193 | 1301 | ||
1194 | clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); | 1302 | clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); |
1195 | iwl_mvm_d0i3_enable_tx(mvm, NULL); | 1303 | iwl_mvm_d0i3_enable_tx(mvm, NULL); |
1196 | ret = iwl_mvm_update_quotas(mvm, NULL); | 1304 | ret = iwl_mvm_update_quotas(mvm, false, NULL); |
1197 | if (ret) | 1305 | if (ret) |
1198 | IWL_ERR(mvm, "Failed to update quotas after restart (%d)\n", | 1306 | IWL_ERR(mvm, "Failed to update quotas after restart (%d)\n", |
1199 | ret); | 1307 | ret); |
@@ -1872,7 +1980,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
1872 | sizeof(mvmvif->beacon_stats)); | 1980 | sizeof(mvmvif->beacon_stats)); |
1873 | 1981 | ||
1874 | /* add quota for this interface */ | 1982 | /* add quota for this interface */ |
1875 | ret = iwl_mvm_update_quotas(mvm, NULL); | 1983 | ret = iwl_mvm_update_quotas(mvm, true, NULL); |
1876 | if (ret) { | 1984 | if (ret) { |
1877 | IWL_ERR(mvm, "failed to update quotas\n"); | 1985 | IWL_ERR(mvm, "failed to update quotas\n"); |
1878 | return; | 1986 | return; |
@@ -1924,7 +2032,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, | |||
1924 | mvm->d0i3_ap_sta_id = IWL_MVM_STATION_COUNT; | 2032 | mvm->d0i3_ap_sta_id = IWL_MVM_STATION_COUNT; |
1925 | mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT; | 2033 | mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT; |
1926 | /* remove quota for this interface */ | 2034 | /* remove quota for this interface */ |
1927 | ret = iwl_mvm_update_quotas(mvm, NULL); | 2035 | ret = iwl_mvm_update_quotas(mvm, false, NULL); |
1928 | if (ret) | 2036 | if (ret) |
1929 | IWL_ERR(mvm, "failed to update quotas\n"); | 2037 | IWL_ERR(mvm, "failed to update quotas\n"); |
1930 | 2038 | ||
@@ -2043,7 +2151,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, | |||
2043 | /* power updated needs to be done before quotas */ | 2151 | /* power updated needs to be done before quotas */ |
2044 | iwl_mvm_power_update_mac(mvm); | 2152 | iwl_mvm_power_update_mac(mvm); |
2045 | 2153 | ||
2046 | ret = iwl_mvm_update_quotas(mvm, NULL); | 2154 | ret = iwl_mvm_update_quotas(mvm, false, NULL); |
2047 | if (ret) | 2155 | if (ret) |
2048 | goto out_quota_failed; | 2156 | goto out_quota_failed; |
2049 | 2157 | ||
@@ -2109,7 +2217,7 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw, | |||
2109 | if (vif->p2p && mvm->p2p_device_vif) | 2217 | if (vif->p2p && mvm->p2p_device_vif) |
2110 | iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false, NULL); | 2218 | iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false, NULL); |
2111 | 2219 | ||
2112 | iwl_mvm_update_quotas(mvm, NULL); | 2220 | iwl_mvm_update_quotas(mvm, false, NULL); |
2113 | iwl_mvm_send_rm_bcast_sta(mvm, vif); | 2221 | iwl_mvm_send_rm_bcast_sta(mvm, vif); |
2114 | iwl_mvm_binding_remove_vif(mvm, vif); | 2222 | iwl_mvm_binding_remove_vif(mvm, vif); |
2115 | 2223 | ||
@@ -2248,6 +2356,12 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw, | |||
2248 | 2356 | ||
2249 | mutex_lock(&mvm->mutex); | 2357 | mutex_lock(&mvm->mutex); |
2250 | 2358 | ||
2359 | if (iwl_mvm_is_lar_supported(mvm) && !mvm->lar_regdom_set) { | ||
2360 | IWL_ERR(mvm, "scan while LAR regdomain is not set\n"); | ||
2361 | ret = -EBUSY; | ||
2362 | goto out; | ||
2363 | } | ||
2364 | |||
2251 | if (mvm->scan_status != IWL_MVM_SCAN_NONE) { | 2365 | if (mvm->scan_status != IWL_MVM_SCAN_NONE) { |
2252 | ret = -EBUSY; | 2366 | ret = -EBUSY; |
2253 | goto out; | 2367 | goto out; |
@@ -2328,25 +2442,35 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, | |||
2328 | { | 2442 | { |
2329 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 2443 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
2330 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | 2444 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
2445 | unsigned long txqs = 0, tids = 0; | ||
2331 | int tid; | 2446 | int tid; |
2332 | 2447 | ||
2448 | spin_lock_bh(&mvmsta->lock); | ||
2449 | for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) { | ||
2450 | struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid]; | ||
2451 | |||
2452 | if (tid_data->state != IWL_AGG_ON && | ||
2453 | tid_data->state != IWL_EMPTYING_HW_QUEUE_DELBA) | ||
2454 | continue; | ||
2455 | |||
2456 | __set_bit(tid_data->txq_id, &txqs); | ||
2457 | |||
2458 | if (iwl_mvm_tid_queued(tid_data) == 0) | ||
2459 | continue; | ||
2460 | |||
2461 | __set_bit(tid, &tids); | ||
2462 | } | ||
2463 | |||
2333 | switch (cmd) { | 2464 | switch (cmd) { |
2334 | case STA_NOTIFY_SLEEP: | 2465 | case STA_NOTIFY_SLEEP: |
2335 | if (atomic_read(&mvm->pending_frames[mvmsta->sta_id]) > 0) | 2466 | if (atomic_read(&mvm->pending_frames[mvmsta->sta_id]) > 0) |
2336 | ieee80211_sta_block_awake(hw, sta, true); | 2467 | ieee80211_sta_block_awake(hw, sta, true); |
2337 | spin_lock_bh(&mvmsta->lock); | ||
2338 | for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) { | ||
2339 | struct iwl_mvm_tid_data *tid_data; | ||
2340 | 2468 | ||
2341 | tid_data = &mvmsta->tid_data[tid]; | 2469 | for_each_set_bit(tid, &tids, IWL_MAX_TID_COUNT) |
2342 | if (tid_data->state != IWL_AGG_ON && | ||
2343 | tid_data->state != IWL_EMPTYING_HW_QUEUE_DELBA) | ||
2344 | continue; | ||
2345 | if (iwl_mvm_tid_queued(tid_data) == 0) | ||
2346 | continue; | ||
2347 | ieee80211_sta_set_buffered(sta, tid, true); | 2470 | ieee80211_sta_set_buffered(sta, tid, true); |
2348 | } | 2471 | |
2349 | spin_unlock_bh(&mvmsta->lock); | 2472 | if (txqs) |
2473 | iwl_trans_freeze_txq_timer(mvm->trans, txqs, true); | ||
2350 | /* | 2474 | /* |
2351 | * The fw updates the STA to be asleep. Tx packets on the Tx | 2475 | * The fw updates the STA to be asleep. Tx packets on the Tx |
2352 | * queues to this station will not be transmitted. The fw will | 2476 | * queues to this station will not be transmitted. The fw will |
@@ -2356,11 +2480,15 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, | |||
2356 | case STA_NOTIFY_AWAKE: | 2480 | case STA_NOTIFY_AWAKE: |
2357 | if (WARN_ON(mvmsta->sta_id == IWL_MVM_STATION_COUNT)) | 2481 | if (WARN_ON(mvmsta->sta_id == IWL_MVM_STATION_COUNT)) |
2358 | break; | 2482 | break; |
2483 | |||
2484 | if (txqs) | ||
2485 | iwl_trans_freeze_txq_timer(mvm->trans, txqs, false); | ||
2359 | iwl_mvm_sta_modify_ps_wake(mvm, sta); | 2486 | iwl_mvm_sta_modify_ps_wake(mvm, sta); |
2360 | break; | 2487 | break; |
2361 | default: | 2488 | default: |
2362 | break; | 2489 | break; |
2363 | } | 2490 | } |
2491 | spin_unlock_bh(&mvmsta->lock); | ||
2364 | } | 2492 | } |
2365 | 2493 | ||
2366 | static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw, | 2494 | static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw, |
@@ -2598,6 +2726,12 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw, | |||
2598 | 2726 | ||
2599 | mutex_lock(&mvm->mutex); | 2727 | mutex_lock(&mvm->mutex); |
2600 | 2728 | ||
2729 | if (iwl_mvm_is_lar_supported(mvm) && !mvm->lar_regdom_set) { | ||
2730 | IWL_ERR(mvm, "sched-scan while LAR regdomain is not set\n"); | ||
2731 | ret = -EBUSY; | ||
2732 | goto out; | ||
2733 | } | ||
2734 | |||
2601 | if (!vif->bss_conf.idle) { | 2735 | if (!vif->bss_conf.idle) { |
2602 | ret = -EBUSY; | 2736 | ret = -EBUSY; |
2603 | goto out; | 2737 | goto out; |
@@ -3159,14 +3293,14 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm, | |||
3159 | */ | 3293 | */ |
3160 | if (vif->type == NL80211_IFTYPE_MONITOR) { | 3294 | if (vif->type == NL80211_IFTYPE_MONITOR) { |
3161 | mvmvif->monitor_active = true; | 3295 | mvmvif->monitor_active = true; |
3162 | ret = iwl_mvm_update_quotas(mvm, NULL); | 3296 | ret = iwl_mvm_update_quotas(mvm, false, NULL); |
3163 | if (ret) | 3297 | if (ret) |
3164 | goto out_remove_binding; | 3298 | goto out_remove_binding; |
3165 | } | 3299 | } |
3166 | 3300 | ||
3167 | /* Handle binding during CSA */ | 3301 | /* Handle binding during CSA */ |
3168 | if (vif->type == NL80211_IFTYPE_AP) { | 3302 | if (vif->type == NL80211_IFTYPE_AP) { |
3169 | iwl_mvm_update_quotas(mvm, NULL); | 3303 | iwl_mvm_update_quotas(mvm, false, NULL); |
3170 | iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); | 3304 | iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); |
3171 | } | 3305 | } |
3172 | 3306 | ||
@@ -3190,7 +3324,7 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm, | |||
3190 | 3324 | ||
3191 | iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_CSA); | 3325 | iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_CSA); |
3192 | 3326 | ||
3193 | iwl_mvm_update_quotas(mvm, NULL); | 3327 | iwl_mvm_update_quotas(mvm, false, NULL); |
3194 | } | 3328 | } |
3195 | 3329 | ||
3196 | goto out; | 3330 | goto out; |
@@ -3263,7 +3397,7 @@ static void __iwl_mvm_unassign_vif_chanctx(struct iwl_mvm *mvm, | |||
3263 | break; | 3397 | break; |
3264 | } | 3398 | } |
3265 | 3399 | ||
3266 | iwl_mvm_update_quotas(mvm, disabled_vif); | 3400 | iwl_mvm_update_quotas(mvm, false, disabled_vif); |
3267 | iwl_mvm_binding_remove_vif(mvm, vif); | 3401 | iwl_mvm_binding_remove_vif(mvm, vif); |
3268 | 3402 | ||
3269 | out: | 3403 | out: |
@@ -3455,7 +3589,7 @@ static int __iwl_mvm_mac_testmode_cmd(struct iwl_mvm *mvm, | |||
3455 | mvm->noa_duration = noa_duration; | 3589 | mvm->noa_duration = noa_duration; |
3456 | mvm->noa_vif = vif; | 3590 | mvm->noa_vif = vif; |
3457 | 3591 | ||
3458 | return iwl_mvm_update_quotas(mvm, NULL); | 3592 | return iwl_mvm_update_quotas(mvm, false, NULL); |
3459 | case IWL_MVM_TM_CMD_SET_BEACON_FILTER: | 3593 | case IWL_MVM_TM_CMD_SET_BEACON_FILTER: |
3460 | /* must be associated client vif - ignore authorized */ | 3594 | /* must be associated client vif - ignore authorized */ |
3461 | if (!vif || vif->type != NL80211_IFTYPE_STATION || | 3595 | if (!vif || vif->type != NL80211_IFTYPE_STATION || |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 95cad68ab069..4b5c8f66df8b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -810,6 +810,9 @@ struct iwl_mvm { | |||
810 | /* system time of last beacon (for AP/GO interface) */ | 810 | /* system time of last beacon (for AP/GO interface) */ |
811 | u32 ap_last_beacon_gp2; | 811 | u32 ap_last_beacon_gp2; |
812 | 812 | ||
813 | bool lar_regdom_set; | ||
814 | enum iwl_mcc_source mcc_src; | ||
815 | |||
813 | u8 low_latency_agg_frame_limit; | 816 | u8 low_latency_agg_frame_limit; |
814 | 817 | ||
815 | /* TDLS channel switch data */ | 818 | /* TDLS channel switch data */ |
@@ -910,6 +913,30 @@ static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm) | |||
910 | (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_D0I3_SUPPORT); | 913 | (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_D0I3_SUPPORT); |
911 | } | 914 | } |
912 | 915 | ||
916 | static inline bool iwl_mvm_is_lar_supported(struct iwl_mvm *mvm) | ||
917 | { | ||
918 | bool nvm_lar = mvm->nvm_data->lar_enabled; | ||
919 | bool tlv_lar = mvm->fw->ucode_capa.capa[0] & | ||
920 | IWL_UCODE_TLV_CAPA_LAR_SUPPORT; | ||
921 | |||
922 | if (iwlwifi_mod_params.lar_disable) | ||
923 | return false; | ||
924 | |||
925 | /* | ||
926 | * Enable LAR only if it is supported by the FW (TLV) && | ||
927 | * enabled in the NVM | ||
928 | */ | ||
929 | if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000) | ||
930 | return nvm_lar && tlv_lar; | ||
931 | else | ||
932 | return tlv_lar; | ||
933 | } | ||
934 | |||
935 | static inline bool iwl_mvm_is_wifi_mcc_supported(struct iwl_mvm *mvm) | ||
936 | { | ||
937 | return mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_WIFI_MCC_UPDATE; | ||
938 | } | ||
939 | |||
913 | static inline bool iwl_mvm_is_scd_cfg_supported(struct iwl_mvm *mvm) | 940 | static inline bool iwl_mvm_is_scd_cfg_supported(struct iwl_mvm *mvm) |
914 | { | 941 | { |
915 | return mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_SCD_CFG; | 942 | return mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_SCD_CFG; |
@@ -921,6 +948,12 @@ static inline bool iwl_mvm_bt_is_plcr_supported(struct iwl_mvm *mvm) | |||
921 | IWL_MVM_BT_COEX_CORUNNING; | 948 | IWL_MVM_BT_COEX_CORUNNING; |
922 | } | 949 | } |
923 | 950 | ||
951 | static inline bool iwl_mvm_bt_is_rrc_supported(struct iwl_mvm *mvm) | ||
952 | { | ||
953 | return (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_BT_COEX_RRC) && | ||
954 | IWL_MVM_BT_COEX_RRC; | ||
955 | } | ||
956 | |||
924 | extern const u8 iwl_mvm_ac_to_tx_fifo[]; | 957 | extern const u8 iwl_mvm_ac_to_tx_fifo[]; |
925 | 958 | ||
926 | struct iwl_rate_info { | 959 | struct iwl_rate_info { |
@@ -1106,7 +1139,7 @@ int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | |||
1106 | int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 1139 | int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
1107 | 1140 | ||
1108 | /* Quota management */ | 1141 | /* Quota management */ |
1109 | int iwl_mvm_update_quotas(struct iwl_mvm *mvm, | 1142 | int iwl_mvm_update_quotas(struct iwl_mvm *mvm, bool force_upload, |
1110 | struct ieee80211_vif *disabled_vif); | 1143 | struct ieee80211_vif *disabled_vif); |
1111 | 1144 | ||
1112 | /* Scanning */ | 1145 | /* Scanning */ |
@@ -1282,17 +1315,6 @@ int iwl_mvm_rx_ant_coupling_notif_old(struct iwl_mvm *mvm, | |||
1282 | struct iwl_rx_cmd_buffer *rxb, | 1315 | struct iwl_rx_cmd_buffer *rxb, |
1283 | struct iwl_device_cmd *cmd); | 1316 | struct iwl_device_cmd *cmd); |
1284 | 1317 | ||
1285 | enum iwl_bt_kill_msk { | ||
1286 | BT_KILL_MSK_DEFAULT, | ||
1287 | BT_KILL_MSK_NEVER, | ||
1288 | BT_KILL_MSK_ALWAYS, | ||
1289 | BT_KILL_MSK_MAX, | ||
1290 | }; | ||
1291 | |||
1292 | extern const u8 iwl_bt_ack_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT]; | ||
1293 | extern const u8 iwl_bt_cts_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT]; | ||
1294 | extern const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX]; | ||
1295 | |||
1296 | /* beacon filtering */ | 1318 | /* beacon filtering */ |
1297 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 1319 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
1298 | void | 1320 | void |
@@ -1389,6 +1411,23 @@ void iwl_mvm_tt_exit(struct iwl_mvm *mvm); | |||
1389 | void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state); | 1411 | void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state); |
1390 | int iwl_mvm_get_temp(struct iwl_mvm *mvm); | 1412 | int iwl_mvm_get_temp(struct iwl_mvm *mvm); |
1391 | 1413 | ||
1414 | /* Location Aware Regulatory */ | ||
1415 | struct iwl_mcc_update_resp * | ||
1416 | iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2, | ||
1417 | enum iwl_mcc_source src_id); | ||
1418 | int iwl_mvm_init_mcc(struct iwl_mvm *mvm); | ||
1419 | int iwl_mvm_rx_chub_update_mcc(struct iwl_mvm *mvm, | ||
1420 | struct iwl_rx_cmd_buffer *rxb, | ||
1421 | struct iwl_device_cmd *cmd); | ||
1422 | struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy, | ||
1423 | const char *alpha2, | ||
1424 | enum iwl_mcc_source src_id, | ||
1425 | bool *changed); | ||
1426 | struct ieee80211_regdomain *iwl_mvm_get_current_regdomain(struct iwl_mvm *mvm, | ||
1427 | bool *changed); | ||
1428 | int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm); | ||
1429 | void iwl_mvm_update_changed_regdom(struct iwl_mvm *mvm); | ||
1430 | |||
1392 | /* smart fifo */ | 1431 | /* smart fifo */ |
1393 | int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 1432 | int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
1394 | bool added_vif); | 1433 | bool added_vif); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index 5383429d96c1..123e0a16aea8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c | |||
@@ -63,12 +63,16 @@ | |||
63 | * | 63 | * |
64 | *****************************************************************************/ | 64 | *****************************************************************************/ |
65 | #include <linux/firmware.h> | 65 | #include <linux/firmware.h> |
66 | #include <linux/rtnetlink.h> | ||
67 | #include <linux/pci.h> | ||
68 | #include <linux/acpi.h> | ||
66 | #include "iwl-trans.h" | 69 | #include "iwl-trans.h" |
67 | #include "iwl-csr.h" | 70 | #include "iwl-csr.h" |
68 | #include "mvm.h" | 71 | #include "mvm.h" |
69 | #include "iwl-eeprom-parse.h" | 72 | #include "iwl-eeprom-parse.h" |
70 | #include "iwl-eeprom-read.h" | 73 | #include "iwl-eeprom-read.h" |
71 | #include "iwl-nvm-parse.h" | 74 | #include "iwl-nvm-parse.h" |
75 | #include "iwl-prph.h" | ||
72 | 76 | ||
73 | /* Default NVM size to read */ | 77 | /* Default NVM size to read */ |
74 | #define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024) | 78 | #define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024) |
@@ -262,7 +266,9 @@ static struct iwl_nvm_data * | |||
262 | iwl_parse_nvm_sections(struct iwl_mvm *mvm) | 266 | iwl_parse_nvm_sections(struct iwl_mvm *mvm) |
263 | { | 267 | { |
264 | struct iwl_nvm_section *sections = mvm->nvm_sections; | 268 | struct iwl_nvm_section *sections = mvm->nvm_sections; |
265 | const __le16 *hw, *sw, *calib, *regulatory, *mac_override; | 269 | const __le16 *hw, *sw, *calib, *regulatory, *mac_override, *phy_sku; |
270 | bool is_family_8000_a_step = false, lar_enabled; | ||
271 | u32 mac_addr0, mac_addr1; | ||
266 | 272 | ||
267 | /* Checking for required sections */ | 273 | /* Checking for required sections */ |
268 | if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) { | 274 | if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) { |
@@ -286,22 +292,43 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) | |||
286 | "Can't parse mac_address, empty sections\n"); | 292 | "Can't parse mac_address, empty sections\n"); |
287 | return NULL; | 293 | return NULL; |
288 | } | 294 | } |
295 | |||
296 | if (CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_A_STEP) | ||
297 | is_family_8000_a_step = true; | ||
298 | |||
299 | /* PHY_SKU section is mandatory in B0 */ | ||
300 | if (!is_family_8000_a_step && | ||
301 | !mvm->nvm_sections[NVM_SECTION_TYPE_PHY_SKU].data) { | ||
302 | IWL_ERR(mvm, | ||
303 | "Can't parse phy_sku in B0, empty sections\n"); | ||
304 | return NULL; | ||
305 | } | ||
289 | } | 306 | } |
290 | 307 | ||
291 | if (WARN_ON(!mvm->cfg)) | 308 | if (WARN_ON(!mvm->cfg)) |
292 | return NULL; | 309 | return NULL; |
293 | 310 | ||
311 | /* read the mac address from WFMP registers */ | ||
312 | mac_addr0 = iwl_trans_read_prph(mvm->trans, WFMP_MAC_ADDR_0); | ||
313 | mac_addr1 = iwl_trans_read_prph(mvm->trans, WFMP_MAC_ADDR_1); | ||
314 | |||
294 | hw = (const __le16 *)sections[mvm->cfg->nvm_hw_section_num].data; | 315 | hw = (const __le16 *)sections[mvm->cfg->nvm_hw_section_num].data; |
295 | sw = (const __le16 *)sections[NVM_SECTION_TYPE_SW].data; | 316 | sw = (const __le16 *)sections[NVM_SECTION_TYPE_SW].data; |
296 | calib = (const __le16 *)sections[NVM_SECTION_TYPE_CALIBRATION].data; | 317 | calib = (const __le16 *)sections[NVM_SECTION_TYPE_CALIBRATION].data; |
297 | regulatory = (const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY].data; | 318 | regulatory = (const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY].data; |
298 | mac_override = | 319 | mac_override = |
299 | (const __le16 *)sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data; | 320 | (const __le16 *)sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data; |
321 | phy_sku = (const __le16 *)sections[NVM_SECTION_TYPE_PHY_SKU].data; | ||
322 | |||
323 | lar_enabled = !iwlwifi_mod_params.lar_disable && | ||
324 | (mvm->fw->ucode_capa.capa[0] & | ||
325 | IWL_UCODE_TLV_CAPA_LAR_SUPPORT); | ||
300 | 326 | ||
301 | return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib, | 327 | return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib, |
302 | regulatory, mac_override, | 328 | regulatory, mac_override, phy_sku, |
303 | mvm->fw->valid_tx_ant, | 329 | mvm->fw->valid_tx_ant, mvm->fw->valid_rx_ant, |
304 | mvm->fw->valid_rx_ant); | 330 | lar_enabled, is_family_8000_a_step, |
331 | mac_addr0, mac_addr1); | ||
305 | } | 332 | } |
306 | 333 | ||
307 | #define MAX_NVM_FILE_LEN 16384 | 334 | #define MAX_NVM_FILE_LEN 16384 |
@@ -570,3 +597,258 @@ int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic) | |||
570 | 597 | ||
571 | return 0; | 598 | return 0; |
572 | } | 599 | } |
600 | |||
601 | struct iwl_mcc_update_resp * | ||
602 | iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2, | ||
603 | enum iwl_mcc_source src_id) | ||
604 | { | ||
605 | struct iwl_mcc_update_cmd mcc_update_cmd = { | ||
606 | .mcc = cpu_to_le16(alpha2[0] << 8 | alpha2[1]), | ||
607 | .source_id = (u8)src_id, | ||
608 | }; | ||
609 | struct iwl_mcc_update_resp *mcc_resp, *resp_cp = NULL; | ||
610 | struct iwl_rx_packet *pkt; | ||
611 | struct iwl_host_cmd cmd = { | ||
612 | .id = MCC_UPDATE_CMD, | ||
613 | .flags = CMD_WANT_SKB, | ||
614 | .data = { &mcc_update_cmd }, | ||
615 | }; | ||
616 | |||
617 | int ret; | ||
618 | u32 status; | ||
619 | int resp_len, n_channels; | ||
620 | u16 mcc; | ||
621 | |||
622 | if (WARN_ON_ONCE(!iwl_mvm_is_lar_supported(mvm))) | ||
623 | return ERR_PTR(-EOPNOTSUPP); | ||
624 | |||
625 | cmd.len[0] = sizeof(struct iwl_mcc_update_cmd); | ||
626 | |||
627 | IWL_DEBUG_LAR(mvm, "send MCC update to FW with '%c%c' src = %d\n", | ||
628 | alpha2[0], alpha2[1], src_id); | ||
629 | |||
630 | ret = iwl_mvm_send_cmd(mvm, &cmd); | ||
631 | if (ret) | ||
632 | return ERR_PTR(ret); | ||
633 | |||
634 | pkt = cmd.resp_pkt; | ||
635 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { | ||
636 | IWL_ERR(mvm, "Bad return from MCC_UPDATE_COMMAND (0x%08X)\n", | ||
637 | pkt->hdr.flags); | ||
638 | ret = -EIO; | ||
639 | goto exit; | ||
640 | } | ||
641 | |||
642 | /* Extract MCC response */ | ||
643 | mcc_resp = (void *)pkt->data; | ||
644 | status = le32_to_cpu(mcc_resp->status); | ||
645 | |||
646 | mcc = le16_to_cpu(mcc_resp->mcc); | ||
647 | |||
648 | /* W/A for a FW/NVM issue - returns 0x00 for the world domain */ | ||
649 | if (mcc == 0) { | ||
650 | mcc = 0x3030; /* "00" - world */ | ||
651 | mcc_resp->mcc = cpu_to_le16(mcc); | ||
652 | } | ||
653 | |||
654 | n_channels = __le32_to_cpu(mcc_resp->n_channels); | ||
655 | IWL_DEBUG_LAR(mvm, | ||
656 | "MCC response status: 0x%x. new MCC: 0x%x ('%c%c') change: %d n_chans: %d\n", | ||
657 | status, mcc, mcc >> 8, mcc & 0xff, | ||
658 | !!(status == MCC_RESP_NEW_CHAN_PROFILE), n_channels); | ||
659 | |||
660 | resp_len = sizeof(*mcc_resp) + n_channels * sizeof(__le32); | ||
661 | resp_cp = kmemdup(mcc_resp, resp_len, GFP_KERNEL); | ||
662 | if (!resp_cp) { | ||
663 | ret = -ENOMEM; | ||
664 | goto exit; | ||
665 | } | ||
666 | |||
667 | ret = 0; | ||
668 | exit: | ||
669 | iwl_free_resp(&cmd); | ||
670 | if (ret) | ||
671 | return ERR_PTR(ret); | ||
672 | return resp_cp; | ||
673 | } | ||
674 | |||
675 | #ifdef CONFIG_ACPI | ||
676 | #define WRD_METHOD "WRDD" | ||
677 | #define WRDD_WIFI (0x07) | ||
678 | #define WRDD_WIGIG (0x10) | ||
679 | |||
680 | static u32 iwl_mvm_wrdd_get_mcc(struct iwl_mvm *mvm, union acpi_object *wrdd) | ||
681 | { | ||
682 | union acpi_object *mcc_pkg, *domain_type, *mcc_value; | ||
683 | u32 i; | ||
684 | |||
685 | if (wrdd->type != ACPI_TYPE_PACKAGE || | ||
686 | wrdd->package.count < 2 || | ||
687 | wrdd->package.elements[0].type != ACPI_TYPE_INTEGER || | ||
688 | wrdd->package.elements[0].integer.value != 0) { | ||
689 | IWL_DEBUG_LAR(mvm, "Unsupported wrdd structure\n"); | ||
690 | return 0; | ||
691 | } | ||
692 | |||
693 | for (i = 1 ; i < wrdd->package.count ; ++i) { | ||
694 | mcc_pkg = &wrdd->package.elements[i]; | ||
695 | |||
696 | if (mcc_pkg->type != ACPI_TYPE_PACKAGE || | ||
697 | mcc_pkg->package.count < 2 || | ||
698 | mcc_pkg->package.elements[0].type != ACPI_TYPE_INTEGER || | ||
699 | mcc_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) { | ||
700 | mcc_pkg = NULL; | ||
701 | continue; | ||
702 | } | ||
703 | |||
704 | domain_type = &mcc_pkg->package.elements[0]; | ||
705 | if (domain_type->integer.value == WRDD_WIFI) | ||
706 | break; | ||
707 | |||
708 | mcc_pkg = NULL; | ||
709 | } | ||
710 | |||
711 | if (mcc_pkg) { | ||
712 | mcc_value = &mcc_pkg->package.elements[1]; | ||
713 | return mcc_value->integer.value; | ||
714 | } | ||
715 | |||
716 | return 0; | ||
717 | } | ||
718 | |||
719 | static int iwl_mvm_get_bios_mcc(struct iwl_mvm *mvm, char *mcc) | ||
720 | { | ||
721 | acpi_handle root_handle; | ||
722 | acpi_handle handle; | ||
723 | struct acpi_buffer wrdd = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
724 | acpi_status status; | ||
725 | u32 mcc_val; | ||
726 | struct pci_dev *pdev = to_pci_dev(mvm->dev); | ||
727 | |||
728 | root_handle = ACPI_HANDLE(&pdev->dev); | ||
729 | if (!root_handle) { | ||
730 | IWL_DEBUG_LAR(mvm, | ||
731 | "Could not retrieve root port ACPI handle\n"); | ||
732 | return -ENOENT; | ||
733 | } | ||
734 | |||
735 | /* Get the method's handle */ | ||
736 | status = acpi_get_handle(root_handle, (acpi_string)WRD_METHOD, &handle); | ||
737 | if (ACPI_FAILURE(status)) { | ||
738 | IWL_DEBUG_LAR(mvm, "WRD method not found\n"); | ||
739 | return -ENOENT; | ||
740 | } | ||
741 | |||
742 | /* Call WRDD with no arguments */ | ||
743 | status = acpi_evaluate_object(handle, NULL, NULL, &wrdd); | ||
744 | if (ACPI_FAILURE(status)) { | ||
745 | IWL_DEBUG_LAR(mvm, "WRDC invocation failed (0x%x)\n", status); | ||
746 | return -ENOENT; | ||
747 | } | ||
748 | |||
749 | mcc_val = iwl_mvm_wrdd_get_mcc(mvm, wrdd.pointer); | ||
750 | kfree(wrdd.pointer); | ||
751 | if (!mcc_val) | ||
752 | return -ENOENT; | ||
753 | |||
754 | mcc[0] = (mcc_val >> 8) & 0xff; | ||
755 | mcc[1] = mcc_val & 0xff; | ||
756 | mcc[2] = '\0'; | ||
757 | return 0; | ||
758 | } | ||
759 | #else /* CONFIG_ACPI */ | ||
760 | static int iwl_mvm_get_bios_mcc(struct iwl_mvm *mvm, char *mcc) | ||
761 | { | ||
762 | return -ENOENT; | ||
763 | } | ||
764 | #endif | ||
765 | |||
766 | int iwl_mvm_init_mcc(struct iwl_mvm *mvm) | ||
767 | { | ||
768 | bool tlv_lar; | ||
769 | bool nvm_lar; | ||
770 | int retval; | ||
771 | struct ieee80211_regdomain *regd; | ||
772 | char mcc[3]; | ||
773 | |||
774 | if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000) { | ||
775 | tlv_lar = mvm->fw->ucode_capa.capa[0] & | ||
776 | IWL_UCODE_TLV_CAPA_LAR_SUPPORT; | ||
777 | nvm_lar = mvm->nvm_data->lar_enabled; | ||
778 | if (tlv_lar != nvm_lar) | ||
779 | IWL_INFO(mvm, | ||
780 | "Conflict between TLV & NVM regarding enabling LAR (TLV = %s NVM =%s)\n", | ||
781 | tlv_lar ? "enabled" : "disabled", | ||
782 | nvm_lar ? "enabled" : "disabled"); | ||
783 | } | ||
784 | |||
785 | if (!iwl_mvm_is_lar_supported(mvm)) | ||
786 | return 0; | ||
787 | |||
788 | /* | ||
789 | * During HW restart, only replay the last set MCC to FW. Otherwise, | ||
790 | * queue an update to cfg80211 to retrieve the default alpha2 from FW. | ||
791 | */ | ||
792 | if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { | ||
793 | /* This should only be called during vif up and hold RTNL */ | ||
794 | return iwl_mvm_init_fw_regd(mvm); | ||
795 | } | ||
796 | |||
797 | /* | ||
798 | * Driver regulatory hint for initial update, this also informs the | ||
799 | * firmware we support wifi location updates. | ||
800 | * Disallow scans that might crash the FW while the LAR regdomain | ||
801 | * is not set. | ||
802 | */ | ||
803 | mvm->lar_regdom_set = false; | ||
804 | |||
805 | regd = iwl_mvm_get_current_regdomain(mvm, NULL); | ||
806 | if (IS_ERR_OR_NULL(regd)) | ||
807 | return -EIO; | ||
808 | |||
809 | if (iwl_mvm_is_wifi_mcc_supported(mvm) && | ||
810 | !iwl_mvm_get_bios_mcc(mvm, mcc)) { | ||
811 | kfree(regd); | ||
812 | regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, mcc, | ||
813 | MCC_SOURCE_BIOS, NULL); | ||
814 | if (IS_ERR_OR_NULL(regd)) | ||
815 | return -EIO; | ||
816 | } | ||
817 | |||
818 | retval = regulatory_set_wiphy_regd_sync_rtnl(mvm->hw->wiphy, regd); | ||
819 | kfree(regd); | ||
820 | return retval; | ||
821 | } | ||
822 | |||
823 | int iwl_mvm_rx_chub_update_mcc(struct iwl_mvm *mvm, | ||
824 | struct iwl_rx_cmd_buffer *rxb, | ||
825 | struct iwl_device_cmd *cmd) | ||
826 | { | ||
827 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
828 | struct iwl_mcc_chub_notif *notif = (void *)pkt->data; | ||
829 | enum iwl_mcc_source src; | ||
830 | char mcc[3]; | ||
831 | struct ieee80211_regdomain *regd; | ||
832 | |||
833 | lockdep_assert_held(&mvm->mutex); | ||
834 | |||
835 | if (WARN_ON_ONCE(!iwl_mvm_is_lar_supported(mvm))) | ||
836 | return 0; | ||
837 | |||
838 | mcc[0] = notif->mcc >> 8; | ||
839 | mcc[1] = notif->mcc & 0xff; | ||
840 | mcc[2] = '\0'; | ||
841 | src = notif->source_id; | ||
842 | |||
843 | IWL_DEBUG_LAR(mvm, | ||
844 | "RX: received chub update mcc cmd (mcc '%s' src %d)\n", | ||
845 | mcc, src); | ||
846 | regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, mcc, src, NULL); | ||
847 | if (IS_ERR_OR_NULL(regd)) | ||
848 | return 0; | ||
849 | |||
850 | regulatory_set_wiphy_regd(mvm->hw->wiphy, regd); | ||
851 | kfree(regd); | ||
852 | |||
853 | return 0; | ||
854 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index fe40922a6b0d..80121e41ca22 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
@@ -82,7 +82,6 @@ | |||
82 | #include "rs.h" | 82 | #include "rs.h" |
83 | #include "fw-api-scan.h" | 83 | #include "fw-api-scan.h" |
84 | #include "time-event.h" | 84 | #include "time-event.h" |
85 | #include "iwl-fw-error-dump.h" | ||
86 | 85 | ||
87 | #define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux" | 86 | #define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux" |
88 | MODULE_DESCRIPTION(DRV_DESCRIPTION); | 87 | MODULE_DESCRIPTION(DRV_DESCRIPTION); |
@@ -234,6 +233,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { | |||
234 | iwl_mvm_rx_ant_coupling_notif, true), | 233 | iwl_mvm_rx_ant_coupling_notif, true), |
235 | 234 | ||
236 | RX_HANDLER(TIME_EVENT_NOTIFICATION, iwl_mvm_rx_time_event_notif, false), | 235 | RX_HANDLER(TIME_EVENT_NOTIFICATION, iwl_mvm_rx_time_event_notif, false), |
236 | RX_HANDLER(MCC_CHUB_UPDATE_CMD, iwl_mvm_rx_chub_update_mcc, true), | ||
237 | 237 | ||
238 | RX_HANDLER(EOSP_NOTIFICATION, iwl_mvm_rx_eosp_notif, false), | 238 | RX_HANDLER(EOSP_NOTIFICATION, iwl_mvm_rx_eosp_notif, false), |
239 | 239 | ||
@@ -358,6 +358,7 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = { | |||
358 | CMD(TDLS_CHANNEL_SWITCH_CMD), | 358 | CMD(TDLS_CHANNEL_SWITCH_CMD), |
359 | CMD(TDLS_CHANNEL_SWITCH_NOTIFICATION), | 359 | CMD(TDLS_CHANNEL_SWITCH_NOTIFICATION), |
360 | CMD(TDLS_CONFIG_CMD), | 360 | CMD(TDLS_CONFIG_CMD), |
361 | CMD(MCC_UPDATE_CMD), | ||
361 | }; | 362 | }; |
362 | #undef CMD | 363 | #undef CMD |
363 | 364 | ||
@@ -871,8 +872,8 @@ static void iwl_mvm_fw_error_dump_wk(struct work_struct *work) | |||
871 | 872 | ||
872 | /* start recording again if the firmware is not crashed */ | 873 | /* start recording again if the firmware is not crashed */ |
873 | WARN_ON_ONCE((!test_bit(STATUS_FW_ERROR, &mvm->trans->status)) && | 874 | WARN_ON_ONCE((!test_bit(STATUS_FW_ERROR, &mvm->trans->status)) && |
874 | mvm->fw->dbg_dest_tlv && | 875 | mvm->fw->dbg_dest_tlv && |
875 | iwl_mvm_start_fw_dbg_conf(mvm, mvm->fw_dbg_conf)); | 876 | iwl_mvm_start_fw_dbg_conf(mvm, mvm->fw_dbg_conf)); |
876 | 877 | ||
877 | mutex_unlock(&mvm->mutex); | 878 | mutex_unlock(&mvm->mutex); |
878 | 879 | ||
@@ -1270,6 +1271,10 @@ static void iwl_mvm_d0i3_exit_work(struct work_struct *wk) | |||
1270 | iwl_free_resp(&get_status_cmd); | 1271 | iwl_free_resp(&get_status_cmd); |
1271 | out: | 1272 | out: |
1272 | iwl_mvm_d0i3_enable_tx(mvm, qos_seq); | 1273 | iwl_mvm_d0i3_enable_tx(mvm, qos_seq); |
1274 | |||
1275 | /* the FW might have updated the regdomain */ | ||
1276 | iwl_mvm_update_changed_regdom(mvm); | ||
1277 | |||
1273 | iwl_mvm_unref(mvm, IWL_MVM_REF_EXIT_WORK); | 1278 | iwl_mvm_unref(mvm, IWL_MVM_REF_EXIT_WORK); |
1274 | mutex_unlock(&mvm->mutex); | 1279 | mutex_unlock(&mvm->mutex); |
1275 | } | 1280 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index 33bbdde0046f..d2c6ba9d326b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c | |||
@@ -358,7 +358,7 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | |||
358 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); | 358 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); |
359 | 359 | ||
360 | if (!vif->bss_conf.ps || iwl_mvm_vif_low_latency(mvmvif) || | 360 | if (!vif->bss_conf.ps || iwl_mvm_vif_low_latency(mvmvif) || |
361 | !mvmvif->pm_enabled || iwl_mvm_tdls_sta_count(mvm, vif)) | 361 | !mvmvif->pm_enabled) |
362 | return; | 362 | return; |
363 | 363 | ||
364 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK); | 364 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK); |
@@ -639,6 +639,10 @@ static void iwl_mvm_power_set_pm(struct iwl_mvm *mvm, | |||
639 | if (vifs->ap_vif) | 639 | if (vifs->ap_vif) |
640 | ap_mvmvif = iwl_mvm_vif_from_mac80211(vifs->ap_vif); | 640 | ap_mvmvif = iwl_mvm_vif_from_mac80211(vifs->ap_vif); |
641 | 641 | ||
642 | /* don't allow PM if any TDLS stations exist */ | ||
643 | if (iwl_mvm_tdls_sta_count(mvm, NULL)) | ||
644 | return; | ||
645 | |||
642 | /* enable PM on bss if bss stand alone */ | 646 | /* enable PM on bss if bss stand alone */ |
643 | if (vifs->bss_active && !vifs->p2p_active && !vifs->ap_active) { | 647 | if (vifs->bss_active && !vifs->p2p_active && !vifs->ap_active) { |
644 | bss_mvmvif->pm_enabled = true; | 648 | bss_mvmvif->pm_enabled = true; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/quota.c b/drivers/net/wireless/iwlwifi/mvm/quota.c index dbb2594390e9..509a66d05245 100644 --- a/drivers/net/wireless/iwlwifi/mvm/quota.c +++ b/drivers/net/wireless/iwlwifi/mvm/quota.c | |||
@@ -172,6 +172,7 @@ static void iwl_mvm_adjust_quota_for_noa(struct iwl_mvm *mvm, | |||
172 | } | 172 | } |
173 | 173 | ||
174 | int iwl_mvm_update_quotas(struct iwl_mvm *mvm, | 174 | int iwl_mvm_update_quotas(struct iwl_mvm *mvm, |
175 | bool force_update, | ||
175 | struct ieee80211_vif *disabled_vif) | 176 | struct ieee80211_vif *disabled_vif) |
176 | { | 177 | { |
177 | struct iwl_time_quota_cmd cmd = {}; | 178 | struct iwl_time_quota_cmd cmd = {}; |
@@ -309,7 +310,7 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, | |||
309 | "zero quota on binding %d\n", i); | 310 | "zero quota on binding %d\n", i); |
310 | } | 311 | } |
311 | 312 | ||
312 | if (!send) { | 313 | if (!send && !force_update) { |
313 | /* don't send a practically unchanged command, the firmware has | 314 | /* don't send a practically unchanged command, the firmware has |
314 | * to re-initialize a lot of state and that can have an adverse | 315 | * to re-initialize a lot of state and that can have an adverse |
315 | * impact on it | 316 | * impact on it |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 6578498dd5af..dd457df9601e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
@@ -1065,6 +1065,37 @@ static inline bool rs_rate_column_match(struct rs_rate *a, | |||
1065 | && ant_match; | 1065 | && ant_match; |
1066 | } | 1066 | } |
1067 | 1067 | ||
1068 | static inline enum rs_column rs_get_column_from_rate(struct rs_rate *rate) | ||
1069 | { | ||
1070 | if (is_legacy(rate)) { | ||
1071 | if (rate->ant == ANT_A) | ||
1072 | return RS_COLUMN_LEGACY_ANT_A; | ||
1073 | |||
1074 | if (rate->ant == ANT_B) | ||
1075 | return RS_COLUMN_LEGACY_ANT_B; | ||
1076 | |||
1077 | goto err; | ||
1078 | } | ||
1079 | |||
1080 | if (is_siso(rate)) { | ||
1081 | if (rate->ant == ANT_A || rate->stbc || rate->bfer) | ||
1082 | return rate->sgi ? RS_COLUMN_SISO_ANT_A_SGI : | ||
1083 | RS_COLUMN_SISO_ANT_A; | ||
1084 | |||
1085 | if (rate->ant == ANT_B) | ||
1086 | return rate->sgi ? RS_COLUMN_SISO_ANT_B_SGI : | ||
1087 | RS_COLUMN_SISO_ANT_B; | ||
1088 | |||
1089 | goto err; | ||
1090 | } | ||
1091 | |||
1092 | if (is_mimo(rate)) | ||
1093 | return rate->sgi ? RS_COLUMN_MIMO2_SGI : RS_COLUMN_MIMO2; | ||
1094 | |||
1095 | err: | ||
1096 | return RS_COLUMN_INVALID; | ||
1097 | } | ||
1098 | |||
1068 | static u8 rs_get_tid(struct ieee80211_hdr *hdr) | 1099 | static u8 rs_get_tid(struct ieee80211_hdr *hdr) |
1069 | { | 1100 | { |
1070 | u8 tid = IWL_MAX_TID_COUNT; | 1101 | u8 tid = IWL_MAX_TID_COUNT; |
@@ -1106,17 +1137,43 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
1106 | return; | 1137 | return; |
1107 | } | 1138 | } |
1108 | 1139 | ||
1140 | /* This packet was aggregated but doesn't carry status info */ | ||
1141 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && | ||
1142 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) | ||
1143 | return; | ||
1144 | |||
1145 | rs_rate_from_ucode_rate(tx_resp_hwrate, info->band, &tx_resp_rate); | ||
1146 | |||
1109 | #ifdef CONFIG_MAC80211_DEBUGFS | 1147 | #ifdef CONFIG_MAC80211_DEBUGFS |
1110 | /* Disable last tx check if we are debugging with fixed rate */ | 1148 | /* Disable last tx check if we are debugging with fixed rate but |
1149 | * update tx stats */ | ||
1111 | if (lq_sta->pers.dbg_fixed_rate) { | 1150 | if (lq_sta->pers.dbg_fixed_rate) { |
1112 | IWL_DEBUG_RATE(mvm, "Fixed rate. avoid rate scaling\n"); | 1151 | int index = tx_resp_rate.index; |
1152 | enum rs_column column; | ||
1153 | int attempts, success; | ||
1154 | |||
1155 | column = rs_get_column_from_rate(&tx_resp_rate); | ||
1156 | if (WARN_ONCE(column == RS_COLUMN_INVALID, | ||
1157 | "Can't map rate 0x%x to column", | ||
1158 | tx_resp_hwrate)) | ||
1159 | return; | ||
1160 | |||
1161 | if (info->flags & IEEE80211_TX_STAT_AMPDU) { | ||
1162 | attempts = info->status.ampdu_len; | ||
1163 | success = info->status.ampdu_ack_len; | ||
1164 | } else { | ||
1165 | attempts = info->status.rates[0].count; | ||
1166 | success = !!(info->flags & IEEE80211_TX_STAT_ACK); | ||
1167 | } | ||
1168 | |||
1169 | lq_sta->pers.tx_stats[column][index].total += attempts; | ||
1170 | lq_sta->pers.tx_stats[column][index].success += success; | ||
1171 | |||
1172 | IWL_DEBUG_RATE(mvm, "Fixed rate 0x%x success %d attempts %d\n", | ||
1173 | tx_resp_hwrate, success, attempts); | ||
1113 | return; | 1174 | return; |
1114 | } | 1175 | } |
1115 | #endif | 1176 | #endif |
1116 | /* This packet was aggregated but doesn't carry status info */ | ||
1117 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && | ||
1118 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) | ||
1119 | return; | ||
1120 | 1177 | ||
1121 | if (time_after(jiffies, | 1178 | if (time_after(jiffies, |
1122 | (unsigned long)(lq_sta->last_tx + | 1179 | (unsigned long)(lq_sta->last_tx + |
@@ -1142,7 +1199,6 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
1142 | table = &lq_sta->lq; | 1199 | table = &lq_sta->lq; |
1143 | lq_hwrate = le32_to_cpu(table->rs_table[0]); | 1200 | lq_hwrate = le32_to_cpu(table->rs_table[0]); |
1144 | rs_rate_from_ucode_rate(lq_hwrate, info->band, &lq_rate); | 1201 | rs_rate_from_ucode_rate(lq_hwrate, info->band, &lq_rate); |
1145 | rs_rate_from_ucode_rate(tx_resp_hwrate, info->band, &tx_resp_rate); | ||
1146 | 1202 | ||
1147 | /* Here we actually compare this rate to the latest LQ command */ | 1203 | /* Here we actually compare this rate to the latest LQ command */ |
1148 | if (!rs_rate_equal(&tx_resp_rate, &lq_rate, allow_ant_mismatch)) { | 1204 | if (!rs_rate_equal(&tx_resp_rate, &lq_rate, allow_ant_mismatch)) { |
@@ -3343,16 +3399,16 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | |||
3343 | (is_legacy(rate)) ? "legacy" : | 3399 | (is_legacy(rate)) ? "legacy" : |
3344 | is_vht(rate) ? "VHT" : "HT"); | 3400 | is_vht(rate) ? "VHT" : "HT"); |
3345 | if (!is_legacy(rate)) { | 3401 | if (!is_legacy(rate)) { |
3346 | desc += sprintf(buff+desc, " %s", | 3402 | desc += sprintf(buff + desc, " %s", |
3347 | (is_siso(rate)) ? "SISO" : "MIMO2"); | 3403 | (is_siso(rate)) ? "SISO" : "MIMO2"); |
3348 | desc += sprintf(buff+desc, " %s", | 3404 | desc += sprintf(buff + desc, " %s", |
3349 | (is_ht20(rate)) ? "20MHz" : | 3405 | (is_ht20(rate)) ? "20MHz" : |
3350 | (is_ht40(rate)) ? "40MHz" : | 3406 | (is_ht40(rate)) ? "40MHz" : |
3351 | (is_ht80(rate)) ? "80Mhz" : "BAD BW"); | 3407 | (is_ht80(rate)) ? "80Mhz" : "BAD BW"); |
3352 | desc += sprintf(buff+desc, " %s %s %s\n", | 3408 | desc += sprintf(buff + desc, " %s %s %s\n", |
3353 | (rate->sgi) ? "SGI" : "NGI", | 3409 | (rate->sgi) ? "SGI" : "NGI", |
3354 | (rate->ldpc) ? "LDPC" : "BCC", | 3410 | (rate->ldpc) ? "LDPC" : "BCC", |
3355 | (lq_sta->is_agg) ? "AGG on" : ""); | 3411 | (lq_sta->is_agg) ? "AGG on" : ""); |
3356 | } | 3412 | } |
3357 | desc += sprintf(buff+desc, "last tx rate=0x%X\n", | 3413 | desc += sprintf(buff+desc, "last tx rate=0x%X\n", |
3358 | lq_sta->last_rate_n_flags); | 3414 | lq_sta->last_rate_n_flags); |
@@ -3373,13 +3429,13 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | |||
3373 | ss_params = le32_to_cpu(lq_sta->lq.ss_params); | 3429 | ss_params = le32_to_cpu(lq_sta->lq.ss_params); |
3374 | desc += sprintf(buff+desc, "single stream params: %s%s%s%s\n", | 3430 | desc += sprintf(buff+desc, "single stream params: %s%s%s%s\n", |
3375 | (ss_params & LQ_SS_PARAMS_VALID) ? | 3431 | (ss_params & LQ_SS_PARAMS_VALID) ? |
3376 | "VALID," : "INVALID", | 3432 | "VALID" : "INVALID", |
3377 | (ss_params & LQ_SS_BFER_ALLOWED) ? | 3433 | (ss_params & LQ_SS_BFER_ALLOWED) ? |
3378 | "BFER," : "", | 3434 | ", BFER" : "", |
3379 | (ss_params & LQ_SS_STBC_1SS_ALLOWED) ? | 3435 | (ss_params & LQ_SS_STBC_1SS_ALLOWED) ? |
3380 | "STBC," : "", | 3436 | ", STBC" : "", |
3381 | (ss_params & LQ_SS_FORCE) ? | 3437 | (ss_params & LQ_SS_FORCE) ? |
3382 | "FORCE" : ""); | 3438 | ", FORCE" : ""); |
3383 | desc += sprintf(buff+desc, | 3439 | desc += sprintf(buff+desc, |
3384 | "Start idx [0]=0x%x [1]=0x%x [2]=0x%x [3]=0x%x\n", | 3440 | "Start idx [0]=0x%x [1]=0x%x [2]=0x%x [3]=0x%x\n", |
3385 | lq_sta->lq.initial_rate_index[0], | 3441 | lq_sta->lq.initial_rate_index[0], |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sf.c b/drivers/net/wireless/iwlwifi/mvm/sf.c index 7eb78e2c240a..b0f59fdd287c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sf.c +++ b/drivers/net/wireless/iwlwifi/mvm/sf.c | |||
@@ -99,7 +99,35 @@ static void iwl_mvm_bound_iface_iterator(void *_data, u8 *mac, | |||
99 | 99 | ||
100 | /* | 100 | /* |
101 | * Aging and idle timeouts for the different possible scenarios | 101 | * Aging and idle timeouts for the different possible scenarios |
102 | * in SF_FULL_ON state. | 102 | * in default configuration |
103 | */ | ||
104 | static const | ||
105 | __le32 sf_full_timeout_def[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES] = { | ||
106 | { | ||
107 | cpu_to_le32(SF_SINGLE_UNICAST_AGING_TIMER_DEF), | ||
108 | cpu_to_le32(SF_SINGLE_UNICAST_IDLE_TIMER_DEF) | ||
109 | }, | ||
110 | { | ||
111 | cpu_to_le32(SF_AGG_UNICAST_AGING_TIMER_DEF), | ||
112 | cpu_to_le32(SF_AGG_UNICAST_IDLE_TIMER_DEF) | ||
113 | }, | ||
114 | { | ||
115 | cpu_to_le32(SF_MCAST_AGING_TIMER_DEF), | ||
116 | cpu_to_le32(SF_MCAST_IDLE_TIMER_DEF) | ||
117 | }, | ||
118 | { | ||
119 | cpu_to_le32(SF_BA_AGING_TIMER_DEF), | ||
120 | cpu_to_le32(SF_BA_IDLE_TIMER_DEF) | ||
121 | }, | ||
122 | { | ||
123 | cpu_to_le32(SF_TX_RE_AGING_TIMER_DEF), | ||
124 | cpu_to_le32(SF_TX_RE_IDLE_TIMER_DEF) | ||
125 | }, | ||
126 | }; | ||
127 | |||
128 | /* | ||
129 | * Aging and idle timeouts for the different possible scenarios | ||
130 | * in single BSS MAC configuration. | ||
103 | */ | 131 | */ |
104 | static const __le32 sf_full_timeout[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES] = { | 132 | static const __le32 sf_full_timeout[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES] = { |
105 | { | 133 | { |
@@ -124,7 +152,8 @@ static const __le32 sf_full_timeout[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES] = { | |||
124 | }, | 152 | }, |
125 | }; | 153 | }; |
126 | 154 | ||
127 | static void iwl_mvm_fill_sf_command(struct iwl_sf_cfg_cmd *sf_cmd, | 155 | static void iwl_mvm_fill_sf_command(struct iwl_mvm *mvm, |
156 | struct iwl_sf_cfg_cmd *sf_cmd, | ||
128 | struct ieee80211_sta *sta) | 157 | struct ieee80211_sta *sta) |
129 | { | 158 | { |
130 | int i, j, watermark; | 159 | int i, j, watermark; |
@@ -163,24 +192,38 @@ static void iwl_mvm_fill_sf_command(struct iwl_sf_cfg_cmd *sf_cmd, | |||
163 | cpu_to_le32(SF_LONG_DELAY_AGING_TIMER); | 192 | cpu_to_le32(SF_LONG_DELAY_AGING_TIMER); |
164 | } | 193 | } |
165 | } | 194 | } |
166 | BUILD_BUG_ON(sizeof(sf_full_timeout) != | ||
167 | sizeof(__le32) * SF_NUM_SCENARIO * SF_NUM_TIMEOUT_TYPES); | ||
168 | 195 | ||
169 | memcpy(sf_cmd->full_on_timeouts, sf_full_timeout, | 196 | if (sta || IWL_UCODE_API(mvm->fw->ucode_ver) < 13) { |
170 | sizeof(sf_full_timeout)); | 197 | BUILD_BUG_ON(sizeof(sf_full_timeout) != |
198 | sizeof(__le32) * SF_NUM_SCENARIO * | ||
199 | SF_NUM_TIMEOUT_TYPES); | ||
200 | |||
201 | memcpy(sf_cmd->full_on_timeouts, sf_full_timeout, | ||
202 | sizeof(sf_full_timeout)); | ||
203 | } else { | ||
204 | BUILD_BUG_ON(sizeof(sf_full_timeout_def) != | ||
205 | sizeof(__le32) * SF_NUM_SCENARIO * | ||
206 | SF_NUM_TIMEOUT_TYPES); | ||
207 | |||
208 | memcpy(sf_cmd->full_on_timeouts, sf_full_timeout_def, | ||
209 | sizeof(sf_full_timeout_def)); | ||
210 | } | ||
211 | |||
171 | } | 212 | } |
172 | 213 | ||
173 | static int iwl_mvm_sf_config(struct iwl_mvm *mvm, u8 sta_id, | 214 | static int iwl_mvm_sf_config(struct iwl_mvm *mvm, u8 sta_id, |
174 | enum iwl_sf_state new_state) | 215 | enum iwl_sf_state new_state) |
175 | { | 216 | { |
176 | struct iwl_sf_cfg_cmd sf_cmd = { | 217 | struct iwl_sf_cfg_cmd sf_cmd = { |
177 | .state = cpu_to_le32(new_state), | 218 | .state = cpu_to_le32(SF_FULL_ON), |
178 | }; | 219 | }; |
179 | struct ieee80211_sta *sta; | 220 | struct ieee80211_sta *sta; |
180 | int ret = 0; | 221 | int ret = 0; |
181 | 222 | ||
182 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_SF_NO_DUMMY_NOTIF && | 223 | if (IWL_UCODE_API(mvm->fw->ucode_ver) < 13) |
183 | mvm->cfg->disable_dummy_notification) | 224 | sf_cmd.state = cpu_to_le32(new_state); |
225 | |||
226 | if (mvm->cfg->disable_dummy_notification) | ||
184 | sf_cmd.state |= cpu_to_le32(SF_CFG_DUMMY_NOTIF_OFF); | 227 | sf_cmd.state |= cpu_to_le32(SF_CFG_DUMMY_NOTIF_OFF); |
185 | 228 | ||
186 | /* | 229 | /* |
@@ -192,6 +235,8 @@ static int iwl_mvm_sf_config(struct iwl_mvm *mvm, u8 sta_id, | |||
192 | 235 | ||
193 | switch (new_state) { | 236 | switch (new_state) { |
194 | case SF_UNINIT: | 237 | case SF_UNINIT: |
238 | if (IWL_UCODE_API(mvm->fw->ucode_ver) >= 13) | ||
239 | iwl_mvm_fill_sf_command(mvm, &sf_cmd, NULL); | ||
195 | break; | 240 | break; |
196 | case SF_FULL_ON: | 241 | case SF_FULL_ON: |
197 | if (sta_id == IWL_MVM_STATION_COUNT) { | 242 | if (sta_id == IWL_MVM_STATION_COUNT) { |
@@ -206,11 +251,11 @@ static int iwl_mvm_sf_config(struct iwl_mvm *mvm, u8 sta_id, | |||
206 | rcu_read_unlock(); | 251 | rcu_read_unlock(); |
207 | return -EINVAL; | 252 | return -EINVAL; |
208 | } | 253 | } |
209 | iwl_mvm_fill_sf_command(&sf_cmd, sta); | 254 | iwl_mvm_fill_sf_command(mvm, &sf_cmd, sta); |
210 | rcu_read_unlock(); | 255 | rcu_read_unlock(); |
211 | break; | 256 | break; |
212 | case SF_INIT_OFF: | 257 | case SF_INIT_OFF: |
213 | iwl_mvm_fill_sf_command(&sf_cmd, NULL); | 258 | iwl_mvm_fill_sf_command(mvm, &sf_cmd, NULL); |
214 | break; | 259 | break; |
215 | default: | 260 | default: |
216 | WARN_ONCE(1, "Invalid state: %d. not sending Smart Fifo cmd\n", | 261 | WARN_ONCE(1, "Invalid state: %d. not sending Smart Fifo cmd\n", |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 5c23cddaaae3..50f9288368af 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
@@ -273,7 +273,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, | |||
273 | else | 273 | else |
274 | sta_id = mvm_sta->sta_id; | 274 | sta_id = mvm_sta->sta_id; |
275 | 275 | ||
276 | if (WARN_ON_ONCE(sta_id == IWL_MVM_STATION_COUNT)) | 276 | if (sta_id == IWL_MVM_STATION_COUNT) |
277 | return -ENOSPC; | 277 | return -ENOSPC; |
278 | 278 | ||
279 | spin_lock_init(&mvm_sta->lock); | 279 | spin_lock_init(&mvm_sta->lock); |
@@ -1681,9 +1681,6 @@ void iwl_mvm_sta_modify_disable_tx(struct iwl_mvm *mvm, | |||
1681 | }; | 1681 | }; |
1682 | int ret; | 1682 | int ret; |
1683 | 1683 | ||
1684 | if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_DISABLE_STA_TX)) | ||
1685 | return; | ||
1686 | |||
1687 | ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd); | 1684 | ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd); |
1688 | if (ret) | 1685 | if (ret) |
1689 | IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); | 1686 | IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index f8d6f306dd76..8d179ab67cc2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c | |||
@@ -197,6 +197,8 @@ iwl_mvm_te_handle_notify_csa(struct iwl_mvm *mvm, | |||
197 | struct iwl_time_event_notif *notif) | 197 | struct iwl_time_event_notif *notif) |
198 | { | 198 | { |
199 | if (!le32_to_cpu(notif->status)) { | 199 | if (!le32_to_cpu(notif->status)) { |
200 | if (te_data->vif->type == NL80211_IFTYPE_STATION) | ||
201 | ieee80211_connection_loss(te_data->vif); | ||
200 | IWL_DEBUG_TE(mvm, "CSA time event failed to start\n"); | 202 | IWL_DEBUG_TE(mvm, "CSA time event failed to start\n"); |
201 | iwl_mvm_te_clear_data(mvm, te_data); | 203 | iwl_mvm_te_clear_data(mvm, te_data); |
202 | return; | 204 | return; |
@@ -261,17 +263,23 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm, | |||
261 | "TE ended - current time %lu, estimated end %lu\n", | 263 | "TE ended - current time %lu, estimated end %lu\n", |
262 | jiffies, te_data->end_jiffies); | 264 | jiffies, te_data->end_jiffies); |
263 | 265 | ||
264 | if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) { | 266 | switch (te_data->vif->type) { |
267 | case NL80211_IFTYPE_P2P_DEVICE: | ||
265 | ieee80211_remain_on_channel_expired(mvm->hw); | 268 | ieee80211_remain_on_channel_expired(mvm->hw); |
266 | iwl_mvm_roc_finished(mvm); | 269 | iwl_mvm_roc_finished(mvm); |
270 | break; | ||
271 | case NL80211_IFTYPE_STATION: | ||
272 | /* | ||
273 | * By now, we should have finished association | ||
274 | * and know the dtim period. | ||
275 | */ | ||
276 | iwl_mvm_te_check_disconnect(mvm, te_data->vif, | ||
277 | "No association and the time event is over already..."); | ||
278 | break; | ||
279 | default: | ||
280 | break; | ||
267 | } | 281 | } |
268 | 282 | ||
269 | /* | ||
270 | * By now, we should have finished association | ||
271 | * and know the dtim period. | ||
272 | */ | ||
273 | iwl_mvm_te_check_disconnect(mvm, te_data->vif, | ||
274 | "No association and the time event is over already..."); | ||
275 | iwl_mvm_te_clear_data(mvm, te_data); | 283 | iwl_mvm_te_clear_data(mvm, te_data); |
276 | } else if (le32_to_cpu(notif->action) & TE_V2_NOTIF_HOST_EVENT_START) { | 284 | } else if (le32_to_cpu(notif->action) & TE_V2_NOTIF_HOST_EVENT_START) { |
277 | te_data->running = true; | 285 | te_data->running = true; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index 2b9de63951e6..435faee0a28e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c | |||
@@ -857,7 +857,7 @@ int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
857 | 857 | ||
858 | mvmvif->low_latency = value; | 858 | mvmvif->low_latency = value; |
859 | 859 | ||
860 | res = iwl_mvm_update_quotas(mvm, NULL); | 860 | res = iwl_mvm_update_quotas(mvm, false, NULL); |
861 | if (res) | 861 | if (res) |
862 | return res; | 862 | return res; |
863 | 863 | ||
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index dbd6bcf52205..2794cd2d3a64 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c | |||
@@ -413,10 +413,35 @@ static const struct pci_device_id iwl_hw_card_ids[] = { | |||
413 | 413 | ||
414 | /* 8000 Series */ | 414 | /* 8000 Series */ |
415 | {IWL_PCI_DEVICE(0x24F3, 0x0010, iwl8260_2ac_cfg)}, | 415 | {IWL_PCI_DEVICE(0x24F3, 0x0010, iwl8260_2ac_cfg)}, |
416 | {IWL_PCI_DEVICE(0x24F3, 0x0004, iwl8260_2n_cfg)}, | 416 | {IWL_PCI_DEVICE(0x24F3, 0x1010, iwl8260_2ac_cfg)}, |
417 | {IWL_PCI_DEVICE(0x24F3, 0x0110, iwl8260_2ac_cfg)}, | ||
418 | {IWL_PCI_DEVICE(0x24F3, 0x1110, iwl8260_2ac_cfg)}, | ||
419 | {IWL_PCI_DEVICE(0x24F3, 0x0050, iwl8260_2ac_cfg)}, | ||
420 | {IWL_PCI_DEVICE(0x24F3, 0x0250, iwl8260_2ac_cfg)}, | ||
421 | {IWL_PCI_DEVICE(0x24F3, 0x1050, iwl8260_2ac_cfg)}, | ||
422 | {IWL_PCI_DEVICE(0x24F3, 0x0150, iwl8260_2ac_cfg)}, | ||
417 | {IWL_PCI_DEVICE(0x24F4, 0x0030, iwl8260_2ac_cfg)}, | 423 | {IWL_PCI_DEVICE(0x24F4, 0x0030, iwl8260_2ac_cfg)}, |
424 | {IWL_PCI_DEVICE(0x24F4, 0x1130, iwl8260_2ac_cfg)}, | ||
425 | {IWL_PCI_DEVICE(0x24F4, 0x1030, iwl8260_2ac_cfg)}, | ||
426 | {IWL_PCI_DEVICE(0x24F3, 0xC010, iwl8260_2ac_cfg)}, | ||
427 | {IWL_PCI_DEVICE(0x24F3, 0xD010, iwl8260_2ac_cfg)}, | ||
428 | {IWL_PCI_DEVICE(0x24F4, 0xC030, iwl8260_2ac_cfg)}, | ||
429 | {IWL_PCI_DEVICE(0x24F4, 0xD030, iwl8260_2ac_cfg)}, | ||
430 | {IWL_PCI_DEVICE(0x24F3, 0xC050, iwl8260_2ac_cfg)}, | ||
431 | {IWL_PCI_DEVICE(0x24F3, 0xD050, iwl8260_2ac_cfg)}, | ||
432 | {IWL_PCI_DEVICE(0x24F3, 0x8010, iwl8260_2ac_cfg)}, | ||
433 | {IWL_PCI_DEVICE(0x24F3, 0x9010, iwl8260_2ac_cfg)}, | ||
434 | {IWL_PCI_DEVICE(0x24F4, 0x8030, iwl8260_2ac_cfg)}, | ||
435 | {IWL_PCI_DEVICE(0x24F4, 0x9030, iwl8260_2ac_cfg)}, | ||
436 | {IWL_PCI_DEVICE(0x24F3, 0x8050, iwl8260_2ac_cfg)}, | ||
437 | {IWL_PCI_DEVICE(0x24F3, 0x9050, iwl8260_2ac_cfg)}, | ||
438 | {IWL_PCI_DEVICE(0x24F3, 0x0004, iwl8260_2n_cfg)}, | ||
418 | {IWL_PCI_DEVICE(0x24F5, 0x0010, iwl4165_2ac_cfg)}, | 439 | {IWL_PCI_DEVICE(0x24F5, 0x0010, iwl4165_2ac_cfg)}, |
419 | {IWL_PCI_DEVICE(0x24F6, 0x0030, iwl4165_2ac_cfg)}, | 440 | {IWL_PCI_DEVICE(0x24F6, 0x0030, iwl4165_2ac_cfg)}, |
441 | {IWL_PCI_DEVICE(0x24F3, 0x0810, iwl8260_2ac_cfg)}, | ||
442 | {IWL_PCI_DEVICE(0x24F3, 0x0910, iwl8260_2ac_cfg)}, | ||
443 | {IWL_PCI_DEVICE(0x24F3, 0x0850, iwl8260_2ac_cfg)}, | ||
444 | {IWL_PCI_DEVICE(0x24F3, 0x0950, iwl8260_2ac_cfg)}, | ||
420 | #endif /* CONFIG_IWLMVM */ | 445 | #endif /* CONFIG_IWLMVM */ |
421 | 446 | ||
422 | {0} | 447 | {0} |
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index cae0eb8835ce..01996c9d98a7 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h | |||
@@ -217,6 +217,8 @@ struct iwl_pcie_txq_scratch_buf { | |||
217 | * @active: stores if queue is active | 217 | * @active: stores if queue is active |
218 | * @ampdu: true if this queue is an ampdu queue for an specific RA/TID | 218 | * @ampdu: true if this queue is an ampdu queue for an specific RA/TID |
219 | * @wd_timeout: queue watchdog timeout (jiffies) - per queue | 219 | * @wd_timeout: queue watchdog timeout (jiffies) - per queue |
220 | * @frozen: tx stuck queue timer is frozen | ||
221 | * @frozen_expiry_remainder: remember how long until the timer fires | ||
220 | * | 222 | * |
221 | * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame | 223 | * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame |
222 | * descriptors) and required locking structures. | 224 | * descriptors) and required locking structures. |
@@ -228,9 +230,11 @@ struct iwl_txq { | |||
228 | dma_addr_t scratchbufs_dma; | 230 | dma_addr_t scratchbufs_dma; |
229 | struct iwl_pcie_txq_entry *entries; | 231 | struct iwl_pcie_txq_entry *entries; |
230 | spinlock_t lock; | 232 | spinlock_t lock; |
233 | unsigned long frozen_expiry_remainder; | ||
231 | struct timer_list stuck_timer; | 234 | struct timer_list stuck_timer; |
232 | struct iwl_trans_pcie *trans_pcie; | 235 | struct iwl_trans_pcie *trans_pcie; |
233 | bool need_update; | 236 | bool need_update; |
237 | bool frozen; | ||
234 | u8 active; | 238 | u8 active; |
235 | bool ampdu; | 239 | bool ampdu; |
236 | unsigned long wd_timeout; | 240 | unsigned long wd_timeout; |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index f31a94160771..dc247325d8d7 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -682,6 +682,43 @@ static int iwl_pcie_load_section(struct iwl_trans *trans, u8 section_num, | |||
682 | return ret; | 682 | return ret; |
683 | } | 683 | } |
684 | 684 | ||
685 | /* | ||
686 | * Driver Takes the ownership on secure machine before FW load | ||
687 | * and prevent race with the BT load. | ||
688 | * W/A for ROM bug. (should be remove in the next Si step) | ||
689 | */ | ||
690 | static int iwl_pcie_rsa_race_bug_wa(struct iwl_trans *trans) | ||
691 | { | ||
692 | u32 val, loop = 1000; | ||
693 | |||
694 | /* Check the RSA semaphore is accessible - if not, we are in trouble */ | ||
695 | val = iwl_read_prph(trans, PREG_AUX_BUS_WPROT_0); | ||
696 | if (val & (BIT(1) | BIT(17))) { | ||
697 | IWL_ERR(trans, | ||
698 | "can't access the RSA semaphore it is write protected\n"); | ||
699 | return 0; | ||
700 | } | ||
701 | |||
702 | /* take ownership on the AUX IF */ | ||
703 | iwl_write_prph(trans, WFPM_CTRL_REG, WFPM_AUX_CTL_AUX_IF_MAC_OWNER_MSK); | ||
704 | iwl_write_prph(trans, AUX_MISC_MASTER1_EN, AUX_MISC_MASTER1_EN_SBE_MSK); | ||
705 | |||
706 | do { | ||
707 | iwl_write_prph(trans, AUX_MISC_MASTER1_SMPHR_STATUS, 0x1); | ||
708 | val = iwl_read_prph(trans, AUX_MISC_MASTER1_SMPHR_STATUS); | ||
709 | if (val == 0x1) { | ||
710 | iwl_write_prph(trans, RSA_ENABLE, 0); | ||
711 | return 0; | ||
712 | } | ||
713 | |||
714 | udelay(10); | ||
715 | loop--; | ||
716 | } while (loop > 0); | ||
717 | |||
718 | IWL_ERR(trans, "Failed to take ownership on secure machine\n"); | ||
719 | return -EIO; | ||
720 | } | ||
721 | |||
685 | static int iwl_pcie_load_cpu_sections_8000b(struct iwl_trans *trans, | 722 | static int iwl_pcie_load_cpu_sections_8000b(struct iwl_trans *trans, |
686 | const struct fw_img *image, | 723 | const struct fw_img *image, |
687 | int cpu, | 724 | int cpu, |
@@ -901,6 +938,11 @@ static int iwl_pcie_load_given_ucode_8000b(struct iwl_trans *trans, | |||
901 | if (trans->dbg_dest_tlv) | 938 | if (trans->dbg_dest_tlv) |
902 | iwl_pcie_apply_destination(trans); | 939 | iwl_pcie_apply_destination(trans); |
903 | 940 | ||
941 | /* TODO: remove in the next Si step */ | ||
942 | ret = iwl_pcie_rsa_race_bug_wa(trans); | ||
943 | if (ret) | ||
944 | return ret; | ||
945 | |||
904 | /* configure the ucode to be ready to get the secured image */ | 946 | /* configure the ucode to be ready to get the secured image */ |
905 | /* release CPU reset */ | 947 | /* release CPU reset */ |
906 | iwl_write_prph(trans, RELEASE_CPU_RESET, RELEASE_CPU_RESET_BIT); | 948 | iwl_write_prph(trans, RELEASE_CPU_RESET, RELEASE_CPU_RESET_BIT); |
@@ -1462,6 +1504,60 @@ static int iwl_trans_pcie_write_mem(struct iwl_trans *trans, u32 addr, | |||
1462 | return ret; | 1504 | return ret; |
1463 | } | 1505 | } |
1464 | 1506 | ||
1507 | static void iwl_trans_pcie_freeze_txq_timer(struct iwl_trans *trans, | ||
1508 | unsigned long txqs, | ||
1509 | bool freeze) | ||
1510 | { | ||
1511 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1512 | int queue; | ||
1513 | |||
1514 | for_each_set_bit(queue, &txqs, BITS_PER_LONG) { | ||
1515 | struct iwl_txq *txq = &trans_pcie->txq[queue]; | ||
1516 | unsigned long now; | ||
1517 | |||
1518 | spin_lock_bh(&txq->lock); | ||
1519 | |||
1520 | now = jiffies; | ||
1521 | |||
1522 | if (txq->frozen == freeze) | ||
1523 | goto next_queue; | ||
1524 | |||
1525 | IWL_DEBUG_TX_QUEUES(trans, "%s TXQ %d\n", | ||
1526 | freeze ? "Freezing" : "Waking", queue); | ||
1527 | |||
1528 | txq->frozen = freeze; | ||
1529 | |||
1530 | if (txq->q.read_ptr == txq->q.write_ptr) | ||
1531 | goto next_queue; | ||
1532 | |||
1533 | if (freeze) { | ||
1534 | if (unlikely(time_after(now, | ||
1535 | txq->stuck_timer.expires))) { | ||
1536 | /* | ||
1537 | * The timer should have fired, maybe it is | ||
1538 | * spinning right now on the lock. | ||
1539 | */ | ||
1540 | goto next_queue; | ||
1541 | } | ||
1542 | /* remember how long until the timer fires */ | ||
1543 | txq->frozen_expiry_remainder = | ||
1544 | txq->stuck_timer.expires - now; | ||
1545 | del_timer(&txq->stuck_timer); | ||
1546 | goto next_queue; | ||
1547 | } | ||
1548 | |||
1549 | /* | ||
1550 | * Wake a non-empty queue -> arm timer with the | ||
1551 | * remainder before it froze | ||
1552 | */ | ||
1553 | mod_timer(&txq->stuck_timer, | ||
1554 | now + txq->frozen_expiry_remainder); | ||
1555 | |||
1556 | next_queue: | ||
1557 | spin_unlock_bh(&txq->lock); | ||
1558 | } | ||
1559 | } | ||
1560 | |||
1465 | #define IWL_FLUSH_WAIT_MS 2000 | 1561 | #define IWL_FLUSH_WAIT_MS 2000 |
1466 | 1562 | ||
1467 | static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, u32 txq_bm) | 1563 | static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, u32 txq_bm) |
@@ -1713,7 +1809,7 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, | |||
1713 | int ret; | 1809 | int ret; |
1714 | size_t bufsz; | 1810 | size_t bufsz; |
1715 | 1811 | ||
1716 | bufsz = sizeof(char) * 64 * trans->cfg->base_params->num_of_queues; | 1812 | bufsz = sizeof(char) * 75 * trans->cfg->base_params->num_of_queues; |
1717 | 1813 | ||
1718 | if (!trans_pcie->txq) | 1814 | if (!trans_pcie->txq) |
1719 | return -EAGAIN; | 1815 | return -EAGAIN; |
@@ -1726,11 +1822,11 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, | |||
1726 | txq = &trans_pcie->txq[cnt]; | 1822 | txq = &trans_pcie->txq[cnt]; |
1727 | q = &txq->q; | 1823 | q = &txq->q; |
1728 | pos += scnprintf(buf + pos, bufsz - pos, | 1824 | pos += scnprintf(buf + pos, bufsz - pos, |
1729 | "hwq %.2d: read=%u write=%u use=%d stop=%d need_update=%d%s\n", | 1825 | "hwq %.2d: read=%u write=%u use=%d stop=%d need_update=%d frozen=%d%s\n", |
1730 | cnt, q->read_ptr, q->write_ptr, | 1826 | cnt, q->read_ptr, q->write_ptr, |
1731 | !!test_bit(cnt, trans_pcie->queue_used), | 1827 | !!test_bit(cnt, trans_pcie->queue_used), |
1732 | !!test_bit(cnt, trans_pcie->queue_stopped), | 1828 | !!test_bit(cnt, trans_pcie->queue_stopped), |
1733 | txq->need_update, | 1829 | txq->need_update, txq->frozen, |
1734 | (cnt == trans_pcie->cmd_queue ? " HCMD" : "")); | 1830 | (cnt == trans_pcie->cmd_queue ? " HCMD" : "")); |
1735 | } | 1831 | } |
1736 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1832 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
@@ -1961,24 +2057,25 @@ static const struct { | |||
1961 | { .start = 0x00a01c7c, .end = 0x00a01c7c }, | 2057 | { .start = 0x00a01c7c, .end = 0x00a01c7c }, |
1962 | { .start = 0x00a01c28, .end = 0x00a01c54 }, | 2058 | { .start = 0x00a01c28, .end = 0x00a01c54 }, |
1963 | { .start = 0x00a01c5c, .end = 0x00a01c5c }, | 2059 | { .start = 0x00a01c5c, .end = 0x00a01c5c }, |
1964 | { .start = 0x00a01c84, .end = 0x00a01c84 }, | 2060 | { .start = 0x00a01c60, .end = 0x00a01cdc }, |
1965 | { .start = 0x00a01ce0, .end = 0x00a01d0c }, | 2061 | { .start = 0x00a01ce0, .end = 0x00a01d0c }, |
1966 | { .start = 0x00a01d18, .end = 0x00a01d20 }, | 2062 | { .start = 0x00a01d18, .end = 0x00a01d20 }, |
1967 | { .start = 0x00a01d2c, .end = 0x00a01d30 }, | 2063 | { .start = 0x00a01d2c, .end = 0x00a01d30 }, |
1968 | { .start = 0x00a01d40, .end = 0x00a01d5c }, | 2064 | { .start = 0x00a01d40, .end = 0x00a01d5c }, |
1969 | { .start = 0x00a01d80, .end = 0x00a01d80 }, | 2065 | { .start = 0x00a01d80, .end = 0x00a01d80 }, |
1970 | { .start = 0x00a01d98, .end = 0x00a01d98 }, | 2066 | { .start = 0x00a01d98, .end = 0x00a01d9c }, |
2067 | { .start = 0x00a01da8, .end = 0x00a01da8 }, | ||
2068 | { .start = 0x00a01db8, .end = 0x00a01df4 }, | ||
1971 | { .start = 0x00a01dc0, .end = 0x00a01dfc }, | 2069 | { .start = 0x00a01dc0, .end = 0x00a01dfc }, |
1972 | { .start = 0x00a01e00, .end = 0x00a01e2c }, | 2070 | { .start = 0x00a01e00, .end = 0x00a01e2c }, |
1973 | { .start = 0x00a01e40, .end = 0x00a01e60 }, | 2071 | { .start = 0x00a01e40, .end = 0x00a01e60 }, |
2072 | { .start = 0x00a01e68, .end = 0x00a01e6c }, | ||
2073 | { .start = 0x00a01e74, .end = 0x00a01e74 }, | ||
1974 | { .start = 0x00a01e84, .end = 0x00a01e90 }, | 2074 | { .start = 0x00a01e84, .end = 0x00a01e90 }, |
1975 | { .start = 0x00a01e9c, .end = 0x00a01ec4 }, | 2075 | { .start = 0x00a01e9c, .end = 0x00a01ec4 }, |
1976 | { .start = 0x00a01ed0, .end = 0x00a01ed0 }, | 2076 | { .start = 0x00a01ed0, .end = 0x00a01ee0 }, |
1977 | { .start = 0x00a01f00, .end = 0x00a01f14 }, | 2077 | { .start = 0x00a01f00, .end = 0x00a01f1c }, |
1978 | { .start = 0x00a01f44, .end = 0x00a01f58 }, | 2078 | { .start = 0x00a01f44, .end = 0x00a01ffc }, |
1979 | { .start = 0x00a01f80, .end = 0x00a01fa8 }, | ||
1980 | { .start = 0x00a01fb0, .end = 0x00a01fbc }, | ||
1981 | { .start = 0x00a01ff8, .end = 0x00a01ffc }, | ||
1982 | { .start = 0x00a02000, .end = 0x00a02048 }, | 2079 | { .start = 0x00a02000, .end = 0x00a02048 }, |
1983 | { .start = 0x00a02068, .end = 0x00a020f0 }, | 2080 | { .start = 0x00a02068, .end = 0x00a020f0 }, |
1984 | { .start = 0x00a02100, .end = 0x00a02118 }, | 2081 | { .start = 0x00a02100, .end = 0x00a02118 }, |
@@ -2305,6 +2402,7 @@ static const struct iwl_trans_ops trans_ops_pcie = { | |||
2305 | .dbgfs_register = iwl_trans_pcie_dbgfs_register, | 2402 | .dbgfs_register = iwl_trans_pcie_dbgfs_register, |
2306 | 2403 | ||
2307 | .wait_tx_queue_empty = iwl_trans_pcie_wait_txq_empty, | 2404 | .wait_tx_queue_empty = iwl_trans_pcie_wait_txq_empty, |
2405 | .freeze_txq_timer = iwl_trans_pcie_freeze_txq_timer, | ||
2308 | 2406 | ||
2309 | .write8 = iwl_trans_pcie_write8, | 2407 | .write8 = iwl_trans_pcie_write8, |
2310 | .write32 = iwl_trans_pcie_write32, | 2408 | .write32 = iwl_trans_pcie_write32, |
@@ -2423,10 +2521,45 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
2423 | * "dash" value). To keep hw_rev backwards compatible - we'll store it | 2521 | * "dash" value). To keep hw_rev backwards compatible - we'll store it |
2424 | * in the old format. | 2522 | * in the old format. |
2425 | */ | 2523 | */ |
2426 | if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) | 2524 | if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) { |
2525 | unsigned long flags; | ||
2526 | int ret; | ||
2527 | |||
2427 | trans->hw_rev = (trans->hw_rev & 0xfff0) | | 2528 | trans->hw_rev = (trans->hw_rev & 0xfff0) | |
2428 | (CSR_HW_REV_STEP(trans->hw_rev << 2) << 2); | 2529 | (CSR_HW_REV_STEP(trans->hw_rev << 2) << 2); |
2429 | 2530 | ||
2531 | /* | ||
2532 | * in-order to recognize C step driver should read chip version | ||
2533 | * id located at the AUX bus MISC address space. | ||
2534 | */ | ||
2535 | iwl_set_bit(trans, CSR_GP_CNTRL, | ||
2536 | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
2537 | udelay(2); | ||
2538 | |||
2539 | ret = iwl_poll_bit(trans, CSR_GP_CNTRL, | ||
2540 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
2541 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
2542 | 25000); | ||
2543 | if (ret < 0) { | ||
2544 | IWL_DEBUG_INFO(trans, "Failed to wake up the nic\n"); | ||
2545 | goto out_pci_disable_msi; | ||
2546 | } | ||
2547 | |||
2548 | if (iwl_trans_grab_nic_access(trans, false, &flags)) { | ||
2549 | u32 hw_step; | ||
2550 | |||
2551 | hw_step = __iwl_read_prph(trans, WFPM_CTRL_REG); | ||
2552 | hw_step |= ENABLE_WFPM; | ||
2553 | __iwl_write_prph(trans, WFPM_CTRL_REG, hw_step); | ||
2554 | hw_step = __iwl_read_prph(trans, AUX_MISC_REG); | ||
2555 | hw_step = (hw_step >> HW_STEP_LOCATION_BITS) & 0xF; | ||
2556 | if (hw_step == 0x3) | ||
2557 | trans->hw_rev = (trans->hw_rev & 0xFFFFFFF3) | | ||
2558 | (SILICON_C_STEP << 2); | ||
2559 | iwl_trans_release_nic_access(trans, &flags); | ||
2560 | } | ||
2561 | } | ||
2562 | |||
2430 | trans->hw_id = (pdev->device << 16) + pdev->subsystem_device; | 2563 | trans->hw_id = (pdev->device << 16) + pdev->subsystem_device; |
2431 | snprintf(trans->hw_id_str, sizeof(trans->hw_id_str), | 2564 | snprintf(trans->hw_id_str, sizeof(trans->hw_id_str), |
2432 | "PCI ID: 0x%04X:0x%04X", pdev->device, pdev->subsystem_device); | 2565 | "PCI ID: 0x%04X:0x%04X", pdev->device, pdev->subsystem_device); |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index af0bce736358..06952aadfd7b 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
@@ -725,33 +725,50 @@ void iwl_trans_pcie_tx_reset(struct iwl_trans *trans) | |||
725 | iwl_pcie_tx_start(trans, 0); | 725 | iwl_pcie_tx_start(trans, 0); |
726 | } | 726 | } |
727 | 727 | ||
728 | static void iwl_pcie_tx_stop_fh(struct iwl_trans *trans) | ||
729 | { | ||
730 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
731 | unsigned long flags; | ||
732 | int ch, ret; | ||
733 | u32 mask = 0; | ||
734 | |||
735 | spin_lock(&trans_pcie->irq_lock); | ||
736 | |||
737 | if (!iwl_trans_grab_nic_access(trans, false, &flags)) | ||
738 | goto out; | ||
739 | |||
740 | /* Stop each Tx DMA channel */ | ||
741 | for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) { | ||
742 | iwl_write32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); | ||
743 | mask |= FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch); | ||
744 | } | ||
745 | |||
746 | /* Wait for DMA channels to be idle */ | ||
747 | ret = iwl_poll_bit(trans, FH_TSSR_TX_STATUS_REG, mask, mask, 5000); | ||
748 | if (ret < 0) | ||
749 | IWL_ERR(trans, | ||
750 | "Failing on timeout while stopping DMA channel %d [0x%08x]\n", | ||
751 | ch, iwl_read32(trans, FH_TSSR_TX_STATUS_REG)); | ||
752 | |||
753 | iwl_trans_release_nic_access(trans, &flags); | ||
754 | |||
755 | out: | ||
756 | spin_unlock(&trans_pcie->irq_lock); | ||
757 | } | ||
758 | |||
728 | /* | 759 | /* |
729 | * iwl_pcie_tx_stop - Stop all Tx DMA channels | 760 | * iwl_pcie_tx_stop - Stop all Tx DMA channels |
730 | */ | 761 | */ |
731 | int iwl_pcie_tx_stop(struct iwl_trans *trans) | 762 | int iwl_pcie_tx_stop(struct iwl_trans *trans) |
732 | { | 763 | { |
733 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 764 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
734 | int ch, txq_id, ret; | 765 | int txq_id; |
735 | 766 | ||
736 | /* Turn off all Tx DMA fifos */ | 767 | /* Turn off all Tx DMA fifos */ |
737 | spin_lock(&trans_pcie->irq_lock); | ||
738 | |||
739 | iwl_scd_deactivate_fifos(trans); | 768 | iwl_scd_deactivate_fifos(trans); |
740 | 769 | ||
741 | /* Stop each Tx DMA channel, and wait for it to be idle */ | 770 | /* Turn off all Tx DMA channels */ |
742 | for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) { | 771 | iwl_pcie_tx_stop_fh(trans); |
743 | iwl_write_direct32(trans, | ||
744 | FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); | ||
745 | ret = iwl_poll_direct_bit(trans, FH_TSSR_TX_STATUS_REG, | ||
746 | FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), 1000); | ||
747 | if (ret < 0) | ||
748 | IWL_ERR(trans, | ||
749 | "Failing on timeout while stopping DMA channel %d [0x%08x]\n", | ||
750 | ch, | ||
751 | iwl_read_direct32(trans, | ||
752 | FH_TSSR_TX_STATUS_REG)); | ||
753 | } | ||
754 | spin_unlock(&trans_pcie->irq_lock); | ||
755 | 772 | ||
756 | /* | 773 | /* |
757 | * This function can be called before the op_mode disabled the | 774 | * This function can be called before the op_mode disabled the |
@@ -912,10 +929,19 @@ error: | |||
912 | 929 | ||
913 | static inline void iwl_pcie_txq_progress(struct iwl_txq *txq) | 930 | static inline void iwl_pcie_txq_progress(struct iwl_txq *txq) |
914 | { | 931 | { |
932 | lockdep_assert_held(&txq->lock); | ||
933 | |||
915 | if (!txq->wd_timeout) | 934 | if (!txq->wd_timeout) |
916 | return; | 935 | return; |
917 | 936 | ||
918 | /* | 937 | /* |
938 | * station is asleep and we send data - that must | ||
939 | * be uAPSD or PS-Poll. Don't rearm the timer. | ||
940 | */ | ||
941 | if (txq->frozen) | ||
942 | return; | ||
943 | |||
944 | /* | ||
919 | * if empty delete timer, otherwise move timer forward | 945 | * if empty delete timer, otherwise move timer forward |
920 | * since we're making progress on this queue | 946 | * since we're making progress on this queue |
921 | */ | 947 | */ |
@@ -1248,6 +1274,9 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id, | |||
1248 | SCD_TX_STTS_QUEUE_OFFSET(txq_id); | 1274 | SCD_TX_STTS_QUEUE_OFFSET(txq_id); |
1249 | static const u32 zero_val[4] = {}; | 1275 | static const u32 zero_val[4] = {}; |
1250 | 1276 | ||
1277 | trans_pcie->txq[txq_id].frozen_expiry_remainder = 0; | ||
1278 | trans_pcie->txq[txq_id].frozen = false; | ||
1279 | |||
1251 | /* | 1280 | /* |
1252 | * Upon HW Rfkill - we stop the device, and then stop the queues | 1281 | * Upon HW Rfkill - we stop the device, and then stop the queues |
1253 | * in the op_mode. Just for the sake of the simplicity of the op_mode, | 1282 | * in the op_mode. Just for the sake of the simplicity of the op_mode, |
diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c index d576dd6665d3..1a20cee5febe 100644 --- a/drivers/net/wireless/libertas_tf/if_usb.c +++ b/drivers/net/wireless/libertas_tf/if_usb.c | |||
@@ -365,7 +365,6 @@ static int if_usb_reset_device(struct if_usb_card *cardp) | |||
365 | 365 | ||
366 | return ret; | 366 | return ret; |
367 | } | 367 | } |
368 | EXPORT_SYMBOL_GPL(if_usb_reset_device); | ||
369 | 368 | ||
370 | /** | 369 | /** |
371 | * usb_tx_block - transfer data to the device | 370 | * usb_tx_block - transfer data to the device |
@@ -907,7 +906,6 @@ restart: | |||
907 | lbtf_deb_leave_args(LBTF_DEB_USB, "ret %d", ret); | 906 | lbtf_deb_leave_args(LBTF_DEB_USB, "ret %d", ret); |
908 | return ret; | 907 | return ret; |
909 | } | 908 | } |
910 | EXPORT_SYMBOL_GPL(if_usb_prog_firmware); | ||
911 | 909 | ||
912 | 910 | ||
913 | #define if_usb_suspend NULL | 911 | #define if_usb_suspend NULL |
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index 543148d27b01..433bd6837c79 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c | |||
@@ -159,6 +159,7 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, | |||
159 | int tid; | 159 | int tid; |
160 | struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &resp->params.add_ba_rsp; | 160 | struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &resp->params.add_ba_rsp; |
161 | struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl; | 161 | struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl; |
162 | struct mwifiex_ra_list_tbl *ra_list; | ||
162 | u16 block_ack_param_set = le16_to_cpu(add_ba_rsp->block_ack_param_set); | 163 | u16 block_ack_param_set = le16_to_cpu(add_ba_rsp->block_ack_param_set); |
163 | 164 | ||
164 | add_ba_rsp->ssn = cpu_to_le16((le16_to_cpu(add_ba_rsp->ssn)) | 165 | add_ba_rsp->ssn = cpu_to_le16((le16_to_cpu(add_ba_rsp->ssn)) |
@@ -166,7 +167,13 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, | |||
166 | 167 | ||
167 | tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK) | 168 | tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK) |
168 | >> BLOCKACKPARAM_TID_POS; | 169 | >> BLOCKACKPARAM_TID_POS; |
170 | ra_list = mwifiex_wmm_get_ralist_node(priv, tid, add_ba_rsp-> | ||
171 | peer_mac_addr); | ||
169 | if (le16_to_cpu(add_ba_rsp->status_code) != BA_RESULT_SUCCESS) { | 172 | if (le16_to_cpu(add_ba_rsp->status_code) != BA_RESULT_SUCCESS) { |
173 | if (ra_list) { | ||
174 | ra_list->ba_status = BA_SETUP_NONE; | ||
175 | ra_list->amsdu_in_ampdu = false; | ||
176 | } | ||
170 | mwifiex_del_ba_tbl(priv, tid, add_ba_rsp->peer_mac_addr, | 177 | mwifiex_del_ba_tbl(priv, tid, add_ba_rsp->peer_mac_addr, |
171 | TYPE_DELBA_SENT, true); | 178 | TYPE_DELBA_SENT, true); |
172 | if (add_ba_rsp->add_rsp_result != BA_RESULT_TIMEOUT) | 179 | if (add_ba_rsp->add_rsp_result != BA_RESULT_TIMEOUT) |
@@ -185,6 +192,10 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, | |||
185 | tx_ba_tbl->amsdu = true; | 192 | tx_ba_tbl->amsdu = true; |
186 | else | 193 | else |
187 | tx_ba_tbl->amsdu = false; | 194 | tx_ba_tbl->amsdu = false; |
195 | if (ra_list) { | ||
196 | ra_list->amsdu_in_ampdu = tx_ba_tbl->amsdu; | ||
197 | ra_list->ba_status = BA_SETUP_COMPLETE; | ||
198 | } | ||
188 | } else { | 199 | } else { |
189 | dev_err(priv->adapter->dev, "BA stream not created\n"); | 200 | dev_err(priv->adapter->dev, "BA stream not created\n"); |
190 | } | 201 | } |
@@ -515,6 +526,7 @@ void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid, | |||
515 | enum mwifiex_ba_status ba_status) | 526 | enum mwifiex_ba_status ba_status) |
516 | { | 527 | { |
517 | struct mwifiex_tx_ba_stream_tbl *new_node; | 528 | struct mwifiex_tx_ba_stream_tbl *new_node; |
529 | struct mwifiex_ra_list_tbl *ra_list; | ||
518 | unsigned long flags; | 530 | unsigned long flags; |
519 | 531 | ||
520 | if (!mwifiex_get_ba_tbl(priv, tid, ra)) { | 532 | if (!mwifiex_get_ba_tbl(priv, tid, ra)) { |
@@ -522,7 +534,11 @@ void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid, | |||
522 | GFP_ATOMIC); | 534 | GFP_ATOMIC); |
523 | if (!new_node) | 535 | if (!new_node) |
524 | return; | 536 | return; |
525 | 537 | ra_list = mwifiex_wmm_get_ralist_node(priv, tid, ra); | |
538 | if (ra_list) { | ||
539 | ra_list->ba_status = ba_status; | ||
540 | ra_list->amsdu_in_ampdu = false; | ||
541 | } | ||
526 | INIT_LIST_HEAD(&new_node->list); | 542 | INIT_LIST_HEAD(&new_node->list); |
527 | 543 | ||
528 | new_node->tid = tid; | 544 | new_node->tid = tid; |
diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h index 8e2e39422ad8..afdd58aa90de 100644 --- a/drivers/net/wireless/mwifiex/11n.h +++ b/drivers/net/wireless/mwifiex/11n.h | |||
@@ -77,22 +77,6 @@ mwifiex_is_station_ampdu_allowed(struct mwifiex_private *priv, | |||
77 | return (node->ampdu_sta[tid] != BA_STREAM_NOT_ALLOWED) ? true : false; | 77 | return (node->ampdu_sta[tid] != BA_STREAM_NOT_ALLOWED) ? true : false; |
78 | } | 78 | } |
79 | 79 | ||
80 | /* This function checks whether AMSDU is allowed for BA stream. */ | ||
81 | static inline u8 | ||
82 | mwifiex_is_amsdu_in_ampdu_allowed(struct mwifiex_private *priv, | ||
83 | struct mwifiex_ra_list_tbl *ptr, int tid) | ||
84 | { | ||
85 | struct mwifiex_tx_ba_stream_tbl *tx_tbl; | ||
86 | |||
87 | if (is_broadcast_ether_addr(ptr->ra)) | ||
88 | return false; | ||
89 | tx_tbl = mwifiex_get_ba_tbl(priv, tid, ptr->ra); | ||
90 | if (tx_tbl) | ||
91 | return tx_tbl->amsdu; | ||
92 | |||
93 | return false; | ||
94 | } | ||
95 | |||
96 | /* This function checks whether AMPDU is allowed or not for a particular TID. */ | 80 | /* This function checks whether AMPDU is allowed or not for a particular TID. */ |
97 | static inline u8 | 81 | static inline u8 |
98 | mwifiex_is_ampdu_allowed(struct mwifiex_private *priv, | 82 | mwifiex_is_ampdu_allowed(struct mwifiex_private *priv, |
@@ -182,22 +166,6 @@ mwifiex_find_stream_to_delete(struct mwifiex_private *priv, int ptr_tid, | |||
182 | } | 166 | } |
183 | 167 | ||
184 | /* | 168 | /* |
185 | * This function checks whether BA stream is set up or not. | ||
186 | */ | ||
187 | static inline int | ||
188 | mwifiex_is_ba_stream_setup(struct mwifiex_private *priv, | ||
189 | struct mwifiex_ra_list_tbl *ptr, int tid) | ||
190 | { | ||
191 | struct mwifiex_tx_ba_stream_tbl *tx_tbl; | ||
192 | |||
193 | tx_tbl = mwifiex_get_ba_tbl(priv, tid, ptr->ra); | ||
194 | if (tx_tbl && IS_BASTREAM_SETUP(tx_tbl)) | ||
195 | return true; | ||
196 | |||
197 | return false; | ||
198 | } | ||
199 | |||
200 | /* | ||
201 | * This function checks whether associated station is 11n enabled | 169 | * This function checks whether associated station is 11n enabled |
202 | */ | 170 | */ |
203 | static inline int mwifiex_is_sta_11n_enabled(struct mwifiex_private *priv, | 171 | static inline int mwifiex_is_sta_11n_enabled(struct mwifiex_private *priv, |
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index 9b983b5cebbd..6183e255e62a 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c | |||
@@ -170,7 +170,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, | |||
170 | struct mwifiex_adapter *adapter = priv->adapter; | 170 | struct mwifiex_adapter *adapter = priv->adapter; |
171 | struct sk_buff *skb_aggr, *skb_src; | 171 | struct sk_buff *skb_aggr, *skb_src; |
172 | struct mwifiex_txinfo *tx_info_aggr, *tx_info_src; | 172 | struct mwifiex_txinfo *tx_info_aggr, *tx_info_src; |
173 | int pad = 0, ret; | 173 | int pad = 0, aggr_num = 0, ret; |
174 | struct mwifiex_tx_param tx_param; | 174 | struct mwifiex_tx_param tx_param; |
175 | struct txpd *ptx_pd = NULL; | 175 | struct txpd *ptx_pd = NULL; |
176 | struct timeval tv; | 176 | struct timeval tv; |
@@ -184,7 +184,8 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, | |||
184 | } | 184 | } |
185 | 185 | ||
186 | tx_info_src = MWIFIEX_SKB_TXCB(skb_src); | 186 | tx_info_src = MWIFIEX_SKB_TXCB(skb_src); |
187 | skb_aggr = dev_alloc_skb(adapter->tx_buf_size); | 187 | skb_aggr = mwifiex_alloc_dma_align_buf(adapter->tx_buf_size, |
188 | GFP_ATOMIC | GFP_DMA); | ||
188 | if (!skb_aggr) { | 189 | if (!skb_aggr) { |
189 | dev_err(adapter->dev, "%s: alloc skb_aggr\n", __func__); | 190 | dev_err(adapter->dev, "%s: alloc skb_aggr\n", __func__); |
190 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, | 191 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, |
@@ -200,6 +201,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, | |||
200 | 201 | ||
201 | if (tx_info_src->flags & MWIFIEX_BUF_FLAG_TDLS_PKT) | 202 | if (tx_info_src->flags & MWIFIEX_BUF_FLAG_TDLS_PKT) |
202 | tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT; | 203 | tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT; |
204 | tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_AGGR_PKT; | ||
203 | skb_aggr->priority = skb_src->priority; | 205 | skb_aggr->priority = skb_src->priority; |
204 | 206 | ||
205 | do_gettimeofday(&tv); | 207 | do_gettimeofday(&tv); |
@@ -211,11 +213,9 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, | |||
211 | break; | 213 | break; |
212 | 214 | ||
213 | skb_src = skb_dequeue(&pra_list->skb_head); | 215 | skb_src = skb_dequeue(&pra_list->skb_head); |
214 | |||
215 | pra_list->total_pkt_count--; | 216 | pra_list->total_pkt_count--; |
216 | |||
217 | atomic_dec(&priv->wmm.tx_pkts_queued); | 217 | atomic_dec(&priv->wmm.tx_pkts_queued); |
218 | 218 | aggr_num++; | |
219 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, | 219 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, |
220 | ra_list_flags); | 220 | ra_list_flags); |
221 | mwifiex_11n_form_amsdu_pkt(skb_aggr, skb_src, &pad); | 221 | mwifiex_11n_form_amsdu_pkt(skb_aggr, skb_src, &pad); |
@@ -251,6 +251,12 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, | |||
251 | ptx_pd = (struct txpd *)skb_aggr->data; | 251 | ptx_pd = (struct txpd *)skb_aggr->data; |
252 | 252 | ||
253 | skb_push(skb_aggr, headroom); | 253 | skb_push(skb_aggr, headroom); |
254 | tx_info_aggr->aggr_num = aggr_num * 2; | ||
255 | if (adapter->data_sent || adapter->tx_lock_flag) { | ||
256 | atomic_add(aggr_num * 2, &adapter->tx_queued); | ||
257 | skb_queue_tail(&adapter->tx_data_q, skb_aggr); | ||
258 | return 0; | ||
259 | } | ||
254 | 260 | ||
255 | if (adapter->iface_type == MWIFIEX_USB) { | 261 | if (adapter->iface_type == MWIFIEX_USB) { |
256 | adapter->data_sent = true; | 262 | adapter->data_sent = true; |
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index a2e8817b56d8..f75f8acfaca0 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c | |||
@@ -659,6 +659,7 @@ mwifiex_del_ba_tbl(struct mwifiex_private *priv, int tid, u8 *peer_mac, | |||
659 | { | 659 | { |
660 | struct mwifiex_rx_reorder_tbl *tbl; | 660 | struct mwifiex_rx_reorder_tbl *tbl; |
661 | struct mwifiex_tx_ba_stream_tbl *ptx_tbl; | 661 | struct mwifiex_tx_ba_stream_tbl *ptx_tbl; |
662 | struct mwifiex_ra_list_tbl *ra_list; | ||
662 | u8 cleanup_rx_reorder_tbl; | 663 | u8 cleanup_rx_reorder_tbl; |
663 | unsigned long flags; | 664 | unsigned long flags; |
664 | 665 | ||
@@ -686,7 +687,11 @@ mwifiex_del_ba_tbl(struct mwifiex_private *priv, int tid, u8 *peer_mac, | |||
686 | "event: TID, RA not found in table\n"); | 687 | "event: TID, RA not found in table\n"); |
687 | return; | 688 | return; |
688 | } | 689 | } |
689 | 690 | ra_list = mwifiex_wmm_get_ralist_node(priv, tid, peer_mac); | |
691 | if (ra_list) { | ||
692 | ra_list->amsdu_in_ampdu = false; | ||
693 | ra_list->ba_status = BA_SETUP_NONE; | ||
694 | } | ||
690 | spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); | 695 | spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); |
691 | mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, ptx_tbl); | 696 | mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, ptx_tbl); |
692 | spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); | 697 | spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 6f8993c12373..bf9020ff2d33 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -717,6 +717,9 @@ mwifiex_cfg80211_init_p2p_go(struct mwifiex_private *priv) | |||
717 | 717 | ||
718 | static int mwifiex_deinit_priv_params(struct mwifiex_private *priv) | 718 | static int mwifiex_deinit_priv_params(struct mwifiex_private *priv) |
719 | { | 719 | { |
720 | struct mwifiex_adapter *adapter = priv->adapter; | ||
721 | unsigned long flags; | ||
722 | |||
720 | priv->mgmt_frame_mask = 0; | 723 | priv->mgmt_frame_mask = 0; |
721 | if (mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG, | 724 | if (mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG, |
722 | HostCmd_ACT_GEN_SET, 0, | 725 | HostCmd_ACT_GEN_SET, 0, |
@@ -727,6 +730,25 @@ static int mwifiex_deinit_priv_params(struct mwifiex_private *priv) | |||
727 | } | 730 | } |
728 | 731 | ||
729 | mwifiex_deauthenticate(priv, NULL); | 732 | mwifiex_deauthenticate(priv, NULL); |
733 | |||
734 | spin_lock_irqsave(&adapter->main_proc_lock, flags); | ||
735 | adapter->main_locked = true; | ||
736 | if (adapter->mwifiex_processing) { | ||
737 | spin_unlock_irqrestore(&adapter->main_proc_lock, flags); | ||
738 | flush_workqueue(adapter->workqueue); | ||
739 | } else { | ||
740 | spin_unlock_irqrestore(&adapter->main_proc_lock, flags); | ||
741 | } | ||
742 | |||
743 | spin_lock_irqsave(&adapter->rx_proc_lock, flags); | ||
744 | adapter->rx_locked = true; | ||
745 | if (adapter->rx_processing) { | ||
746 | spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); | ||
747 | flush_workqueue(adapter->rx_workqueue); | ||
748 | } else { | ||
749 | spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); | ||
750 | } | ||
751 | |||
730 | mwifiex_free_priv(priv); | 752 | mwifiex_free_priv(priv); |
731 | priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; | 753 | priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; |
732 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; | 754 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; |
@@ -740,6 +762,9 @@ mwifiex_init_new_priv_params(struct mwifiex_private *priv, | |||
740 | struct net_device *dev, | 762 | struct net_device *dev, |
741 | enum nl80211_iftype type) | 763 | enum nl80211_iftype type) |
742 | { | 764 | { |
765 | struct mwifiex_adapter *adapter = priv->adapter; | ||
766 | unsigned long flags; | ||
767 | |||
743 | mwifiex_init_priv(priv); | 768 | mwifiex_init_priv(priv); |
744 | 769 | ||
745 | priv->bss_mode = type; | 770 | priv->bss_mode = type; |
@@ -770,6 +795,14 @@ mwifiex_init_new_priv_params(struct mwifiex_private *priv, | |||
770 | return -EOPNOTSUPP; | 795 | return -EOPNOTSUPP; |
771 | } | 796 | } |
772 | 797 | ||
798 | spin_lock_irqsave(&adapter->main_proc_lock, flags); | ||
799 | adapter->main_locked = false; | ||
800 | spin_unlock_irqrestore(&adapter->main_proc_lock, flags); | ||
801 | |||
802 | spin_lock_irqsave(&adapter->rx_proc_lock, flags); | ||
803 | adapter->rx_locked = false; | ||
804 | spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); | ||
805 | |||
773 | return 0; | 806 | return 0; |
774 | } | 807 | } |
775 | 808 | ||
@@ -2733,24 +2766,71 @@ mwifiex_is_pattern_supported(struct cfg80211_pkt_pattern *pat, s8 *byte_seq, | |||
2733 | } | 2766 | } |
2734 | 2767 | ||
2735 | #ifdef CONFIG_PM | 2768 | #ifdef CONFIG_PM |
2736 | static int mwifiex_set_mef_filter(struct mwifiex_private *priv, | 2769 | static void mwifiex_set_auto_arp_mef_entry(struct mwifiex_private *priv, |
2737 | struct cfg80211_wowlan *wowlan) | 2770 | struct mwifiex_mef_entry *mef_entry) |
2771 | { | ||
2772 | int i, filt_num = 0, num_ipv4 = 0; | ||
2773 | struct in_device *in_dev; | ||
2774 | struct in_ifaddr *ifa; | ||
2775 | __be32 ips[MWIFIEX_MAX_SUPPORTED_IPADDR]; | ||
2776 | struct mwifiex_adapter *adapter = priv->adapter; | ||
2777 | |||
2778 | mef_entry->mode = MEF_MODE_HOST_SLEEP; | ||
2779 | mef_entry->action = MEF_ACTION_AUTO_ARP; | ||
2780 | |||
2781 | /* Enable ARP offload feature */ | ||
2782 | memset(ips, 0, sizeof(ips)); | ||
2783 | for (i = 0; i < MWIFIEX_MAX_BSS_NUM; i++) { | ||
2784 | if (adapter->priv[i]->netdev) { | ||
2785 | in_dev = __in_dev_get_rtnl(adapter->priv[i]->netdev); | ||
2786 | if (!in_dev) | ||
2787 | continue; | ||
2788 | ifa = in_dev->ifa_list; | ||
2789 | if (!ifa || !ifa->ifa_local) | ||
2790 | continue; | ||
2791 | ips[i] = ifa->ifa_local; | ||
2792 | num_ipv4++; | ||
2793 | } | ||
2794 | } | ||
2795 | |||
2796 | for (i = 0; i < num_ipv4; i++) { | ||
2797 | if (!ips[i]) | ||
2798 | continue; | ||
2799 | mef_entry->filter[filt_num].repeat = 1; | ||
2800 | memcpy(mef_entry->filter[filt_num].byte_seq, | ||
2801 | (u8 *)&ips[i], sizeof(ips[i])); | ||
2802 | mef_entry->filter[filt_num]. | ||
2803 | byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] = | ||
2804 | sizeof(ips[i]); | ||
2805 | mef_entry->filter[filt_num].offset = 46; | ||
2806 | mef_entry->filter[filt_num].filt_type = TYPE_EQ; | ||
2807 | if (filt_num) { | ||
2808 | mef_entry->filter[filt_num].filt_action = | ||
2809 | TYPE_OR; | ||
2810 | } | ||
2811 | filt_num++; | ||
2812 | } | ||
2813 | |||
2814 | mef_entry->filter[filt_num].repeat = 1; | ||
2815 | mef_entry->filter[filt_num].byte_seq[0] = 0x08; | ||
2816 | mef_entry->filter[filt_num].byte_seq[1] = 0x06; | ||
2817 | mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] = 2; | ||
2818 | mef_entry->filter[filt_num].offset = 20; | ||
2819 | mef_entry->filter[filt_num].filt_type = TYPE_EQ; | ||
2820 | mef_entry->filter[filt_num].filt_action = TYPE_AND; | ||
2821 | } | ||
2822 | |||
2823 | static int mwifiex_set_wowlan_mef_entry(struct mwifiex_private *priv, | ||
2824 | struct mwifiex_ds_mef_cfg *mef_cfg, | ||
2825 | struct mwifiex_mef_entry *mef_entry, | ||
2826 | struct cfg80211_wowlan *wowlan) | ||
2738 | { | 2827 | { |
2739 | int i, filt_num = 0, ret = 0; | 2828 | int i, filt_num = 0, ret = 0; |
2740 | bool first_pat = true; | 2829 | bool first_pat = true; |
2741 | u8 byte_seq[MWIFIEX_MEF_MAX_BYTESEQ + 1]; | 2830 | u8 byte_seq[MWIFIEX_MEF_MAX_BYTESEQ + 1]; |
2742 | const u8 ipv4_mc_mac[] = {0x33, 0x33}; | 2831 | const u8 ipv4_mc_mac[] = {0x33, 0x33}; |
2743 | const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e}; | 2832 | const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e}; |
2744 | struct mwifiex_ds_mef_cfg mef_cfg; | ||
2745 | struct mwifiex_mef_entry *mef_entry; | ||
2746 | 2833 | ||
2747 | mef_entry = kzalloc(sizeof(*mef_entry), GFP_KERNEL); | ||
2748 | if (!mef_entry) | ||
2749 | return -ENOMEM; | ||
2750 | |||
2751 | memset(&mef_cfg, 0, sizeof(mef_cfg)); | ||
2752 | mef_cfg.num_entries = 1; | ||
2753 | mef_cfg.mef_entry = mef_entry; | ||
2754 | mef_entry->mode = MEF_MODE_HOST_SLEEP; | 2834 | mef_entry->mode = MEF_MODE_HOST_SLEEP; |
2755 | mef_entry->action = MEF_ACTION_ALLOW_AND_WAKEUP_HOST; | 2835 | mef_entry->action = MEF_ACTION_ALLOW_AND_WAKEUP_HOST; |
2756 | 2836 | ||
@@ -2767,20 +2847,19 @@ static int mwifiex_set_mef_filter(struct mwifiex_private *priv, | |||
2767 | if (!wowlan->patterns[i].pkt_offset) { | 2847 | if (!wowlan->patterns[i].pkt_offset) { |
2768 | if (!(byte_seq[0] & 0x01) && | 2848 | if (!(byte_seq[0] & 0x01) && |
2769 | (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 1)) { | 2849 | (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 1)) { |
2770 | mef_cfg.criteria |= MWIFIEX_CRITERIA_UNICAST; | 2850 | mef_cfg->criteria |= MWIFIEX_CRITERIA_UNICAST; |
2771 | continue; | 2851 | continue; |
2772 | } else if (is_broadcast_ether_addr(byte_seq)) { | 2852 | } else if (is_broadcast_ether_addr(byte_seq)) { |
2773 | mef_cfg.criteria |= MWIFIEX_CRITERIA_BROADCAST; | 2853 | mef_cfg->criteria |= MWIFIEX_CRITERIA_BROADCAST; |
2774 | continue; | 2854 | continue; |
2775 | } else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) && | 2855 | } else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) && |
2776 | (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 2)) || | 2856 | (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 2)) || |
2777 | (!memcmp(byte_seq, ipv6_mc_mac, 3) && | 2857 | (!memcmp(byte_seq, ipv6_mc_mac, 3) && |
2778 | (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 3))) { | 2858 | (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 3))) { |
2779 | mef_cfg.criteria |= MWIFIEX_CRITERIA_MULTICAST; | 2859 | mef_cfg->criteria |= MWIFIEX_CRITERIA_MULTICAST; |
2780 | continue; | 2860 | continue; |
2781 | } | 2861 | } |
2782 | } | 2862 | } |
2783 | |||
2784 | mef_entry->filter[filt_num].repeat = 1; | 2863 | mef_entry->filter[filt_num].repeat = 1; |
2785 | mef_entry->filter[filt_num].offset = | 2864 | mef_entry->filter[filt_num].offset = |
2786 | wowlan->patterns[i].pkt_offset; | 2865 | wowlan->patterns[i].pkt_offset; |
@@ -2797,7 +2876,7 @@ static int mwifiex_set_mef_filter(struct mwifiex_private *priv, | |||
2797 | } | 2876 | } |
2798 | 2877 | ||
2799 | if (wowlan->magic_pkt) { | 2878 | if (wowlan->magic_pkt) { |
2800 | mef_cfg.criteria |= MWIFIEX_CRITERIA_UNICAST; | 2879 | mef_cfg->criteria |= MWIFIEX_CRITERIA_UNICAST; |
2801 | mef_entry->filter[filt_num].repeat = 16; | 2880 | mef_entry->filter[filt_num].repeat = 16; |
2802 | memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr, | 2881 | memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr, |
2803 | ETH_ALEN); | 2882 | ETH_ALEN); |
@@ -2818,6 +2897,34 @@ static int mwifiex_set_mef_filter(struct mwifiex_private *priv, | |||
2818 | mef_entry->filter[filt_num].filt_type = TYPE_EQ; | 2897 | mef_entry->filter[filt_num].filt_type = TYPE_EQ; |
2819 | mef_entry->filter[filt_num].filt_action = TYPE_OR; | 2898 | mef_entry->filter[filt_num].filt_action = TYPE_OR; |
2820 | } | 2899 | } |
2900 | return ret; | ||
2901 | } | ||
2902 | |||
2903 | static int mwifiex_set_mef_filter(struct mwifiex_private *priv, | ||
2904 | struct cfg80211_wowlan *wowlan) | ||
2905 | { | ||
2906 | int ret = 0, num_entries = 1; | ||
2907 | struct mwifiex_ds_mef_cfg mef_cfg; | ||
2908 | struct mwifiex_mef_entry *mef_entry; | ||
2909 | |||
2910 | if (wowlan->n_patterns || wowlan->magic_pkt) | ||
2911 | num_entries++; | ||
2912 | |||
2913 | mef_entry = kcalloc(num_entries, sizeof(*mef_entry), GFP_KERNEL); | ||
2914 | if (!mef_entry) | ||
2915 | return -ENOMEM; | ||
2916 | |||
2917 | memset(&mef_cfg, 0, sizeof(mef_cfg)); | ||
2918 | mef_cfg.criteria |= MWIFIEX_CRITERIA_BROADCAST | | ||
2919 | MWIFIEX_CRITERIA_UNICAST; | ||
2920 | mef_cfg.num_entries = num_entries; | ||
2921 | mef_cfg.mef_entry = mef_entry; | ||
2922 | |||
2923 | mwifiex_set_auto_arp_mef_entry(priv, &mef_entry[0]); | ||
2924 | |||
2925 | if (wowlan->n_patterns || wowlan->magic_pkt) | ||
2926 | ret = mwifiex_set_wowlan_mef_entry(priv, &mef_cfg, | ||
2927 | &mef_entry[1], wowlan); | ||
2821 | 2928 | ||
2822 | if (!mef_cfg.criteria) | 2929 | if (!mef_cfg.criteria) |
2823 | mef_cfg.criteria = MWIFIEX_CRITERIA_BROADCAST | | 2930 | mef_cfg.criteria = MWIFIEX_CRITERIA_BROADCAST | |
@@ -2825,8 +2932,8 @@ static int mwifiex_set_mef_filter(struct mwifiex_private *priv, | |||
2825 | MWIFIEX_CRITERIA_MULTICAST; | 2932 | MWIFIEX_CRITERIA_MULTICAST; |
2826 | 2933 | ||
2827 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_MEF_CFG, | 2934 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_MEF_CFG, |
2828 | HostCmd_ACT_GEN_SET, 0, &mef_cfg, true); | 2935 | HostCmd_ACT_GEN_SET, 0, |
2829 | 2936 | &mef_cfg, true); | |
2830 | kfree(mef_entry); | 2937 | kfree(mef_entry); |
2831 | return ret; | 2938 | return ret; |
2832 | } | 2939 | } |
@@ -2836,27 +2943,33 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, | |||
2836 | { | 2943 | { |
2837 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); | 2944 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); |
2838 | struct mwifiex_ds_hs_cfg hs_cfg; | 2945 | struct mwifiex_ds_hs_cfg hs_cfg; |
2839 | int ret = 0; | 2946 | int i, ret = 0; |
2840 | struct mwifiex_private *priv = | 2947 | struct mwifiex_private *priv; |
2841 | mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); | 2948 | |
2949 | for (i = 0; i < adapter->priv_num; i++) { | ||
2950 | priv = adapter->priv[i]; | ||
2951 | mwifiex_abort_cac(priv); | ||
2952 | } | ||
2953 | |||
2954 | mwifiex_cancel_all_pending_cmd(adapter); | ||
2842 | 2955 | ||
2843 | if (!wowlan) { | 2956 | if (!wowlan) { |
2844 | dev_warn(adapter->dev, "None of the WOWLAN triggers enabled\n"); | 2957 | dev_warn(adapter->dev, "None of the WOWLAN triggers enabled\n"); |
2845 | return 0; | 2958 | return 0; |
2846 | } | 2959 | } |
2847 | 2960 | ||
2961 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); | ||
2962 | |||
2848 | if (!priv->media_connected) { | 2963 | if (!priv->media_connected) { |
2849 | dev_warn(adapter->dev, | 2964 | dev_warn(adapter->dev, |
2850 | "Can not configure WOWLAN in disconnected state\n"); | 2965 | "Can not configure WOWLAN in disconnected state\n"); |
2851 | return 0; | 2966 | return 0; |
2852 | } | 2967 | } |
2853 | 2968 | ||
2854 | if (wowlan->n_patterns || wowlan->magic_pkt) { | 2969 | ret = mwifiex_set_mef_filter(priv, wowlan); |
2855 | ret = mwifiex_set_mef_filter(priv, wowlan); | 2970 | if (ret) { |
2856 | if (ret) { | 2971 | dev_err(adapter->dev, "Failed to set MEF filter\n"); |
2857 | dev_err(adapter->dev, "Failed to set MEF filter\n"); | 2972 | return ret; |
2858 | return ret; | ||
2859 | } | ||
2860 | } | 2973 | } |
2861 | 2974 | ||
2862 | if (wowlan->disconnect) { | 2975 | if (wowlan->disconnect) { |
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index cf2fa110e251..38f24e0427d2 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h | |||
@@ -83,6 +83,7 @@ | |||
83 | #define MWIFIEX_BUF_FLAG_TDLS_PKT BIT(2) | 83 | #define MWIFIEX_BUF_FLAG_TDLS_PKT BIT(2) |
84 | #define MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS BIT(3) | 84 | #define MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS BIT(3) |
85 | #define MWIFIEX_BUF_FLAG_ACTION_TX_STATUS BIT(4) | 85 | #define MWIFIEX_BUF_FLAG_ACTION_TX_STATUS BIT(4) |
86 | #define MWIFIEX_BUF_FLAG_AGGR_PKT BIT(5) | ||
86 | 87 | ||
87 | #define MWIFIEX_BRIDGED_PKTS_THR_HIGH 1024 | 88 | #define MWIFIEX_BRIDGED_PKTS_THR_HIGH 1024 |
88 | #define MWIFIEX_BRIDGED_PKTS_THR_LOW 128 | 89 | #define MWIFIEX_BRIDGED_PKTS_THR_LOW 128 |
@@ -111,6 +112,11 @@ | |||
111 | 112 | ||
112 | #define MWIFIEX_A_BAND_START_FREQ 5000 | 113 | #define MWIFIEX_A_BAND_START_FREQ 5000 |
113 | 114 | ||
115 | /* SDIO Aggr data packet special info */ | ||
116 | #define SDIO_MAX_AGGR_BUF_SIZE (256 * 255) | ||
117 | #define BLOCK_NUMBER_OFFSET 15 | ||
118 | #define SDIO_HEADER_OFFSET 28 | ||
119 | |||
114 | enum mwifiex_bss_type { | 120 | enum mwifiex_bss_type { |
115 | MWIFIEX_BSS_TYPE_STA = 0, | 121 | MWIFIEX_BSS_TYPE_STA = 0, |
116 | MWIFIEX_BSS_TYPE_UAP = 1, | 122 | MWIFIEX_BSS_TYPE_UAP = 1, |
@@ -168,10 +174,11 @@ struct mwifiex_wait_queue { | |||
168 | }; | 174 | }; |
169 | 175 | ||
170 | struct mwifiex_rxinfo { | 176 | struct mwifiex_rxinfo { |
177 | struct sk_buff *parent; | ||
171 | u8 bss_num; | 178 | u8 bss_num; |
172 | u8 bss_type; | 179 | u8 bss_type; |
173 | struct sk_buff *parent; | ||
174 | u8 use_count; | 180 | u8 use_count; |
181 | u8 buf_type; | ||
175 | }; | 182 | }; |
176 | 183 | ||
177 | struct mwifiex_txinfo { | 184 | struct mwifiex_txinfo { |
@@ -179,6 +186,7 @@ struct mwifiex_txinfo { | |||
179 | u8 flags; | 186 | u8 flags; |
180 | u8 bss_num; | 187 | u8 bss_num; |
181 | u8 bss_type; | 188 | u8 bss_type; |
189 | u8 aggr_num; | ||
182 | u32 pkt_len; | 190 | u32 pkt_len; |
183 | u8 ack_frame_id; | 191 | u8 ack_frame_id; |
184 | u64 cookie; | 192 | u64 cookie; |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index df553e86a0ad..59d8964dd0dc 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -197,6 +197,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
197 | 197 | ||
198 | #define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11)) | 198 | #define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11)) |
199 | #define ISSUPP_TDLS_ENABLED(FwCapInfo) (FwCapInfo & BIT(14)) | 199 | #define ISSUPP_TDLS_ENABLED(FwCapInfo) (FwCapInfo & BIT(14)) |
200 | #define ISSUPP_SDIO_SPA_ENABLED(FwCapInfo) (FwCapInfo & BIT(16)) | ||
200 | 201 | ||
201 | #define MWIFIEX_DEF_HT_CAP (IEEE80211_HT_CAP_DSSSCCK40 | \ | 202 | #define MWIFIEX_DEF_HT_CAP (IEEE80211_HT_CAP_DSSSCCK40 | \ |
202 | (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | \ | 203 | (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | \ |
@@ -353,6 +354,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
353 | #define HostCmd_CMD_REMAIN_ON_CHAN 0x010d | 354 | #define HostCmd_CMD_REMAIN_ON_CHAN 0x010d |
354 | #define HostCmd_CMD_11AC_CFG 0x0112 | 355 | #define HostCmd_CMD_11AC_CFG 0x0112 |
355 | #define HostCmd_CMD_TDLS_OPER 0x0122 | 356 | #define HostCmd_CMD_TDLS_OPER 0x0122 |
357 | #define HostCmd_CMD_SDIO_SP_RX_AGGR_CFG 0x0223 | ||
356 | 358 | ||
357 | #define PROTOCOL_NO_SECURITY 0x01 | 359 | #define PROTOCOL_NO_SECURITY 0x01 |
358 | #define PROTOCOL_STATIC_WEP 0x02 | 360 | #define PROTOCOL_STATIC_WEP 0x02 |
@@ -523,9 +525,11 @@ enum P2P_MODES { | |||
523 | #define TYPE_OR (MAX_OPERAND+5) | 525 | #define TYPE_OR (MAX_OPERAND+5) |
524 | #define MEF_MODE_HOST_SLEEP 1 | 526 | #define MEF_MODE_HOST_SLEEP 1 |
525 | #define MEF_ACTION_ALLOW_AND_WAKEUP_HOST 3 | 527 | #define MEF_ACTION_ALLOW_AND_WAKEUP_HOST 3 |
528 | #define MEF_ACTION_AUTO_ARP 0x10 | ||
526 | #define MWIFIEX_CRITERIA_BROADCAST BIT(0) | 529 | #define MWIFIEX_CRITERIA_BROADCAST BIT(0) |
527 | #define MWIFIEX_CRITERIA_UNICAST BIT(1) | 530 | #define MWIFIEX_CRITERIA_UNICAST BIT(1) |
528 | #define MWIFIEX_CRITERIA_MULTICAST BIT(3) | 531 | #define MWIFIEX_CRITERIA_MULTICAST BIT(3) |
532 | #define MWIFIEX_MAX_SUPPORTED_IPADDR 4 | ||
529 | 533 | ||
530 | #define ACT_TDLS_DELETE 0x00 | 534 | #define ACT_TDLS_DELETE 0x00 |
531 | #define ACT_TDLS_CREATE 0x01 | 535 | #define ACT_TDLS_CREATE 0x01 |
@@ -1240,6 +1244,12 @@ struct host_cmd_ds_chan_rpt_event { | |||
1240 | u8 tlvbuf[0]; | 1244 | u8 tlvbuf[0]; |
1241 | } __packed; | 1245 | } __packed; |
1242 | 1246 | ||
1247 | struct host_cmd_sdio_sp_rx_aggr_cfg { | ||
1248 | u8 action; | ||
1249 | u8 enable; | ||
1250 | __le16 block_size; | ||
1251 | } __packed; | ||
1252 | |||
1243 | struct mwifiex_fixed_bcn_param { | 1253 | struct mwifiex_fixed_bcn_param { |
1244 | __le64 timestamp; | 1254 | __le64 timestamp; |
1245 | __le16 beacon_period; | 1255 | __le16 beacon_period; |
@@ -1962,6 +1972,7 @@ struct host_cmd_ds_command { | |||
1962 | struct host_cmd_ds_coalesce_cfg coalesce_cfg; | 1972 | struct host_cmd_ds_coalesce_cfg coalesce_cfg; |
1963 | struct host_cmd_ds_tdls_oper tdls_oper; | 1973 | struct host_cmd_ds_tdls_oper tdls_oper; |
1964 | struct host_cmd_ds_chan_rpt_req chan_rpt_req; | 1974 | struct host_cmd_ds_chan_rpt_req chan_rpt_req; |
1975 | struct host_cmd_sdio_sp_rx_aggr_cfg sdio_rx_aggr_cfg; | ||
1965 | } params; | 1976 | } params; |
1966 | } __packed; | 1977 | } __packed; |
1967 | 1978 | ||
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 0153ce6d5879..e12192f5cfad 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c | |||
@@ -266,18 +266,15 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) | |||
266 | 266 | ||
267 | mwifiex_wmm_init(adapter); | 267 | mwifiex_wmm_init(adapter); |
268 | 268 | ||
269 | if (adapter->sleep_cfm) { | 269 | sleep_cfm_buf = (struct mwifiex_opt_sleep_confirm *) |
270 | sleep_cfm_buf = (struct mwifiex_opt_sleep_confirm *) | 270 | adapter->sleep_cfm->data; |
271 | adapter->sleep_cfm->data; | 271 | memset(sleep_cfm_buf, 0, adapter->sleep_cfm->len); |
272 | memset(sleep_cfm_buf, 0, adapter->sleep_cfm->len); | 272 | sleep_cfm_buf->command = cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH); |
273 | sleep_cfm_buf->command = | 273 | sleep_cfm_buf->size = cpu_to_le16(adapter->sleep_cfm->len); |
274 | cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH); | 274 | sleep_cfm_buf->result = 0; |
275 | sleep_cfm_buf->size = | 275 | sleep_cfm_buf->action = cpu_to_le16(SLEEP_CONFIRM); |
276 | cpu_to_le16(adapter->sleep_cfm->len); | 276 | sleep_cfm_buf->resp_ctrl = cpu_to_le16(RESP_NEEDED); |
277 | sleep_cfm_buf->result = 0; | 277 | |
278 | sleep_cfm_buf->action = cpu_to_le16(SLEEP_CONFIRM); | ||
279 | sleep_cfm_buf->resp_ctrl = cpu_to_le16(RESP_NEEDED); | ||
280 | } | ||
281 | memset(&adapter->sleep_params, 0, sizeof(adapter->sleep_params)); | 278 | memset(&adapter->sleep_params, 0, sizeof(adapter->sleep_params)); |
282 | memset(&adapter->sleep_period, 0, sizeof(adapter->sleep_period)); | 279 | memset(&adapter->sleep_period, 0, sizeof(adapter->sleep_period)); |
283 | adapter->tx_lock_flag = false; | 280 | adapter->tx_lock_flag = false; |
@@ -481,6 +478,7 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) | |||
481 | spin_lock_init(&adapter->rx_proc_lock); | 478 | spin_lock_init(&adapter->rx_proc_lock); |
482 | 479 | ||
483 | skb_queue_head_init(&adapter->rx_data_q); | 480 | skb_queue_head_init(&adapter->rx_data_q); |
481 | skb_queue_head_init(&adapter->tx_data_q); | ||
484 | 482 | ||
485 | for (i = 0; i < adapter->priv_num; ++i) { | 483 | for (i = 0; i < adapter->priv_num; ++i) { |
486 | INIT_LIST_HEAD(&adapter->bss_prio_tbl[i].bss_prio_head); | 484 | INIT_LIST_HEAD(&adapter->bss_prio_tbl[i].bss_prio_head); |
@@ -688,6 +686,10 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) | |||
688 | } | 686 | } |
689 | } | 687 | } |
690 | 688 | ||
689 | atomic_set(&adapter->tx_queued, 0); | ||
690 | while ((skb = skb_dequeue(&adapter->tx_data_q))) | ||
691 | mwifiex_write_data_complete(adapter, skb, 0, 0); | ||
692 | |||
691 | spin_lock_irqsave(&adapter->rx_proc_lock, flags); | 693 | spin_lock_irqsave(&adapter->rx_proc_lock, flags); |
692 | 694 | ||
693 | while ((skb = skb_dequeue(&adapter->rx_data_q))) { | 695 | while ((skb = skb_dequeue(&adapter->rx_data_q))) { |
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index d73a9217b9da..03a95c7d34bf 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
@@ -131,10 +131,39 @@ static int mwifiex_unregister(struct mwifiex_adapter *adapter) | |||
131 | return 0; | 131 | return 0; |
132 | } | 132 | } |
133 | 133 | ||
134 | void mwifiex_queue_main_work(struct mwifiex_adapter *adapter) | ||
135 | { | ||
136 | unsigned long flags; | ||
137 | |||
138 | spin_lock_irqsave(&adapter->main_proc_lock, flags); | ||
139 | if (adapter->mwifiex_processing) { | ||
140 | adapter->more_task_flag = true; | ||
141 | spin_unlock_irqrestore(&adapter->main_proc_lock, flags); | ||
142 | } else { | ||
143 | spin_unlock_irqrestore(&adapter->main_proc_lock, flags); | ||
144 | queue_work(adapter->workqueue, &adapter->main_work); | ||
145 | } | ||
146 | } | ||
147 | EXPORT_SYMBOL_GPL(mwifiex_queue_main_work); | ||
148 | |||
149 | static void mwifiex_queue_rx_work(struct mwifiex_adapter *adapter) | ||
150 | { | ||
151 | unsigned long flags; | ||
152 | |||
153 | spin_lock_irqsave(&adapter->rx_proc_lock, flags); | ||
154 | if (adapter->rx_processing) { | ||
155 | spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); | ||
156 | } else { | ||
157 | spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); | ||
158 | queue_work(adapter->rx_workqueue, &adapter->rx_work); | ||
159 | } | ||
160 | } | ||
161 | |||
134 | static int mwifiex_process_rx(struct mwifiex_adapter *adapter) | 162 | static int mwifiex_process_rx(struct mwifiex_adapter *adapter) |
135 | { | 163 | { |
136 | unsigned long flags; | 164 | unsigned long flags; |
137 | struct sk_buff *skb; | 165 | struct sk_buff *skb; |
166 | struct mwifiex_rxinfo *rx_info; | ||
138 | 167 | ||
139 | spin_lock_irqsave(&adapter->rx_proc_lock, flags); | 168 | spin_lock_irqsave(&adapter->rx_proc_lock, flags); |
140 | if (adapter->rx_processing || adapter->rx_locked) { | 169 | if (adapter->rx_processing || adapter->rx_locked) { |
@@ -154,9 +183,16 @@ static int mwifiex_process_rx(struct mwifiex_adapter *adapter) | |||
154 | if (adapter->if_ops.submit_rem_rx_urbs) | 183 | if (adapter->if_ops.submit_rem_rx_urbs) |
155 | adapter->if_ops.submit_rem_rx_urbs(adapter); | 184 | adapter->if_ops.submit_rem_rx_urbs(adapter); |
156 | adapter->delay_main_work = false; | 185 | adapter->delay_main_work = false; |
157 | queue_work(adapter->workqueue, &adapter->main_work); | 186 | mwifiex_queue_main_work(adapter); |
187 | } | ||
188 | rx_info = MWIFIEX_SKB_RXCB(skb); | ||
189 | if (rx_info->buf_type == MWIFIEX_TYPE_AGGR_DATA) { | ||
190 | if (adapter->if_ops.deaggr_pkt) | ||
191 | adapter->if_ops.deaggr_pkt(adapter, skb); | ||
192 | dev_kfree_skb_any(skb); | ||
193 | } else { | ||
194 | mwifiex_handle_rx_packet(adapter, skb); | ||
158 | } | 195 | } |
159 | mwifiex_handle_rx_packet(adapter, skb); | ||
160 | } | 196 | } |
161 | spin_lock_irqsave(&adapter->rx_proc_lock, flags); | 197 | spin_lock_irqsave(&adapter->rx_proc_lock, flags); |
162 | adapter->rx_processing = false; | 198 | adapter->rx_processing = false; |
@@ -189,7 +225,7 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter) | |||
189 | spin_lock_irqsave(&adapter->main_proc_lock, flags); | 225 | spin_lock_irqsave(&adapter->main_proc_lock, flags); |
190 | 226 | ||
191 | /* Check if already processing */ | 227 | /* Check if already processing */ |
192 | if (adapter->mwifiex_processing) { | 228 | if (adapter->mwifiex_processing || adapter->main_locked) { |
193 | adapter->more_task_flag = true; | 229 | adapter->more_task_flag = true; |
194 | spin_unlock_irqrestore(&adapter->main_proc_lock, flags); | 230 | spin_unlock_irqrestore(&adapter->main_proc_lock, flags); |
195 | goto exit_main_proc; | 231 | goto exit_main_proc; |
@@ -214,9 +250,7 @@ process_start: | |||
214 | if (atomic_read(&adapter->rx_pending) >= HIGH_RX_PENDING && | 250 | if (atomic_read(&adapter->rx_pending) >= HIGH_RX_PENDING && |
215 | adapter->iface_type != MWIFIEX_USB) { | 251 | adapter->iface_type != MWIFIEX_USB) { |
216 | adapter->delay_main_work = true; | 252 | adapter->delay_main_work = true; |
217 | if (!adapter->rx_processing) | 253 | mwifiex_queue_rx_work(adapter); |
218 | queue_work(adapter->rx_workqueue, | ||
219 | &adapter->rx_work); | ||
220 | break; | 254 | break; |
221 | } | 255 | } |
222 | 256 | ||
@@ -229,13 +263,14 @@ process_start: | |||
229 | } | 263 | } |
230 | 264 | ||
231 | if (adapter->rx_work_enabled && adapter->data_received) | 265 | if (adapter->rx_work_enabled && adapter->data_received) |
232 | queue_work(adapter->rx_workqueue, &adapter->rx_work); | 266 | mwifiex_queue_rx_work(adapter); |
233 | 267 | ||
234 | /* Need to wake up the card ? */ | 268 | /* Need to wake up the card ? */ |
235 | if ((adapter->ps_state == PS_STATE_SLEEP) && | 269 | if ((adapter->ps_state == PS_STATE_SLEEP) && |
236 | (adapter->pm_wakeup_card_req && | 270 | (adapter->pm_wakeup_card_req && |
237 | !adapter->pm_wakeup_fw_try) && | 271 | !adapter->pm_wakeup_fw_try) && |
238 | (is_command_pending(adapter) || | 272 | (is_command_pending(adapter) || |
273 | !skb_queue_empty(&adapter->tx_data_q) || | ||
239 | !mwifiex_wmm_lists_empty(adapter))) { | 274 | !mwifiex_wmm_lists_empty(adapter))) { |
240 | adapter->pm_wakeup_fw_try = true; | 275 | adapter->pm_wakeup_fw_try = true; |
241 | mod_timer(&adapter->wakeup_timer, jiffies + (HZ*3)); | 276 | mod_timer(&adapter->wakeup_timer, jiffies + (HZ*3)); |
@@ -247,7 +282,7 @@ process_start: | |||
247 | if (IS_CARD_RX_RCVD(adapter)) { | 282 | if (IS_CARD_RX_RCVD(adapter)) { |
248 | adapter->data_received = false; | 283 | adapter->data_received = false; |
249 | adapter->pm_wakeup_fw_try = false; | 284 | adapter->pm_wakeup_fw_try = false; |
250 | del_timer_sync(&adapter->wakeup_timer); | 285 | del_timer(&adapter->wakeup_timer); |
251 | if (adapter->ps_state == PS_STATE_SLEEP) | 286 | if (adapter->ps_state == PS_STATE_SLEEP) |
252 | adapter->ps_state = PS_STATE_AWAKE; | 287 | adapter->ps_state = PS_STATE_AWAKE; |
253 | } else { | 288 | } else { |
@@ -260,7 +295,8 @@ process_start: | |||
260 | 295 | ||
261 | if ((!adapter->scan_chan_gap_enabled && | 296 | if ((!adapter->scan_chan_gap_enabled && |
262 | adapter->scan_processing) || adapter->data_sent || | 297 | adapter->scan_processing) || adapter->data_sent || |
263 | mwifiex_wmm_lists_empty(adapter)) { | 298 | (mwifiex_wmm_lists_empty(adapter) && |
299 | skb_queue_empty(&adapter->tx_data_q))) { | ||
264 | if (adapter->cmd_sent || adapter->curr_cmd || | 300 | if (adapter->cmd_sent || adapter->curr_cmd || |
265 | (!is_command_pending(adapter))) | 301 | (!is_command_pending(adapter))) |
266 | break; | 302 | break; |
@@ -312,6 +348,20 @@ process_start: | |||
312 | 348 | ||
313 | if ((adapter->scan_chan_gap_enabled || | 349 | if ((adapter->scan_chan_gap_enabled || |
314 | !adapter->scan_processing) && | 350 | !adapter->scan_processing) && |
351 | !adapter->data_sent && | ||
352 | !skb_queue_empty(&adapter->tx_data_q)) { | ||
353 | mwifiex_process_tx_queue(adapter); | ||
354 | if (adapter->hs_activated) { | ||
355 | adapter->is_hs_configured = false; | ||
356 | mwifiex_hs_activated_event | ||
357 | (mwifiex_get_priv | ||
358 | (adapter, MWIFIEX_BSS_ROLE_ANY), | ||
359 | false); | ||
360 | } | ||
361 | } | ||
362 | |||
363 | if ((adapter->scan_chan_gap_enabled || | ||
364 | !adapter->scan_processing) && | ||
315 | !adapter->data_sent && !mwifiex_wmm_lists_empty(adapter)) { | 365 | !adapter->data_sent && !mwifiex_wmm_lists_empty(adapter)) { |
316 | mwifiex_wmm_process_tx(adapter); | 366 | mwifiex_wmm_process_tx(adapter); |
317 | if (adapter->hs_activated) { | 367 | if (adapter->hs_activated) { |
@@ -325,7 +375,8 @@ process_start: | |||
325 | 375 | ||
326 | if (adapter->delay_null_pkt && !adapter->cmd_sent && | 376 | if (adapter->delay_null_pkt && !adapter->cmd_sent && |
327 | !adapter->curr_cmd && !is_command_pending(adapter) && | 377 | !adapter->curr_cmd && !is_command_pending(adapter) && |
328 | mwifiex_wmm_lists_empty(adapter)) { | 378 | (mwifiex_wmm_lists_empty(adapter) && |
379 | skb_queue_empty(&adapter->tx_data_q))) { | ||
329 | if (!mwifiex_send_null_packet | 380 | if (!mwifiex_send_null_packet |
330 | (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), | 381 | (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), |
331 | MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET | | 382 | MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET | |
@@ -606,7 +657,7 @@ int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb) | |||
606 | atomic_inc(&priv->adapter->tx_pending); | 657 | atomic_inc(&priv->adapter->tx_pending); |
607 | mwifiex_wmm_add_buf_txqueue(priv, skb); | 658 | mwifiex_wmm_add_buf_txqueue(priv, skb); |
608 | 659 | ||
609 | queue_work(priv->adapter->workqueue, &priv->adapter->main_work); | 660 | mwifiex_queue_main_work(priv->adapter); |
610 | 661 | ||
611 | return 0; | 662 | return 0; |
612 | } | 663 | } |
@@ -1098,9 +1149,6 @@ mwifiex_add_card(void *card, struct semaphore *sem, | |||
1098 | INIT_WORK(&adapter->rx_work, mwifiex_rx_work_queue); | 1149 | INIT_WORK(&adapter->rx_work, mwifiex_rx_work_queue); |
1099 | } | 1150 | } |
1100 | 1151 | ||
1101 | if (adapter->if_ops.iface_work) | ||
1102 | INIT_WORK(&adapter->iface_work, adapter->if_ops.iface_work); | ||
1103 | |||
1104 | /* Register the device. Fill up the private data structure with relevant | 1152 | /* Register the device. Fill up the private data structure with relevant |
1105 | information from the card. */ | 1153 | information from the card. */ |
1106 | if (adapter->if_ops.register_dev(adapter)) { | 1154 | if (adapter->if_ops.register_dev(adapter)) { |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index ad8db61aeeef..fe1256044a6c 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/ctype.h> | 35 | #include <linux/ctype.h> |
36 | #include <linux/of.h> | 36 | #include <linux/of.h> |
37 | #include <linux/idr.h> | 37 | #include <linux/idr.h> |
38 | #include <linux/inetdevice.h> | ||
38 | 39 | ||
39 | #include "decl.h" | 40 | #include "decl.h" |
40 | #include "ioctl.h" | 41 | #include "ioctl.h" |
@@ -58,6 +59,8 @@ enum { | |||
58 | 59 | ||
59 | #define MWIFIEX_MAX_AP 64 | 60 | #define MWIFIEX_MAX_AP 64 |
60 | 61 | ||
62 | #define MWIFIEX_MAX_PKTS_TXQ 16 | ||
63 | |||
61 | #define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT (5 * HZ) | 64 | #define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT (5 * HZ) |
62 | 65 | ||
63 | #define MWIFIEX_TIMER_10S 10000 | 66 | #define MWIFIEX_TIMER_10S 10000 |
@@ -118,6 +121,7 @@ enum { | |||
118 | 121 | ||
119 | #define MWIFIEX_TYPE_CMD 1 | 122 | #define MWIFIEX_TYPE_CMD 1 |
120 | #define MWIFIEX_TYPE_DATA 0 | 123 | #define MWIFIEX_TYPE_DATA 0 |
124 | #define MWIFIEX_TYPE_AGGR_DATA 10 | ||
121 | #define MWIFIEX_TYPE_EVENT 3 | 125 | #define MWIFIEX_TYPE_EVENT 3 |
122 | 126 | ||
123 | #define MAX_BITMAP_RATES_SIZE 18 | 127 | #define MAX_BITMAP_RATES_SIZE 18 |
@@ -210,6 +214,12 @@ struct mwifiex_tx_aggr { | |||
210 | u8 amsdu; | 214 | u8 amsdu; |
211 | }; | 215 | }; |
212 | 216 | ||
217 | enum mwifiex_ba_status { | ||
218 | BA_SETUP_NONE = 0, | ||
219 | BA_SETUP_INPROGRESS, | ||
220 | BA_SETUP_COMPLETE | ||
221 | }; | ||
222 | |||
213 | struct mwifiex_ra_list_tbl { | 223 | struct mwifiex_ra_list_tbl { |
214 | struct list_head list; | 224 | struct list_head list; |
215 | struct sk_buff_head skb_head; | 225 | struct sk_buff_head skb_head; |
@@ -218,6 +228,8 @@ struct mwifiex_ra_list_tbl { | |||
218 | u16 max_amsdu; | 228 | u16 max_amsdu; |
219 | u16 ba_pkt_count; | 229 | u16 ba_pkt_count; |
220 | u8 ba_packet_thr; | 230 | u8 ba_packet_thr; |
231 | enum mwifiex_ba_status ba_status; | ||
232 | u8 amsdu_in_ampdu; | ||
221 | u16 total_pkt_count; | 233 | u16 total_pkt_count; |
222 | bool tdls_link; | 234 | bool tdls_link; |
223 | }; | 235 | }; |
@@ -601,11 +613,6 @@ struct mwifiex_private { | |||
601 | struct mwifiex_11h_intf_state state_11h; | 613 | struct mwifiex_11h_intf_state state_11h; |
602 | }; | 614 | }; |
603 | 615 | ||
604 | enum mwifiex_ba_status { | ||
605 | BA_SETUP_NONE = 0, | ||
606 | BA_SETUP_INPROGRESS, | ||
607 | BA_SETUP_COMPLETE | ||
608 | }; | ||
609 | 616 | ||
610 | struct mwifiex_tx_ba_stream_tbl { | 617 | struct mwifiex_tx_ba_stream_tbl { |
611 | struct list_head list; | 618 | struct list_head list; |
@@ -738,6 +745,7 @@ struct mwifiex_if_ops { | |||
738 | int (*clean_pcie_ring) (struct mwifiex_adapter *adapter); | 745 | int (*clean_pcie_ring) (struct mwifiex_adapter *adapter); |
739 | void (*iface_work)(struct work_struct *work); | 746 | void (*iface_work)(struct work_struct *work); |
740 | void (*submit_rem_rx_urbs)(struct mwifiex_adapter *adapter); | 747 | void (*submit_rem_rx_urbs)(struct mwifiex_adapter *adapter); |
748 | void (*deaggr_pkt)(struct mwifiex_adapter *, struct sk_buff *); | ||
741 | }; | 749 | }; |
742 | 750 | ||
743 | struct mwifiex_adapter { | 751 | struct mwifiex_adapter { |
@@ -771,6 +779,7 @@ struct mwifiex_adapter { | |||
771 | bool rx_processing; | 779 | bool rx_processing; |
772 | bool delay_main_work; | 780 | bool delay_main_work; |
773 | bool rx_locked; | 781 | bool rx_locked; |
782 | bool main_locked; | ||
774 | struct mwifiex_bss_prio_tbl bss_prio_tbl[MWIFIEX_MAX_BSS_NUM]; | 783 | struct mwifiex_bss_prio_tbl bss_prio_tbl[MWIFIEX_MAX_BSS_NUM]; |
775 | /* spin lock for init/shutdown */ | 784 | /* spin lock for init/shutdown */ |
776 | spinlock_t mwifiex_lock; | 785 | spinlock_t mwifiex_lock; |
@@ -780,6 +789,8 @@ struct mwifiex_adapter { | |||
780 | u8 more_task_flag; | 789 | u8 more_task_flag; |
781 | u16 tx_buf_size; | 790 | u16 tx_buf_size; |
782 | u16 curr_tx_buf_size; | 791 | u16 curr_tx_buf_size; |
792 | bool sdio_rx_aggr_enable; | ||
793 | u16 sdio_rx_block_size; | ||
783 | u32 ioport; | 794 | u32 ioport; |
784 | enum MWIFIEX_HARDWARE_STATUS hw_status; | 795 | enum MWIFIEX_HARDWARE_STATUS hw_status; |
785 | u16 number_of_antenna; | 796 | u16 number_of_antenna; |
@@ -814,6 +825,8 @@ struct mwifiex_adapter { | |||
814 | spinlock_t scan_pending_q_lock; | 825 | spinlock_t scan_pending_q_lock; |
815 | /* spin lock for RX processing routine */ | 826 | /* spin lock for RX processing routine */ |
816 | spinlock_t rx_proc_lock; | 827 | spinlock_t rx_proc_lock; |
828 | struct sk_buff_head tx_data_q; | ||
829 | atomic_t tx_queued; | ||
817 | u32 scan_processing; | 830 | u32 scan_processing; |
818 | u16 region_code; | 831 | u16 region_code; |
819 | struct mwifiex_802_11d_domain_reg domain_reg; | 832 | struct mwifiex_802_11d_domain_reg domain_reg; |
@@ -885,8 +898,6 @@ struct mwifiex_adapter { | |||
885 | bool ext_scan; | 898 | bool ext_scan; |
886 | u8 fw_api_ver; | 899 | u8 fw_api_ver; |
887 | u8 key_api_major_ver, key_api_minor_ver; | 900 | u8 key_api_major_ver, key_api_minor_ver; |
888 | struct work_struct iface_work; | ||
889 | unsigned long iface_work_flags; | ||
890 | struct memory_type_mapping *mem_type_mapping_tbl; | 901 | struct memory_type_mapping *mem_type_mapping_tbl; |
891 | u8 num_mem_types; | 902 | u8 num_mem_types; |
892 | u8 curr_mem_idx; | 903 | u8 curr_mem_idx; |
@@ -900,6 +911,8 @@ struct mwifiex_adapter { | |||
900 | bool auto_tdls; | 911 | bool auto_tdls; |
901 | }; | 912 | }; |
902 | 913 | ||
914 | void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter); | ||
915 | |||
903 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); | 916 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); |
904 | 917 | ||
905 | void mwifiex_set_trans_start(struct net_device *dev); | 918 | void mwifiex_set_trans_start(struct net_device *dev); |
@@ -1422,7 +1435,8 @@ u8 mwifiex_adjust_data_rate(struct mwifiex_private *priv, | |||
1422 | u8 rx_rate, u8 ht_info); | 1435 | u8 rx_rate, u8 ht_info); |
1423 | 1436 | ||
1424 | void mwifiex_dump_drv_info(struct mwifiex_adapter *adapter); | 1437 | void mwifiex_dump_drv_info(struct mwifiex_adapter *adapter); |
1425 | void *mwifiex_alloc_rx_buf(int rx_len, gfp_t flags); | 1438 | void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags); |
1439 | void mwifiex_queue_main_work(struct mwifiex_adapter *adapter); | ||
1426 | 1440 | ||
1427 | #ifdef CONFIG_DEBUG_FS | 1441 | #ifdef CONFIG_DEBUG_FS |
1428 | void mwifiex_debugfs_init(void); | 1442 | void mwifiex_debugfs_init(void); |
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 4b463c3b9906..bcc7751d883c 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c | |||
@@ -234,8 +234,6 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev) | |||
234 | if (!adapter || !adapter->priv_num) | 234 | if (!adapter || !adapter->priv_num) |
235 | return; | 235 | return; |
236 | 236 | ||
237 | cancel_work_sync(&adapter->iface_work); | ||
238 | |||
239 | if (user_rmmod) { | 237 | if (user_rmmod) { |
240 | #ifdef CONFIG_PM_SLEEP | 238 | #ifdef CONFIG_PM_SLEEP |
241 | if (adapter->is_suspended) | 239 | if (adapter->is_suspended) |
@@ -498,8 +496,8 @@ static int mwifiex_init_rxq_ring(struct mwifiex_adapter *adapter) | |||
498 | 496 | ||
499 | for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { | 497 | for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { |
500 | /* Allocate skb here so that firmware can DMA data from it */ | 498 | /* Allocate skb here so that firmware can DMA data from it */ |
501 | skb = mwifiex_alloc_rx_buf(MWIFIEX_RX_DATA_BUF_SIZE, | 499 | skb = mwifiex_alloc_dma_align_buf(MWIFIEX_RX_DATA_BUF_SIZE, |
502 | GFP_KERNEL | GFP_DMA); | 500 | GFP_KERNEL | GFP_DMA); |
503 | if (!skb) { | 501 | if (!skb) { |
504 | dev_err(adapter->dev, | 502 | dev_err(adapter->dev, |
505 | "Unable to allocate skb for RX ring.\n"); | 503 | "Unable to allocate skb for RX ring.\n"); |
@@ -1298,8 +1296,8 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter) | |||
1298 | } | 1296 | } |
1299 | } | 1297 | } |
1300 | 1298 | ||
1301 | skb_tmp = mwifiex_alloc_rx_buf(MWIFIEX_RX_DATA_BUF_SIZE, | 1299 | skb_tmp = mwifiex_alloc_dma_align_buf(MWIFIEX_RX_DATA_BUF_SIZE, |
1302 | GFP_KERNEL | GFP_DMA); | 1300 | GFP_KERNEL | GFP_DMA); |
1303 | if (!skb_tmp) { | 1301 | if (!skb_tmp) { |
1304 | dev_err(adapter->dev, | 1302 | dev_err(adapter->dev, |
1305 | "Unable to allocate skb.\n"); | 1303 | "Unable to allocate skb.\n"); |
@@ -2101,7 +2099,7 @@ static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context) | |||
2101 | goto exit; | 2099 | goto exit; |
2102 | 2100 | ||
2103 | mwifiex_interrupt_status(adapter); | 2101 | mwifiex_interrupt_status(adapter); |
2104 | queue_work(adapter->workqueue, &adapter->main_work); | 2102 | mwifiex_queue_main_work(adapter); |
2105 | 2103 | ||
2106 | exit: | 2104 | exit: |
2107 | return IRQ_HANDLED; | 2105 | return IRQ_HANDLED; |
@@ -2373,25 +2371,26 @@ done: | |||
2373 | adapter->curr_mem_idx = 0; | 2371 | adapter->curr_mem_idx = 0; |
2374 | } | 2372 | } |
2375 | 2373 | ||
2374 | static unsigned long iface_work_flags; | ||
2375 | static struct mwifiex_adapter *save_adapter; | ||
2376 | static void mwifiex_pcie_work(struct work_struct *work) | 2376 | static void mwifiex_pcie_work(struct work_struct *work) |
2377 | { | 2377 | { |
2378 | struct mwifiex_adapter *adapter = | ||
2379 | container_of(work, struct mwifiex_adapter, iface_work); | ||
2380 | |||
2381 | if (test_and_clear_bit(MWIFIEX_IFACE_WORK_FW_DUMP, | 2378 | if (test_and_clear_bit(MWIFIEX_IFACE_WORK_FW_DUMP, |
2382 | &adapter->iface_work_flags)) | 2379 | &iface_work_flags)) |
2383 | mwifiex_pcie_fw_dump_work(adapter); | 2380 | mwifiex_pcie_fw_dump_work(save_adapter); |
2384 | } | 2381 | } |
2385 | 2382 | ||
2383 | static DECLARE_WORK(pcie_work, mwifiex_pcie_work); | ||
2386 | /* This function dumps FW information */ | 2384 | /* This function dumps FW information */ |
2387 | static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) | 2385 | static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) |
2388 | { | 2386 | { |
2389 | if (test_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &adapter->iface_work_flags)) | 2387 | save_adapter = adapter; |
2388 | if (test_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &iface_work_flags)) | ||
2390 | return; | 2389 | return; |
2391 | 2390 | ||
2392 | set_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &adapter->iface_work_flags); | 2391 | set_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &iface_work_flags); |
2393 | 2392 | ||
2394 | schedule_work(&adapter->iface_work); | 2393 | schedule_work(&pcie_work); |
2395 | } | 2394 | } |
2396 | 2395 | ||
2397 | /* | 2396 | /* |
@@ -2619,7 +2618,6 @@ static struct mwifiex_if_ops pcie_ops = { | |||
2619 | .init_fw_port = mwifiex_pcie_init_fw_port, | 2618 | .init_fw_port = mwifiex_pcie_init_fw_port, |
2620 | .clean_pcie_ring = mwifiex_clean_pcie_ring_buf, | 2619 | .clean_pcie_ring = mwifiex_clean_pcie_ring_buf, |
2621 | .fw_dump = mwifiex_pcie_fw_dump, | 2620 | .fw_dump = mwifiex_pcie_fw_dump, |
2622 | .iface_work = mwifiex_pcie_work, | ||
2623 | }; | 2621 | }; |
2624 | 2622 | ||
2625 | /* | 2623 | /* |
@@ -2665,6 +2663,7 @@ static void mwifiex_pcie_cleanup_module(void) | |||
2665 | /* Set the flag as user is removing this module. */ | 2663 | /* Set the flag as user is removing this module. */ |
2666 | user_rmmod = 1; | 2664 | user_rmmod = 1; |
2667 | 2665 | ||
2666 | cancel_work_sync(&pcie_work); | ||
2668 | pci_unregister_driver(&mwifiex_pcie); | 2667 | pci_unregister_driver(&mwifiex_pcie); |
2669 | } | 2668 | } |
2670 | 2669 | ||
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 57d85ab442bf..d10320f89bc1 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c | |||
@@ -47,6 +47,7 @@ | |||
47 | static u8 user_rmmod; | 47 | static u8 user_rmmod; |
48 | 48 | ||
49 | static struct mwifiex_if_ops sdio_ops; | 49 | static struct mwifiex_if_ops sdio_ops; |
50 | static unsigned long iface_work_flags; | ||
50 | 51 | ||
51 | static struct semaphore add_remove_card_sem; | 52 | static struct semaphore add_remove_card_sem; |
52 | 53 | ||
@@ -200,8 +201,6 @@ mwifiex_sdio_remove(struct sdio_func *func) | |||
200 | if (!adapter || !adapter->priv_num) | 201 | if (!adapter || !adapter->priv_num) |
201 | return; | 202 | return; |
202 | 203 | ||
203 | cancel_work_sync(&adapter->iface_work); | ||
204 | |||
205 | if (user_rmmod) { | 204 | if (user_rmmod) { |
206 | if (adapter->is_suspended) | 205 | if (adapter->is_suspended) |
207 | mwifiex_sdio_resume(adapter->dev); | 206 | mwifiex_sdio_resume(adapter->dev); |
@@ -1043,6 +1042,59 @@ static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, | |||
1043 | } | 1042 | } |
1044 | 1043 | ||
1045 | /* | 1044 | /* |
1045 | * This function decode sdio aggreation pkt. | ||
1046 | * | ||
1047 | * Based on the the data block size and pkt_len, | ||
1048 | * skb data will be decoded to few packets. | ||
1049 | */ | ||
1050 | static void mwifiex_deaggr_sdio_pkt(struct mwifiex_adapter *adapter, | ||
1051 | struct sk_buff *skb) | ||
1052 | { | ||
1053 | u32 total_pkt_len, pkt_len; | ||
1054 | struct sk_buff *skb_deaggr; | ||
1055 | u32 pkt_type; | ||
1056 | u16 blk_size; | ||
1057 | u8 blk_num; | ||
1058 | u8 *data; | ||
1059 | |||
1060 | data = skb->data; | ||
1061 | total_pkt_len = skb->len; | ||
1062 | |||
1063 | while (total_pkt_len >= (SDIO_HEADER_OFFSET + INTF_HEADER_LEN)) { | ||
1064 | if (total_pkt_len < adapter->sdio_rx_block_size) | ||
1065 | break; | ||
1066 | blk_num = *(data + BLOCK_NUMBER_OFFSET); | ||
1067 | blk_size = adapter->sdio_rx_block_size * blk_num; | ||
1068 | if (blk_size > total_pkt_len) { | ||
1069 | dev_err(adapter->dev, "%s: error in pkt,\t" | ||
1070 | "blk_num=%d, blk_size=%d, total_pkt_len=%d\n", | ||
1071 | __func__, blk_num, blk_size, total_pkt_len); | ||
1072 | break; | ||
1073 | } | ||
1074 | pkt_len = le16_to_cpu(*(__le16 *)(data + SDIO_HEADER_OFFSET)); | ||
1075 | pkt_type = le16_to_cpu(*(__le16 *)(data + SDIO_HEADER_OFFSET + | ||
1076 | 2)); | ||
1077 | if ((pkt_len + SDIO_HEADER_OFFSET) > blk_size) { | ||
1078 | dev_err(adapter->dev, "%s: error in pkt,\t" | ||
1079 | "pkt_len=%d, blk_size=%d\n", | ||
1080 | __func__, pkt_len, blk_size); | ||
1081 | break; | ||
1082 | } | ||
1083 | skb_deaggr = mwifiex_alloc_dma_align_buf(pkt_len, | ||
1084 | GFP_KERNEL | GFP_DMA); | ||
1085 | if (!skb_deaggr) | ||
1086 | break; | ||
1087 | skb_put(skb_deaggr, pkt_len); | ||
1088 | memcpy(skb_deaggr->data, data + SDIO_HEADER_OFFSET, pkt_len); | ||
1089 | skb_pull(skb_deaggr, INTF_HEADER_LEN); | ||
1090 | |||
1091 | mwifiex_handle_rx_packet(adapter, skb_deaggr); | ||
1092 | data += blk_size; | ||
1093 | total_pkt_len -= blk_size; | ||
1094 | } | ||
1095 | } | ||
1096 | |||
1097 | /* | ||
1046 | * This function decodes a received packet. | 1098 | * This function decodes a received packet. |
1047 | * | 1099 | * |
1048 | * Based on the type, the packet is treated as either a data, or | 1100 | * Based on the type, the packet is treated as either a data, or |
@@ -1055,11 +1107,28 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter, | |||
1055 | u8 *cmd_buf; | 1107 | u8 *cmd_buf; |
1056 | __le16 *curr_ptr = (__le16 *)skb->data; | 1108 | __le16 *curr_ptr = (__le16 *)skb->data; |
1057 | u16 pkt_len = le16_to_cpu(*curr_ptr); | 1109 | u16 pkt_len = le16_to_cpu(*curr_ptr); |
1110 | struct mwifiex_rxinfo *rx_info; | ||
1058 | 1111 | ||
1059 | skb_trim(skb, pkt_len); | 1112 | if (upld_typ != MWIFIEX_TYPE_AGGR_DATA) { |
1060 | skb_pull(skb, INTF_HEADER_LEN); | 1113 | skb_trim(skb, pkt_len); |
1114 | skb_pull(skb, INTF_HEADER_LEN); | ||
1115 | } | ||
1061 | 1116 | ||
1062 | switch (upld_typ) { | 1117 | switch (upld_typ) { |
1118 | case MWIFIEX_TYPE_AGGR_DATA: | ||
1119 | dev_dbg(adapter->dev, "info: --- Rx: Aggr Data packet ---\n"); | ||
1120 | rx_info = MWIFIEX_SKB_RXCB(skb); | ||
1121 | rx_info->buf_type = MWIFIEX_TYPE_AGGR_DATA; | ||
1122 | if (adapter->rx_work_enabled) { | ||
1123 | skb_queue_tail(&adapter->rx_data_q, skb); | ||
1124 | atomic_inc(&adapter->rx_pending); | ||
1125 | adapter->data_received = true; | ||
1126 | } else { | ||
1127 | mwifiex_deaggr_sdio_pkt(adapter, skb); | ||
1128 | dev_kfree_skb_any(skb); | ||
1129 | } | ||
1130 | break; | ||
1131 | |||
1063 | case MWIFIEX_TYPE_DATA: | 1132 | case MWIFIEX_TYPE_DATA: |
1064 | dev_dbg(adapter->dev, "info: --- Rx: Data packet ---\n"); | 1133 | dev_dbg(adapter->dev, "info: --- Rx: Data packet ---\n"); |
1065 | if (adapter->rx_work_enabled) { | 1134 | if (adapter->rx_work_enabled) { |
@@ -1127,17 +1196,17 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter, | |||
1127 | * provided there is space left, processed and finally uploaded. | 1196 | * provided there is space left, processed and finally uploaded. |
1128 | */ | 1197 | */ |
1129 | static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, | 1198 | static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, |
1130 | struct sk_buff *skb, u8 port) | 1199 | u16 rx_len, u8 port) |
1131 | { | 1200 | { |
1132 | struct sdio_mmc_card *card = adapter->card; | 1201 | struct sdio_mmc_card *card = adapter->card; |
1133 | s32 f_do_rx_aggr = 0; | 1202 | s32 f_do_rx_aggr = 0; |
1134 | s32 f_do_rx_cur = 0; | 1203 | s32 f_do_rx_cur = 0; |
1135 | s32 f_aggr_cur = 0; | 1204 | s32 f_aggr_cur = 0; |
1205 | s32 f_post_aggr_cur = 0; | ||
1136 | struct sk_buff *skb_deaggr; | 1206 | struct sk_buff *skb_deaggr; |
1137 | u32 pind; | 1207 | struct sk_buff *skb = NULL; |
1138 | u32 pkt_len, pkt_type, mport; | 1208 | u32 pkt_len, pkt_type, mport, pind; |
1139 | u8 *curr_ptr; | 1209 | u8 *curr_ptr; |
1140 | u32 rx_len = skb->len; | ||
1141 | 1210 | ||
1142 | if ((card->has_control_mask) && (port == CTRL_PORT)) { | 1211 | if ((card->has_control_mask) && (port == CTRL_PORT)) { |
1143 | /* Read the command Resp without aggr */ | 1212 | /* Read the command Resp without aggr */ |
@@ -1164,12 +1233,12 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, | |||
1164 | dev_dbg(adapter->dev, "info: %s: not last packet\n", __func__); | 1233 | dev_dbg(adapter->dev, "info: %s: not last packet\n", __func__); |
1165 | 1234 | ||
1166 | if (MP_RX_AGGR_IN_PROGRESS(card)) { | 1235 | if (MP_RX_AGGR_IN_PROGRESS(card)) { |
1167 | if (MP_RX_AGGR_BUF_HAS_ROOM(card, skb->len)) { | 1236 | if (MP_RX_AGGR_BUF_HAS_ROOM(card, rx_len)) { |
1168 | f_aggr_cur = 1; | 1237 | f_aggr_cur = 1; |
1169 | } else { | 1238 | } else { |
1170 | /* No room in Aggr buf, do rx aggr now */ | 1239 | /* No room in Aggr buf, do rx aggr now */ |
1171 | f_do_rx_aggr = 1; | 1240 | f_do_rx_aggr = 1; |
1172 | f_do_rx_cur = 1; | 1241 | f_post_aggr_cur = 1; |
1173 | } | 1242 | } |
1174 | } else { | 1243 | } else { |
1175 | /* Rx aggr not in progress */ | 1244 | /* Rx aggr not in progress */ |
@@ -1182,7 +1251,7 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, | |||
1182 | 1251 | ||
1183 | if (MP_RX_AGGR_IN_PROGRESS(card)) { | 1252 | if (MP_RX_AGGR_IN_PROGRESS(card)) { |
1184 | f_do_rx_aggr = 1; | 1253 | f_do_rx_aggr = 1; |
1185 | if (MP_RX_AGGR_BUF_HAS_ROOM(card, skb->len)) | 1254 | if (MP_RX_AGGR_BUF_HAS_ROOM(card, rx_len)) |
1186 | f_aggr_cur = 1; | 1255 | f_aggr_cur = 1; |
1187 | else | 1256 | else |
1188 | /* No room in Aggr buf, do rx aggr now */ | 1257 | /* No room in Aggr buf, do rx aggr now */ |
@@ -1195,7 +1264,7 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, | |||
1195 | if (f_aggr_cur) { | 1264 | if (f_aggr_cur) { |
1196 | dev_dbg(adapter->dev, "info: current packet aggregation\n"); | 1265 | dev_dbg(adapter->dev, "info: current packet aggregation\n"); |
1197 | /* Curr pkt can be aggregated */ | 1266 | /* Curr pkt can be aggregated */ |
1198 | mp_rx_aggr_setup(card, skb, port); | 1267 | mp_rx_aggr_setup(card, rx_len, port); |
1199 | 1268 | ||
1200 | if (MP_RX_AGGR_PKT_LIMIT_REACHED(card) || | 1269 | if (MP_RX_AGGR_PKT_LIMIT_REACHED(card) || |
1201 | mp_rx_aggr_port_limit_reached(card)) { | 1270 | mp_rx_aggr_port_limit_reached(card)) { |
@@ -1238,16 +1307,29 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, | |||
1238 | curr_ptr = card->mpa_rx.buf; | 1307 | curr_ptr = card->mpa_rx.buf; |
1239 | 1308 | ||
1240 | for (pind = 0; pind < card->mpa_rx.pkt_cnt; pind++) { | 1309 | for (pind = 0; pind < card->mpa_rx.pkt_cnt; pind++) { |
1310 | u32 *len_arr = card->mpa_rx.len_arr; | ||
1241 | 1311 | ||
1242 | /* get curr PKT len & type */ | 1312 | /* get curr PKT len & type */ |
1243 | pkt_len = le16_to_cpu(*(__le16 *) &curr_ptr[0]); | 1313 | pkt_len = le16_to_cpu(*(__le16 *) &curr_ptr[0]); |
1244 | pkt_type = le16_to_cpu(*(__le16 *) &curr_ptr[2]); | 1314 | pkt_type = le16_to_cpu(*(__le16 *) &curr_ptr[2]); |
1245 | 1315 | ||
1246 | /* copy pkt to deaggr buf */ | 1316 | /* copy pkt to deaggr buf */ |
1247 | skb_deaggr = card->mpa_rx.skb_arr[pind]; | 1317 | skb_deaggr = mwifiex_alloc_dma_align_buf(len_arr[pind], |
1318 | GFP_KERNEL | | ||
1319 | GFP_DMA); | ||
1320 | if (!skb_deaggr) { | ||
1321 | dev_err(adapter->dev, "skb allocation failure drop pkt len=%d type=%d\n", | ||
1322 | pkt_len, pkt_type); | ||
1323 | curr_ptr += len_arr[pind]; | ||
1324 | continue; | ||
1325 | } | ||
1248 | 1326 | ||
1249 | if ((pkt_type == MWIFIEX_TYPE_DATA) && (pkt_len <= | 1327 | skb_put(skb_deaggr, len_arr[pind]); |
1250 | card->mpa_rx.len_arr[pind])) { | 1328 | |
1329 | if ((pkt_type == MWIFIEX_TYPE_DATA || | ||
1330 | (pkt_type == MWIFIEX_TYPE_AGGR_DATA && | ||
1331 | adapter->sdio_rx_aggr_enable)) && | ||
1332 | (pkt_len <= len_arr[pind])) { | ||
1251 | 1333 | ||
1252 | memcpy(skb_deaggr->data, curr_ptr, pkt_len); | 1334 | memcpy(skb_deaggr->data, curr_ptr, pkt_len); |
1253 | 1335 | ||
@@ -1257,13 +1339,15 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, | |||
1257 | mwifiex_decode_rx_packet(adapter, skb_deaggr, | 1339 | mwifiex_decode_rx_packet(adapter, skb_deaggr, |
1258 | pkt_type); | 1340 | pkt_type); |
1259 | } else { | 1341 | } else { |
1260 | dev_err(adapter->dev, "wrong aggr pkt:" | 1342 | dev_err(adapter->dev, " drop wrong aggr pkt:\t" |
1261 | " type=%d len=%d max_len=%d\n", | 1343 | "sdio_single_port_rx_aggr=%d\t" |
1344 | "type=%d len=%d max_len=%d\n", | ||
1345 | adapter->sdio_rx_aggr_enable, | ||
1262 | pkt_type, pkt_len, | 1346 | pkt_type, pkt_len, |
1263 | card->mpa_rx.len_arr[pind]); | 1347 | len_arr[pind]); |
1264 | dev_kfree_skb_any(skb_deaggr); | 1348 | dev_kfree_skb_any(skb_deaggr); |
1265 | } | 1349 | } |
1266 | curr_ptr += card->mpa_rx.len_arr[pind]; | 1350 | curr_ptr += len_arr[pind]; |
1267 | } | 1351 | } |
1268 | MP_RX_AGGR_BUF_RESET(card); | 1352 | MP_RX_AGGR_BUF_RESET(card); |
1269 | } | 1353 | } |
@@ -1273,28 +1357,46 @@ rx_curr_single: | |||
1273 | dev_dbg(adapter->dev, "info: RX: port: %d, rx_len: %d\n", | 1357 | dev_dbg(adapter->dev, "info: RX: port: %d, rx_len: %d\n", |
1274 | port, rx_len); | 1358 | port, rx_len); |
1275 | 1359 | ||
1360 | skb = mwifiex_alloc_dma_align_buf(rx_len, GFP_KERNEL | GFP_DMA); | ||
1361 | if (!skb) { | ||
1362 | dev_err(adapter->dev, "single skb allocated fail,\t" | ||
1363 | "drop pkt port=%d len=%d\n", port, rx_len); | ||
1364 | if (mwifiex_sdio_card_to_host(adapter, &pkt_type, | ||
1365 | card->mpa_rx.buf, rx_len, | ||
1366 | adapter->ioport + port)) | ||
1367 | goto error; | ||
1368 | return 0; | ||
1369 | } | ||
1370 | |||
1371 | skb_put(skb, rx_len); | ||
1372 | |||
1276 | if (mwifiex_sdio_card_to_host(adapter, &pkt_type, | 1373 | if (mwifiex_sdio_card_to_host(adapter, &pkt_type, |
1277 | skb->data, skb->len, | 1374 | skb->data, skb->len, |
1278 | adapter->ioport + port)) | 1375 | adapter->ioport + port)) |
1279 | goto error; | 1376 | goto error; |
1377 | if (!adapter->sdio_rx_aggr_enable && | ||
1378 | pkt_type == MWIFIEX_TYPE_AGGR_DATA) { | ||
1379 | dev_err(adapter->dev, "drop wrong pkt type %d\t" | ||
1380 | "current SDIO RX Aggr not enabled\n", | ||
1381 | pkt_type); | ||
1382 | dev_kfree_skb_any(skb); | ||
1383 | return 0; | ||
1384 | } | ||
1280 | 1385 | ||
1281 | mwifiex_decode_rx_packet(adapter, skb, pkt_type); | 1386 | mwifiex_decode_rx_packet(adapter, skb, pkt_type); |
1282 | } | 1387 | } |
1388 | if (f_post_aggr_cur) { | ||
1389 | dev_dbg(adapter->dev, "info: current packet aggregation\n"); | ||
1390 | /* Curr pkt can be aggregated */ | ||
1391 | mp_rx_aggr_setup(card, rx_len, port); | ||
1392 | } | ||
1283 | 1393 | ||
1284 | return 0; | 1394 | return 0; |
1285 | |||
1286 | error: | 1395 | error: |
1287 | if (MP_RX_AGGR_IN_PROGRESS(card)) { | 1396 | if (MP_RX_AGGR_IN_PROGRESS(card)) |
1288 | /* Multiport-aggregation transfer failed - cleanup */ | ||
1289 | for (pind = 0; pind < card->mpa_rx.pkt_cnt; pind++) { | ||
1290 | /* copy pkt to deaggr buf */ | ||
1291 | skb_deaggr = card->mpa_rx.skb_arr[pind]; | ||
1292 | dev_kfree_skb_any(skb_deaggr); | ||
1293 | } | ||
1294 | MP_RX_AGGR_BUF_RESET(card); | 1397 | MP_RX_AGGR_BUF_RESET(card); |
1295 | } | ||
1296 | 1398 | ||
1297 | if (f_do_rx_cur) | 1399 | if (f_do_rx_cur && skb) |
1298 | /* Single transfer pending. Free curr buff also */ | 1400 | /* Single transfer pending. Free curr buff also */ |
1299 | dev_kfree_skb_any(skb); | 1401 | dev_kfree_skb_any(skb); |
1300 | 1402 | ||
@@ -1356,8 +1458,9 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) | |||
1356 | MWIFIEX_RX_DATA_BUF_SIZE) | 1458 | MWIFIEX_RX_DATA_BUF_SIZE) |
1357 | return -1; | 1459 | return -1; |
1358 | rx_len = (u16) (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE); | 1460 | rx_len = (u16) (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE); |
1461 | dev_dbg(adapter->dev, "info: rx_len = %d\n", rx_len); | ||
1359 | 1462 | ||
1360 | skb = mwifiex_alloc_rx_buf(rx_len, GFP_KERNEL | GFP_DMA); | 1463 | skb = mwifiex_alloc_dma_align_buf(rx_len, GFP_KERNEL | GFP_DMA); |
1361 | if (!skb) | 1464 | if (!skb) |
1362 | return -1; | 1465 | return -1; |
1363 | 1466 | ||
@@ -1447,28 +1550,16 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) | |||
1447 | 1) / MWIFIEX_SDIO_BLOCK_SIZE; | 1550 | 1) / MWIFIEX_SDIO_BLOCK_SIZE; |
1448 | if (rx_len <= INTF_HEADER_LEN || | 1551 | if (rx_len <= INTF_HEADER_LEN || |
1449 | (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) > | 1552 | (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) > |
1450 | MWIFIEX_RX_DATA_BUF_SIZE) { | 1553 | card->mpa_rx.buf_size) { |
1451 | dev_err(adapter->dev, "invalid rx_len=%d\n", | 1554 | dev_err(adapter->dev, "invalid rx_len=%d\n", |
1452 | rx_len); | 1555 | rx_len); |
1453 | return -1; | 1556 | return -1; |
1454 | } | 1557 | } |
1455 | rx_len = (u16) (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE); | ||
1456 | |||
1457 | skb = mwifiex_alloc_rx_buf(rx_len, | ||
1458 | GFP_KERNEL | GFP_DMA); | ||
1459 | |||
1460 | if (!skb) { | ||
1461 | dev_err(adapter->dev, "%s: failed to alloc skb", | ||
1462 | __func__); | ||
1463 | return -1; | ||
1464 | } | ||
1465 | 1558 | ||
1466 | skb_put(skb, rx_len); | 1559 | rx_len = (u16) (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE); |
1467 | 1560 | dev_dbg(adapter->dev, "info: rx_len = %d\n", rx_len); | |
1468 | dev_dbg(adapter->dev, "info: rx_len = %d skb->len = %d\n", | ||
1469 | rx_len, skb->len); | ||
1470 | 1561 | ||
1471 | if (mwifiex_sdio_card_to_host_mp_aggr(adapter, skb, | 1562 | if (mwifiex_sdio_card_to_host_mp_aggr(adapter, rx_len, |
1472 | port)) { | 1563 | port)) { |
1473 | dev_err(adapter->dev, "card_to_host_mpa failed:" | 1564 | dev_err(adapter->dev, "card_to_host_mpa failed:" |
1474 | " int status=%#x\n", sdio_ireg); | 1565 | " int status=%#x\n", sdio_ireg); |
@@ -1736,6 +1827,7 @@ static int mwifiex_alloc_sdio_mpa_buffers(struct mwifiex_adapter *adapter, | |||
1736 | u32 mpa_tx_buf_size, u32 mpa_rx_buf_size) | 1827 | u32 mpa_tx_buf_size, u32 mpa_rx_buf_size) |
1737 | { | 1828 | { |
1738 | struct sdio_mmc_card *card = adapter->card; | 1829 | struct sdio_mmc_card *card = adapter->card; |
1830 | u32 rx_buf_size; | ||
1739 | int ret = 0; | 1831 | int ret = 0; |
1740 | 1832 | ||
1741 | card->mpa_tx.buf = kzalloc(mpa_tx_buf_size, GFP_KERNEL); | 1833 | card->mpa_tx.buf = kzalloc(mpa_tx_buf_size, GFP_KERNEL); |
@@ -1746,13 +1838,15 @@ static int mwifiex_alloc_sdio_mpa_buffers(struct mwifiex_adapter *adapter, | |||
1746 | 1838 | ||
1747 | card->mpa_tx.buf_size = mpa_tx_buf_size; | 1839 | card->mpa_tx.buf_size = mpa_tx_buf_size; |
1748 | 1840 | ||
1749 | card->mpa_rx.buf = kzalloc(mpa_rx_buf_size, GFP_KERNEL); | 1841 | rx_buf_size = max_t(u32, mpa_rx_buf_size, |
1842 | (u32)SDIO_MAX_AGGR_BUF_SIZE); | ||
1843 | card->mpa_rx.buf = kzalloc(rx_buf_size, GFP_KERNEL); | ||
1750 | if (!card->mpa_rx.buf) { | 1844 | if (!card->mpa_rx.buf) { |
1751 | ret = -1; | 1845 | ret = -1; |
1752 | goto error; | 1846 | goto error; |
1753 | } | 1847 | } |
1754 | 1848 | ||
1755 | card->mpa_rx.buf_size = mpa_rx_buf_size; | 1849 | card->mpa_rx.buf_size = rx_buf_size; |
1756 | 1850 | ||
1757 | error: | 1851 | error: |
1758 | if (ret) { | 1852 | if (ret) { |
@@ -1951,6 +2045,7 @@ mwifiex_update_mp_end_port(struct mwifiex_adapter *adapter, u16 port) | |||
1951 | port, card->mp_data_port_mask); | 2045 | port, card->mp_data_port_mask); |
1952 | } | 2046 | } |
1953 | 2047 | ||
2048 | static struct mwifiex_adapter *save_adapter; | ||
1954 | static void mwifiex_sdio_card_reset_work(struct mwifiex_adapter *adapter) | 2049 | static void mwifiex_sdio_card_reset_work(struct mwifiex_adapter *adapter) |
1955 | { | 2050 | { |
1956 | struct sdio_mmc_card *card = adapter->card; | 2051 | struct sdio_mmc_card *card = adapter->card; |
@@ -2019,10 +2114,8 @@ rdwr_status mwifiex_sdio_rdwr_firmware(struct mwifiex_adapter *adapter, | |||
2019 | } | 2114 | } |
2020 | 2115 | ||
2021 | /* This function dump firmware memory to file */ | 2116 | /* This function dump firmware memory to file */ |
2022 | static void mwifiex_sdio_fw_dump_work(struct work_struct *work) | 2117 | static void mwifiex_sdio_fw_dump_work(struct mwifiex_adapter *adapter) |
2023 | { | 2118 | { |
2024 | struct mwifiex_adapter *adapter = | ||
2025 | container_of(work, struct mwifiex_adapter, iface_work); | ||
2026 | struct sdio_mmc_card *card = adapter->card; | 2119 | struct sdio_mmc_card *card = adapter->card; |
2027 | int ret = 0; | 2120 | int ret = 0; |
2028 | unsigned int reg, reg_start, reg_end; | 2121 | unsigned int reg, reg_start, reg_end; |
@@ -2144,36 +2237,36 @@ done: | |||
2144 | 2237 | ||
2145 | static void mwifiex_sdio_work(struct work_struct *work) | 2238 | static void mwifiex_sdio_work(struct work_struct *work) |
2146 | { | 2239 | { |
2147 | struct mwifiex_adapter *adapter = | ||
2148 | container_of(work, struct mwifiex_adapter, iface_work); | ||
2149 | |||
2150 | if (test_and_clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, | ||
2151 | &adapter->iface_work_flags)) | ||
2152 | mwifiex_sdio_card_reset_work(adapter); | ||
2153 | if (test_and_clear_bit(MWIFIEX_IFACE_WORK_FW_DUMP, | 2240 | if (test_and_clear_bit(MWIFIEX_IFACE_WORK_FW_DUMP, |
2154 | &adapter->iface_work_flags)) | 2241 | &iface_work_flags)) |
2155 | mwifiex_sdio_fw_dump_work(work); | 2242 | mwifiex_sdio_fw_dump_work(save_adapter); |
2243 | if (test_and_clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, | ||
2244 | &iface_work_flags)) | ||
2245 | mwifiex_sdio_card_reset_work(save_adapter); | ||
2156 | } | 2246 | } |
2157 | 2247 | ||
2248 | static DECLARE_WORK(sdio_work, mwifiex_sdio_work); | ||
2158 | /* This function resets the card */ | 2249 | /* This function resets the card */ |
2159 | static void mwifiex_sdio_card_reset(struct mwifiex_adapter *adapter) | 2250 | static void mwifiex_sdio_card_reset(struct mwifiex_adapter *adapter) |
2160 | { | 2251 | { |
2161 | if (test_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &adapter->iface_work_flags)) | 2252 | save_adapter = adapter; |
2253 | if (test_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &iface_work_flags)) | ||
2162 | return; | 2254 | return; |
2163 | 2255 | ||
2164 | set_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &adapter->iface_work_flags); | 2256 | set_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &iface_work_flags); |
2165 | 2257 | ||
2166 | schedule_work(&adapter->iface_work); | 2258 | schedule_work(&sdio_work); |
2167 | } | 2259 | } |
2168 | 2260 | ||
2169 | /* This function dumps FW information */ | 2261 | /* This function dumps FW information */ |
2170 | static void mwifiex_sdio_fw_dump(struct mwifiex_adapter *adapter) | 2262 | static void mwifiex_sdio_fw_dump(struct mwifiex_adapter *adapter) |
2171 | { | 2263 | { |
2172 | if (test_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &adapter->iface_work_flags)) | 2264 | save_adapter = adapter; |
2265 | if (test_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &iface_work_flags)) | ||
2173 | return; | 2266 | return; |
2174 | 2267 | ||
2175 | set_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &adapter->iface_work_flags); | 2268 | set_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &iface_work_flags); |
2176 | schedule_work(&adapter->iface_work); | 2269 | schedule_work(&sdio_work); |
2177 | } | 2270 | } |
2178 | 2271 | ||
2179 | /* Function to dump SDIO function registers and SDIO scratch registers in case | 2272 | /* Function to dump SDIO function registers and SDIO scratch registers in case |
@@ -2289,9 +2382,9 @@ static struct mwifiex_if_ops sdio_ops = { | |||
2289 | .cmdrsp_complete = mwifiex_sdio_cmdrsp_complete, | 2382 | .cmdrsp_complete = mwifiex_sdio_cmdrsp_complete, |
2290 | .event_complete = mwifiex_sdio_event_complete, | 2383 | .event_complete = mwifiex_sdio_event_complete, |
2291 | .card_reset = mwifiex_sdio_card_reset, | 2384 | .card_reset = mwifiex_sdio_card_reset, |
2292 | .iface_work = mwifiex_sdio_work, | ||
2293 | .fw_dump = mwifiex_sdio_fw_dump, | 2385 | .fw_dump = mwifiex_sdio_fw_dump, |
2294 | .reg_dump = mwifiex_sdio_reg_dump, | 2386 | .reg_dump = mwifiex_sdio_reg_dump, |
2387 | .deaggr_pkt = mwifiex_deaggr_sdio_pkt, | ||
2295 | }; | 2388 | }; |
2296 | 2389 | ||
2297 | /* | 2390 | /* |
@@ -2328,6 +2421,7 @@ mwifiex_sdio_cleanup_module(void) | |||
2328 | 2421 | ||
2329 | /* Set the flag as user is removing this module. */ | 2422 | /* Set the flag as user is removing this module. */ |
2330 | user_rmmod = 1; | 2423 | user_rmmod = 1; |
2424 | cancel_work_sync(&sdio_work); | ||
2331 | 2425 | ||
2332 | sdio_unregister_driver(&mwifiex_sdio); | 2426 | sdio_unregister_driver(&mwifiex_sdio); |
2333 | } | 2427 | } |
diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h index c636944c77bc..6f645cf47369 100644 --- a/drivers/net/wireless/mwifiex/sdio.h +++ b/drivers/net/wireless/mwifiex/sdio.h | |||
@@ -67,6 +67,8 @@ | |||
67 | 67 | ||
68 | #define MWIFIEX_MP_AGGR_BUF_SIZE_16K (16384) | 68 | #define MWIFIEX_MP_AGGR_BUF_SIZE_16K (16384) |
69 | #define MWIFIEX_MP_AGGR_BUF_SIZE_32K (32768) | 69 | #define MWIFIEX_MP_AGGR_BUF_SIZE_32K (32768) |
70 | /* we leave one block of 256 bytes for DMA alignment*/ | ||
71 | #define MWIFIEX_MP_AGGR_BUF_SIZE_MAX (65280) | ||
70 | 72 | ||
71 | /* Misc. Config Register : Auto Re-enable interrupts */ | 73 | /* Misc. Config Register : Auto Re-enable interrupts */ |
72 | #define AUTO_RE_ENABLE_INT BIT(4) | 74 | #define AUTO_RE_ENABLE_INT BIT(4) |
@@ -458,8 +460,8 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = { | |||
458 | .max_ports = 32, | 460 | .max_ports = 32, |
459 | .mp_agg_pkt_limit = 16, | 461 | .mp_agg_pkt_limit = 16, |
460 | .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K, | 462 | .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K, |
461 | .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, | 463 | .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX, |
462 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, | 464 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX, |
463 | .supports_sdio_new_mode = true, | 465 | .supports_sdio_new_mode = true, |
464 | .has_control_mask = false, | 466 | .has_control_mask = false, |
465 | .can_dump_fw = true, | 467 | .can_dump_fw = true, |
@@ -571,9 +573,9 @@ mp_tx_aggr_port_limit_reached(struct sdio_mmc_card *card) | |||
571 | 573 | ||
572 | /* Prepare to copy current packet from card to SDIO Rx aggregation buffer */ | 574 | /* Prepare to copy current packet from card to SDIO Rx aggregation buffer */ |
573 | static inline void mp_rx_aggr_setup(struct sdio_mmc_card *card, | 575 | static inline void mp_rx_aggr_setup(struct sdio_mmc_card *card, |
574 | struct sk_buff *skb, u8 port) | 576 | u16 rx_len, u8 port) |
575 | { | 577 | { |
576 | card->mpa_rx.buf_len += skb->len; | 578 | card->mpa_rx.buf_len += rx_len; |
577 | 579 | ||
578 | if (!card->mpa_rx.pkt_cnt) | 580 | if (!card->mpa_rx.pkt_cnt) |
579 | card->mpa_rx.start_port = port; | 581 | card->mpa_rx.start_port = port; |
@@ -586,8 +588,8 @@ static inline void mp_rx_aggr_setup(struct sdio_mmc_card *card, | |||
586 | else | 588 | else |
587 | card->mpa_rx.ports |= 1 << (card->mpa_rx.pkt_cnt + 1); | 589 | card->mpa_rx.ports |= 1 << (card->mpa_rx.pkt_cnt + 1); |
588 | } | 590 | } |
589 | card->mpa_rx.skb_arr[card->mpa_rx.pkt_cnt] = skb; | 591 | card->mpa_rx.skb_arr[card->mpa_rx.pkt_cnt] = NULL; |
590 | card->mpa_rx.len_arr[card->mpa_rx.pkt_cnt] = skb->len; | 592 | card->mpa_rx.len_arr[card->mpa_rx.pkt_cnt] = rx_len; |
591 | card->mpa_rx.pkt_cnt++; | 593 | card->mpa_rx.pkt_cnt++; |
592 | } | 594 | } |
593 | #endif /* _MWIFIEX_SDIO_H */ | 595 | #endif /* _MWIFIEX_SDIO_H */ |
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index f7d204ffd6e9..49422f2a5380 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
@@ -1370,22 +1370,29 @@ mwifiex_cmd_mef_cfg(struct mwifiex_private *priv, | |||
1370 | struct mwifiex_ds_mef_cfg *mef) | 1370 | struct mwifiex_ds_mef_cfg *mef) |
1371 | { | 1371 | { |
1372 | struct host_cmd_ds_mef_cfg *mef_cfg = &cmd->params.mef_cfg; | 1372 | struct host_cmd_ds_mef_cfg *mef_cfg = &cmd->params.mef_cfg; |
1373 | struct mwifiex_fw_mef_entry *mef_entry = NULL; | ||
1373 | u8 *pos = (u8 *)mef_cfg; | 1374 | u8 *pos = (u8 *)mef_cfg; |
1375 | u16 i; | ||
1374 | 1376 | ||
1375 | cmd->command = cpu_to_le16(HostCmd_CMD_MEF_CFG); | 1377 | cmd->command = cpu_to_le16(HostCmd_CMD_MEF_CFG); |
1376 | 1378 | ||
1377 | mef_cfg->criteria = cpu_to_le32(mef->criteria); | 1379 | mef_cfg->criteria = cpu_to_le32(mef->criteria); |
1378 | mef_cfg->num_entries = cpu_to_le16(mef->num_entries); | 1380 | mef_cfg->num_entries = cpu_to_le16(mef->num_entries); |
1379 | pos += sizeof(*mef_cfg); | 1381 | pos += sizeof(*mef_cfg); |
1380 | mef_cfg->mef_entry->mode = mef->mef_entry->mode; | ||
1381 | mef_cfg->mef_entry->action = mef->mef_entry->action; | ||
1382 | pos += sizeof(*(mef_cfg->mef_entry)); | ||
1383 | 1382 | ||
1384 | if (mwifiex_cmd_append_rpn_expression(priv, mef->mef_entry, &pos)) | 1383 | for (i = 0; i < mef->num_entries; i++) { |
1385 | return -1; | 1384 | mef_entry = (struct mwifiex_fw_mef_entry *)pos; |
1385 | mef_entry->mode = mef->mef_entry[i].mode; | ||
1386 | mef_entry->action = mef->mef_entry[i].action; | ||
1387 | pos += sizeof(*mef_cfg->mef_entry); | ||
1388 | |||
1389 | if (mwifiex_cmd_append_rpn_expression(priv, | ||
1390 | &mef->mef_entry[i], &pos)) | ||
1391 | return -1; | ||
1386 | 1392 | ||
1387 | mef_cfg->mef_entry->exprsize = | 1393 | mef_entry->exprsize = |
1388 | cpu_to_le16(pos - mef_cfg->mef_entry->expr); | 1394 | cpu_to_le16(pos - mef_entry->expr); |
1395 | } | ||
1389 | cmd->size = cpu_to_le16((u16) (pos - (u8 *)mef_cfg) + S_DS_GEN); | 1396 | cmd->size = cpu_to_le16((u16) (pos - (u8 *)mef_cfg) + S_DS_GEN); |
1390 | 1397 | ||
1391 | return 0; | 1398 | return 0; |
@@ -1664,6 +1671,25 @@ mwifiex_cmd_tdls_oper(struct mwifiex_private *priv, | |||
1664 | 1671 | ||
1665 | return 0; | 1672 | return 0; |
1666 | } | 1673 | } |
1674 | |||
1675 | /* This function prepares command of sdio rx aggr info. */ | ||
1676 | static int mwifiex_cmd_sdio_rx_aggr_cfg(struct host_cmd_ds_command *cmd, | ||
1677 | u16 cmd_action, void *data_buf) | ||
1678 | { | ||
1679 | struct host_cmd_sdio_sp_rx_aggr_cfg *cfg = | ||
1680 | &cmd->params.sdio_rx_aggr_cfg; | ||
1681 | |||
1682 | cmd->command = cpu_to_le16(HostCmd_CMD_SDIO_SP_RX_AGGR_CFG); | ||
1683 | cmd->size = | ||
1684 | cpu_to_le16(sizeof(struct host_cmd_sdio_sp_rx_aggr_cfg) + | ||
1685 | S_DS_GEN); | ||
1686 | cfg->action = cmd_action; | ||
1687 | if (cmd_action == HostCmd_ACT_GEN_SET) | ||
1688 | cfg->enable = *(u8 *)data_buf; | ||
1689 | |||
1690 | return 0; | ||
1691 | } | ||
1692 | |||
1667 | /* | 1693 | /* |
1668 | * This function prepares the commands before sending them to the firmware. | 1694 | * This function prepares the commands before sending them to the firmware. |
1669 | * | 1695 | * |
@@ -1901,6 +1927,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | |||
1901 | ret = mwifiex_cmd_issue_chan_report_request(priv, cmd_ptr, | 1927 | ret = mwifiex_cmd_issue_chan_report_request(priv, cmd_ptr, |
1902 | data_buf); | 1928 | data_buf); |
1903 | break; | 1929 | break; |
1930 | case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG: | ||
1931 | ret = mwifiex_cmd_sdio_rx_aggr_cfg(cmd_ptr, cmd_action, | ||
1932 | data_buf); | ||
1933 | break; | ||
1904 | default: | 1934 | default: |
1905 | dev_err(priv->adapter->dev, | 1935 | dev_err(priv->adapter->dev, |
1906 | "PREP_CMD: unknown cmd- %#x\n", cmd_no); | 1936 | "PREP_CMD: unknown cmd- %#x\n", cmd_no); |
@@ -1940,6 +1970,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init) | |||
1940 | struct mwifiex_ds_auto_ds auto_ds; | 1970 | struct mwifiex_ds_auto_ds auto_ds; |
1941 | enum state_11d_t state_11d; | 1971 | enum state_11d_t state_11d; |
1942 | struct mwifiex_ds_11n_tx_cfg tx_cfg; | 1972 | struct mwifiex_ds_11n_tx_cfg tx_cfg; |
1973 | u8 sdio_sp_rx_aggr_enable; | ||
1943 | 1974 | ||
1944 | if (first_sta) { | 1975 | if (first_sta) { |
1945 | if (priv->adapter->iface_type == MWIFIEX_PCIE) { | 1976 | if (priv->adapter->iface_type == MWIFIEX_PCIE) { |
@@ -1983,6 +2014,22 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init) | |||
1983 | if (ret) | 2014 | if (ret) |
1984 | return -1; | 2015 | return -1; |
1985 | 2016 | ||
2017 | /** Set SDIO Single Port RX Aggr Info */ | ||
2018 | if (priv->adapter->iface_type == MWIFIEX_SDIO && | ||
2019 | ISSUPP_SDIO_SPA_ENABLED(priv->adapter->fw_cap_info)) { | ||
2020 | sdio_sp_rx_aggr_enable = true; | ||
2021 | ret = mwifiex_send_cmd(priv, | ||
2022 | HostCmd_CMD_SDIO_SP_RX_AGGR_CFG, | ||
2023 | HostCmd_ACT_GEN_SET, 0, | ||
2024 | &sdio_sp_rx_aggr_enable, | ||
2025 | true); | ||
2026 | if (ret) { | ||
2027 | dev_err(priv->adapter->dev, | ||
2028 | "error while enabling SP aggregation..disable it"); | ||
2029 | adapter->sdio_rx_aggr_enable = false; | ||
2030 | } | ||
2031 | } | ||
2032 | |||
1986 | /* Reconfigure tx buf size */ | 2033 | /* Reconfigure tx buf size */ |
1987 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF, | 2034 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF, |
1988 | HostCmd_ACT_GEN_SET, 0, | 2035 | HostCmd_ACT_GEN_SET, 0, |
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 5f8da5924666..88dc6b672ef4 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
@@ -90,6 +90,10 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv, | |||
90 | case HostCmd_CMD_MAC_CONTROL: | 90 | case HostCmd_CMD_MAC_CONTROL: |
91 | break; | 91 | break; |
92 | 92 | ||
93 | case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG: | ||
94 | dev_err(priv->adapter->dev, "SDIO RX single-port aggregation Not support\n"); | ||
95 | break; | ||
96 | |||
93 | default: | 97 | default: |
94 | break; | 98 | break; |
95 | } | 99 | } |
@@ -943,6 +947,20 @@ static int mwifiex_ret_cfg_data(struct mwifiex_private *priv, | |||
943 | return 0; | 947 | return 0; |
944 | } | 948 | } |
945 | 949 | ||
950 | /** This Function handles the command response of sdio rx aggr */ | ||
951 | static int mwifiex_ret_sdio_rx_aggr_cfg(struct mwifiex_private *priv, | ||
952 | struct host_cmd_ds_command *resp) | ||
953 | { | ||
954 | struct mwifiex_adapter *adapter = priv->adapter; | ||
955 | struct host_cmd_sdio_sp_rx_aggr_cfg *cfg = | ||
956 | &resp->params.sdio_rx_aggr_cfg; | ||
957 | |||
958 | adapter->sdio_rx_aggr_enable = cfg->enable; | ||
959 | adapter->sdio_rx_block_size = le16_to_cpu(cfg->block_size); | ||
960 | |||
961 | return 0; | ||
962 | } | ||
963 | |||
946 | /* | 964 | /* |
947 | * This function handles the command responses. | 965 | * This function handles the command responses. |
948 | * | 966 | * |
@@ -1124,6 +1142,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, | |||
1124 | break; | 1142 | break; |
1125 | case HostCmd_CMD_CHAN_REPORT_REQUEST: | 1143 | case HostCmd_CMD_CHAN_REPORT_REQUEST: |
1126 | break; | 1144 | break; |
1145 | case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG: | ||
1146 | ret = mwifiex_ret_sdio_rx_aggr_cfg(priv, resp); | ||
1147 | break; | ||
1127 | default: | 1148 | default: |
1128 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", | 1149 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", |
1129 | resp->command); | 1150 | resp->command); |
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index 64c4223a1e1e..0dc7a1d3993d 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c | |||
@@ -312,7 +312,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) | |||
312 | adapter->ps_state = PS_STATE_AWAKE; | 312 | adapter->ps_state = PS_STATE_AWAKE; |
313 | adapter->pm_wakeup_card_req = false; | 313 | adapter->pm_wakeup_card_req = false; |
314 | adapter->pm_wakeup_fw_try = false; | 314 | adapter->pm_wakeup_fw_try = false; |
315 | del_timer_sync(&adapter->wakeup_timer); | 315 | del_timer(&adapter->wakeup_timer); |
316 | break; | 316 | break; |
317 | } | 317 | } |
318 | if (!mwifiex_send_null_packet | 318 | if (!mwifiex_send_null_packet |
@@ -327,7 +327,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) | |||
327 | adapter->ps_state = PS_STATE_AWAKE; | 327 | adapter->ps_state = PS_STATE_AWAKE; |
328 | adapter->pm_wakeup_card_req = false; | 328 | adapter->pm_wakeup_card_req = false; |
329 | adapter->pm_wakeup_fw_try = false; | 329 | adapter->pm_wakeup_fw_try = false; |
330 | del_timer_sync(&adapter->wakeup_timer); | 330 | del_timer(&adapter->wakeup_timer); |
331 | 331 | ||
332 | break; | 332 | break; |
333 | 333 | ||
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index ea4549f0e0b9..a245f444aeec 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c | |||
@@ -92,6 +92,12 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, | |||
92 | else | 92 | else |
93 | head_ptr = mwifiex_process_sta_txpd(priv, skb); | 93 | head_ptr = mwifiex_process_sta_txpd(priv, skb); |
94 | 94 | ||
95 | if ((adapter->data_sent || adapter->tx_lock_flag) && head_ptr) { | ||
96 | skb_queue_tail(&adapter->tx_data_q, skb); | ||
97 | atomic_inc(&adapter->tx_queued); | ||
98 | return 0; | ||
99 | } | ||
100 | |||
95 | if (head_ptr) { | 101 | if (head_ptr) { |
96 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) | 102 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) |
97 | local_tx_pd = (struct txpd *)(head_ptr + hroom); | 103 | local_tx_pd = (struct txpd *)(head_ptr + hroom); |
@@ -142,6 +148,123 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, | |||
142 | return ret; | 148 | return ret; |
143 | } | 149 | } |
144 | 150 | ||
151 | static int mwifiex_host_to_card(struct mwifiex_adapter *adapter, | ||
152 | struct sk_buff *skb, | ||
153 | struct mwifiex_tx_param *tx_param) | ||
154 | { | ||
155 | struct txpd *local_tx_pd = NULL; | ||
156 | u8 *head_ptr = skb->data; | ||
157 | int ret = 0; | ||
158 | struct mwifiex_private *priv; | ||
159 | struct mwifiex_txinfo *tx_info; | ||
160 | |||
161 | tx_info = MWIFIEX_SKB_TXCB(skb); | ||
162 | priv = mwifiex_get_priv_by_id(adapter, tx_info->bss_num, | ||
163 | tx_info->bss_type); | ||
164 | if (!priv) { | ||
165 | dev_err(adapter->dev, "data: priv not found. Drop TX packet\n"); | ||
166 | adapter->dbg.num_tx_host_to_card_failure++; | ||
167 | mwifiex_write_data_complete(adapter, skb, 0, 0); | ||
168 | return ret; | ||
169 | } | ||
170 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) { | ||
171 | if (adapter->iface_type == MWIFIEX_USB) | ||
172 | local_tx_pd = (struct txpd *)head_ptr; | ||
173 | else | ||
174 | local_tx_pd = (struct txpd *) (head_ptr + | ||
175 | INTF_HEADER_LEN); | ||
176 | } | ||
177 | |||
178 | if (adapter->iface_type == MWIFIEX_USB) { | ||
179 | adapter->data_sent = true; | ||
180 | ret = adapter->if_ops.host_to_card(adapter, | ||
181 | MWIFIEX_USB_EP_DATA, | ||
182 | skb, NULL); | ||
183 | } else { | ||
184 | ret = adapter->if_ops.host_to_card(adapter, | ||
185 | MWIFIEX_TYPE_DATA, | ||
186 | skb, tx_param); | ||
187 | } | ||
188 | switch (ret) { | ||
189 | case -ENOSR: | ||
190 | dev_err(adapter->dev, "data: -ENOSR is returned\n"); | ||
191 | break; | ||
192 | case -EBUSY: | ||
193 | if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && | ||
194 | (adapter->pps_uapsd_mode) && | ||
195 | (adapter->tx_lock_flag)) { | ||
196 | priv->adapter->tx_lock_flag = false; | ||
197 | if (local_tx_pd) | ||
198 | local_tx_pd->flags = 0; | ||
199 | } | ||
200 | skb_queue_head(&adapter->tx_data_q, skb); | ||
201 | if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT) | ||
202 | atomic_add(tx_info->aggr_num, &adapter->tx_queued); | ||
203 | else | ||
204 | atomic_inc(&adapter->tx_queued); | ||
205 | dev_dbg(adapter->dev, "data: -EBUSY is returned\n"); | ||
206 | break; | ||
207 | case -1: | ||
208 | if (adapter->iface_type != MWIFIEX_PCIE) | ||
209 | adapter->data_sent = false; | ||
210 | dev_err(adapter->dev, "mwifiex_write_data_async failed: 0x%X\n", | ||
211 | ret); | ||
212 | adapter->dbg.num_tx_host_to_card_failure++; | ||
213 | mwifiex_write_data_complete(adapter, skb, 0, ret); | ||
214 | break; | ||
215 | case -EINPROGRESS: | ||
216 | if (adapter->iface_type != MWIFIEX_PCIE) | ||
217 | adapter->data_sent = false; | ||
218 | break; | ||
219 | case 0: | ||
220 | mwifiex_write_data_complete(adapter, skb, 0, ret); | ||
221 | break; | ||
222 | default: | ||
223 | break; | ||
224 | } | ||
225 | return ret; | ||
226 | } | ||
227 | |||
228 | static int | ||
229 | mwifiex_dequeue_tx_queue(struct mwifiex_adapter *adapter) | ||
230 | { | ||
231 | struct sk_buff *skb, *skb_next; | ||
232 | struct mwifiex_txinfo *tx_info; | ||
233 | struct mwifiex_tx_param tx_param; | ||
234 | |||
235 | skb = skb_dequeue(&adapter->tx_data_q); | ||
236 | if (!skb) | ||
237 | return -1; | ||
238 | |||
239 | tx_info = MWIFIEX_SKB_TXCB(skb); | ||
240 | if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT) | ||
241 | atomic_sub(tx_info->aggr_num, &adapter->tx_queued); | ||
242 | else | ||
243 | atomic_dec(&adapter->tx_queued); | ||
244 | |||
245 | if (!skb_queue_empty(&adapter->tx_data_q)) | ||
246 | skb_next = skb_peek(&adapter->tx_data_q); | ||
247 | else | ||
248 | skb_next = NULL; | ||
249 | tx_param.next_pkt_len = ((skb_next) ? skb_next->len : 0); | ||
250 | if (!tx_param.next_pkt_len) { | ||
251 | if (!mwifiex_wmm_lists_empty(adapter)) | ||
252 | tx_param.next_pkt_len = 1; | ||
253 | } | ||
254 | return mwifiex_host_to_card(adapter, skb, &tx_param); | ||
255 | } | ||
256 | |||
257 | void | ||
258 | mwifiex_process_tx_queue(struct mwifiex_adapter *adapter) | ||
259 | { | ||
260 | do { | ||
261 | if (adapter->data_sent || adapter->tx_lock_flag) | ||
262 | break; | ||
263 | if (mwifiex_dequeue_tx_queue(adapter)) | ||
264 | break; | ||
265 | } while (!skb_queue_empty(&adapter->tx_data_q)); | ||
266 | } | ||
267 | |||
145 | /* | 268 | /* |
146 | * Packet send completion callback handler. | 269 | * Packet send completion callback handler. |
147 | * | 270 | * |
@@ -179,8 +302,11 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, | |||
179 | priv->stats.tx_errors++; | 302 | priv->stats.tx_errors++; |
180 | } | 303 | } |
181 | 304 | ||
182 | if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT) | 305 | if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT) { |
183 | atomic_dec_return(&adapter->pending_bridged_pkts); | 306 | atomic_dec_return(&adapter->pending_bridged_pkts); |
307 | if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT) | ||
308 | goto done; | ||
309 | } | ||
184 | 310 | ||
185 | if (aggr) | 311 | if (aggr) |
186 | /* For skb_aggr, do not wake up tx queue */ | 312 | /* For skb_aggr, do not wake up tx queue */ |
diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c index 223873022ffe..fd8027f200a0 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c | |||
@@ -193,7 +193,7 @@ static void mwifiex_usb_rx_complete(struct urb *urb) | |||
193 | dev_dbg(adapter->dev, "info: recv_length=%d, status=%d\n", | 193 | dev_dbg(adapter->dev, "info: recv_length=%d, status=%d\n", |
194 | recv_length, status); | 194 | recv_length, status); |
195 | if (status == -EINPROGRESS) { | 195 | if (status == -EINPROGRESS) { |
196 | queue_work(adapter->workqueue, &adapter->main_work); | 196 | mwifiex_queue_main_work(adapter); |
197 | 197 | ||
198 | /* urb for data_ep is re-submitted now; | 198 | /* urb for data_ep is re-submitted now; |
199 | * urb for cmd_ep will be re-submitted in callback | 199 | * urb for cmd_ep will be re-submitted in callback |
@@ -262,7 +262,7 @@ static void mwifiex_usb_tx_complete(struct urb *urb) | |||
262 | urb->status ? -1 : 0); | 262 | urb->status ? -1 : 0); |
263 | } | 263 | } |
264 | 264 | ||
265 | queue_work(adapter->workqueue, &adapter->main_work); | 265 | mwifiex_queue_main_work(adapter); |
266 | 266 | ||
267 | return; | 267 | return; |
268 | } | 268 | } |
@@ -1006,7 +1006,7 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) | |||
1006 | { | 1006 | { |
1007 | /* Simulation of HS_AWAKE event */ | 1007 | /* Simulation of HS_AWAKE event */ |
1008 | adapter->pm_wakeup_fw_try = false; | 1008 | adapter->pm_wakeup_fw_try = false; |
1009 | del_timer_sync(&adapter->wakeup_timer); | 1009 | del_timer(&adapter->wakeup_timer); |
1010 | adapter->pm_wakeup_card_req = false; | 1010 | adapter->pm_wakeup_card_req = false; |
1011 | adapter->ps_state = PS_STATE_AWAKE; | 1011 | adapter->ps_state = PS_STATE_AWAKE; |
1012 | 1012 | ||
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c index 2148a573396b..b8a45872354d 100644 --- a/drivers/net/wireless/mwifiex/util.c +++ b/drivers/net/wireless/mwifiex/util.c | |||
@@ -632,7 +632,7 @@ void mwifiex_hist_data_reset(struct mwifiex_private *priv) | |||
632 | atomic_set(&phist_data->sig_str[ix], 0); | 632 | atomic_set(&phist_data->sig_str[ix], 0); |
633 | } | 633 | } |
634 | 634 | ||
635 | void *mwifiex_alloc_rx_buf(int rx_len, gfp_t flags) | 635 | void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags) |
636 | { | 636 | { |
637 | struct sk_buff *skb; | 637 | struct sk_buff *skb; |
638 | int buf_len, pad; | 638 | int buf_len, pad; |
@@ -653,4 +653,4 @@ void *mwifiex_alloc_rx_buf(int rx_len, gfp_t flags) | |||
653 | 653 | ||
654 | return skb; | 654 | return skb; |
655 | } | 655 | } |
656 | EXPORT_SYMBOL_GPL(mwifiex_alloc_rx_buf); | 656 | EXPORT_SYMBOL_GPL(mwifiex_alloc_dma_align_buf); |
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 0cd4f6bed9fc..b2e99569a0f8 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c | |||
@@ -157,6 +157,8 @@ void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra) | |||
157 | 157 | ||
158 | ra_list->is_11n_enabled = 0; | 158 | ra_list->is_11n_enabled = 0; |
159 | ra_list->tdls_link = false; | 159 | ra_list->tdls_link = false; |
160 | ra_list->ba_status = BA_SETUP_NONE; | ||
161 | ra_list->amsdu_in_ampdu = false; | ||
160 | if (!mwifiex_queuing_ra_based(priv)) { | 162 | if (!mwifiex_queuing_ra_based(priv)) { |
161 | if (mwifiex_get_tdls_link_status(priv, ra) == | 163 | if (mwifiex_get_tdls_link_status(priv, ra) == |
162 | TDLS_SETUP_COMPLETE) { | 164 | TDLS_SETUP_COMPLETE) { |
@@ -574,7 +576,7 @@ mwifiex_clean_txrx(struct mwifiex_private *priv) | |||
574 | * This function retrieves a particular RA list node, matching with the | 576 | * This function retrieves a particular RA list node, matching with the |
575 | * given TID and RA address. | 577 | * given TID and RA address. |
576 | */ | 578 | */ |
577 | static struct mwifiex_ra_list_tbl * | 579 | struct mwifiex_ra_list_tbl * |
578 | mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid, | 580 | mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid, |
579 | const u8 *ra_addr) | 581 | const u8 *ra_addr) |
580 | { | 582 | { |
@@ -942,14 +944,11 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, | |||
942 | struct mwifiex_ra_list_tbl *ptr; | 944 | struct mwifiex_ra_list_tbl *ptr; |
943 | struct mwifiex_tid_tbl *tid_ptr; | 945 | struct mwifiex_tid_tbl *tid_ptr; |
944 | atomic_t *hqp; | 946 | atomic_t *hqp; |
945 | unsigned long flags_bss, flags_ra; | 947 | unsigned long flags_ra; |
946 | int i, j; | 948 | int i, j; |
947 | 949 | ||
948 | /* check the BSS with highest priority first */ | 950 | /* check the BSS with highest priority first */ |
949 | for (j = adapter->priv_num - 1; j >= 0; --j) { | 951 | for (j = adapter->priv_num - 1; j >= 0; --j) { |
950 | spin_lock_irqsave(&adapter->bss_prio_tbl[j].bss_prio_lock, | ||
951 | flags_bss); | ||
952 | |||
953 | /* iterate over BSS with the equal priority */ | 952 | /* iterate over BSS with the equal priority */ |
954 | list_for_each_entry(adapter->bss_prio_tbl[j].bss_prio_cur, | 953 | list_for_each_entry(adapter->bss_prio_tbl[j].bss_prio_cur, |
955 | &adapter->bss_prio_tbl[j].bss_prio_head, | 954 | &adapter->bss_prio_tbl[j].bss_prio_head, |
@@ -985,19 +984,15 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, | |||
985 | } | 984 | } |
986 | } | 985 | } |
987 | 986 | ||
988 | spin_unlock_irqrestore(&adapter->bss_prio_tbl[j].bss_prio_lock, | ||
989 | flags_bss); | ||
990 | } | 987 | } |
991 | 988 | ||
992 | return NULL; | 989 | return NULL; |
993 | 990 | ||
994 | found: | 991 | found: |
995 | /* holds bss_prio_lock / ra_list_spinlock */ | 992 | /* holds ra_list_spinlock */ |
996 | if (atomic_read(hqp) > i) | 993 | if (atomic_read(hqp) > i) |
997 | atomic_set(hqp, i); | 994 | atomic_set(hqp, i); |
998 | spin_unlock_irqrestore(&priv_tmp->wmm.ra_list_spinlock, flags_ra); | 995 | spin_unlock_irqrestore(&priv_tmp->wmm.ra_list_spinlock, flags_ra); |
999 | spin_unlock_irqrestore(&adapter->bss_prio_tbl[j].bss_prio_lock, | ||
1000 | flags_bss); | ||
1001 | 996 | ||
1002 | *priv = priv_tmp; | 997 | *priv = priv_tmp; |
1003 | *tid = tos_to_tid[i]; | 998 | *tid = tos_to_tid[i]; |
@@ -1179,6 +1174,14 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv, | |||
1179 | 1174 | ||
1180 | skb = skb_dequeue(&ptr->skb_head); | 1175 | skb = skb_dequeue(&ptr->skb_head); |
1181 | 1176 | ||
1177 | if (adapter->data_sent || adapter->tx_lock_flag) { | ||
1178 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, | ||
1179 | ra_list_flags); | ||
1180 | skb_queue_tail(&adapter->tx_data_q, skb); | ||
1181 | atomic_inc(&adapter->tx_queued); | ||
1182 | return; | ||
1183 | } | ||
1184 | |||
1182 | if (!skb_queue_empty(&ptr->skb_head)) | 1185 | if (!skb_queue_empty(&ptr->skb_head)) |
1183 | skb_next = skb_peek(&ptr->skb_head); | 1186 | skb_next = skb_peek(&ptr->skb_head); |
1184 | else | 1187 | else |
@@ -1276,13 +1279,13 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) | |||
1276 | } | 1279 | } |
1277 | 1280 | ||
1278 | if (!ptr->is_11n_enabled || | 1281 | if (!ptr->is_11n_enabled || |
1279 | mwifiex_is_ba_stream_setup(priv, ptr, tid) || | 1282 | ptr->ba_status || |
1280 | priv->wps.session_enable) { | 1283 | priv->wps.session_enable) { |
1281 | if (ptr->is_11n_enabled && | 1284 | if (ptr->is_11n_enabled && |
1282 | mwifiex_is_ba_stream_setup(priv, ptr, tid) && | 1285 | ptr->ba_status && |
1283 | mwifiex_is_amsdu_in_ampdu_allowed(priv, ptr, tid) && | 1286 | ptr->amsdu_in_ampdu && |
1284 | mwifiex_is_amsdu_allowed(priv, tid) && | 1287 | mwifiex_is_amsdu_allowed(priv, tid) && |
1285 | mwifiex_is_11n_aggragation_possible(priv, ptr, | 1288 | mwifiex_is_11n_aggragation_possible(priv, ptr, |
1286 | adapter->tx_buf_size)) | 1289 | adapter->tx_buf_size)) |
1287 | mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags); | 1290 | mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags); |
1288 | /* ra_list_spinlock has been freed in | 1291 | /* ra_list_spinlock has been freed in |
@@ -1329,11 +1332,16 @@ void | |||
1329 | mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter) | 1332 | mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter) |
1330 | { | 1333 | { |
1331 | do { | 1334 | do { |
1332 | /* Check if busy */ | ||
1333 | if (adapter->data_sent || adapter->tx_lock_flag) | ||
1334 | break; | ||
1335 | |||
1336 | if (mwifiex_dequeue_tx_packet(adapter)) | 1335 | if (mwifiex_dequeue_tx_packet(adapter)) |
1337 | break; | 1336 | break; |
1337 | if (adapter->iface_type != MWIFIEX_SDIO) { | ||
1338 | if (adapter->data_sent || | ||
1339 | adapter->tx_lock_flag) | ||
1340 | break; | ||
1341 | } else { | ||
1342 | if (atomic_read(&adapter->tx_queued) >= | ||
1343 | MWIFIEX_MAX_PKTS_TXQ) | ||
1344 | break; | ||
1345 | } | ||
1338 | } while (!mwifiex_wmm_lists_empty(adapter)); | 1346 | } while (!mwifiex_wmm_lists_empty(adapter)); |
1339 | } | 1347 | } |
diff --git a/drivers/net/wireless/mwifiex/wmm.h b/drivers/net/wireless/mwifiex/wmm.h index 569bd73f33c5..48ece0b35591 100644 --- a/drivers/net/wireless/mwifiex/wmm.h +++ b/drivers/net/wireless/mwifiex/wmm.h | |||
@@ -127,4 +127,6 @@ mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, | |||
127 | const u8 *ra_addr); | 127 | const u8 *ra_addr); |
128 | u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid); | 128 | u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid); |
129 | 129 | ||
130 | struct mwifiex_ra_list_tbl *mwifiex_wmm_get_ralist_node(struct mwifiex_private | ||
131 | *priv, u8 tid, const u8 *ra_addr); | ||
130 | #endif /* !_MWIFIEX_WMM_H_ */ | 132 | #endif /* !_MWIFIEX_WMM_H_ */ |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 8444313eabe2..6ec2466b52b6 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -233,6 +233,7 @@ static int rt2800usb_autorun_detect(struct rt2x00_dev *rt2x00dev) | |||
233 | { | 233 | { |
234 | __le32 *reg; | 234 | __le32 *reg; |
235 | u32 fw_mode; | 235 | u32 fw_mode; |
236 | int ret; | ||
236 | 237 | ||
237 | reg = kmalloc(sizeof(*reg), GFP_KERNEL); | 238 | reg = kmalloc(sizeof(*reg), GFP_KERNEL); |
238 | if (reg == NULL) | 239 | if (reg == NULL) |
@@ -242,11 +243,14 @@ static int rt2800usb_autorun_detect(struct rt2x00_dev *rt2x00dev) | |||
242 | * magic value USB_MODE_AUTORUN (0x11) to the device, thus the | 243 | * magic value USB_MODE_AUTORUN (0x11) to the device, thus the |
243 | * returned value would be invalid. | 244 | * returned value would be invalid. |
244 | */ | 245 | */ |
245 | rt2x00usb_vendor_request(rt2x00dev, USB_DEVICE_MODE, | 246 | ret = rt2x00usb_vendor_request(rt2x00dev, USB_DEVICE_MODE, |
246 | USB_VENDOR_REQUEST_IN, 0, USB_MODE_AUTORUN, | 247 | USB_VENDOR_REQUEST_IN, 0, |
247 | reg, sizeof(*reg), REGISTER_TIMEOUT_FIRMWARE); | 248 | USB_MODE_AUTORUN, reg, sizeof(*reg), |
249 | REGISTER_TIMEOUT_FIRMWARE); | ||
248 | fw_mode = le32_to_cpu(*reg); | 250 | fw_mode = le32_to_cpu(*reg); |
249 | kfree(reg); | 251 | kfree(reg); |
252 | if (ret < 0) | ||
253 | return ret; | ||
250 | 254 | ||
251 | if ((fw_mode & 0x00000003) == 2) | 255 | if ((fw_mode & 0x00000003) == 2) |
252 | return 1; | 256 | return 1; |
@@ -289,6 +293,7 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev, | |||
289 | if (retval) { | 293 | if (retval) { |
290 | rt2x00_info(rt2x00dev, | 294 | rt2x00_info(rt2x00dev, |
291 | "Firmware loading not required - NIC in AutoRun mode\n"); | 295 | "Firmware loading not required - NIC in AutoRun mode\n"); |
296 | __clear_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags); | ||
292 | } else { | 297 | } else { |
293 | rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, | 298 | rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, |
294 | data + offset, length); | 299 | data + offset, length); |
@@ -374,7 +379,6 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
374 | static void rt2800usb_disable_radio(struct rt2x00_dev *rt2x00dev) | 379 | static void rt2800usb_disable_radio(struct rt2x00_dev *rt2x00dev) |
375 | { | 380 | { |
376 | rt2800_disable_radio(rt2x00dev); | 381 | rt2800_disable_radio(rt2x00dev); |
377 | rt2x00usb_disable_radio(rt2x00dev); | ||
378 | } | 382 | } |
379 | 383 | ||
380 | static int rt2800usb_set_state(struct rt2x00_dev *rt2x00dev, | 384 | static int rt2800usb_set_state(struct rt2x00_dev *rt2x00dev, |
@@ -1040,6 +1044,7 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
1040 | { USB_DEVICE(0x07d1, 0x3c17) }, | 1044 | { USB_DEVICE(0x07d1, 0x3c17) }, |
1041 | { USB_DEVICE(0x2001, 0x3317) }, | 1045 | { USB_DEVICE(0x2001, 0x3317) }, |
1042 | { USB_DEVICE(0x2001, 0x3c1b) }, | 1046 | { USB_DEVICE(0x2001, 0x3c1b) }, |
1047 | { USB_DEVICE(0x2001, 0x3c25) }, | ||
1043 | /* Draytek */ | 1048 | /* Draytek */ |
1044 | { USB_DEVICE(0x07fa, 0x7712) }, | 1049 | { USB_DEVICE(0x07fa, 0x7712) }, |
1045 | /* DVICO */ | 1050 | /* DVICO */ |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index 8f85fbd5f237..569363da00a2 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h | |||
@@ -199,7 +199,7 @@ static inline void rt2x00usb_register_read(struct rt2x00_dev *rt2x00dev, | |||
199 | const unsigned int offset, | 199 | const unsigned int offset, |
200 | u32 *value) | 200 | u32 *value) |
201 | { | 201 | { |
202 | __le32 reg; | 202 | __le32 reg = 0; |
203 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, | 203 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, |
204 | USB_VENDOR_REQUEST_IN, offset, | 204 | USB_VENDOR_REQUEST_IN, offset, |
205 | ®, sizeof(reg)); | 205 | ®, sizeof(reg)); |
@@ -219,7 +219,7 @@ static inline void rt2x00usb_register_read_lock(struct rt2x00_dev *rt2x00dev, | |||
219 | const unsigned int offset, | 219 | const unsigned int offset, |
220 | u32 *value) | 220 | u32 *value) |
221 | { | 221 | { |
222 | __le32 reg; | 222 | __le32 reg = 0; |
223 | rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ, | 223 | rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ, |
224 | USB_VENDOR_REQUEST_IN, offset, | 224 | USB_VENDOR_REQUEST_IN, offset, |
225 | ®, sizeof(reg), REGISTER_TIMEOUT); | 225 | ®, sizeof(reg), REGISTER_TIMEOUT); |
diff --git a/drivers/net/wireless/rtlwifi/base.h b/drivers/net/wireless/rtlwifi/base.h index dee4ac2f27e2..ff9a4bfd4515 100644 --- a/drivers/net/wireless/rtlwifi/base.h +++ b/drivers/net/wireless/rtlwifi/base.h | |||
@@ -123,7 +123,6 @@ bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb); | |||
123 | u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx); | 123 | u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx); |
124 | 124 | ||
125 | void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb); | 125 | void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb); |
126 | void rtl_watch_dog_timer_callback(unsigned long data); | ||
127 | int rtl_tx_agg_start(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 126 | int rtl_tx_agg_start(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
128 | struct ieee80211_sta *sta, u16 tid, u16 *ssn); | 127 | struct ieee80211_sta *sta, u16 tid, u16 *ssn); |
129 | int rtl_tx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 128 | int rtl_tx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c index edc2cbb6253c..86ce5b1930e6 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "../cam.h" | 30 | #include "../cam.h" |
31 | #include "../ps.h" | 31 | #include "../ps.h" |
32 | #include "../pci.h" | 32 | #include "../pci.h" |
33 | #include "../pwrseqcmd.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" |
@@ -885,7 +886,7 @@ static bool _rtl88ee_init_mac(struct ieee80211_hw *hw) | |||
885 | 886 | ||
886 | rtl_write_word(rtlpriv, REG_CR, 0x2ff); | 887 | rtl_write_word(rtlpriv, REG_CR, 0x2ff); |
887 | rtl_write_byte(rtlpriv, REG_CR+1, 0x06); | 888 | rtl_write_byte(rtlpriv, REG_CR+1, 0x06); |
888 | rtl_write_byte(rtlpriv, REG_CR+2, 0x00); | 889 | rtl_write_byte(rtlpriv, MSR, 0x00); |
889 | 890 | ||
890 | if (!rtlhal->mac_func_enable) { | 891 | if (!rtlhal->mac_func_enable) { |
891 | if (_rtl88ee_llt_table_init(hw) == false) { | 892 | if (_rtl88ee_llt_table_init(hw) == false) { |
@@ -1277,7 +1278,7 @@ static int _rtl88ee_set_media_status(struct ieee80211_hw *hw, | |||
1277 | mode); | 1278 | mode); |
1278 | } | 1279 | } |
1279 | 1280 | ||
1280 | rtl_write_byte(rtlpriv, (MSR), bt_msr | mode); | 1281 | rtl_write_byte(rtlpriv, MSR, bt_msr | mode); |
1281 | rtlpriv->cfg->ops->led_control(hw, ledaction); | 1282 | rtlpriv->cfg->ops->led_control(hw, ledaction); |
1282 | if (mode == MSR_AP) | 1283 | if (mode == MSR_AP) |
1283 | rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); | 1284 | rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index 0c20dd74d6ec..d310d55d800e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c | |||
@@ -1364,7 +1364,7 @@ static int _rtl92cu_set_media_status(struct ieee80211_hw *hw, | |||
1364 | "Network type %d not supported!\n", type); | 1364 | "Network type %d not supported!\n", type); |
1365 | goto error_out; | 1365 | goto error_out; |
1366 | } | 1366 | } |
1367 | rtl_write_byte(rtlpriv, (MSR), bt_msr); | 1367 | rtl_write_byte(rtlpriv, MSR, bt_msr); |
1368 | rtlpriv->cfg->ops->led_control(hw, ledaction); | 1368 | rtlpriv->cfg->ops->led_control(hw, ledaction); |
1369 | if ((bt_msr & MSR_MASK) == MSR_AP) | 1369 | if ((bt_msr & MSR_MASK) == MSR_AP) |
1370 | rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); | 1370 | rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); |
@@ -1471,8 +1471,7 @@ static void _InitBeaconParameters(struct ieee80211_hw *hw) | |||
1471 | rtl_write_word(rtlpriv, REG_BCNTCFG, 0x66FF); | 1471 | rtl_write_word(rtlpriv, REG_BCNTCFG, 0x66FF); |
1472 | } | 1472 | } |
1473 | 1473 | ||
1474 | static void _beacon_function_enable(struct ieee80211_hw *hw, bool Enable, | 1474 | static void _beacon_function_enable(struct ieee80211_hw *hw) |
1475 | bool Linked) | ||
1476 | { | 1475 | { |
1477 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1476 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1478 | 1477 | ||
@@ -1517,7 +1516,7 @@ void rtl92cu_set_beacon_related_registers(struct ieee80211_hw *hw) | |||
1517 | rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x50); | 1516 | rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x50); |
1518 | rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x50); | 1517 | rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x50); |
1519 | } | 1518 | } |
1520 | _beacon_function_enable(hw, true, true); | 1519 | _beacon_function_enable(hw); |
1521 | } | 1520 | } |
1522 | 1521 | ||
1523 | void rtl92cu_set_beacon_interval(struct ieee80211_hw *hw) | 1522 | void rtl92cu_set_beacon_interval(struct ieee80211_hw *hw) |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c index 133e395b7401..adb810794eef 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c | |||
@@ -497,7 +497,7 @@ int rtl92c_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) | |||
497 | "Network type %d not supported!\n", type); | 497 | "Network type %d not supported!\n", type); |
498 | return -EOPNOTSUPP; | 498 | return -EOPNOTSUPP; |
499 | } | 499 | } |
500 | rtl_write_byte(rtlpriv, (REG_CR + 2), value); | 500 | rtl_write_byte(rtlpriv, MSR, value); |
501 | return 0; | 501 | return 0; |
502 | } | 502 | } |
503 | 503 | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 90a714c189a8..23806c243a53 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | |||
@@ -321,6 +321,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { | |||
321 | {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/ | 321 | {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/ |
322 | {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/ | 322 | {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/ |
323 | {RTL_USB_DEVICE(0x0846, 0x9041, rtl92cu_hal_cfg)}, /*NetGear WNA1000M*/ | 323 | {RTL_USB_DEVICE(0x0846, 0x9041, rtl92cu_hal_cfg)}, /*NetGear WNA1000M*/ |
324 | {RTL_USB_DEVICE(0x0b05, 0x17ba, rtl92cu_hal_cfg)}, /*ASUS-Edimax*/ | ||
324 | {RTL_USB_DEVICE(0x0bda, 0x5088, rtl92cu_hal_cfg)}, /*Thinkware-CC&C*/ | 325 | {RTL_USB_DEVICE(0x0bda, 0x5088, rtl92cu_hal_cfg)}, /*Thinkware-CC&C*/ |
325 | {RTL_USB_DEVICE(0x0df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/ | 326 | {RTL_USB_DEVICE(0x0df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/ |
326 | {RTL_USB_DEVICE(0x0df6, 0x005c, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/ | 327 | {RTL_USB_DEVICE(0x0df6, 0x005c, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/ |
@@ -377,6 +378,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { | |||
377 | {RTL_USB_DEVICE(0x2001, 0x3307, rtl92cu_hal_cfg)}, /*D-Link-Cameo*/ | 378 | {RTL_USB_DEVICE(0x2001, 0x3307, rtl92cu_hal_cfg)}, /*D-Link-Cameo*/ |
378 | {RTL_USB_DEVICE(0x2001, 0x3309, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/ | 379 | {RTL_USB_DEVICE(0x2001, 0x3309, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/ |
379 | {RTL_USB_DEVICE(0x2001, 0x330a, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/ | 380 | {RTL_USB_DEVICE(0x2001, 0x330a, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/ |
381 | {RTL_USB_DEVICE(0x2001, 0x330d, rtl92cu_hal_cfg)}, /*D-Link DWA-131 */ | ||
380 | {RTL_USB_DEVICE(0x2019, 0xab2b, rtl92cu_hal_cfg)}, /*Planex -Abocom*/ | 382 | {RTL_USB_DEVICE(0x2019, 0xab2b, rtl92cu_hal_cfg)}, /*Planex -Abocom*/ |
381 | {RTL_USB_DEVICE(0x20f4, 0x624d, rtl92cu_hal_cfg)}, /*TRENDNet*/ | 383 | {RTL_USB_DEVICE(0x20f4, 0x624d, rtl92cu_hal_cfg)}, /*TRENDNet*/ |
382 | {RTL_USB_DEVICE(0x2357, 0x0100, rtl92cu_hal_cfg)}, /*TP-Link WN8200ND*/ | 384 | {RTL_USB_DEVICE(0x2357, 0x0100, rtl92cu_hal_cfg)}, /*TP-Link WN8200ND*/ |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c index 01bcc2d218dc..f49b60d31450 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c | |||
@@ -1126,7 +1126,7 @@ static int _rtl92de_set_media_status(struct ieee80211_hw *hw, | |||
1126 | break; | 1126 | break; |
1127 | 1127 | ||
1128 | } | 1128 | } |
1129 | rtl_write_byte(rtlpriv, REG_CR + 2, bt_msr); | 1129 | rtl_write_byte(rtlpriv, MSR, bt_msr); |
1130 | rtlpriv->cfg->ops->led_control(hw, ledaction); | 1130 | rtlpriv->cfg->ops->led_control(hw, ledaction); |
1131 | if ((bt_msr & MSR_MASK) == MSR_AP) | 1131 | if ((bt_msr & MSR_MASK) == MSR_AP) |
1132 | rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); | 1132 | rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c index db230a3f0137..da0a6125f314 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c | |||
@@ -1510,7 +1510,7 @@ static int _rtl92ee_set_media_status(struct ieee80211_hw *hw, | |||
1510 | mode); | 1510 | mode); |
1511 | } | 1511 | } |
1512 | 1512 | ||
1513 | rtl_write_byte(rtlpriv, (MSR), bt_msr | mode); | 1513 | rtl_write_byte(rtlpriv, MSR, bt_msr | mode); |
1514 | rtlpriv->cfg->ops->led_control(hw, ledaction); | 1514 | rtlpriv->cfg->ops->led_control(hw, ledaction); |
1515 | if (mode == MSR_AP) | 1515 | if (mode == MSR_AP) |
1516 | rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); | 1516 | rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c index dee88a80bee1..12b0978ba4fa 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c | |||
@@ -1204,7 +1204,7 @@ static int _rtl92se_set_media_status(struct ieee80211_hw *hw, | |||
1204 | if (type != NL80211_IFTYPE_AP && | 1204 | if (type != NL80211_IFTYPE_AP && |
1205 | rtlpriv->mac80211.link_state < MAC80211_LINKED) | 1205 | rtlpriv->mac80211.link_state < MAC80211_LINKED) |
1206 | bt_msr = rtl_read_byte(rtlpriv, MSR) & ~MSR_LINK_MASK; | 1206 | bt_msr = rtl_read_byte(rtlpriv, MSR) & ~MSR_LINK_MASK; |
1207 | rtl_write_byte(rtlpriv, (MSR), bt_msr); | 1207 | rtl_write_byte(rtlpriv, MSR, bt_msr); |
1208 | 1208 | ||
1209 | temp = rtl_read_dword(rtlpriv, TCR); | 1209 | temp = rtl_read_dword(rtlpriv, TCR); |
1210 | rtl_write_dword(rtlpriv, TCR, temp & (~BIT(8))); | 1210 | rtl_write_dword(rtlpriv, TCR, temp & (~BIT(8))); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c index b3b094759f6d..67bb47d77b68 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c | |||
@@ -1183,7 +1183,7 @@ static int _rtl8723e_set_media_status(struct ieee80211_hw *hw, | |||
1183 | mode); | 1183 | mode); |
1184 | } | 1184 | } |
1185 | 1185 | ||
1186 | rtl_write_byte(rtlpriv, (MSR), bt_msr | mode); | 1186 | rtl_write_byte(rtlpriv, MSR, bt_msr | mode); |
1187 | rtlpriv->cfg->ops->led_control(hw, ledaction); | 1187 | rtlpriv->cfg->ops->led_control(hw, ledaction); |
1188 | if (mode == MSR_AP) | 1188 | if (mode == MSR_AP) |
1189 | rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); | 1189 | rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/rtlwifi/rtl8723be/hw.c index b46998341c40..b681af3c7a35 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723be/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8723be/hw.c | |||
@@ -1558,7 +1558,7 @@ static int _rtl8723be_set_media_status(struct ieee80211_hw *hw, | |||
1558 | mode); | 1558 | mode); |
1559 | } | 1559 | } |
1560 | 1560 | ||
1561 | rtl_write_byte(rtlpriv, (MSR), bt_msr | mode); | 1561 | rtl_write_byte(rtlpriv, MSR, bt_msr | mode); |
1562 | rtlpriv->cfg->ops->led_control(hw, ledaction); | 1562 | rtlpriv->cfg->ops->led_control(hw, ledaction); |
1563 | if (mode == MSR_AP) | 1563 | if (mode == MSR_AP) |
1564 | rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); | 1564 | rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c index 2a0a71bac00c..8704eee9f3a4 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c | |||
@@ -423,7 +423,7 @@ void rtl8821ae_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | |||
423 | *((u16 *)(val+4)) = rtl_read_word(rtlpriv, REG_BSSID+4); | 423 | *((u16 *)(val+4)) = rtl_read_word(rtlpriv, REG_BSSID+4); |
424 | break; | 424 | break; |
425 | case HW_VAR_MEDIA_STATUS: | 425 | case HW_VAR_MEDIA_STATUS: |
426 | val[0] = rtl_read_byte(rtlpriv, REG_CR+2) & 0x3; | 426 | val[0] = rtl_read_byte(rtlpriv, MSR) & 0x3; |
427 | break; | 427 | break; |
428 | case HW_VAR_SLOT_TIME: | 428 | case HW_VAR_SLOT_TIME: |
429 | *((u8 *)(val)) = mac->slot_time; | 429 | *((u8 *)(val)) = mac->slot_time; |
@@ -2178,7 +2178,7 @@ static int _rtl8821ae_set_media_status(struct ieee80211_hw *hw, | |||
2178 | return 1; | 2178 | return 1; |
2179 | } | 2179 | } |
2180 | 2180 | ||
2181 | rtl_write_byte(rtlpriv, (MSR), bt_msr); | 2181 | rtl_write_byte(rtlpriv, MSR, bt_msr); |
2182 | rtlpriv->cfg->ops->led_control(hw, ledaction); | 2182 | rtlpriv->cfg->ops->led_control(hw, ledaction); |
2183 | if ((bt_msr & 0xfc) == MSR_AP) | 2183 | if ((bt_msr & 0xfc) == MSR_AP) |
2184 | rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); | 2184 | rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/trx.c b/drivers/net/wireless/rtlwifi/rtl8821ae/trx.c index 72af4b9ee32b..174743aef943 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8821ae/trx.c | |||
@@ -64,6 +64,20 @@ static u16 odm_cfo(char value) | |||
64 | return ret_val; | 64 | return ret_val; |
65 | } | 65 | } |
66 | 66 | ||
67 | static u8 _rtl8821ae_evm_dbm_jaguar(char value) | ||
68 | { | ||
69 | char ret_val = value; | ||
70 | |||
71 | /* -33dB~0dB to 33dB ~ 0dB*/ | ||
72 | if (ret_val == -128) | ||
73 | ret_val = 127; | ||
74 | else if (ret_val < 0) | ||
75 | ret_val = 0 - ret_val; | ||
76 | |||
77 | ret_val = ret_val >> 1; | ||
78 | return ret_val; | ||
79 | } | ||
80 | |||
67 | static void query_rxphystatus(struct ieee80211_hw *hw, | 81 | static void query_rxphystatus(struct ieee80211_hw *hw, |
68 | struct rtl_stats *pstatus, u8 *pdesc, | 82 | struct rtl_stats *pstatus, u8 *pdesc, |
69 | struct rx_fwinfo_8821ae *p_drvinfo, | 83 | struct rx_fwinfo_8821ae *p_drvinfo, |
@@ -246,7 +260,7 @@ static void query_rxphystatus(struct ieee80211_hw *hw, | |||
246 | 260 | ||
247 | for (i = 0; i < max_spatial_stream; i++) { | 261 | for (i = 0; i < max_spatial_stream; i++) { |
248 | evm = rtl_evm_db_to_percentage(p_phystrpt->rxevm[i]); | 262 | evm = rtl_evm_db_to_percentage(p_phystrpt->rxevm[i]); |
249 | evmdbm = rtl_evm_dbm_jaguar(p_phystrpt->rxevm[i]); | 263 | evmdbm = _rtl8821ae_evm_dbm_jaguar(p_phystrpt->rxevm[i]); |
250 | 264 | ||
251 | if (bpacket_match_bssid) { | 265 | if (bpacket_match_bssid) { |
252 | /* Fill value in RFD, Get the first | 266 | /* Fill value in RFD, Get the first |
diff --git a/drivers/net/wireless/rtlwifi/stats.c b/drivers/net/wireless/rtlwifi/stats.c index 2d0736a09fc0..d8b30690b00d 100644 --- a/drivers/net/wireless/rtlwifi/stats.c +++ b/drivers/net/wireless/rtlwifi/stats.c | |||
@@ -39,15 +39,8 @@ EXPORT_SYMBOL(rtl_query_rxpwrpercentage); | |||
39 | 39 | ||
40 | u8 rtl_evm_db_to_percentage(char value) | 40 | u8 rtl_evm_db_to_percentage(char value) |
41 | { | 41 | { |
42 | char ret_val; | 42 | char ret_val = clamp(-value, 0, 33) * 3; |
43 | ret_val = value; | ||
44 | 43 | ||
45 | if (ret_val >= 0) | ||
46 | ret_val = 0; | ||
47 | if (ret_val <= -33) | ||
48 | ret_val = -33; | ||
49 | ret_val = 0 - ret_val; | ||
50 | ret_val *= 3; | ||
51 | if (ret_val == 99) | 44 | if (ret_val == 99) |
52 | ret_val = 100; | 45 | ret_val = 100; |
53 | 46 | ||
@@ -55,21 +48,6 @@ u8 rtl_evm_db_to_percentage(char value) | |||
55 | } | 48 | } |
56 | EXPORT_SYMBOL(rtl_evm_db_to_percentage); | 49 | EXPORT_SYMBOL(rtl_evm_db_to_percentage); |
57 | 50 | ||
58 | u8 rtl_evm_dbm_jaguar(char value) | ||
59 | { | ||
60 | char ret_val = value; | ||
61 | |||
62 | /* -33dB~0dB to 33dB ~ 0dB*/ | ||
63 | if (ret_val == -128) | ||
64 | ret_val = 127; | ||
65 | else if (ret_val < 0) | ||
66 | ret_val = 0 - ret_val; | ||
67 | |||
68 | ret_val = ret_val >> 1; | ||
69 | return ret_val; | ||
70 | } | ||
71 | EXPORT_SYMBOL(rtl_evm_dbm_jaguar); | ||
72 | |||
73 | static long rtl_translate_todbm(struct ieee80211_hw *hw, | 51 | static long rtl_translate_todbm(struct ieee80211_hw *hw, |
74 | u8 signal_strength_index) | 52 | u8 signal_strength_index) |
75 | { | 53 | { |
diff --git a/drivers/net/wireless/rtlwifi/stats.h b/drivers/net/wireless/rtlwifi/stats.h index aa4eec80ccf7..2b57dffef572 100644 --- a/drivers/net/wireless/rtlwifi/stats.h +++ b/drivers/net/wireless/rtlwifi/stats.h | |||
@@ -35,7 +35,6 @@ | |||
35 | 35 | ||
36 | u8 rtl_query_rxpwrpercentage(char antpower); | 36 | u8 rtl_query_rxpwrpercentage(char antpower); |
37 | u8 rtl_evm_db_to_percentage(char value); | 37 | u8 rtl_evm_db_to_percentage(char value); |
38 | u8 rtl_evm_dbm_jaguar(char value); | ||
39 | long rtl_signal_scale_mapping(struct ieee80211_hw *hw, long currsig); | 38 | long rtl_signal_scale_mapping(struct ieee80211_hw *hw, long currsig); |
40 | void rtl_process_phyinfo(struct ieee80211_hw *hw, u8 *buffer, | 39 | void rtl_process_phyinfo(struct ieee80211_hw *hw, u8 *buffer, |
41 | struct rtl_stats *pstatus); | 40 | struct rtl_stats *pstatus); |
diff --git a/drivers/net/wireless/ti/wl18xx/debugfs.c b/drivers/net/wireless/ti/wl18xx/debugfs.c index c93fae95baac..5fbd2230f372 100644 --- a/drivers/net/wireless/ti/wl18xx/debugfs.c +++ b/drivers/net/wireless/ti/wl18xx/debugfs.c | |||
@@ -139,7 +139,7 @@ WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, protection_filter, "%u"); | |||
139 | WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, accum_arp_pend_requests, "%u"); | 139 | WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, accum_arp_pend_requests, "%u"); |
140 | WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, max_arp_queue_dep, "%u"); | 140 | WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, max_arp_queue_dep, "%u"); |
141 | 141 | ||
142 | WL18XX_DEBUGFS_FWSTATS_FILE(rx_rate, rx_frames_per_rates, "%u"); | 142 | WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(rx_rate, rx_frames_per_rates, 50); |
143 | 143 | ||
144 | WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(aggr_size, tx_agg_vs_rate, | 144 | WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(aggr_size, tx_agg_vs_rate, |
145 | AGGR_STATS_TX_AGG*AGGR_STATS_TX_RATE); | 145 | AGGR_STATS_TX_AGG*AGGR_STATS_TX_RATE); |
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.h b/drivers/net/wireless/ti/wlcore/debugfs.h index 0f2cfb0d2a9e..bf14676e6515 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.h +++ b/drivers/net/wireless/ti/wlcore/debugfs.h | |||
@@ -26,8 +26,8 @@ | |||
26 | 26 | ||
27 | #include "wlcore.h" | 27 | #include "wlcore.h" |
28 | 28 | ||
29 | int wl1271_format_buffer(char __user *userbuf, size_t count, | 29 | __printf(4, 5) int wl1271_format_buffer(char __user *userbuf, size_t count, |
30 | loff_t *ppos, char *fmt, ...); | 30 | loff_t *ppos, char *fmt, ...); |
31 | 31 | ||
32 | int wl1271_debugfs_init(struct wl1271 *wl); | 32 | int wl1271_debugfs_init(struct wl1271 *wl); |
33 | void wl1271_debugfs_exit(struct wl1271 *wl); | 33 | void wl1271_debugfs_exit(struct wl1271 *wl); |