diff options
author | Michal Kazior <michal.kazior@tieto.com> | 2014-07-23 06:20:33 -0400 |
---|---|---|
committer | Kalle Valo <kvalo@qca.qualcomm.com> | 2014-07-25 04:15:39 -0400 |
commit | aa5b4fbcff48234280359da84ac24e6f3057325b (patch) | |
tree | 443d18d669afdc562b5863685dda3c5f220c7a6b /drivers/net/wireless | |
parent | 30d88ce331d566f496fe7bea25ee560dcfd253ae (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.c | 92 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/mac.c | 33 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/txrx.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/txrx.h | 1 |
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 | ||
1426 | static 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 | |||
1466 | static 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 | |||
1425 | void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) | 1506 | void 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 | ||
4336 | static 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 | |||
4336 | static const struct ieee80211_ops ath10k_ops = { | 4368 | static 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 | ||
122 | static struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar, | 122 | struct 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 | ||
25 | struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id, | 25 | struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id, |
26 | const u8 *addr); | 26 | const u8 *addr); |
27 | struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar, int peer_id); | ||
27 | int ath10k_wait_for_peer_created(struct ath10k *ar, int vdev_id, | 28 | int ath10k_wait_for_peer_created(struct ath10k *ar, int vdev_id, |
28 | const u8 *addr); | 29 | const u8 *addr); |
29 | int ath10k_wait_for_peer_deleted(struct ath10k *ar, int vdev_id, | 30 | int ath10k_wait_for_peer_deleted(struct ath10k *ar, int vdev_id, |