Commit 46ee6bca authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'mhi-for-v5.19' of...

Merge tag 'mhi-for-v5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/mani/mhi into char-work-next

Manivannan writes:

MHI changes for v5.19

MHI Host
--------

Support for new modems:

 - Foxconn Cinterion MV32-WA/MV32-WB based on SDX62/SDX65
 - Telit FN980 v1 based on SDX55
 - Telit FN990 based on SDX65
 - Foxconn T99W373/T99W368 based on SDX62/SDX65

Core changes:

 - During the recycle of event ring elements, compute the ctxt_wp based on the
   local cached value instead of reading from shared memory. This is to prevent
   the possible corruption of the ctxt_wp as some of the endpoint devices could
   modify the value in shared memory.

 - Add sysfs support for resetting the endpoint based on the MHI spec. The MHI
   spec allows the host to hard reset the device in the case of an unrecoverable
   error and all other reset mechanisms have failed.

 - During MHI shutdown, wait for the endpoint device to enter the ready state
   post reset before proceeding. This is to avoid a possible race where host
   would remove the interrupt handler and device will send ready state
   interrupt, resulting in IOMMU fault.

 - Bail out updating the MHI register if the read has failed during
   read/modify/write.

 - Use mhi_write_reg() instead of mhi_write_reg_field() for writing the whole
   register fields in mhi_init_mmio().

MAINTAINERS change:

 - Since Qualcomm has moved the email domain for its employess from codeaurora
   domain to quicinc, update the same for Hemant.

* tag 'mhi-for-v5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/mani/mhi: (29 commits)
  bus: mhi: host: Add support for Foxconn T99W373 and T99W368
  bus: mhi: host: pci_generic: add Telit FN990
  bus: mhi: host: pci_generic: add Telit FN980 v1 hardware revision
  bus: mhi: host: Add support for Cinterion MV32-WA/MV32-WB
  bus: mhi: host: Optimize and update MMIO register write method
  bus: mhi: host: Bail on writing register fields if read fails
  bus: mhi: host: Wait for ready state after reset
  bus: mhi: host: Add soc_reset sysfs
  bus: mhi: host: pci_generic: Sort mhi_pci_id_table based on the PID
  bus: mhi: host: Use cached values for calculating the shared write pointer
  MAINTAINERS: Update Hemant's email id
  bus: mhi: ep: Add uevent support for module autoloading
  bus: mhi: ep: Add support for suspending and resuming channels
  bus: mhi: ep: Add support for queueing SKBs to the host
  bus: mhi: ep: Add support for processing channel rings
  bus: mhi: ep: Add support for reading from the host
  bus: mhi: ep: Add support for processing command rings
  bus: mhi: ep: Add support for handling SYS_ERR condition
  bus: mhi: ep: Add support for handling MHI_RESET
  bus: mhi: ep: Add support for powering down the MHI endpoint stack
  ...
parents bcfa9546 13b9b814
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -19,3 +19,13 @@ Description: The file holds the OEM PK Hash value of the endpoint device
		read without having the device power on at least once, the file
		will read all 0's.
Users:		Any userspace application or clients interested in device info.

What:           /sys/bus/mhi/devices/.../soc_reset
Date:           April 2022
KernelVersion:  5.19
Contact:        mhi@lists.linux.dev
Description:	Initiates a SoC reset on the MHI controller.  A SoC reset is
                a reset of last resort, and will require a complete re-init.
                This can be useful as a method of recovery if the device is
                non-responsive, or as a means of loading new firmware as a
                system administration task.
+1 −1
Original line number Diff line number Diff line
@@ -12809,7 +12809,7 @@ F: arch/arm64/boot/dts/marvell/armada-3720-uDPU.dts
MHI BUS
M:	Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
R:	Hemant Kumar <hemantk@codeaurora.org>
R:	Hemant Kumar <quic_hemantk@quicinc.com>
L:	mhi@lists.linux.dev
L:	linux-arm-msm@vger.kernel.org
S:	Maintained
+16 −6
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@
#include "internal.h"

/* Setup RDDM vector table for RDDM transfer and program RXVEC */
void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl,
int mhi_rddm_prepare(struct mhi_controller *mhi_cntrl,
		     struct image_info *img_info)
{
	struct mhi_buf *mhi_buf = img_info->mhi_buf;
@@ -28,6 +28,7 @@ void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl,
	struct device *dev = &mhi_cntrl->mhi_dev->dev;
	u32 sequence_id;
	unsigned int i;
	int ret;

	for (i = 0; i < img_info->entries - 1; i++, mhi_buf++, bhi_vec++) {
		bhi_vec->dma_addr = mhi_buf->dma_addr;
@@ -45,11 +46,17 @@ void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl,
	mhi_write_reg(mhi_cntrl, base, BHIE_RXVECSIZE_OFFS, mhi_buf->len);
	sequence_id = MHI_RANDOM_U32_NONZERO(BHIE_RXVECSTATUS_SEQNUM_BMSK);

	mhi_write_reg_field(mhi_cntrl, base, BHIE_RXVECDB_OFFS,
	ret = mhi_write_reg_field(mhi_cntrl, base, BHIE_RXVECDB_OFFS,
				  BHIE_RXVECDB_SEQNUM_BMSK, sequence_id);
	if (ret) {
		dev_err(dev, "Failed to write sequence ID for BHIE_RXVECDB\n");
		return ret;
	}

	dev_dbg(dev, "Address: %p and len: 0x%zx sequence: %u\n",
		&mhi_buf->dma_addr, mhi_buf->len, sequence_id);

	return 0;
}

/* Collect RDDM buffer during kernel panic */
@@ -198,10 +205,13 @@ static int mhi_fw_load_bhie(struct mhi_controller *mhi_cntrl,

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

	mhi_write_reg_field(mhi_cntrl, base, BHIE_TXVECDB_OFFS,
	ret = mhi_write_reg_field(mhi_cntrl, base, BHIE_TXVECDB_OFFS,
				  BHIE_TXVECDB_SEQNUM_BMSK, sequence_id);
	read_unlock_bh(pm_lock);

	if (ret)
		return ret;

	/* Wait for the image download to complete */
	ret = wait_event_timeout(mhi_cntrl->state_event,
				 MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state) ||
+54 −28
Original line number Diff line number Diff line
@@ -107,9 +107,23 @@ static ssize_t oem_pk_hash_show(struct device *dev,
}
static DEVICE_ATTR_RO(oem_pk_hash);

static ssize_t soc_reset_store(struct device *dev,
			       struct device_attribute *attr,
			       const char *buf,
			       size_t count)
{
	struct mhi_device *mhi_dev = to_mhi_device(dev);
	struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;

	mhi_soc_reset(mhi_cntrl);
	return count;
}
static DEVICE_ATTR_WO(soc_reset);

static struct attribute *mhi_dev_attrs[] = {
	&dev_attr_serial_number.attr,
	&dev_attr_oem_pk_hash.attr,
	&dev_attr_soc_reset.attr,
	NULL,
};
ATTRIBUTE_GROUPS(mhi_dev);
@@ -424,74 +438,65 @@ int mhi_init_mmio(struct mhi_controller *mhi_cntrl)
	struct device *dev = &mhi_cntrl->mhi_dev->dev;
	struct {
		u32 offset;
		u32 mask;
		u32 val;
	} reg_info[] = {
		{
			CCABAP_HIGHER, U32_MAX,
			CCABAP_HIGHER,
			upper_32_bits(mhi_cntrl->mhi_ctxt->chan_ctxt_addr),
		},
		{
			CCABAP_LOWER, U32_MAX,
			CCABAP_LOWER,
			lower_32_bits(mhi_cntrl->mhi_ctxt->chan_ctxt_addr),
		},
		{
			ECABAP_HIGHER, U32_MAX,
			ECABAP_HIGHER,
			upper_32_bits(mhi_cntrl->mhi_ctxt->er_ctxt_addr),
		},
		{
			ECABAP_LOWER, U32_MAX,
			ECABAP_LOWER,
			lower_32_bits(mhi_cntrl->mhi_ctxt->er_ctxt_addr),
		},
		{
			CRCBAP_HIGHER, U32_MAX,
			CRCBAP_HIGHER,
			upper_32_bits(mhi_cntrl->mhi_ctxt->cmd_ctxt_addr),
		},
		{
			CRCBAP_LOWER, U32_MAX,
			CRCBAP_LOWER,
			lower_32_bits(mhi_cntrl->mhi_ctxt->cmd_ctxt_addr),
		},
		{
			MHICFG, MHICFG_NER_MASK,
			mhi_cntrl->total_ev_rings,
		},
		{
			MHICFG, MHICFG_NHWER_MASK,
			mhi_cntrl->hw_ev_rings,
		},
		{
			MHICTRLBASE_HIGHER, U32_MAX,
			MHICTRLBASE_HIGHER,
			upper_32_bits(mhi_cntrl->iova_start),
		},
		{
			MHICTRLBASE_LOWER, U32_MAX,
			MHICTRLBASE_LOWER,
			lower_32_bits(mhi_cntrl->iova_start),
		},
		{
			MHIDATABASE_HIGHER, U32_MAX,
			MHIDATABASE_HIGHER,
			upper_32_bits(mhi_cntrl->iova_start),
		},
		{
			MHIDATABASE_LOWER, U32_MAX,
			MHIDATABASE_LOWER,
			lower_32_bits(mhi_cntrl->iova_start),
		},
		{
			MHICTRLLIMIT_HIGHER, U32_MAX,
			MHICTRLLIMIT_HIGHER,
			upper_32_bits(mhi_cntrl->iova_stop),
		},
		{
			MHICTRLLIMIT_LOWER, U32_MAX,
			MHICTRLLIMIT_LOWER,
			lower_32_bits(mhi_cntrl->iova_stop),
		},
		{
			MHIDATALIMIT_HIGHER, U32_MAX,
			MHIDATALIMIT_HIGHER,
			upper_32_bits(mhi_cntrl->iova_stop),
		},
		{
			MHIDATALIMIT_LOWER, U32_MAX,
			MHIDATALIMIT_LOWER,
			lower_32_bits(mhi_cntrl->iova_stop),
		},
		{ 0, 0, 0 }
		{0, 0}
	};

	dev_dbg(dev, "Initializing MHI registers\n");
@@ -533,8 +538,22 @@ int mhi_init_mmio(struct mhi_controller *mhi_cntrl)

	/* Write to MMIO registers */
	for (i = 0; reg_info[i].offset; i++)
		mhi_write_reg_field(mhi_cntrl, base, reg_info[i].offset,
				    reg_info[i].mask, reg_info[i].val);
		mhi_write_reg(mhi_cntrl, base, reg_info[i].offset,
			      reg_info[i].val);

	ret = mhi_write_reg_field(mhi_cntrl, base, MHICFG, MHICFG_NER_MASK,
				  mhi_cntrl->total_ev_rings);
	if (ret) {
		dev_err(dev, "Unable to write MHICFG register\n");
		return ret;
	}

	ret = mhi_write_reg_field(mhi_cntrl, base, MHICFG, MHICFG_NHWER_MASK,
				  mhi_cntrl->hw_ev_rings);
	if (ret) {
		dev_err(dev, "Unable to write MHICFG register\n");
		return ret;
	}

	return 0;
}
@@ -1102,8 +1121,15 @@ int mhi_prepare_for_power_up(struct mhi_controller *mhi_cntrl)
		 */
		mhi_alloc_bhie_table(mhi_cntrl, &mhi_cntrl->rddm_image,
				     mhi_cntrl->rddm_size);
		if (mhi_cntrl->rddm_image)
			mhi_rddm_prepare(mhi_cntrl, mhi_cntrl->rddm_image);
		if (mhi_cntrl->rddm_image) {
			ret = mhi_rddm_prepare(mhi_cntrl,
					       mhi_cntrl->rddm_image);
			if (ret) {
				mhi_free_bhie_table(mhi_cntrl,
						    mhi_cntrl->rddm_image);
				goto error_reg_offset;
			}
		}
	}

	mutex_unlock(&mhi_cntrl->pm_mutex);
+4 −3
Original line number Diff line number Diff line
@@ -324,8 +324,9 @@ int __must_check mhi_poll_reg_field(struct mhi_controller *mhi_cntrl,
				    u32 val, u32 delayus);
void mhi_write_reg(struct mhi_controller *mhi_cntrl, void __iomem *base,
		   u32 offset, u32 val);
void mhi_write_reg_field(struct mhi_controller *mhi_cntrl, void __iomem *base,
			 u32 offset, u32 mask, u32 val);
int __must_check mhi_write_reg_field(struct mhi_controller *mhi_cntrl,
				     void __iomem *base, u32 offset, u32 mask,
				     u32 val);
void mhi_ring_er_db(struct mhi_event *mhi_event);
void mhi_write_db(struct mhi_controller *mhi_cntrl, void __iomem *db_addr,
		  dma_addr_t db_val);
@@ -339,7 +340,7 @@ int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl);
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);
void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl,
int mhi_rddm_prepare(struct mhi_controller *mhi_cntrl,
		      struct image_info *img_info);
void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl);

Loading