From: Ashok Raj <ashok.raj@intel.com>
To: Lukas Wunner <lukas@wunner.de>
Cc: Bjorn Helgaas <helgaas@kernel.org>, <linux-pci@vger.kernel.org>,
"Alex Williamson" <alex.williamson@redhat.com>,
Amey Narkhede <ameynarkhede03@gmail.com>,
Keith Busch <kbusch@kernel.org>,
"Sathyanarayanan Kuppuswamy"
<sathyanarayanan.kuppuswamy@linux.intel.com>,
"Ravi Kishore Koppuravuri" <ravi.kishore.koppuravuri@intel.com>,
Mika Westerberg <mika.westerberg@linux.intel.com>,
Ashok Raj <ashok.raj@intel.com>
Subject: Re: [PATCH] PCI/DPC: Add Software Trigger as reset method
Date: Tue, 29 Nov 2022 05:09:18 -0800 [thread overview]
Message-ID: <Y4YEfrG2jFLiEyoP@a4bf019067fa.jf.intel.com> (raw)
In-Reply-To: <9c1533fd42e9002bd6d2020656fa1dd0e3e3bf3a.1669706952.git.lukas@wunner.de>
On Tue, Nov 29, 2022 at 08:35:55AM +0100, Lukas Wunner wrote:
> Add DPC Software Trigger as a reset method to be used for silicon
> validation among other things:
>
> # echo dpc_sw_trigger > reset_method
> # echo 1 > reset
>
> After validating DPC, the default reset_method(s) may be reinstated:
>
> # echo default > reset_method
>
> Writing the DPC Control Register requires that control was granted by
> firmware, so expose the reset_method only if DPC is native. (And AER,
> which must always be granted or denied in unison per PCI Firmware Spec
> r3.3 table 4-5.)
>
> The reset attribute in sysfs is meant to reset a single PCI Function,
> but DPC resets the entire hierarchy below the parent. So only expose
> the reset method on PCI Functions without siblings or children.
> Checking for that may happen both *before* the PCI Function has been
> added to the bus list (via pci_device_add() -> pci_init_capabilities())
> and *after* (via reset_method_store()), hence differentiate between
> those two cases on reset probing.
>
> It would be useful for silicon validation to have a separate sysfs
> attribute for PCI bridges to reset their downstream hierarchy. Prepare
> for introduction of such an attribute by adding separate functions
> pci_dpc_sw_trigger() (to reset the hierarchy below a bridge) and
> pci_dpc_sw_trigger_parent() (to reset a single PCI Function), where the
> latter calls the former to trigger DPC on the parent bridge.
>
> Signed-off-by: Lukas Wunner <lukas@wunner.de>
Minor nit: Do you think debugfs might be a better place to stash some of
these non-production use cases?
Reviewed-by: Ashok Raj <ashok.raj@intel.com>
> ---
> drivers/pci/pci.c | 1 +
> drivers/pci/pci.h | 2 ++
> drivers/pci/pcie/dpc.c | 57 +++++++++++++++++++++++++++++++++++
> include/linux/pci.h | 2 +-
> include/uapi/linux/pci_regs.h | 1 +
> 5 files changed, 62 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index fba95486caaf..f561f84a8bca 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -5225,6 +5225,7 @@ static const struct pci_reset_fn_method pci_reset_fn_methods[] = {
> { pci_af_flr, .name = "af_flr" },
> { pci_pm_reset, .name = "pm" },
> { pci_reset_bus_function, .name = "bus" },
> + { pci_dpc_sw_trigger_parent, .name = "dpc_sw_trigger" },
> };
>
> static ssize_t reset_method_show(struct device *dev,
> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
> index 9ed3b5550043..da2a3af4c46c 100644
> --- a/drivers/pci/pci.h
> +++ b/drivers/pci/pci.h
> @@ -425,11 +425,13 @@ void pci_dpc_init(struct pci_dev *pdev);
> void dpc_process_error(struct pci_dev *pdev);
> pci_ers_result_t dpc_reset_link(struct pci_dev *pdev);
> bool pci_dpc_recovered(struct pci_dev *pdev);
> +int pci_dpc_sw_trigger_parent(struct pci_dev *pdev, bool probe);
> #else
> static inline void pci_save_dpc_state(struct pci_dev *dev) {}
> static inline void pci_restore_dpc_state(struct pci_dev *dev) {}
> static inline void pci_dpc_init(struct pci_dev *pdev) {}
> static inline bool pci_dpc_recovered(struct pci_dev *pdev) { return false; }
> +static inline int pci_dpc_sw_trigger_parent(struct pci_dev *pdev, bool probe) { return -ENOTTY; }
> #endif
>
> #ifdef CONFIG_PCIEPORTBUS
> diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c
> index f5ffea17c7f8..47fd69d0a9c2 100644
> --- a/drivers/pci/pcie/dpc.c
> +++ b/drivers/pci/pcie/dpc.c
> @@ -322,6 +322,63 @@ static irqreturn_t dpc_irq(int irq, void *context)
> return IRQ_HANDLED;
> }
>
> +static int pci_dpc_sw_trigger(struct pci_dev *pdev, bool probe)
> +{
> + struct pci_host_bridge *host;
> + u16 cap, ctl;
> +
> + if (probe) {
> + if (!pdev->dpc_cap)
> + return -ENOTTY;
> +
> + host = pci_find_host_bridge(pdev->bus);
> + if (!host->native_dpc && !pcie_ports_dpc_native)
> + return -ENOTTY;
> +
> + if (!pcie_aer_is_native(pdev))
> + return -ENOTTY;
> +
> + pci_read_config_word(pdev, pdev->dpc_cap + PCI_EXP_DPC_CAP,
> + &cap);
> + if (!(cap & PCI_EXP_DPC_CAP_SW_TRIGGER))
> + return -ENOTTY;
> +
> + return 0;
> + }
> +
> + pci_read_config_word(pdev, pdev->dpc_cap + PCI_EXP_DPC_CTL, &ctl);
> + ctl |= PCI_EXP_DPC_CTL_SW_TRIGGER;
> + pci_write_config_word(pdev, pdev->dpc_cap + PCI_EXP_DPC_CTL, ctl);
> + return 0;
> +}
> +
> +int pci_dpc_sw_trigger_parent(struct pci_dev *pdev, bool probe)
> +{
> + if (probe) {
> + /*
> + * Reset must only affect @pdev, so bail out if it has siblings
> + * or descendants. Need to differentiate whether @pdev has
> + * already been added to the bus list or not:
> + */
> + if (list_empty(&pdev->bus_list) &&
> + !list_empty(&pdev->bus->devices))
> + return -ENOTTY;
> +
> + if (!list_empty(&pdev->bus_list) &&
> + !list_is_singular(&pdev->bus->devices))
> + return -ENOTTY;
> +
> + if (pdev->subordinate &&
> + !list_empty(&pdev->subordinate->devices))
> + return -ENOTTY;
> +
> + if (!pdev->bus->self)
> + return -ENOTTY;
> + }
> +
> + return pci_dpc_sw_trigger(pdev->bus->self, probe);
> +}
> +
> void pci_dpc_init(struct pci_dev *pdev)
> {
> u16 cap;
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 28af4414f789..7890cd4eb97d 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -50,7 +50,7 @@
> PCI_STATUS_PARITY)
>
> /* Number of reset methods used in pci_reset_fn_methods array in pci.c */
> -#define PCI_NUM_RESET_METHODS 7
> +#define PCI_NUM_RESET_METHODS 8
>
> #define PCI_RESET_PROBE true
> #define PCI_RESET_DO_RESET false
> diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
> index 1c3591c8e09e..73b3ccdffb3a 100644
> --- a/include/uapi/linux/pci_regs.h
> +++ b/include/uapi/linux/pci_regs.h
> @@ -1035,6 +1035,7 @@
> #define PCI_EXP_DPC_CTL 0x06 /* DPC control */
> #define PCI_EXP_DPC_CTL_EN_FATAL 0x0001 /* Enable trigger on ERR_FATAL message */
> #define PCI_EXP_DPC_CTL_EN_NONFATAL 0x0002 /* Enable trigger on ERR_NONFATAL message */
> +#define PCI_EXP_DPC_CTL_SW_TRIGGER 0x0040 /* Software Trigger */
> #define PCI_EXP_DPC_CTL_INT_EN 0x0008 /* DPC Interrupt Enable */
>
> #define PCI_EXP_DPC_STATUS 0x08 /* DPC Status */
> --
> 2.36.1
>
next prev parent reply other threads:[~2022-11-29 13:09 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-11-29 7:35 [PATCH] PCI/DPC: Add Software Trigger as reset method Lukas Wunner
2022-11-29 13:09 ` Ashok Raj [this message]
2022-11-29 15:44 ` Mika Westerberg
2022-11-29 16:27 ` Sathyanarayanan Kuppuswamy
2022-11-30 7:37 ` Lukas Wunner
2022-11-29 16:36 ` Keith Busch
2022-11-30 7:30 ` Lukas Wunner
2022-12-06 17:11 ` Bjorn Helgaas
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Y4YEfrG2jFLiEyoP@a4bf019067fa.jf.intel.com \
--to=ashok.raj@intel.com \
--cc=alex.williamson@redhat.com \
--cc=ameynarkhede03@gmail.com \
--cc=helgaas@kernel.org \
--cc=kbusch@kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=lukas@wunner.de \
--cc=mika.westerberg@linux.intel.com \
--cc=ravi.kishore.koppuravuri@intel.com \
--cc=sathyanarayanan.kuppuswamy@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox