mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-11 23:24:22 -04:00
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: Priyadarshini Rajagopal <prajagop@qti.qualcomm.com> Signed-off-by: Chaitanya Pratapa <cpratapa@codeaurora.org>
This commit is contained in:
parent
f127bb6378
commit
3eb4edcdfa
13 changed files with 884 additions and 11 deletions
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#define IPA_UC_ERING_n_r 1
|
||||
#define IPA_UC_ERING_n_w 0
|
||||
#define IPA_UC_MON_INTERVAL 5
|
||||
#define IPA_UC_HOLB_WORKQUEUE_NAME "ipa_uc_holb_wq"
|
||||
|
||||
/**
|
||||
* enum ipa3_cpu_2_hw_commands - Values that represent the commands from the CPU
|
||||
|
|
@ -49,6 +50,12 @@
|
|||
* IPA_CPU_2_HW_CMD_UPDATE_FLOW_CTL_MONITOR: Command to update pipes to monitor.
|
||||
* IPA_CPU_2_HW_CMD_DISABLE_FLOW_CTL_MONITOR: Command to disable pipe
|
||||
monitoring, no parameter required.
|
||||
* IPA_CPU_2_HW_CMD_ENABLE_HOLB_MONITOR: Command to enable HOLB monitoring.
|
||||
* IPA_CPU_2_HW_CMD_ADD_HOLB_MONITOR: Command to add GSI channel to HOLB
|
||||
* monitor.
|
||||
* IPA_CPU_2_HW_CMD_DEL_HOLB_MONITOR: Command to delete GSI channel to HOLB
|
||||
* monitor.
|
||||
* IPA_CPU_2_HW_CMD_DISABLE_HOLB_MONITOR: Command to disable HOLB monitoring.
|
||||
*/
|
||||
enum ipa3_cpu_2_hw_commands {
|
||||
IPA_CPU_2_HW_CMD_NO_OP =
|
||||
|
|
@ -83,7 +90,14 @@ enum ipa3_cpu_2_hw_commands {
|
|||
FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 14),
|
||||
IPA_CPU_2_HW_CMD_DISABLE_FLOW_CTL_MONITOR =
|
||||
FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 15),
|
||||
|
||||
IPA_CPU_2_HW_CMD_ENABLE_HOLB_MONITOR =
|
||||
FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 17),
|
||||
IPA_CPU_2_HW_CMD_ADD_HOLB_MONITOR =
|
||||
FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 18),
|
||||
IPA_CPU_2_HW_CMD_DEL_HOLB_MONITOR =
|
||||
FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 19),
|
||||
IPA_CPU_2_HW_CMD_DISABLE_HOLB_MONITOR =
|
||||
FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 20),
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -239,9 +253,64 @@ struct IpaUpdateFlowCtlMonitorData_t {
|
|||
u8 add_delete;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure holding the parameter for
|
||||
* IPA_CPU_2_HW_CMD_ENABLE_HOLB_MONITOR command: HOLB
|
||||
* monitor polling period in ms (expected range min:
|
||||
* 5ms, max: 50ms)
|
||||
*/
|
||||
union IpaEnableHolbMonitorCmdData_t {
|
||||
struct IpaEnableHolbMonitorParams_t {
|
||||
uint32_t holbMonitorPollingPeriod;
|
||||
} params;
|
||||
uint32_t raw32b;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* @brief Structure holding the parameters for
|
||||
* IPA_CPU_2_HW_CMD_ADD_HOLB_MONITOR command
|
||||
*
|
||||
* @param ipaProdGsiChid GSI chid to be HOLB monitored
|
||||
* @param EE EE that the chid belongs to
|
||||
* @param holbActionMask bit0: uC enables HOLB on
|
||||
* corresponding pipe with timer = 0
|
||||
* bit1: Notify AP of bad chid
|
||||
* bits can be set independently or
|
||||
* together
|
||||
* @param maxStuckSampleCnt Max stuck sample count before
|
||||
* taking action
|
||||
*/
|
||||
union IpaAddHolbMonitorCmdData_t {
|
||||
struct IpaAddHolbMonitorParams_t {
|
||||
uint32_t ipaProdGsiChid :8;
|
||||
uint32_t EE :8;
|
||||
uint32_t holbActionMask :8;
|
||||
uint32_t maxStuckSampleCnt :8;
|
||||
} __packed params;
|
||||
uint32_t raw32b;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* @brief Structure holding the parameters for
|
||||
* IPA_CPU_2_HW_CMD_DEL_HOLB_MONITOR command.
|
||||
*
|
||||
* @param ipaProdGsiChid GSI chid to be removed from HOLB
|
||||
* monitoring
|
||||
* @param EE EE that the chid belongs to
|
||||
*/
|
||||
union IpaDelHolbMonitorCmdData_t {
|
||||
struct IpaDelHolbMonitorParams_t {
|
||||
uint32_t ipaProdGsiChid :8;
|
||||
uint32_t EE :8;
|
||||
uint32_t reserved :16;
|
||||
} __packed params;
|
||||
uint32_t raw32b;
|
||||
} __packed;
|
||||
|
||||
static DEFINE_MUTEX(uc_loaded_nb_lock);
|
||||
static BLOCKING_NOTIFIER_HEAD(uc_loaded_notifier);
|
||||
|
||||
static struct workqueue_struct *ipa_uc_holb_wq;
|
||||
struct ipa3_uc_hdlrs ipa3_uc_hdlrs[IPA_HW_NUM_FEATURES] = { { 0 } };
|
||||
|
||||
const char *ipa_hw_error_str(enum ipa3_hw_errors err_type)
|
||||
|
|
@ -283,6 +352,34 @@ const char *ipa_hw_error_str(enum ipa3_hw_errors err_type)
|
|||
return str;
|
||||
}
|
||||
|
||||
static void ipa3_deferred_holb_work(struct work_struct *work)
|
||||
{
|
||||
|
||||
int res;
|
||||
u32 poll_period = ipa3_ctx->uc_ctx.holb_monitor.poll_period;
|
||||
|
||||
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
|
||||
res = ipa3_uc_enable_holb_monitor(poll_period);
|
||||
if (res) {
|
||||
IPAERR("Failed to enable HOLB monitoring %d\n", res);
|
||||
goto fail_holb_enable;
|
||||
}
|
||||
if (!ipa3_ctx->uc_ctx.uc_event_ring_valid) {
|
||||
if (ipa3_uc_setup_event_ring()) {
|
||||
IPAERR("failed to set uc event ring\n");
|
||||
goto fail_holb_enable;
|
||||
}
|
||||
}
|
||||
|
||||
if (ipa3_uc_hdlrs[IPA_HW_FEATURE_COMMON].ipa_uc_holb_enabled_hdlr)
|
||||
ipa3_uc_hdlrs[IPA_HW_FEATURE_COMMON].ipa_uc_holb_enabled_hdlr();
|
||||
|
||||
|
||||
fail_holb_enable:
|
||||
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
|
||||
}
|
||||
DECLARE_WORK(ipa3_holb_enabled_work, ipa3_deferred_holb_work);
|
||||
|
||||
static void ipa3_uc_save_dbg_stats(u32 size)
|
||||
{
|
||||
u8 prot_id;
|
||||
|
|
@ -418,7 +515,7 @@ static void ipa3_event_ring_hdlr(void)
|
|||
u32 ering_rp, offset;
|
||||
void *rp_va;
|
||||
struct ipa_inform_wlan_bw bw_info;
|
||||
struct eventElement_t *e_b = NULL, *e_q = NULL;
|
||||
struct eventElement_t *e_b = NULL, *e_q = NULL, *e_h = NULL;
|
||||
int mul = 0;
|
||||
|
||||
ering_rp = ipahal_read_reg_mn(IPA_UC_MAILBOX_m_n,
|
||||
|
|
@ -456,7 +553,21 @@ static void ipa3_event_ring_hdlr(void)
|
|||
if (ipa3_broadcast_wdi_quota_reach_ind(0,
|
||||
e_q->Value.quota_param.usage))
|
||||
IPAERR_RL("failed on quota_reach for %d\n",
|
||||
e_q->Protocol);
|
||||
e_q->Protocol);
|
||||
} else if (((struct eventElement_t *) rp_va)->Opcode
|
||||
== IPA_HOLB_BAD_PERIPHERAL_EVENT) {
|
||||
e_h = ((struct eventElement_t *) rp_va);
|
||||
IPAERR("Bad Periph for Chan %d QTimer %u %u\n",
|
||||
e_h->Value.holb_notify_param.ipaProdGsiChid,
|
||||
e_h->Value.holb_notify_param.qTimerMSB,
|
||||
e_h->Value.holb_notify_param.qTimerLSB);
|
||||
} else if (((struct eventElement_t *) rp_va)->Opcode
|
||||
== IPA_HOLB_PERIPHERAL_RECOVERED_EVENT) {
|
||||
e_h = ((struct eventElement_t *) rp_va);
|
||||
IPAERR("Recovered Periph Chan %d QTimer %u %u\n",
|
||||
e_h->Value.holb_notify_param.ipaProdGsiChid,
|
||||
e_h->Value.holb_notify_param.qTimerMSB,
|
||||
e_h->Value.holb_notify_param.qTimerLSB);
|
||||
}
|
||||
ipa3_ctx->uc_ctx.ering_rp_local += offset;
|
||||
ipa3_ctx->uc_ctx.ering_rp_local %=
|
||||
|
|
@ -508,6 +619,17 @@ int ipa3_uc_loaded_check(void)
|
|||
}
|
||||
EXPORT_SYMBOL(ipa3_uc_loaded_check);
|
||||
|
||||
/**
|
||||
* ipa3_uc_holb_enabled_check() - Check the uC has been loaded
|
||||
*
|
||||
* Return value: 1 if the uC is loaded, 0 otherwise
|
||||
*/
|
||||
int ipa3_uc_holb_enabled_check(void)
|
||||
{
|
||||
return ipa3_ctx->uc_ctx.uc_holb_enabled;
|
||||
}
|
||||
EXPORT_SYMBOL(ipa3_uc_holb_enabled_check);
|
||||
|
||||
/**
|
||||
* ipa3_uc_register_ready_cb() - register a uC ready callback notifier block
|
||||
* @nb: notifier
|
||||
|
|
@ -694,6 +816,9 @@ static void ipa3_uc_response_hdlr(enum ipa_irq_type interrupt,
|
|||
|
||||
ipa3_ctx->uc_ctx.uc_loaded = true;
|
||||
|
||||
if (ipa3_ctx->uc_ctx.ipa_use_uc_holb_monitor)
|
||||
queue_work(ipa_uc_holb_wq, &ipa3_holb_enabled_work);
|
||||
|
||||
(void) blocking_notifier_call_chain(&uc_loaded_notifier, true,
|
||||
ipa3_ctx);
|
||||
|
||||
|
|
@ -741,6 +866,7 @@ static void ipa3_uc_response_hdlr(enum ipa_irq_type interrupt,
|
|||
ipa3_ctx->uc_ctx.uc_sram_mmio->responseOp);
|
||||
}
|
||||
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
|
||||
|
||||
}
|
||||
|
||||
static void ipa3_uc_wigig_misc_int_handler(enum ipa_irq_type interrupt,
|
||||
|
|
@ -904,6 +1030,7 @@ int ipa3_uc_interface_init(void)
|
|||
}
|
||||
|
||||
mutex_init(&ipa3_ctx->uc_ctx.uc_lock);
|
||||
mutex_init(&ipa3_ctx->uc_ctx.holb_monitor.uc_holb_lock);
|
||||
spin_lock_init(&ipa3_ctx->uc_ctx.uc_spinlock);
|
||||
|
||||
phys_addr = ipa3_ctx->ipa_wrapper_base +
|
||||
|
|
@ -944,10 +1071,22 @@ int ipa3_uc_interface_init(void)
|
|||
goto irq_fail2;
|
||||
}
|
||||
|
||||
if (ipa3_ctx->uc_ctx.ipa_use_uc_holb_monitor) {
|
||||
ipa_uc_holb_wq = alloc_workqueue(IPA_UC_HOLB_WORKQUEUE_NAME,
|
||||
WQ_MEM_RECLAIM | WQ_UNBOUND | WQ_SYSFS, 1);
|
||||
|
||||
if (!ipa_uc_holb_wq) {
|
||||
IPAERR("Failed to create ipa_uc_holb_wq\n");
|
||||
result = -EFAULT;
|
||||
goto fail_wq;
|
||||
}
|
||||
}
|
||||
ipa3_ctx->uc_ctx.uc_inited = true;
|
||||
|
||||
IPADBG("IPA uC interface is initialized\n");
|
||||
return 0;
|
||||
fail_wq:
|
||||
destroy_workqueue(ipa_uc_holb_wq);
|
||||
irq_fail2:
|
||||
ipa3_remove_interrupt_handler(IPA_UC_IRQ_1);
|
||||
irq_fail1:
|
||||
|
|
@ -1038,6 +1177,100 @@ int ipa3_uc_is_gsi_channel_empty(enum ipa_client_type ipa_client)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipa3_uc_enable_holb_monitor() - Enable HOLB monitoring
|
||||
*
|
||||
* Return value: 0 on success, negative value otherwise
|
||||
*/
|
||||
int ipa3_uc_enable_holb_monitor(uint32_t polling_period)
|
||||
{
|
||||
union IpaEnableHolbMonitorCmdData_t cmd;
|
||||
int ret;
|
||||
|
||||
cmd.params.holbMonitorPollingPeriod = polling_period;
|
||||
|
||||
IPADBG("Sending uc CMD ENABLE_HOLB_MONITOR with polling_period (%d)\n",
|
||||
polling_period);
|
||||
|
||||
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
|
||||
ret = ipa3_uc_send_cmd(cmd.raw32b, IPA_CPU_2_HW_CMD_ENABLE_HOLB_MONITOR,
|
||||
0, false, 10*HZ);
|
||||
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipa3_uc_add_holb_monitor() - Add a gsi channel that needs to be monitored
|
||||
*
|
||||
* Return value: 0 on success, negative value otherwise
|
||||
*/
|
||||
int ipa3_uc_add_holb_monitor(uint16_t gsi_ch, uint32_t action_mask,
|
||||
uint32_t max_stuck_cnt, uint8_t ee)
|
||||
{
|
||||
union IpaAddHolbMonitorCmdData_t cmd;
|
||||
int ret;
|
||||
|
||||
cmd.params.ipaProdGsiChid = gsi_ch;
|
||||
cmd.params.EE = ee;
|
||||
cmd.params.holbActionMask = action_mask;
|
||||
cmd.params.maxStuckSampleCnt = max_stuck_cnt;
|
||||
|
||||
IPADBG("Sending uc CMD ADD_HOLB_MONITOR");
|
||||
IPADBG("CMD params gsi_chid (%d), mask (%d), max_stuck_cnt (%d)\n",
|
||||
gsi_ch, action_mask, max_stuck_cnt);
|
||||
|
||||
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
|
||||
ret = ipa3_uc_send_cmd(cmd.raw32b, IPA_CPU_2_HW_CMD_ADD_HOLB_MONITOR, 0,
|
||||
false, 10*HZ);
|
||||
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipa3_uc_del_holb_monitor() - Disable monitoring for a particular
|
||||
* gsi channel
|
||||
*
|
||||
* Return value: 0 on success, negative value otherwise
|
||||
*/
|
||||
int ipa3_uc_del_holb_monitor(uint16_t gsi_ch, uint8_t ee)
|
||||
{
|
||||
union IpaDelHolbMonitorCmdData_t cmd;
|
||||
int ret;
|
||||
|
||||
cmd.params.ipaProdGsiChid = gsi_ch;
|
||||
cmd.params.EE = ee;
|
||||
|
||||
IPADBG("Sending uc IPA_CPU_2_HW_CMD_DEL_HOLB_MONITOR for gsi_ch %d\n",
|
||||
gsi_ch);
|
||||
|
||||
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
|
||||
ret = ipa3_uc_send_cmd(cmd.raw32b, IPA_CPU_2_HW_CMD_DEL_HOLB_MONITOR, 0,
|
||||
false, 10*HZ);
|
||||
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipa3_uc_disable_holb_monitor() - Disable HOLB monitoring
|
||||
*
|
||||
* Return value: 0 on success, negative value otherwise
|
||||
*/
|
||||
int ipa3_uc_disable_holb_monitor(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
IPADBG("Sending uc IPA_CPU_2_HW_CMD_DISABLE_HOLB_MONITOR\n");
|
||||
|
||||
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
|
||||
ret = ipa3_uc_send_cmd(0, IPA_CPU_2_HW_CMD_DISABLE_HOLB_MONITOR, 0,
|
||||
false, 10*HZ);
|
||||
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipa3_uc_notify_clk_state() - notify to uC of clock enable / disable
|
||||
|
|
|
|||
210
drivers/platform/msm/ipa/ipa_v3/ipa_uc_holb_monitor.c
Normal file
210
drivers/platform/msm/ipa/ipa_v3/ipa_uc_holb_monitor.c
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "ipa_i.h"
|
||||
#include "ipa_uc_holb_monitor.h"
|
||||
|
||||
|
||||
/**
|
||||
* ipa3_uc_holb_client_handler - Iterates through all HOLB clients and sends
|
||||
* ADD_HOLB_MONITOR command if necessary.
|
||||
*
|
||||
*/
|
||||
void ipa3_uc_holb_client_handler(void)
|
||||
{
|
||||
int client_idx;
|
||||
struct ipa_uc_holb_client_info *holb_client;
|
||||
int num_clients;
|
||||
|
||||
if (!ipa3_ctx->uc_ctx.ipa_use_uc_holb_monitor)
|
||||
return;
|
||||
|
||||
mutex_lock(&ipa3_ctx->uc_ctx.holb_monitor.uc_holb_lock);
|
||||
|
||||
num_clients = ipa3_ctx->uc_ctx.holb_monitor.num_holb_clients;
|
||||
ipa3_ctx->uc_ctx.uc_holb_enabled = true;
|
||||
|
||||
for (client_idx = 0; client_idx < num_clients; client_idx++) {
|
||||
holb_client =
|
||||
&(ipa3_ctx->uc_ctx.holb_monitor.client[client_idx]);
|
||||
if (holb_client->state == IPA_HOLB_ADD_PENDING) {
|
||||
ipa3_uc_add_holb_monitor(holb_client->gsi_chan_hdl,
|
||||
holb_client->action_mask, holb_client->max_stuck_cnt,
|
||||
holb_client->ee);
|
||||
IPADBG("HOLB Client with GSI %d moved to ADD state\n",
|
||||
holb_client->gsi_chan_hdl);
|
||||
holb_client->state = IPA_HOLB_ADD;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&ipa3_ctx->uc_ctx.holb_monitor.uc_holb_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipa3_get_holb_client_idx_by_ch() - Get client index in client
|
||||
* array with a specified gsi channel
|
||||
* @gsi_chan_hdl: GSI Channel of the client to be monitored
|
||||
*
|
||||
* Returns client index in client array
|
||||
*/
|
||||
static int ipa3_get_holb_client_idx_by_ch(uint16_t gsi_ch)
|
||||
{
|
||||
int client_idx;
|
||||
int num_clients = ipa3_ctx->uc_ctx.holb_monitor.num_holb_clients;
|
||||
struct ipa_uc_holb_client_info *holb_client;
|
||||
|
||||
for (client_idx = 0; client_idx < num_clients; client_idx++) {
|
||||
holb_client =
|
||||
&(ipa3_ctx->uc_ctx.holb_monitor.client[client_idx]);
|
||||
if (holb_client->gsi_chan_hdl == gsi_ch)
|
||||
return client_idx;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipa3_set_holb_client_by_ch() - Set client parameters for specific
|
||||
* gsi channel
|
||||
* @client: Client values to be set for the gsi channel
|
||||
*
|
||||
*/
|
||||
void ipa3_set_holb_client_by_ch(struct ipa_uc_holb_client_info client)
|
||||
{
|
||||
uint16_t gsi_ch;
|
||||
int client_idx, num_clients;
|
||||
struct ipa_uc_holb_client_info *holb_client;
|
||||
|
||||
|
||||
mutex_lock(&ipa3_ctx->uc_ctx.holb_monitor.uc_holb_lock);
|
||||
|
||||
gsi_ch = client.gsi_chan_hdl;
|
||||
client_idx = ipa3_get_holb_client_idx_by_ch(gsi_ch);
|
||||
|
||||
if (client_idx != -EINVAL) {
|
||||
holb_client =
|
||||
&(ipa3_ctx->uc_ctx.holb_monitor.client[client_idx]);
|
||||
} else {
|
||||
num_clients = ipa3_ctx->uc_ctx.holb_monitor.num_holb_clients;
|
||||
holb_client =
|
||||
&(ipa3_ctx->uc_ctx.holb_monitor.client[num_clients]);
|
||||
ipa3_ctx->uc_ctx.holb_monitor.num_holb_clients = ++num_clients;
|
||||
holb_client->gsi_chan_hdl = gsi_ch;
|
||||
}
|
||||
|
||||
holb_client->debugfs_param = client.debugfs_param;
|
||||
if (holb_client->debugfs_param)
|
||||
holb_client->max_stuck_cnt = client.max_stuck_cnt;
|
||||
IPADBG("HOLB gsi_chan %d with max_stuck_cnt %d, set %d\n",
|
||||
gsi_ch, holb_client->max_stuck_cnt, holb_client->debugfs_param);
|
||||
|
||||
mutex_unlock(&ipa3_ctx->uc_ctx.holb_monitor.uc_holb_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipa3_uc_client_add_holb_monitor() - Sends ADD_HOLB_MONITOR for gsi channels
|
||||
* if uC is enabled, else saves client state
|
||||
* @gsi_chan_hdl: GSI Channel of the client to be monitored
|
||||
* @action_mask: HOLB action mask
|
||||
* @max_stuck_cnt: Max number of attempts uC should try before sending an event
|
||||
* @ee: EE that the chid belongs to
|
||||
*
|
||||
* Return value: 0 on success, negative value otherwise
|
||||
*/
|
||||
int ipa3_uc_client_add_holb_monitor(uint16_t gsi_ch, uint32_t action_mask,
|
||||
uint32_t max_stuck_cnt, uint8_t ee)
|
||||
{
|
||||
|
||||
struct ipa_uc_holb_client_info *holb_client;
|
||||
int ret = 0;
|
||||
int client_idx, num_clients;
|
||||
|
||||
if (!ipa3_ctx->uc_ctx.ipa_use_uc_holb_monitor)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&ipa3_ctx->uc_ctx.holb_monitor.uc_holb_lock);
|
||||
|
||||
client_idx = ipa3_get_holb_client_idx_by_ch(gsi_ch);
|
||||
if (client_idx != -EINVAL) {
|
||||
holb_client =
|
||||
&(ipa3_ctx->uc_ctx.holb_monitor.client[client_idx]);
|
||||
} else {
|
||||
num_clients = ipa3_ctx->uc_ctx.holb_monitor.num_holb_clients;
|
||||
holb_client =
|
||||
&(ipa3_ctx->uc_ctx.holb_monitor.client[num_clients]);
|
||||
ipa3_ctx->uc_ctx.holb_monitor.num_holb_clients = ++num_clients;
|
||||
}
|
||||
|
||||
holb_client->gsi_chan_hdl = gsi_ch;
|
||||
holb_client->action_mask = action_mask;
|
||||
if (!holb_client->debugfs_param)
|
||||
holb_client->max_stuck_cnt = max_stuck_cnt;
|
||||
holb_client->ee = ee;
|
||||
|
||||
if (ipa3_uc_holb_enabled_check()) {
|
||||
if (holb_client->state != IPA_HOLB_ADD) {
|
||||
IPADBG("GSI chan %d going to ADD state\n",
|
||||
holb_client->gsi_chan_hdl);
|
||||
ret = ipa3_uc_add_holb_monitor(
|
||||
holb_client->gsi_chan_hdl,
|
||||
holb_client->action_mask, holb_client->max_stuck_cnt,
|
||||
holb_client->ee);
|
||||
holb_client->state = IPA_HOLB_ADD;
|
||||
}
|
||||
} else {
|
||||
IPADBG("GSI chan %d going to ADD_PENDING state\n",
|
||||
holb_client->gsi_chan_hdl);
|
||||
holb_client->state = IPA_HOLB_ADD_PENDING;
|
||||
}
|
||||
|
||||
|
||||
mutex_unlock(&ipa3_ctx->uc_ctx.holb_monitor.uc_holb_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipa3_uc_client_del_holb_monitor() - Sends DEL_HOLB_MONITOR for gsi channels
|
||||
* if uC is enabled, else saves client state
|
||||
* @gsi_chan_hdl: GSI Channel of the client to be monitored
|
||||
* @ee: EE that the chid belongs to
|
||||
*
|
||||
* Return value: 0 on success, negative value otherwise
|
||||
*/
|
||||
int ipa3_uc_client_del_holb_monitor(uint16_t gsi_ch, uint8_t ee)
|
||||
{
|
||||
|
||||
struct ipa_uc_holb_client_info *holb_client;
|
||||
int ret = 0;
|
||||
int client_idx;
|
||||
|
||||
if (!ipa3_ctx->uc_ctx.ipa_use_uc_holb_monitor)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&ipa3_ctx->uc_ctx.holb_monitor.uc_holb_lock);
|
||||
|
||||
client_idx = ipa3_get_holb_client_idx_by_ch(gsi_ch);
|
||||
if (client_idx == -EINVAL) {
|
||||
IPAERR("Invalid client with GSI chan %d\n", gsi_ch);
|
||||
ret = client_idx;
|
||||
}
|
||||
|
||||
holb_client = &(ipa3_ctx->uc_ctx.holb_monitor.client[client_idx]);
|
||||
if (ipa3_uc_holb_enabled_check() &&
|
||||
holb_client->state == IPA_HOLB_ADD) {
|
||||
IPADBG("GSI chan %d going from ADD to DEL state\n",
|
||||
holb_client->gsi_chan_hdl);
|
||||
ret = ipa3_uc_del_holb_monitor(holb_client->gsi_chan_hdl,
|
||||
ee);
|
||||
holb_client->state = IPA_HOLB_DEL;
|
||||
|
||||
} else if (!ipa3_uc_holb_enabled_check() &&
|
||||
holb_client->state == IPA_HOLB_ADD_PENDING) {
|
||||
IPADBG("GSI chan %d going from ADD_PENDING to DEL state\n",
|
||||
holb_client->gsi_chan_hdl);
|
||||
holb_client->state = IPA_HOLB_DEL;
|
||||
}
|
||||
|
||||
mutex_unlock(&ipa3_ctx->uc_ctx.holb_monitor.uc_holb_lock);
|
||||
return ret;
|
||||
}
|
||||
109
drivers/platform/msm/ipa/ipa_v3/ipa_uc_holb_monitor.h
Normal file
109
drivers/platform/msm/ipa/ipa_v3/ipa_uc_holb_monitor.h
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef IPA_UC_HOLB_MONITOR_H
|
||||
#define IPA_UC_HOLB_MONITOR_H
|
||||
|
||||
#define IPA_HOLB_MONITOR_MAX_STUCK_COUNT 5
|
||||
#define IPA_HOLB_POLLING_PERIOD_MS 10
|
||||
#define HOLB_OP 0x1
|
||||
#define NOTIFY_AP_ON_HOLB 0x2
|
||||
#define HOLB_MONITOR_MASK (HOLB_OP | NOTIFY_AP_ON_HOLB)
|
||||
#define IPA_HOLB_CLIENT_MAX 30
|
||||
#define IPA_CLIENT_IS_HOLB_CONS(x) \
|
||||
(x == IPA_CLIENT_USB_CONS || x == IPA_CLIENT_WLAN2_CONS || \
|
||||
x == IPA_CLIENT_WLAN1_CONS || x == IPA_CLIENT_WIGIG1_CONS || \
|
||||
x == IPA_CLIENT_WIGIG2_CONS || x == IPA_CLIENT_WIGIG3_CONS || \
|
||||
x == IPA_CLIENT_WIGIG4_CONS)
|
||||
|
||||
/*
|
||||
* enum holb_client_state - Client state for HOLB
|
||||
* IPA_HOLB_INIT : Initial state on bootup before client connect/disconnect
|
||||
* IPA_HOLB_ADD_PENDING : Client GSI channel started but uC not enabled.
|
||||
* IPA_HOLB_ADD : ADD_HOLB_MONITOR command sent for client.
|
||||
* IPA_HOLB_DEL : DEL_HOLB_MONITOR command sent for client.
|
||||
*/
|
||||
enum ipa_holb_client_state {
|
||||
IPA_HOLB_INIT = 0,
|
||||
IPA_HOLB_ADD_PENDING = 1,
|
||||
IPA_HOLB_ADD = 2,
|
||||
IPA_HOLB_DEL = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ipa_uc_holb_client_info - Client info needed for HOLB callback
|
||||
* @gsi_chan_hdl: GSI Channel of the client to be monitored
|
||||
* @action_mask: HOLB action mask
|
||||
* @max_stuck_cnt: Max number of attempts uC should try before sending an event
|
||||
* @ee: EE that the chid belongs to
|
||||
* @debugfs_param: If debugfs is used to set the client parameters
|
||||
* @state: Client state
|
||||
*
|
||||
*/
|
||||
struct ipa_uc_holb_client_info {
|
||||
uint16_t gsi_chan_hdl;
|
||||
uint32_t action_mask;
|
||||
uint32_t max_stuck_cnt;
|
||||
uint8_t ee;
|
||||
bool debugfs_param;
|
||||
enum ipa_holb_client_state state;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ipa_holb_monitor - Parameters needed for the HOLB monitor feature
|
||||
* @num_holb_clients: Number of clients with holb monitor enabled
|
||||
* @client: Array of clients tracked for HOLB Monitor
|
||||
* @ipa_uc_holb_monitor_poll_period : Polling period in ms
|
||||
* @uc_holb_lock : Lock for feature operations
|
||||
*
|
||||
*/
|
||||
struct ipa_holb_monitor {
|
||||
u32 num_holb_clients;
|
||||
u32 poll_period;
|
||||
u32 max_cnt_wlan;
|
||||
u32 max_cnt_usb;
|
||||
u32 max_cnt_11ad;
|
||||
struct ipa_uc_holb_client_info client[IPA_HOLB_CLIENT_MAX];
|
||||
struct mutex uc_holb_lock;
|
||||
};
|
||||
|
||||
/**
|
||||
* ipa3_uc_holb_client_handler - Iterates through all HOLB clients and sends
|
||||
* ADD_HOLB_MONITOR command if necessary.
|
||||
*
|
||||
*/
|
||||
void ipa3_uc_holb_client_handler(void);
|
||||
|
||||
/**
|
||||
* ipa3_uc_client_add_holb_monitor() - Sends ADD_HOLB_MONITOR for gsi channels
|
||||
* if uC is enabled, else saves client state
|
||||
* @gsi_chan_hdl: GSI Channel of the client to be monitored
|
||||
* @action_mask: HOLB action mask
|
||||
* @max_stuck_cnt: Max number of attempts uC should try before sending an event
|
||||
* @ee: EE that the chid belongs to
|
||||
*
|
||||
* Return value: 0 on success, negative value otherwise
|
||||
*/
|
||||
int ipa3_uc_client_add_holb_monitor(uint16_t gsi_ch, uint32_t action_mask,
|
||||
uint32_t max_stuck_cnt, uint8_t ee);
|
||||
|
||||
/**
|
||||
* ipa3_uc_client_del_holb_monitor() - Sends DEL_HOLB_MONITOR for gsi channels
|
||||
* if uC is enabled, else saves client state
|
||||
* @gsi_chan_hdl: GSI Channel of the client to be monitored
|
||||
* @ee: EE that the chid belongs to
|
||||
*
|
||||
* Return value: 0 on success, negative value otherwise
|
||||
*/
|
||||
int ipa3_uc_client_del_holb_monitor(uint16_t gsi_ch, uint8_t ee);
|
||||
|
||||
/**
|
||||
* ipa3_set_holb_client_by_ch() - Set client parameters for specific
|
||||
* gsi channel
|
||||
* @client: Client values to be set for the gsi channel
|
||||
*
|
||||
*/
|
||||
void ipa3_set_holb_client_by_ch(struct ipa_uc_holb_client_info client);
|
||||
#endif /* IPA_UC_HOLB_MONITOR_H */
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _IPA_UC_OFFLOAD_I_H_
|
||||
|
|
@ -673,6 +673,8 @@ struct IpaHwOffloadCommonChCmdData_t {
|
|||
enum EVENT_2_CPU_OPCODE {
|
||||
BW_NOTIFY = 0x0,
|
||||
QUOTA_NOTIFY = 0x1,
|
||||
IPA_HOLB_BAD_PERIPHERAL_EVENT = 0x2,
|
||||
IPA_HOLB_PERIPHERAL_RECOVERED_EVENT = 0x3
|
||||
};
|
||||
|
||||
struct EventStructureBwMonitoring_t {
|
||||
|
|
@ -686,9 +688,27 @@ struct EventStructureQuotaMonitoring_t {
|
|||
uint64_t usage;
|
||||
} __packed;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Structure holding the parameters for
|
||||
* IPA_HW_2_CPU_EVENT_PERIPH_BAD and
|
||||
* IPA_HW_2_CPU_EVENT_PERIPH_RECOVERED events.
|
||||
*
|
||||
* @param ipaProdGsiChid bad OR recovered GSI chid
|
||||
* @param EE EE that the chid belongs to
|
||||
*/
|
||||
struct EventStructureHolbMonitoring_t {
|
||||
uint32_t ipaProdGsiChid :8;
|
||||
uint32_t EE :8;
|
||||
uint32_t reserved :16;
|
||||
uint32_t qTimerLSB;
|
||||
uint32_t qTimerMSB;
|
||||
} __packed;
|
||||
|
||||
union EventParamFormat_t {
|
||||
struct EventStructureBwMonitoring_t bw_param;
|
||||
struct EventStructureQuotaMonitoring_t quota_param;
|
||||
struct EventStructureHolbMonitoring_t holb_notify_param;
|
||||
} __packed;
|
||||
|
||||
/* EVT RING STRUCTURE
|
||||
|
|
|
|||
|
|
@ -2470,6 +2470,8 @@ int ipa3_resume_gsi_wdi_pipe(u32 clnt_hdl)
|
|||
struct gsi_chan_info chan_info;
|
||||
union __packed gsi_channel_scratch gsi_scratch;
|
||||
struct IpaHwOffloadStatsAllocCmdData_t *pcmd_t = NULL;
|
||||
u32 holb_max_cnt = ipa3_ctx->uc_ctx.holb_monitor.max_cnt_wlan;
|
||||
int res = 0;
|
||||
|
||||
IPADBG("ep=%d\n", clnt_hdl);
|
||||
ep = &ipa3_ctx->ep[clnt_hdl];
|
||||
|
|
@ -2493,6 +2495,14 @@ int ipa3_resume_gsi_wdi_pipe(u32 clnt_hdl)
|
|||
IPAERR("gsi_start_channel failed %d\n", result);
|
||||
ipa_assert();
|
||||
}
|
||||
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);
|
||||
}
|
||||
pcmd_t = &ipa3_ctx->gsi_info[IPA_HW_PROTOCOL_WDI];
|
||||
/* start uC gsi dbg stats monitor */
|
||||
if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5 &&
|
||||
|
|
|
|||
|
|
@ -646,11 +646,6 @@ static const u32 ipa3_rsrc_rx_grp_hps_weight_config
|
|||
},
|
||||
};
|
||||
|
||||
enum ipa_ees {
|
||||
IPA_EE_AP = 0,
|
||||
IPA_EE_Q6 = 1,
|
||||
IPA_EE_UC = 2,
|
||||
};
|
||||
|
||||
enum ipa_qmb_instance_type {
|
||||
IPA_QMB_INSTANCE_DDR = 0,
|
||||
|
|
@ -7964,6 +7959,13 @@ static int __ipa3_stop_gsi_channel(u32 clnt_hdl)
|
|||
|
||||
ep = &ipa3_ctx->ep[clnt_hdl];
|
||||
client_type = ipa3_get_client_mapping(clnt_hdl);
|
||||
if (IPA_CLIENT_IS_HOLB_CONS(client_type)) {
|
||||
res = ipa3_uc_client_del_holb_monitor(ep->gsi_chan_hdl,
|
||||
IPA_EE_AP);
|
||||
if (res)
|
||||
IPAERR("Delete HOLB monitor failed for ch %d\n",
|
||||
ep->gsi_chan_hdl);
|
||||
}
|
||||
memset(&mem, 0, sizeof(mem));
|
||||
|
||||
/* stop uC gsi dbg stats monitor */
|
||||
|
|
|
|||
|
|
@ -726,6 +726,7 @@ int ipa3_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
|
|||
{
|
||||
struct ipa3_ep_context *ep_tx, *ep_rx;
|
||||
int result = 0;
|
||||
u32 holb_max_cnt = ipa3_ctx->uc_ctx.holb_monitor.max_cnt_wlan;
|
||||
|
||||
/* wdi3 only support over gsi */
|
||||
if (!ipa3_ctx->ipa_wdi3_over_gsi) {
|
||||
|
|
@ -778,6 +779,13 @@ int ipa3_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
|
|||
goto fail_enable_path2;
|
||||
}
|
||||
|
||||
result = ipa3_uc_client_add_holb_monitor(ep_tx->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_tx->gsi_chan_hdl);
|
||||
|
||||
/* start gsi rx channel */
|
||||
result = gsi_start_channel(ep_rx->gsi_chan_hdl);
|
||||
if (result) {
|
||||
|
|
@ -875,6 +883,7 @@ int ipa3_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
|
|||
result = -EFAULT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* stop gsi tx channel */
|
||||
result = ipa3_stop_gsi_channel(ipa_ep_idx_tx);
|
||||
if (result) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "ipa_i.h"
|
||||
|
|
@ -1650,6 +1650,7 @@ int ipa3_enable_wigig_pipe_i(enum ipa_client_type client)
|
|||
struct ipa_ep_cfg_ctrl ep_cfg_ctrl;
|
||||
int retry_cnt = 0;
|
||||
uint64_t val;
|
||||
u32 holb_max_cnt = ipa3_ctx->uc_ctx.holb_monitor.max_cnt_11ad;
|
||||
|
||||
IPADBG("\n");
|
||||
|
||||
|
|
@ -1704,6 +1705,14 @@ int ipa3_enable_wigig_pipe_i(enum ipa_client_type client)
|
|||
res = -EFAULT;
|
||||
goto fail_gsi_start;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
/* for TX we have to ring the channel db (last desc in the ring) */
|
||||
if (client != IPA_CLIENT_WIGIG_PROD) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue