فهرست منبع

qcacmn: Add method to configure TID queues flush

This enables the option to configure when a peer's
TID queue needs to be flushed. This is required to
discard packets that are no longer useful to the application.

Change-Id: I558debff043fc0c8038e5f5f2c815b64c90e1561
CRs-Fixed: 3130422
Madhvapathi Sriram 3 سال پیش
والد
کامیت
f4bfa6616b

+ 35 - 1
dp/inc/cdp_txrx_misc.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -960,4 +960,38 @@ cdp_get_tx_rings_grp_bitmap(ol_txrx_soc_handle soc)
 
 	return 0;
 }
+
+#ifdef WLAN_FEATURE_PEER_TXQ_FLUSH_CONF
+/**
+ * cdp_set_peer_txq_flush_config() - Set the peer txq flush configuration
+ * @soc: Opaque handle to the DP soc object
+ * @vdev_id: VDEV identifier
+ * @mac: MAC address of the peer
+ * @ac: access category mask
+ * @tid: TID mask
+ * @policy: Flush policy
+ *
+ * Return: 0 on success, errno on failure
+ */
+static inline int
+cdp_set_peer_txq_flush_config(ol_txrx_soc_handle soc, uint8_t vdev_id,
+			      uint8_t *mac, uint8_t ac, uint32_t tid,
+			      enum cdp_peer_txq_flush_policy policy)
+{
+	if (!soc || !soc->ops || !soc->ops->misc_ops || !mac) {
+		dp_cdp_debug("Invalid parameters");
+		return 0;
+	}
+
+	if (soc->ops->misc_ops->set_peer_txq_flush_config) {
+		return soc->ops->misc_ops->set_peer_txq_flush_config(soc,
+								     vdev_id,
+								     mac, ac,
+								     tid,
+								     policy);
+	}
+
+	return 0;
+}
+#endif /* WLAN_FEATURE_PEER_TXQ_FLUSH_CONF */
 #endif /* _CDP_TXRX_MISC_H_ */

+ 25 - 0
dp/inc/cdp_txrx_ops.h

@@ -119,6 +119,23 @@ enum vdev_ll_conn_actions {
 	CDP_VDEV_LL_CONN_DEL
 };
 
+/**
+ * enum cdp_peer_txq_flush_policy: Values for peer TX TID queues flush policy
+ * @CDP_PEER_TXQ_FLUSH_POLICY_NONE: No flush policy configured
+ * @CDP_PEER_TXQ_FLUSH_POLICY_IMMEDIATE: Flush peer TX TID queue(s) immediately
+ * @CDP_PEER_TXQ_FLUSH_POLICY_TWT_SP_END: Flush peer TX TID queue(s) at SP end
+ *
+ * This is used to map the 'flush_policy' in WMI_PEER_FLUSH_POLICY_CMDID
+ */
+enum cdp_peer_txq_flush_policy {
+	CDP_PEER_TXQ_FLUSH_POLICY_NONE = 0,
+	CDP_PEER_TXQ_FLUSH_POLICY_IMMEDIATE = 1,
+	CDP_PEER_TXQ_FLUSH_POLICY_TWT_SP_END = 2,
+
+	/* keep last */
+	CDP_PEER_TXQ_FLUSH_POLICY_INVALID,
+};
+
 /**
  * struct cdp_mlo_ops - MLO ops for multichip
  * @mlo_soc_setup: setup DP mlo for SOC
@@ -1474,6 +1491,8 @@ struct ol_if_ops {
  * @set_swlm_enable: Enable or Disable Software Latency Manager.
  * @is_swlm_enabled: Check if Software latency manager is enabled or not.
  * @display_txrx_hw_info: Dump the DP rings info
+ * @set_tx_flush_pending: Configures the ac/tid to be flushed and policy
+ *			  to flush.
  *
  * Function pointers for miscellaneous soc/pdev/vdev related operations.
  */
@@ -1566,6 +1585,12 @@ struct cdp_misc_ops {
 	uint8_t (*is_swlm_enabled)(struct cdp_soc_t *soc_hdl);
 	void (*display_txrx_hw_info)(struct cdp_soc_t *soc_hdl);
 	uint32_t (*get_tx_rings_grp_bitmap)(struct cdp_soc_t *soc_hdl);
+#ifdef WLAN_FEATURE_PEER_TXQ_FLUSH_CONF
+	int (*set_peer_txq_flush_config)(struct cdp_soc_t *soc_hdl,
+					 uint8_t vdev_id, uint8_t *addr,
+					 uint8_t ac, uint32_t tid,
+					 enum cdp_peer_txq_flush_policy policy);
+#endif
 };
 
 /**

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

@@ -92,6 +92,9 @@ cdp_dump_flow_pool_info(struct cdp_soc_t *soc)
 #ifdef CONFIG_SAWF_DEF_QUEUES
 #include "dp_sawf.h"
 #endif
+#ifdef WLAN_FEATURE_PEER_TXQ_FLUSH_CONF
+#include <target_if_dp.h>
+#endif
 
 #ifdef WLAN_FEATURE_STATS_EXT
 #define INIT_RX_HW_STATS_LOCK(_soc) \
@@ -13405,6 +13408,35 @@ static void dp_mark_first_wakeup_packet(struct cdp_soc_t *soc_hdl,
 }
 #endif
 
+#ifdef WLAN_FEATURE_PEER_TXQ_FLUSH_CONF
+/**
+ * dp_set_peer_txq_flush_config() - Set the peer txq flush configuration
+ * @soc_hdl: Opaque handle to the DP soc object
+ * @vdev_id: VDEV identifier
+ * @mac: MAC address of the peer
+ * @ac: access category mask
+ * @tid: TID mask
+ * @policy: Flush policy
+ *
+ * Return: 0 on success, errno on failure
+ */
+static int dp_set_peer_txq_flush_config(struct cdp_soc_t *soc_hdl,
+					uint8_t vdev_id, uint8_t *mac,
+					uint8_t ac, uint32_t tid,
+					enum cdp_peer_txq_flush_policy policy)
+{
+	struct dp_soc *soc;
+
+	if (!soc_hdl) {
+		dp_err("soc is null");
+		return -EINVAL;
+	}
+	soc = cdp_soc_t_to_dp_soc(soc_hdl);
+	return target_if_peer_txq_flush_config(soc->ctrl_psoc, vdev_id,
+					       mac, ac, tid, policy);
+}
+#endif
+
 #ifdef DP_PEER_EXTENDED_API
 static struct cdp_misc_ops dp_ops_misc = {
 #ifdef FEATURE_WLAN_TDLS
@@ -13438,6 +13470,9 @@ static struct cdp_misc_ops dp_ops_misc = {
 #ifdef WLAN_FEATURE_MARK_FIRST_WAKEUP_PACKET
 	.mark_first_wakeup_packet = dp_mark_first_wakeup_packet,
 #endif
+#ifdef WLAN_FEATURE_PEER_TXQ_FLUSH_CONF
+	.set_peer_txq_flush_config = dp_set_peer_txq_flush_config,
+#endif
 };
 #endif
 

+ 27 - 1
target_if/dp/inc/target_if_dp.h

@@ -213,4 +213,30 @@ target_if_update_wds_entry(struct cdp_ctrl_objmgr_psoc *soc, uint8_t vdev_id,
 	return QDF_STATUS_SUCCESS;
 }
 #endif /* FEATURE_MCL_REPEATER */
-#endif
+
+#ifdef WLAN_FEATURE_PEER_TXQ_FLUSH_CONF
+/**
+ * target_if_peer_txq_flush_config() - Send flush command for pending frames
+ * @psoc: psoc handle pointer
+ * @vdev_id: VDEV id
+ * @mac: MAC addr of peer for which the tx queue flush is intended
+ * @ac: AC mask for identifying the tx queues to be flushed
+ * @tid: TID mask for identifying the tx queues to be flushed
+ * @policy: Defines the flush policy
+ *
+ * Return: 0 for success or error code
+ */
+int target_if_peer_txq_flush_config(struct cdp_ctrl_objmgr_psoc *psoc,
+				    uint8_t vdev_id, uint8_t *mac,
+				    uint8_t ac, uint32_t tid, uint32_t policy);
+#else
+static inline int
+target_if_peer_txq_flush_config(struct cdp_ctrl_objmgr_psoc *psoc,
+				uint8_t vdev_id, uint8_t *mac,
+				uint8_t ac, uint32_t tid,
+				enum cdp_peer_txq_flush_policy policy)
+{
+	return 0;
+}
+#endif /* WLAN_FEATURE_PEER_TXQ_FLUSH_CONF */
+#endif /* _WLAN_TARGET_IF_DP_H_ */

+ 170 - 0
target_if/dp/src/target_if_dp.c

@@ -24,6 +24,10 @@
 #include <qdf_status.h>
 #include "target_if_dp.h"
 #include <init_deinit_lmac.h>
+#ifdef WLAN_FEATURE_PEER_TXQ_FLUSH_CONF
+#include <wmi_unified_param.h>
+#include <wlan_objmgr_peer_obj.h>
+#endif
 
 uint32_t target_if_get_active_mac_phy_number(struct wlan_objmgr_psoc *psoc)
 {
@@ -452,3 +456,169 @@ target_if_update_wds_entry(struct cdp_ctrl_objmgr_psoc *soc, uint8_t vdev_id,
 	return status;
 }
 #endif
+
+#ifdef WLAN_FEATURE_PEER_TXQ_FLUSH_CONF
+/**
+ * map_flush_policy() - Map DP layer flush policy values to target i/f layer
+ * @policy: The DP layer flush policy value
+ *
+ * Return: Peer flush policy
+ */
+static enum peer_txq_flush_policy
+map_flush_policy(enum cdp_peer_txq_flush_policy policy)
+{
+	switch (policy) {
+	case  CDP_PEER_TXQ_FLUSH_POLICY_NONE:
+		return PEER_TXQ_FLUSH_POLICY_NONE;
+	case CDP_PEER_TXQ_FLUSH_POLICY_TWT_SP_END:
+		return PEER_TXQ_FLUSH_POLICY_TWT_SP_END;
+	default:
+		return PEER_TXQ_FLUSH_POLICY_INVALID;
+	}
+}
+
+/**
+ * send_peer_txq_flush_conf() - Send flush config for peers TID queues
+ * @psoc: Opaque handle for posc object manager object
+ * @mac: MAC addr of peer for which the tx queue flush is intended
+ * @vdev_id: VDEV identifier
+ * @tid: TID mask for identifying the tx queues to be flushed
+ * @policy: The peer tid queue flush policy
+ *
+ * Return: 0 for success or error code
+ */
+static int send_peer_txq_flush_conf(struct cdp_ctrl_objmgr_psoc *psoc,
+				    uint8_t *mac, uint8_t vdev_id,
+				    uint32_t tid,
+				    enum cdp_peer_txq_flush_policy policy)
+{
+	struct wlan_objmgr_psoc *obj_soc;
+	struct wmi_unified *wmi_handle;
+	enum peer_txq_flush_policy flush_policy;
+	struct peer_txq_flush_config_params param = {0};
+	QDF_STATUS status;
+
+	obj_soc = (struct wlan_objmgr_psoc *)psoc;
+	wmi_handle = GET_WMI_HDL_FROM_PSOC(obj_soc);
+	if (!wmi_handle) {
+		target_if_err("Invalid wmi handle");
+		return -EINVAL;
+	}
+
+	flush_policy = map_flush_policy(policy);
+	if (flush_policy >= PEER_TXQ_FLUSH_POLICY_INVALID) {
+		target_if_err("Invalid flush policy : %d", policy);
+		return -EINVAL;
+	}
+
+	param.vdev_id = vdev_id;
+	param.tid_mask = tid;
+	param.policy = flush_policy;
+	qdf_mem_copy(param.peer, mac, QDF_MAC_ADDR_SIZE);
+
+	status = wmi_unified_peer_txq_flush_config_send(wmi_handle, &param);
+	return qdf_status_to_os_return(status);
+}
+
+/**
+ * send_peer_txq_flush_tids() - Send flush command peers TID queues
+ * @psoc: Opaque handle for psoc object manager object
+ * @mac: MAC addr of peer for which the tx queue flush is intended
+ * @vdev_id: VDEV identifier
+ * @tid: TID mask for identifying the tx queues to be flushed
+ *
+ * Return: 0 for success or error code
+ */
+static int send_peer_txq_flush_tids(struct cdp_ctrl_objmgr_psoc *psoc,
+				    uint8_t *mac, uint8_t vdev_id,
+				    uint32_t tid)
+{
+	struct wlan_objmgr_psoc *obj_soc;
+	struct wmi_unified *wmi_handle;
+	struct peer_flush_params param;
+	QDF_STATUS status;
+
+	if (!psoc || !mac) {
+		target_if_err("Invalid params");
+		return -EINVAL;
+	}
+
+	obj_soc = (struct wlan_objmgr_psoc *)psoc;
+	wmi_handle = GET_WMI_HDL_FROM_PSOC(obj_soc);
+	if (!wmi_handle) {
+		target_if_err("Invalid wmi handle");
+		return -EINVAL;
+	}
+
+	param.vdev_id = vdev_id;
+	param.peer_tid_bitmap = tid;
+	qdf_mem_copy(param.peer_mac, mac, QDF_MAC_ADDR_SIZE);
+
+	status = wmi_unified_peer_flush_tids_send(wmi_handle, mac, &param);
+	return qdf_status_to_os_return(status);
+}
+
+int target_if_peer_txq_flush_config(struct cdp_ctrl_objmgr_psoc *psoc,
+				    uint8_t vdev_id, uint8_t *addr,
+				    uint8_t ac, uint32_t tid,
+				    enum cdp_peer_txq_flush_policy policy)
+{
+	static uint8_t ac_to_tid[4][2] = { {0, 3}, {1, 2}, {4, 5}, {6, 7} };
+	struct wlan_objmgr_psoc *obj_soc;
+	struct wlan_objmgr_peer *peer;
+	int i, rc;
+
+	if (!psoc || !addr) {
+		target_if_err("Invalid params");
+		return -EINVAL;
+	}
+
+	if (!tid && !ac) {
+		target_if_err("no ac/tid mask setting");
+		return -EINVAL;
+	}
+
+	if (tid && policy == CDP_PEER_TXQ_FLUSH_POLICY_INVALID) {
+		target_if_err("Invalid flush policy");
+		return -EINVAL;
+	}
+	obj_soc = (struct wlan_objmgr_psoc *)psoc;
+
+	peer = wlan_objmgr_get_peer_by_mac(obj_soc, addr, WLAN_DP_ID);
+	if (!peer) {
+		target_if_err("Peer not found in the list");
+		return -EINVAL;
+	}
+	/* If tid mask is provided and policy is immediate use legacy WMI.
+	 * If tid mask is provided and policy is other than immediate use
+	 * the new WMI command for flush config.
+	 * If tid mask is not provided and ac mask is provided, convert to tid,
+	 * use the legacy WMI cmd for flushing the queues immediately.
+	 */
+	if (tid) {
+		if (policy == CDP_PEER_TXQ_FLUSH_POLICY_IMMEDIATE) {
+			rc = send_peer_txq_flush_tids(psoc, addr, vdev_id, tid);
+			wlan_objmgr_peer_release_ref(peer, WLAN_DP_ID);
+			return rc;
+		}
+		rc = send_peer_txq_flush_conf(psoc, addr, vdev_id, tid, policy);
+		wlan_objmgr_peer_release_ref(peer, WLAN_DP_ID);
+		return rc;
+	}
+
+	if (ac) {
+		tid = 0;
+		for (i = 0; i < 4; ++i) {
+			if (((ac & 0x0f) >> i) & 0x01) {
+				tid |= (1 << ac_to_tid[i][0]) |
+				       (1 << ac_to_tid[i][1]);
+			}
+		}
+		rc = send_peer_txq_flush_tids(psoc, addr, vdev_id, tid);
+		wlan_objmgr_peer_release_ref(peer, WLAN_DP_ID);
+		return rc;
+	}
+	 /* should not hit this line */
+	return 0;
+}
+#endif

+ 12 - 0
wmi/inc/wmi_unified_api.h

@@ -934,6 +934,18 @@ QDF_STATUS
 wmi_unified_peer_flush_tids_send(wmi_unified_t wmi_handle,
 				 uint8_t peer_addr[QDF_MAC_ADDR_SIZE],
 				 struct peer_flush_params *param);
+#ifdef WLAN_FEATURE_PEER_TXQ_FLUSH_CONF
+/**
+ * wmi_unified_peer_txq_flush_config_send() - peer txq flush policy config in fw
+ * @wmi_handle: wmi handle
+ * @pr: peer txq flush config parameters
+ *
+ * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
+ */
+QDF_STATUS
+wmi_unified_peer_txq_flush_config_send(wmi_unified_t wmi_handle,
+				       struct peer_txq_flush_config_params *pr);
+#endif
 
 /**
  * wmi_unified_peer_delete_all_send() - send PEER delete all command to fw

+ 28 - 0
wmi/inc/wmi_unified_param.h

@@ -3696,6 +3696,34 @@ enum wmi_ratemask_type {
 	WMI_RATEMASK_TYPE_HE  = 3,
 };
 
+/**
+ * enum peer_txq_flush_policy - Peer flush policy values
+ * @PEER_TXQ_FLUSH_POLICY_NONE: No policy configured for peer TID queues
+ * @PEER_TXQ_FLUSH_POLICY_TWT_SP_END: flush peer TID queues after SP end
+ *
+ * This is mapped to 'flush_policy' in WMI_PEER_FLUSH_POLICY_CMDID
+ */
+enum peer_txq_flush_policy {
+	PEER_TXQ_FLUSH_POLICY_NONE = 0,
+	PEER_TXQ_FLUSH_POLICY_TWT_SP_END = 1,
+	/*keep last */
+	PEER_TXQ_FLUSH_POLICY_INVALID,
+};
+
+/**
+ * struct peer_txq_flush_config_params: Peer TXQ flush configuration parameters
+ * @vdev_id: vdev id
+ * @peer: Peer mac address
+ * @tid_mask: TID queues of the peer being configured
+ * @policy: Policy to be applied
+ */
+struct peer_txq_flush_config_params {
+	uint8_t vdev_id;
+	uint8_t peer[QDF_MAC_ADDR_SIZE];
+	uint32_t tid_mask;
+	enum peer_txq_flush_policy policy;
+};
+
 /**
  * enum gpio_pull_type - GPIO PULL TYPE
  * @WMI_HOST_GPIO_PULL_NONE: set gpio pull type to none

+ 5 - 0
wmi/inc/wmi_unified_priv.h

@@ -3017,6 +3017,11 @@ QDF_STATUS
 (*extract_pdev_telemetry_stats)(
 		wmi_unified_t wmi_handle, void *evt_buf,
 		struct wmi_host_pdev_telemetry_stats *pdev_stats);
+#ifdef WLAN_FEATURE_PEER_TXQ_FLUSH_CONF
+QDF_STATUS
+(*send_peer_txq_flush_config_cmd)(wmi_unified_t wmi_handle,
+				  struct peer_txq_flush_config_params *param);
+#endif
 };
 
 /* Forward declartion for psoc*/

+ 14 - 0
wmi/src/wmi_unified_api.c

@@ -160,6 +160,20 @@ wmi_unified_peer_flush_tids_send(wmi_unified_t wmi_handle,
 	return QDF_STATUS_E_FAILURE;
 }
 
+#ifdef WLAN_FEATURE_PEER_TXQ_FLUSH_CONF
+QDF_STATUS
+wmi_unified_peer_txq_flush_config_send(wmi_unified_t wmi_handle,
+				       struct peer_txq_flush_config_params *pr)
+{
+	struct wmi_ops *ops = wmi_handle->ops;
+
+	if (ops->send_peer_txq_flush_config_cmd)
+		return ops->send_peer_txq_flush_config_cmd(wmi_handle, pr);
+
+	return QDF_STATUS_E_FAILURE;
+}
+#endif
+
 QDF_STATUS wmi_unified_peer_delete_send(wmi_unified_t wmi_handle,
 					uint8_t peer_addr[QDF_MAC_ADDR_SIZE],
 					struct peer_delete_cmd_params *param)

+ 71 - 0
wmi/src/wmi_unified_tlv.c

@@ -1284,6 +1284,74 @@ static QDF_STATUS send_peer_flush_tids_cmd_tlv(wmi_unified_t wmi,
 	return 0;
 }
 
+#ifdef WLAN_FEATURE_PEER_TXQ_FLUSH_CONF
+/**
+ * map_to_wmi_flush_policy() - Map flush policy to firmware defined values
+ * @policy: The target i/f flush policy value
+ *
+ * Return: WMI layer flush policy
+ */
+static wmi_peer_flush_policy
+map_to_wmi_flush_policy(enum peer_txq_flush_policy policy)
+{
+	switch (policy) {
+	case PEER_TXQ_FLUSH_POLICY_NONE:
+		return WMI_NO_FLUSH;
+	case PEER_TXQ_FLUSH_POLICY_TWT_SP_END:
+		return WMI_TWT_FLUSH;
+	default:
+		return WMI_MAX_FLUSH_POLICY;
+	}
+}
+
+/**
+ * send_peer_txq_flush_config_cmd_tlv() - Send peer TID queue flush config
+ * @wmi: wmi handle
+ * @para: Peer txq flush configuration
+ *
+ * Return: QDF status
+ */
+static QDF_STATUS
+send_peer_txq_flush_config_cmd_tlv(wmi_unified_t wmi,
+				   struct peer_txq_flush_config_params *param)
+{
+	wmi_peer_flush_policy_cmd_fixed_param *cmd;
+	wmi_buf_t buf;
+	int32_t len = sizeof(*cmd);
+
+	buf = wmi_buf_alloc(wmi, len);
+	if (!buf)
+		return QDF_STATUS_E_NOMEM;
+
+	cmd = (wmi_peer_flush_policy_cmd_fixed_param *)wmi_buf_data(buf);
+
+	WMITLV_SET_HDR(&cmd->tlv_header,
+		       WMITLV_TAG_STRUC_wmi_peer_flush_policy_cmd_fixed_param,
+		       WMITLV_GET_STRUCT_TLVLEN
+			       (wmi_peer_flush_policy_cmd_fixed_param));
+
+	WMI_CHAR_ARRAY_TO_MAC_ADDR(param->peer, &cmd->peer_macaddr);
+	cmd->peer_tid_bitmap = param->tid_mask;
+	cmd->vdev_id = param->vdev_id;
+	cmd->flush_policy = map_to_wmi_flush_policy(param->policy);
+	if (cmd->flush_policy == WMI_MAX_FLUSH_POLICY) {
+		wmi_buf_free(buf);
+		wmi_err("Invalid policy");
+		return QDF_STATUS_E_INVAL;
+	}
+	wmi_debug("peer_addr " QDF_MAC_ADDR_FMT "vdev %d tid %x policy %d",
+		  QDF_MAC_ADDR_REF(param->peer), param->vdev_id,
+		  param->tid_mask, param->policy);
+	wmi_mtrace(WMI_PEER_FLUSH_POLICY_CMDID, cmd->vdev_id, 0);
+	if (wmi_unified_cmd_send(wmi, buf, len, WMI_PEER_FLUSH_POLICY_CMDID)) {
+		wmi_err("Failed to send flush policy command");
+		wmi_buf_free(buf);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+#endif
 /**
  * send_peer_delete_cmd_tlv() - send PEER delete command to fw
  * @wmi: wmi handle
@@ -18387,6 +18455,9 @@ struct wmi_ops tlv_ops =  {
 		extract_pktlog_decode_info_event_tlv,
 	.extract_pdev_telemetry_stats = extract_pdev_telemetry_stats_tlv,
 	.extract_mgmt_rx_ext_params = extract_mgmt_rx_ext_params_tlv,
+#ifdef WLAN_FEATURE_PEER_TXQ_FLUSH_CONF
+	.send_peer_txq_flush_config_cmd = send_peer_txq_flush_config_cmd_tlv,
+#endif
 };
 
 #ifdef WLAN_FEATURE_11BE_MLO