Skip to content

Commit 0579388

Browse files
niklas88Vasily Gorbik
authored andcommitted
s390/pci: Pull search for parent PF out of zpci_iov_setup_virtfn()
This creates a new zpci_iov_find_parent_pf() function which a future commit can use to find if a VF has a configured parent PF. Use zdev->rid instead of zdev->devfn such that the new function can be used before it has been decided if the RID will be exposed and zdev->devfn is set. Also handle the hypotheical case that the RID is not available but there is an otherwise matching zbus. Fixes: 25f39d3 ("s390/pci: Ignore RID for isolated VFs") Cc: [email protected] Reviewed-by: Halil Pasic <[email protected]> Signed-off-by: Niklas Schnelle <[email protected]> Signed-off-by: Vasily Gorbik <[email protected]>
1 parent 6166caf commit 0579388

File tree

1 file changed

+42
-14
lines changed

1 file changed

+42
-14
lines changed

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+
static 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
}

0 commit comments

Comments
 (0)