2022-04-04 23:39:22

by Shlomo Pongratz

[permalink] [raw]
Subject: [PATCH V6 0/1] Intel Sky Lake-E host root ports check.

Changes in v6:

Address Bjorn Helgaas comments, e.g. commit line length and using both
"Sky Lake-E" and "SkyLake-E" in comments.
The comments in the code now use Skylake.
However the patch subject still refers to "Sky Lake-E" since
Andrew Maier's original patch used that name.

Changes in v5:

Address Logan Gunthorpe, Jason Gunthorpe and Bjorn Helgaas comments.
Fix indentation.
Update comments.

Changes in v4:

Address Bjorn Helgaas and Jason Gunthorpe comments.
Replace the implementation of pci_is_root_port with a simple check
pci_pcie_type(root) != PCI_EXP_TYPE_ROOT_PORT and remove the added
IS_ROOT_PORT flag.
Update patch text.

Changes in v3:

Use Jason Gunthorpe suggestion, that is add a flag 'IS_ROOT_PORT'
instead of 'port' and then just ignore the slot number entirely for root
ports.

Changes in v2:

Change comment and description based on Logan Gunthorpe comments.

v1:

In commit 7b94b53db34f ("PCI/P2PDMA: Add Intel Sky Lake-E Root Ports B, C,
D to the whitelist")
Andrew Maier added the Sky Lake-E additional devices
2031, 2032 and 2033 root ports to the already existing 2030 device.

The Intel devices 2030, 2031, 2032 and 2033 which are root ports A, B, C
and D, respectively and if all exist they will occupy slots 0 till 3 in
that order.

The original code handled only the case where the devices in the whitelist
are host bridges and assumed that they will be found on slot 0.

Since this assumption doesn't hold for root ports, add a test to cover this
case.

Shlomo Pongratz (1):
Intel Sky Lake-E host root ports check.

drivers/pci/p2pdma.c | 25 ++++++++++++++++++-------
1 file changed, 18 insertions(+), 7 deletions(-)

--
2.17.1


2022-04-05 01:39:31

by Shlomo Pongratz

[permalink] [raw]
Subject: [PATCH V6 1/1] Intel Sky Lake-E host root ports check.

In commit 7b94b53db34f ("PCI/P2PDMA: Add Intel Sky Lake-E Root Ports B, C,
D to the whitelist")
Andrew Maier added the Sky Lake-E additional devices
2031, 2032 and 2033 root ports to the already existing 2030 device.

The Intel devices 2030, 2031, 2032 and 2033 which are root ports A, B, C
and D, respectively and if all exist they will occupy slots 0 till 3 in
that order.

The original code handled only the case where the devices in the whitelist
are host bridges and assumed that they will be found on slot 0.

Since this assumption doesn't hold for root ports, add a test to cover this
case.

Signed-off-by: Shlomo Pongratz <[email protected]>
---
drivers/pci/p2pdma.c | 25 ++++++++++++++++++-------
1 file changed, 18 insertions(+), 7 deletions(-)

diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
index 30b1df3c9d2f..c281bf5b304a 100644
--- a/drivers/pci/p2pdma.c
+++ b/drivers/pci/p2pdma.c
@@ -327,15 +327,19 @@ static const struct pci_p2pdma_whitelist_entry {

/*
* This lookup function tries to find the PCI device corresponding to a given
- * host bridge.
+ * host bridge or a root port.
*
* It assumes the host bridge device is the first PCI device in the
- * bus->devices list and that the devfn is 00.0. These assumptions should hold
- * for all the devices in the whitelist above.
+ * bus->devices list and that the devfn is 00.0. The first assumption should
+ * hold for all the devices in the whitelist above, however the second
+ * assumption doesn't always hold for root ports.
+ * For example for Intel Skylake devices 2030, 2031, 2032 and 2033,
+ * which are root ports (A, B, C and D respectively).
+ * So the function checks explicitly that the device is a root port.
*
- * This function is equivalent to pci_get_slot(host->bus, 0), however it does
- * not take the pci_bus_sem lock seeing __host_bridge_whitelist() must not
- * sleep.
+ * This function is equivalent to pci_get_slot(host->bus, 0) (except for
+ * the root port test), however it does not take the pci_bus_sem lock seeing
+ * __host_bridge_whitelist() must not sleep.
*
* For this to be safe, the caller should hold a reference to a device on the
* bridge, which should ensure the host_bridge device will not be freed
@@ -350,7 +354,14 @@ static struct pci_dev *pci_host_bridge_dev(struct pci_host_bridge *host)

if (!root)
return NULL;
- if (root->devfn != PCI_DEVFN(0, 0))
+
+ /* Verify that the device is a host bridge or a root port
+ * It is assumed that host bridges have a 0 devfn, (common practice)
+ * but some of the entries in the whitelist are root ports that can
+ * have any devfn
+ */
+ if (root->devfn != PCI_DEVFN(0, 0) &&
+ pci_pcie_type(root) != PCI_EXP_TYPE_ROOT_PORT)
return NULL;

return root;
--
2.17.1

2022-04-07 23:01:15

by Bjorn Helgaas

[permalink] [raw]
Subject: Re: [PATCH V6 1/1] Intel Sky Lake-E host root ports check.

On Sun, Apr 03, 2022 at 01:20:08PM +0300, Shlomo Pongratz wrote:
> In commit 7b94b53db34f ("PCI/P2PDMA: Add Intel Sky Lake-E Root Ports B, C,
> D to the whitelist")
> Andrew Maier added the Sky Lake-E additional devices
> 2031, 2032 and 2033 root ports to the already existing 2030 device.
>
> The Intel devices 2030, 2031, 2032 and 2033 which are root ports A, B, C
> and D, respectively and if all exist they will occupy slots 0 till 3 in
> that order.
>
> The original code handled only the case where the devices in the whitelist
> are host bridges and assumed that they will be found on slot 0.
>
> Since this assumption doesn't hold for root ports, add a test to cover this
> case.
>
> Signed-off-by: Shlomo Pongratz <[email protected]>
> ---
> drivers/pci/p2pdma.c | 25 ++++++++++++++++++-------
> 1 file changed, 18 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
> index 30b1df3c9d2f..c281bf5b304a 100644
> --- a/drivers/pci/p2pdma.c
> +++ b/drivers/pci/p2pdma.c
> @@ -327,15 +327,19 @@ static const struct pci_p2pdma_whitelist_entry {
>
> /*
> * This lookup function tries to find the PCI device corresponding to a given
> - * host bridge.
> + * host bridge or a root port.
> *
> * It assumes the host bridge device is the first PCI device in the
> - * bus->devices list and that the devfn is 00.0. These assumptions should hold
> - * for all the devices in the whitelist above.
> + * bus->devices list and that the devfn is 00.0. The first assumption should
> + * hold for all the devices in the whitelist above, however the second
> + * assumption doesn't always hold for root ports.
> + * For example for Intel Skylake devices 2030, 2031, 2032 and 2033,
> + * which are root ports (A, B, C and D respectively).
> + * So the function checks explicitly that the device is a root port.
> *

> - * This function is equivalent to pci_get_slot(host->bus, 0), however it does
> - * not take the pci_bus_sem lock seeing __host_bridge_whitelist() must not
> - * sleep.
> + * This function is equivalent to pci_get_slot(host->bus, 0) (except for
> + * the root port test), however it does not take the pci_bus_sem lock seeing
> + * __host_bridge_whitelist() must not sleep.
> *
> * For this to be safe, the caller should hold a reference to a device on the
> * bridge, which should ensure the host_bridge device will not be freed
> @@ -350,7 +354,14 @@ static struct pci_dev *pci_host_bridge_dev(struct pci_host_bridge *host)
>
> if (!root)
> return NULL;
> - if (root->devfn != PCI_DEVFN(0, 0))
> +
> + /* Verify that the device is a host bridge or a root port
> + * It is assumed that host bridges have a 0 devfn, (common practice)
> + * but some of the entries in the whitelist are root ports that can
> + * have any devfn
> + */
> + if (root->devfn != PCI_DEVFN(0, 0) &&
> + pci_pcie_type(root) != PCI_EXP_TYPE_ROOT_PORT)
> return NULL;
>
> return root;

The negative logic here makes this hard to read. The previous code
was the same as:

if (root->devfn == PCI_DEVFN(0, 0))
return root;

return NULL;

I think this patch would be easier to read if you made it:

if (root->devfn == PCI_DEVFN(0, 0))
return root;

if (pci_pcie_type(root) == PCI_EXP_TYPE_ROOT_PORT)
return root;

return NULL;

IIUC, this patch tweaks it so we take the first device on the bus and
if it is either 00.0 or a Root Port, we search pci_p2pdma_whitelist[]
for it.