1abb95b75SNiklas Schnelle // SPDX-License-Identifier: GPL-2.0 2abb95b75SNiklas Schnelle /* 3abb95b75SNiklas Schnelle * Copyright IBM Corp. 2020 4abb95b75SNiklas Schnelle * 5abb95b75SNiklas Schnelle * Author(s): 6abb95b75SNiklas Schnelle * Niklas Schnelle <schnelle@linux.ibm.com> 7abb95b75SNiklas Schnelle * 8abb95b75SNiklas Schnelle */ 9abb95b75SNiklas Schnelle 10abb95b75SNiklas Schnelle #define KMSG_COMPONENT "zpci" 11abb95b75SNiklas Schnelle #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 12abb95b75SNiklas Schnelle 13abb95b75SNiklas Schnelle #include <linux/kernel.h> 14abb95b75SNiklas Schnelle #include <linux/pci.h> 15abb95b75SNiklas Schnelle 16*4904e194SNiklas Schnelle #include "pci_iov.h" 17*4904e194SNiklas Schnelle 18abb95b75SNiklas Schnelle static struct resource iov_res = { 19abb95b75SNiklas Schnelle .name = "PCI IOV res", 20abb95b75SNiklas Schnelle .start = 0, 21abb95b75SNiklas Schnelle .end = -1, 22abb95b75SNiklas Schnelle .flags = IORESOURCE_MEM, 23abb95b75SNiklas Schnelle }; 24abb95b75SNiklas Schnelle 25abb95b75SNiklas Schnelle void zpci_iov_map_resources(struct pci_dev *pdev) 26abb95b75SNiklas Schnelle { 27abb95b75SNiklas Schnelle resource_size_t len; 28abb95b75SNiklas Schnelle int i; 29abb95b75SNiklas Schnelle 30abb95b75SNiklas Schnelle for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { 31abb95b75SNiklas Schnelle int bar = i + PCI_IOV_RESOURCES; 32abb95b75SNiklas Schnelle 33abb95b75SNiklas Schnelle len = pci_resource_len(pdev, bar); 34abb95b75SNiklas Schnelle if (!len) 35abb95b75SNiklas Schnelle continue; 36abb95b75SNiklas Schnelle pdev->resource[bar].parent = &iov_res; 37abb95b75SNiklas Schnelle } 38abb95b75SNiklas Schnelle } 39abb95b75SNiklas Schnelle 40abb95b75SNiklas Schnelle void zpci_iov_remove_virtfn(struct pci_dev *pdev, int vfn) 41abb95b75SNiklas Schnelle { 42abb95b75SNiklas Schnelle pci_lock_rescan_remove(); 43abb95b75SNiklas Schnelle /* Linux' vfid's start at 0 vfn at 1 */ 44abb95b75SNiklas Schnelle pci_iov_remove_virtfn(pdev->physfn, vfn - 1); 45abb95b75SNiklas Schnelle pci_unlock_rescan_remove(); 46abb95b75SNiklas Schnelle } 47abb95b75SNiklas Schnelle 48abb95b75SNiklas Schnelle static int zpci_iov_link_virtfn(struct pci_dev *pdev, struct pci_dev *virtfn, int vfid) 49abb95b75SNiklas Schnelle { 50abb95b75SNiklas Schnelle int rc; 51abb95b75SNiklas Schnelle 52abb95b75SNiklas Schnelle rc = pci_iov_sysfs_link(pdev, virtfn, vfid); 53abb95b75SNiklas Schnelle if (rc) 54abb95b75SNiklas Schnelle return rc; 55abb95b75SNiklas Schnelle 56abb95b75SNiklas Schnelle virtfn->is_virtfn = 1; 57abb95b75SNiklas Schnelle virtfn->multifunction = 0; 58abb95b75SNiklas Schnelle virtfn->physfn = pci_dev_get(pdev); 59abb95b75SNiklas Schnelle 60abb95b75SNiklas Schnelle return 0; 61abb95b75SNiklas Schnelle } 62abb95b75SNiklas Schnelle 63abb95b75SNiklas Schnelle int zpci_iov_setup_virtfn(struct zpci_bus *zbus, struct pci_dev *virtfn, int vfn) 64abb95b75SNiklas Schnelle { 65abb95b75SNiklas Schnelle int i, cand_devfn; 66abb95b75SNiklas Schnelle struct zpci_dev *zdev; 67abb95b75SNiklas Schnelle struct pci_dev *pdev; 68abb95b75SNiklas Schnelle int vfid = vfn - 1; /* Linux' vfid's start at 0 vfn at 1*/ 69abb95b75SNiklas Schnelle int rc = 0; 70abb95b75SNiklas Schnelle 71abb95b75SNiklas Schnelle if (!zbus->multifunction) 72abb95b75SNiklas Schnelle return 0; 73abb95b75SNiklas Schnelle 74abb95b75SNiklas Schnelle /* If the parent PF for the given VF is also configured in the 75abb95b75SNiklas Schnelle * instance, it must be on the same zbus. 76abb95b75SNiklas Schnelle * We can then identify the parent PF by checking what 77abb95b75SNiklas Schnelle * devfn the VF would have if it belonged to that PF using the PF's 78abb95b75SNiklas Schnelle * stride and offset. Only if this candidate devfn matches the 79abb95b75SNiklas Schnelle * actual devfn will we link both functions. 80abb95b75SNiklas Schnelle */ 81abb95b75SNiklas Schnelle for (i = 0; i < ZPCI_FUNCTIONS_PER_BUS; i++) { 82abb95b75SNiklas Schnelle zdev = zbus->function[i]; 83abb95b75SNiklas Schnelle if (zdev && zdev->is_physfn) { 84abb95b75SNiklas Schnelle pdev = pci_get_slot(zbus->bus, zdev->devfn); 85abb95b75SNiklas Schnelle if (!pdev) 86abb95b75SNiklas Schnelle continue; 87abb95b75SNiklas Schnelle cand_devfn = pci_iov_virtfn_devfn(pdev, vfid); 88abb95b75SNiklas Schnelle if (cand_devfn == virtfn->devfn) { 89abb95b75SNiklas Schnelle rc = zpci_iov_link_virtfn(pdev, virtfn, vfid); 90abb95b75SNiklas Schnelle /* balance pci_get_slot() */ 91abb95b75SNiklas Schnelle pci_dev_put(pdev); 92abb95b75SNiklas Schnelle break; 93abb95b75SNiklas Schnelle } 94abb95b75SNiklas Schnelle /* balance pci_get_slot() */ 95abb95b75SNiklas Schnelle pci_dev_put(pdev); 96abb95b75SNiklas Schnelle } 97abb95b75SNiklas Schnelle } 98abb95b75SNiklas Schnelle return rc; 99abb95b75SNiklas Schnelle } 100