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