Jelajahi Sumber

qcacmn: Add host data path functions for TDLS

Add and enable host data path functions for Napier
TDLS.

Change-Id: I228c2dcf4e8d797d173007a3306d112aca5ba52f
CRs-Fixed: 2114813
Kabilan Kannan 7 tahun lalu
induk
melakukan
60e3b3062d

+ 1 - 1
dp/inc/cdp_txrx_cmn_struct.h

@@ -295,7 +295,7 @@ typedef void
 (*ol_txrx_mgmt_tx_cb)(void *ctxt, qdf_nbuf_t tx_mgmt_frm, int had_error);
 
 /**
- * ol_rxrx_data_tx_cb - Function registered with the data path
+ * ol_txrx_data_tx_cb - Function registered with the data path
  * that is called when tx frames marked as "no free" are
  * done being transmitted
  */

+ 19 - 0
dp/wifi3.0/dp_main.c

@@ -5119,6 +5119,23 @@ static inline void dp_peer_delete_ast_entries(struct dp_soc *soc,
 }
 #endif
 
+/*
+ * dp_txrx_data_tx_cb_set(): set the callback for non standard tx
+ * @vdev_handle - datapath vdev handle
+ * @callback - callback function
+ * @ctxt: callback context
+ *
+ */
+static void
+dp_txrx_data_tx_cb_set(struct cdp_vdev *vdev_handle,
+		       ol_txrx_data_tx_cb callback, void *ctxt)
+{
+	struct dp_vdev *vdev = (struct dp_vdev *)vdev_handle;
+
+	vdev->tx_non_std_data_callback.func = callback;
+	vdev->tx_non_std_data_callback.ctxt = ctxt;
+}
+
 #ifdef CONFIG_WIN
 static void dp_peer_teardown_wifi3(struct cdp_vdev *vdev_hdl, void *peer_hdl)
 {
@@ -5170,6 +5187,7 @@ static struct cdp_cmn_ops dp_ops_cmn = {
 	.txrx_intr_detach = dp_soc_interrupt_detach,
 	.set_pn_check = dp_set_pn_check_wifi3,
 	/* TODO: Add other functions */
+	.txrx_data_tx_cb_set = dp_txrx_data_tx_cb_set
 };
 
 static struct cdp_ctrl_ops dp_ops_ctrl = {
@@ -5309,6 +5327,7 @@ static QDF_STATUS dp_bus_resume(struct cdp_pdev *opaque_pdev)
 
 #ifndef CONFIG_WIN
 static struct cdp_misc_ops dp_ops_misc = {
+	.tx_non_std = dp_tx_non_std,
 	.get_opmode = dp_get_opmode,
 #ifdef FEATURE_RUNTIME_PM
 	.runtime_suspend = dp_runtime_suspend,

+ 66 - 0
dp/wifi3.0/dp_tx.c

@@ -986,6 +986,46 @@ static void dp_tx_classify_tid(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
 	return;
 }
 
+#ifdef CONVERGED_TDLS_ENABLE
+/**
+ * dp_tx_update_tdls_flags() - Update descriptor flags for TDLS frame
+ * @tx_desc: TX descriptor
+ *
+ * Return: None
+ */
+static void dp_tx_update_tdls_flags(struct dp_tx_desc_s *tx_desc)
+{
+	if (tx_desc->vdev) {
+		if (tx_desc->vdev->is_tdls_frame)
+			tx_desc->flags |= DP_TX_DESC_FLAG_TDLS_FRAME;
+			tx_desc->vdev->is_tdls_frame = false;
+	}
+}
+
+/**
+ * dp_non_std_tx_comp_free_buff() - Free the non std tx packet buffer
+ * @tx_desc: TX descriptor
+ * @vdev: datapath vdev handle
+ *
+ * Return: None
+ */
+static void dp_non_std_tx_comp_free_buff(struct dp_tx_desc_s *tx_desc,
+				  struct dp_vdev *vdev)
+{
+	struct hal_tx_completion_status ts = {0};
+	qdf_nbuf_t nbuf = tx_desc->nbuf;
+
+	hal_tx_comp_get_status(&tx_desc->comp, &ts);
+	if (vdev->tx_non_std_data_callback.func) {
+		qdf_nbuf_set_next(tx_desc->nbuf, NULL);
+		vdev->tx_non_std_data_callback.func(
+				vdev->tx_non_std_data_callback.ctxt,
+				nbuf, ts.status);
+		return;
+	}
+}
+#endif
+
 /**
  * dp_tx_send_msdu_single() - Setup descriptor and enqueue single MSDU to TCL
  * @vdev: DP vdev handle
@@ -1018,6 +1058,8 @@ static qdf_nbuf_t dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
 		return nbuf;
 	}
 
+	dp_tx_update_tdls_flags(tx_desc);
+
 	if (qdf_unlikely(hal_srng_access_start(soc->hal_soc, hal_srng))) {
 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
 				"%s %d : HAL RING Access Failed -- %pK\n",
@@ -1702,6 +1744,10 @@ static inline void dp_tx_comp_free_buf(struct dp_soc *soc,
 	struct dp_vdev *vdev = desc->vdev;
 	qdf_nbuf_t nbuf = desc->nbuf;
 
+	/* If it is TDLS mgmt, don't unmap or free the frame */
+	if (desc->flags & DP_TX_DESC_FLAG_TDLS_FRAME)
+		return dp_non_std_tx_comp_free_buff(desc, vdev);
+
 	/* 0 : MSDU buffer, 1 : MLE */
 	if (desc->msdu_ext_desc) {
 		/* TSO free */
@@ -2226,6 +2272,26 @@ uint32_t dp_tx_comp_handler(struct dp_soc *soc, void *hal_srng, uint32_t quota)
 	return num_processed;
 }
 
+/**
+ * dp_tx_non_std() - Allow the control-path SW to send data frames
+ *
+ * @data_vdev - which vdev should transmit the tx data frames
+ * @tx_spec - what non-standard handling to apply to the tx data frames
+ * @msdu_list - NULL-terminated list of tx MSDUs
+ *
+ * Return: NULL on success,
+ *         nbuf when it fails to send
+ */
+qdf_nbuf_t dp_tx_non_std(struct cdp_vdev *vdev_handle,
+		enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list)
+{
+	struct dp_vdev *vdev = (struct dp_vdev *) vdev_handle;
+
+	if (tx_spec & OL_TX_SPEC_NO_FREE)
+		vdev->is_tdls_frame = true;
+	return dp_tx_send(vdev_handle, msdu_list);
+}
+
 /**
  * dp_tx_vdev_attach() - attach vdev to dp tx
  * @vdev: virtual device instance

+ 22 - 2
dp/wifi3.0/dp_tx.h

@@ -30,9 +30,10 @@
 #define DP_TX_DESC_FLAG_FRAG		0x4
 #define DP_TX_DESC_FLAG_RAW		0x8
 #define DP_TX_DESC_FLAG_MESH		0x10
-#define DP_TX_DESC_FLAG_QUEUED_TX		0x20
-#define DP_TX_DESC_FLAG_COMPLETED_TX		0x40
+#define DP_TX_DESC_FLAG_QUEUED_TX	0x20
+#define DP_TX_DESC_FLAG_COMPLETED_TX	0x40
 #define DP_TX_DESC_FLAG_ME		0x80
+#define DP_TX_DESC_FLAG_TDLS_FRAME	0x100
 
 #define DP_TX_FREE_SINGLE_BUF(soc, buf)                  \
 do {                                                           \
@@ -143,11 +144,30 @@ QDF_STATUS dp_tx_pdev_attach(struct dp_pdev *pdev);
 
 qdf_nbuf_t dp_tx_send(void *data_vdev, qdf_nbuf_t nbuf);
 
+qdf_nbuf_t dp_tx_non_std(struct cdp_vdev *vdev_handle,
+		enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list);
+
 uint32_t dp_tx_comp_handler(struct dp_soc *soc, void *hal_srng, uint32_t quota);
 
 int32_t
 dp_tx_prepare_send_me(struct dp_vdev *vdev, qdf_nbuf_t nbuf);
 
+#ifndef CONVERGED_TDLS_ENABLE
+
+static inline void dp_tx_update_tdls_flags(struct dp_tx_desc_s *tx_desc)
+{
+	return;
+}
+
+static inline void dp_non_std_tx_comp_free_buff(struct dp_tx_desc_s *tx_desc,
+				  struct dp_vdev *vdev)
+{
+	return;
+}
+
+#endif
+
+
 
 #ifdef FEATURE_WDS
 void dp_tx_mec_handler(struct dp_vdev *vdev, uint8_t *status);

+ 10 - 1
dp/wifi3.0/dp_types.h

@@ -247,7 +247,7 @@ struct dp_tx_desc_s {
 	struct dp_vdev *vdev;
 	struct dp_pdev *pdev;
 	uint8_t  pool_id;
-	uint8_t flags;
+	uint16_t flags;
 	struct hal_tx_desc_comp_s comp;
 	uint16_t tx_encap_type;
 	uint8_t frm_type;
@@ -1102,6 +1102,13 @@ struct dp_vdev {
 		void *context;
 	} delete;
 
+	/* tx data delivery notification callback function */
+	struct {
+		ol_txrx_data_tx_cb func;
+		void *ctxt;
+	} tx_non_std_data_callback;
+
+
 	/* safe mode control to bypass the encrypt and decipher process*/
 	uint32_t safemode;
 
@@ -1113,6 +1120,8 @@ struct dp_vdev {
 #endif
 	/* TDLS Link status */
 	bool tdls_link_connected;
+	bool is_tdls_frame;
+
 
 	/* VDEV operating mode */
 	enum wlan_op_mode opmode;

+ 33 - 2
umac/tdls/core/src/wlan_tdls_cmds_process.c

@@ -1133,6 +1133,10 @@ QDF_STATUS tdls_process_del_peer(struct tdls_oper_request *req)
 	struct wlan_serialization_command cmd = {0,};
 	enum wlan_serialization_status ser_cmd_status;
 	struct wlan_objmgr_vdev *vdev;
+	struct tdls_vdev_priv_obj *vdev_obj;
+	struct tdls_soc_priv_obj *soc_obj;
+	uint8_t *mac;
+	struct tdls_peer *peer;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
 	if (!req || !req->vdev) {
@@ -1140,7 +1144,35 @@ QDF_STATUS tdls_process_del_peer(struct tdls_oper_request *req)
 		status = QDF_STATUS_E_INVAL;
 		goto error;
 	}
+
 	vdev = req->vdev;
+
+	/* vdev reference cnt is acquired in ucfg_tdls_oper */
+	vdev_obj = wlan_vdev_get_tdls_vdev_obj(vdev);
+	soc_obj = wlan_vdev_get_tdls_soc_obj(vdev);
+
+	if (!vdev_obj || !soc_obj) {
+		tdls_err("tdls vdev_obj: %p soc_obj: %p", vdev_obj, soc_obj);
+		status = QDF_STATUS_E_NULL_VALUE;
+		goto error;
+	}
+
+	mac = req->peer_addr;
+	peer = tdls_find_peer(vdev_obj, mac);
+	if (!peer) {
+		tdls_err(QDF_MAC_ADDRESS_STR
+			 " not found, ignore NL80211_TDLS_ENABLE_LINK",
+			 QDF_MAC_ADDR_ARRAY(mac));
+		status = QDF_STATUS_E_INVAL;
+		goto error;
+	}
+
+	if (soc_obj->tdls_dp_vdev_update)
+		soc_obj->tdls_dp_vdev_update(&soc_obj->soc,
+					peer->sta_id,
+					soc_obj->tdls_update_dp_vdev_flags,
+					false);
+
 	cmd.cmd_type = WLAN_SER_CMD_TDLS_DEL_PEER;
 	cmd.cmd_id = 0;
 	cmd.cmd_cb = (wlan_serialization_cmd_callback)
@@ -1904,8 +1936,7 @@ QDF_STATUS tdls_process_remove_force_peer(struct tdls_oper_request *req)
 		soc_obj->tdls_dp_vdev_update(&soc_obj->soc,
 				peer->sta_id,
 				soc_obj->tdls_update_dp_vdev_flags,
-				((peer->link_status ==
-				TDLS_LINK_CONNECTED) ? true : false));
+				false);
 
 	if (soc_obj->tdls_event_cb) {
 		qdf_mem_copy(ind.peer_mac, macaddr, QDF_MAC_ADDR_SIZE);

+ 1 - 2
umac/tdls/core/src/wlan_tdls_ct.c

@@ -532,8 +532,7 @@ void tdls_indicate_teardown(struct tdls_vdev_priv_obj *tdls_vdev,
 		tdls_soc->tdls_dp_vdev_update(&tdls_soc->soc,
 				curr_peer->sta_id,
 				tdls_soc->tdls_update_dp_vdev_flags,
-				((curr_peer->link_status ==
-				TDLS_LINK_CONNECTED) ? true : false));
+				false);
 
 	indication.reason = reason;
 	indication.vdev = tdls_vdev->vdev;

+ 1 - 0
umac/tdls/dispatcher/src/wlan_tdls_ucfg_api.c

@@ -218,6 +218,7 @@ QDF_STATUS ucfg_tdls_update_config(struct wlan_objmgr_psoc *psoc,
 	soc_obj->tdls_update_peer_state = req->tdls_update_peer_state;
 	soc_obj->tdls_del_all_peers = req->tdls_del_all_peers;
 	soc_obj->tdls_update_dp_vdev_flags = req->tdls_update_dp_vdev_flags;
+	soc_obj->tdls_dp_vdev_update = req->tdls_dp_vdev_update;
 	tdls_pm_call_backs.tdls_notify_increment_session =
 			tdls_notify_increment_session;