Skip to content

← Firmware Downloads

Post-install setup · Reborn (Y2Linux) · Y2

Faster uploads over USB: multi-packet receive DMA — plan (2026-10-17)

Debian-based Linux with a fast clickwheel interface for the Innioasis Y2.

Instructions published by the project, shown here word for word.

Faster uploads over USB: multi-packet receive DMA — plan (2026-10-17)

Status: RELEASED, on by default, in Y2Linux 1.0 Beta 7.11 (Baseline 74, sequence 6352). Owner: "i would like to do multi packet and fix the kernel". Audit row USB-RX-DMA in roadmap-gap-audit. Results: below.

Evidence (owner's player, Beta 7.10, 2026-10-17, mtpbench, libusb direct, SHA-256 verified)

Internal StorageSD card
Download (player → computer), TX DMA37.7 MB/s37.7 MB/s
Upload (computer → player), RX PIO8.7–10.3 MB/s9.0 MB/s
Storage write ceiling (handoff, candidate 11)eMMC 30 MiB/sSD 26 MiB/s

Why receive DMA is off today

kernel/platform/usb.c (y2_dma_is_compatible) keeps bulk-OUT requests unmapped: Mentor/Inventra mode-0 receive DMA costs two interrupts per packet (no gain over PIO), CPU-FIX02 hit the interrupt-storm guard with it (FIX03: the guard counted the normal two-per-packet load; corrected), and a packet the host had already ACKed was lost when it followed an IN completion within microseconds. The runtime switch rx_dma (sysfs) re-enables mode 0 for comparison only.

Design: mode 1 for MTP bulk OUT

Mode 1 lets the DMA engine move consecutive full packets with no CPU work per packet; the CPU acts once per request. Upstream musb has this path only for mass storage (short_not_ok), because a mode-1 transfer gets no DMA completion for a short last packet. MTP data ends with a short packet or a zero-length packet, so the Y2 version adds:

  1. Start: a FunctionFS bulk-OUT request with at least two packets left and a full first packet is programmed as one

    mode-1 DMA transfer of the remaining length (multiple of 512, capped at the channel maximum), with AUTOCLEAR, DMAENAB and the Inventra DMAREQMODE sequence.

  2. Full packets: moved by DMA; one DMA interrupt at the end gives the request back.
  3. Short packet or ZLP before the end: the endpoint interrupt fires (RXPKTRDY, count < 512) while the channel is

    busy. The CPU stops the channel, reads how many bytes it moved (whole packets), takes the short packet by PIO and gives the request back with the exact length. The order (stop, read the count, then the FIFO) decides correctness and is the main thing the tests prove.

  4. Request boundaries: packets that arrive before the next request is queued wait in the double-buffered FIFO (the

    host is NAKed, nothing is lost); the existing late_pio path takes the waiting packet, mode 1 continues after it.

  5. Unchanged: IN (download) DMA, the 16-byte event endpoint, ECM networking, PIO as fallback whenever DMA cannot be

    programmed, the storm guard (it counts per accepted DMA program).

Reference before writing it: the stock MediaTek kernel (out/rea/fm-kernel.elf, REA) for how MTK's own musb driver programmed RX DMA on this exact controller (mode, RXCSR sequence, short-packet handling, errata workarounds).

Safety

Device tests (owner's player; hashes on every byte)

  1. mtpbench uploads at 1–200 packets with every ending: exact multiples (ZLP), one byte short, one byte over, 0 bytes.
  2. 2 000 files of random sizes up and back; 600-file folders (the mtp-file-ops suite) with mode 1 on.
  3. Uploads interleaved with downloads, listings and events (the earlier IN-completion race), Internal Storage and SD.
  4. 4 GB sustained upload soak; throughput and CPU recorded; storm guard and fault counters must stay at 0.
  5. Cable pulled mid-upload, then reconnect; deep sleep and wake with mode 1 on; Windows Explorer and Dolphin copies.

Expected result: uploads near the storage limit (≈20–30 MB/s), CPU mostly idle during uploads.

Steps

  1. Owner approves this plan.
  2. Stock reference (REA), implementation, kernel build, host checks (patch zero-fuzz, ABI, existing tests).
  3. Release with the switch off; owner installs; live A/B with rx_dma=2 (a runtime write the owner authorises).
  4. Fix what the tests find; repeat 3.
  5. Default on in the following release; audit row and report updated.

Results (2026-10-17)

Stock reference (REA, out/rea/fm-kernel.elf, Linux 3.4.67): MediaTek's rxstate is upstream's. Mode 1 only when short_not_ok and the first packet is full (RXCSR AUTOCLEAR, then DMAENAB, then a DMAMODE set/clear pulse), otherwise one mode-0 program per packet; dma_channel_pause/resume/check_residue are stubs. Stock MTP uploads therefore never used mode 1, and the short-packet ending below is our own.

Implementation (kernel/patches/0065-y2-musb-pio-progress.patch, 0055-musb-abort-bus-error.patch, kernel/platform/usb.c):

Defect found on the device: RXCOUNT counts down while the engine unloads a full packet. The first build (sequence

  1. took one such sample for a short packet and ended a 64 MiB upload after 9.6 MB (m1_end=1 with no short packet

on the wire; uMTP lost the container). Fixed by the two-sample rule; a moving count is now seen and ignored.

Measurements (owner's player, tools/usb/mtpbench.c, every byte SHA-256 verified):

PIO (7.10 / 7.11 switch off)Multi-packet DMA
Internal Storage, 1 GiB≈10 MB/s29.6 MB/s
Internal Storage, 256 MiB≈10 MB/s25.7–27.2 MB/s
SD card, 512 MiB≈9 MB/s23.3 MB/s
ECM (100 MB through SSH)6.1–8.1 MB/s9.9–13.9 MB/s
musb interrupts during upload≈22 000/s, one core 96–100 %≈1 450/s, CPU ≈80 % idle

Integrity: boundary sizes 0, 1, 499, 500, 501, 511, 512, 1012, 1024, 65523–65536, 131060/1, 200000, 1048564/5/77, 3145716 on both storages; 100 random sizes; tools/usb/mtp-file-ops.c 26/26 (with the switch on and with the default build); 1 GiB + 512 MiB soak; 300 MB over ECM; host abort mid-upload recovers exactly like PIO. Counters always balance (m1_prog = dma_done + m1_end), no kick, no fallback, no DMA bus error, storm-guard burst ≤ 22.

mtpbench itself lost the closing zero-length packet of a download that fills its last 1 MiB read (fails in PIO too); fixed in the tool.

Still owed (owner): cable pulled mid-upload, sleep and wake with it on, copies from Dolphin and Windows Explorer.

Published by the schulzcode/y2linux project [1] [3]