Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2217869/?format=api
{ "id": 2217869, "url": "http://patchwork.ozlabs.org/api/patches/2217869/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-pci/patch/20260330193347.25072-1-fabio.m.de.francesco@linux.intel.com/", "project": { "id": 28, "url": "http://patchwork.ozlabs.org/api/projects/28/?format=api", "name": "Linux PCI development", "link_name": "linux-pci", "list_id": "linux-pci.vger.kernel.org", "list_email": "linux-pci@vger.kernel.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20260330193347.25072-1-fabio.m.de.francesco@linux.intel.com>", "list_archive_url": null, "date": "2026-03-30T19:33:41", "name": "[RFC,v3] cxl/core: Work around CXL Port PM Init failure when ACS SV enabled", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "ec17db63dab5f07d8fa91588abb421d22e0e8d72", "submitter": { "id": 88588, "url": "http://patchwork.ozlabs.org/api/people/88588/?format=api", "name": "Fabio M. De Francesco", "email": "fabio.m.de.francesco@linux.intel.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/linux-pci/patch/20260330193347.25072-1-fabio.m.de.francesco@linux.intel.com/mbox/", "series": [ { "id": 498086, "url": "http://patchwork.ozlabs.org/api/series/498086/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-pci/list/?series=498086", "date": "2026-03-30T19:33:41", "name": "[RFC,v3] cxl/core: Work around CXL Port PM Init failure when ACS SV enabled", "version": 3, "mbox": "http://patchwork.ozlabs.org/series/498086/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2217869/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2217869/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "\n <linux-pci+bounces-51496-incoming=patchwork.ozlabs.org@vger.kernel.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "linux-pci@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=intel.com header.i=@intel.com header.a=rsa-sha256\n header.s=Intel header.b=dL1dOGKd;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c0a:e001:db::12fc:5321; helo=sea.lore.kernel.org;\n envelope-from=linux-pci+bounces-51496-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)", "smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com\n header.b=\"dL1dOGKd\"", "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=198.175.65.9", "smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=linux.intel.com", "smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=linux.intel.com" ], "Received": [ "from sea.lore.kernel.org (sea.lore.kernel.org\n [IPv6:2600:3c0a:e001:db::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 4fl1jY5C2Rz1xtJ\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 31 Mar 2026 06:37:21 +1100 (AEDT)", "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sea.lore.kernel.org (Postfix) with ESMTP id D0E34301981D\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 30 Mar 2026 19:33:59 +0000 (UTC)", "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 25166399356;\n\tMon, 30 Mar 2026 19:33:59 +0000 (UTC)", "from mgamail.intel.com (mgamail.intel.com [198.175.65.9])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 05C52299A84;\n\tMon, 30 Mar 2026 19:33:56 +0000 (UTC)", "from orviesa006.jf.intel.com ([10.64.159.146])\n by orvoesa101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 30 Mar 2026 12:33:56 -0700", "from ettammin-mobl3.ger.corp.intel.com (HELO\n fdefranc-mobl3.intel.com) ([10.245.246.49])\n by orviesa006-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 30 Mar 2026 12:33:52 -0700" ], "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1774899239; cv=none;\n b=tKKJ6q3XbKrt02AGyfg0tBGXrq3AzRA7EQ5Zlgu3z4VT2wfhKzBNeJXea5lOHZTrEzcWn6O7oCnBxzg9LxI9TdVswyDXwxr9tqEw5KEWhr4A62JoqCHGYvfLR0RQcyFCYPD2KdXxQcxR+JeKe82Tu6r0tsUt+nL+svMlWqRm1YA=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1774899239; c=relaxed/simple;\n\tbh=14W3FkkKF2FOF/YcWpKfpYqjRdWn4aylvVNQ2yfGZUQ=;\n\th=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Content-Type;\n b=MX2JZl/bdnnO/lyPAjbW4s9YqIOx5nERXPk67n2F4jjm63KpDsvfR2fRt90xR8R++uuo7x+HmmjvqEhj7ULvmRBVa3r8MnsbErGAHldKAYj6rZro9ScW3ixATLxKmJY7TOUR3kuBeYLYAgqlqq9uauyslEuAp+BFEtlFG8LOe5A=", "ARC-Authentication-Results": "i=1; smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=linux.intel.com;\n spf=pass smtp.mailfrom=linux.intel.com;\n dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com\n header.b=dL1dOGKd; arc=none smtp.client-ip=198.175.65.9", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple;\n d=intel.com; i=@intel.com; q=dns/txt; s=Intel;\n t=1774899237; x=1806435237;\n h=from:to:cc:subject:date:message-id:mime-version:\n content-transfer-encoding;\n bh=14W3FkkKF2FOF/YcWpKfpYqjRdWn4aylvVNQ2yfGZUQ=;\n b=dL1dOGKd907BKhfxXYgHnpofOpgvzBfkA+8lLMpF00yo4OyfqKcpz3SJ\n QFHYGvUM5+K8us7pg1AxhpIVB+fe2wJJn4BNEHUlgpyyCWCTXpZnDTiG7\n tQs5PbBgAiYxmAliCAvZ62sDh0LRnUlChlvWhSYvyJaCVDr1PEI0JdkWM\n 33z4L0dj1vZ+V786fNrWHTnaNvUzLFT2pZPUI171zWBXpfAdbkFBuVpvk\n OYTfYyZbplRSRgwBrtnMu68JfYa1Mkl/1hDSXN6V3CDpe3RZM59L+ivNz\n Ms3dhSjvAKLshAyQTbiYZghOm5wOYudlEEQJV3rHd8sXpe8GRxJsGkQg/\n w==;", "X-CSE-ConnectionGUID": [ "B6nEiE65R2eeAIbXK2FnqQ==", "NDXhw5oDR9+3UBAKvLIbVg==" ], "X-CSE-MsgGUID": [ "hLKUj+gKQOGK+cGUB0m+5A==", "VsJiOegxSN+d40MeDqd5KA==" ], "X-IronPort-AV": [ "E=McAfee;i=\"6800,10657,11744\"; a=\"98512079\"", "E=Sophos;i=\"6.23,150,1770624000\";\n d=\"scan'208\";a=\"98512079\"", "E=Sophos;i=\"6.23,150,1770624000\";\n d=\"scan'208\";a=\"225158174\"" ], "X-ExtLoop1": "1", "From": "\"Fabio M. De Francesco\" <fabio.m.de.francesco@linux.intel.com>", "To": "linux-cxl@vger.kernel.org", "Cc": "Davidlohr Bueso <dave@stgolabs.net>,\n\tJonathan Cameron <jonathan.cameron@huawei.com>,\n\tDave Jiang <dave.jiang@intel.com>,\n\tAlison Schofield <alison.schofield@intel.com>,\n\tVishal Verma <vishal.l.verma@intel.com>,\n\tIra Weiny <ira.weiny@intel.com>,\n\tDan Williams <dan.j.williams@intel.com>,\n\tBjorn Helgaas <bhelgaas@google.com>,\n\tlinux-kernel@vger.kernel.org,\n\tlinux-pci@vger.kernel.org,\n\t\"Fabio M. De Francesco\" <fabio.m.de.francesco@linux.intel.com>", "Subject": "[RFC PATCH v3] cxl/core: Work around CXL Port PM Init failure when\n ACS SV enabled", "Date": "Mon, 30 Mar 2026 21:33:41 +0200", "Message-ID": "<20260330193347.25072-1-fabio.m.de.francesco@linux.intel.com>", "X-Mailer": "git-send-email 2.53.0", "Precedence": "bulk", "X-Mailing-List": "linux-pci@vger.kernel.org", "List-Id": "<linux-pci.vger.kernel.org>", "List-Subscribe": "<mailto:linux-pci+subscribe@vger.kernel.org>", "List-Unsubscribe": "<mailto:linux-pci+unsubscribe@vger.kernel.org>", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=UTF-8", "Content-Transfer-Encoding": "8bit" }, "content": "Compute Express Link (CXL) Specification Revision 4.0, Version 1.0, Section\n8.1.5.1 - CXL Port Extension Status, Implementation Note, describes a\nscenario where a CXL downstream port may fail PM initialization:\n\n\"Certain conditions such as Link Down, Secondary Bus Reset, or Downstream\nPort Containment reset the Downstream Component’s bus number. If the\nComponent generates the CREDIT_RTN IP2PM message with Requester Bus=0, the\nDownstream Port may reject the IP2PM message if software has enabled ACS\nSource Validation. In this scenario, Power Management initialization may\nfail to complete and another Secondary Bus Reset alone will not facilitate\nrecovery\".\n\nImplement the recommended workaround for this scenario, which involves\nsaving and disabling the ACS Source Validation and Bus Master Enable bits,\nissuing a secondary bus reset, waiting for PM init to complete, and then\nrestoring those bits.\n\nThis is an RFC because it checks for PM init failures in ports enumeration,\nwhere an SBR might not be very welcome. Maybe other call sites are more\nappropriate for this workaround?\n\nSigned-off-by: Fabio M. De Francesco <fabio.m.de.francesco@linux.intel.com>\n---\n\nChanges for v3: \n - match the naming, capitalization, and indentation of two \n definitions with the others in pci_regs.h (Bjorn)\n \nChanges for v2: \n - change subject label from the mistaken PCI (relic of an old \n solution which was later discarded) to cxl/core\n - restore the class storage of sbr_masked() to static (another\n relic of the old solution)\n\n drivers/cxl/core/pci.c | 171 ++++++++++++++++++++++++++++++++++\n drivers/cxl/core/port.c | 19 ++++\n drivers/cxl/cxlpci.h | 3 +\n include/uapi/linux/pci_regs.h | 2 +\n 4 files changed, 195 insertions(+)", "diff": "diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c\nindex f96ce884a213..1e75bd35b0f6 100644\n--- a/drivers/cxl/core/pci.c\n+++ b/drivers/cxl/core/pci.c\n@@ -869,3 +869,174 @@ int cxl_port_get_possible_dports(struct cxl_port *port)\n \n \treturn ctx.count;\n }\n+\n+struct pci_saved_flags {\n+\tu16 pci_command;\n+\tu16 acs_ctrl;\n+};\n+\n+/*\n+ * pci_disable_acs_bme - disable ACS Source Validation and BME\n+ * @pdev: downstream port\n+ * @saved: pointer to pci_saved_acs_bme struct, for saving bit values\n+ *\n+ * Save the current ACS Source Validation and Bus Master Enable (BME)\n+ * bits before disabling them.\n+ */\n+static void pci_disable_acs_bme(struct pci_dev *pdev,\n+\t\t\t\tstruct pci_saved_flags *saved)\n+{\n+\tint pos;\n+\tu16 field;\n+\n+\tpos = pdev->acs_cap;\n+\tif (!pos)\n+\t\treturn;\n+\n+\tpci_read_config_word(pdev, pos + PCI_ACS_CTRL, &field);\n+\tsaved->acs_ctrl = field;\n+\n+\tif (field & PCI_ACS_SV)\n+\t\tpci_write_config_word(pdev, pos + PCI_ACS_CTRL,\n+\t\t\t\t field & ~PCI_ACS_SV);\n+\n+\tpci_read_config_word(pdev, PCI_COMMAND, &field);\n+\tsaved->pci_command = field;\n+\n+\tif (field & PCI_COMMAND_MASTER)\n+\t\tpci_clear_master(pdev);\n+}\n+\n+/*\n+ * pci_enable_acs_bme - enable ACS Source Validation and BME\n+ * @pdev: downstream port\n+ * @saved: pointer to pci_saved_acs_bme struct, for restoring bit values\n+ *\n+ * Restore the previously saved ACS Source Validation and Bus Master\n+ * Enable (BME) bits.\n+ */\n+static void pci_enable_acs_bme(struct pci_dev *pdev,\n+\t\t\t struct pci_saved_flags *saved)\n+{\n+\tint pos;\n+\tu16 field;\n+\n+\tpos = pdev->acs_cap;\n+\tif (!pos)\n+\t\treturn;\n+\n+\tpci_read_config_word(pdev, pos + PCI_ACS_CTRL, &field);\n+\tif (saved->acs_ctrl & PCI_ACS_SV)\n+\t\tpci_write_config_word(pdev, pos + PCI_ACS_CTRL,\n+\t\t\t\t field | PCI_ACS_SV);\n+\n+\tpci_read_config_word(pdev, PCI_COMMAND, &field);\n+\tif (saved->pci_command & PCI_COMMAND_MASTER)\n+\t\tpci_set_master(pdev);\n+}\n+\n+/**\n+ * cxl_port_pm_init_is_complete - check if the downstream port has completed PM\n+ * init\n+ *\n+ * @pdev: downstream port\n+ *\n+ * Check if the Port Power Management Initialization Complete bit is set in the\n+ * Downstream Port's CXL DVSEC Port Extended Status register.\n+ *\n+ * Returns true if PM init is complete, false otherwise.\n+ */\n+bool cxl_port_pm_init_is_complete(struct pci_dev *pdev)\n+{\n+\tint pm_init_complete;\n+\tu16 status;\n+\tu16 dvsec;\n+\n+\tdvsec = pci_find_dvsec_capability(pdev, PCI_VENDOR_ID_CXL,\n+\t\t\t\t\t PCI_DVSEC_CXL_PORT);\n+\tif (!dvsec)\n+\t\treturn false;\n+\n+\tpci_read_config_word(pdev, dvsec + PCI_DVSEC_CXL_PORT_EXT_STATUS,\n+\t\t\t &status);\n+\tpm_init_complete = FIELD_GET(PCI_DVSEC_CXL_PORT_EXT_STATUS_PM_INIT_COMP,\n+\t\t\t\t status);\n+\n+\treturn !!pm_init_complete;\n+}\n+\n+static void mask_sbr(struct pci_dev *pdev)\n+{\n+\tint dvsec;\n+\tu16 reg;\n+\n+\tdvsec = pci_find_dvsec_capability(pdev, PCI_VENDOR_ID_CXL,\n+\t\t\t\t\t PCI_DVSEC_CXL_PORT);\n+\tif (!dvsec)\n+\t\treturn;\n+\n+\tpci_read_config_word(pdev, dvsec + PCI_DVSEC_CXL_PORT_CTL, ®);\n+\n+\tpci_write_config_word(pdev, dvsec + PCI_DVSEC_CXL_PORT_CTL,\n+\t\t\t reg & ~PCI_DVSEC_CXL_PORT_CTL_UNMASK_SBR);\n+}\n+\n+static void unmask_sbr(struct pci_dev *pdev)\n+{\n+\tint dvsec;\n+\tu16 reg;\n+\n+\tdvsec = pci_find_dvsec_capability(pdev, PCI_VENDOR_ID_CXL,\n+\t\t\t\t\t PCI_DVSEC_CXL_PORT);\n+\tif (!dvsec)\n+\t\treturn;\n+\n+\tpci_read_config_word(pdev, dvsec + PCI_DVSEC_CXL_PORT_CTL, ®);\n+\n+\tpci_write_config_word(pdev, dvsec + PCI_DVSEC_CXL_PORT_CTL,\n+\t\t\t reg | PCI_DVSEC_CXL_PORT_CTL_UNMASK_SBR);\n+}\n+\n+/**\n+ * cxl_port_retry_failed_pm_init - retry a downstream port's failed PM init\n+ *\n+ * @pdev: downstream port\n+ *\n+ * Retry a downstream CXL port's failed PM init according to CXL Erratum for\n+ * Section 8.1.5.1 - Port Power Management Initialization Complete.\n+ *\n+ * This entails saving and disabling the ACS Source Validation and Bus Master\n+ * enable bits, and unmasking and masking the SBR, before doing a secondary bus\n+ * reset and then restoring and re-enabling those bits.\n+ *\n+ * return: 0 on success, errors otherwise.\n+ */\n+int cxl_port_retry_failed_pm_init(struct pci_dev *pdev)\n+{\n+\tstruct pci_saved_flags saved;\n+\tint ret;\n+\n+\tif (!is_cxl_port(pdev->dev.parent))\n+\t\treturn -EINVAL;\n+\n+\tpci_disable_acs_bme(pdev, &saved);\n+\tunmask_sbr(pdev);\n+\n+\t/* Generate Secondary Bus Reset */\n+\tret = pci_reset_bus(pdev);\n+\tif (ret)\n+\t\tdev_dbg(&pdev->dev, \"Bus reset failed: %d\\n\", ret);\n+\n+\t/*\n+\t * Wait until the Port Power Management Initialization\n+\t * Complete bit is set in the Downstream Port. CXL Spec 4.0\n+\t * Section 8.1.5.1 of the CXL spec specifies 100 ms as the\n+\t * max time needed for the PM Init Complete bit to be set.\n+\t */\n+\tmsleep(100);\n+\n+\tmask_sbr(pdev);\n+\tpci_enable_acs_bme(pdev, &saved);\n+\n+\treturn ret;\n+}\ndiff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c\nindex b69c2529744c..62fabcdf0faf 100644\n--- a/drivers/cxl/core/port.c\n+++ b/drivers/cxl/core/port.c\n@@ -1829,12 +1829,31 @@ int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd)\n retry:\n \tfor (iter = dev; iter; iter = grandparent(iter)) {\n \t\tstruct device *dport_dev = grandparent(iter);\n+\t\tstruct pci_dev *dport_pdev = to_pci_dev(dport_dev);\n \t\tstruct device *uport_dev;\n \t\tstruct cxl_dport *dport;\n \n \t\tif (is_cxl_host_bridge(dport_dev))\n \t\t\treturn 0;\n \n+\t\t/*\n+\t\t * Check the downstream port's PM init status, and if it has\n+\t\t * failed retry PM init according to CXL Spec. 4.0 Sect. 8.1.5.1\n+\t\t * - Implementation Note\n+\t\t */\n+\t\tif (!cxl_port_pm_init_is_complete(dport_pdev)) {\n+\t\t\tdev_dbg(&cxlmd->dev,\n+\t\t\t\t\"PM init failed for %s, retrying PM init\\n\",\n+\t\t\t\tdev_name(dport_dev));\n+\n+\t\t\tcxl_port_retry_failed_pm_init(dport_pdev);\n+\n+\t\t\tif (!cxl_port_pm_init_is_complete(dport_pdev))\n+\t\t\t\tdev_dbg(&cxlmd->dev,\n+\t\t\t\t\t\"PM init failed retry for %s\\n\",\n+\t\t\t\t\tdev_name(dport_dev));\n+\t\t}\n+\n \t\tuport_dev = dport_dev->parent;\n \t\tif (!uport_dev) {\n \t\t\tdev_warn(dev, \"at %s no parent for dport: %s\\n\",\ndiff --git a/drivers/cxl/cxlpci.h b/drivers/cxl/cxlpci.h\nindex 0cf64218aa16..0458096be2c4 100644\n--- a/drivers/cxl/cxlpci.h\n+++ b/drivers/cxl/cxlpci.h\n@@ -101,4 +101,7 @@ static inline void devm_cxl_port_ras_setup(struct cxl_port *port)\n }\n #endif\n \n+bool cxl_port_pm_init_is_complete(struct pci_dev *pdev);\n+int cxl_port_retry_failed_pm_init(struct pci_dev *pdev);\n+\n #endif /* __CXL_PCI_H__ */\ndiff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h\nindex ec1c54b5a310..6e0b81b2351b 100644\n--- a/include/uapi/linux/pci_regs.h\n+++ b/include/uapi/linux/pci_regs.h\n@@ -1369,6 +1369,8 @@\n \n /* CXL r4.0, 8.1.5: Extensions DVSEC for Ports */\n #define PCI_DVSEC_CXL_PORT\t\t\t\t3\n+#define PCI_DVSEC_CXL_PORT_EXT_STATUS\t\t\t0x0A\n+#define PCI_DVSEC_CXL_PORT_EXT_STATUS_PM_INIT_COMP\t_BITUL(0)\n #define PCI_DVSEC_CXL_PORT_CTL\t\t\t\t0x0c\n #define PCI_DVSEC_CXL_PORT_CTL_UNMASK_SBR\t\t0x00000001\n \n", "prefixes": [ "RFC", "v3" ] }