Merge "msm:ipa: uc based flow control for UL tethering offload"

This commit is contained in:
qctecmdr 2020-01-09 22:00:05 -08:00 • committed by Gerrit - the friendly Code Review server
commit e445a70cfa
3 changed files with 188 additions and 0 deletions

View file

@ -3260,4 +3260,10 @@ static inline void *alloc_and_init(u32 size, u32 init_val)
bool ipa3_is_apq(void);
/* check if odl is connected */
bool ipa3_is_odl_connected(void);
int ipa3_uc_send_enable_flow_control(uint16_t gsi_chid,
uint16_t redMarkerThreshold);
int ipa3_uc_send_disable_flow_control(void);
int ipa3_uc_send_update_flow_control(uint32_t bitmask,
uint8_t add_delete);
#endif /* _IPA3_I_H_ */

View file

@ -71,6 +71,8 @@
#define IPA_CHANNEL_STOP_IN_PROC_TO_MSEC 5
#define IPA_CHANNEL_STOP_IN_PROC_SLEEP_USEC 200
#define IPA_MHIP_HOLB_TMO 31 /* value to match granularity on ipa HW 4.5 */
#define IPA_MPM_FLOW_CTRL_ADD 1
#define IPA_MPM_FLOW_CTRL_DELETE 0
enum mhip_re_type {
MHIP_RE_XFER = 0x2,
@ -393,6 +395,7 @@ struct ipa_mpm_context {
atomic_t probe_cnt;
atomic_t pcie_clk_total_cnt;
atomic_t ipa_clk_total_cnt;
atomic_t flow_ctrl_mask;
atomic_t adpl_over_usb_available;
struct device *parent_pdev;
struct ipa_smmu_cb_ctx carved_smmu_cb;
@ -1719,6 +1722,8 @@ int ipa_mpm_notify_wan_state(struct wan_ioctl_notify_wan_state *state)
int ret = 0;
enum ipa_mpm_mhip_client_type mhip_client = IPA_MPM_MHIP_TETH;
bool is_acted = true;
const struct ipa_gsi_ep_config *ep_cfg;
uint32_t flow_ctrl_mask = 0;
if (!state)
return -EPERM;
@ -1775,6 +1780,35 @@ int ipa_mpm_notify_wan_state(struct wan_ioctl_notify_wan_state *state)
}
IPA_MPM_DBG("MHIP remote channels are started\n");
/*
* Update flow control monitoring end point info.
* This info will be used to set delay on the end points upon
* hitting RED water mark.
*/
ep_cfg = ipa3_get_gsi_ep_info(IPA_CLIENT_WLAN2_PROD);
if (!ep_cfg)
IPA_MPM_ERR("ep = %d not allocated yet\n",
IPA_CLIENT_WLAN2_PROD);
else
flow_ctrl_mask |= 1 << (ep_cfg->ipa_gsi_chan_num);
ep_cfg = ipa3_get_gsi_ep_info(IPA_CLIENT_USB_PROD);
if (!ep_cfg)
IPA_MPM_ERR("ep = %d not allocated yet\n",
IPA_CLIENT_USB_PROD);
else
flow_ctrl_mask |= 1 << (ep_cfg->ipa_gsi_chan_num);
atomic_set(&ipa_mpm_ctx->flow_ctrl_mask, flow_ctrl_mask);
ret = ipa3_uc_send_update_flow_control(flow_ctrl_mask,
IPA_MPM_FLOW_CTRL_ADD);
if (ret)
IPA_MPM_ERR("Err = %d setting uc flow control\n", ret);
status = ipa_mpm_start_stop_mhip_chan(
IPA_MPM_MHIP_CHAN_UL, probe_id, MPM_MHIP_START);
switch (status) {
@ -1812,6 +1846,23 @@ int ipa_mpm_notify_wan_state(struct wan_ioctl_notify_wan_state *state)
}
ipa_mpm_ctx->md[probe_id].mhip_client = mhip_client;
} else {
/*
* Update flow control monitoring end point info.
* This info will be used to reset delay on the end points.
*/
flow_ctrl_mask =
atomic_read(&ipa_mpm_ctx->flow_ctrl_mask);
ret = ipa3_uc_send_update_flow_control(flow_ctrl_mask,
IPA_MPM_FLOW_CTRL_DELETE);
flow_ctrl_mask = 0;
atomic_set(&ipa_mpm_ctx->flow_ctrl_mask, 0);
if (ret) {
IPA_MPM_ERR("Err = %d resetting uc flow control\n",
ret);
ipa_assert();
}
/*
* Make sure to stop Device side channels before
* stopping Host side UL channels. This is to make
@ -1968,6 +2019,8 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev,
u32 wp_addr;
int pipe_idx;
bool is_acted = true;
uint64_t flow_ctrl_mask = 0;
bool add_delete = false;
IPA_MPM_FUNC_ENTRY();
@ -2348,6 +2401,27 @@ static int ipa_mpm_mhi_probe_cb(struct mhi_device *mhi_dev,
mutex_lock(&ipa_mpm_ctx->md[probe_id].mhi_mutex);
ipa_mpm_ctx->md[probe_id].init_complete = true;
mutex_unlock(&ipa_mpm_ctx->md[probe_id].mhi_mutex);
/* Update Flow control Monitoring, only for the teth UL Prod pipes */
if (probe_id == IPA_MPM_MHIP_CH_ID_0) {
ipa_ep_idx = ipa3_get_ep_mapping(ul_prod);
ep = &ipa3_ctx->ep[ipa_ep_idx];
ret = ipa3_uc_send_enable_flow_control(ep->gsi_chan_hdl,
IPA_MPM_RING_LEN / 4);
if (ret) {
IPA_MPM_ERR("Err %d flow control enable\n", ret);
goto fail_flow_control;
}
IPA_MPM_DBG("Flow Control enabled for %d", probe_id);
flow_ctrl_mask = atomic_read(&ipa_mpm_ctx->flow_ctrl_mask);
add_delete = flow_ctrl_mask > 0 ? 1 : 0;
ret = ipa3_uc_send_update_flow_control(flow_ctrl_mask,
add_delete);
if (ret) {
IPA_MPM_ERR("Err %d flow control update\n", ret);
goto fail_flow_control;
}
IPA_MPM_DBG("Flow Control updated for %d", probe_id);
}
IPA_MPM_FUNC_EXIT();
return 0;
@ -2355,6 +2429,7 @@ fail_gsi_setup:
fail_start_channel:
fail_stop_channel:
fail_smmu:
fail_flow_control:
if (ipa_mpm_ctx->dev_info.ipa_smmu_enabled)
IPA_MPM_DBG("SMMU failed\n");
if (is_acted)
@ -2424,6 +2499,9 @@ static void ipa_mpm_mhi_remove_cb(struct mhi_device *mhi_dev)
ipa_mpm_ctx->md[mhip_idx].init_complete = false;
mutex_unlock(&ipa_mpm_ctx->md[mhip_idx].mhi_mutex);
if (mhip_idx == IPA_MPM_MHIP_CH_ID_0)
ipa3_uc_send_disable_flow_control();
ipa_mpm_mhip_shutdown(mhip_idx);
atomic_dec(&ipa_mpm_ctx->probe_cnt);
@ -2909,6 +2987,7 @@ static int ipa_mpm_probe(struct platform_device *pdev)
atomic_set(&ipa_mpm_ctx->ipa_clk_total_cnt, 0);
atomic_set(&ipa_mpm_ctx->pcie_clk_total_cnt, 0);
atomic_set(&ipa_mpm_ctx->flow_ctrl_mask, 0);
for (idx = 0; idx < IPA_MPM_MHIP_CH_ID_MAX; idx++) {
ipa_mpm_ctx->md[idx].ul_prod.gsi_state = GSI_INIT;

View file

@ -45,6 +45,10 @@
* IPA_CPU_2_HW_CMD_GSI_CH_EMPTY : Command to check for GSI channel emptiness.
* IPA_CPU_2_HW_CMD_REMOTE_IPA_INFO: Command to store remote IPA Info
* IPA_CPU_2_HW_CMD_SETUP_EVENT_RING: Command to setup the event ring
* IPA_CPU_2_HW_CMD_ENABLE_FLOW_CTL_MONITOR: Command to enable pipe monitoring.
* 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.
*/
enum ipa3_cpu_2_hw_commands {
IPA_CPU_2_HW_CMD_NO_OP =
@ -73,6 +77,13 @@ enum ipa3_cpu_2_hw_commands {
FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 11),
IPA_CPU_2_HW_CMD_SETUP_EVENT_RING =
FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 12),
IPA_CPU_2_HW_CMD_ENABLE_FLOW_CTL_MONITOR =
FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 13),
IPA_CPU_2_HW_CMD_UPDATE_FLOW_CTL_MONITOR =
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),
};
/**
@ -198,6 +209,36 @@ struct IpaHwDbAddrInfo_t {
uint32_t mboxN;
} __packed;
/**
* Structure holding the parameters for IPA_CPU_2_HW_CMD_ENABLE_PIPE_MONITOR
* command.
* @ipaProdGsiChid IPA prod GSI chid to monitor
* @redMarkerThreshold red marker threshold in elements for the GSI channel
*/
union IpaEnablePipeMonitorCmdData_t {
struct IpaEnablePipeMonitorCmdParams_t {
u32 ipaProdGsiChid:16;
u32 redMarkerThreshold:16;
} __packed params;
u32 raw32b;
} __packed;
/**
* Structure holding the parameters for IPA_CPU_2_HW_CMD_UPDATE_PIPE_MONITOR
* command.
*
* @bitmask The parameter of bitmask to add/delete channels/pipes from
* global monitoring pipemask
* IPA pipe# bitmask or GSI chid bitmask
* add_delete 1: add pipes to monitor
* 0: delete pipes to monitor
*/
struct IpaUpdateFlowCtlMonitorData_t {
u32 bitmask;
u8 add_delete;
};
static DEFINE_MUTEX(uc_loaded_nb_lock);
static BLOCKING_NOTIFIER_HEAD(uc_loaded_notifier);
@ -1484,3 +1525,65 @@ int ipa3_set_wlan_tx_info(struct ipa_wdi_tx_info *info)
return 0;
}
int ipa3_uc_send_enable_flow_control(uint16_t gsi_chid,
uint16_t redMarkerThreshold)
{
int res;
union IpaEnablePipeMonitorCmdData_t cmd;
cmd.params.ipaProdGsiChid = gsi_chid;
cmd.params.redMarkerThreshold = redMarkerThreshold;
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
res = ipa3_uc_send_cmd((cmd.raw32b),
IPA_CPU_2_HW_CMD_ENABLE_FLOW_CTL_MONITOR, 0,
false, 10 * HZ);
if (res)
IPAERR("fail to enable flow ctrl for 0x%x\n",
cmd.params.ipaProdGsiChid);
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
return res;
}
int ipa3_uc_send_disable_flow_control(void)
{
int res;
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
res = ipa3_uc_send_cmd(0,
IPA_CPU_2_HW_CMD_DISABLE_FLOW_CTL_MONITOR, 0,
false, 10 * HZ);
if (res)
IPAERR("fail to disable flow control\n");
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
return res;
}
int ipa3_uc_send_update_flow_control(uint32_t bitmask,
uint8_t add_delete)
{
int res;
if (bitmask == 0) {
IPAERR("Err update flow control, mask = 0\n");
return 0;
}
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
res = ipa3_uc_send_cmd_64b_param(bitmask, add_delete,
IPA_CPU_2_HW_CMD_UPDATE_FLOW_CTL_MONITOR, 0,
false, 10 * HZ);
if (res)
IPAERR("fail flowCtrl update mask = 0x%x add_del = 0x%x\n",
bitmask, add_delete);
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
return res;
}