diff options
author | Sujith Manoharan <Sujith.Manoharan@atheros.com> | 2011-04-13 01:55:54 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-04-13 15:24:03 -0400 |
commit | f2820f4583b233827f10d91adea70225e196d852 (patch) | |
tree | 1ed1a0c97f1960ed402c3723c258cea50916dea9 /drivers/net/wireless | |
parent | 2c5d57f004673a9c8658e20b1fa3f992b5a10f70 (diff) |
ath9k_htc: Use helper functions for TX processing
Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 137 |
1 files changed, 73 insertions, 64 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index ee5b3e281cd3..944440c84c49 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | |||
@@ -325,8 +325,8 @@ send: | |||
325 | return htc_send(priv->htc, skb); | 325 | return htc_send(priv->htc, skb); |
326 | } | 326 | } |
327 | 327 | ||
328 | static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, | 328 | static inline bool __ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, |
329 | struct ath9k_htc_sta *ista, u8 tid) | 329 | struct ath9k_htc_sta *ista, u8 tid) |
330 | { | 330 | { |
331 | bool ret = false; | 331 | bool ret = false; |
332 | 332 | ||
@@ -338,89 +338,98 @@ static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, | |||
338 | return ret; | 338 | return ret; |
339 | } | 339 | } |
340 | 340 | ||
341 | void ath9k_tx_tasklet(unsigned long data) | 341 | static void ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, |
342 | struct ieee80211_vif *vif, | ||
343 | struct sk_buff *skb) | ||
342 | { | 344 | { |
343 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; | ||
344 | struct ath9k_htc_tx_ctl *tx_ctl; | ||
345 | struct ieee80211_vif *vif; | ||
346 | struct ieee80211_sta *sta; | 345 | struct ieee80211_sta *sta; |
347 | struct ieee80211_hdr *hdr; | 346 | struct ieee80211_hdr *hdr; |
348 | struct ieee80211_tx_info *tx_info; | ||
349 | struct sk_buff *skb = NULL; | ||
350 | __le16 fc; | 347 | __le16 fc; |
351 | bool txok; | ||
352 | int slot; | ||
353 | 348 | ||
354 | while ((skb = skb_dequeue(&priv->tx.tx_queue)) != NULL) { | 349 | hdr = (struct ieee80211_hdr *) skb->data; |
350 | fc = hdr->frame_control; | ||
355 | 351 | ||
356 | slot = strip_drv_header(priv, skb); | 352 | rcu_read_lock(); |
357 | if (slot < 0) { | ||
358 | dev_kfree_skb_any(skb); | ||
359 | continue; | ||
360 | } | ||
361 | 353 | ||
362 | tx_ctl = HTC_SKB_CB(skb); | 354 | sta = ieee80211_find_sta(vif, hdr->addr1); |
363 | hdr = (struct ieee80211_hdr *) skb->data; | 355 | if (!sta) { |
364 | fc = hdr->frame_control; | 356 | rcu_read_unlock(); |
365 | tx_info = IEEE80211_SKB_CB(skb); | 357 | return; |
366 | vif = tx_info->control.vif; | 358 | } |
367 | txok = tx_ctl->txok; | ||
368 | 359 | ||
369 | memset(&tx_info->status, 0, sizeof(tx_info->status)); | 360 | if (sta && conf_is_ht(&priv->hw->conf) && |
361 | !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { | ||
362 | if (ieee80211_is_data_qos(fc)) { | ||
363 | u8 *qc, tid; | ||
364 | struct ath9k_htc_sta *ista; | ||
370 | 365 | ||
371 | /* | 366 | qc = ieee80211_get_qos_ctl(hdr); |
372 | * URB submission failed for this frame, it never reached | 367 | tid = qc[0] & 0xf; |
373 | * the target. | 368 | ista = (struct ath9k_htc_sta *)sta->drv_priv; |
374 | */ | 369 | if (__ath9k_htc_check_tx_aggr(priv, ista, tid)) { |
375 | if (!txok) | 370 | ieee80211_start_tx_ba_session(sta, tid, 0); |
376 | goto send_mac80211; | 371 | spin_lock_bh(&priv->tx.tx_lock); |
372 | ista->tid_state[tid] = AGGR_PROGRESS; | ||
373 | spin_unlock_bh(&priv->tx.tx_lock); | ||
374 | } | ||
375 | } | ||
376 | } | ||
377 | 377 | ||
378 | tx_info->flags |= IEEE80211_TX_STAT_ACK; | 378 | rcu_read_unlock(); |
379 | } | ||
379 | 380 | ||
380 | if (!vif) | 381 | static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv, |
381 | goto send_mac80211; | 382 | struct sk_buff *skb) |
383 | { | ||
384 | struct ieee80211_vif *vif; | ||
385 | struct ath9k_htc_tx_ctl *tx_ctl; | ||
386 | struct ieee80211_tx_info *tx_info; | ||
387 | bool txok; | ||
388 | int slot; | ||
382 | 389 | ||
383 | rcu_read_lock(); | 390 | slot = strip_drv_header(priv, skb); |
391 | if (slot < 0) { | ||
392 | dev_kfree_skb_any(skb); | ||
393 | return; | ||
394 | } | ||
384 | 395 | ||
385 | sta = ieee80211_find_sta(vif, hdr->addr1); | 396 | tx_ctl = HTC_SKB_CB(skb); |
386 | if (!sta) { | 397 | txok = tx_ctl->txok; |
387 | rcu_read_unlock(); | 398 | tx_info = IEEE80211_SKB_CB(skb); |
388 | goto send_mac80211; | 399 | vif = tx_info->control.vif; |
389 | } | ||
390 | 400 | ||
391 | /* Check if we need to start aggregation */ | 401 | memset(&tx_info->status, 0, sizeof(tx_info->status)); |
392 | 402 | ||
393 | if (sta && conf_is_ht(&priv->hw->conf) && | 403 | /* |
394 | !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { | 404 | * URB submission failed for this frame, it never reached |
395 | if (ieee80211_is_data_qos(fc)) { | 405 | * the target. |
396 | u8 *qc, tid; | 406 | */ |
397 | struct ath9k_htc_sta *ista; | 407 | if (!txok || !vif) |
408 | goto send_mac80211; | ||
398 | 409 | ||
399 | qc = ieee80211_get_qos_ctl(hdr); | 410 | tx_info->flags |= IEEE80211_TX_STAT_ACK; |
400 | tid = qc[0] & 0xf; | ||
401 | ista = (struct ath9k_htc_sta *)sta->drv_priv; | ||
402 | 411 | ||
403 | if (ath9k_htc_check_tx_aggr(priv, ista, tid)) { | 412 | ath9k_htc_check_tx_aggr(priv, vif, skb); |
404 | ieee80211_start_tx_ba_session(sta, tid, 0); | ||
405 | spin_lock_bh(&priv->tx.tx_lock); | ||
406 | ista->tid_state[tid] = AGGR_PROGRESS; | ||
407 | spin_unlock_bh(&priv->tx.tx_lock); | ||
408 | } | ||
409 | } | ||
410 | } | ||
411 | 413 | ||
412 | rcu_read_unlock(); | 414 | send_mac80211: |
415 | spin_lock_bh(&priv->tx.tx_lock); | ||
416 | if (WARN_ON(--priv->tx.queued_cnt < 0)) | ||
417 | priv->tx.queued_cnt = 0; | ||
418 | spin_unlock_bh(&priv->tx.tx_lock); | ||
413 | 419 | ||
414 | send_mac80211: | 420 | ath9k_htc_tx_clear_slot(priv, slot); |
415 | spin_lock_bh(&priv->tx.tx_lock); | 421 | |
416 | if (WARN_ON(--priv->tx.queued_cnt < 0)) | 422 | /* Send status to mac80211 */ |
417 | priv->tx.queued_cnt = 0; | 423 | ieee80211_tx_status(priv->hw, skb); |
418 | spin_unlock_bh(&priv->tx.tx_lock); | 424 | } |
419 | 425 | ||
420 | ath9k_htc_tx_clear_slot(priv, slot); | 426 | void ath9k_tx_tasklet(unsigned long data) |
427 | { | ||
428 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; | ||
429 | struct sk_buff *skb = NULL; | ||
421 | 430 | ||
422 | /* Send status to mac80211 */ | 431 | while ((skb = skb_dequeue(&priv->tx.tx_queue)) != NULL) { |
423 | ieee80211_tx_status(priv->hw, skb); | 432 | ath9k_htc_tx_process(priv, skb); |
424 | } | 433 | } |
425 | 434 | ||
426 | /* Wake TX queues if needed */ | 435 | /* Wake TX queues if needed */ |