From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pg1-f181.google.com (mail-pg1-f181.google.com [209.85.215.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8DD12384CCA for ; Sat, 11 Jul 2026 09:21:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.181 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783761701; cv=none; b=mLZmfpC4lanuGb2jj0VUu2Gxjp7jzzJMos4KSdAu7gsffdGolVA08B1FOq4gSGIVUYGgjr3JIQpkk5PJyNhD/IveVKO2LT8ySFMKYOpOkzCW40kJskJpOMeS96ua9ePtA9o1K/LcfaWduKOHcqsR6SQwh/skLO8NyDmOKl77KA0= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783761701; c=relaxed/simple; bh=wJMAVoV26Wxtc9n53dd5rXmHTRFOtEAhBau0xCJPIic=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=RBrRPxymIP7FjHFs4kz9D0gsgWQVOQIsfmJep46iAhTqs1oI/IeMsG4CKlgLGH6RaWjFizOpo+A8G3jNrNp97QtVvaFGn12UkxqzjfqsAVgfWwXc222LKZobS1rs+E6euYgekcsmDzmeJMc27qJruSCruqDniNQmFNeZthQrDlk= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=debian.org; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=209.85.215.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=debian.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-pg1-f181.google.com with SMTP id 41be03b00d2f7-ca97d139d8dso1062144a12.2 for ; Sat, 11 Jul 2026 02:21:39 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783761699; x=1784366499; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=tlnA7fLt+6hyELPfR2jAqKN6onKfTqXw2YAeru37F4c=; b=BcxUzDWZTMufc7napqmIJCbrIydDUraGxcddVD3kXv2qfsbxN+5Qr8FRdRhGeWhgVt aFaLLZhbO/juXN4+yPTHNQLIJGHdxDRAt70zKetGdHOD028Eek4LtGfzkL3BRisjUNpi nOy6b641Sd7Nb5TDMO1RnHbZoJLa20hrKYP6JzTJRC9Yz/NwHZT75Huc+VeUEtNGSCGm ue/OzJ1KWWwSRU5Y1pHNqXABAZNkgSy5T7WB07bsVWkEZ1ABig9CmA/U8iK9RWM5eeGQ xcIcr7Ci8DM7k9xJU6Z1tMtlOZkA3pDe3l6ebQzUqv/GH94xd/a5xFCX3U02m83o/BdT OLsg== X-Forwarded-Encrypted: i=1; AHgh+RqfJv8PhQKG82FrLRVMacOc1nIpa5k6k+fjj/2CJjz4RDOZUeHhX8CJ9we3qp66FS3SKfiX9wbPREiCP1s=@vger.kernel.org X-Gm-Message-State: AOJu0YyigiyUycD8Zg8FjwGSrzcFpHs1RF2rT6d+lwMkT809UXn2qlaZ IYdZAkM17C8Doaz0WKt8AKYavC7GzjPdJ0JxgHlLkKcoiSlT6X4X6ZU= X-Gm-Gg: AfdE7ckdbXn7YjmgyRA7uf/JbjBeieExVK5YkY2TTbsckuRAhzH0b46dyaqWr1MTYBx TTLPV6i+36zmrZLmV72bG0Eo48UU4TFsMQcevrWgKpMAZGlTha6SvGSFU8KAmQuD0PuCVe0S47S 79W8E7IG8gdzT4nokgJSS04t4MWZKBx9wbfT+dW9TdqDDWOIgcGBFQBsnGPMZjwRE907L6dsRFN AVy5FU6h7bTmGaaYhPj2oEaejFnqfCBNMohqPR/xR9O9UH0JUUPsnrdzaxeIMFA5G+B0AoDYm2l SHWB+EoZgf84ofMF8EN6TjOdAM7kj/SejpFBSLK+S7TvVthZ5cM62jIeG3Rv16HmpEpJi1masfH BCq6Bhytj+xf1uVqLyciOa1qINWeT5lj9VaaBZ4DFUil1VO3pRfIMgzUKUrwFbm2aS6/t9uNCxa JZ9Quzl4q2n4TaDrxG/jL7iW5kIInBbgVYBOlT3QWOXMSodqNgJXlVPjuJMscmwz3pKIyiv7sth 5DEaWNPkF58p8hBUIv6m5hGBQ== X-Received: by 2002:a05:6a00:2441:b0:848:5eae:3695 with SMTP id d2e1a72fcca58-84889883eebmr2183357b3a.78.1783761698716; Sat, 11 Jul 2026 02:21:38 -0700 (PDT) Received: from penguin.tail0a1999.ts.net (61-228-52-13.dynamic-ip.hinet.net. [61.228.52.13]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-847f6dbfd41sm11468726b3a.57.2026.07.11.02.21.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 11 Jul 2026 02:21:38 -0700 (PDT) From: Shih-Yuan Lee To: Dmitry Torokhov Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, Shih-Yuan Lee Subject: [PATCH v3 1/3] Input: applespi - force PIO mode on MacBook8,1 Date: Sat, 11 Jul 2026 17:20:52 +0800 Message-Id: <20260711092054.13818-2-fourdollars@debian.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260711092054.13818-1-fourdollars@debian.org> References: <20260711092054.13818-1-fourdollars@debian.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit On MacBook8,1 (early 2015 12" MacBook), the LPSS SPI controller's DMA handshake and interrupt routing frequently fail or time out on boot, causing the keyboard and trackpad to become unresponsive. Address this by introducing a DMI quirk and a `force_pio` module parameter. If either is true, override the SPI controller's `can_dma` callback to a helper that always returns false. This forces all SPI transfers to fall back to the reliable PIO mode. To ensure correct timing and architectural safety: 1. Perform the override at the very beginning of applespi_probe() so that all early initialization transfers use PIO. 2. In case of probe failures or module unload (remove), unconditionally restore the original `can_dma` callback (even if it was NULL) to prevent any execute-after-free or dangling pointer vulnerability in the shared host controller. Link: https://bugzilla.kernel.org/show_bug.cgi?id=108331 Signed-off-by: Shih-Yuan Lee --- drivers/input/keyboard/applespi.c | 66 +++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/drivers/input/keyboard/applespi.c b/drivers/input/keyboard/applespi.c index b5ff71cd5a70..79e5cb5001c7 100644 --- a/drivers/input/keyboard/applespi.c +++ b/drivers/input/keyboard/applespi.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -110,6 +111,10 @@ module_param_string(touchpad_dimensions, touchpad_dimensions, sizeof(touchpad_dimensions), 0444); MODULE_PARM_DESC(touchpad_dimensions, "The pixel dimensions of the touchpad, as XxY+W+H ."); +static bool applespi_force_pio; +module_param_named(force_pio, applespi_force_pio, bool, 0444); +MODULE_PARM_DESC(force_pio, "Force PIO mode (disables DMA) for SPI transfers. ([0] = disabled, 1 = enabled)"); + /** * struct keyboard_protocol - keyboard message. * message.type = 0x0110, message.length = 0x000a @@ -431,6 +436,10 @@ struct applespi_data { int tp_dim_max_x; int tp_dim_min_y; int tp_dim_max_y; + + bool (*original_can_dma)(struct spi_controller *controller, + struct spi_device *spi, + struct spi_transfer *xfer); }; static const unsigned char applespi_scancodes[] = { @@ -1605,6 +1614,13 @@ static void applespi_save_bl_level(struct applespi_data *applespi, "Error saving backlight level to EFI vars: 0x%lx\n", sts); } +static bool applespi_can_not_dma(struct spi_controller *controller, + struct spi_device *spi, + struct spi_transfer *xfer) +{ + return false; +} + static int applespi_probe(struct spi_device *spi) { struct applespi_data *applespi; @@ -1612,6 +1628,7 @@ static int applespi_probe(struct spi_device *spi) acpi_status acpi_sts; int sts, i; unsigned long long gpe, usb_status; + bool override_dma = applespi_force_pio || dmi_match(DMI_PRODUCT_NAME, "MacBook8,1"); /* check if the USB interface is present and enabled already */ acpi_sts = acpi_evaluate_integer(spi_handle, "UIST", NULL, &usb_status); @@ -1628,6 +1645,13 @@ static int applespi_probe(struct spi_device *spi) applespi->spi = spi; + /* Save original can_dma and override if requested or needed */ + applespi->original_can_dma = spi->controller->can_dma; + if (override_dma) { + dev_info(&spi->dev, "Disabling DMA for SPI to force PIO mode\n"); + spi->controller->can_dma = applespi_can_not_dma; + } + INIT_WORK(&applespi->work, applespi_worker); /* store the driver data */ @@ -1645,8 +1669,10 @@ static int applespi_probe(struct spi_device *spi) GFP_KERNEL); if (!applespi->tx_buffer || !applespi->tx_status || - !applespi->rx_buffer || !applespi->msg_buf) - return -ENOMEM; + !applespi->rx_buffer || !applespi->msg_buf) { + sts = -ENOMEM; + goto err_restore_dma; + } /* set up our spi messages */ applespi_setup_read_txfrs(applespi); @@ -1658,7 +1684,8 @@ static int applespi_probe(struct spi_device *spi) dev_err(&applespi->spi->dev, "Failed to get SIEN ACPI method handle: %s\n", acpi_format_exception(acpi_sts)); - return -ENODEV; + sts = -ENODEV; + goto err_restore_dma; } acpi_sts = acpi_get_handle(spi_handle, "SIST", &applespi->sist); @@ -1666,23 +1693,26 @@ static int applespi_probe(struct spi_device *spi) dev_err(&applespi->spi->dev, "Failed to get SIST ACPI method handle: %s\n", acpi_format_exception(acpi_sts)); - return -ENODEV; + sts = -ENODEV; + goto err_restore_dma; } /* switch on the SPI interface */ sts = applespi_setup_spi(applespi); if (sts) - return sts; + goto err_restore_dma; sts = applespi_enable_spi(applespi); if (sts) - return sts; + goto err_restore_dma; /* setup the keyboard input dev */ applespi->keyboard_input_dev = devm_input_allocate_device(&spi->dev); - if (!applespi->keyboard_input_dev) - return -ENOMEM; + if (!applespi->keyboard_input_dev) { + sts = -ENOMEM; + goto err_restore_dma; + } applespi->keyboard_input_dev->name = "Apple SPI Keyboard"; applespi->keyboard_input_dev->phys = "applespi/input0"; @@ -1717,7 +1747,7 @@ static int applespi_probe(struct spi_device *spi) if (sts) { dev_err(&applespi->spi->dev, "Unable to register keyboard input device (%d)\n", sts); - return -ENODEV; + goto err_restore_dma; } /* @@ -1729,7 +1759,8 @@ static int applespi_probe(struct spi_device *spi) dev_err(&applespi->spi->dev, "Failed to obtain GPE for SPI slave device: %s\n", acpi_format_exception(acpi_sts)); - return -ENODEV; + sts = -ENODEV; + goto err_restore_dma; } applespi->gpe = (int)gpe; @@ -1740,7 +1771,8 @@ static int applespi_probe(struct spi_device *spi) dev_err(&applespi->spi->dev, "Failed to install GPE handler for GPE %d: %s\n", applespi->gpe, acpi_format_exception(acpi_sts)); - return -ENODEV; + sts = -ENODEV; + goto err_restore_dma; } applespi->suspended = false; @@ -1751,7 +1783,8 @@ static int applespi_probe(struct spi_device *spi) "Failed to enable GPE handler for GPE %d: %s\n", applespi->gpe, acpi_format_exception(acpi_sts)); acpi_remove_gpe_handler(NULL, applespi->gpe, applespi_notify); - return -ENODEV; + sts = -ENODEV; + goto err_restore_dma; } /* trigger touchpad setup */ @@ -1789,6 +1822,11 @@ static int applespi_probe(struct spi_device *spi) &applespi_tp_dim_fops); return 0; + +err_restore_dma: + if (override_dma) + spi->controller->can_dma = applespi->original_can_dma; + return sts; } static void applespi_drain_writes(struct applespi_data *applespi) @@ -1813,6 +1851,7 @@ static void applespi_drain_reads(struct applespi_data *applespi) static void applespi_remove(struct spi_device *spi) { struct applespi_data *applespi = spi_get_drvdata(spi); + bool override_dma = applespi_force_pio || dmi_match(DMI_PRODUCT_NAME, "MacBook8,1"); applespi_drain_writes(applespi); @@ -1822,6 +1861,9 @@ static void applespi_remove(struct spi_device *spi) applespi_drain_reads(applespi); + if (override_dma) + spi->controller->can_dma = applespi->original_can_dma; + debugfs_remove_recursive(applespi->debugfs_root); } -- 2.39.5