Merge "msm: ipa: load IPA FW after smmu CB are probed"

This commit is contained in:
qctecmdr 2019-12-16 11:29:58 -08:00 • committed by Gerrit - the friendly Code Review server
commit 7847fb4f8a
2 changed files with 104 additions and 13 deletions

View file

@ -6174,6 +6174,9 @@ static void ipa3_load_ipa_fw(struct work_struct *work)
result);
return;
}
mutex_lock(&ipa3_ctx->fw_load_data.lock);
ipa3_ctx->fw_load_data.state = IPA_FW_LOAD_STATE_LOADED;
mutex_unlock(&ipa3_ctx->fw_load_data.lock);
pr_info("IPA FW loaded successfully\n");
result = ipa3_post_init(&ipa3_res, ipa3_ctx->cdev.dev);
@ -6201,6 +6204,58 @@ static void ipa3_load_ipa_fw(struct work_struct *work)
}
}
static void ipa_fw_load_sm_handle_event(enum ipa_fw_load_event ev)
{
mutex_lock(&ipa3_ctx->fw_load_data.lock);
IPADBG("state=%d event=%d\n", ipa3_ctx->fw_load_data.state, ev);
if (ev == IPA_FW_LOAD_EVNT_FWFILE_READY) {
if (ipa3_ctx->fw_load_data.state == IPA_FW_LOAD_STATE_INIT) {
ipa3_ctx->fw_load_data.state =
IPA_FW_LOAD_STATE_FWFILE_READY;
goto out;
}
if (ipa3_ctx->fw_load_data.state ==
IPA_FW_LOAD_STATE_SMMU_DONE) {
ipa3_ctx->fw_load_data.state =
IPA_FW_LOAD_STATE_LOAD_READY;
goto sched_fw_load;
}
IPAERR("ignore multiple requests to load FW\n");
goto out;
}
if (ev == IPA_FW_LOAD_EVNT_SMMU_DONE) {
if (ipa3_ctx->fw_load_data.state == IPA_FW_LOAD_STATE_INIT) {
ipa3_ctx->fw_load_data.state =
IPA_FW_LOAD_STATE_SMMU_DONE;
goto out;
}
if (ipa3_ctx->fw_load_data.state ==
IPA_FW_LOAD_STATE_FWFILE_READY) {
ipa3_ctx->fw_load_data.state =
IPA_FW_LOAD_STATE_LOAD_READY;
goto sched_fw_load;
}
IPAERR("ignore multiple smmu done events\n");
goto out;
}
IPAERR("invalid event ev=%d\n", ev);
mutex_unlock(&ipa3_ctx->fw_load_data.lock);
ipa_assert();
return;
out:
mutex_unlock(&ipa3_ctx->fw_load_data.lock);
return;
sched_fw_load:
IPADBG("Scheduled a work to load IPA FW\n");
mutex_unlock(&ipa3_ctx->fw_load_data.lock);
queue_work(ipa3_ctx->transport_power_mgmt_wq,
&ipa3_fw_loading_work);
}
static ssize_t ipa3_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
@ -6280,19 +6335,8 @@ static ssize_t ipa3_write(struct file *file, const char __user *buf,
ipa3_ctx->ipa_config_is_mhi ? "" : "non ");
}
/* Prevent multiple calls from trying to load the FW again. */
if (ipa3_ctx->fw_loaded) {
IPAERR("not load FW again\n");
return count;
}
ipa_fw_load_sm_handle_event(IPA_FW_LOAD_EVNT_FWFILE_READY);
/* Schedule WQ to load ipa-fws */
ipa3_ctx->fw_loaded = true;
queue_work(ipa3_ctx->transport_power_mgmt_wq,
&ipa3_fw_loading_work);
IPADBG("Scheduled a work to load IPA FW\n");
return count;
}
@ -6487,6 +6531,9 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
goto fail_mem_ctx;
}
ipa3_ctx->fw_load_data.state = IPA_FW_LOAD_STATE_INIT;
mutex_init(&ipa3_ctx->fw_load_data.lock);
ipa3_ctx->logbuf = ipc_log_context_create(IPA_IPC_LOG_PAGES, "ipa", 0);
if (ipa3_ctx->logbuf == NULL)
IPADBG("failed to create IPC log, continue...\n");
@ -8158,6 +8205,27 @@ static int ipa3_smp2p_probe(struct device *dev)
return 0;
}
static void ipa_smmu_update_fw_loader(void)
{
int i;
if (smmu_info.arm_smmu) {
IPADBG("smmu is enabled\n");
for (i = 0; i < IPA_SMMU_CB_MAX; i++) {
if (!smmu_info.present[i]) {
IPADBG("CB %d not probed yet\n", i);
break;
}
}
if (i == IPA_SMMU_CB_MAX) {
IPADBG("All %d CBs probed\n", IPA_SMMU_CB_MAX);
ipa_fw_load_sm_handle_event(IPA_FW_LOAD_EVNT_SMMU_DONE);
}
} else {
IPADBG("smmu is disabled\n");
}
}
int ipa3_plat_drv_probe(struct platform_device *pdev_p,
struct ipa_api_controller *api_ctrl,
const struct of_device_id *pdrv_match)
@ -8177,6 +8245,7 @@ int ipa3_plat_drv_probe(struct platform_device *pdev_p,
cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_AP);
cb->dev = dev;
smmu_info.present[IPA_SMMU_CB_AP] = true;
ipa_smmu_update_fw_loader();
return 0;
}
@ -8189,6 +8258,7 @@ int ipa3_plat_drv_probe(struct platform_device *pdev_p,
cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_WLAN);
cb->dev = dev;
smmu_info.present[IPA_SMMU_CB_WLAN] = true;
ipa_smmu_update_fw_loader();
return 0;
}
@ -8201,6 +8271,7 @@ int ipa3_plat_drv_probe(struct platform_device *pdev_p,
cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_UC);
cb->dev = dev;
smmu_info.present[IPA_SMMU_CB_UC] = true;
ipa_smmu_update_fw_loader();
return 0;
}
@ -8213,6 +8284,7 @@ int ipa3_plat_drv_probe(struct platform_device *pdev_p,
cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_11AD);
cb->dev = dev;
smmu_info.present[IPA_SMMU_CB_11AD] = true;
ipa_smmu_update_fw_loader();
return 0;
}
@ -8258,6 +8330,7 @@ int ipa3_plat_drv_probe(struct platform_device *pdev_p,
return -EOPNOTSUPP;
}
}
ipa_fw_load_sm_handle_event(IPA_FW_LOAD_EVNT_SMMU_DONE);
}
/* Proceed to real initialization */

View file

@ -1768,6 +1768,24 @@ struct ipa3_pc_mbox_data {
struct mbox_chan *mbox;
};
enum ipa_fw_load_state {
IPA_FW_LOAD_STATE_INIT,
IPA_FW_LOAD_STATE_FWFILE_READY,
IPA_FW_LOAD_STATE_SMMU_DONE,
IPA_FW_LOAD_STATE_LOAD_READY,
IPA_FW_LOAD_STATE_LOADED,
};
enum ipa_fw_load_event {
IPA_FW_LOAD_EVNT_FWFILE_READY,
IPA_FW_LOAD_EVNT_SMMU_DONE,
};
struct ipa_fw_load_data {
enum ipa_fw_load_state state;
struct mutex lock;
};
/**
* struct ipa3_context - IPA context
* @cdev: cdev context
@ -2025,7 +2043,7 @@ struct ipa3_context {
int (*client_lock_unlock[IPA_MAX_CLNT])(bool is_lock);
bool fw_loaded;
struct ipa_fw_load_data fw_load_data;
bool (*get_teth_port_state[IPA_MAX_CLNT])(void);