Skip to content

Commit 25f39d3

Browse files
niklas88hcahca
authored andcommitted
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 <[email protected]> Signed-off-by: Niklas Schnelle <[email protected]> Signed-off-by: Heiko Carstens <[email protected]>
1 parent 126034f commit 25f39d3

File tree

2 files changed

+20
-15
lines changed

2 files changed

+20
-15
lines changed

arch/s390/pci/pci_bus.c

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,16 @@ void zpci_bus_scan_busses(void)
168168
mutex_unlock(&zbus_list_lock);
169169
}
170170

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+
171178
/* zpci_bus_create_pci_bus - Create the PCI bus associated with this zbus
172179
* @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
174181
* @ops: the pci operations
175182
*
176183
* The PCI function @fr determines the domain (its UID), multifunction property
@@ -188,7 +195,7 @@ static int zpci_bus_create_pci_bus(struct zpci_bus *zbus, struct zpci_dev *fr, s
188195
return domain;
189196

190197
zbus->domain_nr = domain;
191-
zbus->multifunction = fr->rid_available;
198+
zbus->multifunction = zpci_bus_is_multifunction_root(fr);
192199
zbus->max_bus_speed = fr->max_bus_speed;
193200

194201
/*
@@ -238,6 +245,8 @@ static struct zpci_bus *zpci_bus_get(int topo, bool topo_is_tid)
238245

239246
mutex_lock(&zbus_list_lock);
240247
list_for_each_entry(zbus, &zbus_list, bus_next) {
248+
if (!zbus->multifunction)
249+
continue;
241250
if (topo_is_tid == zbus->topo_is_tid && topo == zbus->topo) {
242251
kref_get(&zbus->kref);
243252
goto out_unlock;
@@ -293,19 +302,22 @@ static int zpci_bus_add_device(struct zpci_bus *zbus, struct zpci_dev *zdev)
293302
{
294303
int rc = -EINVAL;
295304

305+
if (zbus->multifunction) {
306+
if (!zdev->rid_available) {
307+
WARN_ONCE(1, "rid_available not set for multifunction\n");
308+
return rc;
309+
}
310+
zdev->devfn = zdev->rid & ZPCI_RID_MASK_DEVFN;
311+
}
312+
296313
if (zbus->function[zdev->devfn]) {
297314
pr_err("devfn %04x is already assigned\n", zdev->devfn);
298315
return rc;
299316
}
300-
301317
zdev->zbus = zbus;
302318
zbus->function[zdev->devfn] = zdev;
303319
zpci_nb_devices++;
304320

305-
if (zbus->multifunction && !zdev->rid_available) {
306-
WARN_ONCE(1, "rid_available not set for multifunction\n");
307-
goto error;
308-
}
309321
rc = zpci_init_slot(zdev);
310322
if (rc)
311323
goto error;
@@ -332,13 +344,8 @@ int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops)
332344
return -ENOSPC;
333345
}
334346

335-
if (zdev->devfn >= ZPCI_FUNCTIONS_PER_BUS)
336-
return -EINVAL;
337-
338347
topo = topo_is_tid ? zdev->tid : zdev->pchid;
339-
if (!s390_pci_no_rid && zdev->rid_available)
340-
zbus = zpci_bus_get(topo, topo_is_tid);
341-
348+
zbus = zpci_bus_get(topo, topo_is_tid);
342349
if (!zbus) {
343350
zbus = zpci_bus_alloc(topo, topo_is_tid);
344351
if (!zbus)

arch/s390/pci/pci_clp.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,6 @@ static int clp_store_query_pci_fn(struct zpci_dev *zdev,
168168
zdev->rid_available = response->rid_avail;
169169
if (zdev->rid_available)
170170
zdev->rid = response->rid;
171-
if (!s390_pci_no_rid && zdev->rid_available)
172-
zdev->devfn = response->rid & ZPCI_RID_MASK_DEVFN;
173171
zdev->tid_avail = response->tid_avail;
174172
if (zdev->tid_avail)
175173
zdev->tid = response->tid;

0 commit comments

Comments
 (0)