aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2014-07-23 06:20:33 -0400
committerKalle Valo <kvalo@qca.qualcomm.com>2014-07-25 04:15:39 -0400
commitaa5b4fbcff48234280359da84ac24e6f3057325b (patch)
tree443d18d669afdc562b5863685dda3c5f220c7a6b /drivers/net/wireless
parent30d88ce331d566f496fe7bea25ee560dcfd253ae (diff)
ath10k: fix Rx aggregation reordering
Firmware doesn't perform Rx reordering so it is left to the host driver to do that. Use mac80211 to perform reordering instead of re-inventing the wheel. This fixes TCP throughput issues in some environments. Reported-by: Denton Gentry <denton.gentry@gmail.com> Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c92
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c33
-rw-r--r--drivers/net/wireless/ath/ath10k/txrx.c3
-rw-r--r--drivers/net/wireless/ath/ath10k/txrx.h1
4 files changed, 126 insertions, 3 deletions
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 318efc35d116..77cdc21e28d7 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -21,6 +21,7 @@
21#include "txrx.h" 21#include "txrx.h"
22#include "debug.h" 22#include "debug.h"
23#include "trace.h" 23#include "trace.h"
24#include "mac.h"
24 25
25#include <linux/log2.h> 26#include <linux/log2.h>
26 27
@@ -1422,6 +1423,86 @@ static void ath10k_htt_rx_frm_tx_compl(struct ath10k *ar,
1422 } 1423 }
1423} 1424}
1424 1425
1426static void ath10k_htt_rx_addba(struct ath10k *ar, struct htt_resp *resp)
1427{
1428 struct htt_rx_addba *ev = &resp->rx_addba;
1429 struct ath10k_peer *peer;
1430 struct ath10k_vif *arvif;
1431 u16 info0, tid, peer_id;
1432
1433 info0 = __le16_to_cpu(ev->info0);
1434 tid = MS(info0, HTT_RX_BA_INFO0_TID);
1435 peer_id = MS(info0, HTT_RX_BA_INFO0_PEER_ID);
1436
1437 ath10k_dbg(ATH10K_DBG_HTT,
1438 "htt rx addba tid %hu peer_id %hu size %hhu\n",
1439 tid, peer_id, ev->window_size);
1440
1441 spin_lock_bh(&ar->data_lock);
1442 peer = ath10k_peer_find_by_id(ar, peer_id);
1443 if (!peer) {
1444 ath10k_warn("received addba event for invalid peer_id: %hu\n",
1445 peer_id);
1446 spin_unlock_bh(&ar->data_lock);
1447 return;
1448 }
1449
1450 arvif = ath10k_get_arvif(ar, peer->vdev_id);
1451 if (!arvif) {
1452 ath10k_warn("received addba event for invalid vdev_id: %u\n",
1453 peer->vdev_id);
1454 spin_unlock_bh(&ar->data_lock);
1455 return;
1456 }
1457
1458 ath10k_dbg(ATH10K_DBG_HTT,
1459 "htt rx start rx ba session sta %pM tid %hu size %hhu\n",
1460 peer->addr, tid, ev->window_size);
1461
1462 ieee80211_start_rx_ba_session_offl(arvif->vif, peer->addr, tid);
1463 spin_unlock_bh(&ar->data_lock);
1464}
1465
1466static void ath10k_htt_rx_delba(struct ath10k *ar, struct htt_resp *resp)
1467{
1468 struct htt_rx_delba *ev = &resp->rx_delba;
1469 struct ath10k_peer *peer;
1470 struct ath10k_vif *arvif;
1471 u16 info0, tid, peer_id;
1472
1473 info0 = __le16_to_cpu(ev->info0);
1474 tid = MS(info0, HTT_RX_BA_INFO0_TID);
1475 peer_id = MS(info0, HTT_RX_BA_INFO0_PEER_ID);
1476
1477 ath10k_dbg(ATH10K_DBG_HTT,
1478 "htt rx delba tid %hu peer_id %hu\n",
1479 tid, peer_id);
1480
1481 spin_lock_bh(&ar->data_lock);
1482 peer = ath10k_peer_find_by_id(ar, peer_id);
1483 if (!peer) {
1484 ath10k_warn("received addba event for invalid peer_id: %hu\n",
1485 peer_id);
1486 spin_unlock_bh(&ar->data_lock);
1487 return;
1488 }
1489
1490 arvif = ath10k_get_arvif(ar, peer->vdev_id);
1491 if (!arvif) {
1492 ath10k_warn("received addba event for invalid vdev_id: %u\n",
1493 peer->vdev_id);
1494 spin_unlock_bh(&ar->data_lock);
1495 return;
1496 }
1497
1498 ath10k_dbg(ATH10K_DBG_HTT,
1499 "htt rx stop rx ba session sta %pM tid %hu\n",
1500 peer->addr, tid);
1501
1502 ieee80211_stop_rx_ba_session_offl(arvif->vif, peer->addr, tid);
1503 spin_unlock_bh(&ar->data_lock);
1504}
1505
1425void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) 1506void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
1426{ 1507{
1427 struct ath10k_htt *htt = &ar->htt; 1508 struct ath10k_htt *htt = &ar->htt;
@@ -1524,8 +1605,17 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
1524 ath10k_warn("received an unexpected htt tx inspect event\n"); 1605 ath10k_warn("received an unexpected htt tx inspect event\n");
1525 break; 1606 break;
1526 case HTT_T2H_MSG_TYPE_RX_ADDBA: 1607 case HTT_T2H_MSG_TYPE_RX_ADDBA:
1608 ath10k_htt_rx_addba(ar, resp);
1609 break;
1527 case HTT_T2H_MSG_TYPE_RX_DELBA: 1610 case HTT_T2H_MSG_TYPE_RX_DELBA:
1528 case HTT_T2H_MSG_TYPE_RX_FLUSH: 1611 ath10k_htt_rx_delba(ar, resp);
1612 break;
1613 case HTT_T2H_MSG_TYPE_RX_FLUSH: {
1614 /* Ignore this event because mac80211 takes care of Rx
1615 * aggregation reordering.
1616 */
1617 break;
1618 }
1529 default: 1619 default:
1530 ath10k_dbg(ATH10K_DBG_HTT, "htt event (%d) not handled\n", 1620 ath10k_dbg(ATH10K_DBG_HTT, "htt event (%d) not handled\n",
1531 resp->hdr.msg_type); 1621 resp->hdr.msg_type);
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 3f9afaa93cca..3baa22915339 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -4333,6 +4333,38 @@ static u64 ath10k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
4333 return 0; 4333 return 0;
4334} 4334}
4335 4335
4336static int ath10k_ampdu_action(struct ieee80211_hw *hw,
4337 struct ieee80211_vif *vif,
4338 enum ieee80211_ampdu_mlme_action action,
4339 struct ieee80211_sta *sta, u16 tid, u16 *ssn,
4340 u8 buf_size)
4341{
4342 struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
4343
4344 ath10k_dbg(ATH10K_DBG_MAC, "mac ampdu vdev_id %i sta %pM tid %hu action %d\n",
4345 arvif->vdev_id, sta->addr, tid, action);
4346
4347 switch (action) {
4348 case IEEE80211_AMPDU_RX_START:
4349 case IEEE80211_AMPDU_RX_STOP:
4350 /* HTT AddBa/DelBa events trigger mac80211 Rx BA session
4351 * creation/removal. Do we need to verify this?
4352 */
4353 return 0;
4354 case IEEE80211_AMPDU_TX_START:
4355 case IEEE80211_AMPDU_TX_STOP_CONT:
4356 case IEEE80211_AMPDU_TX_STOP_FLUSH:
4357 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
4358 case IEEE80211_AMPDU_TX_OPERATIONAL:
4359 /* Firmware offloads Tx aggregation entirely so deny mac80211
4360 * Tx aggregation requests.
4361 */
4362 return -EOPNOTSUPP;
4363 }
4364
4365 return -EINVAL;
4366}
4367
4336static const struct ieee80211_ops ath10k_ops = { 4368static const struct ieee80211_ops ath10k_ops = {
4337 .tx = ath10k_tx, 4369 .tx = ath10k_tx,
4338 .start = ath10k_start, 4370 .start = ath10k_start,
@@ -4360,6 +4392,7 @@ static const struct ieee80211_ops ath10k_ops = {
4360 .set_bitrate_mask = ath10k_set_bitrate_mask, 4392 .set_bitrate_mask = ath10k_set_bitrate_mask,
4361 .sta_rc_update = ath10k_sta_rc_update, 4393 .sta_rc_update = ath10k_sta_rc_update,
4362 .get_tsf = ath10k_get_tsf, 4394 .get_tsf = ath10k_get_tsf,
4395 .ampdu_action = ath10k_ampdu_action,
4363#ifdef CONFIG_PM 4396#ifdef CONFIG_PM
4364 .suspend = ath10k_suspend, 4397 .suspend = ath10k_suspend,
4365 .resume = ath10k_resume, 4398 .resume = ath10k_resume,
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c
index 82669a77e553..f4fa22d1d591 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -119,8 +119,7 @@ struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
119 return NULL; 119 return NULL;
120} 120}
121 121
122static struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar, 122struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar, int peer_id)
123 int peer_id)
124{ 123{
125 struct ath10k_peer *peer; 124 struct ath10k_peer *peer;
126 125
diff --git a/drivers/net/wireless/ath/ath10k/txrx.h b/drivers/net/wireless/ath/ath10k/txrx.h
index aee3e20058f8..a90e09f5c7f2 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.h
+++ b/drivers/net/wireless/ath/ath10k/txrx.h
@@ -24,6 +24,7 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
24 24
25struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id, 25struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
26 const u8 *addr); 26 const u8 *addr);
27struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar, int peer_id);
27int ath10k_wait_for_peer_created(struct ath10k *ar, int vdev_id, 28int ath10k_wait_for_peer_created(struct ath10k *ar, int vdev_id,
28 const u8 *addr); 29 const u8 *addr);
29int ath10k_wait_for_peer_deleted(struct ath10k *ar, int vdev_id, 30int ath10k_wait_for_peer_deleted(struct ath10k *ar, int vdev_id,