Jelajahi Sumber

msm: ipa: Add NTN3 debug stats support

Add debugfs support for NTN3 stats.
Collect stats from uC add print from debugfs.

Change-Id: Iaf31beedb7403ee924a170f3b6c45ce0b78b7680
Signed-off-by: Amir Levy <[email protected]>
Amir Levy 4 tahun lalu
induk
melakukan
4d4a72f1da

+ 69 - 13
drivers/platform/msm/gsi/gsi.c

@@ -4928,25 +4928,81 @@ int gsi_get_refetch_reg(unsigned long chan_hdl, bool is_rp)
 }
 EXPORT_SYMBOL(gsi_get_refetch_reg);
 
-int gsi_get_drop_stats(unsigned long ep_id, int scratch_id)
+int gsi_get_drop_stats(unsigned long ep_id, int scratch_id,
+	unsigned long chan_hdl)
 {
-	/* RTK use scratch 5 */
-	if (scratch_id == 5) {
-		/*
-		 * each channel context is 6 lines of 8 bytes, but n in SHRAM_n
-		 * is in 4 bytes offsets, so multiplying ep_id by 6*2=12 will
-		 * give the beginning of the required channel context, and then
-		 * need to add 7 since the channel context layout has the ring
-		 * rbase (8 bytes) + channel scratch 0-4 (20 bytes) so adding
-		 * additional 28/4 = 7 to get to scratch 5 of the required
-		 * channel.
-		 */
-		gsihal_read_reg_n(GSI_GSI_SHRAM_n, ep_id * 12 + 7);
+#define GSI_RTK_ERR_STATS_MASK 0xFFFF
+#define GSI_NTN_ERR_STATS_MASK 0xFFFFFFFF
+#define GSI_AQC_RX_STATUS_MASK 0x1FFF
+#define GSI_AQC_RX_STATUS_SHIFT 0
+#define GSI_AQC_RDM_ERR_MASK 0x1FFF0000
+#define GSI_AQC_RDM_ERR_SHIFT 16
+
+	uint16_t rx_status;
+	uint16_t rdm_err;
+	uint32_t val;
+
+	/* on newer versions we can read the ch scratch directly from reg */
+	if (gsi_ctx->per.ver >= GSI_VER_3_0) {
+		switch (scratch_id) {
+		case 5:
+			return gsihal_read_reg_nk(
+				GSI_EE_n_GSI_CH_k_SCRATCH_5,
+				gsi_ctx->per.ee,
+				chan_hdl) & GSI_RTK_ERR_STATS_MASK;
+			break;
+		case 6:
+			return gsihal_read_reg_nk(
+				GSI_EE_n_GSI_CH_k_SCRATCH_6,
+				gsi_ctx->per.ee,
+				chan_hdl) & GSI_NTN_ERR_STATS_MASK;
+			break;
+		case 7:
+			val = gsihal_read_reg_nk(
+				GSI_EE_n_GSI_CH_k_SCRATCH_7,
+				gsi_ctx->per.ee,
+				chan_hdl);
+			rx_status = (val & GSI_AQC_RX_STATUS_MASK)
+				>> GSI_AQC_RX_STATUS_SHIFT;
+			rdm_err = (val & GSI_AQC_RDM_ERR_MASK)
+				>> (GSI_AQC_RDM_ERR_SHIFT);
+			return rx_status + rdm_err;
+			break;
+		default:
+			GSIERR("invalid scratch id %d\n", scratch_id);
+			return 0;
+		}
+
+	/* on older versions we need to read the scratch from SHRAM */
+	} else {
+		/* RTK use scratch 5 */
+		if (scratch_id == 5) {
+			/*
+			 * each channel context is 6 lines of 8 bytes, but n in
+			 * SHRAM_n is in 4 bytes offsets, so multiplying ep_id
+			 * by 6*2=12 will give the beginning of the required
+			 * channel context, and then need to add 7 since the
+			 * channel context layout has the ring rbase (8 bytes)
+			 * + channel scratch 0-4 (20 bytes) so adding
+			 * additional 28/4 = 7 to get to scratch 5 of the
+			 * required channel.
+			 */
+			return gsihal_read_reg_n(
+				GSI_GSI_SHRAM_n,
+				ep_id * 12 + 7) & GSI_RTK_ERR_STATS_MASK;
+		}
 	}
 	return 0;
 }
 EXPORT_SYMBOL(gsi_get_drop_stats);
 
+int gsi_get_wp(unsigned long chan_hdl)
+{
+	return gsihal_read_reg_nk(GSI_EE_n_GSI_CH_k_CNTXT_6, gsi_ctx->per.ee,
+		chan_hdl);
+}
+EXPORT_SYMBOL(gsi_get_wp);
+
 void gsi_wdi3_dump_register(unsigned long chan_hdl)
 {
 	uint32_t val;

+ 10 - 1
drivers/platform/msm/gsi/gsi.h

@@ -2233,8 +2233,17 @@ int gsi_get_refetch_reg(unsigned long chan_hdl, bool is_rp);
  *
  * @ep_id: ep index
  * @scratch_id: drop stats on which scratch register
+ * @chan_hdl: gsi channel handle
  */
-int gsi_get_drop_stats(unsigned long ep_id, int scratch_id);
+int gsi_get_drop_stats(unsigned long ep_id, int scratch_id,
+	unsigned long chan_hdl);
+
+/**
+* gsi_get_wp - get channel write pointer for stats
+*
+* @chan_hdl: gsi channel handle
+*/
+int gsi_get_wp(unsigned long chan_hdl);
 
 /**
  * gsi_wdi3_dump_register - dump wdi3 related gsi registers

+ 59 - 40
drivers/platform/msm/ipa/ipa_v3/ipa_client.c

@@ -2014,6 +2014,32 @@ int ipa3_clear_endpoint_delay(u32 clnt_hdl)
 	return 0;
 }
 
+static void ipa3_get_gsi_ring_stats(struct IpaHwRingStats_t *ring,
+	struct ipa3_uc_dbg_stats *ctx_stats, int idx)
+{
+	ring->ringFull = ioread32(
+		ctx_stats->uc_dbg_stats_mmio
+		+ idx * IPA3_UC_DEBUG_STATS_OFF +
+		IPA3_UC_DEBUG_STATS_RINGFULL_OFF);
+
+	ring->ringEmpty = ioread32(
+		ctx_stats->uc_dbg_stats_mmio
+		+ idx * IPA3_UC_DEBUG_STATS_OFF +
+		IPA3_UC_DEBUG_STATS_RINGEMPTY_OFF);
+	ring->ringUsageHigh = ioread32(
+		ctx_stats->uc_dbg_stats_mmio
+		+ idx * IPA3_UC_DEBUG_STATS_OFF +
+		IPA3_UC_DEBUG_STATS_RINGUSAGEHIGH_OFF);
+	ring->ringUsageLow = ioread32(
+		ctx_stats->uc_dbg_stats_mmio
+		+ idx * IPA3_UC_DEBUG_STATS_OFF +
+		IPA3_UC_DEBUG_STATS_RINGUSAGELOW_OFF);
+	ring->RingUtilCount = ioread32(
+		ctx_stats->uc_dbg_stats_mmio
+		+ idx * IPA3_UC_DEBUG_STATS_OFF +
+		IPA3_UC_DEBUG_STATS_RINGUTILCOUNT_OFF);
+}
+
 /**
  * ipa3_get_aqc_gsi_stats() - Query AQC gsi stats from uc
  * @stats:	[inout] stats blob from client populated by driver
@@ -2033,32 +2059,43 @@ int ipa3_get_aqc_gsi_stats(struct ipa_uc_dbg_ring_stats *stats)
 	}
 	IPA_ACTIVE_CLIENTS_INC_SIMPLE();
 	for (i = 0; i < MAX_AQC_CHANNELS; i++) {
-		stats->u.ring[i].ringFull = ioread32(
-			ipa3_ctx->aqc_ctx.dbg_stats.uc_dbg_stats_mmio
-			+ i * IPA3_UC_DEBUG_STATS_OFF +
-			IPA3_UC_DEBUG_STATS_RINGFULL_OFF);
-		stats->u.ring[i].ringEmpty = ioread32(
-			ipa3_ctx->aqc_ctx.dbg_stats.uc_dbg_stats_mmio
-			+ i * IPA3_UC_DEBUG_STATS_OFF +
-			IPA3_UC_DEBUG_STATS_RINGEMPTY_OFF);
-		stats->u.ring[i].ringUsageHigh = ioread32(
-			ipa3_ctx->aqc_ctx.dbg_stats.uc_dbg_stats_mmio
-			+ i * IPA3_UC_DEBUG_STATS_OFF +
-			IPA3_UC_DEBUG_STATS_RINGUSAGEHIGH_OFF);
-		stats->u.ring[i].ringUsageLow = ioread32(
-			ipa3_ctx->aqc_ctx.dbg_stats.uc_dbg_stats_mmio
-			+ i * IPA3_UC_DEBUG_STATS_OFF +
-			IPA3_UC_DEBUG_STATS_RINGUSAGELOW_OFF);
-		stats->u.ring[i].RingUtilCount = ioread32(
-			ipa3_ctx->aqc_ctx.dbg_stats.uc_dbg_stats_mmio
-			+ i * IPA3_UC_DEBUG_STATS_OFF +
-			IPA3_UC_DEBUG_STATS_RINGUTILCOUNT_OFF);
+		ipa3_get_gsi_ring_stats(stats->u.ring + i,
+			&ipa3_ctx->aqc_ctx.dbg_stats, i);
+	}
+	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
+
+
+	return 0;
+}
+
+/**
+* ipa3_get_ntn_gsi_stats() - Query NTN gsi stats from uc
+* @stats:	[inout] stats blob from client populated by driver
+*
+* Returns:	0 on success, negative on failure
+*
+* @note Cannot be called from atomic context
+*
+*/
+int ipa3_get_ntn_gsi_stats(struct ipa_uc_dbg_ring_stats *stats)
+{
+	int i;
+
+	if (!ipa3_ctx->ntn_ctx.dbg_stats.uc_dbg_stats_mmio) {
+		IPAERR("bad parms NULL ntn_gsi_stats_mmio\n");
+		return -EINVAL;
+	}
+	IPA_ACTIVE_CLIENTS_INC_SIMPLE();
+	for (i = 0; i < MAX_NTN_CHANNELS; i++) {
+		ipa3_get_gsi_ring_stats(stats->u.ring + i,
+			&ipa3_ctx->ntn_ctx.dbg_stats, i);
 	}
 	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
 
 
 	return 0;
 }
+
 /**
  * ipa3_get_rtk_gsi_stats() - Query RTK gsi stats from uc
  * @stats:	[inout] stats blob from client populated by driver
@@ -2079,26 +2116,8 @@ int ipa3_get_rtk_gsi_stats(struct ipa_uc_dbg_ring_stats *stats)
 	}
 	IPA_ACTIVE_CLIENTS_INC_SIMPLE();
 	for (i = 0; i < MAX_RTK_CHANNELS; i++) {
-		stats->u.rtk[i].commStats.ringFull = ioread32(
-			ipa3_ctx->rtk_ctx.dbg_stats.uc_dbg_stats_mmio
-			+ i * IPA3_UC_DEBUG_STATS_RTK_OFF +
-			IPA3_UC_DEBUG_STATS_RINGFULL_OFF);
-		stats->u.rtk[i].commStats.ringEmpty = ioread32(
-			ipa3_ctx->rtk_ctx.dbg_stats.uc_dbg_stats_mmio
-			+ i * IPA3_UC_DEBUG_STATS_RTK_OFF +
-			IPA3_UC_DEBUG_STATS_RINGEMPTY_OFF);
-		stats->u.rtk[i].commStats.ringUsageHigh = ioread32(
-			ipa3_ctx->rtk_ctx.dbg_stats.uc_dbg_stats_mmio
-			+ i * IPA3_UC_DEBUG_STATS_RTK_OFF +
-			IPA3_UC_DEBUG_STATS_RINGUSAGEHIGH_OFF);
-		stats->u.rtk[i].commStats.ringUsageLow = ioread32(
-			ipa3_ctx->rtk_ctx.dbg_stats.uc_dbg_stats_mmio
-			+ i * IPA3_UC_DEBUG_STATS_RTK_OFF +
-			IPA3_UC_DEBUG_STATS_RINGUSAGELOW_OFF);
-		stats->u.rtk[i].commStats.RingUtilCount = ioread32(
-			ipa3_ctx->rtk_ctx.dbg_stats.uc_dbg_stats_mmio
-			+ i * IPA3_UC_DEBUG_STATS_RTK_OFF +
-			IPA3_UC_DEBUG_STATS_RINGUTILCOUNT_OFF);
+		ipa3_get_gsi_ring_stats(&stats->u.rtk[i].commStats,
+			&ipa3_ctx->rtk_ctx.dbg_stats, i);
 		stats->u.rtk[i].trCount = ioread32(
 			ipa3_ctx->rtk_ctx.dbg_stats.uc_dbg_stats_mmio
 			+ i * IPA3_UC_DEBUG_STATS_RTK_OFF +

+ 28 - 15
drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c

@@ -3216,9 +3216,16 @@ static ssize_t ipa3_eth_read_perf_status(struct file *file,
 	switch (client->client_type) {
 	case IPA_ETH_CLIENT_AQC107:
 	case IPA_ETH_CLIENT_AQC113:
-		ret = ipa3_get_aqc_gsi_stats(&stats);
-		tx_ep = IPA_CLIENT_AQC_ETHERNET_CONS;
-		rx_ep = IPA_CLIENT_AQC_ETHERNET_PROD;
+	case IPA_ETH_CLIENT_NTN:
+		if (client->client_type == IPA_ETH_CLIENT_NTN) {
+			ret = ipa3_get_ntn_gsi_stats(&stats);
+			tx_ep = IPA_CLIENT_ETHERNET_CONS;
+			rx_ep = IPA_CLIENT_ETHERNET_PROD;
+		} else {
+			ret = ipa3_get_aqc_gsi_stats(&stats);
+			tx_ep = IPA_CLIENT_AQC_ETHERNET_CONS;
+			rx_ep = IPA_CLIENT_AQC_ETHERNET_PROD;
+		}
 		if (!ret) {
 			nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
 			"%s_ringFull=%u\n"
@@ -3258,7 +3265,9 @@ static ssize_t ipa3_eth_read_perf_status(struct file *file,
 		} else {
 			nbytes = scnprintf(dbg_buff,
 				IPA_MAX_MSG_LEN,
-				"Fail to read AQC GSI stats\n");
+				"Fail to read [%s][%s] GSI stats\n",
+				ipa_clients_strings[rx_ep],
+				ipa_clients_strings[tx_ep]);
 			cnt += nbytes;
 		}
 		break;
@@ -3329,7 +3338,7 @@ static ssize_t ipa3_eth_read_perf_status(struct file *file,
 			cnt += nbytes;
 		} else {
 			nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
-				"Fail to read AQC GSI stats\n");
+				"Fail to read RTK GSI stats\n");
 			cnt += nbytes;
 		}
 		break;
@@ -3350,6 +3359,7 @@ static ssize_t ipa3_eth_read_err_status(struct file *file,
 	int tx_ep, rx_ep;
 	struct ipa3_eth_error_stats tx_stats;
 	struct ipa3_eth_error_stats rx_stats;
+	int scratch_num;
 
 	memset(&tx_stats, 0, sizeof(struct ipa3_eth_error_stats));
 	memset(&rx_stats, 0, sizeof(struct ipa3_eth_error_stats));
@@ -3368,42 +3378,45 @@ static ssize_t ipa3_eth_read_err_status(struct file *file,
 	case IPA_ETH_CLIENT_AQC113:
 		tx_ep = IPA_CLIENT_AQC_ETHERNET_CONS;
 		rx_ep = IPA_CLIENT_AQC_ETHERNET_PROD;
-		break;
+		scratch_num = 7;
 	case IPA_ETH_CLIENT_RTK8111K:
 	case IPA_ETH_CLIENT_RTK8125B:
 		tx_ep = IPA_CLIENT_RTK_ETHERNET_CONS;
 		rx_ep = IPA_CLIENT_RTK_ETHERNET_PROD;
-		ipa3_eth_get_status(tx_ep, 5, &tx_stats);
-		ipa3_eth_get_status(rx_ep, 5, &rx_stats);
+		scratch_num = 5;
 		break;
+	case IPA_ETH_CLIENT_NTN:
+		tx_ep = IPA_CLIENT_ETHERNET_CONS;
+		rx_ep = IPA_CLIENT_ETHERNET_PROD;
+		scratch_num = 6;
 	default:
 		IPAERR("Not supported\n");
 		return 0;
 	}
+	ipa3_eth_get_status(tx_ep, scratch_num, &tx_stats);
+	ipa3_eth_get_status(rx_ep, scratch_num, &rx_stats);
+
 	nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
 		"%s_RP=0x%x\n"
 		"%s_WP=0x%x\n"
-		"%s_SCRATCH5=0x%x\n",
+		"%s_err:%u (scratch %d)\n",
 		ipa_clients_strings[tx_ep],
 		tx_stats.rp,
 		ipa_clients_strings[tx_ep],
 		tx_stats.wp,
 		ipa_clients_strings[tx_ep],
-		tx_stats.err);
+		tx_stats.err, scratch_num);
 	cnt += nbytes;
 	nbytes = scnprintf(dbg_buff + cnt, IPA_MAX_MSG_LEN - cnt,
 		"%s_RP=0x%x\n"
 		"%s_WP=0x%x\n"
-		"%s_SCRATCH5=0x%x\n"
-		"%s_err:%u\n",
+		"%s_err:%u (scratch %d)\n",
 		ipa_clients_strings[rx_ep],
 		rx_stats.rp,
 		ipa_clients_strings[rx_ep],
 		rx_stats.wp,
 		ipa_clients_strings[rx_ep],
-		rx_stats.err,
-		ipa_clients_strings[rx_ep],
-		rx_stats.err & 0xff);
+		rx_stats.err, scratch_num);
 	cnt += nbytes;
 done:
 	return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, cnt);

+ 1 - 1
drivers/platform/msm/ipa/ipa_v3/ipa_eth_i.c

@@ -915,7 +915,7 @@ int ipa3_eth_connect(
 		return -EINVAL;
 	}
 
-	if ((pipe->client_info->client_type == IPA_ETH_CLIENT_NTN)) {
+	if (pipe->client_info->client_type == IPA_ETH_CLIENT_NTN) {
 		if (pipe->info.fix_buffer_size != NTN_BUFFER_SIZE) {
 			IPAERR("fix buffer size %u not valid for NTN, use 2K\n"
 				, pipe->info.fix_buffer_size);

+ 9 - 0
drivers/platform/msm/ipa/ipa_v3/ipa_i.h

@@ -1710,6 +1710,13 @@ struct ipa3_rtk_ctx {
 	struct ipa3_uc_dbg_stats dbg_stats;
 };
 
+/**
+* struct ipa3_ntn_ctx - IPA ntn context
+*/
+struct ipa3_ntn_ctx {
+	struct ipa3_uc_dbg_stats dbg_stats;
+};
+
 /**
  * struct ipa3_transport_pm - transport power management related members
  * @transport_pm_mutex: Mutex to protect the transport_pm functionality.
@@ -2180,6 +2187,7 @@ struct ipa3_context {
 	struct ipa3_mhip_ctx mhip_ctx;
 	struct ipa3_aqc_ctx aqc_ctx;
 	struct ipa3_rtk_ctx rtk_ctx;
+	struct ipa3_ntn_ctx ntn_ctx;
 	atomic_t ipa_clk_vote;
 
 	int (*client_lock_unlock[IPA_MAX_CLNT])(bool is_lock);
@@ -2789,6 +2797,7 @@ int ipa3_get_wdi3_gsi_stats(struct ipa_uc_dbg_ring_stats *stats);
 int ipa3_get_usb_gsi_stats(struct ipa_uc_dbg_ring_stats *stats);
 int ipa3_get_aqc_gsi_stats(struct ipa_uc_dbg_ring_stats *stats);
 int ipa3_get_rtk_gsi_stats(struct ipa_uc_dbg_ring_stats *stats);
+int ipa3_get_ntn_gsi_stats(struct ipa_uc_dbg_ring_stats *stats);
 int ipa3_get_wdi_stats(struct IpaHwStatsWDIInfoData_t *stats);
 u16 ipa3_get_smem_restr_bytes(void);
 int ipa3_broadcast_wdi_quota_reach_ind(uint32_t fid, uint64_t num_bytes);

+ 15 - 0
drivers/platform/msm/ipa/ipa_v3/ipa_uc.c

@@ -440,6 +440,17 @@ static void ipa3_uc_save_dbg_stats(u32 size)
 		} else
 			goto unmap;
 		break;
+	case IPA_HW_PROTOCOL_NTN3:
+		if (!ipa3_ctx->ntn_ctx.dbg_stats.uc_dbg_stats_mmio) {
+			ipa3_ctx->ntn_ctx.dbg_stats.uc_dbg_stats_size =
+				size;
+			ipa3_ctx->ntn_ctx.dbg_stats.uc_dbg_stats_ofst =
+				addr_offset;
+			ipa3_ctx->ntn_ctx.dbg_stats.uc_dbg_stats_mmio =
+				mmio;
+		} else
+			goto unmap;
+		break;
 	case IPA_HW_PROTOCOL_WDI:
 		if (!ipa3_ctx->wdi2_ctx.dbg_stats.uc_dbg_stats_mmio) {
 			ipa3_ctx->wdi2_ctx.dbg_stats.uc_dbg_stats_size =
@@ -1627,6 +1638,10 @@ int ipa3_uc_debug_stats_dealloc(uint32_t prot_id)
 		iounmap(ipa3_ctx->rtk_ctx.dbg_stats.uc_dbg_stats_mmio);
 		ipa3_ctx->rtk_ctx.dbg_stats.uc_dbg_stats_mmio = NULL;
 		break;
+	case IPA_HW_PROTOCOL_NTN3:
+		iounmap(ipa3_ctx->ntn_ctx.dbg_stats.uc_dbg_stats_mmio);
+		ipa3_ctx->ntn_ctx.dbg_stats.uc_dbg_stats_mmio = NULL;
+		break;
 	case IPA_HW_PROTOCOL_WDI:
 		iounmap(ipa3_ctx->wdi2_ctx.dbg_stats.uc_dbg_stats_mmio);
 		ipa3_ctx->wdi2_ctx.dbg_stats.uc_dbg_stats_mmio = NULL;

+ 1 - 0
drivers/platform/msm/ipa/ipa_v3/ipa_uc_offload_i.h

@@ -25,6 +25,7 @@
 
 #define MAX_AQC_CHANNELS 2
 #define MAX_RTK_CHANNELS 2
+#define MAX_NTN_CHANNELS 2
 #define MAX_11AD_CHANNELS 5
 #define MAX_WDI2_CHANNELS 2
 #define MAX_WDI3_CHANNELS 3

+ 44 - 4
drivers/platform/msm/ipa/ipa_v3/ipa_utils.c

@@ -11640,7 +11640,9 @@ void ipa3_get_gsi_stats(int prot_id,
 		stats->num_ch = MAX_WDI3_CHANNELS;
 		ipa3_get_wdi3_gsi_stats(stats);
 		break;
-	case IPA_HW_PROTOCOL_ETH:
+	case IPA_HW_PROTOCOL_NTN3:
+		stats->num_ch = MAX_NTN_CHANNELS;
+		ipa3_get_ntn_gsi_stats(stats);
 		break;
 	case IPA_HW_PROTOCOL_MHIP:
 		stats->num_ch = MAX_MHIP_CHANNELS;
@@ -11796,6 +11798,10 @@ int ipa3_get_prot_id(enum ipa_client_type client)
 void ipa3_eth_get_status(u32 client, int scratch_id,
 	struct ipa3_eth_error_stats *stats)
 {
+#define RTK_GSI_SCRATCH_ID 5
+#define AQC_GSI_SCRATCH_ID 7
+#define NTN_GSI_SCRATCH_ID 6
+
 	int ch_id;
 	int ipa_ep_idx;
 
@@ -11804,9 +11810,43 @@ void ipa3_eth_get_status(u32 client, int scratch_id,
 	if (ipa_ep_idx == IPA_EP_NOT_ALLOCATED)
 		return;
 	ch_id = ipa3_ctx->ep[ipa_ep_idx].gsi_chan_hdl;
-	stats->rp = gsi_get_refetch_reg(ch_id, true);
-	stats->wp = gsi_get_refetch_reg(ch_id, false);
-	stats->err = gsi_get_drop_stats(ipa_ep_idx, scratch_id);
+
+	/*
+	 * drop stats sometimes exist for RX and sometimes for Tx,
+	 * wp sometimes acquired from ch_cntxt_6 and sometimes from refetch,
+	 * depending on protocol.
+	 */
+	stats->err = 0;
+	switch (client) {
+	case IPA_CLIENT_RTK_ETHERNET_PROD:
+		stats->err = gsi_get_drop_stats(ipa_ep_idx, RTK_GSI_SCRATCH_ID,
+			ch_id);
+	case IPA_CLIENT_RTK_ETHERNET_CONS:
+		stats->wp = gsi_get_refetch_reg(ch_id, false);
+		stats->rp = gsi_get_refetch_reg(ch_id, true);
+		break;
+
+	case IPA_CLIENT_AQC_ETHERNET_PROD:
+		stats->err = gsi_get_drop_stats(ipa_ep_idx, AQC_GSI_SCRATCH_ID,
+			ch_id);
+		stats->wp = gsi_get_wp(ch_id);
+		stats->rp = gsi_get_refetch_reg(ch_id, true);
+		break;
+	case IPA_CLIENT_AQC_ETHERNET_CONS:
+		stats->wp = gsi_get_refetch_reg(ch_id, false);
+		stats->rp = gsi_get_refetch_reg(ch_id, true);
+		break;
+	case IPA_CLIENT_ETHERNET_PROD:
+		stats->wp = gsi_get_wp(ch_id);
+		stats->rp = gsi_get_refetch_reg(ch_id, true);
+		break;
+	case IPA_CLIENT_ETHERNET_CONS:
+		stats->err = gsi_get_drop_stats(ipa_ep_idx, NTN_GSI_SCRATCH_ID,
+			ch_id);
+		stats->wp = gsi_get_refetch_reg(ch_id, false);
+		stats->rp = gsi_get_refetch_reg(ch_id, true);
+		break;
+	}
 	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
 }