aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/carl9170/main.c
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@googlemail.com>2011-04-24 11:44:19 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-04-26 15:50:30 -0400
commitcaf1eae206688210f61f3b48627ce4ca3c709784 (patch)
tree81afc8accccdf900e01fa9c3cd3697a1724fc8c3 /drivers/net/wireless/ath/carl9170/main.c
parentbe8d98eab81d1f6445461a1631513f7091805e53 (diff)
carl9170: improve unicast PS buffering
Using the ieee80211_sta_block allows the PS code to handle awake->doze->awake transitions of our clients in a race-free manner. Signed-off-by: Christian Lamparter <chunkeey@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/carl9170/main.c')
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c92
1 files changed, 6 insertions, 86 deletions
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index 89fe60accf8..1638468be5a 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -1193,6 +1193,8 @@ static int carl9170_op_sta_add(struct ieee80211_hw *hw,
1193 struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; 1193 struct carl9170_sta_info *sta_info = (void *) sta->drv_priv;
1194 unsigned int i; 1194 unsigned int i;
1195 1195
1196 atomic_set(&sta_info->pending_frames, 0);
1197
1196 if (sta->ht_cap.ht_supported) { 1198 if (sta->ht_cap.ht_supported) {
1197 if (sta->ht_cap.ampdu_density > 6) { 1199 if (sta->ht_cap.ampdu_density > 6) {
1198 /* 1200 /*
@@ -1467,99 +1469,17 @@ static void carl9170_op_sta_notify(struct ieee80211_hw *hw,
1467 enum sta_notify_cmd cmd, 1469 enum sta_notify_cmd cmd,
1468 struct ieee80211_sta *sta) 1470 struct ieee80211_sta *sta)
1469{ 1471{
1470 struct ar9170 *ar = hw->priv;
1471 struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; 1472 struct carl9170_sta_info *sta_info = (void *) sta->drv_priv;
1472 struct sk_buff *skb, *tmp;
1473 struct sk_buff_head free;
1474 int i;
1475 1473
1476 switch (cmd) { 1474 switch (cmd) {
1477 case STA_NOTIFY_SLEEP: 1475 case STA_NOTIFY_SLEEP:
1478 /* 1476 sta_info->sleeping = true;
1479 * Since the peer is no longer listening, we have to return 1477 if (atomic_read(&sta_info->pending_frames))
1480 * as many SKBs as possible back to the mac80211 stack. 1478 ieee80211_sta_block_awake(hw, sta, true);
1481 * It will deal with the retry procedure, once the peer
1482 * has become available again.
1483 *
1484 * NB: Ideally, the driver should return the all frames in
1485 * the correct, ascending order. However, I think that this
1486 * functionality should be implemented in the stack and not
1487 * here...
1488 */
1489
1490 __skb_queue_head_init(&free);
1491
1492 if (sta->ht_cap.ht_supported) {
1493 rcu_read_lock();
1494 for (i = 0; i < CARL9170_NUM_TID; i++) {
1495 struct carl9170_sta_tid *tid_info;
1496
1497 tid_info = rcu_dereference(sta_info->agg[i]);
1498
1499 if (!tid_info)
1500 continue;
1501
1502 spin_lock_bh(&ar->tx_ampdu_list_lock);
1503 if (tid_info->state >
1504 CARL9170_TID_STATE_SUSPEND)
1505 tid_info->state =
1506 CARL9170_TID_STATE_SUSPEND;
1507 spin_unlock_bh(&ar->tx_ampdu_list_lock);
1508
1509 spin_lock_bh(&tid_info->lock);
1510 while ((skb = __skb_dequeue(&tid_info->queue)))
1511 __skb_queue_tail(&free, skb);
1512 spin_unlock_bh(&tid_info->lock);
1513 }
1514 rcu_read_unlock();
1515 }
1516
1517 for (i = 0; i < ar->hw->queues; i++) {
1518 spin_lock_bh(&ar->tx_pending[i].lock);
1519 skb_queue_walk_safe(&ar->tx_pending[i], skb, tmp) {
1520 struct _carl9170_tx_superframe *super;
1521 struct ieee80211_hdr *hdr;
1522 struct ieee80211_tx_info *info;
1523
1524 super = (void *) skb->data;
1525 hdr = (void *) super->frame_data;
1526
1527 if (compare_ether_addr(hdr->addr1, sta->addr))
1528 continue;
1529
1530 __skb_unlink(skb, &ar->tx_pending[i]);
1531
1532 info = IEEE80211_SKB_CB(skb);
1533 if (info->flags & IEEE80211_TX_CTL_AMPDU)
1534 atomic_dec(&ar->tx_ampdu_upload);
1535
1536 carl9170_tx_status(ar, skb, false);
1537 }
1538 spin_unlock_bh(&ar->tx_pending[i].lock);
1539 }
1540
1541 while ((skb = __skb_dequeue(&free)))
1542 carl9170_tx_status(ar, skb, false);
1543
1544 break; 1479 break;
1545 1480
1546 case STA_NOTIFY_AWAKE: 1481 case STA_NOTIFY_AWAKE:
1547 if (!sta->ht_cap.ht_supported) 1482 sta_info->sleeping = false;
1548 return;
1549
1550 rcu_read_lock();
1551 for (i = 0; i < CARL9170_NUM_TID; i++) {
1552 struct carl9170_sta_tid *tid_info;
1553
1554 tid_info = rcu_dereference(sta_info->agg[i]);
1555
1556 if (!tid_info)
1557 continue;
1558
1559 if ((tid_info->state == CARL9170_TID_STATE_SUSPEND))
1560 tid_info->state = CARL9170_TID_STATE_IDLE;
1561 }
1562 rcu_read_unlock();
1563 break; 1483 break;
1564 } 1484 }
1565} 1485}