Merge branch 'pci/enumeration'
- Split out ARI "next function" handling from the traditional one (Niklas Schnelle) - Move jailhouse "isolated function" (non-zero functions where function 0 doesn't exist) handling to pci_scan_slot() to avoid duplicating multi-function scanning in pci_scan_child_bus_extend() (Niklas Schnelle) - Extend "isolated function" probing to s390 (Niklas Schnelle). - Allow s390 zPCI zbus without a function 0 (Niklas Schnelle) * pci/enumeration: s390/pci: allow zPCI zbus without a function zero PCI: Extend isolated function probing to s390 PCI: Move jailhouse's isolated function handling to pci_scan_slot() PCI: Split out next_ari_fn() from next_fn() PCI: Clean up pci_scan_slot()
This commit is contained in:
Коммит
dc5253117a
|
@ -145,9 +145,6 @@ int zpci_bus_scan_bus(struct zpci_bus *zbus)
|
|||
struct zpci_dev *zdev;
|
||||
int devfn, rc, ret = 0;
|
||||
|
||||
if (!zbus->function[0])
|
||||
return 0;
|
||||
|
||||
for (devfn = 0; devfn < ZPCI_FUNCTIONS_PER_BUS; devfn++) {
|
||||
zdev = zbus->function[devfn];
|
||||
if (zdev && zdev->state == ZPCI_FN_STATE_CONFIGURED) {
|
||||
|
@ -184,26 +181,26 @@ void zpci_bus_scan_busses(void)
|
|||
|
||||
/* zpci_bus_create_pci_bus - Create the PCI bus associated with this zbus
|
||||
* @zbus: the zbus holding the zdevices
|
||||
* @f0: function 0 of the bus
|
||||
* @fr: PCI root function that will determine the bus's domain, and bus speeed
|
||||
* @ops: the pci operations
|
||||
*
|
||||
* Function zero is taken as a parameter as this is used to determine the
|
||||
* domain, multifunction property and maximum bus speed of the entire bus.
|
||||
* The PCI function @fr determines the domain (its UID), multifunction property
|
||||
* and maximum bus speed of the entire bus.
|
||||
*
|
||||
* Return: 0 on success, an error code otherwise
|
||||
*/
|
||||
static int zpci_bus_create_pci_bus(struct zpci_bus *zbus, struct zpci_dev *f0, struct pci_ops *ops)
|
||||
static int zpci_bus_create_pci_bus(struct zpci_bus *zbus, struct zpci_dev *fr, struct pci_ops *ops)
|
||||
{
|
||||
struct pci_bus *bus;
|
||||
int domain;
|
||||
|
||||
domain = zpci_alloc_domain((u16)f0->uid);
|
||||
domain = zpci_alloc_domain((u16)fr->uid);
|
||||
if (domain < 0)
|
||||
return domain;
|
||||
|
||||
zbus->domain_nr = domain;
|
||||
zbus->multifunction = f0->rid_available;
|
||||
zbus->max_bus_speed = f0->max_bus_speed;
|
||||
zbus->multifunction = fr->rid_available;
|
||||
zbus->max_bus_speed = fr->max_bus_speed;
|
||||
|
||||
/*
|
||||
* Note that the zbus->resources are taken over and zbus->resources
|
||||
|
@ -303,47 +300,6 @@ void pcibios_bus_add_device(struct pci_dev *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
/* zpci_bus_create_hotplug_slots - Add hotplug slot(s) for device added to bus
|
||||
* @zdev: the zPCI device that was newly added
|
||||
*
|
||||
* Add the hotplug slot(s) for the newly added PCI function. Normally this is
|
||||
* simply the slot for the function itself. If however we are adding the
|
||||
* function 0 on a zbus, it might be that we already registered functions on
|
||||
* that zbus but could not create their hotplug slots yet so add those now too.
|
||||
*
|
||||
* Return: 0 on success, an error code otherwise
|
||||
*/
|
||||
static int zpci_bus_create_hotplug_slots(struct zpci_dev *zdev)
|
||||
{
|
||||
struct zpci_bus *zbus = zdev->zbus;
|
||||
int devfn, rc = 0;
|
||||
|
||||
rc = zpci_init_slot(zdev);
|
||||
if (rc)
|
||||
return rc;
|
||||
zdev->has_hp_slot = 1;
|
||||
|
||||
if (zdev->devfn == 0 && zbus->multifunction) {
|
||||
/* Now that function 0 is there we can finally create the
|
||||
* hotplug slots for those functions with devfn != 0 that have
|
||||
* been parked in zbus->function[] waiting for us to be able to
|
||||
* create the PCI bus.
|
||||
*/
|
||||
for (devfn = 1; devfn < ZPCI_FUNCTIONS_PER_BUS; devfn++) {
|
||||
zdev = zbus->function[devfn];
|
||||
if (zdev && !zdev->has_hp_slot) {
|
||||
rc = zpci_init_slot(zdev);
|
||||
if (rc)
|
||||
return rc;
|
||||
zdev->has_hp_slot = 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int zpci_bus_add_device(struct zpci_bus *zbus, struct zpci_dev *zdev)
|
||||
{
|
||||
int rc = -EINVAL;
|
||||
|
@ -352,21 +308,19 @@ static int zpci_bus_add_device(struct zpci_bus *zbus, struct zpci_dev *zdev)
|
|||
pr_err("devfn %04x is already assigned\n", zdev->devfn);
|
||||
return rc;
|
||||
}
|
||||
|
||||
zdev->zbus = zbus;
|
||||
zbus->function[zdev->devfn] = zdev;
|
||||
zpci_nb_devices++;
|
||||
|
||||
if (zbus->bus) {
|
||||
if (zbus->multifunction && !zdev->rid_available) {
|
||||
WARN_ONCE(1, "rid_available not set for multifunction\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
zpci_bus_create_hotplug_slots(zdev);
|
||||
} else {
|
||||
/* Hotplug slot will be created once function 0 appears */
|
||||
zbus->multifunction = 1;
|
||||
if (zbus->multifunction && !zdev->rid_available) {
|
||||
WARN_ONCE(1, "rid_available not set for multifunction\n");
|
||||
goto error;
|
||||
}
|
||||
rc = zpci_init_slot(zdev);
|
||||
if (rc)
|
||||
goto error;
|
||||
zdev->has_hp_slot = 1;
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -400,7 +354,11 @@ int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (zdev->devfn == 0) {
|
||||
if (!zbus->bus) {
|
||||
/* The UID of the first PCI function registered with a zpci_bus
|
||||
* is used as the domain number for that bus. Currently there
|
||||
* is exactly one zpci_bus per domain.
|
||||
*/
|
||||
rc = zpci_bus_create_pci_bus(zbus, zdev, ops);
|
||||
if (rc)
|
||||
goto error;
|
||||
|
|
|
@ -2579,33 +2579,39 @@ struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn)
|
|||
}
|
||||
EXPORT_SYMBOL(pci_scan_single_device);
|
||||
|
||||
static unsigned int next_fn(struct pci_bus *bus, struct pci_dev *dev,
|
||||
unsigned int fn)
|
||||
static int next_ari_fn(struct pci_bus *bus, struct pci_dev *dev, int fn)
|
||||
{
|
||||
int pos;
|
||||
u16 cap = 0;
|
||||
unsigned int next_fn;
|
||||
|
||||
if (pci_ari_enabled(bus)) {
|
||||
if (!dev)
|
||||
return 0;
|
||||
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI);
|
||||
if (!pos)
|
||||
return 0;
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
pci_read_config_word(dev, pos + PCI_ARI_CAP, &cap);
|
||||
next_fn = PCI_ARI_CAP_NFN(cap);
|
||||
if (next_fn <= fn)
|
||||
return 0; /* protect against malformed list */
|
||||
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI);
|
||||
if (!pos)
|
||||
return -ENODEV;
|
||||
|
||||
return next_fn;
|
||||
}
|
||||
pci_read_config_word(dev, pos + PCI_ARI_CAP, &cap);
|
||||
next_fn = PCI_ARI_CAP_NFN(cap);
|
||||
if (next_fn <= fn)
|
||||
return -ENODEV; /* protect against malformed list */
|
||||
|
||||
/* dev may be NULL for non-contiguous multifunction devices */
|
||||
if (!dev || dev->multifunction)
|
||||
return (fn + 1) % 8;
|
||||
return next_fn;
|
||||
}
|
||||
|
||||
return 0;
|
||||
static int next_fn(struct pci_bus *bus, struct pci_dev *dev, int fn)
|
||||
{
|
||||
if (pci_ari_enabled(bus))
|
||||
return next_ari_fn(bus, dev, fn);
|
||||
|
||||
if (fn >= 7)
|
||||
return -ENODEV;
|
||||
/* only multifunction devices may have more functions */
|
||||
if (dev && !dev->multifunction)
|
||||
return -ENODEV;
|
||||
|
||||
return fn + 1;
|
||||
}
|
||||
|
||||
static int only_one_child(struct pci_bus *bus)
|
||||
|
@ -2643,26 +2649,30 @@ static int only_one_child(struct pci_bus *bus)
|
|||
*/
|
||||
int pci_scan_slot(struct pci_bus *bus, int devfn)
|
||||
{
|
||||
unsigned int fn, nr = 0;
|
||||
struct pci_dev *dev;
|
||||
int fn = 0, nr = 0;
|
||||
|
||||
if (only_one_child(bus) && (devfn > 0))
|
||||
return 0; /* Already scanned the entire slot */
|
||||
|
||||
dev = pci_scan_single_device(bus, devfn);
|
||||
if (!dev)
|
||||
return 0;
|
||||
if (!pci_dev_is_added(dev))
|
||||
nr++;
|
||||
|
||||
for (fn = next_fn(bus, dev, 0); fn > 0; fn = next_fn(bus, dev, fn)) {
|
||||
do {
|
||||
dev = pci_scan_single_device(bus, devfn + fn);
|
||||
if (dev) {
|
||||
if (!pci_dev_is_added(dev))
|
||||
nr++;
|
||||
dev->multifunction = 1;
|
||||
if (fn > 0)
|
||||
dev->multifunction = 1;
|
||||
} else if (fn == 0) {
|
||||
/*
|
||||
* Function 0 is required unless we are running on
|
||||
* a hypervisor that passes through individual PCI
|
||||
* functions.
|
||||
*/
|
||||
if (!hypervisor_isolated_pci_functions())
|
||||
break;
|
||||
}
|
||||
}
|
||||
fn = next_fn(bus, dev, fn);
|
||||
} while (fn >= 0);
|
||||
|
||||
/* Only one slot has PCIe device */
|
||||
if (bus->self && nr)
|
||||
|
@ -2858,29 +2868,14 @@ static unsigned int pci_scan_child_bus_extend(struct pci_bus *bus,
|
|||
{
|
||||
unsigned int used_buses, normal_bridges = 0, hotplug_bridges = 0;
|
||||
unsigned int start = bus->busn_res.start;
|
||||
unsigned int devfn, fn, cmax, max = start;
|
||||
unsigned int devfn, cmax, max = start;
|
||||
struct pci_dev *dev;
|
||||
int nr_devs;
|
||||
|
||||
dev_dbg(&bus->dev, "scanning bus\n");
|
||||
|
||||
/* Go find them, Rover! */
|
||||
for (devfn = 0; devfn < 256; devfn += 8) {
|
||||
nr_devs = pci_scan_slot(bus, devfn);
|
||||
|
||||
/*
|
||||
* The Jailhouse hypervisor may pass individual functions of a
|
||||
* multi-function device to a guest without passing function 0.
|
||||
* Look for them as well.
|
||||
*/
|
||||
if (jailhouse_paravirt() && nr_devs == 0) {
|
||||
for (fn = 1; fn < 8; fn++) {
|
||||
dev = pci_scan_single_device(bus, devfn + fn);
|
||||
if (dev)
|
||||
dev->multifunction = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (devfn = 0; devfn < 256; devfn += 8)
|
||||
pci_scan_slot(bus, devfn);
|
||||
|
||||
/* Reserve buses for SR-IOV capability */
|
||||
used_buses = pci_iov_bus_range(bus);
|
||||
|
|
|
@ -32,4 +32,12 @@ static inline bool jailhouse_paravirt(void)
|
|||
|
||||
#endif /* !CONFIG_X86 */
|
||||
|
||||
static inline bool hypervisor_isolated_pci_functions(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_S390))
|
||||
return true;
|
||||
|
||||
return jailhouse_paravirt();
|
||||
}
|
||||
|
||||
#endif /* __LINUX_HYPEVISOR_H */
|
||||
|
|
Загрузка…
Ссылка в новой задаче