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

Commit 3eb4edcd authored by Chaitanya Pratapa's avatar Chaitanya Pratapa Committed by Gerrit - the friendly Code Review server
Browse files

msm: ipa: Enable uC HOLB monitoring



Includes all changes needed to support the uC HOLB monitoring
feature for slow peripherals.

Change-Id: I09668ab6a2790be766cfddee388de92b9bc83445
Acked-by: default avatarPriyadarshini Rajagopal <prajagop@qti.qualcomm.com>
Signed-off-by: default avatarChaitanya Pratapa <cpratapa@codeaurora.org>
parent f127bb63
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ ipam-y += \
	ipa_v3/ipa_wdi3_i.o \
	ipa_v3/ipa_odl.o \
	ipa_v3/ipa_wigig_i.o \
	ipa_v3/ipa_uc_holb_monitor.o \
	ipa_v3/ipahal/ipahal.o \
	ipa_v3/ipahal/ipahal_reg.o \
	ipa_v3/ipahal/ipahal_fltrt.o \
+84 −1
Original line number Diff line number Diff line
@@ -6056,8 +6056,8 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p,
		IPAERR(":ipa Uc interface init failed (%d)\n", -result);
	else
		IPADBG(":ipa Uc interface init ok\n");

	uc_hdlrs.ipa_uc_loaded_hdlr = ipa3_uc_is_loaded;
	uc_hdlrs.ipa_uc_holb_enabled_hdlr = ipa3_uc_holb_client_handler;
	ipa3_uc_register_handlers(IPA_HW_FEATURE_COMMON, &uc_hdlrs);

	result = ipa3_wdi_init();
@@ -6653,6 +6653,16 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
	ipa3_ctx->wan_rx_ring_size = resource_p->wan_rx_ring_size;
	ipa3_ctx->lan_rx_ring_size = resource_p->lan_rx_ring_size;
	ipa3_ctx->ipa_wan_skb_page = resource_p->ipa_wan_skb_page;
	ipa3_ctx->uc_ctx.ipa_use_uc_holb_monitor =
		resource_p->ipa_use_uc_holb_monitor;
	ipa3_ctx->uc_ctx.holb_monitor.poll_period =
		resource_p->ipa_holb_monitor_poll_period;
	ipa3_ctx->uc_ctx.holb_monitor.max_cnt_wlan =
		resource_p->ipa_holb_monitor_max_cnt_wlan;
	ipa3_ctx->uc_ctx.holb_monitor.max_cnt_usb =
		resource_p->ipa_holb_monitor_max_cnt_usb;
	ipa3_ctx->uc_ctx.holb_monitor.max_cnt_11ad =
		resource_p->ipa_holb_monitor_max_cnt_11ad;
	ipa3_ctx->stats.page_recycle_stats[0].total_replenished = 0;
	ipa3_ctx->stats.page_recycle_stats[0].tmp_alloc = 0;
	ipa3_ctx->stats.page_recycle_stats[1].total_replenished = 0;
@@ -7414,6 +7424,10 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
	u32 *ipa_tz_unlock_reg;
	int elem_num;
	u32 mhi_evid_limits[2];
	u32 ipa_holb_monitor_poll_period;
	u32 ipa_holb_monitor_max_cnt_wlan;
	u32 ipa_holb_monitor_max_cnt_usb;
	u32 ipa_holb_monitor_max_cnt_11ad;

	/* initialize ipa3_res */
	ipa_drv_res->ipa_pipe_mem_start_ofst = IPA_PIPE_MEM_START_OFST;
@@ -7424,6 +7438,7 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
	ipa_drv_res->modem_cfg_emb_pipe_flt = false;
	ipa_drv_res->ipa_wdi2 = false;
	ipa_drv_res->ipa_wan_skb_page = false;
	ipa_drv_res->ipa_use_uc_holb_monitor = false;
	ipa_drv_res->ipa_wdi2_over_gsi = false;
	ipa_drv_res->ipa_wdi3_over_gsi = false;
	ipa_drv_res->ipa_mhi_dynamic_config = false;
@@ -7553,6 +7568,74 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
			ipa_drv_res->ipa_wan_skb_page
			? "True" : "False");

	ipa_drv_res->ipa_use_uc_holb_monitor =
			of_property_read_bool(pdev->dev.of_node,
			"qcom,ipa-uc-holb-monitor");
	IPADBG(": uC HOLB monitor = %s\n",
			ipa_drv_res->ipa_use_uc_holb_monitor
			? "True" : "False");

	/* Get HOLB Monitor Polling Period */
	result = of_property_read_u32(pdev->dev.of_node,
			"qcom,ipa-holb-monitor-poll-period",
			&ipa_holb_monitor_poll_period);
	if (result) {
		IPADBG("ipa holb monitor poll period = %u\n",
			IPA_HOLB_POLLING_PERIOD_MS);
		ipa_holb_monitor_poll_period = IPA_HOLB_POLLING_PERIOD_MS;
	} else
		IPADBG("ipa holb monitor poll period = %u\n",
			ipa_holb_monitor_poll_period);

	ipa_drv_res->ipa_holb_monitor_poll_period =
			ipa_holb_monitor_poll_period;

	/* Get HOLB Monitor Max Stuck Cnt Values */
	result = of_property_read_u32(pdev->dev.of_node,
			"qcom,ipa-holb-monitor-max-cnt-wlan",
			&ipa_holb_monitor_max_cnt_wlan);
	if (result) {
		IPADBG("ipa holb monitor max count wlan = %u\n",
			IPA_HOLB_MONITOR_MAX_STUCK_COUNT);
		ipa_holb_monitor_max_cnt_wlan =
				IPA_HOLB_MONITOR_MAX_STUCK_COUNT;
	} else
		IPADBG("ipa holb monitor max count wlan = %u\n",
			ipa_holb_monitor_max_cnt_wlan);

	ipa_drv_res->ipa_holb_monitor_max_cnt_wlan =
			ipa_holb_monitor_max_cnt_wlan;

	result = of_property_read_u32(pdev->dev.of_node,
			"qcom,ipa-holb-monitor-max-cnt-usb",
			&ipa_holb_monitor_max_cnt_usb);
	if (result) {
		IPADBG("ipa holb monitor max count usb = %u\n",
			IPA_HOLB_MONITOR_MAX_STUCK_COUNT);
		ipa_holb_monitor_max_cnt_usb =
				IPA_HOLB_MONITOR_MAX_STUCK_COUNT;
	} else
		IPADBG("ipa holb monitor max count usb = %u\n",
			ipa_holb_monitor_max_cnt_usb);

	ipa_drv_res->ipa_holb_monitor_max_cnt_usb =
			ipa_holb_monitor_max_cnt_usb;

	result = of_property_read_u32(pdev->dev.of_node,
			"qcom,ipa-holb-monitor-max-cnt-11ad",
			&ipa_holb_monitor_max_cnt_11ad);
	if (result) {
		IPADBG("ipa holb monitor max count 11ad = %u\n",
			IPA_HOLB_MONITOR_MAX_STUCK_COUNT);
		ipa_holb_monitor_max_cnt_11ad =
			IPA_HOLB_MONITOR_MAX_STUCK_COUNT;
	} else
		IPADBG("ipa holb monitor max count 11ad = %u\n",
			ipa_holb_monitor_max_cnt_11ad);

	ipa_drv_res->ipa_holb_monitor_max_cnt_11ad =
			ipa_holb_monitor_max_cnt_11ad;

	ipa_drv_res->ipa_fltrt_not_hashable =
			of_property_read_bool(pdev->dev.of_node,
			"qcom,ipa-fltrt-not-hashable");
+41 −0
Original line number Diff line number Diff line
@@ -824,6 +824,7 @@ int ipa3_xdci_start(u32 clnt_hdl, u8 xferrscidx, bool xferrscidx_valid)
	int result = -EFAULT;
	enum gsi_status gsi_res;
	struct ipa_ep_cfg_ctrl ep_cfg_ctrl;
	u32 holb_max_cnt = ipa3_ctx->uc_ctx.holb_monitor.max_cnt_usb;

	IPADBG("entry\n");
	if (clnt_hdl >= ipa3_ctx->ipa_num_pipes  ||
@@ -866,6 +867,16 @@ int ipa3_xdci_start(u32 clnt_hdl, u8 xferrscidx, bool xferrscidx_valid)
		IPAERR("Error starting channel: %d\n", gsi_res);
		goto write_chan_scratch_fail;
	}

	if (IPA_CLIENT_IS_HOLB_CONS(ep->client)) {
		result = ipa3_uc_client_add_holb_monitor(ep->gsi_chan_hdl,
				HOLB_MONITOR_MASK,
				holb_max_cnt, IPA_EE_AP);
		if (result)
			IPAERR("Add HOLB monitor failed for gsi ch %d\n",
					ep->gsi_chan_hdl);
	}

	ipa3_start_gsi_debug_monitor(clnt_hdl);
	if (!ep->keep_ipa_awake)
		IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(clnt_hdl));
@@ -1520,6 +1531,8 @@ int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
	struct gsi_chan_info ul_gsi_chan_info, dl_gsi_chan_info;
	int aggr_active_bitmap = 0;
	struct ipa_ep_cfg_ctrl ep_cfg_ctrl;
	u32 holb_max_cnt = ipa3_ctx->uc_ctx.holb_monitor.max_cnt_usb;
	int res = 0;

	/* In case of DPL, dl is the DPL channel/client */

@@ -1633,6 +1646,14 @@ int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl,

start_dl_and_exit:
	gsi_start_channel(dl_ep->gsi_chan_hdl);
	if (IPA_CLIENT_IS_HOLB_CONS(dl_ep->client)) {
		res = ipa3_uc_client_add_holb_monitor(dl_ep->gsi_chan_hdl,
			HOLB_MONITOR_MASK, holb_max_cnt,
			IPA_EE_AP);
		if (res)
			IPAERR("Add HOLB monitor failed for gsi ch %d\n",
					dl_ep->gsi_chan_hdl);
	}
	ipa3_start_gsi_debug_monitor(dl_clnt_hdl);
unsuspend_dl_and_exit:
	if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) {
@@ -1653,6 +1674,8 @@ int ipa3_start_gsi_channel(u32 clnt_hdl)
	int result = -EFAULT;
	enum gsi_status gsi_res;
	enum ipa_client_type client_type;
	int res = 0;
	u32 holb_max_cnt = ipa3_ctx->uc_ctx.holb_monitor.max_cnt_usb;

	IPADBG("entry\n");
	if (clnt_hdl >= ipa3_ctx->ipa_num_pipes  ||
@@ -1671,6 +1694,14 @@ int ipa3_start_gsi_channel(u32 clnt_hdl)
		IPAERR("Error starting channel: %d\n", gsi_res);
		goto start_chan_fail;
	}
	if (IPA_CLIENT_IS_HOLB_CONS(ep->client)) {
		res = ipa3_uc_client_add_holb_monitor(ep->gsi_chan_hdl,
				HOLB_MONITOR_MASK,
				holb_max_cnt, IPA_EE_AP);
		if (res)
			IPAERR("Add HOLB monitor failed for gsi ch %d\n",
					ep->gsi_chan_hdl);
	}
	ipa3_start_gsi_debug_monitor(clnt_hdl);

	if (!ep->keep_ipa_awake)
@@ -1692,6 +1723,8 @@ int ipa3_xdci_resume(u32 ul_clnt_hdl, u32 dl_clnt_hdl, bool is_dpl)
	struct ipa3_ep_context *dl_ep = NULL;
	enum gsi_status gsi_res;
	struct ipa_ep_cfg_ctrl ep_cfg_ctrl;
	int result;
	u32 holb_max_cnt = ipa3_ctx->uc_ctx.holb_monitor.max_cnt_usb;

	/* In case of DPL, dl is the DPL channel/client */

@@ -1720,6 +1753,14 @@ int ipa3_xdci_resume(u32 ul_clnt_hdl, u32 dl_clnt_hdl, bool is_dpl)
	gsi_res = gsi_start_channel(dl_ep->gsi_chan_hdl);
	if (gsi_res != GSI_STATUS_SUCCESS)
		IPAERR("Error starting DL channel: %d\n", gsi_res);
	if (!is_dpl) {
		result = ipa3_uc_client_add_holb_monitor(dl_ep->gsi_chan_hdl,
				HOLB_MONITOR_MASK,
				holb_max_cnt, IPA_EE_AP);
		if (result)
			IPAERR("Add HOLB monitor failed for gsi ch %d\n",
					dl_ep->gsi_chan_hdl);
	}
	ipa3_start_gsi_debug_monitor(dl_clnt_hdl);

	/* Start UL channel */
+119 −0
Original line number Diff line number Diff line
@@ -186,6 +186,117 @@ static ssize_t ipa3_write_ep_holb(struct file *file,
	return count;
}

static ssize_t ipa3_write_holb_monitor_client(struct file *file,
		const char __user *buf, size_t count, loff_t *ppos)
{
	struct ipa_uc_holb_client_info holb_client;
	u32 max_stuck_cnt;
	u16 gsi_ch;
	u8 set_client;
	unsigned long missing;
	char *sptr, *token;

	if (count >= sizeof(dbg_buff))
		return -EFAULT;

	missing = copy_from_user(dbg_buff, buf, count);
	if (missing)
		return -EFAULT;

	dbg_buff[count] = '\0';

	sptr = dbg_buff;

	token = strsep(&sptr, " ");
	if (!token)
		return -EINVAL;
	if (kstrtou16(token, 0, &gsi_ch))
		return -EINVAL;

	token = strsep(&sptr, " ");
	if (!token)
		return -EINVAL;
	if (kstrtou32(token, 0, &max_stuck_cnt))
		return -EINVAL;

	token = strsep(&sptr, " ");
	if (!token)
		return -EINVAL;
	if (kstrtou8(token, 0, &set_client))
		return -EINVAL;

	holb_client.gsi_chan_hdl = gsi_ch;
	holb_client.debugfs_param = set_client;
	holb_client.max_stuck_cnt = max_stuck_cnt;
	holb_client.action_mask = HOLB_MONITOR_MASK;
	holb_client.ee = IPA_EE_AP;


	ipa3_set_holb_client_by_ch(holb_client);

	return count;
}

static ssize_t ipa3_write_holb_monitor_client_add_del(struct file *file,
		const char __user *buf, size_t count, loff_t *ppos)
{
	u32 max_stuck_cnt, action_mask;
	u16 gsi_ch;
	u8 ee, add_client;

	unsigned long missing;
	char *sptr, *token;

	if (count >= sizeof(dbg_buff))
		return -EFAULT;

	missing = copy_from_user(dbg_buff, buf, count);
	if (missing)
		return -EFAULT;

	dbg_buff[count] = '\0';

	sptr = dbg_buff;

	token = strsep(&sptr, " ");
	if (!token)
		return -EINVAL;
	if (kstrtou16(token, 0, &gsi_ch))
		return -EINVAL;

	token = strsep(&sptr, " ");
	if (!token)
		return -EINVAL;
	if (kstrtou32(token, 0, &action_mask))
		return -EINVAL;

	token = strsep(&sptr, " ");
	if (!token)
		return -EINVAL;
	if (kstrtou32(token, 0, &max_stuck_cnt))
		return -EINVAL;

	token = strsep(&sptr, " ");
	if (!token)
		return -EINVAL;
	if (kstrtou8(token, 0, &ee))
		return -EINVAL;


	token = strsep(&sptr, " ");
	if (!token)
		return -EINVAL;
	if (kstrtou8(token, 0, &add_client))
		return -EINVAL;

	if (add_client)
		ipa3_uc_client_add_holb_monitor(gsi_ch, action_mask,
			max_stuck_cnt, ee);
	else
		ipa3_uc_client_del_holb_monitor(gsi_ch, ee);

	return count;
}
static ssize_t ipa3_write_ep_reg(struct file *file, const char __user *buf,
		size_t count, loff_t *ppos)
{
@@ -2856,6 +2967,14 @@ static const struct ipa3_debugfs_file debugfs_files[] = {
		"holb", IPA_WRITE_ONLY_MODE, NULL, {
			.write = ipa3_write_ep_holb,
		}
	}, {
		"holb_monitor_client_param", IPA_WRITE_ONLY_MODE, NULL, {
			.write = ipa3_write_holb_monitor_client,
		}
	}, {
		"holb_monitor_client_add_del", IPA_WRITE_ONLY_MODE, NULL, {
			.write = ipa3_write_holb_monitor_client_add_del,
		}
	}, {
		"hdr", IPA_READ_ONLY_MODE, NULL, {
			.read = ipa3_read_hdr,
+27 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@
#include <linux/mailbox/qmp.h>
#include <linux/rmnet_ipa_fd_ioctl.h>
#include <linux/ipa_fmwk.h>
#include "ipa_uc_holb_monitor.h"

#define IPA_DEV_NAME_MAX_LEN 15
#define DRV_NAME "ipa"
@@ -1444,12 +1445,19 @@ struct ipa3_tag_completion {

struct ipa3_controller;

enum ipa_ees {
	IPA_EE_AP = 0,
	IPA_EE_Q6 = 1,
	IPA_EE_UC = 2,
};

/**
 * struct ipa3_uc_hdlrs - IPA uC callback functions
 * @ipa_uc_loaded_hdlr: Function handler when uC is loaded
 * @ipa_uc_event_hdlr: Event handler function
 * @ipa3_uc_response_hdlr: Response handler function
 * @ipa_uc_event_log_info_hdlr: Log event handler function
 * @ipa_uc_holb_enabled_hdlr: Function handler when uC HOLB is enabled
 */
struct ipa3_uc_hdlrs {
	void (*ipa_uc_loaded_hdlr)(void);
@@ -1463,6 +1471,8 @@ struct ipa3_uc_hdlrs {

	void (*ipa_uc_event_log_info_hdlr)
		(struct IpaHwEventLogInfoData_t *uc_event_top_mmio);

	void (*ipa_uc_holb_enabled_hdlr)(void);
};

/**
@@ -1497,6 +1507,7 @@ enum ipa3_hw_flags {
 * @uc_inited: Indicates if uC interface has been initialized
 * @uc_loaded: Indicates if uC has loaded
 * @uc_failed: Indicates if uC has failed / returned an error
 * @uc_holb_enabled: Indicates if uC HOLB enable cmd is sent.
 * @uc_lock: uC interface lock to allow only one uC interaction at a time
 * @uc_spinlock: same as uc_lock but for irq contexts
 * @uc_completation: Completion mechanism to wait for uC commands
@@ -1505,11 +1516,14 @@ enum ipa3_hw_flags {
 * @uc_status: The last status provided by the uC
 * @uc_error_type: error type from uC error event
 * @uc_error_timestamp: tag timer sampled after uC crashed
 * @ipa_use_uc_holb_monitor: Indicates if uC HOLB feature is enabled
 * @ipa_holb_monitor: Struct with all info needed for uC HOLB feature
 */
struct ipa3_uc_ctx {
	bool uc_inited;
	bool uc_loaded;
	bool uc_failed;
	bool uc_holb_enabled;
	struct mutex uc_lock;
	spinlock_t uc_spinlock;
	struct completion uc_completion;
@@ -1534,6 +1548,8 @@ struct ipa3_uc_ctx {
	u32 ering_rp_local;
	u32 ering_wp;
	u32 ering_rp;
	bool ipa_use_uc_holb_monitor;
	struct ipa_holb_monitor holb_monitor;
};

/**
@@ -2124,6 +2140,11 @@ struct ipa3_plat_drv_res {
	const char *icc_path_name[IPA_ICC_PATH_MAX];
	u32 icc_clk_val[IPA_ICC_LVL_MAX][IPA_ICC_MAX];
	bool rmnet_ctl_enable;
	bool ipa_use_uc_holb_monitor;
	u32 ipa_holb_monitor_poll_period;
	u32 ipa_holb_monitor_max_cnt_wlan;
	u32 ipa_holb_monitor_max_cnt_usb;
	u32 ipa_holb_monitor_max_cnt_11ad;
	const char *gsi_fw_file_name;
	const char *uc_fw_file_name;
	u32 tx_wrapper_cache_max_size;
@@ -3006,6 +3027,7 @@ int ipa3_uc_interface_init(void);
int ipa3_uc_is_gsi_channel_empty(enum ipa_client_type ipa_client);
int ipa3_uc_state_check(void);
int ipa3_uc_loaded_check(void);
int ipa3_uc_holb_enabled_check(void);
int ipa3_uc_register_ready_cb(struct notifier_block *nb);
int ipa3_uc_unregister_ready_cb(struct notifier_block *nb);
int ipa3_uc_send_cmd(u32 cmd, u32 opcode, u32 expected_status,
@@ -3039,6 +3061,11 @@ int ipa3_uc_debug_stats_alloc(
	struct IpaHwOffloadStatsAllocCmdData_t cmdinfo);
int ipa3_uc_debug_stats_dealloc(uint32_t protocol);
int ipa3_uc_quota_monitor(uint64_t quota);
int ipa3_uc_enable_holb_monitor(uint32_t polling_period);
int ipa3_uc_add_holb_monitor(uint16_t gsi_ch, uint32_t action_mask,
	uint32_t max_stuck_count, uint8_t ee);
int ipa3_uc_del_holb_monitor(uint16_t gsi_ch, uint8_t ee);
int ipa3_uc_disable_holb_monitor(void);
int ipa3_uc_bw_monitor(struct ipa_wdi_bw_info *info);
int ipa3_uc_setup_event_ring(void);
int ipa3_set_wlan_tx_info(struct ipa_wdi_tx_info *info);
Loading