Browse Source

qcacmn: Add runtime PM support for new data path

Handle runtime PM feature in new data path for QCA6290.

Change-Id: I0a211436d80d68bc94d11ccd3c34860b648e40e7
CRs-fixed: 2023358
Yue Ma 8 years ago
parent
commit
245b47bfb5
4 changed files with 86 additions and 6 deletions
  1. 2 1
      dp/wifi3.0/dp_htt.c
  2. 59 3
      dp/wifi3.0/dp_main.c
  3. 2 0
      dp/wifi3.0/dp_rx.c
  4. 23 2
      dp/wifi3.0/dp_tx.c

+ 2 - 1
dp/wifi3.0/dp_htt.c

@@ -633,7 +633,7 @@ int htt_srng_setup(void *htt_soc, int mac_id, void *hal_srng,
 		qdf_nbuf_data(htt_msg),
 		qdf_nbuf_len(htt_msg),
 		soc->htc_endpoint,
-		1); /* tag - not relevant here */
+		HTC_TX_PACKET_TAG_RUNTIME_PUT); /* tag for no FW response msg */
 
 	SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, htt_msg);
 	DP_HTT_SEND_HTC_PKT(soc, pkt);
@@ -2085,6 +2085,7 @@ static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt)
 #endif
 	case HTT_T2H_MSG_TYPE_VERSION_CONF:
 		{
+			htc_pm_runtime_put(soc->htc_soc);
 			soc->tgt_ver.major = HTT_VER_CONF_MAJOR_GET(*msg_word);
 			soc->tgt_ver.minor = HTT_VER_CONF_MINOR_GET(*msg_word);
 			QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH,

+ 59 - 3
dp/wifi3.0/dp_main.c

@@ -5082,6 +5082,62 @@ static struct cdp_pflow_ops dp_ops_pflow = {
 };
 #endif /* CONFIG_WIN */
 
+#ifdef FEATURE_RUNTIME_PM
+/**
+ * dp_runtime_suspend() - ensure DP is ready to runtime suspend
+ * @opaque_pdev: DP pdev context
+ *
+ * DP is ready to runtime suspend if there are no pending TX packets.
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS dp_runtime_suspend(struct cdp_pdev *opaque_pdev)
+{
+	struct dp_pdev *pdev = (struct dp_pdev *)opaque_pdev;
+	struct dp_soc *soc = pdev->soc;
+
+	/* Call DP TX flow control API to check if there is any
+	   pending packets */
+
+	if (soc->intr_mode == DP_INTR_POLL)
+		qdf_timer_stop(&soc->int_timer);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * dp_runtime_resume() - ensure DP is ready to runtime resume
+ * @opaque_pdev: DP pdev context
+ *
+ * Resume DP for runtime PM.
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS dp_runtime_resume(struct cdp_pdev *opaque_pdev)
+{
+	struct dp_pdev *pdev = (struct dp_pdev *)opaque_pdev;
+	struct dp_soc *soc = pdev->soc;
+	void *hal_srng;
+	int i;
+
+	if (soc->intr_mode == DP_INTR_POLL)
+		qdf_timer_mod(&soc->int_timer, DP_INTR_POLL_TIMER_MS);
+
+	for (i = 0; i < MAX_TCL_DATA_RINGS; i++) {
+		hal_srng = soc->tcl_data_ring[i].hal_srng;
+		if (hal_srng) {
+			/* We actually only need to acquire the lock */
+			hal_srng_access_start(soc->hal_soc, hal_srng);
+			/* Update SRC ring head pointer for HW to send
+			   all pending packets */
+			hal_srng_access_end(soc->hal_soc, hal_srng);
+		}
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+#endif /* FEATURE_RUNTIME_PM */
+
 static QDF_STATUS dp_bus_suspend(struct cdp_pdev *opaque_pdev)
 {
 	struct dp_pdev *pdev = (struct dp_pdev *)opaque_pdev;
@@ -5108,9 +5164,9 @@ static QDF_STATUS dp_bus_resume(struct cdp_pdev *opaque_pdev)
 static struct cdp_misc_ops dp_ops_misc = {
 	.get_opmode = dp_get_opmode,
 #ifdef FEATURE_RUNTIME_PM
-	.runtime_suspend = dp_bus_suspend,
-	.runtime_resume = dp_bus_resume,
-#endif
+	.runtime_suspend = dp_runtime_suspend,
+	.runtime_resume = dp_runtime_resume,
+#endif /* FEATURE_RUNTIME_PM */
 };
 
 static struct cdp_flowctl_ops dp_ops_flowctl = {

+ 2 - 0
dp/wifi3.0/dp_rx.c

@@ -937,6 +937,8 @@ dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, uint32_t quota)
 	/* Debug -- Remove later */
 	qdf_assert(hal_soc);
 
+	hif_pm_runtime_mark_last_busy(soc->osdev->dev);
+
 	if (qdf_unlikely(hal_srng_access_start(hal_soc, hal_ring))) {
 
 		/*

+ 23 - 2
dp/wifi3.0/dp_tx.c

@@ -847,6 +847,14 @@ static QDF_STATUS dp_tx_hw_enqueue(struct dp_soc *soc, struct dp_vdev *vdev,
 	hal_tx_desc_sync(hal_tx_desc_cached, hal_tx_desc);
 	DP_STATS_INC_PKT(vdev, tx_i.processed, 1, length);
 
+	/*
+	 * If one packet is enqueued in HW, PM usage count needs to be
+	 * incremented by one to prevent future runtime suspend. This
+	 * should be tied with the success of enqueuing. It will be
+	 * decremented after the packet has been sent.
+	 */
+	hif_pm_runtime_get_noresume(soc->hif_handle);
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -1042,7 +1050,13 @@ static qdf_nbuf_t dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
 	nbuf = NULL;
 
 fail_return:
-	hal_srng_access_end(soc->hal_soc, hal_srng);
+	if (hif_pm_runtime_get(soc->hif_handle) == 0) {
+		hal_srng_access_end(soc->hal_soc, hal_srng);
+		hif_pm_runtime_put(soc->hif_handle);
+	} else {
+		hal_srng_access_end_reap(soc->hal_soc, hal_srng);
+	}
+
 	return nbuf;
 }
 
@@ -1184,7 +1198,12 @@ qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
 	nbuf = NULL;
 
 done:
-	hal_srng_access_end(soc->hal_soc, hal_srng);
+	if (hif_pm_runtime_get(soc->hif_handle) == 0) {
+		hal_srng_access_end(soc->hal_soc, hal_srng);
+		hif_pm_runtime_put(soc->hif_handle);
+	} else {
+		hal_srng_access_end_reap(soc->hal_soc, hal_srng);
+	}
 
 	return nbuf;
 }
@@ -2185,6 +2204,8 @@ uint32_t dp_tx_comp_handler(struct dp_soc *soc, void *hal_srng, uint32_t quota)
 		}
 
 		num_processed += !(count & DP_TX_NAPI_BUDGET_DIV_MASK);
+		/* Decrement PM usage count if the packet has been sent.*/
+		hif_pm_runtime_put(soc->hif_handle);
 
 		/*
 		 * Processed packet count is more than given quota