[Bug 273694] [patch] _bus_dmamap_count_pages() may miscount

From: <bugzilla-noreply_at_freebsd.org>
Date: Sun, 10 Sep 2023 09:31:48 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=273694

            Bug ID: 273694
           Summary: [patch] _bus_dmamap_count_pages() may miscount
           Product: Base System
           Version: 14.0-CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Only Me
          Priority: ---
         Component: kern
          Assignee: bugs@FreeBSD.org
          Reporter: jsihv@gmx.com

Created attachment 244746
  --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=244746&action=edit
patch files for different architectures

While debugging jh7110 board's MMC driver I found out that the problem had been
a faulty algorithm in DMA code.

_bus_dmamap_count_pages() in sys/riscv/riscv/busdma_bounce.c is called to count
a number of new bounce pages needed in order to complete the DMA transfer (this
happens at least when physical addresses used for data segments go out of DMA
address range). However, unlike a function bounce_bus_dmapmap_load_buffer()
which calls it, _bus_dmamap_count_pages() does not take into account that
segment size may be limited by dmat->common.maxsegsz which is set when creating
bus_dma_tag_t in the driver code. This may lead to a wrong number of pages
counted and thus some needed bounce pages will not be created.

In my case the consequence was that some addresses outside of device's 32-bit
DMA range were assigned to descriptors (IO data structures read by DMA
controller) which nevertheless can only contain first 32 bits of those
addresses. This causes the whole booting process to halt. After a failed
transfer MMC driver code stays waiting for a next interrupt that never arrives.

I found that the _bus_dmamap_count_pages() is similarly deficient in other
architectures though it's possible this bug hasn't surfaced previously. My
actual case is related to charcteristics of Designware's MMC devices (see
comments on file dwmmc.c, line 140) which imply maximum size for data segments.

I don't see any reason why this issue couldn't affect other architectures as
well if circumstances are right, so I've supplied patches for each architecture
in an attachment file. ARM and powerpc have the _bus_dmamap_count_pages()
function in file busdma_machdep.c while other archs (including ARM64) have it
in busdma_bounce.c

-- 
You are receiving this mail because:
You are the assignee for the bug.