0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #define KMSG_COMPONENT "zpci"
0011 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
0012
0013 #include <linux/kernel.h>
0014 #include <linux/pci.h>
0015
0016 #include "pci_iov.h"
0017
0018 static struct resource iov_res = {
0019 .name = "PCI IOV res",
0020 .start = 0,
0021 .end = -1,
0022 .flags = IORESOURCE_MEM,
0023 };
0024
0025 void zpci_iov_map_resources(struct pci_dev *pdev)
0026 {
0027 resource_size_t len;
0028 int i;
0029
0030 for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
0031 int bar = i + PCI_IOV_RESOURCES;
0032
0033 len = pci_resource_len(pdev, bar);
0034 if (!len)
0035 continue;
0036 pdev->resource[bar].parent = &iov_res;
0037 }
0038 }
0039
0040 void zpci_iov_remove_virtfn(struct pci_dev *pdev, int vfn)
0041 {
0042 pci_lock_rescan_remove();
0043
0044 pci_iov_remove_virtfn(pdev->physfn, vfn - 1);
0045 pci_unlock_rescan_remove();
0046 }
0047
0048 static int zpci_iov_link_virtfn(struct pci_dev *pdev, struct pci_dev *virtfn, int vfid)
0049 {
0050 int rc;
0051
0052 rc = pci_iov_sysfs_link(pdev, virtfn, vfid);
0053 if (rc)
0054 return rc;
0055
0056 virtfn->is_virtfn = 1;
0057 virtfn->multifunction = 0;
0058 virtfn->physfn = pci_dev_get(pdev);
0059
0060 return 0;
0061 }
0062
0063 int zpci_iov_setup_virtfn(struct zpci_bus *zbus, struct pci_dev *virtfn, int vfn)
0064 {
0065 int i, cand_devfn;
0066 struct zpci_dev *zdev;
0067 struct pci_dev *pdev;
0068 int vfid = vfn - 1;
0069 int rc = 0;
0070
0071 if (!zbus->multifunction)
0072 return 0;
0073
0074
0075
0076
0077
0078
0079
0080
0081 for (i = 0; i < ZPCI_FUNCTIONS_PER_BUS; i++) {
0082 zdev = zbus->function[i];
0083 if (zdev && zdev->is_physfn) {
0084 pdev = pci_get_slot(zbus->bus, zdev->devfn);
0085 if (!pdev)
0086 continue;
0087 cand_devfn = pci_iov_virtfn_devfn(pdev, vfid);
0088 if (cand_devfn == virtfn->devfn) {
0089 rc = zpci_iov_link_virtfn(pdev, virtfn, vfid);
0090
0091 pci_dev_put(pdev);
0092 break;
0093 }
0094
0095 pci_dev_put(pdev);
0096 }
0097 }
0098 return rc;
0099 }