Skip to content

staging: vchiq_arm: use one DMA device to map and unmap bulk pagelists#7494

Merged
pelwell merged 1 commit into
raspberrypi:rpi-6.18.yfrom
rachmataditiya:vchiq-pagelist-dma-dev-fix
Jul 14, 2026
Merged

staging: vchiq_arm: use one DMA device to map and unmap bulk pagelists#7494
pelwell merged 1 commit into
raspberrypi:rpi-6.18.yfrom
rachmataditiya:vchiq-pagelist-dma-dev-fix

Conversation

@rachmataditiya

Copy link
Copy Markdown

Fixes #7493 — full analysis, reproducer, and oops there.

Since the pagelist code moved into vchiq_core.c, create_pagelist() maps the bulk scatterlist with instance->state->dev while free_pagelist()/cleanup_pagelistinfo() unmap with g_dma_dev (on BCM2711 the brcm,bcm2711-dma device resolved for use_36bit_addrs, with different dma-ranges), and the coherent pagelist buffer is allocated on instance->state->dev but freed on g_dma_dev. This breaks every userspace /dev/vchiq bulk transfer on Pi 4 arm64: the VPU is handed 36-bit pagelist entries computed under the wrong device's dma-ranges (bulk writes arrive as garbage, sustained load wedges the VPU), and the first bulk read oopses in free_pagelist() on the DMA_FROM_DEVICE unmap cache invalidate.

This restores the pairing rpi-6.12.y shipped (map/unmap on g_dma_dev, coherent alloc/free on instance->state->dev), which is the last known-working combination.

Verified on a Pi 4B Rev 1.5 (2GB): on stock 6.18.34+rpt a vc.ril.video_splitter payload loopback from a 64-bit userland oopses as in the issue and vc.ril.video_decode never decodes; on rpi-6.18.y with this patch the loopback round-trips byte-identical and H.264 decode from a 64-bit process runs at full rate (26k frames / 600 s soak, clean dmesg).

Context: 64-bit userland MMAL work discussed in the "Porting Linux VCHIQ Driver To 64 Bit" forum thread.

@popcornmix

Copy link
Copy Markdown
Collaborator

Looks plausible. @pelwell I assume this is still needed after a number of iterations of upstreaming?

@pelwell

pelwell commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

I'm confused - this patch appears to take a mismatch and reverse it, i.e. it is still unbalanced, but the other way round.

@pelwell

pelwell commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

g_dma_dev should be used in both instances.

@6by9

6by9 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

There is vchiq_test in https://github.com/raspberrypi/userland/blob/master/interface/vchiq_arm/vchiq_test.c which should exercise bulk transfers fairly comprehensively.

I'll try and get it running both with and without this patch on Pi4 (Pi0-3 should be identical as g_dma_device is the same device).

@6by9

6by9 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

vchiq_test appears to fail generally on Pi4.
I guess upstream still doesn't have the 40bit DMA controller driver, so that probably accounts for not having had the issue reported there.

Testing on a Pi3 with a 64bit OS seems to work fine, so being associated with the dma device would follow.
The V4L2 drivers avoid doing bulk transfers, so that is likely why they don't have issues.

By the same logic it feels like the dma_pool added in 5252444 should probably also be allocated against g_dma_dev rather than always dev, but this is getting a bit beyond my knowledge of vchiq.

@6by9

6by9 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Mainline 7.2.0-rc1 also fails on a Pi4.

@pelwell

pelwell commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

#7497 fixes vchiq-test on Pi 4/6.18 for me.

@pelwell

pelwell commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Mainline 7.2.0-rc1 also fails on a Pi4.

Does it work on other mainline kernel versions?

@6by9

6by9 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Comparing against 6.12, I think I agree with this patch.

dma_alloc_coherent and dma_free_coherent use instance->state->dev
dma_map_sg and dma_unmap_sg use g_dma_dev
One of each was wrong on 6.18, hence the slightly odd looking patch.

Pass as to why vchiq_test was failing when I'd applied this before. It's working fine now.

Seeing your new PR, whether dma_alloc_coherent and dma_free_coherent should use instance->state->dev is a different question.

@6by9

6by9 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

#7497 fixes vchiq-test on Pi 4/6.18 for me.

vchiq_test -f fails immediately for me with that.

Functional test - iters:100
======== iteration 1 ========
vchiq_test: 1540: expected callback reason VCHIQ_BULK_TRANSMIT_DONE, got 5
vchiq_test: 856: func_error != 0

@pelwell

pelwell commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Seeing your new PR, whether dma_alloc_coherent and dma_free_coherent should use instance->state->dev is a different question.

It's possible the two end up being equivalent if the DMA allocations end up coming from the CMA heap, which we confine to the first 1GB.

The three main vchiq_test modes - ping, bulk and functional - all pass with this patch on a 4GB Pi 4, so I'm happy to merge it and drop mine.

@6by9

6by9 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

I'm on an 8GB Pi4. Swapping dmam_pool_create to use g_dma_dev (as per your patch and my suggestion) then also fails vchiq_test -f with the same error:

Functional test - iters:100
======== iteration 1 ========
vchiq_test: 1540: expected callback reason VCHIQ_BULK_TRANSMIT_DONE, got 5
vchiq_test: 856: func_error != 0

@pelwell

pelwell commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

I think the changes to the device used for allocation may remove the CMA constraint, even though the VPU needs it.

vchiq_test -f fails immediately for me with that.

I've just found the same thing.

create_pagelist() maps the bulk scatterlist with instance->state->dev
(the vchiq platform device) while free_pagelist() and
cleanup_pagelistinfo() unmap it with g_dma_dev - on BCM2711 the
brcm,bcm2711-dma device resolved for use_36bit_addrs, whose dma-ranges
differ from the vchiq node's. The coherent pagelist buffer is likewise
allocated on instance->state->dev but freed on g_dma_dev.

Mapping and unmapping with different devices breaks every userspace
bulk transfer on Pi 4 arm64:

 - the 36-bit addrs[] entries handed to the VPU are computed from
   sg_dma_address() under the wrong device's dma-ranges, so the VPU
   reads/writes the wrong bus addresses (bulk WRITE payloads arrive
   as garbage; under sustained load the VPU stops responding to
   mailbox requests entirely);

 - the first bulk READ oopses in free_pagelist(): the DMA_FROM_DEVICE
   dma_unmap_sg() cache invalidate mis-translates the dma address back
   to phys under the other device's dma-ranges (0xf41e8e80 = phys
   0x341e8e80 still carrying the vchiq device's 0xc0000000 alias):

     Unable to handle kernel paging request at virtual address
     ffffff80f41e8e80
     CPU: 0 PID: 80 Comm: vchiq-slot/0
     Call trace:
      dcache_inval_poc+0x28/0x58 (P)
      dma_direct_unmap_sg+0x224/0x260
      dma_unmap_sg_attrs+0x60/0x148
      free_pagelist.isra.0+0x54/0x1f8
      slot_handler_func+0x4b8/0xdf0

rpi-6.12.y paired these consistently: dma_map_sg/dma_unmap_sg both on
g_dma_dev, dma_alloc_coherent/dma_free_coherent both on
instance->state->dev. Restore that pairing.

Verified on a Pi 4B Rev 1.5: on an unpatched 6.18 kernel a
vc.ril.video_splitter payload loopback from a 64-bit userland oopses
as above and vc.ril.video_decode consumes garbage; with this change
the loopback round-trips byte-identical and decode runs at full rate.
Nothing in-tree exercises userspace vchiq bulk on arm64 (the kernel
MMAL clients use vc-sm-cma zero-copy imports), which is why this went
unnoticed.

Fixes: 35ef141 ("staging: vchiq_arm: Set up dma ranges on child devices")
Link: raspberrypi#7493
Signed-off-by: Rachmat Aditiya <raditiya@me.com>
@rachmataditiya rachmataditiya force-pushed the vchiq-pagelist-dma-dev-fix branch from 8e6f3f7 to fb841f0 Compare July 14, 2026 14:41
@rachmataditiya

Copy link
Copy Markdown
Author

Thanks both — much appreciated.

I've pushed a small amend for the checkpatch bot: re-wrapped one long line in the commit message and fixed a continuation indent in cleanup_pagelistinfo(). Whitespace only — no functional change from what was tested.

On the allocation side: this patch deliberately keeps dma_alloc_coherent/dma_pool_create on instance->state->dev and only re-pairs map/unmap onto g_dma_dev, restoring the 6.12 pairing — for what I think is the reason @pelwell describes: the VPU-visible allocations stay under the CMA / first-GB constraint. The 8GB -f failure when the pool moves to g_dma_dev looks consistent with that. Whether the alloc device should eventually change too seems like a separate question — happy to help dig into it if useful.

@6by9

6by9 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Mainline 7.2.0-rc1 also fails on a Pi4.

Does it work on other mainline kernel versions?

Not tried.
I happened to have the 7.2.0 kernel from my recent upstreaming efforts. Finding an earlier one will be a bit more involved.

@pelwell pelwell merged commit 33cc967 into raspberrypi:rpi-6.18.y Jul 14, 2026
4 of 12 checks passed
popcornmix added a commit to raspberrypi/firmware that referenced this pull request Jul 15, 2026
See: raspberrypi/linux#7500

kernel: staging: vchiq_arm: use one DMA device to map and unmap bulk pagelists
See: raspberrypi/linux#7494

kernel: drm/vc4: hdmi: Remove duplicate hotplug helper call
See: raspberrypi/linux#7489

kernel: ASoC: hifiberry_studio: change driver name and add support for new soundcards
See: raspberrypi/linux#7487

kernel: mmc: Fix MMC request issuing race condition to prevent stall
See: raspberrypi/linux#7486

kernel: dmaengine: dw-axi-dmac: Wait for runtime resume before using a channel
See: raspberrypi/linux#7484

kernel: overlays: i2c-fan: add compatible for upstream compatibility
See: raspberrypi/linux#7483
popcornmix added a commit to raspberrypi/rpi-firmware that referenced this pull request Jul 15, 2026
See: raspberrypi/linux#7500

kernel: staging: vchiq_arm: use one DMA device to map and unmap bulk pagelists
See: raspberrypi/linux#7494

kernel: drm/vc4: hdmi: Remove duplicate hotplug helper call
See: raspberrypi/linux#7489

kernel: ASoC: hifiberry_studio: change driver name and add support for new soundcards
See: raspberrypi/linux#7487

kernel: mmc: Fix MMC request issuing race condition to prevent stall
See: raspberrypi/linux#7486

kernel: dmaengine: dw-axi-dmac: Wait for runtime resume before using a channel
See: raspberrypi/linux#7484

kernel: overlays: i2c-fan: add compatible for upstream compatibility
See: raspberrypi/linux#7483
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

5 participants