[PATCH 1/3] Implement AMPDU

Eugene Krasnikov k.eugene.e at gmail.com
Tue Jul 23 10:45:52 EDT 2013


Declare that wcn36xx supports AMPDU. Configure HW with add_ba_session
and add_ba when session is established and delete it with
wcn36xx_smd_del_ba.

Signed-off-by: Eugene Krasnikov <k.eugene.e at gmail.com>
---
 hal.h     | 44 +++++++++++++++++------------------
 main.c    | 39 ++++++++++++++++++++++++++++++++
 smd.c     | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 smd.h     |  9 ++++++++
 wcn36xx.h |  1 +
 5 files changed, 149 insertions(+), 22 deletions(-)

diff --git a/hal.h b/hal.h
index edc6dfa..e45f8b1 100644
--- a/hal.h
+++ b/hal.h
@@ -2418,7 +2418,7 @@ struct del_ts_rsp_msg {
 
 /* Start of BLOCK ACK related Parameters */
 
-struct add_ba_session_req_msg {
+struct wcn36xx_hal_add_ba_session_req_msg {
 	struct wcn36xx_hal_msg_header header;
 
 	/* Station Index */
@@ -2459,9 +2459,9 @@ struct add_ba_session_req_msg {
 	   1 - Originator
 	   0 - Recipient */
 	u8 direction;
-};
+} __packed;
 
-struct add_ba_session_rsp_msg {
+struct wcn36xx_hal_add_ba_session_rsp_msg {
 	struct wcn36xx_hal_msg_header header;
 
 	/* success or failure */
@@ -2486,23 +2486,23 @@ struct add_ba_session_rsp_msg {
 
 	/* Starting Sequence Number */
 	u16 ssn;
-};
+} __packed;
 
-struct add_ba_req_msg {
+struct wcn36xx_hal_add_ba_req_msg {
 	struct wcn36xx_hal_msg_header header;
 
 	/* Session Id */
 	u8 session_id;
 
 	/* Reorder Window Size */
-	u8 win_Size;
-
+	u8 win_size;
+/* Old FW 1.2.2.4 does not support this*/
 #ifdef FEATURE_ON_CHIP_REORDERING
 	u8 reordering_done_on_chip;
 #endif
-};
+} __packed;
 
-struct add_ba_rsp_msg {
+struct wcn36xx_hal_add_ba_rsp_msg {
 	struct wcn36xx_hal_msg_header header;
 
 	/* success or failure */
@@ -2510,7 +2510,7 @@ struct add_ba_rsp_msg {
 
 	/* Dialog token */
 	u8 dialog_token;
-};
+} __packed;
 
 struct add_ba_info {
 	u16 ba_enable:1;
@@ -2518,17 +2518,17 @@ struct add_ba_info {
 	u16 reserved:3;
 };
 
-struct trigger_ba_rsp_candidate {
+struct wcn36xx_hal_trigger_ba_rsp_candidate {
 	u8 sta_addr[ETH_ALEN];
 	struct add_ba_info ba_info[STACFG_MAX_TC];
-};
+} __packed;
 
-struct trigget_ba_req_candidate {
+struct wcn36xx_hal_trigget_ba_req_candidate {
 	u8 sta_index;
 	u8 tid_bitmap;
-};
+} __packed;
 
-struct trigger_ba_req_msg {
+struct wcn36xx_hal_trigger_ba_req_msg {
 	struct wcn36xx_hal_msg_header header;
 
 	/* Session Id */
@@ -2539,9 +2539,9 @@ struct trigger_ba_req_msg {
 	 */
 	u16 candidate_cnt;
 
-};
+} __packed;
 
-struct trigger_ba_rsp_msg {
+struct wcn36xx_hal_trigger_ba_rsp_msg {
 	struct wcn36xx_hal_msg_header header;
 
 	/* TO SUPPORT BT-AMP */
@@ -2554,9 +2554,9 @@ struct trigger_ba_rsp_msg {
 	 * Rsp Candidate List(tTriggerRspBaCandidate)
 	 */
 	u16 candidate_cnt;
-};
+} __packed;
 
-struct del_ba_req_msg {
+struct wcn36xx_hal_del_ba_req_msg {
 	struct wcn36xx_hal_msg_header header;
 
 	/* Station Index */
@@ -2569,14 +2569,14 @@ struct del_ba_req_msg {
 	   1 - Originator
 	   0 - Recipient */
 	u8 direction;
-};
+} __packed;
 
-struct del_ba_rsp_msg {
+struct wcn36xx_hal_del_ba_rsp_msg {
 	struct wcn36xx_hal_msg_header header;
 
 	/* success or failure */
 	u32 status;
-};
+} __packed;
 
 struct tsm_stats_req_msg {
 	struct wcn36xx_hal_msg_header header;
diff --git a/main.c b/main.c
index 5f95379..c824fce 100644
--- a/main.c
+++ b/main.c
@@ -751,6 +751,43 @@ static int wcn36xx_resume(struct ieee80211_hw *hw)
 }
 #endif
 
+int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
+		    struct ieee80211_vif *vif,
+		    enum ieee80211_ampdu_mlme_action action,
+		    struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+		    u8 buf_size)
+{
+	struct wcn36xx *wcn = hw->priv;
+
+	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d",
+		    action, tid);
+	switch (action) {
+	case IEEE80211_AMPDU_RX_START:
+		wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 0);
+		wcn36xx_smd_add_ba(wcn);
+		wcn36xx_smd_trigger_ba(wcn);
+		ieee80211_start_tx_ba_session(sta, tid, 0);
+		break;
+	case IEEE80211_AMPDU_RX_STOP:
+		wcn36xx_smd_del_ba(wcn, tid);
+		break;
+	case IEEE80211_AMPDU_TX_START:
+		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+		break;
+	case IEEE80211_AMPDU_TX_OPERATIONAL:
+		wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 1);
+		break;
+	/* Not supported so far*/
+	case IEEE80211_AMPDU_TX_STOP_CONT:
+		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+		break;
+	case IEEE80211_AMPDU_TX_STOP_FLUSH:
+	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
+		break;
+	}
+	return 0;
+}
+
 static const struct ieee80211_ops wcn36xx_ops = {
 	.start			= wcn36xx_start,
 	.stop			= wcn36xx_stop,
@@ -771,6 +808,7 @@ static const struct ieee80211_ops wcn36xx_ops = {
 	.set_rts_threshold	= wcn36xx_set_rts_threshold,
 	.sta_add		= wcn36xx_sta_add,
 	.sta_remove		= wcn36xx_sta_remove,
+	.ampdu_action		= wcn36xx_ampdu_action,
 };
 
 static struct ieee80211_hw *wcn36xx_alloc_hw(void)
@@ -794,6 +832,7 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
 		IEEE80211_HW_HAS_RATE_CONTROL |
 		IEEE80211_HW_SUPPORTS_PS |
 		IEEE80211_HW_CONNECTION_MONITOR |
+		IEEE80211_HW_AMPDU_AGGREGATION |
 		IEEE80211_HW_TIMING_BEACON_ONLY;
 
 	wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
diff --git a/smd.c b/smd.c
index 991a70b..46b9a0c 100644
--- a/smd.c
+++ b/smd.c
@@ -1241,6 +1241,80 @@ int wcn36xx_smd_feature_caps_exchange_rsp(void *buf, size_t len)
 	return 0;
 }
 
+int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn,
+		struct ieee80211_sta *sta,
+		u16 tid,
+		u16 *ssn,
+		u8 direction)
+{
+	struct wcn36xx_hal_add_ba_session_req_msg msg_body;
+
+	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_SESSION_REQ);
+
+	msg_body.sta_index = wcn->current_vif->sta_index;
+	memcpy(&msg_body.mac_addr, sta->addr, ETH_ALEN);
+	msg_body.dialog_token = 0x10;
+	msg_body.tid = tid;
+
+	/*Immediate BA because Delayed BA is not supported*/
+	msg_body.policy = 1;
+	msg_body.buffer_size = WCN36XX_AGGR_BUFFER_SIZE;
+	msg_body.timeout = 0;
+	if (ssn)
+		msg_body.ssn = *ssn;
+	msg_body.direction = direction;
+
+	PREPARE_HAL_BUF(wcn->smd_buf, msg_body);
+
+	return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
+}
+int wcn36xx_smd_add_ba(struct wcn36xx *wcn)
+{
+	struct wcn36xx_hal_add_ba_req_msg msg_body;
+
+	INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_REQ);
+
+	msg_body.session_id = 0;
+	msg_body.win_size = WCN36XX_AGGR_BUFFER_SIZE;
+
+	PREPARE_HAL_BUF(wcn->smd_buf, msg_body);
+
+	return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
+}
+
+int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid)
+{
+	struct wcn36xx_hal_del_ba_req_msg msg_body;
+
+	INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_BA_REQ);
+
+	msg_body.sta_index = wcn->current_vif->sta_index;
+	msg_body.tid = tid;
+	msg_body.direction = 0;
+	PREPARE_HAL_BUF(wcn->smd_buf, msg_body);
+
+	return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
+}
+
+int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn)
+{
+	struct wcn36xx_hal_trigger_ba_req_msg msg_body;
+	struct wcn36xx_hal_trigget_ba_req_candidate *candidate;
+
+	INIT_HAL_MSG(msg_body, WCN36XX_HAL_TRIGGER_BA_REQ);
+
+	msg_body.session_id = 0;
+	msg_body.candidate_cnt = 1;
+	msg_body.header.len += sizeof(*candidate);
+	PREPARE_HAL_BUF(wcn->smd_buf, msg_body);
+
+	candidate = (struct wcn36xx_hal_trigget_ba_req_candidate *)
+		(wcn->smd_buf + sizeof(msg_body));
+	candidate->sta_index = wcn->current_vif->sta_index;
+	candidate->tid_bitmap = 1;
+	return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
+}
+
 static void wcn36xx_smd_notify(void *data, unsigned event)
 {
 	struct wcn36xx *wcn = (struct wcn36xx *)data;
@@ -1341,6 +1415,10 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
 	case WCN36XX_HAL_EXIT_BMPS_RSP:
 	case WCN36XX_HAL_KEEP_ALIVE_RSP:
 	case WCN36XX_HAL_DUMP_COMMAND_RSP:
+	case WCN36XX_HAL_ADD_BA_SESSION_RSP:
+	case WCN36XX_HAL_ADD_BA_RSP:
+	case WCN36XX_HAL_DEL_BA_RSP:
+	case WCN36XX_HAL_TRIGGER_BA_RSP:
 		if (wcn36xx_smd_rsp_status_check(buf, len)) {
 			wcn36xx_warn("error response from hal request %d",
 				     msg_header->msg_type);
diff --git a/smd.h b/smd.h
index 935936d..1faf08b 100644
--- a/smd.h
+++ b/smd.h
@@ -94,6 +94,15 @@ int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn, int packet_type);
 int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2,
 			     u32 arg3, u32 arg4, u32 arg5);
 int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn);
+
+int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn,
+		struct ieee80211_sta *sta,
+		u16 tid,
+		u16 *ssn,
+		u8 direction);
+int wcn36xx_smd_add_ba(struct wcn36xx *wcn);
+int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid);
+int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn);
 /* WCN36XX configuration parameters */
 struct wcn36xx_fw_cfg {
 	u16		id;
diff --git a/wcn36xx.h b/wcn36xx.h
index b0d7704..f5652a7 100644
--- a/wcn36xx.h
+++ b/wcn36xx.h
@@ -34,6 +34,7 @@
 #define DRIVER_PREFIX "wcn36xx: "
 #define WLAN_NV_FILE               "wlan/prima/WCNSS_qcom_wlan_nv.bin"
 #define MAC_ADDR_0 "wlan/macaddr0"
+#define WCN36XX_AGGR_BUFFER_SIZE 64
 
 extern unsigned int debug_mask;
 
-- 
1.8.2.2




More information about the wcn36xx mailing list