1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright IBM Corp. 2020
6 * Niklas Schnelle <schnelle@linux.ibm.com>
10 #define KMSG_COMPONENT "zpci"
11 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
13 #include <linux/kernel.h>
14 #include <linux/pci.h>
18 static struct resource iov_res
= {
19 .name
= "PCI IOV res",
22 .flags
= IORESOURCE_MEM
,
25 void zpci_iov_map_resources(struct pci_dev
*pdev
)
30 for (i
= 0; i
< PCI_SRIOV_NUM_BARS
; i
++) {
31 int bar
= i
+ PCI_IOV_RESOURCES
;
33 len
= pci_resource_len(pdev
, bar
);
36 pdev
->resource
[bar
].parent
= &iov_res
;
40 void zpci_iov_remove_virtfn(struct pci_dev
*pdev
, int vfn
)
42 pci_lock_rescan_remove();
43 /* Linux' vfid's start at 0 vfn at 1 */
44 pci_iov_remove_virtfn(pdev
->physfn
, vfn
- 1);
45 pci_unlock_rescan_remove();
48 static int zpci_iov_link_virtfn(struct pci_dev
*pdev
, struct pci_dev
*virtfn
, int vfid
)
52 rc
= pci_iov_sysfs_link(pdev
, virtfn
, vfid
);
56 virtfn
->is_virtfn
= 1;
57 virtfn
->multifunction
= 0;
58 virtfn
->physfn
= pci_dev_get(pdev
);
63 int zpci_iov_setup_virtfn(struct zpci_bus
*zbus
, struct pci_dev
*virtfn
, int vfn
)
66 struct zpci_dev
*zdev
;
68 int vfid
= vfn
- 1; /* Linux' vfid's start at 0 vfn at 1*/
71 if (!zbus
->multifunction
)
74 /* If the parent PF for the given VF is also configured in the
75 * instance, it must be on the same zbus.
76 * We can then identify the parent PF by checking what
77 * devfn the VF would have if it belonged to that PF using the PF's
78 * stride and offset. Only if this candidate devfn matches the
79 * actual devfn will we link both functions.
81 for (i
= 0; i
< ZPCI_FUNCTIONS_PER_BUS
; i
++) {
82 zdev
= zbus
->function
[i
];
83 if (zdev
&& zdev
->is_physfn
) {
84 pdev
= pci_get_slot(zbus
->bus
, zdev
->devfn
);
87 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() */
94 /* balance pci_get_slot() */