diff options
author | David S. Miller <davem@davemloft.net> | 2008-08-29 17:02:13 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-08-29 17:02:13 -0400 |
commit | 143b11c03cd42f2284efe5128afc057d8fc86c78 (patch) | |
tree | 8186830c461b7933c26cdd00b69e4c737c5c88e7 /drivers | |
parent | af01d537463714e36e2c96d2da35902b76cd6827 (diff) | |
parent | 18c8adeb0244f823ba78a51e23f813fe68bc3c54 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers')
72 files changed, 7384 insertions, 6535 deletions
diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index d1b0fbae5a32..28b8d84f49b4 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h | |||
@@ -144,6 +144,7 @@ struct ath_desc { | |||
144 | #define ATH9K_TXDESC_EXT_AND_CTL 0x0080 | 144 | #define ATH9K_TXDESC_EXT_AND_CTL 0x0080 |
145 | #define ATH9K_TXDESC_VMF 0x0100 | 145 | #define ATH9K_TXDESC_VMF 0x0100 |
146 | #define ATH9K_TXDESC_FRAG_IS_ON 0x0200 | 146 | #define ATH9K_TXDESC_FRAG_IS_ON 0x0200 |
147 | #define ATH9K_TXDESC_CAB 0x0400 | ||
147 | 148 | ||
148 | #define ATH9K_RXDESC_INTREQ 0x0020 | 149 | #define ATH9K_RXDESC_INTREQ 0x0020 |
149 | 150 | ||
@@ -564,8 +565,6 @@ enum ath9k_cipher { | |||
564 | #define CTL_5GHT40 8 | 565 | #define CTL_5GHT40 8 |
565 | 566 | ||
566 | #define AR_EEPROM_MAC(i) (0x1d+(i)) | 567 | #define AR_EEPROM_MAC(i) (0x1d+(i)) |
567 | #define EEP_SCALE 100 | ||
568 | #define EEP_DELTA 10 | ||
569 | 568 | ||
570 | #define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c | 569 | #define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c |
571 | #define AR_EEPROM_RFSILENT_GPIO_SEL_S 2 | 570 | #define AR_EEPROM_RFSILENT_GPIO_SEL_S 2 |
@@ -606,9 +605,6 @@ struct ath9k_country_entry { | |||
606 | #define REG_CLR_BIT(_a, _r, _f) \ | 605 | #define REG_CLR_BIT(_a, _r, _f) \ |
607 | REG_WRITE(_a, _r, REG_READ(_a, _r) & ~_f) | 606 | REG_WRITE(_a, _r, REG_READ(_a, _r) & ~_f) |
608 | 607 | ||
609 | #define ATH9K_COMP_BUF_MAX_SIZE 9216 | ||
610 | #define ATH9K_COMP_BUF_ALIGN_SIZE 512 | ||
611 | |||
612 | #define ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS 0x00000001 | 608 | #define ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS 0x00000001 |
613 | 609 | ||
614 | #define INIT_AIFS 2 | 610 | #define INIT_AIFS 2 |
@@ -632,12 +628,6 @@ struct ath9k_country_entry { | |||
632 | (IEEE80211_WEP_IVLEN + \ | 628 | (IEEE80211_WEP_IVLEN + \ |
633 | IEEE80211_WEP_KIDLEN + \ | 629 | IEEE80211_WEP_KIDLEN + \ |
634 | IEEE80211_WEP_CRCLEN)) | 630 | IEEE80211_WEP_CRCLEN)) |
635 | #define IEEE80211_MAX_LEN (2300 + FCS_LEN + \ | ||
636 | (IEEE80211_WEP_IVLEN + \ | ||
637 | IEEE80211_WEP_KIDLEN + \ | ||
638 | IEEE80211_WEP_CRCLEN)) | ||
639 | |||
640 | #define MAX_REG_ADD_COUNT 129 | ||
641 | #define MAX_RATE_POWER 63 | 631 | #define MAX_RATE_POWER 63 |
642 | 632 | ||
643 | enum ath9k_power_mode { | 633 | enum ath9k_power_mode { |
@@ -707,13 +697,6 @@ enum phytype { | |||
707 | }; | 697 | }; |
708 | #define PHY_CCK PHY_DS | 698 | #define PHY_CCK PHY_DS |
709 | 699 | ||
710 | enum start_adhoc_option { | ||
711 | START_ADHOC_NO_11A, | ||
712 | START_ADHOC_PER_11D, | ||
713 | START_ADHOC_IN_11A, | ||
714 | START_ADHOC_IN_11B, | ||
715 | }; | ||
716 | |||
717 | enum ath9k_tp_scale { | 700 | enum ath9k_tp_scale { |
718 | ATH9K_TP_SCALE_MAX = 0, | 701 | ATH9K_TP_SCALE_MAX = 0, |
719 | ATH9K_TP_SCALE_50, | 702 | ATH9K_TP_SCALE_50, |
@@ -769,14 +752,11 @@ struct ath9k_node_stats { | |||
769 | 752 | ||
770 | #define ATH9K_RSSI_EP_MULTIPLIER (1<<7) | 753 | #define ATH9K_RSSI_EP_MULTIPLIER (1<<7) |
771 | 754 | ||
772 | enum ath9k_gpio_output_mux_type { | 755 | #define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0 |
773 | ATH9K_GPIO_OUTPUT_MUX_AS_OUTPUT, | 756 | #define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1 |
774 | ATH9K_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED, | 757 | #define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2 |
775 | ATH9K_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED, | 758 | #define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5 |
776 | ATH9K_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED, | 759 | #define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6 |
777 | ATH9K_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED, | ||
778 | ATH9K_GPIO_OUTPUT_MUX_NUM_ENTRIES | ||
779 | }; | ||
780 | 760 | ||
781 | enum { | 761 | enum { |
782 | ATH9K_RESET_POWER_ON, | 762 | ATH9K_RESET_POWER_ON, |
@@ -790,19 +770,20 @@ struct ath_hal { | |||
790 | u32 ah_magic; | 770 | u32 ah_magic; |
791 | u16 ah_devid; | 771 | u16 ah_devid; |
792 | u16 ah_subvendorid; | 772 | u16 ah_subvendorid; |
793 | struct ath_softc *ah_sc; | ||
794 | void __iomem *ah_sh; | ||
795 | u16 ah_countryCode; | ||
796 | u32 ah_macVersion; | 773 | u32 ah_macVersion; |
797 | u16 ah_macRev; | 774 | u16 ah_macRev; |
798 | u16 ah_phyRev; | 775 | u16 ah_phyRev; |
799 | u16 ah_analog5GhzRev; | 776 | u16 ah_analog5GhzRev; |
800 | u16 ah_analog2GhzRev; | 777 | u16 ah_analog2GhzRev; |
801 | u8 ah_decompMask[ATH9K_DECOMP_MASK_SIZE]; | 778 | |
802 | u32 ah_flags; | 779 | void __iomem *ah_sh; |
780 | struct ath_softc *ah_sc; | ||
803 | enum ath9k_opmode ah_opmode; | 781 | enum ath9k_opmode ah_opmode; |
804 | struct ath9k_ops_config ah_config; | 782 | struct ath9k_ops_config ah_config; |
805 | struct ath9k_hw_capabilities ah_caps; | 783 | struct ath9k_hw_capabilities ah_caps; |
784 | |||
785 | u16 ah_countryCode; | ||
786 | u32 ah_flags; | ||
806 | int16_t ah_powerLimit; | 787 | int16_t ah_powerLimit; |
807 | u16 ah_maxPowerLevel; | 788 | u16 ah_maxPowerLevel; |
808 | u32 ah_tpScale; | 789 | u32 ah_tpScale; |
@@ -812,15 +793,16 @@ struct ath_hal { | |||
812 | u16 ah_currentRD5G; | 793 | u16 ah_currentRD5G; |
813 | u16 ah_currentRD2G; | 794 | u16 ah_currentRD2G; |
814 | char ah_iso[4]; | 795 | char ah_iso[4]; |
815 | enum start_adhoc_option ah_adHocMode; | 796 | |
816 | bool ah_commonMode; | ||
817 | struct ath9k_channel ah_channels[150]; | 797 | struct ath9k_channel ah_channels[150]; |
818 | u32 ah_nchan; | ||
819 | struct ath9k_channel *ah_curchan; | 798 | struct ath9k_channel *ah_curchan; |
799 | u32 ah_nchan; | ||
800 | |||
820 | u16 ah_rfsilent; | 801 | u16 ah_rfsilent; |
821 | bool ah_rfkillEnabled; | 802 | bool ah_rfkillEnabled; |
822 | bool ah_isPciExpress; | 803 | bool ah_isPciExpress; |
823 | u16 ah_txTrigLevel; | 804 | u16 ah_txTrigLevel; |
805 | |||
824 | #ifndef ATH_NF_PER_CHAN | 806 | #ifndef ATH_NF_PER_CHAN |
825 | struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; | 807 | struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; |
826 | #endif | 808 | #endif |
@@ -853,7 +835,7 @@ bool ath9k_regd_init_channels(struct ath_hal *ah, | |||
853 | u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags); | 835 | u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags); |
854 | enum ath9k_int ath9k_hw_set_interrupts(struct ath_hal *ah, | 836 | enum ath9k_int ath9k_hw_set_interrupts(struct ath_hal *ah, |
855 | enum ath9k_int ints); | 837 | enum ath9k_int ints); |
856 | bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode, | 838 | bool ath9k_hw_reset(struct ath_hal *ah, |
857 | struct ath9k_channel *chan, | 839 | struct ath9k_channel *chan, |
858 | enum ath9k_ht_macmode macmode, | 840 | enum ath9k_ht_macmode macmode, |
859 | u8 txchainmask, u8 rxchainmask, | 841 | u8 txchainmask, u8 rxchainmask, |
@@ -1018,4 +1000,7 @@ void ath9k_hw_get_channel_centers(struct ath_hal *ah, | |||
1018 | bool ath9k_get_channel_edges(struct ath_hal *ah, | 1000 | bool ath9k_get_channel_edges(struct ath_hal *ah, |
1019 | u16 flags, u16 *low, | 1001 | u16 flags, u16 *low, |
1020 | u16 *high); | 1002 | u16 *high); |
1003 | void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio, | ||
1004 | u32 ah_signal_type); | ||
1005 | void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 value); | ||
1021 | #endif | 1006 | #endif |
diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c index caf569401a34..c43fd5861163 100644 --- a/drivers/net/wireless/ath9k/beacon.c +++ b/drivers/net/wireless/ath9k/beacon.c | |||
@@ -33,7 +33,7 @@ static int ath_beaconq_config(struct ath_softc *sc) | |||
33 | struct ath9k_tx_queue_info qi; | 33 | struct ath9k_tx_queue_info qi; |
34 | 34 | ||
35 | ath9k_hw_get_txq_props(ah, sc->sc_bhalq, &qi); | 35 | ath9k_hw_get_txq_props(ah, sc->sc_bhalq, &qi); |
36 | if (sc->sc_opmode == ATH9K_M_HOSTAP) { | 36 | if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) { |
37 | /* Always burst out beacon and CAB traffic. */ | 37 | /* Always burst out beacon and CAB traffic. */ |
38 | qi.tqi_aifs = 1; | 38 | qi.tqi_aifs = 1; |
39 | qi.tqi_cwmin = 0; | 39 | qi.tqi_cwmin = 0; |
@@ -85,7 +85,7 @@ static void ath_beacon_setup(struct ath_softc *sc, | |||
85 | 85 | ||
86 | flags = ATH9K_TXDESC_NOACK; | 86 | flags = ATH9K_TXDESC_NOACK; |
87 | 87 | ||
88 | if (sc->sc_opmode == ATH9K_M_IBSS && | 88 | if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS && |
89 | (ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) { | 89 | (ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) { |
90 | ds->ds_link = bf->bf_daddr; /* self-linked */ | 90 | ds->ds_link = bf->bf_daddr; /* self-linked */ |
91 | flags |= ATH9K_TXDESC_VEOL; | 91 | flags |= ATH9K_TXDESC_VEOL; |
@@ -111,24 +111,24 @@ static void ath_beacon_setup(struct ath_softc *sc, | |||
111 | rix = 0; | 111 | rix = 0; |
112 | rt = sc->sc_currates; | 112 | rt = sc->sc_currates; |
113 | rate = rt->info[rix].rateCode; | 113 | rate = rt->info[rix].rateCode; |
114 | if (sc->sc_flags & ATH_PREAMBLE_SHORT) | 114 | if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) |
115 | rate |= rt->info[rix].shortPreamble; | 115 | rate |= rt->info[rix].shortPreamble; |
116 | 116 | ||
117 | ath9k_hw_set11n_txdesc(ah, ds | 117 | ath9k_hw_set11n_txdesc(ah, ds, |
118 | , skb->len + FCS_LEN /* frame length */ | 118 | skb->len + FCS_LEN, /* frame length */ |
119 | , ATH9K_PKT_TYPE_BEACON /* Atheros packet type */ | 119 | ATH9K_PKT_TYPE_BEACON, /* Atheros packet type */ |
120 | , avp->av_btxctl.txpower /* txpower XXX */ | 120 | avp->av_btxctl.txpower, /* txpower XXX */ |
121 | , ATH9K_TXKEYIX_INVALID /* no encryption */ | 121 | ATH9K_TXKEYIX_INVALID, /* no encryption */ |
122 | , ATH9K_KEY_TYPE_CLEAR /* no encryption */ | 122 | ATH9K_KEY_TYPE_CLEAR, /* no encryption */ |
123 | , flags /* no ack, veol for beacons */ | 123 | flags /* no ack, veol for beacons */ |
124 | ); | 124 | ); |
125 | 125 | ||
126 | /* NB: beacon's BufLen must be a multiple of 4 bytes */ | 126 | /* NB: beacon's BufLen must be a multiple of 4 bytes */ |
127 | ath9k_hw_filltxdesc(ah, ds | 127 | ath9k_hw_filltxdesc(ah, ds, |
128 | , roundup(skb->len, 4) /* buffer length */ | 128 | roundup(skb->len, 4), /* buffer length */ |
129 | , true /* first segment */ | 129 | true, /* first segment */ |
130 | , true /* last segment */ | 130 | true, /* last segment */ |
131 | , ds /* first descriptor */ | 131 | ds /* first descriptor */ |
132 | ); | 132 | ); |
133 | 133 | ||
134 | memzero(series, sizeof(struct ath9k_11n_rate_series) * 4); | 134 | memzero(series, sizeof(struct ath9k_11n_rate_series) * 4); |
@@ -140,55 +140,6 @@ static void ath_beacon_setup(struct ath_softc *sc, | |||
140 | ctsrate, ctsduration, series, 4, 0); | 140 | ctsrate, ctsduration, series, 4, 0); |
141 | } | 141 | } |
142 | 142 | ||
143 | /* Move everything from the vap's mcast queue to the hardware cab queue. | ||
144 | * Caller must hold mcasq lock and cabq lock | ||
145 | * XXX MORE_DATA bit? | ||
146 | */ | ||
147 | static void empty_mcastq_into_cabq(struct ath_hal *ah, | ||
148 | struct ath_txq *mcastq, struct ath_txq *cabq) | ||
149 | { | ||
150 | struct ath_buf *bfmcast; | ||
151 | |||
152 | BUG_ON(list_empty(&mcastq->axq_q)); | ||
153 | |||
154 | bfmcast = list_first_entry(&mcastq->axq_q, struct ath_buf, list); | ||
155 | |||
156 | /* link the descriptors */ | ||
157 | if (!cabq->axq_link) | ||
158 | ath9k_hw_puttxbuf(ah, cabq->axq_qnum, bfmcast->bf_daddr); | ||
159 | else | ||
160 | *cabq->axq_link = bfmcast->bf_daddr; | ||
161 | |||
162 | /* append the private vap mcast list to the cabq */ | ||
163 | |||
164 | cabq->axq_depth += mcastq->axq_depth; | ||
165 | cabq->axq_totalqueued += mcastq->axq_totalqueued; | ||
166 | cabq->axq_linkbuf = mcastq->axq_linkbuf; | ||
167 | cabq->axq_link = mcastq->axq_link; | ||
168 | list_splice_tail_init(&mcastq->axq_q, &cabq->axq_q); | ||
169 | mcastq->axq_depth = 0; | ||
170 | mcastq->axq_totalqueued = 0; | ||
171 | mcastq->axq_linkbuf = NULL; | ||
172 | mcastq->axq_link = NULL; | ||
173 | } | ||
174 | |||
175 | /* This is only run at DTIM. We move everything from the vap's mcast queue | ||
176 | * to the hardware cab queue. Caller must hold the mcastq lock. */ | ||
177 | static void trigger_mcastq(struct ath_hal *ah, | ||
178 | struct ath_txq *mcastq, struct ath_txq *cabq) | ||
179 | { | ||
180 | spin_lock_bh(&cabq->axq_lock); | ||
181 | |||
182 | if (!list_empty(&mcastq->axq_q)) | ||
183 | empty_mcastq_into_cabq(ah, mcastq, cabq); | ||
184 | |||
185 | /* cabq is gated by beacon so it is safe to start here */ | ||
186 | if (!list_empty(&cabq->axq_q)) | ||
187 | ath9k_hw_txstart(ah, cabq->axq_qnum); | ||
188 | |||
189 | spin_unlock_bh(&cabq->axq_lock); | ||
190 | } | ||
191 | |||
192 | /* | 143 | /* |
193 | * Generate beacon frame and queue cab data for a vap. | 144 | * Generate beacon frame and queue cab data for a vap. |
194 | * | 145 | * |
@@ -199,19 +150,14 @@ static void trigger_mcastq(struct ath_hal *ah, | |||
199 | */ | 150 | */ |
200 | static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) | 151 | static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) |
201 | { | 152 | { |
202 | struct ath_hal *ah = sc->sc_ah; | ||
203 | struct ath_buf *bf; | 153 | struct ath_buf *bf; |
204 | struct ath_vap *avp; | 154 | struct ath_vap *avp; |
205 | struct sk_buff *skb; | 155 | struct sk_buff *skb; |
206 | int cabq_depth; | 156 | int cabq_depth; |
207 | int mcastq_depth; | ||
208 | int is_beacon_dtim = 0; | ||
209 | unsigned int curlen; | ||
210 | struct ath_txq *cabq; | 157 | struct ath_txq *cabq; |
211 | struct ath_txq *mcastq; | 158 | struct ieee80211_tx_info *info; |
212 | avp = sc->sc_vaps[if_id]; | 159 | avp = sc->sc_vaps[if_id]; |
213 | 160 | ||
214 | mcastq = &avp->av_mcastq; | ||
215 | cabq = sc->sc_cabq; | 161 | cabq = sc->sc_cabq; |
216 | 162 | ||
217 | ASSERT(avp); | 163 | ASSERT(avp); |
@@ -223,32 +169,33 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) | |||
223 | } | 169 | } |
224 | bf = avp->av_bcbuf; | 170 | bf = avp->av_bcbuf; |
225 | skb = (struct sk_buff *) bf->bf_mpdu; | 171 | skb = (struct sk_buff *) bf->bf_mpdu; |
172 | if (skb) { | ||
173 | pci_unmap_single(sc->pdev, bf->bf_dmacontext, | ||
174 | skb_end_pointer(skb) - skb->head, | ||
175 | PCI_DMA_TODEVICE); | ||
176 | } | ||
226 | 177 | ||
227 | /* | 178 | skb = ieee80211_beacon_get(sc->hw, avp->av_if_data); |
228 | * Update dynamic beacon contents. If this returns | 179 | bf->bf_mpdu = skb; |
229 | * non-zero then we need to remap the memory because | 180 | if (skb == NULL) |
230 | * the beacon frame changed size (probably because | 181 | return NULL; |
231 | * of the TIM bitmap). | 182 | info = IEEE80211_SKB_CB(skb); |
232 | */ | 183 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { |
233 | curlen = skb->len; | 184 | /* |
234 | 185 | * TODO: make sure the seq# gets assigned properly (vs. other | |
235 | /* XXX: spin_lock_bh should not be used here, but sparse bitches | 186 | * TX frames) |
236 | * otherwise. We should fix sparse :) */ | 187 | */ |
237 | spin_lock_bh(&mcastq->axq_lock); | 188 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
238 | mcastq_depth = avp->av_mcastq.axq_depth; | 189 | sc->seq_no += 0x10; |
239 | 190 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | |
240 | if (ath_update_beacon(sc, if_id, &avp->av_boff, skb, mcastq_depth) == | 191 | hdr->seq_ctrl |= cpu_to_le16(sc->seq_no); |
241 | 1) { | ||
242 | ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE, | ||
243 | get_dma_mem_context(bf, bf_dmacontext)); | ||
244 | bf->bf_buf_addr = ath_skb_map_single(sc, skb, PCI_DMA_TODEVICE, | ||
245 | get_dma_mem_context(bf, bf_dmacontext)); | ||
246 | } else { | ||
247 | pci_dma_sync_single_for_cpu(sc->pdev, | ||
248 | bf->bf_buf_addr, | ||
249 | skb_tailroom(skb), | ||
250 | PCI_DMA_TODEVICE); | ||
251 | } | 192 | } |
193 | bf->bf_buf_addr = bf->bf_dmacontext = | ||
194 | pci_map_single(sc->pdev, skb->data, | ||
195 | skb_end_pointer(skb) - skb->head, | ||
196 | PCI_DMA_TODEVICE); | ||
197 | |||
198 | skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data); | ||
252 | 199 | ||
253 | /* | 200 | /* |
254 | * if the CABQ traffic from previous DTIM is pending and the current | 201 | * if the CABQ traffic from previous DTIM is pending and the current |
@@ -262,9 +209,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) | |||
262 | cabq_depth = cabq->axq_depth; | 209 | cabq_depth = cabq->axq_depth; |
263 | spin_unlock_bh(&cabq->axq_lock); | 210 | spin_unlock_bh(&cabq->axq_lock); |
264 | 211 | ||
265 | is_beacon_dtim = avp->av_boff.bo_tim[4] & 1; | 212 | if (skb && cabq_depth) { |
266 | |||
267 | if (mcastq_depth && is_beacon_dtim && cabq_depth) { | ||
268 | /* | 213 | /* |
269 | * Unlock the cabq lock as ath_tx_draintxq acquires | 214 | * Unlock the cabq lock as ath_tx_draintxq acquires |
270 | * the lock again which is a common function and that | 215 | * the lock again which is a common function and that |
@@ -284,10 +229,11 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) | |||
284 | * Enable the CAB queue before the beacon queue to | 229 | * Enable the CAB queue before the beacon queue to |
285 | * insure cab frames are triggered by this beacon. | 230 | * insure cab frames are triggered by this beacon. |
286 | */ | 231 | */ |
287 | if (is_beacon_dtim) | 232 | while (skb) { |
288 | trigger_mcastq(ah, mcastq, cabq); | 233 | ath_tx_cabq(sc, skb); |
234 | skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data); | ||
235 | } | ||
289 | 236 | ||
290 | spin_unlock_bh(&mcastq->axq_lock); | ||
291 | return bf; | 237 | return bf; |
292 | } | 238 | } |
293 | 239 | ||
@@ -375,7 +321,7 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) | |||
375 | struct ath_buf, list); | 321 | struct ath_buf, list); |
376 | list_del(&avp->av_bcbuf->list); | 322 | list_del(&avp->av_bcbuf->list); |
377 | 323 | ||
378 | if (sc->sc_opmode == ATH9K_M_HOSTAP || | 324 | if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP || |
379 | !(sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) { | 325 | !(sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) { |
380 | int slot; | 326 | int slot; |
381 | /* | 327 | /* |
@@ -408,8 +354,9 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) | |||
408 | bf = avp->av_bcbuf; | 354 | bf = avp->av_bcbuf; |
409 | if (bf->bf_mpdu != NULL) { | 355 | if (bf->bf_mpdu != NULL) { |
410 | skb = (struct sk_buff *)bf->bf_mpdu; | 356 | skb = (struct sk_buff *)bf->bf_mpdu; |
411 | ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE, | 357 | pci_unmap_single(sc->pdev, bf->bf_dmacontext, |
412 | get_dma_mem_context(bf, bf_dmacontext)); | 358 | skb_end_pointer(skb) - skb->head, |
359 | PCI_DMA_TODEVICE); | ||
413 | dev_kfree_skb_any(skb); | 360 | dev_kfree_skb_any(skb); |
414 | bf->bf_mpdu = NULL; | 361 | bf->bf_mpdu = NULL; |
415 | } | 362 | } |
@@ -418,7 +365,7 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) | |||
418 | * NB: the beacon data buffer must be 32-bit aligned; | 365 | * NB: the beacon data buffer must be 32-bit aligned; |
419 | * we assume the wbuf routines will return us something | 366 | * we assume the wbuf routines will return us something |
420 | * with this alignment (perhaps should assert). | 367 | * with this alignment (perhaps should assert). |
421 | * FIXME: Fill avp->av_boff.bo_tim,avp->av_btxctl.txpower and | 368 | * FIXME: Fill avp->av_btxctl.txpower and |
422 | * avp->av_btxctl.shortPreamble | 369 | * avp->av_btxctl.shortPreamble |
423 | */ | 370 | */ |
424 | skb = ieee80211_beacon_get(sc->hw, avp->av_if_data); | 371 | skb = ieee80211_beacon_get(sc->hw, avp->av_if_data); |
@@ -439,9 +386,8 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) | |||
439 | __le64 val; | 386 | __le64 val; |
440 | int intval; | 387 | int intval; |
441 | 388 | ||
442 | /* FIXME: Use default value for now: Sujith */ | 389 | intval = sc->hw->conf.beacon_int ? |
443 | 390 | sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; | |
444 | intval = ATH_DEFAULT_BINTVAL; | ||
445 | 391 | ||
446 | /* | 392 | /* |
447 | * The beacon interval is in TU's; the TSF in usecs. | 393 | * The beacon interval is in TU's; the TSF in usecs. |
@@ -466,8 +412,10 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) | |||
466 | memcpy(&wh[1], &val, sizeof(val)); | 412 | memcpy(&wh[1], &val, sizeof(val)); |
467 | } | 413 | } |
468 | 414 | ||
469 | bf->bf_buf_addr = ath_skb_map_single(sc, skb, PCI_DMA_TODEVICE, | 415 | bf->bf_buf_addr = bf->bf_dmacontext = |
470 | get_dma_mem_context(bf, bf_dmacontext)); | 416 | pci_map_single(sc->pdev, skb->data, |
417 | skb_end_pointer(skb) - skb->head, | ||
418 | PCI_DMA_TODEVICE); | ||
471 | bf->bf_mpdu = skb; | 419 | bf->bf_mpdu = skb; |
472 | 420 | ||
473 | return 0; | 421 | return 0; |
@@ -493,8 +441,9 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp) | |||
493 | bf = avp->av_bcbuf; | 441 | bf = avp->av_bcbuf; |
494 | if (bf->bf_mpdu != NULL) { | 442 | if (bf->bf_mpdu != NULL) { |
495 | struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; | 443 | struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; |
496 | ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE, | 444 | pci_unmap_single(sc->pdev, bf->bf_dmacontext, |
497 | get_dma_mem_context(bf, bf_dmacontext)); | 445 | skb_end_pointer(skb) - skb->head, |
446 | PCI_DMA_TODEVICE); | ||
498 | dev_kfree_skb_any(skb); | 447 | dev_kfree_skb_any(skb); |
499 | bf->bf_mpdu = NULL; | 448 | bf->bf_mpdu = NULL; |
500 | } | 449 | } |
@@ -505,30 +454,6 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp) | |||
505 | } | 454 | } |
506 | 455 | ||
507 | /* | 456 | /* |
508 | * Reclaim beacon resources and return buffer to the pool. | ||
509 | * | ||
510 | * This function will free any wbuf frames that are still attached to the | ||
511 | * beacon buffers in the ATH object. Note that this does not de-allocate | ||
512 | * any wbuf objects that are in the transmit queue and have not yet returned | ||
513 | * to the ATH object. | ||
514 | */ | ||
515 | |||
516 | void ath_beacon_free(struct ath_softc *sc) | ||
517 | { | ||
518 | struct ath_buf *bf; | ||
519 | |||
520 | list_for_each_entry(bf, &sc->sc_bbuf, list) { | ||
521 | if (bf->bf_mpdu != NULL) { | ||
522 | struct sk_buff *skb = (struct sk_buff *) bf->bf_mpdu; | ||
523 | ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE, | ||
524 | get_dma_mem_context(bf, bf_dmacontext)); | ||
525 | dev_kfree_skb_any(skb); | ||
526 | bf->bf_mpdu = NULL; | ||
527 | } | ||
528 | } | ||
529 | } | ||
530 | |||
531 | /* | ||
532 | * Tasklet for Sending Beacons | 457 | * Tasklet for Sending Beacons |
533 | * | 458 | * |
534 | * Transmit one or more beacon frames at SWBA. Dynamic updates to the frame | 459 | * Transmit one or more beacon frames at SWBA. Dynamic updates to the frame |
@@ -540,9 +465,6 @@ void ath_beacon_free(struct ath_softc *sc) | |||
540 | 465 | ||
541 | void ath9k_beacon_tasklet(unsigned long data) | 466 | void ath9k_beacon_tasklet(unsigned long data) |
542 | { | 467 | { |
543 | #define TSF_TO_TU(_h,_l) \ | ||
544 | ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) | ||
545 | |||
546 | struct ath_softc *sc = (struct ath_softc *)data; | 468 | struct ath_softc *sc = (struct ath_softc *)data; |
547 | struct ath_hal *ah = sc->sc_ah; | 469 | struct ath_hal *ah = sc->sc_ah; |
548 | struct ath_buf *bf = NULL; | 470 | struct ath_buf *bf = NULL; |
@@ -555,7 +477,7 @@ void ath9k_beacon_tasklet(unsigned long data) | |||
555 | u32 tsftu; | 477 | u32 tsftu; |
556 | u16 intval; | 478 | u16 intval; |
557 | 479 | ||
558 | if (sc->sc_noreset) { | 480 | if (sc->sc_flags & SC_OP_NO_RESET) { |
559 | show_cycles = ath9k_hw_GetMibCycleCountsPct(ah, | 481 | show_cycles = ath9k_hw_GetMibCycleCountsPct(ah, |
560 | &rx_clear, | 482 | &rx_clear, |
561 | &rx_frame, | 483 | &rx_frame, |
@@ -577,7 +499,7 @@ void ath9k_beacon_tasklet(unsigned long data) | |||
577 | * (in that layer). | 499 | * (in that layer). |
578 | */ | 500 | */ |
579 | if (sc->sc_bmisscount < BSTUCK_THRESH) { | 501 | if (sc->sc_bmisscount < BSTUCK_THRESH) { |
580 | if (sc->sc_noreset) { | 502 | if (sc->sc_flags & SC_OP_NO_RESET) { |
581 | DPRINTF(sc, ATH_DBG_BEACON, | 503 | DPRINTF(sc, ATH_DBG_BEACON, |
582 | "%s: missed %u consecutive beacons\n", | 504 | "%s: missed %u consecutive beacons\n", |
583 | __func__, sc->sc_bmisscount); | 505 | __func__, sc->sc_bmisscount); |
@@ -605,7 +527,7 @@ void ath9k_beacon_tasklet(unsigned long data) | |||
605 | __func__, sc->sc_bmisscount); | 527 | __func__, sc->sc_bmisscount); |
606 | } | 528 | } |
607 | } else if (sc->sc_bmisscount >= BSTUCK_THRESH) { | 529 | } else if (sc->sc_bmisscount >= BSTUCK_THRESH) { |
608 | if (sc->sc_noreset) { | 530 | if (sc->sc_flags & SC_OP_NO_RESET) { |
609 | if (sc->sc_bmisscount == BSTUCK_THRESH) { | 531 | if (sc->sc_bmisscount == BSTUCK_THRESH) { |
610 | DPRINTF(sc, | 532 | DPRINTF(sc, |
611 | ATH_DBG_BEACON, | 533 | ATH_DBG_BEACON, |
@@ -624,7 +546,7 @@ void ath9k_beacon_tasklet(unsigned long data) | |||
624 | return; | 546 | return; |
625 | } | 547 | } |
626 | if (sc->sc_bmisscount != 0) { | 548 | if (sc->sc_bmisscount != 0) { |
627 | if (sc->sc_noreset) { | 549 | if (sc->sc_flags & SC_OP_NO_RESET) { |
628 | DPRINTF(sc, | 550 | DPRINTF(sc, |
629 | ATH_DBG_BEACON, | 551 | ATH_DBG_BEACON, |
630 | "%s: resume beacon xmit after %u misses\n", | 552 | "%s: resume beacon xmit after %u misses\n", |
@@ -643,8 +565,8 @@ void ath9k_beacon_tasklet(unsigned long data) | |||
643 | * on the tsf to safeguard against missing an swba. | 565 | * on the tsf to safeguard against missing an swba. |
644 | */ | 566 | */ |
645 | 567 | ||
646 | /* FIXME: Use default value for now - Sujith */ | 568 | intval = sc->hw->conf.beacon_int ? |
647 | intval = ATH_DEFAULT_BINTVAL; | 569 | sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; |
648 | 570 | ||
649 | tsf = ath9k_hw_gettsf64(ah); | 571 | tsf = ath9k_hw_gettsf64(ah); |
650 | tsftu = TSF_TO_TU(tsf>>32, tsf); | 572 | tsftu = TSF_TO_TU(tsf>>32, tsf); |
@@ -704,7 +626,6 @@ void ath9k_beacon_tasklet(unsigned long data) | |||
704 | 626 | ||
705 | sc->ast_be_xmit += bc; /* XXX per-vap? */ | 627 | sc->ast_be_xmit += bc; /* XXX per-vap? */ |
706 | } | 628 | } |
707 | #undef TSF_TO_TU | ||
708 | } | 629 | } |
709 | 630 | ||
710 | /* | 631 | /* |
@@ -719,7 +640,7 @@ void ath_bstuck_process(struct ath_softc *sc) | |||
719 | DPRINTF(sc, ATH_DBG_BEACON, | 640 | DPRINTF(sc, ATH_DBG_BEACON, |
720 | "%s: stuck beacon; resetting (bmiss count %u)\n", | 641 | "%s: stuck beacon; resetting (bmiss count %u)\n", |
721 | __func__, sc->sc_bmisscount); | 642 | __func__, sc->sc_bmisscount); |
722 | ath_internal_reset(sc); | 643 | ath_reset(sc, false); |
723 | } | 644 | } |
724 | 645 | ||
725 | /* | 646 | /* |
@@ -740,8 +661,6 @@ void ath_bstuck_process(struct ath_softc *sc) | |||
740 | 661 | ||
741 | void ath_beacon_config(struct ath_softc *sc, int if_id) | 662 | void ath_beacon_config(struct ath_softc *sc, int if_id) |
742 | { | 663 | { |
743 | #define TSF_TO_TU(_h,_l) \ | ||
744 | ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) | ||
745 | struct ath_hal *ah = sc->sc_ah; | 664 | struct ath_hal *ah = sc->sc_ah; |
746 | u32 nexttbtt, intval; | 665 | u32 nexttbtt, intval; |
747 | struct ath_beacon_config conf; | 666 | struct ath_beacon_config conf; |
@@ -750,7 +669,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) | |||
750 | if (if_id != ATH_IF_ID_ANY) | 669 | if (if_id != ATH_IF_ID_ANY) |
751 | av_opmode = sc->sc_vaps[if_id]->av_opmode; | 670 | av_opmode = sc->sc_vaps[if_id]->av_opmode; |
752 | else | 671 | else |
753 | av_opmode = sc->sc_opmode; | 672 | av_opmode = sc->sc_ah->ah_opmode; |
754 | 673 | ||
755 | memzero(&conf, sizeof(struct ath_beacon_config)); | 674 | memzero(&conf, sizeof(struct ath_beacon_config)); |
756 | 675 | ||
@@ -760,7 +679,8 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) | |||
760 | * Protocol stack doesn't support dynamic beacon configuration, | 679 | * Protocol stack doesn't support dynamic beacon configuration, |
761 | * use default configurations. | 680 | * use default configurations. |
762 | */ | 681 | */ |
763 | conf.beacon_interval = ATH_DEFAULT_BINTVAL; | 682 | conf.beacon_interval = sc->hw->conf.beacon_int ? |
683 | sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; | ||
764 | conf.listen_interval = 1; | 684 | conf.listen_interval = 1; |
765 | conf.dtim_period = conf.beacon_interval; | 685 | conf.dtim_period = conf.beacon_interval; |
766 | conf.dtim_count = 1; | 686 | conf.dtim_count = 1; |
@@ -770,7 +690,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) | |||
770 | nexttbtt = TSF_TO_TU(get_unaligned_le32(conf.u.last_tstamp + 4), | 690 | nexttbtt = TSF_TO_TU(get_unaligned_le32(conf.u.last_tstamp + 4), |
771 | get_unaligned_le32(conf.u.last_tstamp)); | 691 | get_unaligned_le32(conf.u.last_tstamp)); |
772 | /* XXX conditionalize multi-bss support? */ | 692 | /* XXX conditionalize multi-bss support? */ |
773 | if (sc->sc_opmode == ATH9K_M_HOSTAP) { | 693 | if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) { |
774 | /* | 694 | /* |
775 | * For multi-bss ap support beacons are either staggered | 695 | * For multi-bss ap support beacons are either staggered |
776 | * evenly over N slots or burst together. For the former | 696 | * evenly over N slots or burst together. For the former |
@@ -791,7 +711,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) | |||
791 | DPRINTF(sc, ATH_DBG_BEACON, "%s: nexttbtt %u intval %u (%u)\n", | 711 | DPRINTF(sc, ATH_DBG_BEACON, "%s: nexttbtt %u intval %u (%u)\n", |
792 | __func__, nexttbtt, intval, conf.beacon_interval); | 712 | __func__, nexttbtt, intval, conf.beacon_interval); |
793 | /* Check for ATH9K_M_HOSTAP and sc_nostabeacons for WDS client */ | 713 | /* Check for ATH9K_M_HOSTAP and sc_nostabeacons for WDS client */ |
794 | if (sc->sc_opmode == ATH9K_M_STA) { | 714 | if (sc->sc_ah->ah_opmode == ATH9K_M_STA) { |
795 | struct ath9k_beacon_state bs; | 715 | struct ath9k_beacon_state bs; |
796 | u64 tsf; | 716 | u64 tsf; |
797 | u32 tsftu; | 717 | u32 tsftu; |
@@ -886,19 +806,19 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) | |||
886 | "cfp:period %u " | 806 | "cfp:period %u " |
887 | "maxdur %u " | 807 | "maxdur %u " |
888 | "next %u " | 808 | "next %u " |
889 | "timoffset %u\n" | 809 | "timoffset %u\n", |
890 | , __func__ | 810 | __func__, |
891 | , (unsigned long long)tsf, tsftu | 811 | (unsigned long long)tsf, tsftu, |
892 | , bs.bs_intval | 812 | bs.bs_intval, |
893 | , bs.bs_nexttbtt | 813 | bs.bs_nexttbtt, |
894 | , bs.bs_dtimperiod | 814 | bs.bs_dtimperiod, |
895 | , bs.bs_nextdtim | 815 | bs.bs_nextdtim, |
896 | , bs.bs_bmissthreshold | 816 | bs.bs_bmissthreshold, |
897 | , bs.bs_sleepduration | 817 | bs.bs_sleepduration, |
898 | , bs.bs_cfpperiod | 818 | bs.bs_cfpperiod, |
899 | , bs.bs_cfpmaxduration | 819 | bs.bs_cfpmaxduration, |
900 | , bs.bs_cfpnext | 820 | bs.bs_cfpnext, |
901 | , bs.bs_timoffset | 821 | bs.bs_timoffset |
902 | ); | 822 | ); |
903 | 823 | ||
904 | ath9k_hw_set_interrupts(ah, 0); | 824 | ath9k_hw_set_interrupts(ah, 0); |
@@ -911,7 +831,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) | |||
911 | ath9k_hw_set_interrupts(ah, 0); | 831 | ath9k_hw_set_interrupts(ah, 0); |
912 | if (nexttbtt == intval) | 832 | if (nexttbtt == intval) |
913 | intval |= ATH9K_BEACON_RESET_TSF; | 833 | intval |= ATH9K_BEACON_RESET_TSF; |
914 | if (sc->sc_opmode == ATH9K_M_IBSS) { | 834 | if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS) { |
915 | /* | 835 | /* |
916 | * Pull nexttbtt forward to reflect the current | 836 | * Pull nexttbtt forward to reflect the current |
917 | * TSF . | 837 | * TSF . |
@@ -943,7 +863,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) | |||
943 | if (!(ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) | 863 | if (!(ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) |
944 | sc->sc_imask |= ATH9K_INT_SWBA; | 864 | sc->sc_imask |= ATH9K_INT_SWBA; |
945 | ath_beaconq_config(sc); | 865 | ath_beaconq_config(sc); |
946 | } else if (sc->sc_opmode == ATH9K_M_HOSTAP) { | 866 | } else if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) { |
947 | /* | 867 | /* |
948 | * In AP mode we enable the beacon timers and | 868 | * In AP mode we enable the beacon timers and |
949 | * SWBA interrupts to prepare beacon frames. | 869 | * SWBA interrupts to prepare beacon frames. |
@@ -959,11 +879,10 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) | |||
959 | * When using a self-linked beacon descriptor in | 879 | * When using a self-linked beacon descriptor in |
960 | * ibss mode load it once here. | 880 | * ibss mode load it once here. |
961 | */ | 881 | */ |
962 | if (sc->sc_opmode == ATH9K_M_IBSS && | 882 | if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS && |
963 | (ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) | 883 | (ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) |
964 | ath_beacon_start_adhoc(sc, 0); | 884 | ath_beacon_start_adhoc(sc, 0); |
965 | } | 885 | } |
966 | #undef TSF_TO_TU | ||
967 | } | 886 | } |
968 | 887 | ||
969 | /* Function to collect beacon rssi data and resync beacon if necessary */ | 888 | /* Function to collect beacon rssi data and resync beacon if necessary */ |
@@ -975,5 +894,5 @@ void ath_beacon_sync(struct ath_softc *sc, int if_id) | |||
975 | * beacon frame we just received. | 894 | * beacon frame we just received. |
976 | */ | 895 | */ |
977 | ath_beacon_config(sc, if_id); | 896 | ath_beacon_config(sc, if_id); |
978 | sc->sc_beacons = 1; | 897 | sc->sc_flags |= SC_OP_BEACONS; |
979 | } | 898 | } |
diff --git a/drivers/net/wireless/ath9k/core.c b/drivers/net/wireless/ath9k/core.c index f6c45288d0e7..c262ef279ff3 100644 --- a/drivers/net/wireless/ath9k/core.c +++ b/drivers/net/wireless/ath9k/core.c | |||
@@ -21,9 +21,6 @@ | |||
21 | 21 | ||
22 | static int ath_outdoor; /* enable outdoor use */ | 22 | static int ath_outdoor; /* enable outdoor use */ |
23 | 23 | ||
24 | static const u8 ath_bcast_mac[ETH_ALEN] = | ||
25 | { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
26 | |||
27 | static u32 ath_chainmask_sel_up_rssi_thres = | 24 | static u32 ath_chainmask_sel_up_rssi_thres = |
28 | ATH_CHAINMASK_SEL_UP_RSSI_THRES; | 25 | ATH_CHAINMASK_SEL_UP_RSSI_THRES; |
29 | static u32 ath_chainmask_sel_down_rssi_thres = | 26 | static u32 ath_chainmask_sel_down_rssi_thres = |
@@ -54,10 +51,8 @@ static void bus_read_cachesize(struct ath_softc *sc, int *csz) | |||
54 | * Set current operating mode | 51 | * Set current operating mode |
55 | * | 52 | * |
56 | * This function initializes and fills the rate table in the ATH object based | 53 | * This function initializes and fills the rate table in the ATH object based |
57 | * on the operating mode. The blink rates are also set up here, although | 54 | * on the operating mode. |
58 | * they have been superceeded by the ath_led module. | ||
59 | */ | 55 | */ |
60 | |||
61 | static void ath_setcurmode(struct ath_softc *sc, enum wireless_mode mode) | 56 | static void ath_setcurmode(struct ath_softc *sc, enum wireless_mode mode) |
62 | { | 57 | { |
63 | const struct ath9k_rate_table *rt; | 58 | const struct ath9k_rate_table *rt; |
@@ -235,7 +230,7 @@ static int ath_setup_channels(struct ath_softc *sc) | |||
235 | * Determine mode from channel flags | 230 | * Determine mode from channel flags |
236 | * | 231 | * |
237 | * This routine will provide the enumerated WIRELESSS_MODE value based | 232 | * This routine will provide the enumerated WIRELESSS_MODE value based |
238 | * on the settings of the channel flags. If ho valid set of flags | 233 | * on the settings of the channel flags. If no valid set of flags |
239 | * exist, the lowest mode (11b) is selected. | 234 | * exist, the lowest mode (11b) is selected. |
240 | */ | 235 | */ |
241 | 236 | ||
@@ -260,7 +255,8 @@ static enum wireless_mode ath_chan2mode(struct ath9k_channel *chan) | |||
260 | else if (chan->chanmode == CHANNEL_G_HT40MINUS) | 255 | else if (chan->chanmode == CHANNEL_G_HT40MINUS) |
261 | return ATH9K_MODE_11NG_HT40MINUS; | 256 | return ATH9K_MODE_11NG_HT40MINUS; |
262 | 257 | ||
263 | /* NB: should not get here */ | 258 | WARN_ON(1); /* should not get here */ |
259 | |||
264 | return ATH9K_MODE_11B; | 260 | return ATH9K_MODE_11B; |
265 | } | 261 | } |
266 | 262 | ||
@@ -275,14 +271,12 @@ static int ath_stop(struct ath_softc *sc) | |||
275 | { | 271 | { |
276 | struct ath_hal *ah = sc->sc_ah; | 272 | struct ath_hal *ah = sc->sc_ah; |
277 | 273 | ||
278 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: invalid %u\n", | 274 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: invalid %ld\n", |
279 | __func__, sc->sc_invalid); | 275 | __func__, sc->sc_flags & SC_OP_INVALID); |
280 | 276 | ||
281 | /* | 277 | /* |
282 | * Shutdown the hardware and driver: | 278 | * Shutdown the hardware and driver: |
283 | * stop output from above | 279 | * stop output from above |
284 | * reset 802.11 state machine | ||
285 | * (sends station deassoc/deauth frames) | ||
286 | * turn off timers | 280 | * turn off timers |
287 | * disable interrupts | 281 | * disable interrupts |
288 | * clear transmit machinery | 282 | * clear transmit machinery |
@@ -294,10 +288,10 @@ static int ath_stop(struct ath_softc *sc) | |||
294 | * hardware is gone (invalid). | 288 | * hardware is gone (invalid). |
295 | */ | 289 | */ |
296 | 290 | ||
297 | if (!sc->sc_invalid) | 291 | if (!(sc->sc_flags & SC_OP_INVALID)) |
298 | ath9k_hw_set_interrupts(ah, 0); | 292 | ath9k_hw_set_interrupts(ah, 0); |
299 | ath_draintxq(sc, false); | 293 | ath_draintxq(sc, false); |
300 | if (!sc->sc_invalid) { | 294 | if (!(sc->sc_flags & SC_OP_INVALID)) { |
301 | ath_stoprecv(sc); | 295 | ath_stoprecv(sc); |
302 | ath9k_hw_phy_disable(ah); | 296 | ath9k_hw_phy_disable(ah); |
303 | } else | 297 | } else |
@@ -307,56 +301,6 @@ static int ath_stop(struct ath_softc *sc) | |||
307 | } | 301 | } |
308 | 302 | ||
309 | /* | 303 | /* |
310 | * Start Scan | ||
311 | * | ||
312 | * This function is called when starting a channel scan. It will perform | ||
313 | * power save wakeup processing, set the filter for the scan, and get the | ||
314 | * chip ready to send broadcast packets out during the scan. | ||
315 | */ | ||
316 | |||
317 | void ath_scan_start(struct ath_softc *sc) | ||
318 | { | ||
319 | struct ath_hal *ah = sc->sc_ah; | ||
320 | u32 rfilt; | ||
321 | u32 now = (u32) jiffies_to_msecs(get_timestamp()); | ||
322 | |||
323 | sc->sc_scanning = 1; | ||
324 | rfilt = ath_calcrxfilter(sc); | ||
325 | ath9k_hw_setrxfilter(ah, rfilt); | ||
326 | ath9k_hw_write_associd(ah, ath_bcast_mac, 0); | ||
327 | |||
328 | /* Restore previous power management state. */ | ||
329 | |||
330 | DPRINTF(sc, ATH_DBG_CONFIG, "%d.%03d | %s: RX filter 0x%x aid 0\n", | ||
331 | now / 1000, now % 1000, __func__, rfilt); | ||
332 | } | ||
333 | |||
334 | /* | ||
335 | * Scan End | ||
336 | * | ||
337 | * This routine is called by the upper layer when the scan is completed. This | ||
338 | * will set the filters back to normal operating mode, set the BSSID to the | ||
339 | * correct value, and restore the power save state. | ||
340 | */ | ||
341 | |||
342 | void ath_scan_end(struct ath_softc *sc) | ||
343 | { | ||
344 | struct ath_hal *ah = sc->sc_ah; | ||
345 | u32 rfilt; | ||
346 | u32 now = (u32) jiffies_to_msecs(get_timestamp()); | ||
347 | |||
348 | sc->sc_scanning = 0; | ||
349 | /* Request for a full reset due to rx packet filter changes */ | ||
350 | sc->sc_full_reset = 1; | ||
351 | rfilt = ath_calcrxfilter(sc); | ||
352 | ath9k_hw_setrxfilter(ah, rfilt); | ||
353 | ath9k_hw_write_associd(ah, sc->sc_curbssid, sc->sc_curaid); | ||
354 | |||
355 | DPRINTF(sc, ATH_DBG_CONFIG, "%d.%03d | %s: RX filter 0x%x aid 0x%x\n", | ||
356 | now / 1000, now % 1000, __func__, rfilt, sc->sc_curaid); | ||
357 | } | ||
358 | |||
359 | /* | ||
360 | * Set the current channel | 304 | * Set the current channel |
361 | * | 305 | * |
362 | * Set/change channels. If the channel is really being changed, it's done | 306 | * Set/change channels. If the channel is really being changed, it's done |
@@ -367,25 +311,23 @@ int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan) | |||
367 | { | 311 | { |
368 | struct ath_hal *ah = sc->sc_ah; | 312 | struct ath_hal *ah = sc->sc_ah; |
369 | bool fastcc = true, stopped; | 313 | bool fastcc = true, stopped; |
370 | enum ath9k_ht_macmode ht_macmode; | ||
371 | 314 | ||
372 | if (sc->sc_invalid) /* if the device is invalid or removed */ | 315 | if (sc->sc_flags & SC_OP_INVALID) /* the device is invalid or removed */ |
373 | return -EIO; | 316 | return -EIO; |
374 | 317 | ||
375 | DPRINTF(sc, ATH_DBG_CONFIG, | 318 | DPRINTF(sc, ATH_DBG_CONFIG, |
376 | "%s: %u (%u MHz) -> %u (%u MHz), cflags:%x\n", | 319 | "%s: %u (%u MHz) -> %u (%u MHz), cflags:%x\n", |
377 | __func__, | 320 | __func__, |
378 | ath9k_hw_mhz2ieee(ah, sc->sc_curchan.channel, | 321 | ath9k_hw_mhz2ieee(ah, sc->sc_ah->ah_curchan->channel, |
379 | sc->sc_curchan.channelFlags), | 322 | sc->sc_ah->ah_curchan->channelFlags), |
380 | sc->sc_curchan.channel, | 323 | sc->sc_ah->ah_curchan->channel, |
381 | ath9k_hw_mhz2ieee(ah, hchan->channel, hchan->channelFlags), | 324 | ath9k_hw_mhz2ieee(ah, hchan->channel, hchan->channelFlags), |
382 | hchan->channel, hchan->channelFlags); | 325 | hchan->channel, hchan->channelFlags); |
383 | 326 | ||
384 | ht_macmode = ath_cwm_macmode(sc); | 327 | if (hchan->channel != sc->sc_ah->ah_curchan->channel || |
385 | 328 | hchan->channelFlags != sc->sc_ah->ah_curchan->channelFlags || | |
386 | if (hchan->channel != sc->sc_curchan.channel || | 329 | (sc->sc_flags & SC_OP_CHAINMASK_UPDATE) || |
387 | hchan->channelFlags != sc->sc_curchan.channelFlags || | 330 | (sc->sc_flags & SC_OP_FULL_RESET)) { |
388 | sc->sc_update_chainmask || sc->sc_full_reset) { | ||
389 | int status; | 331 | int status; |
390 | /* | 332 | /* |
391 | * This is only performed if the channel settings have | 333 | * This is only performed if the channel settings have |
@@ -404,15 +346,16 @@ int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan) | |||
404 | * to flush data frames already in queue because of | 346 | * to flush data frames already in queue because of |
405 | * changing channel. */ | 347 | * changing channel. */ |
406 | 348 | ||
407 | if (!stopped || sc->sc_full_reset) | 349 | if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET)) |
408 | fastcc = false; | 350 | fastcc = false; |
409 | 351 | ||
410 | spin_lock_bh(&sc->sc_resetlock); | 352 | spin_lock_bh(&sc->sc_resetlock); |
411 | if (!ath9k_hw_reset(ah, sc->sc_opmode, hchan, | 353 | if (!ath9k_hw_reset(ah, hchan, |
412 | ht_macmode, sc->sc_tx_chainmask, | 354 | sc->sc_ht_info.tx_chan_width, |
413 | sc->sc_rx_chainmask, | 355 | sc->sc_tx_chainmask, |
414 | sc->sc_ht_extprotspacing, | 356 | sc->sc_rx_chainmask, |
415 | fastcc, &status)) { | 357 | sc->sc_ht_extprotspacing, |
358 | fastcc, &status)) { | ||
416 | DPRINTF(sc, ATH_DBG_FATAL, | 359 | DPRINTF(sc, ATH_DBG_FATAL, |
417 | "%s: unable to reset channel %u (%uMhz) " | 360 | "%s: unable to reset channel %u (%uMhz) " |
418 | "flags 0x%x hal status %u\n", __func__, | 361 | "flags 0x%x hal status %u\n", __func__, |
@@ -424,9 +367,8 @@ int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan) | |||
424 | } | 367 | } |
425 | spin_unlock_bh(&sc->sc_resetlock); | 368 | spin_unlock_bh(&sc->sc_resetlock); |
426 | 369 | ||
427 | sc->sc_curchan = *hchan; | 370 | sc->sc_flags &= ~SC_OP_CHAINMASK_UPDATE; |
428 | sc->sc_update_chainmask = 0; | 371 | sc->sc_flags &= ~SC_OP_FULL_RESET; |
429 | sc->sc_full_reset = 0; | ||
430 | 372 | ||
431 | /* Re-enable rx framework */ | 373 | /* Re-enable rx framework */ |
432 | if (ath_startrecv(sc) != 0) { | 374 | if (ath_startrecv(sc) != 0) { |
@@ -537,7 +479,7 @@ int ath_chainmask_sel_logic(struct ath_softc *sc, struct ath_node *an) | |||
537 | 479 | ||
538 | void ath_update_chainmask(struct ath_softc *sc, int is_ht) | 480 | void ath_update_chainmask(struct ath_softc *sc, int is_ht) |
539 | { | 481 | { |
540 | sc->sc_update_chainmask = 1; | 482 | sc->sc_flags |= SC_OP_CHAINMASK_UPDATE; |
541 | if (is_ht) { | 483 | if (is_ht) { |
542 | sc->sc_tx_chainmask = sc->sc_ah->ah_caps.tx_chainmask; | 484 | sc->sc_tx_chainmask = sc->sc_ah->ah_caps.tx_chainmask; |
543 | sc->sc_rx_chainmask = sc->sc_ah->ah_caps.rx_chainmask; | 485 | sc->sc_rx_chainmask = sc->sc_ah->ah_caps.rx_chainmask; |
@@ -554,62 +496,6 @@ void ath_update_chainmask(struct ath_softc *sc, int is_ht) | |||
554 | /* VAP management */ | 496 | /* VAP management */ |
555 | /******************/ | 497 | /******************/ |
556 | 498 | ||
557 | /* | ||
558 | * VAP in Listen mode | ||
559 | * | ||
560 | * This routine brings the VAP out of the down state into a "listen" state | ||
561 | * where it waits for association requests. This is used in AP and AdHoc | ||
562 | * modes. | ||
563 | */ | ||
564 | |||
565 | int ath_vap_listen(struct ath_softc *sc, int if_id) | ||
566 | { | ||
567 | struct ath_hal *ah = sc->sc_ah; | ||
568 | struct ath_vap *avp; | ||
569 | u32 rfilt = 0; | ||
570 | DECLARE_MAC_BUF(mac); | ||
571 | |||
572 | avp = sc->sc_vaps[if_id]; | ||
573 | if (avp == NULL) { | ||
574 | DPRINTF(sc, ATH_DBG_FATAL, "%s: invalid interface id %u\n", | ||
575 | __func__, if_id); | ||
576 | return -EINVAL; | ||
577 | } | ||
578 | |||
579 | #ifdef CONFIG_SLOW_ANT_DIV | ||
580 | ath_slow_ant_div_stop(&sc->sc_antdiv); | ||
581 | #endif | ||
582 | |||
583 | /* update ratectrl about the new state */ | ||
584 | ath_rate_newstate(sc, avp); | ||
585 | |||
586 | rfilt = ath_calcrxfilter(sc); | ||
587 | ath9k_hw_setrxfilter(ah, rfilt); | ||
588 | |||
589 | if (sc->sc_opmode == ATH9K_M_STA || sc->sc_opmode == ATH9K_M_IBSS) { | ||
590 | memcpy(sc->sc_curbssid, ath_bcast_mac, ETH_ALEN); | ||
591 | ath9k_hw_write_associd(ah, sc->sc_curbssid, sc->sc_curaid); | ||
592 | } else | ||
593 | sc->sc_curaid = 0; | ||
594 | |||
595 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
596 | "%s: RX filter 0x%x bssid %s aid 0x%x\n", | ||
597 | __func__, rfilt, print_mac(mac, | ||
598 | sc->sc_curbssid), sc->sc_curaid); | ||
599 | |||
600 | /* | ||
601 | * XXXX | ||
602 | * Disable BMISS interrupt when we're not associated | ||
603 | */ | ||
604 | ath9k_hw_set_interrupts(ah, | ||
605 | sc->sc_imask & ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS)); | ||
606 | sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); | ||
607 | /* need to reconfigure the beacons when it moves to RUN */ | ||
608 | sc->sc_beacons = 0; | ||
609 | |||
610 | return 0; | ||
611 | } | ||
612 | |||
613 | int ath_vap_attach(struct ath_softc *sc, | 499 | int ath_vap_attach(struct ath_softc *sc, |
614 | int if_id, | 500 | int if_id, |
615 | struct ieee80211_vif *if_data, | 501 | struct ieee80211_vif *if_data, |
@@ -647,16 +533,13 @@ int ath_vap_attach(struct ath_softc *sc, | |||
647 | /* Set the VAP opmode */ | 533 | /* Set the VAP opmode */ |
648 | avp->av_opmode = opmode; | 534 | avp->av_opmode = opmode; |
649 | avp->av_bslot = -1; | 535 | avp->av_bslot = -1; |
650 | INIT_LIST_HEAD(&avp->av_mcastq.axq_q); | ||
651 | INIT_LIST_HEAD(&avp->av_mcastq.axq_acq); | ||
652 | spin_lock_init(&avp->av_mcastq.axq_lock); | ||
653 | 536 | ||
654 | ath9k_hw_set_tsfadjust(sc->sc_ah, 1); | 537 | ath9k_hw_set_tsfadjust(sc->sc_ah, 1); |
655 | 538 | ||
656 | sc->sc_vaps[if_id] = avp; | 539 | sc->sc_vaps[if_id] = avp; |
657 | sc->sc_nvaps++; | 540 | sc->sc_nvaps++; |
658 | /* Set the device opmode */ | 541 | /* Set the device opmode */ |
659 | sc->sc_opmode = opmode; | 542 | sc->sc_ah->ah_opmode = opmode; |
660 | 543 | ||
661 | /* default VAP configuration */ | 544 | /* default VAP configuration */ |
662 | avp->av_config.av_fixed_rateset = IEEE80211_FIXED_RATE_NONE; | 545 | avp->av_config.av_fixed_rateset = IEEE80211_FIXED_RATE_NONE; |
@@ -689,9 +572,6 @@ int ath_vap_detach(struct ath_softc *sc, int if_id) | |||
689 | ath_stoprecv(sc); /* stop recv side */ | 572 | ath_stoprecv(sc); /* stop recv side */ |
690 | ath_flushrecv(sc); /* flush recv queue */ | 573 | ath_flushrecv(sc); /* flush recv queue */ |
691 | 574 | ||
692 | /* Reclaim any pending mcast bufs on the vap. */ | ||
693 | ath_tx_draintxq(sc, &avp->av_mcastq, false); | ||
694 | |||
695 | kfree(avp); | 575 | kfree(avp); |
696 | sc->sc_vaps[if_id] = NULL; | 576 | sc->sc_vaps[if_id] = NULL; |
697 | sc->sc_nvaps--; | 577 | sc->sc_nvaps--; |
@@ -728,9 +608,9 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) | |||
728 | struct ath_hal *ah = sc->sc_ah; | 608 | struct ath_hal *ah = sc->sc_ah; |
729 | int status; | 609 | int status; |
730 | int error = 0; | 610 | int error = 0; |
731 | enum ath9k_ht_macmode ht_macmode = ath_cwm_macmode(sc); | ||
732 | 611 | ||
733 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: mode %d\n", __func__, sc->sc_opmode); | 612 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: mode %d\n", |
613 | __func__, sc->sc_ah->ah_opmode); | ||
734 | 614 | ||
735 | /* | 615 | /* |
736 | * Stop anything previously setup. This is safe | 616 | * Stop anything previously setup. This is safe |
@@ -752,16 +632,16 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) | |||
752 | * be followed by initialization of the appropriate bits | 632 | * be followed by initialization of the appropriate bits |
753 | * and then setup of the interrupt mask. | 633 | * and then setup of the interrupt mask. |
754 | */ | 634 | */ |
755 | sc->sc_curchan = *initial_chan; | ||
756 | 635 | ||
757 | spin_lock_bh(&sc->sc_resetlock); | 636 | spin_lock_bh(&sc->sc_resetlock); |
758 | if (!ath9k_hw_reset(ah, sc->sc_opmode, &sc->sc_curchan, ht_macmode, | 637 | if (!ath9k_hw_reset(ah, initial_chan, |
759 | sc->sc_tx_chainmask, sc->sc_rx_chainmask, | 638 | sc->sc_ht_info.tx_chan_width, |
760 | sc->sc_ht_extprotspacing, false, &status)) { | 639 | sc->sc_tx_chainmask, sc->sc_rx_chainmask, |
640 | sc->sc_ht_extprotspacing, false, &status)) { | ||
761 | DPRINTF(sc, ATH_DBG_FATAL, | 641 | DPRINTF(sc, ATH_DBG_FATAL, |
762 | "%s: unable to reset hardware; hal status %u " | 642 | "%s: unable to reset hardware; hal status %u " |
763 | "(freq %u flags 0x%x)\n", __func__, status, | 643 | "(freq %u flags 0x%x)\n", __func__, status, |
764 | sc->sc_curchan.channel, sc->sc_curchan.channelFlags); | 644 | initial_chan->channel, initial_chan->channelFlags); |
765 | error = -EIO; | 645 | error = -EIO; |
766 | spin_unlock_bh(&sc->sc_resetlock); | 646 | spin_unlock_bh(&sc->sc_resetlock); |
767 | goto done; | 647 | goto done; |
@@ -802,7 +682,8 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) | |||
802 | * Note we only do this (at the moment) for station mode. | 682 | * Note we only do this (at the moment) for station mode. |
803 | */ | 683 | */ |
804 | if (ath9k_hw_phycounters(ah) && | 684 | if (ath9k_hw_phycounters(ah) && |
805 | ((sc->sc_opmode == ATH9K_M_STA) || (sc->sc_opmode == ATH9K_M_IBSS))) | 685 | ((sc->sc_ah->ah_opmode == ATH9K_M_STA) || |
686 | (sc->sc_ah->ah_opmode == ATH9K_M_IBSS))) | ||
806 | sc->sc_imask |= ATH9K_INT_MIB; | 687 | sc->sc_imask |= ATH9K_INT_MIB; |
807 | /* | 688 | /* |
808 | * Some hardware processes the TIM IE and fires an | 689 | * Some hardware processes the TIM IE and fires an |
@@ -811,7 +692,7 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) | |||
811 | * enable the TIM interrupt when operating as station. | 692 | * enable the TIM interrupt when operating as station. |
812 | */ | 693 | */ |
813 | if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_ENHANCEDPM) && | 694 | if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_ENHANCEDPM) && |
814 | (sc->sc_opmode == ATH9K_M_STA) && | 695 | (sc->sc_ah->ah_opmode == ATH9K_M_STA) && |
815 | !sc->sc_config.swBeaconProcess) | 696 | !sc->sc_config.swBeaconProcess) |
816 | sc->sc_imask |= ATH9K_INT_TIM; | 697 | sc->sc_imask |= ATH9K_INT_TIM; |
817 | /* | 698 | /* |
@@ -823,34 +704,34 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) | |||
823 | 704 | ||
824 | /* XXX: we must make sure h/w is ready and clear invalid flag | 705 | /* XXX: we must make sure h/w is ready and clear invalid flag |
825 | * before turning on interrupt. */ | 706 | * before turning on interrupt. */ |
826 | sc->sc_invalid = 0; | 707 | sc->sc_flags &= ~SC_OP_INVALID; |
827 | done: | 708 | done: |
828 | return error; | 709 | return error; |
829 | } | 710 | } |
830 | 711 | ||
831 | /* | 712 | int ath_reset(struct ath_softc *sc, bool retry_tx) |
832 | * Reset the hardware w/o losing operational state. This is | ||
833 | * basically a more efficient way of doing ath_stop, ath_init, | ||
834 | * followed by state transitions to the current 802.11 | ||
835 | * operational state. Used to recover from errors rx overrun | ||
836 | * and to reset the hardware when rf gain settings must be reset. | ||
837 | */ | ||
838 | |||
839 | static int ath_reset_start(struct ath_softc *sc, u32 flag) | ||
840 | { | 713 | { |
841 | struct ath_hal *ah = sc->sc_ah; | 714 | struct ath_hal *ah = sc->sc_ah; |
715 | int status; | ||
716 | int error = 0; | ||
842 | 717 | ||
843 | ath9k_hw_set_interrupts(ah, 0); /* disable interrupts */ | 718 | ath9k_hw_set_interrupts(ah, 0); /* disable interrupts */ |
844 | ath_draintxq(sc, flag & RESET_RETRY_TXQ); /* stop xmit side */ | 719 | ath_draintxq(sc, retry_tx); /* stop xmit */ |
845 | ath_stoprecv(sc); /* stop recv side */ | 720 | ath_stoprecv(sc); /* stop recv */ |
846 | ath_flushrecv(sc); /* flush recv queue */ | 721 | ath_flushrecv(sc); /* flush recv queue */ |
847 | 722 | ||
848 | return 0; | 723 | /* Reset chip */ |
849 | } | 724 | spin_lock_bh(&sc->sc_resetlock); |
850 | 725 | if (!ath9k_hw_reset(ah, sc->sc_ah->ah_curchan, | |
851 | static int ath_reset_end(struct ath_softc *sc, u32 flag) | 726 | sc->sc_ht_info.tx_chan_width, |
852 | { | 727 | sc->sc_tx_chainmask, sc->sc_rx_chainmask, |
853 | struct ath_hal *ah = sc->sc_ah; | 728 | sc->sc_ht_extprotspacing, false, &status)) { |
729 | DPRINTF(sc, ATH_DBG_FATAL, | ||
730 | "%s: unable to reset hardware; hal status %u\n", | ||
731 | __func__, status); | ||
732 | error = -EIO; | ||
733 | } | ||
734 | spin_unlock_bh(&sc->sc_resetlock); | ||
854 | 735 | ||
855 | if (ath_startrecv(sc) != 0) /* restart recv */ | 736 | if (ath_startrecv(sc) != 0) /* restart recv */ |
856 | DPRINTF(sc, ATH_DBG_FATAL, | 737 | DPRINTF(sc, ATH_DBG_FATAL, |
@@ -861,16 +742,17 @@ static int ath_reset_end(struct ath_softc *sc, u32 flag) | |||
861 | * that changes the channel so update any state that | 742 | * that changes the channel so update any state that |
862 | * might change as a result. | 743 | * might change as a result. |
863 | */ | 744 | */ |
864 | ath_setcurmode(sc, ath_chan2mode(&sc->sc_curchan)); | 745 | ath_setcurmode(sc, ath_chan2mode(sc->sc_ah->ah_curchan)); |
865 | 746 | ||
866 | ath_update_txpow(sc); /* update tx power state */ | 747 | ath_update_txpow(sc); |
867 | 748 | ||
868 | if (sc->sc_beacons) | 749 | if (sc->sc_flags & SC_OP_BEACONS) |
869 | ath_beacon_config(sc, ATH_IF_ID_ANY); /* restart beacons */ | 750 | ath_beacon_config(sc, ATH_IF_ID_ANY); /* restart beacons */ |
751 | |||
870 | ath9k_hw_set_interrupts(ah, sc->sc_imask); | 752 | ath9k_hw_set_interrupts(ah, sc->sc_imask); |
871 | 753 | ||
872 | /* Restart the txq */ | 754 | /* Restart the txq */ |
873 | if (flag & RESET_RETRY_TXQ) { | 755 | if (retry_tx) { |
874 | int i; | 756 | int i; |
875 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { | 757 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { |
876 | if (ATH_TXQ_SETUP(sc, i)) { | 758 | if (ATH_TXQ_SETUP(sc, i)) { |
@@ -880,28 +762,6 @@ static int ath_reset_end(struct ath_softc *sc, u32 flag) | |||
880 | } | 762 | } |
881 | } | 763 | } |
882 | } | 764 | } |
883 | return 0; | ||
884 | } | ||
885 | |||
886 | int ath_reset(struct ath_softc *sc) | ||
887 | { | ||
888 | struct ath_hal *ah = sc->sc_ah; | ||
889 | int status; | ||
890 | int error = 0; | ||
891 | enum ath9k_ht_macmode ht_macmode = ath_cwm_macmode(sc); | ||
892 | |||
893 | /* NB: indicate channel change so we do a full reset */ | ||
894 | spin_lock_bh(&sc->sc_resetlock); | ||
895 | if (!ath9k_hw_reset(ah, sc->sc_opmode, &sc->sc_curchan, | ||
896 | ht_macmode, | ||
897 | sc->sc_tx_chainmask, sc->sc_rx_chainmask, | ||
898 | sc->sc_ht_extprotspacing, false, &status)) { | ||
899 | DPRINTF(sc, ATH_DBG_FATAL, | ||
900 | "%s: unable to reset hardware; hal status %u\n", | ||
901 | __func__, status); | ||
902 | error = -EIO; | ||
903 | } | ||
904 | spin_unlock_bh(&sc->sc_resetlock); | ||
905 | 765 | ||
906 | return error; | 766 | return error; |
907 | } | 767 | } |
@@ -911,7 +771,7 @@ int ath_suspend(struct ath_softc *sc) | |||
911 | struct ath_hal *ah = sc->sc_ah; | 771 | struct ath_hal *ah = sc->sc_ah; |
912 | 772 | ||
913 | /* No I/O if device has been surprise removed */ | 773 | /* No I/O if device has been surprise removed */ |
914 | if (sc->sc_invalid) | 774 | if (sc->sc_flags & SC_OP_INVALID) |
915 | return -EIO; | 775 | return -EIO; |
916 | 776 | ||
917 | /* Shut off the interrupt before setting sc->sc_invalid to '1' */ | 777 | /* Shut off the interrupt before setting sc->sc_invalid to '1' */ |
@@ -919,7 +779,7 @@ int ath_suspend(struct ath_softc *sc) | |||
919 | 779 | ||
920 | /* XXX: we must make sure h/w will not generate any interrupt | 780 | /* XXX: we must make sure h/w will not generate any interrupt |
921 | * before setting the invalid flag. */ | 781 | * before setting the invalid flag. */ |
922 | sc->sc_invalid = 1; | 782 | sc->sc_flags |= SC_OP_INVALID; |
923 | 783 | ||
924 | /* disable HAL and put h/w to sleep */ | 784 | /* disable HAL and put h/w to sleep */ |
925 | ath9k_hw_disable(sc->sc_ah); | 785 | ath9k_hw_disable(sc->sc_ah); |
@@ -940,7 +800,7 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
940 | bool sched = false; | 800 | bool sched = false; |
941 | 801 | ||
942 | do { | 802 | do { |
943 | if (sc->sc_invalid) { | 803 | if (sc->sc_flags & SC_OP_INVALID) { |
944 | /* | 804 | /* |
945 | * The hardware is not ready/present, don't | 805 | * The hardware is not ready/present, don't |
946 | * touch anything. Note this can happen early | 806 | * touch anything. Note this can happen early |
@@ -1050,7 +910,7 @@ static void ath9k_tasklet(unsigned long data) | |||
1050 | 910 | ||
1051 | if (status & ATH9K_INT_FATAL) { | 911 | if (status & ATH9K_INT_FATAL) { |
1052 | /* need a chip reset */ | 912 | /* need a chip reset */ |
1053 | ath_internal_reset(sc); | 913 | ath_reset(sc, false); |
1054 | return; | 914 | return; |
1055 | } else { | 915 | } else { |
1056 | 916 | ||
@@ -1093,10 +953,9 @@ int ath_init(u16 devid, struct ath_softc *sc) | |||
1093 | int status; | 953 | int status; |
1094 | int error = 0, i; | 954 | int error = 0, i; |
1095 | int csz = 0; | 955 | int csz = 0; |
1096 | u32 rd; | ||
1097 | 956 | ||
1098 | /* XXX: hardware will not be ready until ath_open() being called */ | 957 | /* XXX: hardware will not be ready until ath_open() being called */ |
1099 | sc->sc_invalid = 1; | 958 | sc->sc_flags |= SC_OP_INVALID; |
1100 | 959 | ||
1101 | sc->sc_debug = DBG_DEFAULT; | 960 | sc->sc_debug = DBG_DEFAULT; |
1102 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: devid 0x%x\n", __func__, devid); | 961 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: devid 0x%x\n", __func__, devid); |
@@ -1126,9 +985,6 @@ int ath_init(u16 devid, struct ath_softc *sc) | |||
1126 | } | 985 | } |
1127 | sc->sc_ah = ah; | 986 | sc->sc_ah = ah; |
1128 | 987 | ||
1129 | /* Get the chipset-specific aggr limit. */ | ||
1130 | sc->sc_rtsaggrlimit = ah->ah_caps.rts_aggr_limit; | ||
1131 | |||
1132 | /* Get the hardware key cache size. */ | 988 | /* Get the hardware key cache size. */ |
1133 | sc->sc_keymax = ah->ah_caps.keycache_size; | 989 | sc->sc_keymax = ah->ah_caps.keycache_size; |
1134 | if (sc->sc_keymax > ATH_KEYMAX) { | 990 | if (sc->sc_keymax > ATH_KEYMAX) { |
@@ -1162,14 +1018,12 @@ int ath_init(u16 devid, struct ath_softc *sc) | |||
1162 | * is resposible for filtering this list based on settings | 1018 | * is resposible for filtering this list based on settings |
1163 | * like the phy mode. | 1019 | * like the phy mode. |
1164 | */ | 1020 | */ |
1165 | rd = ah->ah_currentRD; | ||
1166 | |||
1167 | error = ath_setup_channels(sc); | 1021 | error = ath_setup_channels(sc); |
1168 | if (error) | 1022 | if (error) |
1169 | goto bad; | 1023 | goto bad; |
1170 | 1024 | ||
1171 | /* default to STA mode */ | 1025 | /* default to STA mode */ |
1172 | sc->sc_opmode = ATH9K_M_MONITOR; | 1026 | sc->sc_ah->ah_opmode = ATH9K_M_MONITOR; |
1173 | 1027 | ||
1174 | /* Setup rate tables */ | 1028 | /* Setup rate tables */ |
1175 | 1029 | ||
@@ -1240,7 +1094,7 @@ int ath_init(u16 devid, struct ath_softc *sc) | |||
1240 | 1094 | ||
1241 | sc->sc_rc = ath_rate_attach(ah); | 1095 | sc->sc_rc = ath_rate_attach(ah); |
1242 | if (sc->sc_rc == NULL) { | 1096 | if (sc->sc_rc == NULL) { |
1243 | error = EIO; | 1097 | error = -EIO; |
1244 | goto bad2; | 1098 | goto bad2; |
1245 | } | 1099 | } |
1246 | 1100 | ||
@@ -1280,20 +1134,13 @@ int ath_init(u16 devid, struct ath_softc *sc) | |||
1280 | 1134 | ||
1281 | /* 11n Capabilities */ | 1135 | /* 11n Capabilities */ |
1282 | if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) { | 1136 | if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) { |
1283 | sc->sc_txaggr = 1; | 1137 | sc->sc_flags |= SC_OP_TXAGGR; |
1284 | sc->sc_rxaggr = 1; | 1138 | sc->sc_flags |= SC_OP_RXAGGR; |
1285 | } | 1139 | } |
1286 | 1140 | ||
1287 | sc->sc_tx_chainmask = ah->ah_caps.tx_chainmask; | 1141 | sc->sc_tx_chainmask = ah->ah_caps.tx_chainmask; |
1288 | sc->sc_rx_chainmask = ah->ah_caps.rx_chainmask; | 1142 | sc->sc_rx_chainmask = ah->ah_caps.rx_chainmask; |
1289 | 1143 | ||
1290 | /* Configuration for rx chain detection */ | ||
1291 | sc->sc_rxchaindetect_ref = 0; | ||
1292 | sc->sc_rxchaindetect_thresh5GHz = 35; | ||
1293 | sc->sc_rxchaindetect_thresh2GHz = 35; | ||
1294 | sc->sc_rxchaindetect_delta5GHz = 30; | ||
1295 | sc->sc_rxchaindetect_delta2GHz = 30; | ||
1296 | |||
1297 | ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL); | 1144 | ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL); |
1298 | sc->sc_defant = ath9k_hw_getdefantenna(ah); | 1145 | sc->sc_defant = ath9k_hw_getdefantenna(ah); |
1299 | 1146 | ||
@@ -1337,7 +1184,7 @@ void ath_deinit(struct ath_softc *sc) | |||
1337 | DPRINTF(sc, ATH_DBG_CONFIG, "%s\n", __func__); | 1184 | DPRINTF(sc, ATH_DBG_CONFIG, "%s\n", __func__); |
1338 | 1185 | ||
1339 | ath_stop(sc); | 1186 | ath_stop(sc); |
1340 | if (!sc->sc_invalid) | 1187 | if (!(sc->sc_flags & SC_OP_INVALID)) |
1341 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); | 1188 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); |
1342 | ath_rate_detach(sc->sc_rc); | 1189 | ath_rate_detach(sc->sc_rc); |
1343 | /* cleanup tx queues */ | 1190 | /* cleanup tx queues */ |
@@ -1464,9 +1311,9 @@ void ath_newassoc(struct ath_softc *sc, | |||
1464 | /* if station reassociates, tear down the aggregation state. */ | 1311 | /* if station reassociates, tear down the aggregation state. */ |
1465 | if (!isnew) { | 1312 | if (!isnew) { |
1466 | for (tidno = 0; tidno < WME_NUM_TID; tidno++) { | 1313 | for (tidno = 0; tidno < WME_NUM_TID; tidno++) { |
1467 | if (sc->sc_txaggr) | 1314 | if (sc->sc_flags & SC_OP_TXAGGR) |
1468 | ath_tx_aggr_teardown(sc, an, tidno); | 1315 | ath_tx_aggr_teardown(sc, an, tidno); |
1469 | if (sc->sc_rxaggr) | 1316 | if (sc->sc_flags & SC_OP_RXAGGR) |
1470 | ath_rx_aggr_teardown(sc, an, tidno); | 1317 | ath_rx_aggr_teardown(sc, an, tidno); |
1471 | } | 1318 | } |
1472 | } | 1319 | } |
@@ -1815,13 +1662,6 @@ void ath_descdma_cleanup(struct ath_softc *sc, | |||
1815 | /* Utilities */ | 1662 | /* Utilities */ |
1816 | /*************/ | 1663 | /*************/ |
1817 | 1664 | ||
1818 | void ath_internal_reset(struct ath_softc *sc) | ||
1819 | { | ||
1820 | ath_reset_start(sc, 0); | ||
1821 | ath_reset(sc); | ||
1822 | ath_reset_end(sc, 0); | ||
1823 | } | ||
1824 | |||
1825 | int ath_get_hal_qnum(u16 queue, struct ath_softc *sc) | 1665 | int ath_get_hal_qnum(u16 queue, struct ath_softc *sc) |
1826 | { | 1666 | { |
1827 | int qnum; | 1667 | int qnum; |
diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index 673b3d81133a..1faa1effa02c 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/scatterlist.h> | 39 | #include <linux/scatterlist.h> |
40 | #include <asm/page.h> | 40 | #include <asm/page.h> |
41 | #include <net/mac80211.h> | 41 | #include <net/mac80211.h> |
42 | #include <linux/leds.h> | ||
42 | 43 | ||
43 | #include "ath9k.h" | 44 | #include "ath9k.h" |
44 | #include "rc.h" | 45 | #include "rc.h" |
@@ -79,12 +80,12 @@ struct ath_node; | |||
79 | } \ | 80 | } \ |
80 | } while (0) | 81 | } while (0) |
81 | 82 | ||
83 | #define TSF_TO_TU(_h,_l) \ | ||
84 | ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) | ||
85 | |||
82 | /* XXX: remove */ | 86 | /* XXX: remove */ |
83 | #define memzero(_buf, _len) memset(_buf, 0, _len) | 87 | #define memzero(_buf, _len) memset(_buf, 0, _len) |
84 | 88 | ||
85 | #define get_dma_mem_context(var, field) (&((var)->field)) | ||
86 | #define copy_dma_mem_context(dst, src) (*dst = *src) | ||
87 | |||
88 | #define ATH9K_BH_STATUS_INTACT 0 | 89 | #define ATH9K_BH_STATUS_INTACT 0 |
89 | #define ATH9K_BH_STATUS_CHANGE 1 | 90 | #define ATH9K_BH_STATUS_CHANGE 1 |
90 | 91 | ||
@@ -95,6 +96,8 @@ static inline unsigned long get_timestamp(void) | |||
95 | return ((jiffies / HZ) * 1000) + (jiffies % HZ) * (1000 / HZ); | 96 | return ((jiffies / HZ) * 1000) + (jiffies % HZ) * (1000 / HZ); |
96 | } | 97 | } |
97 | 98 | ||
99 | static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | ||
100 | |||
98 | /*************/ | 101 | /*************/ |
99 | /* Debugging */ | 102 | /* Debugging */ |
100 | /*************/ | 103 | /*************/ |
@@ -175,11 +178,6 @@ void ath_update_chainmask(struct ath_softc *sc, int is_ht); | |||
175 | /* Descriptor Management */ | 178 | /* Descriptor Management */ |
176 | /*************************/ | 179 | /*************************/ |
177 | 180 | ||
178 | /* Number of descriptors per buffer. The only case where we see skbuff | ||
179 | chains is due to FF aggregation in the driver. */ | ||
180 | #define ATH_TXDESC 1 | ||
181 | /* if there's more fragment for this MSDU */ | ||
182 | #define ATH_BF_MORE_MPDU 1 | ||
183 | #define ATH_TXBUF_RESET(_bf) do { \ | 181 | #define ATH_TXBUF_RESET(_bf) do { \ |
184 | (_bf)->bf_status = 0; \ | 182 | (_bf)->bf_status = 0; \ |
185 | (_bf)->bf_lastbf = NULL; \ | 183 | (_bf)->bf_lastbf = NULL; \ |
@@ -189,28 +187,29 @@ chains is due to FF aggregation in the driver. */ | |||
189 | sizeof(struct ath_buf_state)); \ | 187 | sizeof(struct ath_buf_state)); \ |
190 | } while (0) | 188 | } while (0) |
191 | 189 | ||
190 | enum buffer_type { | ||
191 | BUF_DATA = BIT(0), | ||
192 | BUF_AGGR = BIT(1), | ||
193 | BUF_AMPDU = BIT(2), | ||
194 | BUF_HT = BIT(3), | ||
195 | BUF_RETRY = BIT(4), | ||
196 | BUF_XRETRY = BIT(5), | ||
197 | BUF_SHORT_PREAMBLE = BIT(6), | ||
198 | BUF_BAR = BIT(7), | ||
199 | BUF_PSPOLL = BIT(8), | ||
200 | BUF_AGGR_BURST = BIT(9), | ||
201 | BUF_CALC_AIRTIME = BIT(10), | ||
202 | }; | ||
203 | |||
192 | struct ath_buf_state { | 204 | struct ath_buf_state { |
193 | int bfs_nframes; /* # frames in aggregate */ | 205 | int bfs_nframes; /* # frames in aggregate */ |
194 | u16 bfs_al; /* length of aggregate */ | 206 | u16 bfs_al; /* length of aggregate */ |
195 | u16 bfs_frmlen; /* length of frame */ | 207 | u16 bfs_frmlen; /* length of frame */ |
196 | int bfs_seqno; /* sequence number */ | 208 | int bfs_seqno; /* sequence number */ |
197 | int bfs_tidno; /* tid of this frame */ | 209 | int bfs_tidno; /* tid of this frame */ |
198 | int bfs_retries; /* current retries */ | 210 | int bfs_retries; /* current retries */ |
199 | struct ath_rc_series bfs_rcs[4]; /* rate series */ | 211 | struct ath_rc_series bfs_rcs[4]; /* rate series */ |
200 | u8 bfs_isdata:1; /* is a data frame/aggregate */ | 212 | u32 bf_type; /* BUF_* (enum buffer_type) */ |
201 | u8 bfs_isaggr:1; /* is an aggregate */ | ||
202 | u8 bfs_isampdu:1; /* is an a-mpdu, aggregate or not */ | ||
203 | u8 bfs_ht:1; /* is an HT frame */ | ||
204 | u8 bfs_isretried:1; /* is retried */ | ||
205 | u8 bfs_isxretried:1; /* is excessive retried */ | ||
206 | u8 bfs_shpreamble:1; /* is short preamble */ | ||
207 | u8 bfs_isbar:1; /* is a BAR */ | ||
208 | u8 bfs_ispspoll:1; /* is a PS-Poll */ | ||
209 | u8 bfs_aggrburst:1; /* is a aggr burst */ | ||
210 | u8 bfs_calcairtime:1; /* requests airtime be calculated | ||
211 | when set for tx frame */ | ||
212 | int bfs_rifsburst_elem; /* RIFS burst/bar */ | ||
213 | int bfs_nrifsubframes; /* # of elements in burst */ | ||
214 | /* key type use to encrypt this frame */ | 213 | /* key type use to encrypt this frame */ |
215 | enum ath9k_key_type bfs_keytype; | 214 | enum ath9k_key_type bfs_keytype; |
216 | }; | 215 | }; |
@@ -222,26 +221,22 @@ struct ath_buf_state { | |||
222 | #define bf_seqno bf_state.bfs_seqno | 221 | #define bf_seqno bf_state.bfs_seqno |
223 | #define bf_tidno bf_state.bfs_tidno | 222 | #define bf_tidno bf_state.bfs_tidno |
224 | #define bf_rcs bf_state.bfs_rcs | 223 | #define bf_rcs bf_state.bfs_rcs |
225 | #define bf_isdata bf_state.bfs_isdata | ||
226 | #define bf_isaggr bf_state.bfs_isaggr | ||
227 | #define bf_isampdu bf_state.bfs_isampdu | ||
228 | #define bf_ht bf_state.bfs_ht | ||
229 | #define bf_isretried bf_state.bfs_isretried | ||
230 | #define bf_isxretried bf_state.bfs_isxretried | ||
231 | #define bf_shpreamble bf_state.bfs_shpreamble | ||
232 | #define bf_rifsburst_elem bf_state.bfs_rifsburst_elem | ||
233 | #define bf_nrifsubframes bf_state.bfs_nrifsubframes | ||
234 | #define bf_keytype bf_state.bfs_keytype | 224 | #define bf_keytype bf_state.bfs_keytype |
235 | #define bf_isbar bf_state.bfs_isbar | 225 | #define bf_isdata(bf) (bf->bf_state.bf_type & BUF_DATA) |
236 | #define bf_ispspoll bf_state.bfs_ispspoll | 226 | #define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR) |
237 | #define bf_aggrburst bf_state.bfs_aggrburst | 227 | #define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU) |
238 | #define bf_calcairtime bf_state.bfs_calcairtime | 228 | #define bf_isht(bf) (bf->bf_state.bf_type & BUF_HT) |
229 | #define bf_isretried(bf) (bf->bf_state.bf_type & BUF_RETRY) | ||
230 | #define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY) | ||
231 | #define bf_isshpreamble(bf) (bf->bf_state.bf_type & BUF_SHORT_PREAMBLE) | ||
232 | #define bf_isbar(bf) (bf->bf_state.bf_type & BUF_BAR) | ||
233 | #define bf_ispspoll(bf) (bf->bf_state.bf_type & BUF_PSPOLL) | ||
234 | #define bf_isaggrburst(bf) (bf->bf_state.bf_type & BUF_AGGR_BURST) | ||
239 | 235 | ||
240 | /* | 236 | /* |
241 | * Abstraction of a contiguous buffer to transmit/receive. There is only | 237 | * Abstraction of a contiguous buffer to transmit/receive. There is only |
242 | * a single hw descriptor encapsulated here. | 238 | * a single hw descriptor encapsulated here. |
243 | */ | 239 | */ |
244 | |||
245 | struct ath_buf { | 240 | struct ath_buf { |
246 | struct list_head list; | 241 | struct list_head list; |
247 | struct list_head *last; | 242 | struct list_head *last; |
@@ -391,10 +386,10 @@ int ath_rx_input(struct ath_softc *sc, | |||
391 | struct sk_buff *skb, | 386 | struct sk_buff *skb, |
392 | struct ath_recv_status *rx_status, | 387 | struct ath_recv_status *rx_status, |
393 | enum ATH_RX_TYPE *status); | 388 | enum ATH_RX_TYPE *status); |
394 | int ath__rx_indicate(struct ath_softc *sc, | 389 | int _ath_rx_indicate(struct ath_softc *sc, |
395 | struct sk_buff *skb, | 390 | struct sk_buff *skb, |
396 | struct ath_recv_status *status, | 391 | struct ath_recv_status *status, |
397 | u16 keyix); | 392 | u16 keyix); |
398 | int ath_rx_subframe(struct ath_node *an, struct sk_buff *skb, | 393 | int ath_rx_subframe(struct ath_node *an, struct sk_buff *skb, |
399 | struct ath_recv_status *status); | 394 | struct ath_recv_status *status); |
400 | 395 | ||
@@ -402,8 +397,7 @@ int ath_rx_subframe(struct ath_node *an, struct sk_buff *skb, | |||
402 | /* TX */ | 397 | /* TX */ |
403 | /******/ | 398 | /******/ |
404 | 399 | ||
405 | #define ATH_FRAG_PER_MSDU 1 | 400 | #define ATH_TXBUF 512 |
406 | #define ATH_TXBUF (512/ATH_FRAG_PER_MSDU) | ||
407 | /* max number of transmit attempts (tries) */ | 401 | /* max number of transmit attempts (tries) */ |
408 | #define ATH_TXMAXTRY 13 | 402 | #define ATH_TXMAXTRY 13 |
409 | /* max number of 11n transmit attempts (tries) */ | 403 | /* max number of 11n transmit attempts (tries) */ |
@@ -522,7 +516,6 @@ struct ath_tx_control { | |||
522 | u32 keyix; | 516 | u32 keyix; |
523 | int min_rate; | 517 | int min_rate; |
524 | int mcast_rate; | 518 | int mcast_rate; |
525 | u16 nextfraglen; | ||
526 | struct ath_softc *dev; | 519 | struct ath_softc *dev; |
527 | dma_addr_t dmacontext; | 520 | dma_addr_t dmacontext; |
528 | }; | 521 | }; |
@@ -557,10 +550,10 @@ void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq); | |||
557 | int ath_tx_setup(struct ath_softc *sc, int haltype); | 550 | int ath_tx_setup(struct ath_softc *sc, int haltype); |
558 | void ath_draintxq(struct ath_softc *sc, bool retry_tx); | 551 | void ath_draintxq(struct ath_softc *sc, bool retry_tx); |
559 | void ath_tx_draintxq(struct ath_softc *sc, | 552 | void ath_tx_draintxq(struct ath_softc *sc, |
560 | struct ath_txq *txq, bool retry_tx); | 553 | struct ath_txq *txq, bool retry_tx); |
561 | void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an); | 554 | void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an); |
562 | void ath_tx_node_cleanup(struct ath_softc *sc, | 555 | void ath_tx_node_cleanup(struct ath_softc *sc, |
563 | struct ath_node *an, bool bh_flag); | 556 | struct ath_node *an, bool bh_flag); |
564 | void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an); | 557 | void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an); |
565 | void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq); | 558 | void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq); |
566 | int ath_tx_init(struct ath_softc *sc, int nbufs); | 559 | int ath_tx_init(struct ath_softc *sc, int nbufs); |
@@ -575,6 +568,7 @@ u32 ath_txq_aggr_depth(struct ath_softc *sc, int qnum); | |||
575 | void ath_notify_txq_status(struct ath_softc *sc, u16 queue_depth); | 568 | void ath_notify_txq_status(struct ath_softc *sc, u16 queue_depth); |
576 | void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | 569 | void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, |
577 | struct ath_xmit_status *tx_status, struct ath_node *an); | 570 | struct ath_xmit_status *tx_status, struct ath_node *an); |
571 | void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb); | ||
578 | 572 | ||
579 | /**********************/ | 573 | /**********************/ |
580 | /* Node / Aggregation */ | 574 | /* Node / Aggregation */ |
@@ -585,7 +579,6 @@ void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
585 | /* indicates the node is 80211 power save */ | 579 | /* indicates the node is 80211 power save */ |
586 | #define ATH_NODE_PWRSAVE 0x2 | 580 | #define ATH_NODE_PWRSAVE 0x2 |
587 | 581 | ||
588 | #define ADDBA_TIMEOUT 200 /* 200 milliseconds */ | ||
589 | #define ADDBA_EXCHANGE_ATTEMPTS 10 | 582 | #define ADDBA_EXCHANGE_ATTEMPTS 10 |
590 | #define ATH_AGGR_DELIM_SZ 4 /* delimiter size */ | 583 | #define ATH_AGGR_DELIM_SZ 4 /* delimiter size */ |
591 | #define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */ | 584 | #define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */ |
@@ -705,9 +698,6 @@ struct ath_node *ath_node_find(struct ath_softc *sc, u8 *addr); | |||
705 | #define ATH_BCBUF 4 /* number of beacon buffers */ | 698 | #define ATH_BCBUF 4 /* number of beacon buffers */ |
706 | #define ATH_DEFAULT_BINTVAL 100 /* default beacon interval in TU */ | 699 | #define ATH_DEFAULT_BINTVAL 100 /* default beacon interval in TU */ |
707 | #define ATH_DEFAULT_BMISS_LIMIT 10 | 700 | #define ATH_DEFAULT_BMISS_LIMIT 10 |
708 | #define ATH_BEACON_AIFS_DEFAULT 0 /* Default aifs for ap beacon q */ | ||
709 | #define ATH_BEACON_CWMIN_DEFAULT 0 /* Default cwmin for ap beacon q */ | ||
710 | #define ATH_BEACON_CWMAX_DEFAULT 0 /* Default cwmax for ap beacon q */ | ||
711 | #define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) | 701 | #define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) |
712 | 702 | ||
713 | /* beacon configuration */ | 703 | /* beacon configuration */ |
@@ -724,30 +714,16 @@ struct ath_beacon_config { | |||
724 | } u; /* last received beacon/probe response timestamp of this BSS. */ | 714 | } u; /* last received beacon/probe response timestamp of this BSS. */ |
725 | }; | 715 | }; |
726 | 716 | ||
727 | /* offsets in a beacon frame for | ||
728 | * quick acess of beacon content by low-level driver */ | ||
729 | struct ath_beacon_offset { | ||
730 | u8 *bo_tim; /* start of atim/dtim */ | ||
731 | }; | ||
732 | |||
733 | void ath9k_beacon_tasklet(unsigned long data); | 717 | void ath9k_beacon_tasklet(unsigned long data); |
734 | void ath_beacon_config(struct ath_softc *sc, int if_id); | 718 | void ath_beacon_config(struct ath_softc *sc, int if_id); |
735 | int ath_beaconq_setup(struct ath_hal *ah); | 719 | int ath_beaconq_setup(struct ath_hal *ah); |
736 | int ath_beacon_alloc(struct ath_softc *sc, int if_id); | 720 | int ath_beacon_alloc(struct ath_softc *sc, int if_id); |
737 | void ath_bstuck_process(struct ath_softc *sc); | 721 | void ath_bstuck_process(struct ath_softc *sc); |
738 | void ath_beacon_tasklet(struct ath_softc *sc, int *needmark); | ||
739 | void ath_beacon_free(struct ath_softc *sc); | ||
740 | void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp); | 722 | void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp); |
741 | void ath_beacon_sync(struct ath_softc *sc, int if_id); | 723 | void ath_beacon_sync(struct ath_softc *sc, int if_id); |
742 | void ath_update_beacon_info(struct ath_softc *sc, int avgbrssi); | ||
743 | void ath_get_beaconconfig(struct ath_softc *sc, | 724 | void ath_get_beaconconfig(struct ath_softc *sc, |
744 | int if_id, | 725 | int if_id, |
745 | struct ath_beacon_config *conf); | 726 | struct ath_beacon_config *conf); |
746 | int ath_update_beacon(struct ath_softc *sc, | ||
747 | int if_id, | ||
748 | struct ath_beacon_offset *bo, | ||
749 | struct sk_buff *skb, | ||
750 | int mcast); | ||
751 | /********/ | 727 | /********/ |
752 | /* VAPs */ | 728 | /* VAPs */ |
753 | /********/ | 729 | /********/ |
@@ -774,10 +750,8 @@ struct ath_vap { | |||
774 | struct ieee80211_vif *av_if_data; | 750 | struct ieee80211_vif *av_if_data; |
775 | enum ath9k_opmode av_opmode; /* VAP operational mode */ | 751 | enum ath9k_opmode av_opmode; /* VAP operational mode */ |
776 | struct ath_buf *av_bcbuf; /* beacon buffer */ | 752 | struct ath_buf *av_bcbuf; /* beacon buffer */ |
777 | struct ath_beacon_offset av_boff; /* dynamic update state */ | ||
778 | struct ath_tx_control av_btxctl; /* txctl information for beacon */ | 753 | struct ath_tx_control av_btxctl; /* txctl information for beacon */ |
779 | int av_bslot; /* beacon slot index */ | 754 | int av_bslot; /* beacon slot index */ |
780 | struct ath_txq av_mcastq; /* multicast transmit queue */ | ||
781 | struct ath_vap_config av_config;/* vap configuration parameters*/ | 755 | struct ath_vap_config av_config;/* vap configuration parameters*/ |
782 | struct ath_rate_node *rc_node; | 756 | struct ath_rate_node *rc_node; |
783 | }; | 757 | }; |
@@ -788,8 +762,7 @@ int ath_vap_attach(struct ath_softc *sc, | |||
788 | enum ath9k_opmode opmode); | 762 | enum ath9k_opmode opmode); |
789 | int ath_vap_detach(struct ath_softc *sc, int if_id); | 763 | int ath_vap_detach(struct ath_softc *sc, int if_id); |
790 | int ath_vap_config(struct ath_softc *sc, | 764 | int ath_vap_config(struct ath_softc *sc, |
791 | int if_id, struct ath_vap_config *if_config); | 765 | int if_id, struct ath_vap_config *if_config); |
792 | int ath_vap_listen(struct ath_softc *sc, int if_id); | ||
793 | 766 | ||
794 | /*********************/ | 767 | /*********************/ |
795 | /* Antenna diversity */ | 768 | /* Antenna diversity */ |
@@ -830,6 +803,27 @@ void ath_slow_ant_div(struct ath_antdiv *antdiv, | |||
830 | void ath_setdefantenna(void *sc, u32 antenna); | 803 | void ath_setdefantenna(void *sc, u32 antenna); |
831 | 804 | ||
832 | /********************/ | 805 | /********************/ |
806 | /* LED Control */ | ||
807 | /********************/ | ||
808 | |||
809 | #define ATH_LED_PIN 1 | ||
810 | |||
811 | enum ath_led_type { | ||
812 | ATH_LED_RADIO, | ||
813 | ATH_LED_ASSOC, | ||
814 | ATH_LED_TX, | ||
815 | ATH_LED_RX | ||
816 | }; | ||
817 | |||
818 | struct ath_led { | ||
819 | struct ath_softc *sc; | ||
820 | struct led_classdev led_cdev; | ||
821 | enum ath_led_type led_type; | ||
822 | char name[32]; | ||
823 | bool registered; | ||
824 | }; | ||
825 | |||
826 | /********************/ | ||
833 | /* Main driver core */ | 827 | /* Main driver core */ |
834 | /********************/ | 828 | /********************/ |
835 | 829 | ||
@@ -841,11 +835,7 @@ void ath_setdefantenna(void *sc, u32 antenna); | |||
841 | #define ATH_DEFAULT_NOISE_FLOOR -95 | 835 | #define ATH_DEFAULT_NOISE_FLOOR -95 |
842 | #define ATH_REGCLASSIDS_MAX 10 | 836 | #define ATH_REGCLASSIDS_MAX 10 |
843 | #define ATH_CABQ_READY_TIME 80 /* % of beacon interval */ | 837 | #define ATH_CABQ_READY_TIME 80 /* % of beacon interval */ |
844 | #define ATH_PREAMBLE_SHORT (1<<0) | ||
845 | #define ATH_PROTECT_ENABLE (1<<1) | ||
846 | #define ATH_MAX_SW_RETRIES 10 | 838 | #define ATH_MAX_SW_RETRIES 10 |
847 | /* Num farmes difference in tx to flip default recv */ | ||
848 | #define ATH_ANTENNA_DIFF 2 | ||
849 | #define ATH_CHAN_MAX 255 | 839 | #define ATH_CHAN_MAX 255 |
850 | #define IEEE80211_WEP_NKID 4 /* number of key ids */ | 840 | #define IEEE80211_WEP_NKID 4 /* number of key ids */ |
851 | #define IEEE80211_RATE_VAL 0x7f | 841 | #define IEEE80211_RATE_VAL 0x7f |
@@ -859,9 +849,7 @@ void ath_setdefantenna(void *sc, u32 antenna); | |||
859 | */ | 849 | */ |
860 | #define ATH_KEYMAX 128 /* max key cache size we handle */ | 850 | #define ATH_KEYMAX 128 /* max key cache size we handle */ |
861 | 851 | ||
862 | #define RESET_RETRY_TXQ 0x00000001 | ||
863 | #define ATH_IF_ID_ANY 0xff | 852 | #define ATH_IF_ID_ANY 0xff |
864 | |||
865 | #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ | 853 | #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ |
866 | 854 | ||
867 | #define RSSI_LPF_THRESHOLD -20 | 855 | #define RSSI_LPF_THRESHOLD -20 |
@@ -907,60 +895,61 @@ struct ath_ht_info { | |||
907 | u8 ext_chan_offset; | 895 | u8 ext_chan_offset; |
908 | }; | 896 | }; |
909 | 897 | ||
898 | #define SC_OP_INVALID BIT(0) | ||
899 | #define SC_OP_BEACONS BIT(1) | ||
900 | #define SC_OP_RXAGGR BIT(2) | ||
901 | #define SC_OP_TXAGGR BIT(3) | ||
902 | #define SC_OP_CHAINMASK_UPDATE BIT(4) | ||
903 | #define SC_OP_FULL_RESET BIT(5) | ||
904 | #define SC_OP_NO_RESET BIT(6) | ||
905 | #define SC_OP_PREAMBLE_SHORT BIT(7) | ||
906 | #define SC_OP_PROTECT_ENABLE BIT(8) | ||
907 | #define SC_OP_RXFLUSH BIT(9) | ||
908 | #define SC_OP_LED_ASSOCIATED BIT(10) | ||
909 | |||
910 | struct ath_softc { | 910 | struct ath_softc { |
911 | struct ieee80211_hw *hw; | 911 | struct ieee80211_hw *hw; |
912 | struct pci_dev *pdev; | 912 | struct pci_dev *pdev; |
913 | void __iomem *mem; | ||
914 | struct tasklet_struct intr_tq; | 913 | struct tasklet_struct intr_tq; |
915 | struct tasklet_struct bcon_tasklet; | 914 | struct tasklet_struct bcon_tasklet; |
916 | struct ath_config sc_config; /* load-time parameters */ | 915 | struct ath_config sc_config; |
917 | int sc_debug; | ||
918 | struct ath_hal *sc_ah; | 916 | struct ath_hal *sc_ah; |
919 | struct ath_rate_softc *sc_rc; /* tx rate control support */ | 917 | struct ath_rate_softc *sc_rc; |
918 | void __iomem *mem; | ||
919 | |||
920 | u8 sc_curbssid[ETH_ALEN]; | ||
921 | u8 sc_myaddr[ETH_ALEN]; | ||
922 | u8 sc_bssidmask[ETH_ALEN]; | ||
923 | |||
924 | int sc_debug; | ||
920 | u32 sc_intrstatus; | 925 | u32 sc_intrstatus; |
921 | enum ath9k_opmode sc_opmode; /* current operating mode */ | 926 | u32 sc_flags; /* SC_OP_* */ |
922 | 927 | unsigned int rx_filter; | |
923 | u8 sc_invalid; /* being detached */ | ||
924 | u8 sc_beacons; /* beacons running */ | ||
925 | u8 sc_scanning; /* scanning active */ | ||
926 | u8 sc_txaggr; /* enable 11n tx aggregation */ | ||
927 | u8 sc_rxaggr; /* enable 11n rx aggregation */ | ||
928 | u8 sc_update_chainmask; /* change chain mask */ | ||
929 | u8 sc_full_reset; /* force full reset */ | ||
930 | enum wireless_mode sc_curmode; /* current phy mode */ | ||
931 | u16 sc_curtxpow; | 928 | u16 sc_curtxpow; |
932 | u16 sc_curaid; | 929 | u16 sc_curaid; |
933 | u8 sc_curbssid[ETH_ALEN]; | 930 | u16 sc_cachelsz; |
934 | u8 sc_myaddr[ETH_ALEN]; | 931 | int sc_slotupdate; /* slot to next advance fsm */ |
932 | int sc_slottime; | ||
933 | int sc_bslot[ATH_BCBUF]; | ||
934 | u8 sc_tx_chainmask; | ||
935 | u8 sc_rx_chainmask; | ||
936 | enum ath9k_int sc_imask; | ||
937 | enum wireless_mode sc_curmode; /* current phy mode */ | ||
935 | enum PROT_MODE sc_protmode; | 938 | enum PROT_MODE sc_protmode; |
936 | u8 sc_mcastantenna; | 939 | |
937 | u8 sc_txantenna; /* data tx antenna (fixed or auto) */ | ||
938 | u8 sc_nbcnvaps; /* # of vaps sending beacons */ | 940 | u8 sc_nbcnvaps; /* # of vaps sending beacons */ |
939 | u16 sc_nvaps; /* # of active virtual ap's */ | 941 | u16 sc_nvaps; /* # of active virtual ap's */ |
940 | struct ath_vap *sc_vaps[ATH_BCBUF]; | 942 | struct ath_vap *sc_vaps[ATH_BCBUF]; |
941 | enum ath9k_int sc_imask; | 943 | |
942 | u8 sc_bssidmask[ETH_ALEN]; | 944 | u8 sc_mcastantenna; |
943 | u8 sc_defant; /* current default antenna */ | 945 | u8 sc_defant; /* current default antenna */ |
944 | u8 sc_rxotherant; /* rx's on non-default antenna */ | 946 | u8 sc_rxotherant; /* rx's on non-default antenna */ |
945 | u16 sc_cachelsz; | 947 | |
946 | int sc_slotupdate; /* slot to next advance fsm */ | ||
947 | int sc_slottime; | ||
948 | u8 sc_noreset; | ||
949 | int sc_bslot[ATH_BCBUF]; | ||
950 | struct ath9k_node_stats sc_halstats; /* station-mode rssi stats */ | 948 | struct ath9k_node_stats sc_halstats; /* station-mode rssi stats */ |
951 | struct list_head node_list; | 949 | struct list_head node_list; |
952 | struct ath_ht_info sc_ht_info; | 950 | struct ath_ht_info sc_ht_info; |
953 | int16_t sc_noise_floor; /* signal noise floor in dBm */ | ||
954 | enum ath9k_ht_extprotspacing sc_ht_extprotspacing; | 951 | enum ath9k_ht_extprotspacing sc_ht_extprotspacing; |
955 | u8 sc_tx_chainmask; | 952 | |
956 | u8 sc_rx_chainmask; | ||
957 | u8 sc_rxchaindetect_ref; | ||
958 | u8 sc_rxchaindetect_thresh5GHz; | ||
959 | u8 sc_rxchaindetect_thresh2GHz; | ||
960 | u8 sc_rxchaindetect_delta5GHz; | ||
961 | u8 sc_rxchaindetect_delta2GHz; | ||
962 | u32 sc_rtsaggrlimit; /* Chipset specific aggr limit */ | ||
963 | u32 sc_flags; | ||
964 | #ifdef CONFIG_SLOW_ANT_DIV | 953 | #ifdef CONFIG_SLOW_ANT_DIV |
965 | struct ath_antdiv sc_antdiv; | 954 | struct ath_antdiv sc_antdiv; |
966 | #endif | 955 | #endif |
@@ -981,8 +970,6 @@ struct ath_softc { | |||
981 | struct ath_descdma sc_rxdma; | 970 | struct ath_descdma sc_rxdma; |
982 | int sc_rxbufsize; /* rx size based on mtu */ | 971 | int sc_rxbufsize; /* rx size based on mtu */ |
983 | u32 *sc_rxlink; /* link ptr in last RX desc */ | 972 | u32 *sc_rxlink; /* link ptr in last RX desc */ |
984 | u32 sc_rxflush; /* rx flush in progress */ | ||
985 | u64 sc_lastrx; /* tsf of last rx'd frame */ | ||
986 | 973 | ||
987 | /* TX */ | 974 | /* TX */ |
988 | struct list_head sc_txbuf; | 975 | struct list_head sc_txbuf; |
@@ -991,7 +978,7 @@ struct ath_softc { | |||
991 | u32 sc_txqsetup; | 978 | u32 sc_txqsetup; |
992 | u32 sc_txintrperiod; /* tx interrupt batching */ | 979 | u32 sc_txintrperiod; /* tx interrupt batching */ |
993 | int sc_haltype2q[ATH9K_WME_AC_VO+1]; /* HAL WME AC -> h/w qnum */ | 980 | int sc_haltype2q[ATH9K_WME_AC_VO+1]; /* HAL WME AC -> h/w qnum */ |
994 | u32 sc_ant_tx[8]; /* recent tx frames/antenna */ | 981 | u16 seq_no; /* TX sequence number */ |
995 | 982 | ||
996 | /* Beacon */ | 983 | /* Beacon */ |
997 | struct ath9k_tx_queue_info sc_beacon_qi; | 984 | struct ath9k_tx_queue_info sc_beacon_qi; |
@@ -1015,7 +1002,6 @@ struct ath_softc { | |||
1015 | /* Channel, Band */ | 1002 | /* Channel, Band */ |
1016 | struct ieee80211_channel channels[IEEE80211_NUM_BANDS][ATH_CHAN_MAX]; | 1003 | struct ieee80211_channel channels[IEEE80211_NUM_BANDS][ATH_CHAN_MAX]; |
1017 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; | 1004 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; |
1018 | struct ath9k_channel sc_curchan; | ||
1019 | 1005 | ||
1020 | /* Locks */ | 1006 | /* Locks */ |
1021 | spinlock_t sc_rxflushlock; | 1007 | spinlock_t sc_rxflushlock; |
@@ -1023,6 +1009,12 @@ struct ath_softc { | |||
1023 | spinlock_t sc_txbuflock; | 1009 | spinlock_t sc_txbuflock; |
1024 | spinlock_t sc_resetlock; | 1010 | spinlock_t sc_resetlock; |
1025 | spinlock_t node_lock; | 1011 | spinlock_t node_lock; |
1012 | |||
1013 | /* LEDs */ | ||
1014 | struct ath_led radio_led; | ||
1015 | struct ath_led assoc_led; | ||
1016 | struct ath_led tx_led; | ||
1017 | struct ath_led rx_led; | ||
1026 | }; | 1018 | }; |
1027 | 1019 | ||
1028 | int ath_init(u16 devid, struct ath_softc *sc); | 1020 | int ath_init(u16 devid, struct ath_softc *sc); |
@@ -1030,14 +1022,8 @@ void ath_deinit(struct ath_softc *sc); | |||
1030 | int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan); | 1022 | int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan); |
1031 | int ath_suspend(struct ath_softc *sc); | 1023 | int ath_suspend(struct ath_softc *sc); |
1032 | irqreturn_t ath_isr(int irq, void *dev); | 1024 | irqreturn_t ath_isr(int irq, void *dev); |
1033 | int ath_reset(struct ath_softc *sc); | 1025 | int ath_reset(struct ath_softc *sc, bool retry_tx); |
1034 | void ath_scan_start(struct ath_softc *sc); | ||
1035 | void ath_scan_end(struct ath_softc *sc); | ||
1036 | int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan); | 1026 | int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan); |
1037 | void ath_setup_rate(struct ath_softc *sc, | ||
1038 | enum wireless_mode wMode, | ||
1039 | enum RATE_TYPE type, | ||
1040 | const struct ath9k_rate_table *rt); | ||
1041 | 1027 | ||
1042 | /*********************/ | 1028 | /*********************/ |
1043 | /* Utility Functions */ | 1029 | /* Utility Functions */ |
@@ -1056,17 +1042,5 @@ int ath_cabq_update(struct ath_softc *); | |||
1056 | void ath_get_currentCountry(struct ath_softc *sc, | 1042 | void ath_get_currentCountry(struct ath_softc *sc, |
1057 | struct ath9k_country_entry *ctry); | 1043 | struct ath9k_country_entry *ctry); |
1058 | u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp); | 1044 | u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp); |
1059 | void ath_internal_reset(struct ath_softc *sc); | ||
1060 | u32 ath_chan2flags(struct ieee80211_channel *chan, struct ath_softc *sc); | ||
1061 | dma_addr_t ath_skb_map_single(struct ath_softc *sc, | ||
1062 | struct sk_buff *skb, | ||
1063 | int direction, | ||
1064 | dma_addr_t *pa); | ||
1065 | void ath_skb_unmap_single(struct ath_softc *sc, | ||
1066 | struct sk_buff *skb, | ||
1067 | int direction, | ||
1068 | dma_addr_t *pa); | ||
1069 | void ath_mcast_merge(struct ath_softc *sc, u32 mfilt[2]); | ||
1070 | enum ath9k_ht_macmode ath_cwm_macmode(struct ath_softc *sc); | ||
1071 | 1045 | ||
1072 | #endif /* CORE_H */ | 1046 | #endif /* CORE_H */ |
diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index a17eb130f574..2578411c6019 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c | |||
@@ -85,29 +85,6 @@ static const struct hal_percal_data adc_init_dc_cal = { | |||
85 | ath9k_hw_adc_dccal_calibrate | 85 | ath9k_hw_adc_dccal_calibrate |
86 | }; | 86 | }; |
87 | 87 | ||
88 | static const struct ath_hal ar5416hal = { | ||
89 | AR5416_MAGIC, | ||
90 | 0, | ||
91 | 0, | ||
92 | NULL, | ||
93 | NULL, | ||
94 | CTRY_DEFAULT, | ||
95 | 0, | ||
96 | 0, | ||
97 | 0, | ||
98 | 0, | ||
99 | 0, | ||
100 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
101 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
102 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
103 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
104 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
105 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
106 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
107 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
108 | }, | ||
109 | }; | ||
110 | |||
111 | static struct ath9k_rate_table ar5416_11a_table = { | 88 | static struct ath9k_rate_table ar5416_11a_table = { |
112 | 8, | 89 | 8, |
113 | {0}, | 90 | {0}, |
@@ -371,7 +348,7 @@ static void ath9k_hw_set_defaults(struct ath_hal *ah) | |||
371 | ah->ah_config.intr_mitigation = 0; | 348 | ah->ah_config.intr_mitigation = 0; |
372 | } | 349 | } |
373 | 350 | ||
374 | static inline void ath9k_hw_override_ini(struct ath_hal *ah, | 351 | static void ath9k_hw_override_ini(struct ath_hal *ah, |
375 | struct ath9k_channel *chan) | 352 | struct ath9k_channel *chan) |
376 | { | 353 | { |
377 | if (!AR_SREV_5416_V20_OR_LATER(ah) | 354 | if (!AR_SREV_5416_V20_OR_LATER(ah) |
@@ -381,8 +358,8 @@ static inline void ath9k_hw_override_ini(struct ath_hal *ah, | |||
381 | REG_WRITE(ah, 0x9800 + (651 << 2), 0x11); | 358 | REG_WRITE(ah, 0x9800 + (651 << 2), 0x11); |
382 | } | 359 | } |
383 | 360 | ||
384 | static inline void ath9k_hw_init_bb(struct ath_hal *ah, | 361 | static void ath9k_hw_init_bb(struct ath_hal *ah, |
385 | struct ath9k_channel *chan) | 362 | struct ath9k_channel *chan) |
386 | { | 363 | { |
387 | u32 synthDelay; | 364 | u32 synthDelay; |
388 | 365 | ||
@@ -397,8 +374,8 @@ static inline void ath9k_hw_init_bb(struct ath_hal *ah, | |||
397 | udelay(synthDelay + BASE_ACTIVATE_DELAY); | 374 | udelay(synthDelay + BASE_ACTIVATE_DELAY); |
398 | } | 375 | } |
399 | 376 | ||
400 | static inline void ath9k_hw_init_interrupt_masks(struct ath_hal *ah, | 377 | static void ath9k_hw_init_interrupt_masks(struct ath_hal *ah, |
401 | enum ath9k_opmode opmode) | 378 | enum ath9k_opmode opmode) |
402 | { | 379 | { |
403 | struct ath_hal_5416 *ahp = AH5416(ah); | 380 | struct ath_hal_5416 *ahp = AH5416(ah); |
404 | 381 | ||
@@ -428,7 +405,7 @@ static inline void ath9k_hw_init_interrupt_masks(struct ath_hal *ah, | |||
428 | } | 405 | } |
429 | } | 406 | } |
430 | 407 | ||
431 | static inline void ath9k_hw_init_qos(struct ath_hal *ah) | 408 | static void ath9k_hw_init_qos(struct ath_hal *ah) |
432 | { | 409 | { |
433 | REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa); | 410 | REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa); |
434 | REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210); | 411 | REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210); |
@@ -523,7 +500,7 @@ static inline bool ath9k_hw_nvram_read(struct ath_hal *ah, | |||
523 | return ath9k_hw_eeprom_read(ah, off, data); | 500 | return ath9k_hw_eeprom_read(ah, off, data); |
524 | } | 501 | } |
525 | 502 | ||
526 | static inline bool ath9k_hw_fill_eeprom(struct ath_hal *ah) | 503 | static bool ath9k_hw_fill_eeprom(struct ath_hal *ah) |
527 | { | 504 | { |
528 | struct ath_hal_5416 *ahp = AH5416(ah); | 505 | struct ath_hal_5416 *ahp = AH5416(ah); |
529 | struct ar5416_eeprom *eep = &ahp->ah_eeprom; | 506 | struct ar5416_eeprom *eep = &ahp->ah_eeprom; |
@@ -790,7 +767,7 @@ ath9k_hw_eeprom_set_board_values(struct ath_hal *ah, | |||
790 | return true; | 767 | return true; |
791 | } | 768 | } |
792 | 769 | ||
793 | static inline int ath9k_hw_check_eeprom(struct ath_hal *ah) | 770 | static int ath9k_hw_check_eeprom(struct ath_hal *ah) |
794 | { | 771 | { |
795 | u32 sum = 0, el; | 772 | u32 sum = 0, el; |
796 | u16 *eepdata; | 773 | u16 *eepdata; |
@@ -1196,11 +1173,12 @@ static struct ath_hal_5416 *ath9k_hw_newstate(u16 devid, | |||
1196 | 1173 | ||
1197 | ah = &ahp->ah; | 1174 | ah = &ahp->ah; |
1198 | 1175 | ||
1199 | memcpy(&ahp->ah, &ar5416hal, sizeof(struct ath_hal)); | ||
1200 | |||
1201 | ah->ah_sc = sc; | 1176 | ah->ah_sc = sc; |
1202 | ah->ah_sh = mem; | 1177 | ah->ah_sh = mem; |
1203 | 1178 | ||
1179 | ah->ah_magic = AR5416_MAGIC; | ||
1180 | ah->ah_countryCode = CTRY_DEFAULT; | ||
1181 | |||
1204 | ah->ah_devid = devid; | 1182 | ah->ah_devid = devid; |
1205 | ah->ah_subvendorid = 0; | 1183 | ah->ah_subvendorid = 0; |
1206 | 1184 | ||
@@ -1294,7 +1272,7 @@ u32 ath9k_hw_get_eeprom(struct ath_hal_5416 *ahp, | |||
1294 | } | 1272 | } |
1295 | } | 1273 | } |
1296 | 1274 | ||
1297 | static inline int ath9k_hw_get_radiorev(struct ath_hal *ah) | 1275 | static int ath9k_hw_get_radiorev(struct ath_hal *ah) |
1298 | { | 1276 | { |
1299 | u32 val; | 1277 | u32 val; |
1300 | int i; | 1278 | int i; |
@@ -1307,7 +1285,7 @@ static inline int ath9k_hw_get_radiorev(struct ath_hal *ah) | |||
1307 | return ath9k_hw_reverse_bits(val, 8); | 1285 | return ath9k_hw_reverse_bits(val, 8); |
1308 | } | 1286 | } |
1309 | 1287 | ||
1310 | static inline int ath9k_hw_init_macaddr(struct ath_hal *ah) | 1288 | static int ath9k_hw_init_macaddr(struct ath_hal *ah) |
1311 | { | 1289 | { |
1312 | u32 sum; | 1290 | u32 sum; |
1313 | int i; | 1291 | int i; |
@@ -1389,7 +1367,7 @@ static u16 ath9k_hw_eeprom_get_spur_chan(struct ath_hal *ah, | |||
1389 | return spur_val; | 1367 | return spur_val; |
1390 | } | 1368 | } |
1391 | 1369 | ||
1392 | static inline int ath9k_hw_rfattach(struct ath_hal *ah) | 1370 | static int ath9k_hw_rfattach(struct ath_hal *ah) |
1393 | { | 1371 | { |
1394 | bool rfStatus = false; | 1372 | bool rfStatus = false; |
1395 | int ecode = 0; | 1373 | int ecode = 0; |
@@ -1434,8 +1412,8 @@ static int ath9k_hw_rf_claim(struct ath_hal *ah) | |||
1434 | return 0; | 1412 | return 0; |
1435 | } | 1413 | } |
1436 | 1414 | ||
1437 | static inline void ath9k_hw_init_pll(struct ath_hal *ah, | 1415 | static void ath9k_hw_init_pll(struct ath_hal *ah, |
1438 | struct ath9k_channel *chan) | 1416 | struct ath9k_channel *chan) |
1439 | { | 1417 | { |
1440 | u32 pll; | 1418 | u32 pll; |
1441 | 1419 | ||
@@ -1553,7 +1531,7 @@ static void ath9k_hw_set_operating_mode(struct ath_hal *ah, int opmode) | |||
1553 | } | 1531 | } |
1554 | } | 1532 | } |
1555 | 1533 | ||
1556 | static inline void | 1534 | static void |
1557 | ath9k_hw_set_rfmode(struct ath_hal *ah, struct ath9k_channel *chan) | 1535 | ath9k_hw_set_rfmode(struct ath_hal *ah, struct ath9k_channel *chan) |
1558 | { | 1536 | { |
1559 | u32 rfMode = 0; | 1537 | u32 rfMode = 0; |
@@ -1623,7 +1601,7 @@ static bool ath9k_hw_set_reset(struct ath_hal *ah, int type) | |||
1623 | return true; | 1601 | return true; |
1624 | } | 1602 | } |
1625 | 1603 | ||
1626 | static inline bool ath9k_hw_set_reset_power_on(struct ath_hal *ah) | 1604 | static bool ath9k_hw_set_reset_power_on(struct ath_hal *ah) |
1627 | { | 1605 | { |
1628 | REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | | 1606 | REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | |
1629 | AR_RTC_FORCE_WAKE_ON_INT); | 1607 | AR_RTC_FORCE_WAKE_ON_INT); |
@@ -1664,7 +1642,7 @@ static bool ath9k_hw_set_reset_reg(struct ath_hal *ah, | |||
1664 | } | 1642 | } |
1665 | } | 1643 | } |
1666 | 1644 | ||
1667 | static inline | 1645 | static |
1668 | struct ath9k_channel *ath9k_hw_check_chan(struct ath_hal *ah, | 1646 | struct ath9k_channel *ath9k_hw_check_chan(struct ath_hal *ah, |
1669 | struct ath9k_channel *chan) | 1647 | struct ath9k_channel *chan) |
1670 | { | 1648 | { |
@@ -2098,7 +2076,7 @@ static void ath9k_hw_ani_attach(struct ath_hal *ah) | |||
2098 | ahp->ah_procPhyErr |= HAL_PROCESS_ANI; | 2076 | ahp->ah_procPhyErr |= HAL_PROCESS_ANI; |
2099 | } | 2077 | } |
2100 | 2078 | ||
2101 | static inline void ath9k_hw_ani_setup(struct ath_hal *ah) | 2079 | static void ath9k_hw_ani_setup(struct ath_hal *ah) |
2102 | { | 2080 | { |
2103 | struct ath_hal_5416 *ahp = AH5416(ah); | 2081 | struct ath_hal_5416 *ahp = AH5416(ah); |
2104 | int i; | 2082 | int i; |
@@ -2822,32 +2800,11 @@ static void ath9k_hw_gpio_cfg_output_mux(struct ath_hal *ah, | |||
2822 | } | 2800 | } |
2823 | } | 2801 | } |
2824 | 2802 | ||
2825 | static bool ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio, | 2803 | void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio, |
2826 | enum ath9k_gpio_output_mux_type | 2804 | u32 ah_signal_type) |
2827 | halSignalType) | ||
2828 | { | 2805 | { |
2829 | u32 ah_signal_type; | ||
2830 | u32 gpio_shift; | 2806 | u32 gpio_shift; |
2831 | 2807 | ||
2832 | static u32 MuxSignalConversionTable[] = { | ||
2833 | |||
2834 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT, | ||
2835 | |||
2836 | AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED, | ||
2837 | |||
2838 | AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED, | ||
2839 | |||
2840 | AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED, | ||
2841 | |||
2842 | AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED, | ||
2843 | }; | ||
2844 | |||
2845 | if ((halSignalType >= 0) | ||
2846 | && (halSignalType < ARRAY_SIZE(MuxSignalConversionTable))) | ||
2847 | ah_signal_type = MuxSignalConversionTable[halSignalType]; | ||
2848 | else | ||
2849 | return false; | ||
2850 | |||
2851 | ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type); | 2808 | ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type); |
2852 | 2809 | ||
2853 | gpio_shift = 2 * gpio; | 2810 | gpio_shift = 2 * gpio; |
@@ -2856,16 +2813,12 @@ static bool ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio, | |||
2856 | AR_GPIO_OE_OUT, | 2813 | AR_GPIO_OE_OUT, |
2857 | (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift), | 2814 | (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift), |
2858 | (AR_GPIO_OE_OUT_DRV << gpio_shift)); | 2815 | (AR_GPIO_OE_OUT_DRV << gpio_shift)); |
2859 | |||
2860 | return true; | ||
2861 | } | 2816 | } |
2862 | 2817 | ||
2863 | static bool ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, | 2818 | void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 val) |
2864 | u32 val) | ||
2865 | { | 2819 | { |
2866 | REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio), | 2820 | REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio), |
2867 | AR_GPIO_BIT(gpio)); | 2821 | AR_GPIO_BIT(gpio)); |
2868 | return true; | ||
2869 | } | 2822 | } |
2870 | 2823 | ||
2871 | static u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio) | 2824 | static u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio) |
@@ -2883,7 +2836,7 @@ static u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio) | |||
2883 | } | 2836 | } |
2884 | } | 2837 | } |
2885 | 2838 | ||
2886 | static inline int ath9k_hw_post_attach(struct ath_hal *ah) | 2839 | static int ath9k_hw_post_attach(struct ath_hal *ah) |
2887 | { | 2840 | { |
2888 | int ecode; | 2841 | int ecode; |
2889 | 2842 | ||
@@ -3595,7 +3548,7 @@ static inline bool ath9k_hw_fill_vpd_table(u8 pwrMin, | |||
3595 | return true; | 3548 | return true; |
3596 | } | 3549 | } |
3597 | 3550 | ||
3598 | static inline void | 3551 | static void |
3599 | ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hal *ah, | 3552 | ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hal *ah, |
3600 | struct ath9k_channel *chan, | 3553 | struct ath9k_channel *chan, |
3601 | struct cal_data_per_freq *pRawDataSet, | 3554 | struct cal_data_per_freq *pRawDataSet, |
@@ -3777,7 +3730,7 @@ ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hal *ah, | |||
3777 | return; | 3730 | return; |
3778 | } | 3731 | } |
3779 | 3732 | ||
3780 | static inline bool | 3733 | static bool |
3781 | ath9k_hw_set_power_cal_table(struct ath_hal *ah, | 3734 | ath9k_hw_set_power_cal_table(struct ath_hal *ah, |
3782 | struct ar5416_eeprom *pEepData, | 3735 | struct ar5416_eeprom *pEepData, |
3783 | struct ath9k_channel *chan, | 3736 | struct ath9k_channel *chan, |
@@ -3980,7 +3933,7 @@ void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore) | |||
3980 | } | 3933 | } |
3981 | } | 3934 | } |
3982 | 3935 | ||
3983 | static inline void | 3936 | static void |
3984 | ath9k_hw_get_legacy_target_powers(struct ath_hal *ah, | 3937 | ath9k_hw_get_legacy_target_powers(struct ath_hal *ah, |
3985 | struct ath9k_channel *chan, | 3938 | struct ath9k_channel *chan, |
3986 | struct cal_target_power_leg *powInfo, | 3939 | struct cal_target_power_leg *powInfo, |
@@ -4046,7 +3999,7 @@ ath9k_hw_get_legacy_target_powers(struct ath_hal *ah, | |||
4046 | } | 3999 | } |
4047 | } | 4000 | } |
4048 | 4001 | ||
4049 | static inline void | 4002 | static void |
4050 | ath9k_hw_get_target_powers(struct ath_hal *ah, | 4003 | ath9k_hw_get_target_powers(struct ath_hal *ah, |
4051 | struct ath9k_channel *chan, | 4004 | struct ath9k_channel *chan, |
4052 | struct cal_target_power_ht *powInfo, | 4005 | struct cal_target_power_ht *powInfo, |
@@ -4113,7 +4066,7 @@ ath9k_hw_get_target_powers(struct ath_hal *ah, | |||
4113 | } | 4066 | } |
4114 | } | 4067 | } |
4115 | 4068 | ||
4116 | static inline u16 | 4069 | static u16 |
4117 | ath9k_hw_get_max_edge_power(u16 freq, | 4070 | ath9k_hw_get_max_edge_power(u16 freq, |
4118 | struct cal_ctl_edges *pRdEdgesPower, | 4071 | struct cal_ctl_edges *pRdEdgesPower, |
4119 | bool is2GHz) | 4072 | bool is2GHz) |
@@ -4143,7 +4096,7 @@ ath9k_hw_get_max_edge_power(u16 freq, | |||
4143 | return twiceMaxEdgePower; | 4096 | return twiceMaxEdgePower; |
4144 | } | 4097 | } |
4145 | 4098 | ||
4146 | static inline bool | 4099 | static bool |
4147 | ath9k_hw_set_power_per_rate_table(struct ath_hal *ah, | 4100 | ath9k_hw_set_power_per_rate_table(struct ath_hal *ah, |
4148 | struct ar5416_eeprom *pEepData, | 4101 | struct ar5416_eeprom *pEepData, |
4149 | struct ath9k_channel *chan, | 4102 | struct ath9k_channel *chan, |
@@ -5122,7 +5075,7 @@ static void ath9k_hw_spur_mitigate(struct ath_hal *ah, | |||
5122 | REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); | 5075 | REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); |
5123 | } | 5076 | } |
5124 | 5077 | ||
5125 | static inline void ath9k_hw_init_chain_masks(struct ath_hal *ah) | 5078 | static void ath9k_hw_init_chain_masks(struct ath_hal *ah) |
5126 | { | 5079 | { |
5127 | struct ath_hal_5416 *ahp = AH5416(ah); | 5080 | struct ath_hal_5416 *ahp = AH5416(ah); |
5128 | int rx_chainmask, tx_chainmask; | 5081 | int rx_chainmask, tx_chainmask; |
@@ -5326,7 +5279,7 @@ bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us) | |||
5326 | } | 5279 | } |
5327 | } | 5280 | } |
5328 | 5281 | ||
5329 | static inline void ath9k_hw_init_user_settings(struct ath_hal *ah) | 5282 | static void ath9k_hw_init_user_settings(struct ath_hal *ah) |
5330 | { | 5283 | { |
5331 | struct ath_hal_5416 *ahp = AH5416(ah); | 5284 | struct ath_hal_5416 *ahp = AH5416(ah); |
5332 | 5285 | ||
@@ -5345,7 +5298,7 @@ static inline void ath9k_hw_init_user_settings(struct ath_hal *ah) | |||
5345 | ath9k_hw_set_global_txtimeout(ah, ahp->ah_globaltxtimeout); | 5298 | ath9k_hw_set_global_txtimeout(ah, ahp->ah_globaltxtimeout); |
5346 | } | 5299 | } |
5347 | 5300 | ||
5348 | static inline int | 5301 | static int |
5349 | ath9k_hw_process_ini(struct ath_hal *ah, | 5302 | ath9k_hw_process_ini(struct ath_hal *ah, |
5350 | struct ath9k_channel *chan, | 5303 | struct ath9k_channel *chan, |
5351 | enum ath9k_ht_macmode macmode) | 5304 | enum ath9k_ht_macmode macmode) |
@@ -5476,7 +5429,7 @@ ath9k_hw_process_ini(struct ath_hal *ah, | |||
5476 | return 0; | 5429 | return 0; |
5477 | } | 5430 | } |
5478 | 5431 | ||
5479 | static inline void ath9k_hw_setup_calibration(struct ath_hal *ah, | 5432 | static void ath9k_hw_setup_calibration(struct ath_hal *ah, |
5480 | struct hal_cal_list *currCal) | 5433 | struct hal_cal_list *currCal) |
5481 | { | 5434 | { |
5482 | REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0), | 5435 | REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0), |
@@ -5512,8 +5465,8 @@ static inline void ath9k_hw_setup_calibration(struct ath_hal *ah, | |||
5512 | AR_PHY_TIMING_CTRL4_DO_CAL); | 5465 | AR_PHY_TIMING_CTRL4_DO_CAL); |
5513 | } | 5466 | } |
5514 | 5467 | ||
5515 | static inline void ath9k_hw_reset_calibration(struct ath_hal *ah, | 5468 | static void ath9k_hw_reset_calibration(struct ath_hal *ah, |
5516 | struct hal_cal_list *currCal) | 5469 | struct hal_cal_list *currCal) |
5517 | { | 5470 | { |
5518 | struct ath_hal_5416 *ahp = AH5416(ah); | 5471 | struct ath_hal_5416 *ahp = AH5416(ah); |
5519 | int i; | 5472 | int i; |
@@ -5532,7 +5485,7 @@ static inline void ath9k_hw_reset_calibration(struct ath_hal *ah, | |||
5532 | ahp->ah_CalSamples = 0; | 5485 | ahp->ah_CalSamples = 0; |
5533 | } | 5486 | } |
5534 | 5487 | ||
5535 | static inline void | 5488 | static void |
5536 | ath9k_hw_per_calibration(struct ath_hal *ah, | 5489 | ath9k_hw_per_calibration(struct ath_hal *ah, |
5537 | struct ath9k_channel *ichan, | 5490 | struct ath9k_channel *ichan, |
5538 | u8 rxchainmask, | 5491 | u8 rxchainmask, |
@@ -5622,7 +5575,7 @@ static inline bool ath9k_hw_run_init_cals(struct ath_hal *ah, | |||
5622 | return true; | 5575 | return true; |
5623 | } | 5576 | } |
5624 | 5577 | ||
5625 | static inline bool | 5578 | static bool |
5626 | ath9k_hw_channel_change(struct ath_hal *ah, | 5579 | ath9k_hw_channel_change(struct ath_hal *ah, |
5627 | struct ath9k_channel *chan, | 5580 | struct ath9k_channel *chan, |
5628 | enum ath9k_ht_macmode macmode) | 5581 | enum ath9k_ht_macmode macmode) |
@@ -5799,8 +5752,8 @@ static bool ath9k_hw_iscal_supported(struct ath_hal *ah, | |||
5799 | return retval; | 5752 | return retval; |
5800 | } | 5753 | } |
5801 | 5754 | ||
5802 | static inline bool ath9k_hw_init_cal(struct ath_hal *ah, | 5755 | static bool ath9k_hw_init_cal(struct ath_hal *ah, |
5803 | struct ath9k_channel *chan) | 5756 | struct ath9k_channel *chan) |
5804 | { | 5757 | { |
5805 | struct ath_hal_5416 *ahp = AH5416(ah); | 5758 | struct ath_hal_5416 *ahp = AH5416(ah); |
5806 | struct ath9k_channel *ichan = | 5759 | struct ath9k_channel *ichan = |
@@ -5861,7 +5814,7 @@ static inline bool ath9k_hw_init_cal(struct ath_hal *ah, | |||
5861 | } | 5814 | } |
5862 | 5815 | ||
5863 | 5816 | ||
5864 | bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode, | 5817 | bool ath9k_hw_reset(struct ath_hal *ah, |
5865 | struct ath9k_channel *chan, | 5818 | struct ath9k_channel *chan, |
5866 | enum ath9k_ht_macmode macmode, | 5819 | enum ath9k_ht_macmode macmode, |
5867 | u8 txchainmask, u8 rxchainmask, | 5820 | u8 txchainmask, u8 rxchainmask, |
@@ -5945,7 +5898,7 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode, | |||
5945 | else | 5898 | else |
5946 | ath9k_hw_set_gpio(ah, 9, 1); | 5899 | ath9k_hw_set_gpio(ah, 9, 1); |
5947 | } | 5900 | } |
5948 | ath9k_hw_cfg_output(ah, 9, ATH9K_GPIO_OUTPUT_MUX_AS_OUTPUT); | 5901 | ath9k_hw_cfg_output(ah, 9, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); |
5949 | } | 5902 | } |
5950 | 5903 | ||
5951 | ecode = ath9k_hw_process_ini(ah, chan, macmode); | 5904 | ecode = ath9k_hw_process_ini(ah, chan, macmode); |
@@ -5975,7 +5928,7 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode, | |||
5975 | | (ah->ah_config. | 5928 | | (ah->ah_config. |
5976 | ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0) | 5929 | ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0) |
5977 | | ahp->ah_staId1Defaults); | 5930 | | ahp->ah_staId1Defaults); |
5978 | ath9k_hw_set_operating_mode(ah, opmode); | 5931 | ath9k_hw_set_operating_mode(ah, ah->ah_opmode); |
5979 | 5932 | ||
5980 | REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(ahp->ah_bssidmask)); | 5933 | REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(ahp->ah_bssidmask)); |
5981 | REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(ahp->ah_bssidmask + 4)); | 5934 | REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(ahp->ah_bssidmask + 4)); |
@@ -6005,13 +5958,11 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode, | |||
6005 | for (i = 0; i < ah->ah_caps.total_queues; i++) | 5958 | for (i = 0; i < ah->ah_caps.total_queues; i++) |
6006 | ath9k_hw_resettxqueue(ah, i); | 5959 | ath9k_hw_resettxqueue(ah, i); |
6007 | 5960 | ||
6008 | ath9k_hw_init_interrupt_masks(ah, opmode); | 5961 | ath9k_hw_init_interrupt_masks(ah, ah->ah_opmode); |
6009 | ath9k_hw_init_qos(ah); | 5962 | ath9k_hw_init_qos(ah); |
6010 | 5963 | ||
6011 | ath9k_hw_init_user_settings(ah); | 5964 | ath9k_hw_init_user_settings(ah); |
6012 | 5965 | ||
6013 | ah->ah_opmode = opmode; | ||
6014 | |||
6015 | REG_WRITE(ah, AR_STA_ID1, | 5966 | REG_WRITE(ah, AR_STA_ID1, |
6016 | REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM); | 5967 | REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM); |
6017 | 5968 | ||
@@ -7678,8 +7629,7 @@ bool ath9k_hw_resettxqueue(struct ath_hal *ah, u32 q) | |||
7678 | REG_WRITE(ah, AR_DRETRY_LIMIT(q), | 7629 | REG_WRITE(ah, AR_DRETRY_LIMIT(q), |
7679 | SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) | 7630 | SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) |
7680 | | SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) | 7631 | | SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) |
7681 | | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH) | 7632 | | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH)); |
7682 | ); | ||
7683 | 7633 | ||
7684 | REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ); | 7634 | REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ); |
7685 | REG_WRITE(ah, AR_DMISC(q), | 7635 | REG_WRITE(ah, AR_DMISC(q), |
@@ -8324,15 +8274,7 @@ struct ath_hal *ath9k_hw_attach(u16 devid, | |||
8324 | *error = -ENXIO; | 8274 | *error = -ENXIO; |
8325 | break; | 8275 | break; |
8326 | } | 8276 | } |
8327 | if (ah != NULL) { | 8277 | |
8328 | ah->ah_devid = ah->ah_devid; | ||
8329 | ah->ah_subvendorid = ah->ah_subvendorid; | ||
8330 | ah->ah_macVersion = ah->ah_macVersion; | ||
8331 | ah->ah_macRev = ah->ah_macRev; | ||
8332 | ah->ah_phyRev = ah->ah_phyRev; | ||
8333 | ah->ah_analog5GhzRev = ah->ah_analog5GhzRev; | ||
8334 | ah->ah_analog2GhzRev = ah->ah_analog2GhzRev; | ||
8335 | } | ||
8336 | return ah; | 8278 | return ah; |
8337 | } | 8279 | } |
8338 | 8280 | ||
diff --git a/drivers/net/wireless/ath9k/hw.h b/drivers/net/wireless/ath9k/hw.h index ae680f21ba7e..2113818ee934 100644 --- a/drivers/net/wireless/ath9k/hw.h +++ b/drivers/net/wireless/ath9k/hw.h | |||
@@ -314,14 +314,11 @@ struct ar5416_desc { | |||
314 | #define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_V20_OR_LATER(ah) ? \ | 314 | #define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_V20_OR_LATER(ah) ? \ |
315 | MS(ads->ds_rxstatus0, AR_RxRate) : \ | 315 | MS(ads->ds_rxstatus0, AR_RxRate) : \ |
316 | (ads->ds_rxstatus3 >> 2) & 0xFF) | 316 | (ads->ds_rxstatus3 >> 2) & 0xFF) |
317 | #define RXSTATUS_DUPLICATE(ah, ads) (AR_SREV_5416_V20_OR_LATER(ah) ? \ | ||
318 | MS(ads->ds_rxstatus3, AR_Parallel40) : \ | ||
319 | (ads->ds_rxstatus3 >> 10) & 0x1) | ||
320 | 317 | ||
321 | #define set11nTries(_series, _index) \ | 318 | #define set11nTries(_series, _index) \ |
322 | (SM((_series)[_index].Tries, AR_XmitDataTries##_index)) | 319 | (SM((_series)[_index].Tries, AR_XmitDataTries##_index)) |
323 | 320 | ||
324 | #define set11nRate(_series, _index) \ | 321 | #define set11nRate(_series, _index) \ |
325 | (SM((_series)[_index].Rate, AR_XmitRate##_index)) | 322 | (SM((_series)[_index].Rate, AR_XmitRate##_index)) |
326 | 323 | ||
327 | #define set11nPktDurRTSCTS(_series, _index) \ | 324 | #define set11nPktDurRTSCTS(_series, _index) \ |
@@ -330,11 +327,11 @@ struct ar5416_desc { | |||
330 | AR_RTSCTSQual##_index : 0)) | 327 | AR_RTSCTSQual##_index : 0)) |
331 | 328 | ||
332 | #define set11nRateFlags(_series, _index) \ | 329 | #define set11nRateFlags(_series, _index) \ |
333 | (((_series)[_index].RateFlags & ATH9K_RATESERIES_2040 ? \ | 330 | (((_series)[_index].RateFlags & ATH9K_RATESERIES_2040 ? \ |
334 | AR_2040_##_index : 0) \ | 331 | AR_2040_##_index : 0) \ |
335 | |((_series)[_index].RateFlags & ATH9K_RATESERIES_HALFGI ? \ | 332 | |((_series)[_index].RateFlags & ATH9K_RATESERIES_HALFGI ? \ |
336 | AR_GI##_index : 0) \ | 333 | AR_GI##_index : 0) \ |
337 | |SM((_series)[_index].ChSel, AR_ChainSel##_index)) | 334 | |SM((_series)[_index].ChSel, AR_ChainSel##_index)) |
338 | 335 | ||
339 | #define AR_SREV_9100(ah) ((ah->ah_macVersion) == AR_SREV_VERSION_9100) | 336 | #define AR_SREV_9100(ah) ((ah->ah_macVersion) == AR_SREV_VERSION_9100) |
340 | 337 | ||
@@ -346,9 +343,6 @@ struct ar5416_desc { | |||
346 | #define MAX_TX_FIFO_THRESHOLD ((4096 / 64) - 1) | 343 | #define MAX_TX_FIFO_THRESHOLD ((4096 / 64) - 1) |
347 | #define INIT_TX_FIFO_THRESHOLD MIN_TX_FIFO_THRESHOLD | 344 | #define INIT_TX_FIFO_THRESHOLD MIN_TX_FIFO_THRESHOLD |
348 | 345 | ||
349 | #define NUM_CORNER_FIX_BITS_2133 7 | ||
350 | #define CCK_OFDM_GAIN_DELTA 15 | ||
351 | |||
352 | struct ar5416AniState { | 346 | struct ar5416AniState { |
353 | struct ath9k_channel c; | 347 | struct ath9k_channel c; |
354 | u8 noiseImmunityLevel; | 348 | u8 noiseImmunityLevel; |
@@ -377,11 +371,8 @@ struct ar5416AniState { | |||
377 | }; | 371 | }; |
378 | 372 | ||
379 | #define HAL_PROCESS_ANI 0x00000001 | 373 | #define HAL_PROCESS_ANI 0x00000001 |
380 | #define HAL_RADAR_EN 0x80000000 | ||
381 | #define HAL_AR_EN 0x40000000 | ||
382 | |||
383 | #define DO_ANI(ah) \ | 374 | #define DO_ANI(ah) \ |
384 | ((AH5416(ah)->ah_procPhyErr & HAL_PROCESS_ANI)) | 375 | ((AH5416(ah)->ah_procPhyErr & HAL_PROCESS_ANI)) |
385 | 376 | ||
386 | struct ar5416Stats { | 377 | struct ar5416Stats { |
387 | u32 ast_ani_niup; | 378 | u32 ast_ani_niup; |
@@ -425,7 +416,6 @@ struct ar5416Stats { | |||
425 | #define AR5416_EEP_MINOR_VER_7 0x7 | 416 | #define AR5416_EEP_MINOR_VER_7 0x7 |
426 | #define AR5416_EEP_MINOR_VER_9 0x9 | 417 | #define AR5416_EEP_MINOR_VER_9 0x9 |
427 | 418 | ||
428 | #define AR5416_EEP_START_LOC 256 | ||
429 | #define AR5416_NUM_5G_CAL_PIERS 8 | 419 | #define AR5416_NUM_5G_CAL_PIERS 8 |
430 | #define AR5416_NUM_2G_CAL_PIERS 4 | 420 | #define AR5416_NUM_2G_CAL_PIERS 4 |
431 | #define AR5416_NUM_5G_20_TARGET_POWERS 8 | 421 | #define AR5416_NUM_5G_20_TARGET_POWERS 8 |
@@ -441,25 +431,10 @@ struct ar5416Stats { | |||
441 | #define AR5416_EEPROM_MODAL_SPURS 5 | 431 | #define AR5416_EEPROM_MODAL_SPURS 5 |
442 | #define AR5416_MAX_RATE_POWER 63 | 432 | #define AR5416_MAX_RATE_POWER 63 |
443 | #define AR5416_NUM_PDADC_VALUES 128 | 433 | #define AR5416_NUM_PDADC_VALUES 128 |
444 | #define AR5416_NUM_RATES 16 | ||
445 | #define AR5416_BCHAN_UNUSED 0xFF | 434 | #define AR5416_BCHAN_UNUSED 0xFF |
446 | #define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64 | 435 | #define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64 |
447 | #define AR5416_EEPMISC_BIG_ENDIAN 0x01 | ||
448 | #define AR5416_MAX_CHAINS 3 | 436 | #define AR5416_MAX_CHAINS 3 |
449 | #define AR5416_ANT_16S 25 | ||
450 | |||
451 | #define AR5416_NUM_ANT_CHAIN_FIELDS 7 | ||
452 | #define AR5416_NUM_ANT_COMMON_FIELDS 4 | ||
453 | #define AR5416_SIZE_ANT_CHAIN_FIELD 3 | ||
454 | #define AR5416_SIZE_ANT_COMMON_FIELD 4 | ||
455 | #define AR5416_ANT_CHAIN_MASK 0x7 | ||
456 | #define AR5416_ANT_COMMON_MASK 0xf | ||
457 | #define AR5416_CHAIN_0_IDX 0 | ||
458 | #define AR5416_CHAIN_1_IDX 1 | ||
459 | #define AR5416_CHAIN_2_IDX 2 | ||
460 | |||
461 | #define AR5416_PWR_TABLE_OFFSET -5 | 437 | #define AR5416_PWR_TABLE_OFFSET -5 |
462 | #define AR5416_LEGACY_CHAINMASK 1 | ||
463 | 438 | ||
464 | enum eeprom_param { | 439 | enum eeprom_param { |
465 | EEP_NFTHRESH_5, | 440 | EEP_NFTHRESH_5, |
@@ -633,7 +608,7 @@ struct ar5416IniArray { | |||
633 | }; | 608 | }; |
634 | 609 | ||
635 | #define INIT_INI_ARRAY(iniarray, array, rows, columns) do { \ | 610 | #define INIT_INI_ARRAY(iniarray, array, rows, columns) do { \ |
636 | (iniarray)->ia_array = (u32 *)(array); \ | 611 | (iniarray)->ia_array = (u32 *)(array); \ |
637 | (iniarray)->ia_rows = (rows); \ | 612 | (iniarray)->ia_rows = (rows); \ |
638 | (iniarray)->ia_columns = (columns); \ | 613 | (iniarray)->ia_columns = (columns); \ |
639 | } while (0) | 614 | } while (0) |
@@ -641,16 +616,16 @@ struct ar5416IniArray { | |||
641 | #define INI_RA(iniarray, row, column) \ | 616 | #define INI_RA(iniarray, row, column) \ |
642 | (((iniarray)->ia_array)[(row) * ((iniarray)->ia_columns) + (column)]) | 617 | (((iniarray)->ia_array)[(row) * ((iniarray)->ia_columns) + (column)]) |
643 | 618 | ||
644 | #define INIT_CAL(_perCal) do { \ | 619 | #define INIT_CAL(_perCal) do { \ |
645 | (_perCal)->calState = CAL_WAITING; \ | 620 | (_perCal)->calState = CAL_WAITING; \ |
646 | (_perCal)->calNext = NULL; \ | 621 | (_perCal)->calNext = NULL; \ |
647 | } while (0) | 622 | } while (0) |
648 | 623 | ||
649 | #define INSERT_CAL(_ahp, _perCal) \ | 624 | #define INSERT_CAL(_ahp, _perCal) \ |
650 | do { \ | 625 | do { \ |
651 | if ((_ahp)->ah_cal_list_last == NULL) { \ | 626 | if ((_ahp)->ah_cal_list_last == NULL) { \ |
652 | (_ahp)->ah_cal_list = \ | 627 | (_ahp)->ah_cal_list = \ |
653 | (_ahp)->ah_cal_list_last = (_perCal); \ | 628 | (_ahp)->ah_cal_list_last = (_perCal); \ |
654 | ((_ahp)->ah_cal_list_last)->calNext = (_perCal); \ | 629 | ((_ahp)->ah_cal_list_last)->calNext = (_perCal); \ |
655 | } else { \ | 630 | } else { \ |
656 | ((_ahp)->ah_cal_list_last)->calNext = (_perCal); \ | 631 | ((_ahp)->ah_cal_list_last)->calNext = (_perCal); \ |
@@ -696,25 +671,29 @@ struct hal_cal_list { | |||
696 | struct ath_hal_5416 { | 671 | struct ath_hal_5416 { |
697 | struct ath_hal ah; | 672 | struct ath_hal ah; |
698 | struct ar5416_eeprom ah_eeprom; | 673 | struct ar5416_eeprom ah_eeprom; |
674 | struct ar5416Stats ah_stats; | ||
675 | struct ath9k_tx_queue_info ah_txq[ATH9K_NUM_TX_QUEUES]; | ||
676 | void __iomem *ah_cal_mem; | ||
677 | |||
699 | u8 ah_macaddr[ETH_ALEN]; | 678 | u8 ah_macaddr[ETH_ALEN]; |
700 | u8 ah_bssid[ETH_ALEN]; | 679 | u8 ah_bssid[ETH_ALEN]; |
701 | u8 ah_bssidmask[ETH_ALEN]; | 680 | u8 ah_bssidmask[ETH_ALEN]; |
702 | u16 ah_assocId; | 681 | u16 ah_assocId; |
682 | |||
703 | int16_t ah_curchanRadIndex; | 683 | int16_t ah_curchanRadIndex; |
704 | u32 ah_maskReg; | 684 | u32 ah_maskReg; |
705 | struct ar5416Stats ah_stats; | ||
706 | u32 ah_txDescMask; | ||
707 | u32 ah_txOkInterruptMask; | 685 | u32 ah_txOkInterruptMask; |
708 | u32 ah_txErrInterruptMask; | 686 | u32 ah_txErrInterruptMask; |
709 | u32 ah_txDescInterruptMask; | 687 | u32 ah_txDescInterruptMask; |
710 | u32 ah_txEolInterruptMask; | 688 | u32 ah_txEolInterruptMask; |
711 | u32 ah_txUrnInterruptMask; | 689 | u32 ah_txUrnInterruptMask; |
712 | struct ath9k_tx_queue_info ah_txq[ATH9K_NUM_TX_QUEUES]; | ||
713 | enum ath9k_power_mode ah_powerMode; | ||
714 | bool ah_chipFullSleep; | 690 | bool ah_chipFullSleep; |
715 | u32 ah_atimWindow; | 691 | u32 ah_atimWindow; |
716 | enum ath9k_ant_setting ah_diversityControl; | ||
717 | u16 ah_antennaSwitchSwap; | 692 | u16 ah_antennaSwitchSwap; |
693 | enum ath9k_power_mode ah_powerMode; | ||
694 | enum ath9k_ant_setting ah_diversityControl; | ||
695 | |||
696 | /* Calibration */ | ||
718 | enum hal_cal_types ah_suppCals; | 697 | enum hal_cal_types ah_suppCals; |
719 | struct hal_cal_list ah_iqCalData; | 698 | struct hal_cal_list ah_iqCalData; |
720 | struct hal_cal_list ah_adcGainCalData; | 699 | struct hal_cal_list ah_adcGainCalData; |
@@ -751,16 +730,16 @@ struct ath_hal_5416 { | |||
751 | int32_t sign[AR5416_MAX_CHAINS]; | 730 | int32_t sign[AR5416_MAX_CHAINS]; |
752 | } ah_Meas3; | 731 | } ah_Meas3; |
753 | u16 ah_CalSamples; | 732 | u16 ah_CalSamples; |
754 | u32 ah_tx6PowerInHalfDbm; | 733 | |
755 | u32 ah_staId1Defaults; | 734 | u32 ah_staId1Defaults; |
756 | u32 ah_miscMode; | 735 | u32 ah_miscMode; |
757 | bool ah_tpcEnabled; | ||
758 | u32 ah_beaconInterval; | ||
759 | enum { | 736 | enum { |
760 | AUTO_32KHZ, | 737 | AUTO_32KHZ, |
761 | USE_32KHZ, | 738 | USE_32KHZ, |
762 | DONT_USE_32KHZ, | 739 | DONT_USE_32KHZ, |
763 | } ah_enable32kHzClock; | 740 | } ah_enable32kHzClock; |
741 | |||
742 | /* RF */ | ||
764 | u32 *ah_analogBank0Data; | 743 | u32 *ah_analogBank0Data; |
765 | u32 *ah_analogBank1Data; | 744 | u32 *ah_analogBank1Data; |
766 | u32 *ah_analogBank2Data; | 745 | u32 *ah_analogBank2Data; |
@@ -770,8 +749,9 @@ struct ath_hal_5416 { | |||
770 | u32 *ah_analogBank7Data; | 749 | u32 *ah_analogBank7Data; |
771 | u32 *ah_addac5416_21; | 750 | u32 *ah_addac5416_21; |
772 | u32 *ah_bank6Temp; | 751 | u32 *ah_bank6Temp; |
773 | u32 ah_ofdmTxPower; | 752 | |
774 | int16_t ah_txPowerIndexOffset; | 753 | int16_t ah_txPowerIndexOffset; |
754 | u32 ah_beaconInterval; | ||
775 | u32 ah_slottime; | 755 | u32 ah_slottime; |
776 | u32 ah_acktimeout; | 756 | u32 ah_acktimeout; |
777 | u32 ah_ctstimeout; | 757 | u32 ah_ctstimeout; |
@@ -780,7 +760,8 @@ struct ath_hal_5416 { | |||
780 | u32 ah_gpioSelect; | 760 | u32 ah_gpioSelect; |
781 | u32 ah_polarity; | 761 | u32 ah_polarity; |
782 | u32 ah_gpioBit; | 762 | u32 ah_gpioBit; |
783 | bool ah_eepEnabled; | 763 | |
764 | /* ANI */ | ||
784 | u32 ah_procPhyErr; | 765 | u32 ah_procPhyErr; |
785 | bool ah_hasHwPhyCounters; | 766 | bool ah_hasHwPhyCounters; |
786 | u32 ah_aniPeriod; | 767 | u32 ah_aniPeriod; |
@@ -790,18 +771,14 @@ struct ath_hal_5416 { | |||
790 | int ah_coarseHigh[5]; | 771 | int ah_coarseHigh[5]; |
791 | int ah_coarseLow[5]; | 772 | int ah_coarseLow[5]; |
792 | int ah_firpwr[5]; | 773 | int ah_firpwr[5]; |
793 | u16 ah_ratesArray[16]; | 774 | enum ath9k_ani_cmd ah_ani_function; |
775 | |||
794 | u32 ah_intrTxqs; | 776 | u32 ah_intrTxqs; |
795 | bool ah_intrMitigation; | 777 | bool ah_intrMitigation; |
796 | u32 ah_cycleCount; | ||
797 | u32 ah_ctlBusy; | ||
798 | u32 ah_extBusy; | ||
799 | enum ath9k_ht_extprotspacing ah_extprotspacing; | 778 | enum ath9k_ht_extprotspacing ah_extprotspacing; |
800 | u8 ah_txchainmask; | 779 | u8 ah_txchainmask; |
801 | u8 ah_rxchainmask; | 780 | u8 ah_rxchainmask; |
802 | int ah_hwp; | 781 | |
803 | void __iomem *ah_cal_mem; | ||
804 | enum ath9k_ani_cmd ah_ani_function; | ||
805 | struct ar5416IniArray ah_iniModes; | 782 | struct ar5416IniArray ah_iniModes; |
806 | struct ar5416IniArray ah_iniCommon; | 783 | struct ar5416IniArray ah_iniCommon; |
807 | struct ar5416IniArray ah_iniBank0; | 784 | struct ar5416IniArray ah_iniBank0; |
@@ -820,10 +797,6 @@ struct ath_hal_5416 { | |||
820 | 797 | ||
821 | #define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5)) | 798 | #define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5)) |
822 | 799 | ||
823 | #define IS_5416_EMU(ah) \ | ||
824 | ((ah->ah_devid == AR5416_DEVID_EMU) || \ | ||
825 | (ah->ah_devid == AR5416_DEVID_EMU_PCIE)) | ||
826 | |||
827 | #define ar5416RfDetach(ah) do { \ | 800 | #define ar5416RfDetach(ah) do { \ |
828 | if (AH5416(ah)->ah_rfHal.rfDetach != NULL) \ | 801 | if (AH5416(ah)->ah_rfHal.rfDetach != NULL) \ |
829 | AH5416(ah)->ah_rfHal.rfDetach(ah); \ | 802 | AH5416(ah)->ah_rfHal.rfDetach(ah); \ |
@@ -841,8 +814,8 @@ struct ath_hal_5416 { | |||
841 | #define REG_WRITE_ARRAY(iniarray, column, regWr) do { \ | 814 | #define REG_WRITE_ARRAY(iniarray, column, regWr) do { \ |
842 | int r; \ | 815 | int r; \ |
843 | for (r = 0; r < ((iniarray)->ia_rows); r++) { \ | 816 | for (r = 0; r < ((iniarray)->ia_rows); r++) { \ |
844 | REG_WRITE(ah, INI_RA((iniarray), (r), 0), \ | 817 | REG_WRITE(ah, INI_RA((iniarray), (r), 0), \ |
845 | INI_RA((iniarray), r, (column))); \ | 818 | INI_RA((iniarray), r, (column))); \ |
846 | DO_DELAY(regWr); \ | 819 | DO_DELAY(regWr); \ |
847 | } \ | 820 | } \ |
848 | } while (0) | 821 | } while (0) |
@@ -852,30 +825,21 @@ struct ath_hal_5416 { | |||
852 | #define COEF_SCALE_S 24 | 825 | #define COEF_SCALE_S 24 |
853 | #define HT40_CHANNEL_CENTER_SHIFT 10 | 826 | #define HT40_CHANNEL_CENTER_SHIFT 10 |
854 | 827 | ||
855 | #define ar5416CheckOpMode(_opmode) \ | ||
856 | ((_opmode == ATH9K_M_STA) || (_opmode == ATH9K_M_IBSS) || \ | ||
857 | (_opmode == ATH9K_M_HOSTAP) || (_opmode == ATH9K_M_MONITOR)) | ||
858 | |||
859 | #define AR5416_EEPROM_MAGIC_OFFSET 0x0 | 828 | #define AR5416_EEPROM_MAGIC_OFFSET 0x0 |
860 | 829 | ||
861 | #define AR5416_EEPROM_S 2 | 830 | #define AR5416_EEPROM_S 2 |
862 | #define AR5416_EEPROM_OFFSET 0x2000 | 831 | #define AR5416_EEPROM_OFFSET 0x2000 |
863 | #define AR5416_EEPROM_START_ADDR \ | 832 | #define AR5416_EEPROM_START_ADDR \ |
864 | (AR_SREV_9100(ah)) ? 0x1fff1000 : 0x503f1200 | 833 | (AR_SREV_9100(ah)) ? 0x1fff1000 : 0x503f1200 |
865 | #define AR5416_EEPROM_MAX 0xae0 | 834 | #define AR5416_EEPROM_MAX 0xae0 |
866 | #define ar5416_get_eep_ver(_ahp) \ | 835 | #define ar5416_get_eep_ver(_ahp) \ |
867 | (((_ahp)->ah_eeprom.baseEepHeader.version >> 12) & 0xF) | 836 | (((_ahp)->ah_eeprom.baseEepHeader.version >> 12) & 0xF) |
868 | #define ar5416_get_eep_rev(_ahp) \ | 837 | #define ar5416_get_eep_rev(_ahp) \ |
869 | (((_ahp)->ah_eeprom.baseEepHeader.version) & 0xFFF) | 838 | (((_ahp)->ah_eeprom.baseEepHeader.version) & 0xFFF) |
870 | #define ar5416_get_ntxchains(_txchainmask) \ | 839 | #define ar5416_get_ntxchains(_txchainmask) \ |
871 | (((_txchainmask >> 2) & 1) + \ | 840 | (((_txchainmask >> 2) & 1) + \ |
872 | ((_txchainmask >> 1) & 1) + (_txchainmask & 1)) | 841 | ((_txchainmask >> 1) & 1) + (_txchainmask & 1)) |
873 | 842 | ||
874 | #define IS_EEP_MINOR_V3(_ahp) \ | ||
875 | (ath9k_hw_get_eeprom((_ahp), EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_3) | ||
876 | |||
877 | #define FIXED_CCA_THRESHOLD 15 | ||
878 | |||
879 | #ifdef __BIG_ENDIAN | 843 | #ifdef __BIG_ENDIAN |
880 | #define AR5416_EEPROM_MAGIC 0x5aa5 | 844 | #define AR5416_EEPROM_MAGIC 0x5aa5 |
881 | #else | 845 | #else |
@@ -910,8 +874,6 @@ struct ath_hal_5416 { | |||
910 | #define AR_GPIOD_MASK 0x00001FFF | 874 | #define AR_GPIOD_MASK 0x00001FFF |
911 | #define AR_GPIO_BIT(_gpio) (1 << (_gpio)) | 875 | #define AR_GPIO_BIT(_gpio) (1 << (_gpio)) |
912 | 876 | ||
913 | #define MAX_ANALOG_START 319 | ||
914 | |||
915 | #define HAL_EP_RND(x, mul) \ | 877 | #define HAL_EP_RND(x, mul) \ |
916 | ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) | 878 | ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) |
917 | #define BEACON_RSSI(ahp) \ | 879 | #define BEACON_RSSI(ahp) \ |
@@ -923,8 +885,6 @@ struct ath_hal_5416 { | |||
923 | #define AH_TIMEOUT 100000 | 885 | #define AH_TIMEOUT 100000 |
924 | #define AH_TIME_QUANTUM 10 | 886 | #define AH_TIME_QUANTUM 10 |
925 | 887 | ||
926 | #define IS(_c, _f) (((_c)->channelFlags & _f) || 0) | ||
927 | |||
928 | #define AR_KEYTABLE_SIZE 128 | 888 | #define AR_KEYTABLE_SIZE 128 |
929 | #define POWER_UP_TIME 200000 | 889 | #define POWER_UP_TIME 200000 |
930 | 890 | ||
@@ -964,6 +924,6 @@ struct ath_hal_5416 { | |||
964 | #define OFDM_SYMBOL_TIME_QUARTER 16 | 924 | #define OFDM_SYMBOL_TIME_QUARTER 16 |
965 | 925 | ||
966 | u32 ath9k_hw_get_eeprom(struct ath_hal_5416 *ahp, | 926 | u32 ath9k_hw_get_eeprom(struct ath_hal_5416 *ahp, |
967 | enum eeprom_param param); | 927 | enum eeprom_param param); |
968 | 928 | ||
969 | #endif | 929 | #endif |
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 2888778040e4..dc45eef3289a 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c | |||
@@ -22,8 +22,6 @@ | |||
22 | #define ATH_PCI_VERSION "0.1" | 22 | #define ATH_PCI_VERSION "0.1" |
23 | 23 | ||
24 | #define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13 | 24 | #define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13 |
25 | #define IEEE80211_ACTION_CAT_HT 7 | ||
26 | #define IEEE80211_ACTION_HT_TXCHWIDTH 0 | ||
27 | 25 | ||
28 | static char *dev_info = "ath9k"; | 26 | static char *dev_info = "ath9k"; |
29 | 27 | ||
@@ -212,21 +210,16 @@ static int ath_key_config(struct ath_softc *sc, | |||
212 | 210 | ||
213 | static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key) | 211 | static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key) |
214 | { | 212 | { |
215 | #define ATH_MAX_NUM_KEYS 4 | ||
216 | int freeslot; | 213 | int freeslot; |
217 | 214 | ||
218 | freeslot = (key->keyidx >= ATH_MAX_NUM_KEYS) ? 1 : 0; | 215 | freeslot = (key->keyidx >= 4) ? 1 : 0; |
219 | ath_key_reset(sc, key->keyidx, freeslot); | 216 | ath_key_reset(sc, key->keyidx, freeslot); |
220 | #undef ATH_MAX_NUM_KEYS | ||
221 | } | 217 | } |
222 | 218 | ||
223 | static void setup_ht_cap(struct ieee80211_ht_info *ht_info) | 219 | static void setup_ht_cap(struct ieee80211_ht_info *ht_info) |
224 | { | 220 | { |
225 | /* Until mac80211 includes these fields */ | 221 | #define ATH9K_HT_CAP_MAXRXAMPDU_65536 0x3 /* 2 ^ 16 */ |
226 | 222 | #define ATH9K_HT_CAP_MPDUDENSITY_8 0x6 /* 8 usec */ | |
227 | #define IEEE80211_HT_CAP_DSSSCCK40 0x1000 | ||
228 | #define IEEE80211_HT_CAP_MAXRXAMPDU_65536 0x3 /* 2 ^ 16 */ | ||
229 | #define IEEE80211_HT_CAP_MPDUDENSITY_8 0x6 /* 8 usec */ | ||
230 | 223 | ||
231 | ht_info->ht_supported = 1; | 224 | ht_info->ht_supported = 1; |
232 | ht_info->cap = (u16)IEEE80211_HT_CAP_SUP_WIDTH | 225 | ht_info->cap = (u16)IEEE80211_HT_CAP_SUP_WIDTH |
@@ -234,8 +227,8 @@ static void setup_ht_cap(struct ieee80211_ht_info *ht_info) | |||
234 | |(u16)IEEE80211_HT_CAP_SGI_40 | 227 | |(u16)IEEE80211_HT_CAP_SGI_40 |
235 | |(u16)IEEE80211_HT_CAP_DSSSCCK40; | 228 | |(u16)IEEE80211_HT_CAP_DSSSCCK40; |
236 | 229 | ||
237 | ht_info->ampdu_factor = IEEE80211_HT_CAP_MAXRXAMPDU_65536; | 230 | ht_info->ampdu_factor = ATH9K_HT_CAP_MAXRXAMPDU_65536; |
238 | ht_info->ampdu_density = IEEE80211_HT_CAP_MPDUDENSITY_8; | 231 | ht_info->ampdu_density = ATH9K_HT_CAP_MPDUDENSITY_8; |
239 | /* setup supported mcs set */ | 232 | /* setup supported mcs set */ |
240 | memset(ht_info->supp_mcs_set, 0, 16); | 233 | memset(ht_info->supp_mcs_set, 0, 16); |
241 | ht_info->supp_mcs_set[0] = 0xff; | 234 | ht_info->supp_mcs_set[0] = 0xff; |
@@ -368,6 +361,20 @@ static int ath9k_tx(struct ieee80211_hw *hw, | |||
368 | { | 361 | { |
369 | struct ath_softc *sc = hw->priv; | 362 | struct ath_softc *sc = hw->priv; |
370 | int hdrlen, padsize; | 363 | int hdrlen, padsize; |
364 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
365 | |||
366 | /* | ||
367 | * As a temporary workaround, assign seq# here; this will likely need | ||
368 | * to be cleaned up to work better with Beacon transmission and virtual | ||
369 | * BSSes. | ||
370 | */ | ||
371 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | ||
372 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
373 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) | ||
374 | sc->seq_no += 0x10; | ||
375 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
376 | hdr->seq_ctrl |= cpu_to_le16(sc->seq_no); | ||
377 | } | ||
371 | 378 | ||
372 | /* Add the padding after the header if this is not already done */ | 379 | /* Add the padding after the header if this is not already done */ |
373 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 380 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
@@ -426,10 +433,13 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
426 | case IEEE80211_IF_TYPE_IBSS: | 433 | case IEEE80211_IF_TYPE_IBSS: |
427 | ic_opmode = ATH9K_M_IBSS; | 434 | ic_opmode = ATH9K_M_IBSS; |
428 | break; | 435 | break; |
436 | case IEEE80211_IF_TYPE_AP: | ||
437 | ic_opmode = ATH9K_M_HOSTAP; | ||
438 | break; | ||
429 | default: | 439 | default: |
430 | DPRINTF(sc, ATH_DBG_FATAL, | 440 | DPRINTF(sc, ATH_DBG_FATAL, |
431 | "%s: Only STA and IBSS are supported currently\n", | 441 | "%s: Interface type %d not yet supported\n", |
432 | __func__); | 442 | __func__, conf->type); |
433 | return -EOPNOTSUPP; | 443 | return -EOPNOTSUPP; |
434 | } | 444 | } |
435 | 445 | ||
@@ -472,7 +482,8 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
472 | ath_rate_newstate(sc, avp); | 482 | ath_rate_newstate(sc, avp); |
473 | 483 | ||
474 | /* Reclaim beacon resources */ | 484 | /* Reclaim beacon resources */ |
475 | if (sc->sc_opmode == ATH9K_M_HOSTAP || sc->sc_opmode == ATH9K_M_IBSS) { | 485 | if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP || |
486 | sc->sc_ah->ah_opmode == ATH9K_M_IBSS) { | ||
476 | ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq); | 487 | ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq); |
477 | ath_beacon_return(sc, avp); | 488 | ath_beacon_return(sc, avp); |
478 | } | 489 | } |
@@ -480,7 +491,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
480 | /* Set interrupt mask */ | 491 | /* Set interrupt mask */ |
481 | sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); | 492 | sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); |
482 | ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask & ~ATH9K_INT_GLOBAL); | 493 | ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask & ~ATH9K_INT_GLOBAL); |
483 | sc->sc_beacons = 0; | 494 | sc->sc_flags &= ~SC_OP_BEACONS; |
484 | 495 | ||
485 | error = ath_vap_detach(sc, 0); | 496 | error = ath_vap_detach(sc, 0); |
486 | if (error) | 497 | if (error) |
@@ -529,6 +540,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, | |||
529 | struct ieee80211_if_conf *conf) | 540 | struct ieee80211_if_conf *conf) |
530 | { | 541 | { |
531 | struct ath_softc *sc = hw->priv; | 542 | struct ath_softc *sc = hw->priv; |
543 | struct ath_hal *ah = sc->sc_ah; | ||
532 | struct ath_vap *avp; | 544 | struct ath_vap *avp; |
533 | u32 rfilt = 0; | 545 | u32 rfilt = 0; |
534 | int error, i; | 546 | int error, i; |
@@ -541,6 +553,17 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, | |||
541 | return -EINVAL; | 553 | return -EINVAL; |
542 | } | 554 | } |
543 | 555 | ||
556 | /* TODO: Need to decide which hw opmode to use for multi-interface | ||
557 | * cases */ | ||
558 | if (vif->type == IEEE80211_IF_TYPE_AP && | ||
559 | ah->ah_opmode != ATH9K_M_HOSTAP) { | ||
560 | ah->ah_opmode = ATH9K_M_HOSTAP; | ||
561 | ath9k_hw_setopmode(ah); | ||
562 | ath9k_hw_write_associd(ah, sc->sc_myaddr, 0); | ||
563 | /* Request full reset to get hw opmode changed properly */ | ||
564 | sc->sc_flags |= SC_OP_FULL_RESET; | ||
565 | } | ||
566 | |||
544 | if ((conf->changed & IEEE80211_IFCC_BSSID) && | 567 | if ((conf->changed & IEEE80211_IFCC_BSSID) && |
545 | !is_zero_ether_addr(conf->bssid)) { | 568 | !is_zero_ether_addr(conf->bssid)) { |
546 | switch (vif->type) { | 569 | switch (vif->type) { |
@@ -549,10 +572,6 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, | |||
549 | /* Update ratectrl about the new state */ | 572 | /* Update ratectrl about the new state */ |
550 | ath_rate_newstate(sc, avp); | 573 | ath_rate_newstate(sc, avp); |
551 | 574 | ||
552 | /* Set rx filter */ | ||
553 | rfilt = ath_calcrxfilter(sc); | ||
554 | ath9k_hw_setrxfilter(sc->sc_ah, rfilt); | ||
555 | |||
556 | /* Set BSSID */ | 575 | /* Set BSSID */ |
557 | memcpy(sc->sc_curbssid, conf->bssid, ETH_ALEN); | 576 | memcpy(sc->sc_curbssid, conf->bssid, ETH_ALEN); |
558 | sc->sc_curaid = 0; | 577 | sc->sc_curaid = 0; |
@@ -585,7 +604,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, | |||
585 | print_mac(mac, sc->sc_curbssid), sc->sc_curaid); | 604 | print_mac(mac, sc->sc_curbssid), sc->sc_curaid); |
586 | 605 | ||
587 | /* need to reconfigure the beacon */ | 606 | /* need to reconfigure the beacon */ |
588 | sc->sc_beacons = 0; | 607 | sc->sc_flags &= ~SC_OP_BEACONS ; |
589 | 608 | ||
590 | break; | 609 | break; |
591 | default: | 610 | default: |
@@ -594,7 +613,8 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, | |||
594 | } | 613 | } |
595 | 614 | ||
596 | if ((conf->changed & IEEE80211_IFCC_BEACON) && | 615 | if ((conf->changed & IEEE80211_IFCC_BEACON) && |
597 | (vif->type == IEEE80211_IF_TYPE_IBSS)) { | 616 | ((vif->type == IEEE80211_IF_TYPE_IBSS) || |
617 | (vif->type == IEEE80211_IF_TYPE_AP))) { | ||
598 | /* | 618 | /* |
599 | * Allocate and setup the beacon frame. | 619 | * Allocate and setup the beacon frame. |
600 | * | 620 | * |
@@ -636,8 +656,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, | |||
636 | FIF_BCN_PRBRESP_PROMISC | \ | 656 | FIF_BCN_PRBRESP_PROMISC | \ |
637 | FIF_FCSFAIL) | 657 | FIF_FCSFAIL) |
638 | 658 | ||
639 | /* Accept unicast, bcast and mcast frames */ | 659 | /* FIXME: sc->sc_full_reset ? */ |
640 | |||
641 | static void ath9k_configure_filter(struct ieee80211_hw *hw, | 660 | static void ath9k_configure_filter(struct ieee80211_hw *hw, |
642 | unsigned int changed_flags, | 661 | unsigned int changed_flags, |
643 | unsigned int *total_flags, | 662 | unsigned int *total_flags, |
@@ -645,16 +664,22 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw, | |||
645 | struct dev_mc_list *mclist) | 664 | struct dev_mc_list *mclist) |
646 | { | 665 | { |
647 | struct ath_softc *sc = hw->priv; | 666 | struct ath_softc *sc = hw->priv; |
667 | u32 rfilt; | ||
648 | 668 | ||
649 | changed_flags &= SUPPORTED_FILTERS; | 669 | changed_flags &= SUPPORTED_FILTERS; |
650 | *total_flags &= SUPPORTED_FILTERS; | 670 | *total_flags &= SUPPORTED_FILTERS; |
651 | 671 | ||
672 | sc->rx_filter = *total_flags; | ||
673 | rfilt = ath_calcrxfilter(sc); | ||
674 | ath9k_hw_setrxfilter(sc->sc_ah, rfilt); | ||
675 | |||
652 | if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { | 676 | if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { |
653 | if (*total_flags & FIF_BCN_PRBRESP_PROMISC) | 677 | if (*total_flags & FIF_BCN_PRBRESP_PROMISC) |
654 | ath_scan_start(sc); | 678 | ath9k_hw_write_associd(sc->sc_ah, ath_bcast_mac, 0); |
655 | else | ||
656 | ath_scan_end(sc); | ||
657 | } | 679 | } |
680 | |||
681 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set HW RX filter: 0x%x\n", | ||
682 | __func__, sc->rx_filter); | ||
658 | } | 683 | } |
659 | 684 | ||
660 | static void ath9k_sta_notify(struct ieee80211_hw *hw, | 685 | static void ath9k_sta_notify(struct ieee80211_hw *hw, |
@@ -831,7 +856,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, | |||
831 | 856 | ||
832 | /* Configure the beacon */ | 857 | /* Configure the beacon */ |
833 | ath_beacon_config(sc, 0); | 858 | ath_beacon_config(sc, 0); |
834 | sc->sc_beacons = 1; | 859 | sc->sc_flags |= SC_OP_BEACONS; |
835 | 860 | ||
836 | /* Reset rssi stats */ | 861 | /* Reset rssi stats */ |
837 | sc->sc_halstats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER; | 862 | sc->sc_halstats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER; |
@@ -894,9 +919,9 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
894 | __func__, | 919 | __func__, |
895 | bss_conf->use_short_preamble); | 920 | bss_conf->use_short_preamble); |
896 | if (bss_conf->use_short_preamble) | 921 | if (bss_conf->use_short_preamble) |
897 | sc->sc_flags |= ATH_PREAMBLE_SHORT; | 922 | sc->sc_flags |= SC_OP_PREAMBLE_SHORT; |
898 | else | 923 | else |
899 | sc->sc_flags &= ~ATH_PREAMBLE_SHORT; | 924 | sc->sc_flags &= ~SC_OP_PREAMBLE_SHORT; |
900 | } | 925 | } |
901 | 926 | ||
902 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { | 927 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { |
@@ -905,9 +930,9 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
905 | bss_conf->use_cts_prot); | 930 | bss_conf->use_cts_prot); |
906 | if (bss_conf->use_cts_prot && | 931 | if (bss_conf->use_cts_prot && |
907 | hw->conf.channel->band != IEEE80211_BAND_5GHZ) | 932 | hw->conf.channel->band != IEEE80211_BAND_5GHZ) |
908 | sc->sc_flags |= ATH_PROTECT_ENABLE; | 933 | sc->sc_flags |= SC_OP_PROTECT_ENABLE; |
909 | else | 934 | else |
910 | sc->sc_flags &= ~ATH_PROTECT_ENABLE; | 935 | sc->sc_flags &= ~SC_OP_PROTECT_ENABLE; |
911 | } | 936 | } |
912 | 937 | ||
913 | if (changed & BSS_CHANGED_HT) { | 938 | if (changed & BSS_CHANGED_HT) { |
@@ -1035,15 +1060,6 @@ void ath_get_beaconconfig(struct ath_softc *sc, | |||
1035 | conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval; | 1060 | conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval; |
1036 | } | 1061 | } |
1037 | 1062 | ||
1038 | int ath_update_beacon(struct ath_softc *sc, | ||
1039 | int if_id, | ||
1040 | struct ath_beacon_offset *bo, | ||
1041 | struct sk_buff *skb, | ||
1042 | int mcast) | ||
1043 | { | ||
1044 | return 0; | ||
1045 | } | ||
1046 | |||
1047 | void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | 1063 | void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, |
1048 | struct ath_xmit_status *tx_status, struct ath_node *an) | 1064 | struct ath_xmit_status *tx_status, struct ath_node *an) |
1049 | { | 1065 | { |
@@ -1065,8 +1081,16 @@ void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1065 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | 1081 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; |
1066 | tx_status->flags &= ~ATH_TX_BAR; | 1082 | tx_status->flags &= ~ATH_TX_BAR; |
1067 | } | 1083 | } |
1068 | if (tx_status->flags) | 1084 | |
1069 | tx_info->status.excessive_retries = 1; | 1085 | if (tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY)) { |
1086 | if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) { | ||
1087 | /* Frame was not ACKed, but an ACK was expected */ | ||
1088 | tx_info->status.excessive_retries = 1; | ||
1089 | } | ||
1090 | } else { | ||
1091 | /* Frame was ACKed */ | ||
1092 | tx_info->flags |= IEEE80211_TX_STAT_ACK; | ||
1093 | } | ||
1070 | 1094 | ||
1071 | tx_info->status.retry_count = tx_status->retries; | 1095 | tx_info->status.retry_count = tx_status->retries; |
1072 | 1096 | ||
@@ -1075,7 +1099,7 @@ void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1075 | ath_node_put(sc, an, ATH9K_BH_STATUS_CHANGE); | 1099 | ath_node_put(sc, an, ATH9K_BH_STATUS_CHANGE); |
1076 | } | 1100 | } |
1077 | 1101 | ||
1078 | int ath__rx_indicate(struct ath_softc *sc, | 1102 | int _ath_rx_indicate(struct ath_softc *sc, |
1079 | struct sk_buff *skb, | 1103 | struct sk_buff *skb, |
1080 | struct ath_recv_status *status, | 1104 | struct ath_recv_status *status, |
1081 | u16 keyix) | 1105 | u16 keyix) |
@@ -1095,9 +1119,6 @@ int ath__rx_indicate(struct ath_softc *sc, | |||
1095 | skb_pull(skb, padsize); | 1119 | skb_pull(skb, padsize); |
1096 | } | 1120 | } |
1097 | 1121 | ||
1098 | /* remove FCS before passing up to protocol stack */ | ||
1099 | skb_trim(skb, (skb->len - FCS_LEN)); | ||
1100 | |||
1101 | /* Prepare rx status */ | 1122 | /* Prepare rx status */ |
1102 | ath9k_rx_prepare(sc, skb, status, &rx_status); | 1123 | ath9k_rx_prepare(sc, skb, status, &rx_status); |
1103 | 1124 | ||
@@ -1146,9 +1167,119 @@ int ath_rx_subframe(struct ath_node *an, | |||
1146 | return 0; | 1167 | return 0; |
1147 | } | 1168 | } |
1148 | 1169 | ||
1149 | enum ath9k_ht_macmode ath_cwm_macmode(struct ath_softc *sc) | 1170 | /********************************/ |
1171 | /* LED functions */ | ||
1172 | /********************************/ | ||
1173 | |||
1174 | static void ath_led_brightness(struct led_classdev *led_cdev, | ||
1175 | enum led_brightness brightness) | ||
1150 | { | 1176 | { |
1151 | return sc->sc_ht_info.tx_chan_width; | 1177 | struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev); |
1178 | struct ath_softc *sc = led->sc; | ||
1179 | |||
1180 | switch (brightness) { | ||
1181 | case LED_OFF: | ||
1182 | if (led->led_type == ATH_LED_ASSOC || | ||
1183 | led->led_type == ATH_LED_RADIO) | ||
1184 | sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; | ||
1185 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, | ||
1186 | (led->led_type == ATH_LED_RADIO) ? 1 : | ||
1187 | !!(sc->sc_flags & SC_OP_LED_ASSOCIATED)); | ||
1188 | break; | ||
1189 | case LED_FULL: | ||
1190 | if (led->led_type == ATH_LED_ASSOC) | ||
1191 | sc->sc_flags |= SC_OP_LED_ASSOCIATED; | ||
1192 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0); | ||
1193 | break; | ||
1194 | default: | ||
1195 | break; | ||
1196 | } | ||
1197 | } | ||
1198 | |||
1199 | static int ath_register_led(struct ath_softc *sc, struct ath_led *led, | ||
1200 | char *trigger) | ||
1201 | { | ||
1202 | int ret; | ||
1203 | |||
1204 | led->sc = sc; | ||
1205 | led->led_cdev.name = led->name; | ||
1206 | led->led_cdev.default_trigger = trigger; | ||
1207 | led->led_cdev.brightness_set = ath_led_brightness; | ||
1208 | |||
1209 | ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev); | ||
1210 | if (ret) | ||
1211 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1212 | "Failed to register led:%s", led->name); | ||
1213 | else | ||
1214 | led->registered = 1; | ||
1215 | return ret; | ||
1216 | } | ||
1217 | |||
1218 | static void ath_unregister_led(struct ath_led *led) | ||
1219 | { | ||
1220 | if (led->registered) { | ||
1221 | led_classdev_unregister(&led->led_cdev); | ||
1222 | led->registered = 0; | ||
1223 | } | ||
1224 | } | ||
1225 | |||
1226 | static void ath_deinit_leds(struct ath_softc *sc) | ||
1227 | { | ||
1228 | ath_unregister_led(&sc->assoc_led); | ||
1229 | sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; | ||
1230 | ath_unregister_led(&sc->tx_led); | ||
1231 | ath_unregister_led(&sc->rx_led); | ||
1232 | ath_unregister_led(&sc->radio_led); | ||
1233 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); | ||
1234 | } | ||
1235 | |||
1236 | static void ath_init_leds(struct ath_softc *sc) | ||
1237 | { | ||
1238 | char *trigger; | ||
1239 | int ret; | ||
1240 | |||
1241 | /* Configure gpio 1 for output */ | ||
1242 | ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN, | ||
1243 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | ||
1244 | /* LED off, active low */ | ||
1245 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); | ||
1246 | |||
1247 | trigger = ieee80211_get_radio_led_name(sc->hw); | ||
1248 | snprintf(sc->radio_led.name, sizeof(sc->radio_led.name), | ||
1249 | "ath9k-%s:radio", wiphy_name(sc->hw->wiphy)); | ||
1250 | ret = ath_register_led(sc, &sc->radio_led, trigger); | ||
1251 | sc->radio_led.led_type = ATH_LED_RADIO; | ||
1252 | if (ret) | ||
1253 | goto fail; | ||
1254 | |||
1255 | trigger = ieee80211_get_assoc_led_name(sc->hw); | ||
1256 | snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name), | ||
1257 | "ath9k-%s:assoc", wiphy_name(sc->hw->wiphy)); | ||
1258 | ret = ath_register_led(sc, &sc->assoc_led, trigger); | ||
1259 | sc->assoc_led.led_type = ATH_LED_ASSOC; | ||
1260 | if (ret) | ||
1261 | goto fail; | ||
1262 | |||
1263 | trigger = ieee80211_get_tx_led_name(sc->hw); | ||
1264 | snprintf(sc->tx_led.name, sizeof(sc->tx_led.name), | ||
1265 | "ath9k-%s:tx", wiphy_name(sc->hw->wiphy)); | ||
1266 | ret = ath_register_led(sc, &sc->tx_led, trigger); | ||
1267 | sc->tx_led.led_type = ATH_LED_TX; | ||
1268 | if (ret) | ||
1269 | goto fail; | ||
1270 | |||
1271 | trigger = ieee80211_get_rx_led_name(sc->hw); | ||
1272 | snprintf(sc->rx_led.name, sizeof(sc->rx_led.name), | ||
1273 | "ath9k-%s:rx", wiphy_name(sc->hw->wiphy)); | ||
1274 | ret = ath_register_led(sc, &sc->rx_led, trigger); | ||
1275 | sc->rx_led.led_type = ATH_LED_RX; | ||
1276 | if (ret) | ||
1277 | goto fail; | ||
1278 | |||
1279 | return; | ||
1280 | |||
1281 | fail: | ||
1282 | ath_deinit_leds(sc); | ||
1152 | } | 1283 | } |
1153 | 1284 | ||
1154 | static int ath_detach(struct ath_softc *sc) | 1285 | static int ath_detach(struct ath_softc *sc) |
@@ -1157,6 +1288,9 @@ static int ath_detach(struct ath_softc *sc) | |||
1157 | 1288 | ||
1158 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__); | 1289 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__); |
1159 | 1290 | ||
1291 | /* Deinit LED control */ | ||
1292 | ath_deinit_leds(sc); | ||
1293 | |||
1160 | /* Unregister hw */ | 1294 | /* Unregister hw */ |
1161 | 1295 | ||
1162 | ieee80211_unregister_hw(hw); | 1296 | ieee80211_unregister_hw(hw); |
@@ -1250,18 +1384,21 @@ static int ath_attach(u16 devid, | |||
1250 | goto bad; | 1384 | goto bad; |
1251 | } | 1385 | } |
1252 | 1386 | ||
1387 | /* Initialize LED control */ | ||
1388 | ath_init_leds(sc); | ||
1389 | |||
1253 | /* initialize tx/rx engine */ | 1390 | /* initialize tx/rx engine */ |
1254 | 1391 | ||
1255 | error = ath_tx_init(sc, ATH_TXBUF); | 1392 | error = ath_tx_init(sc, ATH_TXBUF); |
1256 | if (error != 0) | 1393 | if (error != 0) |
1257 | goto bad1; | 1394 | goto detach; |
1258 | 1395 | ||
1259 | error = ath_rx_init(sc, ATH_RXBUF); | 1396 | error = ath_rx_init(sc, ATH_RXBUF); |
1260 | if (error != 0) | 1397 | if (error != 0) |
1261 | goto bad1; | 1398 | goto detach; |
1262 | 1399 | ||
1263 | return 0; | 1400 | return 0; |
1264 | bad1: | 1401 | detach: |
1265 | ath_detach(sc); | 1402 | ath_detach(sc); |
1266 | bad: | 1403 | bad: |
1267 | return error; | 1404 | return error; |
@@ -1340,7 +1477,9 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1340 | goto bad2; | 1477 | goto bad2; |
1341 | } | 1478 | } |
1342 | 1479 | ||
1343 | hw->flags = IEEE80211_HW_SIGNAL_DBM | | 1480 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | |
1481 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | ||
1482 | IEEE80211_HW_SIGNAL_DBM | | ||
1344 | IEEE80211_HW_NOISE_DBM; | 1483 | IEEE80211_HW_NOISE_DBM; |
1345 | 1484 | ||
1346 | SET_IEEE80211_DEV(hw, &pdev->dev); | 1485 | SET_IEEE80211_DEV(hw, &pdev->dev); |
@@ -1404,6 +1543,10 @@ static void ath_pci_remove(struct pci_dev *pdev) | |||
1404 | 1543 | ||
1405 | static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state) | 1544 | static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state) |
1406 | { | 1545 | { |
1546 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | ||
1547 | struct ath_softc *sc = hw->priv; | ||
1548 | |||
1549 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); | ||
1407 | pci_save_state(pdev); | 1550 | pci_save_state(pdev); |
1408 | pci_disable_device(pdev); | 1551 | pci_disable_device(pdev); |
1409 | pci_set_power_state(pdev, 3); | 1552 | pci_set_power_state(pdev, 3); |
@@ -1413,6 +1556,8 @@ static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state) | |||
1413 | 1556 | ||
1414 | static int ath_pci_resume(struct pci_dev *pdev) | 1557 | static int ath_pci_resume(struct pci_dev *pdev) |
1415 | { | 1558 | { |
1559 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | ||
1560 | struct ath_softc *sc = hw->priv; | ||
1416 | u32 val; | 1561 | u32 val; |
1417 | int err; | 1562 | int err; |
1418 | 1563 | ||
@@ -1429,6 +1574,11 @@ static int ath_pci_resume(struct pci_dev *pdev) | |||
1429 | if ((val & 0x0000ff00) != 0) | 1574 | if ((val & 0x0000ff00) != 0) |
1430 | pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); | 1575 | pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); |
1431 | 1576 | ||
1577 | /* Enable LED */ | ||
1578 | ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN, | ||
1579 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | ||
1580 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); | ||
1581 | |||
1432 | return 0; | 1582 | return 0; |
1433 | } | 1583 | } |
1434 | 1584 | ||
diff --git a/drivers/net/wireless/ath9k/phy.h b/drivers/net/wireless/ath9k/phy.h index 0cd399a5344a..14702344448b 100644 --- a/drivers/net/wireless/ath9k/phy.h +++ b/drivers/net/wireless/ath9k/phy.h | |||
@@ -18,19 +18,19 @@ | |||
18 | #define PHY_H | 18 | #define PHY_H |
19 | 19 | ||
20 | bool ath9k_hw_ar9280_set_channel(struct ath_hal *ah, | 20 | bool ath9k_hw_ar9280_set_channel(struct ath_hal *ah, |
21 | struct ath9k_channel | 21 | struct ath9k_channel |
22 | *chan); | 22 | *chan); |
23 | bool ath9k_hw_set_channel(struct ath_hal *ah, | 23 | bool ath9k_hw_set_channel(struct ath_hal *ah, |
24 | struct ath9k_channel *chan); | 24 | struct ath9k_channel *chan); |
25 | void ath9k_hw_write_regs(struct ath_hal *ah, u32 modesIndex, | 25 | void ath9k_hw_write_regs(struct ath_hal *ah, u32 modesIndex, |
26 | u32 freqIndex, int regWrites); | 26 | u32 freqIndex, int regWrites); |
27 | bool ath9k_hw_set_rf_regs(struct ath_hal *ah, | 27 | bool ath9k_hw_set_rf_regs(struct ath_hal *ah, |
28 | struct ath9k_channel *chan, | 28 | struct ath9k_channel *chan, |
29 | u16 modesIndex); | 29 | u16 modesIndex); |
30 | void ath9k_hw_decrease_chain_power(struct ath_hal *ah, | 30 | void ath9k_hw_decrease_chain_power(struct ath_hal *ah, |
31 | struct ath9k_channel *chan); | 31 | struct ath9k_channel *chan); |
32 | bool ath9k_hw_init_rf(struct ath_hal *ah, | 32 | bool ath9k_hw_init_rf(struct ath_hal *ah, |
33 | int *status); | 33 | int *status); |
34 | 34 | ||
35 | #define AR_PHY_BASE 0x9800 | 35 | #define AR_PHY_BASE 0x9800 |
36 | #define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2)) | 36 | #define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2)) |
diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 73c460ad355f..390019ed398e 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c | |||
@@ -653,8 +653,8 @@ ath_rc_sib_init_validrates(struct ath_rate_node *ath_rc_priv, | |||
653 | rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv); | 653 | rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv); |
654 | for (i = 0; i < rate_table->rate_cnt; i++) { | 654 | for (i = 0; i < rate_table->rate_cnt; i++) { |
655 | valid = (ath_rc_priv->single_stream ? | 655 | valid = (ath_rc_priv->single_stream ? |
656 | rate_table->info[i].valid_single_stream : | 656 | rate_table->info[i].valid_single_stream : |
657 | rate_table->info[i].valid); | 657 | rate_table->info[i].valid); |
658 | if (valid == TRUE) { | 658 | if (valid == TRUE) { |
659 | u32 phy = rate_table->info[i].phy; | 659 | u32 phy = rate_table->info[i].phy; |
660 | u8 valid_rate_count = 0; | 660 | u8 valid_rate_count = 0; |
@@ -740,14 +740,14 @@ ath_rc_sib_setvalid_htrates(struct ath_rate_node *ath_rc_priv, | |||
740 | for (j = 0; j < rate_table->rate_cnt; j++) { | 740 | for (j = 0; j < rate_table->rate_cnt; j++) { |
741 | u32 phy = rate_table->info[j].phy; | 741 | u32 phy = rate_table->info[j].phy; |
742 | u32 valid = (ath_rc_priv->single_stream ? | 742 | u32 valid = (ath_rc_priv->single_stream ? |
743 | rate_table->info[j].valid_single_stream : | 743 | rate_table->info[j].valid_single_stream : |
744 | rate_table->info[j].valid); | 744 | rate_table->info[j].valid); |
745 | 745 | ||
746 | if (((((struct ath_rateset *) | 746 | if (((((struct ath_rateset *) |
747 | mcs_set)->rs_rates[i] & 0x7F) != | 747 | mcs_set)->rs_rates[i] & 0x7F) != |
748 | (rate_table->info[j].dot11rate & 0x7F)) || | 748 | (rate_table->info[j].dot11rate & 0x7F)) || |
749 | !WLAN_RC_PHY_HT(phy) || | 749 | !WLAN_RC_PHY_HT(phy) || |
750 | !WLAN_RC_PHY_HT_VALID(valid, capflag)) | 750 | !WLAN_RC_PHY_HT_VALID(valid, capflag)) |
751 | continue; | 751 | continue; |
752 | 752 | ||
753 | if (!ath_rc_valid_phyrate(phy, capflag, FALSE)) | 753 | if (!ath_rc_valid_phyrate(phy, capflag, FALSE)) |
@@ -847,9 +847,9 @@ void ath_rate_newstate(struct ath_softc *sc, struct ath_vap *avp) | |||
847 | /* For half and quarter rate channles use different | 847 | /* For half and quarter rate channles use different |
848 | * rate tables | 848 | * rate tables |
849 | */ | 849 | */ |
850 | if (sc->sc_curchan.channelFlags & CHANNEL_HALF) | 850 | if (sc->sc_ah->ah_curchan->channelFlags & CHANNEL_HALF) |
851 | ar5416_sethalf_ratetable(asc); | 851 | ar5416_sethalf_ratetable(asc); |
852 | else if (sc->sc_curchan.channelFlags & CHANNEL_QUARTER) | 852 | else if (sc->sc_ah->ah_curchan->channelFlags & CHANNEL_QUARTER) |
853 | ar5416_setquarter_ratetable(asc); | 853 | ar5416_setquarter_ratetable(asc); |
854 | else /* full rate */ | 854 | else /* full rate */ |
855 | ar5416_setfull_ratetable(asc); | 855 | ar5416_setfull_ratetable(asc); |
@@ -866,10 +866,10 @@ void ath_rate_newstate(struct ath_softc *sc, struct ath_vap *avp) | |||
866 | } | 866 | } |
867 | 867 | ||
868 | static u8 ath_rc_ratefind_ht(struct ath_softc *sc, | 868 | static u8 ath_rc_ratefind_ht(struct ath_softc *sc, |
869 | struct ath_rate_node *ath_rc_priv, | 869 | struct ath_rate_node *ath_rc_priv, |
870 | const struct ath_rate_table *rate_table, | 870 | const struct ath_rate_table *rate_table, |
871 | int probe_allowed, int *is_probing, | 871 | int probe_allowed, int *is_probing, |
872 | int is_retry) | 872 | int is_retry) |
873 | { | 873 | { |
874 | u32 dt, best_thruput, this_thruput, now_msec; | 874 | u32 dt, best_thruput, this_thruput, now_msec; |
875 | u8 rate, next_rate, best_rate, maxindex, minindex; | 875 | u8 rate, next_rate, best_rate, maxindex, minindex; |
@@ -997,8 +997,8 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc, | |||
997 | rate = rate_ctrl->rate_table_size - 1; | 997 | rate = rate_ctrl->rate_table_size - 1; |
998 | 998 | ||
999 | ASSERT((rate_table->info[rate].valid && !ath_rc_priv->single_stream) || | 999 | ASSERT((rate_table->info[rate].valid && !ath_rc_priv->single_stream) || |
1000 | (rate_table->info[rate].valid_single_stream && | 1000 | (rate_table->info[rate].valid_single_stream && |
1001 | ath_rc_priv->single_stream)); | 1001 | ath_rc_priv->single_stream)); |
1002 | 1002 | ||
1003 | return rate; | 1003 | return rate; |
1004 | } | 1004 | } |
@@ -1023,10 +1023,10 @@ static void ath_rc_rate_set_series(const struct ath_rate_table *rate_table , | |||
1023 | } | 1023 | } |
1024 | 1024 | ||
1025 | static u8 ath_rc_rate_getidx(struct ath_softc *sc, | 1025 | static u8 ath_rc_rate_getidx(struct ath_softc *sc, |
1026 | struct ath_rate_node *ath_rc_priv, | 1026 | struct ath_rate_node *ath_rc_priv, |
1027 | const struct ath_rate_table *rate_table, | 1027 | const struct ath_rate_table *rate_table, |
1028 | u8 rix, u16 stepdown, | 1028 | u8 rix, u16 stepdown, |
1029 | u16 min_rate) | 1029 | u16 min_rate) |
1030 | { | 1030 | { |
1031 | u32 j; | 1031 | u32 j; |
1032 | u8 nextindex; | 1032 | u8 nextindex; |
@@ -1066,8 +1066,8 @@ static void ath_rc_ratefind(struct ath_softc *sc, | |||
1066 | rate_table = | 1066 | rate_table = |
1067 | (struct ath_rate_table *)asc->hw_rate_table[sc->sc_curmode]; | 1067 | (struct ath_rate_table *)asc->hw_rate_table[sc->sc_curmode]; |
1068 | rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table, | 1068 | rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table, |
1069 | (rcflag & ATH_RC_PROBE_ALLOWED) ? 1 : 0, | 1069 | (rcflag & ATH_RC_PROBE_ALLOWED) ? 1 : 0, |
1070 | is_probe, is_retry); | 1070 | is_probe, is_retry); |
1071 | nrix = rix; | 1071 | nrix = rix; |
1072 | 1072 | ||
1073 | if ((rcflag & ATH_RC_PROBE_ALLOWED) && (*is_probe)) { | 1073 | if ((rcflag & ATH_RC_PROBE_ALLOWED) && (*is_probe)) { |
@@ -1099,13 +1099,13 @@ static void ath_rc_ratefind(struct ath_softc *sc, | |||
1099 | try_num = ((i + 1) == num_rates) ? | 1099 | try_num = ((i + 1) == num_rates) ? |
1100 | num_tries - (try_per_rate * i) : try_per_rate ; | 1100 | num_tries - (try_per_rate * i) : try_per_rate ; |
1101 | min_rate = (((i + 1) == num_rates) && | 1101 | min_rate = (((i + 1) == num_rates) && |
1102 | (rcflag & ATH_RC_MINRATE_LASTRATE)) ? 1 : 0; | 1102 | (rcflag & ATH_RC_MINRATE_LASTRATE)) ? 1 : 0; |
1103 | 1103 | ||
1104 | nrix = ath_rc_rate_getidx(sc, ath_rc_priv, | 1104 | nrix = ath_rc_rate_getidx(sc, ath_rc_priv, |
1105 | rate_table, nrix, 1, min_rate); | 1105 | rate_table, nrix, 1, min_rate); |
1106 | /* All other rates in the series have RTS enabled */ | 1106 | /* All other rates in the series have RTS enabled */ |
1107 | ath_rc_rate_set_series(rate_table, | 1107 | ath_rc_rate_set_series(rate_table, |
1108 | &series[i], try_num, nrix, TRUE); | 1108 | &series[i], try_num, nrix, TRUE); |
1109 | } | 1109 | } |
1110 | 1110 | ||
1111 | /* | 1111 | /* |
@@ -1124,13 +1124,13 @@ static void ath_rc_ratefind(struct ath_softc *sc, | |||
1124 | * above conditions. | 1124 | * above conditions. |
1125 | */ | 1125 | */ |
1126 | if ((sc->sc_curmode == ATH9K_MODE_11NG_HT20) || | 1126 | if ((sc->sc_curmode == ATH9K_MODE_11NG_HT20) || |
1127 | (sc->sc_curmode == ATH9K_MODE_11NG_HT40PLUS) || | 1127 | (sc->sc_curmode == ATH9K_MODE_11NG_HT40PLUS) || |
1128 | (sc->sc_curmode == ATH9K_MODE_11NG_HT40MINUS)) { | 1128 | (sc->sc_curmode == ATH9K_MODE_11NG_HT40MINUS)) { |
1129 | u8 dot11rate = rate_table->info[rix].dot11rate; | 1129 | u8 dot11rate = rate_table->info[rix].dot11rate; |
1130 | u8 phy = rate_table->info[rix].phy; | 1130 | u8 phy = rate_table->info[rix].phy; |
1131 | if (i == 4 && | 1131 | if (i == 4 && |
1132 | ((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) || | 1132 | ((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) || |
1133 | (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) { | 1133 | (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) { |
1134 | series[3].rix = series[2].rix; | 1134 | series[3].rix = series[2].rix; |
1135 | series[3].flags = series[2].flags; | 1135 | series[3].flags = series[2].flags; |
1136 | series[3].max_4ms_framelen = series[2].max_4ms_framelen; | 1136 | series[3].max_4ms_framelen = series[2].max_4ms_framelen; |
@@ -1141,18 +1141,19 @@ static void ath_rc_ratefind(struct ath_softc *sc, | |||
1141 | /* | 1141 | /* |
1142 | * Return the Tx rate series. | 1142 | * Return the Tx rate series. |
1143 | */ | 1143 | */ |
1144 | void ath_rate_findrate(struct ath_softc *sc, | 1144 | static void ath_rate_findrate(struct ath_softc *sc, |
1145 | struct ath_rate_node *ath_rc_priv, | 1145 | struct ath_rate_node *ath_rc_priv, |
1146 | int num_tries, | 1146 | int num_tries, |
1147 | int num_rates, | 1147 | int num_rates, |
1148 | unsigned int rcflag, | 1148 | unsigned int rcflag, |
1149 | struct ath_rc_series series[], | 1149 | struct ath_rc_series series[], |
1150 | int *is_probe, | 1150 | int *is_probe, |
1151 | int is_retry) | 1151 | int is_retry) |
1152 | { | 1152 | { |
1153 | struct ath_vap *avp = ath_rc_priv->avp; | 1153 | struct ath_vap *avp = ath_rc_priv->avp; |
1154 | 1154 | ||
1155 | DPRINTF(sc, ATH_DBG_RATE, "%s", __func__); | 1155 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); |
1156 | |||
1156 | if (!num_rates || !num_tries) | 1157 | if (!num_rates || !num_tries) |
1157 | return; | 1158 | return; |
1158 | 1159 | ||
@@ -1174,9 +1175,8 @@ void ath_rate_findrate(struct ath_softc *sc, | |||
1174 | unsigned int mcs; | 1175 | unsigned int mcs; |
1175 | u8 series_rix = 0; | 1176 | u8 series_rix = 0; |
1176 | 1177 | ||
1177 | series[idx].tries = | 1178 | series[idx].tries = IEEE80211_RATE_IDX_ENTRY( |
1178 | IEEE80211_RATE_IDX_ENTRY( | 1179 | avp->av_config.av_fixed_retryset, idx); |
1179 | avp->av_config.av_fixed_retryset, idx); | ||
1180 | 1180 | ||
1181 | mcs = IEEE80211_RATE_IDX_ENTRY( | 1181 | mcs = IEEE80211_RATE_IDX_ENTRY( |
1182 | avp->av_config.av_fixed_rateset, idx); | 1182 | avp->av_config.av_fixed_rateset, idx); |
@@ -1228,7 +1228,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1228 | u32 now_msec = jiffies_to_msecs(jiffies); | 1228 | u32 now_msec = jiffies_to_msecs(jiffies); |
1229 | int state_change = FALSE, rate, count; | 1229 | int state_change = FALSE, rate, count; |
1230 | u8 last_per; | 1230 | u8 last_per; |
1231 | struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; | 1231 | struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; |
1232 | struct ath_rate_table *rate_table = | 1232 | struct ath_rate_table *rate_table = |
1233 | (struct ath_rate_table *)asc->hw_rate_table[sc->sc_curmode]; | 1233 | (struct ath_rate_table *)asc->hw_rate_table[sc->sc_curmode]; |
1234 | 1234 | ||
@@ -1272,14 +1272,14 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1272 | } else { | 1272 | } else { |
1273 | /* xretries == 2 */ | 1273 | /* xretries == 2 */ |
1274 | count = sizeof(nretry_to_per_lookup) / | 1274 | count = sizeof(nretry_to_per_lookup) / |
1275 | sizeof(nretry_to_per_lookup[0]); | 1275 | sizeof(nretry_to_per_lookup[0]); |
1276 | if (retries >= count) | 1276 | if (retries >= count) |
1277 | retries = count - 1; | 1277 | retries = count - 1; |
1278 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ | 1278 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ |
1279 | rate_ctrl->state[tx_rate].per = | 1279 | rate_ctrl->state[tx_rate].per = |
1280 | (u8)(rate_ctrl->state[tx_rate].per - | 1280 | (u8)(rate_ctrl->state[tx_rate].per - |
1281 | (rate_ctrl->state[tx_rate].per >> 3) + | 1281 | (rate_ctrl->state[tx_rate].per >> 3) + |
1282 | ((100) >> 3)); | 1282 | ((100) >> 3)); |
1283 | } | 1283 | } |
1284 | 1284 | ||
1285 | /* xretries == 1 or 2 */ | 1285 | /* xretries == 1 or 2 */ |
@@ -1295,8 +1295,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1295 | if (retries >= count) | 1295 | if (retries >= count) |
1296 | retries = count - 1; | 1296 | retries = count - 1; |
1297 | if (info_priv->n_bad_frames) { | 1297 | if (info_priv->n_bad_frames) { |
1298 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ | 1298 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) |
1299 | /* | ||
1300 | * Assuming that n_frames is not 0. The current PER | 1299 | * Assuming that n_frames is not 0. The current PER |
1301 | * from the retries is 100 * retries / (retries+1), | 1300 | * from the retries is 100 * retries / (retries+1), |
1302 | * since the first retries attempts failed, and the | 1301 | * since the first retries attempts failed, and the |
@@ -1386,7 +1385,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1386 | * rssi_ack values. | 1385 | * rssi_ack values. |
1387 | */ | 1386 | */ |
1388 | if (tx_rate == rate_ctrl->rate_max_phy && | 1387 | if (tx_rate == rate_ctrl->rate_max_phy && |
1389 | rate_ctrl->hw_maxretry_pktcnt < 255) { | 1388 | rate_ctrl->hw_maxretry_pktcnt < 255) { |
1390 | rate_ctrl->hw_maxretry_pktcnt++; | 1389 | rate_ctrl->hw_maxretry_pktcnt++; |
1391 | } | 1390 | } |
1392 | 1391 | ||
@@ -1418,7 +1417,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1418 | /* Now reduce the current | 1417 | /* Now reduce the current |
1419 | * rssi threshold. */ | 1418 | * rssi threshold. */ |
1420 | if ((rssi_ackAvg < rssi_thres + 2) && | 1419 | if ((rssi_ackAvg < rssi_thres + 2) && |
1421 | (rssi_thres > rssi_ack_vmin)) { | 1420 | (rssi_thres > rssi_ack_vmin)) { |
1422 | rate_ctrl->state[tx_rate]. | 1421 | rate_ctrl->state[tx_rate]. |
1423 | rssi_thres--; | 1422 | rssi_thres--; |
1424 | } | 1423 | } |
@@ -1436,10 +1435,10 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1436 | * a while (except if we are probing). | 1435 | * a while (except if we are probing). |
1437 | */ | 1436 | */ |
1438 | if (rate_ctrl->state[tx_rate].per >= 55 && tx_rate > 0 && | 1437 | if (rate_ctrl->state[tx_rate].per >= 55 && tx_rate > 0 && |
1439 | rate_table->info[tx_rate].ratekbps <= | 1438 | rate_table->info[tx_rate].ratekbps <= |
1440 | rate_table->info[rate_ctrl->rate_max_phy].ratekbps) { | 1439 | rate_table->info[rate_ctrl->rate_max_phy].ratekbps) { |
1441 | ath_rc_get_nextlowervalid_txrate(rate_table, rate_ctrl, | 1440 | ath_rc_get_nextlowervalid_txrate(rate_table, rate_ctrl, |
1442 | (u8) tx_rate, &rate_ctrl->rate_max_phy); | 1441 | (u8) tx_rate, &rate_ctrl->rate_max_phy); |
1443 | 1442 | ||
1444 | /* Don't probe for a little while. */ | 1443 | /* Don't probe for a little while. */ |
1445 | rate_ctrl->probe_time = now_msec; | 1444 | rate_ctrl->probe_time = now_msec; |
@@ -1460,43 +1459,43 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1460 | break; | 1459 | break; |
1461 | 1460 | ||
1462 | if (rate_ctrl->state[rate].rssi_thres + | 1461 | if (rate_ctrl->state[rate].rssi_thres + |
1463 | rate_table->info[rate].rssi_ack_deltamin > | 1462 | rate_table->info[rate].rssi_ack_deltamin > |
1464 | rate_ctrl->state[rate+1].rssi_thres) { | 1463 | rate_ctrl->state[rate+1].rssi_thres) { |
1465 | rate_ctrl->state[rate+1].rssi_thres = | 1464 | rate_ctrl->state[rate+1].rssi_thres = |
1466 | rate_ctrl->state[rate]. | 1465 | rate_ctrl->state[rate]. |
1467 | rssi_thres + | 1466 | rssi_thres + |
1468 | rate_table->info[rate]. | 1467 | rate_table->info[rate]. |
1469 | rssi_ack_deltamin; | 1468 | rssi_ack_deltamin; |
1470 | } | 1469 | } |
1471 | } | 1470 | } |
1472 | 1471 | ||
1473 | /* Make sure the rates below this have lower rssi thresholds. */ | 1472 | /* Make sure the rates below this have lower rssi thresholds. */ |
1474 | for (rate = tx_rate - 1; rate >= 0; rate--) { | 1473 | for (rate = tx_rate - 1; rate >= 0; rate--) { |
1475 | if (rate_table->info[rate].phy != | 1474 | if (rate_table->info[rate].phy != |
1476 | rate_table->info[tx_rate].phy) | 1475 | rate_table->info[tx_rate].phy) |
1477 | break; | 1476 | break; |
1478 | 1477 | ||
1479 | if (rate_ctrl->state[rate].rssi_thres + | 1478 | if (rate_ctrl->state[rate].rssi_thres + |
1480 | rate_table->info[rate].rssi_ack_deltamin > | 1479 | rate_table->info[rate].rssi_ack_deltamin > |
1481 | rate_ctrl->state[rate+1].rssi_thres) { | 1480 | rate_ctrl->state[rate+1].rssi_thres) { |
1482 | if (rate_ctrl->state[rate+1].rssi_thres < | 1481 | if (rate_ctrl->state[rate+1].rssi_thres < |
1483 | rate_table->info[rate]. | 1482 | rate_table->info[rate]. |
1484 | rssi_ack_deltamin) | 1483 | rssi_ack_deltamin) |
1485 | rate_ctrl->state[rate].rssi_thres = 0; | 1484 | rate_ctrl->state[rate].rssi_thres = 0; |
1486 | else { | 1485 | else { |
1487 | rate_ctrl->state[rate].rssi_thres = | 1486 | rate_ctrl->state[rate].rssi_thres = |
1488 | rate_ctrl->state[rate+1]. | 1487 | rate_ctrl->state[rate+1]. |
1489 | rssi_thres - | 1488 | rssi_thres - |
1490 | rate_table->info[rate]. | 1489 | rate_table->info[rate]. |
1491 | rssi_ack_deltamin; | 1490 | rssi_ack_deltamin; |
1492 | } | 1491 | } |
1493 | 1492 | ||
1494 | if (rate_ctrl->state[rate].rssi_thres < | 1493 | if (rate_ctrl->state[rate].rssi_thres < |
1495 | rate_table->info[rate]. | 1494 | rate_table->info[rate]. |
1496 | rssi_ack_validmin) { | 1495 | rssi_ack_validmin) { |
1497 | rate_ctrl->state[rate].rssi_thres = | 1496 | rate_ctrl->state[rate].rssi_thres = |
1498 | rate_table->info[rate]. | 1497 | rate_table->info[rate]. |
1499 | rssi_ack_validmin; | 1498 | rssi_ack_validmin; |
1500 | } | 1499 | } |
1501 | } | 1500 | } |
1502 | } | 1501 | } |
@@ -1507,11 +1506,11 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1507 | if (rate_ctrl->state[tx_rate].per < last_per) { | 1506 | if (rate_ctrl->state[tx_rate].per < last_per) { |
1508 | for (rate = tx_rate - 1; rate >= 0; rate--) { | 1507 | for (rate = tx_rate - 1; rate >= 0; rate--) { |
1509 | if (rate_table->info[rate].phy != | 1508 | if (rate_table->info[rate].phy != |
1510 | rate_table->info[tx_rate].phy) | 1509 | rate_table->info[tx_rate].phy) |
1511 | break; | 1510 | break; |
1512 | 1511 | ||
1513 | if (rate_ctrl->state[rate].per > | 1512 | if (rate_ctrl->state[rate].per > |
1514 | rate_ctrl->state[rate+1].per) { | 1513 | rate_ctrl->state[rate+1].per) { |
1515 | rate_ctrl->state[rate].per = | 1514 | rate_ctrl->state[rate].per = |
1516 | rate_ctrl->state[rate+1].per; | 1515 | rate_ctrl->state[rate+1].per; |
1517 | } | 1516 | } |
@@ -1528,11 +1527,11 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1528 | /* Every so often, we reduce the thresholds and | 1527 | /* Every so often, we reduce the thresholds and |
1529 | * PER (different for CCK and OFDM). */ | 1528 | * PER (different for CCK and OFDM). */ |
1530 | if (now_msec - rate_ctrl->rssi_down_time >= | 1529 | if (now_msec - rate_ctrl->rssi_down_time >= |
1531 | rate_table->rssi_reduce_interval) { | 1530 | rate_table->rssi_reduce_interval) { |
1532 | 1531 | ||
1533 | for (rate = 0; rate < rate_ctrl->rate_table_size; rate++) { | 1532 | for (rate = 0; rate < rate_ctrl->rate_table_size; rate++) { |
1534 | if (rate_ctrl->state[rate].rssi_thres > | 1533 | if (rate_ctrl->state[rate].rssi_thres > |
1535 | rate_table->info[rate].rssi_ack_validmin) | 1534 | rate_table->info[rate].rssi_ack_validmin) |
1536 | rate_ctrl->state[rate].rssi_thres -= 1; | 1535 | rate_ctrl->state[rate].rssi_thres -= 1; |
1537 | } | 1536 | } |
1538 | rate_ctrl->rssi_down_time = now_msec; | 1537 | rate_ctrl->rssi_down_time = now_msec; |
@@ -1541,7 +1540,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1541 | /* Every so often, we reduce the thresholds | 1540 | /* Every so often, we reduce the thresholds |
1542 | * and PER (different for CCK and OFDM). */ | 1541 | * and PER (different for CCK and OFDM). */ |
1543 | if (now_msec - rate_ctrl->per_down_time >= | 1542 | if (now_msec - rate_ctrl->per_down_time >= |
1544 | rate_table->rssi_reduce_interval) { | 1543 | rate_table->rssi_reduce_interval) { |
1545 | for (rate = 0; rate < rate_ctrl->rate_table_size; rate++) { | 1544 | for (rate = 0; rate < rate_ctrl->rate_table_size; rate++) { |
1546 | rate_ctrl->state[rate].per = | 1545 | rate_ctrl->state[rate].per = |
1547 | 7 * rate_ctrl->state[rate].per / 8; | 1546 | 7 * rate_ctrl->state[rate].per / 8; |
@@ -1560,7 +1559,7 @@ static void ath_rc_update(struct ath_softc *sc, | |||
1560 | struct ath_tx_info_priv *info_priv, int final_ts_idx, | 1559 | struct ath_tx_info_priv *info_priv, int final_ts_idx, |
1561 | int xretries, int long_retry) | 1560 | int xretries, int long_retry) |
1562 | { | 1561 | { |
1563 | struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; | 1562 | struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; |
1564 | struct ath_rate_table *rate_table; | 1563 | struct ath_rate_table *rate_table; |
1565 | struct ath_tx_ratectrl *rate_ctrl; | 1564 | struct ath_tx_ratectrl *rate_ctrl; |
1566 | struct ath_rc_series rcs[4]; | 1565 | struct ath_rc_series rcs[4]; |
@@ -1637,7 +1636,6 @@ static void ath_rc_update(struct ath_softc *sc, | |||
1637 | xretries, long_retry); | 1636 | xretries, long_retry); |
1638 | } | 1637 | } |
1639 | 1638 | ||
1640 | |||
1641 | /* | 1639 | /* |
1642 | * Process a tx descriptor for a completed transmit (success or failure). | 1640 | * Process a tx descriptor for a completed transmit (success or failure). |
1643 | */ | 1641 | */ |
@@ -1651,13 +1649,13 @@ static void ath_rate_tx_complete(struct ath_softc *sc, | |||
1651 | struct ath_vap *avp; | 1649 | struct ath_vap *avp; |
1652 | 1650 | ||
1653 | avp = rc_priv->avp; | 1651 | avp = rc_priv->avp; |
1654 | if ((avp->av_config.av_fixed_rateset != IEEE80211_FIXED_RATE_NONE) | 1652 | if ((avp->av_config.av_fixed_rateset != IEEE80211_FIXED_RATE_NONE) || |
1655 | || info_priv->tx.ts_status & ATH9K_TXERR_FILT) | 1653 | (info_priv->tx.ts_status & ATH9K_TXERR_FILT)) |
1656 | return; | 1654 | return; |
1657 | 1655 | ||
1658 | if (info_priv->tx.ts_rssi > 0) { | 1656 | if (info_priv->tx.ts_rssi > 0) { |
1659 | ATH_RSSI_LPF(an->an_chainmask_sel.tx_avgrssi, | 1657 | ATH_RSSI_LPF(an->an_chainmask_sel.tx_avgrssi, |
1660 | info_priv->tx.ts_rssi); | 1658 | info_priv->tx.ts_rssi); |
1661 | } | 1659 | } |
1662 | 1660 | ||
1663 | /* | 1661 | /* |
@@ -1682,7 +1680,6 @@ static void ath_rate_tx_complete(struct ath_softc *sc, | |||
1682 | info_priv->tx.ts_longretry); | 1680 | info_priv->tx.ts_longretry); |
1683 | } | 1681 | } |
1684 | 1682 | ||
1685 | |||
1686 | /* | 1683 | /* |
1687 | * Update the SIB's rate control information | 1684 | * Update the SIB's rate control information |
1688 | * | 1685 | * |
@@ -1701,8 +1698,8 @@ static void ath_rc_sib_update(struct ath_softc *sc, | |||
1701 | struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; | 1698 | struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; |
1702 | struct ath_rateset *rateset = negotiated_rates; | 1699 | struct ath_rateset *rateset = negotiated_rates; |
1703 | u8 *ht_mcs = (u8 *)negotiated_htrates; | 1700 | u8 *ht_mcs = (u8 *)negotiated_htrates; |
1704 | struct ath_tx_ratectrl *rate_ctrl = (struct ath_tx_ratectrl *) | 1701 | struct ath_tx_ratectrl *rate_ctrl = |
1705 | (ath_rc_priv); | 1702 | (struct ath_tx_ratectrl *)ath_rc_priv; |
1706 | u8 i, j, k, hi = 0, hthi = 0; | 1703 | u8 i, j, k, hi = 0, hthi = 0; |
1707 | 1704 | ||
1708 | rate_table = (struct ath_rate_table *) | 1705 | rate_table = (struct ath_rate_table *) |
@@ -1824,7 +1821,8 @@ static void ath_setup_rates(struct ieee80211_local *local, struct sta_info *sta) | |||
1824 | struct ath_rate_node *rc_priv = sta->rate_ctrl_priv; | 1821 | struct ath_rate_node *rc_priv = sta->rate_ctrl_priv; |
1825 | int i, j = 0; | 1822 | int i, j = 0; |
1826 | 1823 | ||
1827 | DPRINTF(sc, ATH_DBG_RATE, "%s", __func__); | 1824 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); |
1825 | |||
1828 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1826 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
1829 | for (i = 0; i < sband->n_bitrates; i++) { | 1827 | for (i = 0; i < sband->n_bitrates; i++) { |
1830 | if (sta->supp_rates[local->hw.conf.channel->band] & BIT(i)) { | 1828 | if (sta->supp_rates[local->hw.conf.channel->band] & BIT(i)) { |
@@ -1903,7 +1901,7 @@ static void ath_tx_aggr_resp(struct ath_softc *sc, | |||
1903 | int state; | 1901 | int state; |
1904 | DECLARE_MAC_BUF(mac); | 1902 | DECLARE_MAC_BUF(mac); |
1905 | 1903 | ||
1906 | if (!sc->sc_txaggr) | 1904 | if (!(sc->sc_flags & SC_OP_TXAGGR)) |
1907 | return; | 1905 | return; |
1908 | 1906 | ||
1909 | txtid = ATH_AN_2_TID(an, tidno); | 1907 | txtid = ATH_AN_2_TID(an, tidno); |
@@ -1944,7 +1942,7 @@ static void ath_get_rate(void *priv, struct net_device *dev, | |||
1944 | struct ath_rate_node *ath_rc_priv; | 1942 | struct ath_rate_node *ath_rc_priv; |
1945 | struct ath_node *an; | 1943 | struct ath_node *an; |
1946 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1944 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1947 | int is_probe, chk, ret; | 1945 | int is_probe = FALSE, chk, ret; |
1948 | s8 lowest_idx; | 1946 | s8 lowest_idx; |
1949 | __le16 fc = hdr->frame_control; | 1947 | __le16 fc = hdr->frame_control; |
1950 | u8 *qc, tid; | 1948 | u8 *qc, tid; |
@@ -1962,7 +1960,7 @@ static void ath_get_rate(void *priv, struct net_device *dev, | |||
1962 | tx_info_priv->min_rate = (sband->bitrates[lowest_idx].bitrate * 2) / 10; | 1960 | tx_info_priv->min_rate = (sband->bitrates[lowest_idx].bitrate * 2) / 10; |
1963 | /* lowest rate for management and multicast/broadcast frames */ | 1961 | /* lowest rate for management and multicast/broadcast frames */ |
1964 | if (!ieee80211_is_data(fc) || | 1962 | if (!ieee80211_is_data(fc) || |
1965 | is_multicast_ether_addr(hdr->addr1) || !sta) { | 1963 | is_multicast_ether_addr(hdr->addr1) || !sta) { |
1966 | sel->rate_idx = lowest_idx; | 1964 | sel->rate_idx = lowest_idx; |
1967 | return; | 1965 | return; |
1968 | } | 1966 | } |
@@ -1978,7 +1976,7 @@ static void ath_get_rate(void *priv, struct net_device *dev, | |||
1978 | false); | 1976 | false); |
1979 | if (is_probe) | 1977 | if (is_probe) |
1980 | sel->probe_idx = ((struct ath_tx_ratectrl *) | 1978 | sel->probe_idx = ((struct ath_tx_ratectrl *) |
1981 | sta->rate_ctrl_priv)->probe_rate; | 1979 | sta->rate_ctrl_priv)->probe_rate; |
1982 | 1980 | ||
1983 | /* Ratecontrol sometimes returns invalid rate index */ | 1981 | /* Ratecontrol sometimes returns invalid rate index */ |
1984 | if (tx_info_priv->rcs[0].rix != 0xff) | 1982 | if (tx_info_priv->rcs[0].rix != 0xff) |
@@ -2035,6 +2033,7 @@ static void ath_rate_init(void *priv, void *priv_sta, | |||
2035 | struct ieee80211_hw *hw = local_to_hw(local); | 2033 | struct ieee80211_hw *hw = local_to_hw(local); |
2036 | struct ieee80211_conf *conf = &local->hw.conf; | 2034 | struct ieee80211_conf *conf = &local->hw.conf; |
2037 | struct ath_softc *sc = hw->priv; | 2035 | struct ath_softc *sc = hw->priv; |
2036 | struct ath_rate_node *ath_rc_priv = priv_sta; | ||
2038 | int i, j = 0; | 2037 | int i, j = 0; |
2039 | 2038 | ||
2040 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); | 2039 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); |
@@ -2046,12 +2045,11 @@ static void ath_rate_init(void *priv, void *priv_sta, | |||
2046 | if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { | 2045 | if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { |
2047 | for (i = 0; i < MCS_SET_SIZE; i++) { | 2046 | for (i = 0; i < MCS_SET_SIZE; i++) { |
2048 | if (conf->ht_conf.supp_mcs_set[i/8] & (1<<(i%8))) | 2047 | if (conf->ht_conf.supp_mcs_set[i/8] & (1<<(i%8))) |
2049 | ((struct ath_rate_node *) | 2048 | ath_rc_priv->neg_ht_rates.rs_rates[j++] = i; |
2050 | priv_sta)->neg_ht_rates.rs_rates[j++] = i; | ||
2051 | if (j == ATH_RATE_MAX) | 2049 | if (j == ATH_RATE_MAX) |
2052 | break; | 2050 | break; |
2053 | } | 2051 | } |
2054 | ((struct ath_rate_node *)priv_sta)->neg_ht_rates.rs_nrates = j; | 2052 | ath_rc_priv->neg_ht_rates.rs_nrates = j; |
2055 | } | 2053 | } |
2056 | ath_rc_node_update(hw, priv_sta); | 2054 | ath_rc_node_update(hw, priv_sta); |
2057 | } | 2055 | } |
@@ -2066,7 +2064,7 @@ static void *ath_rate_alloc(struct ieee80211_local *local) | |||
2066 | struct ieee80211_hw *hw = local_to_hw(local); | 2064 | struct ieee80211_hw *hw = local_to_hw(local); |
2067 | struct ath_softc *sc = hw->priv; | 2065 | struct ath_softc *sc = hw->priv; |
2068 | 2066 | ||
2069 | DPRINTF(sc, ATH_DBG_RATE, "%s", __func__); | 2067 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); |
2070 | return local->hw.priv; | 2068 | return local->hw.priv; |
2071 | } | 2069 | } |
2072 | 2070 | ||
@@ -2081,14 +2079,17 @@ static void *ath_rate_alloc_sta(void *priv, gfp_t gfp) | |||
2081 | struct ath_vap *avp = sc->sc_vaps[0]; | 2079 | struct ath_vap *avp = sc->sc_vaps[0]; |
2082 | struct ath_rate_node *rate_priv; | 2080 | struct ath_rate_node *rate_priv; |
2083 | 2081 | ||
2084 | DPRINTF(sc, ATH_DBG_RATE, "%s", __func__); | 2082 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); |
2083 | |||
2085 | rate_priv = ath_rate_node_alloc(avp, sc->sc_rc, gfp); | 2084 | rate_priv = ath_rate_node_alloc(avp, sc->sc_rc, gfp); |
2086 | if (!rate_priv) { | 2085 | if (!rate_priv) { |
2087 | DPRINTF(sc, ATH_DBG_FATAL, "%s:Unable to allocate" | 2086 | DPRINTF(sc, ATH_DBG_FATAL, |
2088 | "private rate control structure", __func__); | 2087 | "%s: Unable to allocate private rc structure\n", |
2088 | __func__); | ||
2089 | return NULL; | 2089 | return NULL; |
2090 | } | 2090 | } |
2091 | ath_rc_sib_init(rate_priv); | 2091 | ath_rc_sib_init(rate_priv); |
2092 | |||
2092 | return rate_priv; | 2093 | return rate_priv; |
2093 | } | 2094 | } |
2094 | 2095 | ||
diff --git a/drivers/net/wireless/ath9k/rc.h b/drivers/net/wireless/ath9k/rc.h index 71aef9c75232..b95b41508b98 100644 --- a/drivers/net/wireless/ath9k/rc.h +++ b/drivers/net/wireless/ath9k/rc.h | |||
@@ -71,9 +71,6 @@ enum ieee80211_fixed_rate_mode { | |||
71 | */ | 71 | */ |
72 | #define IEEE80211_RATE_IDX_ENTRY(val, idx) (((val&(0xff<<(idx*8)))>>(idx*8))) | 72 | #define IEEE80211_RATE_IDX_ENTRY(val, idx) (((val&(0xff<<(idx*8)))>>(idx*8))) |
73 | 73 | ||
74 | #define SHORT_PRE 1 | ||
75 | #define LONG_PRE 0 | ||
76 | |||
77 | #define WLAN_PHY_HT_20_SS WLAN_RC_PHY_HT_20_SS | 74 | #define WLAN_PHY_HT_20_SS WLAN_RC_PHY_HT_20_SS |
78 | #define WLAN_PHY_HT_20_DS WLAN_RC_PHY_HT_20_DS | 75 | #define WLAN_PHY_HT_20_DS WLAN_RC_PHY_HT_20_DS |
79 | #define WLAN_PHY_HT_20_DS_HGI WLAN_RC_PHY_HT_20_DS_HGI | 76 | #define WLAN_PHY_HT_20_DS_HGI WLAN_RC_PHY_HT_20_DS_HGI |
@@ -102,18 +99,18 @@ enum { | |||
102 | WLAN_RC_PHY_MAX | 99 | WLAN_RC_PHY_MAX |
103 | }; | 100 | }; |
104 | 101 | ||
105 | #define WLAN_RC_PHY_DS(_phy) ((_phy == WLAN_RC_PHY_HT_20_DS) \ | 102 | #define WLAN_RC_PHY_DS(_phy) ((_phy == WLAN_RC_PHY_HT_20_DS) \ |
106 | || (_phy == WLAN_RC_PHY_HT_40_DS) \ | 103 | || (_phy == WLAN_RC_PHY_HT_40_DS) \ |
107 | || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ | 104 | || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ |
108 | || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) | 105 | || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) |
109 | #define WLAN_RC_PHY_40(_phy) ((_phy == WLAN_RC_PHY_HT_40_SS) \ | 106 | #define WLAN_RC_PHY_40(_phy) ((_phy == WLAN_RC_PHY_HT_40_SS) \ |
110 | || (_phy == WLAN_RC_PHY_HT_40_DS) \ | 107 | || (_phy == WLAN_RC_PHY_HT_40_DS) \ |
111 | || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ | 108 | || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ |
112 | || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) | 109 | || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) |
113 | #define WLAN_RC_PHY_SGI(_phy) ((_phy == WLAN_RC_PHY_HT_20_SS_HGI) \ | 110 | #define WLAN_RC_PHY_SGI(_phy) ((_phy == WLAN_RC_PHY_HT_20_SS_HGI) \ |
114 | || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ | 111 | || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ |
115 | || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ | 112 | || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ |
116 | || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) | 113 | || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) |
117 | 114 | ||
118 | #define WLAN_RC_PHY_HT(_phy) (_phy >= WLAN_RC_PHY_HT_20_SS) | 115 | #define WLAN_RC_PHY_HT(_phy) (_phy >= WLAN_RC_PHY_HT_20_SS) |
119 | 116 | ||
@@ -135,56 +132,59 @@ enum { | |||
135 | #define WLAN_RC_SGI_FLAG (0x04) | 132 | #define WLAN_RC_SGI_FLAG (0x04) |
136 | #define WLAN_RC_HT_FLAG (0x08) | 133 | #define WLAN_RC_HT_FLAG (0x08) |
137 | 134 | ||
138 | /* Index into the rate table */ | ||
139 | #define INIT_RATE_MAX_20 23 | ||
140 | #define INIT_RATE_MAX_40 40 | ||
141 | |||
142 | #define RATE_TABLE_SIZE 64 | 135 | #define RATE_TABLE_SIZE 64 |
143 | 136 | ||
144 | /* XXX: Convert to kdoc */ | 137 | /** |
138 | * struct ath_rate_table - Rate Control table | ||
139 | * @valid: valid for use in rate control | ||
140 | * @valid_single_stream: valid for use in rate control for | ||
141 | * single stream operation | ||
142 | * @phy: CCK/OFDM | ||
143 | * @ratekbps: rate in Kbits per second | ||
144 | * @user_ratekbps: user rate in Kbits per second | ||
145 | * @ratecode: rate that goes into HW descriptors | ||
146 | * @short_preamble: Mask for enabling short preamble in ratecode for CCK | ||
147 | * @dot11rate: value that goes into supported | ||
148 | * rates info element of MLME | ||
149 | * @ctrl_rate: Index of next lower basic rate, used for duration computation | ||
150 | * @max_4ms_framelen: maximum frame length(bytes) for tx duration | ||
151 | * @probe_interval: interval for rate control to probe for other rates | ||
152 | * @rssi_reduce_interval: interval for rate control to reduce rssi | ||
153 | * @initial_ratemax: initial ratemax value used in ath_rc_sib_update() | ||
154 | */ | ||
145 | struct ath_rate_table { | 155 | struct ath_rate_table { |
146 | int rate_cnt; | 156 | int rate_cnt; |
147 | struct { | 157 | struct { |
148 | int valid; /* Valid for use in rate control */ | 158 | int valid; |
149 | int valid_single_stream;/* Valid for use in rate control | 159 | int valid_single_stream; |
150 | for single stream operation */ | 160 | u8 phy; |
151 | u8 phy; /* CCK/OFDM/TURBO/XR */ | 161 | u32 ratekbps; |
152 | u32 ratekbps; /* Rate in Kbits per second */ | 162 | u32 user_ratekbps; |
153 | u32 user_ratekbps; /* User rate in KBits per second */ | 163 | u8 ratecode; |
154 | u8 ratecode; /* rate that goes into | 164 | u8 short_preamble; |
155 | hw descriptors */ | 165 | u8 dot11rate; |
156 | u8 short_preamble; /* Mask for enabling short preamble | 166 | u8 ctrl_rate; |
157 | in rate code for CCK */ | 167 | int8_t rssi_ack_validmin; |
158 | u8 dot11rate; /* Value that goes into supported | 168 | int8_t rssi_ack_deltamin; |
159 | rates info element of MLME */ | 169 | u8 base_index; |
160 | u8 ctrl_rate; /* Index of next lower basic rate, | 170 | u8 cw40index; |
161 | used for duration computation */ | 171 | u8 sgi_index; |
162 | int8_t rssi_ack_validmin; /* Rate control related */ | 172 | u8 ht_index; |
163 | int8_t rssi_ack_deltamin; /* Rate control related */ | 173 | u32 max_4ms_framelen; |
164 | u8 base_index; /* base rate index */ | ||
165 | u8 cw40index; /* 40cap rate index */ | ||
166 | u8 sgi_index; /* shortgi rate index */ | ||
167 | u8 ht_index; /* shortgi rate index */ | ||
168 | u32 max_4ms_framelen; /* Maximum frame length(bytes) | ||
169 | for 4ms tx duration */ | ||
170 | } info[RATE_TABLE_SIZE]; | 174 | } info[RATE_TABLE_SIZE]; |
171 | u32 probe_interval; /* interval for ratectrl to | 175 | u32 probe_interval; |
172 | probe for other rates */ | 176 | u32 rssi_reduce_interval; |
173 | u32 rssi_reduce_interval; /* interval for ratectrl | 177 | u8 initial_ratemax; |
174 | to reduce RSSI */ | ||
175 | u8 initial_ratemax; /* the initial ratemax value used | ||
176 | in ath_rc_sib_update() */ | ||
177 | }; | 178 | }; |
178 | 179 | ||
179 | #define ATH_RC_PROBE_ALLOWED 0x00000001 | 180 | #define ATH_RC_PROBE_ALLOWED 0x00000001 |
180 | #define ATH_RC_MINRATE_LASTRATE 0x00000002 | 181 | #define ATH_RC_MINRATE_LASTRATE 0x00000002 |
181 | #define ATH_RC_SHORT_PREAMBLE 0x00000004 | ||
182 | 182 | ||
183 | struct ath_rc_series { | 183 | struct ath_rc_series { |
184 | u8 rix; | 184 | u8 rix; |
185 | u8 tries; | 185 | u8 tries; |
186 | u8 flags; | 186 | u8 flags; |
187 | u32 max_4ms_framelen; | 187 | u32 max_4ms_framelen; |
188 | }; | 188 | }; |
189 | 189 | ||
190 | /* rcs_flags definition */ | 190 | /* rcs_flags definition */ |
@@ -201,42 +201,56 @@ struct ath_rc_series { | |||
201 | #define MAX_TX_RATE_PHY 48 | 201 | #define MAX_TX_RATE_PHY 48 |
202 | 202 | ||
203 | struct ath_tx_ratectrl_state { | 203 | struct ath_tx_ratectrl_state { |
204 | int8_t rssi_thres; /* required rssi for this rate (dB) */ | 204 | int8_t rssi_thres; /* required rssi for this rate (dB) */ |
205 | u8 per; /* recent estimate of packet error rate (%) */ | 205 | u8 per; /* recent estimate of packet error rate (%) */ |
206 | }; | 206 | }; |
207 | 207 | ||
208 | /** | ||
209 | * struct ath_tx_ratectrl - TX Rate control Information | ||
210 | * @state: RC state | ||
211 | * @rssi_last: last ACK rssi | ||
212 | * @rssi_last_lookup: last ACK rssi used for lookup | ||
213 | * @rssi_last_prev: previous last ACK rssi | ||
214 | * @rssi_last_prev2: 2nd previous last ACK rssi | ||
215 | * @rssi_sum_cnt: count of rssi_sum for averaging | ||
216 | * @rssi_sum_rate: rate that we are averaging | ||
217 | * @rssi_sum: running sum of rssi for averaging | ||
218 | * @probe_rate: rate we are probing at | ||
219 | * @rssi_time: msec timestamp for last ack rssi | ||
220 | * @rssi_down_time: msec timestamp for last down step | ||
221 | * @probe_time: msec timestamp for last probe | ||
222 | * @hw_maxretry_pktcnt: num of packets since we got HW max retry error | ||
223 | * @max_valid_rate: maximum number of valid rate | ||
224 | * @per_down_time: msec timestamp for last PER down step | ||
225 | * @valid_phy_ratecnt: valid rate count | ||
226 | * @rate_max_phy: phy index for the max rate | ||
227 | * @probe_interval: interval for ratectrl to probe for other rates | ||
228 | */ | ||
208 | struct ath_tx_ratectrl { | 229 | struct ath_tx_ratectrl { |
209 | struct ath_tx_ratectrl_state state[MAX_TX_RATE_TBL]; /* state */ | 230 | struct ath_tx_ratectrl_state state[MAX_TX_RATE_TBL]; |
210 | int8_t rssi_last; /* last ack rssi */ | 231 | int8_t rssi_last; |
211 | int8_t rssi_last_lookup; /* last ack rssi used for lookup */ | 232 | int8_t rssi_last_lookup; |
212 | int8_t rssi_last_prev; /* previous last ack rssi */ | 233 | int8_t rssi_last_prev; |
213 | int8_t rssi_last_prev2; /* 2nd previous last ack rssi */ | 234 | int8_t rssi_last_prev2; |
214 | int32_t rssi_sum_cnt; /* count of rssi_sum for averaging */ | 235 | int32_t rssi_sum_cnt; |
215 | int32_t rssi_sum_rate; /* rate that we are averaging */ | 236 | int32_t rssi_sum_rate; |
216 | int32_t rssi_sum; /* running sum of rssi for averaging */ | 237 | int32_t rssi_sum; |
217 | u32 valid_txrate_mask; /* mask of valid rates */ | 238 | u8 rate_table_size; |
218 | u8 rate_table_size; /* rate table size */ | 239 | u8 probe_rate; |
219 | u8 rate_max; /* max rate that has recently worked */ | 240 | u32 rssi_time; |
220 | u8 probe_rate; /* rate we are probing at */ | 241 | u32 rssi_down_time; |
221 | u32 rssi_time; /* msec timestamp for last ack rssi */ | 242 | u32 probe_time; |
222 | u32 rssi_down_time; /* msec timestamp for last down step */ | 243 | u8 hw_maxretry_pktcnt; |
223 | u32 probe_time; /* msec timestamp for last probe */ | 244 | u8 max_valid_rate; |
224 | u8 hw_maxretry_pktcnt; /* num packets since we got | 245 | u8 valid_rate_index[MAX_TX_RATE_TBL]; |
225 | HW max retry error */ | 246 | u32 per_down_time; |
226 | u8 max_valid_rate; /* maximum number of valid rate */ | ||
227 | u8 valid_rate_index[MAX_TX_RATE_TBL]; /* valid rate index */ | ||
228 | u32 per_down_time; /* msec timstamp for last | ||
229 | PER down step */ | ||
230 | 247 | ||
231 | /* 11n state */ | 248 | /* 11n state */ |
232 | u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX]; /* valid rate count */ | 249 | u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX]; |
233 | u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][MAX_TX_RATE_TBL]; | 250 | u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][MAX_TX_RATE_TBL]; |
234 | u8 rc_phy_mode; | 251 | u8 rc_phy_mode; |
235 | u8 rate_max_phy; /* Phy index for the max rate */ | 252 | u8 rate_max_phy; |
236 | u32 rate_max_lastused; /* msec timstamp of when we | 253 | u32 probe_interval; |
237 | last used rateMaxPhy */ | ||
238 | u32 probe_interval; /* interval for ratectrl to probe | ||
239 | for other rates */ | ||
240 | }; | 254 | }; |
241 | 255 | ||
242 | struct ath_rateset { | 256 | struct ath_rateset { |
@@ -248,29 +262,32 @@ struct ath_rateset { | |||
248 | struct ath_rate_softc { | 262 | struct ath_rate_softc { |
249 | /* phy tables that contain rate control data */ | 263 | /* phy tables that contain rate control data */ |
250 | const void *hw_rate_table[ATH9K_MODE_MAX]; | 264 | const void *hw_rate_table[ATH9K_MODE_MAX]; |
251 | int fixedrix; /* -1 or index of fixed rate */ | 265 | |
266 | /* -1 or index of fixed rate */ | ||
267 | int fixedrix; | ||
252 | }; | 268 | }; |
253 | 269 | ||
254 | /* per-node state */ | 270 | /* per-node state */ |
255 | struct ath_rate_node { | 271 | struct ath_rate_node { |
256 | struct ath_tx_ratectrl tx_ratectrl; /* rate control state proper */ | 272 | struct ath_tx_ratectrl tx_ratectrl; |
257 | u32 prev_data_rix; /* rate idx of last data frame */ | ||
258 | 273 | ||
259 | /* map of rate ix -> negotiated rate set ix */ | 274 | /* rate idx of last data frame */ |
260 | u8 rixmap[MAX_TX_RATE_TBL]; | 275 | u32 prev_data_rix; |
261 | 276 | ||
262 | /* map of ht rate ix -> negotiated rate set ix */ | 277 | /* ht capabilities */ |
263 | u8 ht_rixmap[MAX_TX_RATE_TBL]; | 278 | u8 ht_cap; |
264 | 279 | ||
265 | u8 ht_cap; /* ht capabilities */ | 280 | /* When TRUE, only single stream Tx possible */ |
266 | u8 ant_tx; /* current transmit antenna */ | 281 | u8 single_stream; |
267 | 282 | ||
268 | u8 single_stream; /* When TRUE, only single | 283 | /* Negotiated rates */ |
269 | stream Tx possible */ | 284 | struct ath_rateset neg_rates; |
270 | struct ath_rateset neg_rates; /* Negotiated rates */ | 285 | |
271 | struct ath_rateset neg_ht_rates; /* Negotiated HT rates */ | 286 | /* Negotiated HT rates */ |
272 | struct ath_rate_softc *asc; /* back pointer to atheros softc */ | 287 | struct ath_rateset neg_ht_rates; |
273 | struct ath_vap *avp; /* back pointer to vap */ | 288 | |
289 | struct ath_rate_softc *asc; | ||
290 | struct ath_vap *avp; | ||
274 | }; | 291 | }; |
275 | 292 | ||
276 | /* Driver data of ieee80211_tx_info */ | 293 | /* Driver data of ieee80211_tx_info */ |
@@ -297,17 +314,10 @@ void ath_rc_node_update(struct ieee80211_hw *hw, struct ath_rate_node *rc_priv); | |||
297 | void ath_rate_newstate(struct ath_softc *sc, struct ath_vap *avp); | 314 | void ath_rate_newstate(struct ath_softc *sc, struct ath_vap *avp); |
298 | 315 | ||
299 | /* | 316 | /* |
300 | * Return the tx rate series. | ||
301 | */ | ||
302 | void ath_rate_findrate(struct ath_softc *sc, struct ath_rate_node *ath_rc_priv, | ||
303 | int num_tries, int num_rates, | ||
304 | unsigned int rcflag, struct ath_rc_series[], | ||
305 | int *is_probe, int isretry); | ||
306 | /* | ||
307 | * Return rate index for given Dot11 Rate. | 317 | * Return rate index for given Dot11 Rate. |
308 | */ | 318 | */ |
309 | u8 ath_rate_findrateix(struct ath_softc *sc, | 319 | u8 ath_rate_findrateix(struct ath_softc *sc, |
310 | u8 dot11_rate); | 320 | u8 dot11_rate); |
311 | 321 | ||
312 | /* Routines to register/unregister rate control algorithm */ | 322 | /* Routines to register/unregister rate control algorithm */ |
313 | int ath_rate_control_register(void); | 323 | int ath_rate_control_register(void); |
diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c index 2fe806175c01..6e13c638cc0b 100644 --- a/drivers/net/wireless/ath9k/recv.c +++ b/drivers/net/wireless/ath9k/recv.c | |||
@@ -184,7 +184,7 @@ static int ath_ampdu_input(struct ath_softc *sc, | |||
184 | tid = qc[0] & 0xf; | 184 | tid = qc[0] & 0xf; |
185 | } | 185 | } |
186 | 186 | ||
187 | if (sc->sc_opmode == ATH9K_M_STA) { | 187 | if (sc->sc_ah->ah_opmode == ATH9K_M_STA) { |
188 | /* Drop the frame not belonging to me. */ | 188 | /* Drop the frame not belonging to me. */ |
189 | if (memcmp(hdr->addr1, sc->sc_myaddr, ETH_ALEN)) { | 189 | if (memcmp(hdr->addr1, sc->sc_myaddr, ETH_ALEN)) { |
190 | dev_kfree_skb(skb); | 190 | dev_kfree_skb(skb); |
@@ -448,17 +448,16 @@ static int ath_rx_indicate(struct ath_softc *sc, | |||
448 | int type; | 448 | int type; |
449 | 449 | ||
450 | /* indicate frame to the stack, which will free the old skb. */ | 450 | /* indicate frame to the stack, which will free the old skb. */ |
451 | type = ath__rx_indicate(sc, skb, status, keyix); | 451 | type = _ath_rx_indicate(sc, skb, status, keyix); |
452 | 452 | ||
453 | /* allocate a new skb and queue it to for H/W processing */ | 453 | /* allocate a new skb and queue it to for H/W processing */ |
454 | nskb = ath_rxbuf_alloc(sc, sc->sc_rxbufsize); | 454 | nskb = ath_rxbuf_alloc(sc, sc->sc_rxbufsize); |
455 | if (nskb != NULL) { | 455 | if (nskb != NULL) { |
456 | bf->bf_mpdu = nskb; | 456 | bf->bf_mpdu = nskb; |
457 | bf->bf_buf_addr = ath_skb_map_single(sc, | 457 | bf->bf_buf_addr = pci_map_single(sc->pdev, nskb->data, |
458 | nskb, | 458 | skb_end_pointer(nskb) - nskb->head, |
459 | PCI_DMA_FROMDEVICE, | 459 | PCI_DMA_FROMDEVICE); |
460 | /* XXX: Remove get_dma_mem_context() */ | 460 | bf->bf_dmacontext = bf->bf_buf_addr; |
461 | get_dma_mem_context(bf, bf_dmacontext)); | ||
462 | ATH_RX_CONTEXT(nskb)->ctx_rxbuf = bf; | 461 | ATH_RX_CONTEXT(nskb)->ctx_rxbuf = bf; |
463 | 462 | ||
464 | /* queue the new wbuf to H/W */ | 463 | /* queue the new wbuf to H/W */ |
@@ -504,7 +503,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) | |||
504 | 503 | ||
505 | do { | 504 | do { |
506 | spin_lock_init(&sc->sc_rxflushlock); | 505 | spin_lock_init(&sc->sc_rxflushlock); |
507 | sc->sc_rxflush = 0; | 506 | sc->sc_flags &= ~SC_OP_RXFLUSH; |
508 | spin_lock_init(&sc->sc_rxbuflock); | 507 | spin_lock_init(&sc->sc_rxbuflock); |
509 | 508 | ||
510 | /* | 509 | /* |
@@ -541,9 +540,10 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) | |||
541 | } | 540 | } |
542 | 541 | ||
543 | bf->bf_mpdu = skb; | 542 | bf->bf_mpdu = skb; |
544 | bf->bf_buf_addr = | 543 | bf->bf_buf_addr = pci_map_single(sc->pdev, skb->data, |
545 | ath_skb_map_single(sc, skb, PCI_DMA_FROMDEVICE, | 544 | skb_end_pointer(skb) - skb->head, |
546 | get_dma_mem_context(bf, bf_dmacontext)); | 545 | PCI_DMA_FROMDEVICE); |
546 | bf->bf_dmacontext = bf->bf_buf_addr; | ||
547 | ATH_RX_CONTEXT(skb)->ctx_rxbuf = bf; | 547 | ATH_RX_CONTEXT(skb)->ctx_rxbuf = bf; |
548 | } | 548 | } |
549 | sc->sc_rxlink = NULL; | 549 | sc->sc_rxlink = NULL; |
@@ -597,6 +597,7 @@ void ath_rx_cleanup(struct ath_softc *sc) | |||
597 | u32 ath_calcrxfilter(struct ath_softc *sc) | 597 | u32 ath_calcrxfilter(struct ath_softc *sc) |
598 | { | 598 | { |
599 | #define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR) | 599 | #define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR) |
600 | |||
600 | u32 rfilt; | 601 | u32 rfilt; |
601 | 602 | ||
602 | rfilt = (ath9k_hw_getrxfilter(sc->sc_ah) & RX_FILTER_PRESERVE) | 603 | rfilt = (ath9k_hw_getrxfilter(sc->sc_ah) & RX_FILTER_PRESERVE) |
@@ -604,25 +605,29 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
604 | | ATH9K_RX_FILTER_MCAST; | 605 | | ATH9K_RX_FILTER_MCAST; |
605 | 606 | ||
606 | /* If not a STA, enable processing of Probe Requests */ | 607 | /* If not a STA, enable processing of Probe Requests */ |
607 | if (sc->sc_opmode != ATH9K_M_STA) | 608 | if (sc->sc_ah->ah_opmode != ATH9K_M_STA) |
608 | rfilt |= ATH9K_RX_FILTER_PROBEREQ; | 609 | rfilt |= ATH9K_RX_FILTER_PROBEREQ; |
609 | 610 | ||
610 | /* Can't set HOSTAP into promiscous mode */ | 611 | /* Can't set HOSTAP into promiscous mode */ |
611 | if (sc->sc_opmode == ATH9K_M_MONITOR) { | 612 | if (((sc->sc_ah->ah_opmode != ATH9K_M_HOSTAP) && |
613 | (sc->rx_filter & FIF_PROMISC_IN_BSS)) || | ||
614 | (sc->sc_ah->ah_opmode == ATH9K_M_MONITOR)) { | ||
612 | rfilt |= ATH9K_RX_FILTER_PROM; | 615 | rfilt |= ATH9K_RX_FILTER_PROM; |
613 | /* ??? To prevent from sending ACK */ | 616 | /* ??? To prevent from sending ACK */ |
614 | rfilt &= ~ATH9K_RX_FILTER_UCAST; | 617 | rfilt &= ~ATH9K_RX_FILTER_UCAST; |
615 | } | 618 | } |
616 | 619 | ||
617 | if (sc->sc_opmode == ATH9K_M_STA || sc->sc_opmode == ATH9K_M_IBSS || | 620 | if (((sc->sc_ah->ah_opmode == ATH9K_M_STA) && |
618 | sc->sc_scanning) | 621 | (sc->rx_filter & FIF_BCN_PRBRESP_PROMISC)) || |
622 | (sc->sc_ah->ah_opmode == ATH9K_M_IBSS)) | ||
619 | rfilt |= ATH9K_RX_FILTER_BEACON; | 623 | rfilt |= ATH9K_RX_FILTER_BEACON; |
620 | 624 | ||
621 | /* If in HOSTAP mode, want to enable reception of PSPOLL frames | 625 | /* If in HOSTAP mode, want to enable reception of PSPOLL frames |
622 | & beacon frames */ | 626 | & beacon frames */ |
623 | if (sc->sc_opmode == ATH9K_M_HOSTAP) | 627 | if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) |
624 | rfilt |= (ATH9K_RX_FILTER_BEACON | ATH9K_RX_FILTER_PSPOLL); | 628 | rfilt |= (ATH9K_RX_FILTER_BEACON | ATH9K_RX_FILTER_PSPOLL); |
625 | return rfilt; | 629 | return rfilt; |
630 | |||
626 | #undef RX_FILTER_PRESERVE | 631 | #undef RX_FILTER_PRESERVE |
627 | } | 632 | } |
628 | 633 | ||
@@ -702,11 +707,11 @@ void ath_flushrecv(struct ath_softc *sc) | |||
702 | * progress (see references to sc_rxflush) | 707 | * progress (see references to sc_rxflush) |
703 | */ | 708 | */ |
704 | spin_lock_bh(&sc->sc_rxflushlock); | 709 | spin_lock_bh(&sc->sc_rxflushlock); |
705 | sc->sc_rxflush = 1; | 710 | sc->sc_flags |= SC_OP_RXFLUSH; |
706 | 711 | ||
707 | ath_rx_tasklet(sc, 1); | 712 | ath_rx_tasklet(sc, 1); |
708 | 713 | ||
709 | sc->sc_rxflush = 0; | 714 | sc->sc_flags &= ~SC_OP_RXFLUSH; |
710 | spin_unlock_bh(&sc->sc_rxflushlock); | 715 | spin_unlock_bh(&sc->sc_rxflushlock); |
711 | } | 716 | } |
712 | 717 | ||
@@ -719,7 +724,7 @@ int ath_rx_input(struct ath_softc *sc, | |||
719 | struct ath_recv_status *rx_status, | 724 | struct ath_recv_status *rx_status, |
720 | enum ATH_RX_TYPE *status) | 725 | enum ATH_RX_TYPE *status) |
721 | { | 726 | { |
722 | if (is_ampdu && sc->sc_rxaggr) { | 727 | if (is_ampdu && (sc->sc_flags & SC_OP_RXAGGR)) { |
723 | *status = ATH_RX_CONSUMED; | 728 | *status = ATH_RX_CONSUMED; |
724 | return ath_ampdu_input(sc, an, skb, rx_status); | 729 | return ath_ampdu_input(sc, an, skb, rx_status); |
725 | } else { | 730 | } else { |
@@ -750,7 +755,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
750 | 755 | ||
751 | do { | 756 | do { |
752 | /* If handling rx interrupt and flush is in progress => exit */ | 757 | /* If handling rx interrupt and flush is in progress => exit */ |
753 | if (sc->sc_rxflush && (flush == 0)) | 758 | if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0)) |
754 | break; | 759 | break; |
755 | 760 | ||
756 | spin_lock_bh(&sc->sc_rxbuflock); | 761 | spin_lock_bh(&sc->sc_rxbuflock); |
@@ -900,7 +905,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
900 | * Enable this if you want to see | 905 | * Enable this if you want to see |
901 | * error frames in Monitor mode. | 906 | * error frames in Monitor mode. |
902 | */ | 907 | */ |
903 | if (sc->sc_opmode != ATH9K_M_MONITOR) | 908 | if (sc->sc_ah->ah_opmode != ATH9K_M_MONITOR) |
904 | goto rx_next; | 909 | goto rx_next; |
905 | #endif | 910 | #endif |
906 | /* fall thru for monitor mode handling... */ | 911 | /* fall thru for monitor mode handling... */ |
@@ -945,7 +950,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
945 | * decryption and MIC failures. For monitor mode, | 950 | * decryption and MIC failures. For monitor mode, |
946 | * we also ignore the CRC error. | 951 | * we also ignore the CRC error. |
947 | */ | 952 | */ |
948 | if (sc->sc_opmode == ATH9K_M_MONITOR) { | 953 | if (sc->sc_ah->ah_opmode == ATH9K_M_MONITOR) { |
949 | if (ds->ds_rxstat.rs_status & | 954 | if (ds->ds_rxstat.rs_status & |
950 | ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | | 955 | ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | |
951 | ATH9K_RXERR_CRC)) | 956 | ATH9K_RXERR_CRC)) |
@@ -1089,7 +1094,7 @@ rx_next: | |||
1089 | "%s: Reset rx chain mask. " | 1094 | "%s: Reset rx chain mask. " |
1090 | "Do internal reset\n", __func__); | 1095 | "Do internal reset\n", __func__); |
1091 | ASSERT(flush == 0); | 1096 | ASSERT(flush == 0); |
1092 | ath_internal_reset(sc); | 1097 | ath_reset(sc, false); |
1093 | } | 1098 | } |
1094 | 1099 | ||
1095 | return 0; | 1100 | return 0; |
@@ -1127,7 +1132,7 @@ int ath_rx_aggr_start(struct ath_softc *sc, | |||
1127 | rxtid = &an->an_aggr.rx.tid[tid]; | 1132 | rxtid = &an->an_aggr.rx.tid[tid]; |
1128 | 1133 | ||
1129 | spin_lock_bh(&rxtid->tidlock); | 1134 | spin_lock_bh(&rxtid->tidlock); |
1130 | if (sc->sc_rxaggr) { | 1135 | if (sc->sc_flags & SC_OP_RXAGGR) { |
1131 | /* Allow aggregation reception | 1136 | /* Allow aggregation reception |
1132 | * Adjust rx BA window size. Peer might indicate a | 1137 | * Adjust rx BA window size. Peer might indicate a |
1133 | * zero buffer size for a _dont_care_ condition. | 1138 | * zero buffer size for a _dont_care_ condition. |
@@ -1227,7 +1232,7 @@ void ath_rx_aggr_teardown(struct ath_softc *sc, | |||
1227 | 1232 | ||
1228 | void ath_rx_node_init(struct ath_softc *sc, struct ath_node *an) | 1233 | void ath_rx_node_init(struct ath_softc *sc, struct ath_node *an) |
1229 | { | 1234 | { |
1230 | if (sc->sc_rxaggr) { | 1235 | if (sc->sc_flags & SC_OP_RXAGGR) { |
1231 | struct ath_arx_tid *rxtid; | 1236 | struct ath_arx_tid *rxtid; |
1232 | int tidno; | 1237 | int tidno; |
1233 | 1238 | ||
@@ -1259,7 +1264,7 @@ void ath_rx_node_init(struct ath_softc *sc, struct ath_node *an) | |||
1259 | 1264 | ||
1260 | void ath_rx_node_cleanup(struct ath_softc *sc, struct ath_node *an) | 1265 | void ath_rx_node_cleanup(struct ath_softc *sc, struct ath_node *an) |
1261 | { | 1266 | { |
1262 | if (sc->sc_rxaggr) { | 1267 | if (sc->sc_flags & SC_OP_RXAGGR) { |
1263 | struct ath_arx_tid *rxtid; | 1268 | struct ath_arx_tid *rxtid; |
1264 | int tidno, i; | 1269 | int tidno, i; |
1265 | 1270 | ||
@@ -1292,27 +1297,3 @@ void ath_rx_node_free(struct ath_softc *sc, struct ath_node *an) | |||
1292 | { | 1297 | { |
1293 | ath_rx_node_cleanup(sc, an); | 1298 | ath_rx_node_cleanup(sc, an); |
1294 | } | 1299 | } |
1295 | |||
1296 | dma_addr_t ath_skb_map_single(struct ath_softc *sc, | ||
1297 | struct sk_buff *skb, | ||
1298 | int direction, | ||
1299 | dma_addr_t *pa) | ||
1300 | { | ||
1301 | /* | ||
1302 | * NB: do NOT use skb->len, which is 0 on initialization. | ||
1303 | * Use skb's entire data area instead. | ||
1304 | */ | ||
1305 | *pa = pci_map_single(sc->pdev, skb->data, | ||
1306 | skb_end_pointer(skb) - skb->head, direction); | ||
1307 | return *pa; | ||
1308 | } | ||
1309 | |||
1310 | void ath_skb_unmap_single(struct ath_softc *sc, | ||
1311 | struct sk_buff *skb, | ||
1312 | int direction, | ||
1313 | dma_addr_t *pa) | ||
1314 | { | ||
1315 | /* Unmap skb's entire data area */ | ||
1316 | pci_unmap_single(sc->pdev, *pa, | ||
1317 | skb_end_pointer(skb) - skb->head, direction); | ||
1318 | } | ||
diff --git a/drivers/net/wireless/ath9k/reg.h b/drivers/net/wireless/ath9k/reg.h index 42b0890a4685..60617ae66209 100644 --- a/drivers/net/wireless/ath9k/reg.h +++ b/drivers/net/wireless/ath9k/reg.h | |||
@@ -899,12 +899,6 @@ enum { | |||
899 | #define AR_GPIO_OUTPUT_MUX2 0x4064 | 899 | #define AR_GPIO_OUTPUT_MUX2 0x4064 |
900 | #define AR_GPIO_OUTPUT_MUX3 0x4068 | 900 | #define AR_GPIO_OUTPUT_MUX3 0x4068 |
901 | 901 | ||
902 | #define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0 | ||
903 | #define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1 | ||
904 | #define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2 | ||
905 | #define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5 | ||
906 | #define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6 | ||
907 | |||
908 | #define AR_INPUT_STATE 0x406c | 902 | #define AR_INPUT_STATE 0x406c |
909 | 903 | ||
910 | #define AR_EEPROM_STATUS_DATA 0x407c | 904 | #define AR_EEPROM_STATUS_DATA 0x407c |
diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 157f830ee6b8..3fc6641e8bf7 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c | |||
@@ -60,79 +60,6 @@ static u32 bits_per_symbol[][2] = { | |||
60 | #define IS_HT_RATE(_rate) ((_rate) & 0x80) | 60 | #define IS_HT_RATE(_rate) ((_rate) & 0x80) |
61 | 61 | ||
62 | /* | 62 | /* |
63 | * Insert a chain of ath_buf (descriptors) on a multicast txq | ||
64 | * but do NOT start tx DMA on this queue. | ||
65 | * NB: must be called with txq lock held | ||
66 | */ | ||
67 | |||
68 | static void ath_tx_mcastqaddbuf(struct ath_softc *sc, | ||
69 | struct ath_txq *txq, | ||
70 | struct list_head *head) | ||
71 | { | ||
72 | struct ath_hal *ah = sc->sc_ah; | ||
73 | struct ath_buf *bf; | ||
74 | |||
75 | if (list_empty(head)) | ||
76 | return; | ||
77 | |||
78 | /* | ||
79 | * Insert the frame on the outbound list and | ||
80 | * pass it on to the hardware. | ||
81 | */ | ||
82 | bf = list_first_entry(head, struct ath_buf, list); | ||
83 | |||
84 | /* | ||
85 | * The CAB queue is started from the SWBA handler since | ||
86 | * frames only go out on DTIM and to avoid possible races. | ||
87 | */ | ||
88 | ath9k_hw_set_interrupts(ah, 0); | ||
89 | |||
90 | /* | ||
91 | * If there is anything in the mcastq, we want to set | ||
92 | * the "more data" bit in the last item in the queue to | ||
93 | * indicate that there is "more data". It makes sense to add | ||
94 | * it here since you are *always* going to have | ||
95 | * more data when adding to this queue, no matter where | ||
96 | * you call from. | ||
97 | */ | ||
98 | |||
99 | if (txq->axq_depth) { | ||
100 | struct ath_buf *lbf; | ||
101 | struct ieee80211_hdr *hdr; | ||
102 | |||
103 | /* | ||
104 | * Add the "more data flag" to the last frame | ||
105 | */ | ||
106 | |||
107 | lbf = list_entry(txq->axq_q.prev, struct ath_buf, list); | ||
108 | hdr = (struct ieee80211_hdr *) | ||
109 | ((struct sk_buff *)(lbf->bf_mpdu))->data; | ||
110 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); | ||
111 | } | ||
112 | |||
113 | /* | ||
114 | * Now, concat the frame onto the queue | ||
115 | */ | ||
116 | list_splice_tail_init(head, &txq->axq_q); | ||
117 | txq->axq_depth++; | ||
118 | txq->axq_totalqueued++; | ||
119 | txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list); | ||
120 | |||
121 | DPRINTF(sc, ATH_DBG_QUEUE, | ||
122 | "%s: txq depth = %d\n", __func__, txq->axq_depth); | ||
123 | if (txq->axq_link != NULL) { | ||
124 | *txq->axq_link = bf->bf_daddr; | ||
125 | DPRINTF(sc, ATH_DBG_XMIT, | ||
126 | "%s: link[%u](%p)=%llx (%p)\n", | ||
127 | __func__, | ||
128 | txq->axq_qnum, txq->axq_link, | ||
129 | ito64(bf->bf_daddr), bf->bf_desc); | ||
130 | } | ||
131 | txq->axq_link = &(bf->bf_lastbf->bf_desc->ds_link); | ||
132 | ath9k_hw_set_interrupts(ah, sc->sc_imask); | ||
133 | } | ||
134 | |||
135 | /* | ||
136 | * Insert a chain of ath_buf (descriptors) on a txq and | 63 | * Insert a chain of ath_buf (descriptors) on a txq and |
137 | * assume the descriptors are already chained together by caller. | 64 | * assume the descriptors are already chained together by caller. |
138 | * NB: must be called with txq lock held | 65 | * NB: must be called with txq lock held |
@@ -277,8 +204,6 @@ static int ath_tx_prepare(struct ath_softc *sc, | |||
277 | __le16 fc; | 204 | __le16 fc; |
278 | u8 *qc; | 205 | u8 *qc; |
279 | 206 | ||
280 | memset(txctl, 0, sizeof(struct ath_tx_control)); | ||
281 | |||
282 | txctl->dev = sc; | 207 | txctl->dev = sc; |
283 | hdr = (struct ieee80211_hdr *)skb->data; | 208 | hdr = (struct ieee80211_hdr *)skb->data; |
284 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 209 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
@@ -302,7 +227,6 @@ static int ath_tx_prepare(struct ath_softc *sc, | |||
302 | } | 227 | } |
303 | 228 | ||
304 | txctl->if_id = 0; | 229 | txctl->if_id = 0; |
305 | txctl->nextfraglen = 0; | ||
306 | txctl->frmlen = skb->len + FCS_LEN - (hdrlen & 3); | 230 | txctl->frmlen = skb->len + FCS_LEN - (hdrlen & 3); |
307 | txctl->txpower = MAX_RATE_POWER; /* FIXME */ | 231 | txctl->txpower = MAX_RATE_POWER; /* FIXME */ |
308 | 232 | ||
@@ -329,12 +253,18 @@ static int ath_tx_prepare(struct ath_softc *sc, | |||
329 | 253 | ||
330 | /* Fill qnum */ | 254 | /* Fill qnum */ |
331 | 255 | ||
332 | txctl->qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc); | 256 | if (unlikely(txctl->flags & ATH9K_TXDESC_CAB)) { |
333 | txq = &sc->sc_txq[txctl->qnum]; | 257 | txctl->qnum = 0; |
258 | txq = sc->sc_cabq; | ||
259 | } else { | ||
260 | txctl->qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc); | ||
261 | txq = &sc->sc_txq[txctl->qnum]; | ||
262 | } | ||
334 | spin_lock_bh(&txq->axq_lock); | 263 | spin_lock_bh(&txq->axq_lock); |
335 | 264 | ||
336 | /* Try to avoid running out of descriptors */ | 265 | /* Try to avoid running out of descriptors */ |
337 | if (txq->axq_depth >= (ATH_TXBUF - 20)) { | 266 | if (txq->axq_depth >= (ATH_TXBUF - 20) && |
267 | !(txctl->flags & ATH9K_TXDESC_CAB)) { | ||
338 | DPRINTF(sc, ATH_DBG_FATAL, | 268 | DPRINTF(sc, ATH_DBG_FATAL, |
339 | "%s: TX queue: %d is full, depth: %d\n", | 269 | "%s: TX queue: %d is full, depth: %d\n", |
340 | __func__, | 270 | __func__, |
@@ -354,12 +284,12 @@ static int ath_tx_prepare(struct ath_softc *sc, | |||
354 | 284 | ||
355 | /* Fill flags */ | 285 | /* Fill flags */ |
356 | 286 | ||
357 | txctl->flags = ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */ | 287 | txctl->flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */ |
358 | 288 | ||
359 | if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) | 289 | if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) |
360 | tx_info->flags |= ATH9K_TXDESC_NOACK; | 290 | txctl->flags |= ATH9K_TXDESC_NOACK; |
361 | if (tx_info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) | 291 | if (tx_info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) |
362 | tx_info->flags |= ATH9K_TXDESC_RTSENA; | 292 | txctl->flags |= ATH9K_TXDESC_RTSENA; |
363 | 293 | ||
364 | /* | 294 | /* |
365 | * Setup for rate calculations. | 295 | * Setup for rate calculations. |
@@ -392,7 +322,7 @@ static int ath_tx_prepare(struct ath_softc *sc, | |||
392 | * incremented by the fragmentation routine. | 322 | * incremented by the fragmentation routine. |
393 | */ | 323 | */ |
394 | if (likely(!(txctl->flags & ATH9K_TXDESC_FRAG_IS_ON)) && | 324 | if (likely(!(txctl->flags & ATH9K_TXDESC_FRAG_IS_ON)) && |
395 | txctl->ht && sc->sc_txaggr) { | 325 | txctl->ht && (sc->sc_flags & SC_OP_TXAGGR)) { |
396 | struct ath_atx_tid *tid; | 326 | struct ath_atx_tid *tid; |
397 | 327 | ||
398 | tid = ATH_AN_2_TID(txctl->an, txctl->tidno); | 328 | tid = ATH_AN_2_TID(txctl->an, txctl->tidno); |
@@ -413,50 +343,18 @@ static int ath_tx_prepare(struct ath_softc *sc, | |||
413 | } | 343 | } |
414 | rix = rcs[0].rix; | 344 | rix = rcs[0].rix; |
415 | 345 | ||
416 | /* | 346 | if (ieee80211_has_morefrags(fc) || |
417 | * Calculate duration. This logically belongs in the 802.11 | 347 | (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) { |
418 | * layer but it lacks sufficient information to calculate it. | ||
419 | */ | ||
420 | if ((txctl->flags & ATH9K_TXDESC_NOACK) == 0 && !ieee80211_is_ctl(fc)) { | ||
421 | u16 dur; | ||
422 | /* | 348 | /* |
423 | * XXX not right with fragmentation. | 349 | ** Force hardware to use computed duration for next |
424 | */ | 350 | ** fragment by disabling multi-rate retry, which |
425 | if (sc->sc_flags & ATH_PREAMBLE_SHORT) | 351 | ** updates duration based on the multi-rate |
426 | dur = rt->info[rix].spAckDuration; | 352 | ** duration table. |
427 | else | 353 | */ |
428 | dur = rt->info[rix].lpAckDuration; | 354 | rcs[1].tries = rcs[2].tries = rcs[3].tries = 0; |
429 | 355 | rcs[1].rix = rcs[2].rix = rcs[3].rix = 0; | |
430 | if (le16_to_cpu(hdr->frame_control) & | 356 | /* reset tries but keep rate index */ |
431 | IEEE80211_FCTL_MOREFRAGS) { | 357 | rcs[0].tries = ATH_TXMAXTRY; |
432 | dur += dur; /* Add additional 'SIFS + ACK' */ | ||
433 | |||
434 | /* | ||
435 | ** Compute size of next fragment in order to compute | ||
436 | ** durations needed to update NAV. | ||
437 | ** The last fragment uses the ACK duration only. | ||
438 | ** Add time for next fragment. | ||
439 | */ | ||
440 | dur += ath9k_hw_computetxtime(sc->sc_ah, rt, | ||
441 | txctl->nextfraglen, | ||
442 | rix, sc->sc_flags & ATH_PREAMBLE_SHORT); | ||
443 | } | ||
444 | |||
445 | if (ieee80211_has_morefrags(fc) || | ||
446 | (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) { | ||
447 | /* | ||
448 | ** Force hardware to use computed duration for next | ||
449 | ** fragment by disabling multi-rate retry, which | ||
450 | ** updates duration based on the multi-rate | ||
451 | ** duration table. | ||
452 | */ | ||
453 | rcs[1].tries = rcs[2].tries = rcs[3].tries = 0; | ||
454 | rcs[1].rix = rcs[2].rix = rcs[3].rix = 0; | ||
455 | /* reset tries but keep rate index */ | ||
456 | rcs[0].tries = ATH_TXMAXTRY; | ||
457 | } | ||
458 | |||
459 | hdr->duration_id = cpu_to_le16(dur); | ||
460 | } | 358 | } |
461 | 359 | ||
462 | /* | 360 | /* |
@@ -484,12 +382,8 @@ static int ath_tx_prepare(struct ath_softc *sc, | |||
484 | if (is_multicast_ether_addr(hdr->addr1)) { | 382 | if (is_multicast_ether_addr(hdr->addr1)) { |
485 | antenna = sc->sc_mcastantenna + 1; | 383 | antenna = sc->sc_mcastantenna + 1; |
486 | sc->sc_mcastantenna = (sc->sc_mcastantenna + 1) & 0x1; | 384 | sc->sc_mcastantenna = (sc->sc_mcastantenna + 1) & 0x1; |
487 | } else | 385 | } |
488 | antenna = sc->sc_txantenna; | ||
489 | 386 | ||
490 | #ifdef USE_LEGACY_HAL | ||
491 | txctl->antenna = antenna; | ||
492 | #endif | ||
493 | return 0; | 387 | return 0; |
494 | } | 388 | } |
495 | 389 | ||
@@ -502,7 +396,6 @@ static void ath_tx_complete_buf(struct ath_softc *sc, | |||
502 | { | 396 | { |
503 | struct sk_buff *skb = bf->bf_mpdu; | 397 | struct sk_buff *skb = bf->bf_mpdu; |
504 | struct ath_xmit_status tx_status; | 398 | struct ath_xmit_status tx_status; |
505 | dma_addr_t *pa; | ||
506 | 399 | ||
507 | /* | 400 | /* |
508 | * Set retry information. | 401 | * Set retry information. |
@@ -518,13 +411,12 @@ static void ath_tx_complete_buf(struct ath_softc *sc, | |||
518 | if (!txok) { | 411 | if (!txok) { |
519 | tx_status.flags |= ATH_TX_ERROR; | 412 | tx_status.flags |= ATH_TX_ERROR; |
520 | 413 | ||
521 | if (bf->bf_isxretried) | 414 | if (bf_isxretried(bf)) |
522 | tx_status.flags |= ATH_TX_XRETRY; | 415 | tx_status.flags |= ATH_TX_XRETRY; |
523 | } | 416 | } |
524 | /* Unmap this frame */ | 417 | /* Unmap this frame */ |
525 | pa = get_dma_mem_context(bf, bf_dmacontext); | ||
526 | pci_unmap_single(sc->pdev, | 418 | pci_unmap_single(sc->pdev, |
527 | *pa, | 419 | bf->bf_dmacontext, |
528 | skb->len, | 420 | skb->len, |
529 | PCI_DMA_TODEVICE); | 421 | PCI_DMA_TODEVICE); |
530 | /* complete this frame */ | 422 | /* complete this frame */ |
@@ -629,7 +521,7 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, | |||
629 | if (isnodegone || ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED) | 521 | if (isnodegone || ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED) |
630 | return 0; | 522 | return 0; |
631 | 523 | ||
632 | isaggr = bf->bf_isaggr; | 524 | isaggr = bf_isaggr(bf); |
633 | if (isaggr) { | 525 | if (isaggr) { |
634 | seq_st = ATH_DS_BA_SEQ(ds); | 526 | seq_st = ATH_DS_BA_SEQ(ds); |
635 | memcpy(ba, ATH_DS_BA_BITMAP(ds), WME_BA_BMP_SIZE >> 3); | 527 | memcpy(ba, ATH_DS_BA_BITMAP(ds), WME_BA_BMP_SIZE >> 3); |
@@ -651,7 +543,7 @@ static void ath_tx_set_retry(struct ath_softc *sc, struct ath_buf *bf) | |||
651 | struct sk_buff *skb; | 543 | struct sk_buff *skb; |
652 | struct ieee80211_hdr *hdr; | 544 | struct ieee80211_hdr *hdr; |
653 | 545 | ||
654 | bf->bf_isretried = 1; | 546 | bf->bf_state.bf_type |= BUF_RETRY; |
655 | bf->bf_retries++; | 547 | bf->bf_retries++; |
656 | 548 | ||
657 | skb = bf->bf_mpdu; | 549 | skb = bf->bf_mpdu; |
@@ -698,7 +590,7 @@ static u32 ath_pkt_duration(struct ath_softc *sc, | |||
698 | u8 rc; | 590 | u8 rc; |
699 | int streams, pktlen; | 591 | int streams, pktlen; |
700 | 592 | ||
701 | pktlen = bf->bf_isaggr ? bf->bf_al : bf->bf_frmlen; | 593 | pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen; |
702 | rc = rt->info[rix].rateCode; | 594 | rc = rt->info[rix].rateCode; |
703 | 595 | ||
704 | /* | 596 | /* |
@@ -742,7 +634,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) | |||
742 | int i, flags, rtsctsena = 0, dynamic_mimops = 0; | 634 | int i, flags, rtsctsena = 0, dynamic_mimops = 0; |
743 | u32 ctsduration = 0; | 635 | u32 ctsduration = 0; |
744 | u8 rix = 0, cix, ctsrate = 0; | 636 | u8 rix = 0, cix, ctsrate = 0; |
745 | u32 aggr_limit_with_rts = sc->sc_rtsaggrlimit; | 637 | u32 aggr_limit_with_rts = ah->ah_caps.rts_aggr_limit; |
746 | struct ath_node *an = (struct ath_node *) bf->bf_node; | 638 | struct ath_node *an = (struct ath_node *) bf->bf_node; |
747 | 639 | ||
748 | /* | 640 | /* |
@@ -781,7 +673,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) | |||
781 | * let rate series flags determine which rates will actually | 673 | * let rate series flags determine which rates will actually |
782 | * use RTS. | 674 | * use RTS. |
783 | */ | 675 | */ |
784 | if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) && bf->bf_isdata) { | 676 | if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) && bf_isdata(bf)) { |
785 | BUG_ON(!an); | 677 | BUG_ON(!an); |
786 | /* | 678 | /* |
787 | * 802.11g protection not needed, use our default behavior | 679 | * 802.11g protection not needed, use our default behavior |
@@ -793,7 +685,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) | |||
793 | * and the second aggregate should have any protection at all. | 685 | * and the second aggregate should have any protection at all. |
794 | */ | 686 | */ |
795 | if (an->an_smmode == ATH_SM_PWRSAV_DYNAMIC) { | 687 | if (an->an_smmode == ATH_SM_PWRSAV_DYNAMIC) { |
796 | if (!bf->bf_aggrburst) { | 688 | if (!bf_isaggrburst(bf)) { |
797 | flags = ATH9K_TXDESC_RTSENA; | 689 | flags = ATH9K_TXDESC_RTSENA; |
798 | dynamic_mimops = 1; | 690 | dynamic_mimops = 1; |
799 | } else { | 691 | } else { |
@@ -806,7 +698,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) | |||
806 | * Set protection if aggregate protection on | 698 | * Set protection if aggregate protection on |
807 | */ | 699 | */ |
808 | if (sc->sc_config.ath_aggr_prot && | 700 | if (sc->sc_config.ath_aggr_prot && |
809 | (!bf->bf_isaggr || (bf->bf_isaggr && bf->bf_al < 8192))) { | 701 | (!bf_isaggr(bf) || (bf_isaggr(bf) && bf->bf_al < 8192))) { |
810 | flags = ATH9K_TXDESC_RTSENA; | 702 | flags = ATH9K_TXDESC_RTSENA; |
811 | cix = rt->info[sc->sc_protrix].controlRate; | 703 | cix = rt->info[sc->sc_protrix].controlRate; |
812 | rtsctsena = 1; | 704 | rtsctsena = 1; |
@@ -815,7 +707,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) | |||
815 | /* | 707 | /* |
816 | * For AR5416 - RTS cannot be followed by a frame larger than 8K. | 708 | * For AR5416 - RTS cannot be followed by a frame larger than 8K. |
817 | */ | 709 | */ |
818 | if (bf->bf_isaggr && (bf->bf_al > aggr_limit_with_rts)) { | 710 | if (bf_isaggr(bf) && (bf->bf_al > aggr_limit_with_rts)) { |
819 | /* | 711 | /* |
820 | * Ensure that in the case of SM Dynamic power save | 712 | * Ensure that in the case of SM Dynamic power save |
821 | * while we are bursting the second aggregate the | 713 | * while we are bursting the second aggregate the |
@@ -832,7 +724,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) | |||
832 | /* NB: cix is set above where RTS/CTS is enabled */ | 724 | /* NB: cix is set above where RTS/CTS is enabled */ |
833 | BUG_ON(cix == 0xff); | 725 | BUG_ON(cix == 0xff); |
834 | ctsrate = rt->info[cix].rateCode | | 726 | ctsrate = rt->info[cix].rateCode | |
835 | (bf->bf_shpreamble ? rt->info[cix].shortPreamble : 0); | 727 | (bf_isshpreamble(bf) ? rt->info[cix].shortPreamble : 0); |
836 | 728 | ||
837 | /* | 729 | /* |
838 | * Setup HAL rate series | 730 | * Setup HAL rate series |
@@ -846,7 +738,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) | |||
846 | rix = bf->bf_rcs[i].rix; | 738 | rix = bf->bf_rcs[i].rix; |
847 | 739 | ||
848 | series[i].Rate = rt->info[rix].rateCode | | 740 | series[i].Rate = rt->info[rix].rateCode | |
849 | (bf->bf_shpreamble ? rt->info[rix].shortPreamble : 0); | 741 | (bf_isshpreamble(bf) ? rt->info[rix].shortPreamble : 0); |
850 | 742 | ||
851 | series[i].Tries = bf->bf_rcs[i].tries; | 743 | series[i].Tries = bf->bf_rcs[i].tries; |
852 | 744 | ||
@@ -862,7 +754,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) | |||
862 | sc, rix, bf, | 754 | sc, rix, bf, |
863 | (bf->bf_rcs[i].flags & ATH_RC_CW40_FLAG) != 0, | 755 | (bf->bf_rcs[i].flags & ATH_RC_CW40_FLAG) != 0, |
864 | (bf->bf_rcs[i].flags & ATH_RC_SGI_FLAG), | 756 | (bf->bf_rcs[i].flags & ATH_RC_SGI_FLAG), |
865 | bf->bf_shpreamble); | 757 | bf_isshpreamble(bf)); |
866 | 758 | ||
867 | if ((an->an_smmode == ATH_SM_PWRSAV_STATIC) && | 759 | if ((an->an_smmode == ATH_SM_PWRSAV_STATIC) && |
868 | (bf->bf_rcs[i].flags & ATH_RC_DS_FLAG) == 0) { | 760 | (bf->bf_rcs[i].flags & ATH_RC_DS_FLAG) == 0) { |
@@ -875,7 +767,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) | |||
875 | */ | 767 | */ |
876 | series[i].ChSel = sc->sc_tx_chainmask; | 768 | series[i].ChSel = sc->sc_tx_chainmask; |
877 | } else { | 769 | } else { |
878 | if (bf->bf_ht) | 770 | if (bf_isht(bf)) |
879 | series[i].ChSel = | 771 | series[i].ChSel = |
880 | ath_chainmask_sel_logic(sc, an); | 772 | ath_chainmask_sel_logic(sc, an); |
881 | else | 773 | else |
@@ -908,7 +800,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) | |||
908 | * use the precalculated ACK durations. | 800 | * use the precalculated ACK durations. |
909 | */ | 801 | */ |
910 | if (flags & ATH9K_TXDESC_RTSENA) { /* SIFS + CTS */ | 802 | if (flags & ATH9K_TXDESC_RTSENA) { /* SIFS + CTS */ |
911 | ctsduration += bf->bf_shpreamble ? | 803 | ctsduration += bf_isshpreamble(bf) ? |
912 | rt->info[cix].spAckDuration : | 804 | rt->info[cix].spAckDuration : |
913 | rt->info[cix].lpAckDuration; | 805 | rt->info[cix].lpAckDuration; |
914 | } | 806 | } |
@@ -916,7 +808,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) | |||
916 | ctsduration += series[0].PktDuration; | 808 | ctsduration += series[0].PktDuration; |
917 | 809 | ||
918 | if ((bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) { /* SIFS + ACK */ | 810 | if ((bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) { /* SIFS + ACK */ |
919 | ctsduration += bf->bf_shpreamble ? | 811 | ctsduration += bf_isshpreamble(bf) ? |
920 | rt->info[rix].spAckDuration : | 812 | rt->info[rix].spAckDuration : |
921 | rt->info[rix].lpAckDuration; | 813 | rt->info[rix].lpAckDuration; |
922 | } | 814 | } |
@@ -932,10 +824,10 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) | |||
932 | * set dur_update_en for l-sig computation except for PS-Poll frames | 824 | * set dur_update_en for l-sig computation except for PS-Poll frames |
933 | */ | 825 | */ |
934 | ath9k_hw_set11n_ratescenario(ah, ds, lastds, | 826 | ath9k_hw_set11n_ratescenario(ah, ds, lastds, |
935 | !bf->bf_ispspoll, | 827 | !bf_ispspoll(bf), |
936 | ctsrate, | 828 | ctsrate, |
937 | ctsduration, | 829 | ctsduration, |
938 | series, 4, flags); | 830 | series, 4, flags); |
939 | if (sc->sc_config.ath_aggr_prot && flags) | 831 | if (sc->sc_config.ath_aggr_prot && flags) |
940 | ath9k_hw_set11n_burstduration(ah, ds, 8192); | 832 | ath9k_hw_set11n_burstduration(ah, ds, 8192); |
941 | } | 833 | } |
@@ -958,7 +850,7 @@ static int ath_tx_send_normal(struct ath_softc *sc, | |||
958 | BUG_ON(list_empty(bf_head)); | 850 | BUG_ON(list_empty(bf_head)); |
959 | 851 | ||
960 | bf = list_first_entry(bf_head, struct ath_buf, list); | 852 | bf = list_first_entry(bf_head, struct ath_buf, list); |
961 | bf->bf_isampdu = 0; /* regular HT frame */ | 853 | bf->bf_state.bf_type &= ~BUF_AMPDU; /* regular HT frame */ |
962 | 854 | ||
963 | skb = (struct sk_buff *)bf->bf_mpdu; | 855 | skb = (struct sk_buff *)bf->bf_mpdu; |
964 | tx_info = IEEE80211_SKB_CB(skb); | 856 | tx_info = IEEE80211_SKB_CB(skb); |
@@ -998,7 +890,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | |||
998 | 890 | ||
999 | while (!list_empty(&tid->buf_q)) { | 891 | while (!list_empty(&tid->buf_q)) { |
1000 | bf = list_first_entry(&tid->buf_q, struct ath_buf, list); | 892 | bf = list_first_entry(&tid->buf_q, struct ath_buf, list); |
1001 | ASSERT(!bf->bf_isretried); | 893 | ASSERT(!bf_isretried(bf)); |
1002 | list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list); | 894 | list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list); |
1003 | ath_tx_send_normal(sc, txq, tid, &bf_head); | 895 | ath_tx_send_normal(sc, txq, tid, &bf_head); |
1004 | } | 896 | } |
@@ -1025,7 +917,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, | |||
1025 | int isaggr, txfail, txpending, sendbar = 0, needreset = 0; | 917 | int isaggr, txfail, txpending, sendbar = 0, needreset = 0; |
1026 | int isnodegone = (an->an_flags & ATH_NODE_CLEAN); | 918 | int isnodegone = (an->an_flags & ATH_NODE_CLEAN); |
1027 | 919 | ||
1028 | isaggr = bf->bf_isaggr; | 920 | isaggr = bf_isaggr(bf); |
1029 | if (isaggr) { | 921 | if (isaggr) { |
1030 | if (txok) { | 922 | if (txok) { |
1031 | if (ATH_DS_TX_BA(ds)) { | 923 | if (ATH_DS_TX_BA(ds)) { |
@@ -1047,7 +939,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, | |||
1047 | * when perform internal reset in this routine. | 939 | * when perform internal reset in this routine. |
1048 | * Only enable reset in STA mode for now. | 940 | * Only enable reset in STA mode for now. |
1049 | */ | 941 | */ |
1050 | if (sc->sc_opmode == ATH9K_M_STA) | 942 | if (sc->sc_ah->ah_opmode == ATH9K_M_STA) |
1051 | needreset = 1; | 943 | needreset = 1; |
1052 | } | 944 | } |
1053 | } else { | 945 | } else { |
@@ -1075,7 +967,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, | |||
1075 | ath_tx_set_retry(sc, bf); | 967 | ath_tx_set_retry(sc, bf); |
1076 | txpending = 1; | 968 | txpending = 1; |
1077 | } else { | 969 | } else { |
1078 | bf->bf_isxretried = 1; | 970 | bf->bf_state.bf_type |= BUF_XRETRY; |
1079 | txfail = 1; | 971 | txfail = 1; |
1080 | sendbar = 1; | 972 | sendbar = 1; |
1081 | } | 973 | } |
@@ -1175,11 +1067,8 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, | |||
1175 | tbf->bf_lastfrm->bf_desc); | 1067 | tbf->bf_lastfrm->bf_desc); |
1176 | 1068 | ||
1177 | /* copy the DMA context */ | 1069 | /* copy the DMA context */ |
1178 | copy_dma_mem_context( | 1070 | tbf->bf_dmacontext = |
1179 | get_dma_mem_context(tbf, | 1071 | bf_last->bf_dmacontext; |
1180 | bf_dmacontext), | ||
1181 | get_dma_mem_context(bf_last, | ||
1182 | bf_dmacontext)); | ||
1183 | } | 1072 | } |
1184 | list_add_tail(&tbf->list, &bf_head); | 1073 | list_add_tail(&tbf->list, &bf_head); |
1185 | } else { | 1074 | } else { |
@@ -1188,7 +1077,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, | |||
1188 | * software retry | 1077 | * software retry |
1189 | */ | 1078 | */ |
1190 | ath9k_hw_cleartxdesc(sc->sc_ah, | 1079 | ath9k_hw_cleartxdesc(sc->sc_ah, |
1191 | bf->bf_lastfrm->bf_desc); | 1080 | bf->bf_lastfrm->bf_desc); |
1192 | } | 1081 | } |
1193 | 1082 | ||
1194 | /* | 1083 | /* |
@@ -1242,7 +1131,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, | |||
1242 | } | 1131 | } |
1243 | 1132 | ||
1244 | if (needreset) | 1133 | if (needreset) |
1245 | ath_internal_reset(sc); | 1134 | ath_reset(sc, false); |
1246 | 1135 | ||
1247 | return; | 1136 | return; |
1248 | } | 1137 | } |
@@ -1331,7 +1220,7 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
1331 | 1220 | ||
1332 | txq->axq_depth--; | 1221 | txq->axq_depth--; |
1333 | 1222 | ||
1334 | if (bf->bf_isaggr) | 1223 | if (bf_isaggr(bf)) |
1335 | txq->axq_aggr_depth--; | 1224 | txq->axq_aggr_depth--; |
1336 | 1225 | ||
1337 | txok = (ds->ds_txstat.ts_status == 0); | 1226 | txok = (ds->ds_txstat.ts_status == 0); |
@@ -1345,14 +1234,14 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
1345 | spin_unlock_bh(&sc->sc_txbuflock); | 1234 | spin_unlock_bh(&sc->sc_txbuflock); |
1346 | } | 1235 | } |
1347 | 1236 | ||
1348 | if (!bf->bf_isampdu) { | 1237 | if (!bf_isampdu(bf)) { |
1349 | /* | 1238 | /* |
1350 | * This frame is sent out as a single frame. | 1239 | * This frame is sent out as a single frame. |
1351 | * Use hardware retry status for this frame. | 1240 | * Use hardware retry status for this frame. |
1352 | */ | 1241 | */ |
1353 | bf->bf_retries = ds->ds_txstat.ts_longretry; | 1242 | bf->bf_retries = ds->ds_txstat.ts_longretry; |
1354 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) | 1243 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) |
1355 | bf->bf_isxretried = 1; | 1244 | bf->bf_state.bf_type |= BUF_XRETRY; |
1356 | nbad = 0; | 1245 | nbad = 0; |
1357 | } else { | 1246 | } else { |
1358 | nbad = ath_tx_num_badfrms(sc, bf, txok); | 1247 | nbad = ath_tx_num_badfrms(sc, bf, txok); |
@@ -1368,7 +1257,7 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
1368 | if (ds->ds_txstat.ts_status == 0) | 1257 | if (ds->ds_txstat.ts_status == 0) |
1369 | nacked++; | 1258 | nacked++; |
1370 | 1259 | ||
1371 | if (bf->bf_isdata) { | 1260 | if (bf_isdata(bf)) { |
1372 | if (isrifs) | 1261 | if (isrifs) |
1373 | tmp_ds = bf->bf_rifslast->bf_desc; | 1262 | tmp_ds = bf->bf_rifslast->bf_desc; |
1374 | else | 1263 | else |
@@ -1384,7 +1273,7 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
1384 | /* | 1273 | /* |
1385 | * Complete this transmit unit | 1274 | * Complete this transmit unit |
1386 | */ | 1275 | */ |
1387 | if (bf->bf_isampdu) | 1276 | if (bf_isampdu(bf)) |
1388 | ath_tx_complete_aggr_rifs(sc, txq, bf, &bf_head, txok); | 1277 | ath_tx_complete_aggr_rifs(sc, txq, bf, &bf_head, txok); |
1389 | else | 1278 | else |
1390 | ath_tx_complete_buf(sc, bf, &bf_head, txok, 0); | 1279 | ath_tx_complete_buf(sc, bf, &bf_head, txok, 0); |
@@ -1406,7 +1295,7 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
1406 | /* | 1295 | /* |
1407 | * schedule any pending packets if aggregation is enabled | 1296 | * schedule any pending packets if aggregation is enabled |
1408 | */ | 1297 | */ |
1409 | if (sc->sc_txaggr) | 1298 | if (sc->sc_flags & SC_OP_TXAGGR) |
1410 | ath_txq_schedule(sc, txq); | 1299 | ath_txq_schedule(sc, txq); |
1411 | spin_unlock_bh(&txq->axq_lock); | 1300 | spin_unlock_bh(&txq->axq_lock); |
1412 | } | 1301 | } |
@@ -1430,10 +1319,9 @@ static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx) | |||
1430 | struct ath_hal *ah = sc->sc_ah; | 1319 | struct ath_hal *ah = sc->sc_ah; |
1431 | int i; | 1320 | int i; |
1432 | int npend = 0; | 1321 | int npend = 0; |
1433 | enum ath9k_ht_macmode ht_macmode = ath_cwm_macmode(sc); | ||
1434 | 1322 | ||
1435 | /* XXX return value */ | 1323 | /* XXX return value */ |
1436 | if (!sc->sc_invalid) { | 1324 | if (!(sc->sc_flags & SC_OP_INVALID)) { |
1437 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { | 1325 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { |
1438 | if (ATH_TXQ_SETUP(sc, i)) { | 1326 | if (ATH_TXQ_SETUP(sc, i)) { |
1439 | ath_tx_stopdma(sc, &sc->sc_txq[i]); | 1327 | ath_tx_stopdma(sc, &sc->sc_txq[i]); |
@@ -1454,10 +1342,11 @@ static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx) | |||
1454 | "%s: Unable to stop TxDMA. Reset HAL!\n", __func__); | 1342 | "%s: Unable to stop TxDMA. Reset HAL!\n", __func__); |
1455 | 1343 | ||
1456 | spin_lock_bh(&sc->sc_resetlock); | 1344 | spin_lock_bh(&sc->sc_resetlock); |
1457 | if (!ath9k_hw_reset(ah, sc->sc_opmode, | 1345 | if (!ath9k_hw_reset(ah, |
1458 | &sc->sc_curchan, ht_macmode, | 1346 | sc->sc_ah->ah_curchan, |
1459 | sc->sc_tx_chainmask, sc->sc_rx_chainmask, | 1347 | sc->sc_ht_info.tx_chan_width, |
1460 | sc->sc_ht_extprotspacing, true, &status)) { | 1348 | sc->sc_tx_chainmask, sc->sc_rx_chainmask, |
1349 | sc->sc_ht_extprotspacing, true, &status)) { | ||
1461 | 1350 | ||
1462 | DPRINTF(sc, ATH_DBG_FATAL, | 1351 | DPRINTF(sc, ATH_DBG_FATAL, |
1463 | "%s: unable to reset hardware; hal status %u\n", | 1352 | "%s: unable to reset hardware; hal status %u\n", |
@@ -1481,7 +1370,7 @@ static void ath_tx_addto_baw(struct ath_softc *sc, | |||
1481 | { | 1370 | { |
1482 | int index, cindex; | 1371 | int index, cindex; |
1483 | 1372 | ||
1484 | if (bf->bf_isretried) | 1373 | if (bf_isretried(bf)) |
1485 | return; | 1374 | return; |
1486 | 1375 | ||
1487 | index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno); | 1376 | index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno); |
@@ -1516,7 +1405,7 @@ static int ath_tx_send_ampdu(struct ath_softc *sc, | |||
1516 | BUG_ON(list_empty(bf_head)); | 1405 | BUG_ON(list_empty(bf_head)); |
1517 | 1406 | ||
1518 | bf = list_first_entry(bf_head, struct ath_buf, list); | 1407 | bf = list_first_entry(bf_head, struct ath_buf, list); |
1519 | bf->bf_isampdu = 1; | 1408 | bf->bf_state.bf_type |= BUF_AMPDU; |
1520 | bf->bf_seqno = txctl->seqno; /* save seqno and tidno in buffer */ | 1409 | bf->bf_seqno = txctl->seqno; /* save seqno and tidno in buffer */ |
1521 | bf->bf_tidno = txctl->tidno; | 1410 | bf->bf_tidno = txctl->tidno; |
1522 | 1411 | ||
@@ -1860,7 +1749,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, | |||
1860 | if (bf->bf_nframes == 1) { | 1749 | if (bf->bf_nframes == 1) { |
1861 | ASSERT(bf->bf_lastfrm == bf_last); | 1750 | ASSERT(bf->bf_lastfrm == bf_last); |
1862 | 1751 | ||
1863 | bf->bf_isaggr = 0; | 1752 | bf->bf_state.bf_type &= ~BUF_AGGR; |
1864 | /* | 1753 | /* |
1865 | * clear aggr bits for every descriptor | 1754 | * clear aggr bits for every descriptor |
1866 | * XXX TODO: is there a way to optimize it? | 1755 | * XXX TODO: is there a way to optimize it? |
@@ -1877,7 +1766,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, | |||
1877 | /* | 1766 | /* |
1878 | * setup first desc with rate and aggr info | 1767 | * setup first desc with rate and aggr info |
1879 | */ | 1768 | */ |
1880 | bf->bf_isaggr = 1; | 1769 | bf->bf_state.bf_type |= BUF_AGGR; |
1881 | ath_buf_set_rate(sc, bf); | 1770 | ath_buf_set_rate(sc, bf); |
1882 | ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, bf->bf_al); | 1771 | ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, bf->bf_al); |
1883 | 1772 | ||
@@ -1925,7 +1814,7 @@ static void ath_tid_drain(struct ath_softc *sc, | |||
1925 | list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list); | 1814 | list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list); |
1926 | 1815 | ||
1927 | /* update baw for software retried frame */ | 1816 | /* update baw for software retried frame */ |
1928 | if (bf->bf_isretried) | 1817 | if (bf_isretried(bf)) |
1929 | ath_tx_update_baw(sc, tid, bf->bf_seqno); | 1818 | ath_tx_update_baw(sc, tid, bf->bf_seqno); |
1930 | 1819 | ||
1931 | /* | 1820 | /* |
@@ -1990,13 +1879,18 @@ static int ath_tx_start_dma(struct ath_softc *sc, | |||
1990 | struct list_head bf_head; | 1879 | struct list_head bf_head; |
1991 | struct ath_desc *ds; | 1880 | struct ath_desc *ds; |
1992 | struct ath_hal *ah = sc->sc_ah; | 1881 | struct ath_hal *ah = sc->sc_ah; |
1993 | struct ath_txq *txq = &sc->sc_txq[txctl->qnum]; | 1882 | struct ath_txq *txq; |
1994 | struct ath_tx_info_priv *tx_info_priv; | 1883 | struct ath_tx_info_priv *tx_info_priv; |
1995 | struct ath_rc_series *rcs; | 1884 | struct ath_rc_series *rcs; |
1996 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 1885 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
1997 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1886 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1998 | __le16 fc = hdr->frame_control; | 1887 | __le16 fc = hdr->frame_control; |
1999 | 1888 | ||
1889 | if (unlikely(txctl->flags & ATH9K_TXDESC_CAB)) | ||
1890 | txq = sc->sc_cabq; | ||
1891 | else | ||
1892 | txq = &sc->sc_txq[txctl->qnum]; | ||
1893 | |||
2000 | /* For each sglist entry, allocate an ath_buf for DMA */ | 1894 | /* For each sglist entry, allocate an ath_buf for DMA */ |
2001 | INIT_LIST_HEAD(&bf_head); | 1895 | INIT_LIST_HEAD(&bf_head); |
2002 | spin_lock_bh(&sc->sc_txbuflock); | 1896 | spin_lock_bh(&sc->sc_txbuflock); |
@@ -2014,11 +1908,21 @@ static int ath_tx_start_dma(struct ath_softc *sc, | |||
2014 | /* set up this buffer */ | 1908 | /* set up this buffer */ |
2015 | ATH_TXBUF_RESET(bf); | 1909 | ATH_TXBUF_RESET(bf); |
2016 | bf->bf_frmlen = txctl->frmlen; | 1910 | bf->bf_frmlen = txctl->frmlen; |
2017 | bf->bf_isdata = ieee80211_is_data(fc); | 1911 | |
2018 | bf->bf_isbar = ieee80211_is_back_req(fc); | 1912 | ieee80211_is_data(fc) ? |
2019 | bf->bf_ispspoll = ieee80211_is_pspoll(fc); | 1913 | (bf->bf_state.bf_type |= BUF_DATA) : |
1914 | (bf->bf_state.bf_type &= ~BUF_DATA); | ||
1915 | ieee80211_is_back_req(fc) ? | ||
1916 | (bf->bf_state.bf_type |= BUF_BAR) : | ||
1917 | (bf->bf_state.bf_type &= ~BUF_BAR); | ||
1918 | ieee80211_is_pspoll(fc) ? | ||
1919 | (bf->bf_state.bf_type |= BUF_PSPOLL) : | ||
1920 | (bf->bf_state.bf_type &= ~BUF_PSPOLL); | ||
1921 | (sc->sc_flags & SC_OP_PREAMBLE_SHORT) ? | ||
1922 | (bf->bf_state.bf_type |= BUF_SHORT_PREAMBLE) : | ||
1923 | (bf->bf_state.bf_type &= ~BUF_SHORT_PREAMBLE); | ||
1924 | |||
2020 | bf->bf_flags = txctl->flags; | 1925 | bf->bf_flags = txctl->flags; |
2021 | bf->bf_shpreamble = sc->sc_flags & ATH_PREAMBLE_SHORT; | ||
2022 | bf->bf_keytype = txctl->keytype; | 1926 | bf->bf_keytype = txctl->keytype; |
2023 | tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; | 1927 | tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; |
2024 | rcs = tx_info_priv->rcs; | 1928 | rcs = tx_info_priv->rcs; |
@@ -2038,8 +1942,7 @@ static int ath_tx_start_dma(struct ath_softc *sc, | |||
2038 | /* | 1942 | /* |
2039 | * Save the DMA context in the first ath_buf | 1943 | * Save the DMA context in the first ath_buf |
2040 | */ | 1944 | */ |
2041 | copy_dma_mem_context(get_dma_mem_context(bf, bf_dmacontext), | 1945 | bf->bf_dmacontext = txctl->dmacontext; |
2042 | get_dma_mem_context(txctl, dmacontext)); | ||
2043 | 1946 | ||
2044 | /* | 1947 | /* |
2045 | * Formulate first tx descriptor with tx controls. | 1948 | * Formulate first tx descriptor with tx controls. |
@@ -2060,11 +1963,13 @@ static int ath_tx_start_dma(struct ath_softc *sc, | |||
2060 | ds); /* first descriptor */ | 1963 | ds); /* first descriptor */ |
2061 | 1964 | ||
2062 | bf->bf_lastfrm = bf; | 1965 | bf->bf_lastfrm = bf; |
2063 | bf->bf_ht = txctl->ht; | 1966 | (txctl->ht) ? |
1967 | (bf->bf_state.bf_type |= BUF_HT) : | ||
1968 | (bf->bf_state.bf_type &= ~BUF_HT); | ||
2064 | 1969 | ||
2065 | spin_lock_bh(&txq->axq_lock); | 1970 | spin_lock_bh(&txq->axq_lock); |
2066 | 1971 | ||
2067 | if (txctl->ht && sc->sc_txaggr) { | 1972 | if (txctl->ht && (sc->sc_flags & SC_OP_TXAGGR)) { |
2068 | struct ath_atx_tid *tid = ATH_AN_2_TID(an, txctl->tidno); | 1973 | struct ath_atx_tid *tid = ATH_AN_2_TID(an, txctl->tidno); |
2069 | if (ath_aggr_query(sc, an, txctl->tidno)) { | 1974 | if (ath_aggr_query(sc, an, txctl->tidno)) { |
2070 | /* | 1975 | /* |
@@ -2090,27 +1995,7 @@ static int ath_tx_start_dma(struct ath_softc *sc, | |||
2090 | bf->bf_tidno = txctl->tidno; | 1995 | bf->bf_tidno = txctl->tidno; |
2091 | } | 1996 | } |
2092 | 1997 | ||
2093 | if (is_multicast_ether_addr(hdr->addr1)) { | 1998 | ath_tx_txqaddbuf(sc, txq, &bf_head); |
2094 | struct ath_vap *avp = sc->sc_vaps[txctl->if_id]; | ||
2095 | |||
2096 | /* | ||
2097 | * When servicing one or more stations in power-save | ||
2098 | * mode (or) if there is some mcast data waiting on | ||
2099 | * mcast queue (to prevent out of order delivery of | ||
2100 | * mcast,bcast packets) multicast frames must be | ||
2101 | * buffered until after the beacon. We use the private | ||
2102 | * mcast queue for that. | ||
2103 | */ | ||
2104 | /* XXX? more bit in 802.11 frame header */ | ||
2105 | spin_lock_bh(&avp->av_mcastq.axq_lock); | ||
2106 | if (txctl->ps || avp->av_mcastq.axq_depth) | ||
2107 | ath_tx_mcastqaddbuf(sc, | ||
2108 | &avp->av_mcastq, &bf_head); | ||
2109 | else | ||
2110 | ath_tx_txqaddbuf(sc, txq, &bf_head); | ||
2111 | spin_unlock_bh(&avp->av_mcastq.axq_lock); | ||
2112 | } else | ||
2113 | ath_tx_txqaddbuf(sc, txq, &bf_head); | ||
2114 | } | 1999 | } |
2115 | spin_unlock_bh(&txq->axq_lock); | 2000 | spin_unlock_bh(&txq->axq_lock); |
2116 | return 0; | 2001 | return 0; |
@@ -2118,30 +2003,31 @@ static int ath_tx_start_dma(struct ath_softc *sc, | |||
2118 | 2003 | ||
2119 | static void xmit_map_sg(struct ath_softc *sc, | 2004 | static void xmit_map_sg(struct ath_softc *sc, |
2120 | struct sk_buff *skb, | 2005 | struct sk_buff *skb, |
2121 | dma_addr_t *pa, | ||
2122 | struct ath_tx_control *txctl) | 2006 | struct ath_tx_control *txctl) |
2123 | { | 2007 | { |
2124 | struct ath_xmit_status tx_status; | 2008 | struct ath_xmit_status tx_status; |
2125 | struct ath_atx_tid *tid; | 2009 | struct ath_atx_tid *tid; |
2126 | struct scatterlist sg; | 2010 | struct scatterlist sg; |
2127 | 2011 | ||
2128 | *pa = pci_map_single(sc->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); | 2012 | txctl->dmacontext = pci_map_single(sc->pdev, skb->data, |
2013 | skb->len, PCI_DMA_TODEVICE); | ||
2129 | 2014 | ||
2130 | /* setup S/G list */ | 2015 | /* setup S/G list */ |
2131 | memset(&sg, 0, sizeof(struct scatterlist)); | 2016 | memset(&sg, 0, sizeof(struct scatterlist)); |
2132 | sg_dma_address(&sg) = *pa; | 2017 | sg_dma_address(&sg) = txctl->dmacontext; |
2133 | sg_dma_len(&sg) = skb->len; | 2018 | sg_dma_len(&sg) = skb->len; |
2134 | 2019 | ||
2135 | if (ath_tx_start_dma(sc, skb, &sg, 1, txctl) != 0) { | 2020 | if (ath_tx_start_dma(sc, skb, &sg, 1, txctl) != 0) { |
2136 | /* | 2021 | /* |
2137 | * We have to do drop frame here. | 2022 | * We have to do drop frame here. |
2138 | */ | 2023 | */ |
2139 | pci_unmap_single(sc->pdev, *pa, skb->len, PCI_DMA_TODEVICE); | 2024 | pci_unmap_single(sc->pdev, txctl->dmacontext, |
2025 | skb->len, PCI_DMA_TODEVICE); | ||
2140 | 2026 | ||
2141 | tx_status.retries = 0; | 2027 | tx_status.retries = 0; |
2142 | tx_status.flags = ATH_TX_ERROR; | 2028 | tx_status.flags = ATH_TX_ERROR; |
2143 | 2029 | ||
2144 | if (txctl->ht && sc->sc_txaggr) { | 2030 | if (txctl->ht && (sc->sc_flags & SC_OP_TXAGGR)) { |
2145 | /* Reclaim the seqno. */ | 2031 | /* Reclaim the seqno. */ |
2146 | tid = ATH_AN_2_TID((struct ath_node *) | 2032 | tid = ATH_AN_2_TID((struct ath_node *) |
2147 | txctl->an, txctl->tidno); | 2033 | txctl->an, txctl->tidno); |
@@ -2162,7 +2048,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs) | |||
2162 | 2048 | ||
2163 | /* Setup tx descriptors */ | 2049 | /* Setup tx descriptors */ |
2164 | error = ath_descdma_setup(sc, &sc->sc_txdma, &sc->sc_txbuf, | 2050 | error = ath_descdma_setup(sc, &sc->sc_txdma, &sc->sc_txbuf, |
2165 | "tx", nbufs * ATH_FRAG_PER_MSDU, ATH_TXDESC); | 2051 | "tx", nbufs, 1); |
2166 | if (error != 0) { | 2052 | if (error != 0) { |
2167 | DPRINTF(sc, ATH_DBG_FATAL, | 2053 | DPRINTF(sc, ATH_DBG_FATAL, |
2168 | "%s: failed to allocate tx descriptors: %d\n", | 2054 | "%s: failed to allocate tx descriptors: %d\n", |
@@ -2403,6 +2289,7 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb) | |||
2403 | struct ath_tx_control txctl; | 2289 | struct ath_tx_control txctl; |
2404 | int error = 0; | 2290 | int error = 0; |
2405 | 2291 | ||
2292 | memset(&txctl, 0, sizeof(struct ath_tx_control)); | ||
2406 | error = ath_tx_prepare(sc, skb, &txctl); | 2293 | error = ath_tx_prepare(sc, skb, &txctl); |
2407 | if (error == 0) | 2294 | if (error == 0) |
2408 | /* | 2295 | /* |
@@ -2410,9 +2297,7 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb) | |||
2410 | * ath_tx_start_dma() will be called either synchronously | 2297 | * ath_tx_start_dma() will be called either synchronously |
2411 | * or asynchrounsly once DMA is complete. | 2298 | * or asynchrounsly once DMA is complete. |
2412 | */ | 2299 | */ |
2413 | xmit_map_sg(sc, skb, | 2300 | xmit_map_sg(sc, skb, &txctl); |
2414 | get_dma_mem_context(&txctl, dmacontext), | ||
2415 | &txctl); | ||
2416 | else | 2301 | else |
2417 | ath_node_put(sc, txctl.an, ATH9K_BH_STATUS_CHANGE); | 2302 | ath_node_put(sc, txctl.an, ATH9K_BH_STATUS_CHANGE); |
2418 | 2303 | ||
@@ -2424,8 +2309,7 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb) | |||
2424 | 2309 | ||
2425 | void ath_tx_tasklet(struct ath_softc *sc) | 2310 | void ath_tx_tasklet(struct ath_softc *sc) |
2426 | { | 2311 | { |
2427 | u64 tsf = ath9k_hw_gettsf64(sc->sc_ah); | 2312 | int i; |
2428 | int i, nacked = 0; | ||
2429 | u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1); | 2313 | u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1); |
2430 | 2314 | ||
2431 | ath9k_hw_gettxintrtxqs(sc->sc_ah, &qcumask); | 2315 | ath9k_hw_gettxintrtxqs(sc->sc_ah, &qcumask); |
@@ -2435,10 +2319,8 @@ void ath_tx_tasklet(struct ath_softc *sc) | |||
2435 | */ | 2319 | */ |
2436 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { | 2320 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { |
2437 | if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i))) | 2321 | if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i))) |
2438 | nacked += ath_tx_processq(sc, &sc->sc_txq[i]); | 2322 | ath_tx_processq(sc, &sc->sc_txq[i]); |
2439 | } | 2323 | } |
2440 | if (nacked) | ||
2441 | sc->sc_lastrx = tsf; | ||
2442 | } | 2324 | } |
2443 | 2325 | ||
2444 | void ath_tx_draintxq(struct ath_softc *sc, | 2326 | void ath_tx_draintxq(struct ath_softc *sc, |
@@ -2486,14 +2368,14 @@ void ath_tx_draintxq(struct ath_softc *sc, | |||
2486 | 2368 | ||
2487 | spin_unlock_bh(&txq->axq_lock); | 2369 | spin_unlock_bh(&txq->axq_lock); |
2488 | 2370 | ||
2489 | if (bf->bf_isampdu) | 2371 | if (bf_isampdu(bf)) |
2490 | ath_tx_complete_aggr_rifs(sc, txq, bf, &bf_head, 0); | 2372 | ath_tx_complete_aggr_rifs(sc, txq, bf, &bf_head, 0); |
2491 | else | 2373 | else |
2492 | ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); | 2374 | ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); |
2493 | } | 2375 | } |
2494 | 2376 | ||
2495 | /* flush any pending frames if aggregation is enabled */ | 2377 | /* flush any pending frames if aggregation is enabled */ |
2496 | if (sc->sc_txaggr) { | 2378 | if (sc->sc_flags & SC_OP_TXAGGR) { |
2497 | if (!retry_tx) { | 2379 | if (!retry_tx) { |
2498 | spin_lock_bh(&txq->axq_lock); | 2380 | spin_lock_bh(&txq->axq_lock); |
2499 | ath_txq_drain_pending_buffers(sc, txq, | 2381 | ath_txq_drain_pending_buffers(sc, txq, |
@@ -2509,7 +2391,7 @@ void ath_draintxq(struct ath_softc *sc, bool retry_tx) | |||
2509 | { | 2391 | { |
2510 | /* stop beacon queue. The beacon will be freed when | 2392 | /* stop beacon queue. The beacon will be freed when |
2511 | * we go to INIT state */ | 2393 | * we go to INIT state */ |
2512 | if (!sc->sc_invalid) { | 2394 | if (!(sc->sc_flags & SC_OP_INVALID)) { |
2513 | (void) ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq); | 2395 | (void) ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq); |
2514 | DPRINTF(sc, ATH_DBG_XMIT, "%s: beacon queue %x\n", __func__, | 2396 | DPRINTF(sc, ATH_DBG_XMIT, "%s: beacon queue %x\n", __func__, |
2515 | ath9k_hw_gettxbuf(sc->sc_ah, sc->sc_bhalq)); | 2397 | ath9k_hw_gettxbuf(sc->sc_ah, sc->sc_bhalq)); |
@@ -2536,7 +2418,7 @@ enum ATH_AGGR_CHECK ath_tx_aggr_check(struct ath_softc *sc, | |||
2536 | struct ath_atx_tid *txtid; | 2418 | struct ath_atx_tid *txtid; |
2537 | DECLARE_MAC_BUF(mac); | 2419 | DECLARE_MAC_BUF(mac); |
2538 | 2420 | ||
2539 | if (!sc->sc_txaggr) | 2421 | if (!(sc->sc_flags & SC_OP_TXAGGR)) |
2540 | return AGGR_NOT_REQUIRED; | 2422 | return AGGR_NOT_REQUIRED; |
2541 | 2423 | ||
2542 | /* ADDBA exchange must be completed before sending aggregates */ | 2424 | /* ADDBA exchange must be completed before sending aggregates */ |
@@ -2583,7 +2465,7 @@ int ath_tx_aggr_start(struct ath_softc *sc, | |||
2583 | return -1; | 2465 | return -1; |
2584 | } | 2466 | } |
2585 | 2467 | ||
2586 | if (sc->sc_txaggr) { | 2468 | if (sc->sc_flags & SC_OP_TXAGGR) { |
2587 | txtid = ATH_AN_2_TID(an, tid); | 2469 | txtid = ATH_AN_2_TID(an, tid); |
2588 | txtid->addba_exchangeinprogress = 1; | 2470 | txtid->addba_exchangeinprogress = 1; |
2589 | ath_tx_pause_tid(sc, txtid); | 2471 | ath_tx_pause_tid(sc, txtid); |
@@ -2647,7 +2529,7 @@ void ath_tx_aggr_teardown(struct ath_softc *sc, | |||
2647 | spin_lock_bh(&txq->axq_lock); | 2529 | spin_lock_bh(&txq->axq_lock); |
2648 | while (!list_empty(&txtid->buf_q)) { | 2530 | while (!list_empty(&txtid->buf_q)) { |
2649 | bf = list_first_entry(&txtid->buf_q, struct ath_buf, list); | 2531 | bf = list_first_entry(&txtid->buf_q, struct ath_buf, list); |
2650 | if (!bf->bf_isretried) { | 2532 | if (!bf_isretried(bf)) { |
2651 | /* | 2533 | /* |
2652 | * NB: it's based on the assumption that | 2534 | * NB: it's based on the assumption that |
2653 | * software retried frame will always stay | 2535 | * software retried frame will always stay |
@@ -2743,7 +2625,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) | |||
2743 | 2625 | ||
2744 | void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) | 2626 | void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) |
2745 | { | 2627 | { |
2746 | if (sc->sc_txaggr) { | 2628 | if (sc->sc_flags & SC_OP_TXAGGR) { |
2747 | struct ath_atx_tid *tid; | 2629 | struct ath_atx_tid *tid; |
2748 | struct ath_atx_ac *ac; | 2630 | struct ath_atx_ac *ac; |
2749 | int tidno, acno; | 2631 | int tidno, acno; |
@@ -2855,7 +2737,7 @@ void ath_tx_node_cleanup(struct ath_softc *sc, | |||
2855 | 2737 | ||
2856 | void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an) | 2738 | void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an) |
2857 | { | 2739 | { |
2858 | if (sc->sc_txaggr) { | 2740 | if (sc->sc_flags & SC_OP_TXAGGR) { |
2859 | struct ath_atx_tid *tid; | 2741 | struct ath_atx_tid *tid; |
2860 | int tidno, i; | 2742 | int tidno, i; |
2861 | 2743 | ||
@@ -2869,3 +2751,57 @@ void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an) | |||
2869 | } | 2751 | } |
2870 | } | 2752 | } |
2871 | } | 2753 | } |
2754 | |||
2755 | void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb) | ||
2756 | { | ||
2757 | int hdrlen, padsize; | ||
2758 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
2759 | struct ath_tx_control txctl; | ||
2760 | |||
2761 | /* | ||
2762 | * As a temporary workaround, assign seq# here; this will likely need | ||
2763 | * to be cleaned up to work better with Beacon transmission and virtual | ||
2764 | * BSSes. | ||
2765 | */ | ||
2766 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | ||
2767 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
2768 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) | ||
2769 | sc->seq_no += 0x10; | ||
2770 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
2771 | hdr->seq_ctrl |= cpu_to_le16(sc->seq_no); | ||
2772 | } | ||
2773 | |||
2774 | /* Add the padding after the header if this is not already done */ | ||
2775 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | ||
2776 | if (hdrlen & 3) { | ||
2777 | padsize = hdrlen % 4; | ||
2778 | if (skb_headroom(skb) < padsize) { | ||
2779 | DPRINTF(sc, ATH_DBG_XMIT, "%s: TX CABQ padding " | ||
2780 | "failed\n", __func__); | ||
2781 | dev_kfree_skb_any(skb); | ||
2782 | return; | ||
2783 | } | ||
2784 | skb_push(skb, padsize); | ||
2785 | memmove(skb->data, skb->data + padsize, hdrlen); | ||
2786 | } | ||
2787 | |||
2788 | DPRINTF(sc, ATH_DBG_XMIT, "%s: transmitting CABQ packet, skb: %p\n", | ||
2789 | __func__, | ||
2790 | skb); | ||
2791 | |||
2792 | memset(&txctl, 0, sizeof(struct ath_tx_control)); | ||
2793 | txctl.flags = ATH9K_TXDESC_CAB; | ||
2794 | if (ath_tx_prepare(sc, skb, &txctl) == 0) { | ||
2795 | /* | ||
2796 | * Start DMA mapping. | ||
2797 | * ath_tx_start_dma() will be called either synchronously | ||
2798 | * or asynchrounsly once DMA is complete. | ||
2799 | */ | ||
2800 | xmit_map_sg(sc, skb, &txctl); | ||
2801 | } else { | ||
2802 | ath_node_put(sc, txctl.an, ATH9K_BH_STATUS_CHANGE); | ||
2803 | DPRINTF(sc, ATH_DBG_XMIT, "%s: TX CABQ failed\n", __func__); | ||
2804 | dev_kfree_skb_any(skb); | ||
2805 | } | ||
2806 | } | ||
2807 | |||
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile index 8c52b0b9862a..fb6ffce03f0a 100644 --- a/drivers/net/wireless/b43/Makefile +++ b/drivers/net/wireless/b43/Makefile | |||
@@ -1,7 +1,9 @@ | |||
1 | b43-y += main.o | 1 | b43-y += main.o |
2 | b43-y += tables.o | 2 | b43-y += tables.o |
3 | b43-$(CONFIG_B43_NPHY) += tables_nphy.o | 3 | b43-$(CONFIG_B43_NPHY) += tables_nphy.o |
4 | b43-y += phy.o | 4 | b43-y += phy_common.o |
5 | b43-y += phy_g.o | ||
6 | b43-y += phy_a.o | ||
5 | b43-$(CONFIG_B43_NPHY) += nphy.o | 7 | b43-$(CONFIG_B43_NPHY) += nphy.o |
6 | b43-y += sysfs.o | 8 | b43-y += sysfs.o |
7 | b43-y += xmit.o | 9 | b43-y += xmit.o |
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index edcdfa366452..f9c8161671d9 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -12,7 +12,7 @@ | |||
12 | #include "leds.h" | 12 | #include "leds.h" |
13 | #include "rfkill.h" | 13 | #include "rfkill.h" |
14 | #include "lo.h" | 14 | #include "lo.h" |
15 | #include "phy.h" | 15 | #include "phy_common.h" |
16 | 16 | ||
17 | 17 | ||
18 | /* The unique identifier of the firmware that's officially supported by | 18 | /* The unique identifier of the firmware that's officially supported by |
@@ -173,6 +173,11 @@ enum { | |||
173 | #define B43_SHM_SH_CHAN 0x00A0 /* Current channel (low 8bit only) */ | 173 | #define B43_SHM_SH_CHAN 0x00A0 /* Current channel (low 8bit only) */ |
174 | #define B43_SHM_SH_CHAN_5GHZ 0x0100 /* Bit set, if 5Ghz channel */ | 174 | #define B43_SHM_SH_CHAN_5GHZ 0x0100 /* Bit set, if 5Ghz channel */ |
175 | #define B43_SHM_SH_BCMCFIFOID 0x0108 /* Last posted cookie to the bcast/mcast FIFO */ | 175 | #define B43_SHM_SH_BCMCFIFOID 0x0108 /* Last posted cookie to the bcast/mcast FIFO */ |
176 | /* TSSI information */ | ||
177 | #define B43_SHM_SH_TSSI_CCK 0x0058 /* TSSI for last 4 CCK frames (32bit) */ | ||
178 | #define B43_SHM_SH_TSSI_OFDM_A 0x0068 /* TSSI for last 4 OFDM frames (32bit) */ | ||
179 | #define B43_SHM_SH_TSSI_OFDM_G 0x0070 /* TSSI for last 4 OFDM frames (32bit) */ | ||
180 | #define B43_TSSI_MAX 0x7F /* Max value for one TSSI value */ | ||
176 | /* SHM_SHARED TX FIFO variables */ | 181 | /* SHM_SHARED TX FIFO variables */ |
177 | #define B43_SHM_SH_SIZE01 0x0098 /* TX FIFO size for FIFO 0 (low) and 1 (high) */ | 182 | #define B43_SHM_SH_SIZE01 0x0098 /* TX FIFO size for FIFO 0 (low) and 1 (high) */ |
178 | #define B43_SHM_SH_SIZE23 0x009A /* TX FIFO size for FIFO 2 and 3 */ | 183 | #define B43_SHM_SH_SIZE23 0x009A /* TX FIFO size for FIFO 2 and 3 */ |
@@ -508,122 +513,6 @@ struct b43_iv { | |||
508 | } __attribute__((__packed__)); | 513 | } __attribute__((__packed__)); |
509 | 514 | ||
510 | 515 | ||
511 | struct b43_phy { | ||
512 | /* Band support flags. */ | ||
513 | bool supports_2ghz; | ||
514 | bool supports_5ghz; | ||
515 | |||
516 | /* GMODE bit enabled? */ | ||
517 | bool gmode; | ||
518 | |||
519 | /* Analog Type */ | ||
520 | u8 analog; | ||
521 | /* B43_PHYTYPE_ */ | ||
522 | u8 type; | ||
523 | /* PHY revision number. */ | ||
524 | u8 rev; | ||
525 | |||
526 | /* Radio versioning */ | ||
527 | u16 radio_manuf; /* Radio manufacturer */ | ||
528 | u16 radio_ver; /* Radio version */ | ||
529 | u8 radio_rev; /* Radio revision */ | ||
530 | |||
531 | bool dyn_tssi_tbl; /* tssi2dbm is kmalloc()ed. */ | ||
532 | |||
533 | /* ACI (adjacent channel interference) flags. */ | ||
534 | bool aci_enable; | ||
535 | bool aci_wlan_automatic; | ||
536 | bool aci_hw_rssi; | ||
537 | |||
538 | /* Radio switched on/off */ | ||
539 | bool radio_on; | ||
540 | struct { | ||
541 | /* Values saved when turning the radio off. | ||
542 | * They are needed when turning it on again. */ | ||
543 | bool valid; | ||
544 | u16 rfover; | ||
545 | u16 rfoverval; | ||
546 | } radio_off_context; | ||
547 | |||
548 | u16 minlowsig[2]; | ||
549 | u16 minlowsigpos[2]; | ||
550 | |||
551 | /* TSSI to dBm table in use */ | ||
552 | const s8 *tssi2dbm; | ||
553 | /* Target idle TSSI */ | ||
554 | int tgt_idle_tssi; | ||
555 | /* Current idle TSSI */ | ||
556 | int cur_idle_tssi; | ||
557 | |||
558 | /* LocalOscillator control values. */ | ||
559 | struct b43_txpower_lo_control *lo_control; | ||
560 | /* Values from b43_calc_loopback_gain() */ | ||
561 | s16 max_lb_gain; /* Maximum Loopback gain in hdB */ | ||
562 | s16 trsw_rx_gain; /* TRSW RX gain in hdB */ | ||
563 | s16 lna_lod_gain; /* LNA lod */ | ||
564 | s16 lna_gain; /* LNA */ | ||
565 | s16 pga_gain; /* PGA */ | ||
566 | |||
567 | /* Desired TX power level (in dBm). | ||
568 | * This is set by the user and adjusted in b43_phy_xmitpower(). */ | ||
569 | u8 power_level; | ||
570 | /* A-PHY TX Power control value. */ | ||
571 | u16 txpwr_offset; | ||
572 | |||
573 | /* Current TX power level attenuation control values */ | ||
574 | struct b43_bbatt bbatt; | ||
575 | struct b43_rfatt rfatt; | ||
576 | u8 tx_control; /* B43_TXCTL_XXX */ | ||
577 | |||
578 | /* Hardware Power Control enabled? */ | ||
579 | bool hardware_power_control; | ||
580 | |||
581 | /* Current Interference Mitigation mode */ | ||
582 | int interfmode; | ||
583 | /* Stack of saved values from the Interference Mitigation code. | ||
584 | * Each value in the stack is layed out as follows: | ||
585 | * bit 0-11: offset | ||
586 | * bit 12-15: register ID | ||
587 | * bit 16-32: value | ||
588 | * register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT | ||
589 | */ | ||
590 | #define B43_INTERFSTACK_SIZE 26 | ||
591 | u32 interfstack[B43_INTERFSTACK_SIZE]; //FIXME: use a data structure | ||
592 | |||
593 | /* Saved values from the NRSSI Slope calculation */ | ||
594 | s16 nrssi[2]; | ||
595 | s32 nrssislope; | ||
596 | /* In memory nrssi lookup table. */ | ||
597 | s8 nrssi_lt[64]; | ||
598 | |||
599 | /* current channel */ | ||
600 | u8 channel; | ||
601 | |||
602 | u16 lofcal; | ||
603 | |||
604 | u16 initval; //FIXME rename? | ||
605 | |||
606 | /* PHY TX errors counter. */ | ||
607 | atomic_t txerr_cnt; | ||
608 | |||
609 | /* The device does address auto increment for the OFDM tables. | ||
610 | * We cache the previously used address here and omit the address | ||
611 | * write on the next table access, if possible. */ | ||
612 | u16 ofdmtab_addr; /* The address currently set in hardware. */ | ||
613 | enum { /* The last data flow direction. */ | ||
614 | B43_OFDMTAB_DIRECTION_UNKNOWN = 0, | ||
615 | B43_OFDMTAB_DIRECTION_READ, | ||
616 | B43_OFDMTAB_DIRECTION_WRITE, | ||
617 | } ofdmtab_addr_direction; | ||
618 | |||
619 | #if B43_DEBUG | ||
620 | /* Manual TX-power control enabled? */ | ||
621 | bool manual_txpower_control; | ||
622 | /* PHY registers locked by b43_phy_lock()? */ | ||
623 | bool phy_locked; | ||
624 | #endif /* B43_DEBUG */ | ||
625 | }; | ||
626 | |||
627 | /* Data structures for DMA transmission, per 80211 core. */ | 516 | /* Data structures for DMA transmission, per 80211 core. */ |
628 | struct b43_dma { | 517 | struct b43_dma { |
629 | struct b43_dmaring *tx_ring_AC_BK; /* Background */ | 518 | struct b43_dmaring *tx_ring_AC_BK; /* Background */ |
@@ -764,6 +653,11 @@ struct b43_wl { | |||
764 | struct b43_qos_params qos_params[4]; | 653 | struct b43_qos_params qos_params[4]; |
765 | /* Workqueue for updating QOS parameters in hardware. */ | 654 | /* Workqueue for updating QOS parameters in hardware. */ |
766 | struct work_struct qos_update_work; | 655 | struct work_struct qos_update_work; |
656 | |||
657 | /* Work for adjustment of the transmission power. | ||
658 | * This is scheduled when we determine that the actual TX output | ||
659 | * power doesn't match what we want. */ | ||
660 | struct work_struct txpower_adjust_work; | ||
767 | }; | 661 | }; |
768 | 662 | ||
769 | /* In-memory representation of a cached microcode file. */ | 663 | /* In-memory representation of a cached microcode file. */ |
@@ -908,6 +802,15 @@ static inline int b43_is_mode(struct b43_wl *wl, int type) | |||
908 | return (wl->operating && wl->if_type == type); | 802 | return (wl->operating && wl->if_type == type); |
909 | } | 803 | } |
910 | 804 | ||
805 | /** | ||
806 | * b43_current_band - Returns the currently used band. | ||
807 | * Returns one of IEEE80211_BAND_2GHZ and IEEE80211_BAND_5GHZ. | ||
808 | */ | ||
809 | static inline enum ieee80211_band b43_current_band(struct b43_wl *wl) | ||
810 | { | ||
811 | return wl->hw->conf.channel->band; | ||
812 | } | ||
813 | |||
911 | static inline u16 b43_read16(struct b43_wldev *dev, u16 offset) | 814 | static inline u16 b43_read16(struct b43_wldev *dev, u16 offset) |
912 | { | 815 | { |
913 | return ssb_read16(dev->dev, offset); | 816 | return ssb_read16(dev->dev, offset); |
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c index 29851bc1101f..06a01da80160 100644 --- a/drivers/net/wireless/b43/debugfs.c +++ b/drivers/net/wireless/b43/debugfs.c | |||
@@ -443,76 +443,6 @@ out_unlock: | |||
443 | return count; | 443 | return count; |
444 | } | 444 | } |
445 | 445 | ||
446 | static ssize_t txpower_g_read_file(struct b43_wldev *dev, | ||
447 | char *buf, size_t bufsize) | ||
448 | { | ||
449 | ssize_t count = 0; | ||
450 | |||
451 | if (dev->phy.type != B43_PHYTYPE_G) { | ||
452 | fappend("Device is not a G-PHY\n"); | ||
453 | goto out; | ||
454 | } | ||
455 | fappend("Control: %s\n", dev->phy.manual_txpower_control ? | ||
456 | "MANUAL" : "AUTOMATIC"); | ||
457 | fappend("Baseband attenuation: %u\n", dev->phy.bbatt.att); | ||
458 | fappend("Radio attenuation: %u\n", dev->phy.rfatt.att); | ||
459 | fappend("TX Mixer Gain: %s\n", | ||
460 | (dev->phy.tx_control & B43_TXCTL_TXMIX) ? "ON" : "OFF"); | ||
461 | fappend("PA Gain 2dB: %s\n", | ||
462 | (dev->phy.tx_control & B43_TXCTL_PA2DB) ? "ON" : "OFF"); | ||
463 | fappend("PA Gain 3dB: %s\n", | ||
464 | (dev->phy.tx_control & B43_TXCTL_PA3DB) ? "ON" : "OFF"); | ||
465 | fappend("\n\n"); | ||
466 | fappend("You can write to this file:\n"); | ||
467 | fappend("Writing \"auto\" enables automatic txpower control.\n"); | ||
468 | fappend | ||
469 | ("Writing the attenuation values as \"bbatt rfatt txmix pa2db pa3db\" " | ||
470 | "enables manual txpower control.\n"); | ||
471 | fappend("Example: 5 4 0 0 1\n"); | ||
472 | fappend("Enables manual control with Baseband attenuation 5, " | ||
473 | "Radio attenuation 4, No TX Mixer Gain, " | ||
474 | "No PA Gain 2dB, With PA Gain 3dB.\n"); | ||
475 | out: | ||
476 | return count; | ||
477 | } | ||
478 | |||
479 | static int txpower_g_write_file(struct b43_wldev *dev, | ||
480 | const char *buf, size_t count) | ||
481 | { | ||
482 | if (dev->phy.type != B43_PHYTYPE_G) | ||
483 | return -ENODEV; | ||
484 | if ((count >= 4) && (memcmp(buf, "auto", 4) == 0)) { | ||
485 | /* Automatic control */ | ||
486 | dev->phy.manual_txpower_control = 0; | ||
487 | b43_phy_xmitpower(dev); | ||
488 | } else { | ||
489 | int bbatt = 0, rfatt = 0, txmix = 0, pa2db = 0, pa3db = 0; | ||
490 | /* Manual control */ | ||
491 | if (sscanf(buf, "%d %d %d %d %d", &bbatt, &rfatt, | ||
492 | &txmix, &pa2db, &pa3db) != 5) | ||
493 | return -EINVAL; | ||
494 | b43_put_attenuation_into_ranges(dev, &bbatt, &rfatt); | ||
495 | dev->phy.manual_txpower_control = 1; | ||
496 | dev->phy.bbatt.att = bbatt; | ||
497 | dev->phy.rfatt.att = rfatt; | ||
498 | dev->phy.tx_control = 0; | ||
499 | if (txmix) | ||
500 | dev->phy.tx_control |= B43_TXCTL_TXMIX; | ||
501 | if (pa2db) | ||
502 | dev->phy.tx_control |= B43_TXCTL_PA2DB; | ||
503 | if (pa3db) | ||
504 | dev->phy.tx_control |= B43_TXCTL_PA3DB; | ||
505 | b43_phy_lock(dev); | ||
506 | b43_radio_lock(dev); | ||
507 | b43_set_txpower_g(dev, &dev->phy.bbatt, | ||
508 | &dev->phy.rfatt, dev->phy.tx_control); | ||
509 | b43_radio_unlock(dev); | ||
510 | b43_phy_unlock(dev); | ||
511 | } | ||
512 | |||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | /* wl->irq_lock is locked */ | 446 | /* wl->irq_lock is locked */ |
517 | static int restart_write_file(struct b43_wldev *dev, | 447 | static int restart_write_file(struct b43_wldev *dev, |
518 | const char *buf, size_t count) | 448 | const char *buf, size_t count) |
@@ -560,7 +490,7 @@ static ssize_t loctls_read_file(struct b43_wldev *dev, | |||
560 | err = -ENODEV; | 490 | err = -ENODEV; |
561 | goto out; | 491 | goto out; |
562 | } | 492 | } |
563 | lo = phy->lo_control; | 493 | lo = phy->g->lo_control; |
564 | fappend("-- Local Oscillator calibration data --\n\n"); | 494 | fappend("-- Local Oscillator calibration data --\n\n"); |
565 | fappend("HW-power-control enabled: %d\n", | 495 | fappend("HW-power-control enabled: %d\n", |
566 | dev->phy.hardware_power_control); | 496 | dev->phy.hardware_power_control); |
@@ -578,8 +508,8 @@ static ssize_t loctls_read_file(struct b43_wldev *dev, | |||
578 | list_for_each_entry(cal, &lo->calib_list, list) { | 508 | list_for_each_entry(cal, &lo->calib_list, list) { |
579 | bool active; | 509 | bool active; |
580 | 510 | ||
581 | active = (b43_compare_bbatt(&cal->bbatt, &phy->bbatt) && | 511 | active = (b43_compare_bbatt(&cal->bbatt, &phy->g->bbatt) && |
582 | b43_compare_rfatt(&cal->rfatt, &phy->rfatt)); | 512 | b43_compare_rfatt(&cal->rfatt, &phy->g->rfatt)); |
583 | fappend("BB(%d), RF(%d,%d) -> I=%d, Q=%d " | 513 | fappend("BB(%d), RF(%d,%d) -> I=%d, Q=%d " |
584 | "(expires in %lu sec)%s\n", | 514 | "(expires in %lu sec)%s\n", |
585 | cal->bbatt.att, | 515 | cal->bbatt.att, |
@@ -763,7 +693,6 @@ B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file, 1); | |||
763 | B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file, 1); | 693 | B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file, 1); |
764 | B43_DEBUGFS_FOPS(tsf, tsf_read_file, tsf_write_file, 1); | 694 | B43_DEBUGFS_FOPS(tsf, tsf_read_file, tsf_write_file, 1); |
765 | B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL, 0); | 695 | B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL, 0); |
766 | B43_DEBUGFS_FOPS(txpower_g, txpower_g_read_file, txpower_g_write_file, 0); | ||
767 | B43_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1); | 696 | B43_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1); |
768 | B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL, 0); | 697 | B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL, 0); |
769 | 698 | ||
@@ -877,7 +806,6 @@ void b43_debugfs_add_device(struct b43_wldev *dev) | |||
877 | ADD_FILE(mmio32write, 0200); | 806 | ADD_FILE(mmio32write, 0200); |
878 | ADD_FILE(tsf, 0600); | 807 | ADD_FILE(tsf, 0600); |
879 | ADD_FILE(txstat, 0400); | 808 | ADD_FILE(txstat, 0400); |
880 | ADD_FILE(txpower_g, 0600); | ||
881 | ADD_FILE(restart, 0200); | 809 | ADD_FILE(restart, 0200); |
882 | ADD_FILE(loctls, 0400); | 810 | ADD_FILE(loctls, 0400); |
883 | 811 | ||
@@ -907,7 +835,6 @@ void b43_debugfs_remove_device(struct b43_wldev *dev) | |||
907 | debugfs_remove(e->file_mmio32write.dentry); | 835 | debugfs_remove(e->file_mmio32write.dentry); |
908 | debugfs_remove(e->file_tsf.dentry); | 836 | debugfs_remove(e->file_tsf.dentry); |
909 | debugfs_remove(e->file_txstat.dentry); | 837 | debugfs_remove(e->file_txstat.dentry); |
910 | debugfs_remove(e->file_txpower_g.dentry); | ||
911 | debugfs_remove(e->file_restart.dentry); | 838 | debugfs_remove(e->file_restart.dentry); |
912 | debugfs_remove(e->file_loctls.dentry); | 839 | debugfs_remove(e->file_loctls.dentry); |
913 | 840 | ||
diff --git a/drivers/net/wireless/b43/lo.c b/drivers/net/wireless/b43/lo.c index 9c854d6aae36..6a18a1470465 100644 --- a/drivers/net/wireless/b43/lo.c +++ b/drivers/net/wireless/b43/lo.c | |||
@@ -29,7 +29,7 @@ | |||
29 | 29 | ||
30 | #include "b43.h" | 30 | #include "b43.h" |
31 | #include "lo.h" | 31 | #include "lo.h" |
32 | #include "phy.h" | 32 | #include "phy_g.h" |
33 | #include "main.h" | 33 | #include "main.h" |
34 | 34 | ||
35 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
@@ -174,7 +174,8 @@ static u16 lo_txctl_register_table(struct b43_wldev *dev, | |||
174 | static void lo_measure_txctl_values(struct b43_wldev *dev) | 174 | static void lo_measure_txctl_values(struct b43_wldev *dev) |
175 | { | 175 | { |
176 | struct b43_phy *phy = &dev->phy; | 176 | struct b43_phy *phy = &dev->phy; |
177 | struct b43_txpower_lo_control *lo = phy->lo_control; | 177 | struct b43_phy_g *gphy = phy->g; |
178 | struct b43_txpower_lo_control *lo = gphy->lo_control; | ||
178 | u16 reg, mask; | 179 | u16 reg, mask; |
179 | u16 trsw_rx, pga; | 180 | u16 trsw_rx, pga; |
180 | u16 radio_pctl_reg; | 181 | u16 radio_pctl_reg; |
@@ -195,7 +196,7 @@ static void lo_measure_txctl_values(struct b43_wldev *dev) | |||
195 | int lb_gain; /* Loopback gain (in dB) */ | 196 | int lb_gain; /* Loopback gain (in dB) */ |
196 | 197 | ||
197 | trsw_rx = 0; | 198 | trsw_rx = 0; |
198 | lb_gain = phy->max_lb_gain / 2; | 199 | lb_gain = gphy->max_lb_gain / 2; |
199 | if (lb_gain > 10) { | 200 | if (lb_gain > 10) { |
200 | radio_pctl_reg = 0; | 201 | radio_pctl_reg = 0; |
201 | pga = abs(10 - lb_gain) / 6; | 202 | pga = abs(10 - lb_gain) / 6; |
@@ -226,7 +227,7 @@ static void lo_measure_txctl_values(struct b43_wldev *dev) | |||
226 | } | 227 | } |
227 | b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43) | 228 | b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43) |
228 | & 0xFFF0) | radio_pctl_reg); | 229 | & 0xFFF0) | radio_pctl_reg); |
229 | b43_phy_set_baseband_attenuation(dev, 2); | 230 | b43_gphy_set_baseband_attenuation(dev, 2); |
230 | 231 | ||
231 | reg = lo_txctl_register_table(dev, &mask, NULL); | 232 | reg = lo_txctl_register_table(dev, &mask, NULL); |
232 | mask = ~mask; | 233 | mask = ~mask; |
@@ -277,7 +278,8 @@ static void lo_measure_txctl_values(struct b43_wldev *dev) | |||
277 | static void lo_read_power_vector(struct b43_wldev *dev) | 278 | static void lo_read_power_vector(struct b43_wldev *dev) |
278 | { | 279 | { |
279 | struct b43_phy *phy = &dev->phy; | 280 | struct b43_phy *phy = &dev->phy; |
280 | struct b43_txpower_lo_control *lo = phy->lo_control; | 281 | struct b43_phy_g *gphy = phy->g; |
282 | struct b43_txpower_lo_control *lo = gphy->lo_control; | ||
281 | int i; | 283 | int i; |
282 | u64 tmp; | 284 | u64 tmp; |
283 | u64 power_vector = 0; | 285 | u64 power_vector = 0; |
@@ -298,6 +300,7 @@ static void lo_measure_gain_values(struct b43_wldev *dev, | |||
298 | s16 max_rx_gain, int use_trsw_rx) | 300 | s16 max_rx_gain, int use_trsw_rx) |
299 | { | 301 | { |
300 | struct b43_phy *phy = &dev->phy; | 302 | struct b43_phy *phy = &dev->phy; |
303 | struct b43_phy_g *gphy = phy->g; | ||
301 | u16 tmp; | 304 | u16 tmp; |
302 | 305 | ||
303 | if (max_rx_gain < 0) | 306 | if (max_rx_gain < 0) |
@@ -308,7 +311,7 @@ static void lo_measure_gain_values(struct b43_wldev *dev, | |||
308 | int trsw_rx_gain; | 311 | int trsw_rx_gain; |
309 | 312 | ||
310 | if (use_trsw_rx) { | 313 | if (use_trsw_rx) { |
311 | trsw_rx_gain = phy->trsw_rx_gain / 2; | 314 | trsw_rx_gain = gphy->trsw_rx_gain / 2; |
312 | if (max_rx_gain >= trsw_rx_gain) { | 315 | if (max_rx_gain >= trsw_rx_gain) { |
313 | trsw_rx_gain = max_rx_gain - trsw_rx_gain; | 316 | trsw_rx_gain = max_rx_gain - trsw_rx_gain; |
314 | trsw_rx = 0x20; | 317 | trsw_rx = 0x20; |
@@ -316,38 +319,38 @@ static void lo_measure_gain_values(struct b43_wldev *dev, | |||
316 | } else | 319 | } else |
317 | trsw_rx_gain = max_rx_gain; | 320 | trsw_rx_gain = max_rx_gain; |
318 | if (trsw_rx_gain < 9) { | 321 | if (trsw_rx_gain < 9) { |
319 | phy->lna_lod_gain = 0; | 322 | gphy->lna_lod_gain = 0; |
320 | } else { | 323 | } else { |
321 | phy->lna_lod_gain = 1; | 324 | gphy->lna_lod_gain = 1; |
322 | trsw_rx_gain -= 8; | 325 | trsw_rx_gain -= 8; |
323 | } | 326 | } |
324 | trsw_rx_gain = clamp_val(trsw_rx_gain, 0, 0x2D); | 327 | trsw_rx_gain = clamp_val(trsw_rx_gain, 0, 0x2D); |
325 | phy->pga_gain = trsw_rx_gain / 3; | 328 | gphy->pga_gain = trsw_rx_gain / 3; |
326 | if (phy->pga_gain >= 5) { | 329 | if (gphy->pga_gain >= 5) { |
327 | phy->pga_gain -= 5; | 330 | gphy->pga_gain -= 5; |
328 | phy->lna_gain = 2; | 331 | gphy->lna_gain = 2; |
329 | } else | 332 | } else |
330 | phy->lna_gain = 0; | 333 | gphy->lna_gain = 0; |
331 | } else { | 334 | } else { |
332 | phy->lna_gain = 0; | 335 | gphy->lna_gain = 0; |
333 | phy->trsw_rx_gain = 0x20; | 336 | gphy->trsw_rx_gain = 0x20; |
334 | if (max_rx_gain >= 0x14) { | 337 | if (max_rx_gain >= 0x14) { |
335 | phy->lna_lod_gain = 1; | 338 | gphy->lna_lod_gain = 1; |
336 | phy->pga_gain = 2; | 339 | gphy->pga_gain = 2; |
337 | } else if (max_rx_gain >= 0x12) { | 340 | } else if (max_rx_gain >= 0x12) { |
338 | phy->lna_lod_gain = 1; | 341 | gphy->lna_lod_gain = 1; |
339 | phy->pga_gain = 1; | 342 | gphy->pga_gain = 1; |
340 | } else if (max_rx_gain >= 0xF) { | 343 | } else if (max_rx_gain >= 0xF) { |
341 | phy->lna_lod_gain = 1; | 344 | gphy->lna_lod_gain = 1; |
342 | phy->pga_gain = 0; | 345 | gphy->pga_gain = 0; |
343 | } else { | 346 | } else { |
344 | phy->lna_lod_gain = 0; | 347 | gphy->lna_lod_gain = 0; |
345 | phy->pga_gain = 0; | 348 | gphy->pga_gain = 0; |
346 | } | 349 | } |
347 | } | 350 | } |
348 | 351 | ||
349 | tmp = b43_radio_read16(dev, 0x7A); | 352 | tmp = b43_radio_read16(dev, 0x7A); |
350 | if (phy->lna_lod_gain == 0) | 353 | if (gphy->lna_lod_gain == 0) |
351 | tmp &= ~0x0008; | 354 | tmp &= ~0x0008; |
352 | else | 355 | else |
353 | tmp |= 0x0008; | 356 | tmp |= 0x0008; |
@@ -392,10 +395,11 @@ static void lo_measure_setup(struct b43_wldev *dev, | |||
392 | { | 395 | { |
393 | struct ssb_sprom *sprom = &dev->dev->bus->sprom; | 396 | struct ssb_sprom *sprom = &dev->dev->bus->sprom; |
394 | struct b43_phy *phy = &dev->phy; | 397 | struct b43_phy *phy = &dev->phy; |
395 | struct b43_txpower_lo_control *lo = phy->lo_control; | 398 | struct b43_phy_g *gphy = phy->g; |
399 | struct b43_txpower_lo_control *lo = gphy->lo_control; | ||
396 | u16 tmp; | 400 | u16 tmp; |
397 | 401 | ||
398 | if (b43_has_hardware_pctl(phy)) { | 402 | if (b43_has_hardware_pctl(dev)) { |
399 | sav->phy_lo_mask = b43_phy_read(dev, B43_PHY_LO_MASK); | 403 | sav->phy_lo_mask = b43_phy_read(dev, B43_PHY_LO_MASK); |
400 | sav->phy_extg_01 = b43_phy_read(dev, B43_PHY_EXTG(0x01)); | 404 | sav->phy_extg_01 = b43_phy_read(dev, B43_PHY_EXTG(0x01)); |
401 | sav->phy_dacctl_hwpctl = b43_phy_read(dev, B43_PHY_DACCTL); | 405 | sav->phy_dacctl_hwpctl = b43_phy_read(dev, B43_PHY_DACCTL); |
@@ -496,7 +500,7 @@ static void lo_measure_setup(struct b43_wldev *dev, | |||
496 | b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x0802); | 500 | b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x0802); |
497 | if (phy->rev >= 2) | 501 | if (phy->rev >= 2) |
498 | b43_dummy_transmission(dev); | 502 | b43_dummy_transmission(dev); |
499 | b43_radio_selectchannel(dev, 6, 0); | 503 | b43_gphy_channel_switch(dev, 6, 0); |
500 | b43_radio_read16(dev, 0x51); /* dummy read */ | 504 | b43_radio_read16(dev, 0x51); /* dummy read */ |
501 | if (phy->type == B43_PHYTYPE_G) | 505 | if (phy->type == B43_PHYTYPE_G) |
502 | b43_phy_write(dev, B43_PHY_CCK(0x2F), 0); | 506 | b43_phy_write(dev, B43_PHY_CCK(0x2F), 0); |
@@ -520,18 +524,19 @@ static void lo_measure_restore(struct b43_wldev *dev, | |||
520 | struct lo_g_saved_values *sav) | 524 | struct lo_g_saved_values *sav) |
521 | { | 525 | { |
522 | struct b43_phy *phy = &dev->phy; | 526 | struct b43_phy *phy = &dev->phy; |
527 | struct b43_phy_g *gphy = phy->g; | ||
523 | u16 tmp; | 528 | u16 tmp; |
524 | 529 | ||
525 | if (phy->rev >= 2) { | 530 | if (phy->rev >= 2) { |
526 | b43_phy_write(dev, B43_PHY_PGACTL, 0xE300); | 531 | b43_phy_write(dev, B43_PHY_PGACTL, 0xE300); |
527 | tmp = (phy->pga_gain << 8); | 532 | tmp = (gphy->pga_gain << 8); |
528 | b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA0); | 533 | b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA0); |
529 | udelay(5); | 534 | udelay(5); |
530 | b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA2); | 535 | b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA2); |
531 | udelay(2); | 536 | udelay(2); |
532 | b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA3); | 537 | b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA3); |
533 | } else { | 538 | } else { |
534 | tmp = (phy->pga_gain | 0xEFA0); | 539 | tmp = (gphy->pga_gain | 0xEFA0); |
535 | b43_phy_write(dev, B43_PHY_PGACTL, tmp); | 540 | b43_phy_write(dev, B43_PHY_PGACTL, tmp); |
536 | } | 541 | } |
537 | if (phy->type == B43_PHYTYPE_G) { | 542 | if (phy->type == B43_PHYTYPE_G) { |
@@ -572,7 +577,7 @@ static void lo_measure_restore(struct b43_wldev *dev, | |||
572 | b43_phy_write(dev, B43_PHY_CCK(0x3E), sav->phy_cck_3E); | 577 | b43_phy_write(dev, B43_PHY_CCK(0x3E), sav->phy_cck_3E); |
573 | b43_phy_write(dev, B43_PHY_CRS0, sav->phy_crs0); | 578 | b43_phy_write(dev, B43_PHY_CRS0, sav->phy_crs0); |
574 | } | 579 | } |
575 | if (b43_has_hardware_pctl(phy)) { | 580 | if (b43_has_hardware_pctl(dev)) { |
576 | tmp = (sav->phy_lo_mask & 0xBFFF); | 581 | tmp = (sav->phy_lo_mask & 0xBFFF); |
577 | b43_phy_write(dev, B43_PHY_LO_MASK, tmp); | 582 | b43_phy_write(dev, B43_PHY_LO_MASK, tmp); |
578 | b43_phy_write(dev, B43_PHY_EXTG(0x01), sav->phy_extg_01); | 583 | b43_phy_write(dev, B43_PHY_EXTG(0x01), sav->phy_extg_01); |
@@ -580,7 +585,7 @@ static void lo_measure_restore(struct b43_wldev *dev, | |||
580 | b43_phy_write(dev, B43_PHY_CCK(0x14), sav->phy_cck_14); | 585 | b43_phy_write(dev, B43_PHY_CCK(0x14), sav->phy_cck_14); |
581 | b43_phy_write(dev, B43_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl); | 586 | b43_phy_write(dev, B43_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl); |
582 | } | 587 | } |
583 | b43_radio_selectchannel(dev, sav->old_channel, 1); | 588 | b43_gphy_channel_switch(dev, sav->old_channel, 1); |
584 | } | 589 | } |
585 | 590 | ||
586 | struct b43_lo_g_statemachine { | 591 | struct b43_lo_g_statemachine { |
@@ -597,6 +602,7 @@ static int lo_probe_possible_loctls(struct b43_wldev *dev, | |||
597 | struct b43_lo_g_statemachine *d) | 602 | struct b43_lo_g_statemachine *d) |
598 | { | 603 | { |
599 | struct b43_phy *phy = &dev->phy; | 604 | struct b43_phy *phy = &dev->phy; |
605 | struct b43_phy_g *gphy = phy->g; | ||
600 | struct b43_loctl test_loctl; | 606 | struct b43_loctl test_loctl; |
601 | struct b43_loctl orig_loctl; | 607 | struct b43_loctl orig_loctl; |
602 | struct b43_loctl prev_loctl = { | 608 | struct b43_loctl prev_loctl = { |
@@ -646,9 +652,9 @@ static int lo_probe_possible_loctls(struct b43_wldev *dev, | |||
646 | test_loctl.q != prev_loctl.q) && | 652 | test_loctl.q != prev_loctl.q) && |
647 | (abs(test_loctl.i) <= 16 && abs(test_loctl.q) <= 16)) { | 653 | (abs(test_loctl.i) <= 16 && abs(test_loctl.q) <= 16)) { |
648 | b43_lo_write(dev, &test_loctl); | 654 | b43_lo_write(dev, &test_loctl); |
649 | feedth = lo_measure_feedthrough(dev, phy->lna_gain, | 655 | feedth = lo_measure_feedthrough(dev, gphy->lna_gain, |
650 | phy->pga_gain, | 656 | gphy->pga_gain, |
651 | phy->trsw_rx_gain); | 657 | gphy->trsw_rx_gain); |
652 | if (feedth < d->lowest_feedth) { | 658 | if (feedth < d->lowest_feedth) { |
653 | memcpy(probe_loctl, &test_loctl, | 659 | memcpy(probe_loctl, &test_loctl, |
654 | sizeof(struct b43_loctl)); | 660 | sizeof(struct b43_loctl)); |
@@ -677,6 +683,7 @@ static void lo_probe_loctls_statemachine(struct b43_wldev *dev, | |||
677 | int *max_rx_gain) | 683 | int *max_rx_gain) |
678 | { | 684 | { |
679 | struct b43_phy *phy = &dev->phy; | 685 | struct b43_phy *phy = &dev->phy; |
686 | struct b43_phy_g *gphy = phy->g; | ||
680 | struct b43_lo_g_statemachine d; | 687 | struct b43_lo_g_statemachine d; |
681 | u16 feedth; | 688 | u16 feedth; |
682 | int found_lower; | 689 | int found_lower; |
@@ -693,17 +700,17 @@ static void lo_probe_loctls_statemachine(struct b43_wldev *dev, | |||
693 | max_repeat = 4; | 700 | max_repeat = 4; |
694 | do { | 701 | do { |
695 | b43_lo_write(dev, &d.min_loctl); | 702 | b43_lo_write(dev, &d.min_loctl); |
696 | feedth = lo_measure_feedthrough(dev, phy->lna_gain, | 703 | feedth = lo_measure_feedthrough(dev, gphy->lna_gain, |
697 | phy->pga_gain, | 704 | gphy->pga_gain, |
698 | phy->trsw_rx_gain); | 705 | gphy->trsw_rx_gain); |
699 | if (feedth < 0x258) { | 706 | if (feedth < 0x258) { |
700 | if (feedth >= 0x12C) | 707 | if (feedth >= 0x12C) |
701 | *max_rx_gain += 6; | 708 | *max_rx_gain += 6; |
702 | else | 709 | else |
703 | *max_rx_gain += 3; | 710 | *max_rx_gain += 3; |
704 | feedth = lo_measure_feedthrough(dev, phy->lna_gain, | 711 | feedth = lo_measure_feedthrough(dev, gphy->lna_gain, |
705 | phy->pga_gain, | 712 | gphy->pga_gain, |
706 | phy->trsw_rx_gain); | 713 | gphy->trsw_rx_gain); |
707 | } | 714 | } |
708 | d.lowest_feedth = feedth; | 715 | d.lowest_feedth = feedth; |
709 | 716 | ||
@@ -752,6 +759,7 @@ struct b43_lo_calib * b43_calibrate_lo_setting(struct b43_wldev *dev, | |||
752 | const struct b43_rfatt *rfatt) | 759 | const struct b43_rfatt *rfatt) |
753 | { | 760 | { |
754 | struct b43_phy *phy = &dev->phy; | 761 | struct b43_phy *phy = &dev->phy; |
762 | struct b43_phy_g *gphy = phy->g; | ||
755 | struct b43_loctl loctl = { | 763 | struct b43_loctl loctl = { |
756 | .i = 0, | 764 | .i = 0, |
757 | .q = 0, | 765 | .q = 0, |
@@ -782,11 +790,11 @@ struct b43_lo_calib * b43_calibrate_lo_setting(struct b43_wldev *dev, | |||
782 | if (rfatt->with_padmix) | 790 | if (rfatt->with_padmix) |
783 | max_rx_gain -= pad_mix_gain; | 791 | max_rx_gain -= pad_mix_gain; |
784 | if (has_loopback_gain(phy)) | 792 | if (has_loopback_gain(phy)) |
785 | max_rx_gain += phy->max_lb_gain; | 793 | max_rx_gain += gphy->max_lb_gain; |
786 | lo_measure_gain_values(dev, max_rx_gain, | 794 | lo_measure_gain_values(dev, max_rx_gain, |
787 | has_loopback_gain(phy)); | 795 | has_loopback_gain(phy)); |
788 | 796 | ||
789 | b43_phy_set_baseband_attenuation(dev, bbatt->att); | 797 | b43_gphy_set_baseband_attenuation(dev, bbatt->att); |
790 | lo_probe_loctls_statemachine(dev, &loctl, &max_rx_gain); | 798 | lo_probe_loctls_statemachine(dev, &loctl, &max_rx_gain); |
791 | 799 | ||
792 | lo_measure_restore(dev, &saved_regs); | 800 | lo_measure_restore(dev, &saved_regs); |
@@ -820,7 +828,7 @@ struct b43_lo_calib * b43_get_calib_lo_settings(struct b43_wldev *dev, | |||
820 | const struct b43_bbatt *bbatt, | 828 | const struct b43_bbatt *bbatt, |
821 | const struct b43_rfatt *rfatt) | 829 | const struct b43_rfatt *rfatt) |
822 | { | 830 | { |
823 | struct b43_txpower_lo_control *lo = dev->phy.lo_control; | 831 | struct b43_txpower_lo_control *lo = dev->phy.g->lo_control; |
824 | struct b43_lo_calib *c; | 832 | struct b43_lo_calib *c; |
825 | 833 | ||
826 | c = b43_find_lo_calib(lo, bbatt, rfatt); | 834 | c = b43_find_lo_calib(lo, bbatt, rfatt); |
@@ -839,7 +847,8 @@ struct b43_lo_calib * b43_get_calib_lo_settings(struct b43_wldev *dev, | |||
839 | void b43_gphy_dc_lt_init(struct b43_wldev *dev, bool update_all) | 847 | void b43_gphy_dc_lt_init(struct b43_wldev *dev, bool update_all) |
840 | { | 848 | { |
841 | struct b43_phy *phy = &dev->phy; | 849 | struct b43_phy *phy = &dev->phy; |
842 | struct b43_txpower_lo_control *lo = phy->lo_control; | 850 | struct b43_phy_g *gphy = phy->g; |
851 | struct b43_txpower_lo_control *lo = gphy->lo_control; | ||
843 | int i; | 852 | int i; |
844 | int rf_offset, bb_offset; | 853 | int rf_offset, bb_offset; |
845 | const struct b43_rfatt *rfatt; | 854 | const struct b43_rfatt *rfatt; |
@@ -917,14 +926,14 @@ static inline void b43_lo_fixup_rfatt(struct b43_rfatt *rf) | |||
917 | 926 | ||
918 | void b43_lo_g_adjust(struct b43_wldev *dev) | 927 | void b43_lo_g_adjust(struct b43_wldev *dev) |
919 | { | 928 | { |
920 | struct b43_phy *phy = &dev->phy; | 929 | struct b43_phy_g *gphy = dev->phy.g; |
921 | struct b43_lo_calib *cal; | 930 | struct b43_lo_calib *cal; |
922 | struct b43_rfatt rf; | 931 | struct b43_rfatt rf; |
923 | 932 | ||
924 | memcpy(&rf, &phy->rfatt, sizeof(rf)); | 933 | memcpy(&rf, &gphy->rfatt, sizeof(rf)); |
925 | b43_lo_fixup_rfatt(&rf); | 934 | b43_lo_fixup_rfatt(&rf); |
926 | 935 | ||
927 | cal = b43_get_calib_lo_settings(dev, &phy->bbatt, &rf); | 936 | cal = b43_get_calib_lo_settings(dev, &gphy->bbatt, &rf); |
928 | if (!cal) | 937 | if (!cal) |
929 | return; | 938 | return; |
930 | b43_lo_write(dev, &cal->ctl); | 939 | b43_lo_write(dev, &cal->ctl); |
@@ -952,7 +961,8 @@ void b43_lo_g_adjust_to(struct b43_wldev *dev, | |||
952 | void b43_lo_g_maintanance_work(struct b43_wldev *dev) | 961 | void b43_lo_g_maintanance_work(struct b43_wldev *dev) |
953 | { | 962 | { |
954 | struct b43_phy *phy = &dev->phy; | 963 | struct b43_phy *phy = &dev->phy; |
955 | struct b43_txpower_lo_control *lo = phy->lo_control; | 964 | struct b43_phy_g *gphy = phy->g; |
965 | struct b43_txpower_lo_control *lo = gphy->lo_control; | ||
956 | unsigned long now; | 966 | unsigned long now; |
957 | unsigned long expire; | 967 | unsigned long expire; |
958 | struct b43_lo_calib *cal, *tmp; | 968 | struct b43_lo_calib *cal, *tmp; |
@@ -962,7 +972,7 @@ void b43_lo_g_maintanance_work(struct b43_wldev *dev) | |||
962 | if (!lo) | 972 | if (!lo) |
963 | return; | 973 | return; |
964 | now = jiffies; | 974 | now = jiffies; |
965 | hwpctl = b43_has_hardware_pctl(phy); | 975 | hwpctl = b43_has_hardware_pctl(dev); |
966 | 976 | ||
967 | if (hwpctl) { | 977 | if (hwpctl) { |
968 | /* Read the power vector and update it, if needed. */ | 978 | /* Read the power vector and update it, if needed. */ |
@@ -983,8 +993,8 @@ void b43_lo_g_maintanance_work(struct b43_wldev *dev) | |||
983 | if (!time_before(cal->calib_time, expire)) | 993 | if (!time_before(cal->calib_time, expire)) |
984 | continue; | 994 | continue; |
985 | /* This item expired. */ | 995 | /* This item expired. */ |
986 | if (b43_compare_bbatt(&cal->bbatt, &phy->bbatt) && | 996 | if (b43_compare_bbatt(&cal->bbatt, &gphy->bbatt) && |
987 | b43_compare_rfatt(&cal->rfatt, &phy->rfatt)) { | 997 | b43_compare_rfatt(&cal->rfatt, &gphy->rfatt)) { |
988 | B43_WARN_ON(current_item_expired); | 998 | B43_WARN_ON(current_item_expired); |
989 | current_item_expired = 1; | 999 | current_item_expired = 1; |
990 | } | 1000 | } |
@@ -1002,7 +1012,7 @@ void b43_lo_g_maintanance_work(struct b43_wldev *dev) | |||
1002 | /* Recalibrate currently used LO setting. */ | 1012 | /* Recalibrate currently used LO setting. */ |
1003 | if (b43_debug(dev, B43_DBG_LO)) | 1013 | if (b43_debug(dev, B43_DBG_LO)) |
1004 | b43dbg(dev->wl, "LO: Recalibrating current LO setting\n"); | 1014 | b43dbg(dev->wl, "LO: Recalibrating current LO setting\n"); |
1005 | cal = b43_calibrate_lo_setting(dev, &phy->bbatt, &phy->rfatt); | 1015 | cal = b43_calibrate_lo_setting(dev, &gphy->bbatt, &gphy->rfatt); |
1006 | if (cal) { | 1016 | if (cal) { |
1007 | list_add(&cal->list, &lo->calib_list); | 1017 | list_add(&cal->list, &lo->calib_list); |
1008 | b43_lo_write(dev, &cal->ctl); | 1018 | b43_lo_write(dev, &cal->ctl); |
@@ -1013,7 +1023,7 @@ void b43_lo_g_maintanance_work(struct b43_wldev *dev) | |||
1013 | 1023 | ||
1014 | void b43_lo_g_cleanup(struct b43_wldev *dev) | 1024 | void b43_lo_g_cleanup(struct b43_wldev *dev) |
1015 | { | 1025 | { |
1016 | struct b43_txpower_lo_control *lo = dev->phy.lo_control; | 1026 | struct b43_txpower_lo_control *lo = dev->phy.g->lo_control; |
1017 | struct b43_lo_calib *cal, *tmp; | 1027 | struct b43_lo_calib *cal, *tmp; |
1018 | 1028 | ||
1019 | if (!lo) | 1029 | if (!lo) |
@@ -1027,9 +1037,7 @@ void b43_lo_g_cleanup(struct b43_wldev *dev) | |||
1027 | /* LO Initialization */ | 1037 | /* LO Initialization */ |
1028 | void b43_lo_g_init(struct b43_wldev *dev) | 1038 | void b43_lo_g_init(struct b43_wldev *dev) |
1029 | { | 1039 | { |
1030 | struct b43_phy *phy = &dev->phy; | 1040 | if (b43_has_hardware_pctl(dev)) { |
1031 | |||
1032 | if (b43_has_hardware_pctl(phy)) { | ||
1033 | lo_read_power_vector(dev); | 1041 | lo_read_power_vector(dev); |
1034 | b43_gphy_dc_lt_init(dev, 1); | 1042 | b43_gphy_dc_lt_init(dev, 1); |
1035 | } | 1043 | } |
diff --git a/drivers/net/wireless/b43/lo.h b/drivers/net/wireless/b43/lo.h index 1da321cabc12..3b27e20eff80 100644 --- a/drivers/net/wireless/b43/lo.h +++ b/drivers/net/wireless/b43/lo.h | |||
@@ -1,7 +1,9 @@ | |||
1 | #ifndef B43_LO_H_ | 1 | #ifndef B43_LO_H_ |
2 | #define B43_LO_H_ | 2 | #define B43_LO_H_ |
3 | 3 | ||
4 | #include "phy.h" | 4 | /* G-PHY Local Oscillator */ |
5 | |||
6 | #include "phy_g.h" | ||
5 | 7 | ||
6 | struct b43_wldev; | 8 | struct b43_wldev; |
7 | 9 | ||
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 7205a936ec74..63bafc2f3f0a 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -44,7 +44,8 @@ | |||
44 | #include "b43.h" | 44 | #include "b43.h" |
45 | #include "main.h" | 45 | #include "main.h" |
46 | #include "debugfs.h" | 46 | #include "debugfs.h" |
47 | #include "phy.h" | 47 | #include "phy_common.h" |
48 | #include "phy_g.h" | ||
48 | #include "nphy.h" | 49 | #include "nphy.h" |
49 | #include "dma.h" | 50 | #include "dma.h" |
50 | #include "pio.h" | 51 | #include "pio.h" |
@@ -1174,6 +1175,8 @@ static void b43_calculate_link_quality(struct b43_wldev *dev) | |||
1174 | { | 1175 | { |
1175 | /* Top half of Link Quality calculation. */ | 1176 | /* Top half of Link Quality calculation. */ |
1176 | 1177 | ||
1178 | if (dev->phy.type != B43_PHYTYPE_G) | ||
1179 | return; | ||
1177 | if (dev->noisecalc.calculation_running) | 1180 | if (dev->noisecalc.calculation_running) |
1178 | return; | 1181 | return; |
1179 | dev->noisecalc.calculation_running = 1; | 1182 | dev->noisecalc.calculation_running = 1; |
@@ -1184,7 +1187,7 @@ static void b43_calculate_link_quality(struct b43_wldev *dev) | |||
1184 | 1187 | ||
1185 | static void handle_irq_noise(struct b43_wldev *dev) | 1188 | static void handle_irq_noise(struct b43_wldev *dev) |
1186 | { | 1189 | { |
1187 | struct b43_phy *phy = &dev->phy; | 1190 | struct b43_phy_g *phy = dev->phy.g; |
1188 | u16 tmp; | 1191 | u16 tmp; |
1189 | u8 noise[4]; | 1192 | u8 noise[4]; |
1190 | u8 i, j; | 1193 | u8 i, j; |
@@ -1192,6 +1195,9 @@ static void handle_irq_noise(struct b43_wldev *dev) | |||
1192 | 1195 | ||
1193 | /* Bottom half of Link Quality calculation. */ | 1196 | /* Bottom half of Link Quality calculation. */ |
1194 | 1197 | ||
1198 | if (dev->phy.type != B43_PHYTYPE_G) | ||
1199 | return; | ||
1200 | |||
1195 | /* Possible race condition: It might be possible that the user | 1201 | /* Possible race condition: It might be possible that the user |
1196 | * changed to a different channel in the meantime since we | 1202 | * changed to a different channel in the meantime since we |
1197 | * started the calculation. We ignore that fact, since it's | 1203 | * started the calculation. We ignore that fact, since it's |
@@ -2688,9 +2694,7 @@ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna) | |||
2688 | /* This is the opposite of b43_chip_init() */ | 2694 | /* This is the opposite of b43_chip_init() */ |
2689 | static void b43_chip_exit(struct b43_wldev *dev) | 2695 | static void b43_chip_exit(struct b43_wldev *dev) |
2690 | { | 2696 | { |
2691 | b43_radio_turn_off(dev, 1); | ||
2692 | b43_gpio_cleanup(dev); | 2697 | b43_gpio_cleanup(dev); |
2693 | b43_lo_g_cleanup(dev); | ||
2694 | /* firmware is released later */ | 2698 | /* firmware is released later */ |
2695 | } | 2699 | } |
2696 | 2700 | ||
@@ -2700,7 +2704,7 @@ static void b43_chip_exit(struct b43_wldev *dev) | |||
2700 | static int b43_chip_init(struct b43_wldev *dev) | 2704 | static int b43_chip_init(struct b43_wldev *dev) |
2701 | { | 2705 | { |
2702 | struct b43_phy *phy = &dev->phy; | 2706 | struct b43_phy *phy = &dev->phy; |
2703 | int err, tmp; | 2707 | int err; |
2704 | u32 value32, macctl; | 2708 | u32 value32, macctl; |
2705 | u16 value16; | 2709 | u16 value16; |
2706 | 2710 | ||
@@ -2725,19 +2729,19 @@ static int b43_chip_init(struct b43_wldev *dev) | |||
2725 | err = b43_upload_initvals(dev); | 2729 | err = b43_upload_initvals(dev); |
2726 | if (err) | 2730 | if (err) |
2727 | goto err_gpio_clean; | 2731 | goto err_gpio_clean; |
2728 | b43_radio_turn_on(dev); | ||
2729 | 2732 | ||
2730 | b43_write16(dev, 0x03E6, 0x0000); | 2733 | b43_write16(dev, 0x03E6, 0x0000); |
2731 | err = b43_phy_init(dev); | 2734 | err = b43_phy_init(dev); |
2732 | if (err) | 2735 | if (err) |
2733 | goto err_radio_off; | 2736 | goto err_gpio_clean; |
2734 | 2737 | ||
2735 | /* Select initial Interference Mitigation. */ | 2738 | /* Disable Interference Mitigation. */ |
2736 | tmp = phy->interfmode; | 2739 | if (phy->ops->interf_mitigation) |
2737 | phy->interfmode = B43_INTERFMODE_NONE; | 2740 | phy->ops->interf_mitigation(dev, B43_INTERFMODE_NONE); |
2738 | b43_radio_set_interference_mitigation(dev, tmp); | ||
2739 | 2741 | ||
2740 | b43_set_rx_antenna(dev, B43_ANTENNA_DEFAULT); | 2742 | /* Select the antennae */ |
2743 | if (phy->ops->set_rx_antenna) | ||
2744 | phy->ops->set_rx_antenna(dev, B43_ANTENNA_DEFAULT); | ||
2741 | b43_mgmtframe_txantenna(dev, B43_ANTENNA_DEFAULT); | 2745 | b43_mgmtframe_txantenna(dev, B43_ANTENNA_DEFAULT); |
2742 | 2746 | ||
2743 | if (phy->type == B43_PHYTYPE_B) { | 2747 | if (phy->type == B43_PHYTYPE_B) { |
@@ -2790,8 +2794,6 @@ static int b43_chip_init(struct b43_wldev *dev) | |||
2790 | out: | 2794 | out: |
2791 | return err; | 2795 | return err; |
2792 | 2796 | ||
2793 | err_radio_off: | ||
2794 | b43_radio_turn_off(dev, 1); | ||
2795 | err_gpio_clean: | 2797 | err_gpio_clean: |
2796 | b43_gpio_cleanup(dev); | 2798 | b43_gpio_cleanup(dev); |
2797 | return err; | 2799 | return err; |
@@ -2799,25 +2801,13 @@ err_gpio_clean: | |||
2799 | 2801 | ||
2800 | static void b43_periodic_every60sec(struct b43_wldev *dev) | 2802 | static void b43_periodic_every60sec(struct b43_wldev *dev) |
2801 | { | 2803 | { |
2802 | struct b43_phy *phy = &dev->phy; | 2804 | const struct b43_phy_operations *ops = dev->phy.ops; |
2803 | 2805 | ||
2804 | if (phy->type != B43_PHYTYPE_G) | 2806 | if (ops->pwork_60sec) |
2805 | return; | 2807 | ops->pwork_60sec(dev); |
2806 | if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) { | 2808 | |
2807 | b43_mac_suspend(dev); | 2809 | /* Force check the TX power emission now. */ |
2808 | b43_calc_nrssi_slope(dev); | 2810 | b43_phy_txpower_check(dev, B43_TXPWR_IGNORE_TIME); |
2809 | if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 8)) { | ||
2810 | u8 old_chan = phy->channel; | ||
2811 | |||
2812 | /* VCO Calibration */ | ||
2813 | if (old_chan >= 8) | ||
2814 | b43_radio_selectchannel(dev, 1, 0); | ||
2815 | else | ||
2816 | b43_radio_selectchannel(dev, 13, 0); | ||
2817 | b43_radio_selectchannel(dev, old_chan, 0); | ||
2818 | } | ||
2819 | b43_mac_enable(dev); | ||
2820 | } | ||
2821 | } | 2811 | } |
2822 | 2812 | ||
2823 | static void b43_periodic_every30sec(struct b43_wldev *dev) | 2813 | static void b43_periodic_every30sec(struct b43_wldev *dev) |
@@ -2845,32 +2835,8 @@ static void b43_periodic_every15sec(struct b43_wldev *dev) | |||
2845 | } | 2835 | } |
2846 | } | 2836 | } |
2847 | 2837 | ||
2848 | if (phy->type == B43_PHYTYPE_G) { | 2838 | if (phy->ops->pwork_15sec) |
2849 | //TODO: update_aci_moving_average | 2839 | phy->ops->pwork_15sec(dev); |
2850 | if (phy->aci_enable && phy->aci_wlan_automatic) { | ||
2851 | b43_mac_suspend(dev); | ||
2852 | if (!phy->aci_enable && 1 /*TODO: not scanning? */ ) { | ||
2853 | if (0 /*TODO: bunch of conditions */ ) { | ||
2854 | b43_radio_set_interference_mitigation | ||
2855 | (dev, B43_INTERFMODE_MANUALWLAN); | ||
2856 | } | ||
2857 | } else if (1 /*TODO*/) { | ||
2858 | /* | ||
2859 | if ((aci_average > 1000) && !(b43_radio_aci_scan(dev))) { | ||
2860 | b43_radio_set_interference_mitigation(dev, | ||
2861 | B43_INTERFMODE_NONE); | ||
2862 | } | ||
2863 | */ | ||
2864 | } | ||
2865 | b43_mac_enable(dev); | ||
2866 | } else if (phy->interfmode == B43_INTERFMODE_NONWLAN && | ||
2867 | phy->rev == 1) { | ||
2868 | //TODO: implement rev1 workaround | ||
2869 | } | ||
2870 | } | ||
2871 | b43_phy_xmitpower(dev); //FIXME: unless scanning? | ||
2872 | b43_lo_g_maintanance_work(dev); | ||
2873 | //TODO for APHY (temperature?) | ||
2874 | 2840 | ||
2875 | atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); | 2841 | atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); |
2876 | wmb(); | 2842 | wmb(); |
@@ -3401,7 +3367,7 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) | |||
3401 | /* Switch to the requested channel. | 3367 | /* Switch to the requested channel. |
3402 | * The firmware takes care of races with the TX handler. */ | 3368 | * The firmware takes care of races with the TX handler. */ |
3403 | if (conf->channel->hw_value != phy->channel) | 3369 | if (conf->channel->hw_value != phy->channel) |
3404 | b43_radio_selectchannel(dev, conf->channel->hw_value, 0); | 3370 | b43_switch_channel(dev, conf->channel->hw_value); |
3405 | 3371 | ||
3406 | /* Enable/Disable ShortSlot timing. */ | 3372 | /* Enable/Disable ShortSlot timing. */ |
3407 | if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) != | 3373 | if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) != |
@@ -3417,17 +3383,21 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) | |||
3417 | 3383 | ||
3418 | /* Adjust the desired TX power level. */ | 3384 | /* Adjust the desired TX power level. */ |
3419 | if (conf->power_level != 0) { | 3385 | if (conf->power_level != 0) { |
3420 | if (conf->power_level != phy->power_level) { | 3386 | spin_lock_irqsave(&wl->irq_lock, flags); |
3421 | phy->power_level = conf->power_level; | 3387 | if (conf->power_level != phy->desired_txpower) { |
3422 | b43_phy_xmitpower(dev); | 3388 | phy->desired_txpower = conf->power_level; |
3389 | b43_phy_txpower_check(dev, B43_TXPWR_IGNORE_TIME | | ||
3390 | B43_TXPWR_IGNORE_TSSI); | ||
3423 | } | 3391 | } |
3392 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3424 | } | 3393 | } |
3425 | 3394 | ||
3426 | /* Antennas for RX and management frame TX. */ | 3395 | /* Antennas for RX and management frame TX. */ |
3427 | antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_tx); | 3396 | antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_tx); |
3428 | b43_mgmtframe_txantenna(dev, antenna); | 3397 | b43_mgmtframe_txantenna(dev, antenna); |
3429 | antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_rx); | 3398 | antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_rx); |
3430 | b43_set_rx_antenna(dev, antenna); | 3399 | if (phy->ops->set_rx_antenna) |
3400 | phy->ops->set_rx_antenna(dev, antenna); | ||
3431 | 3401 | ||
3432 | /* Update templates for AP/mesh mode. */ | 3402 | /* Update templates for AP/mesh mode. */ |
3433 | if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) || | 3403 | if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) || |
@@ -3436,7 +3406,7 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) | |||
3436 | 3406 | ||
3437 | if (!!conf->radio_enabled != phy->radio_on) { | 3407 | if (!!conf->radio_enabled != phy->radio_on) { |
3438 | if (conf->radio_enabled) { | 3408 | if (conf->radio_enabled) { |
3439 | b43_radio_turn_on(dev); | 3409 | b43_software_rfkill(dev, RFKILL_STATE_UNBLOCKED); |
3440 | b43info(dev->wl, "Radio turned on by software\n"); | 3410 | b43info(dev->wl, "Radio turned on by software\n"); |
3441 | if (!dev->radio_hw_enable) { | 3411 | if (!dev->radio_hw_enable) { |
3442 | b43info(dev->wl, "The hardware RF-kill button " | 3412 | b43info(dev->wl, "The hardware RF-kill button " |
@@ -3444,7 +3414,7 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) | |||
3444 | "Press the button to turn it on.\n"); | 3414 | "Press the button to turn it on.\n"); |
3445 | } | 3415 | } |
3446 | } else { | 3416 | } else { |
3447 | b43_radio_turn_off(dev, 0); | 3417 | b43_software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED); |
3448 | b43info(dev->wl, "Radio turned off by software\n"); | 3418 | b43info(dev->wl, "Radio turned off by software\n"); |
3449 | } | 3419 | } |
3450 | } | 3420 | } |
@@ -3818,48 +3788,10 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
3818 | static void setup_struct_phy_for_init(struct b43_wldev *dev, | 3788 | static void setup_struct_phy_for_init(struct b43_wldev *dev, |
3819 | struct b43_phy *phy) | 3789 | struct b43_phy *phy) |
3820 | { | 3790 | { |
3821 | struct b43_txpower_lo_control *lo; | ||
3822 | int i; | ||
3823 | |||
3824 | memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig)); | ||
3825 | memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos)); | ||
3826 | |||
3827 | phy->aci_enable = 0; | ||
3828 | phy->aci_wlan_automatic = 0; | ||
3829 | phy->aci_hw_rssi = 0; | ||
3830 | |||
3831 | phy->radio_off_context.valid = 0; | ||
3832 | |||
3833 | lo = phy->lo_control; | ||
3834 | if (lo) { | ||
3835 | memset(lo, 0, sizeof(*(phy->lo_control))); | ||
3836 | lo->tx_bias = 0xFF; | ||
3837 | INIT_LIST_HEAD(&lo->calib_list); | ||
3838 | } | ||
3839 | phy->max_lb_gain = 0; | ||
3840 | phy->trsw_rx_gain = 0; | ||
3841 | phy->txpwr_offset = 0; | ||
3842 | |||
3843 | /* NRSSI */ | ||
3844 | phy->nrssislope = 0; | ||
3845 | for (i = 0; i < ARRAY_SIZE(phy->nrssi); i++) | ||
3846 | phy->nrssi[i] = -1000; | ||
3847 | for (i = 0; i < ARRAY_SIZE(phy->nrssi_lt); i++) | ||
3848 | phy->nrssi_lt[i] = i; | ||
3849 | |||
3850 | phy->lofcal = 0xFFFF; | ||
3851 | phy->initval = 0xFFFF; | ||
3852 | |||
3853 | phy->interfmode = B43_INTERFMODE_NONE; | ||
3854 | phy->channel = 0xFF; | ||
3855 | |||
3856 | phy->hardware_power_control = !!modparam_hwpctl; | 3791 | phy->hardware_power_control = !!modparam_hwpctl; |
3857 | 3792 | phy->next_txpwr_check_time = jiffies; | |
3858 | /* PHY TX errors counter. */ | 3793 | /* PHY TX errors counter. */ |
3859 | atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); | 3794 | atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); |
3860 | |||
3861 | /* OFDM-table address caching. */ | ||
3862 | phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_UNKNOWN; | ||
3863 | } | 3795 | } |
3864 | 3796 | ||
3865 | static void setup_struct_wldev_for_init(struct b43_wldev *dev) | 3797 | static void setup_struct_wldev_for_init(struct b43_wldev *dev) |
@@ -3995,7 +3927,6 @@ static void b43_set_pretbtt(struct b43_wldev *dev) | |||
3995 | /* Locking: wl->mutex */ | 3927 | /* Locking: wl->mutex */ |
3996 | static void b43_wireless_core_exit(struct b43_wldev *dev) | 3928 | static void b43_wireless_core_exit(struct b43_wldev *dev) |
3997 | { | 3929 | { |
3998 | struct b43_phy *phy = &dev->phy; | ||
3999 | u32 macctl; | 3930 | u32 macctl; |
4000 | 3931 | ||
4001 | B43_WARN_ON(b43_status(dev) > B43_STAT_INITIALIZED); | 3932 | B43_WARN_ON(b43_status(dev) > B43_STAT_INITIALIZED); |
@@ -4016,16 +3947,12 @@ static void b43_wireless_core_exit(struct b43_wldev *dev) | |||
4016 | b43_dma_free(dev); | 3947 | b43_dma_free(dev); |
4017 | b43_pio_free(dev); | 3948 | b43_pio_free(dev); |
4018 | b43_chip_exit(dev); | 3949 | b43_chip_exit(dev); |
4019 | b43_radio_turn_off(dev, 1); | ||
4020 | b43_switch_analog(dev, 0); | 3950 | b43_switch_analog(dev, 0); |
4021 | if (phy->dyn_tssi_tbl) | ||
4022 | kfree(phy->tssi2dbm); | ||
4023 | kfree(phy->lo_control); | ||
4024 | phy->lo_control = NULL; | ||
4025 | if (dev->wl->current_beacon) { | 3951 | if (dev->wl->current_beacon) { |
4026 | dev_kfree_skb_any(dev->wl->current_beacon); | 3952 | dev_kfree_skb_any(dev->wl->current_beacon); |
4027 | dev->wl->current_beacon = NULL; | 3953 | dev->wl->current_beacon = NULL; |
4028 | } | 3954 | } |
3955 | b43_phy_exit(dev); | ||
4029 | 3956 | ||
4030 | ssb_device_disable(dev->dev, 0); | 3957 | ssb_device_disable(dev->dev, 0); |
4031 | ssb_bus_may_powerdown(dev->dev->bus); | 3958 | ssb_bus_may_powerdown(dev->dev->bus); |
@@ -4052,29 +3979,24 @@ static int b43_wireless_core_init(struct b43_wldev *dev) | |||
4052 | b43_wireless_core_reset(dev, tmp); | 3979 | b43_wireless_core_reset(dev, tmp); |
4053 | } | 3980 | } |
4054 | 3981 | ||
4055 | if ((phy->type == B43_PHYTYPE_B) || (phy->type == B43_PHYTYPE_G)) { | ||
4056 | phy->lo_control = | ||
4057 | kzalloc(sizeof(*(phy->lo_control)), GFP_KERNEL); | ||
4058 | if (!phy->lo_control) { | ||
4059 | err = -ENOMEM; | ||
4060 | goto err_busdown; | ||
4061 | } | ||
4062 | } | ||
4063 | setup_struct_wldev_for_init(dev); | 3982 | setup_struct_wldev_for_init(dev); |
4064 | 3983 | err = b43_phy_operations_setup(dev); | |
4065 | err = b43_phy_init_tssi2dbm_table(dev); | ||
4066 | if (err) | 3984 | if (err) |
4067 | goto err_kfree_lo_control; | 3985 | goto err_busdown; |
4068 | 3986 | ||
4069 | /* Enable IRQ routing to this device. */ | 3987 | /* Enable IRQ routing to this device. */ |
4070 | ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev); | 3988 | ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev); |
4071 | 3989 | ||
4072 | b43_imcfglo_timeouts_workaround(dev); | 3990 | b43_imcfglo_timeouts_workaround(dev); |
4073 | b43_bluetooth_coext_disable(dev); | 3991 | b43_bluetooth_coext_disable(dev); |
4074 | b43_phy_early_init(dev); | 3992 | if (phy->ops->prepare) { |
3993 | err = phy->ops->prepare(dev); | ||
3994 | if (err) | ||
3995 | goto err_phy_exit; | ||
3996 | } | ||
4075 | err = b43_chip_init(dev); | 3997 | err = b43_chip_init(dev); |
4076 | if (err) | 3998 | if (err) |
4077 | goto err_kfree_tssitbl; | 3999 | goto err_phy_exit; |
4078 | b43_shm_write16(dev, B43_SHM_SHARED, | 4000 | b43_shm_write16(dev, B43_SHM_SHARED, |
4079 | B43_SHM_SH_WLCOREREV, dev->dev->id.revision); | 4001 | B43_SHM_SH_WLCOREREV, dev->dev->id.revision); |
4080 | hf = b43_hf_read(dev); | 4002 | hf = b43_hf_read(dev); |
@@ -4140,15 +4062,11 @@ static int b43_wireless_core_init(struct b43_wldev *dev) | |||
4140 | out: | 4062 | out: |
4141 | return err; | 4063 | return err; |
4142 | 4064 | ||
4143 | err_chip_exit: | 4065 | err_chip_exit: |
4144 | b43_chip_exit(dev); | 4066 | b43_chip_exit(dev); |
4145 | err_kfree_tssitbl: | 4067 | err_phy_exit: |
4146 | if (phy->dyn_tssi_tbl) | 4068 | b43_phy_exit(dev); |
4147 | kfree(phy->tssi2dbm); | 4069 | err_busdown: |
4148 | err_kfree_lo_control: | ||
4149 | kfree(phy->lo_control); | ||
4150 | phy->lo_control = NULL; | ||
4151 | err_busdown: | ||
4152 | ssb_bus_may_powerdown(bus); | 4070 | ssb_bus_may_powerdown(bus); |
4153 | B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT); | 4071 | B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT); |
4154 | return err; | 4072 | return err; |
@@ -4291,6 +4209,8 @@ static void b43_op_stop(struct ieee80211_hw *hw) | |||
4291 | b43_wireless_core_stop(dev); | 4209 | b43_wireless_core_stop(dev); |
4292 | b43_wireless_core_exit(dev); | 4210 | b43_wireless_core_exit(dev); |
4293 | mutex_unlock(&wl->mutex); | 4211 | mutex_unlock(&wl->mutex); |
4212 | |||
4213 | cancel_work_sync(&(wl->txpower_adjust_work)); | ||
4294 | } | 4214 | } |
4295 | 4215 | ||
4296 | static int b43_op_set_retry_limit(struct ieee80211_hw *hw, | 4216 | static int b43_op_set_retry_limit(struct ieee80211_hw *hw, |
@@ -4511,7 +4431,6 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) | |||
4511 | wl->current_dev = dev; | 4431 | wl->current_dev = dev; |
4512 | INIT_WORK(&dev->restart_work, b43_chip_reset); | 4432 | INIT_WORK(&dev->restart_work, b43_chip_reset); |
4513 | 4433 | ||
4514 | b43_radio_turn_off(dev, 1); | ||
4515 | b43_switch_analog(dev, 0); | 4434 | b43_switch_analog(dev, 0); |
4516 | ssb_device_disable(dev->dev, 0); | 4435 | ssb_device_disable(dev->dev, 0); |
4517 | ssb_bus_may_powerdown(bus); | 4436 | ssb_bus_may_powerdown(bus); |
@@ -4669,6 +4588,7 @@ static int b43_wireless_init(struct ssb_device *dev) | |||
4669 | INIT_LIST_HEAD(&wl->devlist); | 4588 | INIT_LIST_HEAD(&wl->devlist); |
4670 | INIT_WORK(&wl->qos_update_work, b43_qos_update_work); | 4589 | INIT_WORK(&wl->qos_update_work, b43_qos_update_work); |
4671 | INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work); | 4590 | INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work); |
4591 | INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work); | ||
4672 | 4592 | ||
4673 | ssb_set_devtypedata(dev, wl); | 4593 | ssb_set_devtypedata(dev, wl); |
4674 | b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id); | 4594 | b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id); |
diff --git a/drivers/net/wireless/b43/nphy.c b/drivers/net/wireless/b43/nphy.c index 644eed993bea..4cfeab8560f6 100644 --- a/drivers/net/wireless/b43/nphy.c +++ b/drivers/net/wireless/b43/nphy.c | |||
@@ -34,10 +34,16 @@ void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) | |||
34 | {//TODO | 34 | {//TODO |
35 | } | 35 | } |
36 | 36 | ||
37 | void b43_nphy_xmitpower(struct b43_wldev *dev) | 37 | static void b43_nphy_op_adjust_txpower(struct b43_wldev *dev) |
38 | {//TODO | 38 | {//TODO |
39 | } | 39 | } |
40 | 40 | ||
41 | static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev, | ||
42 | bool ignore_tssi) | ||
43 | {//TODO | ||
44 | return B43_TXPWR_RES_DONE; | ||
45 | } | ||
46 | |||
41 | static void b43_chantab_radio_upload(struct b43_wldev *dev, | 47 | static void b43_chantab_radio_upload(struct b43_wldev *dev, |
42 | const struct b43_nphy_channeltab_entry *e) | 48 | const struct b43_nphy_channeltab_entry *e) |
43 | { | 49 | { |
@@ -81,9 +87,8 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev) | |||
81 | //TODO | 87 | //TODO |
82 | } | 88 | } |
83 | 89 | ||
84 | /* Tune the hardware to a new channel. Don't call this directly. | 90 | /* Tune the hardware to a new channel. */ |
85 | * Use b43_radio_selectchannel() */ | 91 | static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel) |
86 | int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel) | ||
87 | { | 92 | { |
88 | const struct b43_nphy_channeltab_entry *tabent; | 93 | const struct b43_nphy_channeltab_entry *tabent; |
89 | 94 | ||
@@ -162,7 +167,7 @@ static void b43_radio_init2055_post(struct b43_wldev *dev) | |||
162 | msleep(1); | 167 | msleep(1); |
163 | b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F); | 168 | b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F); |
164 | msleep(1); | 169 | msleep(1); |
165 | b43_radio_selectchannel(dev, dev->phy.channel, 0); | 170 | nphy_channel_switch(dev, dev->phy.channel); |
166 | b43_radio_write16(dev, B2055_C1_RX_BB_LPF, 0x9); | 171 | b43_radio_write16(dev, B2055_C1_RX_BB_LPF, 0x9); |
167 | b43_radio_write16(dev, B2055_C2_RX_BB_LPF, 0x9); | 172 | b43_radio_write16(dev, B2055_C2_RX_BB_LPF, 0x9); |
168 | b43_radio_write16(dev, B2055_C1_RX_BB_MIDACHP, 0x83); | 173 | b43_radio_write16(dev, B2055_C1_RX_BB_MIDACHP, 0x83); |
@@ -484,3 +489,136 @@ int b43_phy_initn(struct b43_wldev *dev) | |||
484 | b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n"); | 489 | b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n"); |
485 | return 0; | 490 | return 0; |
486 | } | 491 | } |
492 | |||
493 | static int b43_nphy_op_allocate(struct b43_wldev *dev) | ||
494 | { | ||
495 | struct b43_phy_n *nphy; | ||
496 | |||
497 | nphy = kzalloc(sizeof(*nphy), GFP_KERNEL); | ||
498 | if (!nphy) | ||
499 | return -ENOMEM; | ||
500 | dev->phy.n = nphy; | ||
501 | |||
502 | //TODO init struct b43_phy_n | ||
503 | |||
504 | return 0; | ||
505 | } | ||
506 | |||
507 | static int b43_nphy_op_init(struct b43_wldev *dev) | ||
508 | { | ||
509 | struct b43_phy_n *nphy = dev->phy.n; | ||
510 | int err; | ||
511 | |||
512 | err = b43_phy_initn(dev); | ||
513 | if (err) | ||
514 | return err; | ||
515 | nphy->initialised = 1; | ||
516 | |||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | static void b43_nphy_op_exit(struct b43_wldev *dev) | ||
521 | { | ||
522 | struct b43_phy_n *nphy = dev->phy.n; | ||
523 | |||
524 | if (nphy->initialised) { | ||
525 | //TODO | ||
526 | nphy->initialised = 0; | ||
527 | } | ||
528 | //TODO | ||
529 | kfree(nphy); | ||
530 | dev->phy.n = NULL; | ||
531 | } | ||
532 | |||
533 | static inline void check_phyreg(struct b43_wldev *dev, u16 offset) | ||
534 | { | ||
535 | #if B43_DEBUG | ||
536 | if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) { | ||
537 | /* OFDM registers are onnly available on A/G-PHYs */ | ||
538 | b43err(dev->wl, "Invalid OFDM PHY access at " | ||
539 | "0x%04X on N-PHY\n", offset); | ||
540 | dump_stack(); | ||
541 | } | ||
542 | if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) { | ||
543 | /* Ext-G registers are only available on G-PHYs */ | ||
544 | b43err(dev->wl, "Invalid EXT-G PHY access at " | ||
545 | "0x%04X on N-PHY\n", offset); | ||
546 | dump_stack(); | ||
547 | } | ||
548 | #endif /* B43_DEBUG */ | ||
549 | } | ||
550 | |||
551 | static u16 b43_nphy_op_read(struct b43_wldev *dev, u16 reg) | ||
552 | { | ||
553 | check_phyreg(dev, reg); | ||
554 | b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); | ||
555 | return b43_read16(dev, B43_MMIO_PHY_DATA); | ||
556 | } | ||
557 | |||
558 | static void b43_nphy_op_write(struct b43_wldev *dev, u16 reg, u16 value) | ||
559 | { | ||
560 | check_phyreg(dev, reg); | ||
561 | b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); | ||
562 | b43_write16(dev, B43_MMIO_PHY_DATA, value); | ||
563 | } | ||
564 | |||
565 | static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg) | ||
566 | { | ||
567 | /* Register 1 is a 32-bit register. */ | ||
568 | B43_WARN_ON(reg == 1); | ||
569 | /* N-PHY needs 0x100 for read access */ | ||
570 | reg |= 0x100; | ||
571 | |||
572 | b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); | ||
573 | return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW); | ||
574 | } | ||
575 | |||
576 | static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) | ||
577 | { | ||
578 | /* Register 1 is a 32-bit register. */ | ||
579 | B43_WARN_ON(reg == 1); | ||
580 | |||
581 | b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); | ||
582 | b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); | ||
583 | } | ||
584 | |||
585 | static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, | ||
586 | enum rfkill_state state) | ||
587 | {//TODO | ||
588 | } | ||
589 | |||
590 | static int b43_nphy_op_switch_channel(struct b43_wldev *dev, | ||
591 | unsigned int new_channel) | ||
592 | { | ||
593 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | ||
594 | if ((new_channel < 1) || (new_channel > 14)) | ||
595 | return -EINVAL; | ||
596 | } else { | ||
597 | if (new_channel > 200) | ||
598 | return -EINVAL; | ||
599 | } | ||
600 | |||
601 | return nphy_channel_switch(dev, new_channel); | ||
602 | } | ||
603 | |||
604 | static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev) | ||
605 | { | ||
606 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | ||
607 | return 1; | ||
608 | return 36; | ||
609 | } | ||
610 | |||
611 | const struct b43_phy_operations b43_phyops_n = { | ||
612 | .allocate = b43_nphy_op_allocate, | ||
613 | .init = b43_nphy_op_init, | ||
614 | .exit = b43_nphy_op_exit, | ||
615 | .phy_read = b43_nphy_op_read, | ||
616 | .phy_write = b43_nphy_op_write, | ||
617 | .radio_read = b43_nphy_op_radio_read, | ||
618 | .radio_write = b43_nphy_op_radio_write, | ||
619 | .software_rfkill = b43_nphy_op_software_rfkill, | ||
620 | .switch_channel = b43_nphy_op_switch_channel, | ||
621 | .get_default_chan = b43_nphy_op_get_default_chan, | ||
622 | .recalc_txpower = b43_nphy_op_recalc_txpower, | ||
623 | .adjust_txpower = b43_nphy_op_adjust_txpower, | ||
624 | }; | ||
diff --git a/drivers/net/wireless/b43/nphy.h b/drivers/net/wireless/b43/nphy.h index faf46b9cbf1b..3d1f65ed2012 100644 --- a/drivers/net/wireless/b43/nphy.h +++ b/drivers/net/wireless/b43/nphy.h | |||
@@ -1,7 +1,7 @@ | |||
1 | #ifndef B43_NPHY_H_ | 1 | #ifndef B43_NPHY_H_ |
2 | #define B43_NPHY_H_ | 2 | #define B43_NPHY_H_ |
3 | 3 | ||
4 | #include "phy.h" | 4 | #include "phy_common.h" |
5 | 5 | ||
6 | 6 | ||
7 | /* N-PHY registers. */ | 7 | /* N-PHY registers. */ |
@@ -919,54 +919,14 @@ | |||
919 | 919 | ||
920 | struct b43_wldev; | 920 | struct b43_wldev; |
921 | 921 | ||
922 | struct b43_phy_n { | ||
923 | bool initialised; | ||
922 | 924 | ||
923 | #ifdef CONFIG_B43_NPHY | 925 | //TODO lots of missing stuff |
924 | /* N-PHY support enabled */ | 926 | }; |
925 | 927 | ||
926 | int b43_phy_initn(struct b43_wldev *dev); | ||
927 | 928 | ||
928 | void b43_nphy_radio_turn_on(struct b43_wldev *dev); | 929 | struct b43_phy_operations; |
929 | void b43_nphy_radio_turn_off(struct b43_wldev *dev); | 930 | extern const struct b43_phy_operations b43_phyops_n; |
930 | 931 | ||
931 | int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel); | ||
932 | |||
933 | void b43_nphy_xmitpower(struct b43_wldev *dev); | ||
934 | void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna); | ||
935 | |||
936 | |||
937 | #else /* CONFIG_B43_NPHY */ | ||
938 | /* N-PHY support disabled */ | ||
939 | |||
940 | |||
941 | static inline | ||
942 | int b43_phy_initn(struct b43_wldev *dev) | ||
943 | { | ||
944 | return -EOPNOTSUPP; | ||
945 | } | ||
946 | |||
947 | static inline | ||
948 | void b43_nphy_radio_turn_on(struct b43_wldev *dev) | ||
949 | { | ||
950 | } | ||
951 | static inline | ||
952 | void b43_nphy_radio_turn_off(struct b43_wldev *dev) | ||
953 | { | ||
954 | } | ||
955 | |||
956 | static inline | ||
957 | int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel) | ||
958 | { | ||
959 | return -ENOSYS; | ||
960 | } | ||
961 | |||
962 | static inline | ||
963 | void b43_nphy_xmitpower(struct b43_wldev *dev) | ||
964 | { | ||
965 | } | ||
966 | static inline | ||
967 | void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) | ||
968 | { | ||
969 | } | ||
970 | |||
971 | #endif /* CONFIG_B43_NPHY */ | ||
972 | #endif /* B43_NPHY_H_ */ | 932 | #endif /* B43_NPHY_H_ */ |
diff --git a/drivers/net/wireless/b43/phy.c b/drivers/net/wireless/b43/phy.c index 305d4cd6fd03..02ae450beb00 100644 --- a/drivers/net/wireless/b43/phy.c +++ b/drivers/net/wireless/b43/phy.c | |||
@@ -39,160 +39,6 @@ | |||
39 | #include "wa.h" | 39 | #include "wa.h" |
40 | 40 | ||
41 | 41 | ||
42 | static const s8 b43_tssi2dbm_b_table[] = { | ||
43 | 0x4D, 0x4C, 0x4B, 0x4A, | ||
44 | 0x4A, 0x49, 0x48, 0x47, | ||
45 | 0x47, 0x46, 0x45, 0x45, | ||
46 | 0x44, 0x43, 0x42, 0x42, | ||
47 | 0x41, 0x40, 0x3F, 0x3E, | ||
48 | 0x3D, 0x3C, 0x3B, 0x3A, | ||
49 | 0x39, 0x38, 0x37, 0x36, | ||
50 | 0x35, 0x34, 0x32, 0x31, | ||
51 | 0x30, 0x2F, 0x2D, 0x2C, | ||
52 | 0x2B, 0x29, 0x28, 0x26, | ||
53 | 0x25, 0x23, 0x21, 0x1F, | ||
54 | 0x1D, 0x1A, 0x17, 0x14, | ||
55 | 0x10, 0x0C, 0x06, 0x00, | ||
56 | -7, -7, -7, -7, | ||
57 | -7, -7, -7, -7, | ||
58 | -7, -7, -7, -7, | ||
59 | }; | ||
60 | |||
61 | static const s8 b43_tssi2dbm_g_table[] = { | ||
62 | 77, 77, 77, 76, | ||
63 | 76, 76, 75, 75, | ||
64 | 74, 74, 73, 73, | ||
65 | 73, 72, 72, 71, | ||
66 | 71, 70, 70, 69, | ||
67 | 68, 68, 67, 67, | ||
68 | 66, 65, 65, 64, | ||
69 | 63, 63, 62, 61, | ||
70 | 60, 59, 58, 57, | ||
71 | 56, 55, 54, 53, | ||
72 | 52, 50, 49, 47, | ||
73 | 45, 43, 40, 37, | ||
74 | 33, 28, 22, 14, | ||
75 | 5, -7, -20, -20, | ||
76 | -20, -20, -20, -20, | ||
77 | -20, -20, -20, -20, | ||
78 | }; | ||
79 | |||
80 | const u8 b43_radio_channel_codes_bg[] = { | ||
81 | 12, 17, 22, 27, | ||
82 | 32, 37, 42, 47, | ||
83 | 52, 57, 62, 67, | ||
84 | 72, 84, | ||
85 | }; | ||
86 | |||
87 | #define bitrev4(tmp) (bitrev8(tmp) >> 4) | ||
88 | static void b43_phy_initg(struct b43_wldev *dev); | ||
89 | |||
90 | static void generate_rfatt_list(struct b43_wldev *dev, | ||
91 | struct b43_rfatt_list *list) | ||
92 | { | ||
93 | struct b43_phy *phy = &dev->phy; | ||
94 | |||
95 | /* APHY.rev < 5 || GPHY.rev < 6 */ | ||
96 | static const struct b43_rfatt rfatt_0[] = { | ||
97 | {.att = 3,.with_padmix = 0,}, | ||
98 | {.att = 1,.with_padmix = 0,}, | ||
99 | {.att = 5,.with_padmix = 0,}, | ||
100 | {.att = 7,.with_padmix = 0,}, | ||
101 | {.att = 9,.with_padmix = 0,}, | ||
102 | {.att = 2,.with_padmix = 0,}, | ||
103 | {.att = 0,.with_padmix = 0,}, | ||
104 | {.att = 4,.with_padmix = 0,}, | ||
105 | {.att = 6,.with_padmix = 0,}, | ||
106 | {.att = 8,.with_padmix = 0,}, | ||
107 | {.att = 1,.with_padmix = 1,}, | ||
108 | {.att = 2,.with_padmix = 1,}, | ||
109 | {.att = 3,.with_padmix = 1,}, | ||
110 | {.att = 4,.with_padmix = 1,}, | ||
111 | }; | ||
112 | /* Radio.rev == 8 && Radio.version == 0x2050 */ | ||
113 | static const struct b43_rfatt rfatt_1[] = { | ||
114 | {.att = 2,.with_padmix = 1,}, | ||
115 | {.att = 4,.with_padmix = 1,}, | ||
116 | {.att = 6,.with_padmix = 1,}, | ||
117 | {.att = 8,.with_padmix = 1,}, | ||
118 | {.att = 10,.with_padmix = 1,}, | ||
119 | {.att = 12,.with_padmix = 1,}, | ||
120 | {.att = 14,.with_padmix = 1,}, | ||
121 | }; | ||
122 | /* Otherwise */ | ||
123 | static const struct b43_rfatt rfatt_2[] = { | ||
124 | {.att = 0,.with_padmix = 1,}, | ||
125 | {.att = 2,.with_padmix = 1,}, | ||
126 | {.att = 4,.with_padmix = 1,}, | ||
127 | {.att = 6,.with_padmix = 1,}, | ||
128 | {.att = 8,.with_padmix = 1,}, | ||
129 | {.att = 9,.with_padmix = 1,}, | ||
130 | {.att = 9,.with_padmix = 1,}, | ||
131 | }; | ||
132 | |||
133 | if (!b43_has_hardware_pctl(phy)) { | ||
134 | /* Software pctl */ | ||
135 | list->list = rfatt_0; | ||
136 | list->len = ARRAY_SIZE(rfatt_0); | ||
137 | list->min_val = 0; | ||
138 | list->max_val = 9; | ||
139 | return; | ||
140 | } | ||
141 | if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) { | ||
142 | /* Hardware pctl */ | ||
143 | list->list = rfatt_1; | ||
144 | list->len = ARRAY_SIZE(rfatt_1); | ||
145 | list->min_val = 0; | ||
146 | list->max_val = 14; | ||
147 | return; | ||
148 | } | ||
149 | /* Hardware pctl */ | ||
150 | list->list = rfatt_2; | ||
151 | list->len = ARRAY_SIZE(rfatt_2); | ||
152 | list->min_val = 0; | ||
153 | list->max_val = 9; | ||
154 | } | ||
155 | |||
156 | static void generate_bbatt_list(struct b43_wldev *dev, | ||
157 | struct b43_bbatt_list *list) | ||
158 | { | ||
159 | static const struct b43_bbatt bbatt_0[] = { | ||
160 | {.att = 0,}, | ||
161 | {.att = 1,}, | ||
162 | {.att = 2,}, | ||
163 | {.att = 3,}, | ||
164 | {.att = 4,}, | ||
165 | {.att = 5,}, | ||
166 | {.att = 6,}, | ||
167 | {.att = 7,}, | ||
168 | {.att = 8,}, | ||
169 | }; | ||
170 | |||
171 | list->list = bbatt_0; | ||
172 | list->len = ARRAY_SIZE(bbatt_0); | ||
173 | list->min_val = 0; | ||
174 | list->max_val = 8; | ||
175 | } | ||
176 | |||
177 | bool b43_has_hardware_pctl(struct b43_phy *phy) | ||
178 | { | ||
179 | if (!phy->hardware_power_control) | ||
180 | return 0; | ||
181 | switch (phy->type) { | ||
182 | case B43_PHYTYPE_A: | ||
183 | if (phy->rev >= 5) | ||
184 | return 1; | ||
185 | break; | ||
186 | case B43_PHYTYPE_G: | ||
187 | if (phy->rev >= 6) | ||
188 | return 1; | ||
189 | break; | ||
190 | default: | ||
191 | B43_WARN_ON(1); | ||
192 | } | ||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | static void b43_shm_clear_tssi(struct b43_wldev *dev) | 42 | static void b43_shm_clear_tssi(struct b43_wldev *dev) |
197 | { | 43 | { |
198 | struct b43_phy *phy = &dev->phy; | 44 | struct b43_phy *phy = &dev->phy; |
@@ -212,1242 +58,6 @@ static void b43_shm_clear_tssi(struct b43_wldev *dev) | |||
212 | } | 58 | } |
213 | } | 59 | } |
214 | 60 | ||
215 | /* Lock the PHY registers against concurrent access from the microcode. | ||
216 | * This lock is nonrecursive. */ | ||
217 | void b43_phy_lock(struct b43_wldev *dev) | ||
218 | { | ||
219 | #if B43_DEBUG | ||
220 | B43_WARN_ON(dev->phy.phy_locked); | ||
221 | dev->phy.phy_locked = 1; | ||
222 | #endif | ||
223 | B43_WARN_ON(dev->dev->id.revision < 3); | ||
224 | |||
225 | if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP)) | ||
226 | b43_power_saving_ctl_bits(dev, B43_PS_AWAKE); | ||
227 | } | ||
228 | |||
229 | void b43_phy_unlock(struct b43_wldev *dev) | ||
230 | { | ||
231 | #if B43_DEBUG | ||
232 | B43_WARN_ON(!dev->phy.phy_locked); | ||
233 | dev->phy.phy_locked = 0; | ||
234 | #endif | ||
235 | B43_WARN_ON(dev->dev->id.revision < 3); | ||
236 | |||
237 | if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP)) | ||
238 | b43_power_saving_ctl_bits(dev, 0); | ||
239 | } | ||
240 | |||
241 | /* Different PHYs require different register routing flags. | ||
242 | * This adjusts (and does sanity checks on) the routing flags. | ||
243 | */ | ||
244 | static inline u16 adjust_phyreg_for_phytype(struct b43_phy *phy, | ||
245 | u16 offset, struct b43_wldev *dev) | ||
246 | { | ||
247 | if (phy->type == B43_PHYTYPE_A) { | ||
248 | /* OFDM registers are base-registers for the A-PHY. */ | ||
249 | if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) { | ||
250 | offset &= ~B43_PHYROUTE; | ||
251 | offset |= B43_PHYROUTE_BASE; | ||
252 | } | ||
253 | } | ||
254 | |||
255 | #if B43_DEBUG | ||
256 | if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) { | ||
257 | /* Ext-G registers are only available on G-PHYs */ | ||
258 | if (phy->type != B43_PHYTYPE_G) { | ||
259 | b43err(dev->wl, "Invalid EXT-G PHY access at " | ||
260 | "0x%04X on PHY type %u\n", offset, phy->type); | ||
261 | dump_stack(); | ||
262 | } | ||
263 | } | ||
264 | if ((offset & B43_PHYROUTE) == B43_PHYROUTE_N_BMODE) { | ||
265 | /* N-BMODE registers are only available on N-PHYs */ | ||
266 | if (phy->type != B43_PHYTYPE_N) { | ||
267 | b43err(dev->wl, "Invalid N-BMODE PHY access at " | ||
268 | "0x%04X on PHY type %u\n", offset, phy->type); | ||
269 | dump_stack(); | ||
270 | } | ||
271 | } | ||
272 | #endif /* B43_DEBUG */ | ||
273 | |||
274 | return offset; | ||
275 | } | ||
276 | |||
277 | u16 b43_phy_read(struct b43_wldev * dev, u16 offset) | ||
278 | { | ||
279 | struct b43_phy *phy = &dev->phy; | ||
280 | |||
281 | offset = adjust_phyreg_for_phytype(phy, offset, dev); | ||
282 | b43_write16(dev, B43_MMIO_PHY_CONTROL, offset); | ||
283 | return b43_read16(dev, B43_MMIO_PHY_DATA); | ||
284 | } | ||
285 | |||
286 | void b43_phy_write(struct b43_wldev *dev, u16 offset, u16 val) | ||
287 | { | ||
288 | struct b43_phy *phy = &dev->phy; | ||
289 | |||
290 | offset = adjust_phyreg_for_phytype(phy, offset, dev); | ||
291 | b43_write16(dev, B43_MMIO_PHY_CONTROL, offset); | ||
292 | b43_write16(dev, B43_MMIO_PHY_DATA, val); | ||
293 | } | ||
294 | |||
295 | void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask) | ||
296 | { | ||
297 | b43_phy_write(dev, offset, | ||
298 | b43_phy_read(dev, offset) & mask); | ||
299 | } | ||
300 | |||
301 | void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set) | ||
302 | { | ||
303 | b43_phy_write(dev, offset, | ||
304 | b43_phy_read(dev, offset) | set); | ||
305 | } | ||
306 | |||
307 | void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set) | ||
308 | { | ||
309 | b43_phy_write(dev, offset, | ||
310 | (b43_phy_read(dev, offset) & mask) | set); | ||
311 | } | ||
312 | |||
313 | /* Adjust the transmission power output (G-PHY) */ | ||
314 | void b43_set_txpower_g(struct b43_wldev *dev, | ||
315 | const struct b43_bbatt *bbatt, | ||
316 | const struct b43_rfatt *rfatt, u8 tx_control) | ||
317 | { | ||
318 | struct b43_phy *phy = &dev->phy; | ||
319 | struct b43_txpower_lo_control *lo = phy->lo_control; | ||
320 | u16 bb, rf; | ||
321 | u16 tx_bias, tx_magn; | ||
322 | |||
323 | bb = bbatt->att; | ||
324 | rf = rfatt->att; | ||
325 | tx_bias = lo->tx_bias; | ||
326 | tx_magn = lo->tx_magn; | ||
327 | if (unlikely(tx_bias == 0xFF)) | ||
328 | tx_bias = 0; | ||
329 | |||
330 | /* Save the values for later */ | ||
331 | phy->tx_control = tx_control; | ||
332 | memcpy(&phy->rfatt, rfatt, sizeof(*rfatt)); | ||
333 | phy->rfatt.with_padmix = !!(tx_control & B43_TXCTL_TXMIX); | ||
334 | memcpy(&phy->bbatt, bbatt, sizeof(*bbatt)); | ||
335 | |||
336 | if (b43_debug(dev, B43_DBG_XMITPOWER)) { | ||
337 | b43dbg(dev->wl, "Tuning TX-power to bbatt(%u), " | ||
338 | "rfatt(%u), tx_control(0x%02X), " | ||
339 | "tx_bias(0x%02X), tx_magn(0x%02X)\n", | ||
340 | bb, rf, tx_control, tx_bias, tx_magn); | ||
341 | } | ||
342 | |||
343 | b43_phy_set_baseband_attenuation(dev, bb); | ||
344 | b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_RFATT, rf); | ||
345 | if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) { | ||
346 | b43_radio_write16(dev, 0x43, | ||
347 | (rf & 0x000F) | (tx_control & 0x0070)); | ||
348 | } else { | ||
349 | b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43) | ||
350 | & 0xFFF0) | (rf & 0x000F)); | ||
351 | b43_radio_write16(dev, 0x52, (b43_radio_read16(dev, 0x52) | ||
352 | & ~0x0070) | (tx_control & | ||
353 | 0x0070)); | ||
354 | } | ||
355 | if (has_tx_magnification(phy)) { | ||
356 | b43_radio_write16(dev, 0x52, tx_magn | tx_bias); | ||
357 | } else { | ||
358 | b43_radio_write16(dev, 0x52, (b43_radio_read16(dev, 0x52) | ||
359 | & 0xFFF0) | (tx_bias & 0x000F)); | ||
360 | } | ||
361 | if (phy->type == B43_PHYTYPE_G) | ||
362 | b43_lo_g_adjust(dev); | ||
363 | } | ||
364 | |||
365 | static void default_baseband_attenuation(struct b43_wldev *dev, | ||
366 | struct b43_bbatt *bb) | ||
367 | { | ||
368 | struct b43_phy *phy = &dev->phy; | ||
369 | |||
370 | if (phy->radio_ver == 0x2050 && phy->radio_rev < 6) | ||
371 | bb->att = 0; | ||
372 | else | ||
373 | bb->att = 2; | ||
374 | } | ||
375 | |||
376 | static void default_radio_attenuation(struct b43_wldev *dev, | ||
377 | struct b43_rfatt *rf) | ||
378 | { | ||
379 | struct ssb_bus *bus = dev->dev->bus; | ||
380 | struct b43_phy *phy = &dev->phy; | ||
381 | |||
382 | rf->with_padmix = 0; | ||
383 | |||
384 | if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM && | ||
385 | bus->boardinfo.type == SSB_BOARD_BCM4309G) { | ||
386 | if (bus->boardinfo.rev < 0x43) { | ||
387 | rf->att = 2; | ||
388 | return; | ||
389 | } else if (bus->boardinfo.rev < 0x51) { | ||
390 | rf->att = 3; | ||
391 | return; | ||
392 | } | ||
393 | } | ||
394 | |||
395 | if (phy->type == B43_PHYTYPE_A) { | ||
396 | rf->att = 0x60; | ||
397 | return; | ||
398 | } | ||
399 | |||
400 | switch (phy->radio_ver) { | ||
401 | case 0x2053: | ||
402 | switch (phy->radio_rev) { | ||
403 | case 1: | ||
404 | rf->att = 6; | ||
405 | return; | ||
406 | } | ||
407 | break; | ||
408 | case 0x2050: | ||
409 | switch (phy->radio_rev) { | ||
410 | case 0: | ||
411 | rf->att = 5; | ||
412 | return; | ||
413 | case 1: | ||
414 | if (phy->type == B43_PHYTYPE_G) { | ||
415 | if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM | ||
416 | && bus->boardinfo.type == SSB_BOARD_BCM4309G | ||
417 | && bus->boardinfo.rev >= 30) | ||
418 | rf->att = 3; | ||
419 | else if (bus->boardinfo.vendor == | ||
420 | SSB_BOARDVENDOR_BCM | ||
421 | && bus->boardinfo.type == | ||
422 | SSB_BOARD_BU4306) | ||
423 | rf->att = 3; | ||
424 | else | ||
425 | rf->att = 1; | ||
426 | } else { | ||
427 | if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM | ||
428 | && bus->boardinfo.type == SSB_BOARD_BCM4309G | ||
429 | && bus->boardinfo.rev >= 30) | ||
430 | rf->att = 7; | ||
431 | else | ||
432 | rf->att = 6; | ||
433 | } | ||
434 | return; | ||
435 | case 2: | ||
436 | if (phy->type == B43_PHYTYPE_G) { | ||
437 | if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM | ||
438 | && bus->boardinfo.type == SSB_BOARD_BCM4309G | ||
439 | && bus->boardinfo.rev >= 30) | ||
440 | rf->att = 3; | ||
441 | else if (bus->boardinfo.vendor == | ||
442 | SSB_BOARDVENDOR_BCM | ||
443 | && bus->boardinfo.type == | ||
444 | SSB_BOARD_BU4306) | ||
445 | rf->att = 5; | ||
446 | else if (bus->chip_id == 0x4320) | ||
447 | rf->att = 4; | ||
448 | else | ||
449 | rf->att = 3; | ||
450 | } else | ||
451 | rf->att = 6; | ||
452 | return; | ||
453 | case 3: | ||
454 | rf->att = 5; | ||
455 | return; | ||
456 | case 4: | ||
457 | case 5: | ||
458 | rf->att = 1; | ||
459 | return; | ||
460 | case 6: | ||
461 | case 7: | ||
462 | rf->att = 5; | ||
463 | return; | ||
464 | case 8: | ||
465 | rf->att = 0xA; | ||
466 | rf->with_padmix = 1; | ||
467 | return; | ||
468 | case 9: | ||
469 | default: | ||
470 | rf->att = 5; | ||
471 | return; | ||
472 | } | ||
473 | } | ||
474 | rf->att = 5; | ||
475 | } | ||
476 | |||
477 | static u16 default_tx_control(struct b43_wldev *dev) | ||
478 | { | ||
479 | struct b43_phy *phy = &dev->phy; | ||
480 | |||
481 | if (phy->radio_ver != 0x2050) | ||
482 | return 0; | ||
483 | if (phy->radio_rev == 1) | ||
484 | return B43_TXCTL_PA2DB | B43_TXCTL_TXMIX; | ||
485 | if (phy->radio_rev < 6) | ||
486 | return B43_TXCTL_PA2DB; | ||
487 | if (phy->radio_rev == 8) | ||
488 | return B43_TXCTL_TXMIX; | ||
489 | return 0; | ||
490 | } | ||
491 | |||
492 | /* This func is called "PHY calibrate" in the specs... */ | ||
493 | void b43_phy_early_init(struct b43_wldev *dev) | ||
494 | { | ||
495 | struct b43_phy *phy = &dev->phy; | ||
496 | struct b43_txpower_lo_control *lo = phy->lo_control; | ||
497 | |||
498 | default_baseband_attenuation(dev, &phy->bbatt); | ||
499 | default_radio_attenuation(dev, &phy->rfatt); | ||
500 | phy->tx_control = (default_tx_control(dev) << 4); | ||
501 | |||
502 | /* Commit previous writes */ | ||
503 | b43_read32(dev, B43_MMIO_MACCTL); | ||
504 | |||
505 | if (phy->type == B43_PHYTYPE_B || phy->type == B43_PHYTYPE_G) { | ||
506 | generate_rfatt_list(dev, &lo->rfatt_list); | ||
507 | generate_bbatt_list(dev, &lo->bbatt_list); | ||
508 | } | ||
509 | if (phy->type == B43_PHYTYPE_G && phy->rev == 1) { | ||
510 | /* Workaround: Temporarly disable gmode through the early init | ||
511 | * phase, as the gmode stuff is not needed for phy rev 1 */ | ||
512 | phy->gmode = 0; | ||
513 | b43_wireless_core_reset(dev, 0); | ||
514 | b43_phy_initg(dev); | ||
515 | phy->gmode = 1; | ||
516 | b43_wireless_core_reset(dev, B43_TMSLOW_GMODE); | ||
517 | } | ||
518 | } | ||
519 | |||
520 | /* GPHY_TSSI_Power_Lookup_Table_Init */ | ||
521 | static void b43_gphy_tssi_power_lt_init(struct b43_wldev *dev) | ||
522 | { | ||
523 | struct b43_phy *phy = &dev->phy; | ||
524 | int i; | ||
525 | u16 value; | ||
526 | |||
527 | for (i = 0; i < 32; i++) | ||
528 | b43_ofdmtab_write16(dev, 0x3C20, i, phy->tssi2dbm[i]); | ||
529 | for (i = 32; i < 64; i++) | ||
530 | b43_ofdmtab_write16(dev, 0x3C00, i - 32, phy->tssi2dbm[i]); | ||
531 | for (i = 0; i < 64; i += 2) { | ||
532 | value = (u16) phy->tssi2dbm[i]; | ||
533 | value |= ((u16) phy->tssi2dbm[i + 1]) << 8; | ||
534 | b43_phy_write(dev, 0x380 + (i / 2), value); | ||
535 | } | ||
536 | } | ||
537 | |||
538 | /* GPHY_Gain_Lookup_Table_Init */ | ||
539 | static void b43_gphy_gain_lt_init(struct b43_wldev *dev) | ||
540 | { | ||
541 | struct b43_phy *phy = &dev->phy; | ||
542 | struct b43_txpower_lo_control *lo = phy->lo_control; | ||
543 | u16 nr_written = 0; | ||
544 | u16 tmp; | ||
545 | u8 rf, bb; | ||
546 | |||
547 | for (rf = 0; rf < lo->rfatt_list.len; rf++) { | ||
548 | for (bb = 0; bb < lo->bbatt_list.len; bb++) { | ||
549 | if (nr_written >= 0x40) | ||
550 | return; | ||
551 | tmp = lo->bbatt_list.list[bb].att; | ||
552 | tmp <<= 8; | ||
553 | if (phy->radio_rev == 8) | ||
554 | tmp |= 0x50; | ||
555 | else | ||
556 | tmp |= 0x40; | ||
557 | tmp |= lo->rfatt_list.list[rf].att; | ||
558 | b43_phy_write(dev, 0x3C0 + nr_written, tmp); | ||
559 | nr_written++; | ||
560 | } | ||
561 | } | ||
562 | } | ||
563 | |||
564 | static void hardware_pctl_init_aphy(struct b43_wldev *dev) | ||
565 | { | ||
566 | //TODO | ||
567 | } | ||
568 | |||
569 | static void hardware_pctl_init_gphy(struct b43_wldev *dev) | ||
570 | { | ||
571 | struct b43_phy *phy = &dev->phy; | ||
572 | |||
573 | b43_phy_write(dev, 0x0036, (b43_phy_read(dev, 0x0036) & 0xFFC0) | ||
574 | | (phy->tgt_idle_tssi - phy->cur_idle_tssi)); | ||
575 | b43_phy_write(dev, 0x0478, (b43_phy_read(dev, 0x0478) & 0xFF00) | ||
576 | | (phy->tgt_idle_tssi - phy->cur_idle_tssi)); | ||
577 | b43_gphy_tssi_power_lt_init(dev); | ||
578 | b43_gphy_gain_lt_init(dev); | ||
579 | b43_phy_write(dev, 0x0060, b43_phy_read(dev, 0x0060) & 0xFFBF); | ||
580 | b43_phy_write(dev, 0x0014, 0x0000); | ||
581 | |||
582 | B43_WARN_ON(phy->rev < 6); | ||
583 | b43_phy_write(dev, 0x0478, b43_phy_read(dev, 0x0478) | ||
584 | | 0x0800); | ||
585 | b43_phy_write(dev, 0x0478, b43_phy_read(dev, 0x0478) | ||
586 | & 0xFEFF); | ||
587 | b43_phy_write(dev, 0x0801, b43_phy_read(dev, 0x0801) | ||
588 | & 0xFFBF); | ||
589 | |||
590 | b43_gphy_dc_lt_init(dev, 1); | ||
591 | } | ||
592 | |||
593 | /* HardwarePowerControl init for A and G PHY */ | ||
594 | static void b43_hardware_pctl_init(struct b43_wldev *dev) | ||
595 | { | ||
596 | struct b43_phy *phy = &dev->phy; | ||
597 | |||
598 | if (!b43_has_hardware_pctl(phy)) { | ||
599 | /* No hardware power control */ | ||
600 | b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_HWPCTL); | ||
601 | return; | ||
602 | } | ||
603 | /* Init the hwpctl related hardware */ | ||
604 | switch (phy->type) { | ||
605 | case B43_PHYTYPE_A: | ||
606 | hardware_pctl_init_aphy(dev); | ||
607 | break; | ||
608 | case B43_PHYTYPE_G: | ||
609 | hardware_pctl_init_gphy(dev); | ||
610 | break; | ||
611 | default: | ||
612 | B43_WARN_ON(1); | ||
613 | } | ||
614 | /* Enable hardware pctl in firmware. */ | ||
615 | b43_hf_write(dev, b43_hf_read(dev) | B43_HF_HWPCTL); | ||
616 | } | ||
617 | |||
618 | static void b43_hardware_pctl_early_init(struct b43_wldev *dev) | ||
619 | { | ||
620 | struct b43_phy *phy = &dev->phy; | ||
621 | |||
622 | if (!b43_has_hardware_pctl(phy)) { | ||
623 | b43_phy_write(dev, 0x047A, 0xC111); | ||
624 | return; | ||
625 | } | ||
626 | |||
627 | b43_phy_write(dev, 0x0036, b43_phy_read(dev, 0x0036) & 0xFEFF); | ||
628 | b43_phy_write(dev, 0x002F, 0x0202); | ||
629 | b43_phy_write(dev, 0x047C, b43_phy_read(dev, 0x047C) | 0x0002); | ||
630 | b43_phy_write(dev, 0x047A, b43_phy_read(dev, 0x047A) | 0xF000); | ||
631 | if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) { | ||
632 | b43_phy_write(dev, 0x047A, (b43_phy_read(dev, 0x047A) | ||
633 | & 0xFF0F) | 0x0010); | ||
634 | b43_phy_write(dev, 0x005D, b43_phy_read(dev, 0x005D) | ||
635 | | 0x8000); | ||
636 | b43_phy_write(dev, 0x004E, (b43_phy_read(dev, 0x004E) | ||
637 | & 0xFFC0) | 0x0010); | ||
638 | b43_phy_write(dev, 0x002E, 0xC07F); | ||
639 | b43_phy_write(dev, 0x0036, b43_phy_read(dev, 0x0036) | ||
640 | | 0x0400); | ||
641 | } else { | ||
642 | b43_phy_write(dev, 0x0036, b43_phy_read(dev, 0x0036) | ||
643 | | 0x0200); | ||
644 | b43_phy_write(dev, 0x0036, b43_phy_read(dev, 0x0036) | ||
645 | | 0x0400); | ||
646 | b43_phy_write(dev, 0x005D, b43_phy_read(dev, 0x005D) | ||
647 | & 0x7FFF); | ||
648 | b43_phy_write(dev, 0x004F, b43_phy_read(dev, 0x004F) | ||
649 | & 0xFFFE); | ||
650 | b43_phy_write(dev, 0x004E, (b43_phy_read(dev, 0x004E) | ||
651 | & 0xFFC0) | 0x0010); | ||
652 | b43_phy_write(dev, 0x002E, 0xC07F); | ||
653 | b43_phy_write(dev, 0x047A, (b43_phy_read(dev, 0x047A) | ||
654 | & 0xFF0F) | 0x0010); | ||
655 | } | ||
656 | } | ||
657 | |||
658 | /* Intialize B/G PHY power control | ||
659 | * as described in http://bcm-specs.sipsolutions.net/InitPowerControl | ||
660 | */ | ||
661 | static void b43_phy_init_pctl(struct b43_wldev *dev) | ||
662 | { | ||
663 | struct ssb_bus *bus = dev->dev->bus; | ||
664 | struct b43_phy *phy = &dev->phy; | ||
665 | struct b43_rfatt old_rfatt; | ||
666 | struct b43_bbatt old_bbatt; | ||
667 | u8 old_tx_control = 0; | ||
668 | |||
669 | if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) && | ||
670 | (bus->boardinfo.type == SSB_BOARD_BU4306)) | ||
671 | return; | ||
672 | |||
673 | b43_phy_write(dev, 0x0028, 0x8018); | ||
674 | |||
675 | /* This does something with the Analog... */ | ||
676 | b43_write16(dev, B43_MMIO_PHY0, b43_read16(dev, B43_MMIO_PHY0) | ||
677 | & 0xFFDF); | ||
678 | |||
679 | if (phy->type == B43_PHYTYPE_G && !phy->gmode) | ||
680 | return; | ||
681 | b43_hardware_pctl_early_init(dev); | ||
682 | if (phy->cur_idle_tssi == 0) { | ||
683 | if (phy->radio_ver == 0x2050 && phy->analog == 0) { | ||
684 | b43_radio_write16(dev, 0x0076, | ||
685 | (b43_radio_read16(dev, 0x0076) | ||
686 | & 0x00F7) | 0x0084); | ||
687 | } else { | ||
688 | struct b43_rfatt rfatt; | ||
689 | struct b43_bbatt bbatt; | ||
690 | |||
691 | memcpy(&old_rfatt, &phy->rfatt, sizeof(old_rfatt)); | ||
692 | memcpy(&old_bbatt, &phy->bbatt, sizeof(old_bbatt)); | ||
693 | old_tx_control = phy->tx_control; | ||
694 | |||
695 | bbatt.att = 11; | ||
696 | if (phy->radio_rev == 8) { | ||
697 | rfatt.att = 15; | ||
698 | rfatt.with_padmix = 1; | ||
699 | } else { | ||
700 | rfatt.att = 9; | ||
701 | rfatt.with_padmix = 0; | ||
702 | } | ||
703 | b43_set_txpower_g(dev, &bbatt, &rfatt, 0); | ||
704 | } | ||
705 | b43_dummy_transmission(dev); | ||
706 | phy->cur_idle_tssi = b43_phy_read(dev, B43_PHY_ITSSI); | ||
707 | if (B43_DEBUG) { | ||
708 | /* Current-Idle-TSSI sanity check. */ | ||
709 | if (abs(phy->cur_idle_tssi - phy->tgt_idle_tssi) >= 20) { | ||
710 | b43dbg(dev->wl, | ||
711 | "!WARNING! Idle-TSSI phy->cur_idle_tssi " | ||
712 | "measuring failed. (cur=%d, tgt=%d). Disabling TX power " | ||
713 | "adjustment.\n", phy->cur_idle_tssi, | ||
714 | phy->tgt_idle_tssi); | ||
715 | phy->cur_idle_tssi = 0; | ||
716 | } | ||
717 | } | ||
718 | if (phy->radio_ver == 0x2050 && phy->analog == 0) { | ||
719 | b43_radio_write16(dev, 0x0076, | ||
720 | b43_radio_read16(dev, 0x0076) | ||
721 | & 0xFF7B); | ||
722 | } else { | ||
723 | b43_set_txpower_g(dev, &old_bbatt, | ||
724 | &old_rfatt, old_tx_control); | ||
725 | } | ||
726 | } | ||
727 | b43_hardware_pctl_init(dev); | ||
728 | b43_shm_clear_tssi(dev); | ||
729 | } | ||
730 | |||
731 | static void b43_phy_rssiagc(struct b43_wldev *dev, u8 enable) | ||
732 | { | ||
733 | int i; | ||
734 | |||
735 | if (dev->phy.rev < 3) { | ||
736 | if (enable) | ||
737 | for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++) { | ||
738 | b43_ofdmtab_write16(dev, | ||
739 | B43_OFDMTAB_LNAHPFGAIN1, i, 0xFFF8); | ||
740 | b43_ofdmtab_write16(dev, | ||
741 | B43_OFDMTAB_WRSSI, i, 0xFFF8); | ||
742 | } | ||
743 | else | ||
744 | for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++) { | ||
745 | b43_ofdmtab_write16(dev, | ||
746 | B43_OFDMTAB_LNAHPFGAIN1, i, b43_tab_rssiagc1[i]); | ||
747 | b43_ofdmtab_write16(dev, | ||
748 | B43_OFDMTAB_WRSSI, i, b43_tab_rssiagc1[i]); | ||
749 | } | ||
750 | } else { | ||
751 | if (enable) | ||
752 | for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++) | ||
753 | b43_ofdmtab_write16(dev, | ||
754 | B43_OFDMTAB_WRSSI, i, 0x0820); | ||
755 | else | ||
756 | for (i = 0; i < B43_TAB_RSSIAGC2_SIZE; i++) | ||
757 | b43_ofdmtab_write16(dev, | ||
758 | B43_OFDMTAB_WRSSI, i, b43_tab_rssiagc2[i]); | ||
759 | } | ||
760 | } | ||
761 | |||
762 | static void b43_phy_ww(struct b43_wldev *dev) | ||
763 | { | ||
764 | u16 b, curr_s, best_s = 0xFFFF; | ||
765 | int i; | ||
766 | |||
767 | b43_phy_write(dev, B43_PHY_CRS0, | ||
768 | b43_phy_read(dev, B43_PHY_CRS0) & ~B43_PHY_CRS0_EN); | ||
769 | b43_phy_write(dev, B43_PHY_OFDM(0x1B), | ||
770 | b43_phy_read(dev, B43_PHY_OFDM(0x1B)) | 0x1000); | ||
771 | b43_phy_write(dev, B43_PHY_OFDM(0x82), | ||
772 | (b43_phy_read(dev, B43_PHY_OFDM(0x82)) & 0xF0FF) | 0x0300); | ||
773 | b43_radio_write16(dev, 0x0009, | ||
774 | b43_radio_read16(dev, 0x0009) | 0x0080); | ||
775 | b43_radio_write16(dev, 0x0012, | ||
776 | (b43_radio_read16(dev, 0x0012) & 0xFFFC) | 0x0002); | ||
777 | b43_wa_initgains(dev); | ||
778 | b43_phy_write(dev, B43_PHY_OFDM(0xBA), 0x3ED5); | ||
779 | b = b43_phy_read(dev, B43_PHY_PWRDOWN); | ||
780 | b43_phy_write(dev, B43_PHY_PWRDOWN, (b & 0xFFF8) | 0x0005); | ||
781 | b43_radio_write16(dev, 0x0004, | ||
782 | b43_radio_read16(dev, 0x0004) | 0x0004); | ||
783 | for (i = 0x10; i <= 0x20; i++) { | ||
784 | b43_radio_write16(dev, 0x0013, i); | ||
785 | curr_s = b43_phy_read(dev, B43_PHY_OTABLEQ) & 0x00FF; | ||
786 | if (!curr_s) { | ||
787 | best_s = 0x0000; | ||
788 | break; | ||
789 | } else if (curr_s >= 0x0080) | ||
790 | curr_s = 0x0100 - curr_s; | ||
791 | if (curr_s < best_s) | ||
792 | best_s = curr_s; | ||
793 | } | ||
794 | b43_phy_write(dev, B43_PHY_PWRDOWN, b); | ||
795 | b43_radio_write16(dev, 0x0004, | ||
796 | b43_radio_read16(dev, 0x0004) & 0xFFFB); | ||
797 | b43_radio_write16(dev, 0x0013, best_s); | ||
798 | b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 0, 0xFFEC); | ||
799 | b43_phy_write(dev, B43_PHY_OFDM(0xB7), 0x1E80); | ||
800 | b43_phy_write(dev, B43_PHY_OFDM(0xB6), 0x1C00); | ||
801 | b43_phy_write(dev, B43_PHY_OFDM(0xB5), 0x0EC0); | ||
802 | b43_phy_write(dev, B43_PHY_OFDM(0xB2), 0x00C0); | ||
803 | b43_phy_write(dev, B43_PHY_OFDM(0xB9), 0x1FFF); | ||
804 | b43_phy_write(dev, B43_PHY_OFDM(0xBB), | ||
805 | (b43_phy_read(dev, B43_PHY_OFDM(0xBB)) & 0xF000) | 0x0053); | ||
806 | b43_phy_write(dev, B43_PHY_OFDM61, | ||
807 | (b43_phy_read(dev, B43_PHY_OFDM61) & 0xFE1F) | 0x0120); | ||
808 | b43_phy_write(dev, B43_PHY_OFDM(0x13), | ||
809 | (b43_phy_read(dev, B43_PHY_OFDM(0x13)) & 0x0FFF) | 0x3000); | ||
810 | b43_phy_write(dev, B43_PHY_OFDM(0x14), | ||
811 | (b43_phy_read(dev, B43_PHY_OFDM(0x14)) & 0x0FFF) | 0x3000); | ||
812 | b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 6, 0x0017); | ||
813 | for (i = 0; i < 6; i++) | ||
814 | b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, i, 0x000F); | ||
815 | b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0D, 0x000E); | ||
816 | b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0E, 0x0011); | ||
817 | b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0F, 0x0013); | ||
818 | b43_phy_write(dev, B43_PHY_OFDM(0x33), 0x5030); | ||
819 | b43_phy_write(dev, B43_PHY_CRS0, | ||
820 | b43_phy_read(dev, B43_PHY_CRS0) | B43_PHY_CRS0_EN); | ||
821 | } | ||
822 | |||
823 | /* Initialize APHY. This is also called for the GPHY in some cases. */ | ||
824 | static void b43_phy_inita(struct b43_wldev *dev) | ||
825 | { | ||
826 | struct ssb_bus *bus = dev->dev->bus; | ||
827 | struct b43_phy *phy = &dev->phy; | ||
828 | |||
829 | might_sleep(); | ||
830 | |||
831 | if (phy->rev >= 6) { | ||
832 | if (phy->type == B43_PHYTYPE_A) | ||
833 | b43_phy_write(dev, B43_PHY_OFDM(0x1B), | ||
834 | b43_phy_read(dev, B43_PHY_OFDM(0x1B)) & ~0x1000); | ||
835 | if (b43_phy_read(dev, B43_PHY_ENCORE) & B43_PHY_ENCORE_EN) | ||
836 | b43_phy_write(dev, B43_PHY_ENCORE, | ||
837 | b43_phy_read(dev, B43_PHY_ENCORE) | 0x0010); | ||
838 | else | ||
839 | b43_phy_write(dev, B43_PHY_ENCORE, | ||
840 | b43_phy_read(dev, B43_PHY_ENCORE) & ~0x1010); | ||
841 | } | ||
842 | |||
843 | b43_wa_all(dev); | ||
844 | |||
845 | if (phy->type == B43_PHYTYPE_A) { | ||
846 | if (phy->gmode && (phy->rev < 3)) | ||
847 | b43_phy_write(dev, 0x0034, | ||
848 | b43_phy_read(dev, 0x0034) | 0x0001); | ||
849 | b43_phy_rssiagc(dev, 0); | ||
850 | |||
851 | b43_phy_write(dev, B43_PHY_CRS0, | ||
852 | b43_phy_read(dev, B43_PHY_CRS0) | B43_PHY_CRS0_EN); | ||
853 | |||
854 | b43_radio_init2060(dev); | ||
855 | |||
856 | if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) && | ||
857 | ((bus->boardinfo.type == SSB_BOARD_BU4306) || | ||
858 | (bus->boardinfo.type == SSB_BOARD_BU4309))) { | ||
859 | ; //TODO: A PHY LO | ||
860 | } | ||
861 | |||
862 | if (phy->rev >= 3) | ||
863 | b43_phy_ww(dev); | ||
864 | |||
865 | hardware_pctl_init_aphy(dev); | ||
866 | |||
867 | //TODO: radar detection | ||
868 | } | ||
869 | |||
870 | if ((phy->type == B43_PHYTYPE_G) && | ||
871 | (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)) { | ||
872 | b43_phy_write(dev, B43_PHY_OFDM(0x6E), | ||
873 | (b43_phy_read(dev, B43_PHY_OFDM(0x6E)) | ||
874 | & 0xE000) | 0x3CF); | ||
875 | } | ||
876 | } | ||
877 | |||
878 | static void b43_phy_initb5(struct b43_wldev *dev) | ||
879 | { | ||
880 | struct ssb_bus *bus = dev->dev->bus; | ||
881 | struct b43_phy *phy = &dev->phy; | ||
882 | u16 offset, value; | ||
883 | u8 old_channel; | ||
884 | |||
885 | if (phy->analog == 1) { | ||
886 | b43_radio_write16(dev, 0x007A, b43_radio_read16(dev, 0x007A) | ||
887 | | 0x0050); | ||
888 | } | ||
889 | if ((bus->boardinfo.vendor != SSB_BOARDVENDOR_BCM) && | ||
890 | (bus->boardinfo.type != SSB_BOARD_BU4306)) { | ||
891 | value = 0x2120; | ||
892 | for (offset = 0x00A8; offset < 0x00C7; offset++) { | ||
893 | b43_phy_write(dev, offset, value); | ||
894 | value += 0x202; | ||
895 | } | ||
896 | } | ||
897 | b43_phy_write(dev, 0x0035, (b43_phy_read(dev, 0x0035) & 0xF0FF) | ||
898 | | 0x0700); | ||
899 | if (phy->radio_ver == 0x2050) | ||
900 | b43_phy_write(dev, 0x0038, 0x0667); | ||
901 | |||
902 | if (phy->gmode || phy->rev >= 2) { | ||
903 | if (phy->radio_ver == 0x2050) { | ||
904 | b43_radio_write16(dev, 0x007A, | ||
905 | b43_radio_read16(dev, 0x007A) | ||
906 | | 0x0020); | ||
907 | b43_radio_write16(dev, 0x0051, | ||
908 | b43_radio_read16(dev, 0x0051) | ||
909 | | 0x0004); | ||
910 | } | ||
911 | b43_write16(dev, B43_MMIO_PHY_RADIO, 0x0000); | ||
912 | |||
913 | b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) | 0x0100); | ||
914 | b43_phy_write(dev, 0x042B, b43_phy_read(dev, 0x042B) | 0x2000); | ||
915 | |||
916 | b43_phy_write(dev, 0x001C, 0x186A); | ||
917 | |||
918 | b43_phy_write(dev, 0x0013, | ||
919 | (b43_phy_read(dev, 0x0013) & 0x00FF) | 0x1900); | ||
920 | b43_phy_write(dev, 0x0035, | ||
921 | (b43_phy_read(dev, 0x0035) & 0xFFC0) | 0x0064); | ||
922 | b43_phy_write(dev, 0x005D, | ||
923 | (b43_phy_read(dev, 0x005D) & 0xFF80) | 0x000A); | ||
924 | } | ||
925 | |||
926 | if (dev->bad_frames_preempt) { | ||
927 | b43_phy_write(dev, B43_PHY_RADIO_BITFIELD, | ||
928 | b43_phy_read(dev, | ||
929 | B43_PHY_RADIO_BITFIELD) | (1 << 11)); | ||
930 | } | ||
931 | |||
932 | if (phy->analog == 1) { | ||
933 | b43_phy_write(dev, 0x0026, 0xCE00); | ||
934 | b43_phy_write(dev, 0x0021, 0x3763); | ||
935 | b43_phy_write(dev, 0x0022, 0x1BC3); | ||
936 | b43_phy_write(dev, 0x0023, 0x06F9); | ||
937 | b43_phy_write(dev, 0x0024, 0x037E); | ||
938 | } else | ||
939 | b43_phy_write(dev, 0x0026, 0xCC00); | ||
940 | b43_phy_write(dev, 0x0030, 0x00C6); | ||
941 | b43_write16(dev, 0x03EC, 0x3F22); | ||
942 | |||
943 | if (phy->analog == 1) | ||
944 | b43_phy_write(dev, 0x0020, 0x3E1C); | ||
945 | else | ||
946 | b43_phy_write(dev, 0x0020, 0x301C); | ||
947 | |||
948 | if (phy->analog == 0) | ||
949 | b43_write16(dev, 0x03E4, 0x3000); | ||
950 | |||
951 | old_channel = phy->channel; | ||
952 | /* Force to channel 7, even if not supported. */ | ||
953 | b43_radio_selectchannel(dev, 7, 0); | ||
954 | |||
955 | if (phy->radio_ver != 0x2050) { | ||
956 | b43_radio_write16(dev, 0x0075, 0x0080); | ||
957 | b43_radio_write16(dev, 0x0079, 0x0081); | ||
958 | } | ||
959 | |||
960 | b43_radio_write16(dev, 0x0050, 0x0020); | ||
961 | b43_radio_write16(dev, 0x0050, 0x0023); | ||
962 | |||
963 | if (phy->radio_ver == 0x2050) { | ||
964 | b43_radio_write16(dev, 0x0050, 0x0020); | ||
965 | b43_radio_write16(dev, 0x005A, 0x0070); | ||
966 | } | ||
967 | |||
968 | b43_radio_write16(dev, 0x005B, 0x007B); | ||
969 | b43_radio_write16(dev, 0x005C, 0x00B0); | ||
970 | |||
971 | b43_radio_write16(dev, 0x007A, b43_radio_read16(dev, 0x007A) | 0x0007); | ||
972 | |||
973 | b43_radio_selectchannel(dev, old_channel, 0); | ||
974 | |||
975 | b43_phy_write(dev, 0x0014, 0x0080); | ||
976 | b43_phy_write(dev, 0x0032, 0x00CA); | ||
977 | b43_phy_write(dev, 0x002A, 0x88A3); | ||
978 | |||
979 | b43_set_txpower_g(dev, &phy->bbatt, &phy->rfatt, phy->tx_control); | ||
980 | |||
981 | if (phy->radio_ver == 0x2050) | ||
982 | b43_radio_write16(dev, 0x005D, 0x000D); | ||
983 | |||
984 | b43_write16(dev, 0x03E4, (b43_read16(dev, 0x03E4) & 0xFFC0) | 0x0004); | ||
985 | } | ||
986 | |||
987 | static void b43_phy_initb6(struct b43_wldev *dev) | ||
988 | { | ||
989 | struct b43_phy *phy = &dev->phy; | ||
990 | u16 offset, val; | ||
991 | u8 old_channel; | ||
992 | |||
993 | b43_phy_write(dev, 0x003E, 0x817A); | ||
994 | b43_radio_write16(dev, 0x007A, | ||
995 | (b43_radio_read16(dev, 0x007A) | 0x0058)); | ||
996 | if (phy->radio_rev == 4 || phy->radio_rev == 5) { | ||
997 | b43_radio_write16(dev, 0x51, 0x37); | ||
998 | b43_radio_write16(dev, 0x52, 0x70); | ||
999 | b43_radio_write16(dev, 0x53, 0xB3); | ||
1000 | b43_radio_write16(dev, 0x54, 0x9B); | ||
1001 | b43_radio_write16(dev, 0x5A, 0x88); | ||
1002 | b43_radio_write16(dev, 0x5B, 0x88); | ||
1003 | b43_radio_write16(dev, 0x5D, 0x88); | ||
1004 | b43_radio_write16(dev, 0x5E, 0x88); | ||
1005 | b43_radio_write16(dev, 0x7D, 0x88); | ||
1006 | b43_hf_write(dev, b43_hf_read(dev) | ||
1007 | | B43_HF_TSSIRPSMW); | ||
1008 | } | ||
1009 | B43_WARN_ON(phy->radio_rev == 6 || phy->radio_rev == 7); /* We had code for these revs here... */ | ||
1010 | if (phy->radio_rev == 8) { | ||
1011 | b43_radio_write16(dev, 0x51, 0); | ||
1012 | b43_radio_write16(dev, 0x52, 0x40); | ||
1013 | b43_radio_write16(dev, 0x53, 0xB7); | ||
1014 | b43_radio_write16(dev, 0x54, 0x98); | ||
1015 | b43_radio_write16(dev, 0x5A, 0x88); | ||
1016 | b43_radio_write16(dev, 0x5B, 0x6B); | ||
1017 | b43_radio_write16(dev, 0x5C, 0x0F); | ||
1018 | if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_ALTIQ) { | ||
1019 | b43_radio_write16(dev, 0x5D, 0xFA); | ||
1020 | b43_radio_write16(dev, 0x5E, 0xD8); | ||
1021 | } else { | ||
1022 | b43_radio_write16(dev, 0x5D, 0xF5); | ||
1023 | b43_radio_write16(dev, 0x5E, 0xB8); | ||
1024 | } | ||
1025 | b43_radio_write16(dev, 0x0073, 0x0003); | ||
1026 | b43_radio_write16(dev, 0x007D, 0x00A8); | ||
1027 | b43_radio_write16(dev, 0x007C, 0x0001); | ||
1028 | b43_radio_write16(dev, 0x007E, 0x0008); | ||
1029 | } | ||
1030 | val = 0x1E1F; | ||
1031 | for (offset = 0x0088; offset < 0x0098; offset++) { | ||
1032 | b43_phy_write(dev, offset, val); | ||
1033 | val -= 0x0202; | ||
1034 | } | ||
1035 | val = 0x3E3F; | ||
1036 | for (offset = 0x0098; offset < 0x00A8; offset++) { | ||
1037 | b43_phy_write(dev, offset, val); | ||
1038 | val -= 0x0202; | ||
1039 | } | ||
1040 | val = 0x2120; | ||
1041 | for (offset = 0x00A8; offset < 0x00C8; offset++) { | ||
1042 | b43_phy_write(dev, offset, (val & 0x3F3F)); | ||
1043 | val += 0x0202; | ||
1044 | } | ||
1045 | if (phy->type == B43_PHYTYPE_G) { | ||
1046 | b43_radio_write16(dev, 0x007A, | ||
1047 | b43_radio_read16(dev, 0x007A) | 0x0020); | ||
1048 | b43_radio_write16(dev, 0x0051, | ||
1049 | b43_radio_read16(dev, 0x0051) | 0x0004); | ||
1050 | b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) | 0x0100); | ||
1051 | b43_phy_write(dev, 0x042B, b43_phy_read(dev, 0x042B) | 0x2000); | ||
1052 | b43_phy_write(dev, 0x5B, 0); | ||
1053 | b43_phy_write(dev, 0x5C, 0); | ||
1054 | } | ||
1055 | |||
1056 | old_channel = phy->channel; | ||
1057 | if (old_channel >= 8) | ||
1058 | b43_radio_selectchannel(dev, 1, 0); | ||
1059 | else | ||
1060 | b43_radio_selectchannel(dev, 13, 0); | ||
1061 | |||
1062 | b43_radio_write16(dev, 0x0050, 0x0020); | ||
1063 | b43_radio_write16(dev, 0x0050, 0x0023); | ||
1064 | udelay(40); | ||
1065 | if (phy->radio_rev < 6 || phy->radio_rev == 8) { | ||
1066 | b43_radio_write16(dev, 0x7C, (b43_radio_read16(dev, 0x7C) | ||
1067 | | 0x0002)); | ||
1068 | b43_radio_write16(dev, 0x50, 0x20); | ||
1069 | } | ||
1070 | if (phy->radio_rev <= 2) { | ||
1071 | b43_radio_write16(dev, 0x7C, 0x20); | ||
1072 | b43_radio_write16(dev, 0x5A, 0x70); | ||
1073 | b43_radio_write16(dev, 0x5B, 0x7B); | ||
1074 | b43_radio_write16(dev, 0x5C, 0xB0); | ||
1075 | } | ||
1076 | b43_radio_write16(dev, 0x007A, | ||
1077 | (b43_radio_read16(dev, 0x007A) & 0x00F8) | 0x0007); | ||
1078 | |||
1079 | b43_radio_selectchannel(dev, old_channel, 0); | ||
1080 | |||
1081 | b43_phy_write(dev, 0x0014, 0x0200); | ||
1082 | if (phy->radio_rev >= 6) | ||
1083 | b43_phy_write(dev, 0x2A, 0x88C2); | ||
1084 | else | ||
1085 | b43_phy_write(dev, 0x2A, 0x8AC0); | ||
1086 | b43_phy_write(dev, 0x0038, 0x0668); | ||
1087 | b43_set_txpower_g(dev, &phy->bbatt, &phy->rfatt, phy->tx_control); | ||
1088 | if (phy->radio_rev <= 5) { | ||
1089 | b43_phy_write(dev, 0x5D, (b43_phy_read(dev, 0x5D) | ||
1090 | & 0xFF80) | 0x0003); | ||
1091 | } | ||
1092 | if (phy->radio_rev <= 2) | ||
1093 | b43_radio_write16(dev, 0x005D, 0x000D); | ||
1094 | |||
1095 | if (phy->analog == 4) { | ||
1096 | b43_write16(dev, 0x3E4, 9); | ||
1097 | b43_phy_write(dev, 0x61, b43_phy_read(dev, 0x61) | ||
1098 | & 0x0FFF); | ||
1099 | } else { | ||
1100 | b43_phy_write(dev, 0x0002, (b43_phy_read(dev, 0x0002) & 0xFFC0) | ||
1101 | | 0x0004); | ||
1102 | } | ||
1103 | if (phy->type == B43_PHYTYPE_B) | ||
1104 | B43_WARN_ON(1); | ||
1105 | else if (phy->type == B43_PHYTYPE_G) | ||
1106 | b43_write16(dev, 0x03E6, 0x0); | ||
1107 | } | ||
1108 | |||
1109 | static void b43_calc_loopback_gain(struct b43_wldev *dev) | ||
1110 | { | ||
1111 | struct b43_phy *phy = &dev->phy; | ||
1112 | u16 backup_phy[16] = { 0 }; | ||
1113 | u16 backup_radio[3]; | ||
1114 | u16 backup_bband; | ||
1115 | u16 i, j, loop_i_max; | ||
1116 | u16 trsw_rx; | ||
1117 | u16 loop1_outer_done, loop1_inner_done; | ||
1118 | |||
1119 | backup_phy[0] = b43_phy_read(dev, B43_PHY_CRS0); | ||
1120 | backup_phy[1] = b43_phy_read(dev, B43_PHY_CCKBBANDCFG); | ||
1121 | backup_phy[2] = b43_phy_read(dev, B43_PHY_RFOVER); | ||
1122 | backup_phy[3] = b43_phy_read(dev, B43_PHY_RFOVERVAL); | ||
1123 | if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */ | ||
1124 | backup_phy[4] = b43_phy_read(dev, B43_PHY_ANALOGOVER); | ||
1125 | backup_phy[5] = b43_phy_read(dev, B43_PHY_ANALOGOVERVAL); | ||
1126 | } | ||
1127 | backup_phy[6] = b43_phy_read(dev, B43_PHY_CCK(0x5A)); | ||
1128 | backup_phy[7] = b43_phy_read(dev, B43_PHY_CCK(0x59)); | ||
1129 | backup_phy[8] = b43_phy_read(dev, B43_PHY_CCK(0x58)); | ||
1130 | backup_phy[9] = b43_phy_read(dev, B43_PHY_CCK(0x0A)); | ||
1131 | backup_phy[10] = b43_phy_read(dev, B43_PHY_CCK(0x03)); | ||
1132 | backup_phy[11] = b43_phy_read(dev, B43_PHY_LO_MASK); | ||
1133 | backup_phy[12] = b43_phy_read(dev, B43_PHY_LO_CTL); | ||
1134 | backup_phy[13] = b43_phy_read(dev, B43_PHY_CCK(0x2B)); | ||
1135 | backup_phy[14] = b43_phy_read(dev, B43_PHY_PGACTL); | ||
1136 | backup_phy[15] = b43_phy_read(dev, B43_PHY_LO_LEAKAGE); | ||
1137 | backup_bband = phy->bbatt.att; | ||
1138 | backup_radio[0] = b43_radio_read16(dev, 0x52); | ||
1139 | backup_radio[1] = b43_radio_read16(dev, 0x43); | ||
1140 | backup_radio[2] = b43_radio_read16(dev, 0x7A); | ||
1141 | |||
1142 | b43_phy_write(dev, B43_PHY_CRS0, | ||
1143 | b43_phy_read(dev, B43_PHY_CRS0) & 0x3FFF); | ||
1144 | b43_phy_write(dev, B43_PHY_CCKBBANDCFG, | ||
1145 | b43_phy_read(dev, B43_PHY_CCKBBANDCFG) | 0x8000); | ||
1146 | b43_phy_write(dev, B43_PHY_RFOVER, | ||
1147 | b43_phy_read(dev, B43_PHY_RFOVER) | 0x0002); | ||
1148 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1149 | b43_phy_read(dev, B43_PHY_RFOVERVAL) & 0xFFFD); | ||
1150 | b43_phy_write(dev, B43_PHY_RFOVER, | ||
1151 | b43_phy_read(dev, B43_PHY_RFOVER) | 0x0001); | ||
1152 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1153 | b43_phy_read(dev, B43_PHY_RFOVERVAL) & 0xFFFE); | ||
1154 | if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */ | ||
1155 | b43_phy_write(dev, B43_PHY_ANALOGOVER, | ||
1156 | b43_phy_read(dev, B43_PHY_ANALOGOVER) | 0x0001); | ||
1157 | b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, | ||
1158 | b43_phy_read(dev, | ||
1159 | B43_PHY_ANALOGOVERVAL) & 0xFFFE); | ||
1160 | b43_phy_write(dev, B43_PHY_ANALOGOVER, | ||
1161 | b43_phy_read(dev, B43_PHY_ANALOGOVER) | 0x0002); | ||
1162 | b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, | ||
1163 | b43_phy_read(dev, | ||
1164 | B43_PHY_ANALOGOVERVAL) & 0xFFFD); | ||
1165 | } | ||
1166 | b43_phy_write(dev, B43_PHY_RFOVER, | ||
1167 | b43_phy_read(dev, B43_PHY_RFOVER) | 0x000C); | ||
1168 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1169 | b43_phy_read(dev, B43_PHY_RFOVERVAL) | 0x000C); | ||
1170 | b43_phy_write(dev, B43_PHY_RFOVER, | ||
1171 | b43_phy_read(dev, B43_PHY_RFOVER) | 0x0030); | ||
1172 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1173 | (b43_phy_read(dev, B43_PHY_RFOVERVAL) | ||
1174 | & 0xFFCF) | 0x10); | ||
1175 | |||
1176 | b43_phy_write(dev, B43_PHY_CCK(0x5A), 0x0780); | ||
1177 | b43_phy_write(dev, B43_PHY_CCK(0x59), 0xC810); | ||
1178 | b43_phy_write(dev, B43_PHY_CCK(0x58), 0x000D); | ||
1179 | |||
1180 | b43_phy_write(dev, B43_PHY_CCK(0x0A), | ||
1181 | b43_phy_read(dev, B43_PHY_CCK(0x0A)) | 0x2000); | ||
1182 | if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */ | ||
1183 | b43_phy_write(dev, B43_PHY_ANALOGOVER, | ||
1184 | b43_phy_read(dev, B43_PHY_ANALOGOVER) | 0x0004); | ||
1185 | b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, | ||
1186 | b43_phy_read(dev, | ||
1187 | B43_PHY_ANALOGOVERVAL) & 0xFFFB); | ||
1188 | } | ||
1189 | b43_phy_write(dev, B43_PHY_CCK(0x03), | ||
1190 | (b43_phy_read(dev, B43_PHY_CCK(0x03)) | ||
1191 | & 0xFF9F) | 0x40); | ||
1192 | |||
1193 | if (phy->radio_rev == 8) { | ||
1194 | b43_radio_write16(dev, 0x43, 0x000F); | ||
1195 | } else { | ||
1196 | b43_radio_write16(dev, 0x52, 0); | ||
1197 | b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43) | ||
1198 | & 0xFFF0) | 0x9); | ||
1199 | } | ||
1200 | b43_phy_set_baseband_attenuation(dev, 11); | ||
1201 | |||
1202 | if (phy->rev >= 3) | ||
1203 | b43_phy_write(dev, B43_PHY_LO_MASK, 0xC020); | ||
1204 | else | ||
1205 | b43_phy_write(dev, B43_PHY_LO_MASK, 0x8020); | ||
1206 | b43_phy_write(dev, B43_PHY_LO_CTL, 0); | ||
1207 | |||
1208 | b43_phy_write(dev, B43_PHY_CCK(0x2B), | ||
1209 | (b43_phy_read(dev, B43_PHY_CCK(0x2B)) | ||
1210 | & 0xFFC0) | 0x01); | ||
1211 | b43_phy_write(dev, B43_PHY_CCK(0x2B), | ||
1212 | (b43_phy_read(dev, B43_PHY_CCK(0x2B)) | ||
1213 | & 0xC0FF) | 0x800); | ||
1214 | |||
1215 | b43_phy_write(dev, B43_PHY_RFOVER, | ||
1216 | b43_phy_read(dev, B43_PHY_RFOVER) | 0x0100); | ||
1217 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1218 | b43_phy_read(dev, B43_PHY_RFOVERVAL) & 0xCFFF); | ||
1219 | |||
1220 | if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) { | ||
1221 | if (phy->rev >= 7) { | ||
1222 | b43_phy_write(dev, B43_PHY_RFOVER, | ||
1223 | b43_phy_read(dev, B43_PHY_RFOVER) | ||
1224 | | 0x0800); | ||
1225 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1226 | b43_phy_read(dev, B43_PHY_RFOVERVAL) | ||
1227 | | 0x8000); | ||
1228 | } | ||
1229 | } | ||
1230 | b43_radio_write16(dev, 0x7A, b43_radio_read16(dev, 0x7A) | ||
1231 | & 0x00F7); | ||
1232 | |||
1233 | j = 0; | ||
1234 | loop_i_max = (phy->radio_rev == 8) ? 15 : 9; | ||
1235 | for (i = 0; i < loop_i_max; i++) { | ||
1236 | for (j = 0; j < 16; j++) { | ||
1237 | b43_radio_write16(dev, 0x43, i); | ||
1238 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1239 | (b43_phy_read(dev, B43_PHY_RFOVERVAL) | ||
1240 | & 0xF0FF) | (j << 8)); | ||
1241 | b43_phy_write(dev, B43_PHY_PGACTL, | ||
1242 | (b43_phy_read(dev, B43_PHY_PGACTL) | ||
1243 | & 0x0FFF) | 0xA000); | ||
1244 | b43_phy_write(dev, B43_PHY_PGACTL, | ||
1245 | b43_phy_read(dev, B43_PHY_PGACTL) | ||
1246 | | 0xF000); | ||
1247 | udelay(20); | ||
1248 | if (b43_phy_read(dev, B43_PHY_LO_LEAKAGE) >= 0xDFC) | ||
1249 | goto exit_loop1; | ||
1250 | } | ||
1251 | } | ||
1252 | exit_loop1: | ||
1253 | loop1_outer_done = i; | ||
1254 | loop1_inner_done = j; | ||
1255 | if (j >= 8) { | ||
1256 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1257 | b43_phy_read(dev, B43_PHY_RFOVERVAL) | ||
1258 | | 0x30); | ||
1259 | trsw_rx = 0x1B; | ||
1260 | for (j = j - 8; j < 16; j++) { | ||
1261 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1262 | (b43_phy_read(dev, B43_PHY_RFOVERVAL) | ||
1263 | & 0xF0FF) | (j << 8)); | ||
1264 | b43_phy_write(dev, B43_PHY_PGACTL, | ||
1265 | (b43_phy_read(dev, B43_PHY_PGACTL) | ||
1266 | & 0x0FFF) | 0xA000); | ||
1267 | b43_phy_write(dev, B43_PHY_PGACTL, | ||
1268 | b43_phy_read(dev, B43_PHY_PGACTL) | ||
1269 | | 0xF000); | ||
1270 | udelay(20); | ||
1271 | trsw_rx -= 3; | ||
1272 | if (b43_phy_read(dev, B43_PHY_LO_LEAKAGE) >= 0xDFC) | ||
1273 | goto exit_loop2; | ||
1274 | } | ||
1275 | } else | ||
1276 | trsw_rx = 0x18; | ||
1277 | exit_loop2: | ||
1278 | |||
1279 | if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */ | ||
1280 | b43_phy_write(dev, B43_PHY_ANALOGOVER, backup_phy[4]); | ||
1281 | b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, backup_phy[5]); | ||
1282 | } | ||
1283 | b43_phy_write(dev, B43_PHY_CCK(0x5A), backup_phy[6]); | ||
1284 | b43_phy_write(dev, B43_PHY_CCK(0x59), backup_phy[7]); | ||
1285 | b43_phy_write(dev, B43_PHY_CCK(0x58), backup_phy[8]); | ||
1286 | b43_phy_write(dev, B43_PHY_CCK(0x0A), backup_phy[9]); | ||
1287 | b43_phy_write(dev, B43_PHY_CCK(0x03), backup_phy[10]); | ||
1288 | b43_phy_write(dev, B43_PHY_LO_MASK, backup_phy[11]); | ||
1289 | b43_phy_write(dev, B43_PHY_LO_CTL, backup_phy[12]); | ||
1290 | b43_phy_write(dev, B43_PHY_CCK(0x2B), backup_phy[13]); | ||
1291 | b43_phy_write(dev, B43_PHY_PGACTL, backup_phy[14]); | ||
1292 | |||
1293 | b43_phy_set_baseband_attenuation(dev, backup_bband); | ||
1294 | |||
1295 | b43_radio_write16(dev, 0x52, backup_radio[0]); | ||
1296 | b43_radio_write16(dev, 0x43, backup_radio[1]); | ||
1297 | b43_radio_write16(dev, 0x7A, backup_radio[2]); | ||
1298 | |||
1299 | b43_phy_write(dev, B43_PHY_RFOVER, backup_phy[2] | 0x0003); | ||
1300 | udelay(10); | ||
1301 | b43_phy_write(dev, B43_PHY_RFOVER, backup_phy[2]); | ||
1302 | b43_phy_write(dev, B43_PHY_RFOVERVAL, backup_phy[3]); | ||
1303 | b43_phy_write(dev, B43_PHY_CRS0, backup_phy[0]); | ||
1304 | b43_phy_write(dev, B43_PHY_CCKBBANDCFG, backup_phy[1]); | ||
1305 | |||
1306 | phy->max_lb_gain = | ||
1307 | ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11; | ||
1308 | phy->trsw_rx_gain = trsw_rx * 2; | ||
1309 | } | ||
1310 | |||
1311 | static void b43_phy_initg(struct b43_wldev *dev) | ||
1312 | { | ||
1313 | struct b43_phy *phy = &dev->phy; | ||
1314 | u16 tmp; | ||
1315 | |||
1316 | if (phy->rev == 1) | ||
1317 | b43_phy_initb5(dev); | ||
1318 | else | ||
1319 | b43_phy_initb6(dev); | ||
1320 | |||
1321 | if (phy->rev >= 2 || phy->gmode) | ||
1322 | b43_phy_inita(dev); | ||
1323 | |||
1324 | if (phy->rev >= 2) { | ||
1325 | b43_phy_write(dev, B43_PHY_ANALOGOVER, 0); | ||
1326 | b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, 0); | ||
1327 | } | ||
1328 | if (phy->rev == 2) { | ||
1329 | b43_phy_write(dev, B43_PHY_RFOVER, 0); | ||
1330 | b43_phy_write(dev, B43_PHY_PGACTL, 0xC0); | ||
1331 | } | ||
1332 | if (phy->rev > 5) { | ||
1333 | b43_phy_write(dev, B43_PHY_RFOVER, 0x400); | ||
1334 | b43_phy_write(dev, B43_PHY_PGACTL, 0xC0); | ||
1335 | } | ||
1336 | if (phy->gmode || phy->rev >= 2) { | ||
1337 | tmp = b43_phy_read(dev, B43_PHY_VERSION_OFDM); | ||
1338 | tmp &= B43_PHYVER_VERSION; | ||
1339 | if (tmp == 3 || tmp == 5) { | ||
1340 | b43_phy_write(dev, B43_PHY_OFDM(0xC2), 0x1816); | ||
1341 | b43_phy_write(dev, B43_PHY_OFDM(0xC3), 0x8006); | ||
1342 | } | ||
1343 | if (tmp == 5) { | ||
1344 | b43_phy_write(dev, B43_PHY_OFDM(0xCC), | ||
1345 | (b43_phy_read(dev, B43_PHY_OFDM(0xCC)) | ||
1346 | & 0x00FF) | 0x1F00); | ||
1347 | } | ||
1348 | } | ||
1349 | if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2) | ||
1350 | b43_phy_write(dev, B43_PHY_OFDM(0x7E), 0x78); | ||
1351 | if (phy->radio_rev == 8) { | ||
1352 | b43_phy_write(dev, B43_PHY_EXTG(0x01), | ||
1353 | b43_phy_read(dev, B43_PHY_EXTG(0x01)) | ||
1354 | | 0x80); | ||
1355 | b43_phy_write(dev, B43_PHY_OFDM(0x3E), | ||
1356 | b43_phy_read(dev, B43_PHY_OFDM(0x3E)) | ||
1357 | | 0x4); | ||
1358 | } | ||
1359 | if (has_loopback_gain(phy)) | ||
1360 | b43_calc_loopback_gain(dev); | ||
1361 | |||
1362 | if (phy->radio_rev != 8) { | ||
1363 | if (phy->initval == 0xFFFF) | ||
1364 | phy->initval = b43_radio_init2050(dev); | ||
1365 | else | ||
1366 | b43_radio_write16(dev, 0x0078, phy->initval); | ||
1367 | } | ||
1368 | b43_lo_g_init(dev); | ||
1369 | if (has_tx_magnification(phy)) { | ||
1370 | b43_radio_write16(dev, 0x52, | ||
1371 | (b43_radio_read16(dev, 0x52) & 0xFF00) | ||
1372 | | phy->lo_control->tx_bias | phy-> | ||
1373 | lo_control->tx_magn); | ||
1374 | } else { | ||
1375 | b43_radio_write16(dev, 0x52, | ||
1376 | (b43_radio_read16(dev, 0x52) & 0xFFF0) | ||
1377 | | phy->lo_control->tx_bias); | ||
1378 | } | ||
1379 | if (phy->rev >= 6) { | ||
1380 | b43_phy_write(dev, B43_PHY_CCK(0x36), | ||
1381 | (b43_phy_read(dev, B43_PHY_CCK(0x36)) | ||
1382 | & 0x0FFF) | (phy->lo_control-> | ||
1383 | tx_bias << 12)); | ||
1384 | } | ||
1385 | if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) | ||
1386 | b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8075); | ||
1387 | else | ||
1388 | b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x807F); | ||
1389 | if (phy->rev < 2) | ||
1390 | b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x101); | ||
1391 | else | ||
1392 | b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x202); | ||
1393 | if (phy->gmode || phy->rev >= 2) { | ||
1394 | b43_lo_g_adjust(dev); | ||
1395 | b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078); | ||
1396 | } | ||
1397 | |||
1398 | if (!(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) { | ||
1399 | /* The specs state to update the NRSSI LT with | ||
1400 | * the value 0x7FFFFFFF here. I think that is some weird | ||
1401 | * compiler optimization in the original driver. | ||
1402 | * Essentially, what we do here is resetting all NRSSI LT | ||
1403 | * entries to -32 (see the clamp_val() in nrssi_hw_update()) | ||
1404 | */ | ||
1405 | b43_nrssi_hw_update(dev, 0xFFFF); //FIXME? | ||
1406 | b43_calc_nrssi_threshold(dev); | ||
1407 | } else if (phy->gmode || phy->rev >= 2) { | ||
1408 | if (phy->nrssi[0] == -1000) { | ||
1409 | B43_WARN_ON(phy->nrssi[1] != -1000); | ||
1410 | b43_calc_nrssi_slope(dev); | ||
1411 | } else | ||
1412 | b43_calc_nrssi_threshold(dev); | ||
1413 | } | ||
1414 | if (phy->radio_rev == 8) | ||
1415 | b43_phy_write(dev, B43_PHY_EXTG(0x05), 0x3230); | ||
1416 | b43_phy_init_pctl(dev); | ||
1417 | /* FIXME: The spec says in the following if, the 0 should be replaced | ||
1418 | 'if OFDM may not be used in the current locale' | ||
1419 | but OFDM is legal everywhere */ | ||
1420 | if ((dev->dev->bus->chip_id == 0x4306 | ||
1421 | && dev->dev->bus->chip_package == 2) || 0) { | ||
1422 | b43_phy_write(dev, B43_PHY_CRS0, b43_phy_read(dev, B43_PHY_CRS0) | ||
1423 | & 0xBFFF); | ||
1424 | b43_phy_write(dev, B43_PHY_OFDM(0xC3), | ||
1425 | b43_phy_read(dev, B43_PHY_OFDM(0xC3)) | ||
1426 | & 0x7FFF); | ||
1427 | } | ||
1428 | } | ||
1429 | |||
1430 | /* Set the baseband attenuation value on chip. */ | ||
1431 | void b43_phy_set_baseband_attenuation(struct b43_wldev *dev, | ||
1432 | u16 baseband_attenuation) | ||
1433 | { | ||
1434 | struct b43_phy *phy = &dev->phy; | ||
1435 | |||
1436 | if (phy->analog == 0) { | ||
1437 | b43_write16(dev, B43_MMIO_PHY0, (b43_read16(dev, B43_MMIO_PHY0) | ||
1438 | & 0xFFF0) | | ||
1439 | baseband_attenuation); | ||
1440 | } else if (phy->analog > 1) { | ||
1441 | b43_phy_write(dev, B43_PHY_DACCTL, | ||
1442 | (b43_phy_read(dev, B43_PHY_DACCTL) | ||
1443 | & 0xFFC3) | (baseband_attenuation << 2)); | ||
1444 | } else { | ||
1445 | b43_phy_write(dev, B43_PHY_DACCTL, | ||
1446 | (b43_phy_read(dev, B43_PHY_DACCTL) | ||
1447 | & 0xFF87) | (baseband_attenuation << 3)); | ||
1448 | } | ||
1449 | } | ||
1450 | |||
1451 | /* http://bcm-specs.sipsolutions.net/EstimatePowerOut | 61 | /* http://bcm-specs.sipsolutions.net/EstimatePowerOut |
1452 | * This function converts a TSSI value to dBm in Q5.2 | 62 | * This function converts a TSSI value to dBm in Q5.2 |
1453 | */ | 63 | */ |
@@ -1819,2009 +429,6 @@ int b43_phy_init_tssi2dbm_table(struct b43_wldev *dev) | |||
1819 | return 0; | 429 | return 0; |
1820 | } | 430 | } |
1821 | 431 | ||
1822 | int b43_phy_init(struct b43_wldev *dev) | ||
1823 | { | ||
1824 | struct b43_phy *phy = &dev->phy; | ||
1825 | bool unsupported = 0; | ||
1826 | int err = 0; | ||
1827 | |||
1828 | switch (phy->type) { | ||
1829 | case B43_PHYTYPE_A: | ||
1830 | if (phy->rev == 2 || phy->rev == 3) | ||
1831 | b43_phy_inita(dev); | ||
1832 | else | ||
1833 | unsupported = 1; | ||
1834 | break; | ||
1835 | case B43_PHYTYPE_G: | ||
1836 | b43_phy_initg(dev); | ||
1837 | break; | ||
1838 | case B43_PHYTYPE_N: | ||
1839 | err = b43_phy_initn(dev); | ||
1840 | break; | ||
1841 | default: | ||
1842 | unsupported = 1; | ||
1843 | } | ||
1844 | if (unsupported) | ||
1845 | b43err(dev->wl, "Unknown PHYTYPE found\n"); | ||
1846 | |||
1847 | return err; | ||
1848 | } | ||
1849 | |||
1850 | void b43_set_rx_antenna(struct b43_wldev *dev, int antenna) | ||
1851 | { | ||
1852 | struct b43_phy *phy = &dev->phy; | ||
1853 | u64 hf; | ||
1854 | u16 tmp; | ||
1855 | int autodiv = 0; | ||
1856 | |||
1857 | if (antenna == B43_ANTENNA_AUTO0 || antenna == B43_ANTENNA_AUTO1) | ||
1858 | autodiv = 1; | ||
1859 | |||
1860 | hf = b43_hf_read(dev); | ||
1861 | hf &= ~B43_HF_ANTDIVHELP; | ||
1862 | b43_hf_write(dev, hf); | ||
1863 | |||
1864 | switch (phy->type) { | ||
1865 | case B43_PHYTYPE_A: | ||
1866 | case B43_PHYTYPE_G: | ||
1867 | tmp = b43_phy_read(dev, B43_PHY_BBANDCFG); | ||
1868 | tmp &= ~B43_PHY_BBANDCFG_RXANT; | ||
1869 | tmp |= (autodiv ? B43_ANTENNA_AUTO0 : antenna) | ||
1870 | << B43_PHY_BBANDCFG_RXANT_SHIFT; | ||
1871 | b43_phy_write(dev, B43_PHY_BBANDCFG, tmp); | ||
1872 | |||
1873 | if (autodiv) { | ||
1874 | tmp = b43_phy_read(dev, B43_PHY_ANTDWELL); | ||
1875 | if (antenna == B43_ANTENNA_AUTO0) | ||
1876 | tmp &= ~B43_PHY_ANTDWELL_AUTODIV1; | ||
1877 | else | ||
1878 | tmp |= B43_PHY_ANTDWELL_AUTODIV1; | ||
1879 | b43_phy_write(dev, B43_PHY_ANTDWELL, tmp); | ||
1880 | } | ||
1881 | if (phy->type == B43_PHYTYPE_G) { | ||
1882 | tmp = b43_phy_read(dev, B43_PHY_ANTWRSETT); | ||
1883 | if (autodiv) | ||
1884 | tmp |= B43_PHY_ANTWRSETT_ARXDIV; | ||
1885 | else | ||
1886 | tmp &= ~B43_PHY_ANTWRSETT_ARXDIV; | ||
1887 | b43_phy_write(dev, B43_PHY_ANTWRSETT, tmp); | ||
1888 | if (phy->rev >= 2) { | ||
1889 | tmp = b43_phy_read(dev, B43_PHY_OFDM61); | ||
1890 | tmp |= B43_PHY_OFDM61_10; | ||
1891 | b43_phy_write(dev, B43_PHY_OFDM61, tmp); | ||
1892 | |||
1893 | tmp = | ||
1894 | b43_phy_read(dev, B43_PHY_DIVSRCHGAINBACK); | ||
1895 | tmp = (tmp & 0xFF00) | 0x15; | ||
1896 | b43_phy_write(dev, B43_PHY_DIVSRCHGAINBACK, | ||
1897 | tmp); | ||
1898 | |||
1899 | if (phy->rev == 2) { | ||
1900 | b43_phy_write(dev, B43_PHY_ADIVRELATED, | ||
1901 | 8); | ||
1902 | } else { | ||
1903 | tmp = | ||
1904 | b43_phy_read(dev, | ||
1905 | B43_PHY_ADIVRELATED); | ||
1906 | tmp = (tmp & 0xFF00) | 8; | ||
1907 | b43_phy_write(dev, B43_PHY_ADIVRELATED, | ||
1908 | tmp); | ||
1909 | } | ||
1910 | } | ||
1911 | if (phy->rev >= 6) | ||
1912 | b43_phy_write(dev, B43_PHY_OFDM9B, 0xDC); | ||
1913 | } else { | ||
1914 | if (phy->rev < 3) { | ||
1915 | tmp = b43_phy_read(dev, B43_PHY_ANTDWELL); | ||
1916 | tmp = (tmp & 0xFF00) | 0x24; | ||
1917 | b43_phy_write(dev, B43_PHY_ANTDWELL, tmp); | ||
1918 | } else { | ||
1919 | tmp = b43_phy_read(dev, B43_PHY_OFDM61); | ||
1920 | tmp |= 0x10; | ||
1921 | b43_phy_write(dev, B43_PHY_OFDM61, tmp); | ||
1922 | if (phy->analog == 3) { | ||
1923 | b43_phy_write(dev, B43_PHY_CLIPPWRDOWNT, | ||
1924 | 0x1D); | ||
1925 | b43_phy_write(dev, B43_PHY_ADIVRELATED, | ||
1926 | 8); | ||
1927 | } else { | ||
1928 | b43_phy_write(dev, B43_PHY_CLIPPWRDOWNT, | ||
1929 | 0x3A); | ||
1930 | tmp = | ||
1931 | b43_phy_read(dev, | ||
1932 | B43_PHY_ADIVRELATED); | ||
1933 | tmp = (tmp & 0xFF00) | 8; | ||
1934 | b43_phy_write(dev, B43_PHY_ADIVRELATED, | ||
1935 | tmp); | ||
1936 | } | ||
1937 | } | ||
1938 | } | ||
1939 | break; | ||
1940 | case B43_PHYTYPE_B: | ||
1941 | tmp = b43_phy_read(dev, B43_PHY_CCKBBANDCFG); | ||
1942 | tmp &= ~B43_PHY_BBANDCFG_RXANT; | ||
1943 | tmp |= (autodiv ? B43_ANTENNA_AUTO0 : antenna) | ||
1944 | << B43_PHY_BBANDCFG_RXANT_SHIFT; | ||
1945 | b43_phy_write(dev, B43_PHY_CCKBBANDCFG, tmp); | ||
1946 | break; | ||
1947 | case B43_PHYTYPE_N: | ||
1948 | b43_nphy_set_rxantenna(dev, antenna); | ||
1949 | break; | ||
1950 | default: | ||
1951 | B43_WARN_ON(1); | ||
1952 | } | ||
1953 | |||
1954 | hf |= B43_HF_ANTDIVHELP; | ||
1955 | b43_hf_write(dev, hf); | ||
1956 | } | ||
1957 | |||
1958 | /* Get the freq, as it has to be written to the device. */ | ||
1959 | static inline u16 channel2freq_bg(u8 channel) | ||
1960 | { | ||
1961 | B43_WARN_ON(!(channel >= 1 && channel <= 14)); | ||
1962 | |||
1963 | return b43_radio_channel_codes_bg[channel - 1]; | ||
1964 | } | ||
1965 | |||
1966 | /* Get the freq, as it has to be written to the device. */ | ||
1967 | static inline u16 channel2freq_a(u8 channel) | ||
1968 | { | ||
1969 | B43_WARN_ON(channel > 200); | ||
1970 | |||
1971 | return (5000 + 5 * channel); | ||
1972 | } | ||
1973 | |||
1974 | void b43_radio_lock(struct b43_wldev *dev) | ||
1975 | { | ||
1976 | u32 macctl; | ||
1977 | |||
1978 | macctl = b43_read32(dev, B43_MMIO_MACCTL); | ||
1979 | B43_WARN_ON(macctl & B43_MACCTL_RADIOLOCK); | ||
1980 | macctl |= B43_MACCTL_RADIOLOCK; | ||
1981 | b43_write32(dev, B43_MMIO_MACCTL, macctl); | ||
1982 | /* Commit the write and wait for the device | ||
1983 | * to exit any radio register access. */ | ||
1984 | b43_read32(dev, B43_MMIO_MACCTL); | ||
1985 | udelay(10); | ||
1986 | } | ||
1987 | |||
1988 | void b43_radio_unlock(struct b43_wldev *dev) | ||
1989 | { | ||
1990 | u32 macctl; | ||
1991 | |||
1992 | /* Commit any write */ | ||
1993 | b43_read16(dev, B43_MMIO_PHY_VER); | ||
1994 | /* unlock */ | ||
1995 | macctl = b43_read32(dev, B43_MMIO_MACCTL); | ||
1996 | B43_WARN_ON(!(macctl & B43_MACCTL_RADIOLOCK)); | ||
1997 | macctl &= ~B43_MACCTL_RADIOLOCK; | ||
1998 | b43_write32(dev, B43_MMIO_MACCTL, macctl); | ||
1999 | } | ||
2000 | |||
2001 | u16 b43_radio_read16(struct b43_wldev *dev, u16 offset) | ||
2002 | { | ||
2003 | struct b43_phy *phy = &dev->phy; | ||
2004 | |||
2005 | /* Offset 1 is a 32-bit register. */ | ||
2006 | B43_WARN_ON(offset == 1); | ||
2007 | |||
2008 | switch (phy->type) { | ||
2009 | case B43_PHYTYPE_A: | ||
2010 | offset |= 0x40; | ||
2011 | break; | ||
2012 | case B43_PHYTYPE_B: | ||
2013 | if (phy->radio_ver == 0x2053) { | ||
2014 | if (offset < 0x70) | ||
2015 | offset += 0x80; | ||
2016 | else if (offset < 0x80) | ||
2017 | offset += 0x70; | ||
2018 | } else if (phy->radio_ver == 0x2050) { | ||
2019 | offset |= 0x80; | ||
2020 | } else | ||
2021 | B43_WARN_ON(1); | ||
2022 | break; | ||
2023 | case B43_PHYTYPE_G: | ||
2024 | offset |= 0x80; | ||
2025 | break; | ||
2026 | case B43_PHYTYPE_N: | ||
2027 | offset |= 0x100; | ||
2028 | break; | ||
2029 | case B43_PHYTYPE_LP: | ||
2030 | /* No adjustment required. */ | ||
2031 | break; | ||
2032 | default: | ||
2033 | B43_WARN_ON(1); | ||
2034 | } | ||
2035 | |||
2036 | b43_write16(dev, B43_MMIO_RADIO_CONTROL, offset); | ||
2037 | return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW); | ||
2038 | } | ||
2039 | |||
2040 | void b43_radio_write16(struct b43_wldev *dev, u16 offset, u16 val) | ||
2041 | { | ||
2042 | /* Offset 1 is a 32-bit register. */ | ||
2043 | B43_WARN_ON(offset == 1); | ||
2044 | |||
2045 | b43_write16(dev, B43_MMIO_RADIO_CONTROL, offset); | ||
2046 | b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, val); | ||
2047 | } | ||
2048 | |||
2049 | void b43_radio_mask(struct b43_wldev *dev, u16 offset, u16 mask) | ||
2050 | { | ||
2051 | b43_radio_write16(dev, offset, | ||
2052 | b43_radio_read16(dev, offset) & mask); | ||
2053 | } | ||
2054 | |||
2055 | void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set) | ||
2056 | { | ||
2057 | b43_radio_write16(dev, offset, | ||
2058 | b43_radio_read16(dev, offset) | set); | ||
2059 | } | ||
2060 | |||
2061 | void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set) | ||
2062 | { | ||
2063 | b43_radio_write16(dev, offset, | ||
2064 | (b43_radio_read16(dev, offset) & mask) | set); | ||
2065 | } | ||
2066 | |||
2067 | static void b43_set_all_gains(struct b43_wldev *dev, | ||
2068 | s16 first, s16 second, s16 third) | ||
2069 | { | ||
2070 | struct b43_phy *phy = &dev->phy; | ||
2071 | u16 i; | ||
2072 | u16 start = 0x08, end = 0x18; | ||
2073 | u16 tmp; | ||
2074 | u16 table; | ||
2075 | |||
2076 | if (phy->rev <= 1) { | ||
2077 | start = 0x10; | ||
2078 | end = 0x20; | ||
2079 | } | ||
2080 | |||
2081 | table = B43_OFDMTAB_GAINX; | ||
2082 | if (phy->rev <= 1) | ||
2083 | table = B43_OFDMTAB_GAINX_R1; | ||
2084 | for (i = 0; i < 4; i++) | ||
2085 | b43_ofdmtab_write16(dev, table, i, first); | ||
2086 | |||
2087 | for (i = start; i < end; i++) | ||
2088 | b43_ofdmtab_write16(dev, table, i, second); | ||
2089 | |||
2090 | if (third != -1) { | ||
2091 | tmp = ((u16) third << 14) | ((u16) third << 6); | ||
2092 | b43_phy_write(dev, 0x04A0, | ||
2093 | (b43_phy_read(dev, 0x04A0) & 0xBFBF) | tmp); | ||
2094 | b43_phy_write(dev, 0x04A1, | ||
2095 | (b43_phy_read(dev, 0x04A1) & 0xBFBF) | tmp); | ||
2096 | b43_phy_write(dev, 0x04A2, | ||
2097 | (b43_phy_read(dev, 0x04A2) & 0xBFBF) | tmp); | ||
2098 | } | ||
2099 | b43_dummy_transmission(dev); | ||
2100 | } | ||
2101 | |||
2102 | static void b43_set_original_gains(struct b43_wldev *dev) | ||
2103 | { | ||
2104 | struct b43_phy *phy = &dev->phy; | ||
2105 | u16 i, tmp; | ||
2106 | u16 table; | ||
2107 | u16 start = 0x0008, end = 0x0018; | ||
2108 | |||
2109 | if (phy->rev <= 1) { | ||
2110 | start = 0x0010; | ||
2111 | end = 0x0020; | ||
2112 | } | ||
2113 | |||
2114 | table = B43_OFDMTAB_GAINX; | ||
2115 | if (phy->rev <= 1) | ||
2116 | table = B43_OFDMTAB_GAINX_R1; | ||
2117 | for (i = 0; i < 4; i++) { | ||
2118 | tmp = (i & 0xFFFC); | ||
2119 | tmp |= (i & 0x0001) << 1; | ||
2120 | tmp |= (i & 0x0002) >> 1; | ||
2121 | |||
2122 | b43_ofdmtab_write16(dev, table, i, tmp); | ||
2123 | } | ||
2124 | |||
2125 | for (i = start; i < end; i++) | ||
2126 | b43_ofdmtab_write16(dev, table, i, i - start); | ||
2127 | |||
2128 | b43_phy_write(dev, 0x04A0, | ||
2129 | (b43_phy_read(dev, 0x04A0) & 0xBFBF) | 0x4040); | ||
2130 | b43_phy_write(dev, 0x04A1, | ||
2131 | (b43_phy_read(dev, 0x04A1) & 0xBFBF) | 0x4040); | ||
2132 | b43_phy_write(dev, 0x04A2, | ||
2133 | (b43_phy_read(dev, 0x04A2) & 0xBFBF) | 0x4000); | ||
2134 | b43_dummy_transmission(dev); | ||
2135 | } | ||
2136 | |||
2137 | /* Synthetic PU workaround */ | ||
2138 | static void b43_synth_pu_workaround(struct b43_wldev *dev, u8 channel) | ||
2139 | { | ||
2140 | struct b43_phy *phy = &dev->phy; | ||
2141 | |||
2142 | might_sleep(); | ||
2143 | |||
2144 | if (phy->radio_ver != 0x2050 || phy->radio_rev >= 6) { | ||
2145 | /* We do not need the workaround. */ | ||
2146 | return; | ||
2147 | } | ||
2148 | |||
2149 | if (channel <= 10) { | ||
2150 | b43_write16(dev, B43_MMIO_CHANNEL, | ||
2151 | channel2freq_bg(channel + 4)); | ||
2152 | } else { | ||
2153 | b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(1)); | ||
2154 | } | ||
2155 | msleep(1); | ||
2156 | b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel)); | ||
2157 | } | ||
2158 | |||
2159 | u8 b43_radio_aci_detect(struct b43_wldev *dev, u8 channel) | ||
2160 | { | ||
2161 | struct b43_phy *phy = &dev->phy; | ||
2162 | u8 ret = 0; | ||
2163 | u16 saved, rssi, temp; | ||
2164 | int i, j = 0; | ||
2165 | |||
2166 | saved = b43_phy_read(dev, 0x0403); | ||
2167 | b43_radio_selectchannel(dev, channel, 0); | ||
2168 | b43_phy_write(dev, 0x0403, (saved & 0xFFF8) | 5); | ||
2169 | if (phy->aci_hw_rssi) | ||
2170 | rssi = b43_phy_read(dev, 0x048A) & 0x3F; | ||
2171 | else | ||
2172 | rssi = saved & 0x3F; | ||
2173 | /* clamp temp to signed 5bit */ | ||
2174 | if (rssi > 32) | ||
2175 | rssi -= 64; | ||
2176 | for (i = 0; i < 100; i++) { | ||
2177 | temp = (b43_phy_read(dev, 0x047F) >> 8) & 0x3F; | ||
2178 | if (temp > 32) | ||
2179 | temp -= 64; | ||
2180 | if (temp < rssi) | ||
2181 | j++; | ||
2182 | if (j >= 20) | ||
2183 | ret = 1; | ||
2184 | } | ||
2185 | b43_phy_write(dev, 0x0403, saved); | ||
2186 | |||
2187 | return ret; | ||
2188 | } | ||
2189 | |||
2190 | u8 b43_radio_aci_scan(struct b43_wldev * dev) | ||
2191 | { | ||
2192 | struct b43_phy *phy = &dev->phy; | ||
2193 | u8 ret[13]; | ||
2194 | unsigned int channel = phy->channel; | ||
2195 | unsigned int i, j, start, end; | ||
2196 | |||
2197 | if (!((phy->type == B43_PHYTYPE_G) && (phy->rev > 0))) | ||
2198 | return 0; | ||
2199 | |||
2200 | b43_phy_lock(dev); | ||
2201 | b43_radio_lock(dev); | ||
2202 | b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) & 0xFFFC); | ||
2203 | b43_phy_write(dev, B43_PHY_G_CRS, | ||
2204 | b43_phy_read(dev, B43_PHY_G_CRS) & 0x7FFF); | ||
2205 | b43_set_all_gains(dev, 3, 8, 1); | ||
2206 | |||
2207 | start = (channel - 5 > 0) ? channel - 5 : 1; | ||
2208 | end = (channel + 5 < 14) ? channel + 5 : 13; | ||
2209 | |||
2210 | for (i = start; i <= end; i++) { | ||
2211 | if (abs(channel - i) > 2) | ||
2212 | ret[i - 1] = b43_radio_aci_detect(dev, i); | ||
2213 | } | ||
2214 | b43_radio_selectchannel(dev, channel, 0); | ||
2215 | b43_phy_write(dev, 0x0802, | ||
2216 | (b43_phy_read(dev, 0x0802) & 0xFFFC) | 0x0003); | ||
2217 | b43_phy_write(dev, 0x0403, b43_phy_read(dev, 0x0403) & 0xFFF8); | ||
2218 | b43_phy_write(dev, B43_PHY_G_CRS, | ||
2219 | b43_phy_read(dev, B43_PHY_G_CRS) | 0x8000); | ||
2220 | b43_set_original_gains(dev); | ||
2221 | for (i = 0; i < 13; i++) { | ||
2222 | if (!ret[i]) | ||
2223 | continue; | ||
2224 | end = (i + 5 < 13) ? i + 5 : 13; | ||
2225 | for (j = i; j < end; j++) | ||
2226 | ret[j] = 1; | ||
2227 | } | ||
2228 | b43_radio_unlock(dev); | ||
2229 | b43_phy_unlock(dev); | ||
2230 | |||
2231 | return ret[channel - 1]; | ||
2232 | } | ||
2233 | |||
2234 | /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ | ||
2235 | void b43_nrssi_hw_write(struct b43_wldev *dev, u16 offset, s16 val) | ||
2236 | { | ||
2237 | b43_phy_write(dev, B43_PHY_NRSSILT_CTRL, offset); | ||
2238 | mmiowb(); | ||
2239 | b43_phy_write(dev, B43_PHY_NRSSILT_DATA, (u16) val); | ||
2240 | } | ||
2241 | |||
2242 | /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ | ||
2243 | s16 b43_nrssi_hw_read(struct b43_wldev *dev, u16 offset) | ||
2244 | { | ||
2245 | u16 val; | ||
2246 | |||
2247 | b43_phy_write(dev, B43_PHY_NRSSILT_CTRL, offset); | ||
2248 | val = b43_phy_read(dev, B43_PHY_NRSSILT_DATA); | ||
2249 | |||
2250 | return (s16) val; | ||
2251 | } | ||
2252 | |||
2253 | /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ | ||
2254 | void b43_nrssi_hw_update(struct b43_wldev *dev, u16 val) | ||
2255 | { | ||
2256 | u16 i; | ||
2257 | s16 tmp; | ||
2258 | |||
2259 | for (i = 0; i < 64; i++) { | ||
2260 | tmp = b43_nrssi_hw_read(dev, i); | ||
2261 | tmp -= val; | ||
2262 | tmp = clamp_val(tmp, -32, 31); | ||
2263 | b43_nrssi_hw_write(dev, i, tmp); | ||
2264 | } | ||
2265 | } | ||
2266 | |||
2267 | /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ | ||
2268 | void b43_nrssi_mem_update(struct b43_wldev *dev) | ||
2269 | { | ||
2270 | struct b43_phy *phy = &dev->phy; | ||
2271 | s16 i, delta; | ||
2272 | s32 tmp; | ||
2273 | |||
2274 | delta = 0x1F - phy->nrssi[0]; | ||
2275 | for (i = 0; i < 64; i++) { | ||
2276 | tmp = (i - delta) * phy->nrssislope; | ||
2277 | tmp /= 0x10000; | ||
2278 | tmp += 0x3A; | ||
2279 | tmp = clamp_val(tmp, 0, 0x3F); | ||
2280 | phy->nrssi_lt[i] = tmp; | ||
2281 | } | ||
2282 | } | ||
2283 | |||
2284 | static void b43_calc_nrssi_offset(struct b43_wldev *dev) | ||
2285 | { | ||
2286 | struct b43_phy *phy = &dev->phy; | ||
2287 | u16 backup[20] = { 0 }; | ||
2288 | s16 v47F; | ||
2289 | u16 i; | ||
2290 | u16 saved = 0xFFFF; | ||
2291 | |||
2292 | backup[0] = b43_phy_read(dev, 0x0001); | ||
2293 | backup[1] = b43_phy_read(dev, 0x0811); | ||
2294 | backup[2] = b43_phy_read(dev, 0x0812); | ||
2295 | if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */ | ||
2296 | backup[3] = b43_phy_read(dev, 0x0814); | ||
2297 | backup[4] = b43_phy_read(dev, 0x0815); | ||
2298 | } | ||
2299 | backup[5] = b43_phy_read(dev, 0x005A); | ||
2300 | backup[6] = b43_phy_read(dev, 0x0059); | ||
2301 | backup[7] = b43_phy_read(dev, 0x0058); | ||
2302 | backup[8] = b43_phy_read(dev, 0x000A); | ||
2303 | backup[9] = b43_phy_read(dev, 0x0003); | ||
2304 | backup[10] = b43_radio_read16(dev, 0x007A); | ||
2305 | backup[11] = b43_radio_read16(dev, 0x0043); | ||
2306 | |||
2307 | b43_phy_write(dev, 0x0429, b43_phy_read(dev, 0x0429) & 0x7FFF); | ||
2308 | b43_phy_write(dev, 0x0001, | ||
2309 | (b43_phy_read(dev, 0x0001) & 0x3FFF) | 0x4000); | ||
2310 | b43_phy_write(dev, 0x0811, b43_phy_read(dev, 0x0811) | 0x000C); | ||
2311 | b43_phy_write(dev, 0x0812, | ||
2312 | (b43_phy_read(dev, 0x0812) & 0xFFF3) | 0x0004); | ||
2313 | b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) & ~(0x1 | 0x2)); | ||
2314 | if (phy->rev >= 6) { | ||
2315 | backup[12] = b43_phy_read(dev, 0x002E); | ||
2316 | backup[13] = b43_phy_read(dev, 0x002F); | ||
2317 | backup[14] = b43_phy_read(dev, 0x080F); | ||
2318 | backup[15] = b43_phy_read(dev, 0x0810); | ||
2319 | backup[16] = b43_phy_read(dev, 0x0801); | ||
2320 | backup[17] = b43_phy_read(dev, 0x0060); | ||
2321 | backup[18] = b43_phy_read(dev, 0x0014); | ||
2322 | backup[19] = b43_phy_read(dev, 0x0478); | ||
2323 | |||
2324 | b43_phy_write(dev, 0x002E, 0); | ||
2325 | b43_phy_write(dev, 0x002F, 0); | ||
2326 | b43_phy_write(dev, 0x080F, 0); | ||
2327 | b43_phy_write(dev, 0x0810, 0); | ||
2328 | b43_phy_write(dev, 0x0478, b43_phy_read(dev, 0x0478) | 0x0100); | ||
2329 | b43_phy_write(dev, 0x0801, b43_phy_read(dev, 0x0801) | 0x0040); | ||
2330 | b43_phy_write(dev, 0x0060, b43_phy_read(dev, 0x0060) | 0x0040); | ||
2331 | b43_phy_write(dev, 0x0014, b43_phy_read(dev, 0x0014) | 0x0200); | ||
2332 | } | ||
2333 | b43_radio_write16(dev, 0x007A, b43_radio_read16(dev, 0x007A) | 0x0070); | ||
2334 | b43_radio_write16(dev, 0x007A, b43_radio_read16(dev, 0x007A) | 0x0080); | ||
2335 | udelay(30); | ||
2336 | |||
2337 | v47F = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F); | ||
2338 | if (v47F >= 0x20) | ||
2339 | v47F -= 0x40; | ||
2340 | if (v47F == 31) { | ||
2341 | for (i = 7; i >= 4; i--) { | ||
2342 | b43_radio_write16(dev, 0x007B, i); | ||
2343 | udelay(20); | ||
2344 | v47F = | ||
2345 | (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F); | ||
2346 | if (v47F >= 0x20) | ||
2347 | v47F -= 0x40; | ||
2348 | if (v47F < 31 && saved == 0xFFFF) | ||
2349 | saved = i; | ||
2350 | } | ||
2351 | if (saved == 0xFFFF) | ||
2352 | saved = 4; | ||
2353 | } else { | ||
2354 | b43_radio_write16(dev, 0x007A, | ||
2355 | b43_radio_read16(dev, 0x007A) & 0x007F); | ||
2356 | if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */ | ||
2357 | b43_phy_write(dev, 0x0814, | ||
2358 | b43_phy_read(dev, 0x0814) | 0x0001); | ||
2359 | b43_phy_write(dev, 0x0815, | ||
2360 | b43_phy_read(dev, 0x0815) & 0xFFFE); | ||
2361 | } | ||
2362 | b43_phy_write(dev, 0x0811, b43_phy_read(dev, 0x0811) | 0x000C); | ||
2363 | b43_phy_write(dev, 0x0812, b43_phy_read(dev, 0x0812) | 0x000C); | ||
2364 | b43_phy_write(dev, 0x0811, b43_phy_read(dev, 0x0811) | 0x0030); | ||
2365 | b43_phy_write(dev, 0x0812, b43_phy_read(dev, 0x0812) | 0x0030); | ||
2366 | b43_phy_write(dev, 0x005A, 0x0480); | ||
2367 | b43_phy_write(dev, 0x0059, 0x0810); | ||
2368 | b43_phy_write(dev, 0x0058, 0x000D); | ||
2369 | if (phy->rev == 0) { | ||
2370 | b43_phy_write(dev, 0x0003, 0x0122); | ||
2371 | } else { | ||
2372 | b43_phy_write(dev, 0x000A, b43_phy_read(dev, 0x000A) | ||
2373 | | 0x2000); | ||
2374 | } | ||
2375 | if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */ | ||
2376 | b43_phy_write(dev, 0x0814, | ||
2377 | b43_phy_read(dev, 0x0814) | 0x0004); | ||
2378 | b43_phy_write(dev, 0x0815, | ||
2379 | b43_phy_read(dev, 0x0815) & 0xFFFB); | ||
2380 | } | ||
2381 | b43_phy_write(dev, 0x0003, (b43_phy_read(dev, 0x0003) & 0xFF9F) | ||
2382 | | 0x0040); | ||
2383 | b43_radio_write16(dev, 0x007A, | ||
2384 | b43_radio_read16(dev, 0x007A) | 0x000F); | ||
2385 | b43_set_all_gains(dev, 3, 0, 1); | ||
2386 | b43_radio_write16(dev, 0x0043, (b43_radio_read16(dev, 0x0043) | ||
2387 | & 0x00F0) | 0x000F); | ||
2388 | udelay(30); | ||
2389 | v47F = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F); | ||
2390 | if (v47F >= 0x20) | ||
2391 | v47F -= 0x40; | ||
2392 | if (v47F == -32) { | ||
2393 | for (i = 0; i < 4; i++) { | ||
2394 | b43_radio_write16(dev, 0x007B, i); | ||
2395 | udelay(20); | ||
2396 | v47F = | ||
2397 | (s16) ((b43_phy_read(dev, 0x047F) >> 8) & | ||
2398 | 0x003F); | ||
2399 | if (v47F >= 0x20) | ||
2400 | v47F -= 0x40; | ||
2401 | if (v47F > -31 && saved == 0xFFFF) | ||
2402 | saved = i; | ||
2403 | } | ||
2404 | if (saved == 0xFFFF) | ||
2405 | saved = 3; | ||
2406 | } else | ||
2407 | saved = 0; | ||
2408 | } | ||
2409 | b43_radio_write16(dev, 0x007B, saved); | ||
2410 | |||
2411 | if (phy->rev >= 6) { | ||
2412 | b43_phy_write(dev, 0x002E, backup[12]); | ||
2413 | b43_phy_write(dev, 0x002F, backup[13]); | ||
2414 | b43_phy_write(dev, 0x080F, backup[14]); | ||
2415 | b43_phy_write(dev, 0x0810, backup[15]); | ||
2416 | } | ||
2417 | if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */ | ||
2418 | b43_phy_write(dev, 0x0814, backup[3]); | ||
2419 | b43_phy_write(dev, 0x0815, backup[4]); | ||
2420 | } | ||
2421 | b43_phy_write(dev, 0x005A, backup[5]); | ||
2422 | b43_phy_write(dev, 0x0059, backup[6]); | ||
2423 | b43_phy_write(dev, 0x0058, backup[7]); | ||
2424 | b43_phy_write(dev, 0x000A, backup[8]); | ||
2425 | b43_phy_write(dev, 0x0003, backup[9]); | ||
2426 | b43_radio_write16(dev, 0x0043, backup[11]); | ||
2427 | b43_radio_write16(dev, 0x007A, backup[10]); | ||
2428 | b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) | 0x1 | 0x2); | ||
2429 | b43_phy_write(dev, 0x0429, b43_phy_read(dev, 0x0429) | 0x8000); | ||
2430 | b43_set_original_gains(dev); | ||
2431 | if (phy->rev >= 6) { | ||
2432 | b43_phy_write(dev, 0x0801, backup[16]); | ||
2433 | b43_phy_write(dev, 0x0060, backup[17]); | ||
2434 | b43_phy_write(dev, 0x0014, backup[18]); | ||
2435 | b43_phy_write(dev, 0x0478, backup[19]); | ||
2436 | } | ||
2437 | b43_phy_write(dev, 0x0001, backup[0]); | ||
2438 | b43_phy_write(dev, 0x0812, backup[2]); | ||
2439 | b43_phy_write(dev, 0x0811, backup[1]); | ||
2440 | } | ||
2441 | |||
2442 | void b43_calc_nrssi_slope(struct b43_wldev *dev) | ||
2443 | { | ||
2444 | struct b43_phy *phy = &dev->phy; | ||
2445 | u16 backup[18] = { 0 }; | ||
2446 | u16 tmp; | ||
2447 | s16 nrssi0, nrssi1; | ||
2448 | |||
2449 | switch (phy->type) { | ||
2450 | case B43_PHYTYPE_B: | ||
2451 | backup[0] = b43_radio_read16(dev, 0x007A); | ||
2452 | backup[1] = b43_radio_read16(dev, 0x0052); | ||
2453 | backup[2] = b43_radio_read16(dev, 0x0043); | ||
2454 | backup[3] = b43_phy_read(dev, 0x0030); | ||
2455 | backup[4] = b43_phy_read(dev, 0x0026); | ||
2456 | backup[5] = b43_phy_read(dev, 0x0015); | ||
2457 | backup[6] = b43_phy_read(dev, 0x002A); | ||
2458 | backup[7] = b43_phy_read(dev, 0x0020); | ||
2459 | backup[8] = b43_phy_read(dev, 0x005A); | ||
2460 | backup[9] = b43_phy_read(dev, 0x0059); | ||
2461 | backup[10] = b43_phy_read(dev, 0x0058); | ||
2462 | backup[11] = b43_read16(dev, 0x03E2); | ||
2463 | backup[12] = b43_read16(dev, 0x03E6); | ||
2464 | backup[13] = b43_read16(dev, B43_MMIO_CHANNEL_EXT); | ||
2465 | |||
2466 | tmp = b43_radio_read16(dev, 0x007A); | ||
2467 | tmp &= (phy->rev >= 5) ? 0x007F : 0x000F; | ||
2468 | b43_radio_write16(dev, 0x007A, tmp); | ||
2469 | b43_phy_write(dev, 0x0030, 0x00FF); | ||
2470 | b43_write16(dev, 0x03EC, 0x7F7F); | ||
2471 | b43_phy_write(dev, 0x0026, 0x0000); | ||
2472 | b43_phy_write(dev, 0x0015, b43_phy_read(dev, 0x0015) | 0x0020); | ||
2473 | b43_phy_write(dev, 0x002A, 0x08A3); | ||
2474 | b43_radio_write16(dev, 0x007A, | ||
2475 | b43_radio_read16(dev, 0x007A) | 0x0080); | ||
2476 | |||
2477 | nrssi0 = (s16) b43_phy_read(dev, 0x0027); | ||
2478 | b43_radio_write16(dev, 0x007A, | ||
2479 | b43_radio_read16(dev, 0x007A) & 0x007F); | ||
2480 | if (phy->rev >= 2) { | ||
2481 | b43_write16(dev, 0x03E6, 0x0040); | ||
2482 | } else if (phy->rev == 0) { | ||
2483 | b43_write16(dev, 0x03E6, 0x0122); | ||
2484 | } else { | ||
2485 | b43_write16(dev, B43_MMIO_CHANNEL_EXT, | ||
2486 | b43_read16(dev, | ||
2487 | B43_MMIO_CHANNEL_EXT) & 0x2000); | ||
2488 | } | ||
2489 | b43_phy_write(dev, 0x0020, 0x3F3F); | ||
2490 | b43_phy_write(dev, 0x0015, 0xF330); | ||
2491 | b43_radio_write16(dev, 0x005A, 0x0060); | ||
2492 | b43_radio_write16(dev, 0x0043, | ||
2493 | b43_radio_read16(dev, 0x0043) & 0x00F0); | ||
2494 | b43_phy_write(dev, 0x005A, 0x0480); | ||
2495 | b43_phy_write(dev, 0x0059, 0x0810); | ||
2496 | b43_phy_write(dev, 0x0058, 0x000D); | ||
2497 | udelay(20); | ||
2498 | |||
2499 | nrssi1 = (s16) b43_phy_read(dev, 0x0027); | ||
2500 | b43_phy_write(dev, 0x0030, backup[3]); | ||
2501 | b43_radio_write16(dev, 0x007A, backup[0]); | ||
2502 | b43_write16(dev, 0x03E2, backup[11]); | ||
2503 | b43_phy_write(dev, 0x0026, backup[4]); | ||
2504 | b43_phy_write(dev, 0x0015, backup[5]); | ||
2505 | b43_phy_write(dev, 0x002A, backup[6]); | ||
2506 | b43_synth_pu_workaround(dev, phy->channel); | ||
2507 | if (phy->rev != 0) | ||
2508 | b43_write16(dev, 0x03F4, backup[13]); | ||
2509 | |||
2510 | b43_phy_write(dev, 0x0020, backup[7]); | ||
2511 | b43_phy_write(dev, 0x005A, backup[8]); | ||
2512 | b43_phy_write(dev, 0x0059, backup[9]); | ||
2513 | b43_phy_write(dev, 0x0058, backup[10]); | ||
2514 | b43_radio_write16(dev, 0x0052, backup[1]); | ||
2515 | b43_radio_write16(dev, 0x0043, backup[2]); | ||
2516 | |||
2517 | if (nrssi0 == nrssi1) | ||
2518 | phy->nrssislope = 0x00010000; | ||
2519 | else | ||
2520 | phy->nrssislope = 0x00400000 / (nrssi0 - nrssi1); | ||
2521 | |||
2522 | if (nrssi0 <= -4) { | ||
2523 | phy->nrssi[0] = nrssi0; | ||
2524 | phy->nrssi[1] = nrssi1; | ||
2525 | } | ||
2526 | break; | ||
2527 | case B43_PHYTYPE_G: | ||
2528 | if (phy->radio_rev >= 9) | ||
2529 | return; | ||
2530 | if (phy->radio_rev == 8) | ||
2531 | b43_calc_nrssi_offset(dev); | ||
2532 | |||
2533 | b43_phy_write(dev, B43_PHY_G_CRS, | ||
2534 | b43_phy_read(dev, B43_PHY_G_CRS) & 0x7FFF); | ||
2535 | b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) & 0xFFFC); | ||
2536 | backup[7] = b43_read16(dev, 0x03E2); | ||
2537 | b43_write16(dev, 0x03E2, b43_read16(dev, 0x03E2) | 0x8000); | ||
2538 | backup[0] = b43_radio_read16(dev, 0x007A); | ||
2539 | backup[1] = b43_radio_read16(dev, 0x0052); | ||
2540 | backup[2] = b43_radio_read16(dev, 0x0043); | ||
2541 | backup[3] = b43_phy_read(dev, 0x0015); | ||
2542 | backup[4] = b43_phy_read(dev, 0x005A); | ||
2543 | backup[5] = b43_phy_read(dev, 0x0059); | ||
2544 | backup[6] = b43_phy_read(dev, 0x0058); | ||
2545 | backup[8] = b43_read16(dev, 0x03E6); | ||
2546 | backup[9] = b43_read16(dev, B43_MMIO_CHANNEL_EXT); | ||
2547 | if (phy->rev >= 3) { | ||
2548 | backup[10] = b43_phy_read(dev, 0x002E); | ||
2549 | backup[11] = b43_phy_read(dev, 0x002F); | ||
2550 | backup[12] = b43_phy_read(dev, 0x080F); | ||
2551 | backup[13] = b43_phy_read(dev, B43_PHY_G_LO_CONTROL); | ||
2552 | backup[14] = b43_phy_read(dev, 0x0801); | ||
2553 | backup[15] = b43_phy_read(dev, 0x0060); | ||
2554 | backup[16] = b43_phy_read(dev, 0x0014); | ||
2555 | backup[17] = b43_phy_read(dev, 0x0478); | ||
2556 | b43_phy_write(dev, 0x002E, 0); | ||
2557 | b43_phy_write(dev, B43_PHY_G_LO_CONTROL, 0); | ||
2558 | switch (phy->rev) { | ||
2559 | case 4: | ||
2560 | case 6: | ||
2561 | case 7: | ||
2562 | b43_phy_write(dev, 0x0478, | ||
2563 | b43_phy_read(dev, 0x0478) | ||
2564 | | 0x0100); | ||
2565 | b43_phy_write(dev, 0x0801, | ||
2566 | b43_phy_read(dev, 0x0801) | ||
2567 | | 0x0040); | ||
2568 | break; | ||
2569 | case 3: | ||
2570 | case 5: | ||
2571 | b43_phy_write(dev, 0x0801, | ||
2572 | b43_phy_read(dev, 0x0801) | ||
2573 | & 0xFFBF); | ||
2574 | break; | ||
2575 | } | ||
2576 | b43_phy_write(dev, 0x0060, b43_phy_read(dev, 0x0060) | ||
2577 | | 0x0040); | ||
2578 | b43_phy_write(dev, 0x0014, b43_phy_read(dev, 0x0014) | ||
2579 | | 0x0200); | ||
2580 | } | ||
2581 | b43_radio_write16(dev, 0x007A, | ||
2582 | b43_radio_read16(dev, 0x007A) | 0x0070); | ||
2583 | b43_set_all_gains(dev, 0, 8, 0); | ||
2584 | b43_radio_write16(dev, 0x007A, | ||
2585 | b43_radio_read16(dev, 0x007A) & 0x00F7); | ||
2586 | if (phy->rev >= 2) { | ||
2587 | b43_phy_write(dev, 0x0811, | ||
2588 | (b43_phy_read(dev, 0x0811) & 0xFFCF) | | ||
2589 | 0x0030); | ||
2590 | b43_phy_write(dev, 0x0812, | ||
2591 | (b43_phy_read(dev, 0x0812) & 0xFFCF) | | ||
2592 | 0x0010); | ||
2593 | } | ||
2594 | b43_radio_write16(dev, 0x007A, | ||
2595 | b43_radio_read16(dev, 0x007A) | 0x0080); | ||
2596 | udelay(20); | ||
2597 | |||
2598 | nrssi0 = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F); | ||
2599 | if (nrssi0 >= 0x0020) | ||
2600 | nrssi0 -= 0x0040; | ||
2601 | |||
2602 | b43_radio_write16(dev, 0x007A, | ||
2603 | b43_radio_read16(dev, 0x007A) & 0x007F); | ||
2604 | if (phy->rev >= 2) { | ||
2605 | b43_phy_write(dev, 0x0003, (b43_phy_read(dev, 0x0003) | ||
2606 | & 0xFF9F) | 0x0040); | ||
2607 | } | ||
2608 | |||
2609 | b43_write16(dev, B43_MMIO_CHANNEL_EXT, | ||
2610 | b43_read16(dev, B43_MMIO_CHANNEL_EXT) | ||
2611 | | 0x2000); | ||
2612 | b43_radio_write16(dev, 0x007A, | ||
2613 | b43_radio_read16(dev, 0x007A) | 0x000F); | ||
2614 | b43_phy_write(dev, 0x0015, 0xF330); | ||
2615 | if (phy->rev >= 2) { | ||
2616 | b43_phy_write(dev, 0x0812, | ||
2617 | (b43_phy_read(dev, 0x0812) & 0xFFCF) | | ||
2618 | 0x0020); | ||
2619 | b43_phy_write(dev, 0x0811, | ||
2620 | (b43_phy_read(dev, 0x0811) & 0xFFCF) | | ||
2621 | 0x0020); | ||
2622 | } | ||
2623 | |||
2624 | b43_set_all_gains(dev, 3, 0, 1); | ||
2625 | if (phy->radio_rev == 8) { | ||
2626 | b43_radio_write16(dev, 0x0043, 0x001F); | ||
2627 | } else { | ||
2628 | tmp = b43_radio_read16(dev, 0x0052) & 0xFF0F; | ||
2629 | b43_radio_write16(dev, 0x0052, tmp | 0x0060); | ||
2630 | tmp = b43_radio_read16(dev, 0x0043) & 0xFFF0; | ||
2631 | b43_radio_write16(dev, 0x0043, tmp | 0x0009); | ||
2632 | } | ||
2633 | b43_phy_write(dev, 0x005A, 0x0480); | ||
2634 | b43_phy_write(dev, 0x0059, 0x0810); | ||
2635 | b43_phy_write(dev, 0x0058, 0x000D); | ||
2636 | udelay(20); | ||
2637 | nrssi1 = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F); | ||
2638 | if (nrssi1 >= 0x0020) | ||
2639 | nrssi1 -= 0x0040; | ||
2640 | if (nrssi0 == nrssi1) | ||
2641 | phy->nrssislope = 0x00010000; | ||
2642 | else | ||
2643 | phy->nrssislope = 0x00400000 / (nrssi0 - nrssi1); | ||
2644 | if (nrssi0 >= -4) { | ||
2645 | phy->nrssi[0] = nrssi1; | ||
2646 | phy->nrssi[1] = nrssi0; | ||
2647 | } | ||
2648 | if (phy->rev >= 3) { | ||
2649 | b43_phy_write(dev, 0x002E, backup[10]); | ||
2650 | b43_phy_write(dev, 0x002F, backup[11]); | ||
2651 | b43_phy_write(dev, 0x080F, backup[12]); | ||
2652 | b43_phy_write(dev, B43_PHY_G_LO_CONTROL, backup[13]); | ||
2653 | } | ||
2654 | if (phy->rev >= 2) { | ||
2655 | b43_phy_write(dev, 0x0812, | ||
2656 | b43_phy_read(dev, 0x0812) & 0xFFCF); | ||
2657 | b43_phy_write(dev, 0x0811, | ||
2658 | b43_phy_read(dev, 0x0811) & 0xFFCF); | ||
2659 | } | ||
2660 | |||
2661 | b43_radio_write16(dev, 0x007A, backup[0]); | ||
2662 | b43_radio_write16(dev, 0x0052, backup[1]); | ||
2663 | b43_radio_write16(dev, 0x0043, backup[2]); | ||
2664 | b43_write16(dev, 0x03E2, backup[7]); | ||
2665 | b43_write16(dev, 0x03E6, backup[8]); | ||
2666 | b43_write16(dev, B43_MMIO_CHANNEL_EXT, backup[9]); | ||
2667 | b43_phy_write(dev, 0x0015, backup[3]); | ||
2668 | b43_phy_write(dev, 0x005A, backup[4]); | ||
2669 | b43_phy_write(dev, 0x0059, backup[5]); | ||
2670 | b43_phy_write(dev, 0x0058, backup[6]); | ||
2671 | b43_synth_pu_workaround(dev, phy->channel); | ||
2672 | b43_phy_write(dev, 0x0802, | ||
2673 | b43_phy_read(dev, 0x0802) | (0x0001 | 0x0002)); | ||
2674 | b43_set_original_gains(dev); | ||
2675 | b43_phy_write(dev, B43_PHY_G_CRS, | ||
2676 | b43_phy_read(dev, B43_PHY_G_CRS) | 0x8000); | ||
2677 | if (phy->rev >= 3) { | ||
2678 | b43_phy_write(dev, 0x0801, backup[14]); | ||
2679 | b43_phy_write(dev, 0x0060, backup[15]); | ||
2680 | b43_phy_write(dev, 0x0014, backup[16]); | ||
2681 | b43_phy_write(dev, 0x0478, backup[17]); | ||
2682 | } | ||
2683 | b43_nrssi_mem_update(dev); | ||
2684 | b43_calc_nrssi_threshold(dev); | ||
2685 | break; | ||
2686 | default: | ||
2687 | B43_WARN_ON(1); | ||
2688 | } | ||
2689 | } | ||
2690 | |||
2691 | void b43_calc_nrssi_threshold(struct b43_wldev *dev) | ||
2692 | { | ||
2693 | struct b43_phy *phy = &dev->phy; | ||
2694 | s32 threshold; | ||
2695 | s32 a, b; | ||
2696 | s16 tmp16; | ||
2697 | u16 tmp_u16; | ||
2698 | |||
2699 | switch (phy->type) { | ||
2700 | case B43_PHYTYPE_B:{ | ||
2701 | if (phy->radio_ver != 0x2050) | ||
2702 | return; | ||
2703 | if (! | ||
2704 | (dev->dev->bus->sprom. | ||
2705 | boardflags_lo & B43_BFL_RSSI)) | ||
2706 | return; | ||
2707 | |||
2708 | if (phy->radio_rev >= 6) { | ||
2709 | threshold = | ||
2710 | (phy->nrssi[1] - phy->nrssi[0]) * 32; | ||
2711 | threshold += 20 * (phy->nrssi[0] + 1); | ||
2712 | threshold /= 40; | ||
2713 | } else | ||
2714 | threshold = phy->nrssi[1] - 5; | ||
2715 | |||
2716 | threshold = clamp_val(threshold, 0, 0x3E); | ||
2717 | b43_phy_read(dev, 0x0020); /* dummy read */ | ||
2718 | b43_phy_write(dev, 0x0020, | ||
2719 | (((u16) threshold) << 8) | 0x001C); | ||
2720 | |||
2721 | if (phy->radio_rev >= 6) { | ||
2722 | b43_phy_write(dev, 0x0087, 0x0E0D); | ||
2723 | b43_phy_write(dev, 0x0086, 0x0C0B); | ||
2724 | b43_phy_write(dev, 0x0085, 0x0A09); | ||
2725 | b43_phy_write(dev, 0x0084, 0x0808); | ||
2726 | b43_phy_write(dev, 0x0083, 0x0808); | ||
2727 | b43_phy_write(dev, 0x0082, 0x0604); | ||
2728 | b43_phy_write(dev, 0x0081, 0x0302); | ||
2729 | b43_phy_write(dev, 0x0080, 0x0100); | ||
2730 | } | ||
2731 | break; | ||
2732 | } | ||
2733 | case B43_PHYTYPE_G: | ||
2734 | if (!phy->gmode || | ||
2735 | !(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) { | ||
2736 | tmp16 = b43_nrssi_hw_read(dev, 0x20); | ||
2737 | if (tmp16 >= 0x20) | ||
2738 | tmp16 -= 0x40; | ||
2739 | if (tmp16 < 3) { | ||
2740 | b43_phy_write(dev, 0x048A, | ||
2741 | (b43_phy_read(dev, 0x048A) | ||
2742 | & 0xF000) | 0x09EB); | ||
2743 | } else { | ||
2744 | b43_phy_write(dev, 0x048A, | ||
2745 | (b43_phy_read(dev, 0x048A) | ||
2746 | & 0xF000) | 0x0AED); | ||
2747 | } | ||
2748 | } else { | ||
2749 | if (phy->interfmode == B43_INTERFMODE_NONWLAN) { | ||
2750 | a = 0xE; | ||
2751 | b = 0xA; | ||
2752 | } else if (!phy->aci_wlan_automatic && phy->aci_enable) { | ||
2753 | a = 0x13; | ||
2754 | b = 0x12; | ||
2755 | } else { | ||
2756 | a = 0xE; | ||
2757 | b = 0x11; | ||
2758 | } | ||
2759 | |||
2760 | a = a * (phy->nrssi[1] - phy->nrssi[0]); | ||
2761 | a += (phy->nrssi[0] << 6); | ||
2762 | if (a < 32) | ||
2763 | a += 31; | ||
2764 | else | ||
2765 | a += 32; | ||
2766 | a = a >> 6; | ||
2767 | a = clamp_val(a, -31, 31); | ||
2768 | |||
2769 | b = b * (phy->nrssi[1] - phy->nrssi[0]); | ||
2770 | b += (phy->nrssi[0] << 6); | ||
2771 | if (b < 32) | ||
2772 | b += 31; | ||
2773 | else | ||
2774 | b += 32; | ||
2775 | b = b >> 6; | ||
2776 | b = clamp_val(b, -31, 31); | ||
2777 | |||
2778 | tmp_u16 = b43_phy_read(dev, 0x048A) & 0xF000; | ||
2779 | tmp_u16 |= ((u32) b & 0x0000003F); | ||
2780 | tmp_u16 |= (((u32) a & 0x0000003F) << 6); | ||
2781 | b43_phy_write(dev, 0x048A, tmp_u16); | ||
2782 | } | ||
2783 | break; | ||
2784 | default: | ||
2785 | B43_WARN_ON(1); | ||
2786 | } | ||
2787 | } | ||
2788 | |||
2789 | /* Stack implementation to save/restore values from the | ||
2790 | * interference mitigation code. | ||
2791 | * It is save to restore values in random order. | ||
2792 | */ | ||
2793 | static void _stack_save(u32 * _stackptr, size_t * stackidx, | ||
2794 | u8 id, u16 offset, u16 value) | ||
2795 | { | ||
2796 | u32 *stackptr = &(_stackptr[*stackidx]); | ||
2797 | |||
2798 | B43_WARN_ON(offset & 0xF000); | ||
2799 | B43_WARN_ON(id & 0xF0); | ||
2800 | *stackptr = offset; | ||
2801 | *stackptr |= ((u32) id) << 12; | ||
2802 | *stackptr |= ((u32) value) << 16; | ||
2803 | (*stackidx)++; | ||
2804 | B43_WARN_ON(*stackidx >= B43_INTERFSTACK_SIZE); | ||
2805 | } | ||
2806 | |||
2807 | static u16 _stack_restore(u32 * stackptr, u8 id, u16 offset) | ||
2808 | { | ||
2809 | size_t i; | ||
2810 | |||
2811 | B43_WARN_ON(offset & 0xF000); | ||
2812 | B43_WARN_ON(id & 0xF0); | ||
2813 | for (i = 0; i < B43_INTERFSTACK_SIZE; i++, stackptr++) { | ||
2814 | if ((*stackptr & 0x00000FFF) != offset) | ||
2815 | continue; | ||
2816 | if (((*stackptr & 0x0000F000) >> 12) != id) | ||
2817 | continue; | ||
2818 | return ((*stackptr & 0xFFFF0000) >> 16); | ||
2819 | } | ||
2820 | B43_WARN_ON(1); | ||
2821 | |||
2822 | return 0; | ||
2823 | } | ||
2824 | |||
2825 | #define phy_stacksave(offset) \ | ||
2826 | do { \ | ||
2827 | _stack_save(stack, &stackidx, 0x1, (offset), \ | ||
2828 | b43_phy_read(dev, (offset))); \ | ||
2829 | } while (0) | ||
2830 | #define phy_stackrestore(offset) \ | ||
2831 | do { \ | ||
2832 | b43_phy_write(dev, (offset), \ | ||
2833 | _stack_restore(stack, 0x1, \ | ||
2834 | (offset))); \ | ||
2835 | } while (0) | ||
2836 | #define radio_stacksave(offset) \ | ||
2837 | do { \ | ||
2838 | _stack_save(stack, &stackidx, 0x2, (offset), \ | ||
2839 | b43_radio_read16(dev, (offset))); \ | ||
2840 | } while (0) | ||
2841 | #define radio_stackrestore(offset) \ | ||
2842 | do { \ | ||
2843 | b43_radio_write16(dev, (offset), \ | ||
2844 | _stack_restore(stack, 0x2, \ | ||
2845 | (offset))); \ | ||
2846 | } while (0) | ||
2847 | #define ofdmtab_stacksave(table, offset) \ | ||
2848 | do { \ | ||
2849 | _stack_save(stack, &stackidx, 0x3, (offset)|(table), \ | ||
2850 | b43_ofdmtab_read16(dev, (table), (offset))); \ | ||
2851 | } while (0) | ||
2852 | #define ofdmtab_stackrestore(table, offset) \ | ||
2853 | do { \ | ||
2854 | b43_ofdmtab_write16(dev, (table), (offset), \ | ||
2855 | _stack_restore(stack, 0x3, \ | ||
2856 | (offset)|(table))); \ | ||
2857 | } while (0) | ||
2858 | |||
2859 | static void | ||
2860 | b43_radio_interference_mitigation_enable(struct b43_wldev *dev, int mode) | ||
2861 | { | ||
2862 | struct b43_phy *phy = &dev->phy; | ||
2863 | u16 tmp, flipped; | ||
2864 | size_t stackidx = 0; | ||
2865 | u32 *stack = phy->interfstack; | ||
2866 | |||
2867 | switch (mode) { | ||
2868 | case B43_INTERFMODE_NONWLAN: | ||
2869 | if (phy->rev != 1) { | ||
2870 | b43_phy_write(dev, 0x042B, | ||
2871 | b43_phy_read(dev, 0x042B) | 0x0800); | ||
2872 | b43_phy_write(dev, B43_PHY_G_CRS, | ||
2873 | b43_phy_read(dev, | ||
2874 | B43_PHY_G_CRS) & ~0x4000); | ||
2875 | break; | ||
2876 | } | ||
2877 | radio_stacksave(0x0078); | ||
2878 | tmp = (b43_radio_read16(dev, 0x0078) & 0x001E); | ||
2879 | B43_WARN_ON(tmp > 15); | ||
2880 | flipped = bitrev4(tmp); | ||
2881 | if (flipped < 10 && flipped >= 8) | ||
2882 | flipped = 7; | ||
2883 | else if (flipped >= 10) | ||
2884 | flipped -= 3; | ||
2885 | flipped = (bitrev4(flipped) << 1) | 0x0020; | ||
2886 | b43_radio_write16(dev, 0x0078, flipped); | ||
2887 | |||
2888 | b43_calc_nrssi_threshold(dev); | ||
2889 | |||
2890 | phy_stacksave(0x0406); | ||
2891 | b43_phy_write(dev, 0x0406, 0x7E28); | ||
2892 | |||
2893 | b43_phy_write(dev, 0x042B, b43_phy_read(dev, 0x042B) | 0x0800); | ||
2894 | b43_phy_write(dev, B43_PHY_RADIO_BITFIELD, | ||
2895 | b43_phy_read(dev, | ||
2896 | B43_PHY_RADIO_BITFIELD) | 0x1000); | ||
2897 | |||
2898 | phy_stacksave(0x04A0); | ||
2899 | b43_phy_write(dev, 0x04A0, | ||
2900 | (b43_phy_read(dev, 0x04A0) & 0xC0C0) | 0x0008); | ||
2901 | phy_stacksave(0x04A1); | ||
2902 | b43_phy_write(dev, 0x04A1, | ||
2903 | (b43_phy_read(dev, 0x04A1) & 0xC0C0) | 0x0605); | ||
2904 | phy_stacksave(0x04A2); | ||
2905 | b43_phy_write(dev, 0x04A2, | ||
2906 | (b43_phy_read(dev, 0x04A2) & 0xC0C0) | 0x0204); | ||
2907 | phy_stacksave(0x04A8); | ||
2908 | b43_phy_write(dev, 0x04A8, | ||
2909 | (b43_phy_read(dev, 0x04A8) & 0xC0C0) | 0x0803); | ||
2910 | phy_stacksave(0x04AB); | ||
2911 | b43_phy_write(dev, 0x04AB, | ||
2912 | (b43_phy_read(dev, 0x04AB) & 0xC0C0) | 0x0605); | ||
2913 | |||
2914 | phy_stacksave(0x04A7); | ||
2915 | b43_phy_write(dev, 0x04A7, 0x0002); | ||
2916 | phy_stacksave(0x04A3); | ||
2917 | b43_phy_write(dev, 0x04A3, 0x287A); | ||
2918 | phy_stacksave(0x04A9); | ||
2919 | b43_phy_write(dev, 0x04A9, 0x2027); | ||
2920 | phy_stacksave(0x0493); | ||
2921 | b43_phy_write(dev, 0x0493, 0x32F5); | ||
2922 | phy_stacksave(0x04AA); | ||
2923 | b43_phy_write(dev, 0x04AA, 0x2027); | ||
2924 | phy_stacksave(0x04AC); | ||
2925 | b43_phy_write(dev, 0x04AC, 0x32F5); | ||
2926 | break; | ||
2927 | case B43_INTERFMODE_MANUALWLAN: | ||
2928 | if (b43_phy_read(dev, 0x0033) & 0x0800) | ||
2929 | break; | ||
2930 | |||
2931 | phy->aci_enable = 1; | ||
2932 | |||
2933 | phy_stacksave(B43_PHY_RADIO_BITFIELD); | ||
2934 | phy_stacksave(B43_PHY_G_CRS); | ||
2935 | if (phy->rev < 2) { | ||
2936 | phy_stacksave(0x0406); | ||
2937 | } else { | ||
2938 | phy_stacksave(0x04C0); | ||
2939 | phy_stacksave(0x04C1); | ||
2940 | } | ||
2941 | phy_stacksave(0x0033); | ||
2942 | phy_stacksave(0x04A7); | ||
2943 | phy_stacksave(0x04A3); | ||
2944 | phy_stacksave(0x04A9); | ||
2945 | phy_stacksave(0x04AA); | ||
2946 | phy_stacksave(0x04AC); | ||
2947 | phy_stacksave(0x0493); | ||
2948 | phy_stacksave(0x04A1); | ||
2949 | phy_stacksave(0x04A0); | ||
2950 | phy_stacksave(0x04A2); | ||
2951 | phy_stacksave(0x048A); | ||
2952 | phy_stacksave(0x04A8); | ||
2953 | phy_stacksave(0x04AB); | ||
2954 | if (phy->rev == 2) { | ||
2955 | phy_stacksave(0x04AD); | ||
2956 | phy_stacksave(0x04AE); | ||
2957 | } else if (phy->rev >= 3) { | ||
2958 | phy_stacksave(0x04AD); | ||
2959 | phy_stacksave(0x0415); | ||
2960 | phy_stacksave(0x0416); | ||
2961 | phy_stacksave(0x0417); | ||
2962 | ofdmtab_stacksave(0x1A00, 0x2); | ||
2963 | ofdmtab_stacksave(0x1A00, 0x3); | ||
2964 | } | ||
2965 | phy_stacksave(0x042B); | ||
2966 | phy_stacksave(0x048C); | ||
2967 | |||
2968 | b43_phy_write(dev, B43_PHY_RADIO_BITFIELD, | ||
2969 | b43_phy_read(dev, B43_PHY_RADIO_BITFIELD) | ||
2970 | & ~0x1000); | ||
2971 | b43_phy_write(dev, B43_PHY_G_CRS, | ||
2972 | (b43_phy_read(dev, B43_PHY_G_CRS) | ||
2973 | & 0xFFFC) | 0x0002); | ||
2974 | |||
2975 | b43_phy_write(dev, 0x0033, 0x0800); | ||
2976 | b43_phy_write(dev, 0x04A3, 0x2027); | ||
2977 | b43_phy_write(dev, 0x04A9, 0x1CA8); | ||
2978 | b43_phy_write(dev, 0x0493, 0x287A); | ||
2979 | b43_phy_write(dev, 0x04AA, 0x1CA8); | ||
2980 | b43_phy_write(dev, 0x04AC, 0x287A); | ||
2981 | |||
2982 | b43_phy_write(dev, 0x04A0, (b43_phy_read(dev, 0x04A0) | ||
2983 | & 0xFFC0) | 0x001A); | ||
2984 | b43_phy_write(dev, 0x04A7, 0x000D); | ||
2985 | |||
2986 | if (phy->rev < 2) { | ||
2987 | b43_phy_write(dev, 0x0406, 0xFF0D); | ||
2988 | } else if (phy->rev == 2) { | ||
2989 | b43_phy_write(dev, 0x04C0, 0xFFFF); | ||
2990 | b43_phy_write(dev, 0x04C1, 0x00A9); | ||
2991 | } else { | ||
2992 | b43_phy_write(dev, 0x04C0, 0x00C1); | ||
2993 | b43_phy_write(dev, 0x04C1, 0x0059); | ||
2994 | } | ||
2995 | |||
2996 | b43_phy_write(dev, 0x04A1, (b43_phy_read(dev, 0x04A1) | ||
2997 | & 0xC0FF) | 0x1800); | ||
2998 | b43_phy_write(dev, 0x04A1, (b43_phy_read(dev, 0x04A1) | ||
2999 | & 0xFFC0) | 0x0015); | ||
3000 | b43_phy_write(dev, 0x04A8, (b43_phy_read(dev, 0x04A8) | ||
3001 | & 0xCFFF) | 0x1000); | ||
3002 | b43_phy_write(dev, 0x04A8, (b43_phy_read(dev, 0x04A8) | ||
3003 | & 0xF0FF) | 0x0A00); | ||
3004 | b43_phy_write(dev, 0x04AB, (b43_phy_read(dev, 0x04AB) | ||
3005 | & 0xCFFF) | 0x1000); | ||
3006 | b43_phy_write(dev, 0x04AB, (b43_phy_read(dev, 0x04AB) | ||
3007 | & 0xF0FF) | 0x0800); | ||
3008 | b43_phy_write(dev, 0x04AB, (b43_phy_read(dev, 0x04AB) | ||
3009 | & 0xFFCF) | 0x0010); | ||
3010 | b43_phy_write(dev, 0x04AB, (b43_phy_read(dev, 0x04AB) | ||
3011 | & 0xFFF0) | 0x0005); | ||
3012 | b43_phy_write(dev, 0x04A8, (b43_phy_read(dev, 0x04A8) | ||
3013 | & 0xFFCF) | 0x0010); | ||
3014 | b43_phy_write(dev, 0x04A8, (b43_phy_read(dev, 0x04A8) | ||
3015 | & 0xFFF0) | 0x0006); | ||
3016 | b43_phy_write(dev, 0x04A2, (b43_phy_read(dev, 0x04A2) | ||
3017 | & 0xF0FF) | 0x0800); | ||
3018 | b43_phy_write(dev, 0x04A0, (b43_phy_read(dev, 0x04A0) | ||
3019 | & 0xF0FF) | 0x0500); | ||
3020 | b43_phy_write(dev, 0x04A2, (b43_phy_read(dev, 0x04A2) | ||
3021 | & 0xFFF0) | 0x000B); | ||
3022 | |||
3023 | if (phy->rev >= 3) { | ||
3024 | b43_phy_write(dev, 0x048A, b43_phy_read(dev, 0x048A) | ||
3025 | & ~0x8000); | ||
3026 | b43_phy_write(dev, 0x0415, (b43_phy_read(dev, 0x0415) | ||
3027 | & 0x8000) | 0x36D8); | ||
3028 | b43_phy_write(dev, 0x0416, (b43_phy_read(dev, 0x0416) | ||
3029 | & 0x8000) | 0x36D8); | ||
3030 | b43_phy_write(dev, 0x0417, (b43_phy_read(dev, 0x0417) | ||
3031 | & 0xFE00) | 0x016D); | ||
3032 | } else { | ||
3033 | b43_phy_write(dev, 0x048A, b43_phy_read(dev, 0x048A) | ||
3034 | | 0x1000); | ||
3035 | b43_phy_write(dev, 0x048A, (b43_phy_read(dev, 0x048A) | ||
3036 | & 0x9FFF) | 0x2000); | ||
3037 | b43_hf_write(dev, b43_hf_read(dev) | B43_HF_ACIW); | ||
3038 | } | ||
3039 | if (phy->rev >= 2) { | ||
3040 | b43_phy_write(dev, 0x042B, b43_phy_read(dev, 0x042B) | ||
3041 | | 0x0800); | ||
3042 | } | ||
3043 | b43_phy_write(dev, 0x048C, (b43_phy_read(dev, 0x048C) | ||
3044 | & 0xF0FF) | 0x0200); | ||
3045 | if (phy->rev == 2) { | ||
3046 | b43_phy_write(dev, 0x04AE, (b43_phy_read(dev, 0x04AE) | ||
3047 | & 0xFF00) | 0x007F); | ||
3048 | b43_phy_write(dev, 0x04AD, (b43_phy_read(dev, 0x04AD) | ||
3049 | & 0x00FF) | 0x1300); | ||
3050 | } else if (phy->rev >= 6) { | ||
3051 | b43_ofdmtab_write16(dev, 0x1A00, 0x3, 0x007F); | ||
3052 | b43_ofdmtab_write16(dev, 0x1A00, 0x2, 0x007F); | ||
3053 | b43_phy_write(dev, 0x04AD, b43_phy_read(dev, 0x04AD) | ||
3054 | & 0x00FF); | ||
3055 | } | ||
3056 | b43_calc_nrssi_slope(dev); | ||
3057 | break; | ||
3058 | default: | ||
3059 | B43_WARN_ON(1); | ||
3060 | } | ||
3061 | } | ||
3062 | |||
3063 | static void | ||
3064 | b43_radio_interference_mitigation_disable(struct b43_wldev *dev, int mode) | ||
3065 | { | ||
3066 | struct b43_phy *phy = &dev->phy; | ||
3067 | u32 *stack = phy->interfstack; | ||
3068 | |||
3069 | switch (mode) { | ||
3070 | case B43_INTERFMODE_NONWLAN: | ||
3071 | if (phy->rev != 1) { | ||
3072 | b43_phy_write(dev, 0x042B, | ||
3073 | b43_phy_read(dev, 0x042B) & ~0x0800); | ||
3074 | b43_phy_write(dev, B43_PHY_G_CRS, | ||
3075 | b43_phy_read(dev, | ||
3076 | B43_PHY_G_CRS) | 0x4000); | ||
3077 | break; | ||
3078 | } | ||
3079 | radio_stackrestore(0x0078); | ||
3080 | b43_calc_nrssi_threshold(dev); | ||
3081 | phy_stackrestore(0x0406); | ||
3082 | b43_phy_write(dev, 0x042B, b43_phy_read(dev, 0x042B) & ~0x0800); | ||
3083 | if (!dev->bad_frames_preempt) { | ||
3084 | b43_phy_write(dev, B43_PHY_RADIO_BITFIELD, | ||
3085 | b43_phy_read(dev, B43_PHY_RADIO_BITFIELD) | ||
3086 | & ~(1 << 11)); | ||
3087 | } | ||
3088 | b43_phy_write(dev, B43_PHY_G_CRS, | ||
3089 | b43_phy_read(dev, B43_PHY_G_CRS) | 0x4000); | ||
3090 | phy_stackrestore(0x04A0); | ||
3091 | phy_stackrestore(0x04A1); | ||
3092 | phy_stackrestore(0x04A2); | ||
3093 | phy_stackrestore(0x04A8); | ||
3094 | phy_stackrestore(0x04AB); | ||
3095 | phy_stackrestore(0x04A7); | ||
3096 | phy_stackrestore(0x04A3); | ||
3097 | phy_stackrestore(0x04A9); | ||
3098 | phy_stackrestore(0x0493); | ||
3099 | phy_stackrestore(0x04AA); | ||
3100 | phy_stackrestore(0x04AC); | ||
3101 | break; | ||
3102 | case B43_INTERFMODE_MANUALWLAN: | ||
3103 | if (!(b43_phy_read(dev, 0x0033) & 0x0800)) | ||
3104 | break; | ||
3105 | |||
3106 | phy->aci_enable = 0; | ||
3107 | |||
3108 | phy_stackrestore(B43_PHY_RADIO_BITFIELD); | ||
3109 | phy_stackrestore(B43_PHY_G_CRS); | ||
3110 | phy_stackrestore(0x0033); | ||
3111 | phy_stackrestore(0x04A3); | ||
3112 | phy_stackrestore(0x04A9); | ||
3113 | phy_stackrestore(0x0493); | ||
3114 | phy_stackrestore(0x04AA); | ||
3115 | phy_stackrestore(0x04AC); | ||
3116 | phy_stackrestore(0x04A0); | ||
3117 | phy_stackrestore(0x04A7); | ||
3118 | if (phy->rev >= 2) { | ||
3119 | phy_stackrestore(0x04C0); | ||
3120 | phy_stackrestore(0x04C1); | ||
3121 | } else | ||
3122 | phy_stackrestore(0x0406); | ||
3123 | phy_stackrestore(0x04A1); | ||
3124 | phy_stackrestore(0x04AB); | ||
3125 | phy_stackrestore(0x04A8); | ||
3126 | if (phy->rev == 2) { | ||
3127 | phy_stackrestore(0x04AD); | ||
3128 | phy_stackrestore(0x04AE); | ||
3129 | } else if (phy->rev >= 3) { | ||
3130 | phy_stackrestore(0x04AD); | ||
3131 | phy_stackrestore(0x0415); | ||
3132 | phy_stackrestore(0x0416); | ||
3133 | phy_stackrestore(0x0417); | ||
3134 | ofdmtab_stackrestore(0x1A00, 0x2); | ||
3135 | ofdmtab_stackrestore(0x1A00, 0x3); | ||
3136 | } | ||
3137 | phy_stackrestore(0x04A2); | ||
3138 | phy_stackrestore(0x048A); | ||
3139 | phy_stackrestore(0x042B); | ||
3140 | phy_stackrestore(0x048C); | ||
3141 | b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_ACIW); | ||
3142 | b43_calc_nrssi_slope(dev); | ||
3143 | break; | ||
3144 | default: | ||
3145 | B43_WARN_ON(1); | ||
3146 | } | ||
3147 | } | ||
3148 | |||
3149 | #undef phy_stacksave | ||
3150 | #undef phy_stackrestore | ||
3151 | #undef radio_stacksave | ||
3152 | #undef radio_stackrestore | ||
3153 | #undef ofdmtab_stacksave | ||
3154 | #undef ofdmtab_stackrestore | ||
3155 | |||
3156 | int b43_radio_set_interference_mitigation(struct b43_wldev *dev, int mode) | ||
3157 | { | ||
3158 | struct b43_phy *phy = &dev->phy; | ||
3159 | int currentmode; | ||
3160 | |||
3161 | if ((phy->type != B43_PHYTYPE_G) || (phy->rev == 0) || (!phy->gmode)) | ||
3162 | return -ENODEV; | ||
3163 | |||
3164 | phy->aci_wlan_automatic = 0; | ||
3165 | switch (mode) { | ||
3166 | case B43_INTERFMODE_AUTOWLAN: | ||
3167 | phy->aci_wlan_automatic = 1; | ||
3168 | if (phy->aci_enable) | ||
3169 | mode = B43_INTERFMODE_MANUALWLAN; | ||
3170 | else | ||
3171 | mode = B43_INTERFMODE_NONE; | ||
3172 | break; | ||
3173 | case B43_INTERFMODE_NONE: | ||
3174 | case B43_INTERFMODE_NONWLAN: | ||
3175 | case B43_INTERFMODE_MANUALWLAN: | ||
3176 | break; | ||
3177 | default: | ||
3178 | return -EINVAL; | ||
3179 | } | ||
3180 | |||
3181 | currentmode = phy->interfmode; | ||
3182 | if (currentmode == mode) | ||
3183 | return 0; | ||
3184 | if (currentmode != B43_INTERFMODE_NONE) | ||
3185 | b43_radio_interference_mitigation_disable(dev, currentmode); | ||
3186 | |||
3187 | if (mode == B43_INTERFMODE_NONE) { | ||
3188 | phy->aci_enable = 0; | ||
3189 | phy->aci_hw_rssi = 0; | ||
3190 | } else | ||
3191 | b43_radio_interference_mitigation_enable(dev, mode); | ||
3192 | phy->interfmode = mode; | ||
3193 | |||
3194 | return 0; | ||
3195 | } | ||
3196 | |||
3197 | static u16 b43_radio_core_calibration_value(struct b43_wldev *dev) | ||
3198 | { | ||
3199 | u16 reg, index, ret; | ||
3200 | |||
3201 | static const u8 rcc_table[] = { | ||
3202 | 0x02, 0x03, 0x01, 0x0F, | ||
3203 | 0x06, 0x07, 0x05, 0x0F, | ||
3204 | 0x0A, 0x0B, 0x09, 0x0F, | ||
3205 | 0x0E, 0x0F, 0x0D, 0x0F, | ||
3206 | }; | ||
3207 | |||
3208 | reg = b43_radio_read16(dev, 0x60); | ||
3209 | index = (reg & 0x001E) >> 1; | ||
3210 | ret = rcc_table[index] << 1; | ||
3211 | ret |= (reg & 0x0001); | ||
3212 | ret |= 0x0020; | ||
3213 | |||
3214 | return ret; | ||
3215 | } | ||
3216 | |||
3217 | #define LPD(L, P, D) (((L) << 2) | ((P) << 1) | ((D) << 0)) | ||
3218 | static u16 radio2050_rfover_val(struct b43_wldev *dev, | ||
3219 | u16 phy_register, unsigned int lpd) | ||
3220 | { | ||
3221 | struct b43_phy *phy = &dev->phy; | ||
3222 | struct ssb_sprom *sprom = &(dev->dev->bus->sprom); | ||
3223 | |||
3224 | if (!phy->gmode) | ||
3225 | return 0; | ||
3226 | |||
3227 | if (has_loopback_gain(phy)) { | ||
3228 | int max_lb_gain = phy->max_lb_gain; | ||
3229 | u16 extlna; | ||
3230 | u16 i; | ||
3231 | |||
3232 | if (phy->radio_rev == 8) | ||
3233 | max_lb_gain += 0x3E; | ||
3234 | else | ||
3235 | max_lb_gain += 0x26; | ||
3236 | if (max_lb_gain >= 0x46) { | ||
3237 | extlna = 0x3000; | ||
3238 | max_lb_gain -= 0x46; | ||
3239 | } else if (max_lb_gain >= 0x3A) { | ||
3240 | extlna = 0x1000; | ||
3241 | max_lb_gain -= 0x3A; | ||
3242 | } else if (max_lb_gain >= 0x2E) { | ||
3243 | extlna = 0x2000; | ||
3244 | max_lb_gain -= 0x2E; | ||
3245 | } else { | ||
3246 | extlna = 0; | ||
3247 | max_lb_gain -= 0x10; | ||
3248 | } | ||
3249 | |||
3250 | for (i = 0; i < 16; i++) { | ||
3251 | max_lb_gain -= (i * 6); | ||
3252 | if (max_lb_gain < 6) | ||
3253 | break; | ||
3254 | } | ||
3255 | |||
3256 | if ((phy->rev < 7) || | ||
3257 | !(sprom->boardflags_lo & B43_BFL_EXTLNA)) { | ||
3258 | if (phy_register == B43_PHY_RFOVER) { | ||
3259 | return 0x1B3; | ||
3260 | } else if (phy_register == B43_PHY_RFOVERVAL) { | ||
3261 | extlna |= (i << 8); | ||
3262 | switch (lpd) { | ||
3263 | case LPD(0, 1, 1): | ||
3264 | return 0x0F92; | ||
3265 | case LPD(0, 0, 1): | ||
3266 | case LPD(1, 0, 1): | ||
3267 | return (0x0092 | extlna); | ||
3268 | case LPD(1, 0, 0): | ||
3269 | return (0x0093 | extlna); | ||
3270 | } | ||
3271 | B43_WARN_ON(1); | ||
3272 | } | ||
3273 | B43_WARN_ON(1); | ||
3274 | } else { | ||
3275 | if (phy_register == B43_PHY_RFOVER) { | ||
3276 | return 0x9B3; | ||
3277 | } else if (phy_register == B43_PHY_RFOVERVAL) { | ||
3278 | if (extlna) | ||
3279 | extlna |= 0x8000; | ||
3280 | extlna |= (i << 8); | ||
3281 | switch (lpd) { | ||
3282 | case LPD(0, 1, 1): | ||
3283 | return 0x8F92; | ||
3284 | case LPD(0, 0, 1): | ||
3285 | return (0x8092 | extlna); | ||
3286 | case LPD(1, 0, 1): | ||
3287 | return (0x2092 | extlna); | ||
3288 | case LPD(1, 0, 0): | ||
3289 | return (0x2093 | extlna); | ||
3290 | } | ||
3291 | B43_WARN_ON(1); | ||
3292 | } | ||
3293 | B43_WARN_ON(1); | ||
3294 | } | ||
3295 | } else { | ||
3296 | if ((phy->rev < 7) || | ||
3297 | !(sprom->boardflags_lo & B43_BFL_EXTLNA)) { | ||
3298 | if (phy_register == B43_PHY_RFOVER) { | ||
3299 | return 0x1B3; | ||
3300 | } else if (phy_register == B43_PHY_RFOVERVAL) { | ||
3301 | switch (lpd) { | ||
3302 | case LPD(0, 1, 1): | ||
3303 | return 0x0FB2; | ||
3304 | case LPD(0, 0, 1): | ||
3305 | return 0x00B2; | ||
3306 | case LPD(1, 0, 1): | ||
3307 | return 0x30B2; | ||
3308 | case LPD(1, 0, 0): | ||
3309 | return 0x30B3; | ||
3310 | } | ||
3311 | B43_WARN_ON(1); | ||
3312 | } | ||
3313 | B43_WARN_ON(1); | ||
3314 | } else { | ||
3315 | if (phy_register == B43_PHY_RFOVER) { | ||
3316 | return 0x9B3; | ||
3317 | } else if (phy_register == B43_PHY_RFOVERVAL) { | ||
3318 | switch (lpd) { | ||
3319 | case LPD(0, 1, 1): | ||
3320 | return 0x8FB2; | ||
3321 | case LPD(0, 0, 1): | ||
3322 | return 0x80B2; | ||
3323 | case LPD(1, 0, 1): | ||
3324 | return 0x20B2; | ||
3325 | case LPD(1, 0, 0): | ||
3326 | return 0x20B3; | ||
3327 | } | ||
3328 | B43_WARN_ON(1); | ||
3329 | } | ||
3330 | B43_WARN_ON(1); | ||
3331 | } | ||
3332 | } | ||
3333 | return 0; | ||
3334 | } | ||
3335 | |||
3336 | struct init2050_saved_values { | ||
3337 | /* Core registers */ | ||
3338 | u16 reg_3EC; | ||
3339 | u16 reg_3E6; | ||
3340 | u16 reg_3F4; | ||
3341 | /* Radio registers */ | ||
3342 | u16 radio_43; | ||
3343 | u16 radio_51; | ||
3344 | u16 radio_52; | ||
3345 | /* PHY registers */ | ||
3346 | u16 phy_pgactl; | ||
3347 | u16 phy_cck_5A; | ||
3348 | u16 phy_cck_59; | ||
3349 | u16 phy_cck_58; | ||
3350 | u16 phy_cck_30; | ||
3351 | u16 phy_rfover; | ||
3352 | u16 phy_rfoverval; | ||
3353 | u16 phy_analogover; | ||
3354 | u16 phy_analogoverval; | ||
3355 | u16 phy_crs0; | ||
3356 | u16 phy_classctl; | ||
3357 | u16 phy_lo_mask; | ||
3358 | u16 phy_lo_ctl; | ||
3359 | u16 phy_syncctl; | ||
3360 | }; | ||
3361 | |||
3362 | u16 b43_radio_init2050(struct b43_wldev *dev) | ||
3363 | { | ||
3364 | struct b43_phy *phy = &dev->phy; | ||
3365 | struct init2050_saved_values sav; | ||
3366 | u16 rcc; | ||
3367 | u16 radio78; | ||
3368 | u16 ret; | ||
3369 | u16 i, j; | ||
3370 | u32 tmp1 = 0, tmp2 = 0; | ||
3371 | |||
3372 | memset(&sav, 0, sizeof(sav)); /* get rid of "may be used uninitialized..." */ | ||
3373 | |||
3374 | sav.radio_43 = b43_radio_read16(dev, 0x43); | ||
3375 | sav.radio_51 = b43_radio_read16(dev, 0x51); | ||
3376 | sav.radio_52 = b43_radio_read16(dev, 0x52); | ||
3377 | sav.phy_pgactl = b43_phy_read(dev, B43_PHY_PGACTL); | ||
3378 | sav.phy_cck_5A = b43_phy_read(dev, B43_PHY_CCK(0x5A)); | ||
3379 | sav.phy_cck_59 = b43_phy_read(dev, B43_PHY_CCK(0x59)); | ||
3380 | sav.phy_cck_58 = b43_phy_read(dev, B43_PHY_CCK(0x58)); | ||
3381 | |||
3382 | if (phy->type == B43_PHYTYPE_B) { | ||
3383 | sav.phy_cck_30 = b43_phy_read(dev, B43_PHY_CCK(0x30)); | ||
3384 | sav.reg_3EC = b43_read16(dev, 0x3EC); | ||
3385 | |||
3386 | b43_phy_write(dev, B43_PHY_CCK(0x30), 0xFF); | ||
3387 | b43_write16(dev, 0x3EC, 0x3F3F); | ||
3388 | } else if (phy->gmode || phy->rev >= 2) { | ||
3389 | sav.phy_rfover = b43_phy_read(dev, B43_PHY_RFOVER); | ||
3390 | sav.phy_rfoverval = b43_phy_read(dev, B43_PHY_RFOVERVAL); | ||
3391 | sav.phy_analogover = b43_phy_read(dev, B43_PHY_ANALOGOVER); | ||
3392 | sav.phy_analogoverval = | ||
3393 | b43_phy_read(dev, B43_PHY_ANALOGOVERVAL); | ||
3394 | sav.phy_crs0 = b43_phy_read(dev, B43_PHY_CRS0); | ||
3395 | sav.phy_classctl = b43_phy_read(dev, B43_PHY_CLASSCTL); | ||
3396 | |||
3397 | b43_phy_write(dev, B43_PHY_ANALOGOVER, | ||
3398 | b43_phy_read(dev, B43_PHY_ANALOGOVER) | ||
3399 | | 0x0003); | ||
3400 | b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, | ||
3401 | b43_phy_read(dev, B43_PHY_ANALOGOVERVAL) | ||
3402 | & 0xFFFC); | ||
3403 | b43_phy_write(dev, B43_PHY_CRS0, b43_phy_read(dev, B43_PHY_CRS0) | ||
3404 | & 0x7FFF); | ||
3405 | b43_phy_write(dev, B43_PHY_CLASSCTL, | ||
3406 | b43_phy_read(dev, B43_PHY_CLASSCTL) | ||
3407 | & 0xFFFC); | ||
3408 | if (has_loopback_gain(phy)) { | ||
3409 | sav.phy_lo_mask = b43_phy_read(dev, B43_PHY_LO_MASK); | ||
3410 | sav.phy_lo_ctl = b43_phy_read(dev, B43_PHY_LO_CTL); | ||
3411 | |||
3412 | if (phy->rev >= 3) | ||
3413 | b43_phy_write(dev, B43_PHY_LO_MASK, 0xC020); | ||
3414 | else | ||
3415 | b43_phy_write(dev, B43_PHY_LO_MASK, 0x8020); | ||
3416 | b43_phy_write(dev, B43_PHY_LO_CTL, 0); | ||
3417 | } | ||
3418 | |||
3419 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
3420 | radio2050_rfover_val(dev, B43_PHY_RFOVERVAL, | ||
3421 | LPD(0, 1, 1))); | ||
3422 | b43_phy_write(dev, B43_PHY_RFOVER, | ||
3423 | radio2050_rfover_val(dev, B43_PHY_RFOVER, 0)); | ||
3424 | } | ||
3425 | b43_write16(dev, 0x3E2, b43_read16(dev, 0x3E2) | 0x8000); | ||
3426 | |||
3427 | sav.phy_syncctl = b43_phy_read(dev, B43_PHY_SYNCCTL); | ||
3428 | b43_phy_write(dev, B43_PHY_SYNCCTL, b43_phy_read(dev, B43_PHY_SYNCCTL) | ||
3429 | & 0xFF7F); | ||
3430 | sav.reg_3E6 = b43_read16(dev, 0x3E6); | ||
3431 | sav.reg_3F4 = b43_read16(dev, 0x3F4); | ||
3432 | |||
3433 | if (phy->analog == 0) { | ||
3434 | b43_write16(dev, 0x03E6, 0x0122); | ||
3435 | } else { | ||
3436 | if (phy->analog >= 2) { | ||
3437 | b43_phy_write(dev, B43_PHY_CCK(0x03), | ||
3438 | (b43_phy_read(dev, B43_PHY_CCK(0x03)) | ||
3439 | & 0xFFBF) | 0x40); | ||
3440 | } | ||
3441 | b43_write16(dev, B43_MMIO_CHANNEL_EXT, | ||
3442 | (b43_read16(dev, B43_MMIO_CHANNEL_EXT) | 0x2000)); | ||
3443 | } | ||
3444 | |||
3445 | rcc = b43_radio_core_calibration_value(dev); | ||
3446 | |||
3447 | if (phy->type == B43_PHYTYPE_B) | ||
3448 | b43_radio_write16(dev, 0x78, 0x26); | ||
3449 | if (phy->gmode || phy->rev >= 2) { | ||
3450 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
3451 | radio2050_rfover_val(dev, B43_PHY_RFOVERVAL, | ||
3452 | LPD(0, 1, 1))); | ||
3453 | } | ||
3454 | b43_phy_write(dev, B43_PHY_PGACTL, 0xBFAF); | ||
3455 | b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x1403); | ||
3456 | if (phy->gmode || phy->rev >= 2) { | ||
3457 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
3458 | radio2050_rfover_val(dev, B43_PHY_RFOVERVAL, | ||
3459 | LPD(0, 0, 1))); | ||
3460 | } | ||
3461 | b43_phy_write(dev, B43_PHY_PGACTL, 0xBFA0); | ||
3462 | b43_radio_write16(dev, 0x51, b43_radio_read16(dev, 0x51) | ||
3463 | | 0x0004); | ||
3464 | if (phy->radio_rev == 8) { | ||
3465 | b43_radio_write16(dev, 0x43, 0x1F); | ||
3466 | } else { | ||
3467 | b43_radio_write16(dev, 0x52, 0); | ||
3468 | b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43) | ||
3469 | & 0xFFF0) | 0x0009); | ||
3470 | } | ||
3471 | b43_phy_write(dev, B43_PHY_CCK(0x58), 0); | ||
3472 | |||
3473 | for (i = 0; i < 16; i++) { | ||
3474 | b43_phy_write(dev, B43_PHY_CCK(0x5A), 0x0480); | ||
3475 | b43_phy_write(dev, B43_PHY_CCK(0x59), 0xC810); | ||
3476 | b43_phy_write(dev, B43_PHY_CCK(0x58), 0x000D); | ||
3477 | if (phy->gmode || phy->rev >= 2) { | ||
3478 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
3479 | radio2050_rfover_val(dev, | ||
3480 | B43_PHY_RFOVERVAL, | ||
3481 | LPD(1, 0, 1))); | ||
3482 | } | ||
3483 | b43_phy_write(dev, B43_PHY_PGACTL, 0xAFB0); | ||
3484 | udelay(10); | ||
3485 | if (phy->gmode || phy->rev >= 2) { | ||
3486 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
3487 | radio2050_rfover_val(dev, | ||
3488 | B43_PHY_RFOVERVAL, | ||
3489 | LPD(1, 0, 1))); | ||
3490 | } | ||
3491 | b43_phy_write(dev, B43_PHY_PGACTL, 0xEFB0); | ||
3492 | udelay(10); | ||
3493 | if (phy->gmode || phy->rev >= 2) { | ||
3494 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
3495 | radio2050_rfover_val(dev, | ||
3496 | B43_PHY_RFOVERVAL, | ||
3497 | LPD(1, 0, 0))); | ||
3498 | } | ||
3499 | b43_phy_write(dev, B43_PHY_PGACTL, 0xFFF0); | ||
3500 | udelay(20); | ||
3501 | tmp1 += b43_phy_read(dev, B43_PHY_LO_LEAKAGE); | ||
3502 | b43_phy_write(dev, B43_PHY_CCK(0x58), 0); | ||
3503 | if (phy->gmode || phy->rev >= 2) { | ||
3504 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
3505 | radio2050_rfover_val(dev, | ||
3506 | B43_PHY_RFOVERVAL, | ||
3507 | LPD(1, 0, 1))); | ||
3508 | } | ||
3509 | b43_phy_write(dev, B43_PHY_PGACTL, 0xAFB0); | ||
3510 | } | ||
3511 | udelay(10); | ||
3512 | |||
3513 | b43_phy_write(dev, B43_PHY_CCK(0x58), 0); | ||
3514 | tmp1++; | ||
3515 | tmp1 >>= 9; | ||
3516 | |||
3517 | for (i = 0; i < 16; i++) { | ||
3518 | radio78 = (bitrev4(i) << 1) | 0x0020; | ||
3519 | b43_radio_write16(dev, 0x78, radio78); | ||
3520 | udelay(10); | ||
3521 | for (j = 0; j < 16; j++) { | ||
3522 | b43_phy_write(dev, B43_PHY_CCK(0x5A), 0x0D80); | ||
3523 | b43_phy_write(dev, B43_PHY_CCK(0x59), 0xC810); | ||
3524 | b43_phy_write(dev, B43_PHY_CCK(0x58), 0x000D); | ||
3525 | if (phy->gmode || phy->rev >= 2) { | ||
3526 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
3527 | radio2050_rfover_val(dev, | ||
3528 | B43_PHY_RFOVERVAL, | ||
3529 | LPD(1, 0, | ||
3530 | 1))); | ||
3531 | } | ||
3532 | b43_phy_write(dev, B43_PHY_PGACTL, 0xAFB0); | ||
3533 | udelay(10); | ||
3534 | if (phy->gmode || phy->rev >= 2) { | ||
3535 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
3536 | radio2050_rfover_val(dev, | ||
3537 | B43_PHY_RFOVERVAL, | ||
3538 | LPD(1, 0, | ||
3539 | 1))); | ||
3540 | } | ||
3541 | b43_phy_write(dev, B43_PHY_PGACTL, 0xEFB0); | ||
3542 | udelay(10); | ||
3543 | if (phy->gmode || phy->rev >= 2) { | ||
3544 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
3545 | radio2050_rfover_val(dev, | ||
3546 | B43_PHY_RFOVERVAL, | ||
3547 | LPD(1, 0, | ||
3548 | 0))); | ||
3549 | } | ||
3550 | b43_phy_write(dev, B43_PHY_PGACTL, 0xFFF0); | ||
3551 | udelay(10); | ||
3552 | tmp2 += b43_phy_read(dev, B43_PHY_LO_LEAKAGE); | ||
3553 | b43_phy_write(dev, B43_PHY_CCK(0x58), 0); | ||
3554 | if (phy->gmode || phy->rev >= 2) { | ||
3555 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
3556 | radio2050_rfover_val(dev, | ||
3557 | B43_PHY_RFOVERVAL, | ||
3558 | LPD(1, 0, | ||
3559 | 1))); | ||
3560 | } | ||
3561 | b43_phy_write(dev, B43_PHY_PGACTL, 0xAFB0); | ||
3562 | } | ||
3563 | tmp2++; | ||
3564 | tmp2 >>= 8; | ||
3565 | if (tmp1 < tmp2) | ||
3566 | break; | ||
3567 | } | ||
3568 | |||
3569 | /* Restore the registers */ | ||
3570 | b43_phy_write(dev, B43_PHY_PGACTL, sav.phy_pgactl); | ||
3571 | b43_radio_write16(dev, 0x51, sav.radio_51); | ||
3572 | b43_radio_write16(dev, 0x52, sav.radio_52); | ||
3573 | b43_radio_write16(dev, 0x43, sav.radio_43); | ||
3574 | b43_phy_write(dev, B43_PHY_CCK(0x5A), sav.phy_cck_5A); | ||
3575 | b43_phy_write(dev, B43_PHY_CCK(0x59), sav.phy_cck_59); | ||
3576 | b43_phy_write(dev, B43_PHY_CCK(0x58), sav.phy_cck_58); | ||
3577 | b43_write16(dev, 0x3E6, sav.reg_3E6); | ||
3578 | if (phy->analog != 0) | ||
3579 | b43_write16(dev, 0x3F4, sav.reg_3F4); | ||
3580 | b43_phy_write(dev, B43_PHY_SYNCCTL, sav.phy_syncctl); | ||
3581 | b43_synth_pu_workaround(dev, phy->channel); | ||
3582 | if (phy->type == B43_PHYTYPE_B) { | ||
3583 | b43_phy_write(dev, B43_PHY_CCK(0x30), sav.phy_cck_30); | ||
3584 | b43_write16(dev, 0x3EC, sav.reg_3EC); | ||
3585 | } else if (phy->gmode) { | ||
3586 | b43_write16(dev, B43_MMIO_PHY_RADIO, | ||
3587 | b43_read16(dev, B43_MMIO_PHY_RADIO) | ||
3588 | & 0x7FFF); | ||
3589 | b43_phy_write(dev, B43_PHY_RFOVER, sav.phy_rfover); | ||
3590 | b43_phy_write(dev, B43_PHY_RFOVERVAL, sav.phy_rfoverval); | ||
3591 | b43_phy_write(dev, B43_PHY_ANALOGOVER, sav.phy_analogover); | ||
3592 | b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, | ||
3593 | sav.phy_analogoverval); | ||
3594 | b43_phy_write(dev, B43_PHY_CRS0, sav.phy_crs0); | ||
3595 | b43_phy_write(dev, B43_PHY_CLASSCTL, sav.phy_classctl); | ||
3596 | if (has_loopback_gain(phy)) { | ||
3597 | b43_phy_write(dev, B43_PHY_LO_MASK, sav.phy_lo_mask); | ||
3598 | b43_phy_write(dev, B43_PHY_LO_CTL, sav.phy_lo_ctl); | ||
3599 | } | ||
3600 | } | ||
3601 | if (i > 15) | ||
3602 | ret = radio78; | ||
3603 | else | ||
3604 | ret = rcc; | ||
3605 | |||
3606 | return ret; | ||
3607 | } | ||
3608 | |||
3609 | void b43_radio_init2060(struct b43_wldev *dev) | ||
3610 | { | ||
3611 | int err; | ||
3612 | |||
3613 | b43_radio_write16(dev, 0x0004, 0x00C0); | ||
3614 | b43_radio_write16(dev, 0x0005, 0x0008); | ||
3615 | b43_radio_write16(dev, 0x0009, 0x0040); | ||
3616 | b43_radio_write16(dev, 0x0005, 0x00AA); | ||
3617 | b43_radio_write16(dev, 0x0032, 0x008F); | ||
3618 | b43_radio_write16(dev, 0x0006, 0x008F); | ||
3619 | b43_radio_write16(dev, 0x0034, 0x008F); | ||
3620 | b43_radio_write16(dev, 0x002C, 0x0007); | ||
3621 | b43_radio_write16(dev, 0x0082, 0x0080); | ||
3622 | b43_radio_write16(dev, 0x0080, 0x0000); | ||
3623 | b43_radio_write16(dev, 0x003F, 0x00DA); | ||
3624 | b43_radio_write16(dev, 0x0005, b43_radio_read16(dev, 0x0005) & ~0x0008); | ||
3625 | b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0010); | ||
3626 | b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0020); | ||
3627 | b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0020); | ||
3628 | msleep(1); /* delay 400usec */ | ||
3629 | |||
3630 | b43_radio_write16(dev, 0x0081, | ||
3631 | (b43_radio_read16(dev, 0x0081) & ~0x0020) | 0x0010); | ||
3632 | msleep(1); /* delay 400usec */ | ||
3633 | |||
3634 | b43_radio_write16(dev, 0x0005, | ||
3635 | (b43_radio_read16(dev, 0x0005) & ~0x0008) | 0x0008); | ||
3636 | b43_radio_write16(dev, 0x0085, b43_radio_read16(dev, 0x0085) & ~0x0010); | ||
3637 | b43_radio_write16(dev, 0x0005, b43_radio_read16(dev, 0x0005) & ~0x0008); | ||
3638 | b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0040); | ||
3639 | b43_radio_write16(dev, 0x0081, | ||
3640 | (b43_radio_read16(dev, 0x0081) & ~0x0040) | 0x0040); | ||
3641 | b43_radio_write16(dev, 0x0005, | ||
3642 | (b43_radio_read16(dev, 0x0081) & ~0x0008) | 0x0008); | ||
3643 | b43_phy_write(dev, 0x0063, 0xDDC6); | ||
3644 | b43_phy_write(dev, 0x0069, 0x07BE); | ||
3645 | b43_phy_write(dev, 0x006A, 0x0000); | ||
3646 | |||
3647 | err = b43_radio_selectchannel(dev, B43_DEFAULT_CHANNEL_A, 0); | ||
3648 | B43_WARN_ON(err); | ||
3649 | |||
3650 | msleep(1); | ||
3651 | } | ||
3652 | |||
3653 | static inline u16 freq_r3A_value(u16 frequency) | ||
3654 | { | ||
3655 | u16 value; | ||
3656 | |||
3657 | if (frequency < 5091) | ||
3658 | value = 0x0040; | ||
3659 | else if (frequency < 5321) | ||
3660 | value = 0x0000; | ||
3661 | else if (frequency < 5806) | ||
3662 | value = 0x0080; | ||
3663 | else | ||
3664 | value = 0x0040; | ||
3665 | |||
3666 | return value; | ||
3667 | } | ||
3668 | |||
3669 | void b43_radio_set_tx_iq(struct b43_wldev *dev) | ||
3670 | { | ||
3671 | static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 }; | ||
3672 | static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A }; | ||
3673 | u16 tmp = b43_radio_read16(dev, 0x001E); | ||
3674 | int i, j; | ||
3675 | |||
3676 | for (i = 0; i < 5; i++) { | ||
3677 | for (j = 0; j < 5; j++) { | ||
3678 | if (tmp == (data_high[i] << 4 | data_low[j])) { | ||
3679 | b43_phy_write(dev, 0x0069, | ||
3680 | (i - j) << 8 | 0x00C0); | ||
3681 | return; | ||
3682 | } | ||
3683 | } | ||
3684 | } | ||
3685 | } | ||
3686 | |||
3687 | int b43_radio_selectchannel(struct b43_wldev *dev, | ||
3688 | u8 channel, int synthetic_pu_workaround) | ||
3689 | { | ||
3690 | struct b43_phy *phy = &dev->phy; | ||
3691 | u16 r8, tmp; | ||
3692 | u16 freq; | ||
3693 | u16 channelcookie, savedcookie; | ||
3694 | int err = 0; | ||
3695 | |||
3696 | if (channel == 0xFF) { | ||
3697 | switch (phy->type) { | ||
3698 | case B43_PHYTYPE_A: | ||
3699 | channel = B43_DEFAULT_CHANNEL_A; | ||
3700 | break; | ||
3701 | case B43_PHYTYPE_B: | ||
3702 | case B43_PHYTYPE_G: | ||
3703 | channel = B43_DEFAULT_CHANNEL_BG; | ||
3704 | break; | ||
3705 | case B43_PHYTYPE_N: | ||
3706 | //FIXME check if we are on 2.4GHz or 5GHz and set a default channel. | ||
3707 | channel = 1; | ||
3708 | break; | ||
3709 | default: | ||
3710 | B43_WARN_ON(1); | ||
3711 | } | ||
3712 | } | ||
3713 | |||
3714 | /* First we set the channel radio code to prevent the | ||
3715 | * firmware from sending ghost packets. | ||
3716 | */ | ||
3717 | channelcookie = channel; | ||
3718 | if (0 /*FIXME on 5Ghz */) | ||
3719 | channelcookie |= 0x100; | ||
3720 | //FIXME set 40Mhz flag if required | ||
3721 | savedcookie = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN); | ||
3722 | b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN, channelcookie); | ||
3723 | |||
3724 | switch (phy->type) { | ||
3725 | case B43_PHYTYPE_A: | ||
3726 | if (channel > 200) { | ||
3727 | err = -EINVAL; | ||
3728 | goto out; | ||
3729 | } | ||
3730 | freq = channel2freq_a(channel); | ||
3731 | |||
3732 | r8 = b43_radio_read16(dev, 0x0008); | ||
3733 | b43_write16(dev, 0x03F0, freq); | ||
3734 | b43_radio_write16(dev, 0x0008, r8); | ||
3735 | |||
3736 | //TODO: write max channel TX power? to Radio 0x2D | ||
3737 | tmp = b43_radio_read16(dev, 0x002E); | ||
3738 | tmp &= 0x0080; | ||
3739 | //TODO: OR tmp with the Power out estimation for this channel? | ||
3740 | b43_radio_write16(dev, 0x002E, tmp); | ||
3741 | |||
3742 | if (freq >= 4920 && freq <= 5500) { | ||
3743 | /* | ||
3744 | * r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0F; | ||
3745 | * = (freq * 0.025862069 | ||
3746 | */ | ||
3747 | r8 = 3 * freq / 116; /* is equal to r8 = freq * 0.025862 */ | ||
3748 | } | ||
3749 | b43_radio_write16(dev, 0x0007, (r8 << 4) | r8); | ||
3750 | b43_radio_write16(dev, 0x0020, (r8 << 4) | r8); | ||
3751 | b43_radio_write16(dev, 0x0021, (r8 << 4) | r8); | ||
3752 | b43_radio_write16(dev, 0x0022, (b43_radio_read16(dev, 0x0022) | ||
3753 | & 0x000F) | (r8 << 4)); | ||
3754 | b43_radio_write16(dev, 0x002A, (r8 << 4)); | ||
3755 | b43_radio_write16(dev, 0x002B, (r8 << 4)); | ||
3756 | b43_radio_write16(dev, 0x0008, (b43_radio_read16(dev, 0x0008) | ||
3757 | & 0x00F0) | (r8 << 4)); | ||
3758 | b43_radio_write16(dev, 0x0029, (b43_radio_read16(dev, 0x0029) | ||
3759 | & 0xFF0F) | 0x00B0); | ||
3760 | b43_radio_write16(dev, 0x0035, 0x00AA); | ||
3761 | b43_radio_write16(dev, 0x0036, 0x0085); | ||
3762 | b43_radio_write16(dev, 0x003A, (b43_radio_read16(dev, 0x003A) | ||
3763 | & 0xFF20) | | ||
3764 | freq_r3A_value(freq)); | ||
3765 | b43_radio_write16(dev, 0x003D, | ||
3766 | b43_radio_read16(dev, 0x003D) & 0x00FF); | ||
3767 | b43_radio_write16(dev, 0x0081, (b43_radio_read16(dev, 0x0081) | ||
3768 | & 0xFF7F) | 0x0080); | ||
3769 | b43_radio_write16(dev, 0x0035, | ||
3770 | b43_radio_read16(dev, 0x0035) & 0xFFEF); | ||
3771 | b43_radio_write16(dev, 0x0035, (b43_radio_read16(dev, 0x0035) | ||
3772 | & 0xFFEF) | 0x0010); | ||
3773 | b43_radio_set_tx_iq(dev); | ||
3774 | //TODO: TSSI2dbm workaround | ||
3775 | b43_phy_xmitpower(dev); //FIXME correct? | ||
3776 | break; | ||
3777 | case B43_PHYTYPE_G: | ||
3778 | if ((channel < 1) || (channel > 14)) { | ||
3779 | err = -EINVAL; | ||
3780 | goto out; | ||
3781 | } | ||
3782 | |||
3783 | if (synthetic_pu_workaround) | ||
3784 | b43_synth_pu_workaround(dev, channel); | ||
3785 | |||
3786 | b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel)); | ||
3787 | |||
3788 | if (channel == 14) { | ||
3789 | if (dev->dev->bus->sprom.country_code == | ||
3790 | SSB_SPROM1CCODE_JAPAN) | ||
3791 | b43_hf_write(dev, | ||
3792 | b43_hf_read(dev) & ~B43_HF_ACPR); | ||
3793 | else | ||
3794 | b43_hf_write(dev, | ||
3795 | b43_hf_read(dev) | B43_HF_ACPR); | ||
3796 | b43_write16(dev, B43_MMIO_CHANNEL_EXT, | ||
3797 | b43_read16(dev, B43_MMIO_CHANNEL_EXT) | ||
3798 | | (1 << 11)); | ||
3799 | } else { | ||
3800 | b43_write16(dev, B43_MMIO_CHANNEL_EXT, | ||
3801 | b43_read16(dev, B43_MMIO_CHANNEL_EXT) | ||
3802 | & 0xF7BF); | ||
3803 | } | ||
3804 | break; | ||
3805 | case B43_PHYTYPE_N: | ||
3806 | err = b43_nphy_selectchannel(dev, channel); | ||
3807 | if (err) | ||
3808 | goto out; | ||
3809 | break; | ||
3810 | default: | ||
3811 | B43_WARN_ON(1); | ||
3812 | } | ||
3813 | |||
3814 | phy->channel = channel; | ||
3815 | /* Wait for the radio to tune to the channel and stabilize. */ | ||
3816 | msleep(8); | ||
3817 | out: | ||
3818 | if (err) { | ||
3819 | b43_shm_write16(dev, B43_SHM_SHARED, | ||
3820 | B43_SHM_SH_CHAN, savedcookie); | ||
3821 | } | ||
3822 | return err; | ||
3823 | } | ||
3824 | |||
3825 | void b43_radio_turn_on(struct b43_wldev *dev) | 432 | void b43_radio_turn_on(struct b43_wldev *dev) |
3826 | { | 433 | { |
3827 | struct b43_phy *phy = &dev->phy; | 434 | struct b43_phy *phy = &dev->phy; |
@@ -3843,21 +450,7 @@ void b43_radio_turn_on(struct b43_wldev *dev) | |||
3843 | break; | 450 | break; |
3844 | case B43_PHYTYPE_B: | 451 | case B43_PHYTYPE_B: |
3845 | case B43_PHYTYPE_G: | 452 | case B43_PHYTYPE_G: |
3846 | b43_phy_write(dev, 0x0015, 0x8000); | 453 | //XXX |
3847 | b43_phy_write(dev, 0x0015, 0xCC00); | ||
3848 | b43_phy_write(dev, 0x0015, (phy->gmode ? 0x00C0 : 0x0000)); | ||
3849 | if (phy->radio_off_context.valid) { | ||
3850 | /* Restore the RFover values. */ | ||
3851 | b43_phy_write(dev, B43_PHY_RFOVER, | ||
3852 | phy->radio_off_context.rfover); | ||
3853 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
3854 | phy->radio_off_context.rfoverval); | ||
3855 | phy->radio_off_context.valid = 0; | ||
3856 | } | ||
3857 | channel = phy->channel; | ||
3858 | err = b43_radio_selectchannel(dev, B43_DEFAULT_CHANNEL_BG, 1); | ||
3859 | err |= b43_radio_selectchannel(dev, channel, 0); | ||
3860 | B43_WARN_ON(err); | ||
3861 | break; | 454 | break; |
3862 | case B43_PHYTYPE_N: | 455 | case B43_PHYTYPE_N: |
3863 | b43_nphy_radio_turn_on(dev); | 456 | b43_nphy_radio_turn_on(dev); |
@@ -3886,17 +479,7 @@ void b43_radio_turn_off(struct b43_wldev *dev, bool force) | |||
3886 | b43_phy_write(dev, 0x0011, b43_phy_read(dev, 0x0011) | 0x0008); | 479 | b43_phy_write(dev, 0x0011, b43_phy_read(dev, 0x0011) | 0x0008); |
3887 | break; | 480 | break; |
3888 | case B43_PHYTYPE_G: { | 481 | case B43_PHYTYPE_G: { |
3889 | u16 rfover, rfoverval; | 482 | //XXX |
3890 | |||
3891 | rfover = b43_phy_read(dev, B43_PHY_RFOVER); | ||
3892 | rfoverval = b43_phy_read(dev, B43_PHY_RFOVERVAL); | ||
3893 | if (!force) { | ||
3894 | phy->radio_off_context.rfover = rfover; | ||
3895 | phy->radio_off_context.rfoverval = rfoverval; | ||
3896 | phy->radio_off_context.valid = 1; | ||
3897 | } | ||
3898 | b43_phy_write(dev, B43_PHY_RFOVER, rfover | 0x008C); | ||
3899 | b43_phy_write(dev, B43_PHY_RFOVERVAL, rfoverval & 0xFF73); | ||
3900 | break; | 483 | break; |
3901 | } | 484 | } |
3902 | default: | 485 | default: |
diff --git a/drivers/net/wireless/b43/phy.h b/drivers/net/wireless/b43/phy.h deleted file mode 100644 index 4aab10903529..000000000000 --- a/drivers/net/wireless/b43/phy.h +++ /dev/null | |||
@@ -1,340 +0,0 @@ | |||
1 | #ifndef B43_PHY_H_ | ||
2 | #define B43_PHY_H_ | ||
3 | |||
4 | #include <linux/types.h> | ||
5 | |||
6 | struct b43_wldev; | ||
7 | struct b43_phy; | ||
8 | |||
9 | /*** PHY Registers ***/ | ||
10 | |||
11 | /* Routing */ | ||
12 | #define B43_PHYROUTE 0x0C00 /* PHY register routing bits mask */ | ||
13 | #define B43_PHYROUTE_BASE 0x0000 /* Base registers */ | ||
14 | #define B43_PHYROUTE_OFDM_GPHY 0x0400 /* OFDM register routing for G-PHYs */ | ||
15 | #define B43_PHYROUTE_EXT_GPHY 0x0800 /* Extended G-PHY registers */ | ||
16 | #define B43_PHYROUTE_N_BMODE 0x0C00 /* N-PHY BMODE registers */ | ||
17 | |||
18 | /* CCK (B-PHY) registers. */ | ||
19 | #define B43_PHY_CCK(reg) ((reg) | B43_PHYROUTE_BASE) | ||
20 | /* N-PHY registers. */ | ||
21 | #define B43_PHY_N(reg) ((reg) | B43_PHYROUTE_BASE) | ||
22 | /* N-PHY BMODE registers. */ | ||
23 | #define B43_PHY_N_BMODE(reg) ((reg) | B43_PHYROUTE_N_BMODE) | ||
24 | /* OFDM (A-PHY) registers. */ | ||
25 | #define B43_PHY_OFDM(reg) ((reg) | B43_PHYROUTE_OFDM_GPHY) | ||
26 | /* Extended G-PHY registers. */ | ||
27 | #define B43_PHY_EXTG(reg) ((reg) | B43_PHYROUTE_EXT_GPHY) | ||
28 | |||
29 | /* OFDM (A) PHY Registers */ | ||
30 | #define B43_PHY_VERSION_OFDM B43_PHY_OFDM(0x00) /* Versioning register for A-PHY */ | ||
31 | #define B43_PHY_BBANDCFG B43_PHY_OFDM(0x01) /* Baseband config */ | ||
32 | #define B43_PHY_BBANDCFG_RXANT 0x180 /* RX Antenna selection */ | ||
33 | #define B43_PHY_BBANDCFG_RXANT_SHIFT 7 | ||
34 | #define B43_PHY_PWRDOWN B43_PHY_OFDM(0x03) /* Powerdown */ | ||
35 | #define B43_PHY_CRSTHRES1_R1 B43_PHY_OFDM(0x06) /* CRS Threshold 1 (phy.rev 1 only) */ | ||
36 | #define B43_PHY_LNAHPFCTL B43_PHY_OFDM(0x1C) /* LNA/HPF control */ | ||
37 | #define B43_PHY_LPFGAINCTL B43_PHY_OFDM(0x20) /* LPF Gain control */ | ||
38 | #define B43_PHY_ADIVRELATED B43_PHY_OFDM(0x27) /* FIXME rename */ | ||
39 | #define B43_PHY_CRS0 B43_PHY_OFDM(0x29) | ||
40 | #define B43_PHY_CRS0_EN 0x4000 | ||
41 | #define B43_PHY_PEAK_COUNT B43_PHY_OFDM(0x30) | ||
42 | #define B43_PHY_ANTDWELL B43_PHY_OFDM(0x2B) /* Antenna dwell */ | ||
43 | #define B43_PHY_ANTDWELL_AUTODIV1 0x0100 /* Automatic RX diversity start antenna */ | ||
44 | #define B43_PHY_ENCORE B43_PHY_OFDM(0x49) /* "Encore" (RangeMax / BroadRange) */ | ||
45 | #define B43_PHY_ENCORE_EN 0x0200 /* Encore enable */ | ||
46 | #define B43_PHY_LMS B43_PHY_OFDM(0x55) | ||
47 | #define B43_PHY_OFDM61 B43_PHY_OFDM(0x61) /* FIXME rename */ | ||
48 | #define B43_PHY_OFDM61_10 0x0010 /* FIXME rename */ | ||
49 | #define B43_PHY_IQBAL B43_PHY_OFDM(0x69) /* I/Q balance */ | ||
50 | #define B43_PHY_BBTXDC_BIAS B43_PHY_OFDM(0x6B) /* Baseband TX DC bias */ | ||
51 | #define B43_PHY_OTABLECTL B43_PHY_OFDM(0x72) /* OFDM table control (see below) */ | ||
52 | #define B43_PHY_OTABLEOFF 0x03FF /* OFDM table offset (see below) */ | ||
53 | #define B43_PHY_OTABLENR 0xFC00 /* OFDM table number (see below) */ | ||
54 | #define B43_PHY_OTABLENR_SHIFT 10 | ||
55 | #define B43_PHY_OTABLEI B43_PHY_OFDM(0x73) /* OFDM table data I */ | ||
56 | #define B43_PHY_OTABLEQ B43_PHY_OFDM(0x74) /* OFDM table data Q */ | ||
57 | #define B43_PHY_HPWR_TSSICTL B43_PHY_OFDM(0x78) /* Hardware power TSSI control */ | ||
58 | #define B43_PHY_ADCCTL B43_PHY_OFDM(0x7A) /* ADC control */ | ||
59 | #define B43_PHY_IDLE_TSSI B43_PHY_OFDM(0x7B) | ||
60 | #define B43_PHY_A_TEMP_SENSE B43_PHY_OFDM(0x7C) /* A PHY temperature sense */ | ||
61 | #define B43_PHY_NRSSITHRES B43_PHY_OFDM(0x8A) /* NRSSI threshold */ | ||
62 | #define B43_PHY_ANTWRSETT B43_PHY_OFDM(0x8C) /* Antenna WR settle */ | ||
63 | #define B43_PHY_ANTWRSETT_ARXDIV 0x2000 /* Automatic RX diversity enabled */ | ||
64 | #define B43_PHY_CLIPPWRDOWNT B43_PHY_OFDM(0x93) /* Clip powerdown threshold */ | ||
65 | #define B43_PHY_OFDM9B B43_PHY_OFDM(0x9B) /* FIXME rename */ | ||
66 | #define B43_PHY_N1P1GAIN B43_PHY_OFDM(0xA0) | ||
67 | #define B43_PHY_P1P2GAIN B43_PHY_OFDM(0xA1) | ||
68 | #define B43_PHY_N1N2GAIN B43_PHY_OFDM(0xA2) | ||
69 | #define B43_PHY_CLIPTHRES B43_PHY_OFDM(0xA3) | ||
70 | #define B43_PHY_CLIPN1P2THRES B43_PHY_OFDM(0xA4) | ||
71 | #define B43_PHY_CCKSHIFTBITS_WA B43_PHY_OFDM(0xA5) /* CCK shiftbits workaround, FIXME rename */ | ||
72 | #define B43_PHY_CCKSHIFTBITS B43_PHY_OFDM(0xA7) /* FIXME rename */ | ||
73 | #define B43_PHY_DIVSRCHIDX B43_PHY_OFDM(0xA8) /* Divider search gain/index */ | ||
74 | #define B43_PHY_CLIPP2THRES B43_PHY_OFDM(0xA9) | ||
75 | #define B43_PHY_CLIPP3THRES B43_PHY_OFDM(0xAA) | ||
76 | #define B43_PHY_DIVP1P2GAIN B43_PHY_OFDM(0xAB) | ||
77 | #define B43_PHY_DIVSRCHGAINBACK B43_PHY_OFDM(0xAD) /* Divider search gain back */ | ||
78 | #define B43_PHY_DIVSRCHGAINCHNG B43_PHY_OFDM(0xAE) /* Divider search gain change */ | ||
79 | #define B43_PHY_CRSTHRES1 B43_PHY_OFDM(0xC0) /* CRS Threshold 1 (phy.rev >= 2 only) */ | ||
80 | #define B43_PHY_CRSTHRES2 B43_PHY_OFDM(0xC1) /* CRS Threshold 2 (phy.rev >= 2 only) */ | ||
81 | #define B43_PHY_TSSIP_LTBASE B43_PHY_OFDM(0x380) /* TSSI power lookup table base */ | ||
82 | #define B43_PHY_DC_LTBASE B43_PHY_OFDM(0x3A0) /* DC lookup table base */ | ||
83 | #define B43_PHY_GAIN_LTBASE B43_PHY_OFDM(0x3C0) /* Gain lookup table base */ | ||
84 | |||
85 | /* CCK (B) PHY Registers */ | ||
86 | #define B43_PHY_VERSION_CCK B43_PHY_CCK(0x00) /* Versioning register for B-PHY */ | ||
87 | #define B43_PHY_CCKBBANDCFG B43_PHY_CCK(0x01) /* Contains antenna 0/1 control bit */ | ||
88 | #define B43_PHY_PGACTL B43_PHY_CCK(0x15) /* PGA control */ | ||
89 | #define B43_PHY_PGACTL_LPF 0x1000 /* Low pass filter (?) */ | ||
90 | #define B43_PHY_PGACTL_LOWBANDW 0x0040 /* Low bandwidth flag */ | ||
91 | #define B43_PHY_PGACTL_UNKNOWN 0xEFA0 | ||
92 | #define B43_PHY_FBCTL1 B43_PHY_CCK(0x18) /* Frequency bandwidth control 1 */ | ||
93 | #define B43_PHY_ITSSI B43_PHY_CCK(0x29) /* Idle TSSI */ | ||
94 | #define B43_PHY_LO_LEAKAGE B43_PHY_CCK(0x2D) /* Measured LO leakage */ | ||
95 | #define B43_PHY_ENERGY B43_PHY_CCK(0x33) /* Energy */ | ||
96 | #define B43_PHY_SYNCCTL B43_PHY_CCK(0x35) | ||
97 | #define B43_PHY_FBCTL2 B43_PHY_CCK(0x38) /* Frequency bandwidth control 2 */ | ||
98 | #define B43_PHY_DACCTL B43_PHY_CCK(0x60) /* DAC control */ | ||
99 | #define B43_PHY_RCCALOVER B43_PHY_CCK(0x78) /* RC calibration override */ | ||
100 | |||
101 | /* Extended G-PHY Registers */ | ||
102 | #define B43_PHY_CLASSCTL B43_PHY_EXTG(0x02) /* Classify control */ | ||
103 | #define B43_PHY_GTABCTL B43_PHY_EXTG(0x03) /* G-PHY table control (see below) */ | ||
104 | #define B43_PHY_GTABOFF 0x03FF /* G-PHY table offset (see below) */ | ||
105 | #define B43_PHY_GTABNR 0xFC00 /* G-PHY table number (see below) */ | ||
106 | #define B43_PHY_GTABNR_SHIFT 10 | ||
107 | #define B43_PHY_GTABDATA B43_PHY_EXTG(0x04) /* G-PHY table data */ | ||
108 | #define B43_PHY_LO_MASK B43_PHY_EXTG(0x0F) /* Local Oscillator control mask */ | ||
109 | #define B43_PHY_LO_CTL B43_PHY_EXTG(0x10) /* Local Oscillator control */ | ||
110 | #define B43_PHY_RFOVER B43_PHY_EXTG(0x11) /* RF override */ | ||
111 | #define B43_PHY_RFOVERVAL B43_PHY_EXTG(0x12) /* RF override value */ | ||
112 | #define B43_PHY_RFOVERVAL_EXTLNA 0x8000 | ||
113 | #define B43_PHY_RFOVERVAL_LNA 0x7000 | ||
114 | #define B43_PHY_RFOVERVAL_LNA_SHIFT 12 | ||
115 | #define B43_PHY_RFOVERVAL_PGA 0x0F00 | ||
116 | #define B43_PHY_RFOVERVAL_PGA_SHIFT 8 | ||
117 | #define B43_PHY_RFOVERVAL_UNK 0x0010 /* Unknown, always set. */ | ||
118 | #define B43_PHY_RFOVERVAL_TRSWRX 0x00E0 | ||
119 | #define B43_PHY_RFOVERVAL_BW 0x0003 /* Bandwidth flags */ | ||
120 | #define B43_PHY_RFOVERVAL_BW_LPF 0x0001 /* Low Pass Filter */ | ||
121 | #define B43_PHY_RFOVERVAL_BW_LBW 0x0002 /* Low Bandwidth (when set), high when unset */ | ||
122 | #define B43_PHY_ANALOGOVER B43_PHY_EXTG(0x14) /* Analog override */ | ||
123 | #define B43_PHY_ANALOGOVERVAL B43_PHY_EXTG(0x15) /* Analog override value */ | ||
124 | |||
125 | /*** OFDM table numbers ***/ | ||
126 | #define B43_OFDMTAB(number, offset) (((number) << B43_PHY_OTABLENR_SHIFT) | (offset)) | ||
127 | #define B43_OFDMTAB_AGC1 B43_OFDMTAB(0x00, 0) | ||
128 | #define B43_OFDMTAB_GAIN0 B43_OFDMTAB(0x00, 0) | ||
129 | #define B43_OFDMTAB_GAINX B43_OFDMTAB(0x01, 0) //TODO rename | ||
130 | #define B43_OFDMTAB_GAIN1 B43_OFDMTAB(0x01, 4) | ||
131 | #define B43_OFDMTAB_AGC3 B43_OFDMTAB(0x02, 0) | ||
132 | #define B43_OFDMTAB_GAIN2 B43_OFDMTAB(0x02, 3) | ||
133 | #define B43_OFDMTAB_LNAHPFGAIN1 B43_OFDMTAB(0x03, 0) | ||
134 | #define B43_OFDMTAB_WRSSI B43_OFDMTAB(0x04, 0) | ||
135 | #define B43_OFDMTAB_LNAHPFGAIN2 B43_OFDMTAB(0x04, 0) | ||
136 | #define B43_OFDMTAB_NOISESCALE B43_OFDMTAB(0x05, 0) | ||
137 | #define B43_OFDMTAB_AGC2 B43_OFDMTAB(0x06, 0) | ||
138 | #define B43_OFDMTAB_ROTOR B43_OFDMTAB(0x08, 0) | ||
139 | #define B43_OFDMTAB_ADVRETARD B43_OFDMTAB(0x09, 0) | ||
140 | #define B43_OFDMTAB_DAC B43_OFDMTAB(0x0C, 0) | ||
141 | #define B43_OFDMTAB_DC B43_OFDMTAB(0x0E, 7) | ||
142 | #define B43_OFDMTAB_PWRDYN2 B43_OFDMTAB(0x0E, 12) | ||
143 | #define B43_OFDMTAB_LNAGAIN B43_OFDMTAB(0x0E, 13) | ||
144 | #define B43_OFDMTAB_UNKNOWN_0F B43_OFDMTAB(0x0F, 0) //TODO rename | ||
145 | #define B43_OFDMTAB_UNKNOWN_APHY B43_OFDMTAB(0x0F, 7) //TODO rename | ||
146 | #define B43_OFDMTAB_LPFGAIN B43_OFDMTAB(0x0F, 12) | ||
147 | #define B43_OFDMTAB_RSSI B43_OFDMTAB(0x10, 0) | ||
148 | #define B43_OFDMTAB_UNKNOWN_11 B43_OFDMTAB(0x11, 4) //TODO rename | ||
149 | #define B43_OFDMTAB_AGC1_R1 B43_OFDMTAB(0x13, 0) | ||
150 | #define B43_OFDMTAB_GAINX_R1 B43_OFDMTAB(0x14, 0) //TODO remove! | ||
151 | #define B43_OFDMTAB_MINSIGSQ B43_OFDMTAB(0x14, 0) | ||
152 | #define B43_OFDMTAB_AGC3_R1 B43_OFDMTAB(0x15, 0) | ||
153 | #define B43_OFDMTAB_WRSSI_R1 B43_OFDMTAB(0x15, 4) | ||
154 | #define B43_OFDMTAB_TSSI B43_OFDMTAB(0x15, 0) | ||
155 | #define B43_OFDMTAB_DACRFPABB B43_OFDMTAB(0x16, 0) | ||
156 | #define B43_OFDMTAB_DACOFF B43_OFDMTAB(0x17, 0) | ||
157 | #define B43_OFDMTAB_DCBIAS B43_OFDMTAB(0x18, 0) | ||
158 | |||
159 | u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset); | ||
160 | void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table, | ||
161 | u16 offset, u16 value); | ||
162 | u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset); | ||
163 | void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table, | ||
164 | u16 offset, u32 value); | ||
165 | |||
166 | /*** G-PHY table numbers */ | ||
167 | #define B43_GTAB(number, offset) (((number) << B43_PHY_GTABNR_SHIFT) | (offset)) | ||
168 | #define B43_GTAB_NRSSI B43_GTAB(0x00, 0) | ||
169 | #define B43_GTAB_TRFEMW B43_GTAB(0x0C, 0x120) | ||
170 | #define B43_GTAB_ORIGTR B43_GTAB(0x2E, 0x298) | ||
171 | |||
172 | u16 b43_gtab_read(struct b43_wldev *dev, u16 table, u16 offset); //TODO implement | ||
173 | void b43_gtab_write(struct b43_wldev *dev, u16 table, u16 offset, u16 value); //TODO implement | ||
174 | |||
175 | #define B43_DEFAULT_CHANNEL_A 36 | ||
176 | #define B43_DEFAULT_CHANNEL_BG 6 | ||
177 | |||
178 | enum { | ||
179 | B43_ANTENNA0, /* Antenna 0 */ | ||
180 | B43_ANTENNA1, /* Antenna 0 */ | ||
181 | B43_ANTENNA_AUTO1, /* Automatic, starting with antenna 1 */ | ||
182 | B43_ANTENNA_AUTO0, /* Automatic, starting with antenna 0 */ | ||
183 | B43_ANTENNA2, | ||
184 | B43_ANTENNA3 = 8, | ||
185 | |||
186 | B43_ANTENNA_AUTO = B43_ANTENNA_AUTO0, | ||
187 | B43_ANTENNA_DEFAULT = B43_ANTENNA_AUTO, | ||
188 | }; | ||
189 | |||
190 | enum { | ||
191 | B43_INTERFMODE_NONE, | ||
192 | B43_INTERFMODE_NONWLAN, | ||
193 | B43_INTERFMODE_MANUALWLAN, | ||
194 | B43_INTERFMODE_AUTOWLAN, | ||
195 | }; | ||
196 | |||
197 | /* Masks for the different PHY versioning registers. */ | ||
198 | #define B43_PHYVER_ANALOG 0xF000 | ||
199 | #define B43_PHYVER_ANALOG_SHIFT 12 | ||
200 | #define B43_PHYVER_TYPE 0x0F00 | ||
201 | #define B43_PHYVER_TYPE_SHIFT 8 | ||
202 | #define B43_PHYVER_VERSION 0x00FF | ||
203 | |||
204 | void b43_phy_lock(struct b43_wldev *dev); | ||
205 | void b43_phy_unlock(struct b43_wldev *dev); | ||
206 | |||
207 | |||
208 | /* Read a value from a PHY register */ | ||
209 | u16 b43_phy_read(struct b43_wldev *dev, u16 offset); | ||
210 | /* Write a value to a PHY register */ | ||
211 | void b43_phy_write(struct b43_wldev *dev, u16 offset, u16 val); | ||
212 | /* Mask a PHY register with a mask */ | ||
213 | void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask); | ||
214 | /* OR a PHY register with a bitmap */ | ||
215 | void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set); | ||
216 | /* Mask and OR a PHY register with a mask and bitmap */ | ||
217 | void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set); | ||
218 | |||
219 | |||
220 | int b43_phy_init_tssi2dbm_table(struct b43_wldev *dev); | ||
221 | |||
222 | void b43_phy_early_init(struct b43_wldev *dev); | ||
223 | int b43_phy_init(struct b43_wldev *dev); | ||
224 | |||
225 | void b43_set_rx_antenna(struct b43_wldev *dev, int antenna); | ||
226 | |||
227 | void b43_phy_xmitpower(struct b43_wldev *dev); | ||
228 | |||
229 | /* Returns the boolean whether the board has HardwarePowerControl */ | ||
230 | bool b43_has_hardware_pctl(struct b43_phy *phy); | ||
231 | /* Returns the boolean whether "TX Magnification" is enabled. */ | ||
232 | #define has_tx_magnification(phy) \ | ||
233 | (((phy)->rev >= 2) && \ | ||
234 | ((phy)->radio_ver == 0x2050) && \ | ||
235 | ((phy)->radio_rev == 8)) | ||
236 | /* Card uses the loopback gain stuff */ | ||
237 | #define has_loopback_gain(phy) \ | ||
238 | (((phy)->rev > 1) || ((phy)->gmode)) | ||
239 | |||
240 | /* Radio Attenuation (RF Attenuation) */ | ||
241 | struct b43_rfatt { | ||
242 | u8 att; /* Attenuation value */ | ||
243 | bool with_padmix; /* Flag, PAD Mixer enabled. */ | ||
244 | }; | ||
245 | struct b43_rfatt_list { | ||
246 | /* Attenuation values list */ | ||
247 | const struct b43_rfatt *list; | ||
248 | u8 len; | ||
249 | /* Minimum/Maximum attenuation values */ | ||
250 | u8 min_val; | ||
251 | u8 max_val; | ||
252 | }; | ||
253 | |||
254 | /* Returns true, if the values are the same. */ | ||
255 | static inline bool b43_compare_rfatt(const struct b43_rfatt *a, | ||
256 | const struct b43_rfatt *b) | ||
257 | { | ||
258 | return ((a->att == b->att) && | ||
259 | (a->with_padmix == b->with_padmix)); | ||
260 | } | ||
261 | |||
262 | /* Baseband Attenuation */ | ||
263 | struct b43_bbatt { | ||
264 | u8 att; /* Attenuation value */ | ||
265 | }; | ||
266 | struct b43_bbatt_list { | ||
267 | /* Attenuation values list */ | ||
268 | const struct b43_bbatt *list; | ||
269 | u8 len; | ||
270 | /* Minimum/Maximum attenuation values */ | ||
271 | u8 min_val; | ||
272 | u8 max_val; | ||
273 | }; | ||
274 | |||
275 | /* Returns true, if the values are the same. */ | ||
276 | static inline bool b43_compare_bbatt(const struct b43_bbatt *a, | ||
277 | const struct b43_bbatt *b) | ||
278 | { | ||
279 | return (a->att == b->att); | ||
280 | } | ||
281 | |||
282 | /* tx_control bits. */ | ||
283 | #define B43_TXCTL_PA3DB 0x40 /* PA Gain 3dB */ | ||
284 | #define B43_TXCTL_PA2DB 0x20 /* PA Gain 2dB */ | ||
285 | #define B43_TXCTL_TXMIX 0x10 /* TX Mixer Gain */ | ||
286 | |||
287 | /* Write BasebandAttenuation value to the device. */ | ||
288 | void b43_phy_set_baseband_attenuation(struct b43_wldev *dev, | ||
289 | u16 baseband_attenuation); | ||
290 | |||
291 | extern const u8 b43_radio_channel_codes_bg[]; | ||
292 | |||
293 | void b43_radio_lock(struct b43_wldev *dev); | ||
294 | void b43_radio_unlock(struct b43_wldev *dev); | ||
295 | |||
296 | |||
297 | /* Read a value from a 16bit radio register */ | ||
298 | u16 b43_radio_read16(struct b43_wldev *dev, u16 offset); | ||
299 | /* Write a value to a 16bit radio register */ | ||
300 | void b43_radio_write16(struct b43_wldev *dev, u16 offset, u16 val); | ||
301 | /* Mask a 16bit radio register with a mask */ | ||
302 | void b43_radio_mask(struct b43_wldev *dev, u16 offset, u16 mask); | ||
303 | /* OR a 16bit radio register with a bitmap */ | ||
304 | void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set); | ||
305 | /* Mask and OR a PHY register with a mask and bitmap */ | ||
306 | void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set); | ||
307 | |||
308 | |||
309 | u16 b43_radio_init2050(struct b43_wldev *dev); | ||
310 | void b43_radio_init2060(struct b43_wldev *dev); | ||
311 | |||
312 | void b43_radio_turn_on(struct b43_wldev *dev); | ||
313 | void b43_radio_turn_off(struct b43_wldev *dev, bool force); | ||
314 | |||
315 | int b43_radio_selectchannel(struct b43_wldev *dev, u8 channel, | ||
316 | int synthetic_pu_workaround); | ||
317 | |||
318 | u8 b43_radio_aci_detect(struct b43_wldev *dev, u8 channel); | ||
319 | u8 b43_radio_aci_scan(struct b43_wldev *dev); | ||
320 | |||
321 | int b43_radio_set_interference_mitigation(struct b43_wldev *dev, int mode); | ||
322 | |||
323 | void b43_calc_nrssi_slope(struct b43_wldev *dev); | ||
324 | void b43_calc_nrssi_threshold(struct b43_wldev *dev); | ||
325 | s16 b43_nrssi_hw_read(struct b43_wldev *dev, u16 offset); | ||
326 | void b43_nrssi_hw_write(struct b43_wldev *dev, u16 offset, s16 val); | ||
327 | void b43_nrssi_hw_update(struct b43_wldev *dev, u16 val); | ||
328 | void b43_nrssi_mem_update(struct b43_wldev *dev); | ||
329 | |||
330 | void b43_radio_set_tx_iq(struct b43_wldev *dev); | ||
331 | u16 b43_radio_calibrationvalue(struct b43_wldev *dev); | ||
332 | |||
333 | void b43_put_attenuation_into_ranges(struct b43_wldev *dev, | ||
334 | int *_bbatt, int *_rfatt); | ||
335 | |||
336 | void b43_set_txpower_g(struct b43_wldev *dev, | ||
337 | const struct b43_bbatt *bbatt, | ||
338 | const struct b43_rfatt *rfatt, u8 tx_control); | ||
339 | |||
340 | #endif /* B43_PHY_H_ */ | ||
diff --git a/drivers/net/wireless/b43/phy_a.c b/drivers/net/wireless/b43/phy_a.c new file mode 100644 index 000000000000..4d7d59e30960 --- /dev/null +++ b/drivers/net/wireless/b43/phy_a.c | |||
@@ -0,0 +1,543 @@ | |||
1 | /* | ||
2 | |||
3 | Broadcom B43 wireless driver | ||
4 | IEEE 802.11a PHY driver | ||
5 | |||
6 | Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>, | ||
7 | Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it> | ||
8 | Copyright (c) 2005-2008 Michael Buesch <mb@bu3sch.de> | ||
9 | Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org> | ||
10 | Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch> | ||
11 | |||
12 | This program is free software; you can redistribute it and/or modify | ||
13 | it under the terms of the GNU General Public License as published by | ||
14 | the Free Software Foundation; either version 2 of the License, or | ||
15 | (at your option) any later version. | ||
16 | |||
17 | This program is distributed in the hope that it will be useful, | ||
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | GNU General Public License for more details. | ||
21 | |||
22 | You should have received a copy of the GNU General Public License | ||
23 | along with this program; see the file COPYING. If not, write to | ||
24 | the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, | ||
25 | Boston, MA 02110-1301, USA. | ||
26 | |||
27 | */ | ||
28 | |||
29 | #include "b43.h" | ||
30 | #include "phy_a.h" | ||
31 | #include "phy_common.h" | ||
32 | #include "wa.h" | ||
33 | #include "tables.h" | ||
34 | #include "main.h" | ||
35 | |||
36 | |||
37 | /* Get the freq, as it has to be written to the device. */ | ||
38 | static inline u16 channel2freq_a(u8 channel) | ||
39 | { | ||
40 | B43_WARN_ON(channel > 200); | ||
41 | |||
42 | return (5000 + 5 * channel); | ||
43 | } | ||
44 | |||
45 | static inline u16 freq_r3A_value(u16 frequency) | ||
46 | { | ||
47 | u16 value; | ||
48 | |||
49 | if (frequency < 5091) | ||
50 | value = 0x0040; | ||
51 | else if (frequency < 5321) | ||
52 | value = 0x0000; | ||
53 | else if (frequency < 5806) | ||
54 | value = 0x0080; | ||
55 | else | ||
56 | value = 0x0040; | ||
57 | |||
58 | return value; | ||
59 | } | ||
60 | |||
61 | void b43_radio_set_tx_iq(struct b43_wldev *dev) | ||
62 | { | ||
63 | static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 }; | ||
64 | static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A }; | ||
65 | u16 tmp = b43_radio_read16(dev, 0x001E); | ||
66 | int i, j; | ||
67 | |||
68 | for (i = 0; i < 5; i++) { | ||
69 | for (j = 0; j < 5; j++) { | ||
70 | if (tmp == (data_high[i] << 4 | data_low[j])) { | ||
71 | b43_phy_write(dev, 0x0069, | ||
72 | (i - j) << 8 | 0x00C0); | ||
73 | return; | ||
74 | } | ||
75 | } | ||
76 | } | ||
77 | } | ||
78 | |||
79 | static void aphy_channel_switch(struct b43_wldev *dev, unsigned int channel) | ||
80 | { | ||
81 | u16 freq, r8, tmp; | ||
82 | |||
83 | freq = channel2freq_a(channel); | ||
84 | |||
85 | r8 = b43_radio_read16(dev, 0x0008); | ||
86 | b43_write16(dev, 0x03F0, freq); | ||
87 | b43_radio_write16(dev, 0x0008, r8); | ||
88 | |||
89 | //TODO: write max channel TX power? to Radio 0x2D | ||
90 | tmp = b43_radio_read16(dev, 0x002E); | ||
91 | tmp &= 0x0080; | ||
92 | //TODO: OR tmp with the Power out estimation for this channel? | ||
93 | b43_radio_write16(dev, 0x002E, tmp); | ||
94 | |||
95 | if (freq >= 4920 && freq <= 5500) { | ||
96 | /* | ||
97 | * r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0F; | ||
98 | * = (freq * 0.025862069 | ||
99 | */ | ||
100 | r8 = 3 * freq / 116; /* is equal to r8 = freq * 0.025862 */ | ||
101 | } | ||
102 | b43_radio_write16(dev, 0x0007, (r8 << 4) | r8); | ||
103 | b43_radio_write16(dev, 0x0020, (r8 << 4) | r8); | ||
104 | b43_radio_write16(dev, 0x0021, (r8 << 4) | r8); | ||
105 | b43_radio_write16(dev, 0x0022, (b43_radio_read16(dev, 0x0022) | ||
106 | & 0x000F) | (r8 << 4)); | ||
107 | b43_radio_write16(dev, 0x002A, (r8 << 4)); | ||
108 | b43_radio_write16(dev, 0x002B, (r8 << 4)); | ||
109 | b43_radio_write16(dev, 0x0008, (b43_radio_read16(dev, 0x0008) | ||
110 | & 0x00F0) | (r8 << 4)); | ||
111 | b43_radio_write16(dev, 0x0029, (b43_radio_read16(dev, 0x0029) | ||
112 | & 0xFF0F) | 0x00B0); | ||
113 | b43_radio_write16(dev, 0x0035, 0x00AA); | ||
114 | b43_radio_write16(dev, 0x0036, 0x0085); | ||
115 | b43_radio_write16(dev, 0x003A, (b43_radio_read16(dev, 0x003A) | ||
116 | & 0xFF20) | | ||
117 | freq_r3A_value(freq)); | ||
118 | b43_radio_write16(dev, 0x003D, | ||
119 | b43_radio_read16(dev, 0x003D) & 0x00FF); | ||
120 | b43_radio_write16(dev, 0x0081, (b43_radio_read16(dev, 0x0081) | ||
121 | & 0xFF7F) | 0x0080); | ||
122 | b43_radio_write16(dev, 0x0035, | ||
123 | b43_radio_read16(dev, 0x0035) & 0xFFEF); | ||
124 | b43_radio_write16(dev, 0x0035, (b43_radio_read16(dev, 0x0035) | ||
125 | & 0xFFEF) | 0x0010); | ||
126 | b43_radio_set_tx_iq(dev); | ||
127 | //TODO: TSSI2dbm workaround | ||
128 | //FIXME b43_phy_xmitpower(dev); | ||
129 | } | ||
130 | |||
131 | void b43_radio_init2060(struct b43_wldev *dev) | ||
132 | { | ||
133 | b43_radio_write16(dev, 0x0004, 0x00C0); | ||
134 | b43_radio_write16(dev, 0x0005, 0x0008); | ||
135 | b43_radio_write16(dev, 0x0009, 0x0040); | ||
136 | b43_radio_write16(dev, 0x0005, 0x00AA); | ||
137 | b43_radio_write16(dev, 0x0032, 0x008F); | ||
138 | b43_radio_write16(dev, 0x0006, 0x008F); | ||
139 | b43_radio_write16(dev, 0x0034, 0x008F); | ||
140 | b43_radio_write16(dev, 0x002C, 0x0007); | ||
141 | b43_radio_write16(dev, 0x0082, 0x0080); | ||
142 | b43_radio_write16(dev, 0x0080, 0x0000); | ||
143 | b43_radio_write16(dev, 0x003F, 0x00DA); | ||
144 | b43_radio_write16(dev, 0x0005, b43_radio_read16(dev, 0x0005) & ~0x0008); | ||
145 | b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0010); | ||
146 | b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0020); | ||
147 | b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0020); | ||
148 | msleep(1); /* delay 400usec */ | ||
149 | |||
150 | b43_radio_write16(dev, 0x0081, | ||
151 | (b43_radio_read16(dev, 0x0081) & ~0x0020) | 0x0010); | ||
152 | msleep(1); /* delay 400usec */ | ||
153 | |||
154 | b43_radio_write16(dev, 0x0005, | ||
155 | (b43_radio_read16(dev, 0x0005) & ~0x0008) | 0x0008); | ||
156 | b43_radio_write16(dev, 0x0085, b43_radio_read16(dev, 0x0085) & ~0x0010); | ||
157 | b43_radio_write16(dev, 0x0005, b43_radio_read16(dev, 0x0005) & ~0x0008); | ||
158 | b43_radio_write16(dev, 0x0081, b43_radio_read16(dev, 0x0081) & ~0x0040); | ||
159 | b43_radio_write16(dev, 0x0081, | ||
160 | (b43_radio_read16(dev, 0x0081) & ~0x0040) | 0x0040); | ||
161 | b43_radio_write16(dev, 0x0005, | ||
162 | (b43_radio_read16(dev, 0x0081) & ~0x0008) | 0x0008); | ||
163 | b43_phy_write(dev, 0x0063, 0xDDC6); | ||
164 | b43_phy_write(dev, 0x0069, 0x07BE); | ||
165 | b43_phy_write(dev, 0x006A, 0x0000); | ||
166 | |||
167 | aphy_channel_switch(dev, dev->phy.ops->get_default_chan(dev)); | ||
168 | |||
169 | msleep(1); | ||
170 | } | ||
171 | |||
172 | static void b43_phy_rssiagc(struct b43_wldev *dev, u8 enable) | ||
173 | { | ||
174 | int i; | ||
175 | |||
176 | if (dev->phy.rev < 3) { | ||
177 | if (enable) | ||
178 | for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++) { | ||
179 | b43_ofdmtab_write16(dev, | ||
180 | B43_OFDMTAB_LNAHPFGAIN1, i, 0xFFF8); | ||
181 | b43_ofdmtab_write16(dev, | ||
182 | B43_OFDMTAB_WRSSI, i, 0xFFF8); | ||
183 | } | ||
184 | else | ||
185 | for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++) { | ||
186 | b43_ofdmtab_write16(dev, | ||
187 | B43_OFDMTAB_LNAHPFGAIN1, i, b43_tab_rssiagc1[i]); | ||
188 | b43_ofdmtab_write16(dev, | ||
189 | B43_OFDMTAB_WRSSI, i, b43_tab_rssiagc1[i]); | ||
190 | } | ||
191 | } else { | ||
192 | if (enable) | ||
193 | for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++) | ||
194 | b43_ofdmtab_write16(dev, | ||
195 | B43_OFDMTAB_WRSSI, i, 0x0820); | ||
196 | else | ||
197 | for (i = 0; i < B43_TAB_RSSIAGC2_SIZE; i++) | ||
198 | b43_ofdmtab_write16(dev, | ||
199 | B43_OFDMTAB_WRSSI, i, b43_tab_rssiagc2[i]); | ||
200 | } | ||
201 | } | ||
202 | |||
203 | static void b43_phy_ww(struct b43_wldev *dev) | ||
204 | { | ||
205 | u16 b, curr_s, best_s = 0xFFFF; | ||
206 | int i; | ||
207 | |||
208 | b43_phy_write(dev, B43_PHY_CRS0, | ||
209 | b43_phy_read(dev, B43_PHY_CRS0) & ~B43_PHY_CRS0_EN); | ||
210 | b43_phy_write(dev, B43_PHY_OFDM(0x1B), | ||
211 | b43_phy_read(dev, B43_PHY_OFDM(0x1B)) | 0x1000); | ||
212 | b43_phy_write(dev, B43_PHY_OFDM(0x82), | ||
213 | (b43_phy_read(dev, B43_PHY_OFDM(0x82)) & 0xF0FF) | 0x0300); | ||
214 | b43_radio_write16(dev, 0x0009, | ||
215 | b43_radio_read16(dev, 0x0009) | 0x0080); | ||
216 | b43_radio_write16(dev, 0x0012, | ||
217 | (b43_radio_read16(dev, 0x0012) & 0xFFFC) | 0x0002); | ||
218 | b43_wa_initgains(dev); | ||
219 | b43_phy_write(dev, B43_PHY_OFDM(0xBA), 0x3ED5); | ||
220 | b = b43_phy_read(dev, B43_PHY_PWRDOWN); | ||
221 | b43_phy_write(dev, B43_PHY_PWRDOWN, (b & 0xFFF8) | 0x0005); | ||
222 | b43_radio_write16(dev, 0x0004, | ||
223 | b43_radio_read16(dev, 0x0004) | 0x0004); | ||
224 | for (i = 0x10; i <= 0x20; i++) { | ||
225 | b43_radio_write16(dev, 0x0013, i); | ||
226 | curr_s = b43_phy_read(dev, B43_PHY_OTABLEQ) & 0x00FF; | ||
227 | if (!curr_s) { | ||
228 | best_s = 0x0000; | ||
229 | break; | ||
230 | } else if (curr_s >= 0x0080) | ||
231 | curr_s = 0x0100 - curr_s; | ||
232 | if (curr_s < best_s) | ||
233 | best_s = curr_s; | ||
234 | } | ||
235 | b43_phy_write(dev, B43_PHY_PWRDOWN, b); | ||
236 | b43_radio_write16(dev, 0x0004, | ||
237 | b43_radio_read16(dev, 0x0004) & 0xFFFB); | ||
238 | b43_radio_write16(dev, 0x0013, best_s); | ||
239 | b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 0, 0xFFEC); | ||
240 | b43_phy_write(dev, B43_PHY_OFDM(0xB7), 0x1E80); | ||
241 | b43_phy_write(dev, B43_PHY_OFDM(0xB6), 0x1C00); | ||
242 | b43_phy_write(dev, B43_PHY_OFDM(0xB5), 0x0EC0); | ||
243 | b43_phy_write(dev, B43_PHY_OFDM(0xB2), 0x00C0); | ||
244 | b43_phy_write(dev, B43_PHY_OFDM(0xB9), 0x1FFF); | ||
245 | b43_phy_write(dev, B43_PHY_OFDM(0xBB), | ||
246 | (b43_phy_read(dev, B43_PHY_OFDM(0xBB)) & 0xF000) | 0x0053); | ||
247 | b43_phy_write(dev, B43_PHY_OFDM61, | ||
248 | (b43_phy_read(dev, B43_PHY_OFDM61) & 0xFE1F) | 0x0120); | ||
249 | b43_phy_write(dev, B43_PHY_OFDM(0x13), | ||
250 | (b43_phy_read(dev, B43_PHY_OFDM(0x13)) & 0x0FFF) | 0x3000); | ||
251 | b43_phy_write(dev, B43_PHY_OFDM(0x14), | ||
252 | (b43_phy_read(dev, B43_PHY_OFDM(0x14)) & 0x0FFF) | 0x3000); | ||
253 | b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 6, 0x0017); | ||
254 | for (i = 0; i < 6; i++) | ||
255 | b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, i, 0x000F); | ||
256 | b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0D, 0x000E); | ||
257 | b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0E, 0x0011); | ||
258 | b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0F, 0x0013); | ||
259 | b43_phy_write(dev, B43_PHY_OFDM(0x33), 0x5030); | ||
260 | b43_phy_write(dev, B43_PHY_CRS0, | ||
261 | b43_phy_read(dev, B43_PHY_CRS0) | B43_PHY_CRS0_EN); | ||
262 | } | ||
263 | |||
264 | static void hardware_pctl_init_aphy(struct b43_wldev *dev) | ||
265 | { | ||
266 | //TODO | ||
267 | } | ||
268 | |||
269 | void b43_phy_inita(struct b43_wldev *dev) | ||
270 | { | ||
271 | struct ssb_bus *bus = dev->dev->bus; | ||
272 | struct b43_phy *phy = &dev->phy; | ||
273 | |||
274 | /* This lowlevel A-PHY init is also called from G-PHY init. | ||
275 | * So we must not access phy->a, if called from G-PHY code. | ||
276 | */ | ||
277 | B43_WARN_ON((phy->type != B43_PHYTYPE_A) && | ||
278 | (phy->type != B43_PHYTYPE_G)); | ||
279 | |||
280 | might_sleep(); | ||
281 | |||
282 | if (phy->rev >= 6) { | ||
283 | if (phy->type == B43_PHYTYPE_A) | ||
284 | b43_phy_write(dev, B43_PHY_OFDM(0x1B), | ||
285 | b43_phy_read(dev, B43_PHY_OFDM(0x1B)) & ~0x1000); | ||
286 | if (b43_phy_read(dev, B43_PHY_ENCORE) & B43_PHY_ENCORE_EN) | ||
287 | b43_phy_write(dev, B43_PHY_ENCORE, | ||
288 | b43_phy_read(dev, B43_PHY_ENCORE) | 0x0010); | ||
289 | else | ||
290 | b43_phy_write(dev, B43_PHY_ENCORE, | ||
291 | b43_phy_read(dev, B43_PHY_ENCORE) & ~0x1010); | ||
292 | } | ||
293 | |||
294 | b43_wa_all(dev); | ||
295 | |||
296 | if (phy->type == B43_PHYTYPE_A) { | ||
297 | if (phy->gmode && (phy->rev < 3)) | ||
298 | b43_phy_write(dev, 0x0034, | ||
299 | b43_phy_read(dev, 0x0034) | 0x0001); | ||
300 | b43_phy_rssiagc(dev, 0); | ||
301 | |||
302 | b43_phy_write(dev, B43_PHY_CRS0, | ||
303 | b43_phy_read(dev, B43_PHY_CRS0) | B43_PHY_CRS0_EN); | ||
304 | |||
305 | b43_radio_init2060(dev); | ||
306 | |||
307 | if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) && | ||
308 | ((bus->boardinfo.type == SSB_BOARD_BU4306) || | ||
309 | (bus->boardinfo.type == SSB_BOARD_BU4309))) { | ||
310 | ; //TODO: A PHY LO | ||
311 | } | ||
312 | |||
313 | if (phy->rev >= 3) | ||
314 | b43_phy_ww(dev); | ||
315 | |||
316 | hardware_pctl_init_aphy(dev); | ||
317 | |||
318 | //TODO: radar detection | ||
319 | } | ||
320 | |||
321 | if ((phy->type == B43_PHYTYPE_G) && | ||
322 | (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)) { | ||
323 | b43_phy_write(dev, B43_PHY_OFDM(0x6E), | ||
324 | (b43_phy_read(dev, B43_PHY_OFDM(0x6E)) | ||
325 | & 0xE000) | 0x3CF); | ||
326 | } | ||
327 | } | ||
328 | |||
329 | static int b43_aphy_op_allocate(struct b43_wldev *dev) | ||
330 | { | ||
331 | struct b43_phy_a *aphy; | ||
332 | |||
333 | aphy = kzalloc(sizeof(*aphy), GFP_KERNEL); | ||
334 | if (!aphy) | ||
335 | return -ENOMEM; | ||
336 | dev->phy.a = aphy; | ||
337 | |||
338 | //TODO init struct b43_phy_a | ||
339 | |||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | static int b43_aphy_op_init(struct b43_wldev *dev) | ||
344 | { | ||
345 | struct b43_phy_a *aphy = dev->phy.a; | ||
346 | |||
347 | b43_phy_inita(dev); | ||
348 | aphy->initialised = 1; | ||
349 | |||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | static void b43_aphy_op_exit(struct b43_wldev *dev) | ||
354 | { | ||
355 | struct b43_phy_a *aphy = dev->phy.a; | ||
356 | |||
357 | if (aphy->initialised) { | ||
358 | //TODO | ||
359 | aphy->initialised = 0; | ||
360 | } | ||
361 | //TODO | ||
362 | kfree(aphy); | ||
363 | dev->phy.a = NULL; | ||
364 | } | ||
365 | |||
366 | static inline u16 adjust_phyreg(struct b43_wldev *dev, u16 offset) | ||
367 | { | ||
368 | /* OFDM registers are base-registers for the A-PHY. */ | ||
369 | if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) { | ||
370 | offset &= ~B43_PHYROUTE; | ||
371 | offset |= B43_PHYROUTE_BASE; | ||
372 | } | ||
373 | |||
374 | #if B43_DEBUG | ||
375 | if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) { | ||
376 | /* Ext-G registers are only available on G-PHYs */ | ||
377 | b43err(dev->wl, "Invalid EXT-G PHY access at " | ||
378 | "0x%04X on A-PHY\n", offset); | ||
379 | dump_stack(); | ||
380 | } | ||
381 | if ((offset & B43_PHYROUTE) == B43_PHYROUTE_N_BMODE) { | ||
382 | /* N-BMODE registers are only available on N-PHYs */ | ||
383 | b43err(dev->wl, "Invalid N-BMODE PHY access at " | ||
384 | "0x%04X on A-PHY\n", offset); | ||
385 | dump_stack(); | ||
386 | } | ||
387 | #endif /* B43_DEBUG */ | ||
388 | |||
389 | return offset; | ||
390 | } | ||
391 | |||
392 | static u16 b43_aphy_op_read(struct b43_wldev *dev, u16 reg) | ||
393 | { | ||
394 | reg = adjust_phyreg(dev, reg); | ||
395 | b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); | ||
396 | return b43_read16(dev, B43_MMIO_PHY_DATA); | ||
397 | } | ||
398 | |||
399 | static void b43_aphy_op_write(struct b43_wldev *dev, u16 reg, u16 value) | ||
400 | { | ||
401 | reg = adjust_phyreg(dev, reg); | ||
402 | b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); | ||
403 | b43_write16(dev, B43_MMIO_PHY_DATA, value); | ||
404 | } | ||
405 | |||
406 | static u16 b43_aphy_op_radio_read(struct b43_wldev *dev, u16 reg) | ||
407 | { | ||
408 | /* Register 1 is a 32-bit register. */ | ||
409 | B43_WARN_ON(reg == 1); | ||
410 | /* A-PHY needs 0x40 for read access */ | ||
411 | reg |= 0x40; | ||
412 | |||
413 | b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); | ||
414 | return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW); | ||
415 | } | ||
416 | |||
417 | static void b43_aphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) | ||
418 | { | ||
419 | /* Register 1 is a 32-bit register. */ | ||
420 | B43_WARN_ON(reg == 1); | ||
421 | |||
422 | b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); | ||
423 | b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); | ||
424 | } | ||
425 | |||
426 | static bool b43_aphy_op_supports_hwpctl(struct b43_wldev *dev) | ||
427 | { | ||
428 | return (dev->phy.rev >= 5); | ||
429 | } | ||
430 | |||
431 | static void b43_aphy_op_software_rfkill(struct b43_wldev *dev, | ||
432 | enum rfkill_state state) | ||
433 | {//TODO | ||
434 | } | ||
435 | |||
436 | static int b43_aphy_op_switch_channel(struct b43_wldev *dev, | ||
437 | unsigned int new_channel) | ||
438 | { | ||
439 | if (new_channel > 200) | ||
440 | return -EINVAL; | ||
441 | aphy_channel_switch(dev, new_channel); | ||
442 | |||
443 | return 0; | ||
444 | } | ||
445 | |||
446 | static unsigned int b43_aphy_op_get_default_chan(struct b43_wldev *dev) | ||
447 | { | ||
448 | return 36; /* Default to channel 36 */ | ||
449 | } | ||
450 | |||
451 | static void b43_aphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna) | ||
452 | {//TODO | ||
453 | struct b43_phy *phy = &dev->phy; | ||
454 | u64 hf; | ||
455 | u16 tmp; | ||
456 | int autodiv = 0; | ||
457 | |||
458 | if (antenna == B43_ANTENNA_AUTO0 || antenna == B43_ANTENNA_AUTO1) | ||
459 | autodiv = 1; | ||
460 | |||
461 | hf = b43_hf_read(dev); | ||
462 | hf &= ~B43_HF_ANTDIVHELP; | ||
463 | b43_hf_write(dev, hf); | ||
464 | |||
465 | tmp = b43_phy_read(dev, B43_PHY_BBANDCFG); | ||
466 | tmp &= ~B43_PHY_BBANDCFG_RXANT; | ||
467 | tmp |= (autodiv ? B43_ANTENNA_AUTO0 : antenna) | ||
468 | << B43_PHY_BBANDCFG_RXANT_SHIFT; | ||
469 | b43_phy_write(dev, B43_PHY_BBANDCFG, tmp); | ||
470 | |||
471 | if (autodiv) { | ||
472 | tmp = b43_phy_read(dev, B43_PHY_ANTDWELL); | ||
473 | if (antenna == B43_ANTENNA_AUTO0) | ||
474 | tmp &= ~B43_PHY_ANTDWELL_AUTODIV1; | ||
475 | else | ||
476 | tmp |= B43_PHY_ANTDWELL_AUTODIV1; | ||
477 | b43_phy_write(dev, B43_PHY_ANTDWELL, tmp); | ||
478 | } | ||
479 | if (phy->rev < 3) { | ||
480 | tmp = b43_phy_read(dev, B43_PHY_ANTDWELL); | ||
481 | tmp = (tmp & 0xFF00) | 0x24; | ||
482 | b43_phy_write(dev, B43_PHY_ANTDWELL, tmp); | ||
483 | } else { | ||
484 | tmp = b43_phy_read(dev, B43_PHY_OFDM61); | ||
485 | tmp |= 0x10; | ||
486 | b43_phy_write(dev, B43_PHY_OFDM61, tmp); | ||
487 | if (phy->analog == 3) { | ||
488 | b43_phy_write(dev, B43_PHY_CLIPPWRDOWNT, | ||
489 | 0x1D); | ||
490 | b43_phy_write(dev, B43_PHY_ADIVRELATED, | ||
491 | 8); | ||
492 | } else { | ||
493 | b43_phy_write(dev, B43_PHY_CLIPPWRDOWNT, | ||
494 | 0x3A); | ||
495 | tmp = | ||
496 | b43_phy_read(dev, | ||
497 | B43_PHY_ADIVRELATED); | ||
498 | tmp = (tmp & 0xFF00) | 8; | ||
499 | b43_phy_write(dev, B43_PHY_ADIVRELATED, | ||
500 | tmp); | ||
501 | } | ||
502 | } | ||
503 | |||
504 | hf |= B43_HF_ANTDIVHELP; | ||
505 | b43_hf_write(dev, hf); | ||
506 | } | ||
507 | |||
508 | static void b43_aphy_op_adjust_txpower(struct b43_wldev *dev) | ||
509 | {//TODO | ||
510 | } | ||
511 | |||
512 | static enum b43_txpwr_result b43_aphy_op_recalc_txpower(struct b43_wldev *dev, | ||
513 | bool ignore_tssi) | ||
514 | {//TODO | ||
515 | return B43_TXPWR_RES_DONE; | ||
516 | } | ||
517 | |||
518 | static void b43_aphy_op_pwork_15sec(struct b43_wldev *dev) | ||
519 | {//TODO | ||
520 | } | ||
521 | |||
522 | static void b43_aphy_op_pwork_60sec(struct b43_wldev *dev) | ||
523 | {//TODO | ||
524 | } | ||
525 | |||
526 | const struct b43_phy_operations b43_phyops_a = { | ||
527 | .allocate = b43_aphy_op_allocate, | ||
528 | .init = b43_aphy_op_init, | ||
529 | .exit = b43_aphy_op_exit, | ||
530 | .phy_read = b43_aphy_op_read, | ||
531 | .phy_write = b43_aphy_op_write, | ||
532 | .radio_read = b43_aphy_op_radio_read, | ||
533 | .radio_write = b43_aphy_op_radio_write, | ||
534 | .supports_hwpctl = b43_aphy_op_supports_hwpctl, | ||
535 | .software_rfkill = b43_aphy_op_software_rfkill, | ||
536 | .switch_channel = b43_aphy_op_switch_channel, | ||
537 | .get_default_chan = b43_aphy_op_get_default_chan, | ||
538 | .set_rx_antenna = b43_aphy_op_set_rx_antenna, | ||
539 | .recalc_txpower = b43_aphy_op_recalc_txpower, | ||
540 | .adjust_txpower = b43_aphy_op_adjust_txpower, | ||
541 | .pwork_15sec = b43_aphy_op_pwork_15sec, | ||
542 | .pwork_60sec = b43_aphy_op_pwork_60sec, | ||
543 | }; | ||
diff --git a/drivers/net/wireless/b43/phy_a.h b/drivers/net/wireless/b43/phy_a.h new file mode 100644 index 000000000000..e8640f7312bf --- /dev/null +++ b/drivers/net/wireless/b43/phy_a.h | |||
@@ -0,0 +1,124 @@ | |||
1 | #ifndef LINUX_B43_PHY_A_H_ | ||
2 | #define LINUX_B43_PHY_A_H_ | ||
3 | |||
4 | #include "phy_common.h" | ||
5 | |||
6 | |||
7 | /* OFDM (A) PHY Registers */ | ||
8 | #define B43_PHY_VERSION_OFDM B43_PHY_OFDM(0x00) /* Versioning register for A-PHY */ | ||
9 | #define B43_PHY_BBANDCFG B43_PHY_OFDM(0x01) /* Baseband config */ | ||
10 | #define B43_PHY_BBANDCFG_RXANT 0x180 /* RX Antenna selection */ | ||
11 | #define B43_PHY_BBANDCFG_RXANT_SHIFT 7 | ||
12 | #define B43_PHY_PWRDOWN B43_PHY_OFDM(0x03) /* Powerdown */ | ||
13 | #define B43_PHY_CRSTHRES1_R1 B43_PHY_OFDM(0x06) /* CRS Threshold 1 (phy.rev 1 only) */ | ||
14 | #define B43_PHY_LNAHPFCTL B43_PHY_OFDM(0x1C) /* LNA/HPF control */ | ||
15 | #define B43_PHY_LPFGAINCTL B43_PHY_OFDM(0x20) /* LPF Gain control */ | ||
16 | #define B43_PHY_ADIVRELATED B43_PHY_OFDM(0x27) /* FIXME rename */ | ||
17 | #define B43_PHY_CRS0 B43_PHY_OFDM(0x29) | ||
18 | #define B43_PHY_CRS0_EN 0x4000 | ||
19 | #define B43_PHY_PEAK_COUNT B43_PHY_OFDM(0x30) | ||
20 | #define B43_PHY_ANTDWELL B43_PHY_OFDM(0x2B) /* Antenna dwell */ | ||
21 | #define B43_PHY_ANTDWELL_AUTODIV1 0x0100 /* Automatic RX diversity start antenna */ | ||
22 | #define B43_PHY_ENCORE B43_PHY_OFDM(0x49) /* "Encore" (RangeMax / BroadRange) */ | ||
23 | #define B43_PHY_ENCORE_EN 0x0200 /* Encore enable */ | ||
24 | #define B43_PHY_LMS B43_PHY_OFDM(0x55) | ||
25 | #define B43_PHY_OFDM61 B43_PHY_OFDM(0x61) /* FIXME rename */ | ||
26 | #define B43_PHY_OFDM61_10 0x0010 /* FIXME rename */ | ||
27 | #define B43_PHY_IQBAL B43_PHY_OFDM(0x69) /* I/Q balance */ | ||
28 | #define B43_PHY_BBTXDC_BIAS B43_PHY_OFDM(0x6B) /* Baseband TX DC bias */ | ||
29 | #define B43_PHY_OTABLECTL B43_PHY_OFDM(0x72) /* OFDM table control (see below) */ | ||
30 | #define B43_PHY_OTABLEOFF 0x03FF /* OFDM table offset (see below) */ | ||
31 | #define B43_PHY_OTABLENR 0xFC00 /* OFDM table number (see below) */ | ||
32 | #define B43_PHY_OTABLENR_SHIFT 10 | ||
33 | #define B43_PHY_OTABLEI B43_PHY_OFDM(0x73) /* OFDM table data I */ | ||
34 | #define B43_PHY_OTABLEQ B43_PHY_OFDM(0x74) /* OFDM table data Q */ | ||
35 | #define B43_PHY_HPWR_TSSICTL B43_PHY_OFDM(0x78) /* Hardware power TSSI control */ | ||
36 | #define B43_PHY_ADCCTL B43_PHY_OFDM(0x7A) /* ADC control */ | ||
37 | #define B43_PHY_IDLE_TSSI B43_PHY_OFDM(0x7B) | ||
38 | #define B43_PHY_A_TEMP_SENSE B43_PHY_OFDM(0x7C) /* A PHY temperature sense */ | ||
39 | #define B43_PHY_NRSSITHRES B43_PHY_OFDM(0x8A) /* NRSSI threshold */ | ||
40 | #define B43_PHY_ANTWRSETT B43_PHY_OFDM(0x8C) /* Antenna WR settle */ | ||
41 | #define B43_PHY_ANTWRSETT_ARXDIV 0x2000 /* Automatic RX diversity enabled */ | ||
42 | #define B43_PHY_CLIPPWRDOWNT B43_PHY_OFDM(0x93) /* Clip powerdown threshold */ | ||
43 | #define B43_PHY_OFDM9B B43_PHY_OFDM(0x9B) /* FIXME rename */ | ||
44 | #define B43_PHY_N1P1GAIN B43_PHY_OFDM(0xA0) | ||
45 | #define B43_PHY_P1P2GAIN B43_PHY_OFDM(0xA1) | ||
46 | #define B43_PHY_N1N2GAIN B43_PHY_OFDM(0xA2) | ||
47 | #define B43_PHY_CLIPTHRES B43_PHY_OFDM(0xA3) | ||
48 | #define B43_PHY_CLIPN1P2THRES B43_PHY_OFDM(0xA4) | ||
49 | #define B43_PHY_CCKSHIFTBITS_WA B43_PHY_OFDM(0xA5) /* CCK shiftbits workaround, FIXME rename */ | ||
50 | #define B43_PHY_CCKSHIFTBITS B43_PHY_OFDM(0xA7) /* FIXME rename */ | ||
51 | #define B43_PHY_DIVSRCHIDX B43_PHY_OFDM(0xA8) /* Divider search gain/index */ | ||
52 | #define B43_PHY_CLIPP2THRES B43_PHY_OFDM(0xA9) | ||
53 | #define B43_PHY_CLIPP3THRES B43_PHY_OFDM(0xAA) | ||
54 | #define B43_PHY_DIVP1P2GAIN B43_PHY_OFDM(0xAB) | ||
55 | #define B43_PHY_DIVSRCHGAINBACK B43_PHY_OFDM(0xAD) /* Divider search gain back */ | ||
56 | #define B43_PHY_DIVSRCHGAINCHNG B43_PHY_OFDM(0xAE) /* Divider search gain change */ | ||
57 | #define B43_PHY_CRSTHRES1 B43_PHY_OFDM(0xC0) /* CRS Threshold 1 (phy.rev >= 2 only) */ | ||
58 | #define B43_PHY_CRSTHRES2 B43_PHY_OFDM(0xC1) /* CRS Threshold 2 (phy.rev >= 2 only) */ | ||
59 | #define B43_PHY_TSSIP_LTBASE B43_PHY_OFDM(0x380) /* TSSI power lookup table base */ | ||
60 | #define B43_PHY_DC_LTBASE B43_PHY_OFDM(0x3A0) /* DC lookup table base */ | ||
61 | #define B43_PHY_GAIN_LTBASE B43_PHY_OFDM(0x3C0) /* Gain lookup table base */ | ||
62 | |||
63 | /*** OFDM table numbers ***/ | ||
64 | #define B43_OFDMTAB(number, offset) (((number) << B43_PHY_OTABLENR_SHIFT) | (offset)) | ||
65 | #define B43_OFDMTAB_AGC1 B43_OFDMTAB(0x00, 0) | ||
66 | #define B43_OFDMTAB_GAIN0 B43_OFDMTAB(0x00, 0) | ||
67 | #define B43_OFDMTAB_GAINX B43_OFDMTAB(0x01, 0) //TODO rename | ||
68 | #define B43_OFDMTAB_GAIN1 B43_OFDMTAB(0x01, 4) | ||
69 | #define B43_OFDMTAB_AGC3 B43_OFDMTAB(0x02, 0) | ||
70 | #define B43_OFDMTAB_GAIN2 B43_OFDMTAB(0x02, 3) | ||
71 | #define B43_OFDMTAB_LNAHPFGAIN1 B43_OFDMTAB(0x03, 0) | ||
72 | #define B43_OFDMTAB_WRSSI B43_OFDMTAB(0x04, 0) | ||
73 | #define B43_OFDMTAB_LNAHPFGAIN2 B43_OFDMTAB(0x04, 0) | ||
74 | #define B43_OFDMTAB_NOISESCALE B43_OFDMTAB(0x05, 0) | ||
75 | #define B43_OFDMTAB_AGC2 B43_OFDMTAB(0x06, 0) | ||
76 | #define B43_OFDMTAB_ROTOR B43_OFDMTAB(0x08, 0) | ||
77 | #define B43_OFDMTAB_ADVRETARD B43_OFDMTAB(0x09, 0) | ||
78 | #define B43_OFDMTAB_DAC B43_OFDMTAB(0x0C, 0) | ||
79 | #define B43_OFDMTAB_DC B43_OFDMTAB(0x0E, 7) | ||
80 | #define B43_OFDMTAB_PWRDYN2 B43_OFDMTAB(0x0E, 12) | ||
81 | #define B43_OFDMTAB_LNAGAIN B43_OFDMTAB(0x0E, 13) | ||
82 | #define B43_OFDMTAB_UNKNOWN_0F B43_OFDMTAB(0x0F, 0) //TODO rename | ||
83 | #define B43_OFDMTAB_UNKNOWN_APHY B43_OFDMTAB(0x0F, 7) //TODO rename | ||
84 | #define B43_OFDMTAB_LPFGAIN B43_OFDMTAB(0x0F, 12) | ||
85 | #define B43_OFDMTAB_RSSI B43_OFDMTAB(0x10, 0) | ||
86 | #define B43_OFDMTAB_UNKNOWN_11 B43_OFDMTAB(0x11, 4) //TODO rename | ||
87 | #define B43_OFDMTAB_AGC1_R1 B43_OFDMTAB(0x13, 0) | ||
88 | #define B43_OFDMTAB_GAINX_R1 B43_OFDMTAB(0x14, 0) //TODO remove! | ||
89 | #define B43_OFDMTAB_MINSIGSQ B43_OFDMTAB(0x14, 0) | ||
90 | #define B43_OFDMTAB_AGC3_R1 B43_OFDMTAB(0x15, 0) | ||
91 | #define B43_OFDMTAB_WRSSI_R1 B43_OFDMTAB(0x15, 4) | ||
92 | #define B43_OFDMTAB_TSSI B43_OFDMTAB(0x15, 0) | ||
93 | #define B43_OFDMTAB_DACRFPABB B43_OFDMTAB(0x16, 0) | ||
94 | #define B43_OFDMTAB_DACOFF B43_OFDMTAB(0x17, 0) | ||
95 | #define B43_OFDMTAB_DCBIAS B43_OFDMTAB(0x18, 0) | ||
96 | |||
97 | u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset); | ||
98 | void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table, | ||
99 | u16 offset, u16 value); | ||
100 | u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset); | ||
101 | void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table, | ||
102 | u16 offset, u32 value); | ||
103 | |||
104 | |||
105 | struct b43_phy_a { | ||
106 | bool initialised; | ||
107 | |||
108 | /* A-PHY TX Power control value. */ | ||
109 | u16 txpwr_offset; | ||
110 | |||
111 | //TODO lots of missing stuff | ||
112 | }; | ||
113 | |||
114 | /** | ||
115 | * b43_phy_inita - Lowlevel A-PHY init routine. | ||
116 | * This is _only_ used by the G-PHY code. | ||
117 | */ | ||
118 | void b43_phy_inita(struct b43_wldev *dev); | ||
119 | |||
120 | |||
121 | struct b43_phy_operations; | ||
122 | extern const struct b43_phy_operations b43_phyops_a; | ||
123 | |||
124 | #endif /* LINUX_B43_PHY_A_H_ */ | ||
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c new file mode 100644 index 000000000000..5a550a7af2e9 --- /dev/null +++ b/drivers/net/wireless/b43/phy_common.c | |||
@@ -0,0 +1,367 @@ | |||
1 | /* | ||
2 | |||
3 | Broadcom B43 wireless driver | ||
4 | Common PHY routines | ||
5 | |||
6 | Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>, | ||
7 | Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it> | ||
8 | Copyright (c) 2005-2008 Michael Buesch <mb@bu3sch.de> | ||
9 | Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org> | ||
10 | Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch> | ||
11 | |||
12 | This program is free software; you can redistribute it and/or modify | ||
13 | it under the terms of the GNU General Public License as published by | ||
14 | the Free Software Foundation; either version 2 of the License, or | ||
15 | (at your option) any later version. | ||
16 | |||
17 | This program is distributed in the hope that it will be useful, | ||
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | GNU General Public License for more details. | ||
21 | |||
22 | You should have received a copy of the GNU General Public License | ||
23 | along with this program; see the file COPYING. If not, write to | ||
24 | the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, | ||
25 | Boston, MA 02110-1301, USA. | ||
26 | |||
27 | */ | ||
28 | |||
29 | #include "phy_common.h" | ||
30 | #include "phy_g.h" | ||
31 | #include "phy_a.h" | ||
32 | #include "nphy.h" | ||
33 | #include "b43.h" | ||
34 | #include "main.h" | ||
35 | |||
36 | |||
37 | int b43_phy_operations_setup(struct b43_wldev *dev) | ||
38 | { | ||
39 | struct b43_phy *phy = &(dev->phy); | ||
40 | int err; | ||
41 | |||
42 | phy->ops = NULL; | ||
43 | |||
44 | switch (phy->type) { | ||
45 | case B43_PHYTYPE_A: | ||
46 | phy->ops = &b43_phyops_a; | ||
47 | break; | ||
48 | case B43_PHYTYPE_G: | ||
49 | phy->ops = &b43_phyops_g; | ||
50 | break; | ||
51 | case B43_PHYTYPE_N: | ||
52 | #ifdef CONFIG_B43_NPHY | ||
53 | phy->ops = &b43_phyops_n; | ||
54 | #endif | ||
55 | break; | ||
56 | case B43_PHYTYPE_LP: | ||
57 | /* FIXME: Not yet */ | ||
58 | break; | ||
59 | } | ||
60 | if (B43_WARN_ON(!phy->ops)) | ||
61 | return -ENODEV; | ||
62 | |||
63 | err = phy->ops->allocate(dev); | ||
64 | if (err) | ||
65 | phy->ops = NULL; | ||
66 | |||
67 | return err; | ||
68 | } | ||
69 | |||
70 | int b43_phy_init(struct b43_wldev *dev) | ||
71 | { | ||
72 | struct b43_phy *phy = &dev->phy; | ||
73 | const struct b43_phy_operations *ops = phy->ops; | ||
74 | int err; | ||
75 | |||
76 | phy->channel = ops->get_default_chan(dev); | ||
77 | |||
78 | ops->software_rfkill(dev, RFKILL_STATE_UNBLOCKED); | ||
79 | err = ops->init(dev); | ||
80 | if (err) { | ||
81 | b43err(dev->wl, "PHY init failed\n"); | ||
82 | goto err_block_rf; | ||
83 | } | ||
84 | /* Make sure to switch hardware and firmware (SHM) to | ||
85 | * the default channel. */ | ||
86 | err = b43_switch_channel(dev, ops->get_default_chan(dev)); | ||
87 | if (err) { | ||
88 | b43err(dev->wl, "PHY init: Channel switch to default failed\n"); | ||
89 | goto err_phy_exit; | ||
90 | } | ||
91 | |||
92 | return 0; | ||
93 | |||
94 | err_phy_exit: | ||
95 | if (ops->exit) | ||
96 | ops->exit(dev); | ||
97 | err_block_rf: | ||
98 | ops->software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED); | ||
99 | |||
100 | return err; | ||
101 | } | ||
102 | |||
103 | void b43_phy_exit(struct b43_wldev *dev) | ||
104 | { | ||
105 | const struct b43_phy_operations *ops = dev->phy.ops; | ||
106 | |||
107 | ops->software_rfkill(dev, RFKILL_STATE_SOFT_BLOCKED); | ||
108 | if (ops->exit) | ||
109 | ops->exit(dev); | ||
110 | } | ||
111 | |||
112 | bool b43_has_hardware_pctl(struct b43_wldev *dev) | ||
113 | { | ||
114 | if (!dev->phy.hardware_power_control) | ||
115 | return 0; | ||
116 | if (!dev->phy.ops->supports_hwpctl) | ||
117 | return 0; | ||
118 | return dev->phy.ops->supports_hwpctl(dev); | ||
119 | } | ||
120 | |||
121 | void b43_radio_lock(struct b43_wldev *dev) | ||
122 | { | ||
123 | u32 macctl; | ||
124 | |||
125 | macctl = b43_read32(dev, B43_MMIO_MACCTL); | ||
126 | B43_WARN_ON(macctl & B43_MACCTL_RADIOLOCK); | ||
127 | macctl |= B43_MACCTL_RADIOLOCK; | ||
128 | b43_write32(dev, B43_MMIO_MACCTL, macctl); | ||
129 | /* Commit the write and wait for the device | ||
130 | * to exit any radio register access. */ | ||
131 | b43_read32(dev, B43_MMIO_MACCTL); | ||
132 | udelay(10); | ||
133 | } | ||
134 | |||
135 | void b43_radio_unlock(struct b43_wldev *dev) | ||
136 | { | ||
137 | u32 macctl; | ||
138 | |||
139 | /* Commit any write */ | ||
140 | b43_read16(dev, B43_MMIO_PHY_VER); | ||
141 | /* unlock */ | ||
142 | macctl = b43_read32(dev, B43_MMIO_MACCTL); | ||
143 | B43_WARN_ON(!(macctl & B43_MACCTL_RADIOLOCK)); | ||
144 | macctl &= ~B43_MACCTL_RADIOLOCK; | ||
145 | b43_write32(dev, B43_MMIO_MACCTL, macctl); | ||
146 | } | ||
147 | |||
148 | void b43_phy_lock(struct b43_wldev *dev) | ||
149 | { | ||
150 | #if B43_DEBUG | ||
151 | B43_WARN_ON(dev->phy.phy_locked); | ||
152 | dev->phy.phy_locked = 1; | ||
153 | #endif | ||
154 | B43_WARN_ON(dev->dev->id.revision < 3); | ||
155 | |||
156 | if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP)) | ||
157 | b43_power_saving_ctl_bits(dev, B43_PS_AWAKE); | ||
158 | } | ||
159 | |||
160 | void b43_phy_unlock(struct b43_wldev *dev) | ||
161 | { | ||
162 | #if B43_DEBUG | ||
163 | B43_WARN_ON(!dev->phy.phy_locked); | ||
164 | dev->phy.phy_locked = 0; | ||
165 | #endif | ||
166 | B43_WARN_ON(dev->dev->id.revision < 3); | ||
167 | |||
168 | if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP)) | ||
169 | b43_power_saving_ctl_bits(dev, 0); | ||
170 | } | ||
171 | |||
172 | u16 b43_radio_read(struct b43_wldev *dev, u16 reg) | ||
173 | { | ||
174 | return dev->phy.ops->radio_read(dev, reg); | ||
175 | } | ||
176 | |||
177 | void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value) | ||
178 | { | ||
179 | dev->phy.ops->radio_write(dev, reg, value); | ||
180 | } | ||
181 | |||
182 | void b43_radio_mask(struct b43_wldev *dev, u16 offset, u16 mask) | ||
183 | { | ||
184 | b43_radio_write16(dev, offset, | ||
185 | b43_radio_read16(dev, offset) & mask); | ||
186 | } | ||
187 | |||
188 | void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set) | ||
189 | { | ||
190 | b43_radio_write16(dev, offset, | ||
191 | b43_radio_read16(dev, offset) | set); | ||
192 | } | ||
193 | |||
194 | void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set) | ||
195 | { | ||
196 | b43_radio_write16(dev, offset, | ||
197 | (b43_radio_read16(dev, offset) & mask) | set); | ||
198 | } | ||
199 | |||
200 | u16 b43_phy_read(struct b43_wldev *dev, u16 reg) | ||
201 | { | ||
202 | return dev->phy.ops->phy_read(dev, reg); | ||
203 | } | ||
204 | |||
205 | void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value) | ||
206 | { | ||
207 | dev->phy.ops->phy_write(dev, reg, value); | ||
208 | } | ||
209 | |||
210 | void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask) | ||
211 | { | ||
212 | b43_phy_write(dev, offset, | ||
213 | b43_phy_read(dev, offset) & mask); | ||
214 | } | ||
215 | |||
216 | void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set) | ||
217 | { | ||
218 | b43_phy_write(dev, offset, | ||
219 | b43_phy_read(dev, offset) | set); | ||
220 | } | ||
221 | |||
222 | void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set) | ||
223 | { | ||
224 | b43_phy_write(dev, offset, | ||
225 | (b43_phy_read(dev, offset) & mask) | set); | ||
226 | } | ||
227 | |||
228 | int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel) | ||
229 | { | ||
230 | struct b43_phy *phy = &(dev->phy); | ||
231 | u16 channelcookie, savedcookie; | ||
232 | int err; | ||
233 | |||
234 | if (new_channel == B43_DEFAULT_CHANNEL) | ||
235 | new_channel = phy->ops->get_default_chan(dev); | ||
236 | |||
237 | /* First we set the channel radio code to prevent the | ||
238 | * firmware from sending ghost packets. | ||
239 | */ | ||
240 | channelcookie = new_channel; | ||
241 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) | ||
242 | channelcookie |= 0x100; | ||
243 | //FIXME set 40Mhz flag if required | ||
244 | savedcookie = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN); | ||
245 | b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN, channelcookie); | ||
246 | |||
247 | /* Now try to switch the PHY hardware channel. */ | ||
248 | err = phy->ops->switch_channel(dev, new_channel); | ||
249 | if (err) | ||
250 | goto err_restore_cookie; | ||
251 | |||
252 | dev->phy.channel = new_channel; | ||
253 | /* Wait for the radio to tune to the channel and stabilize. */ | ||
254 | msleep(8); | ||
255 | |||
256 | return 0; | ||
257 | |||
258 | err_restore_cookie: | ||
259 | b43_shm_write16(dev, B43_SHM_SHARED, | ||
260 | B43_SHM_SH_CHAN, savedcookie); | ||
261 | |||
262 | return err; | ||
263 | } | ||
264 | |||
265 | void b43_software_rfkill(struct b43_wldev *dev, enum rfkill_state state) | ||
266 | { | ||
267 | struct b43_phy *phy = &dev->phy; | ||
268 | |||
269 | if (state == RFKILL_STATE_HARD_BLOCKED) { | ||
270 | /* We cannot hardware-block the device */ | ||
271 | state = RFKILL_STATE_SOFT_BLOCKED; | ||
272 | } | ||
273 | |||
274 | phy->ops->software_rfkill(dev, state); | ||
275 | phy->radio_on = (state == RFKILL_STATE_UNBLOCKED); | ||
276 | } | ||
277 | |||
278 | /** | ||
279 | * b43_phy_txpower_adjust_work - TX power workqueue. | ||
280 | * | ||
281 | * Workqueue for updating the TX power parameters in hardware. | ||
282 | */ | ||
283 | void b43_phy_txpower_adjust_work(struct work_struct *work) | ||
284 | { | ||
285 | struct b43_wl *wl = container_of(work, struct b43_wl, | ||
286 | txpower_adjust_work); | ||
287 | struct b43_wldev *dev; | ||
288 | |||
289 | mutex_lock(&wl->mutex); | ||
290 | dev = wl->current_dev; | ||
291 | |||
292 | if (likely(dev && (b43_status(dev) >= B43_STAT_STARTED))) | ||
293 | dev->phy.ops->adjust_txpower(dev); | ||
294 | |||
295 | mutex_unlock(&wl->mutex); | ||
296 | } | ||
297 | |||
298 | /* Called with wl->irq_lock locked */ | ||
299 | void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags) | ||
300 | { | ||
301 | struct b43_phy *phy = &dev->phy; | ||
302 | unsigned long now = jiffies; | ||
303 | enum b43_txpwr_result result; | ||
304 | |||
305 | if (!(flags & B43_TXPWR_IGNORE_TIME)) { | ||
306 | /* Check if it's time for a TXpower check. */ | ||
307 | if (time_before(now, phy->next_txpwr_check_time)) | ||
308 | return; /* Not yet */ | ||
309 | } | ||
310 | /* The next check will be needed in two seconds, or later. */ | ||
311 | phy->next_txpwr_check_time = round_jiffies(now + (HZ * 2)); | ||
312 | |||
313 | if ((dev->dev->bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) && | ||
314 | (dev->dev->bus->boardinfo.type == SSB_BOARD_BU4306)) | ||
315 | return; /* No software txpower adjustment needed */ | ||
316 | |||
317 | result = phy->ops->recalc_txpower(dev, !!(flags & B43_TXPWR_IGNORE_TSSI)); | ||
318 | if (result == B43_TXPWR_RES_DONE) | ||
319 | return; /* We are done. */ | ||
320 | B43_WARN_ON(result != B43_TXPWR_RES_NEED_ADJUST); | ||
321 | B43_WARN_ON(phy->ops->adjust_txpower == NULL); | ||
322 | |||
323 | /* We must adjust the transmission power in hardware. | ||
324 | * Schedule b43_phy_txpower_adjust_work(). */ | ||
325 | queue_work(dev->wl->hw->workqueue, &dev->wl->txpower_adjust_work); | ||
326 | } | ||
327 | |||
328 | int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset) | ||
329 | { | ||
330 | const bool is_ofdm = (shm_offset != B43_SHM_SH_TSSI_CCK); | ||
331 | unsigned int a, b, c, d; | ||
332 | unsigned int average; | ||
333 | u32 tmp; | ||
334 | |||
335 | tmp = b43_shm_read32(dev, B43_SHM_SHARED, shm_offset); | ||
336 | a = tmp & 0xFF; | ||
337 | b = (tmp >> 8) & 0xFF; | ||
338 | c = (tmp >> 16) & 0xFF; | ||
339 | d = (tmp >> 24) & 0xFF; | ||
340 | if (a == 0 || a == B43_TSSI_MAX || | ||
341 | b == 0 || b == B43_TSSI_MAX || | ||
342 | c == 0 || c == B43_TSSI_MAX || | ||
343 | d == 0 || d == B43_TSSI_MAX) | ||
344 | return -ENOENT; | ||
345 | /* The values are OK. Clear them. */ | ||
346 | tmp = B43_TSSI_MAX | (B43_TSSI_MAX << 8) | | ||
347 | (B43_TSSI_MAX << 16) | (B43_TSSI_MAX << 24); | ||
348 | b43_shm_write32(dev, B43_SHM_SHARED, shm_offset, tmp); | ||
349 | |||
350 | if (is_ofdm) { | ||
351 | a = (a + 32) & 0x3F; | ||
352 | b = (b + 32) & 0x3F; | ||
353 | c = (c + 32) & 0x3F; | ||
354 | d = (d + 32) & 0x3F; | ||
355 | } | ||
356 | |||
357 | /* Get the average of the values with 0.5 added to each value. */ | ||
358 | average = (a + b + c + d + 2) / 4; | ||
359 | if (is_ofdm) { | ||
360 | /* Adjust for CCK-boost */ | ||
361 | if (b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO) | ||
362 | & B43_HF_CCKBOOST) | ||
363 | average = (average >= 13) ? (average - 13) : 0; | ||
364 | } | ||
365 | |||
366 | return average; | ||
367 | } | ||
diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h new file mode 100644 index 000000000000..f8db9f40df5d --- /dev/null +++ b/drivers/net/wireless/b43/phy_common.h | |||
@@ -0,0 +1,381 @@ | |||
1 | #ifndef LINUX_B43_PHY_COMMON_H_ | ||
2 | #define LINUX_B43_PHY_COMMON_H_ | ||
3 | |||
4 | #include <linux/rfkill.h> | ||
5 | |||
6 | struct b43_wldev; | ||
7 | |||
8 | |||
9 | /* PHY register routing bits */ | ||
10 | #define B43_PHYROUTE 0x0C00 /* PHY register routing bits mask */ | ||
11 | #define B43_PHYROUTE_BASE 0x0000 /* Base registers */ | ||
12 | #define B43_PHYROUTE_OFDM_GPHY 0x0400 /* OFDM register routing for G-PHYs */ | ||
13 | #define B43_PHYROUTE_EXT_GPHY 0x0800 /* Extended G-PHY registers */ | ||
14 | #define B43_PHYROUTE_N_BMODE 0x0C00 /* N-PHY BMODE registers */ | ||
15 | |||
16 | /* CCK (B-PHY) registers. */ | ||
17 | #define B43_PHY_CCK(reg) ((reg) | B43_PHYROUTE_BASE) | ||
18 | /* N-PHY registers. */ | ||
19 | #define B43_PHY_N(reg) ((reg) | B43_PHYROUTE_BASE) | ||
20 | /* N-PHY BMODE registers. */ | ||
21 | #define B43_PHY_N_BMODE(reg) ((reg) | B43_PHYROUTE_N_BMODE) | ||
22 | /* OFDM (A-PHY) registers. */ | ||
23 | #define B43_PHY_OFDM(reg) ((reg) | B43_PHYROUTE_OFDM_GPHY) | ||
24 | /* Extended G-PHY registers. */ | ||
25 | #define B43_PHY_EXTG(reg) ((reg) | B43_PHYROUTE_EXT_GPHY) | ||
26 | |||
27 | |||
28 | /* Masks for the PHY versioning registers. */ | ||
29 | #define B43_PHYVER_ANALOG 0xF000 | ||
30 | #define B43_PHYVER_ANALOG_SHIFT 12 | ||
31 | #define B43_PHYVER_TYPE 0x0F00 | ||
32 | #define B43_PHYVER_TYPE_SHIFT 8 | ||
33 | #define B43_PHYVER_VERSION 0x00FF | ||
34 | |||
35 | /** | ||
36 | * enum b43_interference_mitigation - Interference Mitigation mode | ||
37 | * | ||
38 | * @B43_INTERFMODE_NONE: Disabled | ||
39 | * @B43_INTERFMODE_NONWLAN: Non-WLAN Interference Mitigation | ||
40 | * @B43_INTERFMODE_MANUALWLAN: WLAN Interference Mitigation | ||
41 | * @B43_INTERFMODE_AUTOWLAN: Automatic WLAN Interference Mitigation | ||
42 | */ | ||
43 | enum b43_interference_mitigation { | ||
44 | B43_INTERFMODE_NONE, | ||
45 | B43_INTERFMODE_NONWLAN, | ||
46 | B43_INTERFMODE_MANUALWLAN, | ||
47 | B43_INTERFMODE_AUTOWLAN, | ||
48 | }; | ||
49 | |||
50 | /* Antenna identifiers */ | ||
51 | enum { | ||
52 | B43_ANTENNA0, /* Antenna 0 */ | ||
53 | B43_ANTENNA1, /* Antenna 0 */ | ||
54 | B43_ANTENNA_AUTO1, /* Automatic, starting with antenna 1 */ | ||
55 | B43_ANTENNA_AUTO0, /* Automatic, starting with antenna 0 */ | ||
56 | B43_ANTENNA2, | ||
57 | B43_ANTENNA3 = 8, | ||
58 | |||
59 | B43_ANTENNA_AUTO = B43_ANTENNA_AUTO0, | ||
60 | B43_ANTENNA_DEFAULT = B43_ANTENNA_AUTO, | ||
61 | }; | ||
62 | |||
63 | /** | ||
64 | * enum b43_txpwr_result - Return value for the recalc_txpower PHY op. | ||
65 | * | ||
66 | * @B43_TXPWR_RES_NEED_ADJUST: Values changed. Hardware adjustment is needed. | ||
67 | * @B43_TXPWR_RES_DONE: No more work to do. Everything is done. | ||
68 | */ | ||
69 | enum b43_txpwr_result { | ||
70 | B43_TXPWR_RES_NEED_ADJUST, | ||
71 | B43_TXPWR_RES_DONE, | ||
72 | }; | ||
73 | |||
74 | /** | ||
75 | * struct b43_phy_operations - Function pointers for PHY ops. | ||
76 | * | ||
77 | * @prepare: Prepare the PHY. This is called before @init. | ||
78 | * Can be NULL, if not required. | ||
79 | * @init: Initialize the PHY. | ||
80 | * Must not be NULL. | ||
81 | * @exit: Shutdown the PHY and free all data structures. | ||
82 | * Can be NULL, if not required. | ||
83 | * | ||
84 | * @phy_read: Read from a PHY register. | ||
85 | * Must not be NULL. | ||
86 | * @phy_write: Write to a PHY register. | ||
87 | * Must not be NULL. | ||
88 | * @radio_read: Read from a Radio register. | ||
89 | * Must not be NULL. | ||
90 | * @radio_write: Write to a Radio register. | ||
91 | * Must not be NULL. | ||
92 | * | ||
93 | * @supports_hwpctl: Returns a boolean whether Hardware Power Control | ||
94 | * is supported or not. | ||
95 | * If NULL, hwpctl is assumed to be never supported. | ||
96 | * @software_rfkill: Turn the radio ON or OFF. | ||
97 | * Possible state values are | ||
98 | * RFKILL_STATE_SOFT_BLOCKED or | ||
99 | * RFKILL_STATE_UNBLOCKED | ||
100 | * Must not be NULL. | ||
101 | * @switch_channel: Switch the radio to another channel. | ||
102 | * Must not be NULL. | ||
103 | * @get_default_chan: Just returns the default channel number. | ||
104 | * Must not be NULL. | ||
105 | * @set_rx_antenna: Set the antenna used for RX. | ||
106 | * Can be NULL, if not supported. | ||
107 | * @interf_mitigation: Switch the Interference Mitigation mode. | ||
108 | * Can be NULL, if not supported. | ||
109 | * | ||
110 | * @recalc_txpower: Recalculate the transmission power parameters. | ||
111 | * This callback has to recalculate the TX power settings, | ||
112 | * but does not need to write them to the hardware, yet. | ||
113 | * Returns enum b43_txpwr_result to indicate whether the hardware | ||
114 | * needs to be adjusted. | ||
115 | * If B43_TXPWR_NEED_ADJUST is returned, @adjust_txpower | ||
116 | * will be called later. | ||
117 | * If the parameter "ignore_tssi" is true, the TSSI values should | ||
118 | * be ignored and a recalculation of the power settings should be | ||
119 | * done even if the TSSI values did not change. | ||
120 | * This callback is called with wl->irq_lock held and must not sleep. | ||
121 | * Must not be NULL. | ||
122 | * @adjust_txpower: Write the previously calculated TX power settings | ||
123 | * (from @recalc_txpower) to the hardware. | ||
124 | * This function may sleep. | ||
125 | * Can be NULL, if (and ONLY if) @recalc_txpower _always_ | ||
126 | * returns B43_TXPWR_RES_DONE. | ||
127 | * | ||
128 | * @pwork_15sec: Periodic work. Called every 15 seconds. | ||
129 | * Can be NULL, if not required. | ||
130 | * @pwork_60sec: Periodic work. Called every 60 seconds. | ||
131 | * Can be NULL, if not required. | ||
132 | */ | ||
133 | struct b43_phy_operations { | ||
134 | /* Initialisation */ | ||
135 | int (*allocate)(struct b43_wldev *dev); | ||
136 | int (*prepare)(struct b43_wldev *dev); | ||
137 | int (*init)(struct b43_wldev *dev); | ||
138 | void (*exit)(struct b43_wldev *dev); | ||
139 | |||
140 | /* Register access */ | ||
141 | u16 (*phy_read)(struct b43_wldev *dev, u16 reg); | ||
142 | void (*phy_write)(struct b43_wldev *dev, u16 reg, u16 value); | ||
143 | u16 (*radio_read)(struct b43_wldev *dev, u16 reg); | ||
144 | void (*radio_write)(struct b43_wldev *dev, u16 reg, u16 value); | ||
145 | |||
146 | /* Radio */ | ||
147 | bool (*supports_hwpctl)(struct b43_wldev *dev); | ||
148 | void (*software_rfkill)(struct b43_wldev *dev, enum rfkill_state state); | ||
149 | int (*switch_channel)(struct b43_wldev *dev, unsigned int new_channel); | ||
150 | unsigned int (*get_default_chan)(struct b43_wldev *dev); | ||
151 | void (*set_rx_antenna)(struct b43_wldev *dev, int antenna); | ||
152 | int (*interf_mitigation)(struct b43_wldev *dev, | ||
153 | enum b43_interference_mitigation new_mode); | ||
154 | |||
155 | /* Transmission power adjustment */ | ||
156 | enum b43_txpwr_result (*recalc_txpower)(struct b43_wldev *dev, | ||
157 | bool ignore_tssi); | ||
158 | void (*adjust_txpower)(struct b43_wldev *dev); | ||
159 | |||
160 | /* Misc */ | ||
161 | void (*pwork_15sec)(struct b43_wldev *dev); | ||
162 | void (*pwork_60sec)(struct b43_wldev *dev); | ||
163 | }; | ||
164 | |||
165 | struct b43_phy_a; | ||
166 | struct b43_phy_g; | ||
167 | struct b43_phy_n; | ||
168 | |||
169 | struct b43_phy { | ||
170 | /* Hardware operation callbacks. */ | ||
171 | const struct b43_phy_operations *ops; | ||
172 | |||
173 | /* Most hardware context information is stored in the standard- | ||
174 | * specific data structures pointed to by the pointers below. | ||
175 | * Only one of them is valid (the currently enabled PHY). */ | ||
176 | #ifdef CONFIG_B43_DEBUG | ||
177 | /* No union for debug build to force NULL derefs in buggy code. */ | ||
178 | struct { | ||
179 | #else | ||
180 | union { | ||
181 | #endif | ||
182 | /* A-PHY specific information */ | ||
183 | struct b43_phy_a *a; | ||
184 | /* G-PHY specific information */ | ||
185 | struct b43_phy_g *g; | ||
186 | /* N-PHY specific information */ | ||
187 | struct b43_phy_n *n; | ||
188 | }; | ||
189 | |||
190 | /* Band support flags. */ | ||
191 | bool supports_2ghz; | ||
192 | bool supports_5ghz; | ||
193 | |||
194 | /* GMODE bit enabled? */ | ||
195 | bool gmode; | ||
196 | |||
197 | /* Analog Type */ | ||
198 | u8 analog; | ||
199 | /* B43_PHYTYPE_ */ | ||
200 | u8 type; | ||
201 | /* PHY revision number. */ | ||
202 | u8 rev; | ||
203 | |||
204 | /* Radio versioning */ | ||
205 | u16 radio_manuf; /* Radio manufacturer */ | ||
206 | u16 radio_ver; /* Radio version */ | ||
207 | u8 radio_rev; /* Radio revision */ | ||
208 | |||
209 | /* Software state of the radio */ | ||
210 | bool radio_on; | ||
211 | |||
212 | /* Desired TX power level (in dBm). | ||
213 | * This is set by the user and adjusted in b43_phy_xmitpower(). */ | ||
214 | int desired_txpower; | ||
215 | |||
216 | /* Hardware Power Control enabled? */ | ||
217 | bool hardware_power_control; | ||
218 | |||
219 | /* The time (in absolute jiffies) when the next TX power output | ||
220 | * check is needed. */ | ||
221 | unsigned long next_txpwr_check_time; | ||
222 | |||
223 | /* current channel */ | ||
224 | unsigned int channel; | ||
225 | |||
226 | /* PHY TX errors counter. */ | ||
227 | atomic_t txerr_cnt; | ||
228 | |||
229 | #ifdef CONFIG_B43_DEBUG | ||
230 | /* PHY registers locked by b43_phy_lock()? */ | ||
231 | bool phy_locked; | ||
232 | #endif /* B43_DEBUG */ | ||
233 | }; | ||
234 | |||
235 | |||
236 | /** | ||
237 | * b43_phy_operations_setup - Initialize the PHY operations datastructure | ||
238 | * based on the current PHY type. | ||
239 | */ | ||
240 | int b43_phy_operations_setup(struct b43_wldev *dev); | ||
241 | |||
242 | /** | ||
243 | * b43_phy_init - Initialise the PHY | ||
244 | */ | ||
245 | int b43_phy_init(struct b43_wldev *dev); | ||
246 | |||
247 | /** | ||
248 | * b43_phy_exit - Cleanup PHY | ||
249 | */ | ||
250 | void b43_phy_exit(struct b43_wldev *dev); | ||
251 | |||
252 | /** | ||
253 | * b43_has_hardware_pctl - Hardware Power Control supported? | ||
254 | * Returns a boolean, whether hardware power control is supported. | ||
255 | */ | ||
256 | bool b43_has_hardware_pctl(struct b43_wldev *dev); | ||
257 | |||
258 | /** | ||
259 | * b43_phy_read - 16bit PHY register read access | ||
260 | */ | ||
261 | u16 b43_phy_read(struct b43_wldev *dev, u16 reg); | ||
262 | |||
263 | /** | ||
264 | * b43_phy_write - 16bit PHY register write access | ||
265 | */ | ||
266 | void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value); | ||
267 | |||
268 | /** | ||
269 | * b43_phy_mask - Mask a PHY register with a mask | ||
270 | */ | ||
271 | void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask); | ||
272 | |||
273 | /** | ||
274 | * b43_phy_set - OR a PHY register with a bitmap | ||
275 | */ | ||
276 | void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set); | ||
277 | |||
278 | /** | ||
279 | * b43_phy_maskset - Mask and OR a PHY register with a mask and bitmap | ||
280 | */ | ||
281 | void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set); | ||
282 | |||
283 | /** | ||
284 | * b43_radio_read - 16bit Radio register read access | ||
285 | */ | ||
286 | u16 b43_radio_read(struct b43_wldev *dev, u16 reg); | ||
287 | #define b43_radio_read16 b43_radio_read /* DEPRECATED */ | ||
288 | |||
289 | /** | ||
290 | * b43_radio_write - 16bit Radio register write access | ||
291 | */ | ||
292 | void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value); | ||
293 | #define b43_radio_write16 b43_radio_write /* DEPRECATED */ | ||
294 | |||
295 | /** | ||
296 | * b43_radio_mask - Mask a 16bit radio register with a mask | ||
297 | */ | ||
298 | void b43_radio_mask(struct b43_wldev *dev, u16 offset, u16 mask); | ||
299 | |||
300 | /** | ||
301 | * b43_radio_set - OR a 16bit radio register with a bitmap | ||
302 | */ | ||
303 | void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set); | ||
304 | |||
305 | /** | ||
306 | * b43_radio_maskset - Mask and OR a radio register with a mask and bitmap | ||
307 | */ | ||
308 | void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set); | ||
309 | |||
310 | /** | ||
311 | * b43_radio_lock - Lock firmware radio register access | ||
312 | */ | ||
313 | void b43_radio_lock(struct b43_wldev *dev); | ||
314 | |||
315 | /** | ||
316 | * b43_radio_unlock - Unlock firmware radio register access | ||
317 | */ | ||
318 | void b43_radio_unlock(struct b43_wldev *dev); | ||
319 | |||
320 | /** | ||
321 | * b43_phy_lock - Lock firmware PHY register access | ||
322 | */ | ||
323 | void b43_phy_lock(struct b43_wldev *dev); | ||
324 | |||
325 | /** | ||
326 | * b43_phy_unlock - Unlock firmware PHY register access | ||
327 | */ | ||
328 | void b43_phy_unlock(struct b43_wldev *dev); | ||
329 | |||
330 | /** | ||
331 | * b43_switch_channel - Switch to another channel | ||
332 | */ | ||
333 | int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel); | ||
334 | /** | ||
335 | * B43_DEFAULT_CHANNEL - Switch to the default channel. | ||
336 | */ | ||
337 | #define B43_DEFAULT_CHANNEL UINT_MAX | ||
338 | |||
339 | /** | ||
340 | * b43_software_rfkill - Turn the radio ON or OFF in software. | ||
341 | */ | ||
342 | void b43_software_rfkill(struct b43_wldev *dev, enum rfkill_state state); | ||
343 | |||
344 | /** | ||
345 | * b43_phy_txpower_check - Check TX power output. | ||
346 | * | ||
347 | * Compare the current TX power output to the desired power emission | ||
348 | * and schedule an adjustment in case it mismatches. | ||
349 | * Requires wl->irq_lock locked. | ||
350 | * | ||
351 | * @flags: OR'ed enum b43_phy_txpower_check_flags flags. | ||
352 | * See the docs below. | ||
353 | */ | ||
354 | void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags); | ||
355 | /** | ||
356 | * enum b43_phy_txpower_check_flags - Flags for b43_phy_txpower_check() | ||
357 | * | ||
358 | * @B43_TXPWR_IGNORE_TIME: Ignore the schedule time and force-redo | ||
359 | * the check now. | ||
360 | * @B43_TXPWR_IGNORE_TSSI: Redo the recalculation, even if the average | ||
361 | * TSSI did not change. | ||
362 | */ | ||
363 | enum b43_phy_txpower_check_flags { | ||
364 | B43_TXPWR_IGNORE_TIME = (1 << 0), | ||
365 | B43_TXPWR_IGNORE_TSSI = (1 << 1), | ||
366 | }; | ||
367 | |||
368 | struct work_struct; | ||
369 | void b43_phy_txpower_adjust_work(struct work_struct *work); | ||
370 | |||
371 | /** | ||
372 | * b43_phy_shm_tssi_read - Read the average of the last 4 TSSI from SHM. | ||
373 | * | ||
374 | * @shm_offset: The SHM address to read the values from. | ||
375 | * | ||
376 | * Returns the average of the 4 TSSI values, or a negative error code. | ||
377 | */ | ||
378 | int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset); | ||
379 | |||
380 | |||
381 | #endif /* LINUX_B43_PHY_COMMON_H_ */ | ||
diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c new file mode 100644 index 000000000000..fce84896d34c --- /dev/null +++ b/drivers/net/wireless/b43/phy_g.c | |||
@@ -0,0 +1,3251 @@ | |||
1 | /* | ||
2 | |||
3 | Broadcom B43 wireless driver | ||
4 | IEEE 802.11g PHY driver | ||
5 | |||
6 | Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>, | ||
7 | Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it> | ||
8 | Copyright (c) 2005-2008 Michael Buesch <mb@bu3sch.de> | ||
9 | Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org> | ||
10 | Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch> | ||
11 | |||
12 | This program is free software; you can redistribute it and/or modify | ||
13 | it under the terms of the GNU General Public License as published by | ||
14 | the Free Software Foundation; either version 2 of the License, or | ||
15 | (at your option) any later version. | ||
16 | |||
17 | This program is distributed in the hope that it will be useful, | ||
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | GNU General Public License for more details. | ||
21 | |||
22 | You should have received a copy of the GNU General Public License | ||
23 | along with this program; see the file COPYING. If not, write to | ||
24 | the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, | ||
25 | Boston, MA 02110-1301, USA. | ||
26 | |||
27 | */ | ||
28 | |||
29 | #include "b43.h" | ||
30 | #include "phy_g.h" | ||
31 | #include "phy_common.h" | ||
32 | #include "lo.h" | ||
33 | #include "main.h" | ||
34 | |||
35 | #include <linux/bitrev.h> | ||
36 | |||
37 | |||
38 | static const s8 b43_tssi2dbm_g_table[] = { | ||
39 | 77, 77, 77, 76, | ||
40 | 76, 76, 75, 75, | ||
41 | 74, 74, 73, 73, | ||
42 | 73, 72, 72, 71, | ||
43 | 71, 70, 70, 69, | ||
44 | 68, 68, 67, 67, | ||
45 | 66, 65, 65, 64, | ||
46 | 63, 63, 62, 61, | ||
47 | 60, 59, 58, 57, | ||
48 | 56, 55, 54, 53, | ||
49 | 52, 50, 49, 47, | ||
50 | 45, 43, 40, 37, | ||
51 | 33, 28, 22, 14, | ||
52 | 5, -7, -20, -20, | ||
53 | -20, -20, -20, -20, | ||
54 | -20, -20, -20, -20, | ||
55 | }; | ||
56 | |||
57 | const u8 b43_radio_channel_codes_bg[] = { | ||
58 | 12, 17, 22, 27, | ||
59 | 32, 37, 42, 47, | ||
60 | 52, 57, 62, 67, | ||
61 | 72, 84, | ||
62 | }; | ||
63 | |||
64 | |||
65 | static void b43_calc_nrssi_threshold(struct b43_wldev *dev); | ||
66 | |||
67 | |||
68 | #define bitrev4(tmp) (bitrev8(tmp) >> 4) | ||
69 | |||
70 | |||
71 | /* Get the freq, as it has to be written to the device. */ | ||
72 | static inline u16 channel2freq_bg(u8 channel) | ||
73 | { | ||
74 | B43_WARN_ON(!(channel >= 1 && channel <= 14)); | ||
75 | |||
76 | return b43_radio_channel_codes_bg[channel - 1]; | ||
77 | } | ||
78 | |||
79 | static void generate_rfatt_list(struct b43_wldev *dev, | ||
80 | struct b43_rfatt_list *list) | ||
81 | { | ||
82 | struct b43_phy *phy = &dev->phy; | ||
83 | |||
84 | /* APHY.rev < 5 || GPHY.rev < 6 */ | ||
85 | static const struct b43_rfatt rfatt_0[] = { | ||
86 | {.att = 3,.with_padmix = 0,}, | ||
87 | {.att = 1,.with_padmix = 0,}, | ||
88 | {.att = 5,.with_padmix = 0,}, | ||
89 | {.att = 7,.with_padmix = 0,}, | ||
90 | {.att = 9,.with_padmix = 0,}, | ||
91 | {.att = 2,.with_padmix = 0,}, | ||
92 | {.att = 0,.with_padmix = 0,}, | ||
93 | {.att = 4,.with_padmix = 0,}, | ||
94 | {.att = 6,.with_padmix = 0,}, | ||
95 | {.att = 8,.with_padmix = 0,}, | ||
96 | {.att = 1,.with_padmix = 1,}, | ||
97 | {.att = 2,.with_padmix = 1,}, | ||
98 | {.att = 3,.with_padmix = 1,}, | ||
99 | {.att = 4,.with_padmix = 1,}, | ||
100 | }; | ||
101 | /* Radio.rev == 8 && Radio.version == 0x2050 */ | ||
102 | static const struct b43_rfatt rfatt_1[] = { | ||
103 | {.att = 2,.with_padmix = 1,}, | ||
104 | {.att = 4,.with_padmix = 1,}, | ||
105 | {.att = 6,.with_padmix = 1,}, | ||
106 | {.att = 8,.with_padmix = 1,}, | ||
107 | {.att = 10,.with_padmix = 1,}, | ||
108 | {.att = 12,.with_padmix = 1,}, | ||
109 | {.att = 14,.with_padmix = 1,}, | ||
110 | }; | ||
111 | /* Otherwise */ | ||
112 | static const struct b43_rfatt rfatt_2[] = { | ||
113 | {.att = 0,.with_padmix = 1,}, | ||
114 | {.att = 2,.with_padmix = 1,}, | ||
115 | {.att = 4,.with_padmix = 1,}, | ||
116 | {.att = 6,.with_padmix = 1,}, | ||
117 | {.att = 8,.with_padmix = 1,}, | ||
118 | {.att = 9,.with_padmix = 1,}, | ||
119 | {.att = 9,.with_padmix = 1,}, | ||
120 | }; | ||
121 | |||
122 | if (!b43_has_hardware_pctl(dev)) { | ||
123 | /* Software pctl */ | ||
124 | list->list = rfatt_0; | ||
125 | list->len = ARRAY_SIZE(rfatt_0); | ||
126 | list->min_val = 0; | ||
127 | list->max_val = 9; | ||
128 | return; | ||
129 | } | ||
130 | if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) { | ||
131 | /* Hardware pctl */ | ||
132 | list->list = rfatt_1; | ||
133 | list->len = ARRAY_SIZE(rfatt_1); | ||
134 | list->min_val = 0; | ||
135 | list->max_val = 14; | ||
136 | return; | ||
137 | } | ||
138 | /* Hardware pctl */ | ||
139 | list->list = rfatt_2; | ||
140 | list->len = ARRAY_SIZE(rfatt_2); | ||
141 | list->min_val = 0; | ||
142 | list->max_val = 9; | ||
143 | } | ||
144 | |||
145 | static void generate_bbatt_list(struct b43_wldev *dev, | ||
146 | struct b43_bbatt_list *list) | ||
147 | { | ||
148 | static const struct b43_bbatt bbatt_0[] = { | ||
149 | {.att = 0,}, | ||
150 | {.att = 1,}, | ||
151 | {.att = 2,}, | ||
152 | {.att = 3,}, | ||
153 | {.att = 4,}, | ||
154 | {.att = 5,}, | ||
155 | {.att = 6,}, | ||
156 | {.att = 7,}, | ||
157 | {.att = 8,}, | ||
158 | }; | ||
159 | |||
160 | list->list = bbatt_0; | ||
161 | list->len = ARRAY_SIZE(bbatt_0); | ||
162 | list->min_val = 0; | ||
163 | list->max_val = 8; | ||
164 | } | ||
165 | |||
166 | static void b43_shm_clear_tssi(struct b43_wldev *dev) | ||
167 | { | ||
168 | b43_shm_write16(dev, B43_SHM_SHARED, 0x0058, 0x7F7F); | ||
169 | b43_shm_write16(dev, B43_SHM_SHARED, 0x005a, 0x7F7F); | ||
170 | b43_shm_write16(dev, B43_SHM_SHARED, 0x0070, 0x7F7F); | ||
171 | b43_shm_write16(dev, B43_SHM_SHARED, 0x0072, 0x7F7F); | ||
172 | } | ||
173 | |||
174 | /* Synthetic PU workaround */ | ||
175 | static void b43_synth_pu_workaround(struct b43_wldev *dev, u8 channel) | ||
176 | { | ||
177 | struct b43_phy *phy = &dev->phy; | ||
178 | |||
179 | might_sleep(); | ||
180 | |||
181 | if (phy->radio_ver != 0x2050 || phy->radio_rev >= 6) { | ||
182 | /* We do not need the workaround. */ | ||
183 | return; | ||
184 | } | ||
185 | |||
186 | if (channel <= 10) { | ||
187 | b43_write16(dev, B43_MMIO_CHANNEL, | ||
188 | channel2freq_bg(channel + 4)); | ||
189 | } else { | ||
190 | b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(1)); | ||
191 | } | ||
192 | msleep(1); | ||
193 | b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel)); | ||
194 | } | ||
195 | |||
196 | /* Set the baseband attenuation value on chip. */ | ||
197 | void b43_gphy_set_baseband_attenuation(struct b43_wldev *dev, | ||
198 | u16 baseband_attenuation) | ||
199 | { | ||
200 | struct b43_phy *phy = &dev->phy; | ||
201 | |||
202 | if (phy->analog == 0) { | ||
203 | b43_write16(dev, B43_MMIO_PHY0, (b43_read16(dev, B43_MMIO_PHY0) | ||
204 | & 0xFFF0) | | ||
205 | baseband_attenuation); | ||
206 | } else if (phy->analog > 1) { | ||
207 | b43_phy_write(dev, B43_PHY_DACCTL, | ||
208 | (b43_phy_read(dev, B43_PHY_DACCTL) | ||
209 | & 0xFFC3) | (baseband_attenuation << 2)); | ||
210 | } else { | ||
211 | b43_phy_write(dev, B43_PHY_DACCTL, | ||
212 | (b43_phy_read(dev, B43_PHY_DACCTL) | ||
213 | & 0xFF87) | (baseband_attenuation << 3)); | ||
214 | } | ||
215 | } | ||
216 | |||
217 | /* Adjust the transmission power output (G-PHY) */ | ||
218 | void b43_set_txpower_g(struct b43_wldev *dev, | ||
219 | const struct b43_bbatt *bbatt, | ||
220 | const struct b43_rfatt *rfatt, u8 tx_control) | ||
221 | { | ||
222 | struct b43_phy *phy = &dev->phy; | ||
223 | struct b43_phy_g *gphy = phy->g; | ||
224 | struct b43_txpower_lo_control *lo = gphy->lo_control; | ||
225 | u16 bb, rf; | ||
226 | u16 tx_bias, tx_magn; | ||
227 | |||
228 | bb = bbatt->att; | ||
229 | rf = rfatt->att; | ||
230 | tx_bias = lo->tx_bias; | ||
231 | tx_magn = lo->tx_magn; | ||
232 | if (unlikely(tx_bias == 0xFF)) | ||
233 | tx_bias = 0; | ||
234 | |||
235 | /* Save the values for later */ | ||
236 | gphy->tx_control = tx_control; | ||
237 | memcpy(&gphy->rfatt, rfatt, sizeof(*rfatt)); | ||
238 | gphy->rfatt.with_padmix = !!(tx_control & B43_TXCTL_TXMIX); | ||
239 | memcpy(&gphy->bbatt, bbatt, sizeof(*bbatt)); | ||
240 | |||
241 | if (b43_debug(dev, B43_DBG_XMITPOWER)) { | ||
242 | b43dbg(dev->wl, "Tuning TX-power to bbatt(%u), " | ||
243 | "rfatt(%u), tx_control(0x%02X), " | ||
244 | "tx_bias(0x%02X), tx_magn(0x%02X)\n", | ||
245 | bb, rf, tx_control, tx_bias, tx_magn); | ||
246 | } | ||
247 | |||
248 | b43_gphy_set_baseband_attenuation(dev, bb); | ||
249 | b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_RFATT, rf); | ||
250 | if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) { | ||
251 | b43_radio_write16(dev, 0x43, | ||
252 | (rf & 0x000F) | (tx_control & 0x0070)); | ||
253 | } else { | ||
254 | b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43) | ||
255 | & 0xFFF0) | (rf & 0x000F)); | ||
256 | b43_radio_write16(dev, 0x52, (b43_radio_read16(dev, 0x52) | ||
257 | & ~0x0070) | (tx_control & | ||
258 | 0x0070)); | ||
259 | } | ||
260 | if (has_tx_magnification(phy)) { | ||
261 | b43_radio_write16(dev, 0x52, tx_magn | tx_bias); | ||
262 | } else { | ||
263 | b43_radio_write16(dev, 0x52, (b43_radio_read16(dev, 0x52) | ||
264 | & 0xFFF0) | (tx_bias & 0x000F)); | ||
265 | } | ||
266 | b43_lo_g_adjust(dev); | ||
267 | } | ||
268 | |||
269 | /* GPHY_TSSI_Power_Lookup_Table_Init */ | ||
270 | static void b43_gphy_tssi_power_lt_init(struct b43_wldev *dev) | ||
271 | { | ||
272 | struct b43_phy_g *gphy = dev->phy.g; | ||
273 | int i; | ||
274 | u16 value; | ||
275 | |||
276 | for (i = 0; i < 32; i++) | ||
277 | b43_ofdmtab_write16(dev, 0x3C20, i, gphy->tssi2dbm[i]); | ||
278 | for (i = 32; i < 64; i++) | ||
279 | b43_ofdmtab_write16(dev, 0x3C00, i - 32, gphy->tssi2dbm[i]); | ||
280 | for (i = 0; i < 64; i += 2) { | ||
281 | value = (u16) gphy->tssi2dbm[i]; | ||
282 | value |= ((u16) gphy->tssi2dbm[i + 1]) << 8; | ||
283 | b43_phy_write(dev, 0x380 + (i / 2), value); | ||
284 | } | ||
285 | } | ||
286 | |||
287 | /* GPHY_Gain_Lookup_Table_Init */ | ||
288 | static void b43_gphy_gain_lt_init(struct b43_wldev *dev) | ||
289 | { | ||
290 | struct b43_phy *phy = &dev->phy; | ||
291 | struct b43_phy_g *gphy = phy->g; | ||
292 | struct b43_txpower_lo_control *lo = gphy->lo_control; | ||
293 | u16 nr_written = 0; | ||
294 | u16 tmp; | ||
295 | u8 rf, bb; | ||
296 | |||
297 | for (rf = 0; rf < lo->rfatt_list.len; rf++) { | ||
298 | for (bb = 0; bb < lo->bbatt_list.len; bb++) { | ||
299 | if (nr_written >= 0x40) | ||
300 | return; | ||
301 | tmp = lo->bbatt_list.list[bb].att; | ||
302 | tmp <<= 8; | ||
303 | if (phy->radio_rev == 8) | ||
304 | tmp |= 0x50; | ||
305 | else | ||
306 | tmp |= 0x40; | ||
307 | tmp |= lo->rfatt_list.list[rf].att; | ||
308 | b43_phy_write(dev, 0x3C0 + nr_written, tmp); | ||
309 | nr_written++; | ||
310 | } | ||
311 | } | ||
312 | } | ||
313 | |||
314 | static void b43_set_all_gains(struct b43_wldev *dev, | ||
315 | s16 first, s16 second, s16 third) | ||
316 | { | ||
317 | struct b43_phy *phy = &dev->phy; | ||
318 | u16 i; | ||
319 | u16 start = 0x08, end = 0x18; | ||
320 | u16 tmp; | ||
321 | u16 table; | ||
322 | |||
323 | if (phy->rev <= 1) { | ||
324 | start = 0x10; | ||
325 | end = 0x20; | ||
326 | } | ||
327 | |||
328 | table = B43_OFDMTAB_GAINX; | ||
329 | if (phy->rev <= 1) | ||
330 | table = B43_OFDMTAB_GAINX_R1; | ||
331 | for (i = 0; i < 4; i++) | ||
332 | b43_ofdmtab_write16(dev, table, i, first); | ||
333 | |||
334 | for (i = start; i < end; i++) | ||
335 | b43_ofdmtab_write16(dev, table, i, second); | ||
336 | |||
337 | if (third != -1) { | ||
338 | tmp = ((u16) third << 14) | ((u16) third << 6); | ||
339 | b43_phy_write(dev, 0x04A0, | ||
340 | (b43_phy_read(dev, 0x04A0) & 0xBFBF) | tmp); | ||
341 | b43_phy_write(dev, 0x04A1, | ||
342 | (b43_phy_read(dev, 0x04A1) & 0xBFBF) | tmp); | ||
343 | b43_phy_write(dev, 0x04A2, | ||
344 | (b43_phy_read(dev, 0x04A2) & 0xBFBF) | tmp); | ||
345 | } | ||
346 | b43_dummy_transmission(dev); | ||
347 | } | ||
348 | |||
349 | static void b43_set_original_gains(struct b43_wldev *dev) | ||
350 | { | ||
351 | struct b43_phy *phy = &dev->phy; | ||
352 | u16 i, tmp; | ||
353 | u16 table; | ||
354 | u16 start = 0x0008, end = 0x0018; | ||
355 | |||
356 | if (phy->rev <= 1) { | ||
357 | start = 0x0010; | ||
358 | end = 0x0020; | ||
359 | } | ||
360 | |||
361 | table = B43_OFDMTAB_GAINX; | ||
362 | if (phy->rev <= 1) | ||
363 | table = B43_OFDMTAB_GAINX_R1; | ||
364 | for (i = 0; i < 4; i++) { | ||
365 | tmp = (i & 0xFFFC); | ||
366 | tmp |= (i & 0x0001) << 1; | ||
367 | tmp |= (i & 0x0002) >> 1; | ||
368 | |||
369 | b43_ofdmtab_write16(dev, table, i, tmp); | ||
370 | } | ||
371 | |||
372 | for (i = start; i < end; i++) | ||
373 | b43_ofdmtab_write16(dev, table, i, i - start); | ||
374 | |||
375 | b43_phy_write(dev, 0x04A0, | ||
376 | (b43_phy_read(dev, 0x04A0) & 0xBFBF) | 0x4040); | ||
377 | b43_phy_write(dev, 0x04A1, | ||
378 | (b43_phy_read(dev, 0x04A1) & 0xBFBF) | 0x4040); | ||
379 | b43_phy_write(dev, 0x04A2, | ||
380 | (b43_phy_read(dev, 0x04A2) & 0xBFBF) | 0x4000); | ||
381 | b43_dummy_transmission(dev); | ||
382 | } | ||
383 | |||
384 | /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ | ||
385 | void b43_nrssi_hw_write(struct b43_wldev *dev, u16 offset, s16 val) | ||
386 | { | ||
387 | b43_phy_write(dev, B43_PHY_NRSSILT_CTRL, offset); | ||
388 | mmiowb(); | ||
389 | b43_phy_write(dev, B43_PHY_NRSSILT_DATA, (u16) val); | ||
390 | } | ||
391 | |||
392 | /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ | ||
393 | s16 b43_nrssi_hw_read(struct b43_wldev *dev, u16 offset) | ||
394 | { | ||
395 | u16 val; | ||
396 | |||
397 | b43_phy_write(dev, B43_PHY_NRSSILT_CTRL, offset); | ||
398 | val = b43_phy_read(dev, B43_PHY_NRSSILT_DATA); | ||
399 | |||
400 | return (s16) val; | ||
401 | } | ||
402 | |||
403 | /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ | ||
404 | void b43_nrssi_hw_update(struct b43_wldev *dev, u16 val) | ||
405 | { | ||
406 | u16 i; | ||
407 | s16 tmp; | ||
408 | |||
409 | for (i = 0; i < 64; i++) { | ||
410 | tmp = b43_nrssi_hw_read(dev, i); | ||
411 | tmp -= val; | ||
412 | tmp = clamp_val(tmp, -32, 31); | ||
413 | b43_nrssi_hw_write(dev, i, tmp); | ||
414 | } | ||
415 | } | ||
416 | |||
417 | /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ | ||
418 | void b43_nrssi_mem_update(struct b43_wldev *dev) | ||
419 | { | ||
420 | struct b43_phy_g *gphy = dev->phy.g; | ||
421 | s16 i, delta; | ||
422 | s32 tmp; | ||
423 | |||
424 | delta = 0x1F - gphy->nrssi[0]; | ||
425 | for (i = 0; i < 64; i++) { | ||
426 | tmp = (i - delta) * gphy->nrssislope; | ||
427 | tmp /= 0x10000; | ||
428 | tmp += 0x3A; | ||
429 | tmp = clamp_val(tmp, 0, 0x3F); | ||
430 | gphy->nrssi_lt[i] = tmp; | ||
431 | } | ||
432 | } | ||
433 | |||
434 | static void b43_calc_nrssi_offset(struct b43_wldev *dev) | ||
435 | { | ||
436 | struct b43_phy *phy = &dev->phy; | ||
437 | u16 backup[20] = { 0 }; | ||
438 | s16 v47F; | ||
439 | u16 i; | ||
440 | u16 saved = 0xFFFF; | ||
441 | |||
442 | backup[0] = b43_phy_read(dev, 0x0001); | ||
443 | backup[1] = b43_phy_read(dev, 0x0811); | ||
444 | backup[2] = b43_phy_read(dev, 0x0812); | ||
445 | if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */ | ||
446 | backup[3] = b43_phy_read(dev, 0x0814); | ||
447 | backup[4] = b43_phy_read(dev, 0x0815); | ||
448 | } | ||
449 | backup[5] = b43_phy_read(dev, 0x005A); | ||
450 | backup[6] = b43_phy_read(dev, 0x0059); | ||
451 | backup[7] = b43_phy_read(dev, 0x0058); | ||
452 | backup[8] = b43_phy_read(dev, 0x000A); | ||
453 | backup[9] = b43_phy_read(dev, 0x0003); | ||
454 | backup[10] = b43_radio_read16(dev, 0x007A); | ||
455 | backup[11] = b43_radio_read16(dev, 0x0043); | ||
456 | |||
457 | b43_phy_write(dev, 0x0429, b43_phy_read(dev, 0x0429) & 0x7FFF); | ||
458 | b43_phy_write(dev, 0x0001, | ||
459 | (b43_phy_read(dev, 0x0001) & 0x3FFF) | 0x4000); | ||
460 | b43_phy_write(dev, 0x0811, b43_phy_read(dev, 0x0811) | 0x000C); | ||
461 | b43_phy_write(dev, 0x0812, | ||
462 | (b43_phy_read(dev, 0x0812) & 0xFFF3) | 0x0004); | ||
463 | b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) & ~(0x1 | 0x2)); | ||
464 | if (phy->rev >= 6) { | ||
465 | backup[12] = b43_phy_read(dev, 0x002E); | ||
466 | backup[13] = b43_phy_read(dev, 0x002F); | ||
467 | backup[14] = b43_phy_read(dev, 0x080F); | ||
468 | backup[15] = b43_phy_read(dev, 0x0810); | ||
469 | backup[16] = b43_phy_read(dev, 0x0801); | ||
470 | backup[17] = b43_phy_read(dev, 0x0060); | ||
471 | backup[18] = b43_phy_read(dev, 0x0014); | ||
472 | backup[19] = b43_phy_read(dev, 0x0478); | ||
473 | |||
474 | b43_phy_write(dev, 0x002E, 0); | ||
475 | b43_phy_write(dev, 0x002F, 0); | ||
476 | b43_phy_write(dev, 0x080F, 0); | ||
477 | b43_phy_write(dev, 0x0810, 0); | ||
478 | b43_phy_write(dev, 0x0478, b43_phy_read(dev, 0x0478) | 0x0100); | ||
479 | b43_phy_write(dev, 0x0801, b43_phy_read(dev, 0x0801) | 0x0040); | ||
480 | b43_phy_write(dev, 0x0060, b43_phy_read(dev, 0x0060) | 0x0040); | ||
481 | b43_phy_write(dev, 0x0014, b43_phy_read(dev, 0x0014) | 0x0200); | ||
482 | } | ||
483 | b43_radio_write16(dev, 0x007A, b43_radio_read16(dev, 0x007A) | 0x0070); | ||
484 | b43_radio_write16(dev, 0x007A, b43_radio_read16(dev, 0x007A) | 0x0080); | ||
485 | udelay(30); | ||
486 | |||
487 | v47F = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F); | ||
488 | if (v47F >= 0x20) | ||
489 | v47F -= 0x40; | ||
490 | if (v47F == 31) { | ||
491 | for (i = 7; i >= 4; i--) { | ||
492 | b43_radio_write16(dev, 0x007B, i); | ||
493 | udelay(20); | ||
494 | v47F = | ||
495 | (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F); | ||
496 | if (v47F >= 0x20) | ||
497 | v47F -= 0x40; | ||
498 | if (v47F < 31 && saved == 0xFFFF) | ||
499 | saved = i; | ||
500 | } | ||
501 | if (saved == 0xFFFF) | ||
502 | saved = 4; | ||
503 | } else { | ||
504 | b43_radio_write16(dev, 0x007A, | ||
505 | b43_radio_read16(dev, 0x007A) & 0x007F); | ||
506 | if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */ | ||
507 | b43_phy_write(dev, 0x0814, | ||
508 | b43_phy_read(dev, 0x0814) | 0x0001); | ||
509 | b43_phy_write(dev, 0x0815, | ||
510 | b43_phy_read(dev, 0x0815) & 0xFFFE); | ||
511 | } | ||
512 | b43_phy_write(dev, 0x0811, b43_phy_read(dev, 0x0811) | 0x000C); | ||
513 | b43_phy_write(dev, 0x0812, b43_phy_read(dev, 0x0812) | 0x000C); | ||
514 | b43_phy_write(dev, 0x0811, b43_phy_read(dev, 0x0811) | 0x0030); | ||
515 | b43_phy_write(dev, 0x0812, b43_phy_read(dev, 0x0812) | 0x0030); | ||
516 | b43_phy_write(dev, 0x005A, 0x0480); | ||
517 | b43_phy_write(dev, 0x0059, 0x0810); | ||
518 | b43_phy_write(dev, 0x0058, 0x000D); | ||
519 | if (phy->rev == 0) { | ||
520 | b43_phy_write(dev, 0x0003, 0x0122); | ||
521 | } else { | ||
522 | b43_phy_write(dev, 0x000A, b43_phy_read(dev, 0x000A) | ||
523 | | 0x2000); | ||
524 | } | ||
525 | if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */ | ||
526 | b43_phy_write(dev, 0x0814, | ||
527 | b43_phy_read(dev, 0x0814) | 0x0004); | ||
528 | b43_phy_write(dev, 0x0815, | ||
529 | b43_phy_read(dev, 0x0815) & 0xFFFB); | ||
530 | } | ||
531 | b43_phy_write(dev, 0x0003, (b43_phy_read(dev, 0x0003) & 0xFF9F) | ||
532 | | 0x0040); | ||
533 | b43_radio_write16(dev, 0x007A, | ||
534 | b43_radio_read16(dev, 0x007A) | 0x000F); | ||
535 | b43_set_all_gains(dev, 3, 0, 1); | ||
536 | b43_radio_write16(dev, 0x0043, (b43_radio_read16(dev, 0x0043) | ||
537 | & 0x00F0) | 0x000F); | ||
538 | udelay(30); | ||
539 | v47F = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F); | ||
540 | if (v47F >= 0x20) | ||
541 | v47F -= 0x40; | ||
542 | if (v47F == -32) { | ||
543 | for (i = 0; i < 4; i++) { | ||
544 | b43_radio_write16(dev, 0x007B, i); | ||
545 | udelay(20); | ||
546 | v47F = | ||
547 | (s16) ((b43_phy_read(dev, 0x047F) >> 8) & | ||
548 | 0x003F); | ||
549 | if (v47F >= 0x20) | ||
550 | v47F -= 0x40; | ||
551 | if (v47F > -31 && saved == 0xFFFF) | ||
552 | saved = i; | ||
553 | } | ||
554 | if (saved == 0xFFFF) | ||
555 | saved = 3; | ||
556 | } else | ||
557 | saved = 0; | ||
558 | } | ||
559 | b43_radio_write16(dev, 0x007B, saved); | ||
560 | |||
561 | if (phy->rev >= 6) { | ||
562 | b43_phy_write(dev, 0x002E, backup[12]); | ||
563 | b43_phy_write(dev, 0x002F, backup[13]); | ||
564 | b43_phy_write(dev, 0x080F, backup[14]); | ||
565 | b43_phy_write(dev, 0x0810, backup[15]); | ||
566 | } | ||
567 | if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */ | ||
568 | b43_phy_write(dev, 0x0814, backup[3]); | ||
569 | b43_phy_write(dev, 0x0815, backup[4]); | ||
570 | } | ||
571 | b43_phy_write(dev, 0x005A, backup[5]); | ||
572 | b43_phy_write(dev, 0x0059, backup[6]); | ||
573 | b43_phy_write(dev, 0x0058, backup[7]); | ||
574 | b43_phy_write(dev, 0x000A, backup[8]); | ||
575 | b43_phy_write(dev, 0x0003, backup[9]); | ||
576 | b43_radio_write16(dev, 0x0043, backup[11]); | ||
577 | b43_radio_write16(dev, 0x007A, backup[10]); | ||
578 | b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) | 0x1 | 0x2); | ||
579 | b43_phy_write(dev, 0x0429, b43_phy_read(dev, 0x0429) | 0x8000); | ||
580 | b43_set_original_gains(dev); | ||
581 | if (phy->rev >= 6) { | ||
582 | b43_phy_write(dev, 0x0801, backup[16]); | ||
583 | b43_phy_write(dev, 0x0060, backup[17]); | ||
584 | b43_phy_write(dev, 0x0014, backup[18]); | ||
585 | b43_phy_write(dev, 0x0478, backup[19]); | ||
586 | } | ||
587 | b43_phy_write(dev, 0x0001, backup[0]); | ||
588 | b43_phy_write(dev, 0x0812, backup[2]); | ||
589 | b43_phy_write(dev, 0x0811, backup[1]); | ||
590 | } | ||
591 | |||
592 | void b43_calc_nrssi_slope(struct b43_wldev *dev) | ||
593 | { | ||
594 | struct b43_phy *phy = &dev->phy; | ||
595 | struct b43_phy_g *gphy = phy->g; | ||
596 | u16 backup[18] = { 0 }; | ||
597 | u16 tmp; | ||
598 | s16 nrssi0, nrssi1; | ||
599 | |||
600 | B43_WARN_ON(phy->type != B43_PHYTYPE_G); | ||
601 | |||
602 | if (phy->radio_rev >= 9) | ||
603 | return; | ||
604 | if (phy->radio_rev == 8) | ||
605 | b43_calc_nrssi_offset(dev); | ||
606 | |||
607 | b43_phy_write(dev, B43_PHY_G_CRS, | ||
608 | b43_phy_read(dev, B43_PHY_G_CRS) & 0x7FFF); | ||
609 | b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) & 0xFFFC); | ||
610 | backup[7] = b43_read16(dev, 0x03E2); | ||
611 | b43_write16(dev, 0x03E2, b43_read16(dev, 0x03E2) | 0x8000); | ||
612 | backup[0] = b43_radio_read16(dev, 0x007A); | ||
613 | backup[1] = b43_radio_read16(dev, 0x0052); | ||
614 | backup[2] = b43_radio_read16(dev, 0x0043); | ||
615 | backup[3] = b43_phy_read(dev, 0x0015); | ||
616 | backup[4] = b43_phy_read(dev, 0x005A); | ||
617 | backup[5] = b43_phy_read(dev, 0x0059); | ||
618 | backup[6] = b43_phy_read(dev, 0x0058); | ||
619 | backup[8] = b43_read16(dev, 0x03E6); | ||
620 | backup[9] = b43_read16(dev, B43_MMIO_CHANNEL_EXT); | ||
621 | if (phy->rev >= 3) { | ||
622 | backup[10] = b43_phy_read(dev, 0x002E); | ||
623 | backup[11] = b43_phy_read(dev, 0x002F); | ||
624 | backup[12] = b43_phy_read(dev, 0x080F); | ||
625 | backup[13] = b43_phy_read(dev, B43_PHY_G_LO_CONTROL); | ||
626 | backup[14] = b43_phy_read(dev, 0x0801); | ||
627 | backup[15] = b43_phy_read(dev, 0x0060); | ||
628 | backup[16] = b43_phy_read(dev, 0x0014); | ||
629 | backup[17] = b43_phy_read(dev, 0x0478); | ||
630 | b43_phy_write(dev, 0x002E, 0); | ||
631 | b43_phy_write(dev, B43_PHY_G_LO_CONTROL, 0); | ||
632 | switch (phy->rev) { | ||
633 | case 4: | ||
634 | case 6: | ||
635 | case 7: | ||
636 | b43_phy_write(dev, 0x0478, | ||
637 | b43_phy_read(dev, 0x0478) | ||
638 | | 0x0100); | ||
639 | b43_phy_write(dev, 0x0801, | ||
640 | b43_phy_read(dev, 0x0801) | ||
641 | | 0x0040); | ||
642 | break; | ||
643 | case 3: | ||
644 | case 5: | ||
645 | b43_phy_write(dev, 0x0801, | ||
646 | b43_phy_read(dev, 0x0801) | ||
647 | & 0xFFBF); | ||
648 | break; | ||
649 | } | ||
650 | b43_phy_write(dev, 0x0060, b43_phy_read(dev, 0x0060) | ||
651 | | 0x0040); | ||
652 | b43_phy_write(dev, 0x0014, b43_phy_read(dev, 0x0014) | ||
653 | | 0x0200); | ||
654 | } | ||
655 | b43_radio_write16(dev, 0x007A, | ||
656 | b43_radio_read16(dev, 0x007A) | 0x0070); | ||
657 | b43_set_all_gains(dev, 0, 8, 0); | ||
658 | b43_radio_write16(dev, 0x007A, | ||
659 | b43_radio_read16(dev, 0x007A) & 0x00F7); | ||
660 | if (phy->rev >= 2) { | ||
661 | b43_phy_write(dev, 0x0811, | ||
662 | (b43_phy_read(dev, 0x0811) & 0xFFCF) | | ||
663 | 0x0030); | ||
664 | b43_phy_write(dev, 0x0812, | ||
665 | (b43_phy_read(dev, 0x0812) & 0xFFCF) | | ||
666 | 0x0010); | ||
667 | } | ||
668 | b43_radio_write16(dev, 0x007A, | ||
669 | b43_radio_read16(dev, 0x007A) | 0x0080); | ||
670 | udelay(20); | ||
671 | |||
672 | nrssi0 = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F); | ||
673 | if (nrssi0 >= 0x0020) | ||
674 | nrssi0 -= 0x0040; | ||
675 | |||
676 | b43_radio_write16(dev, 0x007A, | ||
677 | b43_radio_read16(dev, 0x007A) & 0x007F); | ||
678 | if (phy->rev >= 2) { | ||
679 | b43_phy_write(dev, 0x0003, (b43_phy_read(dev, 0x0003) | ||
680 | & 0xFF9F) | 0x0040); | ||
681 | } | ||
682 | |||
683 | b43_write16(dev, B43_MMIO_CHANNEL_EXT, | ||
684 | b43_read16(dev, B43_MMIO_CHANNEL_EXT) | ||
685 | | 0x2000); | ||
686 | b43_radio_write16(dev, 0x007A, | ||
687 | b43_radio_read16(dev, 0x007A) | 0x000F); | ||
688 | b43_phy_write(dev, 0x0015, 0xF330); | ||
689 | if (phy->rev >= 2) { | ||
690 | b43_phy_write(dev, 0x0812, | ||
691 | (b43_phy_read(dev, 0x0812) & 0xFFCF) | | ||
692 | 0x0020); | ||
693 | b43_phy_write(dev, 0x0811, | ||
694 | (b43_phy_read(dev, 0x0811) & 0xFFCF) | | ||
695 | 0x0020); | ||
696 | } | ||
697 | |||
698 | b43_set_all_gains(dev, 3, 0, 1); | ||
699 | if (phy->radio_rev == 8) { | ||
700 | b43_radio_write16(dev, 0x0043, 0x001F); | ||
701 | } else { | ||
702 | tmp = b43_radio_read16(dev, 0x0052) & 0xFF0F; | ||
703 | b43_radio_write16(dev, 0x0052, tmp | 0x0060); | ||
704 | tmp = b43_radio_read16(dev, 0x0043) & 0xFFF0; | ||
705 | b43_radio_write16(dev, 0x0043, tmp | 0x0009); | ||
706 | } | ||
707 | b43_phy_write(dev, 0x005A, 0x0480); | ||
708 | b43_phy_write(dev, 0x0059, 0x0810); | ||
709 | b43_phy_write(dev, 0x0058, 0x000D); | ||
710 | udelay(20); | ||
711 | nrssi1 = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F); | ||
712 | if (nrssi1 >= 0x0020) | ||
713 | nrssi1 -= 0x0040; | ||
714 | if (nrssi0 == nrssi1) | ||
715 | gphy->nrssislope = 0x00010000; | ||
716 | else | ||
717 | gphy->nrssislope = 0x00400000 / (nrssi0 - nrssi1); | ||
718 | if (nrssi0 >= -4) { | ||
719 | gphy->nrssi[0] = nrssi1; | ||
720 | gphy->nrssi[1] = nrssi0; | ||
721 | } | ||
722 | if (phy->rev >= 3) { | ||
723 | b43_phy_write(dev, 0x002E, backup[10]); | ||
724 | b43_phy_write(dev, 0x002F, backup[11]); | ||
725 | b43_phy_write(dev, 0x080F, backup[12]); | ||
726 | b43_phy_write(dev, B43_PHY_G_LO_CONTROL, backup[13]); | ||
727 | } | ||
728 | if (phy->rev >= 2) { | ||
729 | b43_phy_write(dev, 0x0812, | ||
730 | b43_phy_read(dev, 0x0812) & 0xFFCF); | ||
731 | b43_phy_write(dev, 0x0811, | ||
732 | b43_phy_read(dev, 0x0811) & 0xFFCF); | ||
733 | } | ||
734 | |||
735 | b43_radio_write16(dev, 0x007A, backup[0]); | ||
736 | b43_radio_write16(dev, 0x0052, backup[1]); | ||
737 | b43_radio_write16(dev, 0x0043, backup[2]); | ||
738 | b43_write16(dev, 0x03E2, backup[7]); | ||
739 | b43_write16(dev, 0x03E6, backup[8]); | ||
740 | b43_write16(dev, B43_MMIO_CHANNEL_EXT, backup[9]); | ||
741 | b43_phy_write(dev, 0x0015, backup[3]); | ||
742 | b43_phy_write(dev, 0x005A, backup[4]); | ||
743 | b43_phy_write(dev, 0x0059, backup[5]); | ||
744 | b43_phy_write(dev, 0x0058, backup[6]); | ||
745 | b43_synth_pu_workaround(dev, phy->channel); | ||
746 | b43_phy_write(dev, 0x0802, | ||
747 | b43_phy_read(dev, 0x0802) | (0x0001 | 0x0002)); | ||
748 | b43_set_original_gains(dev); | ||
749 | b43_phy_write(dev, B43_PHY_G_CRS, | ||
750 | b43_phy_read(dev, B43_PHY_G_CRS) | 0x8000); | ||
751 | if (phy->rev >= 3) { | ||
752 | b43_phy_write(dev, 0x0801, backup[14]); | ||
753 | b43_phy_write(dev, 0x0060, backup[15]); | ||
754 | b43_phy_write(dev, 0x0014, backup[16]); | ||
755 | b43_phy_write(dev, 0x0478, backup[17]); | ||
756 | } | ||
757 | b43_nrssi_mem_update(dev); | ||
758 | b43_calc_nrssi_threshold(dev); | ||
759 | } | ||
760 | |||
761 | static void b43_calc_nrssi_threshold(struct b43_wldev *dev) | ||
762 | { | ||
763 | struct b43_phy *phy = &dev->phy; | ||
764 | struct b43_phy_g *gphy = phy->g; | ||
765 | s32 a, b; | ||
766 | s16 tmp16; | ||
767 | u16 tmp_u16; | ||
768 | |||
769 | B43_WARN_ON(phy->type != B43_PHYTYPE_G); | ||
770 | |||
771 | if (!phy->gmode || | ||
772 | !(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) { | ||
773 | tmp16 = b43_nrssi_hw_read(dev, 0x20); | ||
774 | if (tmp16 >= 0x20) | ||
775 | tmp16 -= 0x40; | ||
776 | if (tmp16 < 3) { | ||
777 | b43_phy_write(dev, 0x048A, | ||
778 | (b43_phy_read(dev, 0x048A) | ||
779 | & 0xF000) | 0x09EB); | ||
780 | } else { | ||
781 | b43_phy_write(dev, 0x048A, | ||
782 | (b43_phy_read(dev, 0x048A) | ||
783 | & 0xF000) | 0x0AED); | ||
784 | } | ||
785 | } else { | ||
786 | if (gphy->interfmode == B43_INTERFMODE_NONWLAN) { | ||
787 | a = 0xE; | ||
788 | b = 0xA; | ||
789 | } else if (!gphy->aci_wlan_automatic && gphy->aci_enable) { | ||
790 | a = 0x13; | ||
791 | b = 0x12; | ||
792 | } else { | ||
793 | a = 0xE; | ||
794 | b = 0x11; | ||
795 | } | ||
796 | |||
797 | a = a * (gphy->nrssi[1] - gphy->nrssi[0]); | ||
798 | a += (gphy->nrssi[0] << 6); | ||
799 | if (a < 32) | ||
800 | a += 31; | ||
801 | else | ||
802 | a += 32; | ||
803 | a = a >> 6; | ||
804 | a = clamp_val(a, -31, 31); | ||
805 | |||
806 | b = b * (gphy->nrssi[1] - gphy->nrssi[0]); | ||
807 | b += (gphy->nrssi[0] << 6); | ||
808 | if (b < 32) | ||
809 | b += 31; | ||
810 | else | ||
811 | b += 32; | ||
812 | b = b >> 6; | ||
813 | b = clamp_val(b, -31, 31); | ||
814 | |||
815 | tmp_u16 = b43_phy_read(dev, 0x048A) & 0xF000; | ||
816 | tmp_u16 |= ((u32) b & 0x0000003F); | ||
817 | tmp_u16 |= (((u32) a & 0x0000003F) << 6); | ||
818 | b43_phy_write(dev, 0x048A, tmp_u16); | ||
819 | } | ||
820 | } | ||
821 | |||
822 | /* Stack implementation to save/restore values from the | ||
823 | * interference mitigation code. | ||
824 | * It is save to restore values in random order. | ||
825 | */ | ||
826 | static void _stack_save(u32 * _stackptr, size_t * stackidx, | ||
827 | u8 id, u16 offset, u16 value) | ||
828 | { | ||
829 | u32 *stackptr = &(_stackptr[*stackidx]); | ||
830 | |||
831 | B43_WARN_ON(offset & 0xF000); | ||
832 | B43_WARN_ON(id & 0xF0); | ||
833 | *stackptr = offset; | ||
834 | *stackptr |= ((u32) id) << 12; | ||
835 | *stackptr |= ((u32) value) << 16; | ||
836 | (*stackidx)++; | ||
837 | B43_WARN_ON(*stackidx >= B43_INTERFSTACK_SIZE); | ||
838 | } | ||
839 | |||
840 | static u16 _stack_restore(u32 * stackptr, u8 id, u16 offset) | ||
841 | { | ||
842 | size_t i; | ||
843 | |||
844 | B43_WARN_ON(offset & 0xF000); | ||
845 | B43_WARN_ON(id & 0xF0); | ||
846 | for (i = 0; i < B43_INTERFSTACK_SIZE; i++, stackptr++) { | ||
847 | if ((*stackptr & 0x00000FFF) != offset) | ||
848 | continue; | ||
849 | if (((*stackptr & 0x0000F000) >> 12) != id) | ||
850 | continue; | ||
851 | return ((*stackptr & 0xFFFF0000) >> 16); | ||
852 | } | ||
853 | B43_WARN_ON(1); | ||
854 | |||
855 | return 0; | ||
856 | } | ||
857 | |||
858 | #define phy_stacksave(offset) \ | ||
859 | do { \ | ||
860 | _stack_save(stack, &stackidx, 0x1, (offset), \ | ||
861 | b43_phy_read(dev, (offset))); \ | ||
862 | } while (0) | ||
863 | #define phy_stackrestore(offset) \ | ||
864 | do { \ | ||
865 | b43_phy_write(dev, (offset), \ | ||
866 | _stack_restore(stack, 0x1, \ | ||
867 | (offset))); \ | ||
868 | } while (0) | ||
869 | #define radio_stacksave(offset) \ | ||
870 | do { \ | ||
871 | _stack_save(stack, &stackidx, 0x2, (offset), \ | ||
872 | b43_radio_read16(dev, (offset))); \ | ||
873 | } while (0) | ||
874 | #define radio_stackrestore(offset) \ | ||
875 | do { \ | ||
876 | b43_radio_write16(dev, (offset), \ | ||
877 | _stack_restore(stack, 0x2, \ | ||
878 | (offset))); \ | ||
879 | } while (0) | ||
880 | #define ofdmtab_stacksave(table, offset) \ | ||
881 | do { \ | ||
882 | _stack_save(stack, &stackidx, 0x3, (offset)|(table), \ | ||
883 | b43_ofdmtab_read16(dev, (table), (offset))); \ | ||
884 | } while (0) | ||
885 | #define ofdmtab_stackrestore(table, offset) \ | ||
886 | do { \ | ||
887 | b43_ofdmtab_write16(dev, (table), (offset), \ | ||
888 | _stack_restore(stack, 0x3, \ | ||
889 | (offset)|(table))); \ | ||
890 | } while (0) | ||
891 | |||
892 | static void | ||
893 | b43_radio_interference_mitigation_enable(struct b43_wldev *dev, int mode) | ||
894 | { | ||
895 | struct b43_phy *phy = &dev->phy; | ||
896 | struct b43_phy_g *gphy = phy->g; | ||
897 | u16 tmp, flipped; | ||
898 | size_t stackidx = 0; | ||
899 | u32 *stack = gphy->interfstack; | ||
900 | |||
901 | switch (mode) { | ||
902 | case B43_INTERFMODE_NONWLAN: | ||
903 | if (phy->rev != 1) { | ||
904 | b43_phy_write(dev, 0x042B, | ||
905 | b43_phy_read(dev, 0x042B) | 0x0800); | ||
906 | b43_phy_write(dev, B43_PHY_G_CRS, | ||
907 | b43_phy_read(dev, | ||
908 | B43_PHY_G_CRS) & ~0x4000); | ||
909 | break; | ||
910 | } | ||
911 | radio_stacksave(0x0078); | ||
912 | tmp = (b43_radio_read16(dev, 0x0078) & 0x001E); | ||
913 | B43_WARN_ON(tmp > 15); | ||
914 | flipped = bitrev4(tmp); | ||
915 | if (flipped < 10 && flipped >= 8) | ||
916 | flipped = 7; | ||
917 | else if (flipped >= 10) | ||
918 | flipped -= 3; | ||
919 | flipped = (bitrev4(flipped) << 1) | 0x0020; | ||
920 | b43_radio_write16(dev, 0x0078, flipped); | ||
921 | |||
922 | b43_calc_nrssi_threshold(dev); | ||
923 | |||
924 | phy_stacksave(0x0406); | ||
925 | b43_phy_write(dev, 0x0406, 0x7E28); | ||
926 | |||
927 | b43_phy_write(dev, 0x042B, b43_phy_read(dev, 0x042B) | 0x0800); | ||
928 | b43_phy_write(dev, B43_PHY_RADIO_BITFIELD, | ||
929 | b43_phy_read(dev, | ||
930 | B43_PHY_RADIO_BITFIELD) | 0x1000); | ||
931 | |||
932 | phy_stacksave(0x04A0); | ||
933 | b43_phy_write(dev, 0x04A0, | ||
934 | (b43_phy_read(dev, 0x04A0) & 0xC0C0) | 0x0008); | ||
935 | phy_stacksave(0x04A1); | ||
936 | b43_phy_write(dev, 0x04A1, | ||
937 | (b43_phy_read(dev, 0x04A1) & 0xC0C0) | 0x0605); | ||
938 | phy_stacksave(0x04A2); | ||
939 | b43_phy_write(dev, 0x04A2, | ||
940 | (b43_phy_read(dev, 0x04A2) & 0xC0C0) | 0x0204); | ||
941 | phy_stacksave(0x04A8); | ||
942 | b43_phy_write(dev, 0x04A8, | ||
943 | (b43_phy_read(dev, 0x04A8) & 0xC0C0) | 0x0803); | ||
944 | phy_stacksave(0x04AB); | ||
945 | b43_phy_write(dev, 0x04AB, | ||
946 | (b43_phy_read(dev, 0x04AB) & 0xC0C0) | 0x0605); | ||
947 | |||
948 | phy_stacksave(0x04A7); | ||
949 | b43_phy_write(dev, 0x04A7, 0x0002); | ||
950 | phy_stacksave(0x04A3); | ||
951 | b43_phy_write(dev, 0x04A3, 0x287A); | ||
952 | phy_stacksave(0x04A9); | ||
953 | b43_phy_write(dev, 0x04A9, 0x2027); | ||
954 | phy_stacksave(0x0493); | ||
955 | b43_phy_write(dev, 0x0493, 0x32F5); | ||
956 | phy_stacksave(0x04AA); | ||
957 | b43_phy_write(dev, 0x04AA, 0x2027); | ||
958 | phy_stacksave(0x04AC); | ||
959 | b43_phy_write(dev, 0x04AC, 0x32F5); | ||
960 | break; | ||
961 | case B43_INTERFMODE_MANUALWLAN: | ||
962 | if (b43_phy_read(dev, 0x0033) & 0x0800) | ||
963 | break; | ||
964 | |||
965 | gphy->aci_enable = 1; | ||
966 | |||
967 | phy_stacksave(B43_PHY_RADIO_BITFIELD); | ||
968 | phy_stacksave(B43_PHY_G_CRS); | ||
969 | if (phy->rev < 2) { | ||
970 | phy_stacksave(0x0406); | ||
971 | } else { | ||
972 | phy_stacksave(0x04C0); | ||
973 | phy_stacksave(0x04C1); | ||
974 | } | ||
975 | phy_stacksave(0x0033); | ||
976 | phy_stacksave(0x04A7); | ||
977 | phy_stacksave(0x04A3); | ||
978 | phy_stacksave(0x04A9); | ||
979 | phy_stacksave(0x04AA); | ||
980 | phy_stacksave(0x04AC); | ||
981 | phy_stacksave(0x0493); | ||
982 | phy_stacksave(0x04A1); | ||
983 | phy_stacksave(0x04A0); | ||
984 | phy_stacksave(0x04A2); | ||
985 | phy_stacksave(0x048A); | ||
986 | phy_stacksave(0x04A8); | ||
987 | phy_stacksave(0x04AB); | ||
988 | if (phy->rev == 2) { | ||
989 | phy_stacksave(0x04AD); | ||
990 | phy_stacksave(0x04AE); | ||
991 | } else if (phy->rev >= 3) { | ||
992 | phy_stacksave(0x04AD); | ||
993 | phy_stacksave(0x0415); | ||
994 | phy_stacksave(0x0416); | ||
995 | phy_stacksave(0x0417); | ||
996 | ofdmtab_stacksave(0x1A00, 0x2); | ||
997 | ofdmtab_stacksave(0x1A00, 0x3); | ||
998 | } | ||
999 | phy_stacksave(0x042B); | ||
1000 | phy_stacksave(0x048C); | ||
1001 | |||
1002 | b43_phy_write(dev, B43_PHY_RADIO_BITFIELD, | ||
1003 | b43_phy_read(dev, B43_PHY_RADIO_BITFIELD) | ||
1004 | & ~0x1000); | ||
1005 | b43_phy_write(dev, B43_PHY_G_CRS, | ||
1006 | (b43_phy_read(dev, B43_PHY_G_CRS) | ||
1007 | & 0xFFFC) | 0x0002); | ||
1008 | |||
1009 | b43_phy_write(dev, 0x0033, 0x0800); | ||
1010 | b43_phy_write(dev, 0x04A3, 0x2027); | ||
1011 | b43_phy_write(dev, 0x04A9, 0x1CA8); | ||
1012 | b43_phy_write(dev, 0x0493, 0x287A); | ||
1013 | b43_phy_write(dev, 0x04AA, 0x1CA8); | ||
1014 | b43_phy_write(dev, 0x04AC, 0x287A); | ||
1015 | |||
1016 | b43_phy_write(dev, 0x04A0, (b43_phy_read(dev, 0x04A0) | ||
1017 | & 0xFFC0) | 0x001A); | ||
1018 | b43_phy_write(dev, 0x04A7, 0x000D); | ||
1019 | |||
1020 | if (phy->rev < 2) { | ||
1021 | b43_phy_write(dev, 0x0406, 0xFF0D); | ||
1022 | } else if (phy->rev == 2) { | ||
1023 | b43_phy_write(dev, 0x04C0, 0xFFFF); | ||
1024 | b43_phy_write(dev, 0x04C1, 0x00A9); | ||
1025 | } else { | ||
1026 | b43_phy_write(dev, 0x04C0, 0x00C1); | ||
1027 | b43_phy_write(dev, 0x04C1, 0x0059); | ||
1028 | } | ||
1029 | |||
1030 | b43_phy_write(dev, 0x04A1, (b43_phy_read(dev, 0x04A1) | ||
1031 | & 0xC0FF) | 0x1800); | ||
1032 | b43_phy_write(dev, 0x04A1, (b43_phy_read(dev, 0x04A1) | ||
1033 | & 0xFFC0) | 0x0015); | ||
1034 | b43_phy_write(dev, 0x04A8, (b43_phy_read(dev, 0x04A8) | ||
1035 | & 0xCFFF) | 0x1000); | ||
1036 | b43_phy_write(dev, 0x04A8, (b43_phy_read(dev, 0x04A8) | ||
1037 | & 0xF0FF) | 0x0A00); | ||
1038 | b43_phy_write(dev, 0x04AB, (b43_phy_read(dev, 0x04AB) | ||
1039 | & 0xCFFF) | 0x1000); | ||
1040 | b43_phy_write(dev, 0x04AB, (b43_phy_read(dev, 0x04AB) | ||
1041 | & 0xF0FF) | 0x0800); | ||
1042 | b43_phy_write(dev, 0x04AB, (b43_phy_read(dev, 0x04AB) | ||
1043 | & 0xFFCF) | 0x0010); | ||
1044 | b43_phy_write(dev, 0x04AB, (b43_phy_read(dev, 0x04AB) | ||
1045 | & 0xFFF0) | 0x0005); | ||
1046 | b43_phy_write(dev, 0x04A8, (b43_phy_read(dev, 0x04A8) | ||
1047 | & 0xFFCF) | 0x0010); | ||
1048 | b43_phy_write(dev, 0x04A8, (b43_phy_read(dev, 0x04A8) | ||
1049 | & 0xFFF0) | 0x0006); | ||
1050 | b43_phy_write(dev, 0x04A2, (b43_phy_read(dev, 0x04A2) | ||
1051 | & 0xF0FF) | 0x0800); | ||
1052 | b43_phy_write(dev, 0x04A0, (b43_phy_read(dev, 0x04A0) | ||
1053 | & 0xF0FF) | 0x0500); | ||
1054 | b43_phy_write(dev, 0x04A2, (b43_phy_read(dev, 0x04A2) | ||
1055 | & 0xFFF0) | 0x000B); | ||
1056 | |||
1057 | if (phy->rev >= 3) { | ||
1058 | b43_phy_write(dev, 0x048A, b43_phy_read(dev, 0x048A) | ||
1059 | & ~0x8000); | ||
1060 | b43_phy_write(dev, 0x0415, (b43_phy_read(dev, 0x0415) | ||
1061 | & 0x8000) | 0x36D8); | ||
1062 | b43_phy_write(dev, 0x0416, (b43_phy_read(dev, 0x0416) | ||
1063 | & 0x8000) | 0x36D8); | ||
1064 | b43_phy_write(dev, 0x0417, (b43_phy_read(dev, 0x0417) | ||
1065 | & 0xFE00) | 0x016D); | ||
1066 | } else { | ||
1067 | b43_phy_write(dev, 0x048A, b43_phy_read(dev, 0x048A) | ||
1068 | | 0x1000); | ||
1069 | b43_phy_write(dev, 0x048A, (b43_phy_read(dev, 0x048A) | ||
1070 | & 0x9FFF) | 0x2000); | ||
1071 | b43_hf_write(dev, b43_hf_read(dev) | B43_HF_ACIW); | ||
1072 | } | ||
1073 | if (phy->rev >= 2) { | ||
1074 | b43_phy_write(dev, 0x042B, b43_phy_read(dev, 0x042B) | ||
1075 | | 0x0800); | ||
1076 | } | ||
1077 | b43_phy_write(dev, 0x048C, (b43_phy_read(dev, 0x048C) | ||
1078 | & 0xF0FF) | 0x0200); | ||
1079 | if (phy->rev == 2) { | ||
1080 | b43_phy_write(dev, 0x04AE, (b43_phy_read(dev, 0x04AE) | ||
1081 | & 0xFF00) | 0x007F); | ||
1082 | b43_phy_write(dev, 0x04AD, (b43_phy_read(dev, 0x04AD) | ||
1083 | & 0x00FF) | 0x1300); | ||
1084 | } else if (phy->rev >= 6) { | ||
1085 | b43_ofdmtab_write16(dev, 0x1A00, 0x3, 0x007F); | ||
1086 | b43_ofdmtab_write16(dev, 0x1A00, 0x2, 0x007F); | ||
1087 | b43_phy_write(dev, 0x04AD, b43_phy_read(dev, 0x04AD) | ||
1088 | & 0x00FF); | ||
1089 | } | ||
1090 | b43_calc_nrssi_slope(dev); | ||
1091 | break; | ||
1092 | default: | ||
1093 | B43_WARN_ON(1); | ||
1094 | } | ||
1095 | } | ||
1096 | |||
1097 | static void | ||
1098 | b43_radio_interference_mitigation_disable(struct b43_wldev *dev, int mode) | ||
1099 | { | ||
1100 | struct b43_phy *phy = &dev->phy; | ||
1101 | struct b43_phy_g *gphy = phy->g; | ||
1102 | u32 *stack = gphy->interfstack; | ||
1103 | |||
1104 | switch (mode) { | ||
1105 | case B43_INTERFMODE_NONWLAN: | ||
1106 | if (phy->rev != 1) { | ||
1107 | b43_phy_write(dev, 0x042B, | ||
1108 | b43_phy_read(dev, 0x042B) & ~0x0800); | ||
1109 | b43_phy_write(dev, B43_PHY_G_CRS, | ||
1110 | b43_phy_read(dev, | ||
1111 | B43_PHY_G_CRS) | 0x4000); | ||
1112 | break; | ||
1113 | } | ||
1114 | radio_stackrestore(0x0078); | ||
1115 | b43_calc_nrssi_threshold(dev); | ||
1116 | phy_stackrestore(0x0406); | ||
1117 | b43_phy_write(dev, 0x042B, b43_phy_read(dev, 0x042B) & ~0x0800); | ||
1118 | if (!dev->bad_frames_preempt) { | ||
1119 | b43_phy_write(dev, B43_PHY_RADIO_BITFIELD, | ||
1120 | b43_phy_read(dev, B43_PHY_RADIO_BITFIELD) | ||
1121 | & ~(1 << 11)); | ||
1122 | } | ||
1123 | b43_phy_write(dev, B43_PHY_G_CRS, | ||
1124 | b43_phy_read(dev, B43_PHY_G_CRS) | 0x4000); | ||
1125 | phy_stackrestore(0x04A0); | ||
1126 | phy_stackrestore(0x04A1); | ||
1127 | phy_stackrestore(0x04A2); | ||
1128 | phy_stackrestore(0x04A8); | ||
1129 | phy_stackrestore(0x04AB); | ||
1130 | phy_stackrestore(0x04A7); | ||
1131 | phy_stackrestore(0x04A3); | ||
1132 | phy_stackrestore(0x04A9); | ||
1133 | phy_stackrestore(0x0493); | ||
1134 | phy_stackrestore(0x04AA); | ||
1135 | phy_stackrestore(0x04AC); | ||
1136 | break; | ||
1137 | case B43_INTERFMODE_MANUALWLAN: | ||
1138 | if (!(b43_phy_read(dev, 0x0033) & 0x0800)) | ||
1139 | break; | ||
1140 | |||
1141 | gphy->aci_enable = 0; | ||
1142 | |||
1143 | phy_stackrestore(B43_PHY_RADIO_BITFIELD); | ||
1144 | phy_stackrestore(B43_PHY_G_CRS); | ||
1145 | phy_stackrestore(0x0033); | ||
1146 | phy_stackrestore(0x04A3); | ||
1147 | phy_stackrestore(0x04A9); | ||
1148 | phy_stackrestore(0x0493); | ||
1149 | phy_stackrestore(0x04AA); | ||
1150 | phy_stackrestore(0x04AC); | ||
1151 | phy_stackrestore(0x04A0); | ||
1152 | phy_stackrestore(0x04A7); | ||
1153 | if (phy->rev >= 2) { | ||
1154 | phy_stackrestore(0x04C0); | ||
1155 | phy_stackrestore(0x04C1); | ||
1156 | } else | ||
1157 | phy_stackrestore(0x0406); | ||
1158 | phy_stackrestore(0x04A1); | ||
1159 | phy_stackrestore(0x04AB); | ||
1160 | phy_stackrestore(0x04A8); | ||
1161 | if (phy->rev == 2) { | ||
1162 | phy_stackrestore(0x04AD); | ||
1163 | phy_stackrestore(0x04AE); | ||
1164 | } else if (phy->rev >= 3) { | ||
1165 | phy_stackrestore(0x04AD); | ||
1166 | phy_stackrestore(0x0415); | ||
1167 | phy_stackrestore(0x0416); | ||
1168 | phy_stackrestore(0x0417); | ||
1169 | ofdmtab_stackrestore(0x1A00, 0x2); | ||
1170 | ofdmtab_stackrestore(0x1A00, 0x3); | ||
1171 | } | ||
1172 | phy_stackrestore(0x04A2); | ||
1173 | phy_stackrestore(0x048A); | ||
1174 | phy_stackrestore(0x042B); | ||
1175 | phy_stackrestore(0x048C); | ||
1176 | b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_ACIW); | ||
1177 | b43_calc_nrssi_slope(dev); | ||
1178 | break; | ||
1179 | default: | ||
1180 | B43_WARN_ON(1); | ||
1181 | } | ||
1182 | } | ||
1183 | |||
1184 | #undef phy_stacksave | ||
1185 | #undef phy_stackrestore | ||
1186 | #undef radio_stacksave | ||
1187 | #undef radio_stackrestore | ||
1188 | #undef ofdmtab_stacksave | ||
1189 | #undef ofdmtab_stackrestore | ||
1190 | |||
1191 | static u16 b43_radio_core_calibration_value(struct b43_wldev *dev) | ||
1192 | { | ||
1193 | u16 reg, index, ret; | ||
1194 | |||
1195 | static const u8 rcc_table[] = { | ||
1196 | 0x02, 0x03, 0x01, 0x0F, | ||
1197 | 0x06, 0x07, 0x05, 0x0F, | ||
1198 | 0x0A, 0x0B, 0x09, 0x0F, | ||
1199 | 0x0E, 0x0F, 0x0D, 0x0F, | ||
1200 | }; | ||
1201 | |||
1202 | reg = b43_radio_read16(dev, 0x60); | ||
1203 | index = (reg & 0x001E) >> 1; | ||
1204 | ret = rcc_table[index] << 1; | ||
1205 | ret |= (reg & 0x0001); | ||
1206 | ret |= 0x0020; | ||
1207 | |||
1208 | return ret; | ||
1209 | } | ||
1210 | |||
1211 | #define LPD(L, P, D) (((L) << 2) | ((P) << 1) | ((D) << 0)) | ||
1212 | static u16 radio2050_rfover_val(struct b43_wldev *dev, | ||
1213 | u16 phy_register, unsigned int lpd) | ||
1214 | { | ||
1215 | struct b43_phy *phy = &dev->phy; | ||
1216 | struct b43_phy_g *gphy = phy->g; | ||
1217 | struct ssb_sprom *sprom = &(dev->dev->bus->sprom); | ||
1218 | |||
1219 | if (!phy->gmode) | ||
1220 | return 0; | ||
1221 | |||
1222 | if (has_loopback_gain(phy)) { | ||
1223 | int max_lb_gain = gphy->max_lb_gain; | ||
1224 | u16 extlna; | ||
1225 | u16 i; | ||
1226 | |||
1227 | if (phy->radio_rev == 8) | ||
1228 | max_lb_gain += 0x3E; | ||
1229 | else | ||
1230 | max_lb_gain += 0x26; | ||
1231 | if (max_lb_gain >= 0x46) { | ||
1232 | extlna = 0x3000; | ||
1233 | max_lb_gain -= 0x46; | ||
1234 | } else if (max_lb_gain >= 0x3A) { | ||
1235 | extlna = 0x1000; | ||
1236 | max_lb_gain -= 0x3A; | ||
1237 | } else if (max_lb_gain >= 0x2E) { | ||
1238 | extlna = 0x2000; | ||
1239 | max_lb_gain -= 0x2E; | ||
1240 | } else { | ||
1241 | extlna = 0; | ||
1242 | max_lb_gain -= 0x10; | ||
1243 | } | ||
1244 | |||
1245 | for (i = 0; i < 16; i++) { | ||
1246 | max_lb_gain -= (i * 6); | ||
1247 | if (max_lb_gain < 6) | ||
1248 | break; | ||
1249 | } | ||
1250 | |||
1251 | if ((phy->rev < 7) || | ||
1252 | !(sprom->boardflags_lo & B43_BFL_EXTLNA)) { | ||
1253 | if (phy_register == B43_PHY_RFOVER) { | ||
1254 | return 0x1B3; | ||
1255 | } else if (phy_register == B43_PHY_RFOVERVAL) { | ||
1256 | extlna |= (i << 8); | ||
1257 | switch (lpd) { | ||
1258 | case LPD(0, 1, 1): | ||
1259 | return 0x0F92; | ||
1260 | case LPD(0, 0, 1): | ||
1261 | case LPD(1, 0, 1): | ||
1262 | return (0x0092 | extlna); | ||
1263 | case LPD(1, 0, 0): | ||
1264 | return (0x0093 | extlna); | ||
1265 | } | ||
1266 | B43_WARN_ON(1); | ||
1267 | } | ||
1268 | B43_WARN_ON(1); | ||
1269 | } else { | ||
1270 | if (phy_register == B43_PHY_RFOVER) { | ||
1271 | return 0x9B3; | ||
1272 | } else if (phy_register == B43_PHY_RFOVERVAL) { | ||
1273 | if (extlna) | ||
1274 | extlna |= 0x8000; | ||
1275 | extlna |= (i << 8); | ||
1276 | switch (lpd) { | ||
1277 | case LPD(0, 1, 1): | ||
1278 | return 0x8F92; | ||
1279 | case LPD(0, 0, 1): | ||
1280 | return (0x8092 | extlna); | ||
1281 | case LPD(1, 0, 1): | ||
1282 | return (0x2092 | extlna); | ||
1283 | case LPD(1, 0, 0): | ||
1284 | return (0x2093 | extlna); | ||
1285 | } | ||
1286 | B43_WARN_ON(1); | ||
1287 | } | ||
1288 | B43_WARN_ON(1); | ||
1289 | } | ||
1290 | } else { | ||
1291 | if ((phy->rev < 7) || | ||
1292 | !(sprom->boardflags_lo & B43_BFL_EXTLNA)) { | ||
1293 | if (phy_register == B43_PHY_RFOVER) { | ||
1294 | return 0x1B3; | ||
1295 | } else if (phy_register == B43_PHY_RFOVERVAL) { | ||
1296 | switch (lpd) { | ||
1297 | case LPD(0, 1, 1): | ||
1298 | return 0x0FB2; | ||
1299 | case LPD(0, 0, 1): | ||
1300 | return 0x00B2; | ||
1301 | case LPD(1, 0, 1): | ||
1302 | return 0x30B2; | ||
1303 | case LPD(1, 0, 0): | ||
1304 | return 0x30B3; | ||
1305 | } | ||
1306 | B43_WARN_ON(1); | ||
1307 | } | ||
1308 | B43_WARN_ON(1); | ||
1309 | } else { | ||
1310 | if (phy_register == B43_PHY_RFOVER) { | ||
1311 | return 0x9B3; | ||
1312 | } else if (phy_register == B43_PHY_RFOVERVAL) { | ||
1313 | switch (lpd) { | ||
1314 | case LPD(0, 1, 1): | ||
1315 | return 0x8FB2; | ||
1316 | case LPD(0, 0, 1): | ||
1317 | return 0x80B2; | ||
1318 | case LPD(1, 0, 1): | ||
1319 | return 0x20B2; | ||
1320 | case LPD(1, 0, 0): | ||
1321 | return 0x20B3; | ||
1322 | } | ||
1323 | B43_WARN_ON(1); | ||
1324 | } | ||
1325 | B43_WARN_ON(1); | ||
1326 | } | ||
1327 | } | ||
1328 | return 0; | ||
1329 | } | ||
1330 | |||
1331 | struct init2050_saved_values { | ||
1332 | /* Core registers */ | ||
1333 | u16 reg_3EC; | ||
1334 | u16 reg_3E6; | ||
1335 | u16 reg_3F4; | ||
1336 | /* Radio registers */ | ||
1337 | u16 radio_43; | ||
1338 | u16 radio_51; | ||
1339 | u16 radio_52; | ||
1340 | /* PHY registers */ | ||
1341 | u16 phy_pgactl; | ||
1342 | u16 phy_cck_5A; | ||
1343 | u16 phy_cck_59; | ||
1344 | u16 phy_cck_58; | ||
1345 | u16 phy_cck_30; | ||
1346 | u16 phy_rfover; | ||
1347 | u16 phy_rfoverval; | ||
1348 | u16 phy_analogover; | ||
1349 | u16 phy_analogoverval; | ||
1350 | u16 phy_crs0; | ||
1351 | u16 phy_classctl; | ||
1352 | u16 phy_lo_mask; | ||
1353 | u16 phy_lo_ctl; | ||
1354 | u16 phy_syncctl; | ||
1355 | }; | ||
1356 | |||
1357 | u16 b43_radio_init2050(struct b43_wldev *dev) | ||
1358 | { | ||
1359 | struct b43_phy *phy = &dev->phy; | ||
1360 | struct init2050_saved_values sav; | ||
1361 | u16 rcc; | ||
1362 | u16 radio78; | ||
1363 | u16 ret; | ||
1364 | u16 i, j; | ||
1365 | u32 tmp1 = 0, tmp2 = 0; | ||
1366 | |||
1367 | memset(&sav, 0, sizeof(sav)); /* get rid of "may be used uninitialized..." */ | ||
1368 | |||
1369 | sav.radio_43 = b43_radio_read16(dev, 0x43); | ||
1370 | sav.radio_51 = b43_radio_read16(dev, 0x51); | ||
1371 | sav.radio_52 = b43_radio_read16(dev, 0x52); | ||
1372 | sav.phy_pgactl = b43_phy_read(dev, B43_PHY_PGACTL); | ||
1373 | sav.phy_cck_5A = b43_phy_read(dev, B43_PHY_CCK(0x5A)); | ||
1374 | sav.phy_cck_59 = b43_phy_read(dev, B43_PHY_CCK(0x59)); | ||
1375 | sav.phy_cck_58 = b43_phy_read(dev, B43_PHY_CCK(0x58)); | ||
1376 | |||
1377 | if (phy->type == B43_PHYTYPE_B) { | ||
1378 | sav.phy_cck_30 = b43_phy_read(dev, B43_PHY_CCK(0x30)); | ||
1379 | sav.reg_3EC = b43_read16(dev, 0x3EC); | ||
1380 | |||
1381 | b43_phy_write(dev, B43_PHY_CCK(0x30), 0xFF); | ||
1382 | b43_write16(dev, 0x3EC, 0x3F3F); | ||
1383 | } else if (phy->gmode || phy->rev >= 2) { | ||
1384 | sav.phy_rfover = b43_phy_read(dev, B43_PHY_RFOVER); | ||
1385 | sav.phy_rfoverval = b43_phy_read(dev, B43_PHY_RFOVERVAL); | ||
1386 | sav.phy_analogover = b43_phy_read(dev, B43_PHY_ANALOGOVER); | ||
1387 | sav.phy_analogoverval = | ||
1388 | b43_phy_read(dev, B43_PHY_ANALOGOVERVAL); | ||
1389 | sav.phy_crs0 = b43_phy_read(dev, B43_PHY_CRS0); | ||
1390 | sav.phy_classctl = b43_phy_read(dev, B43_PHY_CLASSCTL); | ||
1391 | |||
1392 | b43_phy_write(dev, B43_PHY_ANALOGOVER, | ||
1393 | b43_phy_read(dev, B43_PHY_ANALOGOVER) | ||
1394 | | 0x0003); | ||
1395 | b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, | ||
1396 | b43_phy_read(dev, B43_PHY_ANALOGOVERVAL) | ||
1397 | & 0xFFFC); | ||
1398 | b43_phy_write(dev, B43_PHY_CRS0, b43_phy_read(dev, B43_PHY_CRS0) | ||
1399 | & 0x7FFF); | ||
1400 | b43_phy_write(dev, B43_PHY_CLASSCTL, | ||
1401 | b43_phy_read(dev, B43_PHY_CLASSCTL) | ||
1402 | & 0xFFFC); | ||
1403 | if (has_loopback_gain(phy)) { | ||
1404 | sav.phy_lo_mask = b43_phy_read(dev, B43_PHY_LO_MASK); | ||
1405 | sav.phy_lo_ctl = b43_phy_read(dev, B43_PHY_LO_CTL); | ||
1406 | |||
1407 | if (phy->rev >= 3) | ||
1408 | b43_phy_write(dev, B43_PHY_LO_MASK, 0xC020); | ||
1409 | else | ||
1410 | b43_phy_write(dev, B43_PHY_LO_MASK, 0x8020); | ||
1411 | b43_phy_write(dev, B43_PHY_LO_CTL, 0); | ||
1412 | } | ||
1413 | |||
1414 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1415 | radio2050_rfover_val(dev, B43_PHY_RFOVERVAL, | ||
1416 | LPD(0, 1, 1))); | ||
1417 | b43_phy_write(dev, B43_PHY_RFOVER, | ||
1418 | radio2050_rfover_val(dev, B43_PHY_RFOVER, 0)); | ||
1419 | } | ||
1420 | b43_write16(dev, 0x3E2, b43_read16(dev, 0x3E2) | 0x8000); | ||
1421 | |||
1422 | sav.phy_syncctl = b43_phy_read(dev, B43_PHY_SYNCCTL); | ||
1423 | b43_phy_write(dev, B43_PHY_SYNCCTL, b43_phy_read(dev, B43_PHY_SYNCCTL) | ||
1424 | & 0xFF7F); | ||
1425 | sav.reg_3E6 = b43_read16(dev, 0x3E6); | ||
1426 | sav.reg_3F4 = b43_read16(dev, 0x3F4); | ||
1427 | |||
1428 | if (phy->analog == 0) { | ||
1429 | b43_write16(dev, 0x03E6, 0x0122); | ||
1430 | } else { | ||
1431 | if (phy->analog >= 2) { | ||
1432 | b43_phy_write(dev, B43_PHY_CCK(0x03), | ||
1433 | (b43_phy_read(dev, B43_PHY_CCK(0x03)) | ||
1434 | & 0xFFBF) | 0x40); | ||
1435 | } | ||
1436 | b43_write16(dev, B43_MMIO_CHANNEL_EXT, | ||
1437 | (b43_read16(dev, B43_MMIO_CHANNEL_EXT) | 0x2000)); | ||
1438 | } | ||
1439 | |||
1440 | rcc = b43_radio_core_calibration_value(dev); | ||
1441 | |||
1442 | if (phy->type == B43_PHYTYPE_B) | ||
1443 | b43_radio_write16(dev, 0x78, 0x26); | ||
1444 | if (phy->gmode || phy->rev >= 2) { | ||
1445 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1446 | radio2050_rfover_val(dev, B43_PHY_RFOVERVAL, | ||
1447 | LPD(0, 1, 1))); | ||
1448 | } | ||
1449 | b43_phy_write(dev, B43_PHY_PGACTL, 0xBFAF); | ||
1450 | b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x1403); | ||
1451 | if (phy->gmode || phy->rev >= 2) { | ||
1452 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1453 | radio2050_rfover_val(dev, B43_PHY_RFOVERVAL, | ||
1454 | LPD(0, 0, 1))); | ||
1455 | } | ||
1456 | b43_phy_write(dev, B43_PHY_PGACTL, 0xBFA0); | ||
1457 | b43_radio_write16(dev, 0x51, b43_radio_read16(dev, 0x51) | ||
1458 | | 0x0004); | ||
1459 | if (phy->radio_rev == 8) { | ||
1460 | b43_radio_write16(dev, 0x43, 0x1F); | ||
1461 | } else { | ||
1462 | b43_radio_write16(dev, 0x52, 0); | ||
1463 | b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43) | ||
1464 | & 0xFFF0) | 0x0009); | ||
1465 | } | ||
1466 | b43_phy_write(dev, B43_PHY_CCK(0x58), 0); | ||
1467 | |||
1468 | for (i = 0; i < 16; i++) { | ||
1469 | b43_phy_write(dev, B43_PHY_CCK(0x5A), 0x0480); | ||
1470 | b43_phy_write(dev, B43_PHY_CCK(0x59), 0xC810); | ||
1471 | b43_phy_write(dev, B43_PHY_CCK(0x58), 0x000D); | ||
1472 | if (phy->gmode || phy->rev >= 2) { | ||
1473 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1474 | radio2050_rfover_val(dev, | ||
1475 | B43_PHY_RFOVERVAL, | ||
1476 | LPD(1, 0, 1))); | ||
1477 | } | ||
1478 | b43_phy_write(dev, B43_PHY_PGACTL, 0xAFB0); | ||
1479 | udelay(10); | ||
1480 | if (phy->gmode || phy->rev >= 2) { | ||
1481 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1482 | radio2050_rfover_val(dev, | ||
1483 | B43_PHY_RFOVERVAL, | ||
1484 | LPD(1, 0, 1))); | ||
1485 | } | ||
1486 | b43_phy_write(dev, B43_PHY_PGACTL, 0xEFB0); | ||
1487 | udelay(10); | ||
1488 | if (phy->gmode || phy->rev >= 2) { | ||
1489 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1490 | radio2050_rfover_val(dev, | ||
1491 | B43_PHY_RFOVERVAL, | ||
1492 | LPD(1, 0, 0))); | ||
1493 | } | ||
1494 | b43_phy_write(dev, B43_PHY_PGACTL, 0xFFF0); | ||
1495 | udelay(20); | ||
1496 | tmp1 += b43_phy_read(dev, B43_PHY_LO_LEAKAGE); | ||
1497 | b43_phy_write(dev, B43_PHY_CCK(0x58), 0); | ||
1498 | if (phy->gmode || phy->rev >= 2) { | ||
1499 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1500 | radio2050_rfover_val(dev, | ||
1501 | B43_PHY_RFOVERVAL, | ||
1502 | LPD(1, 0, 1))); | ||
1503 | } | ||
1504 | b43_phy_write(dev, B43_PHY_PGACTL, 0xAFB0); | ||
1505 | } | ||
1506 | udelay(10); | ||
1507 | |||
1508 | b43_phy_write(dev, B43_PHY_CCK(0x58), 0); | ||
1509 | tmp1++; | ||
1510 | tmp1 >>= 9; | ||
1511 | |||
1512 | for (i = 0; i < 16; i++) { | ||
1513 | radio78 = (bitrev4(i) << 1) | 0x0020; | ||
1514 | b43_radio_write16(dev, 0x78, radio78); | ||
1515 | udelay(10); | ||
1516 | for (j = 0; j < 16; j++) { | ||
1517 | b43_phy_write(dev, B43_PHY_CCK(0x5A), 0x0D80); | ||
1518 | b43_phy_write(dev, B43_PHY_CCK(0x59), 0xC810); | ||
1519 | b43_phy_write(dev, B43_PHY_CCK(0x58), 0x000D); | ||
1520 | if (phy->gmode || phy->rev >= 2) { | ||
1521 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1522 | radio2050_rfover_val(dev, | ||
1523 | B43_PHY_RFOVERVAL, | ||
1524 | LPD(1, 0, | ||
1525 | 1))); | ||
1526 | } | ||
1527 | b43_phy_write(dev, B43_PHY_PGACTL, 0xAFB0); | ||
1528 | udelay(10); | ||
1529 | if (phy->gmode || phy->rev >= 2) { | ||
1530 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1531 | radio2050_rfover_val(dev, | ||
1532 | B43_PHY_RFOVERVAL, | ||
1533 | LPD(1, 0, | ||
1534 | 1))); | ||
1535 | } | ||
1536 | b43_phy_write(dev, B43_PHY_PGACTL, 0xEFB0); | ||
1537 | udelay(10); | ||
1538 | if (phy->gmode || phy->rev >= 2) { | ||
1539 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1540 | radio2050_rfover_val(dev, | ||
1541 | B43_PHY_RFOVERVAL, | ||
1542 | LPD(1, 0, | ||
1543 | 0))); | ||
1544 | } | ||
1545 | b43_phy_write(dev, B43_PHY_PGACTL, 0xFFF0); | ||
1546 | udelay(10); | ||
1547 | tmp2 += b43_phy_read(dev, B43_PHY_LO_LEAKAGE); | ||
1548 | b43_phy_write(dev, B43_PHY_CCK(0x58), 0); | ||
1549 | if (phy->gmode || phy->rev >= 2) { | ||
1550 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1551 | radio2050_rfover_val(dev, | ||
1552 | B43_PHY_RFOVERVAL, | ||
1553 | LPD(1, 0, | ||
1554 | 1))); | ||
1555 | } | ||
1556 | b43_phy_write(dev, B43_PHY_PGACTL, 0xAFB0); | ||
1557 | } | ||
1558 | tmp2++; | ||
1559 | tmp2 >>= 8; | ||
1560 | if (tmp1 < tmp2) | ||
1561 | break; | ||
1562 | } | ||
1563 | |||
1564 | /* Restore the registers */ | ||
1565 | b43_phy_write(dev, B43_PHY_PGACTL, sav.phy_pgactl); | ||
1566 | b43_radio_write16(dev, 0x51, sav.radio_51); | ||
1567 | b43_radio_write16(dev, 0x52, sav.radio_52); | ||
1568 | b43_radio_write16(dev, 0x43, sav.radio_43); | ||
1569 | b43_phy_write(dev, B43_PHY_CCK(0x5A), sav.phy_cck_5A); | ||
1570 | b43_phy_write(dev, B43_PHY_CCK(0x59), sav.phy_cck_59); | ||
1571 | b43_phy_write(dev, B43_PHY_CCK(0x58), sav.phy_cck_58); | ||
1572 | b43_write16(dev, 0x3E6, sav.reg_3E6); | ||
1573 | if (phy->analog != 0) | ||
1574 | b43_write16(dev, 0x3F4, sav.reg_3F4); | ||
1575 | b43_phy_write(dev, B43_PHY_SYNCCTL, sav.phy_syncctl); | ||
1576 | b43_synth_pu_workaround(dev, phy->channel); | ||
1577 | if (phy->type == B43_PHYTYPE_B) { | ||
1578 | b43_phy_write(dev, B43_PHY_CCK(0x30), sav.phy_cck_30); | ||
1579 | b43_write16(dev, 0x3EC, sav.reg_3EC); | ||
1580 | } else if (phy->gmode) { | ||
1581 | b43_write16(dev, B43_MMIO_PHY_RADIO, | ||
1582 | b43_read16(dev, B43_MMIO_PHY_RADIO) | ||
1583 | & 0x7FFF); | ||
1584 | b43_phy_write(dev, B43_PHY_RFOVER, sav.phy_rfover); | ||
1585 | b43_phy_write(dev, B43_PHY_RFOVERVAL, sav.phy_rfoverval); | ||
1586 | b43_phy_write(dev, B43_PHY_ANALOGOVER, sav.phy_analogover); | ||
1587 | b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, | ||
1588 | sav.phy_analogoverval); | ||
1589 | b43_phy_write(dev, B43_PHY_CRS0, sav.phy_crs0); | ||
1590 | b43_phy_write(dev, B43_PHY_CLASSCTL, sav.phy_classctl); | ||
1591 | if (has_loopback_gain(phy)) { | ||
1592 | b43_phy_write(dev, B43_PHY_LO_MASK, sav.phy_lo_mask); | ||
1593 | b43_phy_write(dev, B43_PHY_LO_CTL, sav.phy_lo_ctl); | ||
1594 | } | ||
1595 | } | ||
1596 | if (i > 15) | ||
1597 | ret = radio78; | ||
1598 | else | ||
1599 | ret = rcc; | ||
1600 | |||
1601 | return ret; | ||
1602 | } | ||
1603 | |||
1604 | static void b43_phy_initb5(struct b43_wldev *dev) | ||
1605 | { | ||
1606 | struct ssb_bus *bus = dev->dev->bus; | ||
1607 | struct b43_phy *phy = &dev->phy; | ||
1608 | struct b43_phy_g *gphy = phy->g; | ||
1609 | u16 offset, value; | ||
1610 | u8 old_channel; | ||
1611 | |||
1612 | if (phy->analog == 1) { | ||
1613 | b43_radio_write16(dev, 0x007A, b43_radio_read16(dev, 0x007A) | ||
1614 | | 0x0050); | ||
1615 | } | ||
1616 | if ((bus->boardinfo.vendor != SSB_BOARDVENDOR_BCM) && | ||
1617 | (bus->boardinfo.type != SSB_BOARD_BU4306)) { | ||
1618 | value = 0x2120; | ||
1619 | for (offset = 0x00A8; offset < 0x00C7; offset++) { | ||
1620 | b43_phy_write(dev, offset, value); | ||
1621 | value += 0x202; | ||
1622 | } | ||
1623 | } | ||
1624 | b43_phy_write(dev, 0x0035, (b43_phy_read(dev, 0x0035) & 0xF0FF) | ||
1625 | | 0x0700); | ||
1626 | if (phy->radio_ver == 0x2050) | ||
1627 | b43_phy_write(dev, 0x0038, 0x0667); | ||
1628 | |||
1629 | if (phy->gmode || phy->rev >= 2) { | ||
1630 | if (phy->radio_ver == 0x2050) { | ||
1631 | b43_radio_write16(dev, 0x007A, | ||
1632 | b43_radio_read16(dev, 0x007A) | ||
1633 | | 0x0020); | ||
1634 | b43_radio_write16(dev, 0x0051, | ||
1635 | b43_radio_read16(dev, 0x0051) | ||
1636 | | 0x0004); | ||
1637 | } | ||
1638 | b43_write16(dev, B43_MMIO_PHY_RADIO, 0x0000); | ||
1639 | |||
1640 | b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) | 0x0100); | ||
1641 | b43_phy_write(dev, 0x042B, b43_phy_read(dev, 0x042B) | 0x2000); | ||
1642 | |||
1643 | b43_phy_write(dev, 0x001C, 0x186A); | ||
1644 | |||
1645 | b43_phy_write(dev, 0x0013, | ||
1646 | (b43_phy_read(dev, 0x0013) & 0x00FF) | 0x1900); | ||
1647 | b43_phy_write(dev, 0x0035, | ||
1648 | (b43_phy_read(dev, 0x0035) & 0xFFC0) | 0x0064); | ||
1649 | b43_phy_write(dev, 0x005D, | ||
1650 | (b43_phy_read(dev, 0x005D) & 0xFF80) | 0x000A); | ||
1651 | } | ||
1652 | |||
1653 | if (dev->bad_frames_preempt) { | ||
1654 | b43_phy_write(dev, B43_PHY_RADIO_BITFIELD, | ||
1655 | b43_phy_read(dev, | ||
1656 | B43_PHY_RADIO_BITFIELD) | (1 << 11)); | ||
1657 | } | ||
1658 | |||
1659 | if (phy->analog == 1) { | ||
1660 | b43_phy_write(dev, 0x0026, 0xCE00); | ||
1661 | b43_phy_write(dev, 0x0021, 0x3763); | ||
1662 | b43_phy_write(dev, 0x0022, 0x1BC3); | ||
1663 | b43_phy_write(dev, 0x0023, 0x06F9); | ||
1664 | b43_phy_write(dev, 0x0024, 0x037E); | ||
1665 | } else | ||
1666 | b43_phy_write(dev, 0x0026, 0xCC00); | ||
1667 | b43_phy_write(dev, 0x0030, 0x00C6); | ||
1668 | b43_write16(dev, 0x03EC, 0x3F22); | ||
1669 | |||
1670 | if (phy->analog == 1) | ||
1671 | b43_phy_write(dev, 0x0020, 0x3E1C); | ||
1672 | else | ||
1673 | b43_phy_write(dev, 0x0020, 0x301C); | ||
1674 | |||
1675 | if (phy->analog == 0) | ||
1676 | b43_write16(dev, 0x03E4, 0x3000); | ||
1677 | |||
1678 | old_channel = phy->channel; | ||
1679 | /* Force to channel 7, even if not supported. */ | ||
1680 | b43_gphy_channel_switch(dev, 7, 0); | ||
1681 | |||
1682 | if (phy->radio_ver != 0x2050) { | ||
1683 | b43_radio_write16(dev, 0x0075, 0x0080); | ||
1684 | b43_radio_write16(dev, 0x0079, 0x0081); | ||
1685 | } | ||
1686 | |||
1687 | b43_radio_write16(dev, 0x0050, 0x0020); | ||
1688 | b43_radio_write16(dev, 0x0050, 0x0023); | ||
1689 | |||
1690 | if (phy->radio_ver == 0x2050) { | ||
1691 | b43_radio_write16(dev, 0x0050, 0x0020); | ||
1692 | b43_radio_write16(dev, 0x005A, 0x0070); | ||
1693 | } | ||
1694 | |||
1695 | b43_radio_write16(dev, 0x005B, 0x007B); | ||
1696 | b43_radio_write16(dev, 0x005C, 0x00B0); | ||
1697 | |||
1698 | b43_radio_write16(dev, 0x007A, b43_radio_read16(dev, 0x007A) | 0x0007); | ||
1699 | |||
1700 | b43_gphy_channel_switch(dev, old_channel, 0); | ||
1701 | |||
1702 | b43_phy_write(dev, 0x0014, 0x0080); | ||
1703 | b43_phy_write(dev, 0x0032, 0x00CA); | ||
1704 | b43_phy_write(dev, 0x002A, 0x88A3); | ||
1705 | |||
1706 | b43_set_txpower_g(dev, &gphy->bbatt, &gphy->rfatt, gphy->tx_control); | ||
1707 | |||
1708 | if (phy->radio_ver == 0x2050) | ||
1709 | b43_radio_write16(dev, 0x005D, 0x000D); | ||
1710 | |||
1711 | b43_write16(dev, 0x03E4, (b43_read16(dev, 0x03E4) & 0xFFC0) | 0x0004); | ||
1712 | } | ||
1713 | |||
1714 | static void b43_phy_initb6(struct b43_wldev *dev) | ||
1715 | { | ||
1716 | struct b43_phy *phy = &dev->phy; | ||
1717 | struct b43_phy_g *gphy = phy->g; | ||
1718 | u16 offset, val; | ||
1719 | u8 old_channel; | ||
1720 | |||
1721 | b43_phy_write(dev, 0x003E, 0x817A); | ||
1722 | b43_radio_write16(dev, 0x007A, | ||
1723 | (b43_radio_read16(dev, 0x007A) | 0x0058)); | ||
1724 | if (phy->radio_rev == 4 || phy->radio_rev == 5) { | ||
1725 | b43_radio_write16(dev, 0x51, 0x37); | ||
1726 | b43_radio_write16(dev, 0x52, 0x70); | ||
1727 | b43_radio_write16(dev, 0x53, 0xB3); | ||
1728 | b43_radio_write16(dev, 0x54, 0x9B); | ||
1729 | b43_radio_write16(dev, 0x5A, 0x88); | ||
1730 | b43_radio_write16(dev, 0x5B, 0x88); | ||
1731 | b43_radio_write16(dev, 0x5D, 0x88); | ||
1732 | b43_radio_write16(dev, 0x5E, 0x88); | ||
1733 | b43_radio_write16(dev, 0x7D, 0x88); | ||
1734 | b43_hf_write(dev, b43_hf_read(dev) | ||
1735 | | B43_HF_TSSIRPSMW); | ||
1736 | } | ||
1737 | B43_WARN_ON(phy->radio_rev == 6 || phy->radio_rev == 7); /* We had code for these revs here... */ | ||
1738 | if (phy->radio_rev == 8) { | ||
1739 | b43_radio_write16(dev, 0x51, 0); | ||
1740 | b43_radio_write16(dev, 0x52, 0x40); | ||
1741 | b43_radio_write16(dev, 0x53, 0xB7); | ||
1742 | b43_radio_write16(dev, 0x54, 0x98); | ||
1743 | b43_radio_write16(dev, 0x5A, 0x88); | ||
1744 | b43_radio_write16(dev, 0x5B, 0x6B); | ||
1745 | b43_radio_write16(dev, 0x5C, 0x0F); | ||
1746 | if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_ALTIQ) { | ||
1747 | b43_radio_write16(dev, 0x5D, 0xFA); | ||
1748 | b43_radio_write16(dev, 0x5E, 0xD8); | ||
1749 | } else { | ||
1750 | b43_radio_write16(dev, 0x5D, 0xF5); | ||
1751 | b43_radio_write16(dev, 0x5E, 0xB8); | ||
1752 | } | ||
1753 | b43_radio_write16(dev, 0x0073, 0x0003); | ||
1754 | b43_radio_write16(dev, 0x007D, 0x00A8); | ||
1755 | b43_radio_write16(dev, 0x007C, 0x0001); | ||
1756 | b43_radio_write16(dev, 0x007E, 0x0008); | ||
1757 | } | ||
1758 | val = 0x1E1F; | ||
1759 | for (offset = 0x0088; offset < 0x0098; offset++) { | ||
1760 | b43_phy_write(dev, offset, val); | ||
1761 | val -= 0x0202; | ||
1762 | } | ||
1763 | val = 0x3E3F; | ||
1764 | for (offset = 0x0098; offset < 0x00A8; offset++) { | ||
1765 | b43_phy_write(dev, offset, val); | ||
1766 | val -= 0x0202; | ||
1767 | } | ||
1768 | val = 0x2120; | ||
1769 | for (offset = 0x00A8; offset < 0x00C8; offset++) { | ||
1770 | b43_phy_write(dev, offset, (val & 0x3F3F)); | ||
1771 | val += 0x0202; | ||
1772 | } | ||
1773 | if (phy->type == B43_PHYTYPE_G) { | ||
1774 | b43_radio_write16(dev, 0x007A, | ||
1775 | b43_radio_read16(dev, 0x007A) | 0x0020); | ||
1776 | b43_radio_write16(dev, 0x0051, | ||
1777 | b43_radio_read16(dev, 0x0051) | 0x0004); | ||
1778 | b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) | 0x0100); | ||
1779 | b43_phy_write(dev, 0x042B, b43_phy_read(dev, 0x042B) | 0x2000); | ||
1780 | b43_phy_write(dev, 0x5B, 0); | ||
1781 | b43_phy_write(dev, 0x5C, 0); | ||
1782 | } | ||
1783 | |||
1784 | old_channel = phy->channel; | ||
1785 | if (old_channel >= 8) | ||
1786 | b43_gphy_channel_switch(dev, 1, 0); | ||
1787 | else | ||
1788 | b43_gphy_channel_switch(dev, 13, 0); | ||
1789 | |||
1790 | b43_radio_write16(dev, 0x0050, 0x0020); | ||
1791 | b43_radio_write16(dev, 0x0050, 0x0023); | ||
1792 | udelay(40); | ||
1793 | if (phy->radio_rev < 6 || phy->radio_rev == 8) { | ||
1794 | b43_radio_write16(dev, 0x7C, (b43_radio_read16(dev, 0x7C) | ||
1795 | | 0x0002)); | ||
1796 | b43_radio_write16(dev, 0x50, 0x20); | ||
1797 | } | ||
1798 | if (phy->radio_rev <= 2) { | ||
1799 | b43_radio_write16(dev, 0x7C, 0x20); | ||
1800 | b43_radio_write16(dev, 0x5A, 0x70); | ||
1801 | b43_radio_write16(dev, 0x5B, 0x7B); | ||
1802 | b43_radio_write16(dev, 0x5C, 0xB0); | ||
1803 | } | ||
1804 | b43_radio_write16(dev, 0x007A, | ||
1805 | (b43_radio_read16(dev, 0x007A) & 0x00F8) | 0x0007); | ||
1806 | |||
1807 | b43_gphy_channel_switch(dev, old_channel, 0); | ||
1808 | |||
1809 | b43_phy_write(dev, 0x0014, 0x0200); | ||
1810 | if (phy->radio_rev >= 6) | ||
1811 | b43_phy_write(dev, 0x2A, 0x88C2); | ||
1812 | else | ||
1813 | b43_phy_write(dev, 0x2A, 0x8AC0); | ||
1814 | b43_phy_write(dev, 0x0038, 0x0668); | ||
1815 | b43_set_txpower_g(dev, &gphy->bbatt, &gphy->rfatt, gphy->tx_control); | ||
1816 | if (phy->radio_rev <= 5) { | ||
1817 | b43_phy_write(dev, 0x5D, (b43_phy_read(dev, 0x5D) | ||
1818 | & 0xFF80) | 0x0003); | ||
1819 | } | ||
1820 | if (phy->radio_rev <= 2) | ||
1821 | b43_radio_write16(dev, 0x005D, 0x000D); | ||
1822 | |||
1823 | if (phy->analog == 4) { | ||
1824 | b43_write16(dev, 0x3E4, 9); | ||
1825 | b43_phy_write(dev, 0x61, b43_phy_read(dev, 0x61) | ||
1826 | & 0x0FFF); | ||
1827 | } else { | ||
1828 | b43_phy_write(dev, 0x0002, (b43_phy_read(dev, 0x0002) & 0xFFC0) | ||
1829 | | 0x0004); | ||
1830 | } | ||
1831 | if (phy->type == B43_PHYTYPE_B) | ||
1832 | B43_WARN_ON(1); | ||
1833 | else if (phy->type == B43_PHYTYPE_G) | ||
1834 | b43_write16(dev, 0x03E6, 0x0); | ||
1835 | } | ||
1836 | |||
1837 | static void b43_calc_loopback_gain(struct b43_wldev *dev) | ||
1838 | { | ||
1839 | struct b43_phy *phy = &dev->phy; | ||
1840 | struct b43_phy_g *gphy = phy->g; | ||
1841 | u16 backup_phy[16] = { 0 }; | ||
1842 | u16 backup_radio[3]; | ||
1843 | u16 backup_bband; | ||
1844 | u16 i, j, loop_i_max; | ||
1845 | u16 trsw_rx; | ||
1846 | u16 loop1_outer_done, loop1_inner_done; | ||
1847 | |||
1848 | backup_phy[0] = b43_phy_read(dev, B43_PHY_CRS0); | ||
1849 | backup_phy[1] = b43_phy_read(dev, B43_PHY_CCKBBANDCFG); | ||
1850 | backup_phy[2] = b43_phy_read(dev, B43_PHY_RFOVER); | ||
1851 | backup_phy[3] = b43_phy_read(dev, B43_PHY_RFOVERVAL); | ||
1852 | if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */ | ||
1853 | backup_phy[4] = b43_phy_read(dev, B43_PHY_ANALOGOVER); | ||
1854 | backup_phy[5] = b43_phy_read(dev, B43_PHY_ANALOGOVERVAL); | ||
1855 | } | ||
1856 | backup_phy[6] = b43_phy_read(dev, B43_PHY_CCK(0x5A)); | ||
1857 | backup_phy[7] = b43_phy_read(dev, B43_PHY_CCK(0x59)); | ||
1858 | backup_phy[8] = b43_phy_read(dev, B43_PHY_CCK(0x58)); | ||
1859 | backup_phy[9] = b43_phy_read(dev, B43_PHY_CCK(0x0A)); | ||
1860 | backup_phy[10] = b43_phy_read(dev, B43_PHY_CCK(0x03)); | ||
1861 | backup_phy[11] = b43_phy_read(dev, B43_PHY_LO_MASK); | ||
1862 | backup_phy[12] = b43_phy_read(dev, B43_PHY_LO_CTL); | ||
1863 | backup_phy[13] = b43_phy_read(dev, B43_PHY_CCK(0x2B)); | ||
1864 | backup_phy[14] = b43_phy_read(dev, B43_PHY_PGACTL); | ||
1865 | backup_phy[15] = b43_phy_read(dev, B43_PHY_LO_LEAKAGE); | ||
1866 | backup_bband = gphy->bbatt.att; | ||
1867 | backup_radio[0] = b43_radio_read16(dev, 0x52); | ||
1868 | backup_radio[1] = b43_radio_read16(dev, 0x43); | ||
1869 | backup_radio[2] = b43_radio_read16(dev, 0x7A); | ||
1870 | |||
1871 | b43_phy_write(dev, B43_PHY_CRS0, | ||
1872 | b43_phy_read(dev, B43_PHY_CRS0) & 0x3FFF); | ||
1873 | b43_phy_write(dev, B43_PHY_CCKBBANDCFG, | ||
1874 | b43_phy_read(dev, B43_PHY_CCKBBANDCFG) | 0x8000); | ||
1875 | b43_phy_write(dev, B43_PHY_RFOVER, | ||
1876 | b43_phy_read(dev, B43_PHY_RFOVER) | 0x0002); | ||
1877 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1878 | b43_phy_read(dev, B43_PHY_RFOVERVAL) & 0xFFFD); | ||
1879 | b43_phy_write(dev, B43_PHY_RFOVER, | ||
1880 | b43_phy_read(dev, B43_PHY_RFOVER) | 0x0001); | ||
1881 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1882 | b43_phy_read(dev, B43_PHY_RFOVERVAL) & 0xFFFE); | ||
1883 | if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */ | ||
1884 | b43_phy_write(dev, B43_PHY_ANALOGOVER, | ||
1885 | b43_phy_read(dev, B43_PHY_ANALOGOVER) | 0x0001); | ||
1886 | b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, | ||
1887 | b43_phy_read(dev, | ||
1888 | B43_PHY_ANALOGOVERVAL) & 0xFFFE); | ||
1889 | b43_phy_write(dev, B43_PHY_ANALOGOVER, | ||
1890 | b43_phy_read(dev, B43_PHY_ANALOGOVER) | 0x0002); | ||
1891 | b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, | ||
1892 | b43_phy_read(dev, | ||
1893 | B43_PHY_ANALOGOVERVAL) & 0xFFFD); | ||
1894 | } | ||
1895 | b43_phy_write(dev, B43_PHY_RFOVER, | ||
1896 | b43_phy_read(dev, B43_PHY_RFOVER) | 0x000C); | ||
1897 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1898 | b43_phy_read(dev, B43_PHY_RFOVERVAL) | 0x000C); | ||
1899 | b43_phy_write(dev, B43_PHY_RFOVER, | ||
1900 | b43_phy_read(dev, B43_PHY_RFOVER) | 0x0030); | ||
1901 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1902 | (b43_phy_read(dev, B43_PHY_RFOVERVAL) | ||
1903 | & 0xFFCF) | 0x10); | ||
1904 | |||
1905 | b43_phy_write(dev, B43_PHY_CCK(0x5A), 0x0780); | ||
1906 | b43_phy_write(dev, B43_PHY_CCK(0x59), 0xC810); | ||
1907 | b43_phy_write(dev, B43_PHY_CCK(0x58), 0x000D); | ||
1908 | |||
1909 | b43_phy_write(dev, B43_PHY_CCK(0x0A), | ||
1910 | b43_phy_read(dev, B43_PHY_CCK(0x0A)) | 0x2000); | ||
1911 | if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */ | ||
1912 | b43_phy_write(dev, B43_PHY_ANALOGOVER, | ||
1913 | b43_phy_read(dev, B43_PHY_ANALOGOVER) | 0x0004); | ||
1914 | b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, | ||
1915 | b43_phy_read(dev, | ||
1916 | B43_PHY_ANALOGOVERVAL) & 0xFFFB); | ||
1917 | } | ||
1918 | b43_phy_write(dev, B43_PHY_CCK(0x03), | ||
1919 | (b43_phy_read(dev, B43_PHY_CCK(0x03)) | ||
1920 | & 0xFF9F) | 0x40); | ||
1921 | |||
1922 | if (phy->radio_rev == 8) { | ||
1923 | b43_radio_write16(dev, 0x43, 0x000F); | ||
1924 | } else { | ||
1925 | b43_radio_write16(dev, 0x52, 0); | ||
1926 | b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43) | ||
1927 | & 0xFFF0) | 0x9); | ||
1928 | } | ||
1929 | b43_gphy_set_baseband_attenuation(dev, 11); | ||
1930 | |||
1931 | if (phy->rev >= 3) | ||
1932 | b43_phy_write(dev, B43_PHY_LO_MASK, 0xC020); | ||
1933 | else | ||
1934 | b43_phy_write(dev, B43_PHY_LO_MASK, 0x8020); | ||
1935 | b43_phy_write(dev, B43_PHY_LO_CTL, 0); | ||
1936 | |||
1937 | b43_phy_write(dev, B43_PHY_CCK(0x2B), | ||
1938 | (b43_phy_read(dev, B43_PHY_CCK(0x2B)) | ||
1939 | & 0xFFC0) | 0x01); | ||
1940 | b43_phy_write(dev, B43_PHY_CCK(0x2B), | ||
1941 | (b43_phy_read(dev, B43_PHY_CCK(0x2B)) | ||
1942 | & 0xC0FF) | 0x800); | ||
1943 | |||
1944 | b43_phy_write(dev, B43_PHY_RFOVER, | ||
1945 | b43_phy_read(dev, B43_PHY_RFOVER) | 0x0100); | ||
1946 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1947 | b43_phy_read(dev, B43_PHY_RFOVERVAL) & 0xCFFF); | ||
1948 | |||
1949 | if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) { | ||
1950 | if (phy->rev >= 7) { | ||
1951 | b43_phy_write(dev, B43_PHY_RFOVER, | ||
1952 | b43_phy_read(dev, B43_PHY_RFOVER) | ||
1953 | | 0x0800); | ||
1954 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1955 | b43_phy_read(dev, B43_PHY_RFOVERVAL) | ||
1956 | | 0x8000); | ||
1957 | } | ||
1958 | } | ||
1959 | b43_radio_write16(dev, 0x7A, b43_radio_read16(dev, 0x7A) | ||
1960 | & 0x00F7); | ||
1961 | |||
1962 | j = 0; | ||
1963 | loop_i_max = (phy->radio_rev == 8) ? 15 : 9; | ||
1964 | for (i = 0; i < loop_i_max; i++) { | ||
1965 | for (j = 0; j < 16; j++) { | ||
1966 | b43_radio_write16(dev, 0x43, i); | ||
1967 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1968 | (b43_phy_read(dev, B43_PHY_RFOVERVAL) | ||
1969 | & 0xF0FF) | (j << 8)); | ||
1970 | b43_phy_write(dev, B43_PHY_PGACTL, | ||
1971 | (b43_phy_read(dev, B43_PHY_PGACTL) | ||
1972 | & 0x0FFF) | 0xA000); | ||
1973 | b43_phy_write(dev, B43_PHY_PGACTL, | ||
1974 | b43_phy_read(dev, B43_PHY_PGACTL) | ||
1975 | | 0xF000); | ||
1976 | udelay(20); | ||
1977 | if (b43_phy_read(dev, B43_PHY_LO_LEAKAGE) >= 0xDFC) | ||
1978 | goto exit_loop1; | ||
1979 | } | ||
1980 | } | ||
1981 | exit_loop1: | ||
1982 | loop1_outer_done = i; | ||
1983 | loop1_inner_done = j; | ||
1984 | if (j >= 8) { | ||
1985 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1986 | b43_phy_read(dev, B43_PHY_RFOVERVAL) | ||
1987 | | 0x30); | ||
1988 | trsw_rx = 0x1B; | ||
1989 | for (j = j - 8; j < 16; j++) { | ||
1990 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
1991 | (b43_phy_read(dev, B43_PHY_RFOVERVAL) | ||
1992 | & 0xF0FF) | (j << 8)); | ||
1993 | b43_phy_write(dev, B43_PHY_PGACTL, | ||
1994 | (b43_phy_read(dev, B43_PHY_PGACTL) | ||
1995 | & 0x0FFF) | 0xA000); | ||
1996 | b43_phy_write(dev, B43_PHY_PGACTL, | ||
1997 | b43_phy_read(dev, B43_PHY_PGACTL) | ||
1998 | | 0xF000); | ||
1999 | udelay(20); | ||
2000 | trsw_rx -= 3; | ||
2001 | if (b43_phy_read(dev, B43_PHY_LO_LEAKAGE) >= 0xDFC) | ||
2002 | goto exit_loop2; | ||
2003 | } | ||
2004 | } else | ||
2005 | trsw_rx = 0x18; | ||
2006 | exit_loop2: | ||
2007 | |||
2008 | if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */ | ||
2009 | b43_phy_write(dev, B43_PHY_ANALOGOVER, backup_phy[4]); | ||
2010 | b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, backup_phy[5]); | ||
2011 | } | ||
2012 | b43_phy_write(dev, B43_PHY_CCK(0x5A), backup_phy[6]); | ||
2013 | b43_phy_write(dev, B43_PHY_CCK(0x59), backup_phy[7]); | ||
2014 | b43_phy_write(dev, B43_PHY_CCK(0x58), backup_phy[8]); | ||
2015 | b43_phy_write(dev, B43_PHY_CCK(0x0A), backup_phy[9]); | ||
2016 | b43_phy_write(dev, B43_PHY_CCK(0x03), backup_phy[10]); | ||
2017 | b43_phy_write(dev, B43_PHY_LO_MASK, backup_phy[11]); | ||
2018 | b43_phy_write(dev, B43_PHY_LO_CTL, backup_phy[12]); | ||
2019 | b43_phy_write(dev, B43_PHY_CCK(0x2B), backup_phy[13]); | ||
2020 | b43_phy_write(dev, B43_PHY_PGACTL, backup_phy[14]); | ||
2021 | |||
2022 | b43_gphy_set_baseband_attenuation(dev, backup_bband); | ||
2023 | |||
2024 | b43_radio_write16(dev, 0x52, backup_radio[0]); | ||
2025 | b43_radio_write16(dev, 0x43, backup_radio[1]); | ||
2026 | b43_radio_write16(dev, 0x7A, backup_radio[2]); | ||
2027 | |||
2028 | b43_phy_write(dev, B43_PHY_RFOVER, backup_phy[2] | 0x0003); | ||
2029 | udelay(10); | ||
2030 | b43_phy_write(dev, B43_PHY_RFOVER, backup_phy[2]); | ||
2031 | b43_phy_write(dev, B43_PHY_RFOVERVAL, backup_phy[3]); | ||
2032 | b43_phy_write(dev, B43_PHY_CRS0, backup_phy[0]); | ||
2033 | b43_phy_write(dev, B43_PHY_CCKBBANDCFG, backup_phy[1]); | ||
2034 | |||
2035 | gphy->max_lb_gain = | ||
2036 | ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11; | ||
2037 | gphy->trsw_rx_gain = trsw_rx * 2; | ||
2038 | } | ||
2039 | |||
2040 | static void b43_hardware_pctl_early_init(struct b43_wldev *dev) | ||
2041 | { | ||
2042 | struct b43_phy *phy = &dev->phy; | ||
2043 | |||
2044 | if (!b43_has_hardware_pctl(dev)) { | ||
2045 | b43_phy_write(dev, 0x047A, 0xC111); | ||
2046 | return; | ||
2047 | } | ||
2048 | |||
2049 | b43_phy_write(dev, 0x0036, b43_phy_read(dev, 0x0036) & 0xFEFF); | ||
2050 | b43_phy_write(dev, 0x002F, 0x0202); | ||
2051 | b43_phy_write(dev, 0x047C, b43_phy_read(dev, 0x047C) | 0x0002); | ||
2052 | b43_phy_write(dev, 0x047A, b43_phy_read(dev, 0x047A) | 0xF000); | ||
2053 | if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) { | ||
2054 | b43_phy_write(dev, 0x047A, (b43_phy_read(dev, 0x047A) | ||
2055 | & 0xFF0F) | 0x0010); | ||
2056 | b43_phy_write(dev, 0x005D, b43_phy_read(dev, 0x005D) | ||
2057 | | 0x8000); | ||
2058 | b43_phy_write(dev, 0x004E, (b43_phy_read(dev, 0x004E) | ||
2059 | & 0xFFC0) | 0x0010); | ||
2060 | b43_phy_write(dev, 0x002E, 0xC07F); | ||
2061 | b43_phy_write(dev, 0x0036, b43_phy_read(dev, 0x0036) | ||
2062 | | 0x0400); | ||
2063 | } else { | ||
2064 | b43_phy_write(dev, 0x0036, b43_phy_read(dev, 0x0036) | ||
2065 | | 0x0200); | ||
2066 | b43_phy_write(dev, 0x0036, b43_phy_read(dev, 0x0036) | ||
2067 | | 0x0400); | ||
2068 | b43_phy_write(dev, 0x005D, b43_phy_read(dev, 0x005D) | ||
2069 | & 0x7FFF); | ||
2070 | b43_phy_write(dev, 0x004F, b43_phy_read(dev, 0x004F) | ||
2071 | & 0xFFFE); | ||
2072 | b43_phy_write(dev, 0x004E, (b43_phy_read(dev, 0x004E) | ||
2073 | & 0xFFC0) | 0x0010); | ||
2074 | b43_phy_write(dev, 0x002E, 0xC07F); | ||
2075 | b43_phy_write(dev, 0x047A, (b43_phy_read(dev, 0x047A) | ||
2076 | & 0xFF0F) | 0x0010); | ||
2077 | } | ||
2078 | } | ||
2079 | |||
2080 | /* Hardware power control for G-PHY */ | ||
2081 | static void b43_hardware_pctl_init_gphy(struct b43_wldev *dev) | ||
2082 | { | ||
2083 | struct b43_phy *phy = &dev->phy; | ||
2084 | struct b43_phy_g *gphy = phy->g; | ||
2085 | |||
2086 | if (!b43_has_hardware_pctl(dev)) { | ||
2087 | /* No hardware power control */ | ||
2088 | b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_HWPCTL); | ||
2089 | return; | ||
2090 | } | ||
2091 | |||
2092 | b43_phy_write(dev, 0x0036, (b43_phy_read(dev, 0x0036) & 0xFFC0) | ||
2093 | | (gphy->tgt_idle_tssi - gphy->cur_idle_tssi)); | ||
2094 | b43_phy_write(dev, 0x0478, (b43_phy_read(dev, 0x0478) & 0xFF00) | ||
2095 | | (gphy->tgt_idle_tssi - gphy->cur_idle_tssi)); | ||
2096 | b43_gphy_tssi_power_lt_init(dev); | ||
2097 | b43_gphy_gain_lt_init(dev); | ||
2098 | b43_phy_write(dev, 0x0060, b43_phy_read(dev, 0x0060) & 0xFFBF); | ||
2099 | b43_phy_write(dev, 0x0014, 0x0000); | ||
2100 | |||
2101 | B43_WARN_ON(phy->rev < 6); | ||
2102 | b43_phy_write(dev, 0x0478, b43_phy_read(dev, 0x0478) | ||
2103 | | 0x0800); | ||
2104 | b43_phy_write(dev, 0x0478, b43_phy_read(dev, 0x0478) | ||
2105 | & 0xFEFF); | ||
2106 | b43_phy_write(dev, 0x0801, b43_phy_read(dev, 0x0801) | ||
2107 | & 0xFFBF); | ||
2108 | |||
2109 | b43_gphy_dc_lt_init(dev, 1); | ||
2110 | |||
2111 | /* Enable hardware pctl in firmware. */ | ||
2112 | b43_hf_write(dev, b43_hf_read(dev) | B43_HF_HWPCTL); | ||
2113 | } | ||
2114 | |||
2115 | /* Intialize B/G PHY power control */ | ||
2116 | static void b43_phy_init_pctl(struct b43_wldev *dev) | ||
2117 | { | ||
2118 | struct ssb_bus *bus = dev->dev->bus; | ||
2119 | struct b43_phy *phy = &dev->phy; | ||
2120 | struct b43_phy_g *gphy = phy->g; | ||
2121 | struct b43_rfatt old_rfatt; | ||
2122 | struct b43_bbatt old_bbatt; | ||
2123 | u8 old_tx_control = 0; | ||
2124 | |||
2125 | B43_WARN_ON(phy->type != B43_PHYTYPE_G); | ||
2126 | |||
2127 | if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) && | ||
2128 | (bus->boardinfo.type == SSB_BOARD_BU4306)) | ||
2129 | return; | ||
2130 | |||
2131 | b43_phy_write(dev, 0x0028, 0x8018); | ||
2132 | |||
2133 | /* This does something with the Analog... */ | ||
2134 | b43_write16(dev, B43_MMIO_PHY0, b43_read16(dev, B43_MMIO_PHY0) | ||
2135 | & 0xFFDF); | ||
2136 | |||
2137 | if (!phy->gmode) | ||
2138 | return; | ||
2139 | b43_hardware_pctl_early_init(dev); | ||
2140 | if (gphy->cur_idle_tssi == 0) { | ||
2141 | if (phy->radio_ver == 0x2050 && phy->analog == 0) { | ||
2142 | b43_radio_write16(dev, 0x0076, | ||
2143 | (b43_radio_read16(dev, 0x0076) | ||
2144 | & 0x00F7) | 0x0084); | ||
2145 | } else { | ||
2146 | struct b43_rfatt rfatt; | ||
2147 | struct b43_bbatt bbatt; | ||
2148 | |||
2149 | memcpy(&old_rfatt, &gphy->rfatt, sizeof(old_rfatt)); | ||
2150 | memcpy(&old_bbatt, &gphy->bbatt, sizeof(old_bbatt)); | ||
2151 | old_tx_control = gphy->tx_control; | ||
2152 | |||
2153 | bbatt.att = 11; | ||
2154 | if (phy->radio_rev == 8) { | ||
2155 | rfatt.att = 15; | ||
2156 | rfatt.with_padmix = 1; | ||
2157 | } else { | ||
2158 | rfatt.att = 9; | ||
2159 | rfatt.with_padmix = 0; | ||
2160 | } | ||
2161 | b43_set_txpower_g(dev, &bbatt, &rfatt, 0); | ||
2162 | } | ||
2163 | b43_dummy_transmission(dev); | ||
2164 | gphy->cur_idle_tssi = b43_phy_read(dev, B43_PHY_ITSSI); | ||
2165 | if (B43_DEBUG) { | ||
2166 | /* Current-Idle-TSSI sanity check. */ | ||
2167 | if (abs(gphy->cur_idle_tssi - gphy->tgt_idle_tssi) >= 20) { | ||
2168 | b43dbg(dev->wl, | ||
2169 | "!WARNING! Idle-TSSI phy->cur_idle_tssi " | ||
2170 | "measuring failed. (cur=%d, tgt=%d). Disabling TX power " | ||
2171 | "adjustment.\n", gphy->cur_idle_tssi, | ||
2172 | gphy->tgt_idle_tssi); | ||
2173 | gphy->cur_idle_tssi = 0; | ||
2174 | } | ||
2175 | } | ||
2176 | if (phy->radio_ver == 0x2050 && phy->analog == 0) { | ||
2177 | b43_radio_write16(dev, 0x0076, | ||
2178 | b43_radio_read16(dev, 0x0076) | ||
2179 | & 0xFF7B); | ||
2180 | } else { | ||
2181 | b43_set_txpower_g(dev, &old_bbatt, | ||
2182 | &old_rfatt, old_tx_control); | ||
2183 | } | ||
2184 | } | ||
2185 | b43_hardware_pctl_init_gphy(dev); | ||
2186 | b43_shm_clear_tssi(dev); | ||
2187 | } | ||
2188 | |||
2189 | static void b43_phy_initg(struct b43_wldev *dev) | ||
2190 | { | ||
2191 | struct b43_phy *phy = &dev->phy; | ||
2192 | struct b43_phy_g *gphy = phy->g; | ||
2193 | u16 tmp; | ||
2194 | |||
2195 | if (phy->rev == 1) | ||
2196 | b43_phy_initb5(dev); | ||
2197 | else | ||
2198 | b43_phy_initb6(dev); | ||
2199 | |||
2200 | if (phy->rev >= 2 || phy->gmode) | ||
2201 | b43_phy_inita(dev); | ||
2202 | |||
2203 | if (phy->rev >= 2) { | ||
2204 | b43_phy_write(dev, B43_PHY_ANALOGOVER, 0); | ||
2205 | b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, 0); | ||
2206 | } | ||
2207 | if (phy->rev == 2) { | ||
2208 | b43_phy_write(dev, B43_PHY_RFOVER, 0); | ||
2209 | b43_phy_write(dev, B43_PHY_PGACTL, 0xC0); | ||
2210 | } | ||
2211 | if (phy->rev > 5) { | ||
2212 | b43_phy_write(dev, B43_PHY_RFOVER, 0x400); | ||
2213 | b43_phy_write(dev, B43_PHY_PGACTL, 0xC0); | ||
2214 | } | ||
2215 | if (phy->gmode || phy->rev >= 2) { | ||
2216 | tmp = b43_phy_read(dev, B43_PHY_VERSION_OFDM); | ||
2217 | tmp &= B43_PHYVER_VERSION; | ||
2218 | if (tmp == 3 || tmp == 5) { | ||
2219 | b43_phy_write(dev, B43_PHY_OFDM(0xC2), 0x1816); | ||
2220 | b43_phy_write(dev, B43_PHY_OFDM(0xC3), 0x8006); | ||
2221 | } | ||
2222 | if (tmp == 5) { | ||
2223 | b43_phy_write(dev, B43_PHY_OFDM(0xCC), | ||
2224 | (b43_phy_read(dev, B43_PHY_OFDM(0xCC)) | ||
2225 | & 0x00FF) | 0x1F00); | ||
2226 | } | ||
2227 | } | ||
2228 | if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2) | ||
2229 | b43_phy_write(dev, B43_PHY_OFDM(0x7E), 0x78); | ||
2230 | if (phy->radio_rev == 8) { | ||
2231 | b43_phy_write(dev, B43_PHY_EXTG(0x01), | ||
2232 | b43_phy_read(dev, B43_PHY_EXTG(0x01)) | ||
2233 | | 0x80); | ||
2234 | b43_phy_write(dev, B43_PHY_OFDM(0x3E), | ||
2235 | b43_phy_read(dev, B43_PHY_OFDM(0x3E)) | ||
2236 | | 0x4); | ||
2237 | } | ||
2238 | if (has_loopback_gain(phy)) | ||
2239 | b43_calc_loopback_gain(dev); | ||
2240 | |||
2241 | if (phy->radio_rev != 8) { | ||
2242 | if (gphy->initval == 0xFFFF) | ||
2243 | gphy->initval = b43_radio_init2050(dev); | ||
2244 | else | ||
2245 | b43_radio_write16(dev, 0x0078, gphy->initval); | ||
2246 | } | ||
2247 | b43_lo_g_init(dev); | ||
2248 | if (has_tx_magnification(phy)) { | ||
2249 | b43_radio_write16(dev, 0x52, | ||
2250 | (b43_radio_read16(dev, 0x52) & 0xFF00) | ||
2251 | | gphy->lo_control->tx_bias | gphy-> | ||
2252 | lo_control->tx_magn); | ||
2253 | } else { | ||
2254 | b43_radio_write16(dev, 0x52, | ||
2255 | (b43_radio_read16(dev, 0x52) & 0xFFF0) | ||
2256 | | gphy->lo_control->tx_bias); | ||
2257 | } | ||
2258 | if (phy->rev >= 6) { | ||
2259 | b43_phy_write(dev, B43_PHY_CCK(0x36), | ||
2260 | (b43_phy_read(dev, B43_PHY_CCK(0x36)) | ||
2261 | & 0x0FFF) | (gphy->lo_control-> | ||
2262 | tx_bias << 12)); | ||
2263 | } | ||
2264 | if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) | ||
2265 | b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8075); | ||
2266 | else | ||
2267 | b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x807F); | ||
2268 | if (phy->rev < 2) | ||
2269 | b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x101); | ||
2270 | else | ||
2271 | b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x202); | ||
2272 | if (phy->gmode || phy->rev >= 2) { | ||
2273 | b43_lo_g_adjust(dev); | ||
2274 | b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078); | ||
2275 | } | ||
2276 | |||
2277 | if (!(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) { | ||
2278 | /* The specs state to update the NRSSI LT with | ||
2279 | * the value 0x7FFFFFFF here. I think that is some weird | ||
2280 | * compiler optimization in the original driver. | ||
2281 | * Essentially, what we do here is resetting all NRSSI LT | ||
2282 | * entries to -32 (see the clamp_val() in nrssi_hw_update()) | ||
2283 | */ | ||
2284 | b43_nrssi_hw_update(dev, 0xFFFF); //FIXME? | ||
2285 | b43_calc_nrssi_threshold(dev); | ||
2286 | } else if (phy->gmode || phy->rev >= 2) { | ||
2287 | if (gphy->nrssi[0] == -1000) { | ||
2288 | B43_WARN_ON(gphy->nrssi[1] != -1000); | ||
2289 | b43_calc_nrssi_slope(dev); | ||
2290 | } else | ||
2291 | b43_calc_nrssi_threshold(dev); | ||
2292 | } | ||
2293 | if (phy->radio_rev == 8) | ||
2294 | b43_phy_write(dev, B43_PHY_EXTG(0x05), 0x3230); | ||
2295 | b43_phy_init_pctl(dev); | ||
2296 | /* FIXME: The spec says in the following if, the 0 should be replaced | ||
2297 | 'if OFDM may not be used in the current locale' | ||
2298 | but OFDM is legal everywhere */ | ||
2299 | if ((dev->dev->bus->chip_id == 0x4306 | ||
2300 | && dev->dev->bus->chip_package == 2) || 0) { | ||
2301 | b43_phy_write(dev, B43_PHY_CRS0, b43_phy_read(dev, B43_PHY_CRS0) | ||
2302 | & 0xBFFF); | ||
2303 | b43_phy_write(dev, B43_PHY_OFDM(0xC3), | ||
2304 | b43_phy_read(dev, B43_PHY_OFDM(0xC3)) | ||
2305 | & 0x7FFF); | ||
2306 | } | ||
2307 | } | ||
2308 | |||
2309 | void b43_gphy_channel_switch(struct b43_wldev *dev, | ||
2310 | unsigned int channel, | ||
2311 | bool synthetic_pu_workaround) | ||
2312 | { | ||
2313 | if (synthetic_pu_workaround) | ||
2314 | b43_synth_pu_workaround(dev, channel); | ||
2315 | |||
2316 | b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel)); | ||
2317 | |||
2318 | if (channel == 14) { | ||
2319 | if (dev->dev->bus->sprom.country_code == | ||
2320 | SSB_SPROM1CCODE_JAPAN) | ||
2321 | b43_hf_write(dev, | ||
2322 | b43_hf_read(dev) & ~B43_HF_ACPR); | ||
2323 | else | ||
2324 | b43_hf_write(dev, | ||
2325 | b43_hf_read(dev) | B43_HF_ACPR); | ||
2326 | b43_write16(dev, B43_MMIO_CHANNEL_EXT, | ||
2327 | b43_read16(dev, B43_MMIO_CHANNEL_EXT) | ||
2328 | | (1 << 11)); | ||
2329 | } else { | ||
2330 | b43_write16(dev, B43_MMIO_CHANNEL_EXT, | ||
2331 | b43_read16(dev, B43_MMIO_CHANNEL_EXT) | ||
2332 | & 0xF7BF); | ||
2333 | } | ||
2334 | } | ||
2335 | |||
2336 | static void default_baseband_attenuation(struct b43_wldev *dev, | ||
2337 | struct b43_bbatt *bb) | ||
2338 | { | ||
2339 | struct b43_phy *phy = &dev->phy; | ||
2340 | |||
2341 | if (phy->radio_ver == 0x2050 && phy->radio_rev < 6) | ||
2342 | bb->att = 0; | ||
2343 | else | ||
2344 | bb->att = 2; | ||
2345 | } | ||
2346 | |||
2347 | static void default_radio_attenuation(struct b43_wldev *dev, | ||
2348 | struct b43_rfatt *rf) | ||
2349 | { | ||
2350 | struct ssb_bus *bus = dev->dev->bus; | ||
2351 | struct b43_phy *phy = &dev->phy; | ||
2352 | |||
2353 | rf->with_padmix = 0; | ||
2354 | |||
2355 | if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM && | ||
2356 | bus->boardinfo.type == SSB_BOARD_BCM4309G) { | ||
2357 | if (bus->boardinfo.rev < 0x43) { | ||
2358 | rf->att = 2; | ||
2359 | return; | ||
2360 | } else if (bus->boardinfo.rev < 0x51) { | ||
2361 | rf->att = 3; | ||
2362 | return; | ||
2363 | } | ||
2364 | } | ||
2365 | |||
2366 | if (phy->type == B43_PHYTYPE_A) { | ||
2367 | rf->att = 0x60; | ||
2368 | return; | ||
2369 | } | ||
2370 | |||
2371 | switch (phy->radio_ver) { | ||
2372 | case 0x2053: | ||
2373 | switch (phy->radio_rev) { | ||
2374 | case 1: | ||
2375 | rf->att = 6; | ||
2376 | return; | ||
2377 | } | ||
2378 | break; | ||
2379 | case 0x2050: | ||
2380 | switch (phy->radio_rev) { | ||
2381 | case 0: | ||
2382 | rf->att = 5; | ||
2383 | return; | ||
2384 | case 1: | ||
2385 | if (phy->type == B43_PHYTYPE_G) { | ||
2386 | if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM | ||
2387 | && bus->boardinfo.type == SSB_BOARD_BCM4309G | ||
2388 | && bus->boardinfo.rev >= 30) | ||
2389 | rf->att = 3; | ||
2390 | else if (bus->boardinfo.vendor == | ||
2391 | SSB_BOARDVENDOR_BCM | ||
2392 | && bus->boardinfo.type == | ||
2393 | SSB_BOARD_BU4306) | ||
2394 | rf->att = 3; | ||
2395 | else | ||
2396 | rf->att = 1; | ||
2397 | } else { | ||
2398 | if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM | ||
2399 | && bus->boardinfo.type == SSB_BOARD_BCM4309G | ||
2400 | && bus->boardinfo.rev >= 30) | ||
2401 | rf->att = 7; | ||
2402 | else | ||
2403 | rf->att = 6; | ||
2404 | } | ||
2405 | return; | ||
2406 | case 2: | ||
2407 | if (phy->type == B43_PHYTYPE_G) { | ||
2408 | if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM | ||
2409 | && bus->boardinfo.type == SSB_BOARD_BCM4309G | ||
2410 | && bus->boardinfo.rev >= 30) | ||
2411 | rf->att = 3; | ||
2412 | else if (bus->boardinfo.vendor == | ||
2413 | SSB_BOARDVENDOR_BCM | ||
2414 | && bus->boardinfo.type == | ||
2415 | SSB_BOARD_BU4306) | ||
2416 | rf->att = 5; | ||
2417 | else if (bus->chip_id == 0x4320) | ||
2418 | rf->att = 4; | ||
2419 | else | ||
2420 | rf->att = 3; | ||
2421 | } else | ||
2422 | rf->att = 6; | ||
2423 | return; | ||
2424 | case 3: | ||
2425 | rf->att = 5; | ||
2426 | return; | ||
2427 | case 4: | ||
2428 | case 5: | ||
2429 | rf->att = 1; | ||
2430 | return; | ||
2431 | case 6: | ||
2432 | case 7: | ||
2433 | rf->att = 5; | ||
2434 | return; | ||
2435 | case 8: | ||
2436 | rf->att = 0xA; | ||
2437 | rf->with_padmix = 1; | ||
2438 | return; | ||
2439 | case 9: | ||
2440 | default: | ||
2441 | rf->att = 5; | ||
2442 | return; | ||
2443 | } | ||
2444 | } | ||
2445 | rf->att = 5; | ||
2446 | } | ||
2447 | |||
2448 | static u16 default_tx_control(struct b43_wldev *dev) | ||
2449 | { | ||
2450 | struct b43_phy *phy = &dev->phy; | ||
2451 | |||
2452 | if (phy->radio_ver != 0x2050) | ||
2453 | return 0; | ||
2454 | if (phy->radio_rev == 1) | ||
2455 | return B43_TXCTL_PA2DB | B43_TXCTL_TXMIX; | ||
2456 | if (phy->radio_rev < 6) | ||
2457 | return B43_TXCTL_PA2DB; | ||
2458 | if (phy->radio_rev == 8) | ||
2459 | return B43_TXCTL_TXMIX; | ||
2460 | return 0; | ||
2461 | } | ||
2462 | |||
2463 | static u8 b43_gphy_aci_detect(struct b43_wldev *dev, u8 channel) | ||
2464 | { | ||
2465 | struct b43_phy *phy = &dev->phy; | ||
2466 | struct b43_phy_g *gphy = phy->g; | ||
2467 | u8 ret = 0; | ||
2468 | u16 saved, rssi, temp; | ||
2469 | int i, j = 0; | ||
2470 | |||
2471 | saved = b43_phy_read(dev, 0x0403); | ||
2472 | b43_switch_channel(dev, channel); | ||
2473 | b43_phy_write(dev, 0x0403, (saved & 0xFFF8) | 5); | ||
2474 | if (gphy->aci_hw_rssi) | ||
2475 | rssi = b43_phy_read(dev, 0x048A) & 0x3F; | ||
2476 | else | ||
2477 | rssi = saved & 0x3F; | ||
2478 | /* clamp temp to signed 5bit */ | ||
2479 | if (rssi > 32) | ||
2480 | rssi -= 64; | ||
2481 | for (i = 0; i < 100; i++) { | ||
2482 | temp = (b43_phy_read(dev, 0x047F) >> 8) & 0x3F; | ||
2483 | if (temp > 32) | ||
2484 | temp -= 64; | ||
2485 | if (temp < rssi) | ||
2486 | j++; | ||
2487 | if (j >= 20) | ||
2488 | ret = 1; | ||
2489 | } | ||
2490 | b43_phy_write(dev, 0x0403, saved); | ||
2491 | |||
2492 | return ret; | ||
2493 | } | ||
2494 | |||
2495 | static u8 b43_gphy_aci_scan(struct b43_wldev *dev) | ||
2496 | { | ||
2497 | struct b43_phy *phy = &dev->phy; | ||
2498 | u8 ret[13]; | ||
2499 | unsigned int channel = phy->channel; | ||
2500 | unsigned int i, j, start, end; | ||
2501 | |||
2502 | if (!((phy->type == B43_PHYTYPE_G) && (phy->rev > 0))) | ||
2503 | return 0; | ||
2504 | |||
2505 | b43_phy_lock(dev); | ||
2506 | b43_radio_lock(dev); | ||
2507 | b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) & 0xFFFC); | ||
2508 | b43_phy_write(dev, B43_PHY_G_CRS, | ||
2509 | b43_phy_read(dev, B43_PHY_G_CRS) & 0x7FFF); | ||
2510 | b43_set_all_gains(dev, 3, 8, 1); | ||
2511 | |||
2512 | start = (channel - 5 > 0) ? channel - 5 : 1; | ||
2513 | end = (channel + 5 < 14) ? channel + 5 : 13; | ||
2514 | |||
2515 | for (i = start; i <= end; i++) { | ||
2516 | if (abs(channel - i) > 2) | ||
2517 | ret[i - 1] = b43_gphy_aci_detect(dev, i); | ||
2518 | } | ||
2519 | b43_switch_channel(dev, channel); | ||
2520 | b43_phy_write(dev, 0x0802, | ||
2521 | (b43_phy_read(dev, 0x0802) & 0xFFFC) | 0x0003); | ||
2522 | b43_phy_write(dev, 0x0403, b43_phy_read(dev, 0x0403) & 0xFFF8); | ||
2523 | b43_phy_write(dev, B43_PHY_G_CRS, | ||
2524 | b43_phy_read(dev, B43_PHY_G_CRS) | 0x8000); | ||
2525 | b43_set_original_gains(dev); | ||
2526 | for (i = 0; i < 13; i++) { | ||
2527 | if (!ret[i]) | ||
2528 | continue; | ||
2529 | end = (i + 5 < 13) ? i + 5 : 13; | ||
2530 | for (j = i; j < end; j++) | ||
2531 | ret[j] = 1; | ||
2532 | } | ||
2533 | b43_radio_unlock(dev); | ||
2534 | b43_phy_unlock(dev); | ||
2535 | |||
2536 | return ret[channel - 1]; | ||
2537 | } | ||
2538 | |||
2539 | static s32 b43_tssi2dbm_ad(s32 num, s32 den) | ||
2540 | { | ||
2541 | if (num < 0) | ||
2542 | return num / den; | ||
2543 | else | ||
2544 | return (num + den / 2) / den; | ||
2545 | } | ||
2546 | |||
2547 | static s8 b43_tssi2dbm_entry(s8 entry[], u8 index, | ||
2548 | s16 pab0, s16 pab1, s16 pab2) | ||
2549 | { | ||
2550 | s32 m1, m2, f = 256, q, delta; | ||
2551 | s8 i = 0; | ||
2552 | |||
2553 | m1 = b43_tssi2dbm_ad(16 * pab0 + index * pab1, 32); | ||
2554 | m2 = max(b43_tssi2dbm_ad(32768 + index * pab2, 256), 1); | ||
2555 | do { | ||
2556 | if (i > 15) | ||
2557 | return -EINVAL; | ||
2558 | q = b43_tssi2dbm_ad(f * 4096 - | ||
2559 | b43_tssi2dbm_ad(m2 * f, 16) * f, 2048); | ||
2560 | delta = abs(q - f); | ||
2561 | f = q; | ||
2562 | i++; | ||
2563 | } while (delta >= 2); | ||
2564 | entry[index] = clamp_val(b43_tssi2dbm_ad(m1 * f, 8192), -127, 128); | ||
2565 | return 0; | ||
2566 | } | ||
2567 | |||
2568 | u8 * b43_generate_dyn_tssi2dbm_tab(struct b43_wldev *dev, | ||
2569 | s16 pab0, s16 pab1, s16 pab2) | ||
2570 | { | ||
2571 | unsigned int i; | ||
2572 | u8 *tab; | ||
2573 | int err; | ||
2574 | |||
2575 | tab = kmalloc(64, GFP_KERNEL); | ||
2576 | if (!tab) { | ||
2577 | b43err(dev->wl, "Could not allocate memory " | ||
2578 | "for tssi2dbm table\n"); | ||
2579 | return NULL; | ||
2580 | } | ||
2581 | for (i = 0; i < 64; i++) { | ||
2582 | err = b43_tssi2dbm_entry(tab, i, pab0, pab1, pab2); | ||
2583 | if (err) { | ||
2584 | b43err(dev->wl, "Could not generate " | ||
2585 | "tssi2dBm table\n"); | ||
2586 | kfree(tab); | ||
2587 | return NULL; | ||
2588 | } | ||
2589 | } | ||
2590 | |||
2591 | return tab; | ||
2592 | } | ||
2593 | |||
2594 | /* Initialise the TSSI->dBm lookup table */ | ||
2595 | static int b43_gphy_init_tssi2dbm_table(struct b43_wldev *dev) | ||
2596 | { | ||
2597 | struct b43_phy *phy = &dev->phy; | ||
2598 | struct b43_phy_g *gphy = phy->g; | ||
2599 | s16 pab0, pab1, pab2; | ||
2600 | |||
2601 | pab0 = (s16) (dev->dev->bus->sprom.pa0b0); | ||
2602 | pab1 = (s16) (dev->dev->bus->sprom.pa0b1); | ||
2603 | pab2 = (s16) (dev->dev->bus->sprom.pa0b2); | ||
2604 | |||
2605 | B43_WARN_ON((dev->dev->bus->chip_id == 0x4301) && | ||
2606 | (phy->radio_ver != 0x2050)); /* Not supported anymore */ | ||
2607 | |||
2608 | gphy->dyn_tssi_tbl = 0; | ||
2609 | |||
2610 | if (pab0 != 0 && pab1 != 0 && pab2 != 0 && | ||
2611 | pab0 != -1 && pab1 != -1 && pab2 != -1) { | ||
2612 | /* The pabX values are set in SPROM. Use them. */ | ||
2613 | if ((s8) dev->dev->bus->sprom.itssi_bg != 0 && | ||
2614 | (s8) dev->dev->bus->sprom.itssi_bg != -1) { | ||
2615 | gphy->tgt_idle_tssi = | ||
2616 | (s8) (dev->dev->bus->sprom.itssi_bg); | ||
2617 | } else | ||
2618 | gphy->tgt_idle_tssi = 62; | ||
2619 | gphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0, | ||
2620 | pab1, pab2); | ||
2621 | if (!gphy->tssi2dbm) | ||
2622 | return -ENOMEM; | ||
2623 | gphy->dyn_tssi_tbl = 1; | ||
2624 | } else { | ||
2625 | /* pabX values not set in SPROM. */ | ||
2626 | gphy->tgt_idle_tssi = 52; | ||
2627 | gphy->tssi2dbm = b43_tssi2dbm_g_table; | ||
2628 | } | ||
2629 | |||
2630 | return 0; | ||
2631 | } | ||
2632 | |||
2633 | static int b43_gphy_op_allocate(struct b43_wldev *dev) | ||
2634 | { | ||
2635 | struct b43_phy_g *gphy; | ||
2636 | struct b43_txpower_lo_control *lo; | ||
2637 | int err, i; | ||
2638 | |||
2639 | gphy = kzalloc(sizeof(*gphy), GFP_KERNEL); | ||
2640 | if (!gphy) { | ||
2641 | err = -ENOMEM; | ||
2642 | goto error; | ||
2643 | } | ||
2644 | dev->phy.g = gphy; | ||
2645 | |||
2646 | memset(gphy->minlowsig, 0xFF, sizeof(gphy->minlowsig)); | ||
2647 | |||
2648 | /* NRSSI */ | ||
2649 | for (i = 0; i < ARRAY_SIZE(gphy->nrssi); i++) | ||
2650 | gphy->nrssi[i] = -1000; | ||
2651 | for (i = 0; i < ARRAY_SIZE(gphy->nrssi_lt); i++) | ||
2652 | gphy->nrssi_lt[i] = i; | ||
2653 | |||
2654 | gphy->lofcal = 0xFFFF; | ||
2655 | gphy->initval = 0xFFFF; | ||
2656 | |||
2657 | gphy->interfmode = B43_INTERFMODE_NONE; | ||
2658 | |||
2659 | /* OFDM-table address caching. */ | ||
2660 | gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_UNKNOWN; | ||
2661 | |||
2662 | gphy->average_tssi = 0xFF; | ||
2663 | |||
2664 | lo = kzalloc(sizeof(*lo), GFP_KERNEL); | ||
2665 | if (!lo) { | ||
2666 | err = -ENOMEM; | ||
2667 | goto err_free_gphy; | ||
2668 | } | ||
2669 | gphy->lo_control = lo; | ||
2670 | |||
2671 | lo->tx_bias = 0xFF; | ||
2672 | INIT_LIST_HEAD(&lo->calib_list); | ||
2673 | |||
2674 | err = b43_gphy_init_tssi2dbm_table(dev); | ||
2675 | if (err) | ||
2676 | goto err_free_lo; | ||
2677 | |||
2678 | return 0; | ||
2679 | |||
2680 | err_free_lo: | ||
2681 | kfree(lo); | ||
2682 | err_free_gphy: | ||
2683 | kfree(gphy); | ||
2684 | error: | ||
2685 | return err; | ||
2686 | } | ||
2687 | |||
2688 | static int b43_gphy_op_prepare(struct b43_wldev *dev) | ||
2689 | { | ||
2690 | struct b43_phy *phy = &dev->phy; | ||
2691 | struct b43_phy_g *gphy = phy->g; | ||
2692 | struct b43_txpower_lo_control *lo = gphy->lo_control; | ||
2693 | |||
2694 | B43_WARN_ON(phy->type != B43_PHYTYPE_G); | ||
2695 | |||
2696 | default_baseband_attenuation(dev, &gphy->bbatt); | ||
2697 | default_radio_attenuation(dev, &gphy->rfatt); | ||
2698 | gphy->tx_control = (default_tx_control(dev) << 4); | ||
2699 | generate_rfatt_list(dev, &lo->rfatt_list); | ||
2700 | generate_bbatt_list(dev, &lo->bbatt_list); | ||
2701 | |||
2702 | /* Commit previous writes */ | ||
2703 | b43_read32(dev, B43_MMIO_MACCTL); | ||
2704 | |||
2705 | if (phy->rev == 1) { | ||
2706 | /* Workaround: Temporarly disable gmode through the early init | ||
2707 | * phase, as the gmode stuff is not needed for phy rev 1 */ | ||
2708 | phy->gmode = 0; | ||
2709 | b43_wireless_core_reset(dev, 0); | ||
2710 | b43_phy_initg(dev); | ||
2711 | phy->gmode = 1; | ||
2712 | b43_wireless_core_reset(dev, B43_TMSLOW_GMODE); | ||
2713 | } | ||
2714 | |||
2715 | return 0; | ||
2716 | } | ||
2717 | |||
2718 | static int b43_gphy_op_init(struct b43_wldev *dev) | ||
2719 | { | ||
2720 | struct b43_phy_g *gphy = dev->phy.g; | ||
2721 | |||
2722 | b43_phy_initg(dev); | ||
2723 | gphy->initialised = 1; | ||
2724 | |||
2725 | return 0; | ||
2726 | } | ||
2727 | |||
2728 | static void b43_gphy_op_exit(struct b43_wldev *dev) | ||
2729 | { | ||
2730 | struct b43_phy_g *gphy = dev->phy.g; | ||
2731 | |||
2732 | if (gphy->initialised) { | ||
2733 | //TODO | ||
2734 | gphy->initialised = 0; | ||
2735 | } | ||
2736 | b43_lo_g_cleanup(dev); | ||
2737 | kfree(gphy->lo_control); | ||
2738 | if (gphy->dyn_tssi_tbl) | ||
2739 | kfree(gphy->tssi2dbm); | ||
2740 | kfree(gphy); | ||
2741 | dev->phy.g = NULL; | ||
2742 | } | ||
2743 | |||
2744 | static u16 b43_gphy_op_read(struct b43_wldev *dev, u16 reg) | ||
2745 | { | ||
2746 | b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); | ||
2747 | return b43_read16(dev, B43_MMIO_PHY_DATA); | ||
2748 | } | ||
2749 | |||
2750 | static void b43_gphy_op_write(struct b43_wldev *dev, u16 reg, u16 value) | ||
2751 | { | ||
2752 | b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); | ||
2753 | b43_write16(dev, B43_MMIO_PHY_DATA, value); | ||
2754 | } | ||
2755 | |||
2756 | static u16 b43_gphy_op_radio_read(struct b43_wldev *dev, u16 reg) | ||
2757 | { | ||
2758 | /* Register 1 is a 32-bit register. */ | ||
2759 | B43_WARN_ON(reg == 1); | ||
2760 | /* G-PHY needs 0x80 for read access. */ | ||
2761 | reg |= 0x80; | ||
2762 | |||
2763 | b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); | ||
2764 | return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW); | ||
2765 | } | ||
2766 | |||
2767 | static void b43_gphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) | ||
2768 | { | ||
2769 | /* Register 1 is a 32-bit register. */ | ||
2770 | B43_WARN_ON(reg == 1); | ||
2771 | |||
2772 | b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); | ||
2773 | b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); | ||
2774 | } | ||
2775 | |||
2776 | static bool b43_gphy_op_supports_hwpctl(struct b43_wldev *dev) | ||
2777 | { | ||
2778 | return (dev->phy.rev >= 6); | ||
2779 | } | ||
2780 | |||
2781 | static void b43_gphy_op_software_rfkill(struct b43_wldev *dev, | ||
2782 | enum rfkill_state state) | ||
2783 | { | ||
2784 | struct b43_phy *phy = &dev->phy; | ||
2785 | struct b43_phy_g *gphy = phy->g; | ||
2786 | unsigned int channel; | ||
2787 | |||
2788 | might_sleep(); | ||
2789 | |||
2790 | if (state == RFKILL_STATE_UNBLOCKED) { | ||
2791 | /* Turn radio ON */ | ||
2792 | if (phy->radio_on) | ||
2793 | return; | ||
2794 | |||
2795 | b43_phy_write(dev, 0x0015, 0x8000); | ||
2796 | b43_phy_write(dev, 0x0015, 0xCC00); | ||
2797 | b43_phy_write(dev, 0x0015, (phy->gmode ? 0x00C0 : 0x0000)); | ||
2798 | if (gphy->radio_off_context.valid) { | ||
2799 | /* Restore the RFover values. */ | ||
2800 | b43_phy_write(dev, B43_PHY_RFOVER, | ||
2801 | gphy->radio_off_context.rfover); | ||
2802 | b43_phy_write(dev, B43_PHY_RFOVERVAL, | ||
2803 | gphy->radio_off_context.rfoverval); | ||
2804 | gphy->radio_off_context.valid = 0; | ||
2805 | } | ||
2806 | channel = phy->channel; | ||
2807 | b43_gphy_channel_switch(dev, 6, 1); | ||
2808 | b43_gphy_channel_switch(dev, channel, 0); | ||
2809 | } else { | ||
2810 | /* Turn radio OFF */ | ||
2811 | u16 rfover, rfoverval; | ||
2812 | |||
2813 | rfover = b43_phy_read(dev, B43_PHY_RFOVER); | ||
2814 | rfoverval = b43_phy_read(dev, B43_PHY_RFOVERVAL); | ||
2815 | gphy->radio_off_context.rfover = rfover; | ||
2816 | gphy->radio_off_context.rfoverval = rfoverval; | ||
2817 | gphy->radio_off_context.valid = 1; | ||
2818 | b43_phy_write(dev, B43_PHY_RFOVER, rfover | 0x008C); | ||
2819 | b43_phy_write(dev, B43_PHY_RFOVERVAL, rfoverval & 0xFF73); | ||
2820 | } | ||
2821 | } | ||
2822 | |||
2823 | static int b43_gphy_op_switch_channel(struct b43_wldev *dev, | ||
2824 | unsigned int new_channel) | ||
2825 | { | ||
2826 | if ((new_channel < 1) || (new_channel > 14)) | ||
2827 | return -EINVAL; | ||
2828 | b43_gphy_channel_switch(dev, new_channel, 0); | ||
2829 | |||
2830 | return 0; | ||
2831 | } | ||
2832 | |||
2833 | static unsigned int b43_gphy_op_get_default_chan(struct b43_wldev *dev) | ||
2834 | { | ||
2835 | return 1; /* Default to channel 1 */ | ||
2836 | } | ||
2837 | |||
2838 | static void b43_gphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna) | ||
2839 | { | ||
2840 | struct b43_phy *phy = &dev->phy; | ||
2841 | u64 hf; | ||
2842 | u16 tmp; | ||
2843 | int autodiv = 0; | ||
2844 | |||
2845 | if (antenna == B43_ANTENNA_AUTO0 || antenna == B43_ANTENNA_AUTO1) | ||
2846 | autodiv = 1; | ||
2847 | |||
2848 | hf = b43_hf_read(dev); | ||
2849 | hf &= ~B43_HF_ANTDIVHELP; | ||
2850 | b43_hf_write(dev, hf); | ||
2851 | |||
2852 | tmp = b43_phy_read(dev, B43_PHY_BBANDCFG); | ||
2853 | tmp &= ~B43_PHY_BBANDCFG_RXANT; | ||
2854 | tmp |= (autodiv ? B43_ANTENNA_AUTO0 : antenna) | ||
2855 | << B43_PHY_BBANDCFG_RXANT_SHIFT; | ||
2856 | b43_phy_write(dev, B43_PHY_BBANDCFG, tmp); | ||
2857 | |||
2858 | if (autodiv) { | ||
2859 | tmp = b43_phy_read(dev, B43_PHY_ANTDWELL); | ||
2860 | if (antenna == B43_ANTENNA_AUTO0) | ||
2861 | tmp &= ~B43_PHY_ANTDWELL_AUTODIV1; | ||
2862 | else | ||
2863 | tmp |= B43_PHY_ANTDWELL_AUTODIV1; | ||
2864 | b43_phy_write(dev, B43_PHY_ANTDWELL, tmp); | ||
2865 | } | ||
2866 | tmp = b43_phy_read(dev, B43_PHY_ANTWRSETT); | ||
2867 | if (autodiv) | ||
2868 | tmp |= B43_PHY_ANTWRSETT_ARXDIV; | ||
2869 | else | ||
2870 | tmp &= ~B43_PHY_ANTWRSETT_ARXDIV; | ||
2871 | b43_phy_write(dev, B43_PHY_ANTWRSETT, tmp); | ||
2872 | if (phy->rev >= 2) { | ||
2873 | tmp = b43_phy_read(dev, B43_PHY_OFDM61); | ||
2874 | tmp |= B43_PHY_OFDM61_10; | ||
2875 | b43_phy_write(dev, B43_PHY_OFDM61, tmp); | ||
2876 | |||
2877 | tmp = | ||
2878 | b43_phy_read(dev, B43_PHY_DIVSRCHGAINBACK); | ||
2879 | tmp = (tmp & 0xFF00) | 0x15; | ||
2880 | b43_phy_write(dev, B43_PHY_DIVSRCHGAINBACK, | ||
2881 | tmp); | ||
2882 | |||
2883 | if (phy->rev == 2) { | ||
2884 | b43_phy_write(dev, B43_PHY_ADIVRELATED, | ||
2885 | 8); | ||
2886 | } else { | ||
2887 | tmp = | ||
2888 | b43_phy_read(dev, | ||
2889 | B43_PHY_ADIVRELATED); | ||
2890 | tmp = (tmp & 0xFF00) | 8; | ||
2891 | b43_phy_write(dev, B43_PHY_ADIVRELATED, | ||
2892 | tmp); | ||
2893 | } | ||
2894 | } | ||
2895 | if (phy->rev >= 6) | ||
2896 | b43_phy_write(dev, B43_PHY_OFDM9B, 0xDC); | ||
2897 | |||
2898 | hf |= B43_HF_ANTDIVHELP; | ||
2899 | b43_hf_write(dev, hf); | ||
2900 | } | ||
2901 | |||
2902 | static int b43_gphy_op_interf_mitigation(struct b43_wldev *dev, | ||
2903 | enum b43_interference_mitigation mode) | ||
2904 | { | ||
2905 | struct b43_phy *phy = &dev->phy; | ||
2906 | struct b43_phy_g *gphy = phy->g; | ||
2907 | int currentmode; | ||
2908 | |||
2909 | B43_WARN_ON(phy->type != B43_PHYTYPE_G); | ||
2910 | if ((phy->rev == 0) || (!phy->gmode)) | ||
2911 | return -ENODEV; | ||
2912 | |||
2913 | gphy->aci_wlan_automatic = 0; | ||
2914 | switch (mode) { | ||
2915 | case B43_INTERFMODE_AUTOWLAN: | ||
2916 | gphy->aci_wlan_automatic = 1; | ||
2917 | if (gphy->aci_enable) | ||
2918 | mode = B43_INTERFMODE_MANUALWLAN; | ||
2919 | else | ||
2920 | mode = B43_INTERFMODE_NONE; | ||
2921 | break; | ||
2922 | case B43_INTERFMODE_NONE: | ||
2923 | case B43_INTERFMODE_NONWLAN: | ||
2924 | case B43_INTERFMODE_MANUALWLAN: | ||
2925 | break; | ||
2926 | default: | ||
2927 | return -EINVAL; | ||
2928 | } | ||
2929 | |||
2930 | currentmode = gphy->interfmode; | ||
2931 | if (currentmode == mode) | ||
2932 | return 0; | ||
2933 | if (currentmode != B43_INTERFMODE_NONE) | ||
2934 | b43_radio_interference_mitigation_disable(dev, currentmode); | ||
2935 | |||
2936 | if (mode == B43_INTERFMODE_NONE) { | ||
2937 | gphy->aci_enable = 0; | ||
2938 | gphy->aci_hw_rssi = 0; | ||
2939 | } else | ||
2940 | b43_radio_interference_mitigation_enable(dev, mode); | ||
2941 | gphy->interfmode = mode; | ||
2942 | |||
2943 | return 0; | ||
2944 | } | ||
2945 | |||
2946 | /* http://bcm-specs.sipsolutions.net/EstimatePowerOut | ||
2947 | * This function converts a TSSI value to dBm in Q5.2 | ||
2948 | */ | ||
2949 | static s8 b43_gphy_estimate_power_out(struct b43_wldev *dev, s8 tssi) | ||
2950 | { | ||
2951 | struct b43_phy_g *gphy = dev->phy.g; | ||
2952 | s8 dbm; | ||
2953 | s32 tmp; | ||
2954 | |||
2955 | tmp = (gphy->tgt_idle_tssi - gphy->cur_idle_tssi + tssi); | ||
2956 | tmp = clamp_val(tmp, 0x00, 0x3F); | ||
2957 | dbm = gphy->tssi2dbm[tmp]; | ||
2958 | |||
2959 | return dbm; | ||
2960 | } | ||
2961 | |||
2962 | static void b43_put_attenuation_into_ranges(struct b43_wldev *dev, | ||
2963 | int *_bbatt, int *_rfatt) | ||
2964 | { | ||
2965 | int rfatt = *_rfatt; | ||
2966 | int bbatt = *_bbatt; | ||
2967 | struct b43_txpower_lo_control *lo = dev->phy.g->lo_control; | ||
2968 | |||
2969 | /* Get baseband and radio attenuation values into their permitted ranges. | ||
2970 | * Radio attenuation affects power level 4 times as much as baseband. */ | ||
2971 | |||
2972 | /* Range constants */ | ||
2973 | const int rf_min = lo->rfatt_list.min_val; | ||
2974 | const int rf_max = lo->rfatt_list.max_val; | ||
2975 | const int bb_min = lo->bbatt_list.min_val; | ||
2976 | const int bb_max = lo->bbatt_list.max_val; | ||
2977 | |||
2978 | while (1) { | ||
2979 | if (rfatt > rf_max && bbatt > bb_max - 4) | ||
2980 | break; /* Can not get it into ranges */ | ||
2981 | if (rfatt < rf_min && bbatt < bb_min + 4) | ||
2982 | break; /* Can not get it into ranges */ | ||
2983 | if (bbatt > bb_max && rfatt > rf_max - 1) | ||
2984 | break; /* Can not get it into ranges */ | ||
2985 | if (bbatt < bb_min && rfatt < rf_min + 1) | ||
2986 | break; /* Can not get it into ranges */ | ||
2987 | |||
2988 | if (bbatt > bb_max) { | ||
2989 | bbatt -= 4; | ||
2990 | rfatt += 1; | ||
2991 | continue; | ||
2992 | } | ||
2993 | if (bbatt < bb_min) { | ||
2994 | bbatt += 4; | ||
2995 | rfatt -= 1; | ||
2996 | continue; | ||
2997 | } | ||
2998 | if (rfatt > rf_max) { | ||
2999 | rfatt -= 1; | ||
3000 | bbatt += 4; | ||
3001 | continue; | ||
3002 | } | ||
3003 | if (rfatt < rf_min) { | ||
3004 | rfatt += 1; | ||
3005 | bbatt -= 4; | ||
3006 | continue; | ||
3007 | } | ||
3008 | break; | ||
3009 | } | ||
3010 | |||
3011 | *_rfatt = clamp_val(rfatt, rf_min, rf_max); | ||
3012 | *_bbatt = clamp_val(bbatt, bb_min, bb_max); | ||
3013 | } | ||
3014 | |||
3015 | static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev) | ||
3016 | { | ||
3017 | struct b43_phy *phy = &dev->phy; | ||
3018 | struct b43_phy_g *gphy = phy->g; | ||
3019 | int rfatt, bbatt; | ||
3020 | u8 tx_control; | ||
3021 | |||
3022 | spin_lock_irq(&dev->wl->irq_lock); | ||
3023 | |||
3024 | /* Calculate the new attenuation values. */ | ||
3025 | bbatt = gphy->bbatt.att; | ||
3026 | bbatt += gphy->bbatt_delta; | ||
3027 | rfatt = gphy->rfatt.att; | ||
3028 | rfatt += gphy->rfatt_delta; | ||
3029 | |||
3030 | b43_put_attenuation_into_ranges(dev, &bbatt, &rfatt); | ||
3031 | tx_control = gphy->tx_control; | ||
3032 | if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 2)) { | ||
3033 | if (rfatt <= 1) { | ||
3034 | if (tx_control == 0) { | ||
3035 | tx_control = | ||
3036 | B43_TXCTL_PA2DB | | ||
3037 | B43_TXCTL_TXMIX; | ||
3038 | rfatt += 2; | ||
3039 | bbatt += 2; | ||
3040 | } else if (dev->dev->bus->sprom. | ||
3041 | boardflags_lo & | ||
3042 | B43_BFL_PACTRL) { | ||
3043 | bbatt += 4 * (rfatt - 2); | ||
3044 | rfatt = 2; | ||
3045 | } | ||
3046 | } else if (rfatt > 4 && tx_control) { | ||
3047 | tx_control = 0; | ||
3048 | if (bbatt < 3) { | ||
3049 | rfatt -= 3; | ||
3050 | bbatt += 2; | ||
3051 | } else { | ||
3052 | rfatt -= 2; | ||
3053 | bbatt -= 2; | ||
3054 | } | ||
3055 | } | ||
3056 | } | ||
3057 | /* Save the control values */ | ||
3058 | gphy->tx_control = tx_control; | ||
3059 | b43_put_attenuation_into_ranges(dev, &bbatt, &rfatt); | ||
3060 | gphy->rfatt.att = rfatt; | ||
3061 | gphy->bbatt.att = bbatt; | ||
3062 | |||
3063 | /* We drop the lock early, so we can sleep during hardware | ||
3064 | * adjustment. Possible races with op_recalc_txpower are harmless, | ||
3065 | * as we will be called once again in case we raced. */ | ||
3066 | spin_unlock_irq(&dev->wl->irq_lock); | ||
3067 | |||
3068 | if (b43_debug(dev, B43_DBG_XMITPOWER)) | ||
3069 | b43dbg(dev->wl, "Adjusting TX power\n"); | ||
3070 | |||
3071 | /* Adjust the hardware */ | ||
3072 | b43_phy_lock(dev); | ||
3073 | b43_radio_lock(dev); | ||
3074 | b43_set_txpower_g(dev, &gphy->bbatt, &gphy->rfatt, | ||
3075 | gphy->tx_control); | ||
3076 | b43_radio_unlock(dev); | ||
3077 | b43_phy_unlock(dev); | ||
3078 | } | ||
3079 | |||
3080 | static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev, | ||
3081 | bool ignore_tssi) | ||
3082 | { | ||
3083 | struct b43_phy *phy = &dev->phy; | ||
3084 | struct b43_phy_g *gphy = phy->g; | ||
3085 | unsigned int average_tssi; | ||
3086 | int cck_result, ofdm_result; | ||
3087 | int estimated_pwr, desired_pwr, pwr_adjust; | ||
3088 | int rfatt_delta, bbatt_delta; | ||
3089 | unsigned int max_pwr; | ||
3090 | |||
3091 | /* First get the average TSSI */ | ||
3092 | cck_result = b43_phy_shm_tssi_read(dev, B43_SHM_SH_TSSI_CCK); | ||
3093 | ofdm_result = b43_phy_shm_tssi_read(dev, B43_SHM_SH_TSSI_OFDM_G); | ||
3094 | if ((cck_result < 0) && (ofdm_result < 0)) { | ||
3095 | /* No TSSI information available */ | ||
3096 | if (!ignore_tssi) | ||
3097 | goto no_adjustment_needed; | ||
3098 | cck_result = 0; | ||
3099 | ofdm_result = 0; | ||
3100 | } | ||
3101 | if (cck_result < 0) | ||
3102 | average_tssi = ofdm_result; | ||
3103 | else if (ofdm_result < 0) | ||
3104 | average_tssi = cck_result; | ||
3105 | else | ||
3106 | average_tssi = (cck_result + ofdm_result) / 2; | ||
3107 | /* Merge the average with the stored value. */ | ||
3108 | if (likely(gphy->average_tssi != 0xFF)) | ||
3109 | average_tssi = (average_tssi + gphy->average_tssi) / 2; | ||
3110 | gphy->average_tssi = average_tssi; | ||
3111 | B43_WARN_ON(average_tssi >= B43_TSSI_MAX); | ||
3112 | |||
3113 | /* Estimate the TX power emission based on the TSSI */ | ||
3114 | estimated_pwr = b43_gphy_estimate_power_out(dev, average_tssi); | ||
3115 | |||
3116 | B43_WARN_ON(phy->type != B43_PHYTYPE_G); | ||
3117 | max_pwr = dev->dev->bus->sprom.maxpwr_bg; | ||
3118 | if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) | ||
3119 | max_pwr -= 3; /* minus 0.75 */ | ||
3120 | if (unlikely(max_pwr >= INT_TO_Q52(30/*dBm*/))) { | ||
3121 | b43warn(dev->wl, | ||
3122 | "Invalid max-TX-power value in SPROM.\n"); | ||
3123 | max_pwr = INT_TO_Q52(20); /* fake it */ | ||
3124 | dev->dev->bus->sprom.maxpwr_bg = max_pwr; | ||
3125 | } | ||
3126 | |||
3127 | /* Get desired power (in Q5.2) */ | ||
3128 | if (phy->desired_txpower < 0) | ||
3129 | desired_pwr = INT_TO_Q52(0); | ||
3130 | else | ||
3131 | desired_pwr = INT_TO_Q52(phy->desired_txpower); | ||
3132 | /* And limit it. max_pwr already is Q5.2 */ | ||
3133 | desired_pwr = clamp_val(desired_pwr, 0, max_pwr); | ||
3134 | if (b43_debug(dev, B43_DBG_XMITPOWER)) { | ||
3135 | b43dbg(dev->wl, | ||
3136 | "[TX power] current = " Q52_FMT | ||
3137 | " dBm, desired = " Q52_FMT | ||
3138 | " dBm, max = " Q52_FMT "\n", | ||
3139 | Q52_ARG(estimated_pwr), | ||
3140 | Q52_ARG(desired_pwr), | ||
3141 | Q52_ARG(max_pwr)); | ||
3142 | } | ||
3143 | |||
3144 | /* Calculate the adjustment delta. */ | ||
3145 | pwr_adjust = desired_pwr - estimated_pwr; | ||
3146 | if (pwr_adjust == 0) | ||
3147 | goto no_adjustment_needed; | ||
3148 | |||
3149 | /* RF attenuation delta. */ | ||
3150 | rfatt_delta = ((pwr_adjust + 7) / 8); | ||
3151 | /* Lower attenuation => Bigger power output. Negate it. */ | ||
3152 | rfatt_delta = -rfatt_delta; | ||
3153 | |||
3154 | /* Baseband attenuation delta. */ | ||
3155 | bbatt_delta = pwr_adjust / 2; | ||
3156 | /* Lower attenuation => Bigger power output. Negate it. */ | ||
3157 | bbatt_delta = -bbatt_delta; | ||
3158 | /* RF att affects power level 4 times as much as | ||
3159 | * Baseband attennuation. Subtract it. */ | ||
3160 | bbatt_delta -= 4 * rfatt_delta; | ||
3161 | |||
3162 | if (b43_debug(dev, B43_DBG_XMITPOWER)) { | ||
3163 | int dbm = pwr_adjust < 0 ? -pwr_adjust : pwr_adjust; | ||
3164 | b43dbg(dev->wl, | ||
3165 | "[TX power deltas] %s" Q52_FMT " dBm => " | ||
3166 | "bbatt-delta = %d, rfatt-delta = %d\n", | ||
3167 | (pwr_adjust < 0 ? "-" : ""), Q52_ARG(dbm), | ||
3168 | bbatt_delta, rfatt_delta); | ||
3169 | } | ||
3170 | /* So do we finally need to adjust something in hardware? */ | ||
3171 | if ((rfatt_delta == 0) && (bbatt_delta == 0)) | ||
3172 | goto no_adjustment_needed; | ||
3173 | |||
3174 | /* Save the deltas for later when we adjust the power. */ | ||
3175 | gphy->bbatt_delta = bbatt_delta; | ||
3176 | gphy->rfatt_delta = rfatt_delta; | ||
3177 | |||
3178 | /* We need to adjust the TX power on the device. */ | ||
3179 | return B43_TXPWR_RES_NEED_ADJUST; | ||
3180 | |||
3181 | no_adjustment_needed: | ||
3182 | return B43_TXPWR_RES_DONE; | ||
3183 | } | ||
3184 | |||
3185 | static void b43_gphy_op_pwork_15sec(struct b43_wldev *dev) | ||
3186 | { | ||
3187 | struct b43_phy *phy = &dev->phy; | ||
3188 | struct b43_phy_g *gphy = phy->g; | ||
3189 | |||
3190 | //TODO: update_aci_moving_average | ||
3191 | if (gphy->aci_enable && gphy->aci_wlan_automatic) { | ||
3192 | b43_mac_suspend(dev); | ||
3193 | if (!gphy->aci_enable && 1 /*TODO: not scanning? */ ) { | ||
3194 | if (0 /*TODO: bunch of conditions */ ) { | ||
3195 | phy->ops->interf_mitigation(dev, | ||
3196 | B43_INTERFMODE_MANUALWLAN); | ||
3197 | } | ||
3198 | } else if (0 /*TODO*/) { | ||
3199 | if (/*(aci_average > 1000) &&*/ !b43_gphy_aci_scan(dev)) | ||
3200 | phy->ops->interf_mitigation(dev, B43_INTERFMODE_NONE); | ||
3201 | } | ||
3202 | b43_mac_enable(dev); | ||
3203 | } else if (gphy->interfmode == B43_INTERFMODE_NONWLAN && | ||
3204 | phy->rev == 1) { | ||
3205 | //TODO: implement rev1 workaround | ||
3206 | } | ||
3207 | b43_lo_g_maintanance_work(dev); | ||
3208 | } | ||
3209 | |||
3210 | static void b43_gphy_op_pwork_60sec(struct b43_wldev *dev) | ||
3211 | { | ||
3212 | struct b43_phy *phy = &dev->phy; | ||
3213 | |||
3214 | if (!(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) | ||
3215 | return; | ||
3216 | |||
3217 | b43_mac_suspend(dev); | ||
3218 | b43_calc_nrssi_slope(dev); | ||
3219 | if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 8)) { | ||
3220 | u8 old_chan = phy->channel; | ||
3221 | |||
3222 | /* VCO Calibration */ | ||
3223 | if (old_chan >= 8) | ||
3224 | b43_switch_channel(dev, 1); | ||
3225 | else | ||
3226 | b43_switch_channel(dev, 13); | ||
3227 | b43_switch_channel(dev, old_chan); | ||
3228 | } | ||
3229 | b43_mac_enable(dev); | ||
3230 | } | ||
3231 | |||
3232 | const struct b43_phy_operations b43_phyops_g = { | ||
3233 | .allocate = b43_gphy_op_allocate, | ||
3234 | .prepare = b43_gphy_op_prepare, | ||
3235 | .init = b43_gphy_op_init, | ||
3236 | .exit = b43_gphy_op_exit, | ||
3237 | .phy_read = b43_gphy_op_read, | ||
3238 | .phy_write = b43_gphy_op_write, | ||
3239 | .radio_read = b43_gphy_op_radio_read, | ||
3240 | .radio_write = b43_gphy_op_radio_write, | ||
3241 | .supports_hwpctl = b43_gphy_op_supports_hwpctl, | ||
3242 | .software_rfkill = b43_gphy_op_software_rfkill, | ||
3243 | .switch_channel = b43_gphy_op_switch_channel, | ||
3244 | .get_default_chan = b43_gphy_op_get_default_chan, | ||
3245 | .set_rx_antenna = b43_gphy_op_set_rx_antenna, | ||
3246 | .interf_mitigation = b43_gphy_op_interf_mitigation, | ||
3247 | .recalc_txpower = b43_gphy_op_recalc_txpower, | ||
3248 | .adjust_txpower = b43_gphy_op_adjust_txpower, | ||
3249 | .pwork_15sec = b43_gphy_op_pwork_15sec, | ||
3250 | .pwork_60sec = b43_gphy_op_pwork_60sec, | ||
3251 | }; | ||
diff --git a/drivers/net/wireless/b43/phy_g.h b/drivers/net/wireless/b43/phy_g.h new file mode 100644 index 000000000000..7f95edea1c63 --- /dev/null +++ b/drivers/net/wireless/b43/phy_g.h | |||
@@ -0,0 +1,209 @@ | |||
1 | #ifndef LINUX_B43_PHY_G_H_ | ||
2 | #define LINUX_B43_PHY_G_H_ | ||
3 | |||
4 | /* OFDM PHY registers are defined in the A-PHY header. */ | ||
5 | #include "phy_a.h" | ||
6 | |||
7 | /* CCK (B) PHY Registers */ | ||
8 | #define B43_PHY_VERSION_CCK B43_PHY_CCK(0x00) /* Versioning register for B-PHY */ | ||
9 | #define B43_PHY_CCKBBANDCFG B43_PHY_CCK(0x01) /* Contains antenna 0/1 control bit */ | ||
10 | #define B43_PHY_PGACTL B43_PHY_CCK(0x15) /* PGA control */ | ||
11 | #define B43_PHY_PGACTL_LPF 0x1000 /* Low pass filter (?) */ | ||
12 | #define B43_PHY_PGACTL_LOWBANDW 0x0040 /* Low bandwidth flag */ | ||
13 | #define B43_PHY_PGACTL_UNKNOWN 0xEFA0 | ||
14 | #define B43_PHY_FBCTL1 B43_PHY_CCK(0x18) /* Frequency bandwidth control 1 */ | ||
15 | #define B43_PHY_ITSSI B43_PHY_CCK(0x29) /* Idle TSSI */ | ||
16 | #define B43_PHY_LO_LEAKAGE B43_PHY_CCK(0x2D) /* Measured LO leakage */ | ||
17 | #define B43_PHY_ENERGY B43_PHY_CCK(0x33) /* Energy */ | ||
18 | #define B43_PHY_SYNCCTL B43_PHY_CCK(0x35) | ||
19 | #define B43_PHY_FBCTL2 B43_PHY_CCK(0x38) /* Frequency bandwidth control 2 */ | ||
20 | #define B43_PHY_DACCTL B43_PHY_CCK(0x60) /* DAC control */ | ||
21 | #define B43_PHY_RCCALOVER B43_PHY_CCK(0x78) /* RC calibration override */ | ||
22 | |||
23 | /* Extended G-PHY Registers */ | ||
24 | #define B43_PHY_CLASSCTL B43_PHY_EXTG(0x02) /* Classify control */ | ||
25 | #define B43_PHY_GTABCTL B43_PHY_EXTG(0x03) /* G-PHY table control (see below) */ | ||
26 | #define B43_PHY_GTABOFF 0x03FF /* G-PHY table offset (see below) */ | ||
27 | #define B43_PHY_GTABNR 0xFC00 /* G-PHY table number (see below) */ | ||
28 | #define B43_PHY_GTABNR_SHIFT 10 | ||
29 | #define B43_PHY_GTABDATA B43_PHY_EXTG(0x04) /* G-PHY table data */ | ||
30 | #define B43_PHY_LO_MASK B43_PHY_EXTG(0x0F) /* Local Oscillator control mask */ | ||
31 | #define B43_PHY_LO_CTL B43_PHY_EXTG(0x10) /* Local Oscillator control */ | ||
32 | #define B43_PHY_RFOVER B43_PHY_EXTG(0x11) /* RF override */ | ||
33 | #define B43_PHY_RFOVERVAL B43_PHY_EXTG(0x12) /* RF override value */ | ||
34 | #define B43_PHY_RFOVERVAL_EXTLNA 0x8000 | ||
35 | #define B43_PHY_RFOVERVAL_LNA 0x7000 | ||
36 | #define B43_PHY_RFOVERVAL_LNA_SHIFT 12 | ||
37 | #define B43_PHY_RFOVERVAL_PGA 0x0F00 | ||
38 | #define B43_PHY_RFOVERVAL_PGA_SHIFT 8 | ||
39 | #define B43_PHY_RFOVERVAL_UNK 0x0010 /* Unknown, always set. */ | ||
40 | #define B43_PHY_RFOVERVAL_TRSWRX 0x00E0 | ||
41 | #define B43_PHY_RFOVERVAL_BW 0x0003 /* Bandwidth flags */ | ||
42 | #define B43_PHY_RFOVERVAL_BW_LPF 0x0001 /* Low Pass Filter */ | ||
43 | #define B43_PHY_RFOVERVAL_BW_LBW 0x0002 /* Low Bandwidth (when set), high when unset */ | ||
44 | #define B43_PHY_ANALOGOVER B43_PHY_EXTG(0x14) /* Analog override */ | ||
45 | #define B43_PHY_ANALOGOVERVAL B43_PHY_EXTG(0x15) /* Analog override value */ | ||
46 | |||
47 | |||
48 | /*** G-PHY table numbers */ | ||
49 | #define B43_GTAB(number, offset) (((number) << B43_PHY_GTABNR_SHIFT) | (offset)) | ||
50 | #define B43_GTAB_NRSSI B43_GTAB(0x00, 0) | ||
51 | #define B43_GTAB_TRFEMW B43_GTAB(0x0C, 0x120) | ||
52 | #define B43_GTAB_ORIGTR B43_GTAB(0x2E, 0x298) | ||
53 | |||
54 | u16 b43_gtab_read(struct b43_wldev *dev, u16 table, u16 offset); | ||
55 | void b43_gtab_write(struct b43_wldev *dev, u16 table, u16 offset, u16 value); | ||
56 | |||
57 | |||
58 | /* Returns the boolean whether "TX Magnification" is enabled. */ | ||
59 | #define has_tx_magnification(phy) \ | ||
60 | (((phy)->rev >= 2) && \ | ||
61 | ((phy)->radio_ver == 0x2050) && \ | ||
62 | ((phy)->radio_rev == 8)) | ||
63 | /* Card uses the loopback gain stuff */ | ||
64 | #define has_loopback_gain(phy) \ | ||
65 | (((phy)->rev > 1) || ((phy)->gmode)) | ||
66 | |||
67 | /* Radio Attenuation (RF Attenuation) */ | ||
68 | struct b43_rfatt { | ||
69 | u8 att; /* Attenuation value */ | ||
70 | bool with_padmix; /* Flag, PAD Mixer enabled. */ | ||
71 | }; | ||
72 | struct b43_rfatt_list { | ||
73 | /* Attenuation values list */ | ||
74 | const struct b43_rfatt *list; | ||
75 | u8 len; | ||
76 | /* Minimum/Maximum attenuation values */ | ||
77 | u8 min_val; | ||
78 | u8 max_val; | ||
79 | }; | ||
80 | |||
81 | /* Returns true, if the values are the same. */ | ||
82 | static inline bool b43_compare_rfatt(const struct b43_rfatt *a, | ||
83 | const struct b43_rfatt *b) | ||
84 | { | ||
85 | return ((a->att == b->att) && | ||
86 | (a->with_padmix == b->with_padmix)); | ||
87 | } | ||
88 | |||
89 | /* Baseband Attenuation */ | ||
90 | struct b43_bbatt { | ||
91 | u8 att; /* Attenuation value */ | ||
92 | }; | ||
93 | struct b43_bbatt_list { | ||
94 | /* Attenuation values list */ | ||
95 | const struct b43_bbatt *list; | ||
96 | u8 len; | ||
97 | /* Minimum/Maximum attenuation values */ | ||
98 | u8 min_val; | ||
99 | u8 max_val; | ||
100 | }; | ||
101 | |||
102 | /* Returns true, if the values are the same. */ | ||
103 | static inline bool b43_compare_bbatt(const struct b43_bbatt *a, | ||
104 | const struct b43_bbatt *b) | ||
105 | { | ||
106 | return (a->att == b->att); | ||
107 | } | ||
108 | |||
109 | /* tx_control bits. */ | ||
110 | #define B43_TXCTL_PA3DB 0x40 /* PA Gain 3dB */ | ||
111 | #define B43_TXCTL_PA2DB 0x20 /* PA Gain 2dB */ | ||
112 | #define B43_TXCTL_TXMIX 0x10 /* TX Mixer Gain */ | ||
113 | |||
114 | struct b43_txpower_lo_control; | ||
115 | |||
116 | struct b43_phy_g { | ||
117 | bool initialised; | ||
118 | |||
119 | /* ACI (adjacent channel interference) flags. */ | ||
120 | bool aci_enable; | ||
121 | bool aci_wlan_automatic; | ||
122 | bool aci_hw_rssi; | ||
123 | |||
124 | /* Radio switched on/off */ | ||
125 | bool radio_on; | ||
126 | struct { | ||
127 | /* Values saved when turning the radio off. | ||
128 | * They are needed when turning it on again. */ | ||
129 | bool valid; | ||
130 | u16 rfover; | ||
131 | u16 rfoverval; | ||
132 | } radio_off_context; | ||
133 | |||
134 | u16 minlowsig[2]; | ||
135 | u16 minlowsigpos[2]; | ||
136 | |||
137 | /* Pointer to the table used to convert a | ||
138 | * TSSI value to dBm-Q5.2 */ | ||
139 | const s8 *tssi2dbm; | ||
140 | /* tssi2dbm is kmalloc()ed. Only used for free()ing. */ | ||
141 | bool dyn_tssi_tbl; | ||
142 | /* Target idle TSSI */ | ||
143 | int tgt_idle_tssi; | ||
144 | /* Current idle TSSI */ | ||
145 | int cur_idle_tssi; | ||
146 | /* The current average TSSI. | ||
147 | * Needs irq_lock, as it's updated in the IRQ path. */ | ||
148 | u8 average_tssi; | ||
149 | /* Current TX power level attenuation control values */ | ||
150 | struct b43_bbatt bbatt; | ||
151 | struct b43_rfatt rfatt; | ||
152 | u8 tx_control; /* B43_TXCTL_XXX */ | ||
153 | /* The calculated attenuation deltas that are used later | ||
154 | * when adjusting the actual power output. */ | ||
155 | int bbatt_delta; | ||
156 | int rfatt_delta; | ||
157 | |||
158 | /* LocalOscillator control values. */ | ||
159 | struct b43_txpower_lo_control *lo_control; | ||
160 | /* Values from b43_calc_loopback_gain() */ | ||
161 | s16 max_lb_gain; /* Maximum Loopback gain in hdB */ | ||
162 | s16 trsw_rx_gain; /* TRSW RX gain in hdB */ | ||
163 | s16 lna_lod_gain; /* LNA lod */ | ||
164 | s16 lna_gain; /* LNA */ | ||
165 | s16 pga_gain; /* PGA */ | ||
166 | |||
167 | /* Current Interference Mitigation mode */ | ||
168 | int interfmode; | ||
169 | /* Stack of saved values from the Interference Mitigation code. | ||
170 | * Each value in the stack is layed out as follows: | ||
171 | * bit 0-11: offset | ||
172 | * bit 12-15: register ID | ||
173 | * bit 16-32: value | ||
174 | * register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT | ||
175 | */ | ||
176 | #define B43_INTERFSTACK_SIZE 26 | ||
177 | u32 interfstack[B43_INTERFSTACK_SIZE]; //FIXME: use a data structure | ||
178 | |||
179 | /* Saved values from the NRSSI Slope calculation */ | ||
180 | s16 nrssi[2]; | ||
181 | s32 nrssislope; | ||
182 | /* In memory nrssi lookup table. */ | ||
183 | s8 nrssi_lt[64]; | ||
184 | |||
185 | u16 lofcal; | ||
186 | |||
187 | u16 initval; //FIXME rename? | ||
188 | |||
189 | /* The device does address auto increment for the OFDM tables. | ||
190 | * We cache the previously used address here and omit the address | ||
191 | * write on the next table access, if possible. */ | ||
192 | u16 ofdmtab_addr; /* The address currently set in hardware. */ | ||
193 | enum { /* The last data flow direction. */ | ||
194 | B43_OFDMTAB_DIRECTION_UNKNOWN = 0, | ||
195 | B43_OFDMTAB_DIRECTION_READ, | ||
196 | B43_OFDMTAB_DIRECTION_WRITE, | ||
197 | } ofdmtab_addr_direction; | ||
198 | }; | ||
199 | |||
200 | void b43_gphy_set_baseband_attenuation(struct b43_wldev *dev, | ||
201 | u16 baseband_attenuation); | ||
202 | void b43_gphy_channel_switch(struct b43_wldev *dev, | ||
203 | unsigned int channel, | ||
204 | bool synthetic_pu_workaround); | ||
205 | |||
206 | struct b43_phy_operations; | ||
207 | extern const struct b43_phy_operations b43_phyops_g; | ||
208 | |||
209 | #endif /* LINUX_B43_PHY_G_H_ */ | ||
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index fec5645944a4..7b9e99adb8c3 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c | |||
@@ -24,6 +24,7 @@ | |||
24 | 24 | ||
25 | #include "rfkill.h" | 25 | #include "rfkill.h" |
26 | #include "b43.h" | 26 | #include "b43.h" |
27 | #include "phy_common.h" | ||
27 | 28 | ||
28 | #include <linux/kmod.h> | 29 | #include <linux/kmod.h> |
29 | 30 | ||
@@ -114,11 +115,11 @@ static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state) | |||
114 | goto out_unlock; | 115 | goto out_unlock; |
115 | } | 116 | } |
116 | if (!dev->phy.radio_on) | 117 | if (!dev->phy.radio_on) |
117 | b43_radio_turn_on(dev); | 118 | b43_software_rfkill(dev, state); |
118 | break; | 119 | break; |
119 | case RFKILL_STATE_SOFT_BLOCKED: | 120 | case RFKILL_STATE_SOFT_BLOCKED: |
120 | if (dev->phy.radio_on) | 121 | if (dev->phy.radio_on) |
121 | b43_radio_turn_off(dev, 0); | 122 | b43_software_rfkill(dev, state); |
122 | break; | 123 | break; |
123 | default: | 124 | default: |
124 | b43warn(wl, "Received unexpected rfkill state %d.\n", state); | 125 | b43warn(wl, "Received unexpected rfkill state %d.\n", state); |
diff --git a/drivers/net/wireless/b43/sysfs.c b/drivers/net/wireless/b43/sysfs.c index 275095b8cbe7..5adaa3692d75 100644 --- a/drivers/net/wireless/b43/sysfs.c +++ b/drivers/net/wireless/b43/sysfs.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include "b43.h" | 29 | #include "b43.h" |
30 | #include "sysfs.h" | 30 | #include "sysfs.h" |
31 | #include "main.h" | 31 | #include "main.h" |
32 | #include "phy.h" | 32 | #include "phy_common.h" |
33 | 33 | ||
34 | #define GENERIC_FILESIZE 64 | 34 | #define GENERIC_FILESIZE 64 |
35 | 35 | ||
@@ -59,7 +59,12 @@ static ssize_t b43_attr_interfmode_show(struct device *dev, | |||
59 | 59 | ||
60 | mutex_lock(&wldev->wl->mutex); | 60 | mutex_lock(&wldev->wl->mutex); |
61 | 61 | ||
62 | switch (wldev->phy.interfmode) { | 62 | if (wldev->phy.type != B43_PHYTYPE_G) { |
63 | mutex_unlock(&wldev->wl->mutex); | ||
64 | return -ENOSYS; | ||
65 | } | ||
66 | |||
67 | switch (wldev->phy.g->interfmode) { | ||
63 | case B43_INTERFMODE_NONE: | 68 | case B43_INTERFMODE_NONE: |
64 | count = | 69 | count = |
65 | snprintf(buf, PAGE_SIZE, | 70 | snprintf(buf, PAGE_SIZE, |
@@ -117,11 +122,15 @@ static ssize_t b43_attr_interfmode_store(struct device *dev, | |||
117 | mutex_lock(&wldev->wl->mutex); | 122 | mutex_lock(&wldev->wl->mutex); |
118 | spin_lock_irqsave(&wldev->wl->irq_lock, flags); | 123 | spin_lock_irqsave(&wldev->wl->irq_lock, flags); |
119 | 124 | ||
120 | err = b43_radio_set_interference_mitigation(wldev, mode); | 125 | if (wldev->phy.ops->interf_mitigation) { |
121 | if (err) { | 126 | err = wldev->phy.ops->interf_mitigation(wldev, mode); |
122 | b43err(wldev->wl, "Interference Mitigation not " | 127 | if (err) { |
123 | "supported by device\n"); | 128 | b43err(wldev->wl, "Interference Mitigation not " |
124 | } | 129 | "supported by device\n"); |
130 | } | ||
131 | } else | ||
132 | err = -ENOSYS; | ||
133 | |||
125 | mmiowb(); | 134 | mmiowb(); |
126 | spin_unlock_irqrestore(&wldev->wl->irq_lock, flags); | 135 | spin_unlock_irqrestore(&wldev->wl->irq_lock, flags); |
127 | mutex_unlock(&wldev->wl->mutex); | 136 | mutex_unlock(&wldev->wl->mutex); |
diff --git a/drivers/net/wireless/b43/tables.c b/drivers/net/wireless/b43/tables.c index 3f5ea06bf13c..1ef9a6463ec6 100644 --- a/drivers/net/wireless/b43/tables.c +++ b/drivers/net/wireless/b43/tables.c | |||
@@ -27,7 +27,8 @@ | |||
27 | 27 | ||
28 | #include "b43.h" | 28 | #include "b43.h" |
29 | #include "tables.h" | 29 | #include "tables.h" |
30 | #include "phy.h" | 30 | #include "phy_g.h" |
31 | |||
31 | 32 | ||
32 | const u32 b43_tab_rotor[] = { | 33 | const u32 b43_tab_rotor[] = { |
33 | 0xFEB93FFD, 0xFEC63FFD, /* 0 */ | 34 | 0xFEB93FFD, 0xFEC63FFD, /* 0 */ |
@@ -377,17 +378,17 @@ static inline void assert_sizes(void) | |||
377 | 378 | ||
378 | u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset) | 379 | u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset) |
379 | { | 380 | { |
380 | struct b43_phy *phy = &dev->phy; | 381 | struct b43_phy_g *gphy = dev->phy.g; |
381 | u16 addr; | 382 | u16 addr; |
382 | 383 | ||
383 | addr = table + offset; | 384 | addr = table + offset; |
384 | if ((phy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) || | 385 | if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) || |
385 | (addr - 1 != phy->ofdmtab_addr)) { | 386 | (addr - 1 != gphy->ofdmtab_addr)) { |
386 | /* The hardware has a different address in memory. Update it. */ | 387 | /* The hardware has a different address in memory. Update it. */ |
387 | b43_phy_write(dev, B43_PHY_OTABLECTL, addr); | 388 | b43_phy_write(dev, B43_PHY_OTABLECTL, addr); |
388 | phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ; | 389 | gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ; |
389 | } | 390 | } |
390 | phy->ofdmtab_addr = addr; | 391 | gphy->ofdmtab_addr = addr; |
391 | 392 | ||
392 | return b43_phy_read(dev, B43_PHY_OTABLEI); | 393 | return b43_phy_read(dev, B43_PHY_OTABLEI); |
393 | 394 | ||
@@ -398,34 +399,34 @@ u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset) | |||
398 | void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table, | 399 | void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table, |
399 | u16 offset, u16 value) | 400 | u16 offset, u16 value) |
400 | { | 401 | { |
401 | struct b43_phy *phy = &dev->phy; | 402 | struct b43_phy_g *gphy = dev->phy.g; |
402 | u16 addr; | 403 | u16 addr; |
403 | 404 | ||
404 | addr = table + offset; | 405 | addr = table + offset; |
405 | if ((phy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) || | 406 | if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) || |
406 | (addr - 1 != phy->ofdmtab_addr)) { | 407 | (addr - 1 != gphy->ofdmtab_addr)) { |
407 | /* The hardware has a different address in memory. Update it. */ | 408 | /* The hardware has a different address in memory. Update it. */ |
408 | b43_phy_write(dev, B43_PHY_OTABLECTL, addr); | 409 | b43_phy_write(dev, B43_PHY_OTABLECTL, addr); |
409 | phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE; | 410 | gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE; |
410 | } | 411 | } |
411 | phy->ofdmtab_addr = addr; | 412 | gphy->ofdmtab_addr = addr; |
412 | b43_phy_write(dev, B43_PHY_OTABLEI, value); | 413 | b43_phy_write(dev, B43_PHY_OTABLEI, value); |
413 | } | 414 | } |
414 | 415 | ||
415 | u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset) | 416 | u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset) |
416 | { | 417 | { |
417 | struct b43_phy *phy = &dev->phy; | 418 | struct b43_phy_g *gphy = dev->phy.g; |
418 | u32 ret; | 419 | u32 ret; |
419 | u16 addr; | 420 | u16 addr; |
420 | 421 | ||
421 | addr = table + offset; | 422 | addr = table + offset; |
422 | if ((phy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) || | 423 | if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) || |
423 | (addr - 1 != phy->ofdmtab_addr)) { | 424 | (addr - 1 != gphy->ofdmtab_addr)) { |
424 | /* The hardware has a different address in memory. Update it. */ | 425 | /* The hardware has a different address in memory. Update it. */ |
425 | b43_phy_write(dev, B43_PHY_OTABLECTL, addr); | 426 | b43_phy_write(dev, B43_PHY_OTABLECTL, addr); |
426 | phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ; | 427 | gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ; |
427 | } | 428 | } |
428 | phy->ofdmtab_addr = addr; | 429 | gphy->ofdmtab_addr = addr; |
429 | ret = b43_phy_read(dev, B43_PHY_OTABLEQ); | 430 | ret = b43_phy_read(dev, B43_PHY_OTABLEQ); |
430 | ret <<= 16; | 431 | ret <<= 16; |
431 | ret |= b43_phy_read(dev, B43_PHY_OTABLEI); | 432 | ret |= b43_phy_read(dev, B43_PHY_OTABLEI); |
@@ -436,17 +437,17 @@ u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset) | |||
436 | void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table, | 437 | void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table, |
437 | u16 offset, u32 value) | 438 | u16 offset, u32 value) |
438 | { | 439 | { |
439 | struct b43_phy *phy = &dev->phy; | 440 | struct b43_phy_g *gphy = dev->phy.g; |
440 | u16 addr; | 441 | u16 addr; |
441 | 442 | ||
442 | addr = table + offset; | 443 | addr = table + offset; |
443 | if ((phy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) || | 444 | if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) || |
444 | (addr - 1 != phy->ofdmtab_addr)) { | 445 | (addr - 1 != gphy->ofdmtab_addr)) { |
445 | /* The hardware has a different address in memory. Update it. */ | 446 | /* The hardware has a different address in memory. Update it. */ |
446 | b43_phy_write(dev, B43_PHY_OTABLECTL, addr); | 447 | b43_phy_write(dev, B43_PHY_OTABLECTL, addr); |
447 | phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE; | 448 | gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE; |
448 | } | 449 | } |
449 | phy->ofdmtab_addr = addr; | 450 | gphy->ofdmtab_addr = addr; |
450 | 451 | ||
451 | b43_phy_write(dev, B43_PHY_OTABLEI, value); | 452 | b43_phy_write(dev, B43_PHY_OTABLEI, value); |
452 | b43_phy_write(dev, B43_PHY_OTABLEQ, (value >> 16)); | 453 | b43_phy_write(dev, B43_PHY_OTABLEQ, (value >> 16)); |
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index 2aa57551786a..1de2c2e2e14c 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c | |||
@@ -24,7 +24,7 @@ | |||
24 | 24 | ||
25 | #include "b43.h" | 25 | #include "b43.h" |
26 | #include "tables_nphy.h" | 26 | #include "tables_nphy.h" |
27 | #include "phy.h" | 27 | #include "phy_common.h" |
28 | #include "nphy.h" | 28 | #include "nphy.h" |
29 | 29 | ||
30 | 30 | ||
diff --git a/drivers/net/wireless/b43/wa.c b/drivers/net/wireless/b43/wa.c index daa94211f838..0c0fb15abb9f 100644 --- a/drivers/net/wireless/b43/wa.c +++ b/drivers/net/wireless/b43/wa.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include "b43.h" | 27 | #include "b43.h" |
28 | #include "main.h" | 28 | #include "main.h" |
29 | #include "tables.h" | 29 | #include "tables.h" |
30 | #include "phy.h" | 30 | #include "phy_common.h" |
31 | #include "wa.h" | 31 | #include "wa.h" |
32 | 32 | ||
33 | static void b43_wa_papd(struct b43_wldev *dev) | 33 | static void b43_wa_papd(struct b43_wldev *dev) |
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 9dda8169f7cc..5e0b71c3ad02 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c | |||
@@ -28,7 +28,7 @@ | |||
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include "xmit.h" | 30 | #include "xmit.h" |
31 | #include "phy.h" | 31 | #include "phy_common.h" |
32 | #include "dma.h" | 32 | #include "dma.h" |
33 | #include "pio.h" | 33 | #include "pio.h" |
34 | 34 | ||
@@ -431,6 +431,7 @@ static s8 b43_rssi_postprocess(struct b43_wldev *dev, | |||
431 | int adjust_2053, int adjust_2050) | 431 | int adjust_2053, int adjust_2050) |
432 | { | 432 | { |
433 | struct b43_phy *phy = &dev->phy; | 433 | struct b43_phy *phy = &dev->phy; |
434 | struct b43_phy_g *gphy = phy->g; | ||
434 | s32 tmp; | 435 | s32 tmp; |
435 | 436 | ||
436 | switch (phy->radio_ver) { | 437 | switch (phy->radio_ver) { |
@@ -450,7 +451,8 @@ static s8 b43_rssi_postprocess(struct b43_wldev *dev, | |||
450 | boardflags_lo & B43_BFL_RSSI) { | 451 | boardflags_lo & B43_BFL_RSSI) { |
451 | if (in_rssi > 63) | 452 | if (in_rssi > 63) |
452 | in_rssi = 63; | 453 | in_rssi = 63; |
453 | tmp = phy->nrssi_lt[in_rssi]; | 454 | B43_WARN_ON(phy->type != B43_PHYTYPE_G); |
455 | tmp = gphy->nrssi_lt[in_rssi]; | ||
454 | tmp = 31 - tmp; | 456 | tmp = 31 - tmp; |
455 | tmp *= -131; | 457 | tmp *= -131; |
456 | tmp /= 128; | 458 | tmp /= 128; |
@@ -678,6 +680,8 @@ void b43_handle_txstatus(struct b43_wldev *dev, | |||
678 | b43_pio_handle_txstatus(dev, status); | 680 | b43_pio_handle_txstatus(dev, status); |
679 | else | 681 | else |
680 | b43_dma_handle_txstatus(dev, status); | 682 | b43_dma_handle_txstatus(dev, status); |
683 | |||
684 | b43_phy_txpower_check(dev, 0); | ||
681 | } | 685 | } |
682 | 686 | ||
683 | /* Fill out the mac80211 TXstatus report based on the b43-specific | 687 | /* Fill out the mac80211 TXstatus report based on the b43-specific |
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 2541c81932f0..1cb77db5c292 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/moduleparam.h> | 34 | #include <linux/moduleparam.h> |
35 | #include <linux/if_arp.h> | 35 | #include <linux/if_arp.h> |
36 | #include <linux/etherdevice.h> | 36 | #include <linux/etherdevice.h> |
37 | #include <linux/version.h> | ||
38 | #include <linux/firmware.h> | 37 | #include <linux/firmware.h> |
39 | #include <linux/wireless.h> | 38 | #include <linux/wireless.h> |
40 | #include <linux/workqueue.h> | 39 | #include <linux/workqueue.h> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index d3336966b6b5..705c65bed9fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c | |||
@@ -27,7 +27,6 @@ | |||
27 | 27 | ||
28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/version.h> | ||
31 | #include <linux/init.h> | 30 | #include <linux/init.h> |
32 | #include <linux/pci.h> | 31 | #include <linux/pci.h> |
33 | #include <linux/dma-mapping.h> | 32 | #include <linux/dma-mapping.h> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index cb11c4a4d691..4eee1b163cd2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c | |||
@@ -27,7 +27,6 @@ | |||
27 | 27 | ||
28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/version.h> | ||
31 | #include <linux/init.h> | 30 | #include <linux/init.h> |
32 | #include <linux/pci.h> | 31 | #include <linux/pci.h> |
33 | #include <linux/dma-mapping.h> | 32 | #include <linux/dma-mapping.h> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c index e5e5846e9f25..5d642298f04c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c | |||
@@ -27,7 +27,6 @@ | |||
27 | *****************************************************************************/ | 27 | *****************************************************************************/ |
28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/version.h> | ||
31 | #include <linux/init.h> | 30 | #include <linux/init.h> |
32 | 31 | ||
33 | #include <net/mac80211.h> | 32 | #include <net/mac80211.h> |
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index a267d6e65f03..4ddf44b2758b 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include "scan.h" | 8 | #include "scan.h" |
9 | #include "cmd.h" | 9 | #include "cmd.h" |
10 | 10 | ||
11 | static int lbs_adhoc_post(struct lbs_private *priv, struct cmd_header *resp); | ||
11 | 12 | ||
12 | static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) = | 13 | static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) = |
13 | { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | 14 | { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; |
@@ -20,12 +21,88 @@ static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) = | |||
20 | #define CAPINFO_MASK (~(0xda00)) | 21 | #define CAPINFO_MASK (~(0xda00)) |
21 | 22 | ||
22 | 23 | ||
24 | /** | ||
25 | * @brief This function finds common rates between rates and card rates. | ||
26 | * | ||
27 | * It will fill common rates in rates as output if found. | ||
28 | * | ||
29 | * NOTE: Setting the MSB of the basic rates need to be taken | ||
30 | * care, either before or after calling this function | ||
31 | * | ||
32 | * @param priv A pointer to struct lbs_private structure | ||
33 | * @param rates the buffer which keeps input and output | ||
34 | * @param rates_size the size of rate1 buffer; new size of buffer on return | ||
35 | * | ||
36 | * @return 0 on success, or -1 on error | ||
37 | */ | ||
38 | static int get_common_rates(struct lbs_private *priv, | ||
39 | u8 *rates, | ||
40 | u16 *rates_size) | ||
41 | { | ||
42 | u8 *card_rates = lbs_bg_rates; | ||
43 | size_t num_card_rates = sizeof(lbs_bg_rates); | ||
44 | int ret = 0, i, j; | ||
45 | u8 tmp[30]; | ||
46 | size_t tmp_size = 0; | ||
47 | |||
48 | /* For each rate in card_rates that exists in rate1, copy to tmp */ | ||
49 | for (i = 0; card_rates[i] && (i < num_card_rates); i++) { | ||
50 | for (j = 0; rates[j] && (j < *rates_size); j++) { | ||
51 | if (rates[j] == card_rates[i]) | ||
52 | tmp[tmp_size++] = card_rates[i]; | ||
53 | } | ||
54 | } | ||
55 | |||
56 | lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size); | ||
57 | lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, num_card_rates); | ||
58 | lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size); | ||
59 | lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate); | ||
60 | |||
61 | if (!priv->enablehwauto) { | ||
62 | for (i = 0; i < tmp_size; i++) { | ||
63 | if (tmp[i] == priv->cur_rate) | ||
64 | goto done; | ||
65 | } | ||
66 | lbs_pr_alert("Previously set fixed data rate %#x isn't " | ||
67 | "compatible with the network.\n", priv->cur_rate); | ||
68 | ret = -1; | ||
69 | goto done; | ||
70 | } | ||
71 | ret = 0; | ||
72 | |||
73 | done: | ||
74 | memset(rates, 0, *rates_size); | ||
75 | *rates_size = min_t(int, tmp_size, *rates_size); | ||
76 | memcpy(rates, tmp, *rates_size); | ||
77 | return ret; | ||
78 | } | ||
79 | |||
80 | |||
81 | /** | ||
82 | * @brief Sets the MSB on basic rates as the firmware requires | ||
83 | * | ||
84 | * Scan through an array and set the MSB for basic data rates. | ||
85 | * | ||
86 | * @param rates buffer of data rates | ||
87 | * @param len size of buffer | ||
88 | */ | ||
89 | static void lbs_set_basic_rate_flags(u8 *rates, size_t len) | ||
90 | { | ||
91 | int i; | ||
92 | |||
93 | for (i = 0; i < len; i++) { | ||
94 | if (rates[i] == 0x02 || rates[i] == 0x04 || | ||
95 | rates[i] == 0x0b || rates[i] == 0x16) | ||
96 | rates[i] |= 0x80; | ||
97 | } | ||
98 | } | ||
99 | |||
23 | 100 | ||
24 | /** | 101 | /** |
25 | * @brief Associate to a specific BSS discovered in a scan | 102 | * @brief Associate to a specific BSS discovered in a scan |
26 | * | 103 | * |
27 | * @param priv A pointer to struct lbs_private structure | 104 | * @param priv A pointer to struct lbs_private structure |
28 | * @param pbssdesc Pointer to the BSS descriptor to associate with. | 105 | * @param assoc_req The association request describing the BSS to associate with |
29 | * | 106 | * |
30 | * @return 0-success, otherwise fail | 107 | * @return 0-success, otherwise fail |
31 | */ | 108 | */ |
@@ -33,29 +110,29 @@ static int lbs_associate(struct lbs_private *priv, | |||
33 | struct assoc_request *assoc_req) | 110 | struct assoc_request *assoc_req) |
34 | { | 111 | { |
35 | int ret; | 112 | int ret; |
113 | u8 preamble = RADIO_PREAMBLE_LONG; | ||
36 | 114 | ||
37 | lbs_deb_enter(LBS_DEB_ASSOC); | 115 | lbs_deb_enter(LBS_DEB_ASSOC); |
38 | 116 | ||
39 | ret = lbs_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE, | 117 | ret = lbs_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE, |
40 | 0, CMD_OPTION_WAITFORRSP, | 118 | 0, CMD_OPTION_WAITFORRSP, |
41 | 0, assoc_req->bss.bssid); | 119 | 0, assoc_req->bss.bssid); |
42 | |||
43 | if (ret) | 120 | if (ret) |
44 | goto done; | 121 | goto out; |
45 | 122 | ||
46 | /* set preamble to firmware */ | 123 | /* Use short preamble only when both the BSS and firmware support it */ |
47 | if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && | 124 | if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && |
48 | (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) | 125 | (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) |
49 | priv->preamble = CMD_TYPE_SHORT_PREAMBLE; | 126 | preamble = RADIO_PREAMBLE_SHORT; |
50 | else | ||
51 | priv->preamble = CMD_TYPE_LONG_PREAMBLE; | ||
52 | 127 | ||
53 | lbs_set_radio_control(priv); | 128 | ret = lbs_set_radio(priv, preamble, 1); |
129 | if (ret) | ||
130 | goto out; | ||
54 | 131 | ||
55 | ret = lbs_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE, | 132 | ret = lbs_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE, |
56 | 0, CMD_OPTION_WAITFORRSP, 0, assoc_req); | 133 | 0, CMD_OPTION_WAITFORRSP, 0, assoc_req); |
57 | 134 | ||
58 | done: | 135 | out: |
59 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | 136 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); |
60 | return ret; | 137 | return ret; |
61 | } | 138 | } |
@@ -64,17 +141,22 @@ done: | |||
64 | * @brief Join an adhoc network found in a previous scan | 141 | * @brief Join an adhoc network found in a previous scan |
65 | * | 142 | * |
66 | * @param priv A pointer to struct lbs_private structure | 143 | * @param priv A pointer to struct lbs_private structure |
67 | * @param pbssdesc Pointer to a BSS descriptor found in a previous scan | 144 | * @param assoc_req The association request describing the BSS to join |
68 | * to attempt to join | ||
69 | * | 145 | * |
70 | * @return 0--success, -1--fail | 146 | * @return 0 on success, error on failure |
71 | */ | 147 | */ |
72 | static int lbs_join_adhoc_network(struct lbs_private *priv, | 148 | static int lbs_adhoc_join(struct lbs_private *priv, |
73 | struct assoc_request *assoc_req) | 149 | struct assoc_request *assoc_req) |
74 | { | 150 | { |
151 | struct cmd_ds_802_11_ad_hoc_join cmd; | ||
75 | struct bss_descriptor *bss = &assoc_req->bss; | 152 | struct bss_descriptor *bss = &assoc_req->bss; |
153 | u8 preamble = RADIO_PREAMBLE_LONG; | ||
154 | DECLARE_MAC_BUF(mac); | ||
155 | u16 ratesize = 0; | ||
76 | int ret = 0; | 156 | int ret = 0; |
77 | 157 | ||
158 | lbs_deb_enter(LBS_DEB_ASSOC); | ||
159 | |||
78 | lbs_deb_join("current SSID '%s', ssid length %u\n", | 160 | lbs_deb_join("current SSID '%s', ssid length %u\n", |
79 | escape_essid(priv->curbssparams.ssid, | 161 | escape_essid(priv->curbssparams.ssid, |
80 | priv->curbssparams.ssid_len), | 162 | priv->curbssparams.ssid_len), |
@@ -106,29 +188,106 @@ static int lbs_join_adhoc_network(struct lbs_private *priv, | |||
106 | goto out; | 188 | goto out; |
107 | } | 189 | } |
108 | 190 | ||
109 | /* Use shortpreamble only when both creator and card supports | 191 | /* Use short preamble only when both the BSS and firmware support it */ |
110 | short preamble */ | 192 | if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && |
111 | if (!(bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) || | 193 | (bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) { |
112 | !(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) { | ||
113 | lbs_deb_join("AdhocJoin: Long preamble\n"); | ||
114 | priv->preamble = CMD_TYPE_LONG_PREAMBLE; | ||
115 | } else { | ||
116 | lbs_deb_join("AdhocJoin: Short preamble\n"); | 194 | lbs_deb_join("AdhocJoin: Short preamble\n"); |
117 | priv->preamble = CMD_TYPE_SHORT_PREAMBLE; | 195 | preamble = RADIO_PREAMBLE_SHORT; |
118 | } | 196 | } |
119 | 197 | ||
120 | lbs_set_radio_control(priv); | 198 | ret = lbs_set_radio(priv, preamble, 1); |
199 | if (ret) | ||
200 | goto out; | ||
121 | 201 | ||
122 | lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel); | 202 | lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel); |
123 | lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band); | 203 | lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band); |
124 | 204 | ||
125 | priv->adhoccreate = 0; | 205 | priv->adhoccreate = 0; |
206 | priv->curbssparams.channel = bss->channel; | ||
126 | 207 | ||
127 | ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_JOIN, | 208 | /* Build the join command */ |
128 | 0, CMD_OPTION_WAITFORRSP, | 209 | memset(&cmd, 0, sizeof(cmd)); |
129 | OID_802_11_SSID, assoc_req); | 210 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); |
211 | |||
212 | cmd.bss.type = CMD_BSS_TYPE_IBSS; | ||
213 | cmd.bss.beaconperiod = cpu_to_le16(bss->beaconperiod); | ||
214 | |||
215 | memcpy(&cmd.bss.bssid, &bss->bssid, ETH_ALEN); | ||
216 | memcpy(&cmd.bss.ssid, &bss->ssid, bss->ssid_len); | ||
217 | |||
218 | memcpy(&cmd.bss.phyparamset, &bss->phyparamset, | ||
219 | sizeof(union ieeetypes_phyparamset)); | ||
220 | |||
221 | memcpy(&cmd.bss.ssparamset, &bss->ssparamset, | ||
222 | sizeof(union IEEEtypes_ssparamset)); | ||
223 | |||
224 | cmd.bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK); | ||
225 | lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n", | ||
226 | bss->capability, CAPINFO_MASK); | ||
227 | |||
228 | /* information on BSSID descriptor passed to FW */ | ||
229 | lbs_deb_join("ADHOC_J_CMD: BSSID = %s, SSID = '%s'\n", | ||
230 | print_mac(mac, cmd.bss.bssid), cmd.bss.ssid); | ||
231 | |||
232 | /* Only v8 and below support setting these */ | ||
233 | if (priv->fwrelease < 0x09000000) { | ||
234 | /* failtimeout */ | ||
235 | cmd.failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT); | ||
236 | /* probedelay */ | ||
237 | cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME); | ||
238 | } | ||
239 | |||
240 | /* Copy Data rates from the rates recorded in scan response */ | ||
241 | memset(cmd.bss.rates, 0, sizeof(cmd.bss.rates)); | ||
242 | ratesize = min_t(u16, sizeof(cmd.bss.rates), MAX_RATES); | ||
243 | memcpy(cmd.bss.rates, bss->rates, ratesize); | ||
244 | if (get_common_rates(priv, cmd.bss.rates, &ratesize)) { | ||
245 | lbs_deb_join("ADHOC_JOIN: get_common_rates returned error.\n"); | ||
246 | ret = -1; | ||
247 | goto out; | ||
248 | } | ||
249 | |||
250 | /* Copy the ad-hoc creation rates into Current BSS state structure */ | ||
251 | memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); | ||
252 | memcpy(&priv->curbssparams.rates, cmd.bss.rates, ratesize); | ||
253 | |||
254 | /* Set MSB on basic rates as the firmware requires, but _after_ | ||
255 | * copying to current bss rates. | ||
256 | */ | ||
257 | lbs_set_basic_rate_flags(cmd.bss.rates, ratesize); | ||
258 | |||
259 | cmd.bss.ssparamset.ibssparamset.atimwindow = cpu_to_le16(bss->atimwindow); | ||
260 | |||
261 | if (assoc_req->secinfo.wep_enabled) { | ||
262 | u16 tmp = le16_to_cpu(cmd.bss.capability); | ||
263 | tmp |= WLAN_CAPABILITY_PRIVACY; | ||
264 | cmd.bss.capability = cpu_to_le16(tmp); | ||
265 | } | ||
266 | |||
267 | if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { | ||
268 | __le32 local_ps_mode = cpu_to_le32(LBS802_11POWERMODECAM); | ||
269 | |||
270 | /* wake up first */ | ||
271 | ret = lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE, | ||
272 | CMD_ACT_SET, 0, 0, | ||
273 | &local_ps_mode); | ||
274 | if (ret) { | ||
275 | ret = -1; | ||
276 | goto out; | ||
277 | } | ||
278 | } | ||
279 | |||
280 | if (lbs_parse_dnld_countryinfo_11d(priv, bss)) { | ||
281 | ret = -1; | ||
282 | goto out; | ||
283 | } | ||
284 | |||
285 | ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd); | ||
286 | if (ret == 0) | ||
287 | ret = lbs_adhoc_post(priv, (struct cmd_header *) &cmd); | ||
130 | 288 | ||
131 | out: | 289 | out: |
290 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | ||
132 | return ret; | 291 | return ret; |
133 | } | 292 | } |
134 | 293 | ||
@@ -136,39 +295,131 @@ out: | |||
136 | * @brief Start an Adhoc Network | 295 | * @brief Start an Adhoc Network |
137 | * | 296 | * |
138 | * @param priv A pointer to struct lbs_private structure | 297 | * @param priv A pointer to struct lbs_private structure |
139 | * @param adhocssid The ssid of the Adhoc Network | 298 | * @param assoc_req The association request describing the BSS to start |
140 | * @return 0--success, -1--fail | 299 | * |
300 | * @return 0 on success, error on failure | ||
141 | */ | 301 | */ |
142 | static int lbs_start_adhoc_network(struct lbs_private *priv, | 302 | static int lbs_adhoc_start(struct lbs_private *priv, |
143 | struct assoc_request *assoc_req) | 303 | struct assoc_request *assoc_req) |
144 | { | 304 | { |
305 | struct cmd_ds_802_11_ad_hoc_start cmd; | ||
306 | u8 preamble = RADIO_PREAMBLE_LONG; | ||
307 | size_t ratesize = 0; | ||
308 | u16 tmpcap = 0; | ||
145 | int ret = 0; | 309 | int ret = 0; |
146 | 310 | ||
147 | priv->adhoccreate = 1; | 311 | lbs_deb_enter(LBS_DEB_ASSOC); |
148 | 312 | ||
149 | if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) { | 313 | if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) { |
150 | lbs_deb_join("AdhocStart: Short preamble\n"); | 314 | lbs_deb_join("ADHOC_START: Will use short preamble\n"); |
151 | priv->preamble = CMD_TYPE_SHORT_PREAMBLE; | 315 | preamble = RADIO_PREAMBLE_SHORT; |
152 | } else { | ||
153 | lbs_deb_join("AdhocStart: Long preamble\n"); | ||
154 | priv->preamble = CMD_TYPE_LONG_PREAMBLE; | ||
155 | } | 316 | } |
156 | 317 | ||
157 | lbs_set_radio_control(priv); | 318 | ret = lbs_set_radio(priv, preamble, 1); |
319 | if (ret) | ||
320 | goto out; | ||
158 | 321 | ||
159 | lbs_deb_join("AdhocStart: channel = %d\n", assoc_req->channel); | 322 | /* Build the start command */ |
160 | lbs_deb_join("AdhocStart: band = %d\n", assoc_req->band); | 323 | memset(&cmd, 0, sizeof(cmd)); |
324 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
161 | 325 | ||
162 | ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_START, | 326 | memcpy(cmd.ssid, assoc_req->ssid, assoc_req->ssid_len); |
163 | 0, CMD_OPTION_WAITFORRSP, 0, assoc_req); | 327 | |
328 | lbs_deb_join("ADHOC_START: SSID '%s', ssid length %u\n", | ||
329 | escape_essid(assoc_req->ssid, assoc_req->ssid_len), | ||
330 | assoc_req->ssid_len); | ||
164 | 331 | ||
332 | cmd.bsstype = CMD_BSS_TYPE_IBSS; | ||
333 | |||
334 | if (priv->beacon_period == 0) | ||
335 | priv->beacon_period = MRVDRV_BEACON_INTERVAL; | ||
336 | cmd.beaconperiod = cpu_to_le16(priv->beacon_period); | ||
337 | |||
338 | WARN_ON(!assoc_req->channel); | ||
339 | |||
340 | /* set Physical parameter set */ | ||
341 | cmd.phyparamset.dsparamset.elementid = MFIE_TYPE_DS_SET; | ||
342 | cmd.phyparamset.dsparamset.len = 1; | ||
343 | cmd.phyparamset.dsparamset.currentchan = assoc_req->channel; | ||
344 | |||
345 | /* set IBSS parameter set */ | ||
346 | cmd.ssparamset.ibssparamset.elementid = MFIE_TYPE_IBSS_SET; | ||
347 | cmd.ssparamset.ibssparamset.len = 2; | ||
348 | cmd.ssparamset.ibssparamset.atimwindow = 0; | ||
349 | |||
350 | /* set capability info */ | ||
351 | tmpcap = WLAN_CAPABILITY_IBSS; | ||
352 | if (assoc_req->secinfo.wep_enabled) { | ||
353 | lbs_deb_join("ADHOC_START: WEP enabled, setting privacy on\n"); | ||
354 | tmpcap |= WLAN_CAPABILITY_PRIVACY; | ||
355 | } else | ||
356 | lbs_deb_join("ADHOC_START: WEP disabled, setting privacy off\n"); | ||
357 | |||
358 | cmd.capability = cpu_to_le16(tmpcap); | ||
359 | |||
360 | /* Only v8 and below support setting probe delay */ | ||
361 | if (priv->fwrelease < 0x09000000) | ||
362 | cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME); | ||
363 | |||
364 | ratesize = min(sizeof(cmd.rates), sizeof(lbs_bg_rates)); | ||
365 | memcpy(cmd.rates, lbs_bg_rates, ratesize); | ||
366 | |||
367 | /* Copy the ad-hoc creating rates into Current BSS state structure */ | ||
368 | memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); | ||
369 | memcpy(&priv->curbssparams.rates, &cmd.rates, ratesize); | ||
370 | |||
371 | /* Set MSB on basic rates as the firmware requires, but _after_ | ||
372 | * copying to current bss rates. | ||
373 | */ | ||
374 | lbs_set_basic_rate_flags(cmd.rates, ratesize); | ||
375 | |||
376 | lbs_deb_join("ADHOC_START: rates=%02x %02x %02x %02x\n", | ||
377 | cmd.rates[0], cmd.rates[1], cmd.rates[2], cmd.rates[3]); | ||
378 | |||
379 | if (lbs_create_dnld_countryinfo_11d(priv)) { | ||
380 | lbs_deb_join("ADHOC_START: dnld_countryinfo_11d failed\n"); | ||
381 | ret = -1; | ||
382 | goto out; | ||
383 | } | ||
384 | |||
385 | lbs_deb_join("ADHOC_START: Starting Ad-Hoc BSS on channel %d, band %d\n", | ||
386 | assoc_req->channel, assoc_req->band); | ||
387 | |||
388 | priv->adhoccreate = 1; | ||
389 | priv->mode = IW_MODE_ADHOC; | ||
390 | |||
391 | ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_START, &cmd); | ||
392 | if (ret == 0) | ||
393 | ret = lbs_adhoc_post(priv, (struct cmd_header *) &cmd); | ||
394 | |||
395 | out: | ||
396 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | ||
165 | return ret; | 397 | return ret; |
166 | } | 398 | } |
167 | 399 | ||
168 | int lbs_stop_adhoc_network(struct lbs_private *priv) | 400 | /** |
401 | * @brief Stop and Ad-Hoc network and exit Ad-Hoc mode | ||
402 | * | ||
403 | * @param priv A pointer to struct lbs_private structure | ||
404 | * @return 0 on success, or an error | ||
405 | */ | ||
406 | int lbs_adhoc_stop(struct lbs_private *priv) | ||
169 | { | 407 | { |
170 | return lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_STOP, | 408 | struct cmd_ds_802_11_ad_hoc_stop cmd; |
171 | 0, CMD_OPTION_WAITFORRSP, 0, NULL); | 409 | int ret; |
410 | |||
411 | lbs_deb_enter(LBS_DEB_JOIN); | ||
412 | |||
413 | memset(&cmd, 0, sizeof (cmd)); | ||
414 | cmd.hdr.size = cpu_to_le16 (sizeof (cmd)); | ||
415 | |||
416 | ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_STOP, &cmd); | ||
417 | |||
418 | /* Clean up everything even if there was an error */ | ||
419 | lbs_mac_event_disconnected(priv); | ||
420 | |||
421 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | ||
422 | return ret; | ||
172 | } | 423 | } |
173 | 424 | ||
174 | static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, | 425 | static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, |
@@ -480,14 +731,14 @@ static int assoc_helper_essid(struct lbs_private *priv, | |||
480 | if (bss != NULL) { | 731 | if (bss != NULL) { |
481 | lbs_deb_assoc("SSID found, will join\n"); | 732 | lbs_deb_assoc("SSID found, will join\n"); |
482 | memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor)); | 733 | memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor)); |
483 | lbs_join_adhoc_network(priv, assoc_req); | 734 | lbs_adhoc_join(priv, assoc_req); |
484 | } else { | 735 | } else { |
485 | /* else send START command */ | 736 | /* else send START command */ |
486 | lbs_deb_assoc("SSID not found, creating adhoc network\n"); | 737 | lbs_deb_assoc("SSID not found, creating adhoc network\n"); |
487 | memcpy(&assoc_req->bss.ssid, &assoc_req->ssid, | 738 | memcpy(&assoc_req->bss.ssid, &assoc_req->ssid, |
488 | IW_ESSID_MAX_SIZE); | 739 | IW_ESSID_MAX_SIZE); |
489 | assoc_req->bss.ssid_len = assoc_req->ssid_len; | 740 | assoc_req->bss.ssid_len = assoc_req->ssid_len; |
490 | lbs_start_adhoc_network(priv, assoc_req); | 741 | lbs_adhoc_start(priv, assoc_req); |
491 | } | 742 | } |
492 | } | 743 | } |
493 | 744 | ||
@@ -520,7 +771,7 @@ static int assoc_helper_bssid(struct lbs_private *priv, | |||
520 | ret = lbs_associate(priv, assoc_req); | 771 | ret = lbs_associate(priv, assoc_req); |
521 | lbs_deb_assoc("ASSOC: lbs_associate(bssid) returned %d\n", ret); | 772 | lbs_deb_assoc("ASSOC: lbs_associate(bssid) returned %d\n", ret); |
522 | } else if (assoc_req->mode == IW_MODE_ADHOC) { | 773 | } else if (assoc_req->mode == IW_MODE_ADHOC) { |
523 | lbs_join_adhoc_network(priv, assoc_req); | 774 | lbs_adhoc_join(priv, assoc_req); |
524 | } | 775 | } |
525 | 776 | ||
526 | out: | 777 | out: |
@@ -1029,7 +1280,9 @@ void lbs_association_worker(struct work_struct *work) | |||
1029 | */ | 1280 | */ |
1030 | if (priv->mode == IW_MODE_INFRA) { | 1281 | if (priv->mode == IW_MODE_INFRA) { |
1031 | if (should_deauth_infrastructure(priv, assoc_req)) { | 1282 | if (should_deauth_infrastructure(priv, assoc_req)) { |
1032 | ret = lbs_send_deauthentication(priv); | 1283 | ret = lbs_cmd_80211_deauthenticate(priv, |
1284 | priv->curbssparams.bssid, | ||
1285 | WLAN_REASON_DEAUTH_LEAVING); | ||
1033 | if (ret) { | 1286 | if (ret) { |
1034 | lbs_deb_assoc("Deauthentication due to new " | 1287 | lbs_deb_assoc("Deauthentication due to new " |
1035 | "configuration request failed: %d\n", | 1288 | "configuration request failed: %d\n", |
@@ -1038,7 +1291,7 @@ void lbs_association_worker(struct work_struct *work) | |||
1038 | } | 1291 | } |
1039 | } else if (priv->mode == IW_MODE_ADHOC) { | 1292 | } else if (priv->mode == IW_MODE_ADHOC) { |
1040 | if (should_stop_adhoc(priv, assoc_req)) { | 1293 | if (should_stop_adhoc(priv, assoc_req)) { |
1041 | ret = lbs_stop_adhoc_network(priv); | 1294 | ret = lbs_adhoc_stop(priv); |
1042 | if (ret) { | 1295 | if (ret) { |
1043 | lbs_deb_assoc("Teardown of AdHoc network due to " | 1296 | lbs_deb_assoc("Teardown of AdHoc network due to " |
1044 | "new configuration request failed: %d\n", | 1297 | "new configuration request failed: %d\n", |
@@ -1214,94 +1467,6 @@ struct assoc_request *lbs_get_association_request(struct lbs_private *priv) | |||
1214 | 1467 | ||
1215 | 1468 | ||
1216 | /** | 1469 | /** |
1217 | * @brief This function finds common rates between rate1 and card rates. | ||
1218 | * | ||
1219 | * It will fill common rates in rate1 as output if found. | ||
1220 | * | ||
1221 | * NOTE: Setting the MSB of the basic rates need to be taken | ||
1222 | * care, either before or after calling this function | ||
1223 | * | ||
1224 | * @param priv A pointer to struct lbs_private structure | ||
1225 | * @param rate1 the buffer which keeps input and output | ||
1226 | * @param rate1_size the size of rate1 buffer; new size of buffer on return | ||
1227 | * | ||
1228 | * @return 0 or -1 | ||
1229 | */ | ||
1230 | static int get_common_rates(struct lbs_private *priv, | ||
1231 | u8 *rates, | ||
1232 | u16 *rates_size) | ||
1233 | { | ||
1234 | u8 *card_rates = lbs_bg_rates; | ||
1235 | size_t num_card_rates = sizeof(lbs_bg_rates); | ||
1236 | int ret = 0, i, j; | ||
1237 | u8 tmp[30]; | ||
1238 | size_t tmp_size = 0; | ||
1239 | |||
1240 | /* For each rate in card_rates that exists in rate1, copy to tmp */ | ||
1241 | for (i = 0; card_rates[i] && (i < num_card_rates); i++) { | ||
1242 | for (j = 0; rates[j] && (j < *rates_size); j++) { | ||
1243 | if (rates[j] == card_rates[i]) | ||
1244 | tmp[tmp_size++] = card_rates[i]; | ||
1245 | } | ||
1246 | } | ||
1247 | |||
1248 | lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size); | ||
1249 | lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, num_card_rates); | ||
1250 | lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size); | ||
1251 | lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate); | ||
1252 | |||
1253 | if (!priv->enablehwauto) { | ||
1254 | for (i = 0; i < tmp_size; i++) { | ||
1255 | if (tmp[i] == priv->cur_rate) | ||
1256 | goto done; | ||
1257 | } | ||
1258 | lbs_pr_alert("Previously set fixed data rate %#x isn't " | ||
1259 | "compatible with the network.\n", priv->cur_rate); | ||
1260 | ret = -1; | ||
1261 | goto done; | ||
1262 | } | ||
1263 | ret = 0; | ||
1264 | |||
1265 | done: | ||
1266 | memset(rates, 0, *rates_size); | ||
1267 | *rates_size = min_t(int, tmp_size, *rates_size); | ||
1268 | memcpy(rates, tmp, *rates_size); | ||
1269 | return ret; | ||
1270 | } | ||
1271 | |||
1272 | |||
1273 | /** | ||
1274 | * @brief Sets the MSB on basic rates as the firmware requires | ||
1275 | * | ||
1276 | * Scan through an array and set the MSB for basic data rates. | ||
1277 | * | ||
1278 | * @param rates buffer of data rates | ||
1279 | * @param len size of buffer | ||
1280 | */ | ||
1281 | static void lbs_set_basic_rate_flags(u8 *rates, size_t len) | ||
1282 | { | ||
1283 | int i; | ||
1284 | |||
1285 | for (i = 0; i < len; i++) { | ||
1286 | if (rates[i] == 0x02 || rates[i] == 0x04 || | ||
1287 | rates[i] == 0x0b || rates[i] == 0x16) | ||
1288 | rates[i] |= 0x80; | ||
1289 | } | ||
1290 | } | ||
1291 | |||
1292 | /** | ||
1293 | * @brief Send Deauthentication Request | ||
1294 | * | ||
1295 | * @param priv A pointer to struct lbs_private structure | ||
1296 | * @return 0--success, -1--fail | ||
1297 | */ | ||
1298 | int lbs_send_deauthentication(struct lbs_private *priv) | ||
1299 | { | ||
1300 | return lbs_prepare_and_send_command(priv, CMD_802_11_DEAUTHENTICATE, | ||
1301 | 0, CMD_OPTION_WAITFORRSP, 0, NULL); | ||
1302 | } | ||
1303 | |||
1304 | /** | ||
1305 | * @brief This function prepares command of authenticate. | 1470 | * @brief This function prepares command of authenticate. |
1306 | * | 1471 | * |
1307 | * @param priv A pointer to struct lbs_private structure | 1472 | * @param priv A pointer to struct lbs_private structure |
@@ -1353,26 +1518,37 @@ out: | |||
1353 | return ret; | 1518 | return ret; |
1354 | } | 1519 | } |
1355 | 1520 | ||
1356 | int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, | 1521 | /** |
1357 | struct cmd_ds_command *cmd) | 1522 | * @brief Deauthenticate from a specific BSS |
1523 | * | ||
1524 | * @param priv A pointer to struct lbs_private structure | ||
1525 | * @param bssid The specific BSS to deauthenticate from | ||
1526 | * @param reason The 802.11 sec. 7.3.1.7 Reason Code for deauthenticating | ||
1527 | * | ||
1528 | * @return 0 on success, error on failure | ||
1529 | */ | ||
1530 | int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, u8 bssid[ETH_ALEN], | ||
1531 | u16 reason) | ||
1358 | { | 1532 | { |
1359 | struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth; | 1533 | struct cmd_ds_802_11_deauthenticate cmd; |
1534 | int ret; | ||
1360 | 1535 | ||
1361 | lbs_deb_enter(LBS_DEB_JOIN); | 1536 | lbs_deb_enter(LBS_DEB_JOIN); |
1362 | 1537 | ||
1363 | cmd->command = cpu_to_le16(CMD_802_11_DEAUTHENTICATE); | 1538 | memset(&cmd, 0, sizeof(cmd)); |
1364 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) + | 1539 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); |
1365 | S_DS_GEN); | 1540 | memcpy(cmd.macaddr, &bssid[0], ETH_ALEN); |
1541 | cmd.reasoncode = cpu_to_le16(reason); | ||
1366 | 1542 | ||
1367 | /* set AP MAC address */ | 1543 | ret = lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd); |
1368 | memmove(dauth->macaddr, priv->curbssparams.bssid, ETH_ALEN); | ||
1369 | 1544 | ||
1370 | /* Reason code 3 = Station is leaving */ | 1545 | /* Clean up everything even if there was an error; can't assume that |
1371 | #define REASON_CODE_STA_LEAVING 3 | 1546 | * we're still authenticated to the AP after trying to deauth. |
1372 | dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING); | 1547 | */ |
1548 | lbs_mac_event_disconnected(priv); | ||
1373 | 1549 | ||
1374 | lbs_deb_leave(LBS_DEB_JOIN); | 1550 | lbs_deb_leave(LBS_DEB_JOIN); |
1375 | return 0; | 1551 | return ret; |
1376 | } | 1552 | } |
1377 | 1553 | ||
1378 | int lbs_cmd_80211_associate(struct lbs_private *priv, | 1554 | int lbs_cmd_80211_associate(struct lbs_private *priv, |
@@ -1489,231 +1665,6 @@ done: | |||
1489 | return ret; | 1665 | return ret; |
1490 | } | 1666 | } |
1491 | 1667 | ||
1492 | int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv, | ||
1493 | struct cmd_ds_command *cmd, void *pdata_buf) | ||
1494 | { | ||
1495 | struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads; | ||
1496 | int ret = 0; | ||
1497 | int cmdappendsize = 0; | ||
1498 | struct assoc_request *assoc_req = pdata_buf; | ||
1499 | u16 tmpcap = 0; | ||
1500 | size_t ratesize = 0; | ||
1501 | |||
1502 | lbs_deb_enter(LBS_DEB_JOIN); | ||
1503 | |||
1504 | if (!priv) { | ||
1505 | ret = -1; | ||
1506 | goto done; | ||
1507 | } | ||
1508 | |||
1509 | cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_START); | ||
1510 | |||
1511 | /* | ||
1512 | * Fill in the parameters for 2 data structures: | ||
1513 | * 1. cmd_ds_802_11_ad_hoc_start command | ||
1514 | * 2. priv->scantable[i] | ||
1515 | * | ||
1516 | * Driver will fill up SSID, bsstype,IBSS param, Physical Param, | ||
1517 | * probe delay, and cap info. | ||
1518 | * | ||
1519 | * Firmware will fill up beacon period, DTIM, Basic rates | ||
1520 | * and operational rates. | ||
1521 | */ | ||
1522 | |||
1523 | memset(adhs->ssid, 0, IW_ESSID_MAX_SIZE); | ||
1524 | memcpy(adhs->ssid, assoc_req->ssid, assoc_req->ssid_len); | ||
1525 | |||
1526 | lbs_deb_join("ADHOC_S_CMD: SSID '%s', ssid length %u\n", | ||
1527 | escape_essid(assoc_req->ssid, assoc_req->ssid_len), | ||
1528 | assoc_req->ssid_len); | ||
1529 | |||
1530 | /* set the BSS type */ | ||
1531 | adhs->bsstype = CMD_BSS_TYPE_IBSS; | ||
1532 | priv->mode = IW_MODE_ADHOC; | ||
1533 | if (priv->beacon_period == 0) | ||
1534 | priv->beacon_period = MRVDRV_BEACON_INTERVAL; | ||
1535 | adhs->beaconperiod = cpu_to_le16(priv->beacon_period); | ||
1536 | |||
1537 | /* set Physical param set */ | ||
1538 | #define DS_PARA_IE_ID 3 | ||
1539 | #define DS_PARA_IE_LEN 1 | ||
1540 | |||
1541 | adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID; | ||
1542 | adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN; | ||
1543 | |||
1544 | WARN_ON(!assoc_req->channel); | ||
1545 | |||
1546 | lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n", | ||
1547 | assoc_req->channel); | ||
1548 | |||
1549 | adhs->phyparamset.dsparamset.currentchan = assoc_req->channel; | ||
1550 | |||
1551 | /* set IBSS param set */ | ||
1552 | #define IBSS_PARA_IE_ID 6 | ||
1553 | #define IBSS_PARA_IE_LEN 2 | ||
1554 | |||
1555 | adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID; | ||
1556 | adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN; | ||
1557 | adhs->ssparamset.ibssparamset.atimwindow = 0; | ||
1558 | |||
1559 | /* set capability info */ | ||
1560 | tmpcap = WLAN_CAPABILITY_IBSS; | ||
1561 | if (assoc_req->secinfo.wep_enabled) { | ||
1562 | lbs_deb_join("ADHOC_S_CMD: WEP enabled, " | ||
1563 | "setting privacy on\n"); | ||
1564 | tmpcap |= WLAN_CAPABILITY_PRIVACY; | ||
1565 | } else { | ||
1566 | lbs_deb_join("ADHOC_S_CMD: WEP disabled, " | ||
1567 | "setting privacy off\n"); | ||
1568 | } | ||
1569 | adhs->capability = cpu_to_le16(tmpcap); | ||
1570 | |||
1571 | /* probedelay */ | ||
1572 | adhs->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME); | ||
1573 | |||
1574 | memset(adhs->rates, 0, sizeof(adhs->rates)); | ||
1575 | ratesize = min(sizeof(adhs->rates), sizeof(lbs_bg_rates)); | ||
1576 | memcpy(adhs->rates, lbs_bg_rates, ratesize); | ||
1577 | |||
1578 | /* Copy the ad-hoc creating rates into Current BSS state structure */ | ||
1579 | memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); | ||
1580 | memcpy(&priv->curbssparams.rates, &adhs->rates, ratesize); | ||
1581 | |||
1582 | /* Set MSB on basic rates as the firmware requires, but _after_ | ||
1583 | * copying to current bss rates. | ||
1584 | */ | ||
1585 | lbs_set_basic_rate_flags(adhs->rates, ratesize); | ||
1586 | |||
1587 | lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n", | ||
1588 | adhs->rates[0], adhs->rates[1], adhs->rates[2], adhs->rates[3]); | ||
1589 | |||
1590 | lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n"); | ||
1591 | |||
1592 | if (lbs_create_dnld_countryinfo_11d(priv)) { | ||
1593 | lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n"); | ||
1594 | ret = -1; | ||
1595 | goto done; | ||
1596 | } | ||
1597 | |||
1598 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start) + | ||
1599 | S_DS_GEN + cmdappendsize); | ||
1600 | |||
1601 | ret = 0; | ||
1602 | done: | ||
1603 | lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); | ||
1604 | return ret; | ||
1605 | } | ||
1606 | |||
1607 | int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd) | ||
1608 | { | ||
1609 | cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_STOP); | ||
1610 | cmd->size = cpu_to_le16(S_DS_GEN); | ||
1611 | |||
1612 | return 0; | ||
1613 | } | ||
1614 | |||
1615 | int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv, | ||
1616 | struct cmd_ds_command *cmd, void *pdata_buf) | ||
1617 | { | ||
1618 | struct cmd_ds_802_11_ad_hoc_join *join_cmd = &cmd->params.adj; | ||
1619 | struct assoc_request *assoc_req = pdata_buf; | ||
1620 | struct bss_descriptor *bss = &assoc_req->bss; | ||
1621 | int cmdappendsize = 0; | ||
1622 | int ret = 0; | ||
1623 | u16 ratesize = 0; | ||
1624 | DECLARE_MAC_BUF(mac); | ||
1625 | |||
1626 | lbs_deb_enter(LBS_DEB_JOIN); | ||
1627 | |||
1628 | cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_JOIN); | ||
1629 | |||
1630 | join_cmd->bss.type = CMD_BSS_TYPE_IBSS; | ||
1631 | join_cmd->bss.beaconperiod = cpu_to_le16(bss->beaconperiod); | ||
1632 | |||
1633 | memcpy(&join_cmd->bss.bssid, &bss->bssid, ETH_ALEN); | ||
1634 | memcpy(&join_cmd->bss.ssid, &bss->ssid, bss->ssid_len); | ||
1635 | |||
1636 | memcpy(&join_cmd->bss.phyparamset, &bss->phyparamset, | ||
1637 | sizeof(union ieeetypes_phyparamset)); | ||
1638 | |||
1639 | memcpy(&join_cmd->bss.ssparamset, &bss->ssparamset, | ||
1640 | sizeof(union IEEEtypes_ssparamset)); | ||
1641 | |||
1642 | join_cmd->bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK); | ||
1643 | lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n", | ||
1644 | bss->capability, CAPINFO_MASK); | ||
1645 | |||
1646 | /* information on BSSID descriptor passed to FW */ | ||
1647 | lbs_deb_join( | ||
1648 | "ADHOC_J_CMD: BSSID = %s, SSID = '%s'\n", | ||
1649 | print_mac(mac, join_cmd->bss.bssid), | ||
1650 | join_cmd->bss.ssid); | ||
1651 | |||
1652 | /* failtimeout */ | ||
1653 | join_cmd->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT); | ||
1654 | |||
1655 | /* probedelay */ | ||
1656 | join_cmd->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME); | ||
1657 | |||
1658 | priv->curbssparams.channel = bss->channel; | ||
1659 | |||
1660 | /* Copy Data rates from the rates recorded in scan response */ | ||
1661 | memset(join_cmd->bss.rates, 0, sizeof(join_cmd->bss.rates)); | ||
1662 | ratesize = min_t(u16, sizeof(join_cmd->bss.rates), MAX_RATES); | ||
1663 | memcpy(join_cmd->bss.rates, bss->rates, ratesize); | ||
1664 | if (get_common_rates(priv, join_cmd->bss.rates, &ratesize)) { | ||
1665 | lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n"); | ||
1666 | ret = -1; | ||
1667 | goto done; | ||
1668 | } | ||
1669 | |||
1670 | /* Copy the ad-hoc creating rates into Current BSS state structure */ | ||
1671 | memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); | ||
1672 | memcpy(&priv->curbssparams.rates, join_cmd->bss.rates, ratesize); | ||
1673 | |||
1674 | /* Set MSB on basic rates as the firmware requires, but _after_ | ||
1675 | * copying to current bss rates. | ||
1676 | */ | ||
1677 | lbs_set_basic_rate_flags(join_cmd->bss.rates, ratesize); | ||
1678 | |||
1679 | join_cmd->bss.ssparamset.ibssparamset.atimwindow = | ||
1680 | cpu_to_le16(bss->atimwindow); | ||
1681 | |||
1682 | if (assoc_req->secinfo.wep_enabled) { | ||
1683 | u16 tmp = le16_to_cpu(join_cmd->bss.capability); | ||
1684 | tmp |= WLAN_CAPABILITY_PRIVACY; | ||
1685 | join_cmd->bss.capability = cpu_to_le16(tmp); | ||
1686 | } | ||
1687 | |||
1688 | if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { | ||
1689 | /* wake up first */ | ||
1690 | __le32 Localpsmode; | ||
1691 | |||
1692 | Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM); | ||
1693 | ret = lbs_prepare_and_send_command(priv, | ||
1694 | CMD_802_11_PS_MODE, | ||
1695 | CMD_ACT_SET, | ||
1696 | 0, 0, &Localpsmode); | ||
1697 | |||
1698 | if (ret) { | ||
1699 | ret = -1; | ||
1700 | goto done; | ||
1701 | } | ||
1702 | } | ||
1703 | |||
1704 | if (lbs_parse_dnld_countryinfo_11d(priv, bss)) { | ||
1705 | ret = -1; | ||
1706 | goto done; | ||
1707 | } | ||
1708 | |||
1709 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join) + | ||
1710 | S_DS_GEN + cmdappendsize); | ||
1711 | |||
1712 | done: | ||
1713 | lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); | ||
1714 | return ret; | ||
1715 | } | ||
1716 | |||
1717 | int lbs_ret_80211_associate(struct lbs_private *priv, | 1668 | int lbs_ret_80211_associate(struct lbs_private *priv, |
1718 | struct cmd_ds_command *resp) | 1669 | struct cmd_ds_command *resp) |
1719 | { | 1670 | { |
@@ -1815,34 +1766,19 @@ done: | |||
1815 | return ret; | 1766 | return ret; |
1816 | } | 1767 | } |
1817 | 1768 | ||
1818 | int lbs_ret_80211_disassociate(struct lbs_private *priv) | 1769 | static int lbs_adhoc_post(struct lbs_private *priv, struct cmd_header *resp) |
1819 | { | ||
1820 | lbs_deb_enter(LBS_DEB_JOIN); | ||
1821 | |||
1822 | lbs_mac_event_disconnected(priv); | ||
1823 | |||
1824 | lbs_deb_leave(LBS_DEB_JOIN); | ||
1825 | return 0; | ||
1826 | } | ||
1827 | |||
1828 | int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv, | ||
1829 | struct cmd_ds_command *resp) | ||
1830 | { | 1770 | { |
1831 | int ret = 0; | 1771 | int ret = 0; |
1832 | u16 command = le16_to_cpu(resp->command); | 1772 | u16 command = le16_to_cpu(resp->command); |
1833 | u16 result = le16_to_cpu(resp->result); | 1773 | u16 result = le16_to_cpu(resp->result); |
1834 | struct cmd_ds_802_11_ad_hoc_result *padhocresult; | 1774 | struct cmd_ds_802_11_ad_hoc_result *adhoc_resp; |
1835 | union iwreq_data wrqu; | 1775 | union iwreq_data wrqu; |
1836 | struct bss_descriptor *bss; | 1776 | struct bss_descriptor *bss; |
1837 | DECLARE_MAC_BUF(mac); | 1777 | DECLARE_MAC_BUF(mac); |
1838 | 1778 | ||
1839 | lbs_deb_enter(LBS_DEB_JOIN); | 1779 | lbs_deb_enter(LBS_DEB_JOIN); |
1840 | 1780 | ||
1841 | padhocresult = &resp->params.result; | 1781 | adhoc_resp = (struct cmd_ds_802_11_ad_hoc_result *) resp; |
1842 | |||
1843 | lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp->size)); | ||
1844 | lbs_deb_join("ADHOC_RESP: command = %x\n", command); | ||
1845 | lbs_deb_join("ADHOC_RESP: result = %x\n", result); | ||
1846 | 1782 | ||
1847 | if (!priv->in_progress_assoc_req) { | 1783 | if (!priv->in_progress_assoc_req) { |
1848 | lbs_deb_join("ADHOC_RESP: no in-progress association " | 1784 | lbs_deb_join("ADHOC_RESP: no in-progress association " |
@@ -1856,26 +1792,19 @@ int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv, | |||
1856 | * Join result code 0 --> SUCCESS | 1792 | * Join result code 0 --> SUCCESS |
1857 | */ | 1793 | */ |
1858 | if (result) { | 1794 | if (result) { |
1859 | lbs_deb_join("ADHOC_RESP: failed\n"); | 1795 | lbs_deb_join("ADHOC_RESP: failed (result 0x%X)\n", result); |
1860 | if (priv->connect_status == LBS_CONNECTED) | 1796 | if (priv->connect_status == LBS_CONNECTED) |
1861 | lbs_mac_event_disconnected(priv); | 1797 | lbs_mac_event_disconnected(priv); |
1862 | ret = -1; | 1798 | ret = -1; |
1863 | goto done; | 1799 | goto done; |
1864 | } | 1800 | } |
1865 | 1801 | ||
1866 | /* | ||
1867 | * Now the join cmd should be successful | ||
1868 | * If BSSID has changed use SSID to compare instead of BSSID | ||
1869 | */ | ||
1870 | lbs_deb_join("ADHOC_RESP: associated to '%s'\n", | ||
1871 | escape_essid(bss->ssid, bss->ssid_len)); | ||
1872 | |||
1873 | /* Send a Media Connected event, according to the Spec */ | 1802 | /* Send a Media Connected event, according to the Spec */ |
1874 | priv->connect_status = LBS_CONNECTED; | 1803 | priv->connect_status = LBS_CONNECTED; |
1875 | 1804 | ||
1876 | if (command == CMD_RET(CMD_802_11_AD_HOC_START)) { | 1805 | if (command == CMD_RET(CMD_802_11_AD_HOC_START)) { |
1877 | /* Update the created network descriptor with the new BSSID */ | 1806 | /* Update the created network descriptor with the new BSSID */ |
1878 | memcpy(bss->bssid, padhocresult->bssid, ETH_ALEN); | 1807 | memcpy(bss->bssid, adhoc_resp->bssid, ETH_ALEN); |
1879 | } | 1808 | } |
1880 | 1809 | ||
1881 | /* Set the BSSID from the joined/started descriptor */ | 1810 | /* Set the BSSID from the joined/started descriptor */ |
@@ -1894,22 +1823,13 @@ int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv, | |||
1894 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | 1823 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; |
1895 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); | 1824 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); |
1896 | 1825 | ||
1897 | lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n"); | 1826 | lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %s, channel %d\n", |
1898 | lbs_deb_join("ADHOC_RESP: channel = %d\n", priv->curbssparams.channel); | 1827 | escape_essid(bss->ssid, bss->ssid_len), |
1899 | lbs_deb_join("ADHOC_RESP: BSSID = %s\n", | 1828 | print_mac(mac, priv->curbssparams.bssid), |
1900 | print_mac(mac, padhocresult->bssid)); | 1829 | priv->curbssparams.channel); |
1901 | 1830 | ||
1902 | done: | 1831 | done: |
1903 | lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); | 1832 | lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); |
1904 | return ret; | 1833 | return ret; |
1905 | } | 1834 | } |
1906 | 1835 | ||
1907 | int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv) | ||
1908 | { | ||
1909 | lbs_deb_enter(LBS_DEB_JOIN); | ||
1910 | |||
1911 | lbs_mac_event_disconnected(priv); | ||
1912 | |||
1913 | lbs_deb_leave(LBS_DEB_JOIN); | ||
1914 | return 0; | ||
1915 | } | ||
diff --git a/drivers/net/wireless/libertas/assoc.h b/drivers/net/wireless/libertas/assoc.h index c516fbe518fd..8b7336dd02a3 100644 --- a/drivers/net/wireless/libertas/assoc.h +++ b/drivers/net/wireless/libertas/assoc.h | |||
@@ -12,28 +12,18 @@ struct cmd_ds_command; | |||
12 | int lbs_cmd_80211_authenticate(struct lbs_private *priv, | 12 | int lbs_cmd_80211_authenticate(struct lbs_private *priv, |
13 | struct cmd_ds_command *cmd, | 13 | struct cmd_ds_command *cmd, |
14 | void *pdata_buf); | 14 | void *pdata_buf); |
15 | int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv, | 15 | |
16 | struct cmd_ds_command *cmd, | 16 | int lbs_adhoc_stop(struct lbs_private *priv); |
17 | void *pdata_buf); | 17 | |
18 | int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd); | ||
19 | int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv, | ||
20 | struct cmd_ds_command *cmd, | ||
21 | void *pdata_buf); | ||
22 | int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, | 18 | int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, |
23 | struct cmd_ds_command *cmd); | 19 | u8 bssid[ETH_ALEN], u16 reason); |
24 | int lbs_cmd_80211_associate(struct lbs_private *priv, | 20 | int lbs_cmd_80211_associate(struct lbs_private *priv, |
25 | struct cmd_ds_command *cmd, | 21 | struct cmd_ds_command *cmd, |
26 | void *pdata_buf); | 22 | void *pdata_buf); |
27 | 23 | ||
28 | int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv, | 24 | int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv, |
29 | struct cmd_ds_command *resp); | 25 | struct cmd_ds_command *resp); |
30 | int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv); | ||
31 | int lbs_ret_80211_disassociate(struct lbs_private *priv); | ||
32 | int lbs_ret_80211_associate(struct lbs_private *priv, | 26 | int lbs_ret_80211_associate(struct lbs_private *priv, |
33 | struct cmd_ds_command *resp); | 27 | struct cmd_ds_command *resp); |
34 | 28 | ||
35 | int lbs_stop_adhoc_network(struct lbs_private *priv); | ||
36 | |||
37 | int lbs_send_deauthentication(struct lbs_private *priv); | ||
38 | |||
39 | #endif /* _LBS_ASSOC_H */ | 29 | #endif /* _LBS_ASSOC_H */ |
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index af5fd709887f..802547e79671 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c | |||
@@ -614,47 +614,67 @@ static int lbs_cmd_802_11_snmp_mib(struct lbs_private *priv, | |||
614 | return 0; | 614 | return 0; |
615 | } | 615 | } |
616 | 616 | ||
617 | static int lbs_cmd_802_11_rf_tx_power(struct cmd_ds_command *cmd, | 617 | /** |
618 | u16 cmd_action, void *pdata_buf) | 618 | * @brief Get the min, max, and current TX power |
619 | * | ||
620 | * @param priv A pointer to struct lbs_private structure | ||
621 | * @param curlevel Current power level in dBm | ||
622 | * @param minlevel Minimum supported power level in dBm (optional) | ||
623 | * @param maxlevel Maximum supported power level in dBm (optional) | ||
624 | * | ||
625 | * @return 0 on success, error on failure | ||
626 | */ | ||
627 | int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel, | ||
628 | s16 *maxlevel) | ||
619 | { | 629 | { |
620 | 630 | struct cmd_ds_802_11_rf_tx_power cmd; | |
621 | struct cmd_ds_802_11_rf_tx_power *prtp = &cmd->params.txp; | 631 | int ret; |
622 | 632 | ||
623 | lbs_deb_enter(LBS_DEB_CMD); | 633 | lbs_deb_enter(LBS_DEB_CMD); |
624 | 634 | ||
625 | cmd->size = | 635 | memset(&cmd, 0, sizeof(cmd)); |
626 | cpu_to_le16((sizeof(struct cmd_ds_802_11_rf_tx_power)) + S_DS_GEN); | 636 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); |
627 | cmd->command = cpu_to_le16(CMD_802_11_RF_TX_POWER); | 637 | cmd.action = cpu_to_le16(CMD_ACT_GET); |
628 | prtp->action = cpu_to_le16(cmd_action); | 638 | |
639 | ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd); | ||
640 | if (ret == 0) { | ||
641 | *curlevel = le16_to_cpu(cmd.curlevel); | ||
642 | if (minlevel) | ||
643 | *minlevel = le16_to_cpu(cmd.minlevel); | ||
644 | if (maxlevel) | ||
645 | *maxlevel = le16_to_cpu(cmd.maxlevel); | ||
646 | } | ||
629 | 647 | ||
630 | lbs_deb_cmd("RF_TX_POWER_CMD: size:%d cmd:0x%x Act:%d\n", | 648 | lbs_deb_leave(LBS_DEB_CMD); |
631 | le16_to_cpu(cmd->size), le16_to_cpu(cmd->command), | 649 | return ret; |
632 | le16_to_cpu(prtp->action)); | 650 | } |
633 | 651 | ||
634 | switch (cmd_action) { | 652 | /** |
635 | case CMD_ACT_TX_POWER_OPT_GET: | 653 | * @brief Set the TX power |
636 | prtp->action = cpu_to_le16(CMD_ACT_GET); | 654 | * |
637 | prtp->currentlevel = 0; | 655 | * @param priv A pointer to struct lbs_private structure |
638 | break; | 656 | * @param dbm The desired power level in dBm |
657 | * | ||
658 | * @return 0 on success, error on failure | ||
659 | */ | ||
660 | int lbs_set_tx_power(struct lbs_private *priv, s16 dbm) | ||
661 | { | ||
662 | struct cmd_ds_802_11_rf_tx_power cmd; | ||
663 | int ret; | ||
639 | 664 | ||
640 | case CMD_ACT_TX_POWER_OPT_SET_HIGH: | 665 | lbs_deb_enter(LBS_DEB_CMD); |
641 | prtp->action = cpu_to_le16(CMD_ACT_SET); | ||
642 | prtp->currentlevel = cpu_to_le16(CMD_ACT_TX_POWER_INDEX_HIGH); | ||
643 | break; | ||
644 | 666 | ||
645 | case CMD_ACT_TX_POWER_OPT_SET_MID: | 667 | memset(&cmd, 0, sizeof(cmd)); |
646 | prtp->action = cpu_to_le16(CMD_ACT_SET); | 668 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); |
647 | prtp->currentlevel = cpu_to_le16(CMD_ACT_TX_POWER_INDEX_MID); | 669 | cmd.action = cpu_to_le16(CMD_ACT_SET); |
648 | break; | 670 | cmd.curlevel = cpu_to_le16(dbm); |
649 | 671 | ||
650 | case CMD_ACT_TX_POWER_OPT_SET_LOW: | 672 | lbs_deb_cmd("SET_RF_TX_POWER: %d dBm\n", dbm); |
651 | prtp->action = cpu_to_le16(CMD_ACT_SET); | 673 | |
652 | prtp->currentlevel = cpu_to_le16(*((u16 *) pdata_buf)); | 674 | ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd); |
653 | break; | ||
654 | } | ||
655 | 675 | ||
656 | lbs_deb_leave(LBS_DEB_CMD); | 676 | lbs_deb_leave(LBS_DEB_CMD); |
657 | return 0; | 677 | return ret; |
658 | } | 678 | } |
659 | 679 | ||
660 | static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd, | 680 | static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd, |
@@ -1269,41 +1289,47 @@ void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, | |||
1269 | priv->cur_cmd = NULL; | 1289 | priv->cur_cmd = NULL; |
1270 | } | 1290 | } |
1271 | 1291 | ||
1272 | int lbs_set_radio_control(struct lbs_private *priv) | 1292 | int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on) |
1273 | { | 1293 | { |
1274 | int ret = 0; | ||
1275 | struct cmd_ds_802_11_radio_control cmd; | 1294 | struct cmd_ds_802_11_radio_control cmd; |
1295 | int ret = -EINVAL; | ||
1276 | 1296 | ||
1277 | lbs_deb_enter(LBS_DEB_CMD); | 1297 | lbs_deb_enter(LBS_DEB_CMD); |
1278 | 1298 | ||
1279 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | 1299 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); |
1280 | cmd.action = cpu_to_le16(CMD_ACT_SET); | 1300 | cmd.action = cpu_to_le16(CMD_ACT_SET); |
1281 | 1301 | ||
1282 | switch (priv->preamble) { | 1302 | /* Only v8 and below support setting the preamble */ |
1283 | case CMD_TYPE_SHORT_PREAMBLE: | 1303 | if (priv->fwrelease < 0x09000000) { |
1284 | cmd.control = cpu_to_le16(SET_SHORT_PREAMBLE); | 1304 | switch (preamble) { |
1285 | break; | 1305 | case RADIO_PREAMBLE_SHORT: |
1286 | 1306 | if (!(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) | |
1287 | case CMD_TYPE_LONG_PREAMBLE: | 1307 | goto out; |
1288 | cmd.control = cpu_to_le16(SET_LONG_PREAMBLE); | 1308 | /* Fall through */ |
1289 | break; | 1309 | case RADIO_PREAMBLE_AUTO: |
1310 | case RADIO_PREAMBLE_LONG: | ||
1311 | cmd.control = cpu_to_le16(preamble); | ||
1312 | break; | ||
1313 | default: | ||
1314 | goto out; | ||
1315 | } | ||
1316 | } | ||
1290 | 1317 | ||
1291 | case CMD_TYPE_AUTO_PREAMBLE: | 1318 | if (radio_on) |
1292 | default: | 1319 | cmd.control |= cpu_to_le16(0x1); |
1293 | cmd.control = cpu_to_le16(SET_AUTO_PREAMBLE); | 1320 | else { |
1294 | break; | 1321 | cmd.control &= cpu_to_le16(~0x1); |
1322 | priv->txpower_cur = 0; | ||
1295 | } | 1323 | } |
1296 | 1324 | ||
1297 | if (priv->radioon) | 1325 | lbs_deb_cmd("RADIO_CONTROL: radio %s, preamble %d\n", |
1298 | cmd.control |= cpu_to_le16(TURN_ON_RF); | 1326 | radio_on ? "ON" : "OFF", preamble); |
1299 | else | ||
1300 | cmd.control &= cpu_to_le16(~TURN_ON_RF); | ||
1301 | 1327 | ||
1302 | lbs_deb_cmd("RADIO_SET: radio %d, preamble %d\n", priv->radioon, | 1328 | priv->radio_on = radio_on; |
1303 | priv->preamble); | ||
1304 | 1329 | ||
1305 | ret = lbs_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd); | 1330 | ret = lbs_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd); |
1306 | 1331 | ||
1332 | out: | ||
1307 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | 1333 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); |
1308 | return ret; | 1334 | return ret; |
1309 | } | 1335 | } |
@@ -1393,14 +1419,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1393 | ret = lbs_cmd_80211_associate(priv, cmdptr, pdata_buf); | 1419 | ret = lbs_cmd_80211_associate(priv, cmdptr, pdata_buf); |
1394 | break; | 1420 | break; |
1395 | 1421 | ||
1396 | case CMD_802_11_DEAUTHENTICATE: | ||
1397 | ret = lbs_cmd_80211_deauthenticate(priv, cmdptr); | ||
1398 | break; | ||
1399 | |||
1400 | case CMD_802_11_AD_HOC_START: | ||
1401 | ret = lbs_cmd_80211_ad_hoc_start(priv, cmdptr, pdata_buf); | ||
1402 | break; | ||
1403 | |||
1404 | case CMD_802_11_RESET: | 1422 | case CMD_802_11_RESET: |
1405 | ret = lbs_cmd_802_11_reset(cmdptr, cmd_action); | 1423 | ret = lbs_cmd_802_11_reset(cmdptr, cmd_action); |
1406 | break; | 1424 | break; |
@@ -1420,28 +1438,15 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1420 | ret = lbs_cmd_reg_access(cmdptr, cmd_action, pdata_buf); | 1438 | ret = lbs_cmd_reg_access(cmdptr, cmd_action, pdata_buf); |
1421 | break; | 1439 | break; |
1422 | 1440 | ||
1423 | case CMD_802_11_RF_TX_POWER: | ||
1424 | ret = lbs_cmd_802_11_rf_tx_power(cmdptr, | ||
1425 | cmd_action, pdata_buf); | ||
1426 | break; | ||
1427 | |||
1428 | case CMD_802_11_MONITOR_MODE: | 1441 | case CMD_802_11_MONITOR_MODE: |
1429 | ret = lbs_cmd_802_11_monitor_mode(cmdptr, | 1442 | ret = lbs_cmd_802_11_monitor_mode(cmdptr, |
1430 | cmd_action, pdata_buf); | 1443 | cmd_action, pdata_buf); |
1431 | break; | 1444 | break; |
1432 | 1445 | ||
1433 | case CMD_802_11_AD_HOC_JOIN: | ||
1434 | ret = lbs_cmd_80211_ad_hoc_join(priv, cmdptr, pdata_buf); | ||
1435 | break; | ||
1436 | |||
1437 | case CMD_802_11_RSSI: | 1446 | case CMD_802_11_RSSI: |
1438 | ret = lbs_cmd_802_11_rssi(priv, cmdptr); | 1447 | ret = lbs_cmd_802_11_rssi(priv, cmdptr); |
1439 | break; | 1448 | break; |
1440 | 1449 | ||
1441 | case CMD_802_11_AD_HOC_STOP: | ||
1442 | ret = lbs_cmd_80211_ad_hoc_stop(cmdptr); | ||
1443 | break; | ||
1444 | |||
1445 | case CMD_802_11_SET_AFC: | 1450 | case CMD_802_11_SET_AFC: |
1446 | case CMD_802_11_GET_AFC: | 1451 | case CMD_802_11_GET_AFC: |
1447 | 1452 | ||
diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h index a53b51f8bdb4..11ac996e895e 100644 --- a/drivers/net/wireless/libertas/cmd.h +++ b/drivers/net/wireless/libertas/cmd.h | |||
@@ -61,4 +61,10 @@ int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action, | |||
61 | int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action, | 61 | int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action, |
62 | struct assoc_request *assoc); | 62 | struct assoc_request *assoc); |
63 | 63 | ||
64 | int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel, | ||
65 | s16 *maxlevel); | ||
66 | int lbs_set_tx_power(struct lbs_private *priv, s16 dbm); | ||
67 | |||
68 | int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on); | ||
69 | |||
64 | #endif /* _LBS_CMD_H */ | 70 | #endif /* _LBS_CMD_H */ |
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 24de3c3cf877..0371c83f5661 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c | |||
@@ -188,21 +188,6 @@ static int lbs_ret_802_11_snmp_mib(struct lbs_private *priv, | |||
188 | return 0; | 188 | return 0; |
189 | } | 189 | } |
190 | 190 | ||
191 | static int lbs_ret_802_11_rf_tx_power(struct lbs_private *priv, | ||
192 | struct cmd_ds_command *resp) | ||
193 | { | ||
194 | struct cmd_ds_802_11_rf_tx_power *rtp = &resp->params.txp; | ||
195 | |||
196 | lbs_deb_enter(LBS_DEB_CMD); | ||
197 | |||
198 | priv->txpowerlevel = le16_to_cpu(rtp->currentlevel); | ||
199 | |||
200 | lbs_deb_cmd("TX power currently %d\n", priv->txpowerlevel); | ||
201 | |||
202 | lbs_deb_leave(LBS_DEB_CMD); | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static int lbs_ret_802_11_rssi(struct lbs_private *priv, | 191 | static int lbs_ret_802_11_rssi(struct lbs_private *priv, |
207 | struct cmd_ds_command *resp) | 192 | struct cmd_ds_command *resp) |
208 | { | 193 | { |
@@ -273,24 +258,10 @@ static inline int handle_cmd_response(struct lbs_private *priv, | |||
273 | ret = lbs_ret_80211_associate(priv, resp); | 258 | ret = lbs_ret_80211_associate(priv, resp); |
274 | break; | 259 | break; |
275 | 260 | ||
276 | case CMD_RET(CMD_802_11_DISASSOCIATE): | ||
277 | case CMD_RET(CMD_802_11_DEAUTHENTICATE): | ||
278 | ret = lbs_ret_80211_disassociate(priv); | ||
279 | break; | ||
280 | |||
281 | case CMD_RET(CMD_802_11_AD_HOC_START): | ||
282 | case CMD_RET(CMD_802_11_AD_HOC_JOIN): | ||
283 | ret = lbs_ret_80211_ad_hoc_start(priv, resp); | ||
284 | break; | ||
285 | |||
286 | case CMD_RET(CMD_802_11_SNMP_MIB): | 261 | case CMD_RET(CMD_802_11_SNMP_MIB): |
287 | ret = lbs_ret_802_11_snmp_mib(priv, resp); | 262 | ret = lbs_ret_802_11_snmp_mib(priv, resp); |
288 | break; | 263 | break; |
289 | 264 | ||
290 | case CMD_RET(CMD_802_11_RF_TX_POWER): | ||
291 | ret = lbs_ret_802_11_rf_tx_power(priv, resp); | ||
292 | break; | ||
293 | |||
294 | case CMD_RET(CMD_802_11_SET_AFC): | 265 | case CMD_RET(CMD_802_11_SET_AFC): |
295 | case CMD_RET(CMD_802_11_GET_AFC): | 266 | case CMD_RET(CMD_802_11_GET_AFC): |
296 | spin_lock_irqsave(&priv->driver_lock, flags); | 267 | spin_lock_irqsave(&priv->driver_lock, flags); |
@@ -309,10 +280,6 @@ static inline int handle_cmd_response(struct lbs_private *priv, | |||
309 | ret = lbs_ret_802_11_rssi(priv, resp); | 280 | ret = lbs_ret_802_11_rssi(priv, resp); |
310 | break; | 281 | break; |
311 | 282 | ||
312 | case CMD_RET(CMD_802_11_AD_HOC_STOP): | ||
313 | ret = lbs_ret_80211_ad_hoc_stop(priv); | ||
314 | break; | ||
315 | |||
316 | case CMD_RET(CMD_802_11D_DOMAIN_INFO): | 283 | case CMD_RET(CMD_802_11D_DOMAIN_INFO): |
317 | ret = lbs_ret_802_11d_domain_info(resp); | 284 | ret = lbs_ret_802_11d_domain_info(resp); |
318 | break; | 285 | break; |
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index a8ac974dacac..1a8888cceadc 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h | |||
@@ -34,7 +34,6 @@ int lbs_process_event(struct lbs_private *priv, u32 event); | |||
34 | void lbs_queue_event(struct lbs_private *priv, u32 event); | 34 | void lbs_queue_event(struct lbs_private *priv, u32 event); |
35 | void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx); | 35 | void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx); |
36 | 36 | ||
37 | int lbs_set_radio_control(struct lbs_private *priv); | ||
38 | u32 lbs_fw_index_to_data_rate(u8 index); | 37 | u32 lbs_fw_index_to_data_rate(u8 index); |
39 | u8 lbs_data_rate_to_fw_index(u32 rate); | 38 | u8 lbs_data_rate_to_fw_index(u32 rate); |
40 | 39 | ||
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index f5bb40c54d85..fd59e1816460 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -253,7 +253,9 @@ struct lbs_private { | |||
253 | u32 connect_status; | 253 | u32 connect_status; |
254 | u32 mesh_connect_status; | 254 | u32 mesh_connect_status; |
255 | u16 regioncode; | 255 | u16 regioncode; |
256 | u16 txpowerlevel; | 256 | s16 txpower_cur; |
257 | s16 txpower_min; | ||
258 | s16 txpower_max; | ||
257 | 259 | ||
258 | /** POWER MANAGEMENT AND PnP SUPPORT */ | 260 | /** POWER MANAGEMENT AND PnP SUPPORT */ |
259 | u8 surpriseremoved; | 261 | u8 surpriseremoved; |
@@ -291,8 +293,7 @@ struct lbs_private { | |||
291 | u16 nextSNRNF; | 293 | u16 nextSNRNF; |
292 | u16 numSNRNF; | 294 | u16 numSNRNF; |
293 | 295 | ||
294 | u8 radioon; | 296 | u8 radio_on; |
295 | u32 preamble; | ||
296 | 297 | ||
297 | /** data rate stuff */ | 298 | /** data rate stuff */ |
298 | u8 cur_rate; | 299 | u8 cur_rate; |
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h index c92e41b4faf4..da618fc997ce 100644 --- a/drivers/net/wireless/libertas/host.h +++ b/drivers/net/wireless/libertas/host.h | |||
@@ -61,7 +61,6 @@ | |||
61 | #define CMD_RF_REG_MAP 0x0023 | 61 | #define CMD_RF_REG_MAP 0x0023 |
62 | #define CMD_802_11_DEAUTHENTICATE 0x0024 | 62 | #define CMD_802_11_DEAUTHENTICATE 0x0024 |
63 | #define CMD_802_11_REASSOCIATE 0x0025 | 63 | #define CMD_802_11_REASSOCIATE 0x0025 |
64 | #define CMD_802_11_DISASSOCIATE 0x0026 | ||
65 | #define CMD_MAC_CONTROL 0x0028 | 64 | #define CMD_MAC_CONTROL 0x0028 |
66 | #define CMD_802_11_AD_HOC_START 0x002b | 65 | #define CMD_802_11_AD_HOC_START 0x002b |
67 | #define CMD_802_11_AD_HOC_JOIN 0x002c | 66 | #define CMD_802_11_AD_HOC_JOIN 0x002c |
@@ -153,11 +152,6 @@ | |||
153 | #define CMD_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100 | 152 | #define CMD_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100 |
154 | #define CMD_ACT_MAC_STRICT_PROTECTION_ENABLE 0x0400 | 153 | #define CMD_ACT_MAC_STRICT_PROTECTION_ENABLE 0x0400 |
155 | 154 | ||
156 | /* Define action or option for CMD_802_11_RADIO_CONTROL */ | ||
157 | #define CMD_TYPE_AUTO_PREAMBLE 0x0001 | ||
158 | #define CMD_TYPE_SHORT_PREAMBLE 0x0002 | ||
159 | #define CMD_TYPE_LONG_PREAMBLE 0x0003 | ||
160 | |||
161 | /* Event flags for CMD_802_11_SUBSCRIBE_EVENT */ | 155 | /* Event flags for CMD_802_11_SUBSCRIBE_EVENT */ |
162 | #define CMD_SUBSCRIBE_RSSI_LOW 0x0001 | 156 | #define CMD_SUBSCRIBE_RSSI_LOW 0x0001 |
163 | #define CMD_SUBSCRIBE_SNR_LOW 0x0002 | 157 | #define CMD_SUBSCRIBE_SNR_LOW 0x0002 |
@@ -166,28 +160,14 @@ | |||
166 | #define CMD_SUBSCRIBE_RSSI_HIGH 0x0010 | 160 | #define CMD_SUBSCRIBE_RSSI_HIGH 0x0010 |
167 | #define CMD_SUBSCRIBE_SNR_HIGH 0x0020 | 161 | #define CMD_SUBSCRIBE_SNR_HIGH 0x0020 |
168 | 162 | ||
169 | #define TURN_ON_RF 0x01 | 163 | #define RADIO_PREAMBLE_LONG 0x00 |
170 | #define RADIO_ON 0x01 | 164 | #define RADIO_PREAMBLE_SHORT 0x02 |
171 | #define RADIO_OFF 0x00 | 165 | #define RADIO_PREAMBLE_AUTO 0x04 |
172 | |||
173 | #define SET_AUTO_PREAMBLE 0x05 | ||
174 | #define SET_SHORT_PREAMBLE 0x03 | ||
175 | #define SET_LONG_PREAMBLE 0x01 | ||
176 | 166 | ||
177 | /* Define action or option for CMD_802_11_RF_CHANNEL */ | 167 | /* Define action or option for CMD_802_11_RF_CHANNEL */ |
178 | #define CMD_OPT_802_11_RF_CHANNEL_GET 0x00 | 168 | #define CMD_OPT_802_11_RF_CHANNEL_GET 0x00 |
179 | #define CMD_OPT_802_11_RF_CHANNEL_SET 0x01 | 169 | #define CMD_OPT_802_11_RF_CHANNEL_SET 0x01 |
180 | 170 | ||
181 | /* Define action or option for CMD_802_11_RF_TX_POWER */ | ||
182 | #define CMD_ACT_TX_POWER_OPT_GET 0x0000 | ||
183 | #define CMD_ACT_TX_POWER_OPT_SET_HIGH 0x8007 | ||
184 | #define CMD_ACT_TX_POWER_OPT_SET_MID 0x8004 | ||
185 | #define CMD_ACT_TX_POWER_OPT_SET_LOW 0x8000 | ||
186 | |||
187 | #define CMD_ACT_TX_POWER_INDEX_HIGH 0x0007 | ||
188 | #define CMD_ACT_TX_POWER_INDEX_MID 0x0004 | ||
189 | #define CMD_ACT_TX_POWER_INDEX_LOW 0x0000 | ||
190 | |||
191 | /* Define action or option for CMD_802_11_DATA_RATE */ | 171 | /* Define action or option for CMD_802_11_DATA_RATE */ |
192 | #define CMD_ACT_SET_TX_AUTO 0x0000 | 172 | #define CMD_ACT_SET_TX_AUTO 0x0000 |
193 | #define CMD_ACT_SET_TX_FIX_RATE 0x0001 | 173 | #define CMD_ACT_SET_TX_FIX_RATE 0x0001 |
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h index 913b480211a9..d27c276b2191 100644 --- a/drivers/net/wireless/libertas/hostcmd.h +++ b/drivers/net/wireless/libertas/hostcmd.h | |||
@@ -232,7 +232,9 @@ struct cmd_ds_802_11_authenticate { | |||
232 | }; | 232 | }; |
233 | 233 | ||
234 | struct cmd_ds_802_11_deauthenticate { | 234 | struct cmd_ds_802_11_deauthenticate { |
235 | u8 macaddr[6]; | 235 | struct cmd_header hdr; |
236 | |||
237 | u8 macaddr[ETH_ALEN]; | ||
236 | __le16 reasoncode; | 238 | __le16 reasoncode; |
237 | }; | 239 | }; |
238 | 240 | ||
@@ -251,20 +253,10 @@ struct cmd_ds_802_11_associate { | |||
251 | #endif | 253 | #endif |
252 | } __attribute__ ((packed)); | 254 | } __attribute__ ((packed)); |
253 | 255 | ||
254 | struct cmd_ds_802_11_disassociate { | ||
255 | u8 destmacaddr[6]; | ||
256 | __le16 reasoncode; | ||
257 | }; | ||
258 | |||
259 | struct cmd_ds_802_11_associate_rsp { | 256 | struct cmd_ds_802_11_associate_rsp { |
260 | struct ieeetypes_assocrsp assocRsp; | 257 | struct ieeetypes_assocrsp assocRsp; |
261 | }; | 258 | }; |
262 | 259 | ||
263 | struct cmd_ds_802_11_ad_hoc_result { | ||
264 | u8 pad[3]; | ||
265 | u8 bssid[ETH_ALEN]; | ||
266 | }; | ||
267 | |||
268 | struct cmd_ds_802_11_set_wep { | 260 | struct cmd_ds_802_11_set_wep { |
269 | struct cmd_header hdr; | 261 | struct cmd_header hdr; |
270 | 262 | ||
@@ -435,8 +427,12 @@ struct cmd_ds_802_11_mac_address { | |||
435 | }; | 427 | }; |
436 | 428 | ||
437 | struct cmd_ds_802_11_rf_tx_power { | 429 | struct cmd_ds_802_11_rf_tx_power { |
430 | struct cmd_header hdr; | ||
431 | |||
438 | __le16 action; | 432 | __le16 action; |
439 | __le16 currentlevel; | 433 | __le16 curlevel; |
434 | s8 maxlevel; | ||
435 | s8 minlevel; | ||
440 | }; | 436 | }; |
441 | 437 | ||
442 | struct cmd_ds_802_11_rf_antenna { | 438 | struct cmd_ds_802_11_rf_antenna { |
@@ -507,10 +503,12 @@ struct cmd_ds_802_11_rate_adapt_rateset { | |||
507 | }; | 503 | }; |
508 | 504 | ||
509 | struct cmd_ds_802_11_ad_hoc_start { | 505 | struct cmd_ds_802_11_ad_hoc_start { |
506 | struct cmd_header hdr; | ||
507 | |||
510 | u8 ssid[IW_ESSID_MAX_SIZE]; | 508 | u8 ssid[IW_ESSID_MAX_SIZE]; |
511 | u8 bsstype; | 509 | u8 bsstype; |
512 | __le16 beaconperiod; | 510 | __le16 beaconperiod; |
513 | u8 dtimperiod; | 511 | u8 dtimperiod; /* Reserved on v9 and later */ |
514 | union IEEEtypes_ssparamset ssparamset; | 512 | union IEEEtypes_ssparamset ssparamset; |
515 | union ieeetypes_phyparamset phyparamset; | 513 | union ieeetypes_phyparamset phyparamset; |
516 | __le16 probedelay; | 514 | __le16 probedelay; |
@@ -519,9 +517,16 @@ struct cmd_ds_802_11_ad_hoc_start { | |||
519 | u8 tlv_memory_size_pad[100]; | 517 | u8 tlv_memory_size_pad[100]; |
520 | } __attribute__ ((packed)); | 518 | } __attribute__ ((packed)); |
521 | 519 | ||
520 | struct cmd_ds_802_11_ad_hoc_result { | ||
521 | struct cmd_header hdr; | ||
522 | |||
523 | u8 pad[3]; | ||
524 | u8 bssid[ETH_ALEN]; | ||
525 | }; | ||
526 | |||
522 | struct adhoc_bssdesc { | 527 | struct adhoc_bssdesc { |
523 | u8 bssid[6]; | 528 | u8 bssid[ETH_ALEN]; |
524 | u8 ssid[32]; | 529 | u8 ssid[IW_ESSID_MAX_SIZE]; |
525 | u8 type; | 530 | u8 type; |
526 | __le16 beaconperiod; | 531 | __le16 beaconperiod; |
527 | u8 dtimperiod; | 532 | u8 dtimperiod; |
@@ -539,10 +544,15 @@ struct adhoc_bssdesc { | |||
539 | } __attribute__ ((packed)); | 544 | } __attribute__ ((packed)); |
540 | 545 | ||
541 | struct cmd_ds_802_11_ad_hoc_join { | 546 | struct cmd_ds_802_11_ad_hoc_join { |
547 | struct cmd_header hdr; | ||
548 | |||
542 | struct adhoc_bssdesc bss; | 549 | struct adhoc_bssdesc bss; |
543 | __le16 failtimeout; | 550 | __le16 failtimeout; /* Reserved on v9 and later */ |
544 | __le16 probedelay; | 551 | __le16 probedelay; /* Reserved on v9 and later */ |
552 | } __attribute__ ((packed)); | ||
545 | 553 | ||
554 | struct cmd_ds_802_11_ad_hoc_stop { | ||
555 | struct cmd_header hdr; | ||
546 | } __attribute__ ((packed)); | 556 | } __attribute__ ((packed)); |
547 | 557 | ||
548 | struct cmd_ds_802_11_enable_rsn { | 558 | struct cmd_ds_802_11_enable_rsn { |
@@ -693,21 +703,15 @@ struct cmd_ds_command { | |||
693 | union { | 703 | union { |
694 | struct cmd_ds_802_11_ps_mode psmode; | 704 | struct cmd_ds_802_11_ps_mode psmode; |
695 | struct cmd_ds_802_11_associate associate; | 705 | struct cmd_ds_802_11_associate associate; |
696 | struct cmd_ds_802_11_deauthenticate deauth; | ||
697 | struct cmd_ds_802_11_ad_hoc_start ads; | ||
698 | struct cmd_ds_802_11_reset reset; | 706 | struct cmd_ds_802_11_reset reset; |
699 | struct cmd_ds_802_11_ad_hoc_result result; | ||
700 | struct cmd_ds_802_11_authenticate auth; | 707 | struct cmd_ds_802_11_authenticate auth; |
701 | struct cmd_ds_802_11_get_stat gstat; | 708 | struct cmd_ds_802_11_get_stat gstat; |
702 | struct cmd_ds_802_3_get_stat gstat_8023; | 709 | struct cmd_ds_802_3_get_stat gstat_8023; |
703 | struct cmd_ds_802_11_snmp_mib smib; | 710 | struct cmd_ds_802_11_snmp_mib smib; |
704 | struct cmd_ds_802_11_rf_tx_power txp; | ||
705 | struct cmd_ds_802_11_rf_antenna rant; | 711 | struct cmd_ds_802_11_rf_antenna rant; |
706 | struct cmd_ds_802_11_monitor_mode monitor; | 712 | struct cmd_ds_802_11_monitor_mode monitor; |
707 | struct cmd_ds_802_11_ad_hoc_join adj; | ||
708 | struct cmd_ds_802_11_rssi rssi; | 713 | struct cmd_ds_802_11_rssi rssi; |
709 | struct cmd_ds_802_11_rssi_rsp rssirsp; | 714 | struct cmd_ds_802_11_rssi_rsp rssirsp; |
710 | struct cmd_ds_802_11_disassociate dassociate; | ||
711 | struct cmd_ds_mac_reg_access macreg; | 715 | struct cmd_ds_mac_reg_access macreg; |
712 | struct cmd_ds_bbp_reg_access bbpreg; | 716 | struct cmd_ds_bbp_reg_access bbpreg; |
713 | struct cmd_ds_rf_reg_access rfreg; | 717 | struct cmd_ds_rf_reg_access rfreg; |
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index bd32ac0b4e07..2436634b6b7e 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -291,9 +291,11 @@ static ssize_t lbs_rtap_set(struct device *dev, | |||
291 | if (priv->infra_open || priv->mesh_open) | 291 | if (priv->infra_open || priv->mesh_open) |
292 | return -EBUSY; | 292 | return -EBUSY; |
293 | if (priv->mode == IW_MODE_INFRA) | 293 | if (priv->mode == IW_MODE_INFRA) |
294 | lbs_send_deauthentication(priv); | 294 | lbs_cmd_80211_deauthenticate(priv, |
295 | priv->curbssparams.bssid, | ||
296 | WLAN_REASON_DEAUTH_LEAVING); | ||
295 | else if (priv->mode == IW_MODE_ADHOC) | 297 | else if (priv->mode == IW_MODE_ADHOC) |
296 | lbs_stop_adhoc_network(priv); | 298 | lbs_adhoc_stop(priv); |
297 | lbs_add_rtap(priv); | 299 | lbs_add_rtap(priv); |
298 | } | 300 | } |
299 | priv->monitormode = monitor_mode; | 301 | priv->monitormode = monitor_mode; |
@@ -956,17 +958,24 @@ EXPORT_SYMBOL_GPL(lbs_resume); | |||
956 | static int lbs_setup_firmware(struct lbs_private *priv) | 958 | static int lbs_setup_firmware(struct lbs_private *priv) |
957 | { | 959 | { |
958 | int ret = -1; | 960 | int ret = -1; |
961 | s16 curlevel = 0, minlevel = 0, maxlevel = 0; | ||
959 | 962 | ||
960 | lbs_deb_enter(LBS_DEB_FW); | 963 | lbs_deb_enter(LBS_DEB_FW); |
961 | 964 | ||
962 | /* | 965 | /* Read MAC address from firmware */ |
963 | * Read MAC address from HW | ||
964 | */ | ||
965 | memset(priv->current_addr, 0xff, ETH_ALEN); | 966 | memset(priv->current_addr, 0xff, ETH_ALEN); |
966 | ret = lbs_update_hw_spec(priv); | 967 | ret = lbs_update_hw_spec(priv); |
967 | if (ret) | 968 | if (ret) |
968 | goto done; | 969 | goto done; |
969 | 970 | ||
971 | /* Read power levels if available */ | ||
972 | ret = lbs_get_tx_power(priv, &curlevel, &minlevel, &maxlevel); | ||
973 | if (ret == 0) { | ||
974 | priv->txpower_cur = curlevel; | ||
975 | priv->txpower_min = minlevel; | ||
976 | priv->txpower_max = maxlevel; | ||
977 | } | ||
978 | |||
970 | lbs_set_mac_control(priv); | 979 | lbs_set_mac_control(priv); |
971 | done: | 980 | done: |
972 | lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); | 981 | lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); |
@@ -1042,7 +1051,7 @@ static int lbs_init_adapter(struct lbs_private *priv) | |||
1042 | priv->mode = IW_MODE_INFRA; | 1051 | priv->mode = IW_MODE_INFRA; |
1043 | priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL; | 1052 | priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL; |
1044 | priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; | 1053 | priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; |
1045 | priv->radioon = RADIO_ON; | 1054 | priv->radio_on = 1; |
1046 | priv->enablehwauto = 1; | 1055 | priv->enablehwauto = 1; |
1047 | priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; | 1056 | priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; |
1048 | priv->psmode = LBS802_11POWERMODECAM; | 1057 | priv->psmode = LBS802_11POWERMODECAM; |
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 4b274562f965..8f66903641b9 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c | |||
@@ -944,6 +944,11 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, | |||
944 | 944 | ||
945 | lbs_deb_enter(LBS_DEB_WEXT); | 945 | lbs_deb_enter(LBS_DEB_WEXT); |
946 | 946 | ||
947 | if (!priv->radio_on) { | ||
948 | ret = -EINVAL; | ||
949 | goto out; | ||
950 | } | ||
951 | |||
947 | if (!netif_running(dev)) { | 952 | if (!netif_running(dev)) { |
948 | ret = -ENETDOWN; | 953 | ret = -ENETDOWN; |
949 | goto out; | 954 | goto out; |
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index 8b3ed77860b3..426f1fe3bb42 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c | |||
@@ -120,34 +120,6 @@ static struct chan_freq_power *find_cfp_by_band_and_freq( | |||
120 | return cfp; | 120 | return cfp; |
121 | } | 121 | } |
122 | 122 | ||
123 | |||
124 | /** | ||
125 | * @brief Set Radio On/OFF | ||
126 | * | ||
127 | * @param priv A pointer to struct lbs_private structure | ||
128 | * @option Radio Option | ||
129 | * @return 0 --success, otherwise fail | ||
130 | */ | ||
131 | static int lbs_radio_ioctl(struct lbs_private *priv, u8 option) | ||
132 | { | ||
133 | int ret = 0; | ||
134 | |||
135 | lbs_deb_enter(LBS_DEB_WEXT); | ||
136 | |||
137 | if (priv->radioon != option) { | ||
138 | lbs_deb_wext("switching radio %s\n", option ? "on" : "off"); | ||
139 | priv->radioon = option; | ||
140 | |||
141 | ret = lbs_prepare_and_send_command(priv, | ||
142 | CMD_802_11_RADIO_CONTROL, | ||
143 | CMD_ACT_SET, | ||
144 | CMD_OPTION_WAITFORRSP, 0, NULL); | ||
145 | } | ||
146 | |||
147 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | ||
148 | return ret; | ||
149 | } | ||
150 | |||
151 | /** | 123 | /** |
152 | * @brief Copy active data rates based on adapter mode and status | 124 | * @brief Copy active data rates based on adapter mode and status |
153 | * | 125 | * |
@@ -420,28 +392,30 @@ static int lbs_get_txpow(struct net_device *dev, | |||
420 | struct iw_request_info *info, | 392 | struct iw_request_info *info, |
421 | struct iw_param *vwrq, char *extra) | 393 | struct iw_param *vwrq, char *extra) |
422 | { | 394 | { |
423 | int ret = 0; | ||
424 | struct lbs_private *priv = dev->priv; | 395 | struct lbs_private *priv = dev->priv; |
396 | s16 curlevel = 0; | ||
397 | int ret = 0; | ||
425 | 398 | ||
426 | lbs_deb_enter(LBS_DEB_WEXT); | 399 | lbs_deb_enter(LBS_DEB_WEXT); |
427 | 400 | ||
428 | ret = lbs_prepare_and_send_command(priv, | 401 | if (!priv->radio_on) { |
429 | CMD_802_11_RF_TX_POWER, | 402 | lbs_deb_wext("tx power off\n"); |
430 | CMD_ACT_TX_POWER_OPT_GET, | 403 | vwrq->value = 0; |
431 | CMD_OPTION_WAITFORRSP, 0, NULL); | 404 | vwrq->disabled = 1; |
405 | goto out; | ||
406 | } | ||
432 | 407 | ||
408 | ret = lbs_get_tx_power(priv, &curlevel, NULL, NULL); | ||
433 | if (ret) | 409 | if (ret) |
434 | goto out; | 410 | goto out; |
435 | 411 | ||
436 | lbs_deb_wext("tx power level %d dbm\n", priv->txpowerlevel); | 412 | lbs_deb_wext("tx power level %d dbm\n", curlevel); |
437 | vwrq->value = priv->txpowerlevel; | 413 | priv->txpower_cur = curlevel; |
414 | |||
415 | vwrq->value = curlevel; | ||
438 | vwrq->fixed = 1; | 416 | vwrq->fixed = 1; |
439 | if (priv->radioon) { | 417 | vwrq->disabled = 0; |
440 | vwrq->disabled = 0; | 418 | vwrq->flags = IW_TXPOW_DBM; |
441 | vwrq->flags = IW_TXPOW_DBM; | ||
442 | } else { | ||
443 | vwrq->disabled = 1; | ||
444 | } | ||
445 | 419 | ||
446 | out: | 420 | out: |
447 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | 421 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); |
@@ -693,22 +667,12 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info, | |||
693 | 667 | ||
694 | range->sensitivity = 0; | 668 | range->sensitivity = 0; |
695 | 669 | ||
696 | /* | 670 | /* Setup the supported power level ranges */ |
697 | * Setup the supported power level ranges | ||
698 | */ | ||
699 | memset(range->txpower, 0, sizeof(range->txpower)); | 671 | memset(range->txpower, 0, sizeof(range->txpower)); |
700 | range->txpower[0] = 5; | 672 | range->txpower_capa = IW_TXPOW_DBM | IW_TXPOW_RANGE; |
701 | range->txpower[1] = 7; | 673 | range->txpower[0] = priv->txpower_min; |
702 | range->txpower[2] = 9; | 674 | range->txpower[1] = priv->txpower_max; |
703 | range->txpower[3] = 11; | 675 | range->num_txpower = 2; |
704 | range->txpower[4] = 13; | ||
705 | range->txpower[5] = 15; | ||
706 | range->txpower[6] = 17; | ||
707 | range->txpower[7] = 19; | ||
708 | |||
709 | range->num_txpower = 8; | ||
710 | range->txpower_capa = IW_TXPOW_DBM; | ||
711 | range->txpower_capa |= IW_TXPOW_RANGE; | ||
712 | 676 | ||
713 | range->event_capa[0] = (IW_EVENT_CAPA_K_0 | | 677 | range->event_capa[0] = (IW_EVENT_CAPA_K_0 | |
714 | IW_EVENT_CAPA_MASK(SIOCGIWAP) | | 678 | IW_EVENT_CAPA_MASK(SIOCGIWAP) | |
@@ -998,9 +962,11 @@ static int lbs_mesh_set_freq(struct net_device *dev, | |||
998 | if (fwrq->m != priv->curbssparams.channel) { | 962 | if (fwrq->m != priv->curbssparams.channel) { |
999 | lbs_deb_wext("mesh channel change forces eth disconnect\n"); | 963 | lbs_deb_wext("mesh channel change forces eth disconnect\n"); |
1000 | if (priv->mode == IW_MODE_INFRA) | 964 | if (priv->mode == IW_MODE_INFRA) |
1001 | lbs_send_deauthentication(priv); | 965 | lbs_cmd_80211_deauthenticate(priv, |
966 | priv->curbssparams.bssid, | ||
967 | WLAN_REASON_DEAUTH_LEAVING); | ||
1002 | else if (priv->mode == IW_MODE_ADHOC) | 968 | else if (priv->mode == IW_MODE_ADHOC) |
1003 | lbs_stop_adhoc_network(priv); | 969 | lbs_adhoc_stop(priv); |
1004 | } | 970 | } |
1005 | lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, fwrq->m); | 971 | lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, fwrq->m); |
1006 | lbs_update_channel(priv); | 972 | lbs_update_channel(priv); |
@@ -1844,39 +1810,50 @@ static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info, | |||
1844 | { | 1810 | { |
1845 | int ret = 0; | 1811 | int ret = 0; |
1846 | struct lbs_private *priv = dev->priv; | 1812 | struct lbs_private *priv = dev->priv; |
1847 | 1813 | s16 dbm = (s16) vwrq->value; | |
1848 | u16 dbm; | ||
1849 | 1814 | ||
1850 | lbs_deb_enter(LBS_DEB_WEXT); | 1815 | lbs_deb_enter(LBS_DEB_WEXT); |
1851 | 1816 | ||
1852 | if (vwrq->disabled) { | 1817 | if (vwrq->disabled) { |
1853 | lbs_radio_ioctl(priv, RADIO_OFF); | 1818 | lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 0); |
1854 | return 0; | 1819 | goto out; |
1855 | } | 1820 | } |
1856 | 1821 | ||
1857 | priv->preamble = CMD_TYPE_AUTO_PREAMBLE; | 1822 | if (vwrq->fixed == 0) { |
1858 | 1823 | /* Auto power control */ | |
1859 | lbs_radio_ioctl(priv, RADIO_ON); | 1824 | dbm = priv->txpower_max; |
1825 | } else { | ||
1826 | /* Userspace check in iwrange if it should use dBm or mW, | ||
1827 | * therefore this should never happen... Jean II */ | ||
1828 | if ((vwrq->flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) { | ||
1829 | ret = -EOPNOTSUPP; | ||
1830 | goto out; | ||
1831 | } | ||
1860 | 1832 | ||
1861 | /* Userspace check in iwrange if it should use dBm or mW, | 1833 | /* Validate requested power level against firmware allowed levels */ |
1862 | * therefore this should never happen... Jean II */ | 1834 | if (priv->txpower_min && (dbm < priv->txpower_min)) { |
1863 | if ((vwrq->flags & IW_TXPOW_TYPE) == IW_TXPOW_MWATT) { | 1835 | ret = -EINVAL; |
1864 | return -EOPNOTSUPP; | 1836 | goto out; |
1865 | } else | 1837 | } |
1866 | dbm = (u16) vwrq->value; | ||
1867 | 1838 | ||
1868 | /* auto tx power control */ | 1839 | if (priv->txpower_max && (dbm > priv->txpower_max)) { |
1840 | ret = -EINVAL; | ||
1841 | goto out; | ||
1842 | } | ||
1843 | } | ||
1869 | 1844 | ||
1870 | if (vwrq->fixed == 0) | 1845 | /* If the radio was off, turn it on */ |
1871 | dbm = 0xffff; | 1846 | if (!priv->radio_on) { |
1847 | ret = lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 1); | ||
1848 | if (ret) | ||
1849 | goto out; | ||
1850 | } | ||
1872 | 1851 | ||
1873 | lbs_deb_wext("txpower set %d dbm\n", dbm); | 1852 | lbs_deb_wext("txpower set %d dBm\n", dbm); |
1874 | 1853 | ||
1875 | ret = lbs_prepare_and_send_command(priv, | 1854 | ret = lbs_set_tx_power(priv, dbm); |
1876 | CMD_802_11_RF_TX_POWER, | ||
1877 | CMD_ACT_TX_POWER_OPT_SET_LOW, | ||
1878 | CMD_OPTION_WAITFORRSP, 0, (void *)&dbm); | ||
1879 | 1855 | ||
1856 | out: | ||
1880 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | 1857 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); |
1881 | return ret; | 1858 | return ret; |
1882 | } | 1859 | } |
@@ -1928,6 +1905,11 @@ static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info, | |||
1928 | 1905 | ||
1929 | lbs_deb_enter(LBS_DEB_WEXT); | 1906 | lbs_deb_enter(LBS_DEB_WEXT); |
1930 | 1907 | ||
1908 | if (!priv->radio_on) { | ||
1909 | ret = -EINVAL; | ||
1910 | goto out; | ||
1911 | } | ||
1912 | |||
1931 | /* Check the size of the string */ | 1913 | /* Check the size of the string */ |
1932 | if (in_ssid_len > IW_ESSID_MAX_SIZE) { | 1914 | if (in_ssid_len > IW_ESSID_MAX_SIZE) { |
1933 | ret = -E2BIG; | 1915 | ret = -E2BIG; |
@@ -2005,6 +1987,11 @@ static int lbs_mesh_set_essid(struct net_device *dev, | |||
2005 | 1987 | ||
2006 | lbs_deb_enter(LBS_DEB_WEXT); | 1988 | lbs_deb_enter(LBS_DEB_WEXT); |
2007 | 1989 | ||
1990 | if (!priv->radio_on) { | ||
1991 | ret = -EINVAL; | ||
1992 | goto out; | ||
1993 | } | ||
1994 | |||
2008 | /* Check the size of the string */ | 1995 | /* Check the size of the string */ |
2009 | if (dwrq->length > IW_ESSID_MAX_SIZE) { | 1996 | if (dwrq->length > IW_ESSID_MAX_SIZE) { |
2010 | ret = -E2BIG; | 1997 | ret = -E2BIG; |
@@ -2046,6 +2033,9 @@ static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info, | |||
2046 | 2033 | ||
2047 | lbs_deb_enter(LBS_DEB_WEXT); | 2034 | lbs_deb_enter(LBS_DEB_WEXT); |
2048 | 2035 | ||
2036 | if (!priv->radio_on) | ||
2037 | return -EINVAL; | ||
2038 | |||
2049 | if (awrq->sa_family != ARPHRD_ETHER) | 2039 | if (awrq->sa_family != ARPHRD_ETHER) |
2050 | return -EINVAL; | 2040 | return -EINVAL; |
2051 | 2041 | ||
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index 2c1d680d2c55..c948021bff6a 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c | |||
@@ -477,9 +477,9 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb) | |||
477 | { | 477 | { |
478 | struct ieee80211_rx_status stats; | 478 | struct ieee80211_rx_status stats; |
479 | struct rxpd *prxpd; | 479 | struct rxpd *prxpd; |
480 | bool is_qos, is_4addr, is_amsdu, need_padding; | 480 | int need_padding; |
481 | unsigned int flags; | 481 | unsigned int flags; |
482 | u16 fc, fc_le; | 482 | struct ieee80211_hdr *hdr; |
483 | 483 | ||
484 | prxpd = (struct rxpd *) skb->data; | 484 | prxpd = (struct rxpd *) skb->data; |
485 | 485 | ||
@@ -497,19 +497,15 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb) | |||
497 | stats.rate_idx = prxpd->rx_rate; | 497 | stats.rate_idx = prxpd->rx_rate; |
498 | skb_pull(skb, sizeof(struct rxpd)); | 498 | skb_pull(skb, sizeof(struct rxpd)); |
499 | 499 | ||
500 | fc_le = *((__le16 *) skb->data); | 500 | hdr = (struct ieee80211_hdr *)skb->data; |
501 | fc = le16_to_cpu(fc_le); | ||
502 | flags = le32_to_cpu(*(__le32 *)(skb->data + 4)); | 501 | flags = le32_to_cpu(*(__le32 *)(skb->data + 4)); |
503 | 502 | ||
504 | is_qos = ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && | 503 | need_padding = ieee80211_is_data_qos(hdr->frame_control); |
505 | (fc & IEEE80211_STYPE_QOS_DATA); | 504 | need_padding ^= ieee80211_has_a4(hdr->frame_control); |
506 | is_4addr = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == | 505 | need_padding ^= ieee80211_is_data_qos(hdr->frame_control) && |
507 | (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS); | 506 | (*ieee80211_get_qos_ctl(hdr) & |
508 | is_amsdu = ((fc & 0x8C) == 0x88) && | 507 | IEEE80211_QOS_CONTROL_A_MSDU_PRESENT); |
509 | (*(skb->data + ieee80211_hdrlen(fc_le) - QOS_CONTROL_LEN) | ||
510 | & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT); | ||
511 | 508 | ||
512 | need_padding = is_qos ^ is_4addr ^ is_amsdu; | ||
513 | if (need_padding) { | 509 | if (need_padding) { |
514 | memmove(skb->data + 2, skb->data, skb->len); | 510 | memmove(skb->data + 2, skb->data, skb->len); |
515 | skb_reserve(skb, 2); | 511 | skb_reserve(skb, 2); |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 248d31a7aa33..732429d49122 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -446,7 +446,8 @@ static int __init init_mac80211_hwsim(void) | |||
446 | SET_IEEE80211_PERM_ADDR(hw, addr); | 446 | SET_IEEE80211_PERM_ADDR(hw, addr); |
447 | 447 | ||
448 | hw->channel_change_time = 1; | 448 | hw->channel_change_time = 1; |
449 | hw->queues = 1; | 449 | hw->queues = 4; |
450 | hw->ampdu_queues = 1; | ||
450 | 451 | ||
451 | memcpy(data->channels, hwsim_channels, sizeof(hwsim_channels)); | 452 | memcpy(data->channels, hwsim_channels, sizeof(hwsim_channels)); |
452 | memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates)); | 453 | memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates)); |
@@ -454,6 +455,19 @@ static int __init init_mac80211_hwsim(void) | |||
454 | data->band.n_channels = ARRAY_SIZE(hwsim_channels); | 455 | data->band.n_channels = ARRAY_SIZE(hwsim_channels); |
455 | data->band.bitrates = data->rates; | 456 | data->band.bitrates = data->rates; |
456 | data->band.n_bitrates = ARRAY_SIZE(hwsim_rates); | 457 | data->band.n_bitrates = ARRAY_SIZE(hwsim_rates); |
458 | data->band.ht_info.ht_supported = 1; | ||
459 | data->band.ht_info.cap = IEEE80211_HT_CAP_SUP_WIDTH | | ||
460 | IEEE80211_HT_CAP_GRN_FLD | | ||
461 | IEEE80211_HT_CAP_SGI_40 | | ||
462 | IEEE80211_HT_CAP_DSSSCCK40; | ||
463 | data->band.ht_info.ampdu_factor = 0x3; | ||
464 | data->band.ht_info.ampdu_density = 0x6; | ||
465 | memset(data->band.ht_info.supp_mcs_set, 0, | ||
466 | sizeof(data->band.ht_info.supp_mcs_set)); | ||
467 | data->band.ht_info.supp_mcs_set[0] = 0xff; | ||
468 | data->band.ht_info.supp_mcs_set[1] = 0xff; | ||
469 | data->band.ht_info.supp_mcs_set[12] = | ||
470 | IEEE80211_HT_CAP_MCS_TX_DEFINED; | ||
457 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &data->band; | 471 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &data->band; |
458 | 472 | ||
459 | err = ieee80211_register_hw(hw); | 473 | err = ieee80211_register_hw(hw); |
diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index 10df07de9e52..fca8762fa069 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h | |||
@@ -66,7 +66,7 @@ struct p54_common { | |||
66 | unsigned int tx_hdr_len; | 66 | unsigned int tx_hdr_len; |
67 | void *cached_vdcf; | 67 | void *cached_vdcf; |
68 | unsigned int fw_var; | 68 | unsigned int fw_var; |
69 | struct ieee80211_tx_queue_stats tx_stats[4]; | 69 | struct ieee80211_tx_queue_stats tx_stats[8]; |
70 | }; | 70 | }; |
71 | 71 | ||
72 | int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb); | 72 | int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb); |
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 29be3dc8ee09..17e06bbc996a 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c | |||
@@ -146,23 +146,23 @@ void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) | |||
146 | 146 | ||
147 | if (priv->fw_var >= 0x300) { | 147 | if (priv->fw_var >= 0x300) { |
148 | /* Firmware supports QoS, use it! */ | 148 | /* Firmware supports QoS, use it! */ |
149 | priv->tx_stats[0].limit = 3; | 149 | priv->tx_stats[4].limit = 3; |
150 | priv->tx_stats[1].limit = 4; | 150 | priv->tx_stats[5].limit = 4; |
151 | priv->tx_stats[2].limit = 3; | 151 | priv->tx_stats[6].limit = 3; |
152 | priv->tx_stats[3].limit = 1; | 152 | priv->tx_stats[7].limit = 1; |
153 | dev->queues = 4; | 153 | dev->queues = 4; |
154 | } | 154 | } |
155 | } | 155 | } |
156 | EXPORT_SYMBOL_GPL(p54_parse_firmware); | 156 | EXPORT_SYMBOL_GPL(p54_parse_firmware); |
157 | 157 | ||
158 | static int p54_convert_rev0_to_rev1(struct ieee80211_hw *dev, | 158 | static int p54_convert_rev0(struct ieee80211_hw *dev, |
159 | struct pda_pa_curve_data *curve_data) | 159 | struct pda_pa_curve_data *curve_data) |
160 | { | 160 | { |
161 | struct p54_common *priv = dev->priv; | 161 | struct p54_common *priv = dev->priv; |
162 | struct pda_pa_curve_data_sample_rev1 *rev1; | 162 | struct p54_pa_curve_data_sample *dst; |
163 | struct pda_pa_curve_data_sample_rev0 *rev0; | 163 | struct pda_pa_curve_data_sample_rev0 *src; |
164 | size_t cd_len = sizeof(*curve_data) + | 164 | size_t cd_len = sizeof(*curve_data) + |
165 | (curve_data->points_per_channel*sizeof(*rev1) + 2) * | 165 | (curve_data->points_per_channel*sizeof(*dst) + 2) * |
166 | curve_data->channels; | 166 | curve_data->channels; |
167 | unsigned int i, j; | 167 | unsigned int i, j; |
168 | void *source, *target; | 168 | void *source, *target; |
@@ -180,27 +180,63 @@ static int p54_convert_rev0_to_rev1(struct ieee80211_hw *dev, | |||
180 | *((__le16 *)target) = *freq; | 180 | *((__le16 *)target) = *freq; |
181 | target += sizeof(__le16); | 181 | target += sizeof(__le16); |
182 | for (j = 0; j < curve_data->points_per_channel; j++) { | 182 | for (j = 0; j < curve_data->points_per_channel; j++) { |
183 | rev1 = target; | 183 | dst = target; |
184 | rev0 = source; | 184 | src = source; |
185 | 185 | ||
186 | rev1->rf_power = rev0->rf_power; | 186 | dst->rf_power = src->rf_power; |
187 | rev1->pa_detector = rev0->pa_detector; | 187 | dst->pa_detector = src->pa_detector; |
188 | rev1->data_64qam = rev0->pcv; | 188 | dst->data_64qam = src->pcv; |
189 | /* "invent" the points for the other modulations */ | 189 | /* "invent" the points for the other modulations */ |
190 | #define SUB(x,y) (u8)((x) - (y)) > (x) ? 0 : (x) - (y) | 190 | #define SUB(x,y) (u8)((x) - (y)) > (x) ? 0 : (x) - (y) |
191 | rev1->data_16qam = SUB(rev0->pcv, 12); | 191 | dst->data_16qam = SUB(src->pcv, 12); |
192 | rev1->data_qpsk = SUB(rev1->data_16qam, 12); | 192 | dst->data_qpsk = SUB(dst->data_16qam, 12); |
193 | rev1->data_bpsk = SUB(rev1->data_qpsk, 12); | 193 | dst->data_bpsk = SUB(dst->data_qpsk, 12); |
194 | rev1->data_barker= SUB(rev1->data_bpsk, 14); | 194 | dst->data_barker = SUB(dst->data_bpsk, 14); |
195 | #undef SUB | 195 | #undef SUB |
196 | target += sizeof(*rev1); | 196 | target += sizeof(*dst); |
197 | source += sizeof(*rev0); | 197 | source += sizeof(*src); |
198 | } | 198 | } |
199 | } | 199 | } |
200 | 200 | ||
201 | return 0; | 201 | return 0; |
202 | } | 202 | } |
203 | 203 | ||
204 | static int p54_convert_rev1(struct ieee80211_hw *dev, | ||
205 | struct pda_pa_curve_data *curve_data) | ||
206 | { | ||
207 | struct p54_common *priv = dev->priv; | ||
208 | struct p54_pa_curve_data_sample *dst; | ||
209 | struct pda_pa_curve_data_sample_rev1 *src; | ||
210 | size_t cd_len = sizeof(*curve_data) + | ||
211 | (curve_data->points_per_channel*sizeof(*dst) + 2) * | ||
212 | curve_data->channels; | ||
213 | unsigned int i, j; | ||
214 | void *source, *target; | ||
215 | |||
216 | priv->curve_data = kmalloc(cd_len, GFP_KERNEL); | ||
217 | if (!priv->curve_data) | ||
218 | return -ENOMEM; | ||
219 | |||
220 | memcpy(priv->curve_data, curve_data, sizeof(*curve_data)); | ||
221 | source = curve_data->data; | ||
222 | target = priv->curve_data->data; | ||
223 | for (i = 0; i < curve_data->channels; i++) { | ||
224 | __le16 *freq = source; | ||
225 | source += sizeof(__le16); | ||
226 | *((__le16 *)target) = *freq; | ||
227 | target += sizeof(__le16); | ||
228 | for (j = 0; j < curve_data->points_per_channel; j++) { | ||
229 | memcpy(target, source, sizeof(*src)); | ||
230 | |||
231 | target += sizeof(*dst); | ||
232 | source += sizeof(*src); | ||
233 | } | ||
234 | source++; | ||
235 | } | ||
236 | |||
237 | return 0; | ||
238 | } | ||
239 | |||
204 | int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) | 240 | int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) |
205 | { | 241 | { |
206 | struct p54_common *priv = dev->priv; | 242 | struct p54_common *priv = dev->priv; |
@@ -250,27 +286,32 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) | |||
250 | entry->data[1]*sizeof(*priv->output_limit)); | 286 | entry->data[1]*sizeof(*priv->output_limit)); |
251 | priv->output_limit_len = entry->data[1]; | 287 | priv->output_limit_len = entry->data[1]; |
252 | break; | 288 | break; |
253 | case PDR_PRISM_PA_CAL_CURVE_DATA: | 289 | case PDR_PRISM_PA_CAL_CURVE_DATA: { |
254 | if (data_len < sizeof(struct pda_pa_curve_data)) { | 290 | struct pda_pa_curve_data *curve_data = |
291 | (struct pda_pa_curve_data *)entry->data; | ||
292 | if (data_len < sizeof(*curve_data)) { | ||
255 | err = -EINVAL; | 293 | err = -EINVAL; |
256 | goto err; | 294 | goto err; |
257 | } | 295 | } |
258 | 296 | ||
259 | if (((struct pda_pa_curve_data *)entry->data)->cal_method_rev) { | 297 | switch (curve_data->cal_method_rev) { |
260 | priv->curve_data = kmalloc(data_len, GFP_KERNEL); | 298 | case 0: |
261 | if (!priv->curve_data) { | 299 | err = p54_convert_rev0(dev, curve_data); |
262 | err = -ENOMEM; | 300 | break; |
263 | goto err; | 301 | case 1: |
264 | } | 302 | err = p54_convert_rev1(dev, curve_data); |
265 | 303 | break; | |
266 | memcpy(priv->curve_data, entry->data, data_len); | 304 | default: |
267 | } else { | 305 | printk(KERN_ERR "p54: unknown curve data " |
268 | err = p54_convert_rev0_to_rev1(dev, (struct pda_pa_curve_data *)entry->data); | 306 | "revision %d\n", |
269 | if (err) | 307 | curve_data->cal_method_rev); |
270 | goto err; | 308 | err = -ENODEV; |
309 | break; | ||
271 | } | 310 | } |
311 | if (err) | ||
312 | goto err; | ||
272 | 313 | ||
273 | break; | 314 | } |
274 | case PDR_PRISM_ZIF_TX_IQ_CALIBRATION: | 315 | case PDR_PRISM_ZIF_TX_IQ_CALIBRATION: |
275 | priv->iq_autocal = kmalloc(data_len, GFP_KERNEL); | 316 | priv->iq_autocal = kmalloc(data_len, GFP_KERNEL); |
276 | if (!priv->iq_autocal) { | 317 | if (!priv->iq_autocal) { |
@@ -377,7 +418,7 @@ static void inline p54_wake_free_queues(struct ieee80211_hw *dev) | |||
377 | int i; | 418 | int i; |
378 | 419 | ||
379 | for (i = 0; i < dev->queues; i++) | 420 | for (i = 0; i < dev->queues; i++) |
380 | if (priv->tx_stats[i].len < priv->tx_stats[i].limit) | 421 | if (priv->tx_stats[i + 4].len < priv->tx_stats[i + 4].limit) |
381 | ieee80211_wake_queue(dev, i); | 422 | ieee80211_wake_queue(dev, i); |
382 | } | 423 | } |
383 | 424 | ||
@@ -391,7 +432,9 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
391 | struct memrecord *range = NULL; | 432 | struct memrecord *range = NULL; |
392 | u32 freed = 0; | 433 | u32 freed = 0; |
393 | u32 last_addr = priv->rx_start; | 434 | u32 last_addr = priv->rx_start; |
435 | unsigned long flags; | ||
394 | 436 | ||
437 | spin_lock_irqsave(&priv->tx_queue.lock, flags); | ||
395 | while (entry != (struct sk_buff *)&priv->tx_queue) { | 438 | while (entry != (struct sk_buff *)&priv->tx_queue) { |
396 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry); | 439 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry); |
397 | range = (void *)info->driver_data; | 440 | range = (void *)info->driver_data; |
@@ -412,13 +455,15 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
412 | 455 | ||
413 | last_addr = range->end_addr; | 456 | last_addr = range->end_addr; |
414 | __skb_unlink(entry, &priv->tx_queue); | 457 | __skb_unlink(entry, &priv->tx_queue); |
458 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); | ||
459 | |||
415 | memset(&info->status, 0, sizeof(info->status)); | 460 | memset(&info->status, 0, sizeof(info->status)); |
416 | entry_hdr = (struct p54_control_hdr *) entry->data; | 461 | entry_hdr = (struct p54_control_hdr *) entry->data; |
417 | entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data; | 462 | entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data; |
418 | if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0) | 463 | if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0) |
419 | pad = entry_data->align[0]; | 464 | pad = entry_data->align[0]; |
420 | 465 | ||
421 | priv->tx_stats[entry_data->hw_queue - 4].len--; | 466 | priv->tx_stats[entry_data->hw_queue].len--; |
422 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { | 467 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { |
423 | if (!(payload->status & 0x01)) | 468 | if (!(payload->status & 0x01)) |
424 | info->flags |= IEEE80211_TX_STAT_ACK; | 469 | info->flags |= IEEE80211_TX_STAT_ACK; |
@@ -429,12 +474,14 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
429 | info->status.ack_signal = le16_to_cpu(payload->ack_rssi); | 474 | info->status.ack_signal = le16_to_cpu(payload->ack_rssi); |
430 | skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data)); | 475 | skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data)); |
431 | ieee80211_tx_status_irqsafe(dev, entry); | 476 | ieee80211_tx_status_irqsafe(dev, entry); |
432 | break; | 477 | goto out; |
433 | } else | 478 | } else |
434 | last_addr = range->end_addr; | 479 | last_addr = range->end_addr; |
435 | entry = entry->next; | 480 | entry = entry->next; |
436 | } | 481 | } |
482 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); | ||
437 | 483 | ||
484 | out: | ||
438 | if (freed >= IEEE80211_MAX_RTS_THRESHOLD + 0x170 + | 485 | if (freed >= IEEE80211_MAX_RTS_THRESHOLD + 0x170 + |
439 | sizeof(struct p54_control_hdr)) | 486 | sizeof(struct p54_control_hdr)) |
440 | p54_wake_free_queues(dev); | 487 | p54_wake_free_queues(dev); |
@@ -559,7 +606,7 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
559 | u8 rate; | 606 | u8 rate; |
560 | u8 cts_rate = 0x20; | 607 | u8 cts_rate = 0x20; |
561 | 608 | ||
562 | current_queue = &priv->tx_stats[skb_get_queue_mapping(skb)]; | 609 | current_queue = &priv->tx_stats[skb_get_queue_mapping(skb) + 4]; |
563 | if (unlikely(current_queue->len > current_queue->limit)) | 610 | if (unlikely(current_queue->len > current_queue->limit)) |
564 | return NETDEV_TX_BUSY; | 611 | return NETDEV_TX_BUSY; |
565 | current_queue->len++; | 612 | current_queue->len++; |
@@ -672,12 +719,9 @@ static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq) | |||
672 | struct p54_control_hdr *hdr; | 719 | struct p54_control_hdr *hdr; |
673 | struct p54_tx_control_channel *chan; | 720 | struct p54_tx_control_channel *chan; |
674 | unsigned int i; | 721 | unsigned int i; |
675 | size_t payload_len = sizeof(*chan) + sizeof(u32)*2 + | ||
676 | sizeof(*chan->curve_data) * | ||
677 | priv->curve_data->points_per_channel; | ||
678 | void *entry; | 722 | void *entry; |
679 | 723 | ||
680 | hdr = kzalloc(sizeof(*hdr) + payload_len + | 724 | hdr = kzalloc(sizeof(*hdr) + sizeof(*chan) + |
681 | priv->tx_hdr_len, GFP_KERNEL); | 725 | priv->tx_hdr_len, GFP_KERNEL); |
682 | if (!hdr) | 726 | if (!hdr) |
683 | return -ENOMEM; | 727 | return -ENOMEM; |
@@ -689,10 +733,10 @@ static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq) | |||
689 | hdr->magic1 = cpu_to_le16(0x8001); | 733 | hdr->magic1 = cpu_to_le16(0x8001); |
690 | hdr->len = cpu_to_le16(sizeof(*chan)); | 734 | hdr->len = cpu_to_le16(sizeof(*chan)); |
691 | hdr->type = cpu_to_le16(P54_CONTROL_TYPE_CHANNEL_CHANGE); | 735 | hdr->type = cpu_to_le16(P54_CONTROL_TYPE_CHANNEL_CHANGE); |
692 | p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + payload_len); | 736 | p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*chan)); |
693 | 737 | ||
694 | chan->magic1 = cpu_to_le16(0x1); | 738 | chan->flags = cpu_to_le16(0x1); |
695 | chan->magic2 = cpu_to_le16(0x0); | 739 | chan->dwell = cpu_to_le16(0x0); |
696 | 740 | ||
697 | for (i = 0; i < priv->iq_autocal_len; i++) { | 741 | for (i = 0; i < priv->iq_autocal_len; i++) { |
698 | if (priv->iq_autocal[i].freq != freq) | 742 | if (priv->iq_autocal[i].freq != freq) |
@@ -710,35 +754,41 @@ static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq) | |||
710 | continue; | 754 | continue; |
711 | 755 | ||
712 | chan->val_barker = 0x38; | 756 | chan->val_barker = 0x38; |
713 | chan->val_bpsk = priv->output_limit[i].val_bpsk; | 757 | chan->val_bpsk = chan->dup_bpsk = |
714 | chan->val_qpsk = priv->output_limit[i].val_qpsk; | 758 | priv->output_limit[i].val_bpsk; |
715 | chan->val_16qam = priv->output_limit[i].val_16qam; | 759 | chan->val_qpsk = chan->dup_qpsk = |
716 | chan->val_64qam = priv->output_limit[i].val_64qam; | 760 | priv->output_limit[i].val_qpsk; |
761 | chan->val_16qam = chan->dup_16qam = | ||
762 | priv->output_limit[i].val_16qam; | ||
763 | chan->val_64qam = chan->dup_64qam = | ||
764 | priv->output_limit[i].val_64qam; | ||
717 | break; | 765 | break; |
718 | } | 766 | } |
719 | if (i == priv->output_limit_len) | 767 | if (i == priv->output_limit_len) |
720 | goto err; | 768 | goto err; |
721 | 769 | ||
722 | chan->pa_points_per_curve = priv->curve_data->points_per_channel; | ||
723 | |||
724 | entry = priv->curve_data->data; | 770 | entry = priv->curve_data->data; |
725 | for (i = 0; i < priv->curve_data->channels; i++) { | 771 | for (i = 0; i < priv->curve_data->channels; i++) { |
726 | if (*((__le16 *)entry) != freq) { | 772 | if (*((__le16 *)entry) != freq) { |
727 | entry += sizeof(__le16); | 773 | entry += sizeof(__le16); |
728 | entry += sizeof(struct pda_pa_curve_data_sample_rev1) * | 774 | entry += sizeof(struct p54_pa_curve_data_sample) * |
729 | chan->pa_points_per_curve; | 775 | priv->curve_data->points_per_channel; |
730 | continue; | 776 | continue; |
731 | } | 777 | } |
732 | 778 | ||
733 | entry += sizeof(__le16); | 779 | entry += sizeof(__le16); |
780 | chan->pa_points_per_curve = | ||
781 | min(priv->curve_data->points_per_channel, (u8) 8); | ||
782 | |||
734 | memcpy(chan->curve_data, entry, sizeof(*chan->curve_data) * | 783 | memcpy(chan->curve_data, entry, sizeof(*chan->curve_data) * |
735 | chan->pa_points_per_curve); | 784 | chan->pa_points_per_curve); |
736 | break; | 785 | break; |
737 | } | 786 | } |
738 | 787 | ||
739 | memcpy(hdr->data + payload_len - 4, &chan->val_bpsk, 4); | 788 | chan->rssical_mul = cpu_to_le16(130); |
789 | chan->rssical_add = cpu_to_le16(0xfe70); /* -400 */ | ||
740 | 790 | ||
741 | priv->tx(dev, hdr, sizeof(*hdr) + payload_len, 1); | 791 | priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*chan), 1); |
742 | return 0; | 792 | return 0; |
743 | 793 | ||
744 | err: | 794 | err: |
@@ -987,7 +1037,7 @@ static int p54_get_tx_stats(struct ieee80211_hw *dev, | |||
987 | { | 1037 | { |
988 | struct p54_common *priv = dev->priv; | 1038 | struct p54_common *priv = dev->priv; |
989 | 1039 | ||
990 | memcpy(stats, &priv->tx_stats, sizeof(stats[0]) * dev->queues); | 1040 | memcpy(stats, &priv->tx_stats[4], sizeof(stats[0]) * dev->queues); |
991 | 1041 | ||
992 | return 0; | 1042 | return 0; |
993 | } | 1043 | } |
@@ -1025,7 +1075,11 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) | |||
1025 | dev->channel_change_time = 1000; /* TODO: find actual value */ | 1075 | dev->channel_change_time = 1000; /* TODO: find actual value */ |
1026 | dev->max_signal = 127; | 1076 | dev->max_signal = 127; |
1027 | 1077 | ||
1028 | priv->tx_stats[0].limit = 5; | 1078 | priv->tx_stats[0].limit = 1; |
1079 | priv->tx_stats[1].limit = 1; | ||
1080 | priv->tx_stats[2].limit = 1; | ||
1081 | priv->tx_stats[3].limit = 1; | ||
1082 | priv->tx_stats[4].limit = 5; | ||
1029 | dev->queues = 1; | 1083 | dev->queues = 1; |
1030 | 1084 | ||
1031 | dev->extra_tx_headroom = sizeof(struct p54_control_hdr) + 4 + | 1085 | dev->extra_tx_headroom = sizeof(struct p54_control_hdr) + 4 + |
diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h index 9bc2a1cf4b57..a79c1a146917 100644 --- a/drivers/net/wireless/p54/p54common.h +++ b/drivers/net/wireless/p54/p54common.h | |||
@@ -89,6 +89,16 @@ struct pda_pa_curve_data_sample_rev1 { | |||
89 | u8 data_qpsk; | 89 | u8 data_qpsk; |
90 | u8 data_16qam; | 90 | u8 data_16qam; |
91 | u8 data_64qam; | 91 | u8 data_64qam; |
92 | } __attribute__ ((packed)); | ||
93 | |||
94 | struct p54_pa_curve_data_sample { | ||
95 | u8 rf_power; | ||
96 | u8 pa_detector; | ||
97 | u8 data_barker; | ||
98 | u8 data_bpsk; | ||
99 | u8 data_qpsk; | ||
100 | u8 data_16qam; | ||
101 | u8 data_64qam; | ||
92 | u8 padding; | 102 | u8 padding; |
93 | } __attribute__ ((packed)); | 103 | } __attribute__ ((packed)); |
94 | 104 | ||
@@ -212,8 +222,8 @@ struct p54_tx_control_filter { | |||
212 | } __attribute__ ((packed)); | 222 | } __attribute__ ((packed)); |
213 | 223 | ||
214 | struct p54_tx_control_channel { | 224 | struct p54_tx_control_channel { |
215 | __le16 magic1; | 225 | __le16 flags; |
216 | __le16 magic2; | 226 | __le16 dwell; |
217 | u8 padding1[20]; | 227 | u8 padding1[20]; |
218 | struct pda_iq_autocal_entry iq_autocal; | 228 | struct pda_iq_autocal_entry iq_autocal; |
219 | u8 pa_points_per_curve; | 229 | u8 pa_points_per_curve; |
@@ -222,8 +232,13 @@ struct p54_tx_control_channel { | |||
222 | u8 val_qpsk; | 232 | u8 val_qpsk; |
223 | u8 val_16qam; | 233 | u8 val_16qam; |
224 | u8 val_64qam; | 234 | u8 val_64qam; |
225 | struct pda_pa_curve_data_sample_rev1 curve_data[0]; | 235 | struct pda_pa_curve_data_sample_rev1 curve_data[8]; |
226 | /* additional padding/data after curve_data */ | 236 | u8 dup_bpsk; |
237 | u8 dup_qpsk; | ||
238 | u8 dup_16qam; | ||
239 | u8 dup_64qam; | ||
240 | __le16 rssical_mul; | ||
241 | __le16 rssical_add; | ||
227 | } __attribute__ ((packed)); | 242 | } __attribute__ ((packed)); |
228 | 243 | ||
229 | struct p54_tx_control_led { | 244 | struct p54_tx_control_led { |
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index ea2dc3d93c4d..e9db4495c626 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * Linux device driver for PCI based Prism54 | 3 | * Linux device driver for PCI based Prism54 |
4 | * | 4 | * |
5 | * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net> | 5 | * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net> |
6 | * Copyright (c) 2008, Christian Lamparter <chunkeey@web.de> | ||
6 | * | 7 | * |
7 | * Based on the islsm (softmac prism54) driver, which is: | 8 | * Based on the islsm (softmac prism54) driver, which is: |
8 | * Copyright 2004-2006 Jean-Baptiste Note <jean-baptiste.note@m4x.org>, et al. | 9 | * Copyright 2004-2006 Jean-Baptiste Note <jean-baptiste.note@m4x.org>, et al. |
@@ -237,20 +238,22 @@ static int p54p_read_eeprom(struct ieee80211_hw *dev) | |||
237 | return err; | 238 | return err; |
238 | } | 239 | } |
239 | 240 | ||
240 | static void p54p_refill_rx_ring(struct ieee80211_hw *dev) | 241 | static void p54p_refill_rx_ring(struct ieee80211_hw *dev, |
242 | int ring_index, struct p54p_desc *ring, u32 ring_limit, | ||
243 | struct sk_buff **rx_buf) | ||
241 | { | 244 | { |
242 | struct p54p_priv *priv = dev->priv; | 245 | struct p54p_priv *priv = dev->priv; |
243 | struct p54p_ring_control *ring_control = priv->ring_control; | 246 | struct p54p_ring_control *ring_control = priv->ring_control; |
244 | u32 limit, host_idx, idx; | 247 | u32 limit, idx, i; |
245 | 248 | ||
246 | host_idx = le32_to_cpu(ring_control->host_idx[0]); | 249 | idx = le32_to_cpu(ring_control->host_idx[ring_index]); |
247 | limit = host_idx; | 250 | limit = idx; |
248 | limit -= le32_to_cpu(ring_control->device_idx[0]); | 251 | limit -= le32_to_cpu(ring_control->device_idx[ring_index]); |
249 | limit = ARRAY_SIZE(ring_control->rx_data) - limit; | 252 | limit = ring_limit - limit; |
250 | 253 | ||
251 | idx = host_idx % ARRAY_SIZE(ring_control->rx_data); | 254 | i = idx % ring_limit; |
252 | while (limit-- > 1) { | 255 | while (limit-- > 1) { |
253 | struct p54p_desc *desc = &ring_control->rx_data[idx]; | 256 | struct p54p_desc *desc = &ring[i]; |
254 | 257 | ||
255 | if (!desc->host_addr) { | 258 | if (!desc->host_addr) { |
256 | struct sk_buff *skb; | 259 | struct sk_buff *skb; |
@@ -267,16 +270,106 @@ static void p54p_refill_rx_ring(struct ieee80211_hw *dev) | |||
267 | desc->device_addr = 0; // FIXME: necessary? | 270 | desc->device_addr = 0; // FIXME: necessary? |
268 | desc->len = cpu_to_le16(MAX_RX_SIZE); | 271 | desc->len = cpu_to_le16(MAX_RX_SIZE); |
269 | desc->flags = 0; | 272 | desc->flags = 0; |
270 | priv->rx_buf[idx] = skb; | 273 | rx_buf[i] = skb; |
271 | } | 274 | } |
272 | 275 | ||
276 | i++; | ||
273 | idx++; | 277 | idx++; |
274 | host_idx++; | 278 | i %= ring_limit; |
275 | idx %= ARRAY_SIZE(ring_control->rx_data); | ||
276 | } | 279 | } |
277 | 280 | ||
278 | wmb(); | 281 | wmb(); |
279 | ring_control->host_idx[0] = cpu_to_le32(host_idx); | 282 | ring_control->host_idx[ring_index] = cpu_to_le32(idx); |
283 | } | ||
284 | |||
285 | static void p54p_check_rx_ring(struct ieee80211_hw *dev, u32 *index, | ||
286 | int ring_index, struct p54p_desc *ring, u32 ring_limit, | ||
287 | struct sk_buff **rx_buf) | ||
288 | { | ||
289 | struct p54p_priv *priv = dev->priv; | ||
290 | struct p54p_ring_control *ring_control = priv->ring_control; | ||
291 | struct p54p_desc *desc; | ||
292 | u32 idx, i; | ||
293 | |||
294 | i = (*index) % ring_limit; | ||
295 | (*index) = idx = le32_to_cpu(ring_control->device_idx[ring_index]); | ||
296 | idx %= ring_limit; | ||
297 | while (i != idx) { | ||
298 | u16 len; | ||
299 | struct sk_buff *skb; | ||
300 | desc = &ring[i]; | ||
301 | len = le16_to_cpu(desc->len); | ||
302 | skb = rx_buf[i]; | ||
303 | |||
304 | if (!skb) | ||
305 | continue; | ||
306 | |||
307 | skb_put(skb, len); | ||
308 | |||
309 | if (p54_rx(dev, skb)) { | ||
310 | pci_unmap_single(priv->pdev, | ||
311 | le32_to_cpu(desc->host_addr), | ||
312 | MAX_RX_SIZE, PCI_DMA_FROMDEVICE); | ||
313 | rx_buf[i] = NULL; | ||
314 | desc->host_addr = 0; | ||
315 | } else { | ||
316 | skb_trim(skb, 0); | ||
317 | desc->len = cpu_to_le16(MAX_RX_SIZE); | ||
318 | } | ||
319 | |||
320 | i++; | ||
321 | i %= ring_limit; | ||
322 | } | ||
323 | |||
324 | p54p_refill_rx_ring(dev, ring_index, ring, ring_limit, rx_buf); | ||
325 | } | ||
326 | |||
327 | /* caller must hold priv->lock */ | ||
328 | static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, | ||
329 | int ring_index, struct p54p_desc *ring, u32 ring_limit, | ||
330 | void **tx_buf) | ||
331 | { | ||
332 | struct p54p_priv *priv = dev->priv; | ||
333 | struct p54p_ring_control *ring_control = priv->ring_control; | ||
334 | struct p54p_desc *desc; | ||
335 | u32 idx, i; | ||
336 | |||
337 | i = (*index) % ring_limit; | ||
338 | (*index) = idx = le32_to_cpu(ring_control->device_idx[1]); | ||
339 | idx %= ring_limit; | ||
340 | |||
341 | while (i != idx) { | ||
342 | desc = &ring[i]; | ||
343 | kfree(tx_buf[i]); | ||
344 | tx_buf[i] = NULL; | ||
345 | |||
346 | pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr), | ||
347 | le16_to_cpu(desc->len), PCI_DMA_TODEVICE); | ||
348 | |||
349 | desc->host_addr = 0; | ||
350 | desc->device_addr = 0; | ||
351 | desc->len = 0; | ||
352 | desc->flags = 0; | ||
353 | |||
354 | i++; | ||
355 | i %= ring_limit; | ||
356 | } | ||
357 | } | ||
358 | |||
359 | static void p54p_rx_tasklet(unsigned long dev_id) | ||
360 | { | ||
361 | struct ieee80211_hw *dev = (struct ieee80211_hw *)dev_id; | ||
362 | struct p54p_priv *priv = dev->priv; | ||
363 | struct p54p_ring_control *ring_control = priv->ring_control; | ||
364 | |||
365 | p54p_check_rx_ring(dev, &priv->rx_idx_mgmt, 2, ring_control->rx_mgmt, | ||
366 | ARRAY_SIZE(ring_control->rx_mgmt), priv->rx_buf_mgmt); | ||
367 | |||
368 | p54p_check_rx_ring(dev, &priv->rx_idx_data, 0, ring_control->rx_data, | ||
369 | ARRAY_SIZE(ring_control->rx_data), priv->rx_buf_data); | ||
370 | |||
371 | wmb(); | ||
372 | P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE)); | ||
280 | } | 373 | } |
281 | 374 | ||
282 | static irqreturn_t p54p_interrupt(int irq, void *dev_id) | 375 | static irqreturn_t p54p_interrupt(int irq, void *dev_id) |
@@ -298,65 +391,18 @@ static irqreturn_t p54p_interrupt(int irq, void *dev_id) | |||
298 | reg &= P54P_READ(int_enable); | 391 | reg &= P54P_READ(int_enable); |
299 | 392 | ||
300 | if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)) { | 393 | if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)) { |
301 | struct p54p_desc *desc; | 394 | p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, |
302 | u32 idx, i; | 395 | 3, ring_control->tx_mgmt, |
303 | i = priv->tx_idx; | 396 | ARRAY_SIZE(ring_control->tx_mgmt), |
304 | i %= ARRAY_SIZE(ring_control->tx_data); | 397 | priv->tx_buf_mgmt); |
305 | priv->tx_idx = idx = le32_to_cpu(ring_control->device_idx[1]); | ||
306 | idx %= ARRAY_SIZE(ring_control->tx_data); | ||
307 | |||
308 | while (i != idx) { | ||
309 | desc = &ring_control->tx_data[i]; | ||
310 | if (priv->tx_buf[i]) { | ||
311 | kfree(priv->tx_buf[i]); | ||
312 | priv->tx_buf[i] = NULL; | ||
313 | } | ||
314 | |||
315 | pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr), | ||
316 | le16_to_cpu(desc->len), PCI_DMA_TODEVICE); | ||
317 | 398 | ||
318 | desc->host_addr = 0; | 399 | p54p_check_tx_ring(dev, &priv->tx_idx_data, |
319 | desc->device_addr = 0; | 400 | 1, ring_control->tx_data, |
320 | desc->len = 0; | 401 | ARRAY_SIZE(ring_control->tx_data), |
321 | desc->flags = 0; | 402 | priv->tx_buf_data); |
322 | 403 | ||
323 | i++; | 404 | tasklet_schedule(&priv->rx_tasklet); |
324 | i %= ARRAY_SIZE(ring_control->tx_data); | ||
325 | } | ||
326 | |||
327 | i = priv->rx_idx; | ||
328 | i %= ARRAY_SIZE(ring_control->rx_data); | ||
329 | priv->rx_idx = idx = le32_to_cpu(ring_control->device_idx[0]); | ||
330 | idx %= ARRAY_SIZE(ring_control->rx_data); | ||
331 | while (i != idx) { | ||
332 | u16 len; | ||
333 | struct sk_buff *skb; | ||
334 | desc = &ring_control->rx_data[i]; | ||
335 | len = le16_to_cpu(desc->len); | ||
336 | skb = priv->rx_buf[i]; | ||
337 | |||
338 | skb_put(skb, len); | ||
339 | |||
340 | if (p54_rx(dev, skb)) { | ||
341 | pci_unmap_single(priv->pdev, | ||
342 | le32_to_cpu(desc->host_addr), | ||
343 | MAX_RX_SIZE, PCI_DMA_FROMDEVICE); | ||
344 | |||
345 | priv->rx_buf[i] = NULL; | ||
346 | desc->host_addr = 0; | ||
347 | } else { | ||
348 | skb_trim(skb, 0); | ||
349 | desc->len = cpu_to_le16(MAX_RX_SIZE); | ||
350 | } | ||
351 | |||
352 | i++; | ||
353 | i %= ARRAY_SIZE(ring_control->rx_data); | ||
354 | } | ||
355 | 405 | ||
356 | p54p_refill_rx_ring(dev); | ||
357 | |||
358 | wmb(); | ||
359 | P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE)); | ||
360 | } else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT)) | 406 | } else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT)) |
361 | complete(&priv->boot_comp); | 407 | complete(&priv->boot_comp); |
362 | 408 | ||
@@ -392,7 +438,7 @@ static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data, | |||
392 | ring_control->host_idx[1] = cpu_to_le32(idx + 1); | 438 | ring_control->host_idx[1] = cpu_to_le32(idx + 1); |
393 | 439 | ||
394 | if (free_on_tx) | 440 | if (free_on_tx) |
395 | priv->tx_buf[i] = data; | 441 | priv->tx_buf_data[i] = data; |
396 | 442 | ||
397 | spin_unlock_irqrestore(&priv->lock, flags); | 443 | spin_unlock_irqrestore(&priv->lock, flags); |
398 | 444 | ||
@@ -420,8 +466,14 @@ static int p54p_open(struct ieee80211_hw *dev) | |||
420 | } | 466 | } |
421 | 467 | ||
422 | memset(priv->ring_control, 0, sizeof(*priv->ring_control)); | 468 | memset(priv->ring_control, 0, sizeof(*priv->ring_control)); |
423 | priv->rx_idx = priv->tx_idx = 0; | 469 | priv->rx_idx_data = priv->tx_idx_data = 0; |
424 | p54p_refill_rx_ring(dev); | 470 | priv->rx_idx_mgmt = priv->tx_idx_mgmt = 0; |
471 | |||
472 | p54p_refill_rx_ring(dev, 0, priv->ring_control->rx_data, | ||
473 | ARRAY_SIZE(priv->ring_control->rx_data), priv->rx_buf_data); | ||
474 | |||
475 | p54p_refill_rx_ring(dev, 2, priv->ring_control->rx_mgmt, | ||
476 | ARRAY_SIZE(priv->ring_control->rx_mgmt), priv->rx_buf_mgmt); | ||
425 | 477 | ||
426 | p54p_upload_firmware(dev); | 478 | p54p_upload_firmware(dev); |
427 | 479 | ||
@@ -465,6 +517,8 @@ static void p54p_stop(struct ieee80211_hw *dev) | |||
465 | unsigned int i; | 517 | unsigned int i; |
466 | struct p54p_desc *desc; | 518 | struct p54p_desc *desc; |
467 | 519 | ||
520 | tasklet_kill(&priv->rx_tasklet); | ||
521 | |||
468 | P54P_WRITE(int_enable, cpu_to_le32(0)); | 522 | P54P_WRITE(int_enable, cpu_to_le32(0)); |
469 | P54P_READ(int_enable); | 523 | P54P_READ(int_enable); |
470 | udelay(10); | 524 | udelay(10); |
@@ -473,26 +527,51 @@ static void p54p_stop(struct ieee80211_hw *dev) | |||
473 | 527 | ||
474 | P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET)); | 528 | P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET)); |
475 | 529 | ||
476 | for (i = 0; i < ARRAY_SIZE(priv->rx_buf); i++) { | 530 | for (i = 0; i < ARRAY_SIZE(priv->rx_buf_data); i++) { |
477 | desc = &ring_control->rx_data[i]; | 531 | desc = &ring_control->rx_data[i]; |
478 | if (desc->host_addr) | 532 | if (desc->host_addr) |
479 | pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr), | 533 | pci_unmap_single(priv->pdev, |
534 | le32_to_cpu(desc->host_addr), | ||
480 | MAX_RX_SIZE, PCI_DMA_FROMDEVICE); | 535 | MAX_RX_SIZE, PCI_DMA_FROMDEVICE); |
481 | kfree_skb(priv->rx_buf[i]); | 536 | kfree_skb(priv->rx_buf_data[i]); |
482 | priv->rx_buf[i] = NULL; | 537 | priv->rx_buf_data[i] = NULL; |
483 | } | 538 | } |
484 | 539 | ||
485 | for (i = 0; i < ARRAY_SIZE(priv->tx_buf); i++) { | 540 | for (i = 0; i < ARRAY_SIZE(priv->rx_buf_mgmt); i++) { |
541 | desc = &ring_control->rx_mgmt[i]; | ||
542 | if (desc->host_addr) | ||
543 | pci_unmap_single(priv->pdev, | ||
544 | le32_to_cpu(desc->host_addr), | ||
545 | MAX_RX_SIZE, PCI_DMA_FROMDEVICE); | ||
546 | kfree_skb(priv->rx_buf_mgmt[i]); | ||
547 | priv->rx_buf_mgmt[i] = NULL; | ||
548 | } | ||
549 | |||
550 | for (i = 0; i < ARRAY_SIZE(priv->tx_buf_data); i++) { | ||
486 | desc = &ring_control->tx_data[i]; | 551 | desc = &ring_control->tx_data[i]; |
487 | if (desc->host_addr) | 552 | if (desc->host_addr) |
488 | pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr), | 553 | pci_unmap_single(priv->pdev, |
489 | le16_to_cpu(desc->len), PCI_DMA_TODEVICE); | 554 | le32_to_cpu(desc->host_addr), |
555 | le16_to_cpu(desc->len), | ||
556 | PCI_DMA_TODEVICE); | ||
557 | |||
558 | kfree(priv->tx_buf_data[i]); | ||
559 | priv->tx_buf_data[i] = NULL; | ||
560 | } | ||
561 | |||
562 | for (i = 0; i < ARRAY_SIZE(priv->tx_buf_mgmt); i++) { | ||
563 | desc = &ring_control->tx_mgmt[i]; | ||
564 | if (desc->host_addr) | ||
565 | pci_unmap_single(priv->pdev, | ||
566 | le32_to_cpu(desc->host_addr), | ||
567 | le16_to_cpu(desc->len), | ||
568 | PCI_DMA_TODEVICE); | ||
490 | 569 | ||
491 | kfree(priv->tx_buf[i]); | 570 | kfree(priv->tx_buf_mgmt[i]); |
492 | priv->tx_buf[i] = NULL; | 571 | priv->tx_buf_mgmt[i] = NULL; |
493 | } | 572 | } |
494 | 573 | ||
495 | memset(ring_control, 0, sizeof(ring_control)); | 574 | memset(ring_control, 0, sizeof(*ring_control)); |
496 | } | 575 | } |
497 | 576 | ||
498 | static int __devinit p54p_probe(struct pci_dev *pdev, | 577 | static int __devinit p54p_probe(struct pci_dev *pdev, |
@@ -585,6 +664,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev, | |||
585 | priv->common.tx = p54p_tx; | 664 | priv->common.tx = p54p_tx; |
586 | 665 | ||
587 | spin_lock_init(&priv->lock); | 666 | spin_lock_init(&priv->lock); |
667 | tasklet_init(&priv->rx_tasklet, p54p_rx_tasklet, (unsigned long)dev); | ||
588 | 668 | ||
589 | err = ieee80211_register_hw(dev); | 669 | err = ieee80211_register_hw(dev); |
590 | if (err) { | 670 | if (err) { |
diff --git a/drivers/net/wireless/p54/p54pci.h b/drivers/net/wireless/p54/p54pci.h index 07678ef5ddc8..4a6778070afc 100644 --- a/drivers/net/wireless/p54/p54pci.h +++ b/drivers/net/wireless/p54/p54pci.h | |||
@@ -92,13 +92,17 @@ struct p54p_priv { | |||
92 | struct p54_common common; | 92 | struct p54_common common; |
93 | struct pci_dev *pdev; | 93 | struct pci_dev *pdev; |
94 | struct p54p_csr __iomem *map; | 94 | struct p54p_csr __iomem *map; |
95 | struct tasklet_struct rx_tasklet; | ||
95 | 96 | ||
96 | spinlock_t lock; | 97 | spinlock_t lock; |
97 | struct p54p_ring_control *ring_control; | 98 | struct p54p_ring_control *ring_control; |
98 | dma_addr_t ring_control_dma; | 99 | dma_addr_t ring_control_dma; |
99 | u32 rx_idx, tx_idx; | 100 | u32 rx_idx_data, tx_idx_data; |
100 | struct sk_buff *rx_buf[8]; | 101 | u32 rx_idx_mgmt, tx_idx_mgmt; |
101 | void *tx_buf[32]; | 102 | struct sk_buff *rx_buf_data[8]; |
103 | struct sk_buff *rx_buf_mgmt[4]; | ||
104 | void *tx_buf_data[32]; | ||
105 | void *tx_buf_mgmt[4]; | ||
102 | struct completion boot_comp; | 106 | struct completion boot_comp; |
103 | }; | 107 | }; |
104 | 108 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 0107cec18b26..18b703c3fc2c 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -1241,7 +1241,7 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) | |||
1241 | if (!reg) | 1241 | if (!reg) |
1242 | return IRQ_NONE; | 1242 | return IRQ_NONE; |
1243 | 1243 | ||
1244 | if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) | 1244 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
1245 | return IRQ_HANDLED; | 1245 | return IRQ_HANDLED; |
1246 | 1246 | ||
1247 | /* | 1247 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index e0ff76ff490d..2a96a011f2ad 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -1316,6 +1316,8 @@ static void rt2500pci_fill_rxdone(struct queue_entry *entry, | |||
1316 | 1316 | ||
1317 | if (rt2x00_get_field32(word0, RXD_W0_OFDM)) | 1317 | if (rt2x00_get_field32(word0, RXD_W0_OFDM)) |
1318 | rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP; | 1318 | rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP; |
1319 | else | ||
1320 | rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE; | ||
1319 | if (rt2x00_get_field32(word0, RXD_W0_MY_BSS)) | 1321 | if (rt2x00_get_field32(word0, RXD_W0_MY_BSS)) |
1320 | rxdesc->dev_flags |= RXDONE_MY_BSS; | 1322 | rxdesc->dev_flags |= RXDONE_MY_BSS; |
1321 | } | 1323 | } |
@@ -1377,7 +1379,7 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) | |||
1377 | if (!reg) | 1379 | if (!reg) |
1378 | return IRQ_NONE; | 1380 | return IRQ_NONE; |
1379 | 1381 | ||
1380 | if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) | 1382 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
1381 | return IRQ_HANDLED; | 1383 | return IRQ_HANDLED; |
1382 | 1384 | ||
1383 | /* | 1385 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 3b90ed622148..0e008b606f70 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -1114,8 +1114,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1114 | rt2x00_set_field32(&word, TXD_W0_NEW_SEQ, | 1114 | rt2x00_set_field32(&word, TXD_W0_NEW_SEQ, |
1115 | test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)); | 1115 | test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)); |
1116 | rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); | 1116 | rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); |
1117 | rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, | 1117 | rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); |
1118 | skb->len - skbdesc->desc_len); | ||
1119 | rt2x00_set_field32(&word, TXD_W0_CIPHER, CIPHER_NONE); | 1118 | rt2x00_set_field32(&word, TXD_W0_CIPHER, CIPHER_NONE); |
1120 | rt2x00_desc_write(txd, 0, word); | 1119 | rt2x00_desc_write(txd, 0, word); |
1121 | } | 1120 | } |
@@ -1280,6 +1279,8 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry, | |||
1280 | 1279 | ||
1281 | if (rt2x00_get_field32(word0, RXD_W0_OFDM)) | 1280 | if (rt2x00_get_field32(word0, RXD_W0_OFDM)) |
1282 | rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP; | 1281 | rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP; |
1282 | else | ||
1283 | rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE; | ||
1283 | if (rt2x00_get_field32(word0, RXD_W0_MY_BSS)) | 1284 | if (rt2x00_get_field32(word0, RXD_W0_MY_BSS)) |
1284 | rxdesc->dev_flags |= RXDONE_MY_BSS; | 1285 | rxdesc->dev_flags |= RXDONE_MY_BSS; |
1285 | 1286 | ||
@@ -1297,7 +1298,7 @@ static void rt2500usb_beacondone(struct urb *urb) | |||
1297 | struct queue_entry *entry = (struct queue_entry *)urb->context; | 1298 | struct queue_entry *entry = (struct queue_entry *)urb->context; |
1298 | struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; | 1299 | struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; |
1299 | 1300 | ||
1300 | if (!test_bit(DEVICE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags)) | 1301 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags)) |
1301 | return; | 1302 | return; |
1302 | 1303 | ||
1303 | /* | 1304 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 3fa3d5b006a6..6f296cef76ad 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -44,7 +44,7 @@ | |||
44 | /* | 44 | /* |
45 | * Module information. | 45 | * Module information. |
46 | */ | 46 | */ |
47 | #define DRV_VERSION "2.2.0" | 47 | #define DRV_VERSION "2.2.1" |
48 | #define DRV_PROJECT "http://rt2x00.serialmonkey.com" | 48 | #define DRV_PROJECT "http://rt2x00.serialmonkey.com" |
49 | 49 | ||
50 | /* | 50 | /* |
@@ -629,14 +629,13 @@ enum rt2x00_flags { | |||
629 | /* | 629 | /* |
630 | * Device state flags | 630 | * Device state flags |
631 | */ | 631 | */ |
632 | DEVICE_PRESENT, | 632 | DEVICE_STATE_PRESENT, |
633 | DEVICE_REGISTERED_HW, | 633 | DEVICE_STATE_REGISTERED_HW, |
634 | DEVICE_INITIALIZED, | 634 | DEVICE_STATE_INITIALIZED, |
635 | DEVICE_STARTED, | 635 | DEVICE_STATE_STARTED, |
636 | DEVICE_STARTED_SUSPEND, | 636 | DEVICE_STATE_STARTED_SUSPEND, |
637 | DEVICE_ENABLED_RADIO, | 637 | DEVICE_STATE_ENABLED_RADIO, |
638 | DEVICE_DISABLED_RADIO_HW, | 638 | DEVICE_STATE_DISABLED_RADIO_HW, |
639 | DEVICE_DIRTY_CONFIG, | ||
640 | 639 | ||
641 | /* | 640 | /* |
642 | * Driver requirements | 641 | * Driver requirements |
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index ea37c7962043..ca051f50ef10 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c | |||
@@ -121,7 +121,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, | |||
121 | * Antenna setup changes require the RX to be disabled, | 121 | * Antenna setup changes require the RX to be disabled, |
122 | * else the changes will be ignored by the device. | 122 | * else the changes will be ignored by the device. |
123 | */ | 123 | */ |
124 | if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) | 124 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
125 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF_LINK); | 125 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF_LINK); |
126 | 126 | ||
127 | /* | 127 | /* |
@@ -136,7 +136,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, | |||
136 | rt2x00dev->link.ant.active.rx = libconf.ant.rx; | 136 | rt2x00dev->link.ant.active.rx = libconf.ant.rx; |
137 | rt2x00dev->link.ant.active.tx = libconf.ant.tx; | 137 | rt2x00dev->link.ant.active.tx = libconf.ant.tx; |
138 | 138 | ||
139 | if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) | 139 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
140 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK); | 140 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK); |
141 | } | 141 | } |
142 | 142 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 328ff8bc4c16..369b0b2d8643 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -34,7 +34,7 @@ | |||
34 | */ | 34 | */ |
35 | void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev) | 35 | void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev) |
36 | { | 36 | { |
37 | if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) | 37 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
38 | return; | 38 | return; |
39 | 39 | ||
40 | /* | 40 | /* |
@@ -94,8 +94,8 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
94 | * Don't enable the radio twice. | 94 | * Don't enable the radio twice. |
95 | * And check if the hardware button has been disabled. | 95 | * And check if the hardware button has been disabled. |
96 | */ | 96 | */ |
97 | if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || | 97 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || |
98 | test_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags)) | 98 | test_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags)) |
99 | return 0; | 99 | return 0; |
100 | 100 | ||
101 | /* | 101 | /* |
@@ -117,7 +117,7 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
117 | rt2x00leds_led_radio(rt2x00dev, true); | 117 | rt2x00leds_led_radio(rt2x00dev, true); |
118 | rt2x00led_led_activity(rt2x00dev, true); | 118 | rt2x00led_led_activity(rt2x00dev, true); |
119 | 119 | ||
120 | __set_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags); | 120 | set_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags); |
121 | 121 | ||
122 | /* | 122 | /* |
123 | * Enable RX. | 123 | * Enable RX. |
@@ -134,7 +134,7 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
134 | 134 | ||
135 | void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) | 135 | void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) |
136 | { | 136 | { |
137 | if (!__test_and_clear_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) | 137 | if (!test_and_clear_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
138 | return; | 138 | return; |
139 | 139 | ||
140 | /* | 140 | /* |
@@ -354,7 +354,7 @@ static void rt2x00lib_link_tuner(struct work_struct *work) | |||
354 | * When the radio is shutting down we should | 354 | * When the radio is shutting down we should |
355 | * immediately cease all link tuning. | 355 | * immediately cease all link tuning. |
356 | */ | 356 | */ |
357 | if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) | 357 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
358 | return; | 358 | return; |
359 | 359 | ||
360 | /* | 360 | /* |
@@ -431,7 +431,7 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, | |||
431 | * note that in the spinlock protected area above the delayed_flags | 431 | * note that in the spinlock protected area above the delayed_flags |
432 | * have been cleared correctly. | 432 | * have been cleared correctly. |
433 | */ | 433 | */ |
434 | if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) | 434 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
435 | return; | 435 | return; |
436 | 436 | ||
437 | if (delayed_flags & DELAYED_UPDATE_BEACON) | 437 | if (delayed_flags & DELAYED_UPDATE_BEACON) |
@@ -484,7 +484,7 @@ static void rt2x00lib_beacondone_iter(void *data, u8 *mac, | |||
484 | 484 | ||
485 | void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) | 485 | void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) |
486 | { | 486 | { |
487 | if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) | 487 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
488 | return; | 488 | return; |
489 | 489 | ||
490 | ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw, | 490 | ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw, |
@@ -572,7 +572,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
572 | 572 | ||
573 | rt2x00dev->ops->lib->init_txentry(rt2x00dev, entry); | 573 | rt2x00dev->ops->lib->init_txentry(rt2x00dev, entry); |
574 | 574 | ||
575 | __clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | 575 | clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); |
576 | rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); | 576 | rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); |
577 | 577 | ||
578 | /* | 578 | /* |
@@ -653,7 +653,7 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, | |||
653 | 653 | ||
654 | if (((rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) && | 654 | if (((rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) && |
655 | (rate->plcp == rxdesc.signal)) || | 655 | (rate->plcp == rxdesc.signal)) || |
656 | (!(rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) && | 656 | ((rxdesc.dev_flags & RXDONE_SIGNAL_BITRATE) && |
657 | (rate->bitrate == rxdesc.signal))) { | 657 | (rate->bitrate == rxdesc.signal))) { |
658 | idx = i; | 658 | idx = i; |
659 | break; | 659 | break; |
@@ -888,7 +888,7 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, | |||
888 | 888 | ||
889 | static void rt2x00lib_remove_hw(struct rt2x00_dev *rt2x00dev) | 889 | static void rt2x00lib_remove_hw(struct rt2x00_dev *rt2x00dev) |
890 | { | 890 | { |
891 | if (test_bit(DEVICE_REGISTERED_HW, &rt2x00dev->flags)) | 891 | if (test_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags)) |
892 | ieee80211_unregister_hw(rt2x00dev->hw); | 892 | ieee80211_unregister_hw(rt2x00dev->hw); |
893 | 893 | ||
894 | if (likely(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ])) { | 894 | if (likely(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ])) { |
@@ -906,6 +906,9 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
906 | struct hw_mode_spec *spec = &rt2x00dev->spec; | 906 | struct hw_mode_spec *spec = &rt2x00dev->spec; |
907 | int status; | 907 | int status; |
908 | 908 | ||
909 | if (test_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags)) | ||
910 | return 0; | ||
911 | |||
909 | /* | 912 | /* |
910 | * Initialize HW modes. | 913 | * Initialize HW modes. |
911 | */ | 914 | */ |
@@ -927,7 +930,7 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
927 | return status; | 930 | return status; |
928 | } | 931 | } |
929 | 932 | ||
930 | __set_bit(DEVICE_REGISTERED_HW, &rt2x00dev->flags); | 933 | set_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags); |
931 | 934 | ||
932 | return 0; | 935 | return 0; |
933 | } | 936 | } |
@@ -937,7 +940,7 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
937 | */ | 940 | */ |
938 | static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev) | 941 | static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev) |
939 | { | 942 | { |
940 | if (!__test_and_clear_bit(DEVICE_INITIALIZED, &rt2x00dev->flags)) | 943 | if (!test_and_clear_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags)) |
941 | return; | 944 | return; |
942 | 945 | ||
943 | /* | 946 | /* |
@@ -960,7 +963,7 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev) | |||
960 | { | 963 | { |
961 | int status; | 964 | int status; |
962 | 965 | ||
963 | if (test_bit(DEVICE_INITIALIZED, &rt2x00dev->flags)) | 966 | if (test_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags)) |
964 | return 0; | 967 | return 0; |
965 | 968 | ||
966 | /* | 969 | /* |
@@ -979,7 +982,7 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev) | |||
979 | return status; | 982 | return status; |
980 | } | 983 | } |
981 | 984 | ||
982 | __set_bit(DEVICE_INITIALIZED, &rt2x00dev->flags); | 985 | set_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags); |
983 | 986 | ||
984 | /* | 987 | /* |
985 | * Register the extra components. | 988 | * Register the extra components. |
@@ -993,7 +996,7 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev) | |||
993 | { | 996 | { |
994 | int retval; | 997 | int retval; |
995 | 998 | ||
996 | if (test_bit(DEVICE_STARTED, &rt2x00dev->flags)) | 999 | if (test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) |
997 | return 0; | 1000 | return 0; |
998 | 1001 | ||
999 | /* | 1002 | /* |
@@ -1011,28 +1014,18 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev) | |||
1011 | if (retval) | 1014 | if (retval) |
1012 | return retval; | 1015 | return retval; |
1013 | 1016 | ||
1014 | /* | ||
1015 | * Enable radio. | ||
1016 | */ | ||
1017 | retval = rt2x00lib_enable_radio(rt2x00dev); | ||
1018 | if (retval) { | ||
1019 | rt2x00lib_uninitialize(rt2x00dev); | ||
1020 | return retval; | ||
1021 | } | ||
1022 | |||
1023 | rt2x00dev->intf_ap_count = 0; | 1017 | rt2x00dev->intf_ap_count = 0; |
1024 | rt2x00dev->intf_sta_count = 0; | 1018 | rt2x00dev->intf_sta_count = 0; |
1025 | rt2x00dev->intf_associated = 0; | 1019 | rt2x00dev->intf_associated = 0; |
1026 | 1020 | ||
1027 | __set_bit(DEVICE_STARTED, &rt2x00dev->flags); | 1021 | set_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags); |
1028 | __set_bit(DEVICE_DIRTY_CONFIG, &rt2x00dev->flags); | ||
1029 | 1022 | ||
1030 | return 0; | 1023 | return 0; |
1031 | } | 1024 | } |
1032 | 1025 | ||
1033 | void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev) | 1026 | void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev) |
1034 | { | 1027 | { |
1035 | if (!test_bit(DEVICE_STARTED, &rt2x00dev->flags)) | 1028 | if (!test_and_clear_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) |
1036 | return; | 1029 | return; |
1037 | 1030 | ||
1038 | /* | 1031 | /* |
@@ -1044,8 +1037,6 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev) | |||
1044 | rt2x00dev->intf_ap_count = 0; | 1037 | rt2x00dev->intf_ap_count = 0; |
1045 | rt2x00dev->intf_sta_count = 0; | 1038 | rt2x00dev->intf_sta_count = 0; |
1046 | rt2x00dev->intf_associated = 0; | 1039 | rt2x00dev->intf_associated = 0; |
1047 | |||
1048 | __clear_bit(DEVICE_STARTED, &rt2x00dev->flags); | ||
1049 | } | 1040 | } |
1050 | 1041 | ||
1051 | /* | 1042 | /* |
@@ -1100,7 +1091,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) | |||
1100 | rt2x00rfkill_allocate(rt2x00dev); | 1091 | rt2x00rfkill_allocate(rt2x00dev); |
1101 | rt2x00debug_register(rt2x00dev); | 1092 | rt2x00debug_register(rt2x00dev); |
1102 | 1093 | ||
1103 | __set_bit(DEVICE_PRESENT, &rt2x00dev->flags); | 1094 | set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); |
1104 | 1095 | ||
1105 | return 0; | 1096 | return 0; |
1106 | 1097 | ||
@@ -1113,7 +1104,7 @@ EXPORT_SYMBOL_GPL(rt2x00lib_probe_dev); | |||
1113 | 1104 | ||
1114 | void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) | 1105 | void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) |
1115 | { | 1106 | { |
1116 | __clear_bit(DEVICE_PRESENT, &rt2x00dev->flags); | 1107 | clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); |
1117 | 1108 | ||
1118 | /* | 1109 | /* |
1119 | * Disable radio. | 1110 | * Disable radio. |
@@ -1158,14 +1149,15 @@ int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state) | |||
1158 | int retval; | 1149 | int retval; |
1159 | 1150 | ||
1160 | NOTICE(rt2x00dev, "Going to sleep.\n"); | 1151 | NOTICE(rt2x00dev, "Going to sleep.\n"); |
1161 | __clear_bit(DEVICE_PRESENT, &rt2x00dev->flags); | ||
1162 | 1152 | ||
1163 | /* | 1153 | /* |
1164 | * Only continue if mac80211 has open interfaces. | 1154 | * Only continue if mac80211 has open interfaces. |
1165 | */ | 1155 | */ |
1166 | if (!test_bit(DEVICE_STARTED, &rt2x00dev->flags)) | 1156 | if (!test_and_clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || |
1157 | !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) | ||
1167 | goto exit; | 1158 | goto exit; |
1168 | __set_bit(DEVICE_STARTED_SUSPEND, &rt2x00dev->flags); | 1159 | |
1160 | set_bit(DEVICE_STATE_STARTED_SUSPEND, &rt2x00dev->flags); | ||
1169 | 1161 | ||
1170 | /* | 1162 | /* |
1171 | * Disable radio. | 1163 | * Disable radio. |
@@ -1237,7 +1229,7 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) | |||
1237 | /* | 1229 | /* |
1238 | * Only continue if mac80211 had open interfaces. | 1230 | * Only continue if mac80211 had open interfaces. |
1239 | */ | 1231 | */ |
1240 | if (!__test_and_clear_bit(DEVICE_STARTED_SUSPEND, &rt2x00dev->flags)) | 1232 | if (!test_and_clear_bit(DEVICE_STATE_STARTED_SUSPEND, &rt2x00dev->flags)) |
1241 | return 0; | 1233 | return 0; |
1242 | 1234 | ||
1243 | /* | 1235 | /* |
@@ -1264,7 +1256,7 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) | |||
1264 | /* | 1256 | /* |
1265 | * We are ready again to receive requests from mac80211. | 1257 | * We are ready again to receive requests from mac80211. |
1266 | */ | 1258 | */ |
1267 | __set_bit(DEVICE_PRESENT, &rt2x00dev->flags); | 1259 | set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); |
1268 | 1260 | ||
1269 | /* | 1261 | /* |
1270 | * It is possible that during that mac80211 has attempted | 1262 | * It is possible that during that mac80211 has attempted |
@@ -1284,7 +1276,7 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) | |||
1284 | return 0; | 1276 | return 0; |
1285 | 1277 | ||
1286 | exit: | 1278 | exit: |
1287 | rt2x00lib_disable_radio(rt2x00dev); | 1279 | rt2x00lib_stop(rt2x00dev); |
1288 | rt2x00lib_uninitialize(rt2x00dev); | 1280 | rt2x00lib_uninitialize(rt2x00dev); |
1289 | rt2x00debug_deregister(rt2x00dev); | 1281 | rt2x00debug_deregister(rt2x00dev); |
1290 | 1282 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 3af427339417..56829fad3471 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -117,7 +117,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
117 | * Note that we can only stop the TX queues inside the TX path | 117 | * Note that we can only stop the TX queues inside the TX path |
118 | * due to possible race conditions in mac80211. | 118 | * due to possible race conditions in mac80211. |
119 | */ | 119 | */ |
120 | if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) | 120 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) |
121 | goto exit_fail; | 121 | goto exit_fail; |
122 | 122 | ||
123 | /* | 123 | /* |
@@ -175,7 +175,7 @@ int rt2x00mac_start(struct ieee80211_hw *hw) | |||
175 | { | 175 | { |
176 | struct rt2x00_dev *rt2x00dev = hw->priv; | 176 | struct rt2x00_dev *rt2x00dev = hw->priv; |
177 | 177 | ||
178 | if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) | 178 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) |
179 | return 0; | 179 | return 0; |
180 | 180 | ||
181 | return rt2x00lib_start(rt2x00dev); | 181 | return rt2x00lib_start(rt2x00dev); |
@@ -186,7 +186,7 @@ void rt2x00mac_stop(struct ieee80211_hw *hw) | |||
186 | { | 186 | { |
187 | struct rt2x00_dev *rt2x00dev = hw->priv; | 187 | struct rt2x00_dev *rt2x00dev = hw->priv; |
188 | 188 | ||
189 | if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) | 189 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) |
190 | return; | 190 | return; |
191 | 191 | ||
192 | rt2x00lib_stop(rt2x00dev); | 192 | rt2x00lib_stop(rt2x00dev); |
@@ -206,8 +206,8 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, | |||
206 | * Don't allow interfaces to be added | 206 | * Don't allow interfaces to be added |
207 | * the device has disappeared. | 207 | * the device has disappeared. |
208 | */ | 208 | */ |
209 | if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) || | 209 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || |
210 | !test_bit(DEVICE_STARTED, &rt2x00dev->flags)) | 210 | !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) |
211 | return -ENODEV; | 211 | return -ENODEV; |
212 | 212 | ||
213 | switch (conf->type) { | 213 | switch (conf->type) { |
@@ -256,7 +256,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, | |||
256 | */ | 256 | */ |
257 | for (i = 0; i < queue->limit; i++) { | 257 | for (i = 0; i < queue->limit; i++) { |
258 | entry = &queue->entries[i]; | 258 | entry = &queue->entries[i]; |
259 | if (!__test_and_set_bit(ENTRY_BCN_ASSIGNED, &entry->flags)) | 259 | if (!test_and_set_bit(ENTRY_BCN_ASSIGNED, &entry->flags)) |
260 | break; | 260 | break; |
261 | } | 261 | } |
262 | 262 | ||
@@ -310,7 +310,7 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw, | |||
310 | * either the device has disappeared or when | 310 | * either the device has disappeared or when |
311 | * no interface is present. | 311 | * no interface is present. |
312 | */ | 312 | */ |
313 | if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) || | 313 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || |
314 | (conf->type == IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_ap_count) || | 314 | (conf->type == IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_ap_count) || |
315 | (conf->type != IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_sta_count)) | 315 | (conf->type != IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_sta_count)) |
316 | return; | 316 | return; |
@@ -324,7 +324,7 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw, | |||
324 | * Release beacon entry so it is available for | 324 | * Release beacon entry so it is available for |
325 | * new interfaces again. | 325 | * new interfaces again. |
326 | */ | 326 | */ |
327 | __clear_bit(ENTRY_BCN_ASSIGNED, &intf->beacon->flags); | 327 | clear_bit(ENTRY_BCN_ASSIGNED, &intf->beacon->flags); |
328 | 328 | ||
329 | /* | 329 | /* |
330 | * Make sure the bssid and mac address registers | 330 | * Make sure the bssid and mac address registers |
@@ -338,45 +338,45 @@ EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface); | |||
338 | int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) | 338 | int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) |
339 | { | 339 | { |
340 | struct rt2x00_dev *rt2x00dev = hw->priv; | 340 | struct rt2x00_dev *rt2x00dev = hw->priv; |
341 | int force_reconfig; | 341 | int radio_on; |
342 | int status; | ||
342 | 343 | ||
343 | /* | 344 | /* |
344 | * Mac80211 might be calling this function while we are trying | 345 | * Mac80211 might be calling this function while we are trying |
345 | * to remove the device or perhaps suspending it. | 346 | * to remove the device or perhaps suspending it. |
346 | */ | 347 | */ |
347 | if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) | 348 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) |
348 | return 0; | 349 | return 0; |
349 | 350 | ||
350 | /* | 351 | /* |
351 | * Check if we need to disable the radio, | 352 | * Only change device state when the radio is enabled. It does not |
352 | * if this is not the case, at least the RX must be disabled. | 353 | * matter what parameters we have configured when the radio is disabled |
354 | * because we won't be able to send or receive anyway. Also note that | ||
355 | * some configuration parameters (e.g. channel and antenna values) can | ||
356 | * only be set when the radio is enabled. | ||
353 | */ | 357 | */ |
354 | if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) { | 358 | radio_on = test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags); |
355 | if (!conf->radio_enabled) | 359 | if (conf->radio_enabled) { |
356 | rt2x00lib_disable_radio(rt2x00dev); | 360 | /* For programming the values, we have to turn RX off */ |
357 | else | 361 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); |
358 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); | ||
359 | } | ||
360 | 362 | ||
361 | /* | 363 | /* Enable the radio */ |
362 | * When the DEVICE_DIRTY_CONFIG flag is set, the device has recently | 364 | status = rt2x00lib_enable_radio(rt2x00dev); |
363 | * been started and the configuration must be forced upon the hardware. | 365 | if (unlikely(status)) |
364 | * Otherwise registers will not be intialized correctly and could | 366 | return status; |
365 | * result in non-working hardware because essential registers aren't | ||
366 | * initialized. | ||
367 | */ | ||
368 | force_reconfig = | ||
369 | __test_and_clear_bit(DEVICE_DIRTY_CONFIG, &rt2x00dev->flags); | ||
370 | 367 | ||
371 | rt2x00lib_config(rt2x00dev, conf, force_reconfig); | 368 | /* |
369 | * When we've just turned on the radio, we want to reprogram | ||
370 | * everything to ensure a consistent state | ||
371 | */ | ||
372 | rt2x00lib_config(rt2x00dev, conf, !radio_on); | ||
372 | 373 | ||
373 | /* | 374 | /* Turn RX back on */ |
374 | * Reenable RX only if the radio should be on. | ||
375 | */ | ||
376 | if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
377 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); | 375 | rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); |
378 | else if (conf->radio_enabled) | 376 | } else { |
379 | return rt2x00lib_enable_radio(rt2x00dev); | 377 | /* Disable the radio */ |
378 | rt2x00lib_disable_radio(rt2x00dev); | ||
379 | } | ||
380 | 380 | ||
381 | return 0; | 381 | return 0; |
382 | } | 382 | } |
@@ -395,7 +395,7 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, | |||
395 | * Mac80211 might be calling this function while we are trying | 395 | * Mac80211 might be calling this function while we are trying |
396 | * to remove the device or perhaps suspending it. | 396 | * to remove the device or perhaps suspending it. |
397 | */ | 397 | */ |
398 | if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) | 398 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) |
399 | return 0; | 399 | return 0; |
400 | 400 | ||
401 | spin_lock(&intf->lock); | 401 | spin_lock(&intf->lock); |
@@ -666,10 +666,11 @@ int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, | |||
666 | queue->cw_max = 10; /* cw_min: 2^10 = 1024. */ | 666 | queue->cw_max = 10; /* cw_min: 2^10 = 1024. */ |
667 | 667 | ||
668 | queue->aifs = params->aifs; | 668 | queue->aifs = params->aifs; |
669 | queue->txop = params->txop; | ||
669 | 670 | ||
670 | INFO(rt2x00dev, | 671 | INFO(rt2x00dev, |
671 | "Configured TX queue %d - CWmin: %d, CWmax: %d, Aifs: %d.\n", | 672 | "Configured TX queue %d - CWmin: %d, CWmax: %d, Aifs: %d, TXop: %d.\n", |
672 | queue_idx, queue->cw_min, queue->cw_max, queue->aifs); | 673 | queue_idx, queue->cw_min, queue->cw_max, queue->aifs, queue->txop); |
673 | 674 | ||
674 | return 0; | 675 | return 0; |
675 | } | 676 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index c0f97c53e5ce..a5e965068c83 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -100,8 +100,21 @@ void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) | |||
100 | { | 100 | { |
101 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); | 101 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); |
102 | 102 | ||
103 | skbdesc->skb_dma = dma_map_single(rt2x00dev->dev, skb->data, skb->len, | 103 | /* |
104 | DMA_TO_DEVICE); | 104 | * If device has requested headroom, we should make sure that |
105 | * is also mapped to the DMA so it can be used for transfering | ||
106 | * additional descriptor information to the hardware. | ||
107 | */ | ||
108 | skb_push(skb, rt2x00dev->hw->extra_tx_headroom); | ||
109 | |||
110 | skbdesc->skb_dma = | ||
111 | dma_map_single(rt2x00dev->dev, skb->data, skb->len, DMA_TO_DEVICE); | ||
112 | |||
113 | /* | ||
114 | * Restore data pointer to original location again. | ||
115 | */ | ||
116 | skb_pull(skb, rt2x00dev->hw->extra_tx_headroom); | ||
117 | |||
105 | skbdesc->flags |= SKBDESC_DMA_MAPPED_TX; | 118 | skbdesc->flags |= SKBDESC_DMA_MAPPED_TX; |
106 | } | 119 | } |
107 | EXPORT_SYMBOL_GPL(rt2x00queue_map_txskb); | 120 | EXPORT_SYMBOL_GPL(rt2x00queue_map_txskb); |
@@ -117,7 +130,12 @@ void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) | |||
117 | } | 130 | } |
118 | 131 | ||
119 | if (skbdesc->flags & SKBDESC_DMA_MAPPED_TX) { | 132 | if (skbdesc->flags & SKBDESC_DMA_MAPPED_TX) { |
120 | dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, skb->len, | 133 | /* |
134 | * Add headroom to the skb length, it has been removed | ||
135 | * by the driver, but it was actually mapped to DMA. | ||
136 | */ | ||
137 | dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, | ||
138 | skb->len + rt2x00dev->hw->extra_tx_headroom, | ||
121 | DMA_TO_DEVICE); | 139 | DMA_TO_DEVICE); |
122 | skbdesc->flags &= ~SKBDESC_DMA_MAPPED_TX; | 140 | skbdesc->flags &= ~SKBDESC_DMA_MAPPED_TX; |
123 | } | 141 | } |
@@ -356,7 +374,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | |||
356 | if (unlikely(rt2x00queue_full(queue))) | 374 | if (unlikely(rt2x00queue_full(queue))) |
357 | return -EINVAL; | 375 | return -EINVAL; |
358 | 376 | ||
359 | if (__test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) { | 377 | if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) { |
360 | ERROR(queue->rt2x00dev, | 378 | ERROR(queue->rt2x00dev, |
361 | "Arrived at non-free entry in the non-full queue %d.\n" | 379 | "Arrived at non-free entry in the non-full queue %d.\n" |
362 | "Please file bug report to %s.\n", | 380 | "Please file bug report to %s.\n", |
@@ -396,7 +414,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | |||
396 | * the frame to mac80211 because the skb->cb has now been tainted. | 414 | * the frame to mac80211 because the skb->cb has now been tainted. |
397 | */ | 415 | */ |
398 | if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry))) { | 416 | if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry))) { |
399 | __clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | 417 | clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); |
400 | dev_kfree_skb_any(entry->skb); | 418 | dev_kfree_skb_any(entry->skb); |
401 | entry->skb = NULL; | 419 | entry->skb = NULL; |
402 | return 0; | 420 | return 0; |
@@ -405,7 +423,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | |||
405 | if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags)) | 423 | if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags)) |
406 | rt2x00queue_map_txskb(queue->rt2x00dev, skb); | 424 | rt2x00queue_map_txskb(queue->rt2x00dev, skb); |
407 | 425 | ||
408 | __set_bit(ENTRY_DATA_PENDING, &entry->flags); | 426 | set_bit(ENTRY_DATA_PENDING, &entry->flags); |
409 | 427 | ||
410 | rt2x00queue_index_inc(queue, Q_INDEX); | 428 | rt2x00queue_index_inc(queue, Q_INDEX); |
411 | rt2x00queue_write_tx_descriptor(entry, &txdesc); | 429 | rt2x00queue_write_tx_descriptor(entry, &txdesc); |
@@ -718,6 +736,7 @@ static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev, | |||
718 | 736 | ||
719 | queue->rt2x00dev = rt2x00dev; | 737 | queue->rt2x00dev = rt2x00dev; |
720 | queue->qid = qid; | 738 | queue->qid = qid; |
739 | queue->txop = 0; | ||
721 | queue->aifs = 2; | 740 | queue->aifs = 2; |
722 | queue->cw_min = 5; | 741 | queue->cw_min = 5; |
723 | queue->cw_max = 10; | 742 | queue->cw_max = 10; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 37f3f98d58a2..9dbf04f0f04c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h | |||
@@ -140,13 +140,14 @@ static inline struct skb_frame_desc* get_skb_frame_desc(struct sk_buff *skb) | |||
140 | /** | 140 | /** |
141 | * enum rxdone_entry_desc_flags: Flags for &struct rxdone_entry_desc | 141 | * enum rxdone_entry_desc_flags: Flags for &struct rxdone_entry_desc |
142 | * | 142 | * |
143 | * @RXDONE_SIGNAL_PLCP: Does the signal field contain the plcp value, | 143 | * @RXDONE_SIGNAL_PLCP: Signal field contains the plcp value. |
144 | * or does it contain the bitrate itself. | 144 | * @RXDONE_SIGNAL_BITRATE: Signal field contains the bitrate value. |
145 | * @RXDONE_MY_BSS: Does this frame originate from device's BSS. | 145 | * @RXDONE_MY_BSS: Does this frame originate from device's BSS. |
146 | */ | 146 | */ |
147 | enum rxdone_entry_desc_flags { | 147 | enum rxdone_entry_desc_flags { |
148 | RXDONE_SIGNAL_PLCP = 1 << 0, | 148 | RXDONE_SIGNAL_PLCP = 1 << 0, |
149 | RXDONE_MY_BSS = 1 << 1, | 149 | RXDONE_SIGNAL_BITRATE = 1 << 1, |
150 | RXDONE_MY_BSS = 1 << 2, | ||
150 | }; | 151 | }; |
151 | 152 | ||
152 | /** | 153 | /** |
@@ -368,6 +369,7 @@ enum queue_index { | |||
368 | * @length: Number of frames in queue. | 369 | * @length: Number of frames in queue. |
369 | * @index: Index pointers to entry positions in the queue, | 370 | * @index: Index pointers to entry positions in the queue, |
370 | * use &enum queue_index to get a specific index field. | 371 | * use &enum queue_index to get a specific index field. |
372 | * @txop: maximum burst time. | ||
371 | * @aifs: The aifs value for outgoing frames (field ignored in RX queue). | 373 | * @aifs: The aifs value for outgoing frames (field ignored in RX queue). |
372 | * @cw_min: The cw min value for outgoing frames (field ignored in RX queue). | 374 | * @cw_min: The cw min value for outgoing frames (field ignored in RX queue). |
373 | * @cw_max: The cw max value for outgoing frames (field ignored in RX queue). | 375 | * @cw_max: The cw max value for outgoing frames (field ignored in RX queue). |
@@ -387,6 +389,7 @@ struct data_queue { | |||
387 | unsigned short length; | 389 | unsigned short length; |
388 | unsigned short index[Q_INDEX_MAX]; | 390 | unsigned short index[Q_INDEX_MAX]; |
389 | 391 | ||
392 | unsigned short txop; | ||
390 | unsigned short aifs; | 393 | unsigned short aifs; |
391 | unsigned short cw_min; | 394 | unsigned short cw_min; |
392 | unsigned short cw_max; | 395 | unsigned short cw_max; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c index 04b29716d356..8a2fefb365b7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c +++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c | |||
@@ -41,16 +41,16 @@ static int rt2x00rfkill_toggle_radio(void *data, enum rfkill_state state) | |||
41 | /* | 41 | /* |
42 | * Only continue if there are enabled interfaces. | 42 | * Only continue if there are enabled interfaces. |
43 | */ | 43 | */ |
44 | if (!test_bit(DEVICE_STARTED, &rt2x00dev->flags)) | 44 | if (!test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) |
45 | return 0; | 45 | return 0; |
46 | 46 | ||
47 | if (state == RFKILL_STATE_UNBLOCKED) { | 47 | if (state == RFKILL_STATE_UNBLOCKED) { |
48 | INFO(rt2x00dev, "Hardware button pressed, enabling radio.\n"); | 48 | INFO(rt2x00dev, "Hardware button pressed, enabling radio.\n"); |
49 | __clear_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags); | 49 | clear_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags); |
50 | retval = rt2x00lib_enable_radio(rt2x00dev); | 50 | retval = rt2x00lib_enable_radio(rt2x00dev); |
51 | } else if (state == RFKILL_STATE_SOFT_BLOCKED) { | 51 | } else if (state == RFKILL_STATE_SOFT_BLOCKED) { |
52 | INFO(rt2x00dev, "Hardware button pressed, disabling radio.\n"); | 52 | INFO(rt2x00dev, "Hardware button pressed, disabling radio.\n"); |
53 | __set_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags); | 53 | set_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags); |
54 | rt2x00lib_disable_radio(rt2x00dev); | 54 | rt2x00lib_disable_radio(rt2x00dev); |
55 | } else { | 55 | } else { |
56 | WARNING(rt2x00dev, "Received unexpected rfkill state %d.\n", | 56 | WARNING(rt2x00dev, "Received unexpected rfkill state %d.\n", |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 2050227ea530..b73a7e0aeed4 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -163,16 +163,11 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) | |||
163 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 163 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
164 | struct txdone_entry_desc txdesc; | 164 | struct txdone_entry_desc txdesc; |
165 | 165 | ||
166 | if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || | 166 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || |
167 | !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | 167 | !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) |
168 | return; | 168 | return; |
169 | 169 | ||
170 | /* | 170 | /* |
171 | * Remove the descriptor data from the buffer. | ||
172 | */ | ||
173 | skb_pull(entry->skb, entry->queue->desc_size); | ||
174 | |||
175 | /* | ||
176 | * Obtain the status about this packet. | 171 | * Obtain the status about this packet. |
177 | * Note that when the status is 0 it does not mean the | 172 | * Note that when the status is 0 it does not mean the |
178 | * frame was send out correctly. It only means the frame | 173 | * frame was send out correctly. It only means the frame |
@@ -224,6 +219,12 @@ int rt2x00usb_write_tx_data(struct queue_entry *entry) | |||
224 | entry->skb->data, length, | 219 | entry->skb->data, length, |
225 | rt2x00usb_interrupt_txdone, entry); | 220 | rt2x00usb_interrupt_txdone, entry); |
226 | 221 | ||
222 | /* | ||
223 | * Make sure the skb->data pointer points to the frame, not the | ||
224 | * descriptor. | ||
225 | */ | ||
226 | skb_pull(entry->skb, entry->queue->desc_size); | ||
227 | |||
227 | return 0; | 228 | return 0; |
228 | } | 229 | } |
229 | EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data); | 230 | EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data); |
@@ -232,7 +233,7 @@ static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry) | |||
232 | { | 233 | { |
233 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; | 234 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; |
234 | 235 | ||
235 | if (__test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags)) | 236 | if (test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags)) |
236 | usb_submit_urb(entry_priv->urb, GFP_ATOMIC); | 237 | usb_submit_urb(entry_priv->urb, GFP_ATOMIC); |
237 | } | 238 | } |
238 | 239 | ||
@@ -283,7 +284,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) | |||
283 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | 284 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); |
284 | u8 rxd[32]; | 285 | u8 rxd[32]; |
285 | 286 | ||
286 | if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || | 287 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || |
287 | !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | 288 | !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) |
288 | return; | 289 | return; |
289 | 290 | ||
@@ -293,7 +294,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) | |||
293 | * a problem. | 294 | * a problem. |
294 | */ | 295 | */ |
295 | if (urb->actual_length < entry->queue->desc_size || urb->status) { | 296 | if (urb->actual_length < entry->queue->desc_size || urb->status) { |
296 | __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | 297 | set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); |
297 | usb_submit_urb(urb, GFP_ATOMIC); | 298 | usb_submit_urb(urb, GFP_ATOMIC); |
298 | return; | 299 | return; |
299 | } | 300 | } |
@@ -361,7 +362,7 @@ void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev, | |||
361 | entry->skb->data, entry->skb->len, | 362 | entry->skb->data, entry->skb->len, |
362 | rt2x00usb_interrupt_rxdone, entry); | 363 | rt2x00usb_interrupt_rxdone, entry); |
363 | 364 | ||
364 | __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | 365 | set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); |
365 | usb_submit_urb(entry_priv->urb, GFP_ATOMIC); | 366 | usb_submit_urb(entry_priv->urb, GFP_ATOMIC); |
366 | } | 367 | } |
367 | EXPORT_SYMBOL_GPL(rt2x00usb_init_rxentry); | 368 | EXPORT_SYMBOL_GPL(rt2x00usb_init_rxentry); |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 23cf93dfda06..d740f560ccd0 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -1478,16 +1478,6 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1478 | 1478 | ||
1479 | rt2x00pci_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff); | 1479 | rt2x00pci_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff); |
1480 | 1480 | ||
1481 | rt2x00pci_register_read(rt2x00dev, AC_TXOP_CSR0, ®); | ||
1482 | rt2x00_set_field32(®, AC_TXOP_CSR0_AC0_TX_OP, 0); | ||
1483 | rt2x00_set_field32(®, AC_TXOP_CSR0_AC1_TX_OP, 0); | ||
1484 | rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR0, reg); | ||
1485 | |||
1486 | rt2x00pci_register_read(rt2x00dev, AC_TXOP_CSR1, ®); | ||
1487 | rt2x00_set_field32(®, AC_TXOP_CSR1_AC2_TX_OP, 192); | ||
1488 | rt2x00_set_field32(®, AC_TXOP_CSR1_AC3_TX_OP, 48); | ||
1489 | rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR1, reg); | ||
1490 | |||
1491 | /* | 1481 | /* |
1492 | * Clear all beacons | 1482 | * Clear all beacons |
1493 | * For the Beacon base registers we only need to clear | 1483 | * For the Beacon base registers we only need to clear |
@@ -2001,6 +1991,8 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry, | |||
2001 | 1991 | ||
2002 | if (rt2x00_get_field32(word0, RXD_W0_OFDM)) | 1992 | if (rt2x00_get_field32(word0, RXD_W0_OFDM)) |
2003 | rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP; | 1993 | rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP; |
1994 | else | ||
1995 | rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE; | ||
2004 | if (rt2x00_get_field32(word0, RXD_W0_MY_BSS)) | 1996 | if (rt2x00_get_field32(word0, RXD_W0_MY_BSS)) |
2005 | rxdesc->dev_flags |= RXDONE_MY_BSS; | 1997 | rxdesc->dev_flags |= RXDONE_MY_BSS; |
2006 | } | 1998 | } |
@@ -2121,7 +2113,7 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) | |||
2121 | if (!reg && !reg_mcu) | 2113 | if (!reg && !reg_mcu) |
2122 | return IRQ_NONE; | 2114 | return IRQ_NONE; |
2123 | 2115 | ||
2124 | if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) | 2116 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
2125 | return IRQ_HANDLED; | 2117 | return IRQ_HANDLED; |
2126 | 2118 | ||
2127 | /* | 2119 | /* |
@@ -2652,6 +2644,63 @@ static int rt61pci_set_retry_limit(struct ieee80211_hw *hw, | |||
2652 | return 0; | 2644 | return 0; |
2653 | } | 2645 | } |
2654 | 2646 | ||
2647 | static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, | ||
2648 | const struct ieee80211_tx_queue_params *params) | ||
2649 | { | ||
2650 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
2651 | struct data_queue *queue; | ||
2652 | struct rt2x00_field32 field; | ||
2653 | int retval; | ||
2654 | u32 reg; | ||
2655 | |||
2656 | /* | ||
2657 | * First pass the configuration through rt2x00lib, that will | ||
2658 | * update the queue settings and validate the input. After that | ||
2659 | * we are free to update the registers based on the value | ||
2660 | * in the queue parameter. | ||
2661 | */ | ||
2662 | retval = rt2x00mac_conf_tx(hw, queue_idx, params); | ||
2663 | if (retval) | ||
2664 | return retval; | ||
2665 | |||
2666 | queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); | ||
2667 | |||
2668 | /* Update WMM TXOP register */ | ||
2669 | if (queue_idx < 2) { | ||
2670 | field.bit_offset = queue_idx * 16; | ||
2671 | field.bit_mask = 0xffff << field.bit_offset; | ||
2672 | |||
2673 | rt2x00pci_register_read(rt2x00dev, AC_TXOP_CSR0, ®); | ||
2674 | rt2x00_set_field32(®, field, queue->txop); | ||
2675 | rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR0, reg); | ||
2676 | } else if (queue_idx < 4) { | ||
2677 | field.bit_offset = (queue_idx - 2) * 16; | ||
2678 | field.bit_mask = 0xffff << field.bit_offset; | ||
2679 | |||
2680 | rt2x00pci_register_read(rt2x00dev, AC_TXOP_CSR1, ®); | ||
2681 | rt2x00_set_field32(®, field, queue->txop); | ||
2682 | rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR1, reg); | ||
2683 | } | ||
2684 | |||
2685 | /* Update WMM registers */ | ||
2686 | field.bit_offset = queue_idx * 4; | ||
2687 | field.bit_mask = 0xf << field.bit_offset; | ||
2688 | |||
2689 | rt2x00pci_register_read(rt2x00dev, AIFSN_CSR, ®); | ||
2690 | rt2x00_set_field32(®, field, queue->aifs); | ||
2691 | rt2x00pci_register_write(rt2x00dev, AIFSN_CSR, reg); | ||
2692 | |||
2693 | rt2x00pci_register_read(rt2x00dev, CWMIN_CSR, ®); | ||
2694 | rt2x00_set_field32(®, field, queue->cw_min); | ||
2695 | rt2x00pci_register_write(rt2x00dev, CWMIN_CSR, reg); | ||
2696 | |||
2697 | rt2x00pci_register_read(rt2x00dev, CWMAX_CSR, ®); | ||
2698 | rt2x00_set_field32(®, field, queue->cw_max); | ||
2699 | rt2x00pci_register_write(rt2x00dev, CWMAX_CSR, reg); | ||
2700 | |||
2701 | return 0; | ||
2702 | } | ||
2703 | |||
2655 | static u64 rt61pci_get_tsf(struct ieee80211_hw *hw) | 2704 | static u64 rt61pci_get_tsf(struct ieee80211_hw *hw) |
2656 | { | 2705 | { |
2657 | struct rt2x00_dev *rt2x00dev = hw->priv; | 2706 | struct rt2x00_dev *rt2x00dev = hw->priv; |
@@ -2679,7 +2728,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { | |||
2679 | .get_stats = rt2x00mac_get_stats, | 2728 | .get_stats = rt2x00mac_get_stats, |
2680 | .set_retry_limit = rt61pci_set_retry_limit, | 2729 | .set_retry_limit = rt61pci_set_retry_limit, |
2681 | .bss_info_changed = rt2x00mac_bss_info_changed, | 2730 | .bss_info_changed = rt2x00mac_bss_info_changed, |
2682 | .conf_tx = rt2x00mac_conf_tx, | 2731 | .conf_tx = rt61pci_conf_tx, |
2683 | .get_tx_stats = rt2x00mac_get_tx_stats, | 2732 | .get_tx_stats = rt2x00mac_get_tx_stats, |
2684 | .get_tsf = rt61pci_get_tsf, | 2733 | .get_tsf = rt61pci_get_tsf, |
2685 | }; | 2734 | }; |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index f58fd059c9a0..e698ae0efbce 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -1277,16 +1277,6 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1277 | rt73usb_register_write(rt2x00dev, PHY_CSR6, 0x00080606); | 1277 | rt73usb_register_write(rt2x00dev, PHY_CSR6, 0x00080606); |
1278 | rt73usb_register_write(rt2x00dev, PHY_CSR7, 0x00000408); | 1278 | rt73usb_register_write(rt2x00dev, PHY_CSR7, 0x00000408); |
1279 | 1279 | ||
1280 | rt73usb_register_read(rt2x00dev, AC_TXOP_CSR0, ®); | ||
1281 | rt2x00_set_field32(®, AC_TXOP_CSR0_AC0_TX_OP, 0); | ||
1282 | rt2x00_set_field32(®, AC_TXOP_CSR0_AC1_TX_OP, 0); | ||
1283 | rt73usb_register_write(rt2x00dev, AC_TXOP_CSR0, reg); | ||
1284 | |||
1285 | rt73usb_register_read(rt2x00dev, AC_TXOP_CSR1, ®); | ||
1286 | rt2x00_set_field32(®, AC_TXOP_CSR1_AC2_TX_OP, 192); | ||
1287 | rt2x00_set_field32(®, AC_TXOP_CSR1_AC3_TX_OP, 48); | ||
1288 | rt73usb_register_write(rt2x00dev, AC_TXOP_CSR1, reg); | ||
1289 | |||
1290 | rt73usb_register_read(rt2x00dev, MAC_CSR9, ®); | 1280 | rt73usb_register_read(rt2x00dev, MAC_CSR9, ®); |
1291 | rt2x00_set_field32(®, MAC_CSR9_CW_SELECT, 0); | 1281 | rt2x00_set_field32(®, MAC_CSR9_CW_SELECT, 0); |
1292 | rt73usb_register_write(rt2x00dev, MAC_CSR9, reg); | 1282 | rt73usb_register_write(rt2x00dev, MAC_CSR9, reg); |
@@ -1566,8 +1556,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1566 | rt2x00_set_field32(&word, TXD_W0_KEY_TABLE, | 1556 | rt2x00_set_field32(&word, TXD_W0_KEY_TABLE, |
1567 | test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags)); | 1557 | test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags)); |
1568 | rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx); | 1558 | rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx); |
1569 | rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, | 1559 | rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); |
1570 | skb->len - skbdesc->desc_len); | ||
1571 | rt2x00_set_field32(&word, TXD_W0_BURST2, | 1560 | rt2x00_set_field32(&word, TXD_W0_BURST2, |
1572 | test_bit(ENTRY_TXD_BURST, &txdesc->flags)); | 1561 | test_bit(ENTRY_TXD_BURST, &txdesc->flags)); |
1573 | rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher); | 1562 | rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher); |
@@ -1776,6 +1765,8 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry, | |||
1776 | 1765 | ||
1777 | if (rt2x00_get_field32(word0, RXD_W0_OFDM)) | 1766 | if (rt2x00_get_field32(word0, RXD_W0_OFDM)) |
1778 | rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP; | 1767 | rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP; |
1768 | else | ||
1769 | rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE; | ||
1779 | if (rt2x00_get_field32(word0, RXD_W0_MY_BSS)) | 1770 | if (rt2x00_get_field32(word0, RXD_W0_MY_BSS)) |
1780 | rxdesc->dev_flags |= RXDONE_MY_BSS; | 1771 | rxdesc->dev_flags |= RXDONE_MY_BSS; |
1781 | 1772 | ||
@@ -2246,6 +2237,63 @@ static int rt73usb_set_retry_limit(struct ieee80211_hw *hw, | |||
2246 | return 0; | 2237 | return 0; |
2247 | } | 2238 | } |
2248 | 2239 | ||
2240 | static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, | ||
2241 | const struct ieee80211_tx_queue_params *params) | ||
2242 | { | ||
2243 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
2244 | struct data_queue *queue; | ||
2245 | struct rt2x00_field32 field; | ||
2246 | int retval; | ||
2247 | u32 reg; | ||
2248 | |||
2249 | /* | ||
2250 | * First pass the configuration through rt2x00lib, that will | ||
2251 | * update the queue settings and validate the input. After that | ||
2252 | * we are free to update the registers based on the value | ||
2253 | * in the queue parameter. | ||
2254 | */ | ||
2255 | retval = rt2x00mac_conf_tx(hw, queue_idx, params); | ||
2256 | if (retval) | ||
2257 | return retval; | ||
2258 | |||
2259 | queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); | ||
2260 | |||
2261 | /* Update WMM TXOP register */ | ||
2262 | if (queue_idx < 2) { | ||
2263 | field.bit_offset = queue_idx * 16; | ||
2264 | field.bit_mask = 0xffff << field.bit_offset; | ||
2265 | |||
2266 | rt73usb_register_read(rt2x00dev, AC_TXOP_CSR0, ®); | ||
2267 | rt2x00_set_field32(®, field, queue->txop); | ||
2268 | rt73usb_register_write(rt2x00dev, AC_TXOP_CSR0, reg); | ||
2269 | } else if (queue_idx < 4) { | ||
2270 | field.bit_offset = (queue_idx - 2) * 16; | ||
2271 | field.bit_mask = 0xffff << field.bit_offset; | ||
2272 | |||
2273 | rt73usb_register_read(rt2x00dev, AC_TXOP_CSR1, ®); | ||
2274 | rt2x00_set_field32(®, field, queue->txop); | ||
2275 | rt73usb_register_write(rt2x00dev, AC_TXOP_CSR1, reg); | ||
2276 | } | ||
2277 | |||
2278 | /* Update WMM registers */ | ||
2279 | field.bit_offset = queue_idx * 4; | ||
2280 | field.bit_mask = 0xf << field.bit_offset; | ||
2281 | |||
2282 | rt73usb_register_read(rt2x00dev, AIFSN_CSR, ®); | ||
2283 | rt2x00_set_field32(®, field, queue->aifs); | ||
2284 | rt73usb_register_write(rt2x00dev, AIFSN_CSR, reg); | ||
2285 | |||
2286 | rt73usb_register_read(rt2x00dev, CWMIN_CSR, ®); | ||
2287 | rt2x00_set_field32(®, field, queue->cw_min); | ||
2288 | rt73usb_register_write(rt2x00dev, CWMIN_CSR, reg); | ||
2289 | |||
2290 | rt73usb_register_read(rt2x00dev, CWMAX_CSR, ®); | ||
2291 | rt2x00_set_field32(®, field, queue->cw_max); | ||
2292 | rt73usb_register_write(rt2x00dev, CWMAX_CSR, reg); | ||
2293 | |||
2294 | return 0; | ||
2295 | } | ||
2296 | |||
2249 | #if 0 | 2297 | #if 0 |
2250 | /* | 2298 | /* |
2251 | * Mac80211 demands get_tsf must be atomic. | 2299 | * Mac80211 demands get_tsf must be atomic. |
@@ -2283,7 +2331,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { | |||
2283 | .get_stats = rt2x00mac_get_stats, | 2331 | .get_stats = rt2x00mac_get_stats, |
2284 | .set_retry_limit = rt73usb_set_retry_limit, | 2332 | .set_retry_limit = rt73usb_set_retry_limit, |
2285 | .bss_info_changed = rt2x00mac_bss_info_changed, | 2333 | .bss_info_changed = rt2x00mac_bss_info_changed, |
2286 | .conf_tx = rt2x00mac_conf_tx, | 2334 | .conf_tx = rt73usb_conf_tx, |
2287 | .get_tx_stats = rt2x00mac_get_tx_stats, | 2335 | .get_tx_stats = rt2x00mac_get_tx_stats, |
2288 | .get_tsf = rt73usb_get_tsf, | 2336 | .get_tsf = rt73usb_get_tsf, |
2289 | }; | 2337 | }; |
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c index f883dcfffe06..d5cde051806b 100644 --- a/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c | |||
@@ -327,11 +327,9 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) | |||
327 | s8 gain; | 327 | s8 gain; |
328 | u16 loc[3]; | 328 | u16 loc[3]; |
329 | 329 | ||
330 | if (out->revision == 3) { /* rev 3 moved MAC */ | 330 | if (out->revision == 3) /* rev 3 moved MAC */ |
331 | loc[0] = SSB_SPROM3_IL0MAC; | 331 | loc[0] = SSB_SPROM3_IL0MAC; |
332 | loc[1] = SSB_SPROM3_ET0MAC; | 332 | else { |
333 | loc[2] = SSB_SPROM3_ET1MAC; | ||
334 | } else { | ||
335 | loc[0] = SSB_SPROM1_IL0MAC; | 333 | loc[0] = SSB_SPROM1_IL0MAC; |
336 | loc[1] = SSB_SPROM1_ET0MAC; | 334 | loc[1] = SSB_SPROM1_ET0MAC; |
337 | loc[2] = SSB_SPROM1_ET1MAC; | 335 | loc[2] = SSB_SPROM1_ET1MAC; |
@@ -340,13 +338,15 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) | |||
340 | v = in[SPOFF(loc[0]) + i]; | 338 | v = in[SPOFF(loc[0]) + i]; |
341 | *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); | 339 | *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); |
342 | } | 340 | } |
343 | for (i = 0; i < 3; i++) { | 341 | if (out->revision < 3) { /* only rev 1-2 have et0, et1 */ |
344 | v = in[SPOFF(loc[1]) + i]; | 342 | for (i = 0; i < 3; i++) { |
345 | *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v); | 343 | v = in[SPOFF(loc[1]) + i]; |
346 | } | 344 | *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v); |
347 | for (i = 0; i < 3; i++) { | 345 | } |
348 | v = in[SPOFF(loc[2]) + i]; | 346 | for (i = 0; i < 3; i++) { |
349 | *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v); | 347 | v = in[SPOFF(loc[2]) + i]; |
348 | *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v); | ||
349 | } | ||
350 | } | 350 | } |
351 | SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0); | 351 | SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0); |
352 | SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A, | 352 | SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A, |
@@ -399,30 +399,33 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) | |||
399 | out->antenna_gain.ghz5.a3 = gain; | 399 | out->antenna_gain.ghz5.a3 = gain; |
400 | } | 400 | } |
401 | 401 | ||
402 | static void sprom_extract_r4(struct ssb_sprom *out, const u16 *in) | 402 | static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) |
403 | { | 403 | { |
404 | int i; | 404 | int i; |
405 | u16 v; | 405 | u16 v; |
406 | u16 il0mac_offset; | ||
406 | 407 | ||
407 | /* extract the equivalent of the r1 variables */ | 408 | if (out->revision == 4) |
409 | il0mac_offset = SSB_SPROM4_IL0MAC; | ||
410 | else | ||
411 | il0mac_offset = SSB_SPROM5_IL0MAC; | ||
412 | /* extract the MAC address */ | ||
408 | for (i = 0; i < 3; i++) { | 413 | for (i = 0; i < 3; i++) { |
409 | v = in[SPOFF(SSB_SPROM4_IL0MAC) + i]; | 414 | v = in[SPOFF(il0mac_offset) + i]; |
410 | *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); | 415 | *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); |
411 | } | 416 | } |
412 | for (i = 0; i < 3; i++) { | ||
413 | v = in[SPOFF(SSB_SPROM4_ET0MAC) + i]; | ||
414 | *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v); | ||
415 | } | ||
416 | for (i = 0; i < 3; i++) { | ||
417 | v = in[SPOFF(SSB_SPROM4_ET1MAC) + i]; | ||
418 | *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v); | ||
419 | } | ||
420 | SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0); | 417 | SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0); |
421 | SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A, | 418 | SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A, |
422 | SSB_SPROM4_ETHPHY_ET1A_SHIFT); | 419 | SSB_SPROM4_ETHPHY_ET1A_SHIFT); |
423 | SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0); | 420 | if (out->revision == 4) { |
424 | SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0); | 421 | SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0); |
425 | SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0); | 422 | SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0); |
423 | SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0); | ||
424 | } else { | ||
425 | SPEX(country_code, SSB_SPROM5_CCODE, 0xFFFF, 0); | ||
426 | SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0); | ||
427 | SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0); | ||
428 | } | ||
426 | SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A, | 429 | SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A, |
427 | SSB_SPROM4_ANTAVAIL_A_SHIFT); | 430 | SSB_SPROM4_ANTAVAIL_A_SHIFT); |
428 | SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG, | 431 | SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG, |
@@ -433,12 +436,21 @@ static void sprom_extract_r4(struct ssb_sprom *out, const u16 *in) | |||
433 | SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0); | 436 | SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0); |
434 | SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A, | 437 | SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A, |
435 | SSB_SPROM4_ITSSI_A_SHIFT); | 438 | SSB_SPROM4_ITSSI_A_SHIFT); |
436 | SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0); | 439 | if (out->revision == 4) { |
437 | SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1, | 440 | SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0); |
438 | SSB_SPROM4_GPIOA_P1_SHIFT); | 441 | SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1, |
439 | SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0); | 442 | SSB_SPROM4_GPIOA_P1_SHIFT); |
440 | SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3, | 443 | SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0); |
441 | SSB_SPROM4_GPIOB_P3_SHIFT); | 444 | SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3, |
445 | SSB_SPROM4_GPIOB_P3_SHIFT); | ||
446 | } else { | ||
447 | SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0); | ||
448 | SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1, | ||
449 | SSB_SPROM5_GPIOA_P1_SHIFT); | ||
450 | SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0); | ||
451 | SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3, | ||
452 | SSB_SPROM5_GPIOB_P3_SHIFT); | ||
453 | } | ||
442 | 454 | ||
443 | /* Extract the antenna gain values. */ | 455 | /* Extract the antenna gain values. */ |
444 | SPEX(antenna_gain.ghz24.a0, SSB_SPROM4_AGAIN01, | 456 | SPEX(antenna_gain.ghz24.a0, SSB_SPROM4_AGAIN01, |
@@ -462,6 +474,8 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, | |||
462 | 474 | ||
463 | out->revision = in[size - 1] & 0x00FF; | 475 | out->revision = in[size - 1] & 0x00FF; |
464 | ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision); | 476 | ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision); |
477 | memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */ | ||
478 | memset(out->et1mac, 0xFF, 6); | ||
465 | if ((bus->chip_id & 0xFF00) == 0x4400) { | 479 | if ((bus->chip_id & 0xFF00) == 0x4400) { |
466 | /* Workaround: The BCM44XX chip has a stupid revision | 480 | /* Workaround: The BCM44XX chip has a stupid revision |
467 | * number stored in the SPROM. | 481 | * number stored in the SPROM. |
@@ -471,16 +485,16 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, | |||
471 | } else if (bus->chip_id == 0x4321) { | 485 | } else if (bus->chip_id == 0x4321) { |
472 | /* the BCM4328 has a chipid == 0x4321 and a rev 4 SPROM */ | 486 | /* the BCM4328 has a chipid == 0x4321 and a rev 4 SPROM */ |
473 | out->revision = 4; | 487 | out->revision = 4; |
474 | sprom_extract_r4(out, in); | 488 | sprom_extract_r45(out, in); |
475 | } else { | 489 | } else { |
476 | if (out->revision == 0) | 490 | if (out->revision == 0) |
477 | goto unsupported; | 491 | goto unsupported; |
478 | if (out->revision >= 1 && out->revision <= 3) { | 492 | if (out->revision >= 1 && out->revision <= 3) { |
479 | sprom_extract_r123(out, in); | 493 | sprom_extract_r123(out, in); |
480 | } | 494 | } |
481 | if (out->revision == 4) | 495 | if (out->revision == 4 || out->revision == 5) |
482 | sprom_extract_r4(out, in); | 496 | sprom_extract_r45(out, in); |
483 | if (out->revision >= 5) | 497 | if (out->revision > 5) |
484 | goto unsupported; | 498 | goto unsupported; |
485 | } | 499 | } |
486 | 500 | ||