Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4accc57b authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: IPA: uC debug stats for gsi offloading protocols"

parents c2795af5 d7238989
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -6143,7 +6143,7 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
		struct platform_device *ipa_pdev)
{
	int result = 0;
	int i;
	int i, j;
	struct ipa3_rt_tbl_set *rset;
	struct ipa_active_client_logging_info log_info;
	struct cdev *cdev;
@@ -6165,6 +6165,15 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
	for (i = 0; i < IPA_SMMU_CB_MAX; i++)
		ipa3_ctx->s1_bypass_arr[i] = true;

	/* initialize the gsi protocol info for uC debug stats */
	for (i = 0; i < IPA_HW_PROTOCOL_MAX; i++) {
		ipa3_ctx->gsi_info[i].protocol = i;
		/* initialize all to be not started */
		for (j = 0; j < MAX_CH_STATS_SUPPORTED; j++)
			ipa3_ctx->gsi_info[i].ch_id_info[j].ch_id =
				0xFF;
	}

	ipa3_ctx->ipa_wrapper_base = resource_p->ipa_mem_base;
	ipa3_ctx->ipa_wrapper_size = resource_p->ipa_mem_size;
	ipa3_ctx->ipa_hw_type = resource_p->ipa_hw_type;
+146 −0
Original line number Diff line number Diff line
@@ -1956,6 +1956,136 @@ static ssize_t ipa3_read_ipahal_regs(struct file *file, char __user *ubuf,
	return 0;
}

static ssize_t ipa3_read_wdi_gsi_stats(struct file *file,
		char __user *ubuf, size_t count, loff_t *ppos)
{
	struct ipa3_uc_dbg_ring_stats stats;
	int nbytes;
	int cnt = 0;

	if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_5) {
		nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
				"This feature only support on IPA4.5+\n");
		cnt += nbytes;
		goto done;
	}

	if (!ipa3_get_wdi_gsi_stats(&stats)) {
		nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
			"TX ringFull=%u\n"
			"TX ringEmpty=%u\n"
			"TX ringUsageHigh=%u\n"
			"TX ringUsageLow=%u\n"
			"TX RingUtilCount=%u\n",
			stats.ring[1].ringFull,
			stats.ring[1].ringEmpty,
			stats.ring[1].ringUsageHigh,
			stats.ring[1].ringUsageLow,
			stats.ring[1].RingUtilCount);
		cnt += nbytes;
		nbytes = scnprintf(dbg_buff + cnt, IPA_MAX_MSG_LEN - cnt,
			"RX ringFull=%u\n"
			"RX ringEmpty=%u\n"
			"RX ringUsageHigh=%u\n"
			"RX ringUsageLow=%u\n"
			"RX RingUtilCount=%u\n",
			stats.ring[0].ringFull,
			stats.ring[0].ringEmpty,
			stats.ring[0].ringUsageHigh,
			stats.ring[0].ringUsageLow,
			stats.ring[0].RingUtilCount);
		cnt += nbytes;
	} else {
		nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
				"Fail to read WDI GSI stats\n");
		cnt += nbytes;
	}
done:
	return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, cnt);
}

static ssize_t ipa3_read_wdi3_gsi_stats(struct file *file,
		char __user *ubuf, size_t count, loff_t *ppos)
{
	struct ipa3_uc_dbg_ring_stats stats;
	int nbytes;
	int cnt = 0;

	if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_5) {
		nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
				"This feature only support on IPA4.5+\n");
		cnt += nbytes;
		goto done;
	}
	if (!ipa3_get_wdi3_gsi_stats(&stats)) {
		nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
			"TX ringFull=%u\n"
			"TX ringEmpty=%u\n"
			"TX ringUsageHigh=%u\n"
			"TX ringUsageLow=%u\n"
			"TX RingUtilCount=%u\n",
			stats.ring[1].ringFull,
			stats.ring[1].ringEmpty,
			stats.ring[1].ringUsageHigh,
			stats.ring[1].ringUsageLow,
			stats.ring[1].RingUtilCount);
		cnt += nbytes;
		nbytes = scnprintf(dbg_buff + cnt, IPA_MAX_MSG_LEN - cnt,
			"RX ringFull=%u\n"
			"RX ringEmpty=%u\n"
			"RX ringUsageHigh=%u\n"
			"RX ringUsageLow=%u\n"
			"RX RingUtilCount=%u\n",
			stats.ring[0].ringFull,
			stats.ring[0].ringEmpty,
			stats.ring[0].ringUsageHigh,
			stats.ring[0].ringUsageLow,
			stats.ring[0].RingUtilCount);
		cnt += nbytes;
	} else {
		nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
				"Fail to read WDI GSI stats\n");
		cnt += nbytes;
	}

done:
	return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, cnt);
}

static ssize_t ipa3_read_11ad_gsi_stats(struct file *file,
		char __user *ubuf, size_t count, loff_t *ppos)
{
	int nbytes;
	int cnt = 0;

	if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_5) {
		nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
				"This feature only support on IPA4.5+\n");
		cnt += nbytes;
		goto done;
	}
	return 0;
done:
	return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, cnt);
}

static ssize_t ipa3_read_aqc_gsi_stats(struct file *file,
		char __user *ubuf, size_t count, loff_t *ppos)
{
	int nbytes;
	int cnt = 0;

	if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_5) {
		nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
				"This feature only support on IPA4.5+\n");
		cnt += nbytes;
		goto done;
	}
	return 0;
done:
	return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, cnt);
}

static void ipa_dump_status(struct ipahal_pkt_status *status)
{
	IPA_DUMP_STATUS_FIELD(status_opcode);
@@ -2230,6 +2360,22 @@ static const struct ipa3_debugfs_file debugfs_files[] = {
		"ipa_dump_regs", IPA_READ_ONLY_MODE, NULL, {
			.read = ipa3_read_ipahal_regs,
		}
	}, {
		"wdi_gsi_stats", IPA_READ_ONLY_MODE, NULL, {
			.read = ipa3_read_wdi_gsi_stats,
		}
	}, {
		"wdi3_gsi_stats", IPA_READ_ONLY_MODE, NULL, {
			.read = ipa3_read_wdi3_gsi_stats,
		}
	}, {
		"11ad_gsi_stats", IPA_READ_ONLY_MODE, NULL, {
			.read = ipa3_read_11ad_gsi_stats,
		}
	}, {
		"aqc_gsi_stats", IPA_READ_ONLY_MODE, NULL, {
			.read = ipa3_read_aqc_gsi_stats,
		}
	}
};

+49 −0
Original line number Diff line number Diff line
@@ -1296,6 +1296,36 @@ struct ipa3_stats {
	u32 tx_non_linear;
};

/* offset for each stats */
#define IPA3_UC_DEBUG_STATS_RINGFULL_OFF (0)
#define IPA3_UC_DEBUG_STATS_RINGEMPTY_OFF (4)
#define IPA3_UC_DEBUG_STATS_RINGUSAGEHIGH_OFF (8)
#define IPA3_UC_DEBUG_STATS_RINGUSAGELOW_OFF (12)
#define IPA3_UC_DEBUG_STATS_RINGUTILCOUNT_OFF (16)
#define IPA3_UC_DEBUG_STATS_OFF (20)

/**
 * struct ipa3_uc_dbg_gsi_stats - uC dbg stats info for each
 * offloading protocol
 * @ring: ring stats for each channel
 */
struct ipa3_uc_dbg_ring_stats {
	struct IpaHwRingStats_t ring[MAX_CH_STATS_SUPPORTED];
};

/**
 * struct ipa3_uc_dbg_stats - uC dbg stats for offloading
 * protocols
 * @uc_dbg_stats_ofst: offset to SRAM base
 * @uc_dbg_stats_size: stats size for all channels
 * @uc_dbg_stats_mmio: mmio offset
 */
struct ipa3_uc_dbg_stats {
	u32 uc_dbg_stats_ofst;
	u16 uc_dbg_stats_size;
	void __iomem *uc_dbg_stats_mmio;
};

struct ipa3_active_clients {
	struct mutex mutex;
	atomic_t cnt;
@@ -1443,7 +1473,16 @@ struct ipa3_wdi2_ctx {
	u32 rdy_comp_ring_size;
	u32 *rdy_ring_rp_va;
	u32 *rdy_comp_ring_wp_va;
	struct ipa3_uc_dbg_stats dbg_stats;
};

/**
 * struct ipa3_wdi3_ctx - IPA wdi3 context
 */
struct ipa3_wdi3_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.
@@ -1684,6 +1723,8 @@ struct ipa3_pc_mbox_data {
 * @mhi_evid_limits: MHI event rings start and end ids
 *  finished initializing. Example of use - IOCTLs to /dev/ipa
 * @flt_rt_counters: the counters usage info for flt rt stats
 * @wdi3_ctx: IPA wdi3 context
 * @gsi_info: channel/protocol info for GSI offloading uC stats
 * IPA context - holds all relevant info about IPA driver and its state
 */
struct ipa3_context {
@@ -1839,6 +1880,7 @@ struct ipa3_context {
	void __iomem *reg_collection_base;
	struct ipa3_wdi2_ctx wdi2_ctx;
	struct ipa3_pc_mbox_data pc_mbox;
	struct ipa3_wdi3_ctx wdi3_ctx;
	atomic_t ipa_clk_vote;
	int gsi_chk_intset_value;
	int uc_mailbox17_chk;
@@ -1847,6 +1889,8 @@ struct ipa3_context {
	atomic_t is_ssr;
	bool (*get_teth_port_state[IPA_MAX_CLNT])(void);
	bool fw_loaded;
	struct IpaHwOffloadStatsAllocCmdData_t
		gsi_info[IPA_HW_PROTOCOL_MAX];
};

struct ipa3_plat_drv_res {
@@ -2428,6 +2472,7 @@ int ipa3_disconnect_gsi_wdi_pipe(u32 clnt_hdl);
int ipa3_resume_wdi_pipe(u32 clnt_hdl);
int ipa3_resume_gsi_wdi_pipe(u32 clnt_hdl);
int ipa3_suspend_wdi_pipe(u32 clnt_hdl);
int ipa3_get_wdi_gsi_stats(struct ipa3_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);
@@ -2738,6 +2783,7 @@ int ipa3_write_qmapid_wdi_pipe(u32 clnt_hdl, u8 qmap_id);
int ipa3_write_qmapid_wdi3_gsi_pipe(u32 clnt_hdl, u8 qmap_id);
int ipa3_tag_process(struct ipa3_desc *desc, int num_descs,
		    unsigned long timeout);
int ipa3_get_wdi3_gsi_stats(struct ipa3_uc_dbg_ring_stats *stats);

void ipa3_q6_pre_shutdown_cleanup(void);
void ipa3_q6_post_shutdown_cleanup(void);
@@ -2783,6 +2829,9 @@ int ipa3_uc_mhi_stop_event_update_channel(int channelHandle);
int ipa3_uc_mhi_print_stats(char *dbg_buff, int size);
int ipa3_uc_memcpy(phys_addr_t dest, phys_addr_t src, int len);
int ipa3_uc_send_remote_ipa_info(u32 remote_addr, uint32_t mbox_n);
int ipa3_uc_debug_stats_alloc(
	struct IpaHwOffloadStatsAllocCmdData_t cmdinfo);
int ipa3_uc_debug_stats_dealloc(uint32_t protocol);
void ipa3_tag_destroy_imm(void *user1, int user2);
const struct ipa_gsi_ep_config *ipa3_get_gsi_ep_info
	(enum ipa_client_type client);
+144 −2
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@
#define IPA_UC_POLL_SLEEP_USEC 100
#define IPA_UC_POLL_MAX_RETRY 10000

#define IPA_UC_DBG_STATS_GET_PROT_ID(x) (0xff & ((x) >> 24))
#define IPA_UC_DBG_STATS_GET_OFFSET(x) (0x00ffffff & (x))

/**
 * Mailbox register to Interrupt HWP for CPU cmd
 * Usage of IPA_UC_MAILBOX_m_n doorbell instead of IPA_IRQ_EE_UC_0
@@ -121,7 +124,7 @@ struct IpaHwRegWriteCmdData_t {
 * for IPA_HW_2_CPU_RESPONSE_CMD_COMPLETED response.
 * @originalCmdOp : The original command opcode
 * @status : 0 for success indication, otherwise failure
 * @reserved : Reserved
 * @responseData : 16b responseData
 *
 * Parameters are sent as 32b immediate parameters.
 */
@@ -129,7 +132,7 @@ union IpaHwCpuCmdCompletedResponseData_t {
	struct IpaHwCpuCmdCompletedResponseParams_t {
		u32 originalCmdOp:8;
		u32 status:8;
		u32 reserved:16;
		u32 responseData:16;
	} __packed params;
	u32 raw32b;
} __packed;
@@ -220,6 +223,45 @@ const char *ipa_hw_error_str(enum ipa3_hw_errors err_type)
	return str;
}

static void ipa3_uc_save_dbg_stats(u32 size)
{
	u8 protocol_id;
	u32 addr_offset;
	void __iomem *mmio;

	protocol_id = IPA_UC_DBG_STATS_GET_PROT_ID(
		ipa3_ctx->uc_ctx.uc_sram_mmio->responseParams_1);
	addr_offset = IPA_UC_DBG_STATS_GET_OFFSET(
		ipa3_ctx->uc_ctx.uc_sram_mmio->responseParams_1);
	mmio = ioremap(ipa3_ctx->ipa_wrapper_base +
		addr_offset, sizeof(struct IpaHwRingStats_t) *
		MAX_CH_STATS_SUPPORTED);
	if (mmio == NULL) {
		IPAERR("unexpected NULL mmio\n");
		return;
	}
	switch (protocol_id) {
	case IPA_HW_PROTOCOL_AQC:
		break;
	case IPA_HW_PROTOCOL_11ad:
		break;
	case IPA_HW_PROTOCOL_WDI:
		ipa3_ctx->wdi2_ctx.dbg_stats.uc_dbg_stats_size = size;
		ipa3_ctx->wdi2_ctx.dbg_stats.uc_dbg_stats_ofst = addr_offset;
		ipa3_ctx->wdi2_ctx.dbg_stats.uc_dbg_stats_mmio = mmio;
		break;
	case IPA_HW_PROTOCOL_WDI3:
		ipa3_ctx->wdi3_ctx.dbg_stats.uc_dbg_stats_size = size;
		ipa3_ctx->wdi3_ctx.dbg_stats.uc_dbg_stats_ofst = addr_offset;
		ipa3_ctx->wdi3_ctx.dbg_stats.uc_dbg_stats_mmio = mmio;
		break;
	case IPA_HW_PROTOCOL_ETH:
		break;
	default:
		IPAERR("unknown protocols %d\n", protocol_id);
	}
}

static void ipa3_log_evt_hdlr(void)
{
	int i;
@@ -519,6 +561,10 @@ static void ipa3_uc_response_hdlr(enum ipa_irq_type interrupt,
		if (uc_rsp.params.originalCmdOp ==
		    ipa3_ctx->uc_ctx.pending_cmd) {
			ipa3_ctx->uc_ctx.uc_status = uc_rsp.params.status;
			if (uc_rsp.params.originalCmdOp ==
				IPA_CPU_2_HW_CMD_OFFLOAD_STATS_ALLOC)
				ipa3_uc_save_dbg_stats(
					uc_rsp.params.responseData);
			complete_all(&ipa3_ctx->uc_ctx.uc_completion);
		} else {
			IPAERR("Expected cmd=%u rcvd cmd=%u\n",
@@ -964,3 +1010,99 @@ int ipa3_uc_send_remote_ipa_info(u32 remote_addr, uint32_t mbox_n)
	dma_free_coherent(ipa3_ctx->uc_pdev, cmd.size, cmd.base, cmd.phys_base);
	return res;
}

int ipa3_uc_debug_stats_alloc(
	struct IpaHwOffloadStatsAllocCmdData_t cmdinfo)
{
	int result;
	struct ipa_mem_buffer cmd;
	enum ipa_cpu_2_hw_offload_commands command;
	struct IpaHwOffloadStatsAllocCmdData_t *cmd_data;

	cmd.size = sizeof(*cmd_data);
	cmd.base = dma_alloc_coherent(ipa3_ctx->uc_pdev, cmd.size,
		&cmd.phys_base, GFP_KERNEL);
	if (cmd.base == NULL) {
		result = -ENOMEM;
		return result;
	}
	cmd_data = (struct IpaHwOffloadStatsAllocCmdData_t *)cmd.base;
	memcpy(cmd_data, &cmdinfo,
		sizeof(struct IpaHwOffloadStatsAllocCmdData_t));
	command = IPA_CPU_2_HW_CMD_OFFLOAD_STATS_ALLOC;

	IPA_ACTIVE_CLIENTS_INC_SIMPLE();

	result = ipa3_uc_send_cmd((u32)(cmd.phys_base),
		command,
		IPA_HW_2_CPU_OFFLOAD_CMD_STATUS_SUCCESS,
		false, 10 * HZ);
	if (result) {
		IPAERR("fail to alloc offload stats\n");
		goto cleanup;
	}
	result = 0;
cleanup:
	dma_free_coherent(ipa3_ctx->uc_pdev,
		cmd.size,
		cmd.base, cmd.phys_base);
	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
	IPADBG("exit\n");
	return result;
}

int ipa3_uc_debug_stats_dealloc(uint32_t protocol)
{
	int result;
	struct ipa_mem_buffer cmd;
	enum ipa_cpu_2_hw_offload_commands command;
	struct IpaHwOffloadStatsDeAllocCmdData_t *cmd_data;

	cmd.size = sizeof(*cmd_data);
	cmd.base = dma_alloc_coherent(ipa3_ctx->uc_pdev, cmd.size,
		&cmd.phys_base, GFP_KERNEL);
	if (cmd.base == NULL) {
		result = -ENOMEM;
		return result;
	}
	cmd_data = (struct IpaHwOffloadStatsDeAllocCmdData_t *)
		cmd.base;
	cmd_data->protocol = protocol;
	command = IPA_CPU_2_HW_CMD_OFFLOAD_STATS_DEALLOC;

	IPA_ACTIVE_CLIENTS_INC_SIMPLE();

	result = ipa3_uc_send_cmd((u32)(cmd.phys_base),
		command,
		IPA_HW_2_CPU_OFFLOAD_CMD_STATUS_SUCCESS,
		false, 10 * HZ);
	if (result) {
		IPAERR("fail to dealloc offload stats\n");
		goto cleanup;
	}
	switch (protocol) {
	case IPA_HW_PROTOCOL_AQC:
		break;
	case IPA_HW_PROTOCOL_11ad:
		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;
		break;
	case IPA_HW_PROTOCOL_WDI3:
		iounmap(ipa3_ctx->wdi3_ctx.dbg_stats.uc_dbg_stats_mmio);
		ipa3_ctx->wdi3_ctx.dbg_stats.uc_dbg_stats_mmio = NULL;
		break;
	case IPA_HW_PROTOCOL_ETH:
		break;
	default:
		IPAERR("unknown protocols %d\n", protocol);
	}
	result = 0;
cleanup:
	dma_free_coherent(ipa3_ctx->uc_pdev, cmd.size,
		cmd.base, cmd.phys_base);
	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
	IPADBG("exit\n");
	return result;
}
+55 −3
Original line number Diff line number Diff line
/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -26,6 +26,11 @@
#define IPA_NTN_TX_DIR 1
#define IPA_NTN_RX_DIR 2

#define MAX_CH_STATS_SUPPORTED 5
#define DIR_CONSUMER 0
#define DIR_PRODUCER 1


/**
 *  @brief   Enum value determined based on the feature it
 *           corresponds to
@@ -71,6 +76,7 @@ enum ipa3_hw_features {
* @IPA_HW_PROTOCOL_AQC : protocol related to AQC operation in IPA HW
* @IPA_HW_PROTOCOL_11ad: protocol related to 11ad operation in IPA HW
* @IPA_HW_PROTOCOL_WDI : protocol related to WDI operation in IPA HW
* @IPA_HW_PROTOCOL_WDI3: protocol related to WDI3 operation in IPA HW
* @IPA_HW_PROTOCOL_ETH : protocol related to ETH operation in IPA HW
*/
enum ipa4_hw_protocol {
@@ -78,6 +84,7 @@ enum ipa4_hw_protocol {
	IPA_HW_PROTOCOL_AQC = 0x1,
	IPA_HW_PROTOCOL_11ad = 0x2,
	IPA_HW_PROTOCOL_WDI = 0x3,
	IPA_HW_PROTOCOL_WDI3 = 0x4,
	IPA_HW_PROTOCOL_ETH = 0x5,
	IPA_HW_PROTOCOL_MAX
};
@@ -158,6 +165,7 @@ enum ipa3_hw_errors {
 * @warningCounter : The warnings counter. The counter carries information
 *						regarding non fatal errors in HW
 * @interfaceVersionCommon : The Common interface version as reported by HW
 * @responseParams_1: offset addr for uC stats
 *
 * The shared memory is used for communication between IPA HW and CPU.
 */
@@ -181,6 +189,7 @@ struct IpaHwSharedMemCommonMapping_t {
	u16 reserved_23_22;
	u16 interfaceVersionCommon;
	u16 reserved_27_26;
	u32 responseParams_1;
} __packed;

/**
@@ -431,6 +440,10 @@ struct Ipa3HwStatsNTNInfoData_t {
 * Offload protocol's Tx/ Rx Path
 * @IPA_CPU_2_HW_CMD_PERIPHERAL_INIT :Command to initialize peripheral
 * @IPA_CPU_2_HW_CMD_PERIPHERAL_DEINIT : Command to deinitialize peripheral
 * @IPA_CPU_2_HW_CMD_OFFLOAD_STATS_ALLOC: Command to start the
 * uC stats calculation for a particular protocol
 * @IPA_CPU_2_HW_CMD_OFFLOAD_STATS_DEALLOC: Command to stop the
 * uC stats calculation for a particular protocol
 */
enum ipa_cpu_2_hw_offload_commands {
	IPA_CPU_2_HW_CMD_OFFLOAD_CHANNEL_SET_UP  =
@@ -441,8 +454,47 @@ enum ipa_cpu_2_hw_offload_commands {
		FEATURE_ENUM_VAL(IPA_HW_FEATURE_OFFLOAD, 3),
	IPA_CPU_2_HW_CMD_PERIPHERAL_DEINIT =
		FEATURE_ENUM_VAL(IPA_HW_FEATURE_OFFLOAD, 4),
	IPA_CPU_2_HW_CMD_OFFLOAD_STATS_ALLOC =
		FEATURE_ENUM_VAL(IPA_HW_FEATURE_OFFLOAD, 5),
	IPA_CPU_2_HW_CMD_OFFLOAD_STATS_DEALLOC =
		FEATURE_ENUM_VAL(IPA_HW_FEATURE_OFFLOAD, 6),
};

/**
 * struct IpaOffloadStatschannel_info - channel info for uC
 * stats
 * @dir: Director of the channel ID DIR_CONSUMER =0,
 * DIR_PRODUCER = 1
 * @ch_id: Channel id of the IPA endpoint for which stats need
 * to be calculated, 0xFF means invalid channel or disable stats
 * on already stats enabled channel
 */
struct IpaOffloadStatschannel_info {
	uint8_t dir;
	uint8_t ch_id;
} __packed;

/**
 * struct IpaHwOffloadStatsAllocCmdData_t - protocol info for uC
 * stats start
 * @protocol: Enum that indicates the protocol type
 * @ch_id_info: Channel id of the IPA endpoint for which stats
 * need to be calculated
 */
struct IpaHwOffloadStatsAllocCmdData_t {
	uint32_t protocol;
	struct IpaOffloadStatschannel_info
		ch_id_info[MAX_CH_STATS_SUPPORTED];
} __packed;

/**
 * struct IpaHwOffloadStatsDeAllocCmdData_t - protocol info for
 * uC stats stop
 * @protocol: Enum that indicates the protocol type
 */
struct IpaHwOffloadStatsDeAllocCmdData_t {
	uint32_t protocol;
} __packed;

/**
 * enum ipa3_hw_offload_channel_states - Values that represent
Loading