qcacmn: data-path changes for dynamic hw-mode config

This feature enables user to change HW mode dynamically
from DBS to DBS_SBS mode and vice-versa. Currently, HW
mode configuration is only possible through INI setting
requiring a subsequent reboot.

Relevant DP changes are:

1. Add API cdp_txrx_handle_pdev_status_change to pass
pdev 'up' or 'down' status to DP module
2. Add pdev-status check in dp_rx_process_invalid_peer
3. Add pdev-status check in dp_tx_comp_handler to free
buffer and release descriptor

Change-Id: I74b144abb1b0dc41a26a18ad28f872e6457e9653
CRs-fixed: 2490212
diff --git a/dp/inc/cdp_txrx_cmn.h b/dp/inc/cdp_txrx_cmn.h
index 787c7a4..3290e01 100644
--- a/dp/inc/cdp_txrx_cmn.h
+++ b/dp/inc/cdp_txrx_cmn.h
@@ -1963,6 +1963,32 @@
 }
 
 /**
+ * cdp_txrx_set_pdev_status_down() - set pdev down/up status
+ * @soc: soc opaque handle
+ * @pdev_handle: data path pdev handle
+ * @is_pdev_down: pdev down/up status
+ *
+ * return: void
+ */
+static inline void cdp_txrx_set_pdev_status_down(ol_txrx_soc_handle soc,
+						 struct cdp_pdev *pdev_handle,
+						 bool is_pdev_down)
+{
+	if (!soc || !soc->ops) {
+		QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG,
+			  "%s: Invalid Instance:", __func__);
+		QDF_BUG(0);
+		return;
+	}
+
+	if (!soc->ops->cmn_drv_ops ||
+	    !soc->ops->cmn_drv_ops->set_pdev_status_down)
+		return;
+
+	soc->ops->cmn_drv_ops->set_pdev_status_down(pdev_handle, is_pdev_down);
+}
+
+/**
  * cdp_tx_send() - enqueue frame for transmission
  * @soc: soc opaque handle
  * @vdev: VAP device
diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h
index b15c76d..8672076 100644
--- a/dp/inc/cdp_txrx_ops.h
+++ b/dp/inc/cdp_txrx_ops.h
@@ -412,6 +412,8 @@
 	void (*map_pdev_to_lmac)(struct cdp_pdev *pdev_hdl,
 				 uint32_t lmac_id);
 
+	void (*set_pdev_status_down)(struct cdp_pdev *pdev_hdl, bool is_pdev_down);
+
 	void (*txrx_peer_reset_ast)
 		(ol_txrx_soc_handle soc, uint8_t *ast_macaddr,
 		 uint8_t *peer_macaddr, void *vdev_hdl);
diff --git a/dp/inc/cdp_txrx_stats_struct.h b/dp/inc/cdp_txrx_stats_struct.h
index 786aea3..9c0746c 100644
--- a/dp/inc/cdp_txrx_stats_struct.h
+++ b/dp/inc/cdp_txrx_stats_struct.h
@@ -1717,6 +1717,8 @@
 	OL_ATH_PARAM_RCHWIDTH = 422,
 	/* Whether external ACS request is in progress */
 	OL_ATH_EXT_ACS_REQUEST_IN_PROGRESS = 423,
+	/* set/get hw mode */
+	OL_ATH_PARAM_HW_MODE  = 424,
 };
 #endif
 /* Bitmasks for stats that can block */
diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c
index 834a970..48814cd 100644
--- a/dp/wifi3.0/dp_main.c
+++ b/dp/wifi3.0/dp_main.c
@@ -3510,7 +3510,6 @@
 			goto fail1;
 		}
 		soc->num_reo_dest_rings++;
-
 	}
 
 	ring_size =
@@ -8411,6 +8410,21 @@
 }
 
 /**
+ * dp_soc_set_pdev_status_down() - set pdev down/up status
+ * @pdev_hdl: datapath pdev handle
+ * @is_pdev_down: pdev down/up status
+ *
+ * Return: void
+ */
+static void
+dp_soc_set_pdev_status_down(struct cdp_pdev *pdev_hdl, bool is_pdev_down)
+{
+	struct dp_pdev *pdev = (struct dp_pdev *)pdev_hdl;
+
+	pdev->is_pdev_down = is_pdev_down;
+}
+
+/**
  * dp_get_cfg_capabilities() - get dp capabilities
  * @soc_handle: datapath soc handle
  * @dp_caps: enum for dp capabilities
@@ -9163,6 +9177,7 @@
 	.get_soc_dp_txrx_handle = dp_soc_get_dp_txrx_handle,
 	.set_soc_dp_txrx_handle = dp_soc_set_dp_txrx_handle,
 	.map_pdev_to_lmac = dp_soc_map_pdev_to_lmac,
+	.set_pdev_status_down = dp_soc_set_pdev_status_down,
 	.txrx_set_ba_aging_timeout = dp_set_ba_aging_timeout,
 	.txrx_get_ba_aging_timeout = dp_get_ba_aging_timeout,
 	.tx_send = dp_tx_send,
diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c
index a31c5ea..a9faec2 100644
--- a/dp/wifi3.0/dp_rx.c
+++ b/dp/wifi3.0/dp_rx.c
@@ -730,9 +730,9 @@
 
 	pdev = dp_get_pdev_for_mac_id(soc, mac_id);
 
-	if (!pdev) {
+	if (!pdev || qdf_unlikely(pdev->is_pdev_down)) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
-			  "PDEV not found");
+			  "PDEV %s", !pdev ? "not found" : "down");
 		goto free;
 	}
 
@@ -751,7 +751,6 @@
 		}
 	}
 
-
 	TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) {
 
 		if (qdf_mem_cmp(wh->i_addr1, vdev->mac_addr.raw,
@@ -1733,6 +1732,7 @@
 		 * In this case host will dump the last 128 descriptors
 		 * including the software descriptor rx_desc and assert.
 		 */
+
 		if (qdf_unlikely(!rx_desc->in_use)) {
 			DP_STATS_INC(soc, rx.err.hal_reo_dest_dup, 1);
 			dp_info_rl("Reaping rx_desc not in use!");
diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c
index 32230c2..69bf65a 100644
--- a/dp/wifi3.0/dp_tx.c
+++ b/dp/wifi3.0/dp_tx.c
@@ -3460,6 +3460,20 @@
 			continue;
 		}
 
+		if (qdf_unlikely(tx_desc->pdev->is_pdev_down)) {
+			QDF_TRACE(QDF_MODULE_ID_DP,
+				  QDF_TRACE_LEVEL_INFO,
+				  "pdev in down state %d",
+				  tx_desc_id);
+
+			num_processed += !(count & DP_TX_NAPI_BUDGET_DIV_MASK);
+			count++;
+
+			dp_tx_comp_free_buf(soc, tx_desc);
+			dp_tx_desc_release(tx_desc, tx_desc->pool_id);
+			continue;
+		}
+
 		/*
 		 * If the release source is FW, process the HTT status
 		 */
diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h
index 3f51331..1edfaa1 100644
--- a/dp/wifi3.0/dp_types.h
+++ b/dp/wifi3.0/dp_types.h
@@ -1372,6 +1372,13 @@
 	 */
 	bool pdev_deinit;
 
+	/* pdev status down or up required to handle dynamic hw
+	 * mode switch between DBS and DBS_SBS.
+	 * 1 = down
+	 * 0 = up
+	 */
+	bool is_pdev_down;
+
 	/* Second ring used to replenish rx buffers */
 	struct dp_srng rx_refill_buf_ring2;