Repository navigation
Conversation
bfae172 to
071e41e
Compare
DjDeveloperr
left a comment
There was a problem hiding this comment.
[3/7] apple-dart: review at 071e41e
Gating: fine. apple_dart_cio_init() sets dart->cio only on apple,j713 T8110 DARTs at eight fixed bases. Every new branch (suspend, resume, resume_noirq, release_device, domain_free, the writer gate) depends on dart->cio or cio_active, so T6050 and every other SoC is unchanged.
M5: this adds no conflict hunk; apple-dart.c already conflicts with the M5 branch in 9 places through the series base. t6050-sleep.c runs the same SPTM-style display-DART sequence with raw writes (streams off one by one, flush, slice bit 4 cleared; on: slice 0x12, diag 0, streams). There is no runtime overlap, but the sequence now exists in two places.
Findings (most severe first)
- Panics the dock path can reach. With
dart->cioset, an unmap or TLB flush on a closed DART callsapple_dart_sleep_release_failed(), andrelease_device()panics for the whole prepare..finish window. For the radio, its owner was the only mapper. Here the mappers are every driver behind the dock and the DRM buffers on the display DARTs.finish()returning-EUCLEANalso leavescio_activeset for the rest of the boot, so a failed wake followed by unplugging the dock (PCI removal, thenrelease_device) panics.
Suggestion: while a DART is closed, let map/unmap publish to memory only, as thedisplay_darkpath already does. Skip the hardware TLB command and mark the TLB stale.dart_cio_restore()flushes before it re-enables streams, so nothing walks a stale entry. Release and free then don't need to panic, and a failed transaction can end with the streams left off but the bookkeeping released. - A rejected map poisons the restore. One map attempted during the window (
cio_violation) makeson()refuse to restore, so the DART stays closed until reboot. A latedma_mapfrom a dock NIC refill or a DRM worker then takes out the dock or the display. With (1), a rejected map is harmless. - Selection by base address. The table sits under
of_machine_is_compatible("apple,j713"). J715 shares t8132-j713-j715.dtsi and the existingj713_*DART detection (firmware path plus address), but this excludes it. Two of these bases (0x48a300000/0x48a340000) are T6050's internal display DART pair int6050-sleep.c, so the machine check is load-bearing. A DT property on the DART node carrying the slice number would be sturdier than a code table. - Hot-path cost with the feature off. The writer gate now takes
managed_lock(irqsave) on every map, unmap and flush on these eight DARTs even with bothcio_s2rparams at 0, becausedart->ciois set at probe. Gate on a bound owner or oncio_activeinstead. commands_gatedis set underdart->lock(apple_dart_quiesce_commands()) but cleared undermanaged_lockhere. That's harmless while requesters are stopped, but it's the only writer that skipsdart->lock.
Verdict: needs changes, mainly (1) and (2).
Review only: read at the head commit, not built or run (no J713 here). Written with Claude Code.
| for_each_stream_map(j, cfg, stream_map) { | ||
| if (READ_ONCE(stream_map->dart->sleep_record)) | ||
| if (READ_ONCE(stream_map->dart->sleep_record) || | ||
| READ_ONCE(stream_map->dart->cio_active)) |
There was a problem hiding this comment.
This extends the radio's panic-on-release to the eight CIO and display DARTs. Unlike the radio, these front hot-pluggable trees (the tunneled PCIe hierarchy behind a dock) and DRM buffers. Two concrete ways in: (a) apple_dart_cio_finish() returns -EUCLEAN and leaves cio_active set permanently, so unplugging the dock after a failed wake panics here; (b) any PCI removal between the NHI's .prepare and .complete, for example a surprise unplug while sleep is starting. See the summary for a memory-only publish while closed, which makes this check unnecessary.
| int ret = 0; | ||
|
|
||
| if (!dart->managed_sids) | ||
| if (!dart->managed_sids && !dart->cio) |
There was a problem hiding this comment.
dart->cio is set at probe on J713 whatever pcie_apple.cio_s2r/thunderbolt_apple.cio_s2r say, so every map, unmap and flush on the tunneled PCIe, NHI and display DARTs now takes managed_lock with IRQs off, even with the feature off. Suggest keying this on a bound owner (dart->cio && dart->cio->owner) or on cio_active. Also note that with cio set, writer_get() failing on the unmap/flush paths now panics (apple_dart_sleep_release_failed()): see summary point 1.
| unsigned int slice, bank = 0; | ||
| bool partitions, display = false; | ||
|
|
||
| if (!of_machine_is_compatible("apple,j713") || dart->hw->type != DART_T8110) |
There was a problem hiding this comment.
J715 uses the same t8132-j713-j715.dtsi and gets the j713_dispext/j713_dcpext treatment in apple_dart_probe(), which is based on firmware path and address, but is left out here. Also, 0x48a300000/0x48a340000 are T6050's internal display DART pair (T6050_DISP0_DART and the DCP DART in t6050-sleep.c), so this machine check is the only thing separating the two. A DT property on the DART nodes (for example apple,cio-power-slice = <N>) would drop the address table and make the opt-in explicit.
|
|
||
| spin_lock_irqsave(&s->dart->managed_lock, flags); | ||
| /* Publish restored translations before admitting hardware commands. */ | ||
| smp_store_release(&s->dart->commands_gated, false); |
There was a problem hiding this comment.
Nit: every other writer of commands_gated (apple_dart_quiesce_commands(), apple_dart_resume_commands(), apple_dart_host_resume()) holds dart->lock; this one holds managed_lock. It's safe while requesters are stopped, but taking dart->lock here too would keep one rule.
|
|
||
| if (!s || !READ_ONCE(s->dart->cio_active)) | ||
| return -EINVAL; | ||
| if (READ_ONCE(s->dart->cio_violation)) |
There was a problem hiding this comment.
A single map attempted while closed (writer_get() sets cio_violation and returns -EBUSY to the caller, so nothing was written) makes this refuse to restore, and the DART stays closed for the rest of the boot. A late dma_map from a dock NIC refill or a DRM worker during the window is enough to lose the dock or the display. Since a rejected map changed nothing, it shouldn't block the restore. With the memory-only publish from the summary, it wouldn't even need rejecting.
| dart = s->dart; | ||
| spin_lock_irqsave(&dart->managed_lock, flags); | ||
| if (dart->cio_violation || dart->sleep_closed || (s->changed && !s->restored)) | ||
| ret = -EUCLEAN; |
There was a problem hiding this comment.
On this path cio_active stays true and the runtime-PM reference stays held forever. From then on apple_dart_suspend()/resume() skip this DART, prepare() returns -EBUSY, domain_free() leaks, and release_device() panics. The header calls this fail-closed, but for a removable tree it means a later unplug crashes the machine. Consider ending the transaction here with the streams left disabled, and releasing the bookkeeping.
…DARTs On T8132, the hosts of some DARTs power them off and restore them around a deep sleep: the ACIO NHIs, the tunneled PCIe ports and the external display coprocessors. They need the same clock protection slice as the internal display DARTs. Extend the description of apple,clock-protection to them. Signed-off-by: Erik Bourget <erik@ebourget.net>
A deep sleep with a Thunderbolt dock attached powers off the ACIO and tunneled PCIe DARTs and the external display coprocessors' DARTs, and their hosts have to bring them back before the first requester runs again. Runtime PM cannot do it: the host decides when its requesters are stopped and when its clocks are back. Add an owner interface for the T8110 DARTs whose device tree node names a clock protection slice, other than the internal display ones. The host binds once, then around a deep sleep calls prepare (before any suspend callback), off (requesters stopped, clocks still on), on (clocks back, before any DMA) and finish. off closes the DART to hardware commands, saves the stream table, tunables and partition words, disables the streams, flushes, and releases the clock-protection slice. on restores the slice and the saved state and reopens the DART. The generic suspend and resume callbacks leave an owned DART alone, and a DART without a bound owner takes no extra lock on its map paths. While a DART is closed, its page tables are still updated, in memory only: map, unmap, attach, release and free never touch its registers. Those writers are counted. Reopening, after a restore or after an off that failed before changing anything, waits for them, and if anything changed meanwhile flushes the whole TLB before the DART opens. finish always ends the transaction. A DART that was not restored stays closed, its registers unused, until reboot, even once its owner is gone; nothing panics on it. Things learned on the J713 that the restore accounts for: - The tunneled PCIe DART has 256 stream slots where Linux allocates 64. The whole bank, as the hardware reports it, is saved, the reserved bypass streams included. - An external display DART's clock-protection slice word reads zero after the sleep. It is saved at off and written back at on. - A locked DART can come back with other bits set in the root of a stream that is not enabled and whose root was, and still is, invalid. That is accepted. Every control register and every valid root must match, and a locked DART is never rewritten. The slice handling follows the internal display DART's power-down. A failed restore dumps the registers that differ. Add host-side models of the register sequence and of the ownership rules, each with negative controls. Based-on-work-by: Bartosz Nitka <niteria@gmail.com> Signed-off-by: Erik Bourget <erik@ebourget.net>
…ction A deep sleep with a dock or an external display attached powers off the DARTs of the ACIO NHIs, the tunneled PCIe ports and the external display coprocessors, and their hosts restore them. Give each of them its clock protection slice, which also marks it as one its host may power-cycle. Signed-off-by: Erik Bourget <erik@ebourget.net>
dcaf73b to
3db00bc
Compare
071e41e to
8178a9f
Compare
A deep sleep with a Thunderbolt dock attached powers off the ACIO and tunneled PCIe DARTs and the external display coprocessors' DARTs. Their hosts have to bring them back before the first requester runs again, at a point only the host knows.
Add an owner interface for these DARTs: bind once, then prepare, off, on and finish around a deep sleep. A DART takes part when its device-tree node names its clock protection slice (
apple,clock-protection, now also on the eight J713 ACIO, tunneled PCIe and external display DARTs); there is no address table.offcloses the DART to hardware commands, saves its registers, disables the streams, flushes and releases the clock-protection slice.onrestores the slice and the saved state and reopens it. The generic suspend and resume callbacks leave an owned DART alone, and a DART with no owner bound takes no extra lock on its map paths.While a DART is closed its page tables are still updated, in memory only, and map, unmap, attach, release and free never touch its registers. Those writers are counted; reopening waits for them and flushes the whole TLB before the DART opens if anything changed.
finishalways ends the transaction: a DART that was not restored stays closed, its registers unused, until reboot, and nothing panics on it.Behaviour seen on the J713 that the restore accounts for:
Part 3/7 of J713 docked S2R, stacked on the native radio series (#1384), which is stacked on #1314.
Series order: #1414 → #1415 → #1416 → #1417 → #1418 → #1419 → #1420.
Depends on #1415.
Validation of the series on this base:
Based-on-work-by:trailers and style in thetools/asahifixtures.The changes since that version (the DT-selected DART owners and memory-only updates while closed, the unplug handling, the failure unwinds, the stock tb.c resume restored, the PMGR and RTKit hardening) are built and covered by the host suites, but have not run on the J713 yet.
Not covered: repeated sleeps on one boot, wake sources other than the RTC, the desktop's own sleep path (lid, logind), a dock unplugged during the sleep on hardware, and docks other than the TS5. Both native parameters (
pcie_apple.cio_s2r,thunderbolt_apple.cio_s2r) default to off.This series was developed and tested by Claude (Anthropic), working with me on the J713.