Skip to content

chore: rebase aurora-wip and merge into integration - #131

Closed
DjDeveloperr wants to merge 569 commits into
omacom:integration/aurorafrom
aurora-silicon:aurora-wip-rebase
Closed

DjDeveloperr wants to merge 569 commits into
omacom:integration/aurorafrom
aurora-silicon:aurora-wip-rebase

Conversation

@DjDeveloperr

Copy link
Copy Markdown
Collaborator

mechanical change mostly

works on

  • neo
  • m1 mini
  • m2 pro

RyanTheTide and others added 30 commits October 16, 2026 00:17
…itted

When btrfs_do_readpage() adds blocks of a compressed extent to a bio it
drops its reference on the extent map, and btrfs_submit_compressed_read()
looks the extent map up again in the inode's extent map tree, by the
bio's file offset, to learn where the extent starts in the file and how
it is compressed. If the lookup misses, the whole bio fails with -EIO.

The lookup can miss. The bio is submitted when a later block does not
fit it, or at the end of the read_folio/readahead call after the range
has been unlocked, and the extent map shrinker can remove the extent map
from the tree in between: apart from pinned extent maps it drops
whatever it finds, regardless of locked io tree ranges or of references
held by readers. Under memory pressure, in particular in a memory cgroup
at its limit whose reclaim keeps invoking the fs shrinker, this shows up
as spurious -EIO on reads of compressed files, and on buffered writes
that have to read a partial folio first.

Have the bio_ctrl hold a reference on the extent map of the compressed
extent its bio reads, handed over by btrfs_do_readpage() once the block
is in the bio and dropped once the bio is submitted, and pass it to
btrfs_submit_compressed_read() instead of looking it up again.

Fixes: 956a17d ("btrfs: add a shrinker for extent maps")
Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
mt_service() drains the RX rings and retires TX descriptors first and
only then writes the causes it read back to the interrupt status
register. A completion that the device posts after a ring has been
drained but before that write sets a status bit that the write clears
again. Its descriptor then waits, unserviced, until some unrelated
interrupt arrives; for a command reply that can be the full command
timeout.

Acknowledge the causes, then service the rings, as other MediaTek PCIe
drivers do. Read the status register back after the write so that the
acknowledgment has reached the device, and the descriptors written
before it are visible, before the rings are read. A completion that
arrives while the rings are being serviced now leaves its status bit
set, and the device interrupts again once the mask is restored.

Fixes: 8709ef5 ("wifi: add existing J700 MT7932 fullmac implementation")
Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
A firmware boot that fails after the first handshake unwinds stage by
stage: it frees the channel table and the extra heap, and only then
stops the coprocessor and powers its domains down. Stage 2 also frees
the extra heap itself when the second handshake does not come. The
firmware is running from the first handshake on, so it can still access
the heap while its pages are released; the pages are unmapped from the
DART first, so a late access faults instead of reaching freed memory,
but it should not happen at all.

isp_firmware_shutdown() already stops the coprocessor before freeing
anything. Share that order with the failed boot: stop the coprocessor
and power its domains down, then free the channel table, the extra heap
and the surfaces the firmware requested. Stage 2 leaves the heap to the
caller, and the heap pointer is cleared once it has been freed, so an
unwind that runs before the heap is allocated has nothing to free.

The runtime PM reference of the ISP and the references on its other
power domains are dropped as before.

Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
apple_isp_power_down_domains() reports a failed runtime PM put of an ISP
power domain as a failure to power it up, which points at the wrong
transition when a domain stays on after the firmware has stopped.

Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The driver state, which embeds the video device, its queue and lock, the
control handler and the media device, is allocated with devm_kzalloc()
and freed as soon as the driver is unbound. A process that still has the
video device open at unbind keeps a reference to the video device, and
when it closes the file, vb2_fop_release() takes the queue lock and
v4l2_fh_release() walks the file handle lists, all in freed memory. A
control event subscription also reaches the freed control handler.

Tie the state to the v4l2_device reference count as V4L2 drivers do:
allocate it with kzalloc(), free it, the control handler and the media
device from the v4l2_device release callback, and drop the driver's own
reference at the end of remove. The video device holds the other one
while it is registered or open, so the state lives until the last file
is closed. Before the video device is registered nothing else can reach
the state, so a failed probe still frees it directly.

Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
mt_net_xmit() writes the TX0 CPU index after every packet, even when
the stack is handing over a burst. Each write is an uncached MMIO store
across the PCIe link, and each makes the device fetch descriptors for
a single packet.

Use netdev_xmit_more() to publish a burst with one doorbell write: ring
it when the stack has nothing more queued, when the queue has just
stopped, and at least every 64 packets so that the device starts on a
long burst early. Descriptors stay published in order behind the
doorbell, and the TX0 accounting is unchanged.

The queue can also stop from outside ndo_start_xmit(), when the access
point goes absent or the link goes down, which ends a burst early. Ring
the doorbell in those paths too, before the connection teardown waits
for TX0 to drain, and on every interrupt, so that no published
descriptor waits behind a doorbell that is never written.

Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
… queue

A regulatory change stops the data queue from the cfg80211 notifier,
outside ndo_start_xmit() and outside data_lock. If that lands in the
middle of a burst, the TX0 descriptors the burst already published stay
behind the doorbell until the next interrupt rings it.

Ring the doorbell there as well, under data_lock nested inside
response_lock in the same order as the receive path, so that every path
that stops the queue from outside ndo_start_xmit() hands the device what
it already holds.

Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The enrol and verify work items report their result and wake the poller
before they return and clear the session's busy marker. After a cancel or
a close they stop only once the capture loop notices. An ENROL_START or
VERIFY_START in that window, or an open right after a close, is refused
with EBUSY. Userspace cannot tell that from a device in use by someone
else: libfprint reports a protocol error, and fprintd turns it into
verify-disconnected. fprintd starts a match again as soon as a capture is
reported unusable, so it lands in that window.

Hold such an open or start until the work item has stopped, for as long
as a capture may take to drain before sleep. Only an open with no other
opener, or a start whose last operation has ended, waits; a start while
an operation is still running is refused at once, as before. If the work
item has not stopped in time, the caller is refused as before, and the
driver logs it.

Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
apple_pmgr_ps_set() writes the new target state and polls the actual
state for 100 us. When the poll times out it logs and returns the error,
but leaves the new target requested, and a power-on also sets
AUTO_ENABLE. genpd then keeps the domain in its previous state: off after
a failed ->power_on(), on after a failed ->power_off(). From then on the
register and genpd disagree, and genpd does not write the domain again
until its next transition.

On T8140 (J700), rebinding the ISP after an unbind fails because the
resident firmware does not boot a second time, and the CPU core domain
stops short of ACTIVE:

  [  760.990199] apple-pmgr-pwrstate 300700000.power-management:power-controller@4008: PS isp_cpu_core0: Failed to reach power state 0xf (requested 0xf00000f, now: 0xf000b4f)

genpd and the ISP driver unwind as if the domain were off, but its
register keeps requesting ACTIVE with auto-PM enabled, so the core sits
clock-gated instead of power-gated until the next boot. A failed
power-off is the opposite case: genpd still treats the domain as on and
will not power it on again for its next consumer, while the register
asks for it to be power-gated.

Follow a failed transition with the opposite one: power the domain back
off after a failed power-on, and back on after a failed power-off. Both
are the normal sequences, so a power-off still sets the force-disable and
force-reset bits first, and the domain is down before genpd powers off
its parents.

genpd ignores power-on errors in the noirq and syscore phases of system
sleep (genpd_sync_power_on()) and records the domain as on there, so
powering it back off would leave a domain off that genpd and its
consumers believe is on. Slow domains do time out there: the gfx domain
misses the poll window on resume from s2idle on M1 Pro (t6000), and did
on T8140 in genpd's noirq resume before it became always-on, then
reaches ACTIVE, and the GPU keeps working. The PM core runs those phases
between the suspend_late and resume_early callbacks of every device. Add
these callbacks to mark the window and keep requesting the domain on
inside it, as before. The probe-time power-on of an always-on domain
also keeps the current behaviour, as genpd never powers those domains.

Transitions that succeed are unchanged.

Fixes: 6df9d38 ("soc: apple: Add driver for Apple PMGR power state controls")
Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
load-driver tries to seal and unseal a trusted key 300 times, 0.1 s
apart, then waits as long again for /dev/sep-bio. On J700 the enclave's
key store arrives around 43 s after boot, and the driver itself waits up
to 90 s for it, so the loader can give up before Touch ID comes up. The
service then fails, and fprintd, which requires it, fails with it.

Measure the waits in seconds of uptime rather than in attempts, wait up
to 120 s for the trusted key and 60 s for the device, and let
AURORA_SEP_READY_TIMEOUT and AURORA_SEP_DEVICE_TIMEOUT override them. Log
why the loader gives up and how long each step took, so a slow boot can
be told from a broken one.

Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
A manual install leaves libfprint under /usr/local, where fprintd only
finds it through a library path drop-in, and puts the loader and the units
under /usr/local and /etc, where no package manager tracks them.

Add packaging for the distributions the driver runs on:

 - packaging/fedora/build.sh rebuilds the release's own libfprint source
   package with the aurora patch added and an ".aurora1" release suffix,
   so it replaces the distribution's library in place. It also builds
   aurora-sep.spec.
 - packaging/arch has libfprint-aurora, which provides and conflicts with
   libfprint, and aurora-sep, for Arch Linux and Arch Linux ARM.
 - aurora-sep installs the loader, its service pointed at the packaged
   loader, and the fprintd policy as a drop-in under /usr/lib. On Fedora
   a preset enables the service at boot when the package is first
   installed; Arch leaves that to the user.

The PKGBUILDs take their local sources through links into this tree, and
a test checks their checksums against it. The README gives the build,
install and rollback steps.

Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The first open of /dev/sep-bio activates Touch ID: the driver restores
the enrolled fingerprints from the enclave before the open returns, which
takes a few seconds. That open is fprintd's first probe of the reader,
so the first fingerprint request after boot, at the lock screen or for
sudo, waits for the restore.

Add aurora-sep-ready.service, which opens the device once after the
loader and before fprintd, and pull it in from aurora-sep.service. It
ends as soon as the open returns; a failed open is only logged, and a
job timeout stops anything ordered after it from waiting beyond 90 s
after boot. Install it in the Fedora and Arch packages.

Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
fprintd exits after 30 s without a client, and each new start probes the
reader again. The login and lock screens ask fprintd for the reader as
they come up, so they wait for that start, and for a reader that is
still being probed.

Add a drop-in that runs fprintd with --no-timeout. Its path differs
between distributions, so the drop-in is a template: the packages fill
it in and check it against fprintd's own unit at build time.

Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
On Macs with Touch ID the sensor is the power button. Touching it to
authenticate goes to the enclave and never produces a key event, but
pressing it does, and logind cannot tell a press meant for the sensor
from a press meant for the button. Its default action is to power off,
so pressing while authenticating outside GNOME ends the session.

Add a logind drop-in that suspends on a short press instead: a press
while authenticating then costs nothing, and the next press wakes the
machine. Holding the button for 5 s powers off cleanly. GNOME sessions
and the GDM login screen take a short press over and suspend by default
already, so this only changes consoles and other desktops.

Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
GNOME Shell 51 connects the greeter's fingerprint reader only when it
re-authenticates a session that is already running, so the login screen
never offers fingerprint, whatever org.gnome.login-screen says. That is
deliberate: a fingerprint cannot unlock the login keyring, and the first
application that wants a stored secret then asks for the password. Some
people want fingerprint login anyway.

Add aurora-sep-greeter-fingerprint.service, off by default. At boot it
takes the greeter source file that holds the check from the installed
GNOME Shell, drops the check, and serves the copy to the login screen's
shell alone, through a GResource overlay set in a runtime drop-in for
org.gnome.Shell@gdm.service. When the check is not exactly as expected,
it changes nothing, so a GNOME update that moves it leaves the login
screen as GNOME ships it. enable-fingerprint-authentication still turns
fingerprint off.

The login screen asks fprintd for the reader once, as it comes up, and
offers no fingerprint until the user is selected again if Touch ID is
not up yet. The unit therefore also orders the display manager after
aurora-sep-ready.service. That holds the login screen back by a few
seconds on a healthy boot, and up to 90 s after boot when the enclave is
slow, which only makes sense when it offers fingerprint, so both come
with the one switch. It needs gresource, which the packages suggest
rather than require.

Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
libfprint with the aurora driver, as a source patch and as Fedora and
Arch Linux packages, is now maintained in
https://github.com/aurora-silicon/aurora-sep-userspace. Two copies of
the userspace driver, built from different trees with colliding package
releases, would drift apart.

Drop the libfprint patch, the Arch libfprint-aurora package and the
libfprint rebuild from the Fedora build script. This tree keeps the
kernel side's userspace pieces: the loader, its services, the fprintd
policy and the desktop integration, packaged as aurora-sep. The README
and the package descriptions point to aurora-sep-userspace for the
driver.

Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
defconfig, asahi.config and j700-radio.config give a J700 kernel that
boots, but not the configuration it is tested with. The boot path
(NVMe/ANS, btrfs, the DockChannel keyboard and trackpad, SMC, SPMI, the
USB-C PHY and Type-C) ends up modular and so depends on what the
initramfs carries, the per-process 4K user page mode stays off, and
several J700 driver choices differ.

Add j700.config, to be merged after j700-radio.config, with each group
commented with its reason, and cover the J700 fragments with one
MAINTAINERS pattern. Together with the device-parity fragment added
next, the fragments reproduce the tested configuration.

Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
The J700 configuration lacks much of what a general-purpose distribution
kernel provides: game controllers and other USB or Bluetooth HID devices,
most USB-serial and USB network adapters, filesystems found on removable
media, dm-crypt, VPN protocols, the nftables and xtables extensions used
by firewall and container tools, and binfmt_misc.

Add j700-device-parity.config, to be merged after j700.config. It takes
the Fedora Asahi Remix 44 kernel configuration as the reference and
enables what can attach to or run on the J700, mostly as modules. It
changes no option that the other fragments set. Options that change
scheduler, memory, security or boot behaviour are left out.

Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Since "acknowledge interrupts before servicing the rings", mt_service()
clears the interrupt causes it is about to service, RX0 included, before
it drains the rings, and restores the interrupt mask after the last ring.

The RAM-config acknowledgment in mt_rx_drain() still clears RX0's status
bit and rewrites the mask in the middle of the drain. The status write
can clear the bit of an RX0 completion that arrived after the up-front
acknowledgment, so the device no longer shows work that is still
pending, and the unmask lets the interrupt fire again while the rings
are still being serviced, with the fixed IRQ_MASK rather than
m->irq_mask.

Clear only the acknowledgment's other two status bits there, and leave
the mask to mt_service(). The diagnostic drain on a command timeout runs
with the interrupt line disabled; a bit it leaves set is serviced once
the line is enabled again.

Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
When a retained reference prevents discarding a clean lazyfree slot,
try_to_unmap_subpage() restores the PTE but then marks the native folio
swap-backed. The extra reference alone does not cancel MADV_FREE, so this
can prevent reclaim without swap and cause unnecessary swap traffic.

Leave the classification unchanged after restoring a clean PTE. Dirty
entries still cancel lazyfree and follow the existing swap-backed path.
Extend the lazyfree KUnit case to retain a reader after whole-folio advice,
check the clean classification, then release the reader and reclaim.

The expanded test passes on 16K and 64K KASAN guests without warnings.

Signed-off-by: Diljit Singh <hey@djdev.me>
(cherry picked from commit e9a25aa)
The IOMMUFD harness selects IOMMU_PT even when IOMMU_SUPPORT is disabled,
excluding the page allocation implementation its selected code requires.
The boolean VFIO harness selectors can also force VFIO built-in while
IOMMUFD is modular, bypassing VFIO's own tristate constraint.

Require IOMMU_SUPPORT for the IOMMUFD harness. Require non-modular IOMMUFD
for both VFIO selectors, including the ioctl selector that selects the
accounting harness. Built-in and disabled IOMMUFD configurations remain
available for VFIO testing.

Six before/after configuration checks cover the invalid combinations and
the retained valid selections. Integrated 16K/64K KASAN images build.

Signed-off-by: Diljit Singh <hey@djdev.me>
(cherry picked from commit cf3e988)
contpte_try_unfold_partial() checks its exclusive endpoint with
contpte_align_down(). That helper derives granule geometry from the PTE's
backing metadata, but ptep + nr can already lie beyond that backing.

Use the mm's contiguous-group size to test alignment at both ends. This
preserves partial-group unfolding while avoiding a metadata lookup for a
pointer that need not identify an allocated page-table entry.

16K/64K KASAN images build and their existing native/4K contiguous-PTE
functional tests pass without warnings. The endpoint defect is established
by source inspection; no runtime reproduction is claimed.

Signed-off-by: Diljit Singh <hey@djdev.me>
(cherry picked from commit f6e776e)
perf_get_pgtable_size() starts with an mm-aware PGD lookup but continues
with native table offsets and leaf sizes. A smaller userspace granule can
therefore select an unrelated entry or report the native page size.

Add mm-aware lockless offset and leaf-size helpers with native fallbacks.
Use the target mm throughout perf's walk, including runtime folding and
contiguous mappings, while preserving the existing interrupt exclusion
and descriptor-snapshot semantics.

Expose the walker only for KUnit testing and cover ordinary mapped and
unmapped addresses across table levels. Extend contiguous-PTE fixtures to
check perf's reported size and cover 16K userspace on a 64K kernel.

The tests pass in 16K/64K KASAN guests for native, 4K and supported 16K
userspace granules. An x86_64 perf-object build checks the native fallbacks.
Hardware PMU event delivery was not tested.

Signed-off-by: Diljit Singh <hey@djdev.me>
(cherry picked from commit 4538d92)
The smaller-page orig_page_is_identical() path compares bytes directly,
bypassing the architecture checks used by pages_identical(). On arm64,
byte equality does not make distinct tagged ranges interchangeable.

Add memcmp_pages_range() with a generic mapped-byte implementation and
an arm64 implementation retaining the existing MTE policy. Distinct
tagged ranges remain non-identical, including different offsets within
one page. Keep full-page comparison as the zero-offset full-length case,
and use the range API for the smaller-page uprobe comparison.

Add direct tests for offset ranges, bytes outside the compared range,
unequal contents, empty ranges and tagged-range identity. These and the
existing ownership tests pass in 16K/64K KASAN guests. The generic util and
uprobe objects also compile for x86. Actual uprobe removal with private
tag state was not runtime reproduced.

Signed-off-by: Diljit Singh <hey@djdev.me>
(cherry picked from commit 0c0dccf)
Size MTE tag segments from dumped bytes rather than a truncated native
page count. For alternative userspace geometry, retain the selected
fragment and save only its tags, preserving the physical subpage offset.
Keep the native page path and share its assembly packing loop through a
bounded tag-range helper.

Add a disposable-guest core-file fixture checking actual ELF data and
tag headers and bytes for split read-only, sparse and excluded mappings.
Native and 4K processes pass on a 16K KASAN kernel; native, 4K and 16K
processes pass on a 64K KASAN kernel. These are emulated MTE checks,
not physical-hardware validation.

Signed-off-by: Diljit Singh <hey@djdev.me>
(cherry picked from commit 886de71)
A VMA can retain vm_file while its fault callback returns independent
pages. Use cache-indexed fault installation only when the returned folio
belongs to that file mapping; otherwise preserve the callback page and
its requested subpage offset. Allow ordinary non-anonymous fragment
references to follow these mappings without requiring page-cache membership.
Keep permission checks and private read-pin COW rules unchanged.

Add native, 4K and supported 16K callback tests with reversed backing
pages, nonzero offsets and remote reads. They pass on 16K/64K KASAN
guests, along with existing file-fragment lifetime/COW and special-mapping
tests. This tests the callback contract, not a physical usbmon device.

Signed-off-by: Diljit Singh <hey@djdev.me>
(cherry picked from commit 09dae19)
walk_page_mapping() truncates a VMA length to native pages and ignores
its subpage file offset. Short mappings can disappear from the walk and
partial first/last native pages can produce incorrect virtual bounds.

Use the existing byte-offset translation and last-index helpers to clip
the requested native file indices to the VMA. Handle an empty request and
reject an overflowing index interval before the interval-tree walk.

Validated native and smaller-granule walks over short mappings and partial
first/last pages in 16K/64K KASAN guests. The temporary fixture and results
remain in the local validation records instead of adding another permanent
arm64 test block. The generic x86 pagewalk object also compiles.

Signed-off-by: Diljit Singh <hey@djdev.me>
(cherry picked from commit 0a08567)
A mapping can be shorter than a native page when its MM uses a smaller
granule. Count a partial final native page in __simple_ioremap_prep()
instead of truncating it away. Native-aligned mappings retain their
existing calculation, and the quotient/remainder form avoids a rounding
addition overflow.

Both 16K/64K KASAN kernels build and pass the existing PFN-remap suite;
the x86 memory object also builds. No device-boundary reproducer was run.
This bounds correction does not qualify every device offset interface.

Signed-off-by: Diljit Singh <hey@djdev.me>
(cherry picked from commit d4e50b5)
The legacy remote-page interface cannot represent smaller-granule backing.
Use the stable-VMA fragment interface for alternative MMs, take the actual
physical offset from the returned record, and bound each transfer by its
length. Release the same retained fragment and dirty its ownership record
on writes. Preserve the native page path and existing ptrace permission
and partial-transfer semantics.

Reused the local core-file fixture to validate own-child ptrace tag reads,
writes and restoration across three differently tagged mappings, including
a read-only mapping. Native/4K cases pass in a 16K KASAN guest and
native/4K/16K cases pass in a 64K guest; resulting core files also pass.
The feature-disabled native MTE object builds. No additional submitted
test program is introduced, and physical MTE hardware remains untested.

Signed-off-by: Diljit Singh <hey@djdev.me>
(cherry picked from commit f41afd8)
Build the SVA context descriptor and invalidation geometry from the bound
MM rather than PAGE_SIZE. Check the target device's granule support at
allocation and attachment, and record the same granule in the domain so
range invalidation commands agree with the CPU page-table geometry.

Extend the existing SVA descriptor transition test to cover the enabled
alternative granules. The existing 25-case SMMUv3 suite passes in both
16K and 64K KASAN guests; native feature-disabled SVA and test objects also
compile. Actual SVA device DMA and invalidation delivery remain untested.
The driver's existing global native-granule capability prerequisite is
preserved.

Signed-off-by: Diljit Singh <hey@djdev.me>
(cherry picked from commit 4ccea57)
RyanTheTide and others added 26 commits October 16, 2026 00:18
On a profile with a nonce session, every registration identifies the
sensor first: PLATFORM_IDENTITY, then REGISTER_SENSOR. The enclave state
is only cleared once the bring-up stage reads ESTABLISHED. If a
registration fails after REGISTER_SENSOR was accepted, the stage stays
FRESH while the enclave holds the partial registration. Each retry then
identified the sensor again without clearing it.

On boot d1962b3a, all 42 retries over 800 s failed that way, and Touch
ID stayed unusable until a reboot.

Count the enclave as holding the sensor once REGISTER_SENSOR has been
submitted, answered or not, since a lost or late reply does not mean the
enclave did not act on it. Clear its sensor state before registering
again whenever it may hold one.
Restarting the bring-up from FRESH does not change that, because only
CLEAR_STATE empties the enclave. Profiles without a nonce session keep
their flow.

The decision is a plain function, with KUnit tests for the first
registration, the retry after a partial one, re-registration and the
other profiles.

Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
A read of a sensor frame can fail on the bus in two ways. The bytes come
back garbled, or the sensor does not take the frame. Either way it keeps
offering the frame at the same length.

Boot 0874c215 showed both: the nonce read failed its CRC, and afterwards
the sensor still offered the complete 43-byte nonce frame with a valid
CRC. On boot 7f0c01be the serial read succeeded but the serial frame was
not taken. The nonce command that followed then waited behind it until
it timed out.

Check the CRC of the serial, nonce, session and challenge replies. The
session and challenge replies were relayed unchecked, but they carry the
same CRC; it held on every boot measured. The calibration module reply
keeps its own handling. When a reply fails its CRC and the sensor still
offers a frame of that length, read it again, at most twice. Before a
command that expects a reply, take any stale frame the sensor still
offers, so the reply is not queued behind it. Two such frames at most:
if one is still on offer after that, fail the step rather than send the
command, because a read does not prove the sensor took the frame.
Report both, since either means an exchange went wrong on the bus.

Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
When the bring-up at attach failed, nothing retried it until the first
verify, minutes later. That verify was then refused before it touched
the sensor, and gdm offered no fingerprint at login.

A bring-up that fails on the bus leaves nothing a new attempt cannot
undo. Each attempt power-cycles the sensor and, after a failed one,
clears the enclave partial registration first. That is the same path
every verify takes, and it has never failed on an idle machine. Try up
to three times at attach, logging each failed attempt. A power cycle that
fails ends the attempt before registration: a sensor that was not reset
may still hold the session of the attempt before.

Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
An SBIO reply is matched to the waiting exchange by opcode alone, and an
error marker is matched before the opcode is checked. The receive work
reads a reply before it takes the reassembly lock. If the requester
times out in between and a retry begins the same opcode, the late reply
completes the retry with the earlier attempt result. Bring-up now
retries the registration, so the window is real.

Number the exchanges. The receive work samples the number before it
reads a reply and passes it with the chunk; a chunk sampled before the
current exchange began is dropped. Replies to the current exchange can
only arrive after it began, since its request is sent after that.

Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Store::open() initialises the host-state store whenever the file is
shorter than the store or its header does not match: it zeroes all 72
blocks and writes an empty superblock. That was by design while the
store held records that a seed import restored after a reset. Since the
SEP's anti-replay records moved to the shared xART gigalocker, though,
the file holds Linux state that nothing regenerates: the Touch ID
identity index and the lockout state. A truncated file, a damaged header
or a store in a format this driver does not know is now erased on the
next probe, together with the evidence needed to recover it.

Initialise the store only when this open created the file and it is
empty, and refuse an existing file that is short or has an unknown
header without writing to it. That includes what an interrupted creation
leaves: in general the driver cannot tell it from a damaged store, so
the decision is the administrator's. The log line says when the file is
empty or all zero: that is all an interrupted creation leaves, and such
a file holds nothing to keep. Creating a new store is logged too: on a
machine that has used Touch ID it means the old store was removed.

Opening also has two ways to lose or leak a record of a store with a
valid header. A pending write intent that names a used block makes it
free that block, discarding the committed record, and a record length
beyond its 32 KiB block makes read() allocate up to 4 GiB and return the
following blocks. No writer of the format produces either; refuse them
as well instead of acting on them.

The on-disk format does not change.

Fixes: 7165ae9 ("soc: apple: use shared xART gigalocker")
Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
Replaying aurora-wip onto integration/aurora carries each aurora-wip change
only where it applies to integration's code. These files still differ from
the resolved merge of the two branches, so bring them to it.

Integration's driver is the base. It covers the M1/M2 firmware, the M3
(G15S) runtime and the J613 HAL200 runtime. The G17P runtime from
aurora-wip joins it as another backend of the DRM-facing GPU interface,
and the shared files select the G17 paths per device or VM, so M1/M2/M3
behaviour does not change. The g17/ code is aurora-wip's.

The UAPI keeps integration's numbers and layouts, which existing M3
userspace depends on. The G17P additions move past them:
- feature bits 10 to 15;
- the render and compute command fields after integration's 64-byte
  timestamp-copy arrays.

G17P rejects nonzero timestamp copies. Neo Mesa must use the matching
header.

Assisted-by: LLM
Signed-off-by: Diljit Singh <hey@djdev.me>
Replaying aurora-wip onto integration/aurora carries each aurora-wip change
only where it applies to integration's code. These files still differ from
the resolved merge of the two branches, so bring them to it.

Integration's driver is the base, including its Type-C fabric, mode
catalog and M3 display work.

The H17-generation display support from aurora-wip sits behind the
firmware the DCP runs: the T8140 internal and external DCPs and the T8142
DCP. It covers the external display lifecycle over AFKV2, DCPLink, the
H17P iomfb template, the parser additions and the DPTX service. The
H17P-only files are aurora-wip's.

The driver binds the T8140 and T8142 display subsystems and DCPs again.

Assisted-by: LLM
Signed-off-by: Diljit Singh <hey@djdev.me>
Replaying aurora-wip onto integration/aurora carries each aurora-wip change
only where it applies to integration's code. These files still differ from
the resolved merge of the two branches, so bring them to it.

The DCP display routes on T8140 and T8142 register prepare, finish and
commit callbacks, so that the DCP lets go before the PHY changes mode.
Run those phases in typec_mux_set() for the mux devices that register
them, with abort in reverse on failure. Devices with only a set callback
behave as before.

On T8140 and T8142 the CD321x driver keeps aurora-wip's error meaning:
-ENOSPC means the display is taken and -EBUSY is retried. Integration's
DP status interrupt and its HPD rules stay off on those SoCs.

Assisted-by: LLM
Signed-off-by: Diljit Singh <hey@djdev.me>
Replaying aurora-wip onto integration/aurora carries each aurora-wip change
only where it applies to integration's code. These files still differ from
the resolved merge of the two branches, so bring them to it.

Keep integration's handling of an adopted co-processor that has crashed
and its warning when the shared buffers of an unstopped co-processor are
retained.

aurora-wip answers no OSLog notification 2 to 5: the T8140 and T8142
co-processors send them during normal operation and keep running without
a reply, which is how the J700 and M5 stacks were tested. integration
acknowledges type 2 so that the M1/M2/M3 DCP can drain its log transport
before sleep. Keep integration's behaviour, and leave the notifications
unanswered on T8140 and T8142.

Assisted-by: LLM
Signed-off-by: Diljit Singh <hey@djdev.me>
Replaying aurora-wip onto integration/aurora carries each aurora-wip change
only where it applies to integration's code. These files still differ from
the resolved merge of the two branches, so bring them to it.

integration's SEP driver is the base: its enrolment budget and stages,
Catacomb save on deletion, entropy requests kept out of system sleep, the
M2 Pro/Max key store chosen by system firmware, the T8122 profile and the
private-key round trip for trusted keys. The J700 work from aurora-wip
sits on top: authenticated sensor sessions and their persistence, capture
draining and binding, serialized SBIO exchanges, and the sensor SPI mode
and enable GPIO taken from the board. Remove the older duplicate profile
and key-store definitions that the replay left behind.

The aurora-wip defaults stay: the module builds by default and loads
through its OF alias, with xART writes and first-boot identity
provisioning enabled. Update the documentation to say so, and refresh the
Arch package checksums of the documents it installs. The Neo GPU
environment helper checks the asahi and apple-drm drivers again.

Assisted-by: LLM
Signed-off-by: Diljit Singh <hey@djdev.me>
Replaying aurora-wip onto integration/aurora carries each aurora-wip change
only where it applies to integration's code. These files still differ from
the resolved merge of the two branches, so bring them to it.

integration's ATC PHY, Thunderbolt and PCIe host code is the base,
including its M3 PIPE parking, s2idle port power-off and tunnel
cold-initialisation. The J700 DisplayPort tunables, AUX power, lane
routing and main-link training, the J700 radio bootstrap and the M5
controller support from aurora-wip apply only on those SoCs. Drop the
aurora-wip variants of shared code that integration's versions replace.

The J700 fixed-hub USB controller is torn down without running the host
and core exit twice.

Assisted-by: LLM
Signed-off-by: Diljit Singh <hey@djdev.me>
Replaying aurora-wip onto integration/aurora carries each aurora-wip change
only where it applies to integration's code. These files still differ from
the resolved merge of the two branches, so bring them to it.

The T8140 PMP report support from aurora-wip moves into the shared
pmp-report driver: the report offsets, the fast-die effort for cpufreq,
and the entry lifetime. It replaces integration's separate T8140 copy.
The T8140 report entry keeps its t6000 fallback compatible.

On T8140 and T8142, PMGR power-state transitions that time out are undone
outside the system-sleep window again, as in aurora-wip: J700 hits this
on every boot with venc0_sys.

On T8140 the PMP endpoint leaves integration's UPDATE_IOREG confirmation
and power-reply interception out, as aurora-wip did.

Assisted-by: LLM
Signed-off-by: Diljit Singh <hey@djdev.me>
Replaying aurora-wip onto integration/aurora carries each aurora-wip change
only where it applies to integration's code. These files still differ from
the resolved merge of the two branches, so bring them to it.

apple-dart: keep integration's reserved-table firmware handoff, and use
the aurora-wip mirroring of firmware-owned slots only on DARTs that
mirror firmware roots without that handoff (T8140 and T8142).

spi-apple-qspi: keep integration's read-only default and its bounded J613
NVRAM writes on T8122 and T8132. The T8140 controller keeps the
aurora-wip read and write paths.

macsmc-hwmon: integration's driver, with the J700 and J813 sensors from
aurora-wip.

Assisted-by: LLM
Signed-off-by: Diljit Singh <hey@djdev.me>
Replaying aurora-wip onto integration/aurora carries each aurora-wip change
only where it applies to integration's code. These files still differ from
the resolved merge of the two branches, so bring them to it.

The J700 radio follows aurora-wip, together with integration's changes
that do not conflict with it. Remove the duplicate channel-policy and
transport code that the replay left behind.

Assisted-by: LLM
Signed-off-by: Diljit Singh <hey@djdev.me>
The main asahi and apple drivers now serve T8140 and T8142 themselves, so
the separate asahi-neo, apple-neo and drm_neo copies introduced for the
isolated T8140 profile are no longer used. Remove them, together with
their Kconfig, Makefile, Rust module and UAPI header entries, and the
test of the isolated display registration.

Assisted-by: LLM
Signed-off-by: Diljit Singh <hey@djdev.me>
Replaying aurora-wip onto integration/aurora carries each aurora-wip change
only where it applies to integration's code. These files still differ from
the resolved merge of the two branches, so bring them to it.

These are the remaining files, mostly duplicate hunks left by the replay
and entries that both branches added in the same place.

Assisted-by: LLM
Signed-off-by: Diljit Singh <hey@djdev.me>
A USB-C monitor with a built-in USB hub (EIZO EV2780) intermittently
stays dark after a cold boot or a hot-plug on the M1 MacBook Air and
the M1 Mac mini. DCP trains the link for the first modeset at about the
time the monitor's hub brings its SuperSpeed link up. When the two
overlap, the sink loses the link, but DCP still reports the modeset as
linked:

  UnifiedPipeline::mode_set_gated(): 2560x1440@59 Hz link: 1

Then one of two things happens. DCP gives up on its own 2.008 s after
asserting HPD:

  IOMFB: IOAVVideoInterface terminated
  VideoInterfaceIOAV::unplug_gated(): display HPD removed

or it keeps driving the dead link without noticing, while the monitor
pulses HPD about 2-4 s later to be detected again. In both cases the
CD321x still reports DP alt mode with HPD high, and nothing re-detects
the sink. With dwc3 kept off the port, 5 out of 5 boots brought the
display up; with it, 3 out of 6 failed.

Replay an unplug and replug of the sink when DCP drops a sink that
still asserts HPD, or when the sink asks for attention (IRQ_HPD): the
link is then retrained after the hub has settled, as a cable replug
does. A request from the sink within 4 s after a relink is the sink's
late reaction to the loss the relink already handled and is ignored;
another relink would only interrupt the new link. A sink request must
not be dropped as an unchanged route state either. A connection gets at
most three relinks; the replay does not reset that count.

Pulsing only DCP's HPD instead, with the connector kept connected,
raced with DCP re-detecting the sink on its own and left the display
dark on the Mac mini.

H17P and native external pipes keep their own recovery. Once the relink
budget is spent, a sink request falls back to dcp_dptx_recover_irq() or
dcp_retrain_oob() as before.

With this, 8 out of 8 cold boots of the MacBook Air and 8 out of 8 of
the Mac mini (EIZO on the port that failed) brought the display up.

Signed-off-by: Thomas Glanzmann <thomas@glanzmann.de>
A DisplayPort sink that lost the link drops HPD and raises it again to
be detected anew. The EIZO EV2780 does so for about 250 ms, which falls
within the 500 ms debounce of cd321x_update_work(). The worker then
sees DP alt mode with HPD high, the state it already applied, and
cd321x_typec_update_mode() returns without telling the mux, so the
display driver never learns that the sink wants attention and the
display stays dark.

The out-of-band DRM hotplug event does not cover this either on the
M1 MacBook Air and Mac mini: their connector nodes have no
"displayport" reference, so connector_fwnode is NULL.

When HPD changed within the debounce window and is high before and
after, pass the state on with DP_STATUS_IRQ_HPD set, even though it
otherwise matches the applied one.

Signed-off-by: Thomas Glanzmann <thomas@glanzmann.de>
Waking a DP alt mode display from DPMS off with sway ("output * power
on") on the M1 Mac mini (Fujitsu E24T-7 Pro on USB-C, which keeps HPD
asserted while blanked) power cycles the display about every 750 ms
until reboot:

  dcp_hotplug() connected:1 valid_mode:0 nr_modes:1
  dcp_poweron() starting
  set_digital_out_mode finished
  dcp_poweroff() done
  ...

With the cable attached, dcp_poweron() reconnects DPTX and waits for
IOMFB to report the sink before the commit does its modeset. At that
point no mode is valid yet, so dcpep_cb_hotplug() takes the HPD for a
sink that asserted HPD only after a failed modeset and sends
DCP_HOTPLUG_NOTIFY. dcp_hotplug() then sets the connector's link-status
to BAD. wlroots treats a bad link as a disconnect and recreates the
output, which disables the CRTC and enables it again. That wake does
the same, so the loop never ends. Each round also leaks AFK service
slots ("AFK[ep:29]: no reusable service slots") and the system becomes
sluggish.

Do not take the HPD that dcp_poweron() waits for as a late one: the
modeset of the same commit follows. A sink that asserts HPD only after
dcp_poweron() stopped waiting is still handled as before.

Signed-off-by: Thomas Glanzmann <thomas@glanzmann.de>
On the M1 Mac mini with two Fujitsu E24T-7 Pro monitors, which have
no audio (single-block EDID 1.3), PipeWire logs

  spa.alsa: hw:0p: snd_pcm_start: No such device or address

about 130000 times a second, for hours, as soon as something plays to
a DCP audio output: 4.1 million log lines in one boot, with journald
dropping most of them, and a core kept busy.

Without a sink, opening, configuring and preparing the PCM succeed, as
userspace drops an output that fails its probe for good, but START
fails with -ENXIO. That does not stop userspace from trying: PipeWire
starts playback after its first write and ignores the error, and a
stream that never starts never makes it wait, so the next wakeup is
immediate and tries again. Any other error ends up in its recovery,
which prepares and starts again.

Play into the void instead, as HDMI PCMs on other platforms do: without
a sink, or once the sink the stream was opened for is gone, START
succeeds and the stream runs on the clock, without DMA and without a
DCP audio link. The position follows the time since START and a work
item reports the periods. The samples are dropped. A stream playing
into the void is not stopped as disconnected when a sink goes away; a
sink attached later is used by the next stream opened.

Signed-off-by: Thomas Glanzmann <thomas@glanzmann.de>
A USB-C monitor with a built-in hub drops the DP link right after the
first modeset of every DPMS wake, which dcp_typec_relink() recovers by
replaying an unplug and replug. Its retry counter is only reset when
the Type-C generation changes, i.e. on a real cable replug, so all wakes
of one connection share DPTX_RELINK_RETRIES tries: after three wakes the
fourth drop is handled as an unplug and the display stays dark until the
cable is replugged.

The limit exists to stop relink loops within one link bring-up. Reset it
in dcp_poweron() when the CRTC comes back from DPMS off. No relink can
run while the CRTC is off, dcp_typec_relink_start() refuses then.

Signed-off-by: Thomas Glanzmann <thomas@glanzmann.de>
Since commit 57f9f36 ("drm/apple: fence EDID publication by service
lifetime and unblock RX"), the teardown of DCP's AV service schedules the
connector hotplug worker to invalidate the EDID. DCP tears that service
down whenever a Type-C CRTC is powered off with the display attached
(DPMS off). dcp_hotplug() then finds the connector connected without a
valid mode and reports the link as bad. wlroots treats a bad link as a
disconnect and replaces the output on the next wake, which powers the
CRTC off and on again, and that power off does the same: the display
never comes back from the first DPMS off (Mac mini, EIZO EV2780 on USB-C).

There is no link while the CRTC is off, and dcp_poweron() retrains one on
wake. Leave the link status and the CRTC alone then; the EDID is still
invalidated.

Signed-off-by: Thomas Glanzmann <thomas@glanzmann.de>
SIO has 64 descriptor slots, shared by all its channels, and its
cyclic prep takes one slot per period. The PCM allowed any number of
periods, so PipeWire's default of 256-frame periods in a 32768-frame
buffer asked for 128 of them. sio_prep_dma_cyclic() then ran out of
slots, snd_dmaengine_pcm_trigger() returned -ENOMEM, ALSA undid the
START with a STOP (a stop_link round trip to DCP), and PipeWire
retried about 100 times a second with no sound.

Up to three DP audio outputs share one SIO on t600x and t602x, so
allow at most 16 periods per stream, 48 slots for all three.

Fixes: cb24343 ("gpu: drm: apple: Add DCP audio driver")
Signed-off-by: Thomas Glanzmann <thomas@glanzmann.de>
The capture queue never sets max_num_buffers, so vb2 limits every
context to VB2_MAX_FRAME (32) buffers. Nothing in the driver needs that
limit: reference frames are looked up by timestamp (vb2_find_buffer())
and handed to the hardware by DMA address, never by buffer index.

32 buffers leave too little room for userspace to decode ahead. With a
16-frame DPB, four frame threads and the frames held for display, mpv's
decoder queue (--vd-queue) gets only a few frames before
VIDIOC_CREATE_BUFS fails with ENOBUFS, and the FFmpeg V4L2 request
hwaccel then falls back to software decoding. Decoding ahead is needed
because the t8103 AVD decodes 4K59.94 H.264 at only ~41 fps during a
125-156 Mbit/s burst, so playback drops frames unless the decoder has
built up a lead of 60-90 frames beforehand.

Add a max_capture_buffers module parameter, default 128. Buffers are
still allocated on demand by userspace, so this only raises the limit.

Signed-off-by: Thomas Glanzmann <thomas@glanzmann.de>
The AV endpoint (0x29) announces a fresh DCPAVSimpleVideoInterface and
DCPAVAudioInterface on new channels for every DPTX connection, so every
display replug or DPMS wake that drops HPD uses two more slots. Since
"drm/apple: pin DP service owners before recycling retired AFK slots" a
torn-down slot is only reclaimed if its ops opt in with .reusable, which
the AV services never did. After eight connections the 16-slot table is
full, every later announcement fails with

  AFK[ep:29]: no reusable service slots

and the audio service of that port is not re-registered until reboot.

Convert the AV owners and opt in to reuse:

 - DCPAVSimpleVideoInterface keeps no pointer to its service.
 - asrv->srv now holds an owner pin taken in init and dropped in
   teardown. A teardown of an older generation no longer clears the
   pointer or unplugs the jack of its successor.
 - av_service_connect() and av_service_disconnect() call into the
   service after dropping srv_rwsem, so they pin it for the duration.
   Add afk_service_pin() for this; unlike afk_service_get() it also
   succeeds after teardown, so the close is still sent.

Add a KUnit case for a close pinned across teardown.

Signed-off-by: Thomas Glanzmann <thomas@glanzmann.de>
drm: apple: Type-C relink and DPMS wake fixes, DCP audio, AVD buffers, AV slot reuse (port to aurora-wip-rebase)
chriskearney added a commit that referenced this pull request Oct 17, 2026
Merge aurora-wip (carries #131) with review fixes
@chriskearney

Copy link
Copy Markdown

Thanks @DjDeveloperr, this is merged into integration/aurora as #136 (merge commit c46d7dc). It carries 568 of the 569 commits here, with your authorship kept, plus 64 fixes from review. #136's description has the details. Closing this one in favour of it.

What changed from this PR:

  • Dropped c4cdb36 (M2 Pro/Max PCIe-C kernel init). Those DT nodes have no oe-fabric register, so probe failed and Thunderbolt PCIe went away. Integration already cold-initialises these ports.
  • Reworded 30 commit messages and a few comments to match our commit-text guidelines. Code is unchanged. This gives the carried commits new hashes, so aurora-wip needs a rebase onto integration/aurora.
  • user4k is built in, but stays off unless the kernel is booted with user4k=on. Its core changes are gated, and setuid exec and hugetlb are fixed for the on case.
  • Restored bindgen's --no-layout-tests, so stock bindgen builds the release. Your layout check is still there as BINDGEN_LAYOUT_TESTS=1.

Before Neo can ship on the next release, we need two things from you:

  1. A Neo Mesa build against the new asahi_drm.h:
    • feature bits move from bit 10 up;
    • render prior_vdm/prior_cdm move to 320/328, and compute scs_layout/prior_* to 128/136/144;
    • queue_create is now 40 bytes;
    • vm_create's pad is now flags;
    • the driver names are now asahi and apple-drm; mesa-neo-env in this tree accepts both the old and new names.
      An old Neo Mesa falls back to software rendering.
  2. A boot of integration on your J700:
    • the LUKS prompt and display, now appledrm.ko plus drm_dma_helper.ko;
    • GPU power-up;
    • an nvram write through the now mostly read-only boot NOR, with a bless --set-boot round trip;
    • with user4k=on, setuid programs run at native pages and hugetlb is refused in 4K mode.

Also: 28 commits here have no Signed-off-by and 3 have a mismatched one. We can't add those for the authors, so please add them on your side going forward.

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants