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

s390/pci: Ignore RID for isolated VFs

Ensure that VFs used in isolation, that is with their parent PF not
visible to the configuration but with their RID exposed, are treated
compatibly with existing isolated VF use cases without exposed RID
including RoCE Express VFs. This allows creating configurations where
one LPAR manages PFs while their child VFs are used by other LPARs. This
gives the LPAR managing the PFs a role analogous to that of the
hypervisor in a typical use case of passing child VFs to guests.

Instead of creating a multifunction struct zpci_bus whenever a PCI
function with RID exposed is discovered only create such a bus for
configured physical functions and only consider multifunction busses
when searching for an existing bus. Additionally only set zdev->devfn to
the devfn part of the RID once the function is added to a multifunction
bus.

This also fixes probing of more than 7 such isolated VFs from the same
physical bus. This is because common PCI code in pci_scan_slot() only
looks for more functions when pdev->multifunction is set which somewhat
counter intutively is not the case for VFs.

Note that PFs are looked at before their child VFs is guaranteed because
we sort the zpci_list by RID ascending.

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
25f39d3d 126034fa

+20 -15
+20 -13
arch/s390/pci/pci_bus.c
··· 168 168 mutex_unlock(&zbus_list_lock); 169 169 } 170 170 171 + static bool zpci_bus_is_multifunction_root(struct zpci_dev *zdev) 172 + { 173 + return !s390_pci_no_rid && zdev->rid_available && 174 + zpci_is_device_configured(zdev) && 175 + !zdev->vfn; 176 + } 177 + 171 178 /* zpci_bus_create_pci_bus - Create the PCI bus associated with this zbus 172 179 * @zbus: the zbus holding the zdevices 173 - * @fr: PCI root function that will determine the bus's domain, and bus speeed 180 + * @fr: PCI root function that will determine the bus's domain, and bus speed 174 181 * @ops: the pci operations 175 182 * 176 183 * The PCI function @fr determines the domain (its UID), multifunction property ··· 195 188 return domain; 196 189 197 190 zbus->domain_nr = domain; 198 - zbus->multifunction = fr->rid_available; 191 + zbus->multifunction = zpci_bus_is_multifunction_root(fr); 199 192 zbus->max_bus_speed = fr->max_bus_speed; 200 193 201 194 /* ··· 245 238 246 239 mutex_lock(&zbus_list_lock); 247 240 list_for_each_entry(zbus, &zbus_list, bus_next) { 241 + if (!zbus->multifunction) 242 + continue; 248 243 if (topo_is_tid == zbus->topo_is_tid && topo == zbus->topo) { 249 244 kref_get(&zbus->kref); 250 245 goto out_unlock; ··· 302 293 { 303 294 int rc = -EINVAL; 304 295 296 + if (zbus->multifunction) { 297 + if (!zdev->rid_available) { 298 + WARN_ONCE(1, "rid_available not set for multifunction\n"); 299 + return rc; 300 + } 301 + zdev->devfn = zdev->rid & ZPCI_RID_MASK_DEVFN; 302 + } 303 + 305 304 if (zbus->function[zdev->devfn]) { 306 305 pr_err("devfn %04x is already assigned\n", zdev->devfn); 307 306 return rc; 308 307 } 309 - 310 308 zdev->zbus = zbus; 311 309 zbus->function[zdev->devfn] = zdev; 312 310 zpci_nb_devices++; 313 311 314 - if (zbus->multifunction && !zdev->rid_available) { 315 - WARN_ONCE(1, "rid_available not set for multifunction\n"); 316 - goto error; 317 - } 318 312 rc = zpci_init_slot(zdev); 319 313 if (rc) 320 314 goto error; ··· 344 332 return -ENOSPC; 345 333 } 346 334 347 - if (zdev->devfn >= ZPCI_FUNCTIONS_PER_BUS) 348 - return -EINVAL; 349 - 350 335 topo = topo_is_tid ? zdev->tid : zdev->pchid; 351 - if (!s390_pci_no_rid && zdev->rid_available) 352 - zbus = zpci_bus_get(topo, topo_is_tid); 353 - 336 + zbus = zpci_bus_get(topo, topo_is_tid); 354 337 if (!zbus) { 355 338 zbus = zpci_bus_alloc(topo, topo_is_tid); 356 339 if (!zbus)
-2
arch/s390/pci/pci_clp.c
··· 168 168 zdev->rid_available = response->rid_avail; 169 169 if (zdev->rid_available) 170 170 zdev->rid = response->rid; 171 - if (!s390_pci_no_rid && zdev->rid_available) 172 - zdev->devfn = response->rid & ZPCI_RID_MASK_DEVFN; 173 171 zdev->tid_avail = response->tid_avail; 174 172 if (zdev->tid_avail) 175 173 zdev->tid = response->tid;