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

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

Merge "mhi: core: do not trigger sys_error if controller already entered RDDM EE"

parents 359b9fc8 7d2793e9
Loading
Loading
Loading
Loading
+25 −86
Original line number Diff line number Diff line
@@ -18,12 +18,14 @@
#include "mhi_internal.h"


/* setup rddm vector table for rddm transfer */
static void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl,
/* setup rddm vector table for rddm transfer and program rxvec */
void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl,
			     struct image_info *img_info)
{
	struct mhi_buf *mhi_buf = img_info->mhi_buf;
	struct bhi_vec_entry *bhi_vec = img_info->bhi_vec;
	void __iomem *base = mhi_cntrl->bhie;
	u32 sequence_id;
	int i = 0;

	for (i = 0; i < img_info->entries - 1; i++, mhi_buf++, bhi_vec++) {
@@ -32,17 +34,35 @@ static void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl,
		bhi_vec->dma_addr = mhi_buf->dma_addr;
		bhi_vec->size = mhi_buf->len;
	}

	MHI_LOG("BHIe programming for RDDM\n");

	mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_HIGH_OFFS,
		      upper_32_bits(mhi_buf->dma_addr));

	mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_LOW_OFFS,
		      lower_32_bits(mhi_buf->dma_addr));

	mhi_write_reg(mhi_cntrl, base, BHIE_RXVECSIZE_OFFS, mhi_buf->len);
	sequence_id = prandom_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK;

	if (unlikely(!sequence_id))
		sequence_id = 1;

	mhi_write_reg_field(mhi_cntrl, base, BHIE_RXVECDB_OFFS,
			    BHIE_RXVECDB_SEQNUM_BMSK, BHIE_RXVECDB_SEQNUM_SHFT,
			    sequence_id);

	MHI_LOG("address:%pad len:0x%lx sequence:%u\n",
		&mhi_buf->dma_addr, mhi_buf->len, sequence_id);
}

/* collect rddm during kernel panic */
static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl)
{
	int ret;
	struct mhi_buf *mhi_buf;
	u32 sequence_id;
	u32 rx_status;
	enum mhi_ee ee;
	struct image_info *rddm_image = mhi_cntrl->rddm_image;
	const u32 delayus = 5000;
	u32 retry = (mhi_cntrl->timeout_ms * 1000) / delayus;
	const u32 rddm_timeout_us = 200000;
@@ -68,29 +88,6 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl)
	/* update should take the effect immediately */
	smp_wmb();

	/* setup the RX vector table */
	mhi_rddm_prepare(mhi_cntrl, rddm_image);
	mhi_buf = &rddm_image->mhi_buf[rddm_image->entries - 1];

	MHI_LOG("Starting BHIe programming for RDDM\n");

	mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_HIGH_OFFS,
		      upper_32_bits(mhi_buf->dma_addr));

	mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_LOW_OFFS,
		      lower_32_bits(mhi_buf->dma_addr));

	mhi_write_reg(mhi_cntrl, base, BHIE_RXVECSIZE_OFFS, mhi_buf->len);
	sequence_id = prandom_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK;

	if (unlikely(!sequence_id))
		sequence_id = 1;


	mhi_write_reg_field(mhi_cntrl, base, BHIE_RXVECDB_OFFS,
			    BHIE_RXVECDB_SEQNUM_BMSK, BHIE_RXVECDB_SEQNUM_SHFT,
			    sequence_id);

	/*
	 * Make sure device is not already in RDDM.
	 * In case device asserts and a kernel panic follows, device will
@@ -157,70 +154,15 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl)
int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl, bool in_panic)
{
	void __iomem *base = mhi_cntrl->bhie;
	rwlock_t *pm_lock = &mhi_cntrl->pm_lock;
	struct image_info *rddm_image = mhi_cntrl->rddm_image;
	struct mhi_buf *mhi_buf;
	int ret;
	u32 rx_status;
	u32 sequence_id;

	if (!rddm_image)
		return -ENOMEM;

	if (in_panic)
		return __mhi_download_rddm_in_panic(mhi_cntrl);

	MHI_LOG("Waiting for device to enter RDDM state from EE:%s\n",
		TO_MHI_EXEC_STR(mhi_cntrl->ee));

	ret = wait_event_timeout(mhi_cntrl->state_event,
				 mhi_cntrl->ee == MHI_EE_RDDM ||
				 MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state),
				 msecs_to_jiffies(mhi_cntrl->timeout_ms));

	if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) {
		MHI_ERR("MHI is not in valid state, pm_state:%s ee:%s\n",
			to_mhi_pm_state_str(mhi_cntrl->pm_state),
			TO_MHI_EXEC_STR(mhi_cntrl->ee));
		return -EIO;
	}

	mhi_rddm_prepare(mhi_cntrl, mhi_cntrl->rddm_image);

	/* vector table is the last entry */
	mhi_buf = &rddm_image->mhi_buf[rddm_image->entries - 1];

	read_lock_bh(pm_lock);
	if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) {
		read_unlock_bh(pm_lock);
		return -EIO;
	}

	MHI_LOG("Starting BHIe Programming for RDDM\n");

	mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_HIGH_OFFS,
		      upper_32_bits(mhi_buf->dma_addr));

	mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_LOW_OFFS,
		      lower_32_bits(mhi_buf->dma_addr));

	mhi_write_reg(mhi_cntrl, base, BHIE_RXVECSIZE_OFFS, mhi_buf->len);

	sequence_id = prandom_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK;
	mhi_write_reg_field(mhi_cntrl, base, BHIE_RXVECDB_OFFS,
			    BHIE_RXVECDB_SEQNUM_BMSK, BHIE_RXVECDB_SEQNUM_SHFT,
			    sequence_id);
	read_unlock_bh(pm_lock);

	MHI_LOG("Upper:0x%x Lower:0x%x len:0x%lx sequence:%u\n",
		upper_32_bits(mhi_buf->dma_addr),
		lower_32_bits(mhi_buf->dma_addr),
		mhi_buf->len, sequence_id);
	MHI_LOG("Waiting for image download completion\n");

	/* waiting for image download completion */
	wait_event_timeout(mhi_cntrl->state_event,
			   MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state) ||
			   mhi_read_reg_field(mhi_cntrl, base,
					      BHIE_RXVECSTATUS_OFFS,
					      BHIE_RXVECSTATUS_STATUS_BMSK,
@@ -228,9 +170,6 @@ int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl, bool in_panic)
					      &rx_status) || rx_status,
			   msecs_to_jiffies(mhi_cntrl->timeout_ms));

	if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state))
		return -EIO;

	return (rx_status == BHIE_RXVECSTATUS_STATUS_XFER_COMPL) ? 0 : -EIO;
}
EXPORT_SYMBOL(mhi_download_rddm_img);
+3 −0
Original line number Diff line number Diff line
@@ -1417,6 +1417,9 @@ int mhi_prepare_for_power_up(struct mhi_controller *mhi_cntrl)

		memset_io(mhi_cntrl->bhie + BHIE_RXVECADDR_LOW_OFFS, 0,
			  BHIE_RXVECSTATUS_OFFS - BHIE_RXVECADDR_LOW_OFFS + 4);

		if (mhi_cntrl->rddm_image)
			mhi_rddm_prepare(mhi_cntrl, mhi_cntrl->rddm_image);
	}

	mhi_cntrl->pre_init = true;
+2 −0
Original line number Diff line number Diff line
@@ -822,6 +822,8 @@ void mhi_deinit_dev_ctxt(struct mhi_controller *mhi_cntrl);
int mhi_init_irq_setup(struct mhi_controller *mhi_cntrl);
void mhi_deinit_free_irq(struct mhi_controller *mhi_cntrl);
int mhi_dtr_init(void);
void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl,
		      struct image_info *img_info);

/* isr handlers */
irqreturn_t mhi_msi_handlr(int irq_number, void *dev);
+17 −3
Original line number Diff line number Diff line
@@ -1458,15 +1458,17 @@ irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev)
	struct mhi_controller *mhi_cntrl = dev;
	enum mhi_dev_state state = MHI_STATE_MAX;
	enum MHI_PM_STATE pm_state = 0;
	enum mhi_ee ee;
	enum mhi_ee ee = 0;

	MHI_VERB("Enter\n");

	write_lock_irq(&mhi_cntrl->pm_lock);
	if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) {
		state = mhi_get_mhi_state(mhi_cntrl);
		ee = mhi_get_exec_env(mhi_cntrl);
		MHI_LOG("device ee:%s dev_state:%s\n", TO_MHI_EXEC_STR(ee),
		ee = mhi_cntrl->ee;
		mhi_cntrl->ee = mhi_get_exec_env(mhi_cntrl);
		MHI_LOG("device ee:%s dev_state:%s\n",
			TO_MHI_EXEC_STR(mhi_cntrl->ee),
			TO_MHI_STATE_STR(state));
	}

@@ -1476,6 +1478,17 @@ irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev)
					       MHI_PM_SYS_ERR_DETECT);
	}
	write_unlock_irq(&mhi_cntrl->pm_lock);

	/* if device in rddm don't bother processing sys error */
	if (mhi_cntrl->ee == MHI_EE_RDDM) {
		if (mhi_cntrl->ee != ee) {
			mhi_cntrl->status_cb(mhi_cntrl, mhi_cntrl->priv_data,
					     MHI_CB_EE_RDDM);
			wake_up_all(&mhi_cntrl->state_event);
		}
		goto exit_intvec;
	}

	if (pm_state == MHI_PM_SYS_ERR_DETECT) {
		wake_up_all(&mhi_cntrl->state_event);

@@ -1487,6 +1500,7 @@ irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev)
			schedule_work(&mhi_cntrl->syserr_worker);
	}

exit_intvec:
	MHI_VERB("Exit\n");

	return IRQ_HANDLED;
+16 −1
Original line number Diff line number Diff line
@@ -522,9 +522,20 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl,
		to_mhi_pm_state_str(transition_state));

	/* We must notify MHI control driver so it can clean up first */
	if (transition_state == MHI_PM_SYS_ERR_PROCESS)
	if (transition_state == MHI_PM_SYS_ERR_PROCESS) {
		/*
		 * if controller support rddm, we do not process
		 * sys error state, instead we will jump directly
		 * to rddm state
		 */
		if (mhi_cntrl->rddm_image) {
			MHI_LOG(
				"Controller Support RDDM, skipping SYS_ERR_PROCESS\n");
			return;
		}
		mhi_cntrl->status_cb(mhi_cntrl, mhi_cntrl->priv_data,
				     MHI_CB_SYS_ERROR);
	}

	mutex_lock(&mhi_cntrl->pm_mutex);
	write_lock_irq(&mhi_cntrl->pm_lock);
@@ -1394,6 +1405,10 @@ int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl)
		to_mhi_pm_state_str(mhi_cntrl->pm_state),
		TO_MHI_EXEC_STR(mhi_cntrl->ee));

	/* device already in rddm */
	if (mhi_cntrl->ee == MHI_EE_RDDM)
		return 0;

	MHI_LOG("Triggering SYS_ERR to force rddm state\n");
	mhi_set_mhi_state(mhi_cntrl, MHI_STATE_SYS_ERR);