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:
Chaitanya Pratapa 2020-02-13 00:05:16 -08:00 • committed by Gerrit - the friendly Code Review server
commit 3eb4edcdfa
13 changed files with 884 additions and 11 deletions

View file

@ -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 \

View file

@ -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");

View file

@ -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 */

View file

@ -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,

View file

@ -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);

View file

@ -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

View 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;
}

View 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 */

View file

@ -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

View file

@ -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 &&

View file

@ -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 */

View file

@ -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) {

View file

@ -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) {