summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/wcn36xx/txrx.c
diff options
context:
space:
mode:
authorLoic Poulain <loic.poulain@linaro.org>2020-07-24 12:20:48 +0200
committerKalle Valo <kvalo@codeaurora.org>2020-08-14 18:02:19 +0300
commitfdf21cc3714939dd4327f3d664fe5863d15ccb31 (patch)
treeb293f02ddb3ba0c7d38af6b1f403092b2507acfa /drivers/net/wireless/ath/wcn36xx/txrx.c
parentffe835aa5bdb33572fceb0b14cba6a44c3371bdd (diff)
wcn36xx: Add TX ack support
The controller is capable of reporting TX indication which can be used to report TX ack when IEEE80211_TX_CTL_REQ_TX_STATUS is set. The support was only partially implemented. The firmware can be configured for reporting event when a packet is acked, without specifying which packet though. In order to send a packet flagged with TX status callback, we need to stop the queue, submit the packet and wait for the firmware ack event. Then the queue can be restarted and mac80211 status callback called. In case the packet is not acked, no ack event will be received, therefore a timeout mechanism is introduced to restart the queue and call the status cb in case no event is received after a 100ms. Signed-off-by: Loic Poulain <loic.poulain@linaro.org> Signed-off-by: Kalle Valo <kvalo@codeaurora.org> Link: https://lore.kernel.org/r/1595586052-16081-3-git-send-email-loic.poulain@linaro.org
Diffstat (limited to 'drivers/net/wireless/ath/wcn36xx/txrx.c')
-rw-r--r--drivers/net/wireless/ath/wcn36xx/txrx.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.c b/drivers/net/wireless/ath/wcn36xx/txrx.c
index dda6d8946aef..0a418ac30765 100644
--- a/drivers/net/wireless/ath/wcn36xx/txrx.c
+++ b/drivers/net/wireless/ath/wcn36xx/txrx.c
@@ -298,9 +298,10 @@ static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd,
bd->dpu_sign = __vif_priv->self_ucast_dpu_sign;
}
- if (ieee80211_is_nullfunc(hdr->frame_control) ||
- (sta_priv && !sta_priv->is_data_encrypted))
+ if (ieee80211_is_any_nullfunc(hdr->frame_control) ||
+ (sta_priv && !sta_priv->is_data_encrypted)) {
bd->dpu_ne = 1;
+ }
if (bcast) {
bd->ub = 1;
@@ -394,9 +395,9 @@ int wcn36xx_start_tx(struct wcn36xx *wcn,
bd.dpu_rf = WCN36XX_BMU_WQ_TX;
- bd.tx_comp = !!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS);
- if (bd.tx_comp) {
+ if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) {
wcn36xx_dbg(WCN36XX_DBG_DXE, "TX_ACK status requested\n");
+
spin_lock_irqsave(&wcn->dxe_lock, flags);
if (wcn->tx_ack_skb) {
spin_unlock_irqrestore(&wcn->dxe_lock, flags);
@@ -409,10 +410,15 @@ int wcn36xx_start_tx(struct wcn36xx *wcn,
/* Only one at a time is supported by fw. Stop the TX queues
* until the ack status gets back.
- *
- * TODO: Add watchdog in case FW does not answer
*/
ieee80211_stop_queues(wcn->hw);
+
+ /* TX watchdog if no TX irq or ack indication received */
+ mod_timer(&wcn->tx_ack_timer, jiffies + HZ / 10);
+
+ /* Request ack indication from the firmware */
+ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
+ bd.tx_comp = 1;
}
/* Data frames served first*/
@@ -426,7 +432,7 @@ int wcn36xx_start_tx(struct wcn36xx *wcn,
bd.tx_bd_sign = 0xbdbdbdbd;
ret = wcn36xx_dxe_tx_frame(wcn, vif_priv, &bd, skb, is_low);
- if (ret && bd.tx_comp) {
+ if (ret && (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) {
/* If the skb has not been transmitted,
* don't keep a reference to it.
*/