Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Niklas Schnelle and committed by
Heiko Carstens
126034fa 0467cdde

+24 -13
+6 -3
arch/s390/include/asm/pci.h
··· 107 107 struct list_head resources; 108 108 struct list_head bus_next; 109 109 struct resource bus_resource; 110 - int pchid; 110 + int topo; /* TID if topo_is_tid, PCHID otherwise */ 111 111 int domain_nr; 112 - bool multifunction; 112 + u8 multifunction : 1; 113 + u8 topo_is_tid : 1; 113 114 enum pci_bus_speed max_bus_speed; 114 115 }; 115 116 ··· 132 131 u16 pchid; /* physical channel ID */ 133 132 u16 maxstbl; /* Maximum store block size */ 134 133 u16 rid; /* RID as supplied by firmware */ 134 + u16 tid; /* Topology for which RID is valid */ 135 135 u8 pfgid; /* function group ID */ 136 136 u8 pft; /* pci function type */ 137 137 u8 port; ··· 143 141 u8 is_physfn : 1; 144 142 u8 util_str_avail : 1; 145 143 u8 irqs_registered : 1; 146 - u8 reserved : 2; 144 + u8 tid_avail : 1; 145 + u8 reserved : 1; 147 146 unsigned int devfn; /* DEVFN part of the RID*/ 148 147 149 148 u8 pfip[CLP_PFIP_NR_SEGMENTS]; /* pci function internal path */
+5 -3
arch/s390/include/asm/pci_clp.h
··· 110 110 struct clp_rsp_query_pci { 111 111 struct clp_rsp_hdr hdr; 112 112 u16 vfn; /* virtual fn number */ 113 - u16 : 3; 113 + u16 : 2; 114 + u16 tid_avail : 1; 114 115 u16 rid_avail : 1; 115 116 u16 is_physfn : 1; 116 117 u16 reserved1 : 1; ··· 131 130 u64 edma; /* end dma as */ 132 131 #define ZPCI_RID_MASK_DEVFN 0x00ff 133 132 u16 rid; /* BUS/DEVFN PCI address */ 134 - u16 reserved0; 135 - u32 reserved[10]; 133 + u32 reserved0; 134 + u16 tid; 135 + u32 reserved[9]; 136 136 u32 uid; /* user defined id */ 137 137 u8 util_str[CLP_UTIL_STR_LEN]; /* utility string */ 138 138 u32 reserved2[16];
+10 -7
arch/s390/pci/pci_bus.c
··· 232 232 kref_put(&zbus->kref, zpci_bus_release); 233 233 } 234 234 235 - static struct zpci_bus *zpci_bus_get(int pchid) 235 + static struct zpci_bus *zpci_bus_get(int topo, bool topo_is_tid) 236 236 { 237 237 struct zpci_bus *zbus; 238 238 239 239 mutex_lock(&zbus_list_lock); 240 240 list_for_each_entry(zbus, &zbus_list, bus_next) { 241 - if (pchid == zbus->pchid) { 241 + if (topo_is_tid == zbus->topo_is_tid && topo == zbus->topo) { 242 242 kref_get(&zbus->kref); 243 243 goto out_unlock; 244 244 } ··· 249 249 return zbus; 250 250 } 251 251 252 - static struct zpci_bus *zpci_bus_alloc(int pchid) 252 + static struct zpci_bus *zpci_bus_alloc(int topo, bool topo_is_tid) 253 253 { 254 254 struct zpci_bus *zbus; 255 255 ··· 257 257 if (!zbus) 258 258 return NULL; 259 259 260 - zbus->pchid = pchid; 260 + zbus->topo = topo; 261 + zbus->topo_is_tid = topo_is_tid; 261 262 INIT_LIST_HEAD(&zbus->bus_next); 262 263 mutex_lock(&zbus_list_lock); 263 264 list_add_tail(&zbus->bus_next, &zbus_list); ··· 322 321 323 322 int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops) 324 323 { 324 + bool topo_is_tid = zdev->tid_avail; 325 325 struct zpci_bus *zbus = NULL; 326 - int rc = -EBADF; 326 + int topo, rc = -EBADF; 327 327 328 328 if (zpci_nb_devices == ZPCI_NR_DEVICES) { 329 329 pr_warn("Adding PCI function %08x failed because the configured limit of %d is reached\n", ··· 335 333 if (zdev->devfn >= ZPCI_FUNCTIONS_PER_BUS) 336 334 return -EINVAL; 337 335 336 + topo = topo_is_tid ? zdev->tid : zdev->pchid; 338 337 if (!s390_pci_no_rid && zdev->rid_available) 339 - zbus = zpci_bus_get(zdev->pchid); 338 + zbus = zpci_bus_get(topo, topo_is_tid); 340 339 341 340 if (!zbus) { 342 - zbus = zpci_bus_alloc(zdev->pchid); 341 + zbus = zpci_bus_alloc(topo, topo_is_tid); 343 342 if (!zbus) 344 343 return -ENOMEM; 345 344 }
+3
arch/s390/pci/pci_clp.c
··· 170 170 zdev->rid = response->rid; 171 171 if (!s390_pci_no_rid && zdev->rid_available) 172 172 zdev->devfn = response->rid & ZPCI_RID_MASK_DEVFN; 173 + zdev->tid_avail = response->tid_avail; 174 + if (zdev->tid_avail) 175 + zdev->tid = response->tid; 173 176 174 177 memcpy(zdev->pfip, response->pfip, sizeof(zdev->pfip)); 175 178 if (response->util_str_avail) {