From patchwork Thu Nov 10 19:50:09 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Derrick X-Patchwork-Id: 13039275 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id F1F6DC43219 for ; Thu, 10 Nov 2022 19:53:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230467AbiKJTxe (ORCPT ); Thu, 10 Nov 2022 14:53:34 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46690 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230422AbiKJTxc (ORCPT ); Thu, 10 Nov 2022 14:53:32 -0500 Received: from resdmta-h1p-028597.sys.comcast.net (resdmta-h1p-028597.sys.comcast.net [IPv6:2001:558:fd02:2446::d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4EDBA47336 for ; Thu, 10 Nov 2022 11:53:19 -0800 (PST) Received: from resomta-h1p-027912.sys.comcast.net ([96.102.179.201]) by resdmta-h1p-028597.sys.comcast.net with ESMTP id tCeRofXGGwwPvtDZYoNduH; Thu, 10 Nov 2022 19:50:48 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=comcastmailservice.net; s=20211018a; t=1668109848; bh=Way0DAlL2ACj9a+XKDlJAFMBT/Xv2jTSB4J5Mymp4EY=; h=Received:Received:From:To:Subject:Date:Message-Id:MIME-Version: Xfinity-Spam-Result; b=Jd6DCUAG1EkFhnB4AtYmQsa2gV+f9s1dU+Qe29DVxNiCCp1H1JKQ325+arJXxBaP5 rM0o/eaJ35AcKCpgUsZ4GYYiXedDt3XPoBojxGbI9WXoPzAB+2Hu5W+f+p/OJSYE2m WugCtQmLeouW7Qdni7pvejpSQfID/9HWDqZ7B8JSyoxyosJpHZ4QPPdmPTRp+wzgJs hZgCi2xhs8qxi1uwIEYWFaOdIq+4tomSW5ii12obDBNy3x8BlCKQjNR/75A/AcSRLs oaua5iy6WkCNy9i8wKIa7VmQPCjdygtLARKu1ZNzpkYoYt/5fIw9hwSR4ep6BQ3F2E GSQcsqLRQKaGw== Received: from jderrick-mobl4.amr.corp.intel.com ([71.205.181.50]) by resomta-h1p-027912.sys.comcast.net with ESMTPA id tDZ4oZTHiVTvltDZDoklht; Thu, 10 Nov 2022 19:50:28 +0000 X-Xfinity-VAAS: gggruggvucftvghtrhhoucdtuddrgedvgedrfeeggddufeduucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuvehomhgtrghsthdqtfgvshhipdfqfgfvpdfpqffurfetoffkrfenuceurghilhhouhhtmecufedtudenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujfgurhephffvvefufffkofgjfhgggfestdekredtredttdenucfhrhhomheplfhonhgrthhhrghnucffvghrrhhitghkuceojhhonhgrthhhrghnrdguvghrrhhitghksehlihhnuhigrdguvghvqeenucggtffrrghtthgvrhhnpedtteeljeffgfffveehhfetveefuedvheevffffhedtjeeuvdevgfeftddtheeftdenucfkphepjedurddvtdehrddukedurdehtdenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhephhgvlhhopehjuggvrhhrihgtkhdqmhhosghlgedrrghmrhdrtghorhhprdhinhhtvghlrdgtohhmpdhinhgvthepjedurddvtdehrddukedurdehtddpmhgrihhlfhhrohhmpehjohhnrghthhgrnhdruggvrhhrihgtkheslhhinhhugidruggvvhdpnhgspghrtghpthhtohepkedprhgtphhtthhopehvihguhigrshesnhhvihguihgrrdgtohhmpdhrtghpthhtohepmhgrnhhisehkvghrnhgvlhdrohhrghdprhgtphhtthhopehlohhrvghniihordhpihgvrhgrlhhishhisegrrhhmrdgtohhmpdhrtghpthhtohephhgvlhhgrggrsheskhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinh hugidqphgtihesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehluhhkrghsseifuhhnnhgvrhdruggvpdhrtghpthhtohepphgrlhhisehkvghrnhgvlhdrohhrghdprhgtphhtthhopehjohhnrghthhgrnhdruggvrhhrihgtkheslhhinhhugidruggvvh X-Xfinity-VMeta: sc=-100.00;st=legit From: Jonathan Derrick To: Vidya Sagar Cc: Manivannan Sadhasivam , Lorenzo Pieralisi , Bjorn Helgaas , , Lukas Wunner , =?utf-8?q?Pali_Roh=C3=A1r?= , Jonathan Derrick Subject: [PATCH v2 1/7] PCI: Allow for indirecting capability registers Date: Thu, 10 Nov 2022 12:50:09 -0700 Message-Id: <20221110195015.207-2-jonathan.derrick@linux.dev> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20221110195015.207-1-jonathan.derrick@linux.dev> References: <20221110195015.207-1-jonathan.derrick@linux.dev> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org Allow another driver to provide alternative operations when doing capability register reads and writes. The intention is to have pcie_bridge_emul provide alternate handlers for the Slot Capabilities, Slot Control, and Slot Status registers. Alternate handlers can return > 0 if unhandled, errno on error, or 0 on success. This could potentially be used to handle quirks in a different manner. Signed-off-by: Jonathan Derrick --- drivers/pci/access.c | 29 +++++++++++++++++++++++++++++ include/linux/pci.h | 11 +++++++++++ 2 files changed, 40 insertions(+) diff --git a/drivers/pci/access.c b/drivers/pci/access.c index 708c7529647f..dbfea6824bd4 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c @@ -424,6 +424,17 @@ int pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val) return ret; } + if (dev->caps_rw_ops) { + u32 reg; + ret = dev->caps_rw_ops->read(dev, pos, 4, ®); + if (!ret) { + *val = reg & 0xffff; + return ret; + } else if (ret < 0) { + return ret; + } + } + /* * For Functions that do not implement the Slot Capabilities, * Slot Status, and Slot Control registers, these spaces must @@ -459,6 +470,12 @@ int pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *val) return ret; } + if (dev->caps_rw_ops) { + ret = dev->caps_rw_ops->read(dev, pos, 4, val); + if (ret <= 0) + return ret; + } + if (pci_is_pcie(dev) && pcie_downstream_port(dev) && pos == PCI_EXP_SLTSTA) *val = PCI_EXP_SLTSTA_PDS; @@ -475,6 +492,12 @@ int pcie_capability_write_word(struct pci_dev *dev, int pos, u16 val) if (!pcie_capability_reg_implemented(dev, pos)) return 0; + if (dev->caps_rw_ops) { + int ret = dev->caps_rw_ops->write(dev, pos, 2, val); + if (ret <= 0) + return ret; + } + return pci_write_config_word(dev, pci_pcie_cap(dev) + pos, val); } EXPORT_SYMBOL(pcie_capability_write_word); @@ -487,6 +510,12 @@ int pcie_capability_write_dword(struct pci_dev *dev, int pos, u32 val) if (!pcie_capability_reg_implemented(dev, pos)) return 0; + if (dev->caps_rw_ops) { + int ret = dev->caps_rw_ops->write(dev, pos, 4, val); + if (ret <= 0) + return ret; + } + return pci_write_config_dword(dev, pci_pcie_cap(dev) + pos, val); } EXPORT_SYMBOL(pcie_capability_write_dword); diff --git a/include/linux/pci.h b/include/linux/pci.h index 2bda4a4e47e8..ff47ef83ab38 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -311,6 +311,15 @@ struct pci_vpd { u8 cap; }; +/* + * Capability reads/write redirect + * Returns 0, errno, or > 0 if unhandled + */ +struct caps_rw_ops { + int (*read)(struct pci_dev *dev, int pos, int len, u32 *val); + int (*write)(struct pci_dev *dev, int pos, int len, u32 val); +}; + struct irq_affinity; struct pcie_link_state; struct pci_sriov; @@ -523,6 +532,8 @@ struct pci_dev { /* These methods index pci_reset_fn_methods[] */ u8 reset_methods[PCI_NUM_RESET_METHODS]; /* In priority order */ + + struct caps_rw_ops *caps_rw_ops; }; static inline struct pci_dev *pci_physfn(struct pci_dev *dev) From patchwork Thu Nov 10 19:50:10 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Derrick X-Patchwork-Id: 13039279 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C0886C4321E for ; Thu, 10 Nov 2022 19:53:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229757AbiKJTxi (ORCPT ); Thu, 10 Nov 2022 14:53:38 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46770 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231262AbiKJTxc (ORCPT ); Thu, 10 Nov 2022 14:53:32 -0500 Received: from resdmta-h1p-028598.sys.comcast.net (resdmta-h1p-028598.sys.comcast.net [IPv6:2001:558:fd02:2446::e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 72B0B48770 for ; Thu, 10 Nov 2022 11:53:19 -0800 (PST) Received: from resomta-h1p-027912.sys.comcast.net ([96.102.179.201]) by resdmta-h1p-028598.sys.comcast.net with ESMTP id tC1fo6ojOpchHtDZYoLN1D; Thu, 10 Nov 2022 19:50:48 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=comcastmailservice.net; s=20211018a; t=1668109848; bh=NLTClUwuOqPb+DvZnmkPWSVY7cPj58FgQv8QIi+tOjY=; h=Received:Received:From:To:Subject:Date:Message-Id:MIME-Version: Xfinity-Spam-Result; b=kAyw+IFh8QzXJh/D8lEvh5kTU9KLSZ9sd88a2FE5QRToVPVeC3zvTpav5/+TTuOBZ rYHNyRVNziuwpmr+2XSQKxLjlJ+qq71P97i4izyad/0/MsCUo189Q0WD11mZuch4Iq PgT9AKTf0xdOAhSBfwuyAt11rKUeZCpsGAfTU2mS1CxniLSwrA/aYpaMZZC4h/I9ha d3dkTcHXVPIqa3MZ/jT5Ybvd6dB8FT4bjOHlyjiVY0ROKd8ffNhc+nbEP+KuAs0C4I Tg/O353UDIXTyYc6geY28fOBhN4k7Y5vzpQR8ewMr+6FcBmWja02okYVEq35Pd5xfZ 3eXf3sqvIjmag== Received: from jderrick-mobl4.amr.corp.intel.com ([71.205.181.50]) by resomta-h1p-027912.sys.comcast.net with ESMTPA id tDZ4oZTHiVTvltDZEoklhz; Thu, 10 Nov 2022 19:50:29 +0000 X-Xfinity-VAAS: gggruggvucftvghtrhhoucdtuddrgedvgedrfeeggddufeduucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuvehomhgtrghsthdqtfgvshhipdfqfgfvpdfpqffurfetoffkrfenuceurghilhhouhhtmecufedtudenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujfgurhephffvvefufffkofgjfhgggfestdekredtredttdenucfhrhhomheplfhonhgrthhhrghnucffvghrrhhitghkuceojhhonhgrthhhrghnrdguvghrrhhitghksehlihhnuhigrdguvghvqeenucggtffrrghtthgvrhhnpedtteeljeffgfffveehhfetveefuedvheevffffhedtjeeuvdevgfeftddtheeftdenucfkphepjedurddvtdehrddukedurdehtdenucevlhhushhtvghrufhiiigvpedunecurfgrrhgrmhephhgvlhhopehjuggvrhhrihgtkhdqmhhosghlgedrrghmrhdrtghorhhprdhinhhtvghlrdgtohhmpdhinhgvthepjedurddvtdehrddukedurdehtddpmhgrihhlfhhrohhmpehjohhnrghthhgrnhdruggvrhhrihgtkheslhhinhhugidruggvvhdpnhgspghrtghpthhtohepkedprhgtphhtthhopehvihguhigrshesnhhvihguihgrrdgtohhmpdhrtghpthhtohepmhgrnhhisehkvghrnhgvlhdrohhrghdprhgtphhtthhopehlohhrvghniihordhpihgvrhgrlhhishhisegrrhhmrdgtohhmpdhrtghpthhtohephhgvlhhgrggrsheskhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinh hugidqphgtihesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehluhhkrghsseifuhhnnhgvrhdruggvpdhrtghpthhtohepphgrlhhisehkvghrnhgvlhdrohhrghdprhgtphhtthhopehjohhnrghthhgrnhdruggvrhhrihgtkheslhhinhhugidruggvvh X-Xfinity-VMeta: sc=-100.00;st=legit From: Jonathan Derrick To: Vidya Sagar Cc: Manivannan Sadhasivam , Lorenzo Pieralisi , Bjorn Helgaas , , Lukas Wunner , =?utf-8?q?Pali_Roh=C3=A1r?= , Jonathan Derrick Subject: [PATCH v2 2/7] PCI: Add pcie_port_slot_emulated stub Date: Thu, 10 Nov 2022 12:50:10 -0700 Message-Id: <20221110195015.207-3-jonathan.derrick@linux.dev> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20221110195015.207-1-jonathan.derrick@linux.dev> References: <20221110195015.207-1-jonathan.derrick@linux.dev> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org Add the checks to allow an emulated slot. An emulated slot will use native Hotplug, AER, and PME services. It also needs to specify itself as a hotplug bridge in order for bridge sizing to account for hotplug reserved windows. Signed-off-by: Jonathan Derrick --- drivers/pci/pci-acpi.c | 3 +++ drivers/pci/pcie/portdrv_core.c | 9 ++++++--- drivers/pci/probe.c | 2 +- include/linux/pci.h | 2 ++ 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index a46fec776ad7..77a3c9e39966 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -798,6 +798,9 @@ bool pciehp_is_native(struct pci_dev *bridge) if (!IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE)) return false; + if (pcie_port_slot_emulated(bridge)) + return true; + pcie_capability_read_dword(bridge, PCI_EXP_SLTCAP, &slot_cap); if (!(slot_cap & PCI_EXP_SLTCAP_HPC)) return false; diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index 1ac7fec47d6f..b3c1e7d4ff10 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -209,7 +209,8 @@ static int get_port_device_capability(struct pci_dev *dev) int services = 0; if (dev->is_hotplug_bridge && - (pcie_ports_native || host->native_pcie_hotplug)) { + (pcie_ports_native || pcie_port_slot_emulated(dev) || + host->native_pcie_hotplug)) { services |= PCIE_PORT_SERVICE_HP; /* @@ -222,14 +223,16 @@ static int get_port_device_capability(struct pci_dev *dev) #ifdef CONFIG_PCIEAER if (dev->aer_cap && pci_aer_available() && - (pcie_ports_native || host->native_aer)) + (pcie_ports_native || pcie_port_slot_emulated(dev) || + host->native_aer)) services |= PCIE_PORT_SERVICE_AER; #endif /* Root Ports and Root Complex Event Collectors may generate PMEs */ if ((pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT || pci_pcie_type(dev) == PCI_EXP_TYPE_RC_EC) && - (pcie_ports_native || host->native_pme)) { + (pcie_ports_native || pcie_port_slot_emulated(dev) || + host->native_pme)) { services |= PCIE_PORT_SERVICE_PME; /* diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index b66fa42c4b1f..86ac4d223eba 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1574,7 +1574,7 @@ void set_pcie_hotplug_bridge(struct pci_dev *pdev) u32 reg32; pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, ®32); - if (reg32 & PCI_EXP_SLTCAP_HPC) + if (reg32 & PCI_EXP_SLTCAP_HPC || pcie_port_slot_emulated(pdev)) pdev->is_hotplug_bridge = 1; } diff --git a/include/linux/pci.h b/include/linux/pci.h index ff47ef83ab38..09f704337955 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1655,6 +1655,8 @@ extern bool pcie_ports_native; #define pcie_ports_native false #endif +#define pcie_port_slot_emulated(dev) false + #define PCIE_LINK_STATE_L0S BIT(0) #define PCIE_LINK_STATE_L1 BIT(1) #define PCIE_LINK_STATE_CLKPM BIT(2) From patchwork Thu Nov 10 19:50:11 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Derrick X-Patchwork-Id: 13039274 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D0F3DC43217 for ; Thu, 10 Nov 2022 19:53:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230320AbiKJTxf (ORCPT ); Thu, 10 Nov 2022 14:53:35 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46694 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231207AbiKJTxc (ORCPT ); Thu, 10 Nov 2022 14:53:32 -0500 Received: from resqmta-h1p-028593.sys.comcast.net (resqmta-h1p-028593.sys.comcast.net [IPv6:2001:558:fd02:2446::7]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 583B548752 for ; Thu, 10 Nov 2022 11:53:19 -0800 (PST) Received: from resomta-h1p-027912.sys.comcast.net ([96.102.179.201]) by resqmta-h1p-028593.sys.comcast.net with ESMTP id tC1fouOrcAj3ltDZYogyp9; Thu, 10 Nov 2022 19:50:48 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=comcastmailservice.net; s=20211018a; t=1668109848; bh=uZ0DssvlJMaoYvlaYu/eog/eR5+SHYKYU+32z9Q9ZIw=; h=Received:Received:From:To:Subject:Date:Message-Id:MIME-Version: Xfinity-Spam-Result; b=PT9AMIyO//Us2zznBwAkRFZmqnBpwM7r/fJVUPDr09cbr2RuT5W76cRToqYxdZTia p8hrX1iCoHzLn/XZqJoG3XQ5yNb6qSXF8zQsDE8ebmrE4uZBw+2gjOdmCEujRPwfee gV+sNurSQexmqbUg5InLvPA/KYLE0W8zblYl40uY5jSg8YpXjQxMlErf/icFBuuOlg Ni+Zt8LOjDu3EBOGdJVshYFwquv0AFlgH+wuJ2DdzjQ7JMZh9kPw0iJPM/73mC6llG tAh74e+PmV3+cDI99gmy2XFl0fRe17yvJNCqvS/2vkuZlNGP1WvNiRzSGUUJDaLkW3 2AgfX9Y6RaFkg== Received: from jderrick-mobl4.amr.corp.intel.com ([71.205.181.50]) by resomta-h1p-027912.sys.comcast.net with ESMTPA id tDZ4oZTHiVTvltDZFokli2; Thu, 10 Nov 2022 19:50:30 +0000 X-Xfinity-VAAS: gggruggvucftvghtrhhoucdtuddrgedvgedrfeeggddufeduucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuvehomhgtrghsthdqtfgvshhipdfqfgfvpdfpqffurfetoffkrfenuceurghilhhouhhtmecufedtudenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujfgurhephffvvefufffkofgjfhgggfestdekredtredttdenucfhrhhomheplfhonhgrthhhrghnucffvghrrhhitghkuceojhhonhgrthhhrghnrdguvghrrhhitghksehlihhnuhigrdguvghvqeenucggtffrrghtthgvrhhnpedtteeljeffgfffveehhfetveefuedvheevffffhedtjeeuvdevgfeftddtheeftdenucfkphepjedurddvtdehrddukedurdehtdenucevlhhushhtvghrufhiiigvpedunecurfgrrhgrmhephhgvlhhopehjuggvrhhrihgtkhdqmhhosghlgedrrghmrhdrtghorhhprdhinhhtvghlrdgtohhmpdhinhgvthepjedurddvtdehrddukedurdehtddpmhgrihhlfhhrohhmpehjohhnrghthhgrnhdruggvrhhrihgtkheslhhinhhugidruggvvhdpnhgspghrtghpthhtohepkedprhgtphhtthhopehvihguhigrshesnhhvihguihgrrdgtohhmpdhrtghpthhtohepmhgrnhhisehkvghrnhgvlhdrohhrghdprhgtphhtthhopehlohhrvghniihordhpihgvrhgrlhhishhisegrrhhmrdgtohhmpdhrtghpthhtohephhgvlhhgrggrsheskhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinh hugidqphgtihesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehluhhkrghsseifuhhnnhgvrhdruggvpdhrtghpthhtohepphgrlhhisehkvghrnhgvlhdrohhrghdprhgtphhtthhopehjohhnrghthhgrnhdruggvrhhrihgtkheslhhinhhugidruggvvh X-Xfinity-VMeta: sc=-100.00;st=legit From: Jonathan Derrick To: Vidya Sagar Cc: Manivannan Sadhasivam , Lorenzo Pieralisi , Bjorn Helgaas , , Lukas Wunner , =?utf-8?q?Pali_Roh=C3=A1r?= , Jonathan Derrick Subject: [PATCH v2 3/7] PCI: pciehp: Expose the poll loop to other drivers Date: Thu, 10 Nov 2022 12:50:11 -0700 Message-Id: <20221110195015.207-4-jonathan.derrick@linux.dev> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20221110195015.207-1-jonathan.derrick@linux.dev> References: <20221110195015.207-1-jonathan.derrick@linux.dev> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org Abstract the poll loop into an 'events pending' check and a 'handle events' method in order to allow another driver to call the polling loop. Signed-off-by: Jonathan Derrick --- drivers/pci/hotplug/pciehp.h | 2 ++ drivers/pci/hotplug/pciehp_hpc.c | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index e0a614acee05..e221f5d12ad5 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -157,6 +157,8 @@ struct controller { #define NO_CMD_CMPL(ctrl) ((ctrl)->slot_cap & PCI_EXP_SLTCAP_NCCS) #define PSN(ctrl) (((ctrl)->slot_cap & PCI_EXP_SLTCAP_PSN) >> 19) +bool pciehp_events_pending(struct controller *ctrl); +void pciehp_handle_events(struct controller *ctrl); void pciehp_request(struct controller *ctrl, int action); void pciehp_handle_button_press(struct controller *ctrl); void pciehp_handle_disable_request(struct controller *ctrl); diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 040ae076ec0e..f711448e0a70 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -764,6 +764,17 @@ static irqreturn_t pciehp_ist(int irq, void *dev_id) return ret; } +bool pciehp_events_pending(struct controller *ctrl) +{ + return pciehp_isr(IRQ_NOTCONNECTED, ctrl) == IRQ_WAKE_THREAD || + atomic_read(&ctrl->pending_events); +} + +void pciehp_handle_events(struct controller *ctrl) +{ + pciehp_ist(IRQ_NOTCONNECTED, ctrl); +} + static int pciehp_poll(void *data) { struct controller *ctrl = data; @@ -772,9 +783,8 @@ static int pciehp_poll(void *data) while (!kthread_should_stop()) { /* poll for interrupt events or user requests */ - while (pciehp_isr(IRQ_NOTCONNECTED, ctrl) == IRQ_WAKE_THREAD || - atomic_read(&ctrl->pending_events)) - pciehp_ist(IRQ_NOTCONNECTED, ctrl); + while (pciehp_events_pending(ctrl)) + pciehp_handle_events(ctrl); if (pciehp_poll_time <= 0 || pciehp_poll_time > 60) pciehp_poll_time = 2; /* clamp to sane value */ From patchwork Thu Nov 10 19:50:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Derrick X-Patchwork-Id: 13039273 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BCB6DC433FE for ; Thu, 10 Nov 2022 19:53:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229894AbiKJTxe (ORCPT ); Thu, 10 Nov 2022 14:53:34 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46692 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230320AbiKJTxc (ORCPT ); Thu, 10 Nov 2022 14:53:32 -0500 X-Greylist: delayed 150 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Thu, 10 Nov 2022 11:53:19 PST Received: from resqmta-h1p-028588.sys.comcast.net (resqmta-h1p-028588.sys.comcast.net [IPv6:2001:558:fd02:2446::a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4817747332 for ; Thu, 10 Nov 2022 11:53:19 -0800 (PST) Received: from resomta-h1p-027912.sys.comcast.net ([96.102.179.201]) by resqmta-h1p-028588.sys.comcast.net with ESMTP id t8NCo9FHCxitjtDZYoR0j0; Thu, 10 Nov 2022 19:50:48 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=comcastmailservice.net; s=20211018a; t=1668109848; bh=sofvAoEwaPb3mNtzuqfqCWvRe5407SRczb2NnSKewQY=; h=Received:Received:From:To:Subject:Date:Message-Id:MIME-Version: Xfinity-Spam-Result; b=UBKIwqr9wltygoaWs9pl4K2yPhxo48Yqp+O8k87EFPX+99XEw2K0QrsegdBU9Hptb geZuI7wvwBWoLPiUV4R0rH7nViMa9jnHCp9iVuXhmm1YUh+L8GLFqTaE5vbsCq839F KeQkMwAzv8LA7svaGoJLuHkewSt556O+914ye6WJutijNH1y8SDWAWa7kUjR7zrfvG DHtSLN1m5tEeKJVqSVEv+ukdCsAiOArUz86yvSZNprxt/jLuwNlkpCWraeivmmNi1X 1MGlyl49eaKJtTljnR9Ltm2VaJ1L4cIJ0q71SAe02O9wUGylu6vP4OMWHBWlltKFz0 0Lmx5xepaq4DA== Received: from jderrick-mobl4.amr.corp.intel.com ([71.205.181.50]) by resomta-h1p-027912.sys.comcast.net with ESMTPA id tDZ4oZTHiVTvltDZGokliB; Thu, 10 Nov 2022 19:50:31 +0000 X-Xfinity-VAAS: gggruggvucftvghtrhhoucdtuddrgedvgedrfeeggddufeduucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuvehomhgtrghsthdqtfgvshhipdfqfgfvpdfpqffurfetoffkrfenuceurghilhhouhhtmecufedtudenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujfgurhephffvvefufffkofgjfhgggfestdekredtredttdenucfhrhhomheplfhonhgrthhhrghnucffvghrrhhitghkuceojhhonhgrthhhrghnrdguvghrrhhitghksehlihhnuhigrdguvghvqeenucggtffrrghtthgvrhhnpedtteeljeffgfffveehhfetveefuedvheevffffhedtjeeuvdevgfeftddtheeftdenucfkphepjedurddvtdehrddukedurdehtdenucevlhhushhtvghrufhiiigvpedunecurfgrrhgrmhephhgvlhhopehjuggvrhhrihgtkhdqmhhosghlgedrrghmrhdrtghorhhprdhinhhtvghlrdgtohhmpdhinhgvthepjedurddvtdehrddukedurdehtddpmhgrihhlfhhrohhmpehjohhnrghthhgrnhdruggvrhhrihgtkheslhhinhhugidruggvvhdpnhgspghrtghpthhtohepkedprhgtphhtthhopehvihguhigrshesnhhvihguihgrrdgtohhmpdhrtghpthhtohepmhgrnhhisehkvghrnhgvlhdrohhrghdprhgtphhtthhopehlohhrvghniihordhpihgvrhgrlhhishhisegrrhhmrdgtohhmpdhrtghpthhtohephhgvlhhgrggrsheskhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinh hugidqphgtihesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehluhhkrghsseifuhhnnhgvrhdruggvpdhrtghpthhtohepphgrlhhisehkvghrnhgvlhdrohhrghdprhgtphhtthhopehjohhnrghthhgrnhdruggvrhhrihgtkheslhhinhhugidruggvvh X-Xfinity-VMeta: sc=-100.00;st=legit From: Jonathan Derrick To: Vidya Sagar Cc: Manivannan Sadhasivam , Lorenzo Pieralisi , Bjorn Helgaas , , Lukas Wunner , =?utf-8?q?Pali_Roh=C3=A1r?= , Jonathan Derrick Subject: [PATCH v2 4/7] PCI: Move pci_dev_str_match to search.c Date: Thu, 10 Nov 2022 12:50:12 -0700 Message-Id: <20221110195015.207-5-jonathan.derrick@linux.dev> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20221110195015.207-1-jonathan.derrick@linux.dev> References: <20221110195015.207-1-jonathan.derrick@linux.dev> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org The method which extracts a string descriptor of one or more PCI devices and matches to a struct pci_dev is useful in general to other subsystems needing to match parameters or sysfs strings. Move this function to search.c for general use. Signed-off-by: Jonathan Derrick --- drivers/pci/pci.c | 163 ------------------------------------------- drivers/pci/search.c | 162 ++++++++++++++++++++++++++++++++++++++++++ include/linux/pci.h | 5 ++ 3 files changed, 167 insertions(+), 163 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 2127aba3550b..b58a8f5a7654 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -250,169 +250,6 @@ void __iomem *pci_ioremap_wc_bar(struct pci_dev *pdev, int bar) EXPORT_SYMBOL_GPL(pci_ioremap_wc_bar); #endif -/** - * pci_dev_str_match_path - test if a path string matches a device - * @dev: the PCI device to test - * @path: string to match the device against - * @endptr: pointer to the string after the match - * - * Test if a string (typically from a kernel parameter) formatted as a - * path of device/function addresses matches a PCI device. The string must - * be of the form: - * - * [:]:.[/.]* - * - * A path for a device can be obtained using 'lspci -t'. Using a path - * is more robust against bus renumbering than using only a single bus, - * device and function address. - * - * Returns 1 if the string matches the device, 0 if it does not and - * a negative error code if it fails to parse the string. - */ -static int pci_dev_str_match_path(struct pci_dev *dev, const char *path, - const char **endptr) -{ - int ret; - unsigned int seg, bus, slot, func; - char *wpath, *p; - char end; - - *endptr = strchrnul(path, ';'); - - wpath = kmemdup_nul(path, *endptr - path, GFP_ATOMIC); - if (!wpath) - return -ENOMEM; - - while (1) { - p = strrchr(wpath, '/'); - if (!p) - break; - ret = sscanf(p, "/%x.%x%c", &slot, &func, &end); - if (ret != 2) { - ret = -EINVAL; - goto free_and_exit; - } - - if (dev->devfn != PCI_DEVFN(slot, func)) { - ret = 0; - goto free_and_exit; - } - - /* - * Note: we don't need to get a reference to the upstream - * bridge because we hold a reference to the top level - * device which should hold a reference to the bridge, - * and so on. - */ - dev = pci_upstream_bridge(dev); - if (!dev) { - ret = 0; - goto free_and_exit; - } - - *p = 0; - } - - ret = sscanf(wpath, "%x:%x:%x.%x%c", &seg, &bus, &slot, - &func, &end); - if (ret != 4) { - seg = 0; - ret = sscanf(wpath, "%x:%x.%x%c", &bus, &slot, &func, &end); - if (ret != 3) { - ret = -EINVAL; - goto free_and_exit; - } - } - - ret = (seg == pci_domain_nr(dev->bus) && - bus == dev->bus->number && - dev->devfn == PCI_DEVFN(slot, func)); - -free_and_exit: - kfree(wpath); - return ret; -} - -/** - * pci_dev_str_match - test if a string matches a device - * @dev: the PCI device to test - * @p: string to match the device against - * @endptr: pointer to the string after the match - * - * Test if a string (typically from a kernel parameter) matches a specified - * PCI device. The string may be of one of the following formats: - * - * [:]:.[/.]* - * pci::[::] - * - * The first format specifies a PCI bus/device/function address which - * may change if new hardware is inserted, if motherboard firmware changes, - * or due to changes caused in kernel parameters. If the domain is - * left unspecified, it is taken to be 0. In order to be robust against - * bus renumbering issues, a path of PCI device/function numbers may be used - * to address the specific device. The path for a device can be determined - * through the use of 'lspci -t'. - * - * The second format matches devices using IDs in the configuration - * space which may match multiple devices in the system. A value of 0 - * for any field will match all devices. (Note: this differs from - * in-kernel code that uses PCI_ANY_ID which is ~0; this is for - * legacy reasons and convenience so users don't have to specify - * FFFFFFFFs on the command line.) - * - * Returns 1 if the string matches the device, 0 if it does not and - * a negative error code if the string cannot be parsed. - */ -static int pci_dev_str_match(struct pci_dev *dev, const char *p, - const char **endptr) -{ - int ret; - int count; - unsigned short vendor, device, subsystem_vendor, subsystem_device; - - if (strncmp(p, "pci:", 4) == 0) { - /* PCI vendor/device (subvendor/subdevice) IDs are specified */ - p += 4; - ret = sscanf(p, "%hx:%hx:%hx:%hx%n", &vendor, &device, - &subsystem_vendor, &subsystem_device, &count); - if (ret != 4) { - ret = sscanf(p, "%hx:%hx%n", &vendor, &device, &count); - if (ret != 2) - return -EINVAL; - - subsystem_vendor = 0; - subsystem_device = 0; - } - - p += count; - - if ((!vendor || vendor == dev->vendor) && - (!device || device == dev->device) && - (!subsystem_vendor || - subsystem_vendor == dev->subsystem_vendor) && - (!subsystem_device || - subsystem_device == dev->subsystem_device)) - goto found; - } else { - /* - * PCI Bus, Device, Function IDs are specified - * (optionally, may include a path of devfns following it) - */ - ret = pci_dev_str_match_path(dev, p, &p); - if (ret < 0) - return ret; - else if (ret) - goto found; - } - - *endptr = p; - return 0; - -found: - *endptr = p; - return 1; -} - static u8 __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn, u8 pos, int cap, int *ttl) { diff --git a/drivers/pci/search.c b/drivers/pci/search.c index b4c138a6ec02..059fc5b9db4c 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -390,3 +390,165 @@ int pci_dev_present(const struct pci_device_id *ids) return 0; } EXPORT_SYMBOL(pci_dev_present); + +/** + * pci_dev_str_match_path - test if a path string matches a device + * @dev: the PCI device to test + * @path: string to match the device against + * @endptr: pointer to the string after the match + * + * Test if a string (typically from a kernel parameter) formatted as a + * path of device/function addresses matches a PCI device. The string must + * be of the form: + * + * [:]:.[/.]* + * + * A path for a device can be obtained using 'lspci -t'. Using a path + * is more robust against bus renumbering than using only a single bus, + * device and function address. + * + * Returns 1 if the string matches the device, 0 if it does not and + * a negative error code if it fails to parse the string. + */ +static int pci_dev_str_match_path(struct pci_dev *dev, const char *path, + const char **endptr) +{ + int ret; + unsigned int seg, bus, slot, func; + char *wpath, *p; + char end; + + *endptr = strchrnul(path, ';'); + + wpath = kmemdup_nul(path, *endptr - path, GFP_ATOMIC); + if (!wpath) + return -ENOMEM; + + while (1) { + p = strrchr(wpath, '/'); + if (!p) + break; + ret = sscanf(p, "/%x.%x%c", &slot, &func, &end); + if (ret != 2) { + ret = -EINVAL; + goto free_and_exit; + } + + if (dev->devfn != PCI_DEVFN(slot, func)) { + ret = 0; + goto free_and_exit; + } + + /* + * Note: we don't need to get a reference to the upstream + * bridge because we hold a reference to the top level + * device which should hold a reference to the bridge, + * and so on. + */ + dev = pci_upstream_bridge(dev); + if (!dev) { + ret = 0; + goto free_and_exit; + } + + *p = 0; + } + + ret = sscanf(wpath, "%x:%x:%x.%x%c", &seg, &bus, &slot, + &func, &end); + if (ret != 4) { + seg = 0; + ret = sscanf(wpath, "%x:%x.%x%c", &bus, &slot, &func, &end); + if (ret != 3) { + ret = -EINVAL; + goto free_and_exit; + } + } + + ret = (seg == pci_domain_nr(dev->bus) && + bus == dev->bus->number && + dev->devfn == PCI_DEVFN(slot, func)); + +free_and_exit: + kfree(wpath); + return ret; +} + +/** + * pci_dev_str_match - test if a string matches a device + * @dev: the PCI device to test + * @p: string to match the device against + * @endptr: pointer to the string after the match + * + * Test if a string (typically from a kernel parameter) matches a specified + * PCI device. The string may be of one of the following formats: + * + * [:]:.[/.]* + * pci::[::] + * + * The first format specifies a PCI bus/device/function address which + * may change if new hardware is inserted, if motherboard firmware changes, + * or due to changes caused in kernel parameters. If the domain is + * left unspecified, it is taken to be 0. In order to be robust against + * bus renumbering issues, a path of PCI device/function numbers may be used + * to address the specific device. The path for a device can be determined + * through the use of 'lspci -t'. + * + * The second format matches devices using IDs in the configuration + * space which may match multiple devices in the system. A value of 0 + * for any field will match all devices. (Note: this differs from + * in-kernel code that uses PCI_ANY_ID which is ~0; this is for + * legacy reasons and convenience so users don't have to specify + * FFFFFFFFs on the command line.) + * + * Returns 1 if the string matches the device, 0 if it does not and + * a negative error code if the string cannot be parsed. + */ +int pci_dev_str_match(struct pci_dev *dev, const char *p, const char **endptr) +{ + int ret; + int count; + unsigned short vendor, device, subsystem_vendor, subsystem_device; + + if (strncmp(p, "pci:", 4) == 0) { + /* PCI vendor/device (subvendor/subdevice) IDs are specified */ + p += 4; + ret = sscanf(p, "%hx:%hx:%hx:%hx%n", &vendor, &device, + &subsystem_vendor, &subsystem_device, &count); + if (ret != 4) { + ret = sscanf(p, "%hx:%hx%n", &vendor, &device, &count); + if (ret != 2) + return -EINVAL; + + subsystem_vendor = 0; + subsystem_device = 0; + } + + p += count; + + if ((!vendor || vendor == dev->vendor) && + (!device || device == dev->device) && + (!subsystem_vendor || + subsystem_vendor == dev->subsystem_vendor) && + (!subsystem_device || + subsystem_device == dev->subsystem_device)) + goto found; + } else { + /* + * PCI Bus, Device, Function IDs are specified + * (optionally, may include a path of devfns following it) + */ + ret = pci_dev_str_match_path(dev, p, &p); + if (ret < 0) + return ret; + else if (ret) + goto found; + } + + *endptr = p; + return 0; + +found: + *endptr = p; + return 1; +} diff --git a/include/linux/pci.h b/include/linux/pci.h index 09f704337955..0c907f94bb61 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1182,6 +1182,7 @@ struct pci_dev *pci_get_domain_bus_and_slot(int domain, unsigned int bus, unsigned int devfn); struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from); int pci_dev_present(const struct pci_device_id *ids); +int pci_dev_str_match(struct pci_dev *dev, const char *p, const char **endptr); int pci_bus_read_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 *val); @@ -1816,6 +1817,10 @@ static inline struct pci_dev *pci_get_class(unsigned int class, static inline int pci_dev_present(const struct pci_device_id *ids) { return 0; } +static inline int pci_dev_str_match(struct pci_dev *dev, const char *p, + const char **endptr) +{ return 0; } + #define no_pci_devices() (1) #define pci_dev_put(dev) do { } while (0) From patchwork Thu Nov 10 19:50:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Derrick X-Patchwork-Id: 13039276 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2793AC4167B for ; Thu, 10 Nov 2022 19:53:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229566AbiKJTxh (ORCPT ); Thu, 10 Nov 2022 14:53:37 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46768 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231250AbiKJTxc (ORCPT ); Thu, 10 Nov 2022 14:53:32 -0500 Received: from resdmta-h1p-028597.sys.comcast.net (resdmta-h1p-028597.sys.comcast.net [IPv6:2001:558:fd02:2446::d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6BBDA4876B for ; Thu, 10 Nov 2022 11:53:19 -0800 (PST) Received: from resomta-h1p-027912.sys.comcast.net ([96.102.179.201]) by resdmta-h1p-028597.sys.comcast.net with ESMTP id t6rzofAFOwwPvtDZYoNduM; Thu, 10 Nov 2022 19:50:48 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=comcastmailservice.net; s=20211018a; t=1668109848; bh=zccPbXOs+Je83CkegCNzQLUUfDjEU/+RJ69WLlkTgqU=; h=Received:Received:From:To:Subject:Date:Message-Id:MIME-Version: Xfinity-Spam-Result; b=uwSnCEFGMYmYTLR0v1pyiI3AmVjuQb4WmLo5iG7dW3tnavD0UI6rBA8UhnUu5uaXZ V6M69kun0e6IejQaVyOed8ax6kznH8ckki2Yx+aRX9zAOfAXZPT7K3tJE0ln1dbQ31 WlCquJDELMi2jTt6XeVYEO2LDsLPRyLY3DcZ0sWOmKDaBqBfFYEgTq/M2uU4CjHSUU 9yw21qpZy1dosVLJvU6otraw38F5+KFdvf8HkVdzFJx2H26DaGRQJM9enfMIL3B4pi IKq6MYAwPLEZLxMA3Iu2mTkPupdN1IzIP+oFmIU192kz6mc4WgRhckGeNv5vvv3Shb RZYwsQox+dqhA== Received: from jderrick-mobl4.amr.corp.intel.com ([71.205.181.50]) by resomta-h1p-027912.sys.comcast.net with ESMTPA id tDZ4oZTHiVTvltDZIokliE; Thu, 10 Nov 2022 19:50:32 +0000 X-Xfinity-VAAS: gggruggvucftvghtrhhoucdtuddrgedvgedrfeeggddufeduucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuvehomhgtrghsthdqtfgvshhipdfqfgfvpdfpqffurfetoffkrfenuceurghilhhouhhtmecufedtudenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujfgurhephffvvefufffkofgjfhgggfestdekredtredttdenucfhrhhomheplfhonhgrthhhrghnucffvghrrhhitghkuceojhhonhgrthhhrghnrdguvghrrhhitghksehlihhnuhigrdguvghvqeenucggtffrrghtthgvrhhnpedtteeljeffgfffveehhfetveefuedvheevffffhedtjeeuvdevgfeftddtheeftdenucfkphepjedurddvtdehrddukedurdehtdenucevlhhushhtvghrufhiiigvpedunecurfgrrhgrmhephhgvlhhopehjuggvrhhrihgtkhdqmhhosghlgedrrghmrhdrtghorhhprdhinhhtvghlrdgtohhmpdhinhgvthepjedurddvtdehrddukedurdehtddpmhgrihhlfhhrohhmpehjohhnrghthhgrnhdruggvrhhrihgtkheslhhinhhugidruggvvhdpnhgspghrtghpthhtohepkedprhgtphhtthhopehvihguhigrshesnhhvihguihgrrdgtohhmpdhrtghpthhtohepmhgrnhhisehkvghrnhgvlhdrohhrghdprhgtphhtthhopehlohhrvghniihordhpihgvrhgrlhhishhisegrrhhmrdgtohhmpdhrtghpthhtohephhgvlhhgrggrsheskhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinh hugidqphgtihesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehluhhkrghsseifuhhnnhgvrhdruggvpdhrtghpthhtohepphgrlhhisehkvghrnhgvlhdrohhrghdprhgtphhtthhopehjohhnrghthhgrnhdruggvrhhrihgtkheslhhinhhugidruggvvh X-Xfinity-VMeta: sc=-100.00;st=legit From: Jonathan Derrick To: Vidya Sagar Cc: Manivannan Sadhasivam , Lorenzo Pieralisi , Bjorn Helgaas , , Lukas Wunner , =?utf-8?q?Pali_Roh=C3=A1r?= , Jonathan Derrick Subject: [PATCH v2 5/7] PCI: pci-bridge-emul: Provide a helper to set behavior Date: Thu, 10 Nov 2022 12:50:13 -0700 Message-Id: <20221110195015.207-6-jonathan.derrick@linux.dev> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20221110195015.207-1-jonathan.derrick@linux.dev> References: <20221110195015.207-1-jonathan.derrick@linux.dev> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org Add a handler to set behavior of a PCI or PCIe register. Add the appropriate enums to specify the register's Read-Only, Read-Write, and Write-1-to-Clear behaviors. Signed-off-by: Jonathan Derrick --- drivers/pci/pci-bridge-emul.c | 19 +++++++++++++++++++ drivers/pci/pci-bridge-emul.h | 10 ++++++++++ 2 files changed, 29 insertions(+) diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c index 9334b2dd4764..3c1a683ece66 100644 --- a/drivers/pci/pci-bridge-emul.c +++ b/drivers/pci/pci-bridge-emul.c @@ -46,6 +46,25 @@ struct pci_bridge_reg_behavior { u32 w1c; }; +void pci_bridge_emul_set_reg_behavior(struct pci_bridge_emul *bridge, + bool pcie, int reg, u32 val, + enum pci_bridge_emul_reg_behavior type) +{ + struct pci_bridge_reg_behavior *behavior; + + if (pcie) + behavior = &bridge->pcie_cap_regs_behavior[reg / 4]; + else + behavior = &bridge->pci_regs_behavior[reg / 4]; + + if (type == PCI_BRIDGE_EMUL_REG_BEHAVIOR_RO) + behavior->ro = val; + else if (type == PCI_BRIDGE_EMUL_REG_BEHAVIOR_RW) + behavior->rw = val; + else /* PCI_BRIDGE_EMUL_REG_BEHAVIOR_W1C */ + behavior->w1c = val; +} + static const struct pci_bridge_reg_behavior pci_regs_behavior[PCI_STD_HEADER_SIZEOF / 4] = { [PCI_VENDOR_ID / 4] = { .ro = ~0 }, diff --git a/drivers/pci/pci-bridge-emul.h b/drivers/pci/pci-bridge-emul.h index 2a0e59c7f0d9..b2401d58518c 100644 --- a/drivers/pci/pci-bridge-emul.h +++ b/drivers/pci/pci-bridge-emul.h @@ -72,6 +72,12 @@ struct pci_bridge_emul; typedef enum { PCI_BRIDGE_EMUL_HANDLED, PCI_BRIDGE_EMUL_NOT_HANDLED } pci_bridge_emul_read_status_t; +enum pci_bridge_emul_reg_behavior { + PCI_BRIDGE_EMUL_REG_BEHAVIOR_RO, + PCI_BRIDGE_EMUL_REG_BEHAVIOR_RW, + PCI_BRIDGE_EMUL_REG_BEHAVIOR_W1C, +}; + struct pci_bridge_emul_ops { /* * Called when reading from the regular PCI bridge @@ -161,4 +167,8 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where, int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where, int size, u32 value); +void pci_bridge_emul_set_reg_behavior(struct pci_bridge_emul *bridge, + bool pcie, int reg, u32 val, + enum pci_bridge_emul_reg_behavior type); + #endif /* __PCI_BRIDGE_EMUL_H__ */ From patchwork Thu Nov 10 19:50:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Derrick X-Patchwork-Id: 13039278 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8D282C4332F for ; Thu, 10 Nov 2022 19:53:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230422AbiKJTxg (ORCPT ); Thu, 10 Nov 2022 14:53:36 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46698 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231231AbiKJTxc (ORCPT ); Thu, 10 Nov 2022 14:53:32 -0500 Received: from resqmta-h1p-028594.sys.comcast.net (resqmta-h1p-028594.sys.comcast.net [IPv6:2001:558:fd02:2446::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6943048769 for ; Thu, 10 Nov 2022 11:53:19 -0800 (PST) Received: from resomta-h1p-027912.sys.comcast.net ([96.102.179.201]) by resqmta-h1p-028594.sys.comcast.net with ESMTP id t7enopKwunCnBtDZYovSAu; Thu, 10 Nov 2022 19:50:48 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=comcastmailservice.net; s=20211018a; t=1668109848; bh=bQerkWg6K2GQUzSCC4gsty8efMvieIoJj52PHPj0HX0=; h=Received:Received:From:To:Subject:Date:Message-Id:MIME-Version: Xfinity-Spam-Result; b=hnxiOFUY/qk2ePrXjsb5lmKj16E86Us90KJnYSXSB43Uny25Wx107HHGVm2+anIgr Nq9oow+2c2puutsoZjahnMNM6ykgW72sNaBRTcoUfliBBLOGIhg5Er4AbWL62yfp+e VIgUmOf+hIYp+K7791ajBROoY9OliY3iH0qBC7C8wnrAK2TwElMRf0ZvEBDz/OQsTi 7wjKc41mhMSWs5r/jk3mev31lUHCq6Mk5Iu+5fo72N9l2R69nJAUr+S3NSbGeolVl2 DjQOp4mRZIqrpDJq23wkwW51BIP9BRiF+l/mTxsFzuU+k7KADMvVWmUhaeAm2ZodMc Trx5gBkDYV0EA== Received: from jderrick-mobl4.amr.corp.intel.com ([71.205.181.50]) by resomta-h1p-027912.sys.comcast.net with ESMTPA id tDZ4oZTHiVTvltDZJokliP; Thu, 10 Nov 2022 19:50:34 +0000 X-Xfinity-VAAS: gggruggvucftvghtrhhoucdtuddrgedvgedrfeeggddufeduucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuvehomhgtrghsthdqtfgvshhipdfqfgfvpdfpqffurfetoffkrfenuceurghilhhouhhtmecufedtudenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujfgurhephffvvefufffkofgjfhgggfestdekredtredttdenucfhrhhomheplfhonhgrthhhrghnucffvghrrhhitghkuceojhhonhgrthhhrghnrdguvghrrhhitghksehlihhnuhigrdguvghvqeenucggtffrrghtthgvrhhnpedtteeljeffgfffveehhfetveefuedvheevffffhedtjeeuvdevgfeftddtheeftdenucfkphepjedurddvtdehrddukedurdehtdenucevlhhushhtvghrufhiiigvpedunecurfgrrhgrmhephhgvlhhopehjuggvrhhrihgtkhdqmhhosghlgedrrghmrhdrtghorhhprdhinhhtvghlrdgtohhmpdhinhgvthepjedurddvtdehrddukedurdehtddpmhgrihhlfhhrohhmpehjohhnrghthhgrnhdruggvrhhrihgtkheslhhinhhugidruggvvhdpnhgspghrtghpthhtohepkedprhgtphhtthhopehvihguhigrshesnhhvihguihgrrdgtohhmpdhrtghpthhtohepmhgrnhhisehkvghrnhgvlhdrohhrghdprhgtphhtthhopehlohhrvghniihordhpihgvrhgrlhhishhisegrrhhmrdgtohhmpdhrtghpthhtohephhgvlhhgrggrsheskhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinh hugidqphgtihesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehluhhkrghsseifuhhnnhgvrhdruggvpdhrtghpthhtohepphgrlhhisehkvghrnhgvlhdrohhrghdprhgtphhtthhopehjohhnrghthhgrnhdruggvrhhrihgtkheslhhinhhugidruggvvh X-Xfinity-VMeta: sc=-100.00;st=legit From: Jonathan Derrick To: Vidya Sagar Cc: Manivannan Sadhasivam , Lorenzo Pieralisi , Bjorn Helgaas , , Lukas Wunner , =?utf-8?q?Pali_Roh=C3=A1r?= , Jonathan Derrick Subject: [PATCH v2 6/7] PCI: pciehp: Add hotplug slot emulation driver Date: Thu, 10 Nov 2022 12:50:14 -0700 Message-Id: <20221110195015.207-7-jonathan.derrick@linux.dev> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20221110195015.207-1-jonathan.derrick@linux.dev> References: <20221110195015.207-1-jonathan.derrick@linux.dev> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org This adds the PCIe Hotplug emulation driver. There may be platforms with specific configurations that can support hotplug but don't provide the logical slot hotplug hardware. For instance, the platform may use an electrically-tolerant interposer between the slot and the device. This driver utilizes the pci-bridge-emul architecture to manage register reads and writes. The underlying functionality of the hotplug emulation driver uses the Data Link Layer Link Active Reporting mechanism in a polling loop, but can tolerate other event sources such as AER or DPC. When enabled and a slot is managed by the driver, all PCIe Port services are managed by the kernel. This is done to ensure that firmware hotplug and error architecture does not (correctly) machine check the system when hotplug is performed on a non-hotplug slot. The driver offers two active mode: auto and force. auto: Bind to non-hotplug slots force: Bind to all slots and overrides the slot's services There are three kernel parameters: pciehp.pciehp_emul_mode={off, auto, force} pciehp.pciehp_emul_time= (def 1000, min 100, max 60000) pciehp.pciehp_emul_ports= The pciehp_emul_ports parameter takes a semi-colon tokenized string representing PCI [S]BDFs and IDs. The pciehp_emul_mode will then be applied to only those slots, leaving other slots unmanaged by pciehp_emul. The string follows the pci_dev_str_match() format: [:]:.[/.]* pci::[::] When using the path format, the path for the device can be obtained using 'lspci -t' and further specified using the upstream bridge and the downstream port's device-function to be more robust against bus renumbering. When using the vendor-device format, a value of '0' in any field acts as a wildcard for that field, matching all values. The driver is enabled with CONFIG_HOTPLUG_PCI_PCIE_EMUL=y. Signed-off-by: Jonathan Derrick --- drivers/pci/hotplug/Makefile | 4 + drivers/pci/hotplug/pciehp_emul.c | 372 ++++++++++++++++++++++++++++++ drivers/pci/pcie/Kconfig | 13 ++ 3 files changed, 389 insertions(+) create mode 100644 drivers/pci/hotplug/pciehp_emul.c diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile index 5196983220df..4c01ecaa1dde 100644 --- a/drivers/pci/hotplug/Makefile +++ b/drivers/pci/hotplug/Makefile @@ -65,6 +65,10 @@ pciehp-objs := pciehp_core.o \ pciehp_pci.o \ pciehp_hpc.o +ifdef CONFIG_HOTPLUG_PCI_PCIE_EMUL +pciehp-objs += pciehp_emul.o +endif + shpchp-objs := shpchp_core.o \ shpchp_ctrl.o \ shpchp_pci.o \ diff --git a/drivers/pci/hotplug/pciehp_emul.c b/drivers/pci/hotplug/pciehp_emul.c new file mode 100644 index 000000000000..716ec57feb79 --- /dev/null +++ b/drivers/pci/hotplug/pciehp_emul.c @@ -0,0 +1,372 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PCI Express PCI Hot Plug Slot Emulation Driver + * Author: Jon Derrick + * + * Copyright (C) 2022 Solidigm + */ + +#define dev_fmt(fmt) "pciehp: " fmt + +#include +#include + +#include "../pci.h" +#include "../pci-bridge-emul.h" +#include "pciehp.h" + +static char *pciehp_emul_ports; +module_param(pciehp_emul_ports, charp, 0444); +MODULE_PARM_DESC(pciehp_emul_ports, "list of port BDF/IDs (optional)"); + +static unsigned int pciehp_emul_time = 1000; +module_param(pciehp_emul_time, uint, 0644); +MODULE_PARM_DESC(pciehp_emul_time, "link polling delay in msecs"); + +enum { + PCIEHP_EMUL_OFF, + PCIEHP_EMUL_AUTO, + PCIEHP_EMUL_FORCE, +}; + +static const char *const pciehp_emul_mode_strings[] = { + "off", + "auto", + "force", +}; + +static int pciehp_emul_mode; +MODULE_PARM_DESC(pciehp_emul_mode, "slot emulation mode"); + +static int pciehp_emul_mode_set(const char *str, const struct kernel_param *kp) +{ + int i; + + i = match_string(pciehp_emul_mode_strings, + ARRAY_SIZE(pciehp_emul_mode_strings), str); + if (i < 0) + return i; + + pciehp_emul_mode = i; + return 0; +} + +static int pciehp_emul_mode_get(char *buffer, const struct kernel_param *kp) +{ + return sprintf(buffer, "%s\n", pciehp_emul_mode_strings[pciehp_emul_mode]); +} + +static const struct kernel_param_ops pciehp_emul_mode_ops = { + .set = pciehp_emul_mode_set, + .get = pciehp_emul_mode_get, +}; + +module_param_cb(pciehp_emul_mode, &pciehp_emul_mode_ops, &pciehp_emul_mode, 0444); + +static LIST_HEAD(pciehp_emul_list); +static DEFINE_MUTEX(list_lock); + +/** + * struct pciehp_emul - Emulated PCIe Hotplug Slot structure + * @node: List of PCIe Hotplug Emulated PCI devices. + * @ctrl: Slot's pciehp controller. + * @bridge: PCI Bridge Emul descriptor. Emulates the common register + * read/write behaviors. + * @poll_thread: Per-slot Data Link Layer Link Active polling thread. + */ +struct pciehp_emul { + struct list_head node; + struct controller *ctrl; + struct pci_bridge_emul bridge; + struct task_struct *poll_thread; +}; + +/* Emul Bridge OPS */ +static struct pci_bridge_emul_ops pciehp_emul_pci_bridge_ops = {}; + +static struct pciehp_emul *pci_dev_to_pciehp_emul(struct pci_dev *dev) +{ + struct pciehp_emul *emul; + + list_for_each_entry(emul, &pciehp_emul_list, node) + if (emul->ctrl->pcie->port == dev) + return emul; + + return NULL; +} + +static int pciehp_emul_slot_rw(struct pci_dev *dev, int pos, int len, + u32 *val, int dir) +{ + struct pciehp_emul *emul; + int ret; + + mutex_lock(&list_lock); + emul = pci_dev_to_pciehp_emul(dev); + if (!emul) { + mutex_unlock(&list_lock); + return PCIBIOS_DEVICE_NOT_FOUND; + } + + if (dir == READ) + ret = pci_bridge_emul_conf_read(&emul->bridge, + pos + PCI_STD_HEADER_SIZEOF, + len, val); + else + ret = pci_bridge_emul_conf_write(&emul->bridge, + pos + PCI_STD_HEADER_SIZEOF, + len, *val); + mutex_unlock(&list_lock); + + return ret; +} + +/* Assuming aligned accesses to slot registers */ +static int pciehp_emul_slot_read(struct pci_dev *dev, int pos, int len, u32 *val) +{ + if (pos >= PCI_EXP_SLTCAP && pos <= PCI_EXP_SLTSTA) + return pciehp_emul_slot_rw(dev, pos, len, val, READ); + return 1; +} + +static int pciehp_emul_slot_write(struct pci_dev *dev, int pos, int len, u32 val) +{ + if (pos >= PCI_EXP_SLTCAP && pos <= PCI_EXP_SLTSTA) + return pciehp_emul_slot_rw(dev, pos, len, &val, WRITE); + return 1; +} + +static struct caps_rw_ops pciehp_emul_slot_ops = { + .read = pciehp_emul_slot_read, + .write = pciehp_emul_slot_write, +}; + +static int pciehp_emul_thread(void *data) +{ + struct pciehp_emul *emul = data; + struct controller *ctrl = emul->ctrl; + struct pci_dev *dev = ctrl->pcie->port; + __le16 *emul_lnksta_p = &emul->bridge.pcie_conf.lnksta; + __le16 *emul_slotsta_p = &emul->bridge.pcie_conf.slotsta; + u16 emul_lnksta, port_lnksta; + int ret; + + /* Store initial link status state */ + ret = pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &port_lnksta); + if (!ret && port_lnksta != (u16)~0) + *emul_lnksta_p = cpu_to_le16(port_lnksta); + + /* Start with 1 sec delay */ + schedule_timeout_idle(1 * HZ); + + /* + * Data Link Layer Link Active (DLLLA) event sets Data Link Layer State + * Changed (DLLSC) and updates internal link status tracking. + */ + set_current_state(TASK_INTERRUPTIBLE); + while (!kthread_should_stop()) { + ret = pcie_capability_read_word(dev, PCI_EXP_LNKSTA, + &port_lnksta); + if (ret || port_lnksta == (u16)~0) + goto cont; + + emul_lnksta = le16_to_cpup(emul_lnksta_p); + if ((port_lnksta ^ emul_lnksta) & PCI_EXP_LNKSTA_DLLLA) { + ctrl_dbg(ctrl, "link change event (%04x->%04x)\n", + emul_lnksta, port_lnksta); + *emul_lnksta_p = cpu_to_le16(port_lnksta); + *emul_slotsta_p |= cpu_to_le16(PCI_EXP_SLTSTA_DLLSC); + + while (pciehp_events_pending(ctrl)) + pciehp_handle_events(ctrl); + } + +cont: + /* Clamp to sane value */ + pciehp_emul_time = clamp(pciehp_emul_time, 100U, 60000U); + schedule_timeout_idle(msecs_to_jiffies(pciehp_emul_time)); + } + + return 0; +} + +/** + * pciehp_emul_ports_check - Matches pci_dev against pciehp_emul_ports filter + * @dev: Struct pci_dev to match against string + * + * Matches a semi-colon tokenized string list of PCI addresses or vendor-device + * IDs to the struct pci_dev. Follows the pci_dev_str_match format in the form: + * + * [:]:.[/.]* + * pci::[::] + * + * When using the path format, the path for the device can be obtained using + * 'lspci -t' and further specified using the upstream bridge and the + * downstream port's device-function to be more robust against bus renumbering. + * + * When using the vendor-device format, a value of '0' in any field acts as a + * wildcard for that field, matching all values. + * + * Returns 0 on match or null/empty string. + */ +static int pciehp_emul_ports_check(struct pci_dev *dev) +{ + const char *p = pciehp_emul_ports; + int ret; + + /* Null or empty string matches all devices */ + if (!p || !*p) + return 0; + + while (*p) { + ret = pci_dev_str_match(dev, p, &p); + if (ret < 0) { + pr_info_once("Can't parse pciehp_emul_ports parameter: %s\n", + pciehp_emul_ports); + return ret; + } + + /* Found a match */ + if (ret == 1) + return 0; + + if (*p != ';' && *p != ',') { + /* End of param or invalid format */ + return -ENODEV; + } + p++; + } + + return -ENODEV; +} + +bool pciehp_emul_will_manage(struct pci_dev *dev) +{ + u32 lnkcap; + u16 sltcap; + int ret; + + if (pciehp_emul_mode == PCIEHP_EMUL_OFF) + return false; + + /* A physical slot must be present for emulation to be useful. */ + if (!(pcie_caps_reg(dev) & PCI_EXP_FLAGS_SLOT)) + return false; + + /* Match a port BDF/ID descriptor if given */ + if (pciehp_emul_ports_check(dev)) + return false; + + /* Port must support Data Link Layer Link Active (DLLLA) Reporting. */ + ret = pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap); + if (ret || lnkcap == (u32)~0) + return false; + if (!(lnkcap & PCI_EXP_LNKCAP_DLLLARC)) + return false; + + /* Require 'force' if the port is already hotplug-capable */ + ret = pcie_capability_read_word(dev, PCI_EXP_SLTCAP, &sltcap); + if (ret || sltcap == (u16)~0) + return false; + if (sltcap & PCI_EXP_SLTCAP_HPC && pciehp_emul_mode != PCIEHP_EMUL_FORCE) + return false; + + return true; +} + +int pciehp_emul_attach(struct controller *ctrl) +{ + struct pciehp_emul *emul; + struct pci_bridge_emul *bridge; + struct pci_dev *dev = ctrl->pcie->port; + u32 slotcap = 0; + int ret; + + emul = kzalloc(sizeof(*emul), GFP_KERNEL); + if (!emul) + return -ENOMEM; + + ret = pcie_capability_read_dword(dev, PCI_EXP_SLTCAP, &slotcap); + if (ret) + goto free_emul; + + emul->ctrl = ctrl; + bridge = &emul->bridge; + bridge->has_pcie = true; + bridge->data = emul; + bridge->ops = &pciehp_emul_pci_bridge_ops; + pci_bridge_emul_init(bridge, 0); + + pci_bridge_emul_set_reg_behavior(bridge, true, PCI_EXP_SLTCTL, + ~PCI_EXP_SLTCTL_DLLSCE, + PCI_BRIDGE_EMUL_REG_BEHAVIOR_RO); + + bridge->pcie_conf.slotcap = cpu_to_le32(PCI_EXP_SLTCAP_HPS | + PCI_EXP_SLTCAP_HPC | + PCI_EXP_SLTCAP_NCCS | + (slotcap & PCI_EXP_SLTCAP_PSN)); + bridge->pcie_conf.slotsta = cpu_to_le16(PCI_EXP_SLTSTA_PDS); + + mutex_lock(&list_lock); + list_add_tail(&emul->node, &pciehp_emul_list); + + dev->caps_rw_ops = &pciehp_emul_slot_ops; + mutex_unlock(&list_lock); + + emul->poll_thread = kthread_run(&pciehp_emul_thread, emul, + "emul-%05x:%04x", + pci_domain_nr(dev->bus), + pci_dev_id(dev)); + ret = PTR_ERR_OR_ZERO(emul->poll_thread); + if (ret) + goto del_node; + + ctrl_info(ctrl, "PCIe Hotplug Emulation active -- use at own risk!\n"); + + return 0; + +del_node: + mutex_lock(&list_lock); + dev->caps_rw_ops = NULL; + list_del(&emul->node); + mutex_unlock(&list_lock); +free_emul: + kfree(emul); + return ret; +} + +static void pciehp_emul_stop_child_threads(struct pci_dev *dev) +{ + struct pciehp_emul *emul; + struct pci_bus *bus = dev->subordinate; + + if (!bus) + return; + + list_for_each_entry(dev, &bus->devices, bus_list) { + pciehp_emul_stop_child_threads(dev); + + emul = pci_dev_to_pciehp_emul(dev); + if (emul) + kthread_stop(emul->poll_thread); + } +} + +void pciehp_emul_detach(struct controller *ctrl) +{ + struct pciehp_emul *emul; + struct pci_dev *dev = ctrl->pcie->port; + + mutex_lock(&list_lock); + pciehp_emul_stop_child_threads(ctrl->pcie->port); + + emul = pci_dev_to_pciehp_emul(ctrl->pcie->port); + if (emul) { + kthread_stop(emul->poll_thread); + dev->caps_rw_ops = NULL; + list_del(&emul->node); + } + mutex_unlock(&list_lock); + + kfree(emul); +} diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig index 788ac8df3f9d..44901b7e30d5 100644 --- a/drivers/pci/pcie/Kconfig +++ b/drivers/pci/pcie/Kconfig @@ -21,6 +21,19 @@ config HOTPLUG_PCI_PCIE When in doubt, say N. +config HOTPLUG_PCI_PCIE_EMUL + bool "PCI Express Hotplug Emulation driver" + depends on HOTPLUG_PCI_PCIE && PCIEAER + select PCI_BRIDGE_EMUL + help + This enables a PCI Express Native Hotplug emulation driver for + non-hotplug-capable PCI Express slots. Hotplug is determined using + link events and this driver can be disabled, or manage either only + non-hotplug-capable slots or both non-hotplug and hotplug slots. + Specific slots may also be targeted. + + When in doubt, say N. + config PCIEAER bool "PCI Express Advanced Error Reporting support" depends on PCIEPORTBUS From patchwork Thu Nov 10 19:50:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Derrick X-Patchwork-Id: 13039277 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E2E26C433FE for ; Thu, 10 Nov 2022 19:53:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231250AbiKJTxh (ORCPT ); Thu, 10 Nov 2022 14:53:37 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46772 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231251AbiKJTxc (ORCPT ); Thu, 10 Nov 2022 14:53:32 -0500 Received: from resqmta-h1p-028589.sys.comcast.net (resqmta-h1p-028589.sys.comcast.net [IPv6:2001:558:fd02:2446::6]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B01A648773 for ; Thu, 10 Nov 2022 11:53:19 -0800 (PST) Received: from resomta-h1p-027912.sys.comcast.net ([96.102.179.201]) by resqmta-h1p-028589.sys.comcast.net with ESMTP id tCeRo6MDBIP6etDZYoVicu; Thu, 10 Nov 2022 19:50:48 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=comcastmailservice.net; s=20211018a; t=1668109848; bh=/aHJeQHePJUbJj7fdHDITqdaKx9GdhGL2xZ60i2fMKo=; h=Received:Received:From:To:Subject:Date:Message-Id:MIME-Version: Xfinity-Spam-Result; b=aN2b7JyrmYa1XHi2EqqtZe7DFk+tLp/QnyszixXJRBeU2VfwYIj/UitsjxxuYcRMu nRA34fUnzLd2O5h+pW5PyutmxgbSU7bYI+iIFl+q7a0bhBG66neUDPRmkwTkrReI0M Na4hSovFcD9i0AQKCPgopvKjvXuY3HBTNvz2FvBH3TEW8hj7yC0l2VzdrNx8LEfYMY qL+Tn8BUBsYqk1cMN7iJg0JQKocZYq9SXJ01vwlXqjVPPXyOQGlHBdMjHyoMqF3Yoc ptZY+WyO5/9H8UZzlKI5r3Ntcbob/Mb/gqnSNpnxQI6Xpe1yfZCCdSxBvIkXfCDTmx u1Avp2ayW28KA== Received: from jderrick-mobl4.amr.corp.intel.com ([71.205.181.50]) by resomta-h1p-027912.sys.comcast.net with ESMTPA id tDZ4oZTHiVTvltDZKokliT; Thu, 10 Nov 2022 19:50:35 +0000 X-Xfinity-VAAS: gggruggvucftvghtrhhoucdtuddrgedvgedrfeeggddufeduucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuvehomhgtrghsthdqtfgvshhipdfqfgfvpdfpqffurfetoffkrfenuceurghilhhouhhtmecufedtudenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujfgurhephffvvefufffkofgjfhgggfestdekredtredttdenucfhrhhomheplfhonhgrthhhrghnucffvghrrhhitghkuceojhhonhgrthhhrghnrdguvghrrhhitghksehlihhnuhigrdguvghvqeenucggtffrrghtthgvrhhnpedtteeljeffgfffveehhfetveefuedvheevffffhedtjeeuvdevgfeftddtheeftdenucfkphepjedurddvtdehrddukedurdehtdenucevlhhushhtvghrufhiiigvpeeinecurfgrrhgrmhephhgvlhhopehjuggvrhhrihgtkhdqmhhosghlgedrrghmrhdrtghorhhprdhinhhtvghlrdgtohhmpdhinhgvthepjedurddvtdehrddukedurdehtddpmhgrihhlfhhrohhmpehjohhnrghthhgrnhdruggvrhhrihgtkheslhhinhhugidruggvvhdpnhgspghrtghpthhtohepkedprhgtphhtthhopehvihguhigrshesnhhvihguihgrrdgtohhmpdhrtghpthhtohepmhgrnhhisehkvghrnhgvlhdrohhrghdprhgtphhtthhopehlohhrvghniihordhpihgvrhgrlhhishhisegrrhhmrdgtohhmpdhrtghpthhtohephhgvlhhgrggrsheskhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinh hugidqphgtihesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehluhhkrghsseifuhhnnhgvrhdruggvpdhrtghpthhtohepphgrlhhisehkvghrnhgvlhdrohhrghdprhgtphhtthhopehjohhnrghthhgrnhdruggvrhhrihgtkheslhhinhhugidruggvvh X-Xfinity-VMeta: sc=-100.00;st=legit From: Jonathan Derrick To: Vidya Sagar Cc: Manivannan Sadhasivam , Lorenzo Pieralisi , Bjorn Helgaas , , Lukas Wunner , =?utf-8?q?Pali_Roh=C3=A1r?= , Jonathan Derrick Subject: [PATCH v2 7/7] PCI: pciehp: Wire up pcie_port_emulate_slot and Date: Thu, 10 Nov 2022 12:50:15 -0700 Message-Id: <20221110195015.207-8-jonathan.derrick@linux.dev> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20221110195015.207-1-jonathan.derrick@linux.dev> References: <20221110195015.207-1-jonathan.derrick@linux.dev> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org Add pcie_port_slot_emulated hook and wire it up to pciehp_emul. Add pciehp_emul_{attach,detach} calls in pciehp and move the management check into the attach caller. Signed-off-by: Jonathan Derrick --- drivers/pci/hotplug/pciehp.h | 18 ++++++++++++++++++ drivers/pci/hotplug/pciehp_emul.c | 8 ++++++++ drivers/pci/hotplug/pciehp_hpc.c | 3 +++ drivers/pci/pcie/portdrv_core.c | 3 +++ include/linux/pci.h | 4 ++++ 5 files changed, 36 insertions(+) diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index e221f5d12ad5..db09705ecb46 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -196,6 +196,24 @@ int pciehp_get_raw_indicator_status(struct hotplug_slot *h_slot, u8 *status); int pciehp_slot_reset(struct pcie_device *dev); +#ifdef CONFIG_HOTPLUG_PCI_PCIE_EMUL +bool pciehp_emul_will_manage(struct pci_dev *dev); +int pciehp_emul_attach(struct controller *ctrl); +void pciehp_emul_detach(struct controller *ctrl); +#else +static inline bool pciehp_emul_will_manage(struct pci_dev *dev) +{ + return false; +}; + +static inline int pciehp_emul_attach(struct controller *ctrl) +{ + return 0; +}; + +static inline void pciehp_emul_detach(struct controller *ctrl) {}; +#endif + static inline const char *slot_name(struct controller *ctrl) { return hotplug_slot_name(&ctrl->hotplug_slot); diff --git a/drivers/pci/hotplug/pciehp_emul.c b/drivers/pci/hotplug/pciehp_emul.c index 716ec57feb79..81e39b0964b4 100644 --- a/drivers/pci/hotplug/pciehp_emul.c +++ b/drivers/pci/hotplug/pciehp_emul.c @@ -370,3 +370,11 @@ void pciehp_emul_detach(struct controller *ctrl) kfree(emul); } + +static int __init pciehp_emul_init(void) +{ + pcie_port_slot_emulated = &pciehp_emul_will_manage; + + return 0; +} +postcore_initcall(pciehp_emul_init); diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index f711448e0a70..fc5983e70997 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -1003,6 +1003,9 @@ struct controller *pcie_init(struct pcie_device *dev) ctrl->pcie = dev; ctrl->depth = pcie_hotplug_depth(dev->port); + if (pciehp_emul_will_manage(pdev) && pciehp_emul_attach(ctrl)) + return NULL; + pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap); if (pdev->hotplug_user_indicators) diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index b3c1e7d4ff10..3df397c01f0e 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -19,6 +19,9 @@ #include "../pci.h" #include "portdrv.h" +/* Hook for hotplug emulation driver */ +bool (*pcie_port_slot_emulated)(struct pci_dev *dev); + struct portdrv_service_data { struct pcie_port_service_driver *drv; struct device *dev; diff --git a/include/linux/pci.h b/include/linux/pci.h index 0c907f94bb61..0011e7775735 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1656,7 +1656,11 @@ extern bool pcie_ports_native; #define pcie_ports_native false #endif +#ifdef CONFIG_HOTPLUG_PCI_PCIE_EMUL +extern bool (*pcie_port_slot_emulated)(struct pci_dev *dev); +#else #define pcie_port_slot_emulated(dev) false +#endif #define PCIE_LINK_STATE_L0S BIT(0) #define PCIE_LINK_STATE_L1 BIT(1)