Documentation/driver-api/usb/dma.rst GitHub 원문 ↗

Linux 6.18.37 · Driver API

USB DMA

USB URB의 DMA mapping 책임, coherent buffer primitive, cache·HIGHMEM 제약과 usb_sg scatterlist API를 설명하는 한국어 전문 번역입니다.

Source pathDocumentation/driver-api/usb/dma.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

dma.rst:1-110

USB driver는 DMA-ready buffer를 제공하되 mapping을 usbcore에 맡기거나 직접 관리할 수 있습니다. Coherent allocation은 반복 mapping 비용이 큰 특수 사례에만 사용하고 일반 buffer와 scatterlist는 DMA API 규칙에 따라 mapping해야 합니다.

문서 구성
원문 줄핵심 내용
1-31DMA 책임과 URB field
32-67coherent buffer
68-87cache와 HIGHMEM
88-110기존 buffer와 scatterlist

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 USB DMA
2 ~~~~~~~
3
4 In Linux 2.5 kernels (and later), USB device drivers have additional control
5 over how DMA may be used to perform I/O operations. The APIs are detailed
6 in the kernel usb programming guide (kerneldoc, from the source code).
7
8 API overview
9 ============
10
11 The big picture is that USB drivers can continue to ignore most DMA issues,
12 though they still must provide DMA-ready buffers (see
13 Documentation/core-api/dma-api-howto.rst). That's how they've worked through
14 the 2.4 (and earlier) kernels, or they can now be DMA-aware.
15
16 DMA-aware usb drivers:
17
18 - New calls enable DMA-aware drivers, letting them allocate dma buffers and
19 manage dma mappings for existing dma-ready buffers (see below).
20
21 - URBs have an additional "transfer_dma" field, as well as a transfer_flags
22 bit saying if it's valid. (Control requests also have "setup_dma", but
23 drivers must not use it.)
24
25 - "usbcore" will map this DMA address, if a DMA-aware driver didn't do
26 it first and set ``URB_NO_TRANSFER_DMA_MAP``. HCDs
27 don't manage dma mappings for URBs.
28
29 - There's a new "generic DMA API", parts of which are usable by USB device
30 drivers. Never use dma_set_mask() on any USB interface or device; that
31 would potentially break all devices sharing that bus.
32
33 Eliminating copies
34 ==================
35
36 It's good to avoid making CPUs copy data needlessly. The costs can add up,
37 and effects like cache-trashing can impose subtle penalties.
38
39 - If you're doing lots of small data transfers from the same buffer all
40 the time, that can really burn up resources on systems which use an
41 IOMMU to manage the DMA mappings. It can cost MUCH more to set up and
42 tear down the IOMMU mappings with each request than perform the I/O!
43
44 For those specific cases, USB has primitives to allocate less expensive
45 memory. They work like kmalloc and kfree versions that give you the right
46 kind of addresses to store in urb->transfer_buffer and urb->transfer_dma.
47 You'd also set ``URB_NO_TRANSFER_DMA_MAP`` in urb->transfer_flags::
48
49 void *usb_alloc_coherent (struct usb_device *dev, size_t size,
50 int mem_flags, dma_addr_t *dma);
51
52 void usb_free_coherent (struct usb_device *dev, size_t size,
53 void *addr, dma_addr_t dma);
54
55 Most drivers should **NOT** be using these primitives; they don't need
56 to use this type of memory ("dma-coherent"), and memory returned from
57 :c:func:`kmalloc` will work just fine.
58
59 The memory buffer returned is "dma-coherent"; sometimes you might need to
60 force a consistent memory access ordering by using memory barriers. It's
61 not using a streaming DMA mapping, so it's good for small transfers on
62 systems where the I/O would otherwise thrash an IOMMU mapping. (See
63 Documentation/core-api/dma-api-howto.rst for definitions of "coherent" and
64 "streaming" DMA mappings.)
65
66 Asking for 1/Nth of a page (as well as asking for N pages) is reasonably
67 space-efficient.
68
69 On most systems the memory returned will be uncached, because the
70 semantics of dma-coherent memory require either bypassing CPU caches
71 or using cache hardware with bus-snooping support. While x86 hardware
72 has such bus-snooping, many other systems use software to flush cache
73 lines to prevent DMA conflicts.
74
75 - Devices on some EHCI controllers could handle DMA to/from high memory.
76
77 Unfortunately, the current Linux DMA infrastructure doesn't have a sane
78 way to expose these capabilities ... and in any case, HIGHMEM is mostly a
79 design wart specific to x86_32. So your best bet is to ensure you never
80 pass a highmem buffer into a USB driver. That's easy; it's the default
81 behavior. Just don't override it; e.g. with ``NETIF_F_HIGHDMA``.
82
83 This may force your callers to do some bounce buffering, copying from
84 high memory to "normal" DMA memory. If you can come up with a good way
85 to fix this issue (for x86_32 machines with over 1 GByte of memory),
86 feel free to submit patches.
87
88 Working with existing buffers
89 =============================
90
91 Existing buffers aren't usable for DMA without first being mapped into the
92 DMA address space of the device. However, most buffers passed to your
93 driver can safely be used with such DMA mapping. (See the first section
94 of Documentation/core-api/dma-api-howto.rst, titled "What memory is DMA-able?")
95
96 - When you have the scatterlists which have been mapped for the USB controller,
97 you could use the new ``usb_sg_*()`` calls, which would turn scatterlist
98 into URBs::
99
100 int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
101 unsigned pipe, unsigned period, struct scatterlist *sg,
102 int nents, size_t length, gfp_t mem_flags);
103
104 void usb_sg_wait(struct usb_sg_request *io);
105
106 void usb_sg_cancel(struct usb_sg_request *io);
107
108 When the USB controller doesn't support DMA, the ``usb_sg_init()`` would try
109 to submit URBs in PIO way as long as the page in scatterlists is not in the
110 Highmem, which could be very rare in modern architectures.
111

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

USB DMA API 개요

1-31

Linux 2.5 이후 USB device driver는 I/O operation에 DMA를 사용하는 방식을 더 세밀하게 제어할 수 있습니다. 상세 API는 source code에서 생성되는 kernel USB programming guide의 kerneldoc에 설명되어 있습니다.

큰 틀에서는 USB driver가 대부분의 DMA 문제를 계속 usbcore에 맡길 수 있지만 `Documentation/core-api/dma-api-howto.rst`에 설명된 DMA-ready buffer는 제공해야 합니다. 이는 Linux 2.4 이전 방식이며, 필요하면 driver가 DMA-aware하게 동작할 수도 있습니다.

DMA-aware driver는 새 API로 DMA buffer를 할당하고 기존 DMA-ready buffer의 mapping을 관리합니다. URB에는 `transfer_dma` field와 이 값의 유효성을 나타내는 `transfer_flags` bit가 있습니다. Control request에도 `setup_dma`가 있지만 driver가 사용하면 안 됩니다.

DMA-aware driver가 먼저 mapping하고 `URB_NO_TRANSFER_DMA_MAP`을 설정하지 않았다면 usbcore가 DMA address를 mapping합니다. HCD는 URB의 DMA mapping을 관리하지 않습니다.

Generic DMA API 일부를 USB device driver에서 사용할 수 있지만 어떤 USB interface나 device에도 `dma_set_mask()`를 호출하면 안 됩니다. 같은 bus를 공유하는 모든 device를 망가뜨릴 수 있습니다.

USB DMA 책임
구성 요소책임
USB driverDMA-ready buffer 제공, 선택적으로 mapping 관리
usbcoreflag가 없으면 URB transfer DMA mapping
HCDURB DMA mapping을 관리하지 않음
driver 금지 사항USB interface·device에 `dma_set_mask()` 사용 금지

USB DMA
~~~~~~~

In Linux 2.5 kernels (and later), USB device drivers have additional control
over how DMA may be used to perform I/O operations.  The APIs are detailed
in the kernel usb programming guide (kerneldoc, from the source code).

API overview
============

The big picture is that USB drivers can continue to ignore most DMA issues,
though they still must provide DMA-ready buffers (see
Documentation/core-api/dma-api-howto.rst).  That's how they've worked through
the 2.4 (and earlier) kernels, or they can now be DMA-aware.

DMA-aware usb drivers:

- New calls enable DMA-aware drivers, letting them allocate dma buffers and
  manage dma mappings for existing dma-ready buffers (see below).

- URBs have an additional "transfer_dma" field, as well as a transfer_flags
  bit saying if it's valid.  (Control requests also have "setup_dma", but
  drivers must not use it.)

- "usbcore" will map this DMA address, if a DMA-aware driver didn't do
  it first and set ``URB_NO_TRANSFER_DMA_MAP``.  HCDs
  don't manage dma mappings for URBs.

- There's a new "generic DMA API", parts of which are usable by USB device
  drivers.  Never use dma_set_mask() on any USB interface or device; that
  would potentially break all devices sharing that bus.

Copy 제거와 coherent buffer

32-67

CPU가 불필요하게 data를 copy하지 않도록 하는 것이 좋습니다. 누적 비용뿐 아니라 cache thrashing 같은 미묘한 penalty도 생길 수 있습니다.

같은 buffer로 작은 transfer를 매우 자주 수행하면 IOMMU가 DMA mapping을 관리하는 system에서 resource 소모가 큽니다. 요청마다 IOMMU mapping을 설정·해제하는 비용이 실제 I/O보다 훨씬 클 수 있습니다.

이 경우 USB는 `usb_alloc_coherent()`와 `usb_free_coherent()`로 더 저렴한 memory를 할당하는 primitive를 제공합니다. `kmalloc`·`kfree`와 비슷하지만 `urb->transfer_buffer`와 `urb->transfer_dma`에 넣을 올바른 종류의 address를 제공하며 `urb->transfer_flags`에는 `URB_NO_TRANSFER_DMA_MAP`을 설정합니다.

대부분의 driver는 이 primitive를 사용하면 안 됩니다. 보통 dma-coherent memory가 필요 없고 `kmalloc()`이 반환한 memory로 충분합니다.

반환 buffer는 dma-coherent이며 일관된 memory access ordering을 강제하려면 memory barrier가 필요할 수 있습니다. Streaming DMA mapping을 사용하지 않으므로 IOMMU mapping을 반복적으로 바꿀 작은 transfer에 적합합니다. Coherent와 streaming mapping의 정의는 `Documentation/core-api/dma-api-howto.rst`를 참조합니다.

Page의 `1/N` 크기나 N page를 요청하는 방식 모두 공간 효율이 합리적입니다.

Coherent URB buffer
`usb_alloc_coherent()`CPU pointer와 DMA address 획득
URB field 설정`transfer_buffer`, `transfer_dma`
transfer flag`URB_NO_TRANSFER_DMA_MAP`
완료 후`usb_free_coherent()`

반복 mapping 비용이 실제 I/O보다 큰 특수한 작은 transfer에만 사용합니다.


Eliminating copies
==================

It's good to avoid making CPUs copy data needlessly.  The costs can add up,
and effects like cache-trashing can impose subtle penalties.

- If you're doing lots of small data transfers from the same buffer all
  the time, that can really burn up resources on systems which use an
  IOMMU to manage the DMA mappings.  It can cost MUCH more to set up and
  tear down the IOMMU mappings with each request than perform the I/O!

  For those specific cases, USB has primitives to allocate less expensive
  memory.  They work like kmalloc and kfree versions that give you the right
  kind of addresses to store in urb->transfer_buffer and urb->transfer_dma.
  You'd also set ``URB_NO_TRANSFER_DMA_MAP`` in urb->transfer_flags::

        void *usb_alloc_coherent (struct usb_device *dev, size_t size,
                int mem_flags, dma_addr_t *dma);

        void usb_free_coherent (struct usb_device *dev, size_t size,
                void *addr, dma_addr_t dma);

  Most drivers should **NOT** be using these primitives; they don't need
  to use this type of memory ("dma-coherent"), and memory returned from
  :c:func:`kmalloc` will work just fine.

  The memory buffer returned is "dma-coherent"; sometimes you might need to
  force a consistent memory access ordering by using memory barriers.  It's
  not using a streaming DMA mapping, so it's good for small transfers on
  systems where the I/O would otherwise thrash an IOMMU mapping.  (See
  Documentation/core-api/dma-api-howto.rst for definitions of "coherent" and
  "streaming" DMA mappings.)

  Asking for 1/Nth of a page (as well as asking for N pages) is reasonably
  space-efficient.

Cache semantics와 HIGHMEM

68-87

대부분의 system에서 dma-coherent memory는 uncached입니다. Coherent semantics를 위해 CPU cache를 bypass하거나 bus snooping을 지원하는 cache hardware가 필요하기 때문입니다. x86은 bus snooping을 지원하지만 많은 다른 system은 DMA conflict를 막기 위해 software로 cache line을 flush합니다.

일부 EHCI controller의 device는 high memory와 DMA를 주고받을 수 있지만 현재 Linux DMA infrastructure는 이 capability를 합리적으로 노출하지 못합니다. HIGHMEM은 주로 x86_32에 특화된 설계상 문제이므로 USB driver에 highmem buffer를 전달하지 않는 것이 가장 안전하며 이것이 기본 동작입니다. `NETIF_F_HIGHDMA` 등으로 기본값을 덮어쓰면 안 됩니다.

이 제한 때문에 caller가 high memory에서 일반 DMA memory로 copy하는 bounce buffering을 수행해야 할 수 있습니다. x86_32에서 1 GiB가 넘는 memory를 위한 해결책이 있다면 patch 제출을 권장합니다.

DMA memory 제약
환경처리
dma-coherent memory보통 uncached 또는 bus snooping 필요
non-snooping systemsoftware cache-line flush
USB와 HIGHMEMhighmem buffer 전달을 피하고 기본 동작 유지
필요한 fallbacknormal DMA memory로 bounce buffering


  On most systems the memory returned will be uncached, because the
  semantics of dma-coherent memory require either bypassing CPU caches
  or using cache hardware with bus-snooping support.  While x86 hardware
  has such bus-snooping, many other systems use software to flush cache
  lines to prevent DMA conflicts.

- Devices on some EHCI controllers could handle DMA to/from high memory.

  Unfortunately, the current Linux DMA infrastructure doesn't have a sane
  way to expose these capabilities ... and in any case, HIGHMEM is mostly a
  design wart specific to x86_32.  So your best bet is to ensure you never
  pass a highmem buffer into a USB driver.  That's easy; it's the default
  behavior.  Just don't override it; e.g. with ``NETIF_F_HIGHDMA``.

  This may force your callers to do some bounce buffering, copying from
  high memory to "normal" DMA memory.  If you can come up with a good way
  to fix this issue (for x86_32 machines with over 1 GByte of memory),
  feel free to submit patches.

기존 buffer와 scatterlist

88-110

기존 buffer는 먼저 device의 DMA address space에 mapping하지 않으면 DMA에 사용할 수 없습니다. 다만 driver에 전달되는 대부분의 buffer는 이런 DMA mapping에 안전하게 사용할 수 있습니다. DMA 가능한 memory 조건은 `Documentation/core-api/dma-api-howto.rst`의 `What memory is DMA-able?` 절을 참조합니다.

USB controller용으로 mapping된 scatterlist가 있으면 `usb_sg_init()`, `usb_sg_wait()`, `usb_sg_cancel()` 계열을 사용해 scatterlist를 URB로 변환할 수 있습니다.

USB controller가 DMA를 지원하지 않을 때도 scatterlist의 page가 Highmem이 아니면 `usb_sg_init()`은 PIO 방식으로 URB 제출을 시도합니다. 현대 architecture에서는 이런 상황이 드뭅니다.

`usb_sg_*()` lifecycle
함수역할
`usb_sg_init()`scatterlist request 초기화와 URB 제출
`usb_sg_wait()`scatter-gather I/O 완료 대기
`usb_sg_cancel()`진행 중인 request 취소

Working with existing buffers
=============================

Existing buffers aren't usable for DMA without first being mapped into the
DMA address space of the device.  However, most buffers passed to your
driver can safely be used with such DMA mapping.  (See the first section
of Documentation/core-api/dma-api-howto.rst, titled "What memory is DMA-able?")

- When you have the scatterlists which have been mapped for the USB controller,
  you could use the new ``usb_sg_*()`` calls, which would turn scatterlist
  into URBs::

        int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
                unsigned pipe, unsigned        period, struct scatterlist *sg,
                int nents, size_t length, gfp_t mem_flags);

        void usb_sg_wait(struct usb_sg_request *io);

        void usb_sg_cancel(struct usb_sg_request *io);

  When the USB controller doesn't support DMA, the ``usb_sg_init()`` would try
  to submit URBs in PIO way as long as the page in scatterlists is not in the
  Highmem, which could be very rare in modern architectures.