msm: ipa4: Enhanced flow control changes
Adding changes to support enhanced flow control. Change-Id: Id656319703a27f5073c6fd129fb4202a37b49aad Signed-off-by: Ashok Vuyyuru <avuyyuru@codeaurora.org>
This commit is contained in:
parent
3da31ea0a2
commit
f20c9b46d4
@ -1367,6 +1367,10 @@ int gsi_register_device(struct gsi_per_props *props, unsigned long *dev_hdl)
|
||||
gsi_writel(0, gsi_ctx->base +
|
||||
GSI_EE_n_ERROR_LOG_OFFS(gsi_ctx->per.ee));
|
||||
|
||||
/* Reset to zero scratch_1 register*/
|
||||
gsi_writel(0, gsi_ctx->base +
|
||||
GSI_EE_n_CNTXT_SCRATCH_1_OFFS(gsi_ctx->per.ee));
|
||||
|
||||
if (running_emulation) {
|
||||
/*
|
||||
* Set up the emulator's interrupt controller...
|
||||
@ -4713,6 +4717,165 @@ free_lock:
|
||||
}
|
||||
EXPORT_SYMBOL(gsi_enable_flow_control_ee);
|
||||
|
||||
int gsi_flow_control_ee(unsigned int chan_idx, unsigned int ee,
|
||||
bool enable, bool prmy_scnd_fc, int *code)
|
||||
{
|
||||
enum gsi_generic_ee_cmd_opcode op = enable ?
|
||||
GSI_GEN_EE_CMD_ENABLE_FLOW_CHANNEL :
|
||||
GSI_GEN_EE_CMD_DISABLE_FLOW_CHANNEL;
|
||||
uint32_t val;
|
||||
int res;
|
||||
|
||||
if (!gsi_ctx) {
|
||||
pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__);
|
||||
return -GSI_STATUS_NODEV;
|
||||
}
|
||||
|
||||
if (chan_idx >= gsi_ctx->max_ch || !code) {
|
||||
GSIERR("bad params chan_idx=%d\n", chan_idx);
|
||||
return -GSI_STATUS_INVALID_PARAMS;
|
||||
}
|
||||
|
||||
mutex_lock(&gsi_ctx->mlock);
|
||||
__gsi_config_glob_irq(gsi_ctx->per.ee,
|
||||
GSI_EE_n_CNTXT_GLOB_IRQ_EN_GP_INT1_BMSK, ~0);
|
||||
reinit_completion(&gsi_ctx->gen_ee_cmd_compl);
|
||||
|
||||
/* invalidate the response */
|
||||
gsi_ctx->scratch.word0.val = gsi_readl(gsi_ctx->base +
|
||||
GSI_EE_n_CNTXT_SCRATCH_0_OFFS(gsi_ctx->per.ee));
|
||||
gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code = 0;
|
||||
gsi_writel(gsi_ctx->scratch.word0.val, gsi_ctx->base +
|
||||
GSI_EE_n_CNTXT_SCRATCH_0_OFFS(gsi_ctx->per.ee));
|
||||
|
||||
gsi_ctx->gen_ee_cmd_dbg.flow_ctrl_channel++;
|
||||
val = (((op << GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_SHFT) &
|
||||
GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_BMSK) |
|
||||
((chan_idx << GSI_EE_n_GSI_EE_GENERIC_CMD_VIRT_CHAN_IDX_SHFT) &
|
||||
GSI_EE_n_GSI_EE_GENERIC_CMD_VIRT_CHAN_IDX_BMSK) |
|
||||
((ee << GSI_EE_n_GSI_EE_GENERIC_CMD_EE_SHFT) &
|
||||
GSI_EE_n_GSI_EE_GENERIC_CMD_EE_BMSK) |
|
||||
((prmy_scnd_fc << GSI_EE_n_GSI_EE_GENERIC_CMD_PARAM_SHFT) &
|
||||
GSI_EE_n_GSI_EE_GENERIC_CMD_PARAM_BMSK));
|
||||
gsi_writel(val, gsi_ctx->base +
|
||||
GSI_EE_n_GSI_EE_GENERIC_CMD_OFFS(gsi_ctx->per.ee));
|
||||
|
||||
res = wait_for_completion_timeout(&gsi_ctx->gen_ee_cmd_compl,
|
||||
msecs_to_jiffies(GSI_CMD_TIMEOUT));
|
||||
if (res == 0) {
|
||||
GSIERR("chan_idx=%u ee=%u timed out\n", chan_idx, ee);
|
||||
res = -GSI_STATUS_TIMED_OUT;
|
||||
GSI_ASSERT();
|
||||
goto free_lock;
|
||||
}
|
||||
|
||||
gsi_ctx->scratch.word0.val = gsi_readl(gsi_ctx->base +
|
||||
GSI_EE_n_CNTXT_SCRATCH_0_OFFS(gsi_ctx->per.ee));
|
||||
if (gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code ==
|
||||
GSI_GEN_EE_CMD_RETURN_CODE_CHANNEL_NOT_RUNNING) {
|
||||
GSIDBG("chan_idx=%u ee=%u not in correct state\n",
|
||||
chan_idx, ee);
|
||||
*code = GSI_GEN_EE_CMD_RETURN_CODE_CHANNEL_NOT_RUNNING;
|
||||
res = -GSI_STATUS_RES_ALLOC_FAILURE;
|
||||
goto free_lock;
|
||||
} else if (gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code ==
|
||||
GSI_GEN_EE_CMD_RETURN_CODE_INCORRECT_CHANNEL_TYPE ||
|
||||
gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code ==
|
||||
GSI_GEN_EE_CMD_RETURN_CODE_INCORRECT_CHANNEL_INDEX){
|
||||
GSIERR("chan_idx=%u ee=%u not in correct state\n",
|
||||
chan_idx, ee);
|
||||
GSI_ASSERT();
|
||||
}
|
||||
if (gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code == 0) {
|
||||
GSIERR("No response received\n");
|
||||
res = -GSI_STATUS_ERROR;
|
||||
goto free_lock;
|
||||
}
|
||||
|
||||
*code = gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code;
|
||||
res = GSI_STATUS_SUCCESS;
|
||||
free_lock:
|
||||
__gsi_config_glob_irq(gsi_ctx->per.ee,
|
||||
GSI_EE_n_CNTXT_GLOB_IRQ_EN_GP_INT1_BMSK, 0);
|
||||
mutex_unlock(&gsi_ctx->mlock);
|
||||
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(gsi_flow_control_ee);
|
||||
|
||||
int gsi_query_flow_control_state_ee(unsigned int chan_idx, unsigned int ee,
|
||||
bool prmy_scnd_fc, int *code)
|
||||
{
|
||||
enum gsi_generic_ee_cmd_opcode op = GSI_GEN_EE_CMD_QUERY_FLOW_CHANNEL;
|
||||
uint32_t val;
|
||||
int res;
|
||||
|
||||
if (!gsi_ctx) {
|
||||
pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__);
|
||||
return -GSI_STATUS_NODEV;
|
||||
}
|
||||
|
||||
if (chan_idx >= gsi_ctx->max_ch || !code) {
|
||||
GSIERR("bad params chan_idx=%d\n", chan_idx);
|
||||
return -GSI_STATUS_INVALID_PARAMS;
|
||||
}
|
||||
|
||||
mutex_lock(&gsi_ctx->mlock);
|
||||
__gsi_config_glob_irq(gsi_ctx->per.ee,
|
||||
GSI_EE_n_CNTXT_GLOB_IRQ_EN_GP_INT1_BMSK, ~0);
|
||||
reinit_completion(&gsi_ctx->gen_ee_cmd_compl);
|
||||
|
||||
/* invalidate the response */
|
||||
gsi_ctx->scratch.word0.val = gsi_readl(gsi_ctx->base +
|
||||
GSI_EE_n_CNTXT_SCRATCH_0_OFFS(gsi_ctx->per.ee));
|
||||
gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code = 0;
|
||||
gsi_writel(gsi_ctx->scratch.word0.val, gsi_ctx->base +
|
||||
GSI_EE_n_CNTXT_SCRATCH_0_OFFS(gsi_ctx->per.ee));
|
||||
|
||||
gsi_ctx->gen_ee_cmd_dbg.flow_ctrl_channel++;
|
||||
val = (((op << GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_SHFT) &
|
||||
GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_BMSK) |
|
||||
((chan_idx << GSI_EE_n_GSI_EE_GENERIC_CMD_VIRT_CHAN_IDX_SHFT) &
|
||||
GSI_EE_n_GSI_EE_GENERIC_CMD_VIRT_CHAN_IDX_BMSK) |
|
||||
((ee << GSI_EE_n_GSI_EE_GENERIC_CMD_EE_SHFT) &
|
||||
GSI_EE_n_GSI_EE_GENERIC_CMD_EE_BMSK) |
|
||||
((prmy_scnd_fc << GSI_EE_n_GSI_EE_GENERIC_CMD_PARAM_SHFT) &
|
||||
GSI_EE_n_GSI_EE_GENERIC_CMD_PARAM_BMSK));
|
||||
gsi_writel(val, gsi_ctx->base +
|
||||
GSI_EE_n_GSI_EE_GENERIC_CMD_OFFS(gsi_ctx->per.ee));
|
||||
|
||||
res = wait_for_completion_timeout(&gsi_ctx->gen_ee_cmd_compl,
|
||||
msecs_to_jiffies(GSI_CMD_TIMEOUT));
|
||||
if (res == 0) {
|
||||
GSIERR("chan_idx=%u ee=%u timed out\n", chan_idx, ee);
|
||||
res = -GSI_STATUS_TIMED_OUT;
|
||||
goto free_lock;
|
||||
}
|
||||
|
||||
gsi_ctx->scratch.word0.val = gsi_readl(gsi_ctx->base +
|
||||
GSI_EE_n_CNTXT_SCRATCH_0_OFFS(gsi_ctx->per.ee));
|
||||
|
||||
*code = gsi_ctx->scratch.word0.s.generic_ee_cmd_return_val;
|
||||
|
||||
if (prmy_scnd_fc)
|
||||
res = (gsi_ctx->scratch.word0.s.generic_ee_cmd_return_val ==
|
||||
GSI_GEN_EE_CMD_RETURN_VAL_FLOW_CONTROL_SECONDARY)?
|
||||
GSI_STATUS_SUCCESS:-GSI_STATUS_ERROR;
|
||||
else
|
||||
res = (gsi_ctx->scratch.word0.s.generic_ee_cmd_return_val ==
|
||||
GSI_GEN_EE_CMD_RETURN_VAL_FLOW_CONTROL_PRIMARY)?
|
||||
GSI_STATUS_SUCCESS:-GSI_STATUS_ERROR;
|
||||
|
||||
free_lock:
|
||||
__gsi_config_glob_irq(gsi_ctx->per.ee,
|
||||
GSI_EE_n_CNTXT_GLOB_IRQ_EN_GP_INT1_BMSK, 0);
|
||||
mutex_unlock(&gsi_ctx->mlock);
|
||||
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(gsi_query_flow_control_state_ee);
|
||||
|
||||
|
||||
int gsi_map_virtual_ch_to_per_ep(u32 ee, u32 chan_num, u32 per_ep_index)
|
||||
{
|
||||
if (!gsi_ctx) {
|
||||
|
@ -1228,7 +1228,9 @@ struct gsi_ee_scratch {
|
||||
uint32_t inter_ee_cmd_return_code:3;
|
||||
uint32_t resvd1:2;
|
||||
uint32_t generic_ee_cmd_return_code:3;
|
||||
uint32_t resvd2:7;
|
||||
uint32_t resvd2:2;
|
||||
uint32_t generic_ee_cmd_return_val:3;
|
||||
uint32_t resvd4:2;
|
||||
uint32_t max_usb_pkt_size:1;
|
||||
uint32_t resvd3:8;
|
||||
uint32_t mhi_base_chan_idx:8;
|
||||
@ -1397,6 +1399,7 @@ enum gsi_generic_ee_cmd_opcode {
|
||||
GSI_GEN_EE_CMD_ALLOC_CHANNEL = 0x2,
|
||||
GSI_GEN_EE_CMD_ENABLE_FLOW_CHANNEL = 0x3,
|
||||
GSI_GEN_EE_CMD_DISABLE_FLOW_CHANNEL = 0x4,
|
||||
GSI_GEN_EE_CMD_QUERY_FLOW_CHANNEL = 0x5,
|
||||
};
|
||||
|
||||
enum gsi_generic_ee_cmd_return_code {
|
||||
@ -1409,6 +1412,11 @@ enum gsi_generic_ee_cmd_return_code {
|
||||
GSI_GEN_EE_CMD_RETURN_CODE_OUT_OF_RESOURCES = 0x7,
|
||||
};
|
||||
|
||||
enum gsi_generic_ee_cmd_query_retun_val {
|
||||
GSI_GEN_EE_CMD_RETURN_VAL_FLOW_CONTROL_PRIMARY = 0,
|
||||
GSI_GEN_EE_CMD_RETURN_VAL_FLOW_CONTROL_SECONDARY = 1,
|
||||
GSI_GEN_EE_CMD_RETURN_VAL_FLOW_CONTROL_PENDING = 2,
|
||||
};
|
||||
extern struct gsi_ctx *gsi_ctx;
|
||||
|
||||
/**
|
||||
@ -2119,7 +2127,10 @@ int gsi_alloc_channel_ee(unsigned int chan_idx, unsigned int ee, int *code);
|
||||
*/
|
||||
int gsi_enable_flow_control_ee(unsigned int chan_idx, unsigned int ee,
|
||||
int *code);
|
||||
|
||||
int gsi_flow_control_ee(unsigned int chan_idx, unsigned int ee,
|
||||
bool enable, bool prmy_scnd_fc, int *code);
|
||||
int gsi_query_flow_control_state_ee(unsigned int chan_idx, unsigned int ee,
|
||||
bool prmy_scnd_fc, int *code);
|
||||
/*
|
||||
* Here is a typical sequence of calls
|
||||
*
|
||||
|
@ -749,6 +749,8 @@
|
||||
#define GSI_EE_n_GSI_EE_GENERIC_CMD_VIRT_CHAN_IDX_SHFT 0x5
|
||||
#define GSI_EE_n_GSI_EE_GENERIC_CMD_EE_BMSK 0x3c00
|
||||
#define GSI_EE_n_GSI_EE_GENERIC_CMD_EE_SHFT 0xa
|
||||
#define GSI_EE_n_GSI_EE_GENERIC_CMD_PARAM_BMSK 0xff000000
|
||||
#define GSI_EE_n_GSI_EE_GENERIC_CMD_PARAM_SHFT 0x18
|
||||
|
||||
#define GSI_V1_0_EE_n_GSI_HW_PARAM_OFFS(n) \
|
||||
(GSI_GSI_REG_BASE_OFFS + 0x0001f040 + 0x4000 * (n))
|
||||
@ -1178,6 +1180,11 @@
|
||||
#define GSI_EE_n_CNTXT_SCRATCH_0_SCRATCH_BMSK 0xffffffff
|
||||
#define GSI_EE_n_CNTXT_SCRATCH_0_SCRATCH_SHFT 0x0
|
||||
|
||||
#define GSI_EE_n_CNTXT_SCRATCH_1_OFFS(n) \
|
||||
(GSI_GSI_REG_BASE_OFFS + 0x00012404 + 0x4000 * (n))
|
||||
#define GSI_EE_n_CNTXT_SCRATCH_1_SCRATCH_BMSK 0xffffffff
|
||||
#define GSI_EE_n_CNTXT_SCRATCH_1_SCRATCH_SHFT 0x0
|
||||
|
||||
#define GSI_INTER_EE_n_SRC_GSI_CH_IRQ_OFFS(n) \
|
||||
(GSI_GSI_REG_BASE_OFFS + 0x0000c018 + 0x1000 * (n))
|
||||
#define GSI_INTER_EE_n_SRC_GSI_CH_IRQ_GSI_CH_BIT_MAP_BMSK 0xffffffff
|
||||
|
@ -3312,6 +3312,40 @@ static void ipa3_destroy_imm(void *user1, int user2)
|
||||
ipahal_destroy_imm_cmd(user1);
|
||||
}
|
||||
|
||||
static void ipa3_q6_pipe_flow_control(bool delay)
|
||||
{
|
||||
int ep_idx;
|
||||
int client_idx;
|
||||
int code = 0, result;
|
||||
const struct ipa_gsi_ep_config *gsi_ep_cfg;
|
||||
|
||||
for (client_idx = 0; client_idx < IPA_CLIENT_MAX; client_idx++) {
|
||||
if (IPA_CLIENT_IS_Q6_PROD(client_idx)) {
|
||||
ep_idx = ipa3_get_ep_mapping(client_idx);
|
||||
if (ep_idx == -1)
|
||||
continue;
|
||||
gsi_ep_cfg = ipa3_get_gsi_ep_info(client_idx);
|
||||
if (!gsi_ep_cfg) {
|
||||
IPAERR("failed to get GSI config\n");
|
||||
ipa_assert();
|
||||
return;
|
||||
}
|
||||
IPADBG("pipe setting V2 flow control\n");
|
||||
/* Configurig primary flow control on Q6 pipes*/
|
||||
result = gsi_flow_control_ee(
|
||||
gsi_ep_cfg->ipa_gsi_chan_num,
|
||||
gsi_ep_cfg->ee, delay, false, &code);
|
||||
if (result == GSI_STATUS_SUCCESS) {
|
||||
IPADBG("sussess gsi ch %d with code %d\n",
|
||||
gsi_ep_cfg->ipa_gsi_chan_num, code);
|
||||
} else {
|
||||
IPADBG("failed gsi ch %d code %d\n",
|
||||
gsi_ep_cfg->ipa_gsi_chan_num, code);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ipa3_q6_pipe_delay(bool delay)
|
||||
{
|
||||
int client_idx;
|
||||
@ -3987,8 +4021,12 @@ void ipa3_q6_pre_shutdown_cleanup(void)
|
||||
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
|
||||
|
||||
ipa3_update_ssr_state(true);
|
||||
if (!ipa3_ctx->ipa_endp_delay_wa)
|
||||
|
||||
if (ipa3_ctx->ipa_endp_delay_wa_v2)
|
||||
ipa3_q6_pipe_flow_control(true);
|
||||
else if (!ipa3_ctx->ipa_endp_delay_wa)
|
||||
ipa3_q6_pipe_delay(true);
|
||||
|
||||
ipa3_q6_avoid_holb();
|
||||
if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) {
|
||||
prod = true;
|
||||
@ -4016,7 +4054,11 @@ void ipa3_q6_pre_shutdown_cleanup(void)
|
||||
/* Remove delay from Q6 PRODs to avoid pending descriptors
|
||||
* on pipe reset procedure
|
||||
*/
|
||||
if (!ipa3_ctx->ipa_endp_delay_wa) {
|
||||
if (ipa3_ctx->ipa_endp_delay_wa_v2) {
|
||||
ipa3_q6_pipe_flow_control(false);
|
||||
ipa3_set_reset_client_prod_pipe_delay(true,
|
||||
IPA_CLIENT_USB_PROD);
|
||||
} else if (!ipa3_ctx->ipa_endp_delay_wa) {
|
||||
ipa3_q6_pipe_delay(false);
|
||||
ipa3_set_reset_client_prod_pipe_delay(true,
|
||||
IPA_CLIENT_USB_PROD);
|
||||
@ -7103,6 +7145,7 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
|
||||
ipa3_ctx->do_testbus_collection_on_crash = false;
|
||||
}
|
||||
ipa3_ctx->ipa_endp_delay_wa = resource_p->ipa_endp_delay_wa;
|
||||
ipa3_ctx->ipa_endp_delay_wa_v2 = resource_p->ipa_endp_delay_wa_v2;
|
||||
|
||||
WARN(ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_NORMAL,
|
||||
"Non NORMAL IPA HW mode, is this emulation platform ?");
|
||||
@ -7850,6 +7893,7 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
|
||||
ipa_drv_res->ipa_config_is_auto = false;
|
||||
ipa_drv_res->manual_fw_load = false;
|
||||
ipa_drv_res->max_num_smmu_cb = IPA_SMMU_CB_MAX;
|
||||
ipa_drv_res->ipa_endp_delay_wa_v2 = false;
|
||||
|
||||
/* Get IPA HW Version */
|
||||
result = of_property_read_u32(pdev->dev.of_node, "qcom,ipa-hw-ver",
|
||||
@ -7942,6 +7986,14 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
|
||||
ipa_drv_res->ipa_endp_delay_wa
|
||||
? "True" : "False");
|
||||
|
||||
ipa_drv_res->ipa_endp_delay_wa_v2 =
|
||||
of_property_read_bool(pdev->dev.of_node,
|
||||
"qcom,ipa-endp-delay-wa-v2");
|
||||
IPADBG(": endppoint delay wa v2 = %s\n",
|
||||
ipa_drv_res->ipa_endp_delay_wa_v2
|
||||
? "True" : "False");
|
||||
|
||||
|
||||
ipa_drv_res->ipa_wdi3_over_gsi =
|
||||
of_property_read_bool(pdev->dev.of_node,
|
||||
"qcom,ipa-wdi3-over-gsi");
|
||||
|
@ -1176,6 +1176,29 @@ static int ipa3_xdci_stop_gsi_ch_brute_force(u32 clnt_hdl,
|
||||
}
|
||||
}
|
||||
|
||||
int ipa3_remove_secondary_flow_ctrl(int gsi_chan_hdl)
|
||||
{
|
||||
int code = 0;
|
||||
int result;
|
||||
|
||||
result = gsi_query_flow_control_state_ee(gsi_chan_hdl, 0, 1, &code);
|
||||
if (result == GSI_STATUS_SUCCESS) {
|
||||
code = 0;
|
||||
result = gsi_flow_control_ee(gsi_chan_hdl, 0, false, true,
|
||||
&code);
|
||||
if (result == GSI_STATUS_SUCCESS) {
|
||||
IPADBG("flow control sussess ch %d code %d\n",
|
||||
gsi_chan_hdl, code);
|
||||
} else {
|
||||
IPADBG("failed to flow control ch %d code %d\n",
|
||||
gsi_chan_hdl, code);
|
||||
}
|
||||
} else {
|
||||
IPADBG("failed to query flow control mode ch %d code %d\n",
|
||||
gsi_chan_hdl, code);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/* Clocks should be voted for before invoking this function */
|
||||
static int ipa3_stop_ul_chan_with_data_drain(u32 qmi_req_id,
|
||||
u32 source_pipe_bitmask, bool should_force_clear, u32 clnt_hdl,
|
||||
@ -1261,10 +1284,15 @@ static int ipa3_stop_ul_chan_with_data_drain(u32 qmi_req_id,
|
||||
IPAERR(
|
||||
"failed to force clear %d, remove delay from SCND reg\n"
|
||||
, result);
|
||||
ep_ctrl_scnd.endp_delay = false;
|
||||
ipahal_write_reg_n_fields(
|
||||
IPA_ENDP_INIT_CTRL_SCND_n, clnt_hdl,
|
||||
&ep_ctrl_scnd);
|
||||
if (ipa3_ctx->ipa_endp_delay_wa_v2) {
|
||||
ipa3_remove_secondary_flow_ctrl(
|
||||
ep->gsi_chan_hdl);
|
||||
} else {
|
||||
ep_ctrl_scnd.endp_delay = false;
|
||||
ipahal_write_reg_n_fields(
|
||||
IPA_ENDP_INIT_CTRL_SCND_n, clnt_hdl,
|
||||
&ep_ctrl_scnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* with force clear, wait for emptiness */
|
||||
|
@ -2144,6 +2144,7 @@ struct ipa3_context {
|
||||
bool manual_fw_load;
|
||||
u32 num_smmu_cb_probed;
|
||||
u32 max_num_smmu_cb;
|
||||
bool ipa_endp_delay_wa_v2;
|
||||
};
|
||||
|
||||
struct ipa3_plat_drv_res {
|
||||
@ -2212,6 +2213,7 @@ struct ipa3_plat_drv_res {
|
||||
bool manual_fw_load;
|
||||
bool ipa_config_is_auto;
|
||||
u32 max_num_smmu_cb;
|
||||
bool ipa_endp_delay_wa_v2;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2904,6 +2906,7 @@ void ipa3_skb_recycle(struct sk_buff *skb);
|
||||
void ipa3_install_dflt_flt_rules(u32 ipa_ep_idx);
|
||||
void ipa3_delete_dflt_flt_rules(u32 ipa_ep_idx);
|
||||
|
||||
int ipa3_remove_secondary_flow_ctrl(int gsi_chan_hdl);
|
||||
int ipa3_enable_data_path(u32 clnt_hdl);
|
||||
int ipa3_disable_data_path(u32 clnt_hdl);
|
||||
int ipa3_disable_gsi_data_path(u32 clnt_hdl);
|
||||
|
@ -1402,12 +1402,6 @@ int ipa3_connect_gsi_wdi_pipe(struct ipa_wdi_in_params *in,
|
||||
ep->skip_ep_cfg = in->sys.skip_ep_cfg;
|
||||
ep->client_notify = in->sys.notify;
|
||||
ep->priv = in->sys.priv;
|
||||
if (IPA_CLIENT_IS_PROD(in->sys.client)) {
|
||||
memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl));
|
||||
ep_cfg_ctrl.ipa_ep_delay = true;
|
||||
ipa3_cfg_ep_ctrl(ipa_ep_idx, &ep_cfg_ctrl);
|
||||
}
|
||||
|
||||
if (IPA_CLIENT_IS_CONS(in->sys.client)) {
|
||||
in->sys.ipa_ep_cfg.aggr.aggr_en = IPA_ENABLE_AGGR;
|
||||
in->sys.ipa_ep_cfg.aggr.aggr = IPA_GENERIC;
|
||||
@ -1444,6 +1438,13 @@ int ipa3_connect_gsi_wdi_pipe(struct ipa_wdi_in_params *in,
|
||||
&ep->gsi_chan_hdl, ep->gsi_evt_ring_hdl);
|
||||
if (result)
|
||||
goto fail_alloc_channel;
|
||||
|
||||
if (IPA_CLIENT_IS_PROD(in->sys.client)) {
|
||||
memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl));
|
||||
ep_cfg_ctrl.ipa_ep_delay = true;
|
||||
ipa3_cfg_ep_ctrl(ipa_ep_idx, &ep_cfg_ctrl);
|
||||
}
|
||||
|
||||
ep->gsi_mem_info.chan_ring_len = gsi_channel_props.ring_len;
|
||||
ep->gsi_mem_info.chan_ring_base_addr = gsi_channel_props.ring_base_addr;
|
||||
ep->gsi_mem_info.chan_ring_base_vaddr =
|
||||
@ -2657,10 +2658,15 @@ int ipa3_suspend_gsi_wdi_pipe(u32 clnt_hdl)
|
||||
*/
|
||||
IPAERR("failed to force clear %d\n", res);
|
||||
IPAERR("remove delay from SCND reg\n");
|
||||
ep_ctrl_scnd.endp_delay = false;
|
||||
ipahal_write_reg_n_fields(
|
||||
IPA_ENDP_INIT_CTRL_SCND_n, clnt_hdl,
|
||||
&ep_ctrl_scnd);
|
||||
if (ipa3_ctx->ipa_endp_delay_wa_v2) {
|
||||
ipa3_remove_secondary_flow_ctrl(
|
||||
ep->gsi_chan_hdl);
|
||||
} else {
|
||||
ep_ctrl_scnd.endp_delay = false;
|
||||
ipahal_write_reg_n_fields(
|
||||
IPA_ENDP_INIT_CTRL_SCND_n,
|
||||
clnt_hdl, &ep_ctrl_scnd);
|
||||
}
|
||||
} else {
|
||||
disable_force_clear = true;
|
||||
}
|
||||
@ -2785,10 +2791,15 @@ int ipa3_suspend_wdi_pipe(u32 clnt_hdl)
|
||||
*/
|
||||
IPAERR("failed to force clear %d\n", result);
|
||||
IPAERR("remove delay from SCND reg\n");
|
||||
ep_ctrl_scnd.endp_delay = false;
|
||||
ipahal_write_reg_n_fields(
|
||||
if (ipa3_ctx->ipa_endp_delay_wa_v2) {
|
||||
ipa3_remove_secondary_flow_ctrl(
|
||||
ep->gsi_chan_hdl);
|
||||
} else {
|
||||
ep_ctrl_scnd.endp_delay = false;
|
||||
ipahal_write_reg_n_fields(
|
||||
IPA_ENDP_INIT_CTRL_SCND_n, clnt_hdl,
|
||||
&ep_ctrl_scnd);
|
||||
}
|
||||
} else {
|
||||
disable_force_clear = true;
|
||||
}
|
||||
|
@ -5792,6 +5792,10 @@ int ipa3_cfg_ep_hdr_ext(u32 clnt_hdl,
|
||||
*/
|
||||
int ipa3_cfg_ep_ctrl(u32 clnt_hdl, const struct ipa_ep_cfg_ctrl *ep_ctrl)
|
||||
{
|
||||
int code = 0, result;
|
||||
struct ipa3_ep_context *ep;
|
||||
bool primary_secondry;
|
||||
|
||||
if (clnt_hdl >= ipa3_ctx->ipa_num_pipes || ep_ctrl == NULL) {
|
||||
IPAERR("bad parm, clnt_hdl = %d\n", clnt_hdl);
|
||||
return -EINVAL;
|
||||
@ -5812,6 +5816,33 @@ int ipa3_cfg_ep_ctrl(u32 clnt_hdl, const struct ipa_ep_cfg_ctrl *ep_ctrl)
|
||||
clnt_hdl,
|
||||
ep_ctrl->ipa_ep_suspend,
|
||||
ep_ctrl->ipa_ep_delay);
|
||||
ep = &ipa3_ctx->ep[clnt_hdl];
|
||||
if (ipa3_ctx->ipa_endp_delay_wa_v2 &&
|
||||
IPA_CLIENT_IS_PROD(ep->client)) {
|
||||
|
||||
IPADBG("Configuring flow control for pipe = %d\n", clnt_hdl);
|
||||
/* Configure enhanced flow control instead of delay
|
||||
* Q6 controlled AP pipes(USB PROD and MHI_PROD) configuring the
|
||||
* secondary flow control.
|
||||
* AP controlled pipe configuring primary flow control.
|
||||
*/
|
||||
if (ep->client == IPA_CLIENT_USB_PROD ||
|
||||
ep->client == IPA_CLIENT_MHI_PROD)
|
||||
primary_secondry = true;
|
||||
else
|
||||
primary_secondry = false;
|
||||
|
||||
result = gsi_flow_control_ee(ep->gsi_chan_hdl, 0,
|
||||
ep_ctrl->ipa_ep_delay, primary_secondry, &code);
|
||||
if (result == GSI_STATUS_SUCCESS) {
|
||||
IPADBG("flow control sussess gsi ch %d with code %d\n",
|
||||
ep->gsi_chan_hdl, code);
|
||||
} else {
|
||||
IPADBG("failed to flow control gsi ch %d code %d\n",
|
||||
ep->gsi_chan_hdl, code);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ipahal_write_reg_n_fields(IPA_ENDP_INIT_CTRL_n, clnt_hdl, ep_ctrl);
|
||||
|
||||
|
@ -974,10 +974,16 @@ int ipa3_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
|
||||
*/
|
||||
IPAERR("failed to force clear %d\n", result);
|
||||
IPAERR("remove delay from SCND reg\n");
|
||||
ep_ctrl_scnd.endp_delay = false;
|
||||
ipahal_write_reg_n_fields(
|
||||
IPA_ENDP_INIT_CTRL_SCND_n, ipa_ep_idx_rx,
|
||||
&ep_ctrl_scnd);
|
||||
if (ipa3_ctx->ipa_endp_delay_wa_v2) {
|
||||
ipa3_remove_secondary_flow_ctrl(
|
||||
ep->gsi_chan_hdl);
|
||||
} else {
|
||||
ep_ctrl_scnd.endp_delay = false;
|
||||
ipahal_write_reg_n_fields(
|
||||
IPA_ENDP_INIT_CTRL_SCND_n,
|
||||
ipa_ep_idx_rx,
|
||||
&ep_ctrl_scnd);
|
||||
}
|
||||
} else {
|
||||
disable_force_clear = true;
|
||||
}
|
||||
|
@ -1820,10 +1820,16 @@ int ipa3_disable_wigig_pipe_i(enum ipa_client_type client)
|
||||
*/
|
||||
IPAERR("failed to force clear %d\n", res);
|
||||
IPAERR("remove delay from SCND reg\n");
|
||||
ep_ctrl_scnd.endp_delay = false;
|
||||
ipahal_write_reg_n_fields(
|
||||
IPA_ENDP_INIT_CTRL_SCND_n, ipa_ep_idx,
|
||||
&ep_ctrl_scnd);
|
||||
if (ipa3_ctx->ipa_endp_delay_wa_v2) {
|
||||
ipa3_remove_secondary_flow_ctrl(
|
||||
ep->gsi_chan_hdl);
|
||||
} else {
|
||||
ep_ctrl_scnd.endp_delay = false;
|
||||
ipahal_write_reg_n_fields(
|
||||
IPA_ENDP_INIT_CTRL_SCND_n,
|
||||
ipa_ep_idx,
|
||||
&ep_ctrl_scnd);
|
||||
}
|
||||
} else {
|
||||
disable_force_clear = true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user