Jelajahi Sumber

qcacmn: Add support for getting CE srng info for Direct Link

Add support to fetch CE srng information used for
direct link datapath.

Change-Id: If38b892b28eba711d7949fa02926205dc601a50e
CRs-Fixed: 3317501
Yeshwanth Sriram Guntuka 2 tahun lalu
induk
melakukan
9b059a3bc0
6 mengubah file dengan 267 tambahan dan 14 penghapusan
  1. 29 6
      hal/wifi3.0/hal_api.h
  2. 0 8
      hal/wifi3.0/hal_srng.c
  3. 70 0
      hif/inc/hif.h
  4. 5 0
      hif/src/ce/ce_api.h
  5. 31 0
      hif/src/ce/ce_main.c
  6. 132 0
      hif/src/ce/ce_service_srng.c

+ 29 - 6
hal/wifi3.0/hal_api.h

@@ -35,6 +35,14 @@
 /* Ring index for WBM2SW2 release ring */
 #define HAL_IPA_TX_COMP_RING_IDX 2
 
+#if defined(CONFIG_SHADOW_V2) || defined(CONFIG_SHADOW_V3)
+#define ignore_shadow false
+#define CHECK_SHADOW_REGISTERS true
+#else
+#define ignore_shadow true
+#define CHECK_SHADOW_REGISTERS false
+#endif
+
 /* calculate the register address offset from bar0 of shadow register x */
 #if defined(QCA_WIFI_QCA6390) || defined(QCA_WIFI_QCA6490) || \
     defined(QCA_WIFI_KIWI)
@@ -2606,9 +2614,17 @@ hal_srng_get_hp_addr(void *hal_soc,
 	struct hal_soc *hal = (struct hal_soc *)hal_soc;
 
 	if (srng->ring_dir == HAL_SRNG_SRC_RING) {
-		return hal->shadow_wrptr_mem_paddr +
-		  ((unsigned long)(srng->u.src_ring.hp_addr) -
-		  (unsigned long)(hal->shadow_wrptr_mem_vaddr));
+		if (srng->flags & HAL_SRNG_LMAC_RING)
+			return hal->shadow_wrptr_mem_paddr +
+				 ((unsigned long)(srng->u.src_ring.hp_addr) -
+				  (unsigned long)(hal->shadow_wrptr_mem_vaddr));
+		else if (ignore_shadow)
+			return (qdf_dma_addr_t)srng->u.src_ring.hp_addr;
+		else
+			return ((struct hif_softc *)hal->hif_handle)->mem_pa +
+				((unsigned long)srng->u.src_ring.hp_addr -
+				 (unsigned long)hal->dev_base_addr);
+
 	} else {
 		return hal->shadow_rdptr_mem_paddr +
 		  ((unsigned long)(srng->u.dst_ring.hp_addr) -
@@ -2634,9 +2650,16 @@ hal_srng_get_tp_addr(void *hal_soc, hal_ring_handle_t hal_ring_hdl)
 			((unsigned long)(srng->u.src_ring.tp_addr) -
 			(unsigned long)(hal->shadow_rdptr_mem_vaddr));
 	} else {
-		return hal->shadow_wrptr_mem_paddr +
-			((unsigned long)(srng->u.dst_ring.tp_addr) -
-			(unsigned long)(hal->shadow_wrptr_mem_vaddr));
+		if (srng->flags & HAL_SRNG_LMAC_RING)
+			return hal->shadow_wrptr_mem_paddr +
+				((unsigned long)(srng->u.dst_ring.tp_addr) -
+				 (unsigned long)(hal->shadow_wrptr_mem_vaddr));
+		else if (ignore_shadow)
+			return (qdf_dma_addr_t)srng->u.dst_ring.tp_addr;
+		else
+			return ((struct hif_softc *)hal->hif_handle)->mem_pa +
+				((unsigned long)srng->u.dst_ring.tp_addr -
+				 (unsigned long)hal->dev_base_addr);
 	}
 }
 

+ 0 - 8
hal/wifi3.0/hal_srng.c

@@ -1431,14 +1431,6 @@ static inline void hal_srng_hw_init(struct hal_soc *hal,
 		hal_srng_dst_hw_init(hal, srng, idle_check);
 }
 
-#if defined(CONFIG_SHADOW_V2) || defined(CONFIG_SHADOW_V3)
-#define ignore_shadow false
-#define CHECK_SHADOW_REGISTERS true
-#else
-#define ignore_shadow true
-#define CHECK_SHADOW_REGISTERS false
-#endif
-
 #ifdef WLAN_FEATURE_NEAR_FULL_IRQ
 /**
  * hal_srng_is_near_full_irq_supported() - Check if near full irq is

+ 70 - 0
hif/inc/hif.h

@@ -442,6 +442,38 @@ struct hif_target_info {
 struct hif_opaque_softc {
 };
 
+/**
+ * struct hif_ce_ring_info - CE ring information
+ * @ring_id: ring id
+ * @ring_dir: ring direction
+ * @num_entries: number of entries in ring
+ * @entry_size: ring entry size
+ * @ring_base_paddr: srng base physical address
+ * @hp_paddr: head pointer physical address
+ * @tp_paddr: tail pointer physical address
+ */
+struct hif_ce_ring_info {
+	uint8_t ring_id;
+	uint8_t ring_dir;
+	uint32_t num_entries;
+	uint32_t entry_size;
+	uint64_t ring_base_paddr;
+	uint64_t hp_paddr;
+	uint64_t tp_paddr;
+};
+
+/**
+ * struct hif_direct_link_ce_info - Direct Link CE information
+ * @ce_id: CE ide
+ * @pipe_dir: Pipe direction
+ * @ring_info: ring information
+ */
+struct hif_direct_link_ce_info {
+	uint8_t ce_id;
+	uint8_t pipe_dir;
+	struct hif_ce_ring_info ring_info;
+};
+
 /**
  * enum hif_event_type - Type of DP events to be recorded
  * @HIF_EVENT_IRQ_TRIGGER: IRQ trigger event
@@ -2450,6 +2482,30 @@ QDF_STATUS hif_unregister_umac_reset_handler(struct hif_opaque_softc *hif_scn)
 QDF_STATUS
 hif_set_irq_config_by_ceid(struct hif_opaque_softc *scn, uint8_t ce_id,
 			   uint64_t addr, uint32_t data);
+
+/**
+ * hif_get_direct_link_ce_dest_srng_buffers() - Get Direct Link ce dest srng
+ *  buffer information
+ * @hif_ctx: hif opaque handle
+ * @dma_addr: pointer to array of dma addresses
+ *
+ * Return: Number of buffers attached to the dest srng.
+ */
+uint16_t hif_get_direct_link_ce_dest_srng_buffers(struct hif_opaque_softc *scn,
+						  uint64_t **dma_addr);
+
+/**
+ * hif_get_direct_link_ce_srng_info() - Get Direct Link CE srng information
+ * @hif_ctx: hif opaque handle
+ * @info: Direct Link CEs information
+ * @max_ce_info_len: max array size of ce info
+ *
+ * Return: QDF status
+ */
+QDF_STATUS
+hif_get_direct_link_ce_srng_info(struct hif_opaque_softc *scn,
+				 struct hif_direct_link_ce_info *info,
+				 uint8_t max_ce_info_len);
 #else
 static inline QDF_STATUS
 hif_set_irq_config_by_ceid(struct hif_opaque_softc *scn, uint8_t ce_id,
@@ -2457,5 +2513,19 @@ hif_set_irq_config_by_ceid(struct hif_opaque_softc *scn, uint8_t ce_id,
 {
 	return QDF_STATUS_SUCCESS;
 }
+
+static inline
+uint16_t hif_get_direct_link_ce_dest_srng_buffers(struct hif_opaque_softc *scn)
+{
+	return 0;
+}
+
+static inline QDF_STATUS
+hif_get_direct_link_ce_srng_info(struct hif_opaque_softc *scn,
+				 struct hif_direct_link_ce_info *info,
+				 uint8_t max_ce_info_len)
+{
+	return QDF_STATUS_SUCCESS;
+}
 #endif
 #endif /* _HIF_H_ */

+ 5 - 0
hif/src/ce/ce_api.h

@@ -601,6 +601,11 @@ struct ce_ops {
 	QDF_STATUS (*ce_set_irq_config_by_ceid)(struct hif_softc *scn,
 						uint8_t ce_id, uint64_t addr,
 						uint32_t data);
+	uint16_t (*ce_get_direct_link_dest_buffers)(struct hif_softc *scn,
+						    uint64_t **dma_addr);
+	QDF_STATUS (*ce_get_direct_link_ring_info)(struct hif_softc *scn,
+					   struct hif_direct_link_ce_info *info,
+					   uint8_t max_ce_info_len);
 #endif
 };
 

+ 31 - 0
hif/src/ce/ce_main.c

@@ -5322,5 +5322,36 @@ hif_set_irq_config_by_ceid(struct hif_opaque_softc *scn, uint8_t ce_id,
 
 	return QDF_STATUS_E_NOSUPPORT;
 }
+
+uint16_t hif_get_direct_link_ce_dest_srng_buffers(struct hif_opaque_softc *scn,
+						  uint64_t **dma_addr)
+{
+	struct hif_softc *hif_ctx = HIF_GET_SOFTC(scn);
+	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
+	struct ce_ops *ce_services = hif_state->ce_services;
+
+	if (ce_services->ce_get_direct_link_dest_buffers)
+		return ce_services->ce_get_direct_link_dest_buffers(hif_ctx,
+								    dma_addr);
+
+	return 0;
+}
+
+QDF_STATUS
+hif_get_direct_link_ce_srng_info(struct hif_opaque_softc *scn,
+				 struct hif_direct_link_ce_info *info,
+				 uint8_t max_ce_info_len)
+{
+	struct hif_softc *hif_ctx = HIF_GET_SOFTC(scn);
+	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
+	struct ce_ops *ce_services = hif_state->ce_services;
+
+	if (ce_services->ce_get_direct_link_ring_info)
+		return ce_services->ce_get_direct_link_ring_info(hif_ctx,
+							       info,
+							       max_ce_info_len);
+
+	return QDF_STATUS_E_NOSUPPORT;
+}
 #endif
 #endif

+ 132 - 0
hif/src/ce/ce_service_srng.c

@@ -1153,6 +1153,136 @@ ce_set_srng_msi_irq_config_by_ceid(struct hif_softc *scn, uint8_t ce_id,
 
 	return QDF_STATUS_SUCCESS;
 }
+
+static
+uint16_t ce_get_direct_link_dest_srng_buffers(struct hif_softc *scn,
+					      uint64_t **dma_addr)
+{
+	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
+	struct CE_state *ce_state;
+	struct service_to_pipe *tgt_svc_cfg;
+	qdf_nbuf_t nbuf;
+	uint64_t *nbuf_dmaaddr = NULL;
+	uint32_t i;
+	uint32_t j = 0;
+
+	tgt_svc_cfg = hif_state->tgt_svc_map;
+
+	for (i = 0; i < hif_state->sz_tgt_svc_map; i++) {
+		if (tgt_svc_cfg[i].service_id != LPASS_DATA_MSG_SVC ||
+		    tgt_svc_cfg[i].pipedir != PIPEDIR_IN)
+			continue;
+
+		ce_state = scn->ce_id_to_state[tgt_svc_cfg[i].pipenum];
+		if (!ce_state || !ce_state->dest_ring) {
+			hif_err("Direct Link CE pipe %d not initialized",
+				tgt_svc_cfg[i].pipenum);
+			return QDF_STATUS_E_FAILURE;
+		}
+
+		nbuf_dmaaddr = qdf_mem_malloc(sizeof(*nbuf_dmaaddr) *
+					      ce_state->dest_ring->nentries);
+		if (!nbuf_dmaaddr)
+			return 0;
+
+		for (j = 0; j < ce_state->dest_ring->nentries; j++) {
+			nbuf = ce_state->dest_ring->per_transfer_context[j];
+			if (!nbuf)
+				break;
+
+			nbuf_dmaaddr[j] = QDF_NBUF_CB_PADDR(nbuf);
+		}
+
+		break;
+	}
+
+	*dma_addr = nbuf_dmaaddr;
+
+	return j;
+}
+
+/**
+ * ce_save_srng_info() - Get and save srng information
+ * @hif_ctx: hif context
+ * @srng_info: Direct Link CE srng information
+ * @srng_ctx: Direct Link CE srng context
+ *
+ * Return: QDF status
+ */
+static void
+ce_save_srng_info(struct hif_softc *hif_ctx, struct hif_ce_ring_info *srng_info,
+		  void *srng_ctx)
+{
+	struct hal_srng_params params;
+
+	hal_get_srng_params(hif_ctx->hal_soc, srng_ctx, &params);
+
+	srng_info->ring_id = params.ring_id;
+	srng_info->ring_dir = params.ring_dir;
+	srng_info->num_entries = params.num_entries;
+	srng_info->entry_size = params.entry_size;
+	srng_info->ring_base_paddr = params.ring_base_paddr;
+	srng_info->hp_paddr =
+		      hal_srng_get_hp_addr(hif_ctx->hal_soc, srng_ctx);
+	srng_info->tp_paddr =
+		      hal_srng_get_tp_addr(hif_ctx->hal_soc, srng_ctx);
+}
+
+static
+QDF_STATUS ce_get_direct_link_srng_info(struct hif_softc *scn,
+					struct hif_direct_link_ce_info *info,
+					uint8_t max_ce_info_len)
+{
+	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
+	struct CE_state *ce_state;
+	struct service_to_pipe *tgt_svc_cfg;
+	uint8_t ce_info_idx = 0;
+	uint32_t i;
+
+	tgt_svc_cfg = hif_state->tgt_svc_map;
+
+	for (i = 0; i < hif_state->sz_tgt_svc_map; i++) {
+		if (tgt_svc_cfg[i].service_id != LPASS_DATA_MSG_SVC)
+			continue;
+
+		ce_state = scn->ce_id_to_state[tgt_svc_cfg[i].pipenum];
+		if (!ce_state) {
+			hif_err("Direct Link CE pipe %d not initialized",
+				tgt_svc_cfg[i].pipenum);
+			return QDF_STATUS_E_FAILURE;
+		}
+
+		if (ce_info_idx > max_ce_info_len)
+			return QDF_STATUS_E_FAILURE;
+
+		info[ce_info_idx].ce_id = ce_state->id;
+		info[ce_info_idx].pipe_dir = tgt_svc_cfg[i].pipedir;
+
+		if (ce_state->src_ring)
+			ce_save_srng_info(scn, &info[ce_info_idx].ring_info,
+					  ce_state->src_ring->srng_ctx);
+		else
+			ce_save_srng_info(scn, &info[ce_info_idx].ring_info,
+					  ce_state->dest_ring->srng_ctx);
+
+		ce_info_idx++;
+
+		if (!ce_state->status_ring)
+			continue;
+
+		if (ce_info_idx > max_ce_info_len)
+			return QDF_STATUS_E_FAILURE;
+
+		info[ce_info_idx].ce_id = ce_state->id;
+		info[ce_info_idx].pipe_dir = tgt_svc_cfg[i].pipedir;
+
+		ce_save_srng_info(scn, &info[ce_info_idx].ring_info,
+				  ce_state->status_ring->srng_ctx);
+		ce_info_idx++;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
 #endif
 
 static struct ce_ops ce_service_srng = {
@@ -1182,6 +1312,8 @@ static struct ce_ops ce_service_srng = {
 #endif
 #ifdef FEATURE_DIRECT_LINK
 	.ce_set_irq_config_by_ceid = ce_set_srng_msi_irq_config_by_ceid,
+	.ce_get_direct_link_dest_buffers = ce_get_direct_link_dest_srng_buffers,
+	.ce_get_direct_link_ring_info = ce_get_direct_link_srng_info,
 #endif
 };