Loading drivers/bus/mhi/controllers/mhi_arch_qcom.c +31 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,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) { Loading drivers/bus/mhi/controllers/mhi_qcom.c +21 −0 Original line number Diff line number Diff line Loading @@ -780,8 +780,29 @@ static struct mhi_controller *mhi_register_controller(struct pci_dev *pci_dev) if (ret) goto error_register; if (mhi_dev->allow_m1) goto skip_offload; 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); skip_offload: return mhi_cntrl; error_free_wq: destroy_workqueue(mhi_cntrl->offload_wq); error_register: mhi_free_controller(mhi_cntrl); Loading drivers/bus/mhi/controllers/mhi_qcom.h +1 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,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 drivers/bus/mhi/core/mhi_internal.h +4 −0 Original line number Diff line number Diff line Loading @@ -834,6 +834,8 @@ void mhi_destroy_timesync(struct mhi_controller *mhi_cntrl); int mhi_create_sysfs(struct mhi_controller *mhi_cntrl); void mhi_destroy_sysfs(struct mhi_controller *mhi_cntrl); int mhi_early_notify_device(struct device *dev, void *data); void mhi_write_reg_offload(struct mhi_controller *mhi_cntrl, void __iomem *base, u32 offset, u32 val); /* timesync log support */ static inline void mhi_timesync_log(struct mhi_controller *mhi_cntrl) Loading Loading @@ -903,6 +905,8 @@ void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl, struct image_info *img_info); int mhi_prepare_channel(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan); void mhi_reset_reg_write_q(struct mhi_controller *mhi_cntrl); void mhi_force_reg_write(struct mhi_controller *mhi_cntrl); /* isr handlers */ irqreturn_t mhi_msi_handlr(int irq_number, void *dev); Loading drivers/bus/mhi/core/mhi_main.c +38 −0 Original line number Diff line number Diff line Loading @@ -100,6 +100,44 @@ int mhi_get_capability_offset(struct mhi_controller *mhi_cntrl, return -ENXIO; } void mhi_force_reg_write(struct mhi_controller *mhi_cntrl) { if (mhi_cntrl->offload_wq) flush_work(&mhi_cntrl->reg_write_work); } void mhi_reset_reg_write_q(struct mhi_controller *mhi_cntrl) { cancel_work_sync(&mhi_cntrl->reg_write_work); memset(mhi_cntrl->reg_write_q, 0, sizeof(struct reg_write_info) * REG_WRITE_QUEUE_LEN); mhi_cntrl->read_idx = 0; atomic_set(&mhi_cntrl->write_idx, -1); } static void mhi_reg_write_enqueue(struct mhi_controller *mhi_cntrl, void __iomem *reg_addr, u32 val) { u32 q_index = atomic_inc_return(&mhi_cntrl->write_idx); q_index = q_index & (REG_WRITE_QUEUE_LEN - 1); MHI_ASSERT(mhi_cntrl->reg_write_q[q_index].valid, "queue full idx %d"); mhi_cntrl->reg_write_q[q_index].reg_addr = reg_addr; mhi_cntrl->reg_write_q[q_index].val = val; mhi_cntrl->reg_write_q[q_index].valid = true; } void mhi_write_reg_offload(struct mhi_controller *mhi_cntrl, void __iomem *base, u32 offset, u32 val) { mhi_reg_write_enqueue(mhi_cntrl, base + offset, val); queue_work(mhi_cntrl->offload_wq, &mhi_cntrl->reg_write_work); } void mhi_write_reg(struct mhi_controller *mhi_cntrl, void __iomem *base, u32 offset, Loading Loading
drivers/bus/mhi/controllers/mhi_arch_qcom.c +31 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,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) { Loading
drivers/bus/mhi/controllers/mhi_qcom.c +21 −0 Original line number Diff line number Diff line Loading @@ -780,8 +780,29 @@ static struct mhi_controller *mhi_register_controller(struct pci_dev *pci_dev) if (ret) goto error_register; if (mhi_dev->allow_m1) goto skip_offload; 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); skip_offload: return mhi_cntrl; error_free_wq: destroy_workqueue(mhi_cntrl->offload_wq); error_register: mhi_free_controller(mhi_cntrl); Loading
drivers/bus/mhi/controllers/mhi_qcom.h +1 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,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
drivers/bus/mhi/core/mhi_internal.h +4 −0 Original line number Diff line number Diff line Loading @@ -834,6 +834,8 @@ void mhi_destroy_timesync(struct mhi_controller *mhi_cntrl); int mhi_create_sysfs(struct mhi_controller *mhi_cntrl); void mhi_destroy_sysfs(struct mhi_controller *mhi_cntrl); int mhi_early_notify_device(struct device *dev, void *data); void mhi_write_reg_offload(struct mhi_controller *mhi_cntrl, void __iomem *base, u32 offset, u32 val); /* timesync log support */ static inline void mhi_timesync_log(struct mhi_controller *mhi_cntrl) Loading Loading @@ -903,6 +905,8 @@ void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl, struct image_info *img_info); int mhi_prepare_channel(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan); void mhi_reset_reg_write_q(struct mhi_controller *mhi_cntrl); void mhi_force_reg_write(struct mhi_controller *mhi_cntrl); /* isr handlers */ irqreturn_t mhi_msi_handlr(int irq_number, void *dev); Loading
drivers/bus/mhi/core/mhi_main.c +38 −0 Original line number Diff line number Diff line Loading @@ -100,6 +100,44 @@ int mhi_get_capability_offset(struct mhi_controller *mhi_cntrl, return -ENXIO; } void mhi_force_reg_write(struct mhi_controller *mhi_cntrl) { if (mhi_cntrl->offload_wq) flush_work(&mhi_cntrl->reg_write_work); } void mhi_reset_reg_write_q(struct mhi_controller *mhi_cntrl) { cancel_work_sync(&mhi_cntrl->reg_write_work); memset(mhi_cntrl->reg_write_q, 0, sizeof(struct reg_write_info) * REG_WRITE_QUEUE_LEN); mhi_cntrl->read_idx = 0; atomic_set(&mhi_cntrl->write_idx, -1); } static void mhi_reg_write_enqueue(struct mhi_controller *mhi_cntrl, void __iomem *reg_addr, u32 val) { u32 q_index = atomic_inc_return(&mhi_cntrl->write_idx); q_index = q_index & (REG_WRITE_QUEUE_LEN - 1); MHI_ASSERT(mhi_cntrl->reg_write_q[q_index].valid, "queue full idx %d"); mhi_cntrl->reg_write_q[q_index].reg_addr = reg_addr; mhi_cntrl->reg_write_q[q_index].val = val; mhi_cntrl->reg_write_q[q_index].valid = true; } void mhi_write_reg_offload(struct mhi_controller *mhi_cntrl, void __iomem *base, u32 offset, u32 val) { mhi_reg_write_enqueue(mhi_cntrl, base + offset, val); queue_work(mhi_cntrl->offload_wq, &mhi_cntrl->reg_write_work); } void mhi_write_reg(struct mhi_controller *mhi_cntrl, void __iomem *base, u32 offset, Loading