Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2227012/?format=api
{ "id": 2227012, "url": "http://patchwork.ozlabs.org/api/patches/2227012/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-i2c/patch/20260423002838.83171-1-william@wkennington.com/", "project": { "id": 35, "url": "http://patchwork.ozlabs.org/api/projects/35/?format=api", "name": "Linux I2C development", "link_name": "linux-i2c", "list_id": "linux-i2c.vger.kernel.org", "list_email": "linux-i2c@vger.kernel.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20260423002838.83171-1-william@wkennington.com>", "list_archive_url": null, "date": "2026-04-23T00:28:36", "name": "i2c: designware: Handle active slave and shutdown cleanly", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "7ae46851a88f2cd3de9bfcd6449f6f27457b0124", "submitter": { "id": 87247, "url": "http://patchwork.ozlabs.org/api/people/87247/?format=api", "name": "William A. Kennington III", "email": "william@wkennington.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/linux-i2c/patch/20260423002838.83171-1-william@wkennington.com/mbox/", "series": [ { "id": 501133, "url": "http://patchwork.ozlabs.org/api/series/501133/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-i2c/list/?series=501133", "date": "2026-04-23T00:28:36", "name": "i2c: designware: Handle active slave and shutdown cleanly", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/501133/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2227012/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2227012/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "\n <linux-i2c+bounces-17133-incoming=patchwork.ozlabs.org@vger.kernel.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "linux-i2c@vger.kernel.org" ], "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=wkennington-com.20251104.gappssmtp.com\n header.i=@wkennington-com.20251104.gappssmtp.com header.a=rsa-sha256\n header.s=20251104 header.b=qwEMjfR8;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c04:e001:36c::12fc:5321; helo=tor.lore.kernel.org;\n envelope-from=linux-i2c+bounces-17133-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)", "smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=wkennington-com.20251104.gappssmtp.com\n header.i=@wkennington-com.20251104.gappssmtp.com header.b=\"qwEMjfR8\"", "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=74.125.82.181", "smtp.subspace.kernel.org;\n dmarc=none (p=none dis=none) header.from=wkennington.com", "smtp.subspace.kernel.org;\n spf=none smtp.mailfrom=wkennington.com" ], "Received": [ "from tor.lore.kernel.org (tor.lore.kernel.org\n [IPv6:2600:3c04:e001:36c::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g1H5J2qcsz1yDD\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 23 Apr 2026 10:28:52 +1000 (AEST)", "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby tor.lore.kernel.org (Postfix) with ESMTP id E3AD4301828A\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 23 Apr 2026 00:28:48 +0000 (UTC)", "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 251B31F151C;\n\tThu, 23 Apr 2026 00:28:47 +0000 (UTC)", "from mail-dy1-f181.google.com (mail-dy1-f181.google.com\n [74.125.82.181])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 51B8A1E9906\n\tfor <linux-i2c@vger.kernel.org>; Thu, 23 Apr 2026 00:28:45 +0000 (UTC)", "by mail-dy1-f181.google.com with SMTP id\n 5a478bee46e88-2e622a9da9cso7124752eec.0\n for <linux-i2c@vger.kernel.org>; Wed, 22 Apr 2026 17:28:45 -0700 (PDT)", "from wak-linux.svl.corp.google.com\n ([2a00:79e0:2ed2:c:c318:833d:66c6:43a0])\n by smtp.gmail.com with ESMTPSA id\n 5a478bee46e88-2e53d4bdaf7sm24632628eec.25.2026.04.22.17.28.43\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Wed, 22 Apr 2026 17:28:43 -0700 (PDT)" ], "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1776904126; cv=none;\n b=J7CdwnH8uE16bpm+RMzSWFc4a7HTfSvQUW505Uh13TnaEiewwEmEf++VVN4wSHd3Sz7hDteiVqkK2sFCYixIy2P0gqvxg48hWJLyuj+GN+HZbVV8M4h8zXnbM4ZPiMtXrRx1LKIo1iiAhv+Ak5tnM2fhkYWgn807SgZYiYZRSng=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1776904126; c=relaxed/simple;\n\tbh=fLuh2yYCliD3/tO4zPDbjuOR6Zrc8covuDSXJPtOtGE=;\n\th=From:To:Cc:Subject:Date:Message-ID:MIME-Version;\n b=PMW7BtlUKr6vGimHM3hvlFoH4Rl5IG+v5Qf5IWwmykxA0THNv1NL6/r+iihU60cMHX3ThHZBRgAXq8KJ1owoZlCUyDBN7pmuIUb+UlvxAelrRIslMmhlv3AJJwZlwL5B4tKQrH6L89hRCyeaOyfC1uPL6nPyNb7NVaO1X0n0uOM=", "ARC-Authentication-Results": "i=1; smtp.subspace.kernel.org;\n dmarc=none (p=none dis=none) header.from=wkennington.com;\n spf=none smtp.mailfrom=wkennington.com;\n dkim=pass (2048-bit key) header.d=wkennington-com.20251104.gappssmtp.com\n header.i=@wkennington-com.20251104.gappssmtp.com header.b=qwEMjfR8;\n arc=none smtp.client-ip=74.125.82.181", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=wkennington-com.20251104.gappssmtp.com; s=20251104; t=1776904124;\n x=1777508924; darn=vger.kernel.org;\n h=content-transfer-encoding:mime-version:message-id:date:subject:cc\n :to:from:from:to:cc:subject:date:message-id:reply-to;\n bh=Q8Zq/XP2zPjzoG7Ee7KkAJncAAl85yYbm00SL2RgdzU=;\n b=qwEMjfR8bJ86el3SwemWZsa2zhM9t0AY8OsDuKiHD1F/UHyP/Fn4us8oCmw9I0mhZ9\n hT1qHChA8edPyUOMOrlTcf1IHCE8M3HWnh1fy0l0h/hWzKQDYksQrNFRacsZdHQHGWtk\n miXeqqEmqMuImCK5+7EJQkY/A1h/425tkDrt4J7WzknF544vwePebK0K+17FREOmbMG/\n 0AcV4I12hpKOwb5VQz9oPgr2hIB8QDlyaa9z4NtknfDFHe89cU+GbrzSLT1uU9dKGnDN\n Wfb0YaVnxJDuvacmjgDcPseRPu4GyZROwNHgNE0wDFll+iLmL8HjL+N5UHdV+H2OsJP+\n 90ww==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776904124; x=1777508924;\n h=content-transfer-encoding:mime-version:message-id:date:subject:cc\n :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date\n :message-id:reply-to;\n bh=Q8Zq/XP2zPjzoG7Ee7KkAJncAAl85yYbm00SL2RgdzU=;\n b=EOvdJuoiywwkpdAetfYrAS45pGzvcaWlEZ5fXlqd4cnc5i95CuBhxE4L6FjiABLOcn\n W5KhDW6gi4AocW0fs/lHfhLyB6HvAMgkF/SDWMagqAy2PYt8Vatu3LmSG/sDsDfX5TEQ\n I7jowXEtBNhNMPJF18kDkRWHvMSw/X3Qi0m/cUMXb1XPNM4lUg5cXKCRSBzMNHnJuOql\n a8jdv74bvteNsBCs3ZCl4No6yJbCWGIyHPyDpnIxysx532w7vFTt/2eY50HgoOFijKFF\n NzLdfpuQAGkAyoFPqwUGGRJ+59yqBx/B1/M7dzvIcaL/HKX+XXBCn0NJ4kw0xZDswCAx\n c9mg==", "X-Forwarded-Encrypted": "i=1;\n AFNElJ/rbpZrb1cvyUql2Kwc0/SRfsWJvRKYie6uci3+MEMSux4K98qHABEO+Wrxwh9kUfpxYkNQ/0OShOc=@vger.kernel.org", "X-Gm-Message-State": "AOJu0YzysAMfNIldyFmUjQsOElJKaz8OSkUswZONQeT626P6Bxj46i+W\n\tQRzFVJffU/FLIyi9g5ZJNnSS5Wl4pQ8KZ6jJf1Pi0BHoegZexCLh3v6BHEwjzTx90rTDxMFcHEd\n\tTe7sksWE4sA==", "X-Gm-Gg": "AeBDietW8zMTP9y9l+yXK5nHYRVDiorX8fnac+ZUWGn+2PSxx/Cyx+W9VasyFRs1TKK\n\tdF23yAcZIDoAK0gAHkpJW9c9KIRUo+E7Rzl7qEruXOdWsV2VZpT+Vnq3a6lYU7v3CcAWumRw+fO\n\tAj9enNgLUtZP6Qw9Ryu6jTsCZ+Y7vBKqepm8nM7loTAyH1BSySQoqxLjIfyx7ozDzQ0himgRIwc\n\t50zYwE3x49gPK80/Rcy2sxckfCfzTrgTf2bZUpHNra7FzJwbjiRNRgTF4khAjpnqjVVUtXLDnnY\n\tVXQ36/nS7jK6s/vEoiyJD2u0nS34Tl+dQ5hK/+GpOqAcW361OxCtyjIHv+ImDxafagWqj2+w1bg\n\t1HdbBfpB96b6ai1ZTJZby/ONFxSWywZ3loFeSmChaf5C8GEaTVykOQkyKsw89s/fydB72WYiE7+\n\t7Q8mwGI4ZXZpihH9QA5HW/dFUM8XNKmAQu8dgB3qgoF/nNOuNKnM9hSFQduBR4Ih5bJQOYQ/7VW\n\tbKUbQgrnNr3U4tOCDv4EvKaFg==", "X-Received": "by 2002:a05:7300:2203:b0:2d9:7bc4:9578 with SMTP id\n 5a478bee46e88-2e47951a762mr18055125eec.28.1776904124283;\n Wed, 22 Apr 2026 17:28:44 -0700 (PDT)", "From": "\"William A. Kennington III\" <william@wkennington.com>", "To": "Mika Westerberg <mika.westerberg@linux.intel.com>,\n\tAndy Shevchenko <andriy.shevchenko@linux.intel.com>,\n\tJan Dabros <jsd@semihalf.com>,\n\tAndi Shyti <andi.shyti@kernel.org>", "Cc": "\"William A. Kennington III\" <wak@google.com>,\n\tlinux-i2c@vger.kernel.org,\n\tlinux-kernel@vger.kernel.org", "Subject": "[PATCH] i2c: designware: Handle active slave and shutdown cleanly", "Date": "Wed, 22 Apr 2026 17:28:36 -0700", "Message-ID": "<20260423002838.83171-1-william@wkennington.com>", "X-Mailer": "git-send-email 2.54.0.545.g6539524ca2-goog", "Precedence": "bulk", "X-Mailing-List": "linux-i2c@vger.kernel.org", "List-Id": "<linux-i2c.vger.kernel.org>", "List-Subscribe": "<mailto:linux-i2c+subscribe@vger.kernel.org>", "List-Unsubscribe": "<mailto:linux-i2c+unsubscribe@vger.kernel.org>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit" }, "content": "From: \"William A. Kennington III\" <wak@google.com>\n\nWhen the I2C master attempts a new transaction while the slave\ncontroller is shutting down or restarting, it can lead to bus lockups\nand system bootloops if the hardware enters an inconsistent state.\n\nAddress this by ensuring that the internal state machines are properly\ncleared when disabling the controller if slave activity is detected.\n\nAdditionally, add a shutdown hook that gracefully sets the slave\ndisable bit before disabling the controller. This guarantees that any\nincoming requests from the master are immediately NACKed during\nshutdown, preventing the bus from hanging.\n\nSigned-off-by: William A. Kennington III <wak@google.com>\n(cherry picked from src/hw/icebreaker commit 2e825fbffc3b20b5148dde046cb56346ffbe301b)\n---\n drivers/i2c/busses/i2c-designware-common.c | 32 +++++++++++++++++++++\n drivers/i2c/busses/i2c-designware-core.h | 1 +\n drivers/i2c/busses/i2c-designware-master.c | 32 ++++++++++++---------\n drivers/i2c/busses/i2c-designware-pcidrv.c | 15 +++++++++-\n drivers/i2c/busses/i2c-designware-platdrv.c | 13 +++++++++\n 5 files changed, 79 insertions(+), 14 deletions(-)", "diff": "diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c\nindex 4dc57fd56170..31394d8fe612 100644\n--- a/drivers/i2c/busses/i2c-designware-common.c\n+++ b/drivers/i2c/busses/i2c-designware-common.c\n@@ -633,6 +633,14 @@ void __i2c_dw_disable(struct dw_i2c_dev *dev)\n \n \tabort_needed = (raw_intr_stats & DW_IC_INTR_MST_ON_HOLD) ||\n \t\t\t(ic_stats & DW_IC_STATUS_MASTER_HOLD_TX_FIFO_EMPTY);\n+\n+\t/*\n+\t * If we are in slave mode and there is activity, we should also\n+\t * trigger an abort to clear the internal state machines.\n+\t */\n+\tif (dev->mode == DW_IC_SLAVE && (ic_stats & DW_IC_STATUS_SLAVE_ACTIVITY))\n+\t\tabort_needed = true;\n+\n \tif (abort_needed) {\n \t\tif (!(enable & DW_IC_ENABLE_ENABLE)) {\n \t\t\tregmap_write(dev->map, DW_IC_ENABLE, DW_IC_ENABLE_ENABLE);\n@@ -1028,5 +1036,29 @@ EXPORT_GPL_DEV_PM_OPS(i2c_dw_dev_pm_ops) = {\n \tRUNTIME_PM_OPS(i2c_dw_runtime_suspend, i2c_dw_runtime_resume, NULL)\n };\n \n+void i2c_dw_shutdown(struct dw_i2c_dev *dev)\n+{\n+\tunsigned int con;\n+\n+\t/*\n+\t * We only need to handle shutdown for slave mode to ensure\n+\t * we NACK any incoming master requests. Master mode cleanup\n+\t * is handled after each transfer in i2c_dw_xfer.\n+\t */\n+\tif (dev->mode != DW_IC_SLAVE)\n+\t\treturn;\n+\n+\t/*\n+\t * To quickly NACK the master during shutdown, we set the slave\n+\t * disable bit while the controller is still enabled.\n+\t */\n+\tregmap_read(dev->map, DW_IC_CON, &con);\n+\tcon |= DW_IC_CON_SLAVE_DISABLE;\n+\tregmap_write(dev->map, DW_IC_CON, con);\n+\n+\ti2c_dw_disable(dev);\n+}\n+EXPORT_SYMBOL_GPL(i2c_dw_shutdown);\n+\n MODULE_DESCRIPTION(\"Synopsys DesignWare I2C bus adapter core\");\n MODULE_LICENSE(\"GPL\");\ndiff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h\nindex 9d8d104cc391..8b422249acbd 100644\n--- a/drivers/i2c/busses/i2c-designware-core.h\n+++ b/drivers/i2c/busses/i2c-designware-core.h\n@@ -393,6 +393,7 @@ static inline void __i2c_dw_read_intr_mask(struct dw_i2c_dev *dev,\n \n void __i2c_dw_disable(struct dw_i2c_dev *dev);\n void i2c_dw_disable(struct dw_i2c_dev *dev);\n+void i2c_dw_shutdown(struct dw_i2c_dev *dev);\n \n extern void i2c_dw_configure_master(struct dw_i2c_dev *dev);\n extern int i2c_dw_probe_master(struct dw_i2c_dev *dev);\ndiff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c\nindex de929b91d5ea..5b3505faa352 100644\n--- a/drivers/i2c/busses/i2c-designware-master.c\n+++ b/drivers/i2c/busses/i2c-designware-master.c\n@@ -785,19 +785,25 @@ __i2c_dw_xfer_one_part(struct dw_i2c_dev *dev, struct i2c_msg *msgs, size_t num)\n \t * IC_RAW_INTR_STAT.MASTER_ON_HOLD holding SCL low. Check if\n \t * controller is still ACTIVE before disabling I2C.\n \t */\n-\tif (i2c_dw_is_controller_active(dev))\n-\t\tdev_err(dev->dev, \"controller active\\n\");\n-\n-\t/*\n-\t * We must disable the adapter before returning and signaling the end\n-\t * of the current transfer. Otherwise the hardware might continue\n-\t * generating interrupts which in turn causes a race condition with\n-\t * the following transfer. Needs some more investigation if the\n-\t * additional interrupts are a hardware bug or this driver doesn't\n-\t * handle them correctly yet.\n-\t */\n-\t__i2c_dw_disable_nowait(dev);\n-\n+\tif (i2c_dw_is_controller_active(dev)) {\n+\t\t/*\n+\t\t * If the controller is still active after the timeout, attempt a\n+\t\t * bus recovery to clear any potentially locked state.\n+\t\t */\n+\t\tdev_err(dev->dev, \"controller active after xfer, recovering\\n\");\n+\t\ti2c_recover_bus(&dev->adapter);\n+\t\ti2c_dw_init(dev);\n+\t} else {\n+\t\t/*\n+\t\t * We must disable the adapter before returning and signaling the end\n+\t\t * of the current transfer. Otherwise the hardware might continue\n+\t\t * generating interrupts which in turn causes a race condition with\n+\t\t * the following transfer. Needs some more investigation if the\n+\t\t * additional interrupts are a hardware bug or this driver doesn't\n+\t\t * handle them correctly yet.\n+\t\t */\n+\t\t__i2c_dw_disable_nowait(dev);\n+\t}\n \tif (dev->msg_err)\n \t\treturn dev->msg_err;\n \ndiff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c\nindex f21f9877c040..87074655c0e7 100644\n--- a/drivers/i2c/busses/i2c-designware-pcidrv.c\n+++ b/drivers/i2c/busses/i2c-designware-pcidrv.c\n@@ -356,11 +356,24 @@ static const struct pci_device_id i2c_designware_pci_ids[] = {\n };\n MODULE_DEVICE_TABLE(pci, i2c_designware_pci_ids);\n \n+static void i2c_dw_pci_shutdown(struct pci_dev *pdev)\n+{\n+\tstruct dw_i2c_dev *i_dev = pci_get_drvdata(pdev);\n+\n+\tif (!i_dev)\n+\t\treturn;\n+\n+\tpm_runtime_disable(&pdev->dev);\n+\tif (!pm_runtime_status_suspended(&pdev->dev))\n+\t\ti2c_dw_shutdown(i_dev);\n+}\n+\n static struct pci_driver dw_i2c_driver = {\n \t.name\t\t= DRIVER_NAME,\n \t.probe\t\t= i2c_dw_pci_probe,\n \t.remove\t\t= i2c_dw_pci_remove,\n-\t.driver = {\n+\t.shutdown\t= i2c_dw_pci_shutdown,\n+\t.driver\t\t= {\n \t\t.pm\t= pm_ptr(&i2c_dw_dev_pm_ops),\n \t},\n \t.id_table\t= i2c_designware_pci_ids,\ndiff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c\nindex 3351c4a9ef11..7ff7c1631e64 100644\n--- a/drivers/i2c/busses/i2c-designware-platdrv.c\n+++ b/drivers/i2c/busses/i2c-designware-platdrv.c\n@@ -289,9 +289,22 @@ static const struct platform_device_id dw_i2c_platform_ids[] = {\n };\n MODULE_DEVICE_TABLE(platform, dw_i2c_platform_ids);\n \n+static void dw_i2c_plat_shutdown(struct platform_device *pdev)\n+{\n+\tstruct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);\n+\n+\tif (!i_dev)\n+\t\treturn;\n+\n+\tpm_runtime_disable(&pdev->dev);\n+\tif (!pm_runtime_status_suspended(&pdev->dev))\n+\t\ti2c_dw_shutdown(i_dev);\n+}\n+\n static struct platform_driver dw_i2c_driver = {\n \t.probe = dw_i2c_plat_probe,\n \t.remove = dw_i2c_plat_remove,\n+\t.shutdown = dw_i2c_plat_shutdown,\n \t.driver\t\t= {\n \t\t.name\t= \"i2c_designware\",\n \t\t.of_match_table = dw_i2c_of_match,\n", "prefixes": [] }