]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
s390/pci: Use topology ID for multi-function devices
authorNiklas Schnelle <schnelle@linux.ibm.com>
Thu, 26 Sep 2024 14:08:30 +0000 (16:08 +0200)
committerHeiko Carstens <hca@linux.ibm.com>
Thu, 10 Oct 2024 13:32:43 +0000 (15:32 +0200)
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>
arch/s390/include/asm/pci.h
arch/s390/include/asm/pci_clp.h
arch/s390/pci/pci_bus.c
arch/s390/pci/pci_clp.c

index 45e87c7c122a61cf3959c768859c354616ab9559..e107eda7af86fc12fe8ee66a9668264b77cbdb95 100644 (file)
@@ -107,9 +107,10 @@ struct zpci_bus {
        struct list_head        resources;
        struct list_head        bus_next;
        struct resource         bus_resource;
-       int                     pchid;
+       int                     topo;           /* TID if topo_is_tid, PCHID otherwise */
        int                     domain_nr;
-       bool                    multifunction;
+       u8                      multifunction   : 1;
+       u8                      topo_is_tid     : 1;
        enum pci_bus_speed      max_bus_speed;
 };
 
@@ -131,6 +132,7 @@ struct zpci_dev {
        u16             pchid;          /* physical channel ID */
        u16             maxstbl;        /* Maximum store block size */
        u16             rid;            /* RID as supplied by firmware */
+       u16             tid;            /* Topology for which RID is valid */
        u8              pfgid;          /* function group ID */
        u8              pft;            /* pci function type */
        u8              port;
@@ -141,7 +143,8 @@ struct zpci_dev {
        u8              is_physfn       : 1;
        u8              util_str_avail  : 1;
        u8              irqs_registered : 1;
-       u8              reserved        : 2;
+       u8              tid_avail       : 1;
+       u8              reserved        : 1;
        unsigned int    devfn;          /* DEVFN part of the RID*/
 
        u8 pfip[CLP_PFIP_NR_SEGMENTS];  /* pci function internal path */
index f0c677ddd270606df61e7fd6ccd9b6c17f89f6b9..14afb9ce91f3bc6804de7c732ca22ae71300038e 100644 (file)
@@ -110,7 +110,8 @@ struct clp_req_query_pci {
 struct clp_rsp_query_pci {
        struct clp_rsp_hdr hdr;
        u16 vfn;                        /* virtual fn number */
-       u16                     :  3;
+       u16                     :  2;
+       u16 tid_avail           :  1;
        u16 rid_avail           :  1;
        u16 is_physfn           :  1;
        u16 reserved1           :  1;
@@ -130,8 +131,9 @@ struct clp_rsp_query_pci {
        u64 edma;                       /* end dma as */
 #define ZPCI_RID_MASK_DEVFN 0x00ff
        u16 rid;                        /* BUS/DEVFN PCI address */
-       u16 reserved0;
-       u32 reserved[10];
+       u32 reserved0;
+       u16 tid;
+       u32 reserved[9];
        u32 uid;                        /* user defined id */
        u8 util_str[CLP_UTIL_STR_LEN];  /* utility string */
        u32 reserved2[16];
index daa5d7450c7d383b254d225d022e23a14c105e41..54879e773e4a317199600c5b1a9f8eedb0255c38 100644 (file)
@@ -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;
        }
index f7430086e97391bae436dbaf38db039d4cba98cc..e222036874e516db6136a4dc848c723308b2f825 100644 (file)
@@ -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) {