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

Commit ad4e066b authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge changes I88c38198,I012573c5 into msm-4.14

* changes:
  mhi: core: add support to trigger modem into RDDM mode
  mhi_bus: core: add support to reset DB mode when processing M0
parents f5824ea7 7978e38f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -50,6 +50,8 @@ Main node properties:
		notifications.
		BIT(1) : Offload channel, MHI host only involved in setting up
		the data pipe. Not involved in active data transfer.
		BIT(2) : Must switch to doorbell mode whenever MHI M0 state
		transition happens.

- mhi,chan-names
  Usage: required
+3 −0
Original line number Diff line number Diff line
@@ -821,6 +821,9 @@ static int of_parse_ch_cfg(struct mhi_controller *mhi_cntrl,

		mhi_chan->lpm_notify = !!(bit_cfg & MHI_CH_CFG_BIT_LPM_NOTIFY);
		mhi_chan->offload_ch = !!(bit_cfg & MHI_CH_CFG_BIT_OFFLOAD_CH);
		mhi_chan->db_cfg.reset_req =
			!!(bit_cfg & MHI_CH_CFG_BIT_DBMODE_RESET_CH);

		ret = of_property_read_string_index(of_node, "mhi,chan-names",
						    i, &mhi_chan->name);
		if (ret)
+2 −0
Original line number Diff line number Diff line
@@ -338,6 +338,7 @@ enum MHI_CH_CFG {

#define MHI_CH_CFG_BIT_LPM_NOTIFY BIT(0) /* require LPM notification */
#define MHI_CH_CFG_BIT_OFFLOAD_CH BIT(1) /* satellite mhi devices */
#define MHI_CH_CFG_BIT_DBMODE_RESET_CH BIT(2) /* require db mode to reset */

enum MHI_EV_CFG {
	MHI_EV_CFG_ELEMENTS = 0,
@@ -466,6 +467,7 @@ enum MHI_ER_TYPE {
};

struct db_cfg {
	bool reset_req;
	bool db_mode;
	u32 pollcfg;
	enum MHI_BRSTMODE brstmode;
+74 −15
Original line number Diff line number Diff line
@@ -360,6 +360,9 @@ int mhi_pm_m0_transition(struct mhi_controller *mhi_cntrl)
		struct mhi_ring *tre_ring = &mhi_chan->tre_ring;

		write_lock_irq(&mhi_chan->lock);
		if (mhi_chan->db_cfg.reset_req)
			mhi_chan->db_cfg.db_mode = true;

		/* only ring DB if ring is not empty */
		if (tre_ring->base && tre_ring->wp  != tre_ring->rp)
			mhi_ring_chan_db(mhi_cntrl, mhi_chan);
@@ -1062,23 +1065,10 @@ int mhi_pm_resume(struct mhi_controller *mhi_cntrl)
	return 0;
}

void mhi_device_get(struct mhi_device *mhi_dev)
static int __mhi_device_get_sync(struct mhi_controller *mhi_cntrl)
{
	struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;

	atomic_inc(&mhi_dev->dev_wake);
	read_lock_bh(&mhi_cntrl->pm_lock);
	mhi_cntrl->wake_get(mhi_cntrl, false);
	read_unlock_bh(&mhi_cntrl->pm_lock);
}
EXPORT_SYMBOL(mhi_device_get);

int mhi_device_get_sync(struct mhi_device *mhi_dev)
{
	struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
	int ret;

	atomic_inc(&mhi_dev->dev_wake);
	read_lock_bh(&mhi_cntrl->pm_lock);
	mhi_cntrl->wake_get(mhi_cntrl, false);
	if (MHI_PM_IN_SUSPEND_STATE(mhi_cntrl->pm_state)) {
@@ -1096,7 +1086,6 @@ int mhi_device_get_sync(struct mhi_device *mhi_dev)
		MHI_ERR("Did not enter M0 state, cur_state:%s pm_state:%s\n",
			TO_MHI_STATE_STR(mhi_cntrl->dev_state),
			to_mhi_pm_state_str(mhi_cntrl->pm_state));
		atomic_dec(&mhi_dev->dev_wake);
		read_lock_bh(&mhi_cntrl->pm_lock);
		mhi_cntrl->wake_put(mhi_cntrl, false);
		read_unlock_bh(&mhi_cntrl->pm_lock);
@@ -1105,6 +1094,29 @@ int mhi_device_get_sync(struct mhi_device *mhi_dev)

	return 0;
}

void mhi_device_get(struct mhi_device *mhi_dev)
{
	struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;

	atomic_inc(&mhi_dev->dev_wake);
	read_lock_bh(&mhi_cntrl->pm_lock);
	mhi_cntrl->wake_get(mhi_cntrl, false);
	read_unlock_bh(&mhi_cntrl->pm_lock);
}
EXPORT_SYMBOL(mhi_device_get);

int mhi_device_get_sync(struct mhi_device *mhi_dev)
{
	struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
	int ret;

	ret = __mhi_device_get_sync(mhi_cntrl);
	if (!ret)
		atomic_inc(&mhi_dev->dev_wake);

	return ret;
}
EXPORT_SYMBOL(mhi_device_get_sync);

void mhi_device_put(struct mhi_device *mhi_dev)
@@ -1117,3 +1129,50 @@ void mhi_device_put(struct mhi_device *mhi_dev)
	read_unlock_bh(&mhi_cntrl->pm_lock);
}
EXPORT_SYMBOL(mhi_device_put);

int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl)
{
	int ret;

	MHI_LOG("Enter with pm_state:%s ee:%s\n",
		to_mhi_pm_state_str(mhi_cntrl->pm_state),
		TO_MHI_EXEC_STR(mhi_cntrl->ee));

	/* before rddm mode, we need to enter M0 state */
	ret = __mhi_device_get_sync(mhi_cntrl);
	if (ret)
		return ret;

	mutex_lock(&mhi_cntrl->pm_mutex);
	write_lock_irq(&mhi_cntrl->pm_lock);
	if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state))
		goto no_reg_access;

	MHI_LOG("Triggering SYS_ERR to force rddm state\n");

	mhi_set_mhi_state(mhi_cntrl, MHI_STATE_SYS_ERR);
	mhi_cntrl->wake_put(mhi_cntrl, false);
	write_unlock_irq(&mhi_cntrl->pm_lock);
	mutex_unlock(&mhi_cntrl->pm_mutex);

	/* wait for rddm event */
	MHI_LOG("Waiting for device to enter RDDM state\n");
	ret = wait_event_timeout(mhi_cntrl->state_event,
				 mhi_cntrl->ee == MHI_EE_RDDM,
				 msecs_to_jiffies(mhi_cntrl->timeout_ms));
	ret = !ret ? 0 : -EIO;

	MHI_LOG("Exiting with pm_state:%s ee:%s ret:%d\n",
		to_mhi_pm_state_str(mhi_cntrl->pm_state),
		TO_MHI_EXEC_STR(mhi_cntrl->ee), ret);

	return ret;

no_reg_access:
	mhi_cntrl->wake_put(mhi_cntrl, false);
	write_unlock_irq(&mhi_cntrl->pm_lock);
	mutex_unlock(&mhi_cntrl->pm_mutex);

	return -EIO;
}
EXPORT_SYMBOL(mhi_force_rddm_mode);
+13 −0
Original line number Diff line number Diff line
@@ -519,6 +519,14 @@ int mhi_pm_resume(struct mhi_controller *mhi_cntrl);
 */
int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl, bool in_panic);

/**
 * mhi_force_rddm_mode - Force external device into rddm mode
 * to collect device ramdump. This is useful if host driver assert
 * and we need to see device state as well.
 * @mhi_cntrl: MHI controller
 */
int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl);

#else

static inline int mhi_driver_register(struct mhi_driver *mhi_drv)
@@ -643,6 +651,11 @@ static inline int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl,
	return -EINVAL;
}

static inlint int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl)
{
	return -EINVAL;
}

#endif

#ifndef CONFIG_ARCH_QCOM