diff options
author | Jouni Malinen <jouni.malinen@atheros.com> | 2008-08-22 10:31:33 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-08-29 16:24:08 -0400 |
commit | e022edbd2bfb5f9a7ddf1cca43544f7b54c6fe02 (patch) | |
tree | 4f46cfa403522902774e37b8cee7198eedde4119 /drivers/net/wireless/ath9k/beacon.c | |
parent | 87e8b64e6856a41c5204a22c47cc14b1b0b57332 (diff) |
ath9k: Use mac80211 for multicast power save buffering
Replace the internal ath9k implementation of multicast/broadcast frame
power save buffering (AP mode) in ath9k with use of mac80211
ieee80211_get_buffered_bc() mechanism. This removes quite a bit of
duplicated functionality and simplifies the driver part.
Signed-off-by: Jouni Malinen <jouni.malinen@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath9k/beacon.c')
-rw-r--r-- | drivers/net/wireless/ath9k/beacon.c | 75 |
1 files changed, 7 insertions, 68 deletions
diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c index ee1185622ba6..fdbabc180228 100644 --- a/drivers/net/wireless/ath9k/beacon.c +++ b/drivers/net/wireless/ath9k/beacon.c | |||
@@ -140,56 +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 | /* TODO: use ieee80211_get_buffered_bc() to fetch power saved mcast frames */ | ||
176 | /* This is only run at DTIM. We move everything from the vap's mcast queue | ||
177 | * to the hardware cab queue. Caller must hold the mcastq lock. */ | ||
178 | static void trigger_mcastq(struct ath_hal *ah, | ||
179 | struct ath_txq *mcastq, struct ath_txq *cabq) | ||
180 | { | ||
181 | spin_lock_bh(&cabq->axq_lock); | ||
182 | |||
183 | if (!list_empty(&mcastq->axq_q)) | ||
184 | empty_mcastq_into_cabq(ah, mcastq, cabq); | ||
185 | |||
186 | /* cabq is gated by beacon so it is safe to start here */ | ||
187 | if (!list_empty(&cabq->axq_q)) | ||
188 | ath9k_hw_txstart(ah, cabq->axq_qnum); | ||
189 | |||
190 | spin_unlock_bh(&cabq->axq_lock); | ||
191 | } | ||
192 | |||
193 | /* | 143 | /* |
194 | * Generate beacon frame and queue cab data for a vap. | 144 | * Generate beacon frame and queue cab data for a vap. |
195 | * | 145 | * |
@@ -200,19 +150,14 @@ static void trigger_mcastq(struct ath_hal *ah, | |||
200 | */ | 150 | */ |
201 | 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) |
202 | { | 152 | { |
203 | struct ath_hal *ah = sc->sc_ah; | ||
204 | struct ath_buf *bf; | 153 | struct ath_buf *bf; |
205 | struct ath_vap *avp; | 154 | struct ath_vap *avp; |
206 | struct sk_buff *skb; | 155 | struct sk_buff *skb; |
207 | int cabq_depth; | 156 | int cabq_depth; |
208 | int mcastq_depth; | ||
209 | int is_beacon_dtim = 0; | ||
210 | struct ath_txq *cabq; | 157 | struct ath_txq *cabq; |
211 | struct ath_txq *mcastq; | ||
212 | struct ieee80211_tx_info *info; | 158 | struct ieee80211_tx_info *info; |
213 | avp = sc->sc_vaps[if_id]; | 159 | avp = sc->sc_vaps[if_id]; |
214 | 160 | ||
215 | mcastq = &avp->av_mcastq; | ||
216 | cabq = sc->sc_cabq; | 161 | cabq = sc->sc_cabq; |
217 | 162 | ||
218 | ASSERT(avp); | 163 | ASSERT(avp); |
@@ -250,11 +195,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) | |||
250 | skb_end_pointer(skb) - skb->head, | 195 | skb_end_pointer(skb) - skb->head, |
251 | PCI_DMA_TODEVICE); | 196 | PCI_DMA_TODEVICE); |
252 | 197 | ||
253 | /* TODO: convert to use ieee80211_get_buffered_bc() */ | 198 | skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data); |
254 | /* XXX: spin_lock_bh should not be used here, but sparse bitches | ||
255 | * otherwise. We should fix sparse :) */ | ||
256 | spin_lock_bh(&mcastq->axq_lock); | ||
257 | mcastq_depth = avp->av_mcastq.axq_depth; | ||
258 | 199 | ||
259 | /* | 200 | /* |
260 | * 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 |
@@ -268,10 +209,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) | |||
268 | cabq_depth = cabq->axq_depth; | 209 | cabq_depth = cabq->axq_depth; |
269 | spin_unlock_bh(&cabq->axq_lock); | 210 | spin_unlock_bh(&cabq->axq_lock); |
270 | 211 | ||
271 | if (avp->av_boff.bo_tim) | 212 | if (skb && cabq_depth) { |
272 | is_beacon_dtim = avp->av_boff.bo_tim[4] & 1; | ||
273 | |||
274 | if (mcastq_depth && is_beacon_dtim && cabq_depth) { | ||
275 | /* | 213 | /* |
276 | * Unlock the cabq lock as ath_tx_draintxq acquires | 214 | * Unlock the cabq lock as ath_tx_draintxq acquires |
277 | * the lock again which is a common function and that | 215 | * the lock again which is a common function and that |
@@ -291,10 +229,11 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) | |||
291 | * Enable the CAB queue before the beacon queue to | 229 | * Enable the CAB queue before the beacon queue to |
292 | * insure cab frames are triggered by this beacon. | 230 | * insure cab frames are triggered by this beacon. |
293 | */ | 231 | */ |
294 | if (is_beacon_dtim) | 232 | while (skb) { |
295 | trigger_mcastq(ah, mcastq, cabq); | 233 | ath_tx_cabq(sc, skb); |
234 | skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data); | ||
235 | } | ||
296 | 236 | ||
297 | spin_unlock_bh(&mcastq->axq_lock); | ||
298 | return bf; | 237 | return bf; |
299 | } | 238 | } |
300 | 239 | ||
@@ -426,7 +365,7 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) | |||
426 | * NB: the beacon data buffer must be 32-bit aligned; | 365 | * NB: the beacon data buffer must be 32-bit aligned; |
427 | * we assume the wbuf routines will return us something | 366 | * we assume the wbuf routines will return us something |
428 | * with this alignment (perhaps should assert). | 367 | * with this alignment (perhaps should assert). |
429 | * FIXME: Fill avp->av_boff.bo_tim,avp->av_btxctl.txpower and | 368 | * FIXME: Fill avp->av_btxctl.txpower and |
430 | * avp->av_btxctl.shortPreamble | 369 | * avp->av_btxctl.shortPreamble |
431 | */ | 370 | */ |
432 | skb = ieee80211_beacon_get(sc->hw, avp->av_if_data); | 371 | skb = ieee80211_beacon_get(sc->hw, avp->av_if_data); |