2 * Copyright (c) 2010 Atheros Communications Inc.
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 int get_hw_qnum(u16 queue
, int *hwq_map
)
27 return hwq_map
[ATH9K_WME_AC_VO
];
29 return hwq_map
[ATH9K_WME_AC_VI
];
31 return hwq_map
[ATH9K_WME_AC_BE
];
33 return hwq_map
[ATH9K_WME_AC_BK
];
35 return hwq_map
[ATH9K_WME_AC_BE
];
39 int ath_htc_txq_update(struct ath9k_htc_priv
*priv
, int qnum
,
40 struct ath9k_tx_queue_info
*qinfo
)
42 struct ath_hw
*ah
= priv
->ah
;
44 struct ath9k_tx_queue_info qi
;
46 ath9k_hw_get_txq_props(ah
, qnum
, &qi
);
48 qi
.tqi_aifs
= qinfo
->tqi_aifs
;
49 qi
.tqi_cwmin
= qinfo
->tqi_cwmin
/ 2; /* XXX */
50 qi
.tqi_cwmax
= qinfo
->tqi_cwmax
;
51 qi
.tqi_burstTime
= qinfo
->tqi_burstTime
;
52 qi
.tqi_readyTime
= qinfo
->tqi_readyTime
;
54 if (!ath9k_hw_set_txq_props(ah
, qnum
, &qi
)) {
55 ath_print(ath9k_hw_common(ah
), ATH_DBG_FATAL
,
56 "Unable to update hardware queue %u!\n", qnum
);
59 ath9k_hw_resettxqueue(ah
, qnum
);
65 int ath9k_htc_tx_start(struct ath9k_htc_priv
*priv
, struct sk_buff
*skb
)
67 struct ieee80211_hdr
*hdr
;
68 struct ieee80211_tx_info
*tx_info
= IEEE80211_SKB_CB(skb
);
69 struct ieee80211_sta
*sta
= tx_info
->control
.sta
;
70 struct ath9k_htc_sta
*ista
;
71 struct ath9k_htc_vif
*avp
;
72 struct ath9k_htc_tx_ctl tx_ctl
;
73 enum htc_endpoint_id epid
;
79 hdr
= (struct ieee80211_hdr
*) skb
->data
;
80 fc
= hdr
->frame_control
;
82 avp
= (struct ath9k_htc_vif
*) tx_info
->control
.vif
->drv_priv
;
84 ista
= (struct ath9k_htc_sta
*) sta
->drv_priv
;
85 sta_idx
= ista
->index
;
90 memset(&tx_ctl
, 0, sizeof(struct ath9k_htc_tx_ctl
));
92 if (ieee80211_is_data(fc
)) {
93 struct tx_frame_hdr tx_hdr
;
96 memset(&tx_hdr
, 0, sizeof(struct tx_frame_hdr
));
98 tx_hdr
.node_idx
= sta_idx
;
99 tx_hdr
.vif_idx
= avp
->index
;
101 if (tx_info
->flags
& IEEE80211_TX_CTL_AMPDU
) {
102 tx_ctl
.type
= ATH9K_HTC_AMPDU
;
103 tx_hdr
.data_type
= ATH9K_HTC_AMPDU
;
105 tx_ctl
.type
= ATH9K_HTC_NORMAL
;
106 tx_hdr
.data_type
= ATH9K_HTC_NORMAL
;
109 if (ieee80211_is_data(fc
)) {
110 qc
= ieee80211_get_qos_ctl(hdr
);
111 tx_hdr
.tidno
= qc
[0] & IEEE80211_QOS_CTL_TID_MASK
;
114 /* Check for RTS protection */
115 if (priv
->hw
->wiphy
->rts_threshold
!= (u32
) -1)
116 if (skb
->len
> priv
->hw
->wiphy
->rts_threshold
)
117 tx_hdr
.flags
|= ATH9K_HTC_TX_RTSCTS
;
120 if (!(tx_hdr
.flags
& ATH9K_HTC_TX_RTSCTS
) &&
121 (priv
->op_flags
& OP_PROTECT_ENABLE
))
122 tx_hdr
.flags
|= ATH9K_HTC_TX_CTSONLY
;
124 tx_hdr
.key_type
= ath9k_cmn_get_hw_crypto_keytype(skb
);
125 if (tx_hdr
.key_type
== ATH9K_KEY_TYPE_CLEAR
)
126 tx_hdr
.keyix
= (u8
) ATH9K_TXKEYIX_INVALID
;
128 tx_hdr
.keyix
= tx_info
->control
.hw_key
->hw_key_idx
;
130 tx_fhdr
= skb_push(skb
, sizeof(tx_hdr
));
131 memcpy(tx_fhdr
, (u8
*) &tx_hdr
, sizeof(tx_hdr
));
133 qnum
= skb_get_queue_mapping(skb
);
134 hw_qnum
= get_hw_qnum(qnum
, priv
->hwq_map
);
138 epid
= priv
->data_be_ep
;
141 epid
= priv
->data_vi_ep
;
144 epid
= priv
->data_vo_ep
;
148 epid
= priv
->data_bk_ep
;
152 struct tx_mgmt_hdr mgmt_hdr
;
154 memset(&mgmt_hdr
, 0, sizeof(struct tx_mgmt_hdr
));
156 tx_ctl
.type
= ATH9K_HTC_NORMAL
;
158 mgmt_hdr
.node_idx
= sta_idx
;
159 mgmt_hdr
.vif_idx
= avp
->index
;
163 mgmt_hdr
.key_type
= ath9k_cmn_get_hw_crypto_keytype(skb
);
164 if (mgmt_hdr
.key_type
== ATH9K_KEY_TYPE_CLEAR
)
165 mgmt_hdr
.keyix
= (u8
) ATH9K_TXKEYIX_INVALID
;
167 mgmt_hdr
.keyix
= tx_info
->control
.hw_key
->hw_key_idx
;
169 tx_fhdr
= skb_push(skb
, sizeof(mgmt_hdr
));
170 memcpy(tx_fhdr
, (u8
*) &mgmt_hdr
, sizeof(mgmt_hdr
));
171 epid
= priv
->mgmt_ep
;
174 return htc_send(priv
->htc
, skb
, epid
, &tx_ctl
);
177 void ath9k_tx_tasklet(unsigned long data
)
179 struct ath9k_htc_priv
*priv
= (struct ath9k_htc_priv
*)data
;
180 struct ieee80211_sta
*sta
;
181 struct ieee80211_hdr
*hdr
;
182 struct ieee80211_tx_info
*tx_info
;
183 struct sk_buff
*skb
= NULL
;
186 while ((skb
= skb_dequeue(&priv
->tx_queue
)) != NULL
) {
188 hdr
= (struct ieee80211_hdr
*) skb
->data
;
189 fc
= hdr
->frame_control
;
190 tx_info
= IEEE80211_SKB_CB(skb
);
192 memset(&tx_info
->status
, 0, sizeof(tx_info
->status
));
196 sta
= ieee80211_find_sta(priv
->vif
, hdr
->addr1
);
199 ieee80211_tx_status(priv
->hw
, skb
);
203 /* Check if we need to start aggregation */
205 if (sta
&& conf_is_ht(&priv
->hw
->conf
) &&
206 (priv
->op_flags
& OP_TXAGGR
)
207 && !(skb
->protocol
== cpu_to_be16(ETH_P_PAE
))) {
208 if (ieee80211_is_data_qos(fc
)) {
210 struct ath9k_htc_sta
*ista
;
212 qc
= ieee80211_get_qos_ctl(hdr
);
214 ista
= (struct ath9k_htc_sta
*)sta
->drv_priv
;
216 if ((tid
< ATH9K_HTC_MAX_TID
) &&
217 ista
->tid_state
[tid
] == AGGR_STOP
) {
218 ieee80211_start_tx_ba_session(sta
, tid
);
219 ista
->tid_state
[tid
] = AGGR_PROGRESS
;
226 /* Send status to mac80211 */
227 ieee80211_tx_status(priv
->hw
, skb
);
230 /* Wake TX queues if needed */
231 spin_lock_bh(&priv
->tx_lock
);
232 if (priv
->tx_queues_stop
) {
233 priv
->tx_queues_stop
= false;
234 spin_unlock_bh(&priv
->tx_lock
);
235 ath_print(ath9k_hw_common(priv
->ah
), ATH_DBG_XMIT
,
236 "Waking up TX queues\n");
237 ieee80211_wake_queues(priv
->hw
);
240 spin_unlock_bh(&priv
->tx_lock
);
243 void ath9k_htc_txep(void *drv_priv
, struct sk_buff
*skb
,
244 enum htc_endpoint_id ep_id
, bool txok
)
246 struct ath9k_htc_priv
*priv
= (struct ath9k_htc_priv
*) drv_priv
;
247 struct ath_common
*common
= ath9k_hw_common(priv
->ah
);
248 struct ieee80211_tx_info
*tx_info
;
253 if (ep_id
== priv
->mgmt_ep
) {
254 skb_pull(skb
, sizeof(struct tx_mgmt_hdr
));
255 } else if ((ep_id
== priv
->data_bk_ep
) ||
256 (ep_id
== priv
->data_be_ep
) ||
257 (ep_id
== priv
->data_vi_ep
) ||
258 (ep_id
== priv
->data_vo_ep
)) {
259 skb_pull(skb
, sizeof(struct tx_frame_hdr
));
261 ath_print(common
, ATH_DBG_FATAL
,
262 "Unsupported TX EPID: %d\n", ep_id
);
263 dev_kfree_skb_any(skb
);
267 tx_info
= IEEE80211_SKB_CB(skb
);
270 tx_info
->flags
|= IEEE80211_TX_STAT_ACK
;
272 skb_queue_tail(&priv
->tx_queue
, skb
);
273 tasklet_schedule(&priv
->tx_tasklet
);
276 int ath9k_tx_init(struct ath9k_htc_priv
*priv
)
278 skb_queue_head_init(&priv
->tx_queue
);
282 void ath9k_tx_cleanup(struct ath9k_htc_priv
*priv
)
287 bool ath9k_htc_txq_setup(struct ath9k_htc_priv
*priv
,
288 enum ath9k_tx_queue_subtype subtype
)
290 struct ath_hw
*ah
= priv
->ah
;
291 struct ath_common
*common
= ath9k_hw_common(ah
);
292 struct ath9k_tx_queue_info qi
;
295 memset(&qi
, 0, sizeof(qi
));
297 qi
.tqi_subtype
= subtype
;
298 qi
.tqi_aifs
= ATH9K_TXQ_USEDEFAULT
;
299 qi
.tqi_cwmin
= ATH9K_TXQ_USEDEFAULT
;
300 qi
.tqi_cwmax
= ATH9K_TXQ_USEDEFAULT
;
301 qi
.tqi_physCompBuf
= 0;
302 qi
.tqi_qflags
= TXQ_FLAG_TXEOLINT_ENABLE
| TXQ_FLAG_TXDESCINT_ENABLE
;
304 qnum
= ath9k_hw_setuptxqueue(priv
->ah
, ATH9K_TX_QUEUE_DATA
, &qi
);
308 if (qnum
>= ARRAY_SIZE(priv
->hwq_map
)) {
309 ath_print(common
, ATH_DBG_FATAL
,
310 "qnum %u out of range, max %u!\n",
311 qnum
, (unsigned int)ARRAY_SIZE(priv
->hwq_map
));
312 ath9k_hw_releasetxqueue(ah
, qnum
);
316 priv
->hwq_map
[subtype
] = qnum
;
325 * Calculate the RX filter to be set in the HW.
327 u32
ath9k_htc_calcrxfilter(struct ath9k_htc_priv
*priv
)
329 #define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR)
331 struct ath_hw
*ah
= priv
->ah
;
334 rfilt
= (ath9k_hw_getrxfilter(ah
) & RX_FILTER_PRESERVE
)
335 | ATH9K_RX_FILTER_UCAST
| ATH9K_RX_FILTER_BCAST
336 | ATH9K_RX_FILTER_MCAST
;
338 /* If not a STA, enable processing of Probe Requests */
339 if (ah
->opmode
!= NL80211_IFTYPE_STATION
)
340 rfilt
|= ATH9K_RX_FILTER_PROBEREQ
;
343 * Set promiscuous mode when FIF_PROMISC_IN_BSS is enabled for station
344 * mode interface or when in monitor mode. AP mode does not need this
345 * since it receives all in-BSS frames anyway.
347 if (((ah
->opmode
!= NL80211_IFTYPE_AP
) &&
348 (priv
->rxfilter
& FIF_PROMISC_IN_BSS
)) ||
349 (ah
->opmode
== NL80211_IFTYPE_MONITOR
))
350 rfilt
|= ATH9K_RX_FILTER_PROM
;
352 if (priv
->rxfilter
& FIF_CONTROL
)
353 rfilt
|= ATH9K_RX_FILTER_CONTROL
;
355 if ((ah
->opmode
== NL80211_IFTYPE_STATION
) &&
356 !(priv
->rxfilter
& FIF_BCN_PRBRESP_PROMISC
))
357 rfilt
|= ATH9K_RX_FILTER_MYBEACON
;
359 rfilt
|= ATH9K_RX_FILTER_BEACON
;
361 if (conf_is_ht(&priv
->hw
->conf
))
362 rfilt
|= ATH9K_RX_FILTER_COMP_BAR
;
366 #undef RX_FILTER_PRESERVE
370 * Recv initialization for opmode change.
372 static void ath9k_htc_opmode_init(struct ath9k_htc_priv
*priv
)
374 struct ath_hw
*ah
= priv
->ah
;
375 struct ath_common
*common
= ath9k_hw_common(ah
);
379 /* configure rx filter */
380 rfilt
= ath9k_htc_calcrxfilter(priv
);
381 ath9k_hw_setrxfilter(ah
, rfilt
);
383 /* configure bssid mask */
384 if (ah
->caps
.hw_caps
& ATH9K_HW_CAP_BSSIDMASK
)
385 ath_hw_setbssidmask(common
);
387 /* configure operational mode */
388 ath9k_hw_setopmode(ah
);
390 /* Handle any link-level address change. */
391 ath9k_hw_setmac(ah
, common
->macaddr
);
393 /* calculate and install multicast filter */
394 mfilt
[0] = mfilt
[1] = ~0;
395 ath9k_hw_setmcastfilter(ah
, mfilt
[0], mfilt
[1]);
398 void ath9k_host_rx_init(struct ath9k_htc_priv
*priv
)
400 ath9k_hw_rxena(priv
->ah
);
401 ath9k_htc_opmode_init(priv
);
402 ath9k_hw_startpcureceive(priv
->ah
);
403 priv
->rx
.last_rssi
= ATH_RSSI_DUMMY_MARKER
;
406 static void ath9k_process_rate(struct ieee80211_hw
*hw
,
407 struct ieee80211_rx_status
*rxs
,
408 u8 rx_rate
, u8 rs_flags
)
410 struct ieee80211_supported_band
*sband
;
411 enum ieee80211_band band
;
414 if (rx_rate
& 0x80) {
416 rxs
->flag
|= RX_FLAG_HT
;
417 if (rs_flags
& ATH9K_RX_2040
)
418 rxs
->flag
|= RX_FLAG_40MHZ
;
419 if (rs_flags
& ATH9K_RX_GI
)
420 rxs
->flag
|= RX_FLAG_SHORT_GI
;
421 rxs
->rate_idx
= rx_rate
& 0x7f;
425 band
= hw
->conf
.channel
->band
;
426 sband
= hw
->wiphy
->bands
[band
];
428 for (i
= 0; i
< sband
->n_bitrates
; i
++) {
429 if (sband
->bitrates
[i
].hw_value
== rx_rate
) {
433 if (sband
->bitrates
[i
].hw_value_short
== rx_rate
) {
435 rxs
->flag
|= RX_FLAG_SHORTPRE
;
442 static bool ath9k_rx_prepare(struct ath9k_htc_priv
*priv
,
443 struct ath9k_htc_rxbuf
*rxbuf
,
444 struct ieee80211_rx_status
*rx_status
)
447 struct ieee80211_hdr
*hdr
;
448 struct ieee80211_hw
*hw
= priv
->hw
;
449 struct sk_buff
*skb
= rxbuf
->skb
;
450 struct ath_common
*common
= ath9k_hw_common(priv
->ah
);
451 struct ath_htc_rx_status
*rxstatus
;
452 int hdrlen
, padpos
, padsize
;
453 int last_rssi
= ATH_RSSI_DUMMY_MARKER
;
456 if (skb
->len
<= HTC_RX_FRAME_HEADER_SIZE
) {
457 ath_print(common
, ATH_DBG_FATAL
,
458 "Corrupted RX frame, dropping\n");
462 rxstatus
= (struct ath_htc_rx_status
*)skb
->data
;
464 if (be16_to_cpu(rxstatus
->rs_datalen
) -
465 (skb
->len
- HTC_RX_FRAME_HEADER_SIZE
) != 0) {
466 ath_print(common
, ATH_DBG_FATAL
,
467 "Corrupted RX data len, dropping "
468 "(dlen: %d, skblen: %d)\n",
469 rxstatus
->rs_datalen
, skb
->len
);
473 /* Get the RX status information */
474 memcpy(&rxbuf
->rxstatus
, rxstatus
, HTC_RX_FRAME_HEADER_SIZE
);
475 skb_pull(skb
, HTC_RX_FRAME_HEADER_SIZE
);
477 hdr
= (struct ieee80211_hdr
*)skb
->data
;
478 fc
= hdr
->frame_control
;
479 hdrlen
= ieee80211_get_hdrlen_from_skb(skb
);
481 padpos
= ath9k_cmn_padpos(fc
);
483 padsize
= padpos
& 3;
484 if (padsize
&& skb
->len
>= padpos
+padsize
+FCS_LEN
) {
485 memmove(skb
->data
+ padsize
, skb
->data
, padpos
);
486 skb_pull(skb
, padsize
);
489 memset(rx_status
, 0, sizeof(struct ieee80211_rx_status
));
491 if (rxbuf
->rxstatus
.rs_status
!= 0) {
492 if (rxbuf
->rxstatus
.rs_status
& ATH9K_RXERR_CRC
)
493 rx_status
->flag
|= RX_FLAG_FAILED_FCS_CRC
;
494 if (rxbuf
->rxstatus
.rs_status
& ATH9K_RXERR_PHY
)
497 if (rxbuf
->rxstatus
.rs_status
& ATH9K_RXERR_DECRYPT
) {
499 } else if (rxbuf
->rxstatus
.rs_status
& ATH9K_RXERR_MIC
) {
500 if (ieee80211_is_ctl(fc
))
502 * Sometimes, we get invalid
503 * MIC failures on valid control frames.
504 * Remove these mic errors.
506 rxbuf
->rxstatus
.rs_status
&= ~ATH9K_RXERR_MIC
;
508 rx_status
->flag
|= RX_FLAG_MMIC_ERROR
;
512 * Reject error frames with the exception of
513 * decryption and MIC failures. For monitor mode,
514 * we also ignore the CRC error.
516 if (priv
->ah
->opmode
== NL80211_IFTYPE_MONITOR
) {
517 if (rxbuf
->rxstatus
.rs_status
&
518 ~(ATH9K_RXERR_DECRYPT
| ATH9K_RXERR_MIC
|
522 if (rxbuf
->rxstatus
.rs_status
&
523 ~(ATH9K_RXERR_DECRYPT
| ATH9K_RXERR_MIC
)) {
529 if (!(rxbuf
->rxstatus
.rs_status
& ATH9K_RXERR_DECRYPT
)) {
531 keyix
= rxbuf
->rxstatus
.rs_keyix
;
532 if (keyix
!= ATH9K_RXKEYIX_INVALID
) {
533 rx_status
->flag
|= RX_FLAG_DECRYPTED
;
534 } else if (ieee80211_has_protected(fc
) &&
535 skb
->len
>= hdrlen
+ 4) {
536 keyix
= skb
->data
[hdrlen
+ 3] >> 6;
537 if (test_bit(keyix
, common
->keymap
))
538 rx_status
->flag
|= RX_FLAG_DECRYPTED
;
542 ath9k_process_rate(hw
, rx_status
, rxbuf
->rxstatus
.rs_rate
,
543 rxbuf
->rxstatus
.rs_flags
);
545 if (priv
->op_flags
& OP_ASSOCIATED
) {
546 if (rxbuf
->rxstatus
.rs_rssi
!= ATH9K_RSSI_BAD
&&
547 !rxbuf
->rxstatus
.rs_moreaggr
)
548 ATH_RSSI_LPF(priv
->rx
.last_rssi
,
549 rxbuf
->rxstatus
.rs_rssi
);
551 last_rssi
= priv
->rx
.last_rssi
;
553 if (likely(last_rssi
!= ATH_RSSI_DUMMY_MARKER
))
554 rxbuf
->rxstatus
.rs_rssi
= ATH_EP_RND(last_rssi
,
555 ATH_RSSI_EP_MULTIPLIER
);
557 if (rxbuf
->rxstatus
.rs_rssi
< 0)
558 rxbuf
->rxstatus
.rs_rssi
= 0;
560 if (ieee80211_is_beacon(fc
))
561 priv
->ah
->stats
.avgbrssi
= rxbuf
->rxstatus
.rs_rssi
;
564 rx_status
->mactime
= be64_to_cpu(rxbuf
->rxstatus
.rs_tstamp
);
565 rx_status
->band
= hw
->conf
.channel
->band
;
566 rx_status
->freq
= hw
->conf
.channel
->center_freq
;
567 rx_status
->signal
= rxbuf
->rxstatus
.rs_rssi
+ ATH_DEFAULT_NOISE_FLOOR
;
568 rx_status
->antenna
= rxbuf
->rxstatus
.rs_antenna
;
569 rx_status
->flag
|= RX_FLAG_TSFT
;
578 * FIXME: Handle FLUSH later on.
580 void ath9k_rx_tasklet(unsigned long data
)
582 struct ath9k_htc_priv
*priv
= (struct ath9k_htc_priv
*)data
;
583 struct ath9k_htc_rxbuf
*rxbuf
= NULL
, *tmp_buf
= NULL
;
584 struct ieee80211_rx_status rx_status
;
587 struct ieee80211_hdr
*hdr
;
590 spin_lock_irqsave(&priv
->rx
.rxbuflock
, flags
);
591 list_for_each_entry(tmp_buf
, &priv
->rx
.rxbuf
, list
) {
592 if (tmp_buf
->in_process
) {
599 spin_unlock_irqrestore(&priv
->rx
.rxbuflock
, flags
);
606 if (!ath9k_rx_prepare(priv
, rxbuf
, &rx_status
)) {
607 dev_kfree_skb_any(rxbuf
->skb
);
611 memcpy(IEEE80211_SKB_RXCB(rxbuf
->skb
), &rx_status
,
612 sizeof(struct ieee80211_rx_status
));
614 hdr
= (struct ieee80211_hdr
*) skb
->data
;
616 if (ieee80211_is_beacon(hdr
->frame_control
) && priv
->ps_enabled
)
617 ieee80211_queue_work(priv
->hw
, &priv
->ps_work
);
619 spin_unlock_irqrestore(&priv
->rx
.rxbuflock
, flags
);
621 ieee80211_rx(priv
->hw
, skb
);
623 spin_lock_irqsave(&priv
->rx
.rxbuflock
, flags
);
625 rxbuf
->in_process
= false;
627 list_move_tail(&rxbuf
->list
, &priv
->rx
.rxbuf
);
629 spin_unlock_irqrestore(&priv
->rx
.rxbuflock
, flags
);
634 void ath9k_htc_rxep(void *drv_priv
, struct sk_buff
*skb
,
635 enum htc_endpoint_id ep_id
)
637 struct ath9k_htc_priv
*priv
= (struct ath9k_htc_priv
*)drv_priv
;
638 struct ath_hw
*ah
= priv
->ah
;
639 struct ath_common
*common
= ath9k_hw_common(ah
);
640 struct ath9k_htc_rxbuf
*rxbuf
= NULL
, *tmp_buf
= NULL
;
642 spin_lock(&priv
->rx
.rxbuflock
);
643 list_for_each_entry(tmp_buf
, &priv
->rx
.rxbuf
, list
) {
644 if (!tmp_buf
->in_process
) {
649 spin_unlock(&priv
->rx
.rxbuflock
);
652 ath_print(common
, ATH_DBG_ANY
,
653 "No free RX buffer\n");
657 spin_lock(&priv
->rx
.rxbuflock
);
659 rxbuf
->in_process
= true;
660 spin_unlock(&priv
->rx
.rxbuflock
);
662 tasklet_schedule(&priv
->rx_tasklet
);
665 dev_kfree_skb_any(skb
);
668 /* FIXME: Locking for cleanup/init */
670 void ath9k_rx_cleanup(struct ath9k_htc_priv
*priv
)
672 struct ath9k_htc_rxbuf
*rxbuf
, *tbuf
;
674 list_for_each_entry_safe(rxbuf
, tbuf
, &priv
->rx
.rxbuf
, list
) {
675 list_del(&rxbuf
->list
);
677 dev_kfree_skb_any(rxbuf
->skb
);
682 int ath9k_rx_init(struct ath9k_htc_priv
*priv
)
684 struct ath_hw
*ah
= priv
->ah
;
685 struct ath_common
*common
= ath9k_hw_common(ah
);
686 struct ath9k_htc_rxbuf
*rxbuf
;
689 INIT_LIST_HEAD(&priv
->rx
.rxbuf
);
690 spin_lock_init(&priv
->rx
.rxbuflock
);
692 for (i
= 0; i
< ATH9K_HTC_RXBUF
; i
++) {
693 rxbuf
= kzalloc(sizeof(struct ath9k_htc_rxbuf
), GFP_KERNEL
);
695 ath_print(common
, ATH_DBG_FATAL
,
696 "Unable to allocate RX buffers\n");
699 list_add_tail(&rxbuf
->list
, &priv
->rx
.rxbuf
);
705 ath9k_rx_cleanup(priv
);