lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20251211-siva_mhi_dp2-v1-10-d2895c4ec73a@oss.qualcomm.com>
Date: Thu, 11 Dec 2025 13:37:42 +0530
From: Sivareddy Surasani <sivareddy.surasani@....qualcomm.com>
To: Manivannan Sadhasivam <mani@...nel.org>, Jonathan Corbet <corbet@....net>,
        Arnd Bergmann <arnd@...db.de>,
        Greg Kroah-Hartman <gregkh@...uxfoundation.org>
Cc: mhi@...ts.linux.dev, linux-arm-msm@...r.kernel.org,
        linux-kernel@...r.kernel.org, linux-doc@...r.kernel.org,
        Upal Kumar Saha <upal.saha@....qualcomm.com>,
        Himanshu Shukla <quic_himashuk@...cinc.com>,
        Sivareddy Surasani <sivareddy.surasani@....qualcomm.com>,
        Vivek Pernamitta <vivek.pernamitta@....qualcomm.com>
Subject: [PATCH 10/11] drivers: bus: mhi: host: Add support for MHI MAX TRB
 capability

From: Vivek Pernamitta <vivek.pernamitta@....qualcomm.com>

Read the MHI capability for MAX TRB length if device is supporting.
Use this information to send MHI data with a higher TRB length, as
supported by the device.

Signed-off-by: Vivek Pernamitta <vivek.pernamitta@....qualcomm.com>
Signed-off-by: Sivareddy Surasani <sivareddy.surasani@....qualcomm.com>
---
 drivers/bus/mhi/common.h    |  9 ++++++++-
 drivers/bus/mhi/host/init.c | 21 +++++++++++++++++++++
 drivers/bus/mhi/host/main.c | 17 ++++++++++++++---
 include/linux/mhi.h         |  2 ++
 4 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/drivers/bus/mhi/common.h b/drivers/bus/mhi/common.h
index 3b3ecbc6169f..4962035f4693 100644
--- a/drivers/bus/mhi/common.h
+++ b/drivers/bus/mhi/common.h
@@ -158,6 +158,8 @@
 #define MHI_TRE_GET_EV_PTR(tre)		le64_to_cpu((tre)->ptr)
 #define MHI_TRE_GET_EV_CODE(tre)	FIELD_GET(GENMASK(31, 24), (MHI_TRE_GET_DWORD(tre, 0)))
 #define MHI_TRE_GET_EV_LEN(tre)		FIELD_GET(GENMASK(15, 0), (MHI_TRE_GET_DWORD(tre, 0)))
+#define MHI_TRE_GET_EV_LEN_MAX_TRB(max_trb, tre)    (GENMASK(__fls(max_trb), 0) & \
+						    (MHI_TRE_GET_DWORD(tre, 0)))
 #define MHI_TRE_GET_EV_CHID(tre)	FIELD_GET(GENMASK(31, 24), (MHI_TRE_GET_DWORD(tre, 1)))
 #define MHI_TRE_GET_EV_TYPE(tre)	FIELD_GET(GENMASK(23, 16), (MHI_TRE_GET_DWORD(tre, 1)))
 #define MHI_TRE_GET_EV_STATE(tre)	FIELD_GET(GENMASK(31, 24), (MHI_TRE_GET_DWORD(tre, 0)))
@@ -188,6 +190,7 @@
 /* Transfer descriptor macros */
 #define MHI_TRE_DATA_PTR(ptr)		cpu_to_le64(ptr)
 #define MHI_TRE_DATA_DWORD0(len)	cpu_to_le32(FIELD_PREP(GENMASK(15, 0), len))
+#define MHI_TRE_DATA_DWORD0_MAX_TREB_CAP(max_len, len)	((GENMASK(__fls(max_len), 0)) & (len))
 #define MHI_TRE_TYPE_TRANSFER		2
 #define MHI_TRE_DATA_DWORD1(bei, ieot, ieob, chain) cpu_to_le32(FIELD_PREP(GENMASK(23, 16), \
 								MHI_TRE_TYPE_TRANSFER) |    \
@@ -206,7 +209,11 @@
 #define MHI_RSCTRE_DATA_PTR(ptr, len)	cpu_to_le64(FIELD_PREP(GENMASK(64, 48), len) | ptr)
 #define MHI_RSCTRE_DATA_DWORD0(cookie)	cpu_to_le32(cookie)
 #define MHI_RSCTRE_DATA_DWORD1		cpu_to_le32(FIELD_PREP(GENMASK(23, 16), \
-							       MHI_PKT_TYPE_COALESCING))
+								MHI_PKT_TYPE_COALESCING))
+
+/* MHI Max TRB Length CAP ID */
+#define MAX_TRB_LEN_CAP_ID		0x5
+#define MAX_TRB_LEN_CFG			0x4
 
 enum mhi_capability_type {
 	MHI_CAP_ID_INTX = 0x1,
diff --git a/drivers/bus/mhi/host/init.c b/drivers/bus/mhi/host/init.c
index 50f96f2c823f..b0982cb24fb9 100644
--- a/drivers/bus/mhi/host/init.c
+++ b/drivers/bus/mhi/host/init.c
@@ -500,6 +500,25 @@ static int mhi_find_capability(struct mhi_controller *mhi_cntrl, u32 capability,
 	return -ENXIO;
 }
 
+static int mhi_init_ext_trb_len(struct mhi_controller *mhi_cntrl)
+{
+	struct device *dev = &mhi_cntrl->mhi_dev->dev;
+	u32 trb_offset;
+	int ret;
+
+	ret = mhi_find_capability(mhi_cntrl, MAX_TRB_LEN_CAP_ID, &trb_offset);
+	if (ret)
+		return ret;
+
+	/* Get max TRB length */
+	ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs,
+			   trb_offset + MAX_TRB_LEN_CFG, &mhi_cntrl->ext_trb_len);
+
+	dev_dbg(dev, "Max TRB length supported is : 0x%x\n", mhi_cntrl->ext_trb_len);
+
+	return 0;
+}
+
 int mhi_init_mmio(struct mhi_controller *mhi_cntrl)
 {
 	u32 val;
@@ -637,6 +656,8 @@ int mhi_init_mmio(struct mhi_controller *mhi_cntrl)
 		return ret;
 	}
 
+	ret = mhi_init_ext_trb_len(mhi_cntrl);
+
 	return 0;
 }
 
diff --git a/drivers/bus/mhi/host/main.c b/drivers/bus/mhi/host/main.c
index 6be15297829d..a11bddce2182 100644
--- a/drivers/bus/mhi/host/main.c
+++ b/drivers/bus/mhi/host/main.c
@@ -648,7 +648,12 @@ static int parse_xfer_event(struct mhi_controller *mhi_cntrl,
 			buf_info = buf_ring->rp;
 			/* If it's the last TRE, get length from the event */
 			if (local_rp == ev_tre) {
-				xfer_len = MHI_TRE_GET_EV_LEN(event);
+				if (mhi_cntrl->ext_trb_len)
+					xfer_len = MHI_TRE_GET_EV_LEN_MAX_TRB(
+								mhi_cntrl->ext_trb_len,
+								event);
+				else
+					xfer_len = MHI_TRE_GET_EV_LEN(event);
 				send_cb = true;
 			} else {
 				xfer_len = buf_info->len;
@@ -664,7 +669,7 @@ static int parse_xfer_event(struct mhi_controller *mhi_cntrl,
 
 			/* truncate to buf len if xfer_len is larger */
 			result.bytes_xferd =
-				min_t(u16, xfer_len, buf_info->len);
+				min_t(u32, xfer_len, buf_info->len);
 			mhi_del_ring_element(mhi_cntrl, buf_ring);
 			mhi_del_ring_element(mhi_cntrl, tre_ring);
 			local_rp = tre_ring->rp;
@@ -1288,7 +1293,13 @@ int __mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan,
 
 	mhi_tre = tre_ring->wp;
 	mhi_tre->ptr = MHI_TRE_DATA_PTR(buf_info->p_addr);
-	mhi_tre->dword[0] = MHI_TRE_DATA_DWORD0(info->len);
+
+	if (mhi_cntrl->ext_trb_len)
+		mhi_tre->dword[0] = MHI_TRE_DATA_DWORD0_MAX_TREB_CAP(mhi_cntrl->ext_trb_len,
+								     info->len);
+	else
+		mhi_tre->dword[0] = MHI_TRE_DATA_DWORD0(info->len);
+
 	mhi_tre->dword[1] = MHI_TRE_DATA_DWORD1(bei, eot, eob, chain);
 
 	if (mhi_chan->dir == DMA_TO_DEVICE)
diff --git a/include/linux/mhi.h b/include/linux/mhi.h
index 013bc2d82196..0d78a95c2fa2 100644
--- a/include/linux/mhi.h
+++ b/include/linux/mhi.h
@@ -370,6 +370,7 @@ struct mhi_controller_config {
  * @wake_set: Device wakeup set flag
  * @irq_flags: irq flags passed to request_irq (optional)
  * @mru: the default MRU for the MHI device
+ * @ext_trb_len: Extended TRB length if device supports (optional)
  *
  * Fields marked as (required) need to be populated by the controller driver
  * before calling mhi_register_controller(). For the fields marked as (optional)
@@ -455,6 +456,7 @@ struct mhi_controller {
 	bool wake_set;
 	unsigned long irq_flags;
 	u32 mru;
+	u32 ext_trb_len;
 };
 
 /**

-- 
2.34.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ