Files
RedBear-OS/local/docs/QUIRKS-IMPROVEMENT-PLAN.md
T

20 KiB
Raw Blame History

Hardware Quirks Improvement Plan

Purpose

This plan replaces vague “quirks support” follow-up work with a concrete path to:

  1. keep quirks data and reporting honest,
  2. integrate quirks into real runtime driver behavior,
  3. reduce duplicated quirk logic,
  4. leave DMI and USB device quirks in a maintainable state.

v2.0 update (2026-07-24): adds the universal quirk-consumption model (§ below) — a redesign assessment grounded in a full cross-reference of Linux 7.1 quirk consumption across all 9 quirk families (PCI, USB, HDA, DMI, ATA, NVMe, HID, ACPI, MMC), and the first implementation of it: the open driver-scoped domain channel ([[<domain>_quirk]] tables + quirks::lookup_driver_quirks), which also resolves the audio_* unknown-flag drift.

Universal quirk-consumption model (v2.0 redesign assessment)

What the Linux 7.1 cross-reference established

Linux has no unified registry — 9 separate per-subsystem tables. But every one of them follows the same three-layer invariant:

[1] MATCH      (typed keys: VID/DID, class, subsystem IDs, model strings, DMI, CID/dates)
[2] STORE      (flag bits or fixup pointers attached to the device object)
[3] CONSUME    (the subsystem CORE or the owning driver, at FIXED lifecycle points)

Three consumption classes exist:

Class Linux example Mechanism
A. Core lifecycle callbacks PCI DECLARE_PCI_FIXUP_* (8 passes: early/header/final/enable/resume/...) Core invokes quirk functions at lifecycle points; drivers never look anything up
B. Core flag checks USB usb_detect_quirks, NVMe .driver_data, HID hid_lookup_quirk, ATA ata_dev_quirks Flags set on the device object at enumeration; the subsystem core checks them at behavior points
C. Driver-owned domain tables HDA snd_hda_pick_fixup (5 actions: PRE_PROBE/PROBE/BUILD/INIT/FREE) The driver matches its OWN table at its own lifecycle points

Red Bear's position (post-cutover, 2026-07-24)

Red Bear diverges from Linux deliberately and correctly by having one unified registry (redox-driver-sys: compiled tables + TOML + DMI) instead of N tables. The registry is the right base; what was missing is the lifecycle model and the Type-C driver-domain channel.

The redesigned model — one registry, three consumption classes:

  1. Bind-time (Class B, owned by driver-manager). Spawn-time quirk decisions: env hints (REDBEAR_DRIVER_PCI_IRQ_MODE, DISABLE_ACCEL, IOMMU_GROUP, NUMA_NODE, MSIX_VECTORS), NEED_FIRMWARE deferral, blacklist interplay. Implemented and QEMU-validated in the cutover.
  2. Core-runtime (Class B, owned by subsystem daemons). Each subsystem daemon queries the registry at its own behavior points: xhcid (51-flag xHCI table), redox-drm (IRQ/accel), linux-kpi C drivers (pci_has_quirk()), acpid (system quirks), and — planned — pcid for config-space behaviors and evdevd/HID for input quirks.
  3. Driver-runtime (Class C, NEW — open domain channel). Driver-owned domains carried as string flags keyed by domain name: [[<domain>_quirk]] TOML tables, matched by (vendor, device) with wildcards, accumulated by quirks::lookup_driver_quirks(domain, vid, did) -> Vec<String>. New domains need zero registry code — the table name is the domain key. First instance: [[audio_quirk]] (quirks.d/15-audio.toml) with quirks::lookup_audio_quirks() for ihdad's future integration, mirroring Linux's per-codec HDA fixup model.

What this changes vs the v1 plan

  • The v1 plan's "brokered quirk bits from pcid-spawner" is stale — pcid-spawner was retired and removed on 2026-07-24 as part of the driver-manager cutover; driver-manager is the bind-time consumer now, and the broker concept is subsumed by Class 1 above.
  • The v1 plan had no answer for driver-specific quirks (audio) — they warned as unknown flags and were dropped. Class 3 is the answer: carried, queryable, zero-warning.
  • Lifecycle beyond spawn (Linux Class A phases: early pre-claim vs enable vs suspend/resume) remains a next-milestone item: phase = "early"|"enable" on entries, with driver-manager consulting the registry during enumeration (early) in addition to spawn (enable). PM phases wait for the power-management roadmap.

Consumption contract per class (who may query what)

Consumer API Class
driver-manager (spawn) lookup_pci_quirks → env hints, deferrals 1
Rust drivers/daemons info.quirks(), lookup_usb_quirks, lookup_xhci_controller_quirks_full, lookup_hid_quirks 2
C drivers via linux-kpi pci_has_quirk() / pci_get_quirk_flags() 2
Driver-owned domains lookup_driver_quirks(domain, vid, did), lookup_audio_quirks(vid, did) 3
Tooling (lspci/lsusb/info) same lookups, display-only

Current status snapshot

Completed from this plan:

  • runtime DMI TOML loading in redox-driver-sys,
  • the former pcid-spawner drift items are now obsoleted by the 2026-07-24 driver-manager cutover,
  • real USB device quirk consumption in xhcid,
  • first real linux-kpi quirk consumption in the Red Bear amdgpu path,
  • canonical GPU quirk policy moved to the Rust driver boundary in redox-drm, so Intel and AMD now consume one shared quirk source for init-time policy,
  • PCI quirk extraction upgraded from handler-name guessing to explicit handler-body evidence in local/scripts/extract-linux-quirks.py.

Still open after this implementation wave:

  • document the provenance of existing AMD need_firmware entries in quirks.d/10-gpu.toml,
  • keep AMD device-specific GPU quirk growth review-gated on Linux-backed evidence,
  • keep Intel GPU quirk expansion deferred until Red Bear has a real Intel-side firmware/runtime policy surface that can honestly consume additional flags.

Current naming/source split:

  • PCI vendor/device names now come from the shipped pciids database (/usr/share/misc/pci.ids).
  • PCI/USB/storage quirk flags still come from Red Bears canonical quirk path: compiled tables, shipped TOML files, and conservative Linux-source extraction where applicable.
  • The extract-linux-quirks.py script remains a quirk-mining tool, not the source of human-readable PCI device names.

The runtime-behavior milestone from this plan is now implemented. The remaining work is maintenance, validation depth, and future refinement rather than missing quirks behavior for the shipped paths.

It is based on the current in-tree state of:

  • redox-driver-sys as the canonical quirks library (three-layer model: match → store → consume; typed bitflag domains plus the open driver-scoped domain channel),
  • driver-manager as the bind-time quirk consumer (spawn env hints, deferrals) — validated in the 2026-07-23/24 QEMU gate,
  • redox-drm, xhcid, and the amdgpu Redox glue/runtime path as runtime quirk consumers,
  • lspci, lsusb, and redbear-info as reporting surfaces.

Reassessment Summary

What is real today

  • redox-driver-sys owns the canonical PCI/USB quirk flag definitions and lookup helpers.
  • redox-drm consumes PCI quirks for interrupt fallback and DISABLE_ACCEL.
  • xhcid consumes PCI controller quirks via PCI_QUIRK_FLAGS for IRQ mode selection and reset delay, and (since 2026-07-18, P2-A) the canonical 51-flag XhciControllerQuirkFlags table (~85 entries, Linux 7.1 port) for BROKEN_MSI/streams/LPM/reset/ring-sizing behavior across ~40 code paths.
  • linux-kpi exposes pci_get_quirk_flags() / pci_has_quirk() for C drivers, and amdgpu now consumes them in its Redox init path.
  • lspci and lsusb surface active PCI/USB quirk flags for discovered devices.
  • redbear-info --quirks reports configured TOML entries and DMI rule counts.

What is still weak

  • USB quirks now have a first real runtime consumer in xhcid, but broader USB-driver adoption is still missing.
  • The linux-kpi bridge now has a first real in-tree C consumer: amdgpu uses it for quirk-aware IRQ expectation logging. Broader C-driver adoption is still missing.

What should not be “fixed” in the wrong layer

  • firmware-loader should stay a generic scheme service. NEED_FIRMWARE belongs in device driver policy, not in the firmware scheme daemon.
  • redbear-info should describe configured and observable state; it should not pretend to prove runtime quirk application.

Target Architecture

Upstream-preference policy

When upstream Redox already provides the same functionality, the upstream path wins by default unless the Red Bear-local implementation is materially better. For quirks and driver support, this means the canonical path should converge on redox-driver-sys instead of preserving lower-quality duplicate quirk engines as a steady state.

Canonical rule

redox-driver-sys remains the authoritative quirks model:

  • flag definitions,
  • compiled-in tables,
  • TOML parsing semantics,
  • DMI matching behavior.

All other code should either:

  1. call the canonical lookup directly, or
  2. receive lookup results from a single broker that is guaranteed to use the same semantics.

Driver integration rule

  • Rust PCI drivers using redox-driver-sys should call info.quirks() directly.
  • C drivers using linux-kpi should call pci_has_quirk() / pci_get_quirk_flags() directly in probe/init paths.
  • Driver-owned domain quirks (audio, future nvme/ata) use lookup_driver_quirks(domain, vendor, device) / lookup_audio_quirks(vendor, device) — see the universal model § above.
  • USB device quirks should be consumed inside xhcid device enumeration/configuration logic, not only in tooling.

Concrete Work Plan

Wave 1 — Cleanup and truthfulness

Task 1.1: Keep docs and reporting surfaces honest

Scope:

  • local/docs/QUIRKS-SYSTEM.md
  • local/recipes/system/redbear-info/source/src/main.rs
  • related AGENTS references if needed

Goals:

  • separate reporting surfaces from real runtime consumers,
  • remove claims that imply driver integration where only tooling exists,
  • keep “not yet implemented” items explicit.

QA:

  • cargo test in local/recipes/system/redbear-info/source
  • review redbear-info --help text and --quirks output strings

Task 1.2: Remove stale equivalence claims from extraction/documentation

Scope:

  • local/scripts/extract-linux-quirks.py
  • local/docs/QUIRKS-SYSTEM.md

Goals:

  • avoid mapping Linux flags to incorrect Red Bear flags,
  • clearly mark the supported explicit PCI extraction patterns and the limits of unsupported handlers.

QA:

  • run the script on a small synthetic USB/PXI input sample,
  • confirm output omits unsupported PCI flag mappings instead of inventing equivalents.

Current state:

  • local/scripts/extract-linux-quirks.py no longer guesses PCI quirks from handler names.
  • PCI extraction now maps only explicit handler-body evidence for supported PCI_DEV_FLAGS_* assignments plus pci_d3cold_disable(...).
  • Running the upgraded extractor on Linux 7.0 drivers/pci/quirks.c currently yields only a very small high-confidence PCI subset and no directly usable modern Intel/AMD DRM GPU entries.
  • This is intentional: false negatives are preferred over wrong GPU quirk claims.
  • The existing AMD need_firmware entries in quirks.d/10-gpu.toml are manually reviewed policy entries, not extractor-produced Linux facts. Future extraction runs will not refresh those flags automatically.
  • Intel firmware classes should be treated explicitly: DMC for display power management, GuC for scheduling/power, HuC for media offload, and GSC for newer authentication flows.
  • Red Bear now has a bounded Intel DMC startup manifest/preload path for the first supported Intel device families, but Intel need_firmware must still stay out of the canonical GPU quirk set until the broader Intel runtime policy surface is real and validated.
  • AMD device-specific GPU quirk growth remains review-gated on explicit Linux-backed evidence.
  • Intel GPU quirk expansion is deferred until Red Bear has a real Intel-side firmware/runtime policy surface that can honestly consume additional flags.

Wave 2 — Unify PCI quirk semantics

Task 2.1: Eliminate semantic drift between pcid-spawner and redox-driver-sysOBSOLETE / superseded

Task 2.1 obsoleted 2026-07-24: pcid-spawner was retired and removed from the tree as part of the driver-manager cutover. The drift-elimination pair no longer exists. The quirks-consumption model (Task 2.2+) is now the live surface.

Constraint:

  • Historical note only: when this task was written, pcid-spawner was upstream-owned base code, so convergence would have required upstream-base changes carried by Red Bear patching.

Best approach (historical):

  • make pcid-spawner consume generated/shared quirk data instead of hand-maintained duplicated tables and flag maps.

Preferred implementation options at the time, in order:

  1. Shared generated data module used by both redox-driver-sys and pcid-spawner.
  2. Protocol extension where a single canonical broker calculates quirk bits and hands them to drivers.
  3. Keep duplication only as a short-term fallback if generation is not yet practical.

Do not continue manually editing two separate PCI quirk engines long-term. That risk is now removed by deleting one side of the pair during the cutover.

Success criteria (historical):

  • one authoritative source for compiled PCI quirk entries and flag name mapping,
  • subsystem matching behavior aligned,
  • explicit decision on whether DMI was brokered by pcid-spawner or left to driver-local lookup.

QA (historical):

  • compare quirk outputs for the same synthetic PCI info through both paths,
  • verify PCI_QUIRK_FLAGS emitted by pcid-spawner matched canonical lookup for representative devices.

Task 2.2: Decide DMI ownership clearly

Decision needed:

  • either the former pcid-spawner path would have become DMI-aware and brokered the final PCI quirk bitmask,
  • or the broker would have remained PCI/TOML-only and DMI stayed driver-local in redox-driver-sys consumers.

Recommendation:

  • near term: document the split clearly,
  • medium term: move toward one brokered result for upstream base drivers.

QA:

  • one design note added to the docs explaining the chosen ownership model.

Wave 3 — Real driver integration

Task 3.1: Integrate USB device quirks in xhcid DONE

Verified complete (see QUIRKS-SYSTEM.md § driver consumption): xhcid calls lookup_usb_quirks() during enumeration and acts on 13 device-level flags in concrete branches — NO_STRING_FETCH, BAD_DESCRIPTOR, RESET_DELAY, HUB_SLOW_RESET, NO_BOS, SHORT_SET_ADDR_TIMEOUT, FORCE_ONE_CONFIG, HONOR_BNUMINTERFACES, DELAY_CTRL_MSG, NO_SET_CONFIG, NO_SET_INTF, NEED_RESET, NO_SUSPEND — covering descriptor reads, SetConfiguration gating, LPM/suspend gating, and reset paths. The success criteria below are all met.

Additionally, since 2026-07-18 (P2-A/P2-B) the controller side is integrated too: xhcid consumes the canonical 51-flag XhciControllerQuirkFlags table from redox-driver-sys (thin re-export shim), including BROKEN_MSI inside get_int_method and HW_LPM_DISABLE in the hw_lpm_support computation.

Original task text (kept for reference):

Best integration points:

  • after device descriptor read,
  • before SetConfiguration,
  • before enabling LPM/U1/U2 or USB3-specific behavior,
  • after reset paths where extra delay or reset-after-probe is needed.

Minimum runtime behaviors to wire first:

  • NO_SET_CONFIG
  • NEED_RESET
  • NO_LPM
  • NO_U1U2
  • BAD_DESCRIPTOR

Success criteria:

  • xhcid calls lookup_usb_quirks() for enumerated devices,
  • these flags alter runtime behavior in concrete branches,
  • tooling and runtime logic agree on the same device-level quirks.

QA:

  • unit/integration tests for selector logic where possible,
  • manual logging proof that a known vendor/product entry triggers the expected path.

Task 3.2: Consume linux-kpi quirks in amdgpu

Best integration points:

  • probe path,
  • IRQ mode selection,
  • firmware gating,
  • memory/power-management setup.

First flags to consume:

  • NO_MSI
  • NO_MSIX
  • NEED_FIRMWARE
  • NO_ASPM
  • NEED_IOMMU

Success criteria:

  • at least one real C driver uses pci_has_quirk() in production code,
  • runtime logs show quirk-informed decision making.

Current state:

  • local/recipes/gpu/amdgpu/source/amdgpu_redox_main.c now queries linux-kpi PCI quirks in the real Redox runtime path,
  • logs now show the active quirk bitmask plus the implied IRQ fallback policy,
  • firmware policy has been pulled back to the Rust-side driver boundary so the C backend does not re-enforce NEED_FIRMWARE independently.

QA:

  • grep shows real in-tree call sites in amdgpu,
  • build passes for linux-kpi + amdgpu recipe path.

Task 3.3: Keep firmware policy in drivers, not firmware-loader

Action:

  • when a driver has NEED_FIRMWARE, the driver should gate initialization until the firmware load succeeds.
  • firmware-loader remains a transport/provider only.

Success criteria:

  • docs stop implying that firmware-loader interprets quirk flags,
  • driver init paths own the policy decision.

QA:

  • driver code path shows firmware gating tied to quirks or explicit device rules.

Current state:

  • local/recipes/gpu/redox-drm/source/src/drivers/intel/mod.rs now reads the canonical info.quirks() policy during init, rejects DISABLE_ACCEL, and explicitly warns if NEED_FIRMWARE appears on Intel instead of silently ignoring quirk policy.
  • local/recipes/gpu/redox-drm/source/src/main.rs now makes firmware preload expectations explicit at the Rust-side driver boundary, reports whether preload is quirk-required, and summarizes missing candidate blobs when preload cannot satisfy the current policy.
  • local/recipes/gpu/amdgpu/source/amdgpu_redox_main.c still consumes linux-kpi quirks for runtime expectations, but it no longer owns the final firmware gating decision.

Wave 4 — DMI completion

Task 4.1: DMI TOML runtime loading

Scope:

  • toml_loader.rs parses [[dmi_system_quirk]],
  • matching uses live DMI info served by acpid at /scheme/acpi/dmi,
  • resulting PCI quirk overrides flow through the canonical redox-driver-sys DMI path.

Success criteria:

  • 50-system.toml entries are no longer config-only,
  • runtime DMI TOML behavior is testable and documented through the live acpid DMI scheme.

QA:

  • tests for TOML parsing,
  • one mock DMI input path proving a TOML DMI rule applies flags.

Task 4.2: ACPI blacklist/override layer

Current state:

  • acpid now supports narrow [[acpi_table_quirk]] skip rules, optionally gated by the same DMI-style match.* fields used elsewhere.
  • The implementation is intentionally limited to table suppression during ACPI table load; it is not a broad AML patching or firmware replacement framework.

Suggested Immediate Deliverables

If work resumes right away, the next concrete implementation sequence should be:

  1. clean remaining stale quirks docs/reporting text done 2026-07-18 (this pass)
  2. write a design note for canonical PCI quirk ownership,
  3. integrate lookup_usb_quirks() into xhcid enumeration/configuration done (Task 3.1)
  4. add first real pci_has_quirk() use in amdgpu done (Task 3.2 — amdgpu consumes linux-kpi quirk flags in its Redox init path)
  5. validate and extend shipped DMI TOML coverage as needed.

Exit Criteria For The Next Quirks Milestone

The next milestone is complete when all are true:

  • OBSOLETED 2026-07-24: pcid-spawner retired/removed during driver-manager cutover, so this drift pair no longer exists,
  • xhcid consumes USB device quirks at runtime met (13 device flags; plus the 51-flag controller table since 2026-07-18),
  • at least one real C driver consumes linux-kpi quirks met (amdgpu),
  • docs distinguish clearly between reporting, infrastructure, and true runtime behavior,
  • DMI TOML entries are either runtime-applied or removed from shipped config.