Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 230ccf8b authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "mhi: controller: qcom: Enable MHI regitser write offload support"

parents 88cfc73d ad7ec668
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -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)
{
+21 −0
Original line number Diff line number Diff line
@@ -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);

+1 −0
Original line number Diff line number Diff line
@@ -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

+4 −0
Original line number Diff line number Diff line
@@ -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)
@@ -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);
+38 −0
Original line number Diff line number Diff line
@@ -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