diff options
Diffstat (limited to 'drivers/net/wireless/ath/carl9170')
-rw-r--r-- | drivers/net/wireless/ath/carl9170/carl9170.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/carl9170/main.c | 92 | ||||
-rw-r--r-- | drivers/net/wireless/ath/carl9170/tx.c | 157 |
3 files changed, 112 insertions, 139 deletions
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index 3d4ed5863732..bb578690935e 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h | |||
@@ -448,6 +448,8 @@ struct carl9170_ba_stats { | |||
448 | 448 | ||
449 | struct carl9170_sta_info { | 449 | struct carl9170_sta_info { |
450 | bool ht_sta; | 450 | bool ht_sta; |
451 | bool sleeping; | ||
452 | atomic_t pending_frames; | ||
451 | unsigned int ampdu_max_len; | 453 | unsigned int ampdu_max_len; |
452 | struct carl9170_sta_tid *agg[CARL9170_NUM_TID]; | 454 | struct carl9170_sta_tid *agg[CARL9170_NUM_TID]; |
453 | struct carl9170_ba_stats stats[CARL9170_NUM_TID]; | 455 | struct carl9170_ba_stats stats[CARL9170_NUM_TID]; |
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 89fe60accf85..1638468be5a3 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 | } |
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c index cb70ed7ec5cc..bf2eff9dd582 100644 --- a/drivers/net/wireless/ath/carl9170/tx.c +++ b/drivers/net/wireless/ath/carl9170/tx.c | |||
@@ -104,6 +104,56 @@ static void carl9170_tx_accounting(struct ar9170 *ar, struct sk_buff *skb) | |||
104 | spin_unlock_bh(&ar->tx_stats_lock); | 104 | spin_unlock_bh(&ar->tx_stats_lock); |
105 | } | 105 | } |
106 | 106 | ||
107 | /* needs rcu_read_lock */ | ||
108 | static struct ieee80211_sta *__carl9170_get_tx_sta(struct ar9170 *ar, | ||
109 | struct sk_buff *skb) | ||
110 | { | ||
111 | struct _carl9170_tx_superframe *super = (void *) skb->data; | ||
112 | struct ieee80211_hdr *hdr = (void *) super->frame_data; | ||
113 | struct ieee80211_vif *vif; | ||
114 | unsigned int vif_id; | ||
115 | |||
116 | vif_id = (super->s.misc & CARL9170_TX_SUPER_MISC_VIF_ID) >> | ||
117 | CARL9170_TX_SUPER_MISC_VIF_ID_S; | ||
118 | |||
119 | if (WARN_ON_ONCE(vif_id >= AR9170_MAX_VIRTUAL_MAC)) | ||
120 | return NULL; | ||
121 | |||
122 | vif = rcu_dereference(ar->vif_priv[vif_id].vif); | ||
123 | if (unlikely(!vif)) | ||
124 | return NULL; | ||
125 | |||
126 | /* | ||
127 | * Normally we should use wrappers like ieee80211_get_DA to get | ||
128 | * the correct peer ieee80211_sta. | ||
129 | * | ||
130 | * But there is a problem with indirect traffic (broadcasts, or | ||
131 | * data which is designated for other stations) in station mode. | ||
132 | * The frame will be directed to the AP for distribution and not | ||
133 | * to the actual destination. | ||
134 | */ | ||
135 | |||
136 | return ieee80211_find_sta(vif, hdr->addr1); | ||
137 | } | ||
138 | |||
139 | static void carl9170_tx_ps_unblock(struct ar9170 *ar, struct sk_buff *skb) | ||
140 | { | ||
141 | struct ieee80211_sta *sta; | ||
142 | struct carl9170_sta_info *sta_info; | ||
143 | |||
144 | rcu_read_lock(); | ||
145 | sta = __carl9170_get_tx_sta(ar, skb); | ||
146 | if (unlikely(!sta)) | ||
147 | goto out_rcu; | ||
148 | |||
149 | sta_info = (struct carl9170_sta_info *) sta->drv_priv; | ||
150 | if (atomic_dec_return(&sta_info->pending_frames) == 0) | ||
151 | ieee80211_sta_block_awake(ar->hw, sta, false); | ||
152 | |||
153 | out_rcu: | ||
154 | rcu_read_unlock(); | ||
155 | } | ||
156 | |||
107 | static void carl9170_tx_accounting_free(struct ar9170 *ar, struct sk_buff *skb) | 157 | static void carl9170_tx_accounting_free(struct ar9170 *ar, struct sk_buff *skb) |
108 | { | 158 | { |
109 | struct ieee80211_tx_info *txinfo; | 159 | struct ieee80211_tx_info *txinfo; |
@@ -135,6 +185,7 @@ static void carl9170_tx_accounting_free(struct ar9170 *ar, struct sk_buff *skb) | |||
135 | } | 185 | } |
136 | 186 | ||
137 | spin_unlock_bh(&ar->tx_stats_lock); | 187 | spin_unlock_bh(&ar->tx_stats_lock); |
188 | |||
138 | if (atomic_dec_and_test(&ar->tx_total_queued)) | 189 | if (atomic_dec_and_test(&ar->tx_total_queued)) |
139 | complete(&ar->tx_flush); | 190 | complete(&ar->tx_flush); |
140 | } | 191 | } |
@@ -329,13 +380,10 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, | |||
329 | { | 380 | { |
330 | struct _carl9170_tx_superframe *super = (void *) skb->data; | 381 | struct _carl9170_tx_superframe *super = (void *) skb->data; |
331 | struct ieee80211_hdr *hdr = (void *) super->frame_data; | 382 | struct ieee80211_hdr *hdr = (void *) super->frame_data; |
332 | struct ieee80211_tx_info *tx_info; | ||
333 | struct carl9170_tx_info *ar_info; | 383 | struct carl9170_tx_info *ar_info; |
334 | struct carl9170_sta_info *sta_info; | ||
335 | struct ieee80211_sta *sta; | 384 | struct ieee80211_sta *sta; |
385 | struct carl9170_sta_info *sta_info; | ||
336 | struct carl9170_sta_tid *tid_info; | 386 | struct carl9170_sta_tid *tid_info; |
337 | struct ieee80211_vif *vif; | ||
338 | unsigned int vif_id; | ||
339 | u8 tid; | 387 | u8 tid; |
340 | 388 | ||
341 | if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) || | 389 | if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) || |
@@ -343,30 +391,10 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, | |||
343 | (!(super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_AGGR)))) | 391 | (!(super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_AGGR)))) |
344 | return; | 392 | return; |
345 | 393 | ||
346 | tx_info = IEEE80211_SKB_CB(skb); | 394 | ar_info = (void *) txinfo->rate_driver_data; |
347 | ar_info = (void *) tx_info->rate_driver_data; | ||
348 | |||
349 | vif_id = (super->s.misc & CARL9170_TX_SUPER_MISC_VIF_ID) >> | ||
350 | CARL9170_TX_SUPER_MISC_VIF_ID_S; | ||
351 | |||
352 | if (WARN_ON_ONCE(vif_id >= AR9170_MAX_VIRTUAL_MAC)) | ||
353 | return; | ||
354 | 395 | ||
355 | rcu_read_lock(); | 396 | rcu_read_lock(); |
356 | vif = rcu_dereference(ar->vif_priv[vif_id].vif); | 397 | sta = __carl9170_get_tx_sta(ar, skb); |
357 | if (unlikely(!vif)) | ||
358 | goto out_rcu; | ||
359 | |||
360 | /* | ||
361 | * Normally we should use wrappers like ieee80211_get_DA to get | ||
362 | * the correct peer ieee80211_sta. | ||
363 | * | ||
364 | * But there is a problem with indirect traffic (broadcasts, or | ||
365 | * data which is designated for other stations) in station mode. | ||
366 | * The frame will be directed to the AP for distribution and not | ||
367 | * to the actual destination. | ||
368 | */ | ||
369 | sta = ieee80211_find_sta(vif, hdr->addr1); | ||
370 | if (unlikely(!sta)) | 398 | if (unlikely(!sta)) |
371 | goto out_rcu; | 399 | goto out_rcu; |
372 | 400 | ||
@@ -427,6 +455,7 @@ void carl9170_tx_status(struct ar9170 *ar, struct sk_buff *skb, | |||
427 | if (txinfo->flags & IEEE80211_TX_CTL_AMPDU) | 455 | if (txinfo->flags & IEEE80211_TX_CTL_AMPDU) |
428 | carl9170_tx_status_process_ampdu(ar, skb, txinfo); | 456 | carl9170_tx_status_process_ampdu(ar, skb, txinfo); |
429 | 457 | ||
458 | carl9170_tx_ps_unblock(ar, skb); | ||
430 | carl9170_tx_put_skb(skb); | 459 | carl9170_tx_put_skb(skb); |
431 | } | 460 | } |
432 | 461 | ||
@@ -540,11 +569,7 @@ static void carl9170_tx_ampdu_timeout(struct ar9170 *ar) | |||
540 | struct sk_buff *skb; | 569 | struct sk_buff *skb; |
541 | struct ieee80211_tx_info *txinfo; | 570 | struct ieee80211_tx_info *txinfo; |
542 | struct carl9170_tx_info *arinfo; | 571 | struct carl9170_tx_info *arinfo; |
543 | struct _carl9170_tx_superframe *super; | ||
544 | struct ieee80211_sta *sta; | 572 | struct ieee80211_sta *sta; |
545 | struct ieee80211_vif *vif; | ||
546 | struct ieee80211_hdr *hdr; | ||
547 | unsigned int vif_id; | ||
548 | 573 | ||
549 | rcu_read_lock(); | 574 | rcu_read_lock(); |
550 | list_for_each_entry_rcu(iter, &ar->tx_ampdu_list, list) { | 575 | list_for_each_entry_rcu(iter, &ar->tx_ampdu_list, list) { |
@@ -562,20 +587,7 @@ static void carl9170_tx_ampdu_timeout(struct ar9170 *ar) | |||
562 | msecs_to_jiffies(CARL9170_QUEUE_TIMEOUT))) | 587 | msecs_to_jiffies(CARL9170_QUEUE_TIMEOUT))) |
563 | goto unlock; | 588 | goto unlock; |
564 | 589 | ||
565 | super = (void *) skb->data; | 590 | sta = __carl9170_get_tx_sta(ar, skb); |
566 | hdr = (void *) super->frame_data; | ||
567 | |||
568 | vif_id = (super->s.misc & CARL9170_TX_SUPER_MISC_VIF_ID) >> | ||
569 | CARL9170_TX_SUPER_MISC_VIF_ID_S; | ||
570 | |||
571 | if (WARN_ON(vif_id >= AR9170_MAX_VIRTUAL_MAC)) | ||
572 | goto unlock; | ||
573 | |||
574 | vif = rcu_dereference(ar->vif_priv[vif_id].vif); | ||
575 | if (WARN_ON(!vif)) | ||
576 | goto unlock; | ||
577 | |||
578 | sta = ieee80211_find_sta(vif, hdr->addr1); | ||
579 | if (WARN_ON(!sta)) | 591 | if (WARN_ON(!sta)) |
580 | goto unlock; | 592 | goto unlock; |
581 | 593 | ||
@@ -1199,15 +1211,6 @@ static struct sk_buff *carl9170_tx_pick_skb(struct ar9170 *ar, | |||
1199 | arinfo = (void *) info->rate_driver_data; | 1211 | arinfo = (void *) info->rate_driver_data; |
1200 | 1212 | ||
1201 | arinfo->timeout = jiffies; | 1213 | arinfo->timeout = jiffies; |
1202 | |||
1203 | /* | ||
1204 | * increase ref count to "2". | ||
1205 | * Ref counting is the easiest way to solve the race between | ||
1206 | * the the urb's completion routine: carl9170_tx_callback and | ||
1207 | * wlan tx status functions: carl9170_tx_status/janitor. | ||
1208 | */ | ||
1209 | carl9170_tx_get_skb(skb); | ||
1210 | |||
1211 | return skb; | 1214 | return skb; |
1212 | 1215 | ||
1213 | err_unlock: | 1216 | err_unlock: |
@@ -1228,6 +1231,36 @@ void carl9170_tx_drop(struct ar9170 *ar, struct sk_buff *skb) | |||
1228 | __carl9170_tx_process_status(ar, super->s.cookie, q); | 1231 | __carl9170_tx_process_status(ar, super->s.cookie, q); |
1229 | } | 1232 | } |
1230 | 1233 | ||
1234 | static bool carl9170_tx_ps_drop(struct ar9170 *ar, struct sk_buff *skb) | ||
1235 | { | ||
1236 | struct ieee80211_sta *sta; | ||
1237 | struct carl9170_sta_info *sta_info; | ||
1238 | |||
1239 | rcu_read_lock(); | ||
1240 | sta = __carl9170_get_tx_sta(ar, skb); | ||
1241 | if (!sta) | ||
1242 | goto out_rcu; | ||
1243 | |||
1244 | sta_info = (void *) sta->drv_priv; | ||
1245 | if (unlikely(sta_info->sleeping)) { | ||
1246 | struct ieee80211_tx_info *tx_info; | ||
1247 | |||
1248 | rcu_read_unlock(); | ||
1249 | |||
1250 | tx_info = IEEE80211_SKB_CB(skb); | ||
1251 | if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) | ||
1252 | atomic_dec(&ar->tx_ampdu_upload); | ||
1253 | |||
1254 | tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | ||
1255 | carl9170_tx_status(ar, skb, false); | ||
1256 | return true; | ||
1257 | } | ||
1258 | |||
1259 | out_rcu: | ||
1260 | rcu_read_unlock(); | ||
1261 | return false; | ||
1262 | } | ||
1263 | |||
1231 | static void carl9170_tx(struct ar9170 *ar) | 1264 | static void carl9170_tx(struct ar9170 *ar) |
1232 | { | 1265 | { |
1233 | struct sk_buff *skb; | 1266 | struct sk_buff *skb; |
@@ -1247,6 +1280,9 @@ static void carl9170_tx(struct ar9170 *ar) | |||
1247 | if (unlikely(!skb)) | 1280 | if (unlikely(!skb)) |
1248 | break; | 1281 | break; |
1249 | 1282 | ||
1283 | if (unlikely(carl9170_tx_ps_drop(ar, skb))) | ||
1284 | continue; | ||
1285 | |||
1250 | atomic_inc(&ar->tx_total_pending); | 1286 | atomic_inc(&ar->tx_total_pending); |
1251 | 1287 | ||
1252 | q = __carl9170_get_queue(ar, i); | 1288 | q = __carl9170_get_queue(ar, i); |
@@ -1256,6 +1292,16 @@ static void carl9170_tx(struct ar9170 *ar) | |||
1256 | */ | 1292 | */ |
1257 | skb_queue_tail(&ar->tx_status[q], skb); | 1293 | skb_queue_tail(&ar->tx_status[q], skb); |
1258 | 1294 | ||
1295 | /* | ||
1296 | * increase ref count to "2". | ||
1297 | * Ref counting is the easiest way to solve the | ||
1298 | * race between the urb's completion routine: | ||
1299 | * carl9170_tx_callback | ||
1300 | * and wlan tx status functions: | ||
1301 | * carl9170_tx_status/janitor. | ||
1302 | */ | ||
1303 | carl9170_tx_get_skb(skb); | ||
1304 | |||
1259 | carl9170_usb_tx(ar, skb); | 1305 | carl9170_usb_tx(ar, skb); |
1260 | schedule_garbagecollector = true; | 1306 | schedule_garbagecollector = true; |
1261 | } | 1307 | } |
@@ -1368,6 +1414,11 @@ void carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1368 | * all ressouces which are associated with the frame. | 1414 | * all ressouces which are associated with the frame. |
1369 | */ | 1415 | */ |
1370 | 1416 | ||
1417 | if (sta) { | ||
1418 | struct carl9170_sta_info *stai = (void *) sta->drv_priv; | ||
1419 | atomic_inc(&stai->pending_frames); | ||
1420 | } | ||
1421 | |||
1371 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { | 1422 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { |
1372 | run = carl9170_tx_ampdu_queue(ar, sta, skb); | 1423 | run = carl9170_tx_ampdu_queue(ar, sta, skb); |
1373 | if (run) | 1424 | if (run) |