summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/wcn36xx/smd.c
diff options
context:
space:
mode:
authorLoic Poulain <loic.poulain@linaro.org>2021-11-22 19:04:11 +0100
committerKalle Valo <kvalo@codeaurora.org>2021-11-26 12:19:28 +0200
commit23cddeb5a7705daf305f02bd01ff73598ebd6461 (patch)
treeb434e77e7b172ac5c59d378347a9b3dfbd9d88f7 /drivers/net/wireless/ath/wcn36xx/smd.c
parentb689f091aafd1a874b2f88137934276ab0fca480 (diff)
wcn36xx: Use correct SSN for ADD BA request
Since firmware uses its own sequence number counters, we need to use firmware number as well when mac80211 generates the ADD_BA request packet. Indeed the firmware sequence counters tend to slightly drift from the mac80211 ones because of firmware offload features like ARP responses. This causes the starting sequence number field of the ADD_BA request to be unaligned, and can possibly cause issues with strict/picky APs. To fix this, we retrieve the current firmware sequence number for a given TID through the smd_trigger_ba API, and use that number as replacement of the mac80211 starting sequence number. This change also ensures that any issue in the smd *ba procedures will cause the ba action to properly fail, and remove useless call to smd_trigger_ba() from IEEE80211_AMPDU_RX_START. Signed-off-by: Loic Poulain <loic.poulain@linaro.org> Signed-off-by: Kalle Valo <kvalo@codeaurora.org> Link: https://lore.kernel.org/r/1637604251-11763-1-git-send-email-loic.poulain@linaro.org
Diffstat (limited to 'drivers/net/wireless/ath/wcn36xx/smd.c')
-rw-r--r--drivers/net/wireless/ath/wcn36xx/smd.c29
1 files changed, 25 insertions, 4 deletions
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c
index d3285a504429..eb7493e2c958 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -2561,6 +2561,7 @@ int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn,
&session_id);
if (ret) {
wcn36xx_err("hal_add_ba_session response failed err=%d\n", ret);
+ ret = -EINVAL;
goto out;
}
@@ -2626,27 +2627,43 @@ out:
return ret;
}
-static int wcn36xx_smd_trigger_ba_rsp(void *buf, int len)
+static int wcn36xx_smd_trigger_ba_rsp(void *buf, int len, struct add_ba_info *ba_info)
{
+ struct wcn36xx_hal_trigger_ba_rsp_candidate *candidate;
struct wcn36xx_hal_trigger_ba_rsp_msg *rsp;
+ int i;
if (len < sizeof(*rsp))
return -EINVAL;
rsp = (struct wcn36xx_hal_trigger_ba_rsp_msg *) buf;
+
+ if (rsp->candidate_cnt < 1)
+ return rsp->status ? rsp->status : -EINVAL;
+
+ candidate = (struct wcn36xx_hal_trigger_ba_rsp_candidate *)(buf + sizeof(*rsp));
+
+ for (i = 0; i < STACFG_MAX_TC; i++) {
+ ba_info[i] = candidate->ba_info[i];
+ }
+
return rsp->status;
}
-int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index, u16 tid, u8 session_id)
+int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index, u16 tid, u16 *ssn)
{
struct wcn36xx_hal_trigger_ba_req_msg msg_body;
struct wcn36xx_hal_trigger_ba_req_candidate *candidate;
+ struct add_ba_info ba_info[STACFG_MAX_TC];
int ret;
+ if (tid >= STACFG_MAX_TC)
+ return -EINVAL;
+
mutex_lock(&wcn->hal_mutex);
INIT_HAL_MSG(msg_body, WCN36XX_HAL_TRIGGER_BA_REQ);
- msg_body.session_id = session_id;
+ msg_body.session_id = 0; /* not really used */
msg_body.candidate_cnt = 1;
msg_body.header.len += sizeof(*candidate);
PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
@@ -2661,13 +2678,17 @@ int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index, u16 tid, u8 sessio
wcn36xx_err("Sending hal_trigger_ba failed\n");
goto out;
}
- ret = wcn36xx_smd_trigger_ba_rsp(wcn->hal_buf, wcn->hal_rsp_len);
+ ret = wcn36xx_smd_trigger_ba_rsp(wcn->hal_buf, wcn->hal_rsp_len, ba_info);
if (ret) {
wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret);
goto out;
}
out:
mutex_unlock(&wcn->hal_mutex);
+
+ if (ssn)
+ *ssn = ba_info[tid].starting_seq_num;
+
return ret;
}