From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: Sam Day <me@samcday.com>, David Heidelberg <david@ixit.cz>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Sasha Levin <sashal@kernel.org>,
linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH AUTOSEL 6.19-6.12] usb: gadget: f_fs: fix DMA-BUF OUT queues
Date: Wed, 18 Feb 2026 21:04:06 -0500 [thread overview]
Message-ID: <20260219020422.1539798-30-sashal@kernel.org> (raw)
In-Reply-To: <20260219020422.1539798-1-sashal@kernel.org>
From: Sam Day <me@samcday.com>
[ Upstream commit 0145e7acd29855dfba4a2f387d455b5d9a520f0e ]
Currently, DMA_FROM_DEVICE is used when attaching DMABUFs to IN
endpoints and DMA_TO_DEVICE for OUT endpoints. This is inverted from
how it should be.
The result is IOMMU read-only mappings placed on OUT queues,
triggering arm-smmu write faults.
Put differently, OUT endpoints flow data from host -> gadget, meaning
the UDC peripheral needs to have write access to the buffer to fill it
with the incoming data.
This commit flips the directions and updates the implicit-sync helpers
so IN endpoints act as readers and OUT endpoints as writers.
Signed-off-by: Sam Day <me@samcday.com>
Tested-by: David Heidelberg <david@ixit.cz> # OnePlus 6T on sdm845-next-20251119
Link: https://patch.msgid.link/20260108-ffs-dmabuf-ioctl-fix-v1-2-e51633891a81@samcday.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
Wait — I see the code at line 1512 still shows the **old** (buggy)
direction. This means the fix commit hasn't been applied yet to this
tree. Let me verify this is the pre-fix state, and confirm the
correctness of the fix.
The key insight about USB gadget directions:
- **IN endpoint** (`epfile->in == true`): Data flows from gadget **to**
host. The UDC reads from the buffer → `DMA_TO_DEVICE` (device reads
the memory)
- **OUT endpoint** (`epfile->in == false`): Data flows from host **to**
gadget. The UDC writes to the buffer → `DMA_FROM_DEVICE` (device
writes to memory)
The current code has it backwards:
- `epfile->in ? DMA_FROM_DEVICE : DMA_TO_DEVICE` — **WRONG**
- Should be: `epfile->in ? DMA_TO_DEVICE : DMA_FROM_DEVICE` —
**CORRECT**
This is consistent with the DMA-BUF perspective where DMA direction
refers to the device's perspective relative to memory.
Similarly for the reservation fences:
- IN endpoint (read from buffer to send to host) → the fence should be
`DMA_RESV_USAGE_READ` (reading from the buffer)
- OUT endpoint (write incoming data to buffer) → the fence should be
`DMA_RESV_USAGE_WRITE` (writing to the buffer)
The current code has:
- `epfile->in ? DMA_RESV_USAGE_WRITE : DMA_RESV_USAGE_READ` — **WRONG**
- Should be: `epfile->in ? DMA_RESV_USAGE_READ : DMA_RESV_USAGE_WRITE` —
**CORRECT**
And for the `dma_resv_wait_timeout`:
- `dma_resv_usage_rw(epfile->in)` means: if IN, wait for both
read+write; if OUT, wait for write only
- Should be `dma_resv_usage_rw(!epfile->in)`: if OUT, wait for both
read+write; if IN, wait for write only
This logic is also inverted and the fix correctly flips it.
## Summary Assessment
### What problem does this commit solve?
This fixes an inverted DMA direction mapping for DMA-BUF operations in
the USB gadget FunctionFS driver. The bug causes:
1. **IOMMU write faults** (arm-smmu) on OUT endpoints because buffers
are mapped read-only when they need write access
2. Incorrect implicit-sync fence semantics (readers treated as writers
and vice versa)
This is a **correctness bug** that makes DMA-BUF OUT transfers
completely non-functional on systems with an IOMMU (which includes most
modern ARM SoCs).
### Does it meet stable kernel rules?
1. **Obviously correct**: Yes — the DMA direction semantics are well-
defined and the fix is a straightforward inversion of three boolean
conditions
2. **Fixes a real bug**: Yes — DMA-BUF OUT transfers cause IOMMU faults
on ARM platforms
3. **Important issue**: Yes — hardware fault/crash-level issue that
prevents a feature from working
4. **Small and contained**: Yes — 3 lines changed in a single file
5. **No new features**: Correct — pure bug fix
6. **Tested**: Yes — "Tested-by: David Heidelberg" on OnePlus 6T
(sdm845)
### Risk vs Benefit
- **Risk**: Very low — the change is mechanical (flip three booleans),
touches only DMA-BUF code paths in f_fs, and cannot affect non-DMA-BUF
USB operations
- **Benefit**: High — fixes broken DMA-BUF OUT transfers that cause
IOMMU faults
### Concerns
- **Affected versions**: The DMA-BUF support was introduced in commit
`7b07a2a7ca02a` during the v6.9 development cycle. Only stable trees
from v6.9 onward need this fix (the code doesn't exist in older
kernels).
- **Dependencies**: None — the fix is self-contained and touches only
the three lines with the bug
- **Backport risk**: Clean application expected since the surrounding
code has not changed significantly
### Verification
- `git log -S "ffs_dmabuf_attach" master` confirmed the DMA-BUF
interface was introduced in commit `7b07a2a7ca02a` (v6.9 cycle,
2024-01-30)
- `git merge-base --is-ancestor 7b07a2a7ca02a master` confirmed the
buggy code is in master
- Read of `f_fs.c` at lines 1490-1549 verified the current (pre-fix)
code shows the inverted `DMA_FROM_DEVICE`/`DMA_TO_DEVICE` direction
- Grep for `epfile->in` confirmed three locations needing the fix (lines
1512, 1642, 1687) matching the patch
- Line 2442 shows `epfile->in = usb_endpoint_dir_in(ep->ep->desc)`
confirming `epfile->in` is true for IN endpoints (data to host)
- USB DMA direction convention verified: IN endpoint = device reads
buffer = `DMA_TO_DEVICE`; OUT endpoint = device writes buffer =
`DMA_FROM_DEVICE`. The original code has these inverted.
- `git tag --contains 7b07a2a7ca02a` shows the commit is in `p-6.12`,
`p-6.15`, `p-6.16` branches, confirming the buggy code exists in
multiple stable trees
- Commit has "Tested-by: David Heidelberg" and was merged by Greg Kroah-
Hartman (USB maintainer), indicating quality review
This is a clear, small, well-tested fix for a real hardware fault that
makes DMA-BUF OUT transfers completely broken on IOMMU-enabled
platforms. It meets all stable kernel criteria.
**YES**
drivers/usb/gadget/function/f_fs.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index fa467a40949d2..928f51fddc64e 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -1509,7 +1509,7 @@ static int ffs_dmabuf_attach(struct file *file, int fd)
goto err_dmabuf_detach;
}
- dir = epfile->in ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+ dir = epfile->in ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
err = ffs_dma_resv_lock(dmabuf, nonblock);
if (err)
@@ -1639,7 +1639,7 @@ static int ffs_dmabuf_transfer(struct file *file,
/* Make sure we don't have writers */
timeout = nonblock ? 0 : msecs_to_jiffies(DMABUF_ENQUEUE_TIMEOUT_MS);
retl = dma_resv_wait_timeout(dmabuf->resv,
- dma_resv_usage_rw(epfile->in),
+ dma_resv_usage_rw(!epfile->in),
true, timeout);
if (retl == 0)
retl = -EBUSY;
@@ -1684,7 +1684,7 @@ static int ffs_dmabuf_transfer(struct file *file,
dma_fence_init(&fence->base, &ffs_dmabuf_fence_ops,
&priv->lock, priv->context, seqno);
- resv_dir = epfile->in ? DMA_RESV_USAGE_WRITE : DMA_RESV_USAGE_READ;
+ resv_dir = epfile->in ? DMA_RESV_USAGE_READ : DMA_RESV_USAGE_WRITE;
dma_resv_add_fence(dmabuf->resv, &fence->base, resv_dir);
dma_resv_unlock(dmabuf->resv);
--
2.51.0
next prev parent reply other threads:[~2026-02-19 2:05 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-19 2:03 [PATCH AUTOSEL 6.19] rust_binder: Fix build failure if !CONFIG_COMPAT Sasha Levin
2026-02-19 2:03 ` [PATCH AUTOSEL 6.19-6.12] usb: chipidea: udc: fix DMA and SG cleanup in _ep_nuke() Sasha Levin
2026-02-19 2:03 ` [PATCH AUTOSEL 6.19-5.15] staging: rtl8723bs: fix memory leak on failure path Sasha Levin
2026-02-19 2:03 ` [PATCH AUTOSEL 6.19] tty: vt/keyboard: Split apart vt_do_diacrit() Sasha Levin
2026-02-19 2:03 ` [PATCH AUTOSEL 6.19-5.10] fix it87_wdt early reboot by reporting running timer Sasha Levin
2026-02-19 2:03 ` [PATCH AUTOSEL 6.19-5.15] misc: eeprom: Fix EWEN/EWDS/ERAL commands for 93xx56 and 93xx66 Sasha Levin
2026-02-19 2:03 ` [PATCH AUTOSEL 6.19-5.15] mmc: rtsx_pci: add quirk to disable MMC_CAP_AGGRESSIVE_PM for RTS525A Sasha Levin
2026-02-19 10:29 ` Ulf Hansson
2026-02-26 13:23 ` Sasha Levin
2026-02-19 2:03 ` [PATCH AUTOSEL 6.19-6.1] fpga: of-fpga-region: Fail if any bridge is missing Sasha Levin
2026-02-19 2:03 ` [PATCH AUTOSEL 6.19-6.12] soundwire: intel_auxdevice: add cs42l45 codec to wake_capable_list Sasha Levin
2026-02-19 2:03 ` [PATCH AUTOSEL 6.19-5.10] iio: magnetometer: Remove IRQF_ONESHOT Sasha Levin
2026-02-19 2:03 ` [PATCH AUTOSEL 6.19-6.1] watchdog: imx7ulp_wdt: handle the nowayout option Sasha Levin
2026-02-19 2:03 ` [PATCH AUTOSEL 6.19-5.10] serial: 8250_dw: handle clock enable errors in runtime_resume Sasha Levin
2026-02-19 2:03 ` [PATCH AUTOSEL 6.19-6.12] most: core: fix resource leak in most_register_interface error paths Sasha Levin
2026-02-19 2:03 ` [PATCH AUTOSEL 6.19] block: fix partial IOVA mapping cleanup in blk_rq_dma_map_iova Sasha Levin
2026-02-19 2:03 ` [PATCH AUTOSEL 6.19-6.1] misc: bcm_vk: Fix possible null-pointer dereferences in bcm_vk_read() Sasha Levin
2026-02-19 2:03 ` [PATCH AUTOSEL 6.19-6.1] dmaengine: sun6i: Choose appropriate burst length under maxburst Sasha Levin
2026-02-19 2:03 ` [PATCH AUTOSEL 6.19-6.1] mmc: rtsx: reset power state on suspend Sasha Levin
2026-02-19 10:27 ` Ulf Hansson
2026-02-26 13:24 ` Sasha Levin
2026-02-19 2:03 ` [PATCH AUTOSEL 6.19] serial: rsci: Add set_rtrg() callback Sasha Levin
2026-02-19 2:03 ` [PATCH AUTOSEL 6.19-5.10] Revert "mfd: da9052-spi: Change read-mask to write-mask" Sasha Levin
2026-02-19 2:03 ` [PATCH AUTOSEL 6.19-6.18] pinctrl: mediatek: make devm allocations safer and clearer in mtk_eint_do_init() Sasha Levin
2026-02-19 2:03 ` [PATCH AUTOSEL 6.19-6.12] serial: 8250: 8250_omap.c: Add support for handling UART error conditions Sasha Levin
2026-02-19 2:03 ` [PATCH AUTOSEL 6.19-6.12] usb: gadget: f_fs: Fix ioctl error handling Sasha Levin
2026-02-19 2:03 ` [PATCH AUTOSEL 6.19-6.12] phy: cadence-torrent: restore parent clock for refclk during resume Sasha Levin
2026-02-19 2:04 ` [PATCH AUTOSEL 6.19-5.10] binder: don't use %pK through printk Sasha Levin
2026-02-19 2:04 ` [PATCH AUTOSEL 6.19-6.18] iio: bmi270_i2c: Add MODULE_DEVICE_TABLE for BMI260/270 Sasha Levin
2026-02-19 2:04 ` [PATCH AUTOSEL 6.19-5.15] iio: Use IRQF_NO_THREAD Sasha Levin
2026-02-19 2:04 ` [PATCH AUTOSEL 6.19-6.12] mfd: intel-lpss: Add Intel Nova Lake-S PCI IDs Sasha Levin
2026-02-19 2:04 ` [PATCH AUTOSEL 6.19-6.12] phy: ti: phy-j721e-wiz: restore mux selection during resume Sasha Levin
2026-02-19 2:04 ` [PATCH AUTOSEL 6.19-5.10] MIPS: Loongson: Make cpumask_of_node() robust against NUMA_NO_NODE Sasha Levin
2026-02-19 2:04 ` Sasha Levin [this message]
2026-02-19 2:04 ` [PATCH AUTOSEL 6.19-5.10] phy: fsl-imx8mq-usb: disable bind/unbind platform driver feature Sasha Levin
2026-02-19 2:04 ` [PATCH AUTOSEL 6.19-6.18] watchdog: rzv2h_wdt: Discard pm_runtime_put() return value Sasha Levin
2026-02-19 2:04 ` [PATCH AUTOSEL 6.19-6.1] soundwire: dmi-quirks: add mapping for Avell B.ON (OEM rebranded of NUC15) Sasha Levin
2026-02-19 2:04 ` [PATCH AUTOSEL 6.19-6.18] pinctrl: renesas: rzt2h: Allow .get_direction() for IRQ function GPIOs Sasha Levin
2026-02-19 2:04 ` [PATCH AUTOSEL 6.19-6.12] dmaengine: stm32-dma3: use module_platform_driver Sasha Levin
2026-02-19 2:04 ` [PATCH AUTOSEL 6.19-5.15] staging: rtl8723bs: fix missing status update on sdio_alloc_irq() failure Sasha Levin
2026-02-19 2:04 ` [PATCH AUTOSEL 6.19-5.15] phy: mvebu-cp110-utmi: fix dr_mode property read from dts Sasha Levin
2026-02-19 2:04 ` [PATCH AUTOSEL 6.19-6.1] usb: typec: ucsi: psy: Fix voltage and current max for non-Fixed PDOs Sasha Levin
2026-02-19 2:04 ` [PATCH AUTOSEL 6.19-5.10] serial: 8250: 8250_omap.c: Clear DMA RX running status only after DMA termination is done Sasha Levin
2026-02-19 2:04 ` [PATCH AUTOSEL 6.19-6.1] dmaengine: stm32-mdma: initialize m2m_hw_period and ccr to fix warnings Sasha Levin
2026-02-19 2:04 ` [PATCH AUTOSEL 6.19-6.18] misc: ti_fpc202: fix a potential memory leak in probe function Sasha Levin
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=20260219020422.1539798-30-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=david@ixit.cz \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=me@samcday.com \
--cc=patches@lists.linux.dev \
--cc=stable@vger.kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox