|
| 1 | +s390/pci: Use topology ID for multi-function devices |
| 2 | + |
| 3 | +jira LE-2349 |
| 4 | +Rebuild_History Non-Buildable kernel-4.18.0-553.40.1.el8_10 |
| 5 | +commit-author Niklas Schnelle <schnelle@linux.ibm.com> |
| 6 | +commit 126034faaac5f356822c4a9bebfa75664da11056 |
| 7 | +Empty-Commit: Cherry-Pick Conflicts during history rebuild. |
| 8 | +Will be included in final tarball splat. Ref for failed cherry-pick at: |
| 9 | +ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/126034fa.failed |
| 10 | + |
| 11 | +The newly introduced topology ID (TID) field in the CLP Query PCI |
| 12 | +Function explicitly identifies groups of PCI functions whose RIDs belong |
| 13 | +to the same (sub-)topology. When available use the TID instead of the |
| 14 | +PCHID to match zPCI busses/domains for multi-function devices. Note that |
| 15 | +currently only a single PCI bus per TID is supported. This change is |
| 16 | +required because in future machines the PCHID will not identify a PCI |
| 17 | +card but a specific port in the case of some multi-port NICs while from |
| 18 | +a PCI point of view the entire card is a subtopology. |
| 19 | + |
| 20 | + Reviewed-by: Gerd Bayer <gbayer@linux.ibm.com> |
| 21 | + Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com> |
| 22 | + Signed-off-by: Heiko Carstens <hca@linux.ibm.com> |
| 23 | +(cherry picked from commit 126034faaac5f356822c4a9bebfa75664da11056) |
| 24 | + Signed-off-by: Jonathan Maple <jmaple@ciq.com> |
| 25 | + |
| 26 | +# Conflicts: |
| 27 | +# arch/s390/include/asm/pci.h |
| 28 | +diff --cc arch/s390/include/asm/pci.h |
| 29 | +index 15948089980a,e107eda7af86..000000000000 |
| 30 | +--- a/arch/s390/include/asm/pci.h |
| 31 | ++++ b/arch/s390/include/asm/pci.h |
| 32 | +@@@ -129,6 -131,8 +130,11 @@@ struct zpci_dev |
| 33 | + u16 vfn; /* virtual function number */ |
| 34 | + u16 pchid; /* physical channel ID */ |
| 35 | + u16 maxstbl; /* Maximum store block size */ |
| 36 | +++<<<<<<< HEAD |
| 37 | +++======= |
| 38 | ++ u16 rid; /* RID as supplied by firmware */ |
| 39 | ++ u16 tid; /* Topology for which RID is valid */ |
| 40 | +++>>>>>>> 126034faaac5 (s390/pci: Use topology ID for multi-function devices) |
| 41 | + u8 pfgid; /* function group ID */ |
| 42 | + u8 pft; /* pci function type */ |
| 43 | + u8 port; |
| 44 | +@@@ -139,10 -143,10 +145,11 @@@ |
| 45 | + u8 is_physfn : 1; |
| 46 | + u8 util_str_avail : 1; |
| 47 | + u8 irqs_registered : 1; |
| 48 | +- u8 reserved : 2; |
| 49 | ++ u8 tid_avail : 1; |
| 50 | ++ u8 reserved : 1; |
| 51 | + unsigned int devfn; /* DEVFN part of the RID*/ |
| 52 | + |
| 53 | + + struct mutex lock; |
| 54 | + u8 pfip[CLP_PFIP_NR_SEGMENTS]; /* pci function internal path */ |
| 55 | + u32 uid; /* user defined id */ |
| 56 | + u8 util_str[CLP_UTIL_STR_LEN]; /* utility string */ |
| 57 | +* Unmerged path arch/s390/include/asm/pci.h |
| 58 | +diff --git a/arch/s390/include/asm/pci_clp.h b/arch/s390/include/asm/pci_clp.h |
| 59 | +index d6189ed14f84..883aba330fea 100644 |
| 60 | +--- a/arch/s390/include/asm/pci_clp.h |
| 61 | ++++ b/arch/s390/include/asm/pci_clp.h |
| 62 | +@@ -107,7 +107,8 @@ struct clp_req_query_pci { |
| 63 | + struct clp_rsp_query_pci { |
| 64 | + struct clp_rsp_hdr hdr; |
| 65 | + u16 vfn; /* virtual fn number */ |
| 66 | +- u16 : 3; |
| 67 | ++ u16 : 2; |
| 68 | ++ u16 tid_avail : 1; |
| 69 | + u16 rid_avail : 1; |
| 70 | + u16 is_physfn : 1; |
| 71 | + u16 reserved1 : 1; |
| 72 | +@@ -127,8 +128,9 @@ struct clp_rsp_query_pci { |
| 73 | + u64 edma; /* end dma as */ |
| 74 | + #define ZPCI_RID_MASK_DEVFN 0x00ff |
| 75 | + u16 rid; /* BUS/DEVFN PCI address */ |
| 76 | +- u16 reserved0; |
| 77 | +- u32 reserved[10]; |
| 78 | ++ u32 reserved0; |
| 79 | ++ u16 tid; |
| 80 | ++ u32 reserved[9]; |
| 81 | + u32 uid; /* user defined id */ |
| 82 | + u8 util_str[CLP_UTIL_STR_LEN]; /* utility string */ |
| 83 | + u32 reserved2[16]; |
| 84 | +diff --git a/arch/s390/pci/pci_bus.c b/arch/s390/pci/pci_bus.c |
| 85 | +index 32245b970a0c..0daefa365cf4 100644 |
| 86 | +--- a/arch/s390/pci/pci_bus.c |
| 87 | ++++ b/arch/s390/pci/pci_bus.c |
| 88 | +@@ -237,13 +237,13 @@ static void zpci_bus_put(struct zpci_bus *zbus) |
| 89 | + kref_put(&zbus->kref, zpci_bus_release); |
| 90 | + } |
| 91 | + |
| 92 | +-static struct zpci_bus *zpci_bus_get(int pchid) |
| 93 | ++static struct zpci_bus *zpci_bus_get(int topo, bool topo_is_tid) |
| 94 | + { |
| 95 | + struct zpci_bus *zbus; |
| 96 | + |
| 97 | + mutex_lock(&zbus_list_lock); |
| 98 | + list_for_each_entry(zbus, &zbus_list, bus_next) { |
| 99 | +- if (pchid == zbus->pchid) { |
| 100 | ++ if (topo_is_tid == zbus->topo_is_tid && topo == zbus->topo) { |
| 101 | + kref_get(&zbus->kref); |
| 102 | + goto out_unlock; |
| 103 | + } |
| 104 | +@@ -254,7 +254,7 @@ static struct zpci_bus *zpci_bus_get(int pchid) |
| 105 | + return zbus; |
| 106 | + } |
| 107 | + |
| 108 | +-static struct zpci_bus *zpci_bus_alloc(int pchid) |
| 109 | ++static struct zpci_bus *zpci_bus_alloc(int topo, bool topo_is_tid) |
| 110 | + { |
| 111 | + struct zpci_bus *zbus; |
| 112 | + |
| 113 | +@@ -262,7 +262,8 @@ static struct zpci_bus *zpci_bus_alloc(int pchid) |
| 114 | + if (!zbus) |
| 115 | + return NULL; |
| 116 | + |
| 117 | +- zbus->pchid = pchid; |
| 118 | ++ zbus->topo = topo; |
| 119 | ++ zbus->topo_is_tid = topo_is_tid; |
| 120 | + INIT_LIST_HEAD(&zbus->bus_next); |
| 121 | + mutex_lock(&zbus_list_lock); |
| 122 | + list_add_tail(&zbus->bus_next, &zbus_list); |
| 123 | +@@ -326,8 +327,9 @@ static int zpci_bus_add_device(struct zpci_bus *zbus, struct zpci_dev *zdev) |
| 124 | + |
| 125 | + int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops) |
| 126 | + { |
| 127 | ++ bool topo_is_tid = zdev->tid_avail; |
| 128 | + struct zpci_bus *zbus = NULL; |
| 129 | +- int rc = -EBADF; |
| 130 | ++ int topo, rc = -EBADF; |
| 131 | + |
| 132 | + if (zpci_nb_devices == ZPCI_NR_DEVICES) { |
| 133 | + pr_warn("Adding PCI function %08x failed because the configured limit of %d is reached\n", |
| 134 | +@@ -338,11 +340,12 @@ int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops) |
| 135 | + if (zdev->devfn >= ZPCI_FUNCTIONS_PER_BUS) |
| 136 | + return -EINVAL; |
| 137 | + |
| 138 | ++ topo = topo_is_tid ? zdev->tid : zdev->pchid; |
| 139 | + if (!s390_pci_no_rid && zdev->rid_available) |
| 140 | +- zbus = zpci_bus_get(zdev->pchid); |
| 141 | ++ zbus = zpci_bus_get(topo, topo_is_tid); |
| 142 | + |
| 143 | + if (!zbus) { |
| 144 | +- zbus = zpci_bus_alloc(zdev->pchid); |
| 145 | ++ zbus = zpci_bus_alloc(topo, topo_is_tid); |
| 146 | + if (!zbus) |
| 147 | + return -ENOMEM; |
| 148 | + } |
| 149 | +diff --git a/arch/s390/pci/pci_clp.c b/arch/s390/pci/pci_clp.c |
| 150 | +index 34759316747b..384fdd16c2ea 100644 |
| 151 | +--- a/arch/s390/pci/pci_clp.c |
| 152 | ++++ b/arch/s390/pci/pci_clp.c |
| 153 | +@@ -167,6 +167,9 @@ static int clp_store_query_pci_fn(struct zpci_dev *zdev, |
| 154 | + zdev->is_physfn = response->is_physfn; |
| 155 | + if (!s390_pci_no_rid && zdev->rid_available) |
| 156 | + zdev->devfn = response->rid & ZPCI_RID_MASK_DEVFN; |
| 157 | ++ zdev->tid_avail = response->tid_avail; |
| 158 | ++ if (zdev->tid_avail) |
| 159 | ++ zdev->tid = response->tid; |
| 160 | + |
| 161 | + memcpy(zdev->pfip, response->pfip, sizeof(zdev->pfip)); |
| 162 | + if (response->util_str_avail) { |
0 commit comments