mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-12 15:49:17 -04:00
mhi: controller: qcom: Enable MHI register write offload support
When PCIe endpoint enters L1SS sleep and mhi client on Host tries to queue a transfer request endpoint takes more than 6ms to come back to L0 state. This can cause CPU stall if MHI register write is followed by a write memory barrier. This can cause other tasks to get blocked. Prevent this situation by offloading MHI register write to a high priority worker thread when in AMSS. When thread gets a chance to run it would first bring the link to L0 and then perform register write. Change-Id: I1b4839801df140fc50973e92e2522eb57d2897fa Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
This commit is contained in:
parent
f69d3db037
commit
574f72b01f
3 changed files with 49 additions and 0 deletions
|
|
@ -54,6 +54,37 @@ enum MHI_DEBUG_LEVEL mhi_ipc_log_lvl = MHI_MSG_LVL_ERROR;
|
|||
|
||||
#endif
|
||||
|
||||
void mhi_reg_write_work(struct work_struct *w)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = container_of(w,
|
||||
struct mhi_controller,
|
||||
reg_write_work);
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
struct pci_dev *pci_dev = mhi_dev->pci_dev;
|
||||
struct reg_write_info *info =
|
||||
&mhi_cntrl->reg_write_q[mhi_cntrl->read_idx];
|
||||
|
||||
if (!info->valid)
|
||||
return;
|
||||
|
||||
if (mhi_is_active(mhi_cntrl->mhi_dev) && msm_pcie_prevent_l1(pci_dev))
|
||||
return;
|
||||
|
||||
while (info->valid) {
|
||||
if (!mhi_is_active(mhi_cntrl->mhi_dev))
|
||||
return;
|
||||
|
||||
writel_relaxed(info->val, info->reg_addr);
|
||||
info->valid = false;
|
||||
mhi_cntrl->read_idx =
|
||||
(mhi_cntrl->read_idx + 1) &
|
||||
(REG_WRITE_QUEUE_LEN - 1);
|
||||
info = &mhi_cntrl->reg_write_q[mhi_cntrl->read_idx];
|
||||
}
|
||||
|
||||
msm_pcie_allow_l1(pci_dev);
|
||||
}
|
||||
|
||||
static int mhi_arch_pm_notifier(struct notifier_block *nb,
|
||||
unsigned long event, void *unused)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -754,11 +754,28 @@ static struct mhi_controller *mhi_register_controller(struct pci_dev *pci_dev)
|
|||
mhi_cntrl->fw_image = firmware_info->fw_image;
|
||||
mhi_cntrl->edl_image = firmware_info->edl_image;
|
||||
|
||||
mhi_cntrl->offload_wq = alloc_ordered_workqueue("offload_wq",
|
||||
WQ_MEM_RECLAIM | WQ_HIGHPRI);
|
||||
if (!mhi_cntrl->offload_wq)
|
||||
goto error_register;
|
||||
|
||||
INIT_WORK(&mhi_cntrl->reg_write_work, mhi_reg_write_work);
|
||||
|
||||
mhi_cntrl->reg_write_q = kcalloc(REG_WRITE_QUEUE_LEN,
|
||||
sizeof(*mhi_cntrl->reg_write_q),
|
||||
GFP_KERNEL);
|
||||
if (!mhi_cntrl->reg_write_q)
|
||||
goto error_free_wq;
|
||||
|
||||
atomic_set(&mhi_cntrl->write_idx, -1);
|
||||
|
||||
if (sysfs_create_group(&mhi_cntrl->mhi_dev->dev.kobj, &mhi_qcom_group))
|
||||
MHI_ERR("Error while creating the sysfs group\n");
|
||||
|
||||
return mhi_cntrl;
|
||||
|
||||
error_free_wq:
|
||||
destroy_workqueue(mhi_cntrl->offload_wq);
|
||||
error_register:
|
||||
mhi_free_controller(mhi_cntrl);
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ struct mhi_dev {
|
|||
void mhi_deinit_pci_dev(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_pci_probe(struct pci_dev *pci_dev,
|
||||
const struct pci_device_id *device_id);
|
||||
void mhi_reg_write_work(struct work_struct *w);
|
||||
|
||||
#ifdef CONFIG_ARCH_QCOM
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue