Skip to content

Commit cf0309b

Browse files
committed
Merge: [s390] s390/pci: Fix PCHID per port multi-function detection
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/6502 JIRA: https://issues.redhat.com/browse/RHEL-81935 Commits: ``` dc287e4 0579388 2844ddb ``` Signed-off-by: Mete Durlu <mdurlu@redhat.com> Approved-by: Steve Best <sbest@redhat.com> Approved-by: Tony Camuso <tcamuso@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Augusto Caringi <acaringi@redhat.com>
2 parents 50da6c6 + ec8f201 commit cf0309b

File tree

3 files changed

+69
-15
lines changed

3 files changed

+69
-15
lines changed

arch/s390/pci/pci_bus.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,6 @@ void zpci_bus_scan_busses(void)
171171
static bool zpci_bus_is_multifunction_root(struct zpci_dev *zdev)
172172
{
173173
return !s390_pci_no_rid && zdev->rid_available &&
174-
zpci_is_device_configured(zdev) &&
175174
!zdev->vfn;
176175
}
177176

@@ -332,6 +331,17 @@ static int zpci_bus_add_device(struct zpci_bus *zbus, struct zpci_dev *zdev)
332331
return rc;
333332
}
334333

334+
static bool zpci_bus_is_isolated_vf(struct zpci_bus *zbus, struct zpci_dev *zdev)
335+
{
336+
struct pci_dev *pdev;
337+
338+
pdev = zpci_iov_find_parent_pf(zbus, zdev);
339+
if (!pdev)
340+
return true;
341+
pci_dev_put(pdev);
342+
return false;
343+
}
344+
335345
int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops)
336346
{
337347
bool topo_is_tid = zdev->tid_avail;
@@ -346,6 +356,15 @@ int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops)
346356

347357
topo = topo_is_tid ? zdev->tid : zdev->pchid;
348358
zbus = zpci_bus_get(topo, topo_is_tid);
359+
/*
360+
* An isolated VF gets its own domain/bus even if there exists
361+
* a matching domain/bus already
362+
*/
363+
if (zbus && zpci_bus_is_isolated_vf(zbus, zdev)) {
364+
zpci_bus_put(zbus);
365+
zbus = NULL;
366+
}
367+
349368
if (!zbus) {
350369
zbus = zpci_bus_alloc(topo, topo_is_tid);
351370
if (!zbus)

arch/s390/pci/pci_iov.c

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -60,18 +60,35 @@ static int zpci_iov_link_virtfn(struct pci_dev *pdev, struct pci_dev *virtfn, in
6060
return 0;
6161
}
6262

63-
int zpci_iov_setup_virtfn(struct zpci_bus *zbus, struct pci_dev *virtfn, int vfn)
63+
/**
64+
* zpci_iov_find_parent_pf - Find the parent PF, if any, of the given function
65+
* @zbus: The bus that the PCI function is on, or would be added on
66+
* @zdev: The PCI function
67+
*
68+
* Finds the parent PF, if it exists and is configured, of the given PCI function
69+
* and increments its refcount. Th PF is searched for on the provided bus so the
70+
* caller has to ensure that this is the correct bus to search. This function may
71+
* be used before adding the PCI function to a zbus.
72+
*
73+
* Return: Pointer to the struct pci_dev of the parent PF or NULL if it not
74+
* found. If the function is not a VF or has no RequesterID information,
75+
* NULL is returned as well.
76+
*/
77+
struct pci_dev *zpci_iov_find_parent_pf(struct zpci_bus *zbus, struct zpci_dev *zdev)
6478
{
65-
int i, cand_devfn;
66-
struct zpci_dev *zdev;
79+
int i, vfid, devfn, cand_devfn;
6780
struct pci_dev *pdev;
68-
int vfid = vfn - 1; /* Linux' vfid's start at 0 vfn at 1*/
69-
int rc = 0;
7081

7182
if (!zbus->multifunction)
72-
return 0;
73-
74-
/* If the parent PF for the given VF is also configured in the
83+
return NULL;
84+
/* Non-VFs and VFs without RID available don't have a parent */
85+
if (!zdev->vfn || !zdev->rid_available)
86+
return NULL;
87+
/* Linux vfid starts at 0 vfn at 1 */
88+
vfid = zdev->vfn - 1;
89+
devfn = zdev->rid & ZPCI_RID_MASK_DEVFN;
90+
/*
91+
* If the parent PF for the given VF is also configured in the
7592
* instance, it must be on the same zbus.
7693
* We can then identify the parent PF by checking what
7794
* devfn the VF would have if it belonged to that PF using the PF's
@@ -85,15 +102,26 @@ int zpci_iov_setup_virtfn(struct zpci_bus *zbus, struct pci_dev *virtfn, int vfn
85102
if (!pdev)
86103
continue;
87104
cand_devfn = pci_iov_virtfn_devfn(pdev, vfid);
88-
if (cand_devfn == virtfn->devfn) {
89-
rc = zpci_iov_link_virtfn(pdev, virtfn, vfid);
90-
/* balance pci_get_slot() */
91-
pci_dev_put(pdev);
92-
break;
93-
}
105+
if (cand_devfn == devfn)
106+
return pdev;
94107
/* balance pci_get_slot() */
95108
pci_dev_put(pdev);
96109
}
97110
}
111+
return NULL;
112+
}
113+
114+
int zpci_iov_setup_virtfn(struct zpci_bus *zbus, struct pci_dev *virtfn, int vfn)
115+
{
116+
struct zpci_dev *zdev = to_zpci(virtfn);
117+
struct pci_dev *pdev_pf;
118+
int rc = 0;
119+
120+
pdev_pf = zpci_iov_find_parent_pf(zbus, zdev);
121+
if (pdev_pf) {
122+
/* Linux' vfids start at 0 while zdev->vfn starts at 1 */
123+
rc = zpci_iov_link_virtfn(pdev_pf, virtfn, zdev->vfn - 1);
124+
pci_dev_put(pdev_pf);
125+
}
98126
return rc;
99127
}

arch/s390/pci/pci_iov.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ void zpci_iov_map_resources(struct pci_dev *pdev);
1717

1818
int zpci_iov_setup_virtfn(struct zpci_bus *zbus, struct pci_dev *virtfn, int vfn);
1919

20+
struct pci_dev *zpci_iov_find_parent_pf(struct zpci_bus *zbus, struct zpci_dev *zdev);
21+
2022
#else /* CONFIG_PCI_IOV */
2123
static inline void zpci_iov_remove_virtfn(struct pci_dev *pdev, int vfn) {}
2224

@@ -26,5 +28,10 @@ static inline int zpci_iov_setup_virtfn(struct zpci_bus *zbus, struct pci_dev *v
2628
{
2729
return 0;
2830
}
31+
32+
static inline struct pci_dev *zpci_iov_find_parent_pf(struct zpci_bus *zbus, struct zpci_dev *zdev)
33+
{
34+
return NULL;
35+
}
2936
#endif /* CONFIG_PCI_IOV */
3037
#endif /* __S390_PCI_IOV_h */

0 commit comments

Comments
 (0)