From 1d8e0b1e8bbafcd30bed013886ea39f3d1be8c07 Mon Sep 17 00:00:00 2001 From: Dmitriy Date: Sat, 7 Nov 2026 14:32:38 +0200 Subject: [PATCH] iommu: apple-dart: Keep a T8142 DART that a live coprocessor uses On T8142 the boot loader may start the MTP for the internal keyboard (for example to read a disk passphrase) and hand the running session to Linux, with its DART streams in bypass. The MTP helper adopts that session, but the DART probe reset the block first and cut the coprocessor off. When an available node with apple,rtkit-handoff = "mtp-live-v1" uses a T8142 DART through iommus, keep the DART as it is, as already done for the J713 and J614s MTPs. The T8142 TCR bypass bits read back as zero even while the streams bypass, so the bypass cannot be confirmed from the registers. Trust the handoff and refuse only a DART that cannot bypass at all. Signed-off-by: Dmitriy Assisted-by: LLM --- drivers/iommu/apple-dart.c | 47 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c index 1234b4a771e7a..c19c6663e405e 100644 --- a/drivers/iommu/apple-dart.c +++ b/drivers/iommu/apple-dart.c @@ -4096,6 +4096,36 @@ static void apple_dart_free_irq(struct apple_dart *dart) apple_dart_display_irq_peers[i] = NULL; } +/* + * Whether an available coprocessor that translates through @np was handed + * over running by the boot loader ("mtp-live-v1"), with its DART streams left + * in bypass. Resetting the DART would cut that live session off. + */ +static bool apple_dart_has_live_rtkit_client(struct device_node *np) +{ + struct of_phandle_args args; + struct device_node *client; + const char *handoff; + bool match; + + for_each_node_with_property(client, "apple,rtkit-handoff") { + if (!of_device_is_available(client) || + of_property_read_string(client, "apple,rtkit-handoff", &handoff) || + strcmp(handoff, "mtp-live-v1")) + continue; + if (of_parse_phandle_with_args(client, "iommus", "#iommu-cells", + 0, &args)) + continue; + match = args.np == np; + of_node_put(args.np); + if (match) { + of_node_put(client); + return true; + } + } + return false; +} + static int apple_dart_probe(struct platform_device *pdev) { int ret, sid; @@ -4539,6 +4569,23 @@ static int apple_dart_probe(struct platform_device *pdev) dart->retained_mtp = true; dev_info(dev, "Retaining the live J713 MTP bypass\n"); } + if (!dart->retained_mtp && + of_device_is_compatible(dev->of_node, "apple,t8142-dart") && + apple_dart_has_live_rtkit_client(dev->of_node)) { + /* + * The T8142 TCR bypass bits do not read back, so the loader's + * bypass cannot be confirmed from the registers; trust the + * handoff, and refuse only a DART that cannot bypass at all. + */ + if (dart->hw->type != DART_T8110 || dart->locked || tunneled || + !dart->supports_bypass) { + dev_err(dev, "Refusing a live coprocessor handoff on a DART that cannot bypass\n"); + ret = -EINVAL; + goto err_clk_disable; + } + dart->retained_mtp = true; + dev_info(dev, "Retaining the live coprocessor bypass\n"); + } if (dart->preserve_display) { if (dart->hw->type != DART_T8110 || !bitmap_empty(dart->remapped, DART_MAX_STREAMS)) { ret = -EINVAL;