All of lore.kernel.org
 help / color / mirror / Atom feed
From: a0282524688@gmail.com
To: lee@kernel.org, Ming Yu <tmyu0@nuvoton.com>
Cc: linux-kernel@vger.kernel.org, Ming Yu <a0282524688@gmail.com>,
	mfd@lists.linux.dev
Subject: [PATCH v7 06/10] mfd: nct6694: Transfer command payloads via a dedicated DMA buffer
Date: Fri, 21 Aug 2026 11:35:01 +0800	[thread overview]
Message-ID: <20260821033505.4017901-7-a0282524688@gmail.com> (raw)
In-Reply-To: <20260821033505.4017901-1-a0282524688@gmail.com>

From: Ming Yu <a0282524688@gmail.com>

The transport hands the caller's payload buffer straight to
usb_bulk_msg(). Sub-device drivers embed those buffers in their private
data structures, so they are neither cacheline aligned nor exclusively
owned by the transfer. On non-coherent architectures, mapping such a
buffer for DMA can corrupt the unrelated fields sharing its cachelines.

Transfer the payload through a buffer owned by the transport instead,
and reject commands exceeding the maximum firmware packet size.

Fixes: 51dad33ede63 ("mfd: Add core driver for Nuvoton NCT6694")
Signed-off-by: Ming Yu <a0282524688@gmail.com>
---
Changes in v7:
- New patch. Fixes the DMA-unsafe use of caller-owned payload buffers
  reported on v6 patch 6/7.

 drivers/mfd/nct6694-usb.c   | 38 +++++++++++++++++++++++++++----------
 include/linux/mfd/nct6694.h |  3 +++
 2 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/drivers/mfd/nct6694-usb.c b/drivers/mfd/nct6694-usb.c
index 2289ebfde7fa..793ce54c02aa 100644
--- a/drivers/mfd/nct6694-usb.c
+++ b/drivers/mfd/nct6694-usb.c
@@ -38,6 +38,7 @@ struct nct6694_usb_data {
 	struct urb *int_in_urb;
 	struct usb_device *udev;
 	union nct6694_usb_msg *usb_msg;
+	void *xfer_buf;
 	__le32 *int_buffer;
 };
 
@@ -120,8 +121,12 @@ int nct6694_usb_read_msg(struct nct6694 *nct6694,
 	struct nct6694_usb_data *udata = nct6694->priv;
 	union nct6694_usb_msg *msg = udata->usb_msg;
 	struct usb_device *udev = udata->udev;
+	u16 len = le16_to_cpu(cmd_hd->len);
 	int tx_len, rx_len, ret;
 
+	if (len > NCT6694_MAX_PACKET_SIZE)
+		return -EINVAL;
+
 	guard(mutex)(&udata->access_lock);
 
 	memcpy(&msg->cmd_header, cmd_hd, sizeof(*cmd_hd));
@@ -140,17 +145,19 @@ int nct6694_usb_read_msg(struct nct6694 *nct6694,
 		return ret;
 
 	/* Receive data packet from USB device */
-	ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, NCT6694_BULK_IN_EP), buf,
-			   le16_to_cpu(cmd_hd->len), &rx_len, NCT6694_URB_TIMEOUT);
+	ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, NCT6694_BULK_IN_EP), udata->xfer_buf,
+			   len, &rx_len, NCT6694_URB_TIMEOUT);
 	if (ret)
 		return ret;
 
-	if (rx_len != le16_to_cpu(cmd_hd->len)) {
+	if (rx_len != len) {
 		dev_err(nct6694->dev, "Expected received length %d, but got %d\n",
-			le16_to_cpu(cmd_hd->len), rx_len);
+			len, rx_len);
 		return -EIO;
 	}
 
+	memcpy(buf, udata->xfer_buf, len);
+
 	return nct6694_usb_err_handling(nct6694, msg->response_header.sts);
 }
 EXPORT_SYMBOL_GPL(nct6694_usb_read_msg);
@@ -173,12 +180,17 @@ int nct6694_usb_write_msg(struct nct6694 *nct6694,
 	struct nct6694_usb_data *udata = nct6694->priv;
 	union nct6694_usb_msg *msg = udata->usb_msg;
 	struct usb_device *udev = udata->udev;
+	u16 len = le16_to_cpu(cmd_hd->len);
 	int tx_len, rx_len, ret;
 
+	if (len > NCT6694_MAX_PACKET_SIZE)
+		return -EINVAL;
+
 	guard(mutex)(&udata->access_lock);
 
 	memcpy(&msg->cmd_header, cmd_hd, sizeof(*cmd_hd));
 	msg->cmd_header.hctrl = NCT6694_HCTRL_SET;
+	memcpy(udata->xfer_buf, buf, len);
 
 	/* Send command packet to USB device */
 	ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, NCT6694_BULK_OUT_EP), &msg->cmd_header,
@@ -187,8 +199,8 @@ int nct6694_usb_write_msg(struct nct6694 *nct6694,
 		return ret;
 
 	/* Send data packet to USB device */
-	ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, NCT6694_BULK_OUT_EP), buf,
-			   le16_to_cpu(cmd_hd->len), &tx_len, NCT6694_URB_TIMEOUT);
+	ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, NCT6694_BULK_OUT_EP), udata->xfer_buf,
+			   len, &tx_len, NCT6694_URB_TIMEOUT);
 	if (ret)
 		return ret;
 
@@ -199,17 +211,19 @@ int nct6694_usb_write_msg(struct nct6694 *nct6694,
 		return ret;
 
 	/* Receive data packet from USB device */
-	ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, NCT6694_BULK_IN_EP), buf,
-			   le16_to_cpu(cmd_hd->len), &rx_len, NCT6694_URB_TIMEOUT);
+	ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, NCT6694_BULK_IN_EP), udata->xfer_buf,
+			   len, &rx_len, NCT6694_URB_TIMEOUT);
 	if (ret)
 		return ret;
 
-	if (rx_len != le16_to_cpu(cmd_hd->len)) {
+	if (rx_len != len) {
 		dev_err(nct6694->dev, "Expected transmitted length %d, but got %d\n",
-			le16_to_cpu(cmd_hd->len), rx_len);
+			len, rx_len);
 		return -EIO;
 	}
 
+	memcpy(buf, udata->xfer_buf, len);
+
 	return nct6694_usb_err_handling(nct6694, msg->response_header.sts);
 }
 EXPORT_SYMBOL_GPL(nct6694_usb_write_msg);
@@ -270,6 +284,10 @@ static int nct6694_usb_probe(struct usb_interface *iface,
 	if (!udata->usb_msg)
 		return -ENOMEM;
 
+	udata->xfer_buf = devm_kzalloc(dev, NCT6694_MAX_PACKET_SIZE, GFP_KERNEL);
+	if (!udata->xfer_buf)
+		return -ENOMEM;
+
 	udata->int_buffer = devm_kzalloc(dev, sizeof(*udata->int_buffer), GFP_KERNEL);
 	if (!udata->int_buffer)
 		return -ENOMEM;
diff --git a/include/linux/mfd/nct6694.h b/include/linux/mfd/nct6694.h
index 853b1530755d..cb311e58a437 100644
--- a/include/linux/mfd/nct6694.h
+++ b/include/linux/mfd/nct6694.h
@@ -29,6 +29,9 @@ struct mfd_cell;
 #define NCT6694_HCTRL_SET	0x40
 #define NCT6694_HCTRL_GET	0x80
 
+/* Maximum payload length the firmware accepts in a single command */
+#define NCT6694_MAX_PACKET_SIZE	0x3F0
+
 enum nct6694_irq_id {
 	NCT6694_IRQ_GPIO0 = 0,
 	NCT6694_IRQ_GPIO1,
-- 
2.34.1


  parent reply	other threads:[~2026-08-21  3:35 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-21  3:34 [PATCH v7 00/10] mfd: nct6694: Refactor transport layer and add HIF (eSPI) support a0282524688
2026-08-21  3:34 ` [PATCH v7 01/10] mfd: nct6694: Move module type macros to shared header a0282524688
2026-08-21  3:45   ` sashiko-bot
2026-08-21  3:34 ` [PATCH v7 02/10] mfd: nct6694: Refactor USB-specific data into nct6694_usb_data a0282524688
2026-08-21  3:34 ` [PATCH v7 03/10] mfd: nct6694: Rename USB transport functions with _usb_ prefix a0282524688
2026-08-21  3:34 ` [PATCH v7 04/10] mfd: nct6694: Rename driver to nct6694-usb and update Kconfig a0282524688
2026-08-21  3:35 ` [PATCH v7 05/10] mfd: nct6694: Extract core device management into a separate module a0282524688
2026-08-21  3:35 ` a0282524688 [this message]
2026-08-21  3:35 ` [PATCH v7 07/10] mfd: nct6694: Validate the interrupt IN endpoint a0282524688
2026-08-21  3:35 ` [PATCH v7 08/10] mfd: nct6694: Submit the interrupt URB after the core is registered a0282524688
2026-08-21  3:35 ` [PATCH v7 09/10] mfd: nct6694: Introduce regmap-based transport abstraction a0282524688
2026-08-21  3:35 ` [PATCH v7 10/10] mfd: nct6694: Add Host Interface (HIF) eSPI transport driver a0282524688

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260821033505.4017901-7-a0282524688@gmail.com \
    --to=a0282524688@gmail.com \
    --cc=lee@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mfd@lists.linux.dev \
    --cc=tmyu0@nuvoton.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.