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

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

Merge "mhi: core: add missing break in fast resume path"

parents 3d78fea7 c56af3db
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -818,3 +818,19 @@ int mhi_arch_link_resume(struct mhi_controller *mhi_cntrl)

	return 0;
}

int mhi_arch_link_lpm_disable(struct mhi_controller *mhi_cntrl)
{
	struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);

	return msm_pcie_prevent_l1(mhi_dev->pci_dev);
}

int mhi_arch_link_lpm_enable(struct mhi_controller *mhi_cntrl)
{
	struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);

	msm_pcie_allow_l1(mhi_dev->pci_dev);

	return 0;
}
+52 −79
Original line number Diff line number Diff line
@@ -81,9 +81,6 @@ void mhi_deinit_pci_dev(struct mhi_controller *mhi_cntrl)
	pm_runtime_dont_use_autosuspend(&pci_dev->dev);
	pm_runtime_disable(&pci_dev->dev);

	/* reset counter for lpm state changes */
	mhi_dev->lpm_disable_depth = 0;

	pci_free_irq_vectors(pci_dev);
	kfree(mhi_cntrl->irq);
	mhi_cntrl->irq = NULL;
@@ -434,89 +431,26 @@ static int mhi_link_status(struct mhi_controller *mhi_cntrl, void *priv)
/* disable PCIe L1 */
static int mhi_lpm_disable(struct mhi_controller *mhi_cntrl, void *priv)
{
	struct mhi_dev *mhi_dev = priv;
	struct pci_dev *pci_dev = mhi_dev->pci_dev;
	int lnkctl = pci_dev->pcie_cap + PCI_EXP_LNKCTL;
	u8 val;
	unsigned long flags;
	int ret = 0;

	spin_lock_irqsave(&mhi_dev->lpm_lock, flags);

	/* L1 is already disabled */
	if (mhi_dev->lpm_disable_depth) {
		mhi_dev->lpm_disable_depth++;
		goto lpm_disable_exit;
	}

	ret = pci_read_config_byte(pci_dev, lnkctl, &val);
	if (ret) {
		MHI_ERR("Error reading LNKCTL, ret:%d\n", ret);
		goto lpm_disable_exit;
	}

	/* L1 is not supported, do not increment lpm_disable_depth */
	if (unlikely(!(val & PCI_EXP_LNKCTL_ASPM_L1)))
		goto lpm_disable_exit;

	val &= ~PCI_EXP_LNKCTL_ASPM_L1;
	ret = pci_write_config_byte(pci_dev, lnkctl, val);
	if (ret) {
		MHI_ERR("Error writing LNKCTL to disable LPM, ret:%d\n", ret);
		goto lpm_disable_exit;
	}

	mhi_dev->lpm_disable_depth++;

lpm_disable_exit:
	spin_unlock_irqrestore(&mhi_dev->lpm_lock, flags);

	return ret;
	return mhi_arch_link_lpm_disable(mhi_cntrl);
}

/* enable PCIe L1 */
static int mhi_lpm_enable(struct mhi_controller *mhi_cntrl, void *priv)
{
	struct mhi_dev *mhi_dev = priv;
	struct pci_dev *pci_dev = mhi_dev->pci_dev;
	int lnkctl = pci_dev->pcie_cap + PCI_EXP_LNKCTL;
	u8 val;
	unsigned long flags;
	int ret = 0;

	spin_lock_irqsave(&mhi_dev->lpm_lock, flags);

	/*
	 * Exit if L1 is not supported or is already disabled or
	 * decrementing lpm_disable_depth still keeps it above 0
	 */
	if (!mhi_dev->lpm_disable_depth)
		goto lpm_enable_exit;

	if (mhi_dev->lpm_disable_depth > 1) {
		mhi_dev->lpm_disable_depth--;
		goto lpm_enable_exit;
	return mhi_arch_link_lpm_enable(mhi_cntrl);
}

	ret = pci_read_config_byte(pci_dev, lnkctl, &val);
	if (ret) {
		MHI_ERR("Error reading LNKCTL, ret:%d\n", ret);
		goto lpm_enable_exit;
	}

	val |= PCI_EXP_LNKCTL_ASPM_L1;
	ret = pci_write_config_byte(pci_dev, lnkctl, val);
	if (ret) {
		MHI_ERR("Error writing LNKCTL to enable LPM, ret:%d\n", ret);
		goto lpm_enable_exit;
	}

	mhi_dev->lpm_disable_depth = 0;
static void mhi_qcom_store_hwinfo(struct mhi_controller *mhi_cntrl)
{
	struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
	int i;

lpm_enable_exit:
	spin_unlock_irqrestore(&mhi_dev->lpm_lock, flags);
	mhi_dev->serial_num = readl_relaxed(mhi_cntrl->bhi +
			MHI_BHI_SERIAL_NUM_OFFS);

	return ret;
	for (i = 0; i < ARRAY_SIZE(mhi_dev->oem_pk_hash); i++)
		mhi_dev->oem_pk_hash[i] = readl_relaxed(mhi_cntrl->bhi +
			MHI_BHI_OEMPKHASH(i));
}

static int mhi_qcom_power_up(struct mhi_controller *mhi_cntrl)
@@ -555,6 +489,10 @@ static int mhi_qcom_power_up(struct mhi_controller *mhi_cntrl)

	ret = mhi_async_power_up(mhi_cntrl);

	/* Update modem serial Info */
	if (!ret)
		mhi_qcom_store_hwinfo(mhi_cntrl);

	/* power up create the dentry */
	if (mhi_cntrl->dentry) {
		debugfs_create_file("m0", 0444, mhi_cntrl->dentry, mhi_cntrl,
@@ -665,9 +603,45 @@ static ssize_t power_up_store(struct device *dev,
}
static DEVICE_ATTR_WO(power_up);

static ssize_t serial_info_show(struct device *dev,
				struct device_attribute *attr,
				char *buf)
{
	struct mhi_device *mhi_device = to_mhi_device(dev);
	struct mhi_controller *mhi_cntrl = mhi_device->mhi_cntrl;
	struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
	int n;

	n = scnprintf(buf, PAGE_SIZE, "Serial Number:%u\n",
		      mhi_dev->serial_num);

	return n;
}
static DEVICE_ATTR_RO(serial_info);

static ssize_t oempkhash_info_show(struct device *dev,
				struct device_attribute *attr,
				char *buf)
{
	struct mhi_device *mhi_device = to_mhi_device(dev);
	struct mhi_controller *mhi_cntrl = mhi_device->mhi_cntrl;
	struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
	int i, n = 0;

	for (i = 0; i < ARRAY_SIZE(mhi_dev->oem_pk_hash); i++)
		n += scnprintf(buf + n, PAGE_SIZE - n, "OEMPKHASH[%d]:%u\n",
		      i, mhi_dev->oem_pk_hash[i]);

	return n;
}
static DEVICE_ATTR_RO(oempkhash_info);


static struct attribute *mhi_qcom_attrs[] = {
	&dev_attr_timeout_ms.attr,
	&dev_attr_power_up.attr,
	&dev_attr_serial_info.attr,
	&dev_attr_oempkhash_info.attr,
	NULL
};

@@ -743,7 +717,6 @@ static struct mhi_controller *mhi_register_controller(struct pci_dev *pci_dev)
	mhi_cntrl->of_node = of_node;

	mhi_dev->pci_dev = pci_dev;
	spin_lock_init(&mhi_dev->lpm_lock);

	/* setup power management apis */
	mhi_cntrl->status_cb = mhi_status_cb;
+19 −3
Original line number Diff line number Diff line
@@ -22,6 +22,10 @@
#define MHI_PCIE_VENDOR_ID (0x17cb)
#define MHI_PCIE_DEBUG_ID (0xffff)

#define MHI_BHI_SERIAL_NUM_OFFS (0x40)
#define MHI_BHI_OEMPKHASH(n) (0x64 + (0x4 * (n)))
#define MHI_BHI_OEMPKHASH_SEG (16)

/* runtime suspend timer */
#define MHI_RPM_SUSPEND_TMR_MS (250)
#define MHI_PCI_BAR_NUM (0)
@@ -61,9 +65,9 @@ struct mhi_dev {
	dma_addr_t iova_stop;
	enum mhi_suspend_mode suspend_mode;

	unsigned int lpm_disable_depth;
	/* lock to toggle low power modes */
	spinlock_t lpm_lock;
	/* hardware info */
	u32 serial_num;
	u32 oem_pk_hash[MHI_BHI_OEMPKHASH_SEG];
};

void mhi_deinit_pci_dev(struct mhi_controller *mhi_cntrl);
@@ -73,6 +77,8 @@ void mhi_reg_write_work(struct work_struct *w);

#ifdef CONFIG_ARCH_QCOM

int mhi_arch_link_lpm_disable(struct mhi_controller *mhi_cntrl);
int mhi_arch_link_lpm_enable(struct mhi_controller *mhi_cntrl);
void mhi_arch_mission_mode_enter(struct mhi_controller *mhi_cntrl);
int mhi_arch_power_up(struct mhi_controller *mhi_cntrl);
int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl);
@@ -125,6 +131,16 @@ static inline void mhi_arch_mission_mode_enter(struct mhi_controller *mhi_cntrl)
{
}

static inline int mhi_arch_link_lpm_disable(struct mhi_controller *mhi_cntrl)
{
	return 0;
}

static inline int mhi_arch_link_lpm_enable(struct mhi_controller *mhi_cntrl)
{
	return 0;
}

#endif

#endif /* _MHI_QCOM_ */
+2 −72
Original line number Diff line number Diff line
@@ -791,75 +791,6 @@ static void mhi_assign_of_node(struct mhi_controller *mhi_cntrl,
	}
}

static ssize_t time_show(struct device *dev,
			 struct device_attribute *attr,
			 char *buf)
{
	struct mhi_device *mhi_dev = to_mhi_device(dev);
	struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
	u64 t_host, t_device;
	int ret;

	ret = mhi_get_remote_time_sync(mhi_dev, &t_host, &t_device);
	if (ret) {
		MHI_ERR("Failed to obtain time, ret:%d\n", ret);
		return ret;
	}

	return scnprintf(buf, PAGE_SIZE, "local: %llu remote: %llu (ticks)\n",
			 t_host, t_device);
}
static DEVICE_ATTR_RO(time);

static ssize_t time_us_show(struct device *dev,
			    struct device_attribute *attr,
			    char *buf)
{
	struct mhi_device *mhi_dev = to_mhi_device(dev);
	struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
	u64 t_host, t_device;
	int ret;

	ret = mhi_get_remote_time_sync(mhi_dev, &t_host, &t_device);
	if (ret) {
		MHI_ERR("Failed to obtain time, ret:%d\n", ret);
		return ret;
	}

	return scnprintf(buf, PAGE_SIZE, "local: %llu remote: %llu (us)\n",
			 LOCAL_TICKS_TO_US(t_host),
			 REMOTE_TICKS_TO_US(t_device));
}
static DEVICE_ATTR_RO(time_us);

static struct attribute *mhi_tsync_attrs[] = {
	&dev_attr_time.attr,
	&dev_attr_time_us.attr,
	NULL,
};

static const struct attribute_group mhi_tsync_group = {
	.attrs = mhi_tsync_attrs,
};

void mhi_destroy_timesync(struct mhi_controller *mhi_cntrl)
{
	if (mhi_cntrl->mhi_tsync) {
		mutex_lock(&mhi_cntrl->tsync_mutex);
		sysfs_remove_group(&mhi_cntrl->mhi_dev->dev.kobj,
				   &mhi_tsync_group);
		kfree(mhi_cntrl->mhi_tsync);
		mhi_cntrl->mhi_tsync = NULL;
		mutex_unlock(&mhi_cntrl->tsync_mutex);
	}
}

int mhi_create_timesync_sysfs(struct mhi_controller *mhi_cntrl)
{
	return sysfs_create_group(&mhi_cntrl->mhi_dev->dev.kobj,
				  &mhi_tsync_group);
}

/* bind mhi channels into mhi devices */
void mhi_create_devices(struct mhi_controller *mhi_cntrl)
{
@@ -1355,7 +1286,7 @@ int mhi_process_data_event_ring(struct mhi_controller *mhi_cntrl,
	struct mhi_chan *mhi_chan;

	if (unlikely(MHI_EVENT_ACCESS_INVALID(mhi_cntrl->pm_state))) {
		MHI_ERR("No EV access, PM_STATE:%s\n",
		MHI_LOG("No EV access, PM_STATE:%s\n",
			to_mhi_pm_state_str(mhi_cntrl->pm_state));
		return -EIO;
	}
@@ -1413,9 +1344,8 @@ int mhi_process_tsync_event_ring(struct mhi_controller *mhi_cntrl,
	u64 remote_time;

	if (unlikely(MHI_EVENT_ACCESS_INVALID(mhi_cntrl->pm_state))) {
		MHI_ERR("No EV access, PM_STATE:%s\n",
		MHI_LOG("No EV access, PM_STATE:%s\n",
			to_mhi_pm_state_str(mhi_cntrl->pm_state));
		read_unlock_bh(&mhi_cntrl->pm_lock);
		return -EIO;
	}

+1 −0
Original line number Diff line number Diff line
@@ -1411,6 +1411,7 @@ int mhi_pm_fast_resume(struct mhi_controller *mhi_cntrl, bool notify_client)
	switch (mhi_cntrl->pm_state) {
	case MHI_PM_M0:
		mhi_pm_m0_transition(mhi_cntrl);
		break;
	case MHI_PM_M2:
		read_lock_bh(&mhi_cntrl->pm_lock);
		/*