forked from Minki/linux
s390/pci: consolidate SR-IOV specific code
currently we have multiple #ifdef CONFIG_PCI_IOV blocks spread over different compliation units and headers, all dealing with SR-IOV specific behavior. This violates the style guide which discourages conditionally compiled code blocks and hinders maintainability by speading SR-IOV functionality over many files. Let's move all of this into a conditionally compiled pci_iov.c file and local header and prefix SR-IOV specific functions with zpci_iov_*. Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com> Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
This commit is contained in:
parent
da1694ad9e
commit
abb95b7550
@ -6,3 +6,4 @@
|
||||
obj-$(CONFIG_PCI) += pci.o pci_irq.o pci_dma.o pci_clp.o pci_sysfs.o \
|
||||
pci_event.o pci_debug.o pci_insn.o pci_mmio.o \
|
||||
pci_bus.o
|
||||
obj-$(CONFIG_PCI_IOV) += pci_iov.o
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <asm/pci_dma.h>
|
||||
|
||||
#include "pci_bus.h"
|
||||
#include "pci_iov.h"
|
||||
|
||||
/* list of all detected zpci devices */
|
||||
static LIST_HEAD(zpci_list);
|
||||
@ -413,15 +414,6 @@ static struct pci_ops pci_root_ops = {
|
||||
.write = pci_write,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
static struct resource iov_res = {
|
||||
.name = "PCI IOV res",
|
||||
.start = 0,
|
||||
.end = -1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
#endif
|
||||
|
||||
static void zpci_map_resources(struct pci_dev *pdev)
|
||||
{
|
||||
struct zpci_dev *zdev = to_zpci(pdev);
|
||||
@ -442,16 +434,7 @@ static void zpci_map_resources(struct pci_dev *pdev)
|
||||
pdev->resource[i].end = pdev->resource[i].start + len - 1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
|
||||
int bar = i + PCI_IOV_RESOURCES;
|
||||
|
||||
len = pci_resource_len(pdev, bar);
|
||||
if (!len)
|
||||
continue;
|
||||
pdev->resource[bar].parent = &iov_res;
|
||||
}
|
||||
#endif
|
||||
zpci_iov_map_resources(pdev);
|
||||
}
|
||||
|
||||
static void zpci_unmap_resources(struct pci_dev *pdev)
|
||||
@ -703,7 +686,7 @@ void zpci_remove_device(struct zpci_dev *zdev)
|
||||
pdev = pci_get_slot(zbus->bus, zdev->devfn);
|
||||
if (pdev) {
|
||||
if (pdev->is_virtfn)
|
||||
return zpci_remove_virtfn(pdev, zdev->vfn);
|
||||
return zpci_iov_remove_virtfn(pdev, zdev->vfn);
|
||||
pci_stop_and_remove_bus_device_locked(pdev);
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <asm/pci_dma.h>
|
||||
|
||||
#include "pci_bus.h"
|
||||
#include "pci_iov.h"
|
||||
|
||||
static LIST_HEAD(zbus_list);
|
||||
static DEFINE_SPINLOCK(zbus_list_lock);
|
||||
@ -126,69 +127,6 @@ static struct zpci_bus *zpci_bus_alloc(int pchid)
|
||||
return zbus;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
static int zpci_bus_link_virtfn(struct pci_dev *pdev,
|
||||
struct pci_dev *virtfn, int vfid)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = pci_iov_sysfs_link(pdev, virtfn, vfid);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
virtfn->is_virtfn = 1;
|
||||
virtfn->multifunction = 0;
|
||||
virtfn->physfn = pci_dev_get(pdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zpci_bus_setup_virtfn(struct zpci_bus *zbus,
|
||||
struct pci_dev *virtfn, int vfn)
|
||||
{
|
||||
int i, cand_devfn;
|
||||
struct zpci_dev *zdev;
|
||||
struct pci_dev *pdev;
|
||||
int vfid = vfn - 1; /* Linux' vfid's start at 0 vfn at 1*/
|
||||
int rc = 0;
|
||||
|
||||
if (!zbus->multifunction)
|
||||
return 0;
|
||||
|
||||
/* If the parent PF for the given VF is also configured in the
|
||||
* instance, it must be on the same zbus.
|
||||
* We can then identify the parent PF by checking what
|
||||
* devfn the VF would have if it belonged to that PF using the PF's
|
||||
* stride and offset. Only if this candidate devfn matches the
|
||||
* actual devfn will we link both functions.
|
||||
*/
|
||||
for (i = 0; i < ZPCI_FUNCTIONS_PER_BUS; i++) {
|
||||
zdev = zbus->function[i];
|
||||
if (zdev && zdev->is_physfn) {
|
||||
pdev = pci_get_slot(zbus->bus, zdev->devfn);
|
||||
if (!pdev)
|
||||
continue;
|
||||
cand_devfn = pci_iov_virtfn_devfn(pdev, vfid);
|
||||
if (cand_devfn == virtfn->devfn) {
|
||||
rc = zpci_bus_link_virtfn(pdev, virtfn, vfid);
|
||||
/* balance pci_get_slot() */
|
||||
pci_dev_put(pdev);
|
||||
break;
|
||||
}
|
||||
/* balance pci_get_slot() */
|
||||
pci_dev_put(pdev);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#else
|
||||
static inline int zpci_bus_setup_virtfn(struct zpci_bus *zbus,
|
||||
struct pci_dev *virtfn, int vfn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void pcibios_bus_add_device(struct pci_dev *pdev)
|
||||
{
|
||||
struct zpci_dev *zdev = to_zpci(pdev);
|
||||
@ -198,7 +136,7 @@ void pcibios_bus_add_device(struct pci_dev *pdev)
|
||||
* perform PF/VF linking.
|
||||
*/
|
||||
if (zdev->vfn)
|
||||
zpci_bus_setup_virtfn(zdev->zbus, pdev, zdev->vfn);
|
||||
zpci_iov_setup_virtfn(zdev->zbus, pdev, zdev->vfn);
|
||||
|
||||
}
|
||||
|
||||
|
@ -30,15 +30,3 @@ static inline struct zpci_dev *get_zdev_by_bus(struct pci_bus *bus,
|
||||
return (devfn >= ZPCI_FUNCTIONS_PER_BUS) ? NULL : zbus->function[devfn];
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
static inline void zpci_remove_virtfn(struct pci_dev *pdev, int vfn)
|
||||
{
|
||||
|
||||
pci_lock_rescan_remove();
|
||||
/* Linux' vfid's start at 0 vfn at 1 */
|
||||
pci_iov_remove_virtfn(pdev->physfn, vfn - 1);
|
||||
pci_unlock_rescan_remove();
|
||||
}
|
||||
#else /* CONFIG_PCI_IOV */
|
||||
static inline void zpci_remove_virtfn(struct pci_dev *pdev, int vfn) {}
|
||||
#endif /* CONFIG_PCI_IOV */
|
||||
|
97
arch/s390/pci/pci_iov.c
Normal file
97
arch/s390/pci/pci_iov.c
Normal file
@ -0,0 +1,97 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright IBM Corp. 2020
|
||||
*
|
||||
* Author(s):
|
||||
* Niklas Schnelle <schnelle@linux.ibm.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#define KMSG_COMPONENT "zpci"
|
||||
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
static struct resource iov_res = {
|
||||
.name = "PCI IOV res",
|
||||
.start = 0,
|
||||
.end = -1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
|
||||
void zpci_iov_map_resources(struct pci_dev *pdev)
|
||||
{
|
||||
resource_size_t len;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
|
||||
int bar = i + PCI_IOV_RESOURCES;
|
||||
|
||||
len = pci_resource_len(pdev, bar);
|
||||
if (!len)
|
||||
continue;
|
||||
pdev->resource[bar].parent = &iov_res;
|
||||
}
|
||||
}
|
||||
|
||||
void zpci_iov_remove_virtfn(struct pci_dev *pdev, int vfn)
|
||||
{
|
||||
pci_lock_rescan_remove();
|
||||
/* Linux' vfid's start at 0 vfn at 1 */
|
||||
pci_iov_remove_virtfn(pdev->physfn, vfn - 1);
|
||||
pci_unlock_rescan_remove();
|
||||
}
|
||||
|
||||
static int zpci_iov_link_virtfn(struct pci_dev *pdev, struct pci_dev *virtfn, int vfid)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = pci_iov_sysfs_link(pdev, virtfn, vfid);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
virtfn->is_virtfn = 1;
|
||||
virtfn->multifunction = 0;
|
||||
virtfn->physfn = pci_dev_get(pdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zpci_iov_setup_virtfn(struct zpci_bus *zbus, struct pci_dev *virtfn, int vfn)
|
||||
{
|
||||
int i, cand_devfn;
|
||||
struct zpci_dev *zdev;
|
||||
struct pci_dev *pdev;
|
||||
int vfid = vfn - 1; /* Linux' vfid's start at 0 vfn at 1*/
|
||||
int rc = 0;
|
||||
|
||||
if (!zbus->multifunction)
|
||||
return 0;
|
||||
|
||||
/* If the parent PF for the given VF is also configured in the
|
||||
* instance, it must be on the same zbus.
|
||||
* We can then identify the parent PF by checking what
|
||||
* devfn the VF would have if it belonged to that PF using the PF's
|
||||
* stride and offset. Only if this candidate devfn matches the
|
||||
* actual devfn will we link both functions.
|
||||
*/
|
||||
for (i = 0; i < ZPCI_FUNCTIONS_PER_BUS; i++) {
|
||||
zdev = zbus->function[i];
|
||||
if (zdev && zdev->is_physfn) {
|
||||
pdev = pci_get_slot(zbus->bus, zdev->devfn);
|
||||
if (!pdev)
|
||||
continue;
|
||||
cand_devfn = pci_iov_virtfn_devfn(pdev, vfid);
|
||||
if (cand_devfn == virtfn->devfn) {
|
||||
rc = zpci_iov_link_virtfn(pdev, virtfn, vfid);
|
||||
/* balance pci_get_slot() */
|
||||
pci_dev_put(pdev);
|
||||
break;
|
||||
}
|
||||
/* balance pci_get_slot() */
|
||||
pci_dev_put(pdev);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
30
arch/s390/pci/pci_iov.h
Normal file
30
arch/s390/pci/pci_iov.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright IBM Corp. 2020
|
||||
*
|
||||
* Author(s):
|
||||
* Niklas Schnelle <schnelle@linux.ibm.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __S390_PCI_IOV_H
|
||||
#define __S390_PCI_IOV_H
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
void zpci_iov_remove_virtfn(struct pci_dev *pdev, int vfn);
|
||||
|
||||
void zpci_iov_map_resources(struct pci_dev *pdev);
|
||||
|
||||
int zpci_iov_setup_virtfn(struct zpci_bus *zbus, struct pci_dev *virtfn, int vfn);
|
||||
|
||||
#else /* CONFIG_PCI_IOV */
|
||||
static inline void zpci_iov_remove_virtfn(struct pci_dev *pdev, int vfn) {}
|
||||
|
||||
static inline void zpci_iov_map_resources(struct pci_dev *pdev) {}
|
||||
|
||||
static inline int zpci_iov_setup_virtfn(struct zpci_bus *zbus, struct pci_dev *virtfn, int vfn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PCI_IOV */
|
||||
#endif /* __S390_PCI_IOV_h */
|
Loading…
Reference in New Issue
Block a user