diff options
author | Niklas Schnelle <schnelle@linux.ibm.com> | 2024-09-26 16:08:30 +0200 |
---|---|---|
committer | Heiko Carstens <hca@linux.ibm.com> | 2024-10-10 15:32:43 +0200 |
commit | 126034faaac5f356822c4a9bebfa75664da11056 (patch) | |
tree | b901575a624b9d6e8e55465c392d2c3f03f2318a /arch/s390/pci | |
parent | s390/pci: Sort PCI functions prior to creating virtual busses (diff) | |
download | linux-126034faaac5f356822c4a9bebfa75664da11056.tar.xz linux-126034faaac5f356822c4a9bebfa75664da11056.zip |
s390/pci: Use topology ID for multi-function devices
The newly introduced topology ID (TID) field in the CLP Query PCI
Function explicitly identifies groups of PCI functions whose RIDs belong
to the same (sub-)topology. When available use the TID instead of the
PCHID to match zPCI busses/domains for multi-function devices. Note that
currently only a single PCI bus per TID is supported. This change is
required because in future machines the PCHID will not identify a PCI
card but a specific port in the case of some multi-port NICs while from
a PCI point of view the entire card is a subtopology.
Reviewed-by: Gerd Bayer <gbayer@linux.ibm.com>
Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Diffstat (limited to 'arch/s390/pci')
-rw-r--r-- | arch/s390/pci/pci_bus.c | 17 | ||||
-rw-r--r-- | arch/s390/pci/pci_clp.c | 3 |
2 files changed, 13 insertions, 7 deletions
diff --git a/arch/s390/pci/pci_bus.c b/arch/s390/pci/pci_bus.c index daa5d7450c7d..54879e773e4a 100644 --- a/arch/s390/pci/pci_bus.c +++ b/arch/s390/pci/pci_bus.c @@ -232,13 +232,13 @@ static void zpci_bus_put(struct zpci_bus *zbus) kref_put(&zbus->kref, zpci_bus_release); } -static struct zpci_bus *zpci_bus_get(int pchid) +static struct zpci_bus *zpci_bus_get(int topo, bool topo_is_tid) { struct zpci_bus *zbus; mutex_lock(&zbus_list_lock); list_for_each_entry(zbus, &zbus_list, bus_next) { - if (pchid == zbus->pchid) { + if (topo_is_tid == zbus->topo_is_tid && topo == zbus->topo) { kref_get(&zbus->kref); goto out_unlock; } @@ -249,7 +249,7 @@ out_unlock: return zbus; } -static struct zpci_bus *zpci_bus_alloc(int pchid) +static struct zpci_bus *zpci_bus_alloc(int topo, bool topo_is_tid) { struct zpci_bus *zbus; @@ -257,7 +257,8 @@ static struct zpci_bus *zpci_bus_alloc(int pchid) if (!zbus) return NULL; - zbus->pchid = pchid; + zbus->topo = topo; + zbus->topo_is_tid = topo_is_tid; INIT_LIST_HEAD(&zbus->bus_next); mutex_lock(&zbus_list_lock); list_add_tail(&zbus->bus_next, &zbus_list); @@ -321,8 +322,9 @@ error: int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops) { + bool topo_is_tid = zdev->tid_avail; struct zpci_bus *zbus = NULL; - int rc = -EBADF; + int topo, rc = -EBADF; if (zpci_nb_devices == ZPCI_NR_DEVICES) { pr_warn("Adding PCI function %08x failed because the configured limit of %d is reached\n", @@ -333,11 +335,12 @@ int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops) if (zdev->devfn >= ZPCI_FUNCTIONS_PER_BUS) return -EINVAL; + topo = topo_is_tid ? zdev->tid : zdev->pchid; if (!s390_pci_no_rid && zdev->rid_available) - zbus = zpci_bus_get(zdev->pchid); + zbus = zpci_bus_get(topo, topo_is_tid); if (!zbus) { - zbus = zpci_bus_alloc(zdev->pchid); + zbus = zpci_bus_alloc(topo, topo_is_tid); if (!zbus) return -ENOMEM; } diff --git a/arch/s390/pci/pci_clp.c b/arch/s390/pci/pci_clp.c index f7430086e973..e222036874e5 100644 --- a/arch/s390/pci/pci_clp.c +++ b/arch/s390/pci/pci_clp.c @@ -170,6 +170,9 @@ static int clp_store_query_pci_fn(struct zpci_dev *zdev, zdev->rid = response->rid; if (!s390_pci_no_rid && zdev->rid_available) zdev->devfn = response->rid & ZPCI_RID_MASK_DEVFN; + zdev->tid_avail = response->tid_avail; + if (zdev->tid_avail) + zdev->tid = response->tid; memcpy(zdev->pfip, response->pfip, sizeof(zdev->pfip)); if (response->util_str_avail) { |