Repository navigation
Conversation
06fc7a3 to
43aec22
Compare
2d903fd to
3464d30
Compare
DjDeveloperr
left a comment
There was a problem hiding this comment.
[5/7] PCI: apple: review at 43aec22
Gating: fine. The new paths only run with pcie_apple.cio_s2r=1 on t8132_pciec_hw with apple,j713. Everywhere else cio_dart is NULL and cio_prepared/cio_changed stay false. The only addition on a shared path, the cio_changed check in apple_pcie_map_bus(), reads false there. No T6050 change; pcie-apple.c already conflicts with the M5 branch in 5 places through the series base, and this adds none.
Stop/restart pairing: fine. A failed noirq suspend recovers itself, since PM won't resume this device. A later abort reaches resume_noirq, and the NHI finishes in .complete.
Findings
- A link that doesn't come back panics.
apple_pcie_cio_resume()waits up to 1 s for LINKSTS_UP, andresume_noirqpanics if it never comes. A dock unplugged or power-cycled during sleep gets there, or gets to #1419's NHI panic first. A dead port should end like a surprise removal of the hierarchy, not a panic. That needs #1416 to stop panicking on release. - The two
cio_s2rparams can disagree. Withpcie_apple.cio_s2r=1andthunderbolt_apple.cio_s2r=0, the port binds its DART through the owner interface but nothing prepares it.suspend_noirqthen refuses every deep sleep (and s2idle unlesss2idle_keep_link), and only after every other device has suspended. Bind the owner from the NHI's prepare, use one parameter, or refuse in.prepare. cio_changedis a plain store, read locklessly inmap_bus(). A config access that passedmap_bus()just before the flag flips can still hit the port after APPCLK is cleared. The risk is small in noirq, butpci_cfg_access_lock()or the buspci_lockcloses it.- Nit: the 1 s and 100 ms polls are
read_poll_timeout_atomic()with 1 ms steps. Noirq callbacks may sleep, soread_poll_timeout()avoids a 1 s busy-wait.
Verdict: needs changes, mainly (1), together with #1416 and #1419.
Review only: read at the head commit, not built or run (no J713 here). Written with Claude Code.
| if (pcie->cio_prepared) { | ||
| ret = apple_pcie_cio_resume(pcie); | ||
| if (ret) | ||
| panic("Apple PCIe-C: resume failed %d; descendants remain suspended", ret); |
There was a problem hiding this comment.
The commonest way here is a dock unplugged or powered off during sleep: the link can't train, and every wake becomes a panic. Please end this the way a surprise removal would: leave the port stopped, mark it dead, finish the transaction, and let the hierarchy be removed after resume. Today that removal would itself panic in apple_dart_release_device() (#1416), so the two need to change together.
| if (pcie->cio_prepared) | ||
| return apple_pcie_cio_suspend(pcie); | ||
| /* The reversed DART link is safe only with retained clocks or native PM. */ | ||
| if (pcie->cio_dart && (!pm_suspend_no_platform() || !s2idle_keep_link)) |
There was a problem hiding this comment.
With pcie_apple.cio_s2r=1 but thunderbolt_apple.cio_s2r=0 (or the NHI not bound), cio_dart is bound and never prepared. Every deep sleep is then refused here, after every device has already gone through suspend and suspend_late, and s2idle is refused unless s2idle_keep_link. Since the NHI owns the transaction, it would be simpler to bind the owner when the NHI asks for it, or to share one parameter.
| port->saved_intmask = apple_pcie_port_readl(port, PORT_INTMSK); | ||
| for_each_set_bit(i, port->sid_map, port->sid_map_sz) | ||
| port->saved_rid2sid[i] = apple_pcie_port_readl(port, port_rid2sid_offset(port, i)); | ||
| pcie->cio_changed = true; |
There was a problem hiding this comment.
apple_pcie_map_bus() reads this locklessly, and it's a plain store here. A config cycle that passed map_bus() just before can still be in flight when APPCLK goes off below. pci_cfg_access_lock() on the root port (or WRITE_ONCE plus taking the bus pci_lock around the flip) would order them.
| apple_pcie_port_writel(port, PORT_LTSSMCTL_START, PORT_LTSSMCTL); | ||
| ret = read_poll_timeout_atomic(apple_pcie_port_readl, stat, | ||
| stat & PORT_LINKSTS_UP, | ||
| 1000, 1000000, false, port, PORT_LINKSTS); |
There was a problem hiding this comment.
Nit: this is a busy-wait of up to 1 s in 1 ms steps. resume_noirq may sleep, so read_poll_timeout() works here, and the same goes for the other polls in this file.
The tunneled PCIe port behind a Thunderbolt dock loses its clocks and its DART in a deep sleep, and nothing brings them back. With pcie_apple.cio_s2r=1 on the J713, the port's DART is owned by the port instead of linked for runtime PM, and the ACIO host prepares and finishes a native transaction around the sleep. In it the port's noirq suspend drains the port, closes config space, asserts the tunnel reset and PERST, powers the DART down and stops the port clock. The noirq resume runs the cold port setup again (tunables, port reset table, PERST and clock, root tunables, interrupt routing), restores the requester and MSI routes and the DART, releases the tunnel reset and waits for the link. If the suspend is abandoned after the local PERST, the same full setup runs. Config space is closed under a lock that config accesses hold from map_bus() to the access. A port whose link does not come back, for a dock unplugged or powered off during the sleep, ends like a surprise removal: the port stays stopped, its hierarchy is marked disconnected and removed with the tunnel after resume, and the DART transaction still ends. When the ACIO host already knows the dock is gone, the port does not wait for the link. A deep sleep that the ACIO host did not prepare for this port is refused in .prepare, before any other device suspends. T8132 acknowledges the tunnel PERST by setting bit 1, and the link wait is bounded to one second. The parameter defaults to off: the ACIO host, PHY and DART parts have to be present and enabled together. Signed-off-by: Erik Bourget <erik@ebourget.net>
3464d30 to
280330c
Compare
43aec22 to
473e2b4
Compare
The tunneled PCIe port behind a Thunderbolt dock loses its clocks and its DART in a deep sleep. With
pcie_apple.cio_s2r=1on the J713, the port owns its DART through the new owner interface and takes part in a transaction the ACIO host prepares and finishes.The port's noirq suspend drains it, closes config space, asserts the tunnel reset and PERST, powers the DART down and stops the port clock. The noirq resume re-runs the cold port setup, restores the requester and MSI routes and the DART, releases the tunnel reset and waits up to one second for the link. An abandoned suspend recovers through the same path. Config space is closed under a lock that config accesses hold from
map_bus()to the access.A port whose link does not come back, for a dock unplugged or powered off during the sleep, ends like a surprise removal: it stays stopped, its hierarchy is marked disconnected and removed with the tunnel after resume, and the DART transaction still ends. When the ACIO host already knows the dock is gone, the port does not wait for the link.
A deep sleep the ACIO host did not prepare for this port (for example
thunderbolt_apple.cio_s2r=0) is refused in.prepare, before any other device suspends.The devices behind the dock stay bound across the sleep.
Part 5/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 #1417.
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.